scan.l revision 87517
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
32#ifdef __FBSDID
33__FBSDID("$FreeBSD: head/usr.bin/colldef/scan.l 87517 2001-12-08 02:28:16Z imp $");
34#endif
35
36#include <ctype.h>
37#include <err.h>
38#include <unistd.h>
39#include <string.h>
40#include <sysexits.h>
41#include "collate.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<INITIAL,nchar,subs>\\.      { yylval.ch = yytext[1]; return CHAR; }
70<subs2>\n               {
71	line_no++;
72	BEGIN(INITIAL);
73	return '\n';
74}
75<INITIAL,nchar>\n       {
76	line_no++;
77	if (map_fp != NULL) {
78		ptr = buf;
79		BEGIN(defn);
80	}
81	return '\n';
82}
83<INITIAL>[;,{}()]       return *yytext;
84<INITIAL>substitute     { BEGIN(subs); return SUBSTITUTE; }
85<subs>with              { BEGIN(subs2); return WITH; }
86<INITIAL>order          return ORDER;
87<INITIAL>charmap        BEGIN(charmap);
88<INITIAL>;[ \t]*\.\.\.[ \t]*;   return RANGE;
89<INITIAL,nchar,subs>\\[0-7]{3}       {
90	u_int v;
91
92	sscanf(&yytext[1], "%o", &v);
93	yylval.ch = (u_char)v;
94	return CHAR;
95}
96<INITIAL,nchar,subs>\\x[0-9a-z]{2}   {
97	u_int v;
98
99	sscanf(&yytext[2], "%x", &v);
100	yylval.ch = (u_char)v;
101	return CHAR;
102}
103<INITIAL>[^;,{}() \t\n"<]+      {
104	if(yyleng == 1) {
105		yylval.ch = *yytext;
106		return CHAR;
107	}
108	if(yyleng > BUFSIZE - 1)
109		errx(EX_UNAVAILABLE, "chain buffer overflow near line %u",
110		     line_no);
111	strcpy(yylval.str, yytext);
112	return CHAIN;
113}
114<nchar,subs>.                {
115	yylval.ch = *yytext;
116	return CHAR;
117}
118<defn>^#.*\n            line_no++;
119<defn>[ \t]+            {
120	if (ptr == buf)
121		errx(EX_UNAVAILABLE, "map expected near line %u of %s",
122		     line_no, map_name);
123	*ptr = '\0';
124	strcpy(yylval.str, buf);
125	BEGIN(nchar);
126	return DEFN;
127}
128<name>\/\/              {
129	if(ptr >= buf + sizeof(buf) - 1)
130		errx(EX_UNAVAILABLE, "name buffer overflow near line %u, character '/'",
131		     line_no);
132	*ptr++ = '/';
133}
134<name>\/\>              {
135	if(ptr >= buf + sizeof(buf) - 1)
136		errx(EX_UNAVAILABLE, "name buffer overflow near line %u, character '>'",
137		     line_no);
138	*ptr++ = '>';
139}
140<string>\\\"		{
141	if(ptr >= buf + sizeof(buf) - 1)
142		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\"'",
143		     line_no);
144	*ptr++ = '"';
145}
146<name>\>		{
147	u_int i;
148
149	if (ptr == buf)
150		errx(EX_UNAVAILABLE, "non-empty name expected near line %u",
151		     line_no);
152	*ptr = '\0';
153	for (i = 0; i <= UCHAR_MAX; i++) {
154		if (strcmp(charmap_table[i], buf) == 0)
155			goto findit;
156	}
157	errx(EX_UNAVAILABLE, "name <%s> not 'charmap'-defined near line %u",
158		buf, line_no);
159 findit:
160	yylval.ch = i;
161	if (fromsubs)
162		BEGIN(subs);
163	else
164		BEGIN(INITIAL);
165	return CHAR;
166}
167<string>\"		{
168	*ptr = '\0';
169	strcpy(yylval.str, buf);
170	BEGIN(subs2);
171	return STRING;
172}
173<name,defn>.            {
174	const char *s = (map_fp != NULL) ? map_name : "input";
175
176	if (!isascii(*yytext) || !isprint(*yytext))
177		errx(EX_UNAVAILABLE, "non-ASCII or non-printable character 0x%02x not allowed in the map/name near line %u of %s",
178		     *yytext, line_no, s);
179	if(ptr >= buf + sizeof(buf) - 1)
180		errx(EX_UNAVAILABLE, "map/name buffer overflow near line %u of %s, character '%c'",
181		     line_no, s, *yytext);
182	*ptr++ = *yytext;
183}
184<string>\\t             {
185	if(ptr >= buf + sizeof(buf) - 1)
186		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\t'",
187		     line_no);
188	*ptr++ = '\t';
189}
190<string>\\b             {
191	if(ptr >= buf + sizeof(buf) - 1)
192		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\b'",
193		     line_no);
194	*ptr++ = '\b';
195}
196<string>\\f             {
197	if(ptr >= buf + sizeof(buf) - 1)
198		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\f'",
199		     line_no);
200	*ptr++ = '\f';
201}
202<string>\\v             {
203	if(ptr >= buf + sizeof(buf) - 1)
204		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\v'",
205		     line_no);
206	*ptr++ = '\v';
207}
208<string>\\n             {
209	if(ptr >= buf + sizeof(buf) - 1)
210		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\n'",
211		     line_no);
212	*ptr++ = '\n';
213}
214<string>\\r             {
215	if(ptr >= buf + sizeof(buf) - 1)
216		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\r'",
217		     line_no);
218	*ptr++ = '\r';
219}
220<string>\\a             {
221	if(ptr >= buf + sizeof(buf) - 1)
222		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\a'",
223		     line_no);
224	*ptr++ = '\a';
225}
226<name,string,defn>\n            {
227	const char *s = (map_fp != NULL) ? map_name : "input";
228
229	errx(EX_UNAVAILABLE, "unterminated map/name/string near line %u of %s", line_no, s);
230}
231<name,string,nchar><<EOF>>      {
232	const char *s = (map_fp != NULL) ? map_name : "input";
233
234	errx(EX_UNAVAILABLE, "premature EOF in the name/string/char near line %u of %s", line_no, s);
235}
236<string>\\x[0-9a-f]{2}          {
237	u_int v;
238
239	sscanf(&yytext[2], "%x", &v);
240	*ptr++ = (u_char)v;
241}
242<string>\\[0-7]{3}              {
243	u_int v;
244
245	sscanf(&yytext[1], "%o", &v);
246	*ptr++ = (u_char)v;
247}
248<string>\\.             {
249	if(ptr >= buf + sizeof(buf) - 1)
250		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '%c'",
251		     line_no, yytext[1]);
252	*ptr++ = yytext[1];
253}
254<string>.               {
255	if(ptr >= buf + sizeof(buf) - 1)
256		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '%c'",
257		     line_no, *yytext);
258	*ptr++ = *yytext;
259}
260<charmap>[^ \t\n]+	{
261	strcat(map_name, "/");
262	strcat(map_name, yytext);
263	if((map_fp = fopen(map_name, "r")) == NULL)
264		err(EX_UNAVAILABLE, "can't open 'charmap' file %s",
265		    map_name);
266	save_no = line_no;
267	line_no = 1;
268	map_buf = yy_new_buffer(map_fp, YY_BUF_SIZE);
269	main_buf = YY_CURRENT_BUFFER;
270	yy_switch_to_buffer(map_buf);
271	ptr = buf;
272	BEGIN(defn);
273}
274<charmap>\n             {
275	errx(EX_UNAVAILABLE, "'charmap' file name expected near line %u",
276	     line_no);
277}
278<charmap><<EOF>>        {
279	errx(EX_UNAVAILABLE, "'charmap' file name expected near line %u",
280	     line_no);
281}
282<INITIAL,defn><<EOF>>                 {
283	if(map_fp != NULL) {
284		if (ptr != buf)
285			errx(EX_UNAVAILABLE, "premature EOF in the map near line %u of %s", line_no, map_name);
286		yy_switch_to_buffer(main_buf);
287		yy_delete_buffer(map_buf);
288		fclose(map_fp);
289		map_fp = NULL;
290		line_no = save_no;
291		BEGIN(INITIAL);
292	} else
293		yyterminate();
294}
295%%
296#ifdef FLEX_DEBUG
297main()
298{
299	while(yylex())
300		;
301	return 0;
302}
303#endif /* FLEX_DEBUG */
304