10 /* eqn input stream */
12 struct ein
*prev
; /* previous buffer */
13 char *buf
; /* input buffer; NULL for stdin */
14 int pos
; /* current position in buf */
15 int unbuf
[LNLEN
]; /* push-back buffer */
17 char *args
[NARGS
]; /* macro arguments */
18 int call
; /* is a macro call */
21 static struct ein ein_stdin
; /* the default input stream */
22 static struct ein
*ein
= &ein_stdin
;
23 static int lineno
= 1; /* current line number */
25 static char *in_strdup(char *s
)
27 char *d
= malloc(strlen(s
) + 1);
32 /* push buf in the input stream; this is a macro call if args is not NULL */
33 static void in_push(char *buf
, char **args
)
35 struct ein
*next
= malloc(sizeof(*next
));
37 memset(next
, 0, sizeof(*next
));
39 next
->buf
= in_strdup(buf
);
40 next
->call
= args
!= NULL
;
42 for (i
= 0; i
< NARGS
; i
++)
43 next
->args
[i
] = args
[i
] ? in_strdup(args
[i
]) : NULL
;
47 /* back to the previous ein buffer */
48 static void in_pop(void)
50 struct ein
*prev
= ein
->prev
;
53 for (i
= 0; i
< NARGS
; i
++)
61 static int in_stdin(void)
69 /* read the next character */
74 return ein
->unbuf
[--ein
->uncnt
];
77 if (ein
->buf
[ein
->pos
])
78 return (unsigned char) ein
->buf
[ein
->pos
++];
88 ein
->unbuf
[ein
->uncnt
++] = c
;
96 void in_lineset(int n
)
106 static struct macro macros
[NMACROS
];
109 static int in_findmacro(char *name
)
112 for (i
= 0; i
< nmacros
; i
++)
113 if (!strcmp(macros
[i
].name
, name
))
119 void in_define(char *name
, char *def
)
121 int idx
= in_findmacro(name
);
122 if (idx
< 0 && nmacros
< NMACROS
)
125 strcpy(macros
[idx
].name
, name
);
126 free(macros
[idx
].def
);
127 macros
[idx
].def
= in_strdup(def
);
134 for (i
= 0; i
< nmacros
; i
++)
138 /* see if name starts with a macro name followed by a '(' */
139 int in_macrocall(char *name
)
142 for (i
= 0; i
< nmacros
; i
++) {
143 mlen
= strlen(macros
[i
].name
);
144 if (!strncmp(macros
[i
].name
, name
, mlen
) && name
[mlen
] == '(')
151 int in_expand(char *name
, char **args
)
153 int i
= in_findmacro(name
);
155 in_push(macros
[i
].def
, args
);
159 /* expand argument */
162 int call
= ein
->call
;
163 if (call
&& ein
->args
[i
- 1])
164 in_push(ein
->args
[i
- 1], NULL
);
168 /* return one if not reading macros and their arguments */