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