From: Ken Hornstein Date: Mon, 10 Dec 2012 21:01:59 +0000 (-0500) Subject: The beginnings of a program to test format functions/files. X-Git-Url: https://diplodocus.org/git/nmh/commitdiff_plain/2f5c4e8664a5bb3a20dfb5e93667022fa2e0abac?ds=sidebyside;hp=-c The beginnings of a program to test format functions/files. --- 2f5c4e8664a5bb3a20dfb5e93667022fa2e0abac diff --git a/.gitignore b/.gitignore index b6e7ab37..e5c3e6f3 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,7 @@ a.out.dSYM/ /uip/dp /uip/flist /uip/fmtdump +/uip/fmttest /uip/folder /uip/forw /uip/inc diff --git a/Makefile.am b/Makefile.am index 27ffdfbb..734f4269 100644 --- a/Makefile.am +++ b/Makefile.am @@ -120,8 +120,8 @@ BUILT_SOURCES = sbr/sigmsg.h ## the latter do not have $(EXEEXT) added on the end. ## bin_PROGRAMS = uip/ali uip/anno uip/burst uip/comp uip/dist uip/flist \ - uip/folder uip/forw uip/inc uip/install-mh uip/mark \ - uip/mhbuild uip/mhlist uip/mhn uip/mhparam \ + uip/fmttest uip/folder uip/forw uip/inc uip/install-mh \ + uip/mark uip/mhbuild uip/mhlist uip/mhn uip/mhparam \ uip/mhpath uip/mhshow uip/mhstore uip/msgchk uip/msh uip/new \ uip/packf uip/pick uip/prompter uip/refile uip/repl uip/rmf \ uip/rmm uip/scan uip/send uip/show uip/sortm uip/whatnow \ @@ -363,6 +363,9 @@ uip_dp_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) uip_fmtdump_SOURCES = uip/fmtdump.c uip_fmtdump_LDADD = $(LDADD) $(ICONVLIB) +uip_fmttest_SOURCES = uip/fmttest.c uip/termsbr.c +uip_fmttest_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) + uip_mhl_SOURCES = uip/mhl.c uip/mhlsbr.c uip/termsbr.c uip_mhl_LDADD = $(LDADD) $(TERMLIB) $(ICONVLIB) diff --git a/uip/fmttest.c b/uip/fmttest.c new file mode 100644 index 00000000..b5d24db3 --- /dev/null +++ b/uip/fmttest.c @@ -0,0 +1,627 @@ + +/* + * fmttest.c -- A program to help test and debug format instructions + * + * This code is Copyright (c) 2012, by the authors of nmh. See the + * COPYRIGHT file in the root directory of the nmh distribution for + * complete copyright information. + */ + +#include +#include +#include +#include +#include + +static struct swit switches[] = { +#define FORMSW 0 + { "form formatfile", 0 }, +#define FMTSW 1 + { "format string", 5 }, +#define DUMPSW 2 + { "dump", 0 }, +#define ADDRSW 3 + { "address", 0 }, +#define DATESW 4 + { "date", 0 }, +#define WIDTHSW 5 + { "width columns", 0 }, +#define BUFSZSW 6 + { "bufsize size-in-bytes", 0 }, +#define VERSIONSW 7 + { "version", 0 }, +#define OTHERSW 8 + { "-component-name component-text", 0 }, +#define HELPSW 9 + { "help", 0 }, + { NULL, 0 } +}; + +/* + * An array containing labels used for branch instructions + */ + +static struct format **lvec = NULL; +static int lused = 0; +static int lallocated = 0; + +/* + * static prototypes + */ +static void fmt_dump (struct format *); +static void dumpone(struct format *); +static int findlabel(struct format *); +static void assignlabel(struct format *); +static char *f_typestr(int); +static char *c_typestr(int); +static char *c_flagsstr(int); +static void litputs(char *); +static void litputc(char); + + +int +main (int argc, char **argv) +{ + char *cp, *form = NULL, *format = NULL; + char buf[BUFSIZ], *nfs, **argp, **arguments; + char **compargs = NULL; + struct format *fmt; + struct comp *cptr; + int dump = 0, compp = 0, comppalloc = 0, i; + int width = 0, bufsize = 0; + int dat[5]; + +#ifdef LOCALE + setlocale(LC_ALL, ""); +#endif + invo_name = r1bindex (argv[0], '/'); + + /* read user profile/context */ + context_read(); + + arguments = getarguments (invo_name, argc, argv, 1); + argp = arguments; + + while ((cp = *argp++)) { + if (*cp == '-') { + /* + * A -- means that we have a component name (like pick); + * save the component name and the next argument for the text. + */ + if (*++cp == '-') { + /* it's -3 because of this ptr, next ptr, and trailing NULL */ + if (compp > comppalloc - 3) { + comppalloc += 32; + compargs = (char **) mh_xrealloc(compargs, sizeof(char *) * + comppalloc); + } + compargs[compp++] = --cp; + /* Grab next argument for component text */ + if (!(cp = *argp++)) + adios(NULL, "missing argument to %s", argp[-2]); + compargs[compp++] = cp; + continue; + } + switch (smatch (cp, switches)) { + case AMBIGSW: + ambigsw (cp, switches); + done (1); + case UNKWNSW: + adios (NULL, "-%s unknown", cp); + + case HELPSW: + snprintf (buf, sizeof(buf), "%s [switches]", invo_name); + print_help (buf, switches, 1); + done (0); + case VERSIONSW: + print_version(invo_name); + done (0); + case OTHERSW: + adios(NULL, "internal argument error!"); + continue; + + case WIDTHSW: + if (!(cp = *argp++) || *cp == '-') + adios(NULL, "missing argument to %s", argp[-2]); + width = atoi(cp); + continue; + case BUFSZSW: + if (!(cp = *argp++) || *cp == '-') + adios(NULL, "missing argument to %s", argp[-2]); + bufsize = atoi(cp); + continue; + + case FORMSW: + if (!(form = *argp++) || *form == '-') + adios (NULL, "missing argument to %s", argp[-2]); + format = NULL; + continue; + case FMTSW: + if (!(format = *argp++) || *format == '-') + adios (NULL, "missing argument to %s", argp[-2]); + form = NULL; + continue; + + case DUMPSW: + dump++; + continue; + + } + } + if (form) + adios (NULL, "only one form at a time!"); + else + form = cp; + } + + if (compargs) + compargs[compp] = NULL; + + /* + * Here's our weird heuristic: + * + * - We allow -dump without any other arguments. + * - If you've given any component arguments, we don't require any + * other arguments. + * - The arguments are interpreted as folders/messages. + */ + + /* + * Get new format string. Must be before chdir(). + */ + nfs = new_fs (form, format, FORMAT); + (void) fmt_compile(nfs, &fmt, 1); + + if (dump) + fmt_dump(fmt); + + if (compargs) { + for (i = 0; compargs[i] != NULL; i += 2) { + cptr = fmt_findcomp(compargs[i]); + if (cptr) + cptr->c_text = getcpy(compargs[i + 1]); + } + } + + if (width == 0) + width = sc_width(); + + /* + * If we don't specify a buffer size, allocate a default one. + */ + + if (bufsize == 0) { + } + + fmt_free(fmt, 1); + + done(0); + return 1; +} + +static void +fmt_dump (struct format *fmth) +{ + int i; + register struct format *fmt, *addr; + + /* Assign labels */ + for (fmt = fmth; fmt; ++fmt) { + i = fmt->f_type; + if (i == FT_IF_S || + i == FT_IF_S_NULL || + i == FT_IF_V_EQ || + i == FT_IF_V_NE || + i == FT_IF_V_GT || + i == FT_IF_MATCH || + i == FT_IF_AMATCH || + i == FT_GOTO) { + addr = fmt + fmt->f_skip; + if (findlabel(addr) < 0) + assignlabel(addr); + } + if (fmt->f_type == FT_DONE && fmt->f_value == 0) + break; + } + + /* Dump them out! */ + for (fmt = fmth; fmt; ++fmt) { + dumpone(fmt); + if (fmt->f_type == FT_DONE && fmt->f_value == 0) + break; + } +} + +static void +dumpone(struct format *fmt) +{ + register int i; + + if ((i = findlabel(fmt)) >= 0) + printf("L%d:", i); + putchar('\t'); + + fputs(f_typestr((int)fmt->f_type), stdout); + + switch (fmt->f_type) { + + case FT_COMP: + case FT_LS_COMP: + case FT_LV_COMPFLAG: + case FT_LV_COMP: + printf(", comp "); + litputs(fmt->f_comp->c_name); + if (fmt->f_comp->c_type) + printf(", c_type %s", c_typestr(fmt->f_comp->c_type)); + if (fmt->f_comp->c_flags) + printf(", c_flags %s", c_flagsstr(fmt->f_comp->c_flags)); + break; + + case FT_LV_SEC: + case FT_LV_MIN: + case FT_LV_HOUR: + case FT_LV_MDAY: + case FT_LV_MON: + case FT_LS_MONTH: + case FT_LS_LMONTH: + case FT_LS_ZONE: + case FT_LV_YEAR: + case FT_LV_WDAY: + case FT_LS_DAY: + case FT_LS_WEEKDAY: + case FT_LV_YDAY: + case FT_LV_ZONE: + case FT_LV_CLOCK: + case FT_LV_RCLOCK: + case FT_LV_DAYF: + case FT_LV_ZONEF: + case FT_LV_DST: + case FT_LS_822DATE: + case FT_LS_PRETTY: + case FT_LOCALDATE: + case FT_GMTDATE: + case FT_PARSEDATE: + printf(", c_name "); + litputs(fmt->f_comp->c_name); + if (fmt->f_comp->c_type) + printf(", c_type %s", c_typestr(fmt->f_comp->c_type)); + if (fmt->f_comp->c_flags) + printf(", c_flags %s", c_flagsstr(fmt->f_comp->c_flags)); + break; + + case FT_LS_ADDR: + case FT_LS_PERS: + case FT_LS_MBOX: + case FT_LS_HOST: + case FT_LS_PATH: + case FT_LS_GNAME: + case FT_LS_NOTE: + case FT_LS_822ADDR: + case FT_LV_HOSTTYPE: + case FT_LV_INGRPF: + case FT_LV_NOHOSTF: + case FT_LS_FRIENDLY: + case FT_PARSEADDR: + case FT_MYMBOX: + printf(", c_name "); + litputs(fmt->f_comp->c_name); + if (fmt->f_comp->c_type) + printf(", c_type %s", c_typestr(fmt->f_comp->c_type)); + if (fmt->f_comp->c_flags) + printf(", c_flags %s", c_flagsstr(fmt->f_comp->c_flags)); + break; + + case FT_COMPF: + printf(", width %d, fill '", fmt->f_width); + litputc(fmt->f_fill); + printf("' name "); + litputs(fmt->f_comp->c_name); + if (fmt->f_comp->c_type) + printf(", c_type %s", c_typestr(fmt->f_comp->c_type)); + if (fmt->f_comp->c_flags) + printf(", c_flags %s", c_flagsstr(fmt->f_comp->c_flags)); + break; + + case FT_STRF: + case FT_NUMF: + printf(", width %d, fill '", fmt->f_width); + litputc(fmt->f_fill); + putchar('\''); + break; + + case FT_LIT: +#ifdef FT_LIT_FORCE + case FT_LIT_FORCE: +#endif + putchar(' '); + litputs(fmt->f_text); + break; + + case FT_LITF: + printf(", width %d, fill '", fmt->f_width); + litputc(fmt->f_fill); + printf("' "); + litputs(fmt->f_text); + break; + + case FT_CHAR: + putchar(' '); + putchar('\''); + litputc(fmt->f_char); + putchar('\''); + break; + + + case FT_IF_S: + case FT_IF_S_NULL: + case FT_IF_MATCH: + case FT_IF_AMATCH: + printf(" continue else goto"); + case FT_GOTO: + i = findlabel(fmt + fmt->f_skip); + printf(" L%d", i); + break; + + case FT_IF_V_EQ: + case FT_IF_V_NE: + case FT_IF_V_GT: + i = findlabel(fmt + fmt->f_skip); + printf(" %d continue else goto L%d", fmt->f_value, i); + break; + + case FT_V_EQ: + case FT_V_NE: + case FT_V_GT: + case FT_LV_LIT: + case FT_LV_PLUS_L: + case FT_LV_MINUS_L: + case FT_LV_DIVIDE_L: + case FT_LV_MODULO_L: + printf(" value %d", fmt->f_value); + break; + + case FT_LS_LIT: + printf(" str "); + litputs(fmt->f_text); + break; + + case FT_LS_GETENV: + printf(" getenv "); + litputs(fmt->f_text); + break; + + case FT_LS_DECODECOMP: + printf(", comp "); + litputs(fmt->f_comp->c_name); + break; + + case FT_LS_DECODE: + break; + + case FT_LS_TRIM: + printf(", width %d", fmt->f_width); + break; + + case FT_LV_DAT: + printf(", value dat[%d]", fmt->f_value); + break; + } + putchar('\n'); +} + +static int +findlabel(struct format *addr) +{ + register int i; + + for (i = 0; i < lused; ++i) + if (addr == lvec[i]) + return(i); + return(-1); +} + +static void +assignlabel(struct format *addr) +{ + if (lused >= lallocated) { + lallocated += 64; + lvec = (struct format **) + mh_xrealloc(lvec, sizeof(struct format *) * lallocated); + } + + lvec[lused++] = addr; +} + +static char * +f_typestr(int t) +{ + static char buf[32]; + + switch (t) { + case FT_COMP: return("COMP"); + case FT_COMPF: return("COMPF"); + case FT_LIT: return("LIT"); + case FT_LITF: return("LITF"); +#ifdef FT_LIT_FORCE + case FT_LIT_FORCE: return("LIT_FORCE"); +#endif + case FT_CHAR: return("CHAR"); + case FT_NUM: return("NUM"); + case FT_NUMF: return("NUMF"); + case FT_STR: return("STR"); + case FT_STRF: return("STRF"); + case FT_STRFW: return("STRFW"); + case FT_PUTADDR: return("PUTADDR"); + case FT_STRLIT: return("STRLIT"); + case FT_STRLITZ: return("STRLITZ"); + case FT_LS_COMP: return("LS_COMP"); + case FT_LS_LIT: return("LS_LIT"); + case FT_LS_GETENV: return("LS_GETENV"); + case FT_LS_DECODECOMP: return("FT_LS_DECODECOMP"); + case FT_LS_DECODE: return("FT_LS_DECODE"); + case FT_LS_TRIM: return("LS_TRIM"); + case FT_LV_COMP: return("LV_COMP"); + case FT_LV_COMPFLAG: return("LV_COMPFLAG"); + case FT_LV_LIT: return("LV_LIT"); + case FT_LV_DAT: return("LV_DAT"); + case FT_LV_STRLEN: return("LV_STRLEN"); + case FT_LV_PLUS_L: return("LV_PLUS_L"); + case FT_LV_MINUS_L: return("LV_MINUS_L"); + case FT_LV_DIVIDE_L: return("LV_DIVIDE_L"); + case FT_LV_MODULO_L: return("LV_MODULO_L"); + case FT_LV_CHAR_LEFT: return("LV_CHAR_LEFT"); + case FT_LS_MONTH: return("LS_MONTH"); + case FT_LS_LMONTH: return("LS_LMONTH"); + case FT_LS_ZONE: return("LS_ZONE"); + case FT_LS_DAY: return("LS_DAY"); + case FT_LS_WEEKDAY: return("LS_WEEKDAY"); + case FT_LS_822DATE: return("LS_822DATE"); + case FT_LS_PRETTY: return("LS_PRETTY"); + case FT_LV_SEC: return("LV_SEC"); + case FT_LV_MIN: return("LV_MIN"); + case FT_LV_HOUR: return("LV_HOUR"); + case FT_LV_MDAY: return("LV_MDAY"); + case FT_LV_MON: return("LV_MON"); + case FT_LV_YEAR: return("LV_YEAR"); + case FT_LV_YDAY: return("LV_YDAY"); + case FT_LV_WDAY: return("LV_WDAY"); + case FT_LV_ZONE: return("LV_ZONE"); + case FT_LV_CLOCK: return("LV_CLOCK"); + case FT_LV_RCLOCK: return("LV_RCLOCK"); + case FT_LV_DAYF: return("LV_DAYF"); + case FT_LV_DST: return("LV_DST"); + case FT_LV_ZONEF: return("LV_ZONEF"); + case FT_LS_ADDR: return("LS_ADDR"); + case FT_LS_PERS: return("LS_PERS"); + case FT_LS_MBOX: return("LS_MBOX"); + case FT_LS_HOST: return("LS_HOST"); + case FT_LS_PATH: return("LS_PATH"); + case FT_LS_GNAME: return("LS_GNAME"); + case FT_LS_NOTE: return("LS_NOTE"); + case FT_LS_822ADDR: return("LS_822ADDR"); + case FT_LS_FRIENDLY: return("LS_FRIENDLY"); + case FT_LV_HOSTTYPE: return("LV_HOSTTYPE"); + case FT_LV_INGRPF: return("LV_INGRPF"); + case FT_LV_NOHOSTF: return("LV_NOHOSTF"); + case FT_LOCALDATE: return("LOCALDATE"); + case FT_GMTDATE: return("GMTDATE"); + case FT_PARSEDATE: return("PARSEDATE"); + case FT_PARSEADDR: return("PARSEADDR"); + case FT_FORMATADDR: return("FORMATADDR"); + case FT_CONCATADDR: return("CONCATADDR"); + case FT_MYMBOX: return("MYMBOX"); +#ifdef FT_ADDTOSEQ + case FT_ADDTOSEQ: return("ADDTOSEQ"); +#endif + case FT_SAVESTR: return("SAVESTR"); +#ifdef FT_PAUSE + case FT_PAUSE: return ("PAUSE"); +#endif + case FT_DONE: return("DONE"); + case FT_NOP: return("NOP"); + case FT_GOTO: return("GOTO"); + case FT_IF_S_NULL: return("IF_S_NULL"); + case FT_IF_S: return("IF_S"); + case FT_IF_V_EQ: return("IF_V_EQ"); + case FT_IF_V_NE: return("IF_V_NE"); + case FT_IF_V_GT: return("IF_V_GT"); + case FT_IF_MATCH: return("IF_MATCH"); + case FT_IF_AMATCH: return("IF_AMATCH"); + case FT_S_NULL: return("S_NULL"); + case FT_S_NONNULL: return("S_NONNULL"); + case FT_V_EQ: return("V_EQ"); + case FT_V_NE: return("V_NE"); + case FT_V_GT: return("V_GT"); + case FT_V_MATCH: return("V_MATCH"); + case FT_V_AMATCH: return("V_AMATCH"); + default: + printf(buf, "/* ??? #%d */", t); + return(buf); + } +} + +#define FNORD(v, s) if (t & (v)) { \ + if (i++ > 0) \ + strcat(buf, "|"); \ + strcat(buf, s); } + +static char * +c_typestr(int t) +{ + register int i; + static char buf[64]; + + buf[0] = '\0'; + if (t & ~(CT_ADDR|CT_DATE)) + printf(buf, "0x%x ", t); + strcat(buf, "<"); + i = 0; + FNORD(CT_ADDR, "ADDR"); + FNORD(CT_DATE, "DATE"); + strcat(buf, ">"); + return(buf); +} + +static char * +c_flagsstr(int t) +{ + register int i; + static char buf[64]; + + buf[0] = '\0'; + if (t & ~(CF_TRUE|CF_PARSED|CF_DATEFAB|CF_TRIMMED)) + printf(buf, "0x%x ", t); + strcat(buf, "<"); + i = 0; + FNORD(CF_TRUE, "TRUE"); + FNORD(CF_PARSED, "PARSED"); + FNORD(CF_DATEFAB, "DATEFAB"); + FNORD(CF_TRIMMED, "TRIMMED"); + strcat(buf, ">"); + return(buf); +} +#undef FNORD + +static void +litputs(char *s) +{ + if (s) { + putc('"', stdout); + while (*s) + litputc(*s++); + putc('"', stdout); + } else + fputs("", stdout); +} + +static void +litputc(char c) +{ + if (c & ~ 0177) { + putc('M', stdout); + putc('-', stdout); + c &= 0177; + } + if (c < 0x20 || c == 0177) { + if (c == '\b') { + putc('\\', stdout); + putc('b', stdout); + } else if (c == '\f') { + putc('\\', stdout); + putc('f', stdout); + } else if (c == '\n') { + putc('\\', stdout); + putc('n', stdout); + } else if (c == '\r') { + putc('\\', stdout); + putc('r', stdout); + } else if (c == '\t') { + putc('\\', stdout); + putc('t', stdout); + } else { + putc('^', stdout); + putc(c ^ 0x40, stdout); /* DEL to ?, others to alpha */ + } + } else + putc(c, stdout); +}