home *** CD-ROM | disk | FTP | other *** search
- #ifndef lint
- static char rcsid[] = "$Header: command.c,v 1.4 86/05/05 14:08:32 root Exp $";
- #endif
-
- /* command.c decodes command. Uses binary search in array
- * of struct cmd.
- */
-
- #include "fmtr.h"
-
- #define HUGE 1000
- #define PLUS '+'
- #define MINUS '-'
-
- #define MAX(x,y) ((x) > (y) ? (x) : (y))
- #define MIN(x,y) ((x) < (y) ? (x) : (y))
-
- /* cmdtype is upper case version of command. All commands of
- * interest to us are either ce, ul, or else equivalent to
- * fi or nf
- */
-
- enum cmdtype
- {
- CE, UL, FI, NF, OTHER
- } cmd, getcmd();
-
- int len;
-
- struct cmd {
- char *name;
- enum cmdtype type;
- } cmd_table[50] = { "ce", CE, /* basic nroff requests */
- "ul", UL,
- "nf", NF,
- "fi", FI,
- "TS", NF, /* universal macros */
- "TE", FI,
- "EQ", NF,
- "EN", FI,
- "PS", NF,
- "PE", FI,
- "IS", NF,
- "IE", FI,
- "DS", NF, /* ms macros */
- "ID", NF,
- "CD", NF,
- "LD", NF,
- "DE", FI,
- "(b", NF, /* me macros */
- ")b", FI,
- "(c", NF,
- ")c", FI,
- "(l", NF,
- ")l", FI,
- "(z", NF,
- ")z", FI,
- (char *) NULL, OTHER
- };
-
- int val; /* both are set in getval() */
- char argtype; /* and used in setparam() */
-
- /* command() takes a line starting with some form of the command start
- * sequence (period or apostrophe, optionally preceded by \&), and
- * calls getcmd() to return an integer representing the command name,
- * and then takes appropriate action.
- *
- * In all cases it produces a break and prints out the command line as is.
- */
-
- command(line)
- char line[];
- {
- cmd = getcmd(line);
-
- if (cmd != OTHER)
- switch (cmd) {
- case CE:
- getval(line); /* only need getval() with CE and UL */
- ce_val = setparam(ce_val, 1, 0, HUGE);
- break;
- case UL:
- getval(line);
- ul_val = setparam(ul_val, 1, 0, HUGE);
- break;
- case NF:
- nf_val = 1;
- break;
- case FI:
- nf_val = 0;
- break;
- }
-
- n_brk();
- puts(line);
- }
-
- enum cmdtype getcmd(line) /* gets command type by binary search */
- char *line; /* stolen from K & R p. 125 with minor changes */
- {
- int high, low, mid, cond;
- char *cp;
-
- low = 0;
- high = len - 1;
-
- cp = (*line == '\\') ? line + 3 : line + 1;
-
- while (low <= high) {
- mid = (low + high)/2;
- if ((cond = strncmp(cp, cmd_table[mid].name, 2)) < 0)
- high = mid - 1;
- else if (cond > 0)
- low = mid + 1;
- else
- return(cmd_table[mid].type);
- }
- return(OTHER);
- }
-
- mk_table(sarray, earray)
- char *sarray, *earray;
- {
- int mycmp();
- char *cp, *malloc(), *strncpy();
- struct cmd *cmdptr;
-
- if (len == 0) { /* find end */
- cmdptr = cmd_table;
- while (cmdptr->name)
- cmdptr++; /* now pointing to NULL ending defined */
- len = cmdptr - cmd_table;
- }
- else
- cmdptr = cmd_table + len;
-
- if (sarray)
- for (cp = sarray; *cp; cp += 3) {
- cmdptr->name = malloc(3);
- (void) strncpy(cmdptr->name, cp + 1, 2);
- cmdptr->type = NF;
- cmdptr++;
- }
-
- if (earray)
- for (cp = earray; *cp; cp += 3) {
- cmdptr->name = malloc(3);
- (void) strncpy(cmdptr->name, cp + 1, 2);
- cmdptr->type = FI;
- cmdptr++;
- }
-
- len = cmdptr - cmd_table;
-
- qsort((char *) cmd_table, len, sizeof cmd_table[0], mycmp);
- }
-
- mycmp(s1, s2)
- struct cmd *s1, *s2;
- {
- return(strcmp(s1->name, s2->name));
- }
-
- /* getval() gets value of argument preceded by optional sign. Here
- we are following the nroff rules: commands are exactly two
- letters long followed by optional spaces before arguments. */
-
- getval(line)
- char *line;
- {
- char *cp;
-
- if (*line == '\\') /* don't test for z_flag, since otherwise */
- cp = line + 5; /* we would not be here */
- else
- cp = line + 3;
- for ( ; isspace(*cp); *cp++)
- ;
- argtype = *cp;
- if (argtype == PLUS || argtype == MINUS)
- cp++;
- val = atoi(cp);
- }
-
- /* setparam() sets parameter. May be set to param if present and legal,
- * otherwise to def_val, if absent, less than min_val or greater than
- * max_val.
- */
-
- setparam(param, def_val, min_val, max_val)
- int param, def_val, min_val, max_val;
- {
- if (argtype == '\0')
- return(def_val);
- else if (argtype == PLUS)
- param += val;
- else if (argtype == MINUS)
- param -= val;
- else
- param = val;
- param = MAX(param, min_val);
- param = MIN(param, max_val);
-
- return(param);
- }
-
- #ifdef DEBUG
- print_tab() /* prints table, useful while debugging */
- {
- struct cmd *cmdptr;
-
- for (cmdptr = cmd_table; cmdptr < cmd_table + len; cmdptr++)
- printf("%s\n", cmdptr->name);
- }
- #endif
-