blob: d384c8b1f601e5c43f71dd1e74a4d52be3792a15 [file] [log] [blame]
/* $Header$
*
* Copyright (c) 1989, Larry Wall
*
* You may distribute under the terms of the GNU General Public License
* as specified in the README file that comes with the perl 3.0 kit.
*
* $Log$
* Revision 1.2 2004/09/01 14:33:24 criswell
* Migrating test suite out of the source tree.
*
* Revision 1.1 2004/02/17 22:21:16 criswell
* Initial commit of the perl Malloc Benchmark. I've cheated a little by
* generating the yacc output files and committing them directly, but it was
* easier than disabling the Bison Voodoo that gets executed by default.
*
* Revision 4.0 91/03/20 01:19:23 lwall
* 4.0 baseline.
*
*/
#include "EXTERN.h"
#include "perl.h"
/* Forms stuff */
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; \
}
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);
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)
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))
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)
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))
chophere++;
}
tmpchar = *s;
*s = '\0';
while (size) {
size--;
*d++ = ' ';
}
size = s - t;
(void)bcopy(t,d,size);
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)
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))
chophere++;
}
tmpchar = *s;
*s = '\0';
halfsize = size / 2;
while (size > halfsize) {
size--;
*d++ = ' ';
}
size = s - t;
(void)bcopy(t,d,size);
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;
(void)bcopy(s,d,size);
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);
/* 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';
}
countlines(s,size)
register char *s;
register int size;
{
register int count = 0;
while (size--) {
if (*s++ == '\n')
count++;
}
return count;
}
do_write(orec,stio,sp)
struct outrec *orec;
register STIO *stio;
int sp;
{
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;
if (!stio->top_name)
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)
(void)putc('\f',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;
}