scan.l revision 102299
1117397Skan%x string name charmap defn nchar subs subs2
2117397Skan%{
3169691Skan/*-
4117397Skan * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
5117397Skan *		at Electronni Visti IA, Kiev, Ukraine.
6117397Skan *			All rights reserved.
7117397Skan *
8117397Skan * Redistribution and use in source and binary forms, with or without
9117397Skan * modification, are permitted provided that the following conditions
10117397Skan * are met:
11117397Skan * 1. Redistributions of source code must retain the above copyright
12117397Skan *    notice, this list of conditions and the following disclaimer.
13117397Skan * 2. Redistributions in binary form must reproduce the above copyright
14117397Skan *    notice, this list of conditions and the following disclaimer in the
15117397Skan *    documentation and/or other materials provided with the distribution.
16117397Skan *
17117397Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
18169691Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19117397Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20117397Skan * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
21117397Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22117397Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23117397Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24117397Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25117397Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26117397Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27117397Skan * SUCH DAMAGE.
28117397Skan */
29117397Skan
30169691Skan#include <sys/cdefs.h>
31117397Skan__FBSDID("$FreeBSD: head/usr.bin/colldef/scan.l 102299 2002-08-23 04:18:26Z ache $");
32169691Skan
33169691Skan#include <ctype.h>
34132720Skan#include <err.h>
35132720Skan#include <limits.h>
36132720Skan#include <unistd.h>
37132720Skan#include <string.h>
38132720Skan#include <sysexits.h>
39132720Skan#include "common.h"
40132720Skan#include "y.tab.h"
41132720Skan
42132720Skanint line_no = 1, save_no, fromsubs;
43132720Skanu_char buf[BUFSIZE], *ptr;
44132720SkanFILE *map_fp;
45132720SkanYY_BUFFER_STATE main_buf, map_buf;
46132720Skan#ifdef FLEX_DEBUG
47132720SkanYYSTYPE yylval;
48132720Skan#endif /* FLEX_DEBUG */
49132720Skanint yylex(void);
50132720Skan%}
51132720Skan%%
52117397Skan<INITIAL,charmap,nchar,subs,subs2>[ \t]+      ;
53169691Skan<subs2>\"               { ptr = buf; BEGIN(string); }
54169691Skan<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<subs2>\n               {
67	line_no++;
68	BEGIN(INITIAL);
69	return '\n';
70}
71<INITIAL,nchar>\n       {
72	line_no++;
73	if (map_fp != NULL) {
74		ptr = buf;
75		BEGIN(defn);
76	}
77	return '\n';
78}
79<INITIAL>[;,{}()]       return *yytext;
80<INITIAL>substitute     { BEGIN(subs); return SUBSTITUTE; }
81<subs>with              { BEGIN(subs2); return WITH; }
82<INITIAL>order          return ORDER;
83<INITIAL>charmap        BEGIN(charmap);
84<INITIAL>;[ \t]*\.\.\.[ \t]*;   return RANGE;
85<INITIAL,nchar,subs>\\[0-7]{3}       {
86	u_int v;
87
88	sscanf(&yytext[1], "%o", &v);
89	yylval.ch = (u_char)v;
90	return CHAR;
91}
92<INITIAL,nchar,subs>\\x[0-9a-fA-F]{2}   {
93	u_int v;
94
95	sscanf(&yytext[2], "%x", &v);
96	yylval.ch = (u_char)v;
97	return CHAR;
98}
99<INITIAL,nchar,subs>\\. { yylval.ch = yytext[1]; return CHAR; }
100<INITIAL,nchar,subs>.   { yylval.ch = *yytext; return CHAR; }
101<defn>^#.*\n            line_no++;
102<defn>[ \t]+            {
103	if (ptr == buf)
104		errx(EX_UNAVAILABLE, "map expected near line %u of %s",
105		     line_no, map_name);
106	*ptr = '\0';
107	strcpy(yylval.str, buf);
108	BEGIN(nchar);
109	return DEFN;
110}
111<name>\/\/              {
112	if(ptr >= buf + sizeof(buf) - 1)
113		errx(EX_UNAVAILABLE, "name buffer overflow near line %u, character '/'",
114		     line_no);
115	*ptr++ = '/';
116}
117<name>\/\>              {
118	if(ptr >= buf + sizeof(buf) - 1)
119		errx(EX_UNAVAILABLE, "name buffer overflow near line %u, character '>'",
120		     line_no);
121	*ptr++ = '>';
122}
123<string>\\\"		{
124	if(ptr >= buf + sizeof(buf) - 1)
125		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\"'",
126		     line_no);
127	*ptr++ = '"';
128}
129<name>\>		{
130	u_int i;
131
132	if (ptr == buf)
133		errx(EX_UNAVAILABLE, "non-empty name expected near line %u",
134		     line_no);
135	*ptr = '\0';
136	for (i = 0; i <= UCHAR_MAX; i++) {
137		if (strcmp(charmap_table[i], buf) == 0)
138			goto findit;
139	}
140	errx(EX_UNAVAILABLE, "name <%s> not 'charmap'-defined near line %u",
141		buf, line_no);
142 findit:
143	yylval.ch = i;
144	if (fromsubs)
145		BEGIN(subs);
146	else
147		BEGIN(INITIAL);
148	return CHAR;
149}
150<string>\"		{
151	*ptr = '\0';
152	strcpy(yylval.str, buf);
153	BEGIN(subs2);
154	return STRING;
155}
156<name,defn>.            {
157	const char *s = (map_fp != NULL) ? map_name : "input";
158
159	if (!isascii(*yytext) || !isprint(*yytext))
160		errx(EX_UNAVAILABLE, "non-ASCII or non-printable character 0x%02x not allowed in the map/name near line %u of %s",
161		     *yytext, line_no, s);
162	if(ptr >= buf + sizeof(buf) - 1)
163		errx(EX_UNAVAILABLE, "map/name buffer overflow near line %u of %s, character '%c'",
164		     line_no, s, *yytext);
165	*ptr++ = *yytext;
166}
167<string>\\t             {
168	if(ptr >= buf + sizeof(buf) - 1)
169		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\t'",
170		     line_no);
171	*ptr++ = '\t';
172}
173<string>\\b             {
174	if(ptr >= buf + sizeof(buf) - 1)
175		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\b'",
176		     line_no);
177	*ptr++ = '\b';
178}
179<string>\\f             {
180	if(ptr >= buf + sizeof(buf) - 1)
181		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\f'",
182		     line_no);
183	*ptr++ = '\f';
184}
185<string>\\v             {
186	if(ptr >= buf + sizeof(buf) - 1)
187		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\v'",
188		     line_no);
189	*ptr++ = '\v';
190}
191<string>\\n             {
192	if(ptr >= buf + sizeof(buf) - 1)
193		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\n'",
194		     line_no);
195	*ptr++ = '\n';
196}
197<string>\\r             {
198	if(ptr >= buf + sizeof(buf) - 1)
199		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\r'",
200		     line_no);
201	*ptr++ = '\r';
202}
203<string>\\a             {
204	if(ptr >= buf + sizeof(buf) - 1)
205		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\a'",
206		     line_no);
207	*ptr++ = '\a';
208}
209<name,string,defn>\n            {
210	const char *s = (map_fp != NULL) ? map_name : "input";
211
212	errx(EX_UNAVAILABLE, "unterminated map/name/string near line %u of %s", line_no, s);
213}
214<name,string,nchar><<EOF>>      {
215	const char *s = (map_fp != NULL) ? map_name : "input";
216
217	errx(EX_UNAVAILABLE, "premature EOF in the name/string/char near line %u of %s", line_no, s);
218}
219<string>\\x[0-9a-f]{2}          {
220	u_int v;
221
222	sscanf(&yytext[2], "%x", &v);
223	*ptr++ = (u_char)v;
224}
225<string>\\[0-7]{3}              {
226	u_int v;
227
228	sscanf(&yytext[1], "%o", &v);
229	*ptr++ = (u_char)v;
230}
231<string>\\.             {
232	if(ptr >= buf + sizeof(buf) - 1)
233		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '%c'",
234		     line_no, yytext[1]);
235	*ptr++ = yytext[1];
236}
237<string>.               {
238	if(ptr >= buf + sizeof(buf) - 1)
239		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '%c'",
240		     line_no, *yytext);
241	*ptr++ = *yytext;
242}
243<charmap>[^ \t\n]+	{
244	strcat(map_name, "/");
245	strcat(map_name, yytext);
246	if((map_fp = fopen(map_name, "r")) == NULL)
247		err(EX_UNAVAILABLE, "can't open 'charmap' file %s",
248		    map_name);
249	save_no = line_no;
250	line_no = 1;
251	map_buf = yy_new_buffer(map_fp, YY_BUF_SIZE);
252	main_buf = YY_CURRENT_BUFFER;
253	yy_switch_to_buffer(map_buf);
254	ptr = buf;
255	BEGIN(defn);
256}
257<charmap>\n             {
258	errx(EX_UNAVAILABLE, "'charmap' file name expected near line %u",
259	     line_no);
260}
261<charmap><<EOF>>        {
262	errx(EX_UNAVAILABLE, "'charmap' file name expected near line %u",
263	     line_no);
264}
265<INITIAL,defn><<EOF>>                 {
266	if(map_fp != NULL) {
267		if (ptr != buf)
268			errx(EX_UNAVAILABLE, "premature EOF in the map near line %u of %s", line_no, map_name);
269		yy_switch_to_buffer(main_buf);
270		yy_delete_buffer(map_buf);
271		fclose(map_fp);
272		map_fp = NULL;
273		line_no = save_no;
274		BEGIN(INITIAL);
275	} else
276		yyterminate();
277}
278%%
279#ifdef FLEX_DEBUG
280main()
281{
282	while(yylex())
283		;
284	return 0;
285}
286#endif /* FLEX_DEBUG */
287