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 } 229