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