home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / tos / gawk / cawf2st.zoo / pass3.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-12  |  20.9 KB  |  579 lines

  1. /*
  2.  *      pass3.c - cawf(1) pass 3 function
  3.  */
  4.  
  5. /*
  6.  *      Copyright (c) 1991 Purdue University Research Foundation,
  7.  *      West Lafayette, Indiana 47907.  All rights reserved.
  8.  *
  9.  *      Written by Victor A. Abell <abe@mace.cc.purdue.edu>,  Purdue
  10.  *      University Computing Center.  Not derived from licensed software;
  11.  *      derived from awf(1) by Henry Spencer of the University of Toronto.
  12.  *
  13.  *      Permission is granted to anyone to use this software for any
  14.  *      purpose on any computer system, and to alter it and redistribute
  15.  *      it freely, subject to the following restrictions:
  16.  *
  17.  *      1. The author is not responsible for any consequences of use of
  18.  *         this software, even if they arise from flaws in it.
  19.  *
  20.  *      2. The origin of this software must not be misrepresented, either
  21.  *         by explicit claim or by omission.  Credits must appear in the
  22.  *         documentation.
  23.  *
  24.  *      3. Altered versions must be plainly marked as such, and must not
  25.  *         be misrepresented as being the original software.  Credits must
  26.  *         appear in the documentation.
  27.  *
  28.  *      4. This notice may not be removed or altered.
  29.  */
  30.  
  31. #include "cawf.h"
  32.  
  33. void
  34. Pass3(len, word, sarg, narg)
  35.         int len;                        /* length (negative is special) */
  36.         char *word;                     /* word */
  37.         char *sarg;                     /* string argument */
  38.         int narg;                       /* numeric argument */
  39. {
  40.         int addto;                      /* spaces to add to all words */
  41.         int i, j, k;                    /* temporary index */
  42.         char msg[MAXLINE];              /* message buffer */
  43.         int n;                          /* temporary number */
  44.         char *s1;                       /* temporary string pointer */
  45.         int wl;                         /* real word length */
  46.         int xsp;                        /* extra spaces to add */
  47.         int vsp;                        /* vertical spacing status */
  48.  
  49.         vsp = 0;
  50.         if (word != NULL)
  51.                 wl = strlen(word);
  52.     /*
  53.      * If not a special command, process a word.
  54.      */
  55.         if (len >= 0 && Outll < 0) {
  56.         /*
  57.          * Enter first word.
  58.          */
  59.                 (void) strcpy(Outln, word);
  60.                 Outll = len;
  61.                 Outlx = wl;
  62.                 Padx = 0;
  63.         } else if (len >= 0
  64.                && (Outll+Contlen+len+narg) <= (LL-Pgoff-Ind-Tind)) {
  65.         /*
  66.          * The word fits, so enter it.
  67.          */
  68.                 if ((Contlen + len) > 0) {
  69. line_too_big:
  70.                         if ((Outlx + Contlen + wl) >= MAXOLL) {
  71.                                 Error3(len, word, sarg, narg,
  72.                                         "output line too big");
  73.                                 return;
  74.                         } else {
  75.                                 if (Contlen > 0 && Cont != NULL) {
  76.                                         if (Contlen == 1 && *Cont == ' ') {
  77.                                                 Padchar[Padx++] = Outlx;
  78.                                                 Outln[Outlx++] = ' ';
  79.                                         } else {
  80.                                                 (void) strcpy(&Outln[Outlx],
  81.                                                         Cont);
  82.                                                 Outlx += Contlen;
  83.                                         }
  84.                                 }
  85.                                 if (len > 0) {
  86.                                         (void) strcpy(&Outln[Outlx], word);
  87.                                         Outlx += wl;
  88.                                 }
  89.                         }
  90.                 }
  91.                 Outll += Contlen + len;
  92.         } else if (len == NOBREAK || len == MESSAGE) {
  93.                 /*
  94.                  * Do nothing (equivalent to break)
  95.                  */
  96.         } else if (len == DOBREAK && strcmp(word, "need") == 0
  97.                &&  (Nxtln + narg) < (Pglen + 1 - Botmarg)) {
  98.                 /*
  99.                  * Do nothing, because there is room on the page.
  100.                  */
  101.         } else if (len == DOBREAK && strcmp(word, "toindent") == 0
  102.                &&  (Ind + Tind + Outll) < Ind) {
  103.         /*
  104.          * Move to indent position with line - there is room.
  105.          */
  106.                 n = Ind - (Ind + Tind +Outll);
  107.                 Outll += n;
  108.                 if ((Outlx + n) >= MAXOLL)
  109.                         goto line_too_big;
  110.                 for (i = n; i; i--)
  111.                         Outln[Outlx++] = ' ';
  112.                 Padx = 0;
  113.                 Free(&Cont);
  114.                 Contlen = 0;
  115.         } else if (Outll >= 0
  116.                || (len == DOBREAK && strcmp(word, "need") == 0)) {
  117.         /*
  118.          * A non-empty line or a "need" forces output.
  119.          */
  120.                 vsp = 0;
  121.  
  122. print_line:
  123.                 if (Nxtln == 1) {
  124.             /*
  125.              * We're at the top of the page, so issue the header.
  126.              */
  127.                         if (Thispg > 1)
  128.                                 Charput('\f');
  129.                         for (i = (Topmarg - 1)/2; i > 0; i--) {
  130.                                 Charput('\n');
  131.                                 Nxtln++;
  132.                         }
  133.                     /*
  134.                      * Print the page header, as required.
  135.                      */
  136.                         if (Fph || Thispg > 1) {
  137.                                 i = LenprtHF(Hdc, Thispg, 0)
  138.                                   + LenprtHF(Hdl, Thispg, 0)
  139.                                   + LenprtHF(Hdr, Thispg, 0) + 2;
  140.                                 j = (LL - i - Pgoff) / 2 + 1;
  141.                                 n = LL - Pgoff - i - j + 2;
  142.                                 for (k = 0; k < Pgoff; k++)
  143.                                         Charput(' ');
  144.                                 if (Hdl)
  145.                                         LenprtHF(Hdl, Thispg, 1);
  146.                                 while (j--)
  147.                                         Charput(' ');
  148.                                 if (Hdc)
  149.                                         LenprtHF(Hdc, Thispg, 1);
  150.                                 while (n--)
  151.                                         Charput(' ');
  152.                                 if (Hdr)
  153.                                         LenprtHF(Hdr, Thispg, 1);
  154.                                 Charput('\n');
  155.                         } else
  156.                                 Charput('\n');
  157.                         Nxtln++;
  158.                         while(Nxtln <= Topmarg) {
  159.                                 Charput('\n');
  160.                                 Nxtln++;
  161.                         }
  162.                 }
  163.             /*
  164.              *  Add a trailing hyphen, if mecessary.
  165.              */
  166.                 if (vsp == 0 && Eollen > 0 && Eol != NULL) {
  167.                         i = strlen(Eol);
  168.                         if ((Outlx + i) >= MAXOLL)
  169.                                 goto line_too_big;
  170.                         (void) strcpy(&Outln[Outlx], Eol);
  171.                         Outlx += i;
  172.                         Outll += Eollen;
  173.                 }
  174.             /*
  175.              * Trim trailing spaces from the output line.
  176.              */
  177.                 while (Outlx > 0) {
  178.                         if (Outln[Outlx - 1] != ' ')
  179.                                 break;
  180.                         if (Padx > 0 && (Outlx - 1) == Padchar[Padx - 1])
  181.                                 Padx--;
  182.                         Outlx--;
  183.                         Outln[Outlx] = '\0';
  184.                         Outll--;
  185.                 }
  186.                 if (Outlx == 0)
  187.                         Charput('\n');
  188.                 else if (len == DOBREAK && strcmp(word, "center") == 0) {
  189.                     /*
  190.                      * Center the output line.
  191.                      */
  192.                         i = (LL - Pgoff - Outll) / 2;
  193.                         if (i < 0)
  194.                                 i = 0;
  195.                         for (j = (Pgoff + Ind + Tind + i); j; j--)
  196.                                 Charput(' ');
  197.                         Stringput(Outln);
  198.                         Charput('\n');
  199.                 } else if (Adj == LEFTADJ || Adj == BOTHADJ
  200.                      &&  (len < 0 || Padx == 0)) {
  201.                     /*
  202.                      * No right margin adjustment - disabled, inappropriate
  203.                      * (line ended by break) or impossible.
  204.                      */
  205.                         for (i = 0; i < (Pgoff + Ind + Tind); i++)
  206.                                 Charput(' ');
  207.                         Stringput(Outln);
  208.                         Charput('\n');
  209.                 } else if (Adj == BOTHADJ) {
  210.                     /*
  211.                      * Adjust right margin.
  212.                      */
  213.                         for (i = 0; i < (Pgoff + Ind + Tind); i++)
  214.                                 Charput(' ');
  215.                         i = LL - (Pgoff + Ind + Tind);
  216.                         j = i - Outll;
  217.                         addto = Padx ? (j / Padx) : 0;
  218.                         xsp = j - (Padx * addto);
  219.                         for (i = 0, s1 = Outln; i < Padx; i++) {
  220.                                 while (*s1 && (s1 - Outln) <= Padchar[i])
  221.                                         Charput(*s1++);
  222.                                 if (*s1 == '\0')
  223.                                         break;
  224.                                 j = addto;
  225.                                 if (Padfrom == PADLEFT) {
  226.                                         if (i < xsp)
  227.                                                 j++;
  228.                                 } else if (i >= (Padx - xsp))
  229.                                         j++;
  230.                                 while (j--)
  231.                                         Charput(' ');
  232.                         }
  233.                         while (*s1)
  234.                                 Charput(*s1++);
  235.                         Charput('\n');
  236.                         Padfrom = (Padfrom == PADLEFT) ? PADRIGHT : PADLEFT;
  237.                 }
  238.             /*
  239.              * End of line housekeeping
  240.              */
  241.                 Nxtln++;
  242.                 Outll = -1;
  243.                 Outlx = 0;
  244.                 Padx = 0;
  245.                 Tind = 0;
  246.                 Nospmode = 0;
  247.                 if (vsp == 0 && len == DOBREAK && strcmp(word, "need") == 0) {
  248.             /*
  249.              * Break caused by "need" - satisfy it.
  250.              */
  251.                         while (Nxtln < (Pglen + 1 - Botmarg)) {
  252.                                 Charput('\n');
  253.                                 Nxtln++;
  254.                         }
  255.                 }
  256.                 if (Nxtln >= (Pglen + 1 - Botmarg)) {
  257.             /*
  258.              * Footer required
  259.              */
  260.                         for (i = (Botmarg - 1)/2; i > 0; i--) {
  261.                                 Charput('\n');
  262.                                 Nxtln++;
  263.                         }
  264.                         i = LenprtHF(Ftl, Thispg, 0) + LenprtHF(Ftc, Thispg, 0)
  265.                           + LenprtHF(Ftr, Thispg, 0) + 2;
  266.                         j = (LL - i - Pgoff) / 2 + 1;
  267.                         n = LL - Pgoff - i - j + 2;
  268.                         for (k = 0; k < Pgoff; k++)
  269.                                 Charput(' ');
  270.                         if (Ftl)
  271.                                 LenprtHF(Ftl, Thispg, 1);
  272.                         while (j--)
  273.                                 Charput(' ');
  274.                         if (Ftc)
  275.                                 LenprtHF(Ftc, Thispg, 1);
  276.                         while (n--)
  277.                                 Charput(' ');
  278.                         if (Ftr)
  279.                                 LenprtHF(Ftr, Thispg, 1);
  280.                         Charput('\n');
  281.                         Nxtln++;
  282.                 /*
  283.                  * The last blank line on the page is suppressed to assist
  284.                  * printers that can't look ahead to the following FF.
  285.                  */
  286.                         while (Nxtln < Pglen) {
  287.                                 Charput('\n');
  288.                                 Nxtln++;
  289.                         }
  290.                         Nxtln = 1;
  291.                         Thispg++;
  292.                         Nospmode = 1;
  293.                         Padfrom = PADRIGHT;
  294.                 }
  295.             /*
  296.              * Initiate any extra vertical spacing.
  297.              */
  298.                 if (++vsp < Vspace)
  299.                         goto print_line;
  300.             /*
  301.              * Save any input word that might have forced output.
  302.              */
  303.                 if (len >= 0) {
  304.                         (void) strcpy(Outln, word);
  305.                         Outll = len;
  306.                         Outlx = wl;
  307.                         Padx = 0;
  308.                 }
  309.         }
  310.     /*
  311.      * A break causes padding reversal.
  312.      */
  313.         if (len == DOBREAK)
  314.                 Padfrom = PADRIGHT;
  315.         if (len >= 0 || strcmp(word, "nohyphen") == 0) {
  316.     /*
  317.      * Reset continuation and hyphenation.
  318.      */
  319.                 if (Contlen != 1 || Cont[0] != ' ') {
  320.                         Free(&Cont);
  321.                         Cont = Newstr(" ");
  322.                         Contlen = 1;
  323.                 }
  324.                 if (Eollen > 0) {
  325.                         Free(&Eol);
  326.                         Eollen = 0;
  327.                 }
  328.                 return;
  329.         }
  330.     /*
  331.      * Now post-process any special commands.
  332.      */
  333.         if (len == MESSAGE) {
  334.                 Error3(len, word, sarg, narg, NULL);
  335.                 return;
  336.         }
  337.  
  338.         switch (*word) {
  339.  
  340.         case 'b':                               /* both */
  341.             /*
  342.              * Adjust on both margins.
  343.              */
  344.                 Adj = BOTHADJ;
  345.                 return;
  346.  
  347.         case 'c':                               /* center */
  348.                 return;
  349.  
  350.         case 'e':                               /* errsto */
  351.             /*
  352.              * "errsto" comes from awf.
  353.              */
  354.                 return;
  355.  
  356.         case 'f':                               /* flush and fph */
  357.                 if (word[1] == 'l')
  358.                         return;
  359.                 else if (word[1] == 'p') {
  360.             /*
  361.              * First page header status
  362.              */
  363.                         Fph = narg;
  364.                         return;
  365.                 }
  366.                 break;
  367.  
  368.         case 'g':                               /* gap */
  369.             /*
  370.              * Increase word gap.  (Space is not paddable.)
  371.              */
  372.                 if (Outll >= 0) {
  373.                         if ((Outlx + narg - 1) >= MAXOLL)
  374.                                 goto line_too_big;
  375.                         for (i = 0; i < (narg - 1); i++) {
  376.                                 Outln[Outlx++] = ' ';
  377.                                 Outll++;
  378.                         }
  379.                 }
  380.                 return;
  381.  
  382.         case 'h':                               /* hyphen */
  383.             /*
  384.              * Set discretionary hyphen.
  385.              */
  386.                 Free(&Cont);
  387.                 Contlen = 0;
  388.                 Free(&Eol);
  389.                 Eol = (sarg != NULL) ? Newstr(sarg) : NULL;
  390.                 Eollen = narg;
  391.                 return;
  392.  
  393.         case 'i':                               /* indent */
  394.             /*
  395.              * Set indentation.
  396.              */
  397.                 Ind = narg;
  398.                 return;
  399.  
  400.         case 'l':                               /* left or linelen */
  401.                 if (word[1] == 'e') {
  402.             /*
  403.              * Adjust on left margin.
  404.              */
  405.                         Adj = LEFTADJ;
  406.                         return;
  407.                 } else if (word[1] == 'i') {
  408.             /*
  409.              * Set line length.
  410.              */
  411.                         LL = narg;
  412.                         return;
  413.                 }
  414.                 break;
  415.  
  416.         case 'n':                               /* need or nospace */
  417.                 if (word[1] == 'e')
  418.                         return;                 /* need */
  419.                 else if (word[1] == 'o') {
  420.             /*
  421.              * Set no space mode.
  422.              */
  423.                         Nospmode = 1;
  424.                         return;
  425.                 }
  426.                 break;
  427.  
  428.         case 'p':                               /* pagelen or pageoffset */
  429.                 if (strncmp(&word[1], "age", 3) != 0)
  430.                         break;
  431.                 if (word[4] == 'l') {
  432.             /*
  433.              * Set page length.
  434.              */
  435.                         Pglen = narg;
  436.                         return;
  437.                 } else if (word[4] == 'o') {
  438.             /*
  439.              * Set page offset.
  440.              */
  441.                         Pgoff = narg;
  442.                         return;
  443.                 }
  444.                 break;
  445.  
  446.         case 's':                               /* space */
  447.             /*
  448.              * Generate an empty line.
  449.              */
  450.                 if (Nospmode == 0) {
  451.                         Outlx = 0;
  452.                         Outln[0] = '\0';
  453.                         Padx = 0;
  454.                         Outll = LL - 1;
  455.                 }
  456.                 return;
  457.  
  458.         case 't':                               /* tabto, tempindent, or
  459.                                                  * toindent */
  460.                 if (word[1] == 'a') {
  461.             /*
  462.              * Move to TAB stop.
  463.              */
  464.                         if (Outll < 0)
  465.                                 Outll = 0;
  466.                         if ((n = narg - Outll) > 0) {
  467.                                 if ((Outlx + n) >= MAXOLL)
  468.                                         goto line_too_big;
  469.                                 Outll += n;
  470.                                 for (i = n; i > 0; i--)
  471.                                         Outln[Outlx++] = ' ';
  472.                                 Free(&Cont);
  473.                                 Contlen = 0;
  474.                                 Padx = 0;
  475.                         }
  476.                         return;
  477.                 } else if (word[1] == 'e') {
  478.             /*
  479.              * Set temporary indentation.
  480.              */
  481.                         if (*sarg == '\0' && narg >= 0)
  482.                                 Tind = narg - Ind;
  483.                         else
  484.                                 Tind = ((Ind + narg) >= 0) ? narg : -Ind;
  485.                         return;
  486.                 } else if (word[1] == 'o')
  487.                         return;                         /* toindent */
  488.                 break;
  489.  
  490.         case 'u':                                       /* userhyphen */
  491.             /*
  492.              * Set line length.
  493.              */
  494.                 Free(&Cont);
  495.                 Free(&Eol);
  496.                 Contlen = Eollen = narg;
  497.                 Cont = (sarg == NULL) ? NULL : Newstr(sarg);
  498.                 Eol = (sarg == NULL) ? NULL : Newstr(sarg);
  499.                 return;
  500.  
  501.         case 'v':                                       /* vspace */
  502.             /*
  503.              * Set vertical spacing.
  504.              */
  505.                 Vspace = (narg == 0) ? 1 : narg;
  506.                 return;
  507.  
  508.         case 'y':                                       /* yesspace */
  509.             /*
  510.              * Set space mode.
  511.              */
  512.                 Nospmode = 0;
  513.                 return;
  514.         }                               /* end of switch(*word) */
  515.     /*
  516.      * Locate header and footer defintions.
  517.      */
  518.         if (regexec(Pat[14].pat, word)) {
  519.                 if (strcmp(word, "LH") == 0) {
  520.                     /*
  521.                      * Left header
  522.                      */
  523.                         Free(&Hdl);
  524.                         if (sarg != NULL)
  525.                                 Hdl = Newstr(sarg);
  526.                         return;
  527.                 }
  528.                 if (strcmp(word, "CH") == 0) {
  529.                     /*
  530.                      * Center header
  531.                      */
  532.                         Free(&Hdc);
  533.                         if (sarg != NULL)
  534.                                 Hdc = Newstr(sarg);
  535.                         return;
  536.                 }
  537.                 if (strcmp(word, "RH") == 0) {
  538.                     /*
  539.                      * Right header
  540.                      */
  541.                         Free(&Hdr);
  542.                         if (sarg != NULL)
  543.                                 Hdr = Newstr(sarg);
  544.                         return;
  545.                 }
  546.                 if (strcmp(word, "LF") == 0) {
  547.                     /*
  548.                      * Left footer
  549.                      */
  550.                         Free(&Ftl);
  551.                         if (sarg != NULL)
  552.                                 Ftl = Newstr(sarg);
  553.                         return;
  554.                 }
  555.                 if (strcmp(word, "CF") == 0) {
  556.                     /*
  557.                      * Center footer
  558.                      */
  559.                         Free(&Ftc);
  560.                         if (sarg != NULL)
  561.                                 Ftc = Newstr(sarg);
  562.                         return;
  563.                 }
  564.                 if (strcmp(word, "RF") == 0) {
  565.                     /*
  566.                      * Right footer
  567.                      */
  568.                         Free(&Ftr);
  569.                         if (sarg != NULL)
  570.                                 Ftr = Newstr(sarg);
  571.                         return;
  572.                 }
  573.         }
  574.     /*
  575.      * Error on unknown arguments
  576.      */
  577.         Error3(len, word, sarg, narg, "unknown request");
  578. }
  579.