Improve mimeview
Old short option '-t' renamed to '-f' for consistency (-f stands for --file in most other utilities). Thus, 'mimevief -f my.types' reads the file 'my.types'. The '-t' option is reused as a short equivalent of the new '--lint' option, which instructs the tool to check the syntax of the mime.types file and exit, ignoring any surplus command line arguments. Added support for priority and regex functions. Improved debugging output. * mimeview/mimetypes.l: Rewrite lexer in a cleaner way. * mimeview/mimetypes.y: Rewrite parser. Track locations. Add line information to nodes and rules. Improve debugging * mimeview/mimeview.c: Remove the debug configuration statement. Using debug { level } provides the same functionality. Use mu_debug for debugging. New option -t (--lint). Rename the -t short option to -f. * mimeview/mimeview.h: Define lexer and parser macros for location tracking. * NEWS: Document changes to mimeview utility. * doc/texinfo/programs.texi: Document changes to mimeview utility. * lib/mailcap.c: Use standart mu_debug calls for debugging. * lib/mailcap.h (display_stream_mailcap): Change last argument: take a mu_debug_handle_t * libmailutils/diag/debcat (app): New category. Application-specific debug * mail/decode.c (display_submessage): Change invocation of display_stream_mailcap. * mail/mailvar.c: Setting "verbose" enables app.trace7, unsetting it clears app.*
Showing
12 changed files
with
532 additions
and
235 deletions
1 | GNU mailutils NEWS -- history of user-visible changes. 2017-04-19 | 1 | GNU mailutils NEWS -- history of user-visible changes. 2017-05-31 |
2 | Copyright (C) 2002-2017 Free Software Foundation, Inc. | 2 | Copyright (C) 2002-2017 Free Software Foundation, Inc. |
3 | See the end of file for copying conditions. | 3 | See the end of file for copying conditions. |
4 | 4 | ||
... | @@ -136,6 +136,19 @@ the implementation in Scheme. The decision has therefore been taken to | ... | @@ -136,6 +136,19 @@ the implementation in Scheme. The decision has therefore been taken to |
136 | discontinue the latter and to concentrate all efforts on the further | 136 | discontinue the latter and to concentrate all efforts on the further |
137 | development of the former. | 137 | development of the former. |
138 | 138 | ||
139 | * mimeview | ||
140 | |||
141 | Old short option '-t' renamed to '-f' for consistency. | ||
142 | Thus, 'mimevief -f my.types' reads the file 'my.types'. | ||
143 | |||
144 | New option '--lint' (short '-t') instructs the tool to check the | ||
145 | syntax of the mime.types file and exit, ignoring any surplus command | ||
146 | line arguments. | ||
147 | |||
148 | Added support for priority and regex functions. | ||
149 | |||
150 | Debugging considerably improved. | ||
151 | |||
139 | 152 | ||
140 | Version 3.2 - 2017-03-11 | 153 | Version 3.2 - 2017-03-11 |
141 | 154 | ... | ... |
... | @@ -7309,22 +7309,28 @@ Enables debugging of @file{mime.types} parser | ... | @@ -7309,22 +7309,28 @@ Enables debugging of @file{mime.types} parser |
7309 | Enables debugging of @file{mime.types} lexical analyzer (warning: | 7309 | Enables debugging of @file{mime.types} lexical analyzer (warning: |
7310 | produces @emph{very} copious output) | 7310 | produces @emph{very} copious output) |
7311 | 7311 | ||
7312 | @item 1 | 7312 | @item 0 |
7313 | Prints basic information about actions to be executed and reports | 7313 | Prints basic information about actions to be executed and reports |
7314 | about exit status of executed commands. | 7314 | about exit status of executed commands. |
7315 | 7315 | ||
7316 | @item 2 | 7316 | @item 1 |
7317 | Additionally displays each file name along with its MIME type | 7317 | Additionally displays each file name along with its MIME type |
7318 | 7318 | ||
7319 | @item 3 | 7319 | @item 2 |
7320 | Additionally traces the process of looking up the matching entry | 7320 | Additionally traces the process of looking up the matching entry |
7321 | in @code{mailcap} files. | 7321 | in @code{mailcap} files. |
7322 | 7322 | ||
7323 | @item digits from 4 to 9 | 7323 | @item 3 |
7324 | The same as 3, currently. | 7324 | Additionally, enables debugging of @file{mime.types} parser (@samp{g}). |
7325 | |||
7326 | @item 4 | ||
7327 | Additionally, enables debugging of @file{mime.types} lexer (@samp{l}). | ||
7328 | |||
7329 | @item digits from 5 to 9 | ||
7330 | The same as 4, currently. | ||
7325 | @end table | 7331 | @end table |
7326 | 7332 | ||
7327 | If @var{flags} are not given, the default @samp{9} is assumed. | 7333 | If @var{flags} are not given, the default @samp{2} is assumed. |
7328 | 7334 | ||
7329 | @item --metamail[=@var{file}] | 7335 | @item --metamail[=@var{file}] |
7330 | Run @command{metamail} to display files, instead of using the internal | 7336 | Run @command{metamail} to display files, instead of using the internal |
... | @@ -7358,10 +7364,15 @@ a @asis{tty} device. | ... | @@ -7358,10 +7364,15 @@ a @asis{tty} device. |
7358 | Do not do anything, just print what would be done. Implies | 7364 | Do not do anything, just print what would be done. Implies |
7359 | @option{--debug=1}, unless the debugging level is set up explicitly. | 7365 | @option{--debug=1}, unless the debugging level is set up explicitly. |
7360 | 7366 | ||
7361 | @item -t @var{file} | 7367 | @item -f @var{file} |
7362 | @itemx --mimetypes @var{file} | 7368 | @itemx --mimetypes @var{file} |
7363 | Use @var{file} as @file{mime.types} file. If @var{file} is a | 7369 | Use @var{file} as @file{mime.types} file. If @var{file} is a |
7364 | directory, use @file{@var{file}/mime.types} | 7370 | directory, use @file{@var{file}/mime.types} |
7371 | |||
7372 | @item -t | ||
7373 | @itemx --lint | ||
7374 | Check syntax of the @file{mime.types} file and exit. Command line | ||
7375 | arguments are ignored. | ||
7365 | @end table | 7376 | @end table |
7366 | 7377 | ||
7367 | @node Mimeview Config | 7378 | @node Mimeview Config |
... | @@ -7375,11 +7386,6 @@ The following configuration statements affect the behavior of | ... | @@ -7375,11 +7386,6 @@ The following configuration statements affect the behavior of |
7375 | @item debug @tab @xref{Debug Statement}. | 7386 | @item debug @tab @xref{Debug Statement}. |
7376 | @end multitable | 7387 | @end multitable |
7377 | 7388 | ||
7378 | @deffn {Mimeview Config} debug @var{number} | ||
7379 | Set @command{mimeview} debug level. @xref{Mimeview Invocation, | ||
7380 | --debug}, for a description of debug levels. | ||
7381 | @end deffn | ||
7382 | |||
7383 | @deffn {Mimeview Config} mimetypes @var{file} | 7389 | @deffn {Mimeview Config} mimetypes @var{file} |
7384 | Read @var{file} instead of the default @file{mime.types}. | 7390 | Read @var{file} instead of the default @file{mime.types}. |
7385 | @end deffn | 7391 | @end deffn | ... | ... |
... | @@ -51,16 +51,14 @@ struct mime_context | ... | @@ -51,16 +51,14 @@ struct mime_context |
51 | int unlink_temp_file; | 51 | int unlink_temp_file; |
52 | 52 | ||
53 | mu_list_t no_ask_types; | 53 | mu_list_t no_ask_types; |
54 | int debug_level; | 54 | int dh; |
55 | int flags; | 55 | int flags; |
56 | }; | 56 | }; |
57 | 57 | ||
58 | #define DEBUG(c,l,f) if ((c)->debug_level > (l)) printf f | ||
59 | |||
60 | static int | 58 | static int |
61 | mime_context_fill (struct mime_context *ctx, const char *file, | 59 | mime_context_fill (struct mime_context *ctx, const char *file, |
62 | mu_stream_t input, mu_header_t hdr, const char *no_ask, | 60 | mu_stream_t input, mu_header_t hdr, const char *no_ask, |
63 | int interactive, int dry_run, int debug_level) | 61 | int interactive, int dry_run, mu_debug_handle_t dh) |
64 | { | 62 | { |
65 | struct mu_wordsplit ws; | 63 | struct mu_wordsplit ws; |
66 | size_t i; | 64 | size_t i; |
... | @@ -91,7 +89,7 @@ mime_context_fill (struct mime_context *ctx, const char *file, | ... | @@ -91,7 +89,7 @@ mime_context_fill (struct mime_context *ctx, const char *file, |
91 | ctx->flags |= FLAGS_INTERACTIVE; | 89 | ctx->flags |= FLAGS_INTERACTIVE; |
92 | if (dry_run) | 90 | if (dry_run) |
93 | ctx->flags |= FLAGS_DRY_RUN; | 91 | ctx->flags |= FLAGS_DRY_RUN; |
94 | ctx->debug_level = debug_level; | 92 | ctx->dh = dh; |
95 | 93 | ||
96 | mu_list_create (&ctx->values); | 94 | mu_list_create (&ctx->values); |
97 | 95 | ||
... | @@ -339,7 +337,7 @@ confirm_action (struct mime_context *ctx, const char *str) | ... | @@ -339,7 +337,7 @@ confirm_action (struct mime_context *ctx, const char *str) |
339 | char *type; | 337 | char *type; |
340 | 338 | ||
341 | mime_context_get_content_type (ctx, &type); | 339 | mime_context_get_content_type (ctx, &type); |
342 | if (dry_run_p (ctx) || !interactive_p (ctx) || mime_context_do_not_ask (ctx)) | 340 | if (!interactive_p (ctx) || mime_context_do_not_ask (ctx)) |
343 | return 1; | 341 | return 1; |
344 | 342 | ||
345 | printf (_("Run `%s'?"), str); | 343 | printf (_("Run `%s'?"), str); |
... | @@ -540,7 +538,7 @@ run_mailcap (mu_mailcap_entry_t entry, struct mime_context *ctx) | ... | @@ -540,7 +538,7 @@ run_mailcap (mu_mailcap_entry_t entry, struct mime_context *ctx) |
540 | int outfd = -1; | 538 | int outfd = -1; |
541 | pid_t pid; | 539 | pid_t pid; |
542 | 540 | ||
543 | if (ctx->debug_level > 1) | 541 | if (mu_debug_level_p (ctx->dh, MU_DEBUG_TRACE3)) |
544 | dump_mailcap_entry (entry); | 542 | dump_mailcap_entry (entry); |
545 | 543 | ||
546 | if (run_test (entry, ctx)) | 544 | if (run_test (entry, ctx)) |
... | @@ -571,11 +569,13 @@ run_mailcap (mu_mailcap_entry_t entry, struct mime_context *ctx) | ... | @@ -571,11 +569,13 @@ run_mailcap (mu_mailcap_entry_t entry, struct mime_context *ctx) |
571 | pfd = NULL; | 569 | pfd = NULL; |
572 | else | 570 | else |
573 | pfd = &fd; | 571 | pfd = &fd; |
574 | DEBUG (ctx, 0, (_("Executing %s...\n"), view_command)); | 572 | mu_debug (ctx->dh, MU_DEBUG_TRACE0, (_("executing %s...\n"), view_command)); |
575 | 573 | ||
576 | if (!confirm_action (ctx, view_command)) | 574 | if (!confirm_action (ctx, view_command)) |
577 | return 1; | 575 | return 1; |
578 | 576 | if (dry_run_p (ctx)) | |
577 | return 0; | ||
578 | |||
579 | flag = 0; | 579 | flag = 0; |
580 | if (interactive_p (ctx) | 580 | if (interactive_p (ctx) |
581 | && mu_mailcap_entry_copiousoutput (entry, &flag) == 0 && flag) | 581 | && mu_mailcap_entry_copiousoutput (entry, &flag) == 0 && flag) |
... | @@ -596,7 +596,7 @@ run_mailcap (mu_mailcap_entry_t entry, struct mime_context *ctx) | ... | @@ -596,7 +596,7 @@ run_mailcap (mu_mailcap_entry_t entry, struct mime_context *ctx) |
596 | mu_error ("waitpid: %s", mu_strerror (errno)); | 596 | mu_error ("waitpid: %s", mu_strerror (errno)); |
597 | break; | 597 | break; |
598 | } | 598 | } |
599 | if (ctx->debug_level) | 599 | if (mu_debug_level_p (ctx->dh, MU_DEBUG_TRACE0)) |
600 | print_exit_status (status); | 600 | print_exit_status (status); |
601 | } | 601 | } |
602 | return 0; | 602 | return 0; |
... | @@ -610,7 +610,7 @@ find_entry (const char *file, struct mime_context *ctx) | ... | @@ -610,7 +610,7 @@ find_entry (const char *file, struct mime_context *ctx) |
610 | mu_stream_t stream; | 610 | mu_stream_t stream; |
611 | int rc = 1; | 611 | int rc = 1; |
612 | 612 | ||
613 | DEBUG (ctx, 2, (_("Trying %s...\n"), file)); | 613 | mu_debug (ctx->dh, MU_DEBUG_TRACE1, (_("trying %s...\n"), file)); |
614 | status = mu_file_stream_create (&stream, file, MU_STREAM_READ); | 614 | status = mu_file_stream_create (&stream, file, MU_STREAM_READ); |
615 | if (status) | 615 | if (status) |
616 | { | 616 | { |
... | @@ -643,7 +643,7 @@ find_entry (const char *file, struct mime_context *ctx) | ... | @@ -643,7 +643,7 @@ find_entry (const char *file, struct mime_context *ctx) |
643 | 643 | ||
644 | if (fnmatch (buffer, type, FNM_CASEFOLD) == 0) | 644 | if (fnmatch (buffer, type, FNM_CASEFOLD) == 0) |
645 | { | 645 | { |
646 | DEBUG (ctx, 2, (_("Found in %s\n"), file)); | 646 | mu_debug (ctx->dh, MU_DEBUG_TRACE1, (_("found in %s\n"), file)); |
647 | if (run_mailcap (entry, ctx) == 0) | 647 | if (run_mailcap (entry, ctx) == 0) |
648 | { | 648 | { |
649 | rc = 0; | 649 | rc = 0; |
... | @@ -664,7 +664,7 @@ find_entry (const char *file, struct mime_context *ctx) | ... | @@ -664,7 +664,7 @@ find_entry (const char *file, struct mime_context *ctx) |
664 | int | 664 | int |
665 | display_stream_mailcap (const char *ident, mu_stream_t stream, mu_header_t hdr, | 665 | display_stream_mailcap (const char *ident, mu_stream_t stream, mu_header_t hdr, |
666 | const char *no_ask, int interactive, int dry_run, | 666 | const char *no_ask, int interactive, int dry_run, |
667 | int debug_level) | 667 | mu_debug_handle_t dh) |
668 | { | 668 | { |
669 | char *mailcap_path, *mailcap_path_tmp = NULL; | 669 | char *mailcap_path, *mailcap_path_tmp = NULL; |
670 | struct mu_wordsplit ws; | 670 | struct mu_wordsplit ws; |
... | @@ -672,7 +672,7 @@ display_stream_mailcap (const char *ident, mu_stream_t stream, mu_header_t hdr, | ... | @@ -672,7 +672,7 @@ display_stream_mailcap (const char *ident, mu_stream_t stream, mu_header_t hdr, |
672 | int rc = 1; | 672 | int rc = 1; |
673 | 673 | ||
674 | if (mime_context_fill (&ctx, ident, stream, hdr, | 674 | if (mime_context_fill (&ctx, ident, stream, hdr, |
675 | no_ask, interactive, dry_run, debug_level)) | 675 | no_ask, interactive, dry_run, dh)) |
676 | return 1; | 676 | return 1; |
677 | mailcap_path = getenv ("MAILCAP"); | 677 | mailcap_path = getenv ("MAILCAP"); |
678 | if (!mailcap_path) | 678 | if (!mailcap_path) | ... | ... |
1 | extern int display_stream_mailcap (const char *ident, mu_stream_t stream, | 1 | extern int display_stream_mailcap (const char *ident, mu_stream_t stream, |
2 | mu_header_t hdr, const char *no_ask, | 2 | mu_header_t hdr, const char *no_ask, |
3 | int interactive, int dry_run, | 3 | int interactive, int dry_run, |
4 | int debug_level); | 4 | mu_debug_handle_t dh); |
5 | 5 | ... | ... |
... | @@ -284,14 +284,11 @@ display_submessage (struct mime_descend_closure *closure, void *data) | ... | @@ -284,14 +284,11 @@ display_submessage (struct mime_descend_closure *closure, void *data) |
284 | if (mailvar_is_true ("metamail")) | 284 | if (mailvar_is_true ("metamail")) |
285 | { | 285 | { |
286 | char *no_ask = NULL; | 286 | char *no_ask = NULL; |
287 | int debug = 0; | ||
288 | 287 | ||
289 | mailvar_get (&no_ask, "mimenoask", mailvar_type_string, 0); | 288 | mailvar_get (&no_ask, "mimenoask", mailvar_type_string, 0); |
290 | if (mailvar_is_true ("verbose")) | ||
291 | debug = 9; | ||
292 | |||
293 | builtin_display = display_stream_mailcap (NULL, stream, hdr, no_ask, | 289 | builtin_display = display_stream_mailcap (NULL, stream, hdr, no_ask, |
294 | interactive, 0, debug); | 290 | interactive, 0, |
291 | MU_DEBCAT_APP); | ||
295 | } | 292 | } |
296 | 293 | ||
297 | if (builtin_display) | 294 | if (builtin_display) | ... | ... |
... | @@ -44,6 +44,8 @@ static int set_replyregex (enum mailvar_cmd cmd, | ... | @@ -44,6 +44,8 @@ static int set_replyregex (enum mailvar_cmd cmd, |
44 | struct mailvar_variable *); | 44 | struct mailvar_variable *); |
45 | static int set_screen (enum mailvar_cmd cmd, | 45 | static int set_screen (enum mailvar_cmd cmd, |
46 | struct mailvar_variable *); | 46 | struct mailvar_variable *); |
47 | static int set_verbose (enum mailvar_cmd cmd, | ||
48 | struct mailvar_variable *); | ||
47 | static int set_debug (enum mailvar_cmd cmd, | 49 | static int set_debug (enum mailvar_cmd cmd, |
48 | struct mailvar_variable *); | 50 | struct mailvar_variable *); |
49 | static int set_folder (enum mailvar_cmd cmd, | 51 | static int set_folder (enum mailvar_cmd cmd, |
... | @@ -272,7 +274,8 @@ struct mailvar_symbol mailvar_tab[] = | ... | @@ -272,7 +274,8 @@ struct mailvar_symbol mailvar_tab[] = |
272 | { { "varstrict", }, MAILVAR_ALIAS }, | 274 | { { "varstrict", }, MAILVAR_ALIAS }, |
273 | { { "verbose", }, | 275 | { { "verbose", }, |
274 | MAILVAR_TYPEMASK (mailvar_type_boolean), | 276 | MAILVAR_TYPEMASK (mailvar_type_boolean), |
275 | N_("verbosely trace the process of message delivery") }, | 277 | N_("verbosely trace the process of message delivery"), |
278 | set_verbose }, | ||
276 | { { "xmailer", }, | 279 | { { "xmailer", }, |
277 | MAILVAR_TYPEMASK (mailvar_type_boolean), | 280 | MAILVAR_TYPEMASK (mailvar_type_boolean), |
278 | N_("add the `X-Mailer' header to the outgoing messages") }, | 281 | N_("add the `X-Mailer' header to the outgoing messages") }, |
... | @@ -666,6 +669,21 @@ set_screen (enum mailvar_cmd cmd, struct mailvar_variable *var) | ... | @@ -666,6 +669,21 @@ set_screen (enum mailvar_cmd cmd, struct mailvar_variable *var) |
666 | #define DEFAULT_DEBUG_LEVEL MU_DEBUG_LEVEL_UPTO (MU_DEBUG_TRACE7) | 669 | #define DEFAULT_DEBUG_LEVEL MU_DEBUG_LEVEL_UPTO (MU_DEBUG_TRACE7) |
667 | 670 | ||
668 | static int | 671 | static int |
672 | set_verbose (enum mailvar_cmd cmd, struct mailvar_variable *var) | ||
673 | { | ||
674 | switch (cmd) | ||
675 | { | ||
676 | case mailvar_cmd_set: | ||
677 | mu_debug_set_category_level (MU_DEBCAT_APP, DEFAULT_DEBUG_LEVEL); | ||
678 | break; | ||
679 | |||
680 | case mailvar_cmd_unset: | ||
681 | mu_debug_set_category_level (MU_DEBCAT_APP, 0); | ||
682 | } | ||
683 | return 0; | ||
684 | } | ||
685 | |||
686 | static int | ||
669 | set_debug (enum mailvar_cmd cmd, struct mailvar_variable *var) | 687 | set_debug (enum mailvar_cmd cmd, struct mailvar_variable *var) |
670 | { | 688 | { |
671 | mu_debug_clear_all (); | 689 | mu_debug_clear_all (); | ... | ... |
... | @@ -28,13 +28,11 @@ | ... | @@ -28,13 +28,11 @@ |
28 | #include <mimeview.h> | 28 | #include <mimeview.h> |
29 | #include <mimetypes-decl.h> | 29 | #include <mimetypes-decl.h> |
30 | #include <mailutils/io.h> | 30 | #include <mailutils/io.h> |
31 | |||
32 | static int line_num; | ||
33 | static char *file_name; | ||
34 | static int file_name_alloc; | ||
35 | 31 | ||
32 | static struct mu_locus loc; | ||
33 | static int newline; | ||
34 | |||
36 | static mu_opool_t pool; | 35 | static mu_opool_t pool; |
37 | static int prev_state; | ||
38 | 36 | ||
39 | static unsigned | 37 | static unsigned |
40 | digit_to_number (char c) | 38 | digit_to_number (char c) |
... | @@ -43,106 +41,121 @@ digit_to_number (char c) | ... | @@ -43,106 +41,121 @@ digit_to_number (char c) |
43 | c >= 'A' && c <= 'Z' ? c-'A'+10 : | 41 | c >= 'A' && c <= 'Z' ? c-'A'+10 : |
44 | c-'a'+10); | 42 | c-'a'+10); |
45 | } | 43 | } |
44 | |||
45 | static void | ||
46 | advance_locus (void) | ||
47 | { | ||
48 | if (newline) | ||
49 | { | ||
50 | loc.mu_line++; | ||
51 | loc.mu_col = 1; | ||
52 | } | ||
53 | yylloc.beg = loc; | ||
54 | loc.mu_col += yyleng; | ||
55 | yylloc.end = loc; | ||
56 | yylloc.end.mu_col--; | ||
57 | |||
58 | newline = yytext[yyleng-1] == '\n'; | ||
59 | mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, | ||
60 | MU_IOCTL_LOGSTREAM_SET_LOCUS, &loc); | ||
61 | } | ||
62 | |||
63 | #define YY_USER_ACTION advance_locus (); | ||
64 | |||
46 | %} | 65 | %} |
47 | 66 | ||
48 | %option nounput | 67 | %option nounput |
49 | %option noinput | 68 | %option noinput |
50 | 69 | ||
51 | %x ARGS HEX | 70 | %s RULE ARGS |
52 | X [0-9a-fA-F] | 71 | X [0-9a-fA-F] |
53 | IDENT [a-zA-Z_\.][a-zA-Z0-9_\.-]* | 72 | IDENT [a-zA-Z_\.][a-zA-Z0-9_\.-]* |
54 | WS [ \t]* | 73 | WS [ \t]* |
55 | %% | 74 | %% |
56 | /* Comments */ | 75 | /* Comments */ |
57 | <INITIAL>#.*\n { line_num++; } | 76 | ^#.*\n ; |
58 | <INITIAL>#.* /* end-of-file comment */; | ||
59 | /* Tokens */ | 77 | /* Tokens */ |
60 | \\\n { line_num++; } | 78 | \\\n ; |
61 | \n { line_num++; return EOL; } | 79 | \n+ { loc.mu_line += yyleng - 1; return EOL; } |
62 | {WS} ; | 80 | {WS} ; |
63 | {IDENT} { | 81 | <INITIAL,RULE>^[^ \t\n/]+"/"[^ \t\n]+ { |
64 | mu_opool_append (pool, yytext, yyleng); | 82 | mu_opool_append (pool, yytext, yyleng); |
65 | mu_opool_append_char (pool, 0); | 83 | mu_opool_append_char (pool, 0); |
66 | yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); | 84 | yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); |
67 | return IDENT; | 85 | BEGIN (RULE); |
86 | return TYPE; | ||
87 | } | ||
88 | |||
89 | <RULE>"priority"/"(" { | ||
90 | return PRIORITY; | ||
68 | } | 91 | } |
69 | <INITIAL>{IDENT}"(" { | 92 | <RULE>{IDENT}/"(" { |
70 | mu_opool_append (pool, yytext, yyleng-1); | 93 | mu_opool_append (pool, yytext, yyleng); |
71 | mu_opool_append_char (pool, 0); | 94 | mu_opool_append_char (pool, 0); |
72 | yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); | 95 | yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); |
73 | BEGIN(ARGS); | 96 | return IDENT; |
74 | return IDENT_L; | ||
75 | } | 97 | } |
76 | <INITIAL,ARGS>\"[^\\"\n]*\" { | 98 | <RULE>{IDENT} { |
77 | mu_opool_append (pool, yytext+1, yyleng-2); | 99 | mu_opool_append (pool, yytext, yyleng); |
78 | mu_opool_append_char (pool, 0); | 100 | mu_opool_append_char (pool, 0); |
79 | yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); | 101 | yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); |
80 | return STRING; | 102 | return STRING; |
81 | } | 103 | } |
82 | <INITIAL,ARGS>"<" { | 104 | <RULE,ARGS>\"[^"\n]*\" { |
83 | prev_state = YYSTATE; | 105 | mu_opool_append (pool, yytext+1, yyleng-2); |
84 | BEGIN(HEX); | ||
85 | } | ||
86 | <ARGS>[^ \t<\\\n),]+/[),] { | ||
87 | mu_opool_append (pool, yytext, yyleng); | ||
88 | mu_opool_append_char (pool, 0); | 106 | mu_opool_append_char (pool, 0); |
89 | yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); | 107 | yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); |
90 | return STRING; | 108 | return STRING; |
91 | } | 109 | } |
92 | <ARGS>[^ \t<\\\n),]+< { | 110 | <RULE,ARGS>"<"({X}{X})+">" { |
93 | mu_opool_append (pool, yytext, yyleng); | 111 | int i; |
94 | prev_state = YYSTATE; | 112 | for (i = 0; i < yyleng; i += 2) |
95 | BEGIN(HEX); | 113 | { |
114 | mu_opool_append_char (pool, digit_to_number (yytext[i])*16 | ||
115 | + digit_to_number (yytext[i+1])); | ||
116 | } | ||
117 | yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); | ||
118 | return STRING; | ||
96 | } | 119 | } |
97 | <INITIAL>[^ \t<\\\n)+,&]/[ \t\\\n)+,&] { | 120 | <ARGS>[^ \t<\n),<"]+/[),<"] { |
98 | mu_opool_append (pool, yytext, yyleng); | 121 | mu_opool_append (pool, yytext, yyleng); |
99 | mu_opool_append_char (pool, 0); | 122 | mu_opool_append_char (pool, 0); |
100 | yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); | 123 | yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); |
101 | return STRING; | 124 | return STRING; |
102 | } | 125 | } |
103 | <ARGS>[^ \t<\\\n),]/[ \t\\\n] { | 126 | <RULE>[^ \t<\\\n)+,&]/[ \t\\\n)+,&] { |
104 | mu_opool_append (pool, yytext, yyleng); | 127 | mu_opool_append (pool, yytext, yyleng); |
105 | mu_opool_append_char (pool, 0); | 128 | mu_opool_append_char (pool, 0); |
106 | yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); | 129 | yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); |
107 | return STRING; | 130 | return STRING; |
108 | } | 131 | } |
109 | <HEX>{X}{X} { | 132 | <ARGS>[^ \t<\\\n),]/[ \t\\\n] { |
110 | int c = digit_to_number (yytext[0])*16 + digit_to_number (yytext[1]); | 133 | mu_opool_append (pool, yytext, yyleng); |
111 | mu_opool_append_char (pool, c); | ||
112 | } | ||
113 | <HEX>">"/[ \t\\\n,)] { | ||
114 | BEGIN(prev_state); | ||
115 | mu_opool_append_char (pool, 0); | 134 | mu_opool_append_char (pool, 0); |
116 | yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); | 135 | yylval.string.ptr = mu_opool_finish (pool, &yylval.string.len); |
117 | return STRING; | 136 | return STRING; |
118 | } | 137 | } |
119 | <HEX>">" { | ||
120 | BEGIN(prev_state); | ||
121 | } | ||
122 | /* Special cases: && and ||. Docs don't say anything about them, but | 138 | /* Special cases: && and ||. Docs don't say anything about them, but |
123 | I've found them in my mime.types file... --Sergey */ | 139 | I've found them in my mime.types file... --Sergey */ |
124 | "&&" return '+'; | 140 | "&&" return '+'; |
125 | "||" return ','; | 141 | "||" return ','; |
126 | /* Operators */ | 142 | /* Operators */ |
127 | "!"|"+"|","|"("|")"|"/" return yytext[0]; | 143 | <RULE>"!"|"+"|","|"("|")"|"/" return yytext[0]; |
128 | <ARGS>"," return yytext[0]; | 144 | <ARGS>"," return yytext[0]; |
129 | <ARGS>")" { BEGIN(INITIAL); return yytext[0]; } | 145 | <ARGS>")" { BEGIN (RULE); return yytext[0]; } |
130 | <INITIAL,ARGS,HEX>. { | 146 | <*>. { |
131 | fprintf (stderr, "Invalid character '%c', state %d\n", yytext[0], YYSTATE); | 147 | mu_error ("invalid character '%c', state %d", yytext[0], YYSTATE); |
132 | abort(); | 148 | return BOGUS; |
133 | } | 149 | } |
134 | %% | 150 | %% |
135 | |||
136 | void | ||
137 | mimetypes_lex_debug (int level) | ||
138 | { | ||
139 | yy_flex_debug = level; | ||
140 | } | ||
141 | |||
142 | int | 151 | int |
143 | mimetypes_open (const char *name) | 152 | mimetypes_open (const char *name) |
144 | { | 153 | { |
145 | struct stat st; | 154 | struct stat st; |
155 | int mode; | ||
156 | |||
157 | yy_flex_debug = mu_debug_level_p (MU_DEBCAT_MIME, MU_DEBUG_TRACE4); | ||
158 | |||
146 | if (stat (name, &st)) | 159 | if (stat (name, &st)) |
147 | { | 160 | { |
148 | mu_error (_("cannot stat `%s': %s"), name, mu_strerror (errno)); | 161 | mu_error (_("cannot stat `%s': %s"), name, mu_strerror (errno)); |
... | @@ -150,28 +163,29 @@ mimetypes_open (const char *name) | ... | @@ -150,28 +163,29 @@ mimetypes_open (const char *name) |
150 | } | 163 | } |
151 | 164 | ||
152 | if (S_ISDIR (st.st_mode)) | 165 | if (S_ISDIR (st.st_mode)) |
153 | { | 166 | loc.mu_file = mu_make_file_name (name, "mime.types"); |
154 | file_name = mu_make_file_name (name, "mime.types"); | ||
155 | file_name_alloc = 1; | ||
156 | } | ||
157 | else | 167 | else |
158 | { | 168 | loc.mu_file = mu_strdup (name); |
159 | file_name = (char*) name; | 169 | loc.mu_line = 1; |
160 | file_name_alloc = 0; | 170 | loc.mu_col = 1; |
161 | } | 171 | newline = 0; |
162 | 172 | ||
163 | yyin = fopen (file_name, "r"); | 173 | yyin = fopen (loc.mu_file, "r"); |
164 | if (!yyin) | 174 | if (!yyin) |
165 | { | 175 | { |
166 | mu_error (_("Cannot open `%s': %s"), file_name, mu_strerror (errno)); | 176 | mu_error (_("cannot open `%s': %s"), loc.mu_file, mu_strerror (errno)); |
167 | if (file_name_alloc) | 177 | free (loc.mu_file); |
168 | { | ||
169 | free (file_name); | ||
170 | file_name_alloc = 0; | ||
171 | } | ||
172 | return -1; | 178 | return -1; |
173 | } | 179 | } |
174 | line_num = 1; | 180 | |
181 | mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, | ||
182 | MU_IOCTL_LOGSTREAM_GET_MODE, &mode); | ||
183 | mode |= MU_LOGMODE_LOCUS; | ||
184 | mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, | ||
185 | MU_IOCTL_LOGSTREAM_SET_MODE, &mode); | ||
186 | mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, | ||
187 | MU_IOCTL_LOGSTREAM_SET_LOCUS, &loc); | ||
188 | |||
175 | mu_opool_create (&pool, MU_OPOOL_ENOMEMABRT); | 189 | mu_opool_create (&pool, MU_OPOOL_ENOMEMABRT); |
176 | return 0; | 190 | return 0; |
177 | } | 191 | } |
... | @@ -179,18 +193,25 @@ mimetypes_open (const char *name) | ... | @@ -179,18 +193,25 @@ mimetypes_open (const char *name) |
179 | void | 193 | void |
180 | mimetypes_close () | 194 | mimetypes_close () |
181 | { | 195 | { |
196 | int mode; | ||
197 | |||
182 | fclose (yyin); | 198 | fclose (yyin); |
183 | if (file_name_alloc) | 199 | /* FIXME: Don't free (loc.mu_file), because it is referenced by |
184 | { | 200 | mu_locus structures in the parse tree */ |
185 | free (file_name); | 201 | |
186 | file_name_alloc = 0; | 202 | mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, |
187 | } | 203 | MU_IOCTL_LOGSTREAM_GET_MODE, &mode); |
204 | mode &= ~MU_LOGMODE_LOCUS; | ||
205 | mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, | ||
206 | MU_IOCTL_LOGSTREAM_SET_MODE, &mode); | ||
207 | mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, | ||
208 | MU_IOCTL_LOGSTREAM_SET_LOCUS, NULL); | ||
188 | } | 209 | } |
189 | 210 | ||
190 | int | 211 | int |
191 | yyerror (char *s) | 212 | yyerror (char *s) |
192 | { | 213 | { |
193 | mu_error ("%s:%d: %s", file_name, line_num, s); | 214 | mu_error (s); |
194 | return 0; | 215 | return 0; |
195 | } | 216 | } |
196 | 217 | ||
... | @@ -200,22 +221,6 @@ yywrap () | ... | @@ -200,22 +221,6 @@ yywrap () |
200 | return 1; | 221 | return 1; |
201 | } | 222 | } |
202 | 223 | ||
203 | struct mimetypes_string | ||
204 | mimetypes_append_string2 (struct mimetypes_string *s1, | ||
205 | char c, | ||
206 | struct mimetypes_string *s2) | ||
207 | { | ||
208 | struct mimetypes_string r; | ||
209 | |||
210 | r.len = s1->len + s2->len + 1; | ||
211 | mu_opool_append (pool, s1->ptr, s1->len); | ||
212 | mu_opool_append_char (pool, c); | ||
213 | mu_opool_append (pool, s2->ptr, s2->len); | ||
214 | mu_opool_append_char (pool, 0); | ||
215 | r.ptr = mu_opool_finish (pool, NULL); | ||
216 | return r; | ||
217 | } | ||
218 | |||
219 | struct mimetypes_string * | 224 | struct mimetypes_string * |
220 | mimetypes_string_dup (struct mimetypes_string *s) | 225 | mimetypes_string_dup (struct mimetypes_string *s) |
221 | { | 226 | { |
... | @@ -231,9 +236,21 @@ mimetypes_malloc (size_t size) | ... | @@ -231,9 +236,21 @@ mimetypes_malloc (size_t size) |
231 | } | 236 | } |
232 | 237 | ||
233 | void | 238 | void |
234 | reset_lex () | 239 | lex_arglist (int enable) |
235 | { | 240 | { |
236 | BEGIN(INITIAL); | 241 | if (enable) |
242 | BEGIN (ARGS); | ||
243 | else | ||
244 | BEGIN (RULE); | ||
237 | } | 245 | } |
238 | 246 | ||
239 | 247 | void | |
248 | lex_concat (struct concat_segm *p, struct mimetypes_string *ret) | ||
249 | { | ||
250 | for (; p; p = p->next) | ||
251 | { | ||
252 | mu_opool_appendz (pool, p->val); | ||
253 | } | ||
254 | mu_opool_append_char (pool, 0); | ||
255 | ret->ptr = mu_opool_finish (pool, &ret->len); | ||
256 | } | ... | ... |
... | @@ -23,6 +23,7 @@ | ... | @@ -23,6 +23,7 @@ |
23 | #include <mailutils/cctype.h> | 23 | #include <mailutils/cctype.h> |
24 | #include <mimeview.h> | 24 | #include <mimeview.h> |
25 | #include <mimetypes-decl.h> | 25 | #include <mimetypes-decl.h> |
26 | #include <regex.h> | ||
26 | 27 | ||
27 | static void | 28 | static void |
28 | yyprint (FILE *output, unsigned short toknum, YYSTYPE val) | 29 | yyprint (FILE *output, unsigned short toknum, YYSTYPE val) |
... | @@ -30,14 +31,20 @@ yyprint (FILE *output, unsigned short toknum, YYSTYPE val) | ... | @@ -30,14 +31,20 @@ yyprint (FILE *output, unsigned short toknum, YYSTYPE val) |
30 | switch (toknum) | 31 | switch (toknum) |
31 | { | 32 | { |
32 | case IDENT: | 33 | case IDENT: |
33 | case IDENT_L: | ||
34 | case STRING: | 34 | case STRING: |
35 | fprintf (output, "[%lu] %s", (unsigned long) val.string.len, | 35 | fprintf (output, "[%lu] %s", (unsigned long) val.string.len, |
36 | val.string.ptr); | 36 | val.string.ptr); |
37 | break; | 37 | break; |
38 | 38 | ||
39 | case EOL: | 39 | case EOL: |
40 | fprintf (output, "\\n"); | ||
41 | break; | ||
42 | |||
40 | default: | 43 | default: |
44 | if (mu_isprint (toknum)) | ||
45 | fprintf (output, "'%c'", toknum); | ||
46 | else | ||
47 | fprintf (output, "tok(%d)", toknum); | ||
41 | break; | 48 | break; |
42 | } | 49 | } |
43 | } | 50 | } |
... | @@ -51,6 +58,7 @@ static mu_list_t arg_list; /* For error recovery */ | ... | @@ -51,6 +58,7 @@ static mu_list_t arg_list; /* For error recovery */ |
51 | 58 | ||
52 | enum node_type | 59 | enum node_type |
53 | { | 60 | { |
61 | true_node, | ||
54 | functional_node, | 62 | functional_node, |
55 | binary_node, | 63 | binary_node, |
56 | negation_node, | 64 | negation_node, |
... | @@ -62,6 +70,7 @@ union argument | ... | @@ -62,6 +70,7 @@ union argument |
62 | struct mimetypes_string *string; | 70 | struct mimetypes_string *string; |
63 | unsigned number; | 71 | unsigned number; |
64 | int c; | 72 | int c; |
73 | regex_t rx; | ||
65 | }; | 74 | }; |
66 | 75 | ||
67 | typedef int (*builtin_t) (union argument *args); | 76 | typedef int (*builtin_t) (union argument *args); |
... | @@ -69,6 +78,7 @@ typedef int (*builtin_t) (union argument *args); | ... | @@ -69,6 +78,7 @@ typedef int (*builtin_t) (union argument *args); |
69 | struct node | 78 | struct node |
70 | { | 79 | { |
71 | enum node_type type; | 80 | enum node_type type; |
81 | struct mu_locus_range loc; | ||
72 | union | 82 | union |
73 | { | 83 | { |
74 | struct | 84 | struct |
... | @@ -87,41 +97,56 @@ struct node | ... | @@ -87,41 +97,56 @@ struct node |
87 | } v; | 97 | } v; |
88 | }; | 98 | }; |
89 | 99 | ||
100 | static struct node *make_node (enum node_type type, | ||
101 | struct mu_locus_range const *loc); | ||
90 | static struct node *make_binary_node (int op, | 102 | static struct node *make_binary_node (int op, |
91 | struct node *left, struct node *rigth); | 103 | struct node *left, struct node *rigth, |
92 | static struct node *make_negation_node (struct node *p); | 104 | struct mu_locus_range const *loc); |
105 | static struct node *make_negation_node (struct node *p, | ||
106 | struct mu_locus_range const *loc); | ||
93 | 107 | ||
94 | static struct node *make_suffix_node (struct mimetypes_string *suffix); | 108 | static struct node *make_suffix_node (struct mimetypes_string *suffix, |
95 | static struct node *make_functional_node (char *ident, mu_list_t list); | 109 | struct mu_locus_range const *loc); |
110 | static struct node *make_functional_node (char *ident, mu_list_t list, | ||
111 | struct mu_locus_range const *loc); | ||
96 | 112 | ||
97 | static int eval_rule (struct node *root); | 113 | static int eval_rule (struct node *root); |
98 | 114 | ||
99 | struct rule_tab | 115 | struct rule_tab |
100 | { | 116 | { |
101 | char *type; | 117 | char *type; |
118 | int priority; | ||
119 | struct mu_locus_range loc; | ||
102 | struct node *node; | 120 | struct node *node; |
103 | }; | 121 | }; |
104 | 122 | ||
105 | static mu_list_t rule_list; | 123 | static mu_list_t rule_list; |
106 | |||
107 | %} | 124 | %} |
108 | 125 | ||
109 | %token <string> IDENT IDENT_L | 126 | %locations |
127 | |||
128 | %token <string> TYPE IDENT | ||
110 | %token <string> STRING | 129 | %token <string> STRING |
111 | %token EOL BOGUS | 130 | %token EOL BOGUS PRIORITY |
112 | 131 | ||
113 | %left ',' | 132 | %left ',' |
114 | %left '+' | 133 | %left '+' |
115 | 134 | ||
116 | %type <string> string arg type | 135 | %type <string> string arg |
117 | %type <list> arglist | 136 | %type <list> arglist |
118 | %type <node> function stmt rule | 137 | %type <node> function stmt rule maybe_rule |
138 | %type <result> priority maybe_priority | ||
139 | %type <concat> concat; | ||
140 | %type <segment> simple_string | ||
119 | 141 | ||
120 | %union { | 142 | %union { |
121 | struct mimetypes_string string; | 143 | struct mimetypes_string string; |
144 | char *s; | ||
122 | mu_list_t list; | 145 | mu_list_t list; |
123 | int result; | 146 | int result; |
124 | struct node *node; | 147 | struct node *node; |
148 | struct { struct concat_segm *head, *tail; } concat; | ||
149 | struct concat_segm *segment; | ||
125 | } | 150 | } |
126 | 151 | ||
127 | %% | 152 | %% |
... | @@ -130,56 +155,65 @@ input : list | ... | @@ -130,56 +155,65 @@ input : list |
130 | ; | 155 | ; |
131 | 156 | ||
132 | list : rule_line | 157 | list : rule_line |
133 | | list eol rule_line | 158 | | list EOL rule_line |
134 | ; | 159 | ; |
135 | 160 | ||
136 | rule_line: /* empty */ | 161 | rule_line: /* empty */ |
137 | | type rule | 162 | | TYPE maybe_rule maybe_priority |
138 | { | 163 | { |
139 | struct rule_tab *p = mimetypes_malloc (sizeof (*p)); | 164 | struct rule_tab *p = mimetypes_malloc (sizeof (*p)); |
140 | if (!rule_list) | 165 | if (!rule_list) |
141 | mu_list_create (&rule_list); | 166 | mu_list_create (&rule_list); |
142 | p->type = $1.ptr; | 167 | p->type = $1.ptr; |
143 | p->node = $2; | 168 | p->node = $2; |
169 | p->priority = $3; | ||
170 | p->loc.beg = @1.beg; | ||
171 | p->loc.end = @3.end; | ||
144 | mu_list_append (rule_list, p); | 172 | mu_list_append (rule_list, p); |
145 | } | 173 | } |
146 | | error eol | 174 | | error EOL |
147 | { | 175 | { |
148 | if (arg_list) | 176 | if (arg_list) |
149 | mu_list_destroy (&arg_list); | 177 | mu_list_destroy (&arg_list); |
150 | arg_list = NULL; | 178 | arg_list = NULL; |
151 | reset_lex (); | 179 | lex_arglist (0); |
152 | } | 180 | } |
153 | ; | 181 | ; |
154 | 182 | ||
155 | eol : EOL | 183 | maybe_rule: /* empty */ |
156 | | eol EOL | ||
157 | ; | ||
158 | |||
159 | type : IDENT '/' IDENT | ||
160 | { | 184 | { |
161 | $$ = mimetypes_append_string2 (&$1, '/', &$3); | 185 | $$ = make_node (true_node, &yylloc); |
162 | } | 186 | } |
163 | ; | 187 | | rule |
188 | ; | ||
164 | 189 | ||
165 | rule : stmt | 190 | rule : stmt |
166 | | rule rule %prec ',' | 191 | | rule rule %prec ',' |
167 | { | 192 | { |
168 | $$ = make_binary_node (L_OR, $1, $2); | 193 | struct mu_locus_range lr; |
194 | lr.beg = @1.beg; | ||
195 | lr.end = @2.end; | ||
196 | $$ = make_binary_node (L_OR, $1, $2, &lr); | ||
169 | } | 197 | } |
170 | | rule ',' rule | 198 | | rule ',' rule |
171 | { | 199 | { |
172 | $$ = make_binary_node (L_OR, $1, $3); | 200 | struct mu_locus_range lr; |
201 | lr.beg = @1.beg; | ||
202 | lr.end = @3.end; | ||
203 | $$ = make_binary_node (L_OR, $1, $3, &lr); | ||
173 | } | 204 | } |
174 | | rule '+' rule | 205 | | rule '+' rule |
175 | { | 206 | { |
176 | $$ = make_binary_node (L_AND, $1, $3); | 207 | struct mu_locus_range lr; |
208 | lr.beg = @1.beg; | ||
209 | lr.end = @3.end; | ||
210 | $$ = make_binary_node (L_AND, $1, $3, &lr); | ||
177 | } | 211 | } |
178 | ; | 212 | ; |
179 | 213 | ||
180 | stmt : '!' stmt | 214 | stmt : '!' stmt |
181 | { | 215 | { |
182 | $$ = make_negation_node ($2); | 216 | $$ = make_negation_node ($2, &@2); |
183 | } | 217 | } |
184 | | '(' rule ')' | 218 | | '(' rule ')' |
185 | { | 219 | { |
... | @@ -187,19 +221,79 @@ stmt : '!' stmt | ... | @@ -187,19 +221,79 @@ stmt : '!' stmt |
187 | } | 221 | } |
188 | | string | 222 | | string |
189 | { | 223 | { |
190 | $$ = make_suffix_node (&$1); | 224 | $$ = make_suffix_node (&$1, &@1); |
191 | } | 225 | } |
192 | | function | 226 | | function |
193 | ; | 227 | ; |
194 | 228 | ||
195 | string : STRING | 229 | string : concat |
196 | | IDENT | 230 | { |
231 | lex_concat ($1.head, &$$); | ||
232 | } | ||
233 | ; | ||
234 | |||
235 | concat : simple_string | ||
236 | { | ||
237 | $$.head = $$.tail = $1; | ||
238 | } | ||
239 | | concat simple_string | ||
240 | { | ||
241 | $$.tail->next = $2; | ||
242 | $$.tail = $2; | ||
243 | } | ||
244 | ; | ||
245 | |||
246 | simple_string : STRING | ||
247 | { | ||
248 | $$ = mu_alloc (sizeof $$); | ||
249 | $$->next = NULL; | ||
250 | $$->val = $1.ptr; | ||
251 | } | ||
252 | ; | ||
253 | |||
254 | priority : PRIORITY oparen arglist cparen | ||
255 | { | ||
256 | size_t count = 0; | ||
257 | struct mimetypes_string *arg; | ||
258 | |||
259 | mu_list_count ($3, &count); | ||
260 | if (count != 1) | ||
261 | { | ||
262 | yyerror (_("priority takes single numberic argument")); | ||
263 | YYERROR; | ||
264 | } | ||
265 | mu_list_head ($3, (void**) &arg); | ||
266 | $$ = atoi (arg->ptr); | ||
267 | mu_list_destroy (&$3); | ||
268 | } | ||
269 | ; | ||
270 | |||
271 | maybe_priority: /* empty */ | ||
272 | { | ||
273 | $$ = 100; | ||
274 | } | ||
275 | | priority | ||
276 | ; | ||
277 | |||
278 | oparen : '(' | ||
279 | { | ||
280 | lex_arglist (1); | ||
281 | } | ||
282 | ; | ||
283 | |||
284 | cparen : ')' | ||
285 | { | ||
286 | lex_arglist (0); | ||
287 | } | ||
197 | ; | 288 | ; |
198 | 289 | ||
199 | function : IDENT_L arglist ')' | 290 | function : IDENT oparen arglist cparen |
200 | { | 291 | { |
201 | reset_lex (); | 292 | struct mu_locus_range lr; |
202 | $$ = make_functional_node ($1.ptr, $2); | 293 | lr.beg = @1.beg; |
294 | lr.end = @4.end; | ||
295 | |||
296 | $$ = make_functional_node ($1.ptr, $3, &lr); | ||
203 | if (!$$) | 297 | if (!$$) |
204 | YYERROR; | 298 | YYERROR; |
205 | } | 299 | } |
... | @@ -229,30 +323,26 @@ mimetypes_parse (const char *name) | ... | @@ -229,30 +323,26 @@ mimetypes_parse (const char *name) |
229 | int rc; | 323 | int rc; |
230 | if (mimetypes_open (name)) | 324 | if (mimetypes_open (name)) |
231 | return 1; | 325 | return 1; |
326 | yydebug = mu_debug_level_p (MU_DEBCAT_MIME, MU_DEBUG_TRACE3); | ||
232 | rc = yyparse (); | 327 | rc = yyparse (); |
233 | mimetypes_close (); | 328 | mimetypes_close (); |
234 | return rc || rule_list == NULL; | 329 | return rc || rule_list == NULL; |
235 | } | 330 | } |
236 | |||
237 | void | ||
238 | mimetypes_gram_debug (int level) | ||
239 | { | ||
240 | yydebug = level; | ||
241 | } | ||
242 | |||
243 | 331 | ||
244 | static struct node * | 332 | static struct node * |
245 | make_node (enum node_type type) | 333 | make_node (enum node_type type, struct mu_locus_range const *loc) |
246 | { | 334 | { |
247 | struct node *p = mimetypes_malloc (sizeof *p); | 335 | struct node *p = mimetypes_malloc (sizeof *p); |
248 | p->type = type; | 336 | p->type = type; |
337 | p->loc = *loc; | ||
249 | return p; | 338 | return p; |
250 | } | 339 | } |
251 | 340 | ||
252 | static struct node * | 341 | static struct node * |
253 | make_binary_node (int op, struct node *left, struct node *right) | 342 | make_binary_node (int op, struct node *left, struct node *right, |
343 | struct mu_locus_range const *loc) | ||
254 | { | 344 | { |
255 | struct node *node = make_node (binary_node); | 345 | struct node *node = make_node (binary_node, loc); |
256 | 346 | ||
257 | node->v.bin.op = op; | 347 | node->v.bin.op = op; |
258 | node->v.bin.arg1 = left; | 348 | node->v.bin.arg1 = left; |
... | @@ -261,17 +351,18 @@ make_binary_node (int op, struct node *left, struct node *right) | ... | @@ -261,17 +351,18 @@ make_binary_node (int op, struct node *left, struct node *right) |
261 | } | 351 | } |
262 | 352 | ||
263 | struct node * | 353 | struct node * |
264 | make_negation_node (struct node *p) | 354 | make_negation_node (struct node *p, struct mu_locus_range const *loc) |
265 | { | 355 | { |
266 | struct node *node = make_node (negation_node); | 356 | struct node *node = make_node (negation_node, loc); |
267 | node->v.arg = p; | 357 | node->v.arg = p; |
268 | return node; | 358 | return node; |
269 | } | 359 | } |
270 | 360 | ||
271 | struct node * | 361 | struct node * |
272 | make_suffix_node (struct mimetypes_string *suffix) | 362 | make_suffix_node (struct mimetypes_string *suffix, |
363 | struct mu_locus_range const *loc) | ||
273 | { | 364 | { |
274 | struct node *node = make_node (suffix_node); | 365 | struct node *node = make_node (suffix_node, loc); |
275 | node->v.suffix = *suffix; | 366 | node->v.suffix = *suffix; |
276 | return node; | 367 | return node; |
277 | } | 368 | } |
... | @@ -508,7 +599,7 @@ b_contains (union argument *args) | ... | @@ -508,7 +599,7 @@ b_contains (union argument *args) |
508 | 599 | ||
509 | buf = mu_alloc (args[1].number); | 600 | buf = mu_alloc (args[1].number); |
510 | rc = mu_stream_read (mimeview_stream, buf, args[1].number, &count); | 601 | rc = mu_stream_read (mimeview_stream, buf, args[1].number, &count); |
511 | if (count != args[1].number) | 602 | if (rc) |
512 | { | 603 | { |
513 | mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_read", NULL, rc); | 604 | mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_read", NULL, rc); |
514 | } | 605 | } |
... | @@ -523,10 +614,41 @@ b_contains (union argument *args) | ... | @@ -523,10 +614,41 @@ b_contains (union argument *args) |
523 | return 0; | 614 | return 0; |
524 | } | 615 | } |
525 | 616 | ||
617 | #define MIME_MAX_BUFFER 4096 | ||
618 | |||
619 | /* regex(offset,"regex") True if bytes match regular expression | ||
620 | */ | ||
621 | static int | ||
622 | b_regex (union argument *args) | ||
623 | { | ||
624 | size_t count; | ||
625 | int rc; | ||
626 | char buf[MIME_MAX_BUFFER]; | ||
627 | |||
628 | rc = mu_stream_seek (mimeview_stream, args[0].number, MU_SEEK_SET, NULL); | ||
629 | if (rc) | ||
630 | { | ||
631 | mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_seek", NULL, rc); | ||
632 | return 0; | ||
633 | } | ||
634 | |||
635 | rc = mu_stream_read (mimeview_stream, buf, sizeof buf - 1, &count); | ||
636 | if (rc) | ||
637 | { | ||
638 | mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_read", NULL, rc); | ||
639 | return 0; | ||
640 | } | ||
641 | buf[count] = 0; | ||
642 | |||
643 | return regexec (&args[1].rx, buf, 0, NULL, 0) == 0; | ||
644 | } | ||
645 | |||
646 | |||
526 | static struct builtin_tab builtin_tab[] = { | 647 | static struct builtin_tab builtin_tab[] = { |
527 | { "match", "s", b_match }, | 648 | { "match", "s", b_match }, |
528 | { "ascii", "dd", b_ascii }, | 649 | { "ascii", "dd", b_ascii }, |
529 | { "printable", "dd", b_printable }, | 650 | { "printable", "dd", b_printable }, |
651 | { "regex", "dx", b_regex }, | ||
530 | { "string", "ds", b_string }, | 652 | { "string", "ds", b_string }, |
531 | { "istring", "ds", b_istring }, | 653 | { "istring", "ds", b_istring }, |
532 | { "char", "dc", b_char }, | 654 | { "char", "dc", b_char }, |
... | @@ -538,13 +660,15 @@ static struct builtin_tab builtin_tab[] = { | ... | @@ -538,13 +660,15 @@ static struct builtin_tab builtin_tab[] = { |
538 | }; | 660 | }; |
539 | 661 | ||
540 | struct node * | 662 | struct node * |
541 | make_functional_node (char *ident, mu_list_t list) | 663 | make_functional_node (char *ident, mu_list_t list, |
664 | struct mu_locus_range const *loc) | ||
542 | { | 665 | { |
543 | size_t count, i; | 666 | size_t count, i; |
544 | struct builtin_tab *p; | 667 | struct builtin_tab *p; |
545 | struct node *node; | 668 | struct node *node; |
546 | union argument *args; | 669 | union argument *args; |
547 | mu_iterator_t itr; | 670 | mu_iterator_t itr; |
671 | int rc; | ||
548 | 672 | ||
549 | for (p = builtin_tab; ; p++) | 673 | for (p = builtin_tab; ; p++) |
550 | { | 674 | { |
... | @@ -602,6 +726,30 @@ make_functional_node (char *ident, mu_list_t list) | ... | @@ -602,6 +726,30 @@ make_functional_node (char *ident, mu_list_t list) |
602 | case 's': | 726 | case 's': |
603 | args[i].string = data; | 727 | args[i].string = data; |
604 | break; | 728 | break; |
729 | |||
730 | case 'x': | ||
731 | { | ||
732 | char *s; | ||
733 | |||
734 | rc = mu_c_str_unescape_trans (data->ptr, | ||
735 | "\\\\\"\"a\ab\bf\fn\nr\rt\tv\v", &s); | ||
736 | if (rc) | ||
737 | { | ||
738 | mu_diag_funcall (MU_DIAG_ERROR, "mu_c_str_unescape_trans", | ||
739 | data->ptr, rc); | ||
740 | return NULL; | ||
741 | } | ||
742 | rc = regcomp (&args[i].rx, s, REG_EXTENDED|REG_NOSUB); | ||
743 | free (s); | ||
744 | if (rc) | ||
745 | { | ||
746 | char errbuf[512]; | ||
747 | regerror (rc, &args[i].rx, errbuf, sizeof errbuf); | ||
748 | yyerror (errbuf); | ||
749 | return NULL; | ||
750 | } | ||
751 | } | ||
752 | break; | ||
605 | 753 | ||
606 | case 'c': | 754 | case 'c': |
607 | args[i].c = strtoul (data->ptr, &tmp, 0); | 755 | args[i].c = strtoul (data->ptr, &tmp, 0); |
... | @@ -614,7 +762,7 @@ make_functional_node (char *ident, mu_list_t list) | ... | @@ -614,7 +762,7 @@ make_functional_node (char *ident, mu_list_t list) |
614 | } | 762 | } |
615 | } | 763 | } |
616 | 764 | ||
617 | node = make_node (functional_node); | 765 | node = make_node (functional_node, loc); |
618 | node->v.function.fun = p->handler; | 766 | node->v.function.fun = p->handler; |
619 | node->v.function.args = args; | 767 | node->v.function.args = args; |
620 | return node; | 768 | return node; |
... | @@ -640,6 +788,45 @@ check_suffix (char *suf) | ... | @@ -640,6 +788,45 @@ check_suffix (char *suf) |
640 | return strcmp (p+1, suf) == 0; | 788 | return strcmp (p+1, suf) == 0; |
641 | } | 789 | } |
642 | 790 | ||
791 | void | ||
792 | mime_debug (int lev, struct mu_locus_range const *loc, char const *fmt, ...) | ||
793 | { | ||
794 | if (mu_debug_level_p (MU_DEBCAT_MIME, lev)) | ||
795 | { | ||
796 | va_list ap; | ||
797 | |||
798 | if (loc->beg.mu_col == 0) | ||
799 | mu_debug_log_begin ("%s:%u", loc->beg.mu_file, loc->beg.mu_line); | ||
800 | else if (strcmp(loc->beg.mu_file, loc->end.mu_file)) | ||
801 | mu_debug_log_begin ("%s:%u.%u-%s:%u.%u", | ||
802 | loc->beg.mu_file, | ||
803 | loc->beg.mu_line, loc->beg.mu_col, | ||
804 | loc->end.mu_file, | ||
805 | loc->end.mu_line, loc->end.mu_col); | ||
806 | else if (loc->beg.mu_line != loc->end.mu_line) | ||
807 | mu_debug_log_begin ("%s:%u.%u-%u.%u", | ||
808 | loc->beg.mu_file, | ||
809 | loc->beg.mu_line, loc->beg.mu_col, | ||
810 | loc->end.mu_line, loc->end.mu_col); | ||
811 | else if (loc->beg.mu_col != loc->end.mu_col) | ||
812 | mu_debug_log_begin ("%s:%u.%u-%u", | ||
813 | loc->beg.mu_file, | ||
814 | loc->beg.mu_line, loc->beg.mu_col, | ||
815 | loc->end.mu_col); | ||
816 | else | ||
817 | mu_debug_log_begin ("%s:%u.%u", | ||
818 | loc->beg.mu_file, | ||
819 | loc->beg.mu_line, loc->beg.mu_col); | ||
820 | |||
821 | mu_stream_write (mu_strerr, ": ", 2, NULL); | ||
822 | |||
823 | va_start (ap, fmt); | ||
824 | mu_stream_vprintf (mu_strerr, fmt, ap); | ||
825 | va_end (ap); | ||
826 | mu_debug_log_nl (); | ||
827 | } | ||
828 | } | ||
829 | |||
643 | static int | 830 | static int |
644 | eval_rule (struct node *root) | 831 | eval_rule (struct node *root) |
645 | { | 832 | { |
... | @@ -647,6 +834,10 @@ eval_rule (struct node *root) | ... | @@ -647,6 +834,10 @@ eval_rule (struct node *root) |
647 | 834 | ||
648 | switch (root->type) | 835 | switch (root->type) |
649 | { | 836 | { |
837 | case true_node: | ||
838 | result = 1; | ||
839 | break; | ||
840 | |||
650 | case functional_node: | 841 | case functional_node: |
651 | result = root->v.function.fun (root->v.function.args); | 842 | result = root->v.function.fun (root->v.function.args); |
652 | break; | 843 | break; |
... | @@ -681,28 +872,50 @@ eval_rule (struct node *root) | ... | @@ -681,28 +872,50 @@ eval_rule (struct node *root) |
681 | default: | 872 | default: |
682 | abort (); | 873 | abort (); |
683 | } | 874 | } |
875 | mime_debug (MU_DEBUG_TRACE2, &root->loc, "result %s", result ? "true" : "false"); | ||
684 | return result; | 876 | return result; |
685 | } | 877 | } |
686 | 878 | ||
687 | static int | 879 | static int |
688 | evaluate (void *item, void *data) | 880 | evaluate (void **itmv, size_t itmc, void *call_data) |
689 | { | 881 | { |
690 | struct rule_tab *p = item; | 882 | struct rule_tab *p = itmv[0]; |
691 | char **ptype = data; | ||
692 | |||
693 | if (eval_rule (p->node)) | 883 | if (eval_rule (p->node)) |
694 | { | 884 | { |
695 | *ptype = p->type; | 885 | itmv[0] = p; |
696 | return MU_ERR_USER0; | 886 | mime_debug (MU_DEBUG_TRACE1, &p->loc, "rule %s matches", p->type); |
887 | return MU_LIST_MAP_OK; | ||
697 | } | 888 | } |
698 | return 0; | 889 | return MU_LIST_MAP_SKIP; |
890 | } | ||
891 | |||
892 | static int | ||
893 | rule_cmp (const void *a, const void *b) | ||
894 | { | ||
895 | struct rule_tab const *arule = a; | ||
896 | struct rule_tab const *brule = b; | ||
897 | |||
898 | if (arule->priority == brule->priority) | ||
899 | return mu_c_strcasecmp (arule->type, brule->type); | ||
900 | return arule->priority - brule->priority; | ||
699 | } | 901 | } |
700 | 902 | ||
701 | const char * | 903 | const char * |
702 | get_file_type () | 904 | get_file_type () |
703 | { | 905 | { |
906 | mu_list_t res = NULL; | ||
704 | const char *type = NULL; | 907 | const char *type = NULL; |
705 | mu_list_foreach (rule_list, evaluate, &type); | 908 | |
909 | mu_list_map (rule_list, evaluate, NULL, 1, &res); | ||
910 | if (!mu_list_is_empty (res)) | ||
911 | { | ||
912 | struct rule_tab *rule; | ||
913 | mu_list_sort (res, rule_cmp); | ||
914 | mu_list_head (res, (void**) &rule); | ||
915 | mime_debug (MU_DEBUG_TRACE0, &rule->loc, "selected rule %s", rule->type); | ||
916 | type = rule->type; | ||
917 | } | ||
918 | mu_list_destroy (&res); | ||
706 | return type; | 919 | return type; |
707 | } | 920 | } |
708 | 921 | ... | ... |
... | @@ -31,8 +31,8 @@ | ... | @@ -31,8 +31,8 @@ |
31 | 31 | ||
32 | #include "mailcap.h" | 32 | #include "mailcap.h" |
33 | 33 | ||
34 | int debug_level; /* Debugging level set by --debug option */ | ||
35 | static int dry_run; /* Dry run mode */ | 34 | static int dry_run; /* Dry run mode */ |
35 | static int lint; /* Syntax check mode */ | ||
36 | static char *metamail; /* Name of metamail program, if requested */ | 36 | static char *metamail; /* Name of metamail program, if requested */ |
37 | static char *mimetypes_config = DEFAULT_CUPS_CONFDIR; | 37 | static char *mimetypes_config = DEFAULT_CUPS_CONFDIR; |
38 | static char *no_ask_types; /* List of MIME types for which no questions | 38 | static char *no_ask_types; /* List of MIME types for which no questions |
... | @@ -41,26 +41,6 @@ static int interactive = -1; | ... | @@ -41,26 +41,6 @@ static int interactive = -1; |
41 | char *mimeview_file; /* Name of the file to view */ | 41 | char *mimeview_file; /* Name of the file to view */ |
42 | mu_stream_t mimeview_stream; /* The corresponding stream */ | 42 | mu_stream_t mimeview_stream; /* The corresponding stream */ |
43 | 43 | ||
44 | static void | ||
45 | set_debug_flags (const char *arg) | ||
46 | { | ||
47 | for (; *arg; arg++) | ||
48 | { | ||
49 | switch (*arg) | ||
50 | { | ||
51 | case 'l': | ||
52 | mimetypes_lex_debug (1); | ||
53 | break; | ||
54 | |||
55 | case 'g': | ||
56 | mimetypes_gram_debug (1); | ||
57 | break; | ||
58 | |||
59 | default: | ||
60 | debug_level = *arg - '0'; | ||
61 | } | ||
62 | } | ||
63 | } | ||
64 | 44 | ||
65 | static void | 45 | static void |
66 | cli_no_ask (struct mu_parseopt *po, struct mu_option *opt, char const *arg) | 46 | cli_no_ask (struct mu_parseopt *po, struct mu_option *opt, char const *arg) |
... | @@ -80,7 +60,34 @@ static void | ... | @@ -80,7 +60,34 @@ static void |
80 | cli_debug (struct mu_parseopt *po, struct mu_option *opt, | 60 | cli_debug (struct mu_parseopt *po, struct mu_option *opt, |
81 | char const *arg) | 61 | char const *arg) |
82 | { | 62 | { |
83 | set_debug_flags (arg); | 63 | mu_debug_level_t lev; |
64 | if (!arg) | ||
65 | lev = MU_DEBUG_LEVEL_UPTO (MU_DEBUG_TRACE2); | ||
66 | else | ||
67 | { | ||
68 | mu_debug_get_category_level (MU_DEBCAT_MIME, &lev); | ||
69 | for (; *arg; arg++) | ||
70 | { | ||
71 | switch (*arg) | ||
72 | { | ||
73 | case 'l': | ||
74 | lev |= MU_DEBUG_LEVEL_MASK (MU_DEBUG_TRACE4); | ||
75 | break; | ||
76 | |||
77 | case 'g': | ||
78 | lev |= MU_DEBUG_LEVEL_MASK (MU_DEBUG_TRACE3); | ||
79 | break; | ||
80 | |||
81 | default: | ||
82 | if (mu_isdigit (*arg)) | ||
83 | lev |= MU_DEBUG_LEVEL_UPTO (MU_DEBUG_TRACE0 + *arg - '0'); | ||
84 | else | ||
85 | mu_parseopt_error (po, _("ignoring invalid debug flag: %c"), | ||
86 | *arg); | ||
87 | } | ||
88 | } | ||
89 | } | ||
90 | mu_debug_set_category_level (MU_DEBCAT_MIME, lev); | ||
84 | } | 91 | } |
85 | 92 | ||
86 | static void | 93 | static void |
... | @@ -103,13 +110,17 @@ static struct mu_option mimeview_options[] = { | ... | @@ -103,13 +110,17 @@ static struct mu_option mimeview_options[] = { |
103 | { "debug", 'd', N_("FLAGS"), MU_OPTION_ARG_OPTIONAL, | 110 | { "debug", 'd', N_("FLAGS"), MU_OPTION_ARG_OPTIONAL, |
104 | N_("enable debugging output"), | 111 | N_("enable debugging output"), |
105 | mu_c_string, NULL, cli_debug }, | 112 | mu_c_string, NULL, cli_debug }, |
106 | { "mimetypes", 't', N_("FILE"), MU_OPTION_DEFAULT, | 113 | { "mimetypes", 'f', N_("FILE"), MU_OPTION_DEFAULT, |
107 | N_("use this mime.types file"), | 114 | N_("use this mime.types file"), |
108 | mu_c_string, &mimetypes_config }, | 115 | mu_c_string, &mimetypes_config }, |
109 | 116 | ||
110 | { "dry-run", 'n', NULL, MU_OPTION_DEFAULT, | 117 | { "dry-run", 'n', NULL, MU_OPTION_DEFAULT, |
111 | N_("do nothing, just print what would have been done"), | 118 | N_("do nothing, just print what would have been done"), |
112 | mu_c_bool, &dry_run }, | 119 | mu_c_bool, &dry_run }, |
120 | |||
121 | { "lint", 't', NULL, MU_OPTION_DEFAULT, | ||
122 | N_("test mime.types syntax and exit"), | ||
123 | mu_c_bool, &lint }, | ||
113 | 124 | ||
114 | { "metamail", 0, N_("FILE"), MU_OPTION_ARG_OPTIONAL, | 125 | { "metamail", 0, N_("FILE"), MU_OPTION_ARG_OPTIONAL, |
115 | N_("use metamail to display files"), | 126 | N_("use metamail to display files"), |
... | @@ -118,19 +129,7 @@ static struct mu_option mimeview_options[] = { | ... | @@ -118,19 +129,7 @@ static struct mu_option mimeview_options[] = { |
118 | MU_OPTION_END | 129 | MU_OPTION_END |
119 | }, *options[] = { mimeview_options, NULL }; | 130 | }, *options[] = { mimeview_options, NULL }; |
120 | 131 | ||
121 | static int | ||
122 | cb_debug (void *data, mu_config_value_t *val) | ||
123 | { | ||
124 | if (mu_cfg_assert_value_type (val, MU_CFG_STRING)) | ||
125 | return 1; | ||
126 | set_debug_flags (val->v.string); | ||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | struct mu_cfg_param mimeview_cfg_param[] = { | 132 | struct mu_cfg_param mimeview_cfg_param[] = { |
131 | { "debug", mu_cfg_callback, NULL, 0, cb_debug, | ||
132 | N_("Set debug verbosity level."), | ||
133 | N_("flags: string") }, | ||
134 | { "mimetypes", mu_c_string, &mimetypes_config, 0, NULL, | 133 | { "mimetypes", mu_c_string, &mimetypes_config, 0, NULL, |
135 | N_("Use this mime.types file."), | 134 | N_("Use this mime.types file."), |
136 | N_("file") }, | 135 | N_("file") }, |
... | @@ -209,11 +208,12 @@ display_file (const char *type) | ... | @@ -209,11 +208,12 @@ display_file (const char *type) |
209 | argv[5] = mimeview_file; | 208 | argv[5] = mimeview_file; |
210 | argv[6] = NULL; | 209 | argv[6] = NULL; |
211 | 210 | ||
212 | if (debug_level) | 211 | if (mu_debug_level_p (MU_DEBCAT_MIME, MU_DEBUG_TRACE0)) |
213 | { | 212 | { |
214 | char *string; | 213 | char *string; |
215 | mu_argcv_string (6, argv, &string); | 214 | mu_argcv_string (6, argv, &string); |
216 | printf (_("Executing %s...\n"), string); | 215 | mu_debug (MU_DEBCAT_MIME, MU_DEBUG_TRACE0, |
216 | (_("executing %s...\n"), string)); | ||
217 | free (string); | 217 | free (string); |
218 | } | 218 | } |
219 | 219 | ||
... | @@ -233,7 +233,7 @@ display_file (const char *type) | ... | @@ -233,7 +233,7 @@ display_file (const char *type) |
233 | { | 233 | { |
234 | display_stream_mailcap (mimeview_file, mimeview_stream, hdr, | 234 | display_stream_mailcap (mimeview_file, mimeview_stream, hdr, |
235 | no_ask_types, interactive, dry_run, | 235 | no_ask_types, interactive, dry_run, |
236 | debug_level); | 236 | MU_DEBCAT_MIME); |
237 | mu_header_destroy (&hdr); | 237 | mu_header_destroy (&hdr); |
238 | } | 238 | } |
239 | } | 239 | } |
... | @@ -244,15 +244,18 @@ main (int argc, char **argv) | ... | @@ -244,15 +244,18 @@ main (int argc, char **argv) |
244 | { | 244 | { |
245 | MU_APP_INIT_NLS (); | 245 | MU_APP_INIT_NLS (); |
246 | 246 | ||
247 | mimetypes_lex_debug (0); | ||
248 | mimetypes_gram_debug (0); | ||
249 | interactive = isatty (fileno (stdin)); | 247 | interactive = isatty (fileno (stdin)); |
250 | 248 | ||
251 | mu_cli (argc, argv, &cli, capa, NULL, &argc, &argv); | 249 | mu_cli (argc, argv, &cli, capa, NULL, &argc, &argv); |
252 | if (dry_run && !debug_level) | 250 | if (dry_run) |
253 | debug_level = 1; | 251 | { |
252 | mu_debug_level_t lev; | ||
253 | mu_debug_get_category_level (MU_DEBCAT_MIME, &lev); | ||
254 | lev |= MU_DEBUG_LEVEL_UPTO (MU_DEBUG_TRACE2); | ||
255 | mu_debug_set_category_level (MU_DEBCAT_MIME, lev); | ||
256 | } | ||
254 | 257 | ||
255 | if (argc == 0) | 258 | if (argc == 0 && !lint) |
256 | { | 259 | { |
257 | mu_error (_("no files given")); | 260 | mu_error (_("no files given")); |
258 | return 1; | 261 | return 1; |
... | @@ -260,6 +263,8 @@ main (int argc, char **argv) | ... | @@ -260,6 +263,8 @@ main (int argc, char **argv) |
260 | 263 | ||
261 | if (mimetypes_parse (mimetypes_config)) | 264 | if (mimetypes_parse (mimetypes_config)) |
262 | return 1; | 265 | return 1; |
266 | if (lint) | ||
267 | return 0; | ||
263 | 268 | ||
264 | while (argc--) | 269 | while (argc--) |
265 | { | 270 | { |
... | @@ -268,7 +273,6 @@ main (int argc, char **argv) | ... | @@ -268,7 +273,6 @@ main (int argc, char **argv) |
268 | if (open_file (*argv++)) | 273 | if (open_file (*argv++)) |
269 | continue; | 274 | continue; |
270 | type = get_file_type (); | 275 | type = get_file_type (); |
271 | DEBUG (1, ("%s: %s\n", mimeview_file, type ? type : "?")); | ||
272 | if (type) | 276 | if (type) |
273 | display_file (type); | 277 | display_file (type); |
274 | close_file (); | 278 | close_file (); | ... | ... |
... | @@ -36,21 +36,48 @@ int mimetypes_yyerror (char *s); | ... | @@ -36,21 +36,48 @@ int mimetypes_yyerror (char *s); |
36 | int mimetypes_open (const char *name); | 36 | int mimetypes_open (const char *name); |
37 | void mimetypes_close (void); | 37 | void mimetypes_close (void); |
38 | int mimetypes_parse (const char *name); | 38 | int mimetypes_parse (const char *name); |
39 | void mimetypes_gram_debug (int level); | ||
40 | void mimetypes_lex_debug (int level); | ||
41 | void mimetypes_lex_init (void); | 39 | void mimetypes_lex_init (void); |
42 | void reset_lex (void); | 40 | void lex_arglist (int); |
43 | void *mimetypes_malloc (size_t size); | 41 | void *mimetypes_malloc (size_t size); |
44 | 42 | ||
45 | struct mimetypes_string mimetypes_append_string2 (struct mimetypes_string *s1, | ||
46 | char c, | ||
47 | struct mimetypes_string *s2); | ||
48 | struct mimetypes_string *mimetypes_string_dup (struct mimetypes_string *s); | 43 | struct mimetypes_string *mimetypes_string_dup (struct mimetypes_string *s); |
49 | 44 | ||
50 | const char *get_file_type (void); | 45 | const char *get_file_type (void); |
51 | 46 | ||
52 | extern char *mimeview_file; | 47 | extern char *mimeview_file; |
53 | extern mu_stream_t mimeview_stream; | 48 | extern mu_stream_t mimeview_stream; |
54 | extern int debug_level; | ||
55 | 49 | ||
56 | #define DEBUG(l,f) if (debug_level > (l)) printf f | 50 | struct concat_segm |
51 | { | ||
52 | struct concat_segm *next; | ||
53 | char const *val; | ||
54 | }; | ||
55 | |||
56 | void lex_concat (struct concat_segm *p, struct mimetypes_string *ret); | ||
57 | |||
58 | struct mu_locus_range | ||
59 | { | ||
60 | struct mu_locus beg; | ||
61 | struct mu_locus end; | ||
62 | }; | ||
63 | |||
64 | #define YYLTYPE struct mu_locus_range | ||
65 | #define YYLLOC_DEFAULT(Current, Rhs, N) \ | ||
66 | do \ | ||
67 | { \ | ||
68 | if (N) \ | ||
69 | { \ | ||
70 | (Current).beg = YYRHSLOC(Rhs, 1).beg; \ | ||
71 | (Current).end = YYRHSLOC(Rhs, N).end; \ | ||
72 | } \ | ||
73 | else \ | ||
74 | { \ | ||
75 | (Current).beg = YYRHSLOC(Rhs, 0).end; \ | ||
76 | (Current).end = (Current).beg; \ | ||
77 | } \ | ||
78 | } while (0) | ||
79 | #define YY_LOCATION_PRINT(File, Loc) \ | ||
80 | fprintf(File, "%s:%u.%u-%u.%u", \ | ||
81 | (Loc).beg.mu_file, \ | ||
82 | (Loc).beg.mu_line, (Loc).beg.mu_col, \ | ||
83 | (Loc).end.mu_line, (Loc).end.mu_col) | ... | ... |
-
Please register or sign in to post a comment