diff options
author | Larry Wall <lwall@netlabs.com> | 1993-02-04 22:50:33 +0000 |
---|---|---|
committer | Larry Wall <lwall@netlabs.com> | 1993-02-04 22:50:33 +0000 |
commit | e334a159a5616cab575044bafaf68f75b7bb3a16 (patch) | |
tree | 47369293eb7417e5322f7fe46e1a1cfc0d9c69ef /form.c.orig | |
parent | 514dae0dba791ec01681adb3b3946a7646e146b3 (diff) | |
download | perl-e334a159a5616cab575044bafaf68f75b7bb3a16.tar.gz |
perl 4.0 patch 36: (combined patch)perl-4.0.36
Since Ed Barton sent me a patch for the malignent form of "Malformed
cmd links", I finally broke down and made a patch for the various
other little things that have been accumulating on version 4.
Diffstat (limited to 'form.c.orig')
-rw-r--r-- | form.c.orig | 397 |
1 files changed, 397 insertions, 0 deletions
diff --git a/form.c.orig b/form.c.orig new file mode 100644 index 0000000000..0eb0976a6a --- /dev/null +++ b/form.c.orig @@ -0,0 +1,397 @@ +/* $RCSfile: form.c,v $$Revision: 4.0.1.3 $$Date: 92/06/08 13:21:42 $ + * + * Copyright (c) 1991, Larry Wall + * + * You may distribute under the terms of either the GNU General Public + * License or the Artistic License, as specified in the README file. + * + * $Log: form.c,v $ + * Revision 4.0.1.3 92/06/08 13:21:42 lwall + * patch20: removed implicit int declarations on funcions + * patch20: form feed for formats is now specifiable via $^L + * patch20: Perl now distinguishes overlapped copies from non-overlapped + * + * Revision 4.0.1.2 91/11/05 17:18:43 lwall + * patch11: formats didn't fill their fields as well as they could + * patch11: ^ fields chopped hyphens on line break + * patch11: # fields could write outside allocated memory + * + * Revision 4.0.1.1 91/06/07 11:07:59 lwall + * patch4: new copyright notice + * patch4: default top-of-form format is now FILEHANDLE_TOP + * + * Revision 4.0 91/03/20 01:19:23 lwall + * 4.0 baseline. + * + */ + +#include "EXTERN.h" +#include "perl.h" + +/* Forms stuff */ + +static int countlines(); + +void +form_parseargs(fcmd) +register FCMD *fcmd; +{ + register int i; + register ARG *arg; + register int items; + STR *str; + ARG *parselist(); + line_t oldline = curcmd->c_line; + int oldsave = savestack->ary_fill; + + str = fcmd->f_unparsed; + curcmd->c_line = fcmd->f_line; + fcmd->f_unparsed = Nullstr; + (void)savehptr(&curstash); + curstash = str->str_u.str_hash; + arg = parselist(str); + restorelist(oldsave); + + items = arg->arg_len - 1; /* ignore $$ on end */ + for (i = 1; i <= items; i++) { + if (!fcmd || fcmd->f_type == F_NULL) + fatal("Too many field values"); + dehoist(arg,i); + fcmd->f_expr = make_op(O_ITEM,1, + arg[i].arg_ptr.arg_arg,Nullarg,Nullarg); + if (fcmd->f_flags & FC_CHOP) { + if ((fcmd->f_expr[1].arg_type & A_MASK) == A_STAB) + fcmd->f_expr[1].arg_type = A_LVAL; + else if ((fcmd->f_expr[1].arg_type & A_MASK) == A_EXPR) + fcmd->f_expr[1].arg_type = A_LEXPR; + else + fatal("^ field requires scalar lvalue"); + } + fcmd = fcmd->f_next; + } + if (fcmd && fcmd->f_type) + fatal("Not enough field values"); + curcmd->c_line = oldline; + Safefree(arg); + str_free(str); +} + +int newsize; + +#define CHKLEN(allow) \ +newsize = (d - orec->o_str) + (allow); \ +if (newsize >= curlen) { \ + curlen = d - orec->o_str; \ + GROWSTR(&orec->o_str,&orec->o_len,orec->o_len + (allow)); \ + d = orec->o_str + curlen; /* in case it moves */ \ + curlen = orec->o_len - 2; \ +} + +void +format(orec,fcmd,sp) +register struct outrec *orec; +register FCMD *fcmd; +int sp; +{ + register char *d = orec->o_str; + register char *s; + register int curlen = orec->o_len - 2; + register int size; + FCMD *nextfcmd; + FCMD *linebeg = fcmd; + char tmpchar; + char *t; + CMD mycmd; + STR *str; + char *chophere; + + mycmd.c_type = C_NULL; + orec->o_lines = 0; + for (; fcmd; fcmd = nextfcmd) { + nextfcmd = fcmd->f_next; + CHKLEN(fcmd->f_presize); + /*SUPPRESS 560*/ + if (s = fcmd->f_pre) { + while (*s) { + if (*s == '\n') { + while (d > orec->o_str && (d[-1] == ' ' || d[-1] == '\t')) + d--; + if (fcmd->f_flags & FC_NOBLANK) { + if (d == orec->o_str || d[-1] == '\n') { + orec->o_lines--; /* don't print blank line */ + linebeg = fcmd->f_next; + break; + } + else if (fcmd->f_flags & FC_REPEAT) + nextfcmd = linebeg; + else + linebeg = fcmd->f_next; + } + else + linebeg = fcmd->f_next; + } + *d++ = *s++; + } + } + if (fcmd->f_unparsed) + form_parseargs(fcmd); + switch (fcmd->f_type) { + case F_NULL: + orec->o_lines++; + break; + case F_LEFT: + (void)eval(fcmd->f_expr,G_SCALAR,sp); + str = stack->ary_array[sp+1]; + s = str_get(str); + size = fcmd->f_size; + CHKLEN(size); + chophere = Nullch; + while (size && *s && *s != '\n') { + if (*s == '\t') + *s = ' '; + size--; + if (*s && index(chopset,(*d++ = *s++))) + chophere = s; + if (*s == '\n' && (fcmd->f_flags & FC_CHOP)) + *s = ' '; + } + if (size || !*s) + chophere = s; + else if (chophere && chophere < s && *s && index(chopset,*s)) + chophere = s; + if (fcmd->f_flags & FC_CHOP) { + if (!chophere) + chophere = s; + size += (s - chophere); + d -= (s - chophere); + if (fcmd->f_flags & FC_MORE && + *chophere && strNE(chophere,"\n")) { + while (size < 3) { + d--; + size++; + } + while (d[-1] == ' ' && size < fcmd->f_size) { + d--; + size++; + } + *d++ = '.'; + *d++ = '.'; + *d++ = '.'; + size -= 3; + } + while (*chophere && index(chopset,*chophere) + && isSPACE(*chophere)) + chophere++; + str_chop(str,chophere); + } + if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n') + size = 0; /* no spaces before newline */ + while (size) { + size--; + *d++ = ' '; + } + break; + case F_RIGHT: + (void)eval(fcmd->f_expr,G_SCALAR,sp); + str = stack->ary_array[sp+1]; + t = s = str_get(str); + size = fcmd->f_size; + CHKLEN(size); + chophere = Nullch; + while (size && *s && *s != '\n') { + if (*s == '\t') + *s = ' '; + size--; + if (*s && index(chopset,*s++)) + chophere = s; + if (*s == '\n' && (fcmd->f_flags & FC_CHOP)) + *s = ' '; + } + if (size || !*s) + chophere = s; + else if (chophere && chophere < s && *s && index(chopset,*s)) + chophere = s; + if (fcmd->f_flags & FC_CHOP) { + if (!chophere) + chophere = s; + size += (s - chophere); + s = chophere; + while (*chophere && index(chopset,*chophere) + && isSPACE(*chophere)) + chophere++; + } + tmpchar = *s; + *s = '\0'; + while (size) { + size--; + *d++ = ' '; + } + size = s - t; + Copy(t,d,size,char); + d += size; + *s = tmpchar; + if (fcmd->f_flags & FC_CHOP) + str_chop(str,chophere); + break; + case F_CENTER: { + int halfsize; + + (void)eval(fcmd->f_expr,G_SCALAR,sp); + str = stack->ary_array[sp+1]; + t = s = str_get(str); + size = fcmd->f_size; + CHKLEN(size); + chophere = Nullch; + while (size && *s && *s != '\n') { + if (*s == '\t') + *s = ' '; + size--; + if (*s && index(chopset,*s++)) + chophere = s; + if (*s == '\n' && (fcmd->f_flags & FC_CHOP)) + *s = ' '; + } + if (size || !*s) + chophere = s; + else if (chophere && chophere < s && *s && index(chopset,*s)) + chophere = s; + if (fcmd->f_flags & FC_CHOP) { + if (!chophere) + chophere = s; + size += (s - chophere); + s = chophere; + while (*chophere && index(chopset,*chophere) + && isSPACE(*chophere)) + chophere++; + } + tmpchar = *s; + *s = '\0'; + halfsize = size / 2; + while (size > halfsize) { + size--; + *d++ = ' '; + } + size = s - t; + Copy(t,d,size,char); + d += size; + *s = tmpchar; + if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n') + size = 0; /* no spaces before newline */ + else + size = halfsize; + while (size) { + size--; + *d++ = ' '; + } + if (fcmd->f_flags & FC_CHOP) + str_chop(str,chophere); + break; + } + case F_LINES: + (void)eval(fcmd->f_expr,G_SCALAR,sp); + str = stack->ary_array[sp+1]; + s = str_get(str); + size = str_len(str); + CHKLEN(size+1); + orec->o_lines += countlines(s,size) - 1; + Copy(s,d,size,char); + d += size; + if (size && s[size-1] != '\n') { + *d++ = '\n'; + orec->o_lines++; + } + linebeg = fcmd->f_next; + break; + case F_DECIMAL: { + double value; + + (void)eval(fcmd->f_expr,G_SCALAR,sp); + str = stack->ary_array[sp+1]; + size = fcmd->f_size; + CHKLEN(size+1); + /* If the field is marked with ^ and the value is undefined, + blank it out. */ + if ((fcmd->f_flags & FC_CHOP) && !str->str_pok && !str->str_nok) { + while (size) { + size--; + *d++ = ' '; + } + break; + } + value = str_gnum(str); + if (fcmd->f_flags & FC_DP) { + sprintf(d, "%#*.*f", size, fcmd->f_decimals, value); + } else { + sprintf(d, "%*.0f", size, value); + } + d += size; + break; + } + } + } + CHKLEN(1); + *d++ = '\0'; +} + +static int +countlines(s,size) +register char *s; +register int size; +{ + register int count = 0; + + while (size--) { + if (*s++ == '\n') + count++; + } + return count; +} + +void +do_write(orec,stab,sp) +struct outrec *orec; +STAB *stab; +int sp; +{ + register STIO *stio = stab_io(stab); + FILE *ofp = stio->ofp; + +#ifdef DEBUGGING + if (debug & 256) + fprintf(stderr,"left=%ld, todo=%ld\n", + (long)stio->lines_left, (long)orec->o_lines); +#endif + if (stio->lines_left < orec->o_lines) { + if (!stio->top_stab) { + STAB *topstab; + char tmpbuf[256]; + + if (!stio->top_name) { + if (!stio->fmt_name) + stio->fmt_name = savestr(stab_name(stab)); + sprintf(tmpbuf, "%s_TOP", stio->fmt_name); + topstab = stabent(tmpbuf,FALSE); + if (topstab && stab_form(topstab)) + stio->top_name = savestr(tmpbuf); + else + stio->top_name = savestr("top"); + } + topstab = stabent(stio->top_name,FALSE); + if (!topstab || !stab_form(topstab)) { + stio->lines_left = 100000000; + goto forget_top; + } + stio->top_stab = topstab; + } + if (stio->lines_left >= 0 && stio->page > 0) + fwrite(formfeed->str_ptr, formfeed->str_cur, 1, ofp); + stio->lines_left = stio->page_len; + stio->page++; + format(&toprec,stab_form(stio->top_stab),sp); + fputs(toprec.o_str,ofp); + stio->lines_left -= toprec.o_lines; + } + forget_top: + fputs(orec->o_str,ofp); + stio->lines_left -= orec->o_lines; +} |