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