xref: /freebsd-12.1/usr.bin/colldef/scan.l (revision 1de7b4b8)
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