Commit 82e2f8ee 82e2f8ee6a860c427d69d1a3652945356f27920e by Sergey Poznyakoff

Switch mh_aliases to line tracker

* mh/mh.h (ali_parse_error): Remove.
* mh/mh_alias_gram.y: Simplify parser.  Use location tracking.
* mh/mh_alias_lex.l: Switch to mu_linetrack facility
* mh/tests/ali.at: Update expected location.
1 parent 4f24c098
...@@ -381,7 +381,6 @@ const char *mh_seq_read (mu_mailbox_t mbox, const char *name, int flags); ...@@ -381,7 +381,6 @@ const char *mh_seq_read (mu_mailbox_t mbox, const char *name, int flags);
381 void mh_comp_draft (const char *formfile, const char *draftfile); 381 void mh_comp_draft (const char *formfile, const char *draftfile);
382 int check_draft_disposition (struct mh_whatnow_env *wh, int use_draft); 382 int check_draft_disposition (struct mh_whatnow_env *wh, int use_draft);
383 383
384 void ali_parse_error (const char *fmt, ...) MU_PRINTFLIKE(1,2);
385 void ali_verbatim (int enable); 384 void ali_verbatim (int enable);
386 385
387 char *mh_safe_make_file_name (const char *dir, const char *file); 386 char *mh_safe_make_file_name (const char *dir, const char *file);
......
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
20 #include <pwd.h> 20 #include <pwd.h>
21 #include <grp.h> 21 #include <grp.h>
22 #include <sys/types.h> 22 #include <sys/types.h>
23 #include <mailutils/locus.h>
24 #include <mailutils/yyloc.h>
23 25
24 struct mh_alias 26 struct mh_alias
25 { 27 {
...@@ -31,7 +33,7 @@ struct mh_alias ...@@ -31,7 +33,7 @@ struct mh_alias
31 static mu_list_t alias_list; 33 static mu_list_t alias_list;
32 34
33 static mu_list_t 35 static mu_list_t
34 list_create_or_die () 36 list_create_or_die (void)
35 { 37 {
36 int status; 38 int status;
37 mu_list_t list; 39 mu_list_t list;
...@@ -39,7 +41,7 @@ list_create_or_die () ...@@ -39,7 +41,7 @@ list_create_or_die ()
39 status = mu_list_create (&list); 41 status = mu_list_create (&list);
40 if (status) 42 if (status)
41 { 43 {
42 ali_parse_error (_("can't create list: %s"), mu_strerror (status)); 44 mu_error (_("can't create list: %s"), mu_strerror (status));
43 exit (1); 45 exit (1);
44 } 46 }
45 return list; 47 return list;
...@@ -86,6 +88,17 @@ ali_list_to_string (mu_list_t *plist) ...@@ -86,6 +88,17 @@ ali_list_to_string (mu_list_t *plist)
86 return string; 88 return string;
87 } 89 }
88 90
91 static void
92 ali_append (struct mh_alias *ali)
93 {
94 if (ali)
95 {
96 if (!alias_list)
97 alias_list = list_create_or_die ();
98 mu_list_append (alias_list, ali);
99 }
100 }
101
89 static mu_list_t unix_group_to_list (char *name); 102 static mu_list_t unix_group_to_list (char *name);
90 static mu_list_t unix_gid_to_list (char *name); 103 static mu_list_t unix_gid_to_list (char *name);
91 static mu_list_t unix_passwd_to_list (void); 104 static mu_list_t unix_passwd_to_list (void);
...@@ -101,37 +114,34 @@ int yylex (void); ...@@ -101,37 +114,34 @@ int yylex (void);
101 struct mh_alias *alias; 114 struct mh_alias *alias;
102 } 115 }
103 116
117 %token EOL
104 %token <string> STRING 118 %token <string> STRING
105 %type <list> address_list address_group string_list 119 %type <list> address_list address_group string_list
106 %type <string> address 120 %type <string> address
107 %type <alias> alias 121 %type <alias> alias
108 122
123 %locations
124
109 %% 125 %%
110 126
111 input : /* empty */ 127 input : alias_list
112 | alias_list
113 | alias_list nl
114 | nl alias_list
115 | nl alias_list nl
116 ; 128 ;
117 129
118 alias_list : alias 130 alias_list : alias
119 { 131 {
120 if (!alias_list) 132 ali_append ($1);
121 alias_list = list_create_or_die ();
122 mu_list_append (alias_list, $1);
123 } 133 }
124 | alias_list nl alias 134 | alias_list EOL alias
125 { 135 {
126 mu_list_append (alias_list, $3); 136 ali_append ($3);
127 } 137 }
128 ; 138 ;
129 139
130 nl : '\n' 140 alias : /* empty */
131 | nl '\n' 141 {
132 ; 142 $$ = NULL;
133 143 }
134 alias : STRING ':' { ali_verbatim (1); } address_group 144 | STRING ':' { ali_verbatim (1); } address_group
135 { 145 {
136 ali_verbatim (0); 146 ali_verbatim (0);
137 $$ = mu_alloc (sizeof (*$$)); 147 $$ = mu_alloc (sizeof (*$$));
...@@ -489,7 +499,7 @@ unix_passwd_to_list () ...@@ -489,7 +499,7 @@ unix_passwd_to_list ()
489 } 499 }
490 500
491 int 501 int
492 mh_read_aliases () 502 mh_read_aliases (void)
493 { 503 {
494 const char *p; 504 const char *p;
495 505
......
...@@ -23,58 +23,23 @@ ...@@ -23,58 +23,23 @@
23 23
24 %{ 24 %{
25 #include <mh.h> 25 #include <mh.h>
26 #include <mailutils/locus.h>
27 #include <mailutils/yyloc.h>
26 #include <mh_alias_gram.h> 28 #include <mh_alias_gram.h>
27 #include <sys/stat.h> 29 #include <sys/stat.h>
28 #include <mailutils/cctype.h> 30 #include <mailutils/cctype.h>
29 #include <mailutils/io.h> 31 #include <mailutils/io.h>
30
31 char *ali_filename;
32 size_t ali_line_num;
33 ino_t ali_source_inode;
34
35 void
36 va_ali_parse_error_loc (const char *name, size_t line,
37 const char *fmt, va_list ap)
38 {
39 char *buf = NULL;
40 size_t size = 0;
41 32
42 mu_vasnprintf (&buf, &size, fmt, ap); 33 static mu_linetrack_t trk;
43 if (name) 34 static ino_t ali_source_inode;
44 mu_error ("%s:%lu: %s", name, (unsigned long) line, buf);
45 else
46 mu_error ("%s", buf);
47 free (buf);
48 }
49
50 void
51 ali_parse_error_loc (const char *name, size_t line, const char *fmt, ...)
52 {
53 va_list ap;
54
55 va_start (ap, fmt);
56 va_ali_parse_error_loc (name, line, fmt, ap);
57 va_end (ap);
58 }
59
60 void
61 ali_parse_error (const char *fmt, ...)
62 {
63 va_list ap;
64
65 va_start (ap, fmt);
66 va_ali_parse_error_loc (ali_filename, ali_line_num, fmt, ap);
67 va_end (ap);
68 }
69 35
70 int 36 int
71 yyerror (char *s) 37 yyerror (char *s)
72 { 38 {
73 ali_parse_error ("%s", s); 39 mu_error ("%s", s);
74 return 0; 40 return 0;
75 } 41 }
76 42
77 #ifdef FLEX_SCANNER
78 #define xinput() (yyin ? getc(yyin) : EOF) 43 #define xinput() (yyin ? getc(yyin) : EOF)
79 #undef YY_INPUT 44 #undef YY_INPUT
80 #define YY_INPUT(buf,result,max_size) do { \ 45 #define YY_INPUT(buf,result,max_size) do { \
...@@ -97,127 +62,20 @@ yyerror (char *s) ...@@ -97,127 +62,20 @@ yyerror (char *s)
97 yy_switch_to_buffer(s); \ 62 yy_switch_to_buffer(s); \
98 } while (0) 63 } while (0)
99 64
100 #else 65 #define YY_USER_ACTION \
101 /* AT&T Lex */ 66 do \
102 67 { \
103 static void lex_set_buffer (FILE *fp); 68 mu_linetrack_advance (trk, &yylloc, yytext, yyleng); \
104 static void lex_delete_buffer (LEX_BUFFER_STATE buf); 69 mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM, \
105 static int xinput (void); 70 MU_IOCTL_LOGSTREAM_SET_LOCUS_RANGE, &yylloc); \
106 static int xunput (void); 71 } \
107 72 while (0);
108 #undef unput
109 #define unput(c) xunput(c)
110 #undef input
111 #define input() xinput()
112
113 #define LEX_BUF_SIZE 16384
114 #define LEX_PUTBACK_SIZE 32
115
116 typedef struct {
117 FILE *yyin;
118 char *buffer;
119 size_t bufsize;
120 size_t level;
121 char *ptr;
122 char *putback;
123 size_t pb_size;
124 size_t pb_level;
125 } LEX_BUFFER_STATE;
126 LEX_BUFFER_STATE current_buffer;
127 73
128 #define SET_BUFFER_STATE(s) do { \
129 (s) = current_buffer; \
130 lex_set_buffer(yyin); \
131 } while (0)
132 #define RESTORE_BUFFER_STATE(s) do { \
133 lex_delete_buffer(current_buffer); \
134 current_buffer = (s); \
135 yyin = current_buffer.yyin; \
136 } while (0)
137
138 void
139 lex_set_buffer (FILE *fp)
140 {
141 char *buf;
142 size_t size;
143
144 for (size = LEX_BUF_SIZE; size > 1; size /= 2)
145 if (buf = malloc (size))
146 break;
147
148 if (!buf)
149 {
150 ali_parse_error (_("not enough memory"));
151 abort ();
152 }
153
154 current_buffer.yyin = yyin;
155 current_buffer.buffer = buf;
156 current_buffer.bufsize = size;
157 current_buffer.level = 0;
158 current_buffer.ptr = current_buffer.buffer;
159 current_buffer.pb_size = current_buffer.pb_level = 0;
160 current_buffer.putback = NULL;
161 }
162
163 void
164 lex_delete_buffer (LEX_BUFFER_STATE buf)
165 {
166 free (buf.buffer);
167 if (buf.putback)
168 free (buf.putback);
169 }
170
171 int
172 xinput ()
173 {
174 if (!yyin)
175 return EOF;
176
177 if (current_buffer.pb_level)
178 return current_buffer.putback[--current_buffer.pb_level];
179
180 if (current_buffer.level <= 0)
181 {
182 int n;
183
184 if (feof (yyin))
185 return 0;
186 n = fread (current_buffer.buffer, 1,
187 current_buffer.bufsize, yyin);
188 if (n <= 0)
189 return 0;
190 current_buffer.level = n;
191 current_buffer.ptr = current_buffer.buffer;
192 }
193 current_buffer.level--;
194 return *current_buffer.ptr++;
195 }
196
197 int
198 xunput (int c)
199 {
200 if (current_buffer.pb_level == current_buffer.pb_size)
201 {
202 char *putback;
203 current_buffer.pb_size += LEX_PUTBACK_SIZE;
204 putback = mu_alloc (current_buffer.pb_size);
205 memcpy (putback, current_buffer.putback,
206 current_buffer.pb_level);
207 free (current_buffer.putback);
208 current_buffer.putback = putback;
209 }
210 current_buffer.putback[current_buffer.pb_level++] = c;
211 return c;
212 }
213
214 #endif
215
216 struct buffer_ctx { 74 struct buffer_ctx {
217 struct buffer_ctx *prev; 75 struct buffer_ctx *prev;
218 char *filename; 76 mu_linetrack_t trk;
219 int line;
220 ino_t i_node; 77 ino_t i_node;
78 struct mu_locus_range incl_range;
221 FILE *yyin; 79 FILE *yyin;
222 int exec_p; 80 int exec_p;
223 LEX_BUFFER_STATE state; 81 LEX_BUFFER_STATE state;
...@@ -250,27 +108,26 @@ push_source (const char *name, int fail) ...@@ -250,27 +108,26 @@ push_source (const char *name, int fail)
250 if (stat (filename, &st)) 108 if (stat (filename, &st))
251 { 109 {
252 if (fail) 110 if (fail)
253 ali_parse_error (_("can't stat `%s': %s"), filename, strerror (errno)); 111 mu_error (_("can't stat `%s': %s"), filename, strerror (errno));
254 free (filename); 112 free (filename);
255 return 1; 113 return 1;
256 } 114 }
257 115
258 if (ali_filename && st.st_ino == ali_source_inode) 116 if (yylloc.beg.mu_file && st.st_ino == ali_source_inode)
259 { 117 {
260 ali_parse_error (_("recursive inclusion")); 118 mu_error (_("recursive inclusion"));
261 free (filename); 119 free (filename);
262 return 1; 120 return 1;
263 } 121 }
264 if ((ctx = ctx_lookup (st.st_ino))) 122 if ((ctx = ctx_lookup (st.st_ino)))
265 { 123 {
266 ali_parse_error (_("recursive inclusion")); 124 mu_error (_("recursive inclusion"));
267 if (ctx->prev) 125 if (ctx->prev)
268 ali_parse_error_loc (ctx->prev->filename, ctx->prev->line, 126 mu_diag_at_locus_range (MU_LOG_ERROR, &ctx->incl_range,
269 _("`%s' already included here"), 127 _("`%s' already included here"),
270 filename); 128 filename);
271 else 129 else
272 ali_parse_error (_("`%s' already included at top level"), 130 mu_error (_("`%s' already included at top level"), filename);
273 filename);
274 free (filename); 131 free (filename);
275 return 1; 132 return 1;
276 } 133 }
...@@ -278,7 +135,7 @@ push_source (const char *name, int fail) ...@@ -278,7 +135,7 @@ push_source (const char *name, int fail)
278 fp = fopen (filename, "r"); 135 fp = fopen (filename, "r");
279 if (!fp) 136 if (!fp)
280 { 137 {
281 ali_parse_error (_("can't open `%s': %s"), filename, strerror (errno)); 138 mu_error (_("can't open `%s': %s"), filename, strerror (errno));
282 free (filename); 139 free (filename);
283 return 1; 140 return 1;
284 } 141 }
...@@ -295,8 +152,8 @@ push_source (const char *name, int fail) ...@@ -295,8 +152,8 @@ push_source (const char *name, int fail)
295 fp = popen (filename, "r"); 152 fp = popen (filename, "r");
296 if (!fp) 153 if (!fp)
297 { 154 {
298 ali_parse_error (_("can't execute `%s': %s"), 155 mu_error (_("can't execute `%s': %s"),
299 filename, strerror (errno)); 156 filename, strerror (errno));
300 free (filename); 157 free (filename);
301 return 1; 158 return 1;
302 } 159 }
...@@ -306,12 +163,12 @@ push_source (const char *name, int fail) ...@@ -306,12 +163,12 @@ push_source (const char *name, int fail)
306 } 163 }
307 164
308 /* Push current context */ 165 /* Push current context */
309 if (ali_filename) 166 if (yylloc.beg.mu_file)
310 { 167 {
311 ctx = mu_alloc (sizeof (*ctx)); 168 ctx = mu_alloc (sizeof (*ctx));
312 ctx->filename = ali_filename; 169 ctx->trk = trk;
170 mu_locus_range_copy (&ctx->incl_range, &yylloc);
313 ctx->exec_p = exec_p; 171 ctx->exec_p = exec_p;
314 ctx->line = ali_line_num;
315 ctx->i_node = ali_source_inode; 172 ctx->i_node = ali_source_inode;
316 ctx->yyin = yyin; 173 ctx->yyin = yyin;
317 ctx->prev = context_stack; 174 ctx->prev = context_stack;
...@@ -330,34 +187,30 @@ push_source (const char *name, int fail) ...@@ -330,34 +187,30 @@ push_source (const char *name, int fail)
330 lex_set_buffer (yyin); 187 lex_set_buffer (yyin);
331 #endif 188 #endif
332 } 189 }
333 ali_filename = filename; 190 MU_ASSERT (mu_linetrack_create (&trk, filename, 2));
334 ali_line_num = 1; 191 free (filename);
335 ali_source_inode = st.st_ino; 192 ali_source_inode = st.st_ino;
336 exec_p = ex; 193 exec_p = ex;
337 return 0; 194 return 0;
338 } 195 }
339 196
340 static int 197 static int
341 pop_source () 198 pop_source (void)
342 { 199 {
343 struct buffer_ctx *ctx; 200 struct buffer_ctx *ctx;
344 201
345 if (yyin) 202 if (yyin)
346 (exec_p ? pclose : fclose) (yyin); 203 (exec_p ? pclose : fclose) (yyin);
347 #ifndef FLEX_SCANNER 204 mu_linetrack_destroy (&trk);
348 lex_delete_buffer (current_buffer);
349 #endif
350 if (ali_filename)
351 free (ali_filename);
352 ali_filename = NULL;
353 if (!context_stack) 205 if (!context_stack)
354 { 206 {
207 mu_locus_range_deinit (&yylloc);
355 yyin = NULL; 208 yyin = NULL;
356 return 1; 209 return 1;
357 } 210 }
211 mu_locus_range_deinit (&context_stack->incl_range);
358 /* Restore previous context */ 212 /* Restore previous context */
359 ali_filename = context_stack->filename; 213 trk = context_stack->trk;
360 ali_line_num = context_stack->line + 1; /* < line did not increment it */
361 ali_source_inode = context_stack->i_node; 214 ali_source_inode = context_stack->i_node;
362 exec_p = context_stack->exec_p; 215 exec_p = context_stack->exec_p;
363 RESTORE_BUFFER_STATE (context_stack->state); 216 RESTORE_BUFFER_STATE (context_stack->state);
...@@ -378,15 +231,15 @@ WORD [^ \t\n,:;<+=\*]+ ...@@ -378,15 +231,15 @@ WORD [^ \t\n,:;<+=\*]+
378 SPEC [,:;+=\*] 231 SPEC [,:;+=\*]
379 %s VERBATIM 232 %s VERBATIM
380 %% 233 %%
381 \\\n { ali_line_num++; } 234 \\\n ;
382 \n { ali_line_num++; return '\n';} 235 \n+ return EOL;
383 ^[ \t]*\;.*\n ali_line_num++; 236 ^[ \t]*\;.*\n ;
384 ^[ \t]*{WORD}\* { char *p; 237 ^[ \t]*{WORD}\* { char *p;
385 for (p = yytext; p < yytext + yyleng; p++) 238 for (p = yytext; p < yytext + yyleng; p++)
386 if (!mu_isspace (*p)) 239 if (!mu_isspace (*p))
387 break; 240 break;
388 yylval.string = mu_strdup (p); 241 yylval.string = mu_strdup (p);
389 return STRING;} 242 return STRING; }
390 {WS} ; 243 {WS} ;
391 {WORD} { yylval.string = mu_strdup (yytext); return STRING;} 244 {WORD} { yylval.string = mu_strdup (yytext); return STRING;}
392 ^{WS}?"<"{WS}?{WORD} { 245 ^{WS}?"<"{WS}?{WORD} {
...@@ -403,26 +256,24 @@ SPEC [,:;+=\*] ...@@ -403,26 +256,24 @@ SPEC [,:;+=\*]
403 memcpy(yylval.string, yytext, yyleng); 256 memcpy(yylval.string, yytext, yyleng);
404 yylval.string[yyleng] = 0; 257 yylval.string[yyleng] = 0;
405 return STRING;} 258 return STRING;}
406 . { char *p; 259 . { mu_error (_("Stray character %03o in alias file"),
407 mu_asprintf (&p, 260 yytext[0]); }
408 _("Stray character %03o in alias file"),
409 yytext[0]);
410 yyerror (p);
411 free (p); }
412 %% 261 %%
413 262
414 int 263 int
415 yywrap () 264 yywrap (void)
416 { 265 {
417 return pop_source(); 266 return pop_source ();
418 } 267 }
419 268
420 /* Parses the named alias file */ 269 /* Parses the named alias file */
421 int 270 int
422 mh_alias_read (char const *name, int fail) 271 mh_alias_read (char const *name, int fail)
423 { 272 {
273 int rc;
274 int old_mode, mode;
424 extern int yydebug; 275 extern int yydebug;
425 char *p = getenv("ALI_YYDEBUG"); 276 char *p = getenv ("ALI_YYDEBUG");
426 277
427 if (p && *p > '0' && *p < '9') 278 if (p && *p > '0' && *p < '9')
428 yydebug = 1; 279 yydebug = 1;
...@@ -431,7 +282,15 @@ mh_alias_read (char const *name, int fail) ...@@ -431,7 +282,15 @@ mh_alias_read (char const *name, int fail)
431 return 1; 282 return 1;
432 if (yydebug) 283 if (yydebug)
433 fprintf (stderr, "Starting parse of %s\n", name); 284 fprintf (stderr, "Starting parse of %s\n", name);
434 return yyparse (); 285
286 mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
287 MU_IOCTL_LOGSTREAM_GET_MODE, &old_mode);
288 mode = old_mode | MU_LOGMODE_LOCUS;
289 mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
290 MU_IOCTL_LOGSTREAM_SET_MODE, &mode);
291 rc = yyparse ();
292 mu_stream_ioctl (mu_strerr, MU_IOCTL_LOGSTREAM,
293 MU_IOCTL_LOGSTREAM_SET_MODE, &old_mode);
435 } 294 }
436 295
437 void 296 void
......
...@@ -70,8 +70,8 @@ exit $code ...@@ -70,8 +70,8 @@ exit $code
70 [0], 70 [0],
71 [gray, polak, admin 71 [gray, polak, admin
72 ], 72 ],
73 [ali: mh_aliases2:2: recursive inclusion 73 [ali: mh_aliases2:2.1-11: recursive inclusion
74 ali: mh_aliases2:2: `mh_aliases' already included at top level 74 ali: mh_aliases2:2.1-11: `mh_aliases' already included at top level
75 ]) 75 ])
76 76
77 MH_CHECK([ali: group name],[ali04 ali-group-name],[ 77 MH_CHECK([ali: group name],[ali04 ali-group-name],[
......