Commit 642cefd5 642cefd563506bdaae17a6f6bd18ed6868cd563e by Sergey Poznyakoff

(mh_format_dump): New function. Produces the

listing of compiled format code.
(builtin_me, builtin_profile, builtin_putstr, print_string,
 builtin_putnum, builtin_putnumf, builtin_tws,
 builtin_pretty): Implemented.
(builtin_pers): Enclose the return in a pair of double-quotes.
1 parent 000309e0
...@@ -52,6 +52,8 @@ struct mh_machine ...@@ -52,6 +52,8 @@ struct mh_machine
52 size_t msgno; /* Its number */ 52 size_t msgno; /* Its number */
53 }; 53 };
54 54
55 static char *_get_builtin_name __P((mh_builtin_fp ptr));
56
55 /* Functions for handling string objects. */ 57 /* Functions for handling string objects. */
56 58
57 void 59 void
...@@ -410,6 +412,180 @@ mh_format (mh_format_t *fmt, message_t msg, size_t msgno, ...@@ -410,6 +412,180 @@ mh_format (mh_format_t *fmt, message_t msg, size_t msgno,
410 return mach.ind; 412 return mach.ind;
411 } 413 }
412 414
415 void
416 mh_format_dump (mh_format_t *fmt)
417 {
418 mh_instr_t *prog = fmt->prog;
419 size_t pc = 1;
420 int stop = 0;
421
422 while (!stop)
423 {
424 mh_opcode_t opcode;
425 int num;
426
427 printf ("% 4.4ld: ", (long) pc);
428 switch (opcode = MHI_OPCODE(prog[pc++]))
429 {
430 case mhop_stop:
431 printf ("stop");
432 stop = 1;
433 break;
434
435 case mhop_branch:
436 num = MHI_NUM(prog[pc++]);
437 printf ("branch %d, %lu",
438 num, (unsigned long) pc + num - 1);
439 break;
440
441 case mhop_num_asgn:
442 printf ("num_asgn");
443 break;
444
445 case mhop_str_asgn:
446 printf ("str_asgn");
447 break;
448
449 case mhop_num_arg:
450 num = MHI_NUM(prog[pc++]);
451 printf ("num_arg %d", num);
452 break;
453
454 case mhop_str_arg:
455 {
456 size_t skip = MHI_NUM(prog[pc++]);
457 char *s = MHI_STR(prog[pc]);
458 printf ("str_arg \"");
459 for (; *s; s++)
460 {
461 switch (*s)
462 {
463 case '\a':
464 printf ("\\a");
465 break;
466
467 case '\b':
468 printf ("\\b");
469 break;
470
471 case '\f':
472 printf ("\\f");
473 break;
474
475 case '\n':
476 printf ("\\n");
477 break;
478
479 case '\r':
480 printf ("\\r");
481 break;
482
483 case '\t':
484 printf ("\\t");
485 break;
486
487 case '"':
488 printf ("\\\"");
489 break;
490
491 default:
492 if (isprint (*s))
493 putchar (*s);
494 else
495 printf ("\\%03o", *s);
496 break;
497 }
498 }
499 printf ("\"");
500 pc += skip;
501 }
502 break;
503
504 case mhop_num_branch:
505 num = MHI_NUM(prog[pc++]);
506 printf ("num_branch %d, %lu",
507 num, (unsigned long) (pc + num - 1));
508 break;
509
510 case mhop_str_branch:
511 num = MHI_NUM(prog[pc++]);
512 printf ("str_branch %d, %lu",
513 num, (unsigned long) (pc + num - 1));
514 break;
515
516 case mhop_call:
517 {
518 char *name = _get_builtin_name (MHI_BUILTIN (prog[pc++]));
519 printf ("call %s", name ? name : "UNKNOWN");
520 }
521 break;
522
523 case mhop_header:
524 printf ("header");
525 break;
526
527 case mhop_body:
528 printf ("body");
529
530 case mhop_num_to_arg:
531 printf ("num_to_arg");
532 break;
533
534 /* assign reg_str to arg_str */
535 case mhop_str_to_arg:
536 printf ("str_to_arg");
537 break;
538
539 /* Convert arg_str to arg_num */
540 case mhop_str_to_num:
541 printf ("str_to_num");
542 break;
543
544 /* Convert arg_num to arg_str */
545 case mhop_num_to_str:
546 printf ("num_to_str");
547 break;
548
549 case mhop_num_print:
550 printf ("print");
551 break;
552
553 case mhop_str_print:
554 printf ("str_print");
555 break;
556
557 case mhop_fmtspec:
558 {
559 int space = 0;
560
561 num = MHI_NUM(prog[pc++]);
562 printf ("fmtspec: %#x, ", num);
563 if (num & MH_FMT_RALIGN)
564 {
565 printf ("MH_FMT_RALIGN");
566 space++;
567 }
568 if (num & MH_FMT_ZEROPAD)
569 {
570 if (space)
571 printf ("|");
572 printf ("MH_FMT_ZEROPAD");
573 space++;
574 }
575 if (space)
576 printf ("; ");
577 printf ("%d", num & MH_WIDTH_MASK);
578 }
579 break;
580
581 default:
582 mh_error ("Unknown opcode: %x", opcode);
583 abort ();
584 }
585 printf ("\n");
586 }
587 }
588
413 /* Free any memory associated with a format structure. The structure 589 /* Free any memory associated with a format structure. The structure
414 itself is assumed to be in static storage. */ 590 itself is assumed to be in static storage. */
415 void 591 void
...@@ -482,8 +658,9 @@ builtin_timenow (struct mh_machine *mach) ...@@ -482,8 +658,9 @@ builtin_timenow (struct mh_machine *mach)
482 static void 658 static void
483 builtin_me (struct mh_machine *mach) 659 builtin_me (struct mh_machine *mach)
484 { 660 {
485 /*FIXME*/ 661 char *s = mh_my_email ();
486 /* mach->arg_str = "me";*/ 662 strobj_free (&mach->arg_str);
663 strobj_create (&mach->arg_str, s);
487 } 664 }
488 665
489 static void 666 static void
...@@ -578,8 +755,9 @@ builtin_getenv (struct mh_machine *mach) ...@@ -578,8 +755,9 @@ builtin_getenv (struct mh_machine *mach)
578 static void 755 static void
579 builtin_profile (struct mh_machine *mach) 756 builtin_profile (struct mh_machine *mach)
580 { 757 {
581 /*FIXME*/ 758 char *val = strobj_ptr (&mach->arg_str);
582 /*mach->arg_str = "profile";*/ 759 strobj_free (&mach->arg_str);
760 strobj_create (&mach->arg_str, mh_global_profile_get (val, ""));
583 } 761 }
584 762
585 static void 763 static void
...@@ -645,28 +823,36 @@ builtin_trim (struct mh_machine *mach) ...@@ -645,28 +823,36 @@ builtin_trim (struct mh_machine *mach)
645 static void 823 static void
646 builtin_putstr (struct mh_machine *mach) 824 builtin_putstr (struct mh_machine *mach)
647 { 825 {
648 /*FIXME*/ 826 print_string (mach, 0,
827 strobj_ptr (&mach->arg_str), strobj_len (&mach->arg_str));
649 } 828 }
650 829
651 /* putstrf expr print str in a fixed width*/ 830 /* putstrf expr print str in a fixed width*/
652 static void 831 static void
653 builtin_putstrf (struct mh_machine *mach) 832 builtin_putstrf (struct mh_machine *mach)
654 { 833 {
655 /*FIXME*/ 834 print_string (mach, mach->reg_num,
835 strobj_ptr (&mach->arg_str), strobj_len (&mach->arg_str));
656 } 836 }
657 837
658 /* putnum expr print num*/ 838 /* putnum expr print num*/
659 static void 839 static void
660 builtin_putnum (struct mh_machine *mach) 840 builtin_putnum (struct mh_machine *mach)
661 { 841 {
662 /*FIXME*/ 842 char *p;
843 asprintf (&p, "%d", mach->arg_num);
844 print_string (mach, 0, p, strlen (p));
845 free (p);
663 } 846 }
664 847
665 /* putnumf expr print num in a fixed width*/ 848 /* putnumf expr print num in a fixed width*/
666 static void 849 static void
667 builtin_putnumf (struct mh_machine *mach) 850 builtin_putnumf (struct mh_machine *mach)
668 { 851 {
669 /*FIXME*/ 852 char *p;
853 asprintf (&p, "%d", mach->arg_num);
854 print_string (mach, mach->reg_num, p, strlen (p));
855 free (p);
670 } 856 }
671 857
672 static int 858 static int
...@@ -979,18 +1165,91 @@ builtin_rclock (struct mh_machine *mach) ...@@ -979,18 +1165,91 @@ builtin_rclock (struct mh_machine *mach)
979 mach->arg_num = now - mu_tm2time (&tm, &tz); 1165 mach->arg_num = now - mu_tm2time (&tm, &tz);
980 } 1166 }
981 1167
1168 struct
1169 {
1170 const char *std;
1171 const char *dst;
1172 int utc_offset; /* offset from GMT (hours) */
1173 } tzs[] = {
1174 { "GMT", "BST", 0 },
1175 { "EST", "EDT", -5 },
1176 { "CST", "CDT", -6 },
1177 { "MST", "MDT", -7 },
1178 { "PST", "PDT", -8 },
1179 { NULL, 0}
1180 };
1181
1182 static void
1183 date_cvt (struct mh_machine *mach, int pretty)
1184 {
1185 struct tm tm;
1186 mu_timezone tz;
1187 char buf[80];
1188 int i, len;
1189 const char *tzname = NULL;
1190
1191 if (_parse_date (mach, &tm, &tz))
1192 return;
1193
1194 if (pretty)
1195 {
1196 for (i = 0; tzs[i].std; i++)
1197 {
1198 int offset = tzs[i].utc_offset;
1199 int dst = 0;
1200
1201 #ifdef HAVE_STRUCT_TM_TM_ISDST
1202 if (tm.tm_isdst)
1203 dst = -1;
1204 #endif
1205
1206 if (tz.utc_offset == (offset + dst) * 3600)
1207 {
1208 if (dst)
1209 tzname = tzs[i].dst;
1210 else
1211 tzname = tzs[i].std;
1212 break;
1213 }
1214 }
1215 }
1216
1217 len = strftime (buf, sizeof buf,
1218 "%a, %d %b %Y %H:%M:%S ", &tm);
1219 if (tzname)
1220 snprintf (buf + len, sizeof(buf) - len, "%s", tzname);
1221 else
1222 {
1223 int min, hrs, sign;
1224 int offset = tz.utc_offset;
1225
1226 if (offset < 0)
1227 {
1228 sign = '-';
1229 offset = - offset;
1230 }
1231 else
1232 sign = '+';
1233 min = offset / 60;
1234 hrs = min / 60;
1235 min %= 60;
1236 snprintf (buf + len, sizeof(buf) - len, "%c%02d%02d", sign, hrs, min);
1237 }
1238 strobj_create (&mach->arg_str, buf);
1239 }
1240
982 /* tws date string official 822 rendering */ 1241 /* tws date string official 822 rendering */
983 static void 1242 static void
984 builtin_tws (struct mh_machine *mach) 1243 builtin_tws (struct mh_machine *mach)
985 { 1244 {
986 /*FIXME: noop*/ 1245 date_cvt (mach, 0);
987 } 1246 }
988 1247
989 /* pretty date string user-friendly rendering*/ 1248 /* pretty date string user-friendly rendering*/
990 static void 1249 static void
991 builtin_pretty (struct mh_machine *mach) 1250 builtin_pretty (struct mh_machine *mach)
992 { 1251 {
993 /*FIXME: noop*/ 1252 date_cvt (mach, 1);
994 } 1253 }
995 1254
996 /* nodate date integer str not a date string */ 1255 /* nodate date integer str not a date string */
...@@ -1050,11 +1309,18 @@ builtin_pers (struct mh_machine *mach) ...@@ -1050,11 +1309,18 @@ builtin_pers (struct mh_machine *mach)
1050 if (rc) 1309 if (rc)
1051 return; 1310 return;
1052 1311
1053 if (address_get_personal (addr, 1, buf, sizeof buf, &n) == 0) 1312 if (address_get_personal (addr, 1, buf, sizeof buf, &n) == 0
1054 strobj_create (&mach->arg_str, buf); 1313 && n > 1)
1314 {
1315 char *p;
1316 asprintf (&p, "\"%s\"", buf);
1317 strobj_create (&mach->arg_str, p);
1318 free (p);
1319 }
1055 address_destroy (&addr); 1320 address_destroy (&addr);
1056 } 1321 }
1057 1322
1323 /* FIXME: address_get_comments never returns any comments. */
1058 /* note addr string commentary text*/ 1324 /* note addr string commentary text*/
1059 static void 1325 static void
1060 builtin_note (struct mh_machine *mach) 1326 builtin_note (struct mh_machine *mach)
...@@ -1375,3 +1641,14 @@ mh_lookup_builtin (char *name, int *rest) ...@@ -1375,3 +1641,14 @@ mh_lookup_builtin (char *name, int *rest)
1375 } 1641 }
1376 return NULL; 1642 return NULL;
1377 } 1643 }
1644
1645 char *
1646 _get_builtin_name (mh_builtin_fp ptr)
1647 {
1648 mh_builtin_t *bp;
1649
1650 for (bp = builtin_tab; bp->name; bp++)
1651 if (bp->fun == ptr)
1652 return bp->name;
1653 return NULL;
1654 }
......