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