Commit a79ec559 a79ec559859084cfe8a357bf9076d472fefbeeee by Sergey Poznyakoff

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.*
1 parent d2952d1c
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
......
...@@ -42,3 +42,4 @@ assoc ...@@ -42,3 +42,4 @@ assoc
42 acl 42 acl
43 server 43 server
44 tls 44 tls
45 app
......
...@@ -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 }
......
...@@ -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)
......
1 /Makefile.in.in
1 /Makevars.template~ 2 /Makevars.template~
2 /Makefile.in.in~ 3 /Makefile.in.in~
3 *.gmo 4 *.gmo
......