home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 215.lha / NRO / nro.c < prev    next >
C/C++ Source or Header  |  1996-02-15  |  9KB  |  498 lines

  1. /*
  2.  *    NRO Text Formatter -
  3.  *    similar to Unix NROFF or RSX-11M RNO -
  4.  *    adaptation of text processor given in
  5.  *    "Software Tools", Kernighan and Plauger.
  6.  *
  7.  *    Originally by Stephen L. Browning, 5723 North Parker Avenue
  8.  *    Indianapolis, Indiana 46220
  9.  *
  10.  *    Transformed beyond immediate recognition, and
  11.  *    adapted for Amiga by Olaf Seibert, KosmoSoft
  12.  *
  13.  *    Vossendijk 149-1 (study)   Beek 5 (home)
  14.  *    5634 TN  Nijmegen       5815 CS  Merselo
  15.  *    The Netherlands        The Netherlands
  16.  *    Phone:
  17.  *           (...-31)80561045     (...-31)4786205
  18.  *        or 080-561045        04786-205
  19.  *
  20.  *    This program is NOT in the public domain. It may, however
  21.  *    be distributed only at no charge, and this notice must be
  22.  *    included unaltered.
  23.  */
  24.  
  25. #include <stdio.h>
  26. #include "nro.h"
  27. #include "nroxtrn.h"
  28.  
  29.  
  30. main(argc, argv)
  31. int argc;
  32. uchar *argv[];
  33. {
  34.     int i;
  35.     int ofp;
  36.  
  37.     pout = stdout;
  38.     ofp = 0;
  39.     init();
  40.     for (i=1; i<argc; i++) {
  41.         if (*argv[i] == '-' || *argv[i] == '+') {
  42.             pswitch(argv[i]);
  43.         } else if (*argv[i] == '>') {
  44.             if (ofp == 0) {
  45. #ifdef CPM
  46.                 if (!strcmp(argv[i]+1, "$P")) {
  47.                     ofp = 1;
  48.                     co.lpr = TRUE;
  49.                 } else
  50. #endif
  51.                 if ((pout = fopen(argv[i]+1, "w")) == NULL) {
  52.                     error("*** nro: cannot create %s\n", argv[i]+1);
  53.                 } else {
  54.                     ofp = 1;
  55.                 }
  56.             } else {
  57.                 error("*** nro: too many output files\n");
  58.             }
  59.         }
  60.     }
  61.  
  62.     for (i=1; i<argc; i++) {
  63.         if (*argv[i] != '-' && *argv[i] != '+' && *argv[i] != '>') {
  64.             if ((sofile[0] = fopen(argv[i], "r")) == NULL) {
  65.                 error("nro: unable to open file %s\n", argv[i]);
  66.                 continue;
  67.             } else {
  68.                 if (verbose > 2)
  69.                     error("nro: processing file '%s'\n", argv[i]);
  70.                 profile();
  71.                 fclose(sofile[0]);
  72.             }
  73.         }
  74.     }
  75.  
  76.     if (argc == 1) {
  77.         error("Usage: nro [-#] [+#] [-p#] [-v] [-b#] [-rn#] [-rd#] [-rp#]\n"
  78.               "           [-mmacfile] infile(s) ... [>outfile]\n");
  79.         fatal();
  80.     } else {
  81.         endfiles();
  82.     }
  83.  
  84. #ifdef CMPEOF
  85.     putc(CPMEOF, pout);
  86. #endif CMPEOF
  87.     fflush(pout);
  88.     if (pout != stdout) {
  89.         fclose(pout);
  90.     }
  91. }
  92.  
  93.  
  94.  
  95. /*
  96.  *    Retrieve one line of input text
  97.  */
  98.  
  99. getlin(p, infile)
  100. uchar *p;
  101. FILE *infile;
  102. {
  103.     int i;
  104.     int c;
  105.     uchar *q;
  106.  
  107.     q = p;
  108.     for (i=0; i<MAXLINE-1; i++) {
  109.         c = ngetc(infile);
  110. #ifdef CPMEOF
  111.         if (c == CPMEOF || c == EOF) {
  112. #if 0
  113. }    /* To keep ctags, cb and such happy */
  114. #endif
  115. #else
  116.         if (c == EOF) {
  117. #endif CPMEOF
  118.             *q = EOS;
  119.             return i == 0 ? EOF : 0;
  120.         }
  121.         *q++ = c;
  122.         if (iseol(c)) break;
  123.     }
  124.     *q = EOS;
  125.     return q - p;    /* strlen(p) */
  126. }
  127.  
  128.  
  129.  
  130. /*
  131.  *    Initialize parameters for nro word processor
  132.  */
  133.  
  134. init()
  135. {
  136.     int i;
  137.     static char nl[] = "\n";
  138.  
  139.     dc.bsflg   = FALSE;
  140.     dc.curmode = FXPLAIN;
  141.     dc.envsp   = 0;
  142.     dc.envstack[0] = 0;
  143.     for (i=0; i<26; i++) dc.nr[i] = 0;
  144. #ifdef CPM
  145.     dc.lpr       = FALSE;
  146. #endif
  147.  
  148.     for (i=0; i<NUMENV; i++) environ[i] = NULL;
  149.  
  150.     initenv();
  151.  
  152.     pg.curpag   = 0;
  153.     pg.newpag   = 1;
  154.     pg.lineno   = 0;
  155.     pg.plval    = PAGELEN;
  156.     pg.m1val    = 2;
  157.     pg.m2val    = 2;
  158.     pg.m3val    = 2;
  159.     pg.m4val    = 2;
  160.     pg.bottom   = pg.plval - pg.m4val - pg.m3val;
  161.     pg.offset   = 0;
  162.     pg.frstpg   = 0;
  163.     pg.lastpg   = 32767;
  164.     pg.prflg   = TRUE;
  165.  
  166.     strncpy(pg.ehead, nl, MAXLINE);
  167.     strncpy(pg.ohead, nl, MAXLINE);
  168.     strncpy(pg.efoot, nl, MAXLINE);
  169.     strncpy(pg.ofoot, nl, MAXLINE);
  170.  
  171.     pg.ehlim[LEFT] = pg.ohlim[LEFT] = env.inval;
  172.     pg.eflim[LEFT] = pg.oflim[LEFT] = env.inval;
  173.     pg.ehlim[RIGHT] = pg.ohlim[RIGHT] = env.rmval;
  174.     pg.eflim[RIGHT] = pg.oflim[RIGHT] = env.rmval;
  175.  
  176.     mac.mxmdef = MXMDEF;
  177.     mac.macbuf = MACBUF;
  178.     mac.mxmlen = MXMLEN;
  179.     mac.mnames = NULL;
  180.     mac.mb       = NULL;
  181.     mac.pbb    = NULL;
  182.     mac.lastp  = 0;
  183.     mac.ppb    = NULL;
  184. }
  185.  
  186.  
  187. /*
  188.  *    Initenv - initialise the environment to default
  189.  */
  190.  
  191. initenv()
  192. {
  193.     int i;
  194.  
  195.     env.fill    = YES;
  196.     env.lsval   = 1;
  197.     env.inval   = 0;
  198.     env.tival   = 0;
  199.     env.rmval   = PAGEWIDTH - 1;
  200.     env.tmval   = PAGEWIDTH - 1;
  201.     env.ceval   = 0;
  202.     env.ulval   = 0;
  203.     env.cuval   = 0;
  204.     env.boval   = 0;
  205.     env.itval   = 0;
  206.     env.juval   = YES;
  207.     env.pgchr   = PGCHAR;
  208.     env.cmdchr  = CMDCHAR;
  209.     env.c2chr   = C2CHAR;
  210.     env.sprdir  = 0;
  211.     env.dontbrk = FALSE;
  212.     env.reqmode = FXPLAIN;
  213.     env.expmode = FXPLAIN;
  214.     env.curmode = FXPLAIN;
  215.     env.outp    = 0;
  216.     env.outw    = 0;
  217.     env.outwds  = 0;
  218.  
  219.     strncpy(env.outbuf, "", MAXLINE);
  220.  
  221.     for (i=0; i<MAXTAB; i++) env.tabstop[i] = NOTAB;
  222. }
  223.  
  224.  
  225. /*
  226.  *    Initialize buffers for macros
  227.  */
  228.  
  229. initbuffers()
  230. {
  231.     static short inited = FALSE;
  232.  
  233.     int i;
  234.  
  235.     if (inited)
  236.         return;
  237.  
  238.     if ((mac.mnames=(uchar **)malloc(sizeof(*mac.mnames)*mac.mxmdef)) &&
  239.         (mac.mb    =(uchar *)malloc(sizeof(*mac.mb)    *mac.macbuf)) &&
  240.         (mac.pbb   =(uchar *)malloc(sizeof(*mac.pbb)   *mac.mxmlen)) ) {
  241.  
  242.         for (i=0; i<mac.mxmdef; i++) mac.mnames[i] = NULL;
  243.         mac.emb = mac.mb;
  244.         mac.ppb = mac.pbb - 1;
  245.         mac.pbbend = mac.pbb + mac.mxmlen;
  246.  
  247.         if (verbose > 1) {
  248.             error("nro: max number of macros: %d\n", mac.mxmdef);
  249.             error("     max total length of macro definitions: %d\n",
  250.                     mac.macbuf);
  251.             error("     max pushback characters: %d\n", mac.mxmlen);
  252.         }
  253.         inited = TRUE;
  254.     } else {
  255.         error("*** nro: cannot allocate memory for macro buffers\n");
  256.     }
  257. }
  258.  
  259. #define rawgetc(infp)\
  260.     ((mac.ppb >= mac.pbb) ? pbbgetc() : getc(infp))
  261.  
  262. #define pbbgetc()       (*mac.ppb--)
  263.  
  264. /*
  265.  *    Get character from input file or push back buffer
  266.  */
  267.  
  268. ngetc(infp)
  269. FILE *infp;
  270. {
  271.     register int chr;
  272.     int i, j;
  273.  
  274. again:
  275.     chr = rawgetc(infp);
  276.  
  277.     if (chr != ESCCHAR) {
  278.         if (dc.iflvl == 0) return chr;
  279.         else goto again;
  280.     }
  281.  
  282.     chr = rawgetc(infp);
  283.  
  284.     switch (chr) {
  285.     case '\n':              /* Concealed newline */
  286.         goto again;
  287.     case ' ':               /* Non breakable space */
  288.         chr =  NBSP;
  289.         break;
  290.     case '"':               /* A comment */
  291.         while (isnteol(chr)) chr = rawgetc(infp);
  292.         break;
  293.     case ESCCHAR:        /* Escaped escape character */
  294.     case 'e':               /* Current value of escape character */
  295.         chr = ESCCHAR;
  296.         break;
  297.     case 'n':               /* Substitute numeric register */
  298.         if (dc.iflvl) goto again;
  299.         chr = rawgetc(infp);
  300.         i = dc.nr[tolower(chr) - 'a'];
  301.         j = abs(i);
  302.         do {
  303.             putbak('0' + j % 10);
  304.             j /= 10;
  305.         } while (j);
  306.         if (i < 0)      chr = '-';
  307.         else chr = pbbgetc();
  308.         break;
  309.     case 't':               /* Tab */
  310.         chr = '\t';
  311.         break;
  312.     case 'X':               /* eXtended Character */
  313.         chr = getval(&i, infp);
  314.         break;
  315.     case '{':               /* Begin of if block */
  316.         if (dc.iflvl) dc.iflvl++;
  317.         chr = BEGIF;
  318.         break;
  319.     case '}':               /* End of if block */
  320.         if (dc.iflvl) dc.iflvl--;
  321.         goto again;
  322.             /* @. to conceal line beginning with command chr */
  323.     default:    /* Dunno. Somebody is mistakin'. Maybe even EOF. */
  324.         if (chr == env.cmdchr) chr |= 0x8000;
  325.     }
  326.  
  327.     if (dc.iflvl) goto again;
  328.  
  329.     return chr;
  330. }
  331.  
  332. /*
  333.  *    Restore push back buffer after closing a file
  334.  */
  335.  
  336. restorepbb()
  337. {
  338.     mac.ppb = mac.pbb - 1;    /* Should not even be necessary */
  339.     mac.pbb = sopbb[dc.flevel - 1];
  340. }
  341.  
  342.  
  343. /*
  344.  *    Process input files from command line
  345.  */
  346.  
  347. profile()
  348. {
  349.     int chr;
  350.     uchar ibuf[MAXWORD];
  351.  
  352.     initbuffers();
  353.  
  354.     for (dc.flevel=0; dc.flevel>=0; --dc.flevel) {
  355.         infile = sofile[dc.flevel];
  356.         while (ibuf[0] = chr = ngetc(infile), chr != EOF) {
  357.             if (chr == env.cmdchr) {
  358.                 comand(ibuf);   /* Command line */
  359.             } else
  360.                 text(ibuf, infile);             /* Text line */
  361.         }
  362.         if (dc.flevel > 0) {
  363.             fclose(infile);
  364.             restorepbb();
  365.         }
  366.     }
  367. }
  368.  
  369.  
  370. /*
  371.  *    End processing of files: eject page if necessary.
  372.  */
  373.  
  374. endfiles()
  375. {
  376.     if (pg.lineno > 0 || env.outp != 0)  space(pg.plval);
  377. }
  378.  
  379.  
  380. #define K *1024
  381. #define M *1024 K
  382.  
  383. /*
  384.  *    Process switch values from command line
  385.  */
  386.  
  387. pswitch(p)
  388. uchar *p;
  389. {
  390.     int swgood;
  391.  
  392.     swgood = TRUE;
  393.     if (*p == '-') {
  394.         switch (tolower(*++p)) {
  395.         case 'b':
  396.             set(&dc.bsflg, ctod(++p), '1', 1, 0, 2);
  397.             break;
  398.         case 'm':
  399.             if ((sofile[0] = fopen(++p, "r")) == NULL) {
  400.                 error("*** nro: unable to open file %s\n", p);
  401.             }
  402.             if (verbose > 2)
  403.                 error("nro: processing file '%s'\n", p);
  404.             profile();
  405.             fclose(sofile[0]);
  406.             break;
  407.         case 'p':
  408.             set(&pg.offset, ctod(++p), '1', 0, 0, HUGE);
  409.             break;
  410.         case 'r':       /* Reserve memory */
  411.             switch(tolower(p[1])) {
  412.             case 'd':       /* Total buffer for definitions */
  413.                 if (mac.mb == NULL)
  414.                     set(&mac.macbuf, ctod(&p[2]), '1', MACBUF, 0, 16 M);
  415.                 else swgood = FALSE;
  416.                 break;
  417.             case 'n':       /* Number of definitions */
  418.                 if (mac.mnames == NULL)
  419.                     set(&mac.mxmdef, ctod(&p[2]), '1', MXMDEF, 0, 10 K);
  420.                 else swgood = FALSE;
  421.                 break;
  422.             case 'p':       /* Pushback buffer */
  423.                 if (mac.pbb == NULL)
  424.                     set(&mac.mxmlen, ctod(&p[2]), '1', MXMLEN, 0, 100 K);
  425.                 else swgood = FALSE;
  426.                 break;
  427.             default:
  428.                 swgood = FALSE;
  429.             }
  430.             break;
  431.         case 'v':
  432.             error("NRO - KosmoSoft version 1.5 - V25.06.88\n");
  433.             verbose = max(1,ctod(++p));
  434.             break;
  435.         case '0': case '1': case '2': case '3': case '4':
  436.         case '5': case '6': case '7': case '8': case '9':
  437.             pg.lastpg = ctod(p);
  438.             break;
  439.         default:
  440.             swgood = FALSE;
  441.             break;
  442.         }
  443.     } else if (*p == '+') {
  444.         pg.frstpg = ctod(++p);
  445.     } else {
  446.         swgood = FALSE;
  447.     }
  448.     if (swgood == FALSE) {
  449.         error("*** nro: illegal switch %s\n", p);
  450.     }
  451.     return;
  452. }
  453.  
  454. #undef K
  455. #undef M
  456.  
  457.  
  458. /*
  459.  *    Print a message at the standard error channel
  460.  */
  461.  
  462. /*VARARGS1*/
  463. error(format, arg1, arg2, arg3)
  464. uchar *format;
  465. long arg1, arg2, arg3;
  466. {
  467.     fflush(pout);
  468.     fprintf(stderr, format, arg1, arg2, arg3);
  469.  
  470.     if (*format == '*')
  471.         fatal();
  472. }
  473.  
  474. /*
  475.  *    fatal - cannot recover from a serious error
  476.  */
  477.  
  478. fatal()
  479. {
  480.     exit(10);
  481. }
  482.  
  483. int tolower(c)
  484. register char c;
  485. {
  486.     if (c >= 'A' && c <= 'Z')
  487.         return c - 'A' + 'a';
  488.     return c;
  489. }
  490.  
  491. int toupper(c)
  492. register char c;
  493. {
  494.     if (c >= 'a' && c <= 'z')
  495.         return c - 'a' + 'A';
  496.     return c;
  497. }
  498.