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