%top { /* GNU Mailutils -- a suite of utilities for electronic mail Copyright (C) 2005-2019 Free Software Foundation, Inc. GNU Mailutils is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GNU Mailutils is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Mailutils. If not, see . */ #ifdef HAVE_CONFIG_H # include #endif } %{ #include #include #include #include #include #include static mu_linetrack_t trk; struct mu_locus_point string_beg; static mu_opool_t pool; static unsigned digit_to_number (char c) { return (unsigned) (c >= '0' && c <= '9' ? c-'0' : c >= 'A' && c <= 'Z' ? c-'A'+10 : c-'a'+10); } static void drop_string (void) { mu_opool_clear (pool); } static void finish_string (void) { mu_opool_append_char (pool, 0); yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); yylval.string.len--; mu_locus_point_copy (&yylloc.end, &yylloc.beg); yylloc.end.mu_col--; mu_locus_point_copy (&yylloc.beg, &string_beg); mu_locus_point_deinit (&string_beg); if (mu_debug_level_p (MU_DEBCAT_APP, MU_DEBUG_TRACE5)) { size_t i; mu_debug_log_begin ("string %zu: ", yylval.string.len); for (i = 0; i < yylval.string.len; i++) if (mu_isprint (yylval.string.ptr[i])) mu_debug_log_cont ("%c", yylval.string.ptr[i]); else mu_debug_log_cont ("\\%03o", yylval.string.ptr[i]); mu_debug_log_nl (); } #if 0 YY_LOCATION_PRINT (stderr, yylloc); fprintf (stderr, ": %s\n", yylval.string.ptr); #endif } #define YY_USER_ACTION \ do \ { \ mu_linetrack_advance (trk, &yylloc, yytext, yyleng); \ mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, \ MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &yylloc); \ } \ while (0); %} %x RULE ARGS ASTRING X [0-9a-fA-F] IDENT [a-zA-Z_\.][a-zA-Z0-9_\.-]* WS [ \t][ \t]* %% { /* Comments */ ^#.*\n ; \n ; ^[^ \t\n/]+"/"[^ \t\n]+ { mu_opool_append (pool, yytext, yyleng); mu_opool_append_char (pool, 0); yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); yylval.string.len--; BEGIN (RULE); return TYPE; } . { mu_error (_("type/subtype is missing")); return BOGUS; } } { \\\n ; \n { BEGIN (INITIAL); return EOL; } {WS} ; /* Operators */ "!"|"+"|","|"("|")"|"/" return yytext[0]; /* Special cases: && and ||. Docs don't say anything about them, but I've found them in my mime.types file... --Sergey */ "&&" return '+'; "||" return ','; "priority"/"(" { return PRIORITY; } {IDENT}/"(" { mu_opool_append (pool, yytext, yyleng); mu_opool_append_char (pool, 0); yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); BEGIN (ARGS); return IDENT; } [a-zA-Z0-9_.-]+/[^(] { mu_opool_append (pool, yytext, yyleng); yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); return STRING; } . mu_error("unexpected character '%c'", yytext[0]); } { "("|"," return yytext[0]; ")" { BEGIN (RULE); return yytext[0]; } {WS} mu_error ("unexpected whitespace in argument list"); \n { mu_error ("unexpected newline in argument list"); return BOGUS; } . { mu_locus_point_copy (&string_beg, &yylloc.beg); mu_linetrack_retreat (trk, 1); yyless (0); BEGIN (ASTRING); } } { /* Quoted string */ \"[^"\n]*\" { mu_opool_append (pool, yytext+1, yyleng-2); } "'"[^'\n]*"'" { mu_opool_append (pool, yytext+1, yyleng-2); } /* Hex string */ "<"({X}{X})+">" { int i; for (i = 1; i < yyleng - 2; i += 2) { mu_opool_append_char (pool, digit_to_number (yytext[i])*16 + digit_to_number (yytext[i+1])); } } /* Unquoted character sequence */ [^ \t\n,)<"']+/[^"'<] { mu_opool_append (pool, yytext, yyleng); } [^ \t\n,)<"]+/< { mu_opool_append (pool, yytext, yyleng); } [^ \t\n,)<"]+/["'] { mu_opool_append (pool, yytext, yyleng); } \n { mu_error ("unexpected newline in argument"); drop_string (); return BOGUS; } . { mu_linetrack_retreat (trk, 1); yyless (0); BEGIN (ARGS); finish_string (); return STRING; } } %% int mimetypes_open (const char *name) { struct stat st; int mode; char *filename; yy_flex_debug = mu_debug_level_p (MU_DEBCAT_APP, MU_DEBUG_TRACE4); if (stat (name, &st)) { mu_error (_("cannot stat `%s': %s"), name, mu_strerror (errno)); return -1; } if (S_ISDIR (st.st_mode)) filename = mu_make_file_name (name, "mime.types"); else filename = mu_strdup (name); yyin = fopen (filename, "r"); if (!yyin) { mu_error (_("cannot open `%s': %s"), filename, mu_strerror (errno)); free (filename); return -1; } MU_ASSERT (mu_linetrack_create (&trk, filename, 3)); free (filename); mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, MU_IOCTL_LOGSTREAM_GET_MODE, &mode); mode |= MU_LOGMODE_LOCUS; mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, MU_IOCTL_LOGSTREAM_SET_MODE, &mode); mu_opool_create (&pool, MU_OPOOL_ENOMEMABRT); return 0; } void mimetypes_close () { int mode; fclose (yyin); mu_locus_range_deinit (&yylloc); mu_linetrack_destroy (&trk); mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, MU_IOCTL_LOGSTREAM_GET_MODE, &mode); mode &= ~MU_LOGMODE_LOCUS; mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, MU_IOCTL_LOGSTREAM_SET_MODE, &mode); mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, NULL); } int yyerror (char *s) { mu_error ("%s", s); return 0; } int yywrap () { return 1; } struct mimetypes_string * mimetypes_string_dup (struct mimetypes_string *s) { mu_opool_append (pool, s, sizeof *s); return mu_opool_finish (pool, NULL); } void * mimetypes_malloc (size_t size) { mu_opool_alloc (pool, size); return mu_opool_finish (pool, NULL); } /* Position input at the beginning of the next rule as a final part of error recovery */ void lex_next_rule (void) { int c; int dbg = yy_flex_debug || mu_debug_level_p (MU_DEBCAT_APP, MU_DEBUG_TRACE6); if (dbg) { YY_LOCATION_PRINT (stderr, yylloc); fprintf (stderr, ": started error recovery\n"); } while ((c = input ()) != EOF) { char ch = c; if (!mu_isspace (c) && mu_linetrack_at_bol (trk)) { unput (c); break; } mu_linetrack_advance (trk, &yylloc, &ch, 1); } if (dbg) { struct mu_locus_range lr = MU_LOCUS_RANGE_INITIALIZER; mu_linetrack_locus (trk, &lr.beg); YY_LOCATION_PRINT (stderr, lr); fprintf (stderr, ": finished error recovery\n"); mu_locus_point_deinit (&lr.beg); } BEGIN (RULE); unput ('\n'); mu_linetrack_retreat (trk, 1); }