10 Infile
*curfile
= infile
;
13 Src src
[MAXSRC
]; /* input source stack */
20 int baldelim(int, char *);
22 void pushsrc(int type
, char *ptr
) /* new input source */
24 if (++srcp
>= src
+ MAXSRC
)
25 ERROR
"inputs nested too deep" FATAL
;
29 printf("\n%3d ", srcp
- src
);
32 printf("push file %s\n", ((Infile
*)ptr
)->fname
);
35 printf("push macro <%s>\n", ptr
);
38 printf("push char <%c>\n", *ptr
);
41 printf("push thru\n");
44 printf("push string <%s>\n", ptr
);
47 printf("push free <%s>\n", ptr
);
50 ERROR
"pushed bad type %d", srcp
->type FATAL
;
55 void popsrc(void) /* restore an old one */
58 ERROR
"too many inputs popped" FATAL
;
60 printf("%3d ", srcp
- src
);
66 printf("pop macro\n");
69 printf("pop char <%c>\n", *srcp
->sp
);
75 printf("pop string\n");
81 ERROR
"pop weird input %d", srcp
->type FATAL
;
87 void definition(char *s
) /* collect definition for s and install */
88 /* definitions picked up lexically */
93 p
= delimstr("definition");
95 if (stp
!= NULL
) { /* it's there before */
96 if (stp
->s_type
!= DEFNAME
) {
97 ERROR
"%s used as variable and definition", s WARNING
;
105 makevar(tostring(s
), DEFNAME
, u
);
107 dprintf("installing %s as `%s'\n", s
, p
);
110 char *delimstr(char *s
) /* get body of X ... X */
111 /* message if too big */
113 int c
, delim
, rdelim
, n
, deep
;
114 static char *buf
= NULL
;
119 buf
= grow(buf
, "buf", nbuf
+= 1000, sizeof(buf
[0]));
120 while ((delim
= input()) == ' ' || delim
== '\t' || delim
== '\n')
122 rdelim
= baldelim(delim
, "{}"); /* could be "(){}[]`'" */
131 if (p
>= buf
+ nbuf
) {
133 buf
= grow(buf
, "buf", nbuf
+= 1000, sizeof(buf
[0]));
137 ERROR
"end of file in %s %c %.20s... %c", s
, delim
, buf
, delim FATAL
;
141 dprintf("delimstr %s %c <%s> %c\n", s
, delim
, buf
, delim
);
142 return tostring(buf
);
145 baldelim(int c
, char *s
) /* replace c by balancing entry in s */
153 void undefine(char *s
) /* undefine macro */
155 while (*s
!= ' ' && *s
!= '\t') /* skip "undef..." */
157 while (*s
== ' ' || *s
== '\t')
163 Arg args
[10]; /* argument frames */
164 Arg
*argfp
= args
; /* frame pointer */
165 int argcnt
; /* number of arguments seen so far */
167 void dodef(struct symtab
*stp
) /* collect args and switch input to defn */
175 ERROR
"arguments too deep" FATAL
;
178 ERROR
"disaster in dodef" FATAL
;
180 ap
->argval
= malloc(1000);
181 for (p
= ap
->argval
; (len
= getarg(p
)) != -1; p
+= len
) {
182 ap
->argstk
[argcnt
++] = p
;
186 for (i
= argcnt
; i
< MAXARGS
; i
++)
189 for (i
= 0; i
< argcnt
; i
++)
190 printf("arg %d.%d = <%s>\n", ap
-args
, i
+1, ap
->argstk
[i
]);
192 pushsrc(Macro
, stp
->s_val
.p
);
195 getarg(char *p
) /* pick up single argument, store in p, return length */
203 ERROR
"end of file in getarg" FATAL
;
204 if (npar
== 0 && (c
== ',' || c
== ')'))
206 if (c
== '"') /* copy quoted stuff intact */
210 } while ((c
= input()) != '"' && c
!= EOF
);
224 char pbuf
[PBSIZE
]; /* pushback buffer */
225 char *pb
= pbuf
-1; /* next pushed back character */
227 char ebuf
[200]; /* collect input here for error reporting */
232 extern struct symtab
*thrudef
;
233 extern char *untilstr
;
246 if (ep
>= ebuf
+ sizeof ebuf
)
248 return *(unsigned char *)ep
++ = c
;
256 switch (srcp
->type
) {
257 case Free
: /* free string */
261 case Thru
: /* end of pushed back line */
271 } else { /* can't happen? */
281 if (*srcp
->sp
== '\0') /* empty, so pop */
289 ERROR
"argfp underflow" FATAL
;
292 } else if (c
== '$' && isdigit(*srcp
->sp
)) {
294 while (isdigit(*srcp
->sp
))
295 n
= 10 * n
+ *srcp
->sp
++ - '0';
296 if (n
> 0 && n
<= MAXARGS
)
297 pushsrc(String
, argfp
->argstk
[n
-1]);
302 c
= getc(curfile
->fin
);
304 if (curfile
== infile
)
305 ERROR
"end of file inside .PS/.PE" FATAL
;
306 if (curfile
->fin
!= stdin
) {
307 fclose(curfile
->fin
);
308 free(curfile
->fname
); /* assumes allocated */
311 printlf(curfile
->lineno
, curfile
->fname
);
313 thru
= 0; /* chicken out */
328 void do_thru(void) /* read one line, make into a macro expansion */
336 ERROR
"arguments too deep" FATAL
;
337 if (ap
->argval
== NULL
)
338 ap
->argval
= malloc(1000);
342 if (thru
== 0) { /* end of file was seen, so thru is done */
346 for ( ; c
!= '\n' && c
!= EOF
; ) {
347 if (c
== ' ' || c
== '\t') {
351 ap
->argstk
[argcnt
++] = p
;
355 if ((c
= nextchar()) == '\\') {
360 } while (c
!= '"' && c
!= '\n' && c
!= EOF
);
367 } while ((c
= nextchar())!=' ' && c
!='\t' && c
!='\n' && c
!=',' && c
!=EOF
);
374 ERROR
"unexpected end of file in do_thru" FATAL
;
375 if (argcnt
== 0) { /* ignore blank line */
376 pushsrc(Thru
, (char *) 0);
379 for (i
= argcnt
; i
< MAXARGS
; i
++)
382 for (i
= 0; i
< argcnt
; i
++)
383 printf("arg %d.%d = <%s>\n", ap
-args
, i
+1, ap
->argstk
[i
]);
384 if (strcmp(ap
->argstk
[0], ".PE") == 0) {
387 pushsrc(String
, "\n.PE\n");
390 if (untilstr
&& strcmp(ap
->argstk
[0], untilstr
) == 0) {
397 pushsrc(Thru
, (char *) 0);
398 dprintf("do_thru pushing back <%s>\n", thrudef
->s_val
.p
);
400 pushsrc(Macro
, thrudef
->s_val
.p
);
405 if (++pb
>= pbuf
+ sizeof pbuf
)
406 ERROR
"pushback overflow" FATAL
;
408 ep
= ebuf
+ sizeof(ebuf
) - 1;
419 double errcheck(double x
, char *s
)
425 ERROR
"%s argument out of domain", s WARNING
;
426 } else if (errno
== ERANGE
) {
428 ERROR
"%s result out of range", s WARNING
;
437 void yyerror(char *s
)
439 extern char *cmdname
;
440 int ern
= errno
; /* cause some libraries clobber it */
445 fprintf(stderr
, "%s: %s", cmdname
, s
);
450 fprintf(stderr
, " near %s:%d\n",
451 curfile
->fname
, curfile
->lineno
+1);
457 void eprint(void) /* try to print context around error */
462 if (p
> ebuf
&& *p
== '\n')
464 for ( ; p
>= ebuf
&& *p
!= '\n'; p
--)
468 fprintf(stderr
, " context is\n\t");
469 for (q
=ep
-1; q
>=p
&& *q
!=' ' && *q
!='\t' && *q
!='\n'; q
--)
473 fprintf(stderr
, " >>> ");
476 fprintf(stderr
, " <<< ");
479 fgets(ebuf
, sizeof ebuf
, curfile
->fin
);
480 fprintf(stderr
, "%s", ebuf
);
481 pbstr("\n.PE\n"); /* safety first */
487 char *newfile
= 0; /* filename for file copy */
488 char *untilstr
= 0; /* string that terminates a thru */
489 int thru
= 0; /* 1 if copying thru macro */
490 struct symtab
*thrudef
= 0; /* macro being used */
492 void copyfile(char *s
) /* remember file to start reading from */
497 void copydef(struct symtab
*p
) /* remember macro symtab ptr */
502 struct symtab
*copythru(char *s
) /* collect the macro name or body for thru */
505 char *q
, *addnewline(char *);
509 if (p
->s_type
== DEFNAME
) {
510 p
->s_val
.p
= addnewline(p
->s_val
.p
);
513 ERROR
"%s used as define and name", s FATAL
;
515 /* have to collect the definition */
516 pbstr(s
); /* first char is the delimiter */
517 q
= delimstr("thru body");
527 p
= makevar(tostring(s
), DEFNAME
, u
);
529 p
->s_val
.p
= addnewline(p
->s_val
.p
);
530 dprintf("installing %s as `%s'\n", s
, p
->s_val
.p
);
534 char *addnewline(char *p
) /* add newline to end of p */
539 if (p
[n
-1] != '\n') {
547 void copyuntil(char *s
) /* string that terminates a thru */
552 void copy(void) /* begin input from file, etc. */
557 if ((fin
= fopen(newfile
, "r")) == NULL
)
558 ERROR
"can't open file %s", newfile FATAL
;
561 curfile
->fname
= newfile
;
563 printlf(1, curfile
->fname
);
564 pushsrc(File
, curfile
->fname
);
569 begin
= 1; /* wrong place */
573 char shellbuf
[1000], *shellp
;
575 void shell_init(void) /* set up to interpret a shell command */
577 sprintf(shellbuf
, "rc -c '");
578 shellp
= shellbuf
+ strlen(shellbuf
);
581 void shell_text(char *s
) /* add string to command being collected */
583 while (*shellp
++ = *s
++)
588 void shell_exec(void) /* do it */