FreeBSD-Date: 2005/04/07 15:39:38
[dragonfly.git] / usr.bin / bc / scan.l
1 %{
2 /*
3  * $OpenBSD: scan.l,v 1.14 2003/12/02 09:00:07 otto Exp $
4  * $DragonFly: src/usr.bin/bc/scan.l,v 1.1 2004/09/20 04:20:34 dillon Exp $
5  */
6
7 /*
8  * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
9  *
10  * Permission to use, copy, modify, and distribute this software for any
11  * purpose with or without fee is hereby granted, provided that the above
12  * copyright notice and this permission notice appear in all copies.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
17  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
20  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  */
22
23 #include <err.h>
24 #include <stdbool.h>
25 #include <string.h>
26
27 #include "extern.h"
28 #include "y.tab.h"
29
30 int             lineno;
31
32 static char     *strbuf = NULL;
33 static size_t   strbuf_sz = 1;
34 static bool     dot_seen;
35
36 static void     init_strbuf(void);
37 static void     add_str(const char *);
38
39 %}
40
41 DIGIT           [0-9A-F]
42 ALPHA           [a-z_]
43 ALPHANUM        [a-z_0-9]
44
45 %x              comment string number
46
47 %%
48
49 "/*"            BEGIN(comment);
50 <comment>{
51         "*/"    BEGIN(INITIAL);
52         \n      lineno++;
53         \*      ;
54         [^*\n]+ ;
55         <<EOF>> fatal("end of file in comment");
56 }
57
58 \"              BEGIN(string); init_strbuf();
59 <string>{
60         [^"\n\\\[\]]+   add_str(yytext);
61         \[      add_str("\\[");
62         \]      add_str("\\]");
63         \\      add_str("\\\\");
64         \n      add_str("\n"); lineno++;
65         \"      BEGIN(INITIAL); yylval.str = strbuf; return STRING;
66         <<EOF>> fatal("end of file in string");
67 }
68
69 {DIGIT}+        {
70                         BEGIN(number);
71                         dot_seen = false;
72                         init_strbuf();
73                         add_str(yytext);
74                 }
75 \.              {
76                         BEGIN(number);
77                         dot_seen = true;
78                         init_strbuf();
79                         add_str(".");
80                 }
81 <number>{
82         {DIGIT}+        add_str(yytext);
83         \.      {
84                         if (dot_seen) {
85                                 BEGIN(INITIAL);
86                                 yylval.str = strbuf;
87                                 unput('.');
88                                 return NUMBER;
89                         } else {
90                                 dot_seen = true;
91                                 add_str(".");
92                         }
93                 }
94         \\\n[ \t]*      lineno++;
95         [^0-9A-F\.]     {
96                         BEGIN(INITIAL);
97                         unput(yytext[0]);
98                         if (strcmp(strbuf, ".") == 0)
99                                 return DOT;
100                         else {
101                                 yylval.str = strbuf;
102                                 return NUMBER;
103                         }
104                 }
105 }
106
107 "auto"          return AUTO;
108 "break"         return BREAK;
109 "continue"      return CONTINUE;
110 "define"        return DEFINE;
111 "else"          return ELSE;
112 "ibase"         return IBASE;
113 "if"            return IF;
114 "last"          return DOT;
115 "for"           return FOR;
116 "length"        return LENGTH;
117 "obase"         return OBASE;
118 "print"         return PRINT;
119 "quit"          return QUIT;
120 "return"        return RETURN;
121 "scale"         return SCALE;
122 "sqrt"          return SQRT;
123 "while"         return WHILE;
124
125 "^"             return EXPONENT;
126 "*"             return MULTIPLY;
127 "/"             return DIVIDE;
128 "%"             return REMAINDER;
129
130 "!"             return BOOL_NOT;
131 "&&"            return BOOL_AND;
132 "||"            return BOOL_OR;
133
134 "+"             return PLUS;
135 "-"             return MINUS;
136
137 "++"            return INCR;
138 "--"            return DECR;
139
140 "="             yylval.str = ""; return ASSIGN_OP;
141 "+="            yylval.str = "+"; return ASSIGN_OP;
142 "-="            yylval.str = "-"; return ASSIGN_OP;
143 "*="            yylval.str = "*"; return ASSIGN_OP;
144 "/="            yylval.str = "/"; return ASSIGN_OP;
145 "%="            yylval.str = "%"; return ASSIGN_OP;
146 "^="            yylval.str = "^"; return ASSIGN_OP;
147
148 "=="            return EQUALS;
149 "<="            return LESS_EQ;
150 ">="            return GREATER_EQ;
151 "!="            return UNEQUALS;
152 "<"             return LESS;
153 ">"             return GREATER;
154
155 ","             return COMMA;
156 ";"             return SEMICOLON;
157
158 "("             return LPAR;
159 ")"             return RPAR;
160
161 "["             return LBRACKET;
162 "]"             return RBRACKET;
163
164 "{"             return LBRACE;
165 "}"             return RBRACE;
166
167 {ALPHA}{ALPHANUM}* {
168                         /* alloc an extra byte for the type marker */
169                         char *p = malloc(yyleng + 2);
170                         if (p == NULL)
171                                 err(1, NULL);
172                         strlcpy(p, yytext, yyleng + 1);
173                         yylval.astr = p;
174                         return LETTER;
175                 }
176
177 \\\n            lineno++;
178 \n              lineno++; return NEWLINE;
179
180 #[^\n]*         ;
181 [ \t]           ;
182 <<EOF>>         return QUIT;
183 .               yyerror("illegal character");
184
185 %%
186
187 static void
188 init_strbuf(void)
189 {
190         if (strbuf == NULL) {
191                 strbuf = malloc(strbuf_sz);
192                 if (strbuf == NULL)
193                         err(1, NULL);
194         }
195         strbuf[0] = '\0';
196 }
197
198 static void
199 add_str(const char *str)
200 {
201         size_t arglen;
202
203         arglen = strlen(str);
204
205         if (strlen(strbuf) + arglen + 1 > strbuf_sz) {
206                 size_t newsize;
207                 char *p;
208
209                 newsize = strbuf_sz + arglen + 1;
210                 p = realloc(strbuf, newsize);
211                 if (p == NULL) {
212                         free(strbuf);
213                         err(1, NULL);
214                 }
215                 strbuf_sz = newsize;
216                 strbuf = p;
217         }
218         strlcat(strbuf, str, strbuf_sz);
219 }
220
221 void
222 abort_line(int sig)
223 {
224         if (isatty(fileno(yyin))) {
225                 YY_FLUSH_BUFFER;
226                 printf("[\n]P\n");
227         }
228 }