1 | |
---|
2 | /* |
---|
3 | * fmtdump.c -- compile format file and dump out instructions |
---|
4 | * |
---|
5 | * $Id: fmtdump.c,v 1.1.1.1 1999-02-07 18:14:13 danw Exp $ |
---|
6 | */ |
---|
7 | |
---|
8 | #include <h/mh.h> |
---|
9 | #include <h/fmt_scan.h> |
---|
10 | #include <h/fmt_compile.h> |
---|
11 | #include <h/scansbr.h> |
---|
12 | |
---|
13 | static struct swit switches[] = { |
---|
14 | #define FORMSW 0 |
---|
15 | { "form formatfile", 0 }, |
---|
16 | #define FMTSW 1 |
---|
17 | { "format string", 5 }, |
---|
18 | #define VERSIONSW 2 |
---|
19 | { "version", 0 }, |
---|
20 | #define HELPSW 3 |
---|
21 | { "help", 4 }, |
---|
22 | { NULL, 0 } |
---|
23 | }; |
---|
24 | |
---|
25 | /* for assignlabel */ |
---|
26 | static struct format *lvec[128]; |
---|
27 | static lused = 0; |
---|
28 | |
---|
29 | /* |
---|
30 | * static prototypes |
---|
31 | */ |
---|
32 | static void fmt_dump (struct format *); |
---|
33 | static void dumpone(struct format *); |
---|
34 | static int findlabel(struct format *); |
---|
35 | static void assignlabel(struct format *); |
---|
36 | static char *f_typestr(int); |
---|
37 | static char *c_typestr(int); |
---|
38 | static void litputs(char *); |
---|
39 | static void litputc(char); |
---|
40 | |
---|
41 | |
---|
42 | int |
---|
43 | main (int argc, char **argv) |
---|
44 | { |
---|
45 | int ncomps; |
---|
46 | char *cp, *form = NULL, *format = NULL; |
---|
47 | char buf[BUFSIZ], *nfs, **argp, **arguments; |
---|
48 | struct format *fmt; |
---|
49 | |
---|
50 | #ifdef LOCALE |
---|
51 | setlocale(LC_ALL, ""); |
---|
52 | #endif |
---|
53 | invo_name = r1bindex (argv[0], '/'); |
---|
54 | |
---|
55 | /* read user profile/context */ |
---|
56 | context_read(); |
---|
57 | |
---|
58 | arguments = getarguments (invo_name, argc, argv, 1); |
---|
59 | argp = arguments; |
---|
60 | |
---|
61 | while ((cp = *argp++)) { |
---|
62 | if (*cp == '-') { |
---|
63 | switch (smatch (++cp, switches)) { |
---|
64 | case AMBIGSW: |
---|
65 | ambigsw (cp, switches); |
---|
66 | done (1); |
---|
67 | case UNKWNSW: |
---|
68 | adios (NULL, "-%s unknown", cp); |
---|
69 | |
---|
70 | case HELPSW: |
---|
71 | snprintf (buf, sizeof(buf), "%s [switches]", invo_name); |
---|
72 | print_help (buf, switches, 1); |
---|
73 | done (1); |
---|
74 | case VERSIONSW: |
---|
75 | print_version(invo_name); |
---|
76 | done (1); |
---|
77 | |
---|
78 | case FORMSW: |
---|
79 | if (!(form = *argp++) || *form == '-') |
---|
80 | adios (NULL, "missing argument to %s", argp[-2]); |
---|
81 | format = NULL; |
---|
82 | continue; |
---|
83 | case FMTSW: |
---|
84 | if (!(format = *argp++) || *format == '-') |
---|
85 | adios (NULL, "missing argument to %s", argp[-2]); |
---|
86 | form = NULL; |
---|
87 | continue; |
---|
88 | |
---|
89 | } |
---|
90 | } |
---|
91 | if (form) |
---|
92 | adios (NULL, "only one form at a time!"); |
---|
93 | else |
---|
94 | form = cp; |
---|
95 | } |
---|
96 | |
---|
97 | /* |
---|
98 | * Get new format string. Must be before chdir(). |
---|
99 | */ |
---|
100 | nfs = new_fs (form, format, FORMAT); |
---|
101 | ncomps = fmt_compile(nfs, &fmt); |
---|
102 | |
---|
103 | fmt_dump(fmt); |
---|
104 | done(0); |
---|
105 | } |
---|
106 | |
---|
107 | static void |
---|
108 | fmt_dump (struct format *fmth) |
---|
109 | { |
---|
110 | int i; |
---|
111 | register struct format *fmt, *addr; |
---|
112 | |
---|
113 | /* Assign labels */ |
---|
114 | for (fmt = fmth; fmt; ++fmt) { |
---|
115 | i = fmt->f_type; |
---|
116 | if (i == FT_IF_S || |
---|
117 | i == FT_IF_S_NULL || |
---|
118 | i == FT_IF_V_EQ || |
---|
119 | i == FT_IF_V_NE || |
---|
120 | i == FT_IF_V_GT || |
---|
121 | i == FT_IF_MATCH || |
---|
122 | i == FT_IF_AMATCH || |
---|
123 | i == FT_GOTO) { |
---|
124 | addr = fmt + fmt->f_skip; |
---|
125 | if (findlabel(addr) < 0) |
---|
126 | assignlabel(addr); |
---|
127 | } |
---|
128 | if (fmt->f_type == FT_DONE && fmt->f_value == 0) |
---|
129 | break; |
---|
130 | } |
---|
131 | |
---|
132 | /* Dump them out! */ |
---|
133 | for (fmt = fmth; fmt; ++fmt) { |
---|
134 | dumpone(fmt); |
---|
135 | if (fmt->f_type == FT_DONE && fmt->f_value == 0) |
---|
136 | break; |
---|
137 | } |
---|
138 | } |
---|
139 | |
---|
140 | static void |
---|
141 | dumpone(struct format *fmt) |
---|
142 | { |
---|
143 | register int i; |
---|
144 | |
---|
145 | if ((i = findlabel(fmt)) >= 0) |
---|
146 | printf("L%d:", i); |
---|
147 | putchar('\t'); |
---|
148 | |
---|
149 | fputs(f_typestr((int)fmt->f_type), stdout); |
---|
150 | |
---|
151 | switch (fmt->f_type) { |
---|
152 | |
---|
153 | case FT_COMP: |
---|
154 | case FT_LS_COMP: |
---|
155 | case FT_LV_COMPFLAG: |
---|
156 | case FT_LV_COMP: |
---|
157 | printf(", comp "); |
---|
158 | litputs(fmt->f_comp->c_name); |
---|
159 | if (fmt->f_comp->c_type) |
---|
160 | printf(", c_type %s", c_typestr(fmt->f_comp->c_type)); |
---|
161 | if (fmt->f_comp->c_flags) |
---|
162 | printf(", c_flags %d", fmt->f_comp->c_flags); |
---|
163 | break; |
---|
164 | |
---|
165 | case FT_LV_SEC: |
---|
166 | case FT_LV_MIN: |
---|
167 | case FT_LV_HOUR: |
---|
168 | case FT_LV_MDAY: |
---|
169 | case FT_LV_MON: |
---|
170 | case FT_LS_MONTH: |
---|
171 | case FT_LS_LMONTH: |
---|
172 | case FT_LS_ZONE: |
---|
173 | case FT_LV_YEAR: |
---|
174 | case FT_LV_WDAY: |
---|
175 | case FT_LS_DAY: |
---|
176 | case FT_LS_WEEKDAY: |
---|
177 | case FT_LV_YDAY: |
---|
178 | case FT_LV_ZONE: |
---|
179 | case FT_LV_CLOCK: |
---|
180 | case FT_LV_RCLOCK: |
---|
181 | case FT_LV_DAYF: |
---|
182 | case FT_LV_ZONEF: |
---|
183 | case FT_LV_DST: |
---|
184 | case FT_LS_822DATE: |
---|
185 | case FT_LS_PRETTY: |
---|
186 | case FT_LOCALDATE: |
---|
187 | case FT_GMTDATE: |
---|
188 | case FT_PARSEDATE: |
---|
189 | printf(", c_name "); |
---|
190 | litputs(fmt->f_comp->c_name); |
---|
191 | if (fmt->f_comp->c_type) |
---|
192 | printf(", c_type %s", c_typestr(fmt->f_comp->c_type)); |
---|
193 | if (fmt->f_comp->c_flags) |
---|
194 | printf(", c_flags %d", fmt->f_comp->c_flags); |
---|
195 | break; |
---|
196 | |
---|
197 | case FT_LS_ADDR: |
---|
198 | case FT_LS_PERS: |
---|
199 | case FT_LS_MBOX: |
---|
200 | case FT_LS_HOST: |
---|
201 | case FT_LS_PATH: |
---|
202 | case FT_LS_GNAME: |
---|
203 | case FT_LS_NOTE: |
---|
204 | case FT_LS_822ADDR: |
---|
205 | case FT_LV_HOSTTYPE: |
---|
206 | case FT_LV_INGRPF: |
---|
207 | case FT_LV_NOHOSTF: |
---|
208 | case FT_LS_FRIENDLY: |
---|
209 | case FT_PARSEADDR: |
---|
210 | case FT_MYMBOX: |
---|
211 | printf(", c_name "); |
---|
212 | litputs(fmt->f_comp->c_name); |
---|
213 | if (fmt->f_comp->c_type) |
---|
214 | printf(", c_type %s", c_typestr(fmt->f_comp->c_type)); |
---|
215 | if (fmt->f_comp->c_flags) |
---|
216 | printf(", c_flags %d", fmt->f_comp->c_flags); |
---|
217 | break; |
---|
218 | |
---|
219 | case FT_COMPF: |
---|
220 | printf(", width %d, fill '", fmt->f_width); |
---|
221 | litputc(fmt->f_fill); |
---|
222 | printf("' name "); |
---|
223 | litputs(fmt->f_comp->c_name); |
---|
224 | if (fmt->f_comp->c_type) |
---|
225 | printf(", c_type %s", c_typestr(fmt->f_comp->c_type)); |
---|
226 | if (fmt->f_comp->c_flags) |
---|
227 | printf(", c_flags %d", fmt->f_comp->c_flags); |
---|
228 | break; |
---|
229 | |
---|
230 | case FT_STRF: |
---|
231 | case FT_NUMF: |
---|
232 | printf(", width %d, fill '", fmt->f_width); |
---|
233 | litputc(fmt->f_fill); |
---|
234 | putchar('\''); |
---|
235 | break; |
---|
236 | |
---|
237 | case FT_LIT: |
---|
238 | #ifdef FT_LIT_FORCE |
---|
239 | case FT_LIT_FORCE: |
---|
240 | #endif |
---|
241 | putchar(' '); |
---|
242 | litputs(fmt->f_text); |
---|
243 | break; |
---|
244 | |
---|
245 | case FT_LITF: |
---|
246 | printf(", width %d, fill '", fmt->f_width); |
---|
247 | litputc(fmt->f_fill); |
---|
248 | printf("' "); |
---|
249 | litputs(fmt->f_text); |
---|
250 | break; |
---|
251 | |
---|
252 | case FT_CHAR: |
---|
253 | putchar(' '); |
---|
254 | putchar('\''); |
---|
255 | litputc(fmt->f_char); |
---|
256 | putchar('\''); |
---|
257 | break; |
---|
258 | |
---|
259 | |
---|
260 | case FT_IF_S: |
---|
261 | case FT_IF_S_NULL: |
---|
262 | case FT_IF_MATCH: |
---|
263 | case FT_IF_AMATCH: |
---|
264 | printf(" continue else goto"); |
---|
265 | case FT_GOTO: |
---|
266 | i = findlabel(fmt + fmt->f_skip); |
---|
267 | printf(" L%d", i); |
---|
268 | break; |
---|
269 | |
---|
270 | case FT_IF_V_EQ: |
---|
271 | case FT_IF_V_NE: |
---|
272 | case FT_IF_V_GT: |
---|
273 | i = findlabel(fmt + fmt->f_skip); |
---|
274 | printf(" %d continue else goto L%d", fmt->f_value, i); |
---|
275 | break; |
---|
276 | |
---|
277 | case FT_V_EQ: |
---|
278 | case FT_V_NE: |
---|
279 | case FT_V_GT: |
---|
280 | case FT_LV_LIT: |
---|
281 | case FT_LV_PLUS_L: |
---|
282 | case FT_LV_MINUS_L: |
---|
283 | case FT_LV_DIVIDE_L: |
---|
284 | case FT_LV_MODULO_L: |
---|
285 | printf(" value %d", fmt->f_value); |
---|
286 | break; |
---|
287 | |
---|
288 | case FT_LS_LIT: |
---|
289 | printf(" str "); |
---|
290 | litputs(fmt->f_text); |
---|
291 | break; |
---|
292 | |
---|
293 | case FT_LS_GETENV: |
---|
294 | printf(" getenv "); |
---|
295 | litputs(fmt->f_text); |
---|
296 | break; |
---|
297 | |
---|
298 | case FT_LS_DECODECOMP: |
---|
299 | printf(", comp "); |
---|
300 | litputs(fmt->f_comp->c_name); |
---|
301 | break; |
---|
302 | |
---|
303 | case FT_LS_DECODE: |
---|
304 | break; |
---|
305 | |
---|
306 | case FT_LS_TRIM: |
---|
307 | printf(", width %d", fmt->f_width); |
---|
308 | break; |
---|
309 | |
---|
310 | case FT_LV_DAT: |
---|
311 | printf(", value dat[%d]", fmt->f_value); |
---|
312 | break; |
---|
313 | } |
---|
314 | putchar('\n'); |
---|
315 | } |
---|
316 | |
---|
317 | static int |
---|
318 | findlabel(struct format *addr) |
---|
319 | { |
---|
320 | register int i; |
---|
321 | |
---|
322 | for (i = 0; i < lused; ++i) |
---|
323 | if (addr == lvec[i]) |
---|
324 | return(i); |
---|
325 | return(-1); |
---|
326 | } |
---|
327 | |
---|
328 | static void |
---|
329 | assignlabel(struct format *addr) |
---|
330 | { |
---|
331 | lvec[lused++] = addr; |
---|
332 | } |
---|
333 | |
---|
334 | static char * |
---|
335 | f_typestr(int t) |
---|
336 | { |
---|
337 | static char buf[32]; |
---|
338 | |
---|
339 | switch (t) { |
---|
340 | case FT_COMP: return("COMP"); |
---|
341 | case FT_COMPF: return("COMPF"); |
---|
342 | case FT_LIT: return("LIT"); |
---|
343 | case FT_LITF: return("LITF"); |
---|
344 | #ifdef FT_LIT_FORCE |
---|
345 | case FT_LIT_FORCE: return("LIT_FORCE"); |
---|
346 | #endif |
---|
347 | case FT_CHAR: return("CHAR"); |
---|
348 | case FT_NUM: return("NUM"); |
---|
349 | case FT_NUMF: return("NUMF"); |
---|
350 | case FT_STR: return("STR"); |
---|
351 | case FT_STRF: return("STRF"); |
---|
352 | case FT_STRFW: return("STRFW"); |
---|
353 | case FT_PUTADDR: return("PUTADDR"); |
---|
354 | case FT_LS_COMP: return("LS_COMP"); |
---|
355 | case FT_LS_LIT: return("LS_LIT"); |
---|
356 | case FT_LS_GETENV: return("LS_GETENV"); |
---|
357 | case FT_LS_DECODECOMP: return("FT_LS_DECODECOMP"); |
---|
358 | case FT_LS_DECODE: return("FT_LS_DECODE"); |
---|
359 | case FT_LS_TRIM: return("LS_TRIM"); |
---|
360 | case FT_LV_COMP: return("LV_COMP"); |
---|
361 | case FT_LV_COMPFLAG: return("LV_COMPFLAG"); |
---|
362 | case FT_LV_LIT: return("LV_LIT"); |
---|
363 | case FT_LV_DAT: return("LV_DAT"); |
---|
364 | case FT_LV_STRLEN: return("LV_STRLEN"); |
---|
365 | case FT_LV_PLUS_L: return("LV_PLUS_L"); |
---|
366 | case FT_LV_MINUS_L: return("LV_MINUS_L"); |
---|
367 | case FT_LV_DIVIDE_L: return("LV_DIVIDE_L"); |
---|
368 | case FT_LV_MODULO_L: return("LV_MODULO_L"); |
---|
369 | case FT_LV_CHAR_LEFT: return("LV_CHAR_LEFT"); |
---|
370 | case FT_LS_MONTH: return("LS_MONTH"); |
---|
371 | case FT_LS_LMONTH: return("LS_LMONTH"); |
---|
372 | case FT_LS_ZONE: return("LS_ZONE"); |
---|
373 | case FT_LS_DAY: return("LS_DAY"); |
---|
374 | case FT_LS_WEEKDAY: return("LS_WEEKDAY"); |
---|
375 | case FT_LS_822DATE: return("LS_822DATE"); |
---|
376 | case FT_LS_PRETTY: return("LS_PRETTY"); |
---|
377 | case FT_LV_SEC: return("LV_SEC"); |
---|
378 | case FT_LV_MIN: return("LV_MIN"); |
---|
379 | case FT_LV_HOUR: return("LV_HOUR"); |
---|
380 | case FT_LV_MDAY: return("LV_MDAY"); |
---|
381 | case FT_LV_MON: return("LV_MON"); |
---|
382 | case FT_LV_YEAR: return("LV_YEAR"); |
---|
383 | case FT_LV_YDAY: return("LV_YDAY"); |
---|
384 | case FT_LV_WDAY: return("LV_WDAY"); |
---|
385 | case FT_LV_ZONE: return("LV_ZONE"); |
---|
386 | case FT_LV_CLOCK: return("LV_CLOCK"); |
---|
387 | case FT_LV_RCLOCK: return("LV_RCLOCK"); |
---|
388 | case FT_LV_DAYF: return("LV_DAYF"); |
---|
389 | case FT_LV_DST: return("LV_DST"); |
---|
390 | case FT_LV_ZONEF: return("LV_ZONEF"); |
---|
391 | case FT_LS_ADDR: return("LS_ADDR"); |
---|
392 | case FT_LS_PERS: return("LS_PERS"); |
---|
393 | case FT_LS_MBOX: return("LS_MBOX"); |
---|
394 | case FT_LS_HOST: return("LS_HOST"); |
---|
395 | case FT_LS_PATH: return("LS_PATH"); |
---|
396 | case FT_LS_GNAME: return("LS_GNAME"); |
---|
397 | case FT_LS_NOTE: return("LS_NOTE"); |
---|
398 | case FT_LS_822ADDR: return("LS_822ADDR"); |
---|
399 | case FT_LS_FRIENDLY: return("LS_FRIENDLY"); |
---|
400 | case FT_LV_HOSTTYPE: return("LV_HOSTTYPE"); |
---|
401 | case FT_LV_INGRPF: return("LV_INGRPF"); |
---|
402 | case FT_LV_NOHOSTF: return("LV_NOHOSTF"); |
---|
403 | case FT_LOCALDATE: return("LOCALDATE"); |
---|
404 | case FT_GMTDATE: return("GMTDATE"); |
---|
405 | case FT_PARSEDATE: return("PARSEDATE"); |
---|
406 | case FT_PARSEADDR: return("PARSEADDR"); |
---|
407 | case FT_FORMATADDR: return("FORMATADDR"); |
---|
408 | case FT_MYMBOX: return("MYMBOX"); |
---|
409 | #ifdef FT_ADDTOSEQ |
---|
410 | case FT_ADDTOSEQ: return("ADDTOSEQ"); |
---|
411 | #endif |
---|
412 | case FT_SAVESTR: return("SAVESTR"); |
---|
413 | #ifdef FT_PAUSE |
---|
414 | case FT_PAUSE: return ("PAUSE"); |
---|
415 | #endif |
---|
416 | case FT_DONE: return("DONE"); |
---|
417 | case FT_NOP: return("NOP"); |
---|
418 | case FT_GOTO: return("GOTO"); |
---|
419 | case FT_IF_S_NULL: return("IF_S_NULL"); |
---|
420 | case FT_IF_S: return("IF_S"); |
---|
421 | case FT_IF_V_EQ: return("IF_V_EQ"); |
---|
422 | case FT_IF_V_NE: return("IF_V_NE"); |
---|
423 | case FT_IF_V_GT: return("IF_V_GT"); |
---|
424 | case FT_IF_MATCH: return("IF_MATCH"); |
---|
425 | case FT_IF_AMATCH: return("IF_AMATCH"); |
---|
426 | case FT_S_NULL: return("S_NULL"); |
---|
427 | case FT_S_NONNULL: return("S_NONNULL"); |
---|
428 | case FT_V_EQ: return("V_EQ"); |
---|
429 | case FT_V_NE: return("V_NE"); |
---|
430 | case FT_V_GT: return("V_GT"); |
---|
431 | case FT_V_MATCH: return("V_MATCH"); |
---|
432 | case FT_V_AMATCH: return("V_AMATCH"); |
---|
433 | default: |
---|
434 | printf(buf, "/* ??? #%d */", t); |
---|
435 | return(buf); |
---|
436 | } |
---|
437 | } |
---|
438 | |
---|
439 | #define FNORD(v, s) if (t & (v)) { \ |
---|
440 | if (i++ > 0) \ |
---|
441 | strcat(buf, "|"); \ |
---|
442 | strcat(buf, s); } |
---|
443 | |
---|
444 | static char * |
---|
445 | c_typestr(int t) |
---|
446 | { |
---|
447 | register int i; |
---|
448 | static char buf[64]; |
---|
449 | |
---|
450 | buf[0] = '\0'; |
---|
451 | if (t & ~(CT_ADDR|CT_DATE|CT_MYMBOX|CT_ADDRPARSE)) |
---|
452 | printf(buf, "0x%x ", t); |
---|
453 | strcat(buf, "<"); |
---|
454 | i = 0; |
---|
455 | FNORD(CT_ADDR, "ADDR"); |
---|
456 | FNORD(CT_DATE, "DATE"); |
---|
457 | FNORD(CT_MYMBOX, "MYMBOX"); |
---|
458 | FNORD(CT_ADDRPARSE, "ADDRPARSE"); |
---|
459 | strcat(buf, ">"); |
---|
460 | return(buf); |
---|
461 | #undef FNORD |
---|
462 | } |
---|
463 | |
---|
464 | static void |
---|
465 | litputs(char *s) |
---|
466 | { |
---|
467 | if (s) { |
---|
468 | putc('"', stdout); |
---|
469 | while (*s) |
---|
470 | litputc(*s++); |
---|
471 | putc('"', stdout); |
---|
472 | } else |
---|
473 | fputs("<nil>", stdout); |
---|
474 | } |
---|
475 | |
---|
476 | static void |
---|
477 | litputc(char c) |
---|
478 | { |
---|
479 | if (c & ~ 0177) { |
---|
480 | putc('M', stdout); |
---|
481 | putc('-', stdout); |
---|
482 | c &= 0177; |
---|
483 | } |
---|
484 | if (c < 0x20 || c == 0177) { |
---|
485 | if (c == '\b') { |
---|
486 | putc('\\', stdout); |
---|
487 | putc('b', stdout); |
---|
488 | } else if (c == '\f') { |
---|
489 | putc('\\', stdout); |
---|
490 | putc('f', stdout); |
---|
491 | } else if (c == '\n') { |
---|
492 | putc('\\', stdout); |
---|
493 | putc('n', stdout); |
---|
494 | } else if (c == '\r') { |
---|
495 | putc('\\', stdout); |
---|
496 | putc('r', stdout); |
---|
497 | } else if (c == '\t') { |
---|
498 | putc('\\', stdout); |
---|
499 | putc('t', stdout); |
---|
500 | } else { |
---|
501 | putc('^', stdout); |
---|
502 | putc(c ^ 0x40, stdout); /* DEL to ?, others to alpha */ |
---|
503 | } |
---|
504 | } else |
---|
505 | putc(c, stdout); |
---|
506 | } |
---|