scan.l revision 175038
1174561Sdas%x string name charmap defn nchar subs subs2 2181074Sdas%{ 3174561Sdas/*- 4174561Sdas * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua> 5174561Sdas * at Electronni Visti IA, Kiev, Ukraine. 6174561Sdas * All rights reserved. 7174561Sdas * 8174561Sdas * Redistribution and use in source and binary forms, with or without 9174561Sdas * modification, are permitted provided that the following conditions 10174561Sdas * are met: 11174561Sdas * 1. Redistributions of source code must retain the above copyright 12174561Sdas * notice, this list of conditions and the following disclaimer. 13174561Sdas * 2. Redistributions in binary form must reproduce the above copyright 14174561Sdas * notice, this list of conditions and the following disclaimer in the 15174561Sdas * documentation and/or other materials provided with the distribution. 16174561Sdas * 17174561Sdas * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 18174561Sdas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19174561Sdas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20174561Sdas * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 21174561Sdas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22174561Sdas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23174561Sdas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24174561Sdas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25174561Sdas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26174561Sdas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27174561Sdas * SUCH DAMAGE. 28174561Sdas */ 29174561Sdas 30174561Sdas#include <sys/cdefs.h> 31174561Sdas__FBSDID("$FreeBSD: head/usr.bin/colldef/scan.l 175038 2008-01-01 10:04:10Z imp $"); 32174561Sdas 33181074Sdas#include <sys/types.h> 34181074Sdas#include <ctype.h> 35174561Sdas#include <err.h> 36174561Sdas#include <limits.h> 37181074Sdas#include <unistd.h> 38174561Sdas#include <string.h> 39#include <sysexits.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<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-fA-F]{2} { 94 u_int v; 95 96 sscanf(&yytext[2], "%x", &v); 97 yylval.ch = (u_char)v; 98 return CHAR; 99} 100<INITIAL,nchar,subs>\\. { yylval.ch = yytext[1]; return CHAR; } 101<INITIAL,nchar,subs>. { yylval.ch = *yytext; return CHAR; } 102<defn>^#.*\n line_no++; 103<defn>[ \t]+ { 104 if (ptr == buf) 105 errx(EX_UNAVAILABLE, "map expected near line %u of %s", 106 line_no, map_name); 107 *ptr = '\0'; 108 strcpy(yylval.str, buf); 109 BEGIN(nchar); 110 return DEFN; 111} 112<name>\/\/ { 113 if(ptr >= buf + sizeof(buf) - 1) 114 errx(EX_UNAVAILABLE, "name buffer overflow near line %u, character '/'", 115 line_no); 116 *ptr++ = '/'; 117} 118<name>\/\> { 119 if(ptr >= buf + sizeof(buf) - 1) 120 errx(EX_UNAVAILABLE, "name buffer overflow near line %u, character '>'", 121 line_no); 122 *ptr++ = '>'; 123} 124<string>\\\" { 125 if(ptr >= buf + sizeof(buf) - 1) 126 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\"'", 127 line_no); 128 *ptr++ = '"'; 129} 130<name>\> { 131 u_int i; 132 133 if (ptr == buf) 134 errx(EX_UNAVAILABLE, "non-empty name expected near line %u", 135 line_no); 136 *ptr = '\0'; 137 for (i = 0; i <= UCHAR_MAX; i++) { 138 if (strcmp(charmap_table[i], buf) == 0) 139 goto findit; 140 } 141 errx(EX_UNAVAILABLE, "name <%s> not 'charmap'-defined near line %u", 142 buf, line_no); 143 findit: 144 yylval.ch = i; 145 if (fromsubs) 146 BEGIN(subs); 147 else 148 BEGIN(INITIAL); 149 return CHAR; 150} 151<string>\" { 152 *ptr = '\0'; 153 strcpy(yylval.str, buf); 154 BEGIN(subs2); 155 return STRING; 156} 157<name,defn>. { 158 const char *s = (map_fp != NULL) ? map_name : "input"; 159 160 if (!isascii(*yytext) || !isprint(*yytext)) 161 errx(EX_UNAVAILABLE, "non-ASCII or non-printable character 0x%02x not allowed in the map/name near line %u of %s", 162 *yytext, line_no, s); 163 if(ptr >= buf + sizeof(buf) - 1) 164 errx(EX_UNAVAILABLE, "map/name buffer overflow near line %u of %s, character '%c'", 165 line_no, s, *yytext); 166 *ptr++ = *yytext; 167} 168<string>\\t { 169 if(ptr >= buf + sizeof(buf) - 1) 170 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\t'", 171 line_no); 172 *ptr++ = '\t'; 173} 174<string>\\b { 175 if(ptr >= buf + sizeof(buf) - 1) 176 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\b'", 177 line_no); 178 *ptr++ = '\b'; 179} 180<string>\\f { 181 if(ptr >= buf + sizeof(buf) - 1) 182 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\f'", 183 line_no); 184 *ptr++ = '\f'; 185} 186<string>\\v { 187 if(ptr >= buf + sizeof(buf) - 1) 188 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\v'", 189 line_no); 190 *ptr++ = '\v'; 191} 192<string>\\n { 193 if(ptr >= buf + sizeof(buf) - 1) 194 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\n'", 195 line_no); 196 *ptr++ = '\n'; 197} 198<string>\\r { 199 if(ptr >= buf + sizeof(buf) - 1) 200 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\r'", 201 line_no); 202 *ptr++ = '\r'; 203} 204<string>\\a { 205 if(ptr >= buf + sizeof(buf) - 1) 206 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\a'", 207 line_no); 208 *ptr++ = '\a'; 209} 210<name,string,defn>\n { 211 const char *s = (map_fp != NULL) ? map_name : "input"; 212 213 errx(EX_UNAVAILABLE, "unterminated map/name/string near line %u of %s", line_no, s); 214} 215<name,string,nchar><<EOF>> { 216 const char *s = (map_fp != NULL) ? map_name : "input"; 217 218 errx(EX_UNAVAILABLE, "premature EOF in the name/string/char near line %u of %s", line_no, s); 219} 220<string>\\x[0-9a-f]{2} { 221 u_int v; 222 223 sscanf(&yytext[2], "%x", &v); 224 *ptr++ = (u_char)v; 225} 226<string>\\[0-7]{3} { 227 u_int v; 228 229 sscanf(&yytext[1], "%o", &v); 230 *ptr++ = (u_char)v; 231} 232<string>\\. { 233 if(ptr >= buf + sizeof(buf) - 1) 234 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '%c'", 235 line_no, yytext[1]); 236 *ptr++ = yytext[1]; 237} 238<string>. { 239 if(ptr >= buf + sizeof(buf) - 1) 240 errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '%c'", 241 line_no, *yytext); 242 *ptr++ = *yytext; 243} 244<charmap>[^ \t\n]+ { 245 strcat(map_name, "/"); 246 strcat(map_name, yytext); 247 if((map_fp = fopen(map_name, "r")) == NULL) 248 err(EX_UNAVAILABLE, "can't open 'charmap' file %s", 249 map_name); 250 save_no = line_no; 251 line_no = 1; 252 map_buf = yy_new_buffer(map_fp, YY_BUF_SIZE); 253 main_buf = YY_CURRENT_BUFFER; 254 yy_switch_to_buffer(map_buf); 255 ptr = buf; 256 BEGIN(defn); 257} 258<charmap>\n { 259 errx(EX_UNAVAILABLE, "'charmap' file name expected near line %u", 260 line_no); 261} 262<charmap><<EOF>> { 263 errx(EX_UNAVAILABLE, "'charmap' file name expected near line %u", 264 line_no); 265} 266<INITIAL,defn><<EOF>> { 267 if(map_fp != NULL) { 268 if (ptr != buf) 269 errx(EX_UNAVAILABLE, "premature EOF in the map near line %u of %s", line_no, map_name); 270 yy_switch_to_buffer(main_buf); 271 yy_delete_buffer(map_buf); 272 fclose(map_fp); 273 map_fp = NULL; 274 line_no = save_no; 275 BEGIN(INITIAL); 276 } else 277 yyterminate(); 278} 279%% 280#ifdef FLEX_DEBUG 281main() 282{ 283 while(yylex()) 284 ; 285 return 0; 286} 287#endif /* FLEX_DEBUG */ 288