eqn: pass the message as a string to fprintf in errdie
[neateqn.git] / src.c
blob6d24a54d5a057b8979e33d69c6b2c10a911a9df8
1 /* reading input */
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include "eqn.h"
7 #define NARGS 10 /* number of arguments */
8 #define NMACROS 512 /* number of macros */
9 #define NSRCDEP 512 /* maximum esrc_depth */
11 /* eqn input stream */
12 struct esrc {
13 struct esrc *prev; /* previous buffer */
14 char *buf; /* input buffer; NULL for stdin */
15 int pos; /* current position in buf */
16 int unbuf[LNLEN]; /* push-back buffer */
17 int uncnt;
18 char *args[NARGS]; /* macro arguments */
19 int call; /* is a macro call */
22 static struct esrc esrc_stdin; /* the default input stream */
23 static struct esrc *esrc = &esrc_stdin;
24 static int lineno = 1; /* current line number */
25 static int esrc_depth; /* the length of esrc chain */
27 static char *src_strdup(char *s)
29 char *d = malloc(strlen(s) + 1);
30 strcpy(d, s);
31 return d;
34 /* push buf in the input stream; this is a macro call if args is not NULL */
35 static void src_push(char *buf, char **args)
37 struct esrc *next;
38 int i;
39 if (esrc_depth > NSRCDEP)
40 errdie("neateqn: macro recursion limit reached\n");
41 next = malloc(sizeof(*next));
42 memset(next, 0, sizeof(*next));
43 next->prev = esrc;
44 next->buf = src_strdup(buf);
45 next->call = args != NULL;
46 if (args)
47 for (i = 0; i < NARGS; i++)
48 next->args[i] = args[i] ? src_strdup(args[i]) : NULL;
49 esrc = next;
50 esrc_depth++;
53 /* back to the previous esrc buffer */
54 static void src_pop(void)
56 struct esrc *prev = esrc->prev;
57 int i;
58 if (prev) {
59 for (i = 0; i < NARGS; i++)
60 free(esrc->args[i]);
61 free(esrc->buf);
62 free(esrc);
63 esrc = prev;
64 esrc_depth--;
68 static int src_stdin(void)
70 int c = fgetc(stdin);
71 if (c == '\n')
72 lineno++;
73 return c;
76 /* read the next character */
77 int src_next(void)
79 while (1) {
80 if (esrc->uncnt)
81 return esrc->unbuf[--esrc->uncnt];
82 if (!esrc->prev)
83 return src_stdin();
84 if (esrc->buf[esrc->pos])
85 return (unsigned char) esrc->buf[esrc->pos++];
86 src_pop();
88 return 0;
91 /* push back c */
92 void src_back(int c)
94 if (c > 0)
95 esrc->unbuf[esrc->uncnt++] = c;
98 int src_lineget(void)
100 return lineno;
103 void src_lineset(int n)
105 lineno = n;
108 /* eqn macros */
109 struct macro {
110 char name[NMLEN];
111 char *def;
113 static struct macro macros[NMACROS];
114 static int nmacros;
116 static int src_findmacro(char *name)
118 int i;
119 for (i = 0; i < nmacros; i++)
120 if (!strcmp(macros[i].name, name))
121 return i;
122 return -1;
125 /* return nonzero if name is a macro */
126 int src_macro(char *name)
128 return src_findmacro(name) >= 0;
131 /* define a macro */
132 void src_define(char *name, char *def)
134 int idx = src_findmacro(name);
135 if (idx < 0 && nmacros < NMACROS)
136 idx = nmacros++;
137 if (idx >= 0) {
138 strcpy(macros[idx].name, name);
139 free(macros[idx].def);
140 macros[idx].def = src_strdup(def);
144 void src_done(void)
146 int i;
147 for (i = 0; i < nmacros; i++)
148 free(macros[i].def);
151 /* expand macro */
152 int src_expand(char *name, char **args)
154 int i = src_findmacro(name);
155 if (i >= 0)
156 src_push(macros[i].def, args);
157 return i < 0;
160 /* expand argument */
161 int src_arg(int i)
163 int call = esrc->call;
164 if (call && esrc->args[i - 1])
165 src_push(esrc->args[i - 1], NULL);
166 return call ? 0 : 1;
169 /* return one if not reading macros and their arguments */
170 int src_top(void)
172 return !esrc->prev;