static char sccsid
[] = "@(#)input.c 3.1 (CWI) 85/07/30";
Infile
*curfile
= infile
;
Src src
[MAXSRC
]; /* input source stack */
pushsrc(type
, ptr
) /* new input source */
if (++srcp
>= src
+ MAXSRC
)
fatal("inputs nested too deep");
printf("\n%3d ", srcp
- src
);
printf("push file %s\n", ((Infile
*)ptr
)->fname
);
printf("push macro <%s>\n", ptr
);
printf("push char <%c>\n", *ptr
);
printf("push string <%s>\n", ptr
);
printf("push free <%s>\n", ptr
);
fatal("pushed bad type %d\n", srcp
->type
);
popsrc() /* restore an old one */
fatal("too many inputs popped");
printf("%3d ", srcp
- src
);
printf("pop char <%c>\n", *srcp
->sp
);
fatal("pop weird input %d\n", srcp
->type
);
definition(s
) /* collect definition for s and install */
char *s
; /* definitions picked up lexically */
p
= delimstr("definition");
if (stp
!= NULL
) { /* it's there before */
if (stp
->s_type
!= DEFNAME
) {
yyerror("%s used as variable and definition\n", s
);
makevar(tostring(s
), DEFNAME
, u
);
dprintf("installing %s as `%s'\n", s
, p
);
char *delimstr(s
) /* get body of X ... X */
char *s
; /* message if too big */
int c
, delim
, rdelim
, n
, deep
;
buf
= grow(buf
, "buf", nbuf
+= 1000, sizeof(buf
[0]));
while ((delim
= input()) == ' ' || delim
== '\t' || delim
== '\n')
rdelim
= baldelim(delim
, "{}"); /* could be "(){}[]`'" */
buf
= grow(buf
, "buf", nbuf
+= 1000, sizeof(buf
[0]));
fatal("end of file in %s %c %.20s... %c", s
, delim
, buf
, delim
);
dprintf("delimstr %s %c <%s> %c\n", s
, delim
, buf
, delim
);
baldelim(c
, s
) /* replace c by balancing entry in s */
undefine(s
) /* undefine macro */
while (*s
!= ' ' && *s
!= '\t') /* skip "undef..." */
while (*s
== ' ' || *s
== '\t')
Arg args
[10]; /* argument frames */
Arg
*argfp
= args
; /* frame pointer */
int argcnt
; /* number of arguments seen so far */
dodef(stp
) /* collect args and switch input to defn */
fatal("arguments too deep");
fatal("disaster in dodef\n");
ap
->argval
= malloc(1000);
for (p
= ap
->argval
; (len
= getarg(p
)) != -1; p
+= len
) {
ap
->argstk
[argcnt
++] = p
;
for (i
= argcnt
; i
< MAXARGS
; i
++)
for (i
= 0; i
< argcnt
; i
++)
printf("arg %d.%d = <%s>\n", ap
-args
, i
+1, ap
->argstk
[i
]);
pushsrc(Macro
, stp
->s_val
.p
);
getarg(p
) /* pick up single argument, store in p, return length */
fatal("end of file in getarg!\n");
if (npar
== 0 && (c
== ',' || c
== ')'))
if (c
== '"') /* copy quoted stuff intact */
} while ((c
= input()) != '"' && c
!= EOF
);
char pbuf
[PBSIZE
]; /* pushback buffer */
char *pb
= pbuf
-1; /* next pushed back character */
char ebuf
[200]; /* collect input here for error reporting */
extern struct symtab
*thrudef
;
if (ep
>= ebuf
+ sizeof ebuf
)
case Free
: /* free string */
case Thru
: /* end of pushed back line */
} else { /* can't happen? */
if (*srcp
->sp
== '\0') /* empty, so pop */
fatal("argfp underflow");
} else if (c
== '$' && isdigit(*srcp
->sp
)) {
while (isdigit(*srcp
->sp
))
n
= 10 * n
+ *srcp
->sp
++ - '0';
if (n
> 0 && n
<= MAXARGS
)
pushsrc(String
, argfp
->argstk
[n
-1]);
fatal("end of file inside .PS/.PE");
if (curfile
->fin
!= stdin
) {
free(curfile
->fname
); /* assumes allocated */
printf(".lf %d %s\n", curfile
->lineno
, curfile
->fname
);
thru
= 0; /* chicken out */
do_thru() /* read one line, make into a macro expansion */
fatal("arguments too deep");
ap
->argval
= malloc(1000);
if (thru
== 0) { /* end of file was seen, so thru is done */
for ( ; c
!= '\n' && c
!= EOF
; ) {
if (c
== ' ' || c
== '\t') {
ap
->argstk
[argcnt
++] = p
;
if ((c
= nextchar()) == '\\') {
} while (c
!= '"' && c
!= '\n' && c
!= EOF
);
} while ((c
= nextchar())!=' ' && c
!='\t' && c
!='\n' && c
!=',' && c
!=EOF
);
fatal("unexpected end of file in do_thru");
if (argcnt
== 0) { /* ignore blank line */
pushsrc(Thru
, (char *) 0);
for (i
= argcnt
; i
< MAXARGS
; i
++)
for (i
= 0; i
< argcnt
; i
++)
printf("arg %d.%d = <%s>\n", ap
-args
, i
+1, ap
->argstk
[i
]);
if (strcmp(ap
->argstk
[0], ".PE") == 0) {
pushsrc(String
, "\n.PE\n");
if (untilstr
&& strcmp(ap
->argstk
[0], untilstr
) == 0) {
pushsrc(Thru
, (char *) 0);
dprintf("do_thru pushing back <%s>\n", thrudef
->s_val
.p
);
pushsrc(Macro
, thrudef
->s_val
.p
);
if (++pb
>= pbuf
+ sizeof pbuf
)
fatal("pushback overflow\n");
ep
= ebuf
+ sizeof(ebuf
) - 1;
yyerror("%s argument out of domain", s
);
} else if (errno
== ERANGE
) {
yyerror("%s result out of range", s
);
fatal(s
, s1
, s2
, s3
, s4
) /* should be a flag on yyerror */
char *s
, *s1
, *s2
, *s3
, *s4
;
yyerror(s
, s1
, s2
, s3
, s4
);
yyerror(s
, s1
, s2
, s3
, s4
)
char *s
, *s1
, *s2
, *s3
, *s4
;
extern char *cmdname
, *sys_errlist
[];
extern int errno
, sys_nerr
;
fprintf(stderr
, "%s: ", cmdname
);
fprintf(stderr
, s
, s1
, s2
, s3
, s4
);
if (errno
> 0 && errno
< sys_nerr
)
fprintf(stderr
, " (%s)", sys_errlist
[errno
]);
fprintf(stderr
, " near line %d, file %s\n",
curfile
->lineno
, curfile
->fname
);
eprint() /* try to print context around error */
if (p
> ebuf
&& *p
== '\n')
for ( ; p
>= ebuf
&& *p
!= '\n'; p
--)
fprintf(stderr
, " context is\n\t");
for (q
=ep
-1; q
>=p
&& *q
!=' ' && *q
!='\t' && *q
!='\n'; q
--)
fprintf(stderr
, " >>> ");
fprintf(stderr
, " <<< ");
fgets(ebuf
, sizeof ebuf
, curfile
->fin
);
fprintf(stderr
, "%s", ebuf
);
pbstr("\n.PE\n"); /* safety first */
char *newfile
= 0; /* filename for file copy */
char *untilstr
= 0; /* string that terminates a thru */
int thru
= 0; /* 1 if copying thru macro */
struct symtab
*thrudef
= 0; /* macro being used */
copyfile(s
) /* remember file to start reading from */
copydef(p
) /* remember macro symtab ptr */
struct symtab
*copythru(s
) /* collect the macro name or body for thru */
if (p
->s_type
== DEFNAME
) {
p
->s_val
.p
= addnewline(p
->s_val
.p
);
fatal("%s used as define and name", s
);
/* have to collect the definition */
pbstr(s
); /* first char is the delimiter */
q
= delimstr("thru body");
p
= makevar(tostring(s
), DEFNAME
, u
);
p
->s_val
.p
= addnewline(p
->s_val
.p
);
dprintf("installing %s as `%s'\n", s
, p
->s_val
.p
);
char *addnewline(p
) /* add newline to end of p */
copyuntil(s
) /* string that terminates a thru */
copy() /* begin input from file, etc. */
if ((fin
= fopen(newfile
, "r")) == NULL
)
fatal("can't open file %s", newfile
);
curfile
->fname
= newfile
;
printf(".lf 1 %s\n", curfile
->fname
);
begin
= 1; /* wrong place */
char shellbuf
[1000], *shellp
;
shell_init() /* set up to interpret a shell command */
sprintf(shellbuf
, "sh -c '");
shellp
= shellbuf
+ strlen(shellbuf
);
shell_text(s
) /* add string to command being collected */