Added to the repository
Showing
3 changed files
with
819 additions
and
2 deletions
... | @@ -68,13 +68,14 @@ libmh_a_SOURCES= \ | ... | @@ -68,13 +68,14 @@ libmh_a_SOURCES= \ |
68 | mh_error.c\ | 68 | mh_error.c\ |
69 | mh_format.c\ | 69 | mh_format.c\ |
70 | mh_init.c\ | 70 | mh_init.c\ |
71 | mh_list.c\ | ||
71 | mh_fmtgram.y\ | 72 | mh_fmtgram.y\ |
72 | mh_msgset.c\ | 73 | mh_msgset.c\ |
73 | mh_whatnow.c | 74 | mh_whatnow.c |
74 | noinst_HEADERS = mh.h mh_getopt.h | 75 | noinst_HEADERS = mh.h mh_getopt.h |
75 | 76 | ||
76 | mhlib_DATA = replcomps | 77 | mhlib_DATA = replcomps mhl.format |
77 | EXTRA_DIST = replcomps | 78 | EXTRA_DIST = replcomps mhl.format |
78 | 79 | ||
79 | INCLUDES = -I${top_srcdir}/include -I${top_srcdir}/lib -I${top_srcdir}/mailbox @INTLINCS@ | 80 | INCLUDES = -I${top_srcdir}/include -I${top_srcdir}/lib -I${top_srcdir}/mailbox @INTLINCS@ |
80 | AM_CPPFLAGS = -DMHLIBDIR=\"$(mhlibdir)\" | 81 | AM_CPPFLAGS = -DMHLIBDIR=\"$(mhlibdir)\" | ... | ... |
mh/mh_list.c
0 → 100644
1 | /* GNU Mailutils -- a suite of utilities for electronic mail | ||
2 | Copyright (C) 2003 Free Software Foundation, Inc. | ||
3 | |||
4 | GNU Mailutils is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | GNU Mailutils is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with GNU Mailutils; if not, write to the Free Software | ||
16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ | ||
17 | |||
18 | /* MH mhl command */ | ||
19 | |||
20 | #include <mh.h> | ||
21 | |||
22 | /* *********************** Compiler for MHL formats *********************** */ | ||
23 | |||
24 | typedef struct | ||
25 | { | ||
26 | char *filename; | ||
27 | int line; | ||
28 | } | ||
29 | locus_t; | ||
30 | |||
31 | enum mhl_type | ||
32 | { | ||
33 | stmt_cleartext, | ||
34 | stmt_component, | ||
35 | stmt_variable | ||
36 | }; | ||
37 | |||
38 | enum mhl_datatype | ||
39 | { | ||
40 | dt_flag, | ||
41 | dt_integer, | ||
42 | dt_string, | ||
43 | dt_format | ||
44 | }; | ||
45 | |||
46 | typedef union mhl_value { | ||
47 | char *str; | ||
48 | int num; | ||
49 | mh_format_t *fmt; | ||
50 | } mhl_value_t; | ||
51 | |||
52 | typedef struct mhl_variable | ||
53 | { | ||
54 | int id; | ||
55 | char *name; | ||
56 | int type; | ||
57 | } | ||
58 | mhl_variable_t; | ||
59 | |||
60 | typedef struct mhl_stmt mhl_stmt_t; | ||
61 | typedef struct mhl_stmt_variable mhl_stmt_variable_t; | ||
62 | typedef struct mhl_stmt_component mhl_stmt_component_t; | ||
63 | |||
64 | struct mhl_stmt_variable | ||
65 | { | ||
66 | mhl_variable_t *id; | ||
67 | mhl_value_t value; | ||
68 | }; | ||
69 | |||
70 | struct mhl_stmt_component | ||
71 | { | ||
72 | char *name; | ||
73 | list_t format; | ||
74 | }; | ||
75 | |||
76 | struct mhl_stmt | ||
77 | { | ||
78 | enum mhl_type type; | ||
79 | union | ||
80 | { | ||
81 | char *cleartext; | ||
82 | mhl_stmt_variable_t variable; | ||
83 | mhl_stmt_component_t component; | ||
84 | } v; | ||
85 | }; | ||
86 | |||
87 | static mhl_variable_t *variable_lookup __P((char *name)); | ||
88 | |||
89 | static mhl_stmt_t * | ||
90 | stmt_alloc (enum mhl_type type) | ||
91 | { | ||
92 | mhl_stmt_t *p = xmalloc (sizeof (*p)); | ||
93 | p->type = type; | ||
94 | return p; | ||
95 | } | ||
96 | |||
97 | static int | ||
98 | compdecl (char **str, char **compname) | ||
99 | { | ||
100 | char *p; | ||
101 | |||
102 | for (p = *str; *p && !isspace (*p); p++) | ||
103 | { | ||
104 | if (*p == ':') | ||
105 | { | ||
106 | int len = p - *str; | ||
107 | *compname = xmalloc (len + 1); | ||
108 | memcpy (*compname, *str, len); | ||
109 | (*compname)[len] = 0; | ||
110 | *str = p + 1; | ||
111 | return 0; | ||
112 | } | ||
113 | } | ||
114 | return 1; | ||
115 | } | ||
116 | |||
117 | static void parse_variable (locus_t *loc, list_t formlist, char *str); | ||
118 | |||
119 | static void | ||
120 | parse_cleartext (locus_t *loc, list_t formlist, char *str) | ||
121 | { | ||
122 | int len; | ||
123 | mhl_stmt_t *stmt = stmt_alloc (stmt_cleartext); | ||
124 | stmt->v.cleartext = strdup (str); | ||
125 | len = strlen (stmt->v.cleartext); | ||
126 | if (len > 0 && stmt->v.cleartext[len-1] == '\n') | ||
127 | stmt->v.cleartext[len-1] = 0; | ||
128 | list_append (formlist, stmt); | ||
129 | } | ||
130 | |||
131 | static void | ||
132 | parse_component (locus_t *loc, list_t formlist, char *compname, char *str) | ||
133 | { | ||
134 | mhl_stmt_t *stmt = stmt_alloc (stmt_component); | ||
135 | stmt->v.component.name = compname; | ||
136 | if (list_create (&stmt->v.component.format)) | ||
137 | { | ||
138 | mh_error (_("%s:%d: can't create list"), | ||
139 | loc->filename, | ||
140 | loc->line); | ||
141 | exit (1); /* FIXME */ | ||
142 | } | ||
143 | parse_variable (loc, stmt->v.component.format, str); | ||
144 | list_append (formlist, stmt); | ||
145 | } | ||
146 | |||
147 | static void | ||
148 | parse_variable (locus_t *loc, list_t formlist, char *str) | ||
149 | { | ||
150 | int i; | ||
151 | int argc; | ||
152 | char **argv; | ||
153 | mh_format_t fmt; | ||
154 | |||
155 | if (argcv_get (str, ",=", NULL, &argc, &argv)) | ||
156 | { | ||
157 | mh_error (_("%s:%d: cannot split string %s"), | ||
158 | loc->filename, | ||
159 | loc->line, | ||
160 | str); | ||
161 | exit (1); | ||
162 | } | ||
163 | |||
164 | for (i = 0; i < argc; i++) | ||
165 | { | ||
166 | mhl_stmt_t *stmt = stmt_alloc (stmt_variable); | ||
167 | char *name = argv[i]; | ||
168 | char *value = NULL; | ||
169 | mhl_variable_t *var; | ||
170 | |||
171 | var = variable_lookup (name); | ||
172 | if (!var) | ||
173 | { | ||
174 | mh_error (_("%s:%d: unknown variable: %s"), | ||
175 | loc->filename, | ||
176 | loc->line, | ||
177 | argv[i]); | ||
178 | exit (1); | ||
179 | } | ||
180 | |||
181 | if (i + 1 < argc && argv[i+1][0] == '=') | ||
182 | { | ||
183 | i++; | ||
184 | value = argv[++i]; | ||
185 | } | ||
186 | |||
187 | if ((var->type == dt_flag && value) | ||
188 | || (var->type != dt_flag && !value)) | ||
189 | { | ||
190 | mh_error (_("%s:%d: wrong datatype for %s"), | ||
191 | loc->filename, | ||
192 | loc->line, | ||
193 | var->name); | ||
194 | exit (1); | ||
195 | } | ||
196 | |||
197 | switch (var->type) | ||
198 | { | ||
199 | case dt_string: | ||
200 | stmt->v.variable.value.str = strdup (value); | ||
201 | break; | ||
202 | |||
203 | case dt_integer: | ||
204 | stmt->v.variable.value.num = strtoul (value, NULL, 0); | ||
205 | break; | ||
206 | |||
207 | case dt_format: | ||
208 | if (mh_format_parse (value, &fmt)) | ||
209 | { | ||
210 | mh_error (_("%s:%d: Bad format string"), | ||
211 | loc->filename, | ||
212 | loc->line); | ||
213 | exit (1); | ||
214 | } | ||
215 | stmt->v.variable.value.fmt = xmalloc (sizeof (mh_format_t)); | ||
216 | *stmt->v.variable.value.fmt = fmt; | ||
217 | break; | ||
218 | |||
219 | case dt_flag: | ||
220 | stmt->v.variable.value.num = strcmp (var->name, name) == 0; | ||
221 | break; | ||
222 | } | ||
223 | stmt->v.variable.id = var; | ||
224 | list_append (formlist, stmt); | ||
225 | |||
226 | i++; | ||
227 | if (i < argc && argv[i][0] != ',') | ||
228 | { | ||
229 | mh_error (_("%s:%d: syntax error"), loc->filename, loc->line); | ||
230 | exit (1); | ||
231 | } | ||
232 | } | ||
233 | |||
234 | argcv_free (argc, argv); | ||
235 | } | ||
236 | |||
237 | static int | ||
238 | parse_line (locus_t *loc, list_t formlist, char *str) | ||
239 | { | ||
240 | char *compname; | ||
241 | |||
242 | if (*str == ':') | ||
243 | parse_cleartext (loc, formlist, str+1); | ||
244 | else if (compdecl (&str, &compname) == 0) | ||
245 | parse_component (loc, formlist, compname, str); | ||
246 | else | ||
247 | parse_variable (loc, formlist, str); | ||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | list_t | ||
252 | mhl_format_compile (char *name) | ||
253 | { | ||
254 | FILE *fp; | ||
255 | list_t formlist; | ||
256 | char *buf = NULL; | ||
257 | size_t n = 0; | ||
258 | locus_t loc; | ||
259 | |||
260 | fp = fopen (name, "r"); | ||
261 | if (!fp) | ||
262 | { | ||
263 | mh_error (_("cannot open file %s: %s"), name, mu_strerror (errno)); | ||
264 | return NULL; | ||
265 | } | ||
266 | |||
267 | if (list_create (&formlist)) | ||
268 | { | ||
269 | fclose (fp); | ||
270 | mh_error (_("can't create list")); | ||
271 | return NULL; | ||
272 | } | ||
273 | |||
274 | loc.filename = name; | ||
275 | loc.line = 1; | ||
276 | while (getline (&buf, &n, fp) > 0) | ||
277 | { | ||
278 | char *p = buf; | ||
279 | |||
280 | while (*p && isspace (*p)) | ||
281 | ; | ||
282 | |||
283 | if (*p == 0 || *p == ';') | ||
284 | continue; | ||
285 | |||
286 | parse_line (&loc, formlist, p); | ||
287 | loc.line++; | ||
288 | } | ||
289 | |||
290 | free (buf); | ||
291 | fclose (fp); | ||
292 | |||
293 | return formlist; | ||
294 | } | ||
295 | |||
296 | |||
297 | /* ********************** Destroy compiled MHL format ********************** */ | ||
298 | |||
299 | static void | ||
300 | _destroy_value (enum mhl_datatype type, mhl_value_t *val) | ||
301 | { | ||
302 | switch (type) | ||
303 | { | ||
304 | case dt_string: | ||
305 | free (val->str); | ||
306 | break; | ||
307 | |||
308 | case dt_flag: | ||
309 | case dt_integer: | ||
310 | break; | ||
311 | |||
312 | case dt_format: | ||
313 | mh_format_free (val->fmt); | ||
314 | free (val->fmt); | ||
315 | break; | ||
316 | |||
317 | default: | ||
318 | abort (); | ||
319 | } | ||
320 | } | ||
321 | |||
322 | static int | ||
323 | _destroy_stmt (void *item, void *data) | ||
324 | { | ||
325 | mhl_stmt_t *stmt = item; | ||
326 | |||
327 | switch (stmt->type) | ||
328 | { | ||
329 | case stmt_cleartext: | ||
330 | free (stmt->v.cleartext); | ||
331 | break; | ||
332 | |||
333 | case stmt_component: | ||
334 | free (stmt->v.component.name); | ||
335 | mhl_format_destroy (&stmt->v.component.format); | ||
336 | break; | ||
337 | |||
338 | case stmt_variable: | ||
339 | _destroy_value (stmt->v.variable.id->type, &stmt->v.variable.value); | ||
340 | break; | ||
341 | |||
342 | default: | ||
343 | abort (); | ||
344 | } | ||
345 | return 0; | ||
346 | } | ||
347 | |||
348 | void | ||
349 | mhl_format_destroy (list_t *fmt) | ||
350 | { | ||
351 | list_do (*fmt, _destroy_stmt, NULL); | ||
352 | list_destroy (fmt); | ||
353 | } | ||
354 | |||
355 | |||
356 | /* *************************** Runtime functions *************************** */ | ||
357 | /* Integer variables */ | ||
358 | #define I_WIDTH 0 | ||
359 | #define I_LENGTH 1 | ||
360 | #define I_OFFSET 2 | ||
361 | #define I_OVERFLOWOFFSET 3 | ||
362 | #define I_COMPWIDTH 4 | ||
363 | #define I_MAX 5 | ||
364 | |||
365 | /* Boolean (flag) variables */ | ||
366 | #define B_UPPERCASE 0 | ||
367 | #define B_CLEARSCREEN 1 | ||
368 | #define B_BELL 2 | ||
369 | #define B_NOCOMPONENT 3 | ||
370 | #define B_CENTER 4 | ||
371 | #define B_LEFTADJUST 5 | ||
372 | #define B_COMPRESS 6 | ||
373 | #define B_SPLIT 7 | ||
374 | #define B_NEWLINE 8 | ||
375 | #define B_ADDRFIELD 9 | ||
376 | #define B_DATEFIELD 10 | ||
377 | #define B_MAX 11 | ||
378 | |||
379 | /* String variables */ | ||
380 | #define S_OVERFLOWTEXT 0 | ||
381 | #define S_COMPONENT 1 | ||
382 | #define S_IGNORES 2 | ||
383 | #define S_MAX 3 | ||
384 | |||
385 | /* Format variables */ | ||
386 | #define F_FORMATFIELD 0 | ||
387 | #define F_MAX 1 | ||
388 | |||
389 | static mhl_variable_t vartab[] = { | ||
390 | /* Integer variables */ | ||
391 | { I_WIDTH, "width", dt_integer }, | ||
392 | { I_LENGTH, "length", dt_integer }, | ||
393 | { I_OFFSET, "offset", dt_integer }, | ||
394 | { I_OVERFLOWOFFSET, "overflowoffset", dt_integer }, | ||
395 | { I_COMPWIDTH, "compwidth", dt_integer }, | ||
396 | |||
397 | /* Boolean (flag) variables */ | ||
398 | { B_UPPERCASE, "uppercase", dt_flag }, | ||
399 | { B_CLEARSCREEN, "clearscreen", dt_flag }, | ||
400 | { B_BELL, "bell", dt_flag }, | ||
401 | { B_NOCOMPONENT, "nocomponent", dt_flag }, | ||
402 | { B_CENTER, "center", dt_flag }, | ||
403 | { B_LEFTADJUST, "leftadjust", dt_flag }, | ||
404 | { B_COMPRESS, "compress", dt_flag }, | ||
405 | { B_SPLIT, "split", dt_flag }, | ||
406 | { B_NEWLINE, "newline", dt_flag }, | ||
407 | { B_ADDRFIELD, "addrfield", dt_flag }, | ||
408 | { B_DATEFIELD, "datefield", dt_flag }, | ||
409 | |||
410 | /* String variables */ | ||
411 | { S_OVERFLOWTEXT, "overflowtext", dt_string }, | ||
412 | { S_COMPONENT, "component", dt_string }, | ||
413 | { S_IGNORES, "ignores", dt_string }, | ||
414 | |||
415 | /* Format variables */ | ||
416 | { F_FORMATFIELD, "formatfield", dt_format }, | ||
417 | { 0 } | ||
418 | }; | ||
419 | |||
420 | static mhl_variable_t * | ||
421 | variable_lookup (char *name) | ||
422 | { | ||
423 | mhl_variable_t *p; | ||
424 | |||
425 | for (p = vartab; p->name; p++) | ||
426 | { | ||
427 | if (p->type == dt_flag | ||
428 | && memcmp (name, "no", 2) == 0 | ||
429 | && strcmp (p->name, name + 2) == 0) | ||
430 | return p; | ||
431 | |||
432 | if (strcmp (p->name, name) == 0) | ||
433 | return p; | ||
434 | } | ||
435 | return NULL; | ||
436 | } | ||
437 | |||
438 | struct eval_env | ||
439 | { | ||
440 | message_t msg; | ||
441 | stream_t output; | ||
442 | list_t printed_fields; /* A list of printed header names */ | ||
443 | int pos; | ||
444 | int nlines; | ||
445 | int ivar[I_MAX]; | ||
446 | int bvar[B_MAX]; | ||
447 | char *svar[S_MAX]; | ||
448 | mh_format_t *fvar[F_MAX]; | ||
449 | char *prefix; | ||
450 | }; | ||
451 | |||
452 | static int eval_stmt (void *item, void *data); | ||
453 | static void newline (struct eval_env *env); | ||
454 | static void goto_offset (struct eval_env *env, int count); | ||
455 | static void print (struct eval_env *env, char *str, int nloff); | ||
456 | |||
457 | static int | ||
458 | _comp_name (void *item, void *date) | ||
459 | { | ||
460 | return strcasecmp (item, date) == 0; | ||
461 | } | ||
462 | |||
463 | int | ||
464 | header_is_printed (struct eval_env *env, char *name) | ||
465 | { | ||
466 | return list_do (env->printed_fields, _comp_name, name) == 1; | ||
467 | } | ||
468 | |||
469 | int | ||
470 | want_header (struct eval_env *env, char *name) | ||
471 | { | ||
472 | char *p, *str = env->svar[S_IGNORES]; | ||
473 | |||
474 | for (p = strchrnul (str, ','); *str; p = strchrnul (str, ',')) | ||
475 | { | ||
476 | if (strncasecmp (name, str, p - str) == 0) | ||
477 | return 0; | ||
478 | str = p; | ||
479 | if (*str) | ||
480 | str++; | ||
481 | } | ||
482 | return 1; | ||
483 | } | ||
484 | |||
485 | static int | ||
486 | eval_var (struct eval_env *env, mhl_stmt_variable_t *var) | ||
487 | { | ||
488 | switch (var->id->type) | ||
489 | { | ||
490 | case dt_flag: | ||
491 | env->bvar[var->id->id] = var->value.num; | ||
492 | break; | ||
493 | |||
494 | case dt_integer: | ||
495 | env->ivar[var->id->id] = var->value.num; | ||
496 | break; | ||
497 | |||
498 | case dt_string: | ||
499 | env->svar[var->id->id] = var->value.str; | ||
500 | break; | ||
501 | |||
502 | case dt_format: | ||
503 | env->fvar[var->id->id] = var->value.fmt; | ||
504 | break; | ||
505 | |||
506 | default: | ||
507 | abort (); | ||
508 | } | ||
509 | return 0; | ||
510 | } | ||
511 | |||
512 | static void | ||
513 | ovf_print (struct eval_env *env, char *str, int size, int nloff) | ||
514 | { | ||
515 | int ovf = 0; | ||
516 | |||
517 | while (size) | ||
518 | { | ||
519 | int len = size; | ||
520 | if (ovf) | ||
521 | { | ||
522 | goto_offset (env, env->ivar[I_OVERFLOWOFFSET]); | ||
523 | if (env->svar[S_OVERFLOWTEXT]) | ||
524 | { | ||
525 | int l = strlen (env->svar[S_OVERFLOWTEXT]); | ||
526 | stream_sequential_write (env->output, | ||
527 | env->svar[S_OVERFLOWTEXT], l); | ||
528 | env->pos += l; | ||
529 | } | ||
530 | } | ||
531 | else | ||
532 | { | ||
533 | if (env->prefix && !env->bvar[B_NOCOMPONENT]) | ||
534 | { | ||
535 | goto_offset (env, env->ivar[I_OFFSET]); | ||
536 | |||
537 | stream_sequential_write (env->output, env->prefix, | ||
538 | strlen (env->prefix)); | ||
539 | env->pos += strlen (env->prefix); | ||
540 | |||
541 | goto_offset (env, nloff); | ||
542 | } | ||
543 | } | ||
544 | |||
545 | if (env->pos + len > env->ivar[I_WIDTH]) | ||
546 | { | ||
547 | ovf = 1; | ||
548 | len = env->ivar[I_WIDTH] - env->pos; | ||
549 | } | ||
550 | |||
551 | stream_sequential_write (env->output, str, len); | ||
552 | env->pos += len; | ||
553 | if (env->pos >= env->ivar[I_WIDTH]) | ||
554 | newline (env); | ||
555 | str += len; | ||
556 | size -= len; | ||
557 | } | ||
558 | } | ||
559 | |||
560 | static void | ||
561 | print (struct eval_env *env, char *str, int nloff) | ||
562 | { | ||
563 | do | ||
564 | { | ||
565 | if (*str == '\n') | ||
566 | { | ||
567 | newline (env); | ||
568 | str++; | ||
569 | } | ||
570 | else | ||
571 | { | ||
572 | char *p = strchrnul (str, '\n'); | ||
573 | ovf_print (env, str, p - str, nloff); | ||
574 | str = p; | ||
575 | if (*p) | ||
576 | { | ||
577 | newline (env); | ||
578 | for (str++; *str && isspace (*str); str++) | ||
579 | ; | ||
580 | } | ||
581 | } | ||
582 | } | ||
583 | while (*str); | ||
584 | } | ||
585 | |||
586 | static void | ||
587 | newline (struct eval_env *env) | ||
588 | { | ||
589 | stream_sequential_write (env->output, "\n", 1); | ||
590 | env->pos = 0; | ||
591 | if (env->ivar[I_LENGTH] && ++env->nlines >= env->ivar[I_LENGTH]) | ||
592 | { | ||
593 | /* FIXME: Better to write it directly on the terminal */ | ||
594 | if (env->bvar[B_BELL]) | ||
595 | stream_sequential_write (env->output, "\a", 1); | ||
596 | if (env->bvar[B_CLEARSCREEN]) | ||
597 | stream_sequential_write (env->output, "\f", 1); | ||
598 | env->nlines = 0; | ||
599 | } | ||
600 | } | ||
601 | |||
602 | static void | ||
603 | goto_offset (struct eval_env *env, int count) | ||
604 | { | ||
605 | for (; env->pos < count; env->pos++) | ||
606 | stream_sequential_write (env->output, " ", 1); | ||
607 | } | ||
608 | |||
609 | int | ||
610 | print_header_value (struct eval_env *env, char *val) | ||
611 | { | ||
612 | char *p; | ||
613 | |||
614 | if (env->fvar[F_FORMATFIELD]) | ||
615 | { | ||
616 | if (mh_format_str (env->fvar[F_FORMATFIELD], val, | ||
617 | env->ivar[I_WIDTH], &p)) | ||
618 | val = p; | ||
619 | } | ||
620 | |||
621 | if (env->bvar[B_UPPERCASE]) | ||
622 | { | ||
623 | for (p = val; *p; p++) | ||
624 | *p = toupper (*p); | ||
625 | } | ||
626 | |||
627 | if (env->bvar[B_COMPRESS]) | ||
628 | for (p = val; *p; p++) | ||
629 | if (*p == '\n') | ||
630 | *p = ' '; | ||
631 | |||
632 | if (env->bvar[B_LEFTADJUST]) | ||
633 | { | ||
634 | for (p = val; *p && isspace (*p); p++) | ||
635 | ; | ||
636 | } | ||
637 | else | ||
638 | p = val; | ||
639 | |||
640 | print (env, p, env->ivar[I_COMPWIDTH]); | ||
641 | return 0; | ||
642 | } | ||
643 | |||
644 | int | ||
645 | eval_component (struct eval_env *env, char *name) | ||
646 | { | ||
647 | header_t hdr; | ||
648 | char *val; | ||
649 | |||
650 | message_get_header (env->msg, &hdr); | ||
651 | if (header_aget_value (hdr, name, &val)) | ||
652 | return 0; | ||
653 | |||
654 | list_append (env->printed_fields, name); | ||
655 | print_header_value (env, val); | ||
656 | free (val); | ||
657 | return 0; | ||
658 | } | ||
659 | |||
660 | int | ||
661 | eval_body (struct eval_env *env) | ||
662 | { | ||
663 | body_t body = NULL; | ||
664 | stream_t input = NULL; | ||
665 | char buf[128]; /* FIXME: Fixed size. Bad */ | ||
666 | size_t n; | ||
667 | |||
668 | env->prefix = env->svar[S_COMPONENT]; | ||
669 | message_get_body (env->msg, &body); | ||
670 | body_get_stream (body, &input); | ||
671 | stream_seek (input, 0, SEEK_SET); | ||
672 | while (stream_sequential_readline (input, buf, sizeof buf, &n) == 0 | ||
673 | && n > 0) | ||
674 | { | ||
675 | buf[n] = 0; | ||
676 | print (env, buf, 0); | ||
677 | } | ||
678 | return 0; | ||
679 | } | ||
680 | |||
681 | int | ||
682 | eval_extras (struct eval_env *env) | ||
683 | { | ||
684 | header_t hdr; | ||
685 | size_t i, num; | ||
686 | char buf[512]; | ||
687 | |||
688 | message_get_header (env->msg, &hdr); | ||
689 | header_get_field_count (hdr, &num); | ||
690 | for (i = 1; i <= num; i++) | ||
691 | { | ||
692 | header_get_field_name (hdr, i, buf, sizeof buf, NULL); | ||
693 | if (want_header (env, buf) | ||
694 | && !header_is_printed (env, buf)) | ||
695 | { | ||
696 | goto_offset (env, env->ivar[I_OFFSET]); | ||
697 | print (env, buf, 0); | ||
698 | print (env, ":", 0); | ||
699 | header_get_field_value (hdr, i, buf, sizeof buf, NULL); | ||
700 | print_header_value (env, buf); | ||
701 | if (env->bvar[B_NEWLINE]) | ||
702 | newline (env); | ||
703 | } | ||
704 | } | ||
705 | return 0; | ||
706 | } | ||
707 | |||
708 | int | ||
709 | eval_comp (struct eval_env *env, char *compname, list_t format) | ||
710 | { | ||
711 | struct eval_env lenv = *env; | ||
712 | |||
713 | list_do (format, eval_stmt, &lenv); | ||
714 | |||
715 | goto_offset (&lenv, lenv.ivar[I_OFFSET]); | ||
716 | |||
717 | if (!lenv.svar[S_COMPONENT]) | ||
718 | lenv.svar[S_COMPONENT] = compname; | ||
719 | |||
720 | if (!lenv.bvar[B_NOCOMPONENT]) | ||
721 | { | ||
722 | print (&lenv, lenv.svar[S_COMPONENT], 0); | ||
723 | if (strcmp (compname, "body")) | ||
724 | print (&lenv, ":", 0); | ||
725 | } | ||
726 | |||
727 | if (strcmp (compname, "extras") == 0) | ||
728 | eval_extras (&lenv); | ||
729 | else if (strcmp (compname, "body") == 0) | ||
730 | eval_body (&lenv); | ||
731 | else | ||
732 | eval_component (&lenv, compname); | ||
733 | |||
734 | if (lenv.bvar[B_NEWLINE]) | ||
735 | newline (&lenv); | ||
736 | |||
737 | env->pos = lenv.pos; | ||
738 | env->nlines = lenv.nlines; | ||
739 | |||
740 | return 0; | ||
741 | } | ||
742 | |||
743 | static int | ||
744 | eval_stmt (void *item, void *data) | ||
745 | { | ||
746 | mhl_stmt_t *stmt = item; | ||
747 | struct eval_env *env = data; | ||
748 | |||
749 | switch (stmt->type) | ||
750 | { | ||
751 | case stmt_cleartext: | ||
752 | print (env, stmt->v.cleartext, 0); | ||
753 | newline (env); | ||
754 | break; | ||
755 | |||
756 | case stmt_component: | ||
757 | eval_comp (env, stmt->v.component.name, stmt->v.component.format); | ||
758 | break; | ||
759 | |||
760 | case stmt_variable: | ||
761 | eval_var (env, &stmt->v.variable); | ||
762 | break; | ||
763 | |||
764 | default: | ||
765 | abort (); | ||
766 | } | ||
767 | |||
768 | return 0; | ||
769 | } | ||
770 | |||
771 | int | ||
772 | mhl_format_run (list_t fmt, | ||
773 | int width, int length, int clearscreen, int bell, | ||
774 | message_t msg, stream_t output) | ||
775 | { | ||
776 | int rc; | ||
777 | struct eval_env env; | ||
778 | |||
779 | /* Initialize the environment */ | ||
780 | memset (&env, 0, sizeof (env)); | ||
781 | |||
782 | env.bvar[B_NEWLINE] = 1; | ||
783 | list_create (&env.printed_fields); | ||
784 | env.ivar[I_WIDTH] = width; | ||
785 | env.ivar[I_LENGTH] = length; | ||
786 | env.bvar[B_CLEARSCREEN] = clearscreen; | ||
787 | env.bvar[B_BELL] = bell; | ||
788 | env.pos = 0; | ||
789 | env.nlines = 0; | ||
790 | env.msg = msg; | ||
791 | env.output = output; | ||
792 | rc = list_do (fmt, eval_stmt, &env); | ||
793 | list_destroy (&env.printed_fields); | ||
794 | return rc; | ||
795 | } |
mh/mhl.format
0 → 100644
1 | ; This is the default mhl.format file for Mailutils MH. | ||
2 | ; | ||
3 | ; GNU Mailutils -- a suite of utilities for electronic mail | ||
4 | ; Copyright (C) 2003 Free Software Foundation, Inc. | ||
5 | ; Distributed under GPL. | ||
6 | ; | ||
7 | : -- using template mhl.format -- | ||
8 | overflowtext="***",overflowoffset=5 | ||
9 | leftadjust,compwidth=9 | ||
10 | ignores="msgid,message-id,received" | ||
11 | Date:formatfield="%<(nodate{text})%{text}%|%(pretty{text})%>" | ||
12 | To: | ||
13 | cc: | ||
14 | : | ||
15 | From: | ||
16 | Subject: | ||
17 | : | ||
18 | extras:nocomponent | ||
19 | : | ||
20 | body:nocomponent,overflowtext="",overflowoffset=0,noleftadjust | ||
21 | ; End of mhl.format | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
-
Please register or sign in to post a comment