scan.l revision 87517
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#ifdef __FBSDID 33__FBSDID("$FreeBSD: head/usr.bin/colldef/scan.l 87517 2001-12-08 02:28:16Z imp $"); 34#endif 35 36#include <ctype.h> 37#include <err.h> 38#include <unistd.h> 39#include <string.h> 40#include <sysexits.h> 41#include "collate.h" 42#include "common.h" 43#include "y.tab.h" 44 45int line_no = 1, save_no, fromsubs; 46u_char buf[BUFSIZE], *ptr; 47FILE *map_fp; 48YY_BUFFER_STATE main_buf, map_buf; 49#ifdef FLEX_DEBUG 50YYSTYPE yylval; 51#endif /* FLEX_DEBUG */ 52int yylex(void); 53%} 54%% 55<INITIAL,charmap,nchar,subs,subs2>[ \t]+ ; 56<subs2>\" { ptr = buf; BEGIN(string); } 57<subs>\< { ptr = buf; fromsubs = 1; BEGIN(name); } 58<INITIAL>\< { ptr = buf; fromsubs = 0; BEGIN(name); } 59^#.*\n line_no++; 60^\n line_no++; 61<INITIAL>\\\n line_no++; 62<INITIAL,nchar,subs>\\t { yylval.ch = '\t'; return CHAR; } 63<INITIAL,nchar,subs>\\n { yylval.ch = '\n'; return CHAR; } 64<INITIAL,nchar,subs>\\b { yylval.ch = '\b'; return CHAR; } 65<INITIAL,nchar,subs>\\f { yylval.ch = '\f'; return CHAR; } 66<INITIAL,nchar,subs>\\v { yylval.ch = '\v'; return CHAR; } 67<INITIAL,nchar,subs>\\r { yylval.ch = '\r'; return CHAR; } 68<INITIAL,nchar,subs>\\a { yylval.ch = '\a'; return CHAR; } 69<INITIAL,nchar,subs>\\. { yylval.ch = yytext[1]; return CHAR; } 70<subs2>\n { 71 line_no++; 72 BEGIN(INITIAL); 73 return '\n'; 74} 75<INITIAL,nchar>\n { 76 line_no++; 77 if (map_fp != NULL) { 78 ptr = buf; 79 BEGIN(defn); 80 } 81 return '\n'; 82} 83<INITIAL>[;,{}()] return *yytext; 84<INITIAL>substitute { BEGIN(subs); return SUBSTITUTE; } 85<subs>with { BEGIN(subs2); return WITH; } 86<INITIAL>order return ORDER; 87<INITIAL>charmap BEGIN(charmap); 88<INITIAL>;[ \t]*\.\.\.[ \t]*; return RANGE; 89<INITIAL,nchar,subs>\\[0-7]{3} { 90 u_int v; 91 92 sscanf(&yytext[1], "%o", &v); 93 yylval.ch = (u_char)v; 94 return CHAR; 95} 96<INITIAL,nchar,subs>\\x[0-9a-z]{2} { 97 u_int v; 98 99 sscanf(&yytext[2], "%x", &v); 100 yylval.ch = (u_char)v; 101 return CHAR; 102} 103<INITIAL>[^;,{}() \t\n"<]+ { 104 if(yyleng == 1) { 105 yylval.ch = *yytext; 106 return CHAR; 107 } 108 if(yyleng > BUFSIZE - 1) 109 errx(EX_UNAVAILABLE, "chain buffer overflow near line %u", 110 line_no); 111 strcpy(yylval.str, yytext); 112 return CHAIN; 113} 114<nchar,subs>. { 115 yylval.ch = *yytext; 116 return CHAR; 117} 118<defn>^#.*\n line_no++; 119<defn>[ \t]+ { 120 if (ptr == buf) 121 errx(EX_UNAVAILABLE, "map expected near line %u of %s", 122 line_no, map_name); 123 *ptr = '\0'; 124 strcpy(yylval.str, buf); 125 BEGIN(nchar); 126 return DEFN; 127} 128<name>\/\/ { 129 if(ptr >= buf + sizeof(buf) - 1) 130 errx(EX_UNAVAILABLE, "name buffer overflow near line %u, character '/'", 131 line_no); 132 *ptr++ = '/'; 133} 134<name>\/\> { 135 if(ptr >= buf + sizeof(buf) - 1) 136 errx(EX_UNAVAILABLE, "name buffer overflow near line %u, character '>'", 137 line_no); 138 *ptr++ = '>'; 139} 140<string>\\\" { 141 if(ptr >= buf + sizeof(buf) - 1) 142 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\"'", 143 line_no); 144 *ptr++ = '"'; 145} 146<name>\> { 147 u_int i; 148 149 if (ptr == buf) 150 errx(EX_UNAVAILABLE, "non-empty name expected near line %u", 151 line_no); 152 *ptr = '\0'; 153 for (i = 0; i <= UCHAR_MAX; i++) { 154 if (strcmp(charmap_table[i], buf) == 0) 155 goto findit; 156 } 157 errx(EX_UNAVAILABLE, "name <%s> not 'charmap'-defined near line %u", 158 buf, line_no); 159 findit: 160 yylval.ch = i; 161 if (fromsubs) 162 BEGIN(subs); 163 else 164 BEGIN(INITIAL); 165 return CHAR; 166} 167<string>\" { 168 *ptr = '\0'; 169 strcpy(yylval.str, buf); 170 BEGIN(subs2); 171 return STRING; 172} 173<name,defn>. { 174 const char *s = (map_fp != NULL) ? map_name : "input"; 175 176 if (!isascii(*yytext) || !isprint(*yytext)) 177 errx(EX_UNAVAILABLE, "non-ASCII or non-printable character 0x%02x not allowed in the map/name near line %u of %s", 178 *yytext, line_no, s); 179 if(ptr >= buf + sizeof(buf) - 1) 180 errx(EX_UNAVAILABLE, "map/name buffer overflow near line %u of %s, character '%c'", 181 line_no, s, *yytext); 182 *ptr++ = *yytext; 183} 184<string>\\t { 185 if(ptr >= buf + sizeof(buf) - 1) 186 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\t'", 187 line_no); 188 *ptr++ = '\t'; 189} 190<string>\\b { 191 if(ptr >= buf + sizeof(buf) - 1) 192 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\b'", 193 line_no); 194 *ptr++ = '\b'; 195} 196<string>\\f { 197 if(ptr >= buf + sizeof(buf) - 1) 198 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\f'", 199 line_no); 200 *ptr++ = '\f'; 201} 202<string>\\v { 203 if(ptr >= buf + sizeof(buf) - 1) 204 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\v'", 205 line_no); 206 *ptr++ = '\v'; 207} 208<string>\\n { 209 if(ptr >= buf + sizeof(buf) - 1) 210 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\n'", 211 line_no); 212 *ptr++ = '\n'; 213} 214<string>\\r { 215 if(ptr >= buf + sizeof(buf) - 1) 216 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\r'", 217 line_no); 218 *ptr++ = '\r'; 219} 220<string>\\a { 221 if(ptr >= buf + sizeof(buf) - 1) 222 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\a'", 223 line_no); 224 *ptr++ = '\a'; 225} 226<name,string,defn>\n { 227 const char *s = (map_fp != NULL) ? map_name : "input"; 228 229 errx(EX_UNAVAILABLE, "unterminated map/name/string near line %u of %s", line_no, s); 230} 231<name,string,nchar><<EOF>> { 232 const char *s = (map_fp != NULL) ? map_name : "input"; 233 234 errx(EX_UNAVAILABLE, "premature EOF in the name/string/char near line %u of %s", line_no, s); 235} 236<string>\\x[0-9a-f]{2} { 237 u_int v; 238 239 sscanf(&yytext[2], "%x", &v); 240 *ptr++ = (u_char)v; 241} 242<string>\\[0-7]{3} { 243 u_int v; 244 245 sscanf(&yytext[1], "%o", &v); 246 *ptr++ = (u_char)v; 247} 248<string>\\. { 249 if(ptr >= buf + sizeof(buf) - 1) 250 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '%c'", 251 line_no, yytext[1]); 252 *ptr++ = yytext[1]; 253} 254<string>. { 255 if(ptr >= buf + sizeof(buf) - 1) 256 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '%c'", 257 line_no, *yytext); 258 *ptr++ = *yytext; 259} 260<charmap>[^ \t\n]+ { 261 strcat(map_name, "/"); 262 strcat(map_name, yytext); 263 if((map_fp = fopen(map_name, "r")) == NULL) 264 err(EX_UNAVAILABLE, "can't open 'charmap' file %s", 265 map_name); 266 save_no = line_no; 267 line_no = 1; 268 map_buf = yy_new_buffer(map_fp, YY_BUF_SIZE); 269 main_buf = YY_CURRENT_BUFFER; 270 yy_switch_to_buffer(map_buf); 271 ptr = buf; 272 BEGIN(defn); 273} 274<charmap>\n { 275 errx(EX_UNAVAILABLE, "'charmap' file name expected near line %u", 276 line_no); 277} 278<charmap><<EOF>> { 279 errx(EX_UNAVAILABLE, "'charmap' file name expected near line %u", 280 line_no); 281} 282<INITIAL,defn><<EOF>> { 283 if(map_fp != NULL) { 284 if (ptr != buf) 285 errx(EX_UNAVAILABLE, "premature EOF in the map near line %u of %s", line_no, map_name); 286 yy_switch_to_buffer(main_buf); 287 yy_delete_buffer(map_buf); 288 fclose(map_fp); 289 map_fp = NULL; 290 line_no = save_no; 291 BEGIN(INITIAL); 292 } else 293 yyterminate(); 294} 295%% 296#ifdef FLEX_DEBUG 297main() 298{ 299 while(yylex()) 300 ; 301 return 0; 302} 303#endif /* FLEX_DEBUG */ 304