home *** CD-ROM | disk | FTP | other *** search
/ APDL Public Domain 1 / APDL_PD1A.iso / program / language / perl / Source / C / Form < prev    next >
Encoding:
Text File  |  1991-02-09  |  8.6 KB  |  378 lines

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