scan.l revision 87243
1%x string name charmap defn nchar subs subs2 2%{ 3/*- 4 * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua> 5 * at Electronni Visti IA, Kiev, Ukraine. 6 * All rights reserved. 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 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> 31 32__FBSDID("$FreeBSD: head/usr.bin/colldef/scan.l 87243 2001-12-02 23:40:46Z markm $"); 33 34#include <ctype.h> 35#include <err.h> 36#include <unistd.h> 37#include <string.h> 38#include <sysexits.h> 39#include "collate.h" 40#include "common.h" 41#include "y.tab.h" 42 43int line_no = 1, save_no, fromsubs; 44u_char buf[BUFSIZE], *ptr; 45FILE *map_fp; 46YY_BUFFER_STATE main_buf, map_buf; 47#ifdef FLEX_DEBUG 48YYSTYPE yylval; 49#endif /* FLEX_DEBUG */ 50int yylex(void); 51%} 52%% 53<INITIAL,charmap,nchar,subs,subs2>[ \t]+ ; 54<subs2>\" { ptr = buf; BEGIN(string); } 55<subs>\< { ptr = buf; fromsubs = 1; BEGIN(name); } 56<INITIAL>\< { ptr = buf; fromsubs = 0; BEGIN(name); } 57^#.*\n line_no++; 58^\n line_no++; 59<INITIAL>\\\n line_no++; 60<INITIAL,nchar,subs>\\t { yylval.ch = '\t'; return CHAR; } 61<INITIAL,nchar,subs>\\n { yylval.ch = '\n'; return CHAR; } 62<INITIAL,nchar,subs>\\b { yylval.ch = '\b'; return CHAR; } 63<INITIAL,nchar,subs>\\f { yylval.ch = '\f'; return CHAR; } 64<INITIAL,nchar,subs>\\v { yylval.ch = '\v'; return CHAR; } 65<INITIAL,nchar,subs>\\r { yylval.ch = '\r'; return CHAR; } 66<INITIAL,nchar,subs>\\a { yylval.ch = '\a'; return CHAR; } 67<INITIAL,nchar,subs>\\. { yylval.ch = yytext[1]; return CHAR; } 68<subs2>\n { 69 line_no++; 70 BEGIN(INITIAL); 71 return '\n'; 72} 73<INITIAL,nchar>\n { 74 line_no++; 75 if (map_fp != NULL) { 76 ptr = buf; 77 BEGIN(defn); 78 } 79 return '\n'; 80} 81<INITIAL>[;,{}()] return *yytext; 82<INITIAL>substitute { BEGIN(subs); return SUBSTITUTE; } 83<subs>with { BEGIN(subs2); return WITH; } 84<INITIAL>order return ORDER; 85<INITIAL>charmap BEGIN(charmap); 86<INITIAL>;[ \t]*\.\.\.[ \t]*; return RANGE; 87<INITIAL,nchar,subs>\\[0-7]{3} { 88 u_int v; 89 90 sscanf(&yytext[1], "%o", &v); 91 yylval.ch = (u_char)v; 92 return CHAR; 93} 94<INITIAL,nchar,subs>\\x[0-9a-z]{2} { 95 u_int v; 96 97 sscanf(&yytext[2], "%x", &v); 98 yylval.ch = (u_char)v; 99 return CHAR; 100} 101<INITIAL>[^;,{}() \t\n"<]+ { 102 if(yyleng == 1) { 103 yylval.ch = *yytext; 104 return CHAR; 105 } 106 if(yyleng > BUFSIZE - 1) 107 errx(EX_UNAVAILABLE, "chain buffer overflow near line %u", 108 line_no); 109 strcpy(yylval.str, yytext); 110 return CHAIN; 111} 112<nchar,subs>. { 113 yylval.ch = *yytext; 114 return CHAR; 115} 116<defn>^#.*\n line_no++; 117<defn>[ \t]+ { 118 if (ptr == buf) 119 errx(EX_UNAVAILABLE, "map expected near line %u of %s", 120 line_no, map_name); 121 *ptr = '\0'; 122 strcpy(yylval.str, buf); 123 BEGIN(nchar); 124 return DEFN; 125} 126<name>\/\/ { 127 if(ptr >= buf + sizeof(buf) - 1) 128 errx(EX_UNAVAILABLE, "name buffer overflow near line %u, character '/'", 129 line_no); 130 *ptr++ = '/'; 131} 132<name>\/\> { 133 if(ptr >= buf + sizeof(buf) - 1) 134 errx(EX_UNAVAILABLE, "name buffer overflow near line %u, character '>'", 135 line_no); 136 *ptr++ = '>'; 137} 138<string>\\\" { 139 if(ptr >= buf + sizeof(buf) - 1) 140 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\"'", 141 line_no); 142 *ptr++ = '"'; 143} 144<name>\> { 145 u_int i; 146 147 if (ptr == buf) 148 errx(EX_UNAVAILABLE, "non-empty name expected near line %u", 149 line_no); 150 *ptr = '\0'; 151 for (i = 0; i <= UCHAR_MAX; i++) { 152 if (strcmp(charmap_table[i], buf) == 0) 153 goto findit; 154 } 155 errx(EX_UNAVAILABLE, "name <%s> not 'charmap'-defined near line %u", 156 buf, line_no); 157 findit: 158 yylval.ch = i; 159 if (fromsubs) 160 BEGIN(subs); 161 else 162 BEGIN(INITIAL); 163 return CHAR; 164} 165<string>\" { 166 *ptr = '\0'; 167 strcpy(yylval.str, buf); 168 BEGIN(subs2); 169 return STRING; 170} 171<name,defn>. { 172 const char *s = (map_fp != NULL) ? map_name : "input"; 173 174 if (!isascii(*yytext) || !isprint(*yytext)) 175 errx(EX_UNAVAILABLE, "non-ASCII or non-printable character 0x%02x not allowed in the map/name near line %u of %s", 176 *yytext, line_no, s); 177 if(ptr >= buf + sizeof(buf) - 1) 178 errx(EX_UNAVAILABLE, "map/name buffer overflow near line %u of %s, character '%c'", 179 line_no, s, *yytext); 180 *ptr++ = *yytext; 181} 182<string>\\t { 183 if(ptr >= buf + sizeof(buf) - 1) 184 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\t'", 185 line_no); 186 *ptr++ = '\t'; 187} 188<string>\\b { 189 if(ptr >= buf + sizeof(buf) - 1) 190 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\b'", 191 line_no); 192 *ptr++ = '\b'; 193} 194<string>\\f { 195 if(ptr >= buf + sizeof(buf) - 1) 196 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\f'", 197 line_no); 198 *ptr++ = '\f'; 199} 200<string>\\v { 201 if(ptr >= buf + sizeof(buf) - 1) 202 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\v'", 203 line_no); 204 *ptr++ = '\v'; 205} 206<string>\\n { 207 if(ptr >= buf + sizeof(buf) - 1) 208 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\n'", 209 line_no); 210 *ptr++ = '\n'; 211} 212<string>\\r { 213 if(ptr >= buf + sizeof(buf) - 1) 214 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\r'", 215 line_no); 216 *ptr++ = '\r'; 217} 218<string>\\a { 219 if(ptr >= buf + sizeof(buf) - 1) 220 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\a'", 221 line_no); 222 *ptr++ = '\a'; 223} 224<name,string,defn>\n { 225 const char *s = (map_fp != NULL) ? map_name : "input"; 226 227 errx(EX_UNAVAILABLE, "unterminated map/name/string near line %u of %s", line_no, s); 228} 229<name,string,nchar><<EOF>> { 230 const char *s = (map_fp != NULL) ? map_name : "input"; 231 232 errx(EX_UNAVAILABLE, "premature EOF in the name/string/char near line %u of %s", line_no, s); 233} 234<string>\\x[0-9a-f]{2} { 235 u_int v; 236 237 sscanf(&yytext[2], "%x", &v); 238 *ptr++ = (u_char)v; 239} 240<string>\\[0-7]{3} { 241 u_int v; 242 243 sscanf(&yytext[1], "%o", &v); 244 *ptr++ = (u_char)v; 245} 246<string>\\. { 247 if(ptr >= buf + sizeof(buf) - 1) 248 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '%c'", 249 line_no, yytext[1]); 250 *ptr++ = yytext[1]; 251} 252<string>. { 253 if(ptr >= buf + sizeof(buf) - 1) 254 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '%c'", 255 line_no, *yytext); 256 *ptr++ = *yytext; 257} 258<charmap>[^ \t\n]+ { 259 strcat(map_name, "/"); 260 strcat(map_name, yytext); 261 if((map_fp = fopen(map_name, "r")) == NULL) 262 err(EX_UNAVAILABLE, "can't open 'charmap' file %s", 263 map_name); 264 save_no = line_no; 265 line_no = 1; 266 map_buf = yy_new_buffer(map_fp, YY_BUF_SIZE); 267 main_buf = YY_CURRENT_BUFFER; 268 yy_switch_to_buffer(map_buf); 269 ptr = buf; 270 BEGIN(defn); 271} 272<charmap>\n { 273 errx(EX_UNAVAILABLE, "'charmap' file name expected near line %u", 274 line_no); 275} 276<charmap><<EOF>> { 277 errx(EX_UNAVAILABLE, "'charmap' file name expected near line %u", 278 line_no); 279} 280<INITIAL,defn><<EOF>> { 281 if(map_fp != NULL) { 282 if (ptr != buf) 283 errx(EX_UNAVAILABLE, "premature EOF in the map near line %u of %s", line_no, map_name); 284 yy_switch_to_buffer(main_buf); 285 yy_delete_buffer(map_buf); 286 fclose(map_fp); 287 map_fp = NULL; 288 line_no = save_no; 289 BEGIN(INITIAL); 290 } else 291 yyterminate(); 292} 293%% 294#ifdef FLEX_DEBUG 295main() 296{ 297 while(yylex()) 298 ; 299 return 0; 300} 301#endif /* FLEX_DEBUG */ 302