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