home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / perl / os2perl / form.c < prev    next >
C/C++ Source or Header  |  1991-06-11  |  9KB  |  379 lines

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