]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/eqn/lex.c
webfs(4): document -d and -D flags
[plan9front.git] / sys / src / cmd / eqn / lex.c
1 #include "e.h"
2 #include "y.tab.h"
3 #include <ctype.h>
4 #include <errno.h>
5
6 #define SSIZE   1000
7 char    token[SSIZE];
8 int     sp;
9
10 void    space(void);
11 void    dodef(tbl *);
12 void    define(int);
13 void    ifdef(void);
14 void    include(void);
15 void    delim(void);
16
17 yylex(void)
18 {
19         register int c;
20         tbl *tp;
21
22   begin:
23         while ((c = input()) == ' ' || c == '\n' || c == '\t')
24                 ;
25         yylval = c;
26         switch (c) {
27         case EOF:
28                 ERROR "unexpected end of input inside equation" WARNING;
29                 return(EOF);
30         case '~':
31                 return(SPACE);
32         case '^':
33                 return(THIN);
34         /* case '\t':
35                 return(TAB);
36         */
37         case '{':
38                 return('{');
39         case '}':
40                 return('}');
41         case '"':
42                 for (sp = 0; (c=input())!='"' && c != '\n'; ) {
43                         if (c == '\\')
44                                 if ((c = input()) != '"')
45                                         token[sp++] = '\\';
46                         token[sp++] = c;
47                         if (sp >= SSIZE)
48                                 ERROR "quoted string %.20s... too long", token FATAL;
49                 }
50                 token[sp] = '\0';
51                 yylval = (int) &token[0];
52                 if (c == '\n')
53                         ERROR "missing \" in %.20s", token WARNING;
54                 return(QTEXT);
55         }
56         if (!display && c == righteq)
57                 return(EOF);
58
59         unput(c);
60         getstr(token, SSIZE);
61         dprintf(".\tlex token = |%s|\n", token);
62         if ((tp = lookup(deftbl, token)) != NULL) {     /* defined term */
63                 c = input();
64                 unput(c);
65                 if (c == '(')   /* macro with args */
66                         dodef(tp);
67                 else {          /* no args */
68                         unput(' ');
69                         pbstr(tp->cval);
70                         dprintf(".\tfound %s|=%s|\n", token, tp->cval);
71                 }
72                 goto begin;
73         }
74
75         if ((tp = lookup(keytbl, token)) == NULL)       /* not a keyword */
76                 return CONTIG;
77
78         switch (tp->ival) {             /* some kind of keyword */
79         case DEFINE: case TDEFINE: case NDEFINE:
80                 define(tp->ival);
81                 break;
82         case IFDEF:
83                 ifdef();
84                 break;
85         case DELIM:
86                 delim();
87                 break;
88         case GSIZE:
89                 globsize();
90                 break;
91         case GFONT:
92                 globfont();
93                 break;
94         case INCLUDE:
95                 include();
96                 break;
97         case SPACE:
98                 space();
99                 break;
100         case DOTEQ:
101                         /* .EQ inside equation -- should warn if at bottom level */
102                 break;
103         case DOTEN:
104                 if (curfile == infile)
105                         return EOF;
106                 /* else ignore nested .EN */
107                 break;
108         default:
109                 return tp->ival;
110         }
111         goto begin;
112 }
113
114 void getstr(char *s, int n)
115 {
116         register int c;
117         register char *p;
118
119         p = s;
120         while ((c = input()) == ' ' || c == '\n')
121                 ;
122         if (c == EOF) {
123                 *s = 0;
124                 return;
125         }
126         while (c != ' ' && c != '\t' && c != '\n' && c != '{' && c != '}'
127             && c != '"' && c != '~' && c != '^') {
128                 if (!display && c == righteq)
129                         break;
130                 if (c == '(' && p > s) {        /* might be defined(...) */
131                         *p = '\0';
132                         if (lookup(deftbl, s) != NULL)
133                                 break;
134                 }
135                 if (c == '\\')
136                         if ((c = input()) != '"')
137                                 *p++ = '\\';
138                 *p++ = c;
139                 if (--n <= 0)
140                         ERROR "token %.20s... too long", s FATAL;
141                 c = input();
142         }
143         unput(c);
144         *p = '\0';
145         yylval = (int) s;
146 }
147
148 cstr(char *s, int quote, int maxs)
149 {
150         int del, c, i;
151
152         s[0] = 0;
153         while ((del=input()) == ' ' || del == '\t')
154                 ;
155         if (quote)
156                 for (i=0; (c=input()) != del && c != EOF;) {
157                         s[i++] = c;
158                         if (i >= maxs)
159                                 return(1);      /* disaster */
160                 }
161         else {
162                 if (del == '\n')
163                         return(1);
164                 s[0] = del;
165                 for (i=1; (c=input())!=' ' && c!= '\t' && c!='\n' && c!=EOF;) {
166                         s[i++] = c;
167                         if (i >= maxs)
168                                 return(1);      /* disaster */
169                 }
170         }
171         s[i] = '\0';
172         if (c == EOF)
173                 ERROR "Unexpected end of input at %.20s", s FATAL;
174         return(0);
175 }
176
177 void define(int type)
178 {
179         char *p1, *p2;
180         extern int ftune(char *, char *);
181
182         getstr(token, SSIZE);   /* get name */
183         if (type != DEFINE) {
184                 cstr(token, 1, SSIZE);  /* skip the definition too */
185                 return;
186         }
187         p1 = strsave(token);
188         if (cstr(token, 1, SSIZE))
189                 ERROR "Unterminated definition at %.20s", token FATAL;
190         if (lookup(ftunetbl, p1) != NULL) {     /* double tuning param */
191                 dprintf(".\ttune %s %s\n", p1, token);
192                 ftune(p1, token);
193         } else {
194                 p2 = strsave(token);
195                 install(deftbl, p1, p2, 0);
196                 dprintf(".\tname %s defined as %s\n", p1, p2);
197         }
198 }
199
200 void ifdef(void)                /* do body if name is defined */
201 {
202         char name[100], *p;
203
204         getstr(name, sizeof(name));     /* get name */
205         cstr(token, 1, SSIZE);          /* and body */
206         if (lookup(deftbl, name) != NULL) {     /* found it */
207                 p = strsave(token);
208                 pushsrc(Free, p);
209                 pushsrc(String, p);
210         }
211 }
212
213 char    *spaceval       = NULL;
214
215 void space(void)        /* collect line of form "space amt" to replace \x in output */
216 {
217         getstr(token, SSIZE);
218         spaceval = strsave(token);
219         dprintf(".\tsetting spaceval to %s\n", token);
220 }
221
222 char *strsave(char *s)
223 {
224         register char *q;
225
226         q = malloc(strlen(s)+1);
227         if (q == NULL)
228                 ERROR "out of space in strsave on %s", s FATAL;
229         strcpy(q, s);
230         return(q);
231 }
232
233 void include(void)
234 {
235         char name[100];
236         FILE *fin;
237         int c;
238
239         while ((c = input()) == ' ')
240                 ;
241         unput(c);
242         cstr(name, c == '"', sizeof(name));     /* gets it quoted or not */
243         if ((fin = fopen(name, "r")) == NULL)
244                 ERROR "can't open file %s", name FATAL;
245         errno = 0;
246         curfile++;
247         curfile->fin = fin;
248         curfile->fname = strsave(name);
249         curfile->lineno = 0;
250         printf(".lf 1 %s\n", curfile->fname);
251         pushsrc(File, curfile->fname);
252 }
253
254 void delim(void)
255 {
256         yyval = eqnreg = 0;
257         if (cstr(token, 0, SSIZE))
258                 ERROR "Bizarre delimiters" FATAL;
259         lefteq = token[0];
260         righteq = token[1];
261         if (!isprint(lefteq) || !isprint(righteq))
262                 ERROR "Bizarre delimiters" FATAL;
263         if (lefteq == 'o' && righteq == 'f')
264                 lefteq = righteq = '\0';
265 }