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