home *** CD-ROM | disk | FTP | other *** search
/ ftp.muug.mb.ca / 2014.06.ftp.muug.mb.ca.tar / ftp.muug.mb.ca / pub / src / perl / form.c < prev    next >
C/C++ Source or Header  |  1992-04-11  |  9KB  |  388 lines

  1. /* $RCSfile: form.c,v $$Revision: 4.0.1.2 $$Date: 91/11/05 17:18:43 $
  2.  *
  3.  *    Copyright (c) 1991, Larry Wall
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  * $Log:    form.c,v $
  9.  * Revision 4.0.1.2  91/11/05  17:18:43  lwall
  10.  * patch11: formats didn't fill their fields as well as they could
  11.  * patch11: ^ fields chopped hyphens on line break
  12.  * patch11: # fields could write outside allocated memory
  13.  * 
  14.  * Revision 4.0.1.1  91/06/07  11:07:59  lwall
  15.  * patch4: new copyright notice
  16.  * patch4: default top-of-form format is now FILEHANDLE_TOP
  17.  * 
  18.  * Revision 4.0  91/03/20  01:19:23  lwall
  19.  * 4.0 baseline.
  20.  * 
  21.  */
  22.  
  23. #include "EXTERN.h"
  24. #include "perl.h"
  25.  
  26. /* Forms stuff */
  27.  
  28. void
  29. form_parseargs(fcmd)
  30. register FCMD *fcmd;
  31. {
  32.     register int i;
  33.     register ARG *arg;
  34.     register int items;
  35.     STR *str;
  36.     ARG *parselist();
  37.     line_t oldline = curcmd->c_line;
  38.     int oldsave = savestack->ary_fill;
  39.  
  40.     str = fcmd->f_unparsed;
  41.     curcmd->c_line = fcmd->f_line;
  42.     fcmd->f_unparsed = Nullstr;
  43.     (void)savehptr(&curstash);
  44.     curstash = str->str_u.str_hash;
  45.     arg = parselist(str);
  46.     restorelist(oldsave);
  47.  
  48.     items = arg->arg_len - 1;    /* ignore $$ on end */
  49.     for (i = 1; i <= items; i++) {
  50.     if (!fcmd || fcmd->f_type == F_NULL)
  51.         fatal("Too many field values");
  52.     dehoist(arg,i);
  53.     fcmd->f_expr = make_op(O_ITEM,1,
  54.       arg[i].arg_ptr.arg_arg,Nullarg,Nullarg);
  55.     if (fcmd->f_flags & FC_CHOP) {
  56.         if ((fcmd->f_expr[1].arg_type & A_MASK) == A_STAB)
  57.         fcmd->f_expr[1].arg_type = A_LVAL;
  58.         else if ((fcmd->f_expr[1].arg_type & A_MASK) == A_EXPR)
  59.         fcmd->f_expr[1].arg_type = A_LEXPR;
  60.         else
  61.         fatal("^ field requires scalar lvalue");
  62.     }
  63.     fcmd = fcmd->f_next;
  64.     }
  65.     if (fcmd && fcmd->f_type)
  66.     fatal("Not enough field values");
  67.     curcmd->c_line = oldline;
  68.     Safefree(arg);
  69.     str_free(str);
  70. }
  71.  
  72. int newsize;
  73.  
  74. #define CHKLEN(allow) \
  75. newsize = (d - orec->o_str) + (allow); \
  76. if (newsize >= curlen) { \
  77.     curlen = d - orec->o_str; \
  78.     GROWSTR(&orec->o_str,&orec->o_len,orec->o_len + (allow)); \
  79.     d = orec->o_str + curlen;    /* in case it moves */ \
  80.     curlen = orec->o_len - 2; \
  81. }
  82.  
  83. format(orec,fcmd,sp)
  84. register struct outrec *orec;
  85. register FCMD *fcmd;
  86. int sp;
  87. {
  88.     register char *d = orec->o_str;
  89.     register char *s;
  90.     register int curlen = orec->o_len - 2;
  91.     register int size;
  92.     FCMD *nextfcmd;
  93.     FCMD *linebeg = fcmd;
  94.     char tmpchar;
  95.     char *t;
  96.     CMD mycmd;
  97.     STR *str;
  98.     char *chophere;
  99.  
  100.     mycmd.c_type = C_NULL;
  101.     orec->o_lines = 0;
  102.     for (; fcmd; fcmd = nextfcmd) {
  103.     nextfcmd = fcmd->f_next;
  104.     CHKLEN(fcmd->f_presize);
  105.     /*SUPPRESS 560*/
  106.     if (s = fcmd->f_pre) {
  107.         while (*s) {
  108.         if (*s == '\n') {
  109.             while (d > orec->o_str && (d[-1] == ' ' || d[-1] == '\t'))
  110.             d--;
  111.             if (fcmd->f_flags & FC_NOBLANK) {
  112.             if (d == orec->o_str || d[-1] == '\n') {
  113.                 orec->o_lines--;    /* don't print blank line */
  114.                 linebeg = fcmd->f_next;
  115.                 break;
  116.             }
  117.             else if (fcmd->f_flags & FC_REPEAT)
  118.                 nextfcmd = linebeg;
  119.             else
  120.                 linebeg = fcmd->f_next;
  121.             }
  122.             else
  123.             linebeg = fcmd->f_next;
  124.         }
  125.         *d++ = *s++;
  126.         }
  127.     }
  128.     if (fcmd->f_unparsed)
  129.         form_parseargs(fcmd);
  130.     switch (fcmd->f_type) {
  131.     case F_NULL:
  132.         orec->o_lines++;
  133.         break;
  134.     case F_LEFT:
  135.         (void)eval(fcmd->f_expr,G_SCALAR,sp);
  136.         str = stack->ary_array[sp+1];
  137.         s = str_get(str);
  138.         size = fcmd->f_size;
  139.         CHKLEN(size);
  140.         chophere = Nullch;
  141.         while (size && *s && *s != '\n') {
  142.         if (*s == '\t')
  143.             *s = ' ';
  144.         size--;
  145.         if (*s && index(chopset,(*d++ = *s++)))
  146.             chophere = s;
  147.         if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
  148.             *s = ' ';
  149.         }
  150.         if (size || !*s)
  151.         chophere = s;
  152.         else if (chophere && chophere < s && *s && index(chopset,*s))
  153.         chophere = s;
  154.         if (fcmd->f_flags & FC_CHOP) {
  155.         if (!chophere)
  156.             chophere = s;
  157.         size += (s - chophere);
  158.         d -= (s - chophere);
  159.         if (fcmd->f_flags & FC_MORE &&
  160.           *chophere && strNE(chophere,"\n")) {
  161.             while (size < 3) {
  162.             d--;
  163.             size++;
  164.             }
  165.             while (d[-1] == ' ' && size < fcmd->f_size) {
  166.             d--;
  167.             size++;
  168.             }
  169.             *d++ = '.';
  170.             *d++ = '.';
  171.             *d++ = '.';
  172.             size -= 3;
  173.         }
  174.         while (*chophere && index(chopset,*chophere)
  175.           && isSPACE(*chophere))
  176.             chophere++;
  177.         str_chop(str,chophere);
  178.         }
  179.         if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n')
  180.         size = 0;            /* no spaces before newline */
  181.         while (size) {
  182.         size--;
  183.         *d++ = ' ';
  184.         }
  185.         break;
  186.     case F_RIGHT:
  187.         (void)eval(fcmd->f_expr,G_SCALAR,sp);
  188.         str = stack->ary_array[sp+1];
  189.         t = s = str_get(str);
  190.         size = fcmd->f_size;
  191.         CHKLEN(size);
  192.         chophere = Nullch;
  193.         while (size && *s && *s != '\n') {
  194.         if (*s == '\t')
  195.             *s = ' ';
  196.         size--;
  197.         if (*s && index(chopset,*s++))
  198.             chophere = s;
  199.         if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
  200.             *s = ' ';
  201.         }
  202.         if (size || !*s)
  203.         chophere = s;
  204.         else if (chophere && chophere < s && *s && index(chopset,*s))
  205.         chophere = s;
  206.         if (fcmd->f_flags & FC_CHOP) {
  207.         if (!chophere)
  208.             chophere = s;
  209.         size += (s - chophere);
  210.         s = chophere;
  211.         while (*chophere && index(chopset,*chophere)
  212.           && isSPACE(*chophere))
  213.             chophere++;
  214.         }
  215.         tmpchar = *s;
  216.         *s = '\0';
  217.         while (size) {
  218.         size--;
  219.         *d++ = ' ';
  220.         }
  221.         size = s - t;
  222.         (void)bcopy(t,d,size);
  223.         d += size;
  224.         *s = tmpchar;
  225.         if (fcmd->f_flags & FC_CHOP)
  226.         str_chop(str,chophere);
  227.         break;
  228.     case F_CENTER: {
  229.         int halfsize;
  230.  
  231.         (void)eval(fcmd->f_expr,G_SCALAR,sp);
  232.         str = stack->ary_array[sp+1];
  233.         t = s = str_get(str);
  234.         size = fcmd->f_size;
  235.         CHKLEN(size);
  236.         chophere = Nullch;
  237.         while (size && *s && *s != '\n') {
  238.         if (*s == '\t')
  239.             *s = ' ';
  240.         size--;
  241.         if (*s && index(chopset,*s++))
  242.             chophere = s;
  243.         if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
  244.             *s = ' ';
  245.         }
  246.         if (size || !*s)
  247.         chophere = s;
  248.         else if (chophere && chophere < s && *s && index(chopset,*s))
  249.         chophere = s;
  250.         if (fcmd->f_flags & FC_CHOP) {
  251.         if (!chophere)
  252.             chophere = s;
  253.         size += (s - chophere);
  254.         s = chophere;
  255.         while (*chophere && index(chopset,*chophere)
  256.           && isSPACE(*chophere))
  257.             chophere++;
  258.         }
  259.         tmpchar = *s;
  260.         *s = '\0';
  261.         halfsize = size / 2;
  262.         while (size > halfsize) {
  263.         size--;
  264.         *d++ = ' ';
  265.         }
  266.         size = s - t;
  267.         (void)bcopy(t,d,size);
  268.         d += size;
  269.         *s = tmpchar;
  270.         if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n')
  271.         size = 0;            /* no spaces before newline */
  272.         else
  273.         size = halfsize;
  274.         while (size) {
  275.         size--;
  276.         *d++ = ' ';
  277.         }
  278.         if (fcmd->f_flags & FC_CHOP)
  279.         str_chop(str,chophere);
  280.         break;
  281.     }
  282.     case F_LINES:
  283.         (void)eval(fcmd->f_expr,G_SCALAR,sp);
  284.         str = stack->ary_array[sp+1];
  285.         s = str_get(str);
  286.         size = str_len(str);
  287.         CHKLEN(size+1);
  288.         orec->o_lines += countlines(s,size) - 1;
  289.         (void)bcopy(s,d,size);
  290.         d += size;
  291.         if (size && s[size-1] != '\n') {
  292.         *d++ = '\n';
  293.         orec->o_lines++;
  294.         }
  295.         linebeg = fcmd->f_next;
  296.         break;
  297.     case F_DECIMAL: {
  298.         double value;
  299.  
  300.         (void)eval(fcmd->f_expr,G_SCALAR,sp);
  301.         str = stack->ary_array[sp+1];
  302.         size = fcmd->f_size;
  303.         CHKLEN(size+1);
  304.         /* If the field is marked with ^ and the value is undefined,
  305.            blank it out. */
  306.         if ((fcmd->f_flags & FC_CHOP) && !str->str_pok && !str->str_nok) {
  307.         while (size) {
  308.             size--;
  309.             *d++ = ' ';
  310.         }
  311.         break;
  312.         }
  313.         value = str_gnum(str);
  314.         if (fcmd->f_flags & FC_DP) {
  315.         sprintf(d, "%#*.*f", size, fcmd->f_decimals, value);
  316.         } else {
  317.         sprintf(d, "%*.0f", size, value);
  318.         }
  319.         d += size;
  320.         break;
  321.     }
  322.     }
  323.     }
  324.     CHKLEN(1);
  325.     *d++ = '\0';
  326. }
  327.  
  328. countlines(s,size)
  329. register char *s;
  330. register int size;
  331. {
  332.     register int count = 0;
  333.  
  334.     while (size--) {
  335.     if (*s++ == '\n')
  336.         count++;
  337.     }
  338.     return count;
  339. }
  340.  
  341. do_write(orec,stab,sp)
  342. struct outrec *orec;
  343. STAB *stab;
  344. int sp;
  345. {
  346.     register STIO *stio = stab_io(stab);
  347.     FILE *ofp = stio->ofp;
  348.  
  349. #ifdef DEBUGGING
  350.     if (debug & 256)
  351.     fprintf(stderr,"left=%ld, todo=%ld\n",
  352.       (long)stio->lines_left, (long)orec->o_lines);
  353. #endif
  354.     if (stio->lines_left < orec->o_lines) {
  355.     if (!stio->top_stab) {
  356.         STAB *topstab;
  357.         char tmpbuf[256];
  358.  
  359.         if (!stio->top_name) {
  360.         if (!stio->fmt_name)
  361.             stio->fmt_name = savestr(stab_name(stab));
  362.         sprintf(tmpbuf, "%s_TOP", stio->fmt_name);
  363.         topstab = stabent(tmpbuf,FALSE);
  364.         if (topstab && stab_form(topstab))
  365.             stio->top_name = savestr(tmpbuf);
  366.         else
  367.             stio->top_name = savestr("top");
  368.         }
  369.         topstab = stabent(stio->top_name,FALSE);
  370.         if (!topstab || !stab_form(topstab)) {
  371.         stio->lines_left = 100000000;
  372.         goto forget_top;
  373.         }
  374.         stio->top_stab = topstab;
  375.     }
  376.     if (stio->lines_left >= 0 && stio->page > 0)
  377.         (void)putc('\f',ofp);
  378.     stio->lines_left = stio->page_len;
  379.     stio->page++;
  380.     format(&toprec,stab_form(stio->top_stab),sp);
  381.     fputs(toprec.o_str,ofp);
  382.     stio->lines_left -= toprec.o_lines;
  383.     }
  384.   forget_top:
  385.     fputs(orec->o_str,ofp);
  386.     stio->lines_left -= orec->o_lines;
  387. }
  388.