home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / TEXT / UTILITY / NROFF1.ZIP / NROCMD.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-07  |  16.6 KB  |  654 lines

  1. /*
  2.  *      Command processor for NRO text processor
  3.  *
  4.  *      Stephen L. Browning
  5.  *      5723 North Parker Avenue
  6.  *      Indianapolis, Indiana 46220
  7.  *
  8.  *    Ported to MS C 5.1 
  9.  *      by John Dudeck (jdudeck@polyslo.calpoly.edu) 11/25/90.
  10.  */
  11.  
  12. #include <stdio.h>
  13. #include "nro.h"
  14. #include "nroxtrn.h"
  15.  
  16. char *skipbl();
  17. char *skipwd();
  18.  
  19. comand(p)
  20. char *p;
  21. {
  22.         int ct, val;
  23.         int spval;
  24.         int index;
  25.         char argtyp;
  26.         char name[MAXLINE];
  27.         char macexp[MXMLEN];
  28.  
  29.         ct = comtyp(p,macexp);
  30.         if (ct == UNKNOWN) {
  31.                 printf("*** nro: unrecognized command %s\n",p);
  32.                 return;
  33.         }
  34.         expesc(p,name);
  35.         val = getval(p,&argtyp);
  36.         switch (ct) {
  37.         case BO: /* bold face */
  38.                 set(&dc.boval,val,argtyp,1,0,HUGE);
  39.                 dc.cuval = dc.ulval = 0;
  40.                 break;
  41.         case BP: /* begin page */
  42.                 if(pg.lineno > 0) space(HUGE);
  43.                 set(&pg.curpag,val,argtyp,pg.curpag+1,-HUGE,HUGE);
  44.                 pg.newpag = pg.curpag;
  45.                 break;
  46.         case BR: /* break */
  47.                 brk();
  48.                 break;
  49.         case BS: /* backspaces in output */
  50.                 set(&dc.bsflg,val,argtyp,1,0,1);
  51.                 break;
  52.         case CC: /* command character */
  53.                 if (argtyp == '\r' || argtyp == '\n') dc.cmdchr = '.';
  54.                 else dc.cmdchr = argtyp;
  55.                 break;
  56.         case CE: /* center */
  57.                 brk();
  58.                 set(&dc.ceval,val,argtyp,1,0,HUGE);
  59.                 break;
  60.         case CU: /* continuous underline */
  61.                 set(&dc.cuval,val,argtyp,1,0,HUGE);
  62.                 dc.ulval = dc.boval = 0;
  63.                 break;
  64.         case DE: /* define macro */
  65.                 defmac(p,sofile[dc.flevel]);
  66.                 break;
  67.         case EF: /* even footer */
  68.                 gettl(p,pg.efoot,&pg.eflim[0]);
  69.                 break;
  70.         case EH: /* even header */
  71.                 gettl(p,pg.ehead,&pg.ehlim[0]);
  72.                 break;
  73.         case EN: /* end macro definition */
  74.                 puts("***nro: missing .de command\n");
  75.                 break;
  76.         case FI: /* fill */
  77.                 brk();
  78.                 dc.fill = YES;
  79.                 break;
  80.         case FO: /* footer */
  81.                 gettl(p,pg.efoot,&pg.eflim[0]);
  82.                 gettl(p,pg.ofoot,&pg.oflim[0]);
  83.                 break;
  84.         case HE: /* header */
  85.                 gettl(p,pg.ehead,&pg.ehlim[0]);
  86.                 gettl(p,pg.ohead,&pg.ohlim[0]);
  87.                 break;
  88.         case IN: /* indenting */
  89.                 set(&dc.inval,val,argtyp,0,0,dc.rmval-1);
  90.                 dc.tival = dc.inval;
  91.                 break;
  92.         case JU: /* justify */
  93.                 dc.juval = YES;
  94.                 break;
  95.         case LS: /* line spacing */
  96.                 set(&dc.lsval,val,argtyp,1,1,HUGE);
  97.                 break;
  98.         case M1: /* set topmost margin */
  99.                 set(&pg.m1val,val,argtyp,2,0,HUGE);
  100.                 break;
  101.         case M2: /* set second top margin */
  102.                 set(&pg.m2val,val,argtyp,2,0,HUGE);
  103.                 break;
  104.         case M3: /* set first bottom margin */
  105.                 set(&pg.m3val,val,argtyp,2,0,HUGE);
  106.                 pg.bottom = pg.plval - pg.m4val - pg.m3val;
  107.                 break;
  108.         case M4: /* set bottom-most margin */
  109.                 set(&pg.m4val,val,argtyp,2,0,HUGE);
  110.                 pg.bottom = pg.plval - pg.m4val - pg.m3val;
  111.                 break;
  112.         case MACRO: /* macro expansion */
  113.                 maceval(p,macexp);
  114.                 break;
  115.         case NE: /* need n lines */
  116.                 brk();
  117.                 if ((pg.bottom-pg.lineno+1) < (val*dc.lsval)) {
  118.                         space(HUGE);
  119.                 }
  120.                 break;
  121.         case NF: /* no fill */
  122.                 brk();
  123.                 dc.fill = NO;
  124.                 break;
  125.         case NJ: /* no justify */
  126.                 dc.juval = NO;
  127.                 break;
  128.         case NR: /* set number register */
  129.                 p = skipwd(p);
  130.                 p = skipbl(p);
  131.                 if (!isalpha(*p)) {
  132.                         puts("***nro: invalid or missing number register name\n");
  133.                 }
  134.                 else {
  135.                         index = tolower(*p) - 'a';
  136.                         p = skipwd(p);
  137.                         val = getval(p,&argtyp);
  138.                         set(&dc.nr[index],val,argtyp,0,-HUGE,HUGE);
  139.                 }
  140.                 break;
  141.         case OF: /* odd footer */
  142.                 gettl(p,pg.ofoot,&pg.oflim[0]);
  143.                 break;
  144.         case OH: /* odd header */
  145.                 gettl(p,pg.ohead,&pg.ohlim[0]);
  146.                 break;
  147.         case PC: /* page number character */
  148.                 if (argtyp == '\r' || argtyp == '\n') dc.pgchr = EOS;
  149.                 else dc.pgchr = argtyp;
  150.                 break;
  151.         case PL: /* page length */
  152.                 set(&pg.plval,val,argtyp,PAGELEN,
  153.                         pg.m1val+pg.m2val+pg.m3val+pg.m4val+1,HUGE);
  154.                 pg.bottom = pg.plval - pg.m3val - pg.m4val;
  155.                 break;
  156.         case PO: /* page offset */
  157.                 set(&pg.offset,val,argtyp,0,0,HUGE);
  158.                 break;
  159.         case RM: /* right margin */
  160.                 set(&dc.rmval,val,argtyp,PAGEWIDTH,dc.tival+1,HUGE);
  161.                 break;
  162.         case SO: /* source file */
  163.                 p = skipwd(p);
  164.                 p = skipbl(p);
  165.                 if (getwrd(p,name) == 0) break;
  166.                 if (dc.flevel+1 >= NFILES) {
  167.                         puts("***nro: .so commands nested too deeply\n");
  168.                         exit(-1);
  169.                 }
  170.                 if ((sofile[dc.flevel+1] = fopen(name,"r")) == NULL) {
  171.                         printf("***nro: unable to open %s\n",name);
  172.                         exit(-1);
  173.                 }
  174.                 ++dc.flevel;
  175.                 break;
  176.         case SP: /* space */
  177.                 set(&spval,val,argtyp,1,0,HUGE);
  178.                 space(spval);
  179.                 break;
  180.         case TI: /* temporary indent */
  181.                 brk();
  182.                 set(&dc.tival,val,argtyp,0,0,dc.rmval);
  183.                 break;
  184.         case UL: /* underline */
  185.                 set(&dc.ulval,val,argtyp,0,1,HUGE);
  186.                 dc.cuval = dc.boval = 0;
  187.                 break;
  188.         }
  189. }
  190.  
  191.  
  192.  
  193. /*
  194.  *      convert ascii character to decimal.
  195.  */
  196.  
  197. atod(c)
  198. char c;
  199. {
  200.         return(((c < '0') || (c > '9')) ? -1 : c-'0');
  201. }
  202.  
  203.  
  204.  
  205. /*
  206.  *      end current filled line
  207.  */
  208.  
  209. brk()
  210. {
  211.         if(co.outp > 0) {
  212.             /*  co.outbuf[co.outp] = '\r'; 
  213.                 co.outbuf[co.outp + 1] = '\n';
  214.                 co.outbuf[co.outp + 2] = EOS; */
  215.                 
  216.                 co.outbuf[co.outp] = '\n';
  217.                 co.outbuf[co.outp + 1] = EOS;
  218.                 put(co.outbuf);
  219.         }
  220.         co.outp = 0;
  221.         co.outw = 0;
  222.         co.outwds = 0;
  223. }
  224.  
  225.  
  226. /*
  227.  *      Collect macro definition from input stream
  228.  */
  229.  
  230. colmac(p,d,i)
  231. char *p, d[];
  232. int i;
  233. {
  234.         while (*p != EOS) {
  235.                 if (i >= MXMLEN-1) {
  236.                         d[i-1] = EOS;
  237.                         return(ERR);
  238.                 }
  239.                 d[i++] = *p++;
  240.         }
  241.         d[i] = EOS;
  242.         return(i);
  243. }
  244.  
  245.  
  246.  
  247.  
  248. /*
  249.  *      decodes nro command and returns its associated
  250.  *      value.
  251.  */
  252.  
  253. comtyp(p,m)
  254. char *p;
  255. char *m;
  256. {
  257.         char c1, c2;
  258.         char macnam[MNLEN];
  259.         char *s;
  260.  
  261.         p++;
  262.         /*
  263.         *       First check to see if the command is a macro.
  264.         *       If it is, truncate to two characters and return
  265.         *       expansion in m.  Note that upper and lower case
  266.         *       characters are handled differently for macro names,
  267.         *       but not for normal command names.
  268.         */
  269.         getwrd(p,macnam);
  270.         macnam[2] = EOS;
  271.         if ((s = getmac(macnam)) != NULL) {
  272.                 strcpy(m,s);
  273.                 return(MACRO);
  274.         }
  275.         c1 = tolower(*p);
  276.         p++;
  277.         c2 = tolower(*p);
  278.         if (c1 == 'b' && c2 == 'o') return(BO);
  279.         if (c1 == 'b' && c2 == 'p') return(BP);
  280.         if (c1 == 'b' && c2 == 'r') return(BR);
  281.         if (c1 == 'b' && c2 == 's') return(BS);
  282.         if (c1 == 'c' && c2 == 'c') return(CC);
  283.         if (c1 == 'c' && c2 == 'e') return(CE);
  284.         if (c1 == 'c' && c2 == 'u') return(CU);
  285.         if (c1 == 'd' && c2 == 'e') return(DE);
  286.         if (c1 == 'e' && c2 == 'f') return(EF);
  287.         if (c1 == 'e' && c2 == 'h') return(EH);
  288.         if (c1 == 'e' && c2 == 'n') return(EN);
  289.         if (c1 == 'f' && c2 == 'i') return(FI);
  290.         if (c1 == 'f' && c2 == 'o') return(FO);
  291.         if (c1 == 'h' && c2 == 'e') return(HE);
  292.         if (c1 == 'i' && c2 == 'n') return(IN);
  293.         if (c1 == 'j' && c2 == 'u') return(JU);
  294.         if (c1 == 'l' && c2 == 's') return(LS);
  295.         if (c1 == 'm' && c2 == '1') return(M1);
  296.         if (c1 == 'm' && c2 == '2') return(M2);
  297.         if (c1 == 'm' && c2 == '3') return(M3);
  298.         if (c1 == 'm' && c2 == '4') return(M4);
  299.         if (c1 == 'n' && c2 == 'e') return(NE);
  300.         if (c1 == 'n' && c2 == 'f') return(NF);
  301.         if (c1 == 'n' && c2 == 'j') return(NJ);
  302.         if (c1 == 'n' && c2 == 'r') return(NR);
  303.         if (c1 == 'o' && c2 == 'f') return(OF);
  304.         if (c1 == 'o' && c2 == 'h') return(OH);
  305.         if (c1 == 'p' && c2 == 'c') return(PC);
  306.         if (c1 == 'p' && c2 == 'l') return(PL);
  307.         if (c1 == 'p' && c2 == 'o') return(PO);
  308.         if (c1 == 'r' && c2 == 'm') return(RM);
  309.         if (c1 == 's' && c2 == 'o') return(SO);
  310.         if (c1 == 's' && c2 == 'p') return(SP);
  311.         if (c1 == 't' && c2 == 'i') return(TI);
  312.         if (c1 == 'u' && c2 == 'l') return(UL);
  313.         return(UNKNOWN);
  314. }
  315.  
  316.  
  317.  
  318. /*
  319.  *      convert string to decimal.
  320.  *      processes only positive values.
  321.  */
  322.  
  323. ctod(p)
  324. char *p;
  325. {
  326.         int val, d;
  327.  
  328.         val = 0;
  329.         while(*p != EOS) {
  330.                 d = atod(*p);
  331.                 p++;
  332.                 if(d == -1) return(val);
  333.                 val = 10 * val + d;
  334.         }
  335.         return(val);
  336. }
  337.  
  338.  
  339. /*
  340.  *      Define a macro
  341.  */
  342.  
  343. defmac(p,infp)
  344. char *p;
  345. FILE *infp;
  346. {
  347.         int i;
  348.         char name[MNLEN];
  349.         char defn[MXMLEN];
  350.         char *q;
  351.  
  352.         q = skipwd(p);
  353.         q = skipbl(q);
  354.         i = getwrd(q,name);
  355.         if (!isalpha(*name)) {
  356.                 puts("***nro: missing or illegal macro definition name\n");
  357.                 exit(-1);
  358.         }
  359.         if (i > 2) name[2] = EOS;
  360.         i = 0;
  361.         while (getlin(p,infp) != EOF) {
  362.                 if (p[0] == dc.cmdchr && tolower(p[1]) == 'e' && tolower(p[2]) == 'n') {
  363.                         break;
  364.                 }
  365.                 if ((i = colmac(p,defn,i)) == ERR) {
  366.                         puts("***nro: macro definition too long\n");
  367.                         exit(-1);
  368.                 }
  369.         }
  370.         if (putmac(name,defn) == ERR) {
  371.                 puts("***nro: macro definition table full\n");
  372.                 exit(-1);
  373.         }
  374. }
  375.  
  376.  
  377. /*
  378.  *      Expand escape sequences
  379.  */
  380.  
  381. expesc(p,q)
  382. char *p;
  383. char *q;
  384. {
  385.         char *s, *t;
  386.  
  387.         s = p;
  388.         t = q;
  389.         while (*s != EOS) {
  390.                 if (*s != '@') {
  391.                         *t++ = *s++;
  392.                 }
  393.                 else if (*(s+1) == '@') {
  394.                         *t++ = *s++;
  395.                         ++s;
  396.                 }
  397.                 else if (tolower(*(s+1)) == 'n' && isalpha(*(s+2))) {
  398.                         s += 2;
  399.                         t += itoda(dc.nr[tolower(*s)-'a'],t,6) - 1;
  400.                         ++s;
  401.                 }
  402.                 else {
  403.                         *t++ = *s++;
  404.                 }
  405.         }
  406.         *t = EOS;
  407.         strcpy(p,q);
  408. }
  409.  
  410.  
  411.  
  412. /*
  413.  *      Get macro definition from table
  414.  */
  415.  
  416. char *getmac(name)
  417. char *name;
  418. {
  419.         int i;
  420.  
  421.         for (i = mac.lastp; i >= 0; --i) {
  422.                 if (!strcmp(name,mac.mnames[i])) {
  423.                         return(mac.mnames[i] + 3);
  424.                 }
  425.         }
  426.         return(NULL);
  427. }
  428.  
  429.  
  430.  
  431.  
  432. /*
  433.  *      get header or footer title
  434.  */
  435.  
  436. gettl(p,q,limit)
  437. char *p;
  438. char *q;
  439. int limit[];
  440. {
  441.         p = skipwd(p);
  442.         p = skipbl(p);
  443.         strcpy(q,p);
  444.         limit[LEFT] = dc.inval;
  445.         limit[RIGHT] = dc.rmval;
  446. }
  447.  
  448.  
  449.  
  450. /*
  451.  *      retrieves optional argument following nro command.
  452.  *      returns positive integer value with sign (if any)
  453.  *      saved in character addressed by p_argt.
  454.  */
  455.  
  456. getval(p,p_argt)
  457. char *p;
  458. char *p_argt;
  459. {
  460.         p = skipwd(p);
  461.         p = skipbl(p);
  462.         *p_argt = *p;
  463.         if((*p == '+') || (*p == '-')) ++p;
  464.         return(ctod(p));
  465. }
  466.  
  467.  
  468. /*
  469.  *      Evaluate macro expansion
  470.  */
  471.  
  472. maceval(p,m)
  473. char *p;
  474. char m[];
  475. {
  476.         int i, j;
  477.         char *argp[10];
  478.         char c;
  479.  
  480.         *p++ = EOS;             /* replace command char with EOS */
  481.         /*
  482.         *       initialize argp array to substitute command
  483.         *       string for any undefined argument
  484.         */
  485.         for (i=0; i<10; ++i) argp[i] = p;
  486.         p = skipwd(p);
  487.         *p++ = EOS;
  488.         for (i=0; i<10; ++i) {
  489.                 p = skipbl(p);
  490.                 if (*p == '\r' || *p == '\n' || *p == EOS) break;
  491.                 if (*p == '\'' || *p == '"') {
  492.                         c = *p++;
  493.                         argp[i] = p;
  494.                         while (*p != c && *p != '\r' && *p != '\n' && *p != EOS) ++p;
  495.                         *p++ = EOS;
  496.                 }
  497.                 else {
  498.                         argp[i] = p;
  499.                         p = skipwd(p);
  500.                         *p++ = EOS;
  501.                 }
  502.         }
  503.         for (i=strlen(m)-1; i>=0; --i) {
  504.                 if (i > 0 && m[i-1] == '$') {
  505.                         if (!isdigit(m[i])) {
  506.                                 putbak(m[i]);
  507.                         }
  508.                         else {
  509.                                 pbstr(argp[m[i]-'0']);
  510.                                 --i;
  511.                         }
  512.                 }
  513.                 else {
  514.                         putbak(m[i]);
  515.                 }
  516.         }
  517. }
  518.  
  519.  
  520. /*
  521.  *      Push back string into input stream
  522.  */
  523.  
  524. pbstr(p)
  525. char p[];
  526. {
  527.         int i;
  528.  
  529.         for (i=strlen(p)-1; i>=0; --i) {
  530.                 putbak(p[i]);
  531.         }
  532. }
  533.  
  534.  
  535.  
  536. /*
  537.  *      Push character back into input stream
  538.  */
  539.  
  540. putbak(c)
  541. char c;
  542. {
  543.         if (mac.ppb < &mac.pbb[0]) {
  544.                 mac.ppb = &mac.pbb[0];
  545.                 *mac.ppb = c;
  546.         }
  547.         else {
  548.                 if (mac.ppb >= &mac.pbb[MAXLINE-1]) {
  549.                         puts("***nro: push back buffer overflow\n");
  550.                         exit(-1);
  551.                 }
  552.                 *++mac.ppb = c;
  553.         }
  554. }
  555.  
  556.  
  557.  
  558.  
  559. /*
  560.  *      Put macro definition into table
  561.  */
  562.  
  563. putmac(name,p)
  564. char *name;
  565. char *p;
  566. {
  567.         if (mac.lastp >= MXMDEF) return(ERR);
  568.         if (mac.emb + strlen(name) + strlen(p) + 1 > &mac.mb[MACBUF]) {
  569.                 return(ERR);
  570.         }
  571.         ++mac.lastp;
  572.         mac.mnames[mac.lastp] = mac.emb;
  573.         strcpy(mac.emb,name);
  574.         strcpy(mac.emb + strlen(name) + 1,p);
  575.         mac.emb += strlen(name) + strlen(p) + 2;
  576.         return(OK);
  577. }
  578.  
  579.  
  580.  
  581.  
  582. /*
  583.  *      set parameter and check range
  584.  */
  585.  
  586. set(param,val,type,defval,minval,maxval)
  587. int *param;
  588. int val;
  589. char type;
  590. int defval,minval,maxval;
  591. {
  592.         switch(type) {
  593.         case '\r':
  594.         case '\n':
  595.                 *param = defval;
  596.                 break;
  597.         case '+':
  598.                 *param += val;
  599.                 break;
  600.         case '-':
  601.                 *param -= val;
  602.                 break;
  603.         default:
  604.                 *param = val;
  605.                 break;
  606.         }
  607.         *param = min(*param,maxval);
  608.         *param = max(*param,minval);
  609. }
  610.  
  611.  
  612.  
  613. /*
  614.  *      skip blanks and tabs in character buffer.
  615.  *      return number of characters skipped.
  616.  */
  617.  
  618. char *skipbl(p)
  619. char *p;
  620. {
  621.         while (*p == ' ' || *p == '\t') ++p;
  622.         return(p);
  623. }
  624.  
  625.  
  626. /*
  627.  *      skip over word and punctuation
  628.  */
  629.  
  630. char *skipwd(p)
  631. char *p;
  632. {
  633.         while (*p != ' ' && *p != '\t' && *p != '\r' && *p != '\n' && *p != EOS)
  634.                 ++p;
  635.         return(p);
  636. }
  637.  
  638.  
  639.  
  640. /*
  641.  *      space vertically n lines
  642.  */
  643.  
  644. space(n)
  645. int n;
  646. {
  647.         brk();
  648.         if (pg.lineno > pg.bottom) return;
  649.         if (pg.lineno == 0) phead();
  650.         skip(min(n,pg.bottom+1-pg.lineno));
  651.         pg.lineno += n;
  652.         if (pg.lineno > pg.bottom) pfoot();
  653. }
  654.