]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/window/scanner.c
unfinished sblive driver, playback/mixer only for now - not enabled in
[FreeBSD/FreeBSD.git] / usr.bin / window / scanner.c
1 /*
2  * Copyright (c) 1983, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Edward Wang at The University of California, Berkeley.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by the University of
19  *      California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36
37 #ifndef lint
38 static char sccsid[] = "@(#)scanner.c   8.1 (Berkeley) 6/6/93";
39 #endif /* not lint */
40
41 #include <ctype.h>
42 #include "value.h"
43 #include "token.h"
44 #include "context.h"
45 #include "string.h"
46
47 s_getc()
48 {
49         register c;
50
51         switch (cx.x_type) {
52         case X_FILE:
53                 c = getc(cx.x_fp);
54                 if (cx.x_bol && c != EOF) {
55                         cx.x_bol = 0;
56                         cx.x_lineno++;
57                 }
58                 if (c == '\n')
59                         cx.x_bol = 1;
60                 return c;
61         case X_BUF:
62                 if (*cx.x_bufp != 0)
63                         return *cx.x_bufp++ & 0xff;
64                 else
65                         return EOF;
66         }
67         /*NOTREACHED*/
68 }
69
70 s_ungetc(c)
71 {
72         if (c == EOF)
73                 return EOF;
74         switch (cx.x_type) {
75         case X_FILE:
76                 cx.x_bol = 0;
77                 return ungetc(c, cx.x_fp);
78         case X_BUF:
79                 if (cx.x_bufp > cx.x_buf)
80                         return *--cx.x_bufp = c;
81                 else
82                         return EOF;
83         }
84         /*NOTREACHED*/
85 }
86
87 s_gettok()
88 {
89         char buf[100];
90         register char *p = buf;
91         register c;
92         register state = 0;
93
94 loop:
95         c = s_getc();
96         switch (state) {
97         case 0:
98                 switch (c) {
99                 case ' ':
100                 case '\t':
101                         break;
102                 case '\n':
103                 case ';':
104                         cx.x_token = T_EOL;
105                         state = -1;
106                         break;
107                 case '#':
108                         state = 1;
109                         break;
110                 case EOF:
111                         cx.x_token = T_EOF;
112                         state = -1;
113                         break;
114                 case '"':
115                         state = 3;
116                         break;
117                 case '\'':
118                         state = 4;
119                         break;
120                 case '\\':
121                         switch (c = s_gettok1()) {
122                         case -1:
123                                 break;
124                         case -2:
125                                 state = 0;
126                                 break;
127                         default:
128                                 *p++ = c;
129                                 state = 2;
130                         }
131                         break;
132                 case '0':
133                         cx.x_val.v_num = 0;
134                         state = 10;
135                         break;
136                 case '1': case '2': case '3': case '4':
137                 case '5': case '6': case '7': case '8': case '9':
138                         cx.x_val.v_num = c - '0';
139                         state = 11;
140                         break;
141                 case '>':
142                         state = 20;
143                         break;
144                 case '<':
145                         state = 21;
146                         break;
147                 case '=':
148                         state = 22;
149                         break;
150                 case '!':
151                         state = 23;
152                         break;
153                 case '&':
154                         state = 24;
155                         break;
156                 case '|':
157                         state = 25;
158                         break;
159                 case '$':
160                         state = 26;
161                         break;
162                 case '~':
163                         cx.x_token = T_COMP;
164                         state = -1;
165                         break;
166                 case '+':
167                         cx.x_token = T_PLUS;
168                         state = -1;
169                         break;
170                 case '-':
171                         cx.x_token = T_MINUS;
172                         state = -1;
173                         break;
174                 case '*':
175                         cx.x_token = T_MUL;
176                         state = -1;
177                         break;
178                 case '/':
179                         cx.x_token = T_DIV;
180                         state = -1;
181                         break;
182                 case '%':
183                         cx.x_token = T_MOD;
184                         state = -1;
185                         break;
186                 case '^':
187                         cx.x_token = T_XOR;
188                         state = -1;
189                         break;
190                 case '(':
191                         cx.x_token = T_LP;
192                         state = -1;
193                         break;
194                 case ')':
195                         cx.x_token = T_RP;
196                         state = -1;
197                         break;
198                 case ',':
199                         cx.x_token = T_COMMA;
200                         state = -1;
201                         break;
202                 case '?':
203                         cx.x_token = T_QUEST;
204                         state = -1;
205                         break;
206                 case ':':
207                         cx.x_token = T_COLON;
208                         state = -1;
209                         break;
210                 case '[':
211                         cx.x_token = T_LB;
212                         state = -1;
213                         break;
214                 case ']':
215                         cx.x_token = T_RB;
216                         state = -1;
217                         break;
218                 default:
219                         if (isalpha(c) || c == '_' || c == '.') {
220                                 *p++ = c;
221                                 state = 2;
222                                 break;
223                         }
224                         cx.x_val.v_num = c;
225                         cx.x_token = T_CHAR;
226                         state = -1;
227                         break;
228                 }
229                 break;
230         case 1:                         /* got # */
231                 if (c == '\n' || c == EOF) {
232                         (void) s_ungetc(c);
233                         state = 0;
234                 }
235                 break;
236         case 2:                         /* unquoted string */
237                 switch (c) {
238                 case '"':
239                         state = 3;
240                         break;
241                 case '\'':
242                         state = 4;
243                         break;
244                 case '\\':
245                         switch (c = s_gettok1()) {
246                         case -2:
247                                 (void) s_ungetc(' ');
248                         case -1:
249                                 break;
250                         default:
251                                 if (p < buf + sizeof buf - 1)
252                                         *p++ = c;
253                         }
254                         break;
255                 default:
256                         if (isalnum(c) || c == '_' || c == '.') {
257                                 if (p < buf + sizeof buf - 1)
258                                         *p++ = c;
259                                 break;
260                         }
261                         (void) s_ungetc(c);
262                 case EOF:
263                         *p = 0;
264                         cx.x_token = T_STR;
265                         switch (*buf) {
266                         case 'i':
267                                 if (buf[1] == 'f' && buf[2] == 0)
268                                         cx.x_token = T_IF;
269                                 break;
270                         case 't':
271                                 if (buf[1] == 'h' && buf[2] == 'e'
272                                     && buf[3] == 'n' && buf[4] == 0)
273                                         cx.x_token = T_THEN;
274                                 break;
275                         case 'e':
276                                 if (buf[1] == 'n' && buf[2] == 'd'
277                                     && buf[3] == 'i' && buf[4] == 'f'
278                                     && buf[5] == 0)
279                                         cx.x_token = T_ENDIF;
280                                 else if (buf[1] == 'l' && buf[2] == 's')
281                                         if (buf[3] == 'i' && buf[4] == 'f'
282                                             && buf[5] == 0)
283                                                 cx.x_token = T_ELSIF;
284                                         else if (buf[3] == 'e' && buf[4] == 0)
285                                                 cx.x_token = T_ELSE;
286                                 break;
287                         }
288                         if (cx.x_token == T_STR
289                             && (cx.x_val.v_str = str_cpy(buf)) == 0) {
290                                 p_memerror();
291                                 cx.x_token = T_EOF;
292                         }
293                         state = -1;
294                         break;
295                 }
296                 break;
297         case 3:                         /* " quoted string */
298                 switch (c) {
299                 case '\n':
300                         (void) s_ungetc(c);
301                 case EOF:
302                 case '"':
303                         state = 2;
304                         break;
305                 case '\\':
306                         switch (c = s_gettok1()) {
307                         case -1:
308                         case -2:        /* newlines are invisible */
309                                 break;
310                         default:
311                                 if (p < buf + sizeof buf - 1)
312                                         *p++ = c;
313                         }
314                         break;
315                 default:
316                         if (p < buf + sizeof buf - 1)
317                                 *p++ = c;
318                         break;
319                 }
320                 break;
321         case 4:                         /* ' quoted string */
322                 switch (c) {
323                 case '\n':
324                         (void) s_ungetc(c);
325                 case EOF:
326                 case '\'':
327                         state = 2;
328                         break;
329                 case '\\':
330                         switch (c = s_gettok1()) {
331                         case -1:
332                         case -2:        /* newlines are invisible */
333                                 break;
334                         default:
335                                 if (p < buf + sizeof buf - 1)
336                                         *p++ = c;
337                         }
338                         break;
339                 default:
340                         if (p < buf + sizeof buf - 1)
341                                 *p++ = c;
342                         break;
343                 }
344                 break;
345         case 10:                        /* got 0 */
346                 switch (c) {
347                 case 'x':
348                 case 'X':
349                         cx.x_val.v_num = 0;
350                         state = 12;
351                         break;
352                 case '0': case '1': case '2': case '3': case '4':
353                 case '5': case '6': case '7':
354                         cx.x_val.v_num = c - '0';
355                         state = 13;
356                         break;
357                 case '8': case '9':
358                         cx.x_val.v_num = c - '0';
359                         state = 11;
360                         break;
361                 default:
362                         (void) s_ungetc(c);
363                         state = -1;
364                         cx.x_token = T_NUM;
365                 }
366                 break;
367         case 11:                        /* decimal number */
368                 switch (c) {
369                 case '0': case '1': case '2': case '3': case '4':
370                 case '5': case '6': case '7': case '8': case '9':
371                         cx.x_val.v_num = cx.x_val.v_num * 10 + c - '0';
372                         break;
373                 default:
374                         (void) s_ungetc(c);
375                         state = -1;
376                         cx.x_token = T_NUM;
377                 }
378                 break;
379         case 12:                        /* hex number */
380                 switch (c) {
381                 case '0': case '1': case '2': case '3': case '4':
382                 case '5': case '6': case '7': case '8': case '9':
383                         cx.x_val.v_num = cx.x_val.v_num * 16 + c - '0';
384                         break;
385                 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
386                         cx.x_val.v_num = cx.x_val.v_num * 16 + c - 'a' + 10;
387                         break;
388                 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
389                         cx.x_val.v_num = cx.x_val.v_num * 16 + c - 'A' + 10;
390                         break;
391                 default:
392                         (void) s_ungetc(c);
393                         state = -1;
394                         cx.x_token = T_NUM;
395                 }
396                 break;
397         case 13:                        /* octal number */
398                 switch (c) {
399                 case '0': case '1': case '2': case '3': case '4':
400                 case '5': case '6': case '7':
401                         cx.x_val.v_num = cx.x_val.v_num * 8 + c - '0';
402                         break;
403                 default:
404                         (void) s_ungetc(c);
405                         state = -1;
406                         cx.x_token = T_NUM;
407                 }
408                 break;
409         case 20:                        /* got > */
410                 switch (c) {
411                 case '=':
412                         cx.x_token = T_GE;
413                         state = -1;
414                         break;
415                 case '>':
416                         cx.x_token = T_RS;
417                         state = -1;
418                         break;
419                 default:
420                         (void) s_ungetc(c);
421                         cx.x_token = T_GT;
422                         state = -1;
423                 }
424                 break;
425         case 21:                        /* got < */
426                 switch (c) {
427                 case '=':
428                         cx.x_token = T_LE;
429                         state = -1;
430                         break;
431                 case '<':
432                         cx.x_token = T_LS;
433                         state = -1;
434                         break;
435                 default:
436                         (void) s_ungetc(c);
437                         cx.x_token = T_LT;
438                         state = -1;
439                 }
440                 break;
441         case 22:                        /* got = */
442                 switch (c) {
443                 case '=':
444                         cx.x_token = T_EQ;
445                         state = -1;
446                         break;
447                 default:
448                         (void) s_ungetc(c);
449                         cx.x_token = T_ASSIGN;
450                         state = -1;
451                 }
452                 break;
453         case 23:                        /* got ! */
454                 switch (c) {
455                 case '=':
456                         cx.x_token = T_NE;
457                         state = -1;
458                         break;
459                 default:
460                         (void) s_ungetc(c);
461                         cx.x_token = T_NOT;
462                         state = -1;
463                 }
464                 break;
465         case 24:                        /* got & */
466                 switch (c) {
467                 case '&':
468                         cx.x_token = T_ANDAND;
469                         state = -1;
470                         break;
471                 default:
472                         (void) s_ungetc(c);
473                         cx.x_token = T_AND;
474                         state = -1;
475                 }
476                 break;
477         case 25:                        /* got | */
478                 switch (c) {
479                 case '|':
480                         cx.x_token = T_OROR;
481                         state = -1;
482                         break;
483                 default:
484                         (void) s_ungetc(c);
485                         cx.x_token = T_OR;
486                         state = -1;
487                 }
488                 break;
489         case 26:                        /* got $ */
490                 switch (c) {
491                 case '?':
492                         cx.x_token = T_DQ;
493                         state = -1;
494                         break;
495                 default:
496                         (void) s_ungetc(c);
497                         cx.x_token = T_DOLLAR;
498                         state = -1;
499                 }
500                 break;
501         default:
502                 abort();
503         }
504         if (state >= 0)
505                 goto loop;
506         return cx.x_token;
507 }
508
509 s_gettok1()
510 {
511         register c;
512         register n;
513
514         c = s_getc();                   /* got \ */
515         switch (c) {
516         case EOF:
517                 return -1;
518         case '\n':
519                 return -2;
520         case 'b':
521                 return '\b';
522         case 'f':
523                 return '\f';
524         case 'n':
525                 return '\n';
526         case 'r':
527                 return '\r';
528         case 't':
529                 return '\t';
530         default:
531                 return c;
532         case '0': case '1': case '2': case '3': case '4':
533         case '5': case '6': case '7':
534                 break;
535         }
536         n = c - '0';
537         c = s_getc();                   /* got \[0-7] */
538         if (c < '0' || c > '7') {
539                 (void) s_ungetc(c);
540                 return n;
541         }
542         n = n * 8 + c - '0';
543         c = s_getc();                   /* got \[0-7][0-7] */
544         if (c < '0' || c > '7') {
545                 (void) s_ungetc(c);
546                 return n;
547         }
548         return n * 8 + c - '0';
549 }