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