scan.l revision 102299
1117397Skan%x string name charmap defn nchar subs subs2 2117397Skan%{ 3169691Skan/*- 4117397Skan * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua> 5117397Skan * at Electronni Visti IA, Kiev, Ukraine. 6117397Skan * All rights reserved. 7117397Skan * 8117397Skan * Redistribution and use in source and binary forms, with or without 9117397Skan * modification, are permitted provided that the following conditions 10117397Skan * are met: 11117397Skan * 1. Redistributions of source code must retain the above copyright 12117397Skan * notice, this list of conditions and the following disclaimer. 13117397Skan * 2. Redistributions in binary form must reproduce the above copyright 14117397Skan * notice, this list of conditions and the following disclaimer in the 15117397Skan * documentation and/or other materials provided with the distribution. 16117397Skan * 17117397Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 18169691Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19117397Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20117397Skan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 21117397Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22117397Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23117397Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24117397Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25117397Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26117397Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27117397Skan * SUCH DAMAGE. 28117397Skan */ 29117397Skan 30169691Skan#include <sys/cdefs.h> 31117397Skan__FBSDID("$FreeBSD: head/usr.bin/colldef/scan.l 102299 2002-08-23 04:18:26Z ache $"); 32169691Skan 33169691Skan#include <ctype.h> 34132720Skan#include <err.h> 35132720Skan#include <limits.h> 36132720Skan#include <unistd.h> 37132720Skan#include <string.h> 38132720Skan#include <sysexits.h> 39132720Skan#include "common.h" 40132720Skan#include "y.tab.h" 41132720Skan 42132720Skanint line_no = 1, save_no, fromsubs; 43132720Skanu_char buf[BUFSIZE], *ptr; 44132720SkanFILE *map_fp; 45132720SkanYY_BUFFER_STATE main_buf, map_buf; 46132720Skan#ifdef FLEX_DEBUG 47132720SkanYYSTYPE yylval; 48132720Skan#endif /* FLEX_DEBUG */ 49132720Skanint yylex(void); 50132720Skan%} 51132720Skan%% 52117397Skan<INITIAL,charmap,nchar,subs,subs2>[ \t]+ ; 53169691Skan<subs2>\" { ptr = buf; BEGIN(string); } 54169691Skan<subs>\< { ptr = buf; fromsubs = 1; BEGIN(name); } 55<INITIAL>\< { ptr = buf; fromsubs = 0; BEGIN(name); } 56^#.*\n line_no++; 57^\n line_no++; 58<INITIAL>\\\n line_no++; 59<INITIAL,nchar,subs>\\t { yylval.ch = '\t'; return CHAR; } 60<INITIAL,nchar,subs>\\n { yylval.ch = '\n'; return CHAR; } 61<INITIAL,nchar,subs>\\b { yylval.ch = '\b'; return CHAR; } 62<INITIAL,nchar,subs>\\f { yylval.ch = '\f'; return CHAR; } 63<INITIAL,nchar,subs>\\v { yylval.ch = '\v'; return CHAR; } 64<INITIAL,nchar,subs>\\r { yylval.ch = '\r'; return CHAR; } 65<INITIAL,nchar,subs>\\a { yylval.ch = '\a'; return CHAR; } 66<subs2>\n { 67 line_no++; 68 BEGIN(INITIAL); 69 return '\n'; 70} 71<INITIAL,nchar>\n { 72 line_no++; 73 if (map_fp != NULL) { 74 ptr = buf; 75 BEGIN(defn); 76 } 77 return '\n'; 78} 79<INITIAL>[;,{}()] return *yytext; 80<INITIAL>substitute { BEGIN(subs); return SUBSTITUTE; } 81<subs>with { BEGIN(subs2); return WITH; } 82<INITIAL>order return ORDER; 83<INITIAL>charmap BEGIN(charmap); 84<INITIAL>;[ \t]*\.\.\.[ \t]*; return RANGE; 85<INITIAL,nchar,subs>\\[0-7]{3} { 86 u_int v; 87 88 sscanf(&yytext[1], "%o", &v); 89 yylval.ch = (u_char)v; 90 return CHAR; 91} 92<INITIAL,nchar,subs>\\x[0-9a-fA-F]{2} { 93 u_int v; 94 95 sscanf(&yytext[2], "%x", &v); 96 yylval.ch = (u_char)v; 97 return CHAR; 98} 99<INITIAL,nchar,subs>\\. { yylval.ch = yytext[1]; return CHAR; } 100<INITIAL,nchar,subs>. { yylval.ch = *yytext; return CHAR; } 101<defn>^#.*\n line_no++; 102<defn>[ \t]+ { 103 if (ptr == buf) 104 errx(EX_UNAVAILABLE, "map expected near line %u of %s", 105 line_no, map_name); 106 *ptr = '\0'; 107 strcpy(yylval.str, buf); 108 BEGIN(nchar); 109 return DEFN; 110} 111<name>\/\/ { 112 if(ptr >= buf + sizeof(buf) - 1) 113 errx(EX_UNAVAILABLE, "name buffer overflow near line %u, character '/'", 114 line_no); 115 *ptr++ = '/'; 116} 117<name>\/\> { 118 if(ptr >= buf + sizeof(buf) - 1) 119 errx(EX_UNAVAILABLE, "name buffer overflow near line %u, character '>'", 120 line_no); 121 *ptr++ = '>'; 122} 123<string>\\\" { 124 if(ptr >= buf + sizeof(buf) - 1) 125 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\"'", 126 line_no); 127 *ptr++ = '"'; 128} 129<name>\> { 130 u_int i; 131 132 if (ptr == buf) 133 errx(EX_UNAVAILABLE, "non-empty name expected near line %u", 134 line_no); 135 *ptr = '\0'; 136 for (i = 0; i <= UCHAR_MAX; i++) { 137 if (strcmp(charmap_table[i], buf) == 0) 138 goto findit; 139 } 140 errx(EX_UNAVAILABLE, "name <%s> not 'charmap'-defined near line %u", 141 buf, line_no); 142 findit: 143 yylval.ch = i; 144 if (fromsubs) 145 BEGIN(subs); 146 else 147 BEGIN(INITIAL); 148 return CHAR; 149} 150<string>\" { 151 *ptr = '\0'; 152 strcpy(yylval.str, buf); 153 BEGIN(subs2); 154 return STRING; 155} 156<name,defn>. { 157 const char *s = (map_fp != NULL) ? map_name : "input"; 158 159 if (!isascii(*yytext) || !isprint(*yytext)) 160 errx(EX_UNAVAILABLE, "non-ASCII or non-printable character 0x%02x not allowed in the map/name near line %u of %s", 161 *yytext, line_no, s); 162 if(ptr >= buf + sizeof(buf) - 1) 163 errx(EX_UNAVAILABLE, "map/name buffer overflow near line %u of %s, character '%c'", 164 line_no, s, *yytext); 165 *ptr++ = *yytext; 166} 167<string>\\t { 168 if(ptr >= buf + sizeof(buf) - 1) 169 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\t'", 170 line_no); 171 *ptr++ = '\t'; 172} 173<string>\\b { 174 if(ptr >= buf + sizeof(buf) - 1) 175 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\b'", 176 line_no); 177 *ptr++ = '\b'; 178} 179<string>\\f { 180 if(ptr >= buf + sizeof(buf) - 1) 181 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\f'", 182 line_no); 183 *ptr++ = '\f'; 184} 185<string>\\v { 186 if(ptr >= buf + sizeof(buf) - 1) 187 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\v'", 188 line_no); 189 *ptr++ = '\v'; 190} 191<string>\\n { 192 if(ptr >= buf + sizeof(buf) - 1) 193 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\n'", 194 line_no); 195 *ptr++ = '\n'; 196} 197<string>\\r { 198 if(ptr >= buf + sizeof(buf) - 1) 199 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\r'", 200 line_no); 201 *ptr++ = '\r'; 202} 203<string>\\a { 204 if(ptr >= buf + sizeof(buf) - 1) 205 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\a'", 206 line_no); 207 *ptr++ = '\a'; 208} 209<name,string,defn>\n { 210 const char *s = (map_fp != NULL) ? map_name : "input"; 211 212 errx(EX_UNAVAILABLE, "unterminated map/name/string near line %u of %s", line_no, s); 213} 214<name,string,nchar><<EOF>> { 215 const char *s = (map_fp != NULL) ? map_name : "input"; 216 217 errx(EX_UNAVAILABLE, "premature EOF in the name/string/char near line %u of %s", line_no, s); 218} 219<string>\\x[0-9a-f]{2} { 220 u_int v; 221 222 sscanf(&yytext[2], "%x", &v); 223 *ptr++ = (u_char)v; 224} 225<string>\\[0-7]{3} { 226 u_int v; 227 228 sscanf(&yytext[1], "%o", &v); 229 *ptr++ = (u_char)v; 230} 231<string>\\. { 232 if(ptr >= buf + sizeof(buf) - 1) 233 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '%c'", 234 line_no, yytext[1]); 235 *ptr++ = yytext[1]; 236} 237<string>. { 238 if(ptr >= buf + sizeof(buf) - 1) 239 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '%c'", 240 line_no, *yytext); 241 *ptr++ = *yytext; 242} 243<charmap>[^ \t\n]+ { 244 strcat(map_name, "/"); 245 strcat(map_name, yytext); 246 if((map_fp = fopen(map_name, "r")) == NULL) 247 err(EX_UNAVAILABLE, "can't open 'charmap' file %s", 248 map_name); 249 save_no = line_no; 250 line_no = 1; 251 map_buf = yy_new_buffer(map_fp, YY_BUF_SIZE); 252 main_buf = YY_CURRENT_BUFFER; 253 yy_switch_to_buffer(map_buf); 254 ptr = buf; 255 BEGIN(defn); 256} 257<charmap>\n { 258 errx(EX_UNAVAILABLE, "'charmap' file name expected near line %u", 259 line_no); 260} 261<charmap><<EOF>> { 262 errx(EX_UNAVAILABLE, "'charmap' file name expected near line %u", 263 line_no); 264} 265<INITIAL,defn><<EOF>> { 266 if(map_fp != NULL) { 267 if (ptr != buf) 268 errx(EX_UNAVAILABLE, "premature EOF in the map near line %u of %s", line_no, map_name); 269 yy_switch_to_buffer(main_buf); 270 yy_delete_buffer(map_buf); 271 fclose(map_fp); 272 map_fp = NULL; 273 line_no = save_no; 274 BEGIN(INITIAL); 275 } else 276 yyterminate(); 277} 278%% 279#ifdef FLEX_DEBUG 280main() 281{ 282 while(yylex()) 283 ; 284 return 0; 285} 286#endif /* FLEX_DEBUG */ 287