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