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 <alex@elvisti.kiev.ua> 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 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<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 283main() 284{ 285 while(yylex()) 286 ; 287 return 0; 288} 289#endif /* FLEX_DEBUG */ 290