/* $RCSfile: form.c,v $$Revision: 4.0.1.4 $$Date: 1993/02/05 19:34:32 $
* 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.
* Revision 4.0.1.4 1993/02/05 19:34:32 lwall
* patch36: formats now ignore literal text for ~~ loop determination
* 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
line_t oldline
= curcmd
->c_line
;
int oldsave
= savestack
->ary_fill
;
curcmd
->c_line
= fcmd
->f_line
;
fcmd
->f_unparsed
= Nullstr
;
(void)savehptr(&curstash
);
curstash
= str
->str_u
.str_hash
;
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");
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
;
fatal("^ field requires scalar lvalue");
if (fcmd
&& fcmd
->f_type
)
fatal("Not enough field values");
curcmd
->c_line
= oldline
;
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; \
register struct outrec
*orec
;
register char *d
= orec
->o_str
;
register int curlen
= orec
->o_len
- 2;
for (; fcmd
; fcmd
= nextfcmd
) {
if (blank
&& (fcmd
->f_flags
& FC_REPEAT
)) {
while (d
> t
&& (d
[-1] != '\n'))
while (d
> t
&& (d
[-1] == ' ' || d
[-1] == '\t'))
if (fcmd
->f_flags
& FC_NOBLANK
) {
if (blank
|| d
== orec
->o_str
|| d
[-1] == '\n') {
orec
->o_lines
--; /* don't print blank line */
else if (fcmd
->f_flags
& FC_REPEAT
)
(void)eval(fcmd
->f_expr
,G_SCALAR
,sp
);
str
= stack
->ary_array
[sp
+1];
while (size
&& *s
&& *s
!= '\n') {
if (*s
&& index(chopset
,(*d
++ = *s
++)))
if (*s
== '\n' && (fcmd
->f_flags
& FC_CHOP
))
else if (chophere
&& chophere
< s
&& *s
&& index(chopset
,*s
))
if (fcmd
->f_flags
& FC_CHOP
) {
if (fcmd
->f_flags
& FC_MORE
&&
*chophere
&& strNE(chophere
,"\n")) {
while (d
[-1] == ' ' && size
< fcmd
->f_size
) {
while (*chophere
&& index(chopset
,*chophere
)
if (fcmd
->f_next
&& fcmd
->f_next
->f_pre
[0] == '\n')
size
= 0; /* no spaces before newline */
(void)eval(fcmd
->f_expr
,G_SCALAR
,sp
);
str
= stack
->ary_array
[sp
+1];
while (size
&& *s
&& *s
!= '\n') {
if (*s
&& index(chopset
,*s
++))
if (*s
== '\n' && (fcmd
->f_flags
& FC_CHOP
))
else if (chophere
&& chophere
< s
&& *s
&& index(chopset
,*s
))
if (fcmd
->f_flags
& FC_CHOP
) {
while (*chophere
&& index(chopset
,*chophere
)
if (fcmd
->f_flags
& FC_CHOP
)
(void)eval(fcmd
->f_expr
,G_SCALAR
,sp
);
str
= stack
->ary_array
[sp
+1];
while (size
&& *s
&& *s
!= '\n') {
if (*s
&& index(chopset
,*s
++))
if (*s
== '\n' && (fcmd
->f_flags
& FC_CHOP
))
else if (chophere
&& chophere
< s
&& *s
&& index(chopset
,*s
))
if (fcmd
->f_flags
& FC_CHOP
) {
while (*chophere
&& index(chopset
,*chophere
)
while (size
> halfsize
) {
if (fcmd
->f_next
&& fcmd
->f_next
->f_pre
[0] == '\n')
size
= 0; /* no spaces before newline */
if (fcmd
->f_flags
& FC_CHOP
)
(void)eval(fcmd
->f_expr
,G_SCALAR
,sp
);
str
= stack
->ary_array
[sp
+1];
orec
->o_lines
+= countlines(s
,size
) - 1;
if (size
&& s
[size
-1] != '\n') {
(void)eval(fcmd
->f_expr
,G_SCALAR
,sp
);
str
= stack
->ary_array
[sp
+1];
/* If the field is marked with ^ and the value is undefined,
if ((fcmd
->f_flags
& FC_CHOP
) && !str
->str_pok
&& !str
->str_nok
) {
if (fcmd
->f_flags
& FC_DP
) {
sprintf(d
, "%#*.*f", size
, fcmd
->f_decimals
, value
);
sprintf(d
, "%*.0f", size
, value
);
register STIO
*stio
= stab_io(stab
);
fprintf(stderr
,"left=%ld, todo=%ld\n",
(long)stio
->lines_left
, (long)orec
->o_lines
);
if (stio
->lines_left
< orec
->o_lines
) {
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
);
stio
->top_name
= savestr("top");
topstab
= stabent(stio
->top_name
,FALSE
);
if (!topstab
|| !stab_form(topstab
)) {
stio
->lines_left
= 100000000;
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
;
format(&toprec
,stab_form(stio
->top_stab
),sp
);
stio
->lines_left
-= toprec
.o_lines
;
stio
->lines_left
-= orec
->o_lines
;