1129468Sru%x string name charmap defn nchar subs subs2
2129468Sru%{
3147647Shmp/*-
4246751Sglebius * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
5137872Srwatson *		at Electronni Visti IA, Kiev, Ukraine.
6129468Sru *			All rights reserved.
7137872Srwatson *
8129468Sru * Redistribution and use in source and binary forms, with or without
9129468Sru * modification, are permitted provided that the following conditions
10129468Sru * are met:
11129468Sru * 1. Redistributions of source code must retain the above copyright
12129468Sru *    notice, this list of conditions and the following disclaimer.
13129468Sru * 2. Redistributions in binary form must reproduce the above copyright
14129468Sru *    notice, this list of conditions and the following disclaimer in the
15129468Sru *    documentation and/or other materials provided with the distribution.
16129468Sru *
17129468Sru * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
18129468Sru * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19129468Sru * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20129468Sru * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
21129468Sru * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22129468Sru * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23175253Smaxim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24129468Sru * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25129468Sru * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26129468Sru * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27129468Sru * SUCH DAMAGE.
28129468Sru */
29129468Sru
30129468Sru#include <sys/cdefs.h>
31129468Sru__FBSDID("$FreeBSD$");
32231564Sed
33129468Sru#include <sys/types.h>
34129468Sru#include <ctype.h>
35129468Sru#include <err.h>
36129468Sru#include <limits.h>
37129468Sru#include <unistd.h>
38129468Sru#include <string.h>
39129468Sru#include <sysexits.h>
40129468Sru#include "common.h"
41129468Sru#include "y.tab.h"
42129468Sru
43129468Sruint line_no = 1, save_no, fromsubs;
44129468Sruu_char buf[BUFSIZE], *ptr;
45129468SruFILE *map_fp;
46129468SruYY_BUFFER_STATE main_buf, map_buf;
47129468Sru#ifdef FLEX_DEBUG
48129468SruYYSTYPE yylval;
49129468Sru#endif /* FLEX_DEBUG */
50129468Sruint yylex(void);
51129468Sru%}
52129468Sru%%
53129468Sru<INITIAL,charmap,nchar,subs,subs2>[ \t]+      ;
54231564Sed<subs2>\"               { ptr = buf; BEGIN(string); }
55129468Sru<subs>\<                { ptr = buf; fromsubs = 1; BEGIN(name); }
56129468Sru<INITIAL>\<             { ptr = buf; fromsubs = 0; BEGIN(name); }
57129468Sru^#.*\n			line_no++;
58129468Sru^\n			line_no++;
59129468Sru<INITIAL>\\\n           line_no++;
60129468Sru<INITIAL,nchar,subs>\\t      { yylval.ch = '\t'; return CHAR; }
61129468Sru<INITIAL,nchar,subs>\\n      { yylval.ch = '\n'; return CHAR; }
62137872Srwatson<INITIAL,nchar,subs>\\b      { yylval.ch = '\b'; return CHAR; }
63137872Srwatson<INITIAL,nchar,subs>\\f      { yylval.ch = '\f'; return CHAR; }
64137872Srwatson<INITIAL,nchar,subs>\\v      { yylval.ch = '\v'; return CHAR; }
65137872Srwatson<INITIAL,nchar,subs>\\r      { yylval.ch = '\r'; return CHAR; }
66137872Srwatson<INITIAL,nchar,subs>\\a      { yylval.ch = '\a'; return CHAR; }
67137872Srwatson<subs2>\n               {
68137872Srwatson	line_no++;
69137953Srwatson	BEGIN(INITIAL);
70137872Srwatson	return '\n';
71137872Srwatson}
72175247Smaxim<INITIAL,nchar>\n       {
73175247Smaxim	line_no++;
74137872Srwatson	if (map_fp != NULL) {
75137872Srwatson		ptr = buf;
76137872Srwatson		BEGIN(defn);
77137872Srwatson	}
78137872Srwatson	return '\n';
79137872Srwatson}
80137872Srwatson<INITIAL>[;,{}()]       return *yytext;
81137953Srwatson<INITIAL>substitute     { BEGIN(subs); return SUBSTITUTE; }
82137953Srwatson<subs>with              { BEGIN(subs2); return WITH; }
83137953Srwatson<INITIAL>order          return ORDER;
84137953Srwatson<INITIAL>charmap        BEGIN(charmap);
85137872Srwatson<INITIAL>;[ \t]*\.\.\.[ \t]*;   return RANGE;
86137872Srwatson<INITIAL,nchar,subs>\\[0-7]{3}       {
87137872Srwatson	u_int v;
88137872Srwatson
89129468Sru	sscanf(&yytext[1], "%o", &v);
90129468Sru	yylval.ch = (u_char)v;
91129468Sru	return CHAR;
92129468Sru}
93129468Sru<INITIAL,nchar,subs>\\x[0-9a-fA-F]{2}   {
94129468Sru	u_int v;
95129468Sru
96129468Sru	sscanf(&yytext[2], "%x", &v);
97129468Sru	yylval.ch = (u_char)v;
98129468Sru	return CHAR;
99129468Sru}
100129468Sru<INITIAL,nchar,subs>\\. { yylval.ch = yytext[1]; return CHAR; }
101129468Sru<INITIAL,nchar,subs>.   { yylval.ch = *yytext; return CHAR; }
102129468Sru<defn>^#.*\n            line_no++;
103231564Sed<defn>[ \t]+            {
104231564Sed	if (ptr == buf)
105231564Sed		errx(EX_UNAVAILABLE, "map expected near line %u of %s",
106129468Sru		     line_no, map_name);
107129468Sru	*ptr = '\0';
108129468Sru	strcpy(yylval.str, buf);
109129468Sru	BEGIN(nchar);
110129468Sru	return DEFN;
111129468Sru}
112129468Sru<name>\/\/              {
113129468Sru	if(ptr >= buf + sizeof(buf) - 1)
114129468Sru		errx(EX_UNAVAILABLE, "name buffer overflow near line %u, character '/'",
115129468Sru		     line_no);
116129468Sru	*ptr++ = '/';
117129468Sru}
118129468Sru<name>\/\>              {
119129468Sru	if(ptr >= buf + sizeof(buf) - 1)
120129468Sru		errx(EX_UNAVAILABLE, "name buffer overflow near line %u, character '>'",
121129468Sru		     line_no);
122129468Sru	*ptr++ = '>';
123136347Sglebius}
124140140Sru<string>\\\"		{
125129468Sru	if(ptr >= buf + sizeof(buf) - 1)
126129468Sru		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\"'",
127129468Sru		     line_no);
128129468Sru	*ptr++ = '"';
129129468Sru}
130129468Sru<name>\>		{
131129468Sru	u_int i;
132129468Sru
133129468Sru	if (ptr == buf)
134129468Sru		errx(EX_UNAVAILABLE, "non-empty name expected near line %u",
135129468Sru		     line_no);
136129468Sru	*ptr = '\0';
137129468Sru	for (i = 0; i <= UCHAR_MAX; i++) {
138129468Sru		if (strcmp(charmap_table[i], buf) == 0)
139129468Sru			goto findit;
140129468Sru	}
141129468Sru	errx(EX_UNAVAILABLE, "name <%s> not 'charmap'-defined near line %u",
142129468Sru		buf, line_no);
143129468Sru findit:
144129468Sru	yylval.ch = i;
145129468Sru	if (fromsubs)
146129468Sru		BEGIN(subs);
147129468Sru	else
148129468Sru		BEGIN(INITIAL);
149129468Sru	return CHAR;
150129468Sru}
151129468Sru<string>\"		{
152129468Sru	*ptr = '\0';
153129468Sru	strcpy(yylval.str, buf);
154129468Sru	BEGIN(subs2);
155129468Sru	return STRING;
156129468Sru}
157129468Sru<name,defn>.            {
158129468Sru	const char *s = (map_fp != NULL) ? map_name : "input";
159129468Sru
160129468Sru	if (!isascii(*yytext) || !isprint(*yytext))
161129468Sru		errx(EX_UNAVAILABLE, "non-ASCII or non-printable character 0x%02x not allowed in the map/name near line %u of %s",
162129468Sru		     *yytext, line_no, s);
163129468Sru	if(ptr >= buf + sizeof(buf) - 1)
164129468Sru		errx(EX_UNAVAILABLE, "map/name buffer overflow near line %u of %s, character '%c'",
165129468Sru		     line_no, s, *yytext);
166129468Sru	*ptr++ = *yytext;
167129468Sru}
168129468Sru<string>\\t             {
169129468Sru	if(ptr >= buf + sizeof(buf) - 1)
170129468Sru		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\t'",
171129468Sru		     line_no);
172129468Sru	*ptr++ = '\t';
173129468Sru}
174129468Sru<string>\\b             {
175129468Sru	if(ptr >= buf + sizeof(buf) - 1)
176129468Sru		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\b'",
177129468Sru		     line_no);
178129468Sru	*ptr++ = '\b';
179129468Sru}
180129468Sru<string>\\f             {
181129468Sru	if(ptr >= buf + sizeof(buf) - 1)
182129468Sru		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\f'",
183129468Sru		     line_no);
184129468Sru	*ptr++ = '\f';
185129468Sru}
186129468Sru<string>\\v             {
187129468Sru	if(ptr >= buf + sizeof(buf) - 1)
188129468Sru		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\v'",
189129468Sru		     line_no);
190129468Sru	*ptr++ = '\v';
191129468Sru}
192129468Sru<string>\\n             {
193129468Sru	if(ptr >= buf + sizeof(buf) - 1)
194129468Sru		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\n'",
195129468Sru		     line_no);
196129468Sru	*ptr++ = '\n';
197129468Sru}
198129468Sru<string>\\r             {
199129468Sru	if(ptr >= buf + sizeof(buf) - 1)
200129468Sru		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\r'",
201129468Sru		     line_no);
202129468Sru	*ptr++ = '\r';
203129468Sru}
204129468Sru<string>\\a             {
205129468Sru	if(ptr >= buf + sizeof(buf) - 1)
206129468Sru		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '\\a'",
207129468Sru		     line_no);
208129468Sru	*ptr++ = '\a';
209129468Sru}
210129468Sru<name,string,defn>\n            {
211129468Sru	const char *s = (map_fp != NULL) ? map_name : "input";
212129468Sru
213129468Sru	errx(EX_UNAVAILABLE, "unterminated map/name/string near line %u of %s", line_no, s);
214129468Sru}
215129468Sru<name,string,nchar><<EOF>>      {
216129468Sru	const char *s = (map_fp != NULL) ? map_name : "input";
217129468Sru
218129468Sru	errx(EX_UNAVAILABLE, "premature EOF in the name/string/char near line %u of %s", line_no, s);
219129468Sru}
220129468Sru<string>\\x[0-9a-f]{2}          {
221129468Sru	u_int v;
222129468Sru
223129468Sru	sscanf(&yytext[2], "%x", &v);
224129468Sru	*ptr++ = (u_char)v;
225129468Sru}
226136347Sglebius<string>\\[0-7]{3}              {
227136347Sglebius	u_int v;
228136347Sglebius
229140140Sru	sscanf(&yytext[1], "%o", &v);
230140140Sru	*ptr++ = (u_char)v;
231140140Sru}
232136347Sglebius<string>\\.             {
233129468Sru	if(ptr >= buf + sizeof(buf) - 1)
234129468Sru		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '%c'",
235129468Sru		     line_no, yytext[1]);
236129468Sru	*ptr++ = yytext[1];
237129468Sru}
238129468Sru<string>.               {
239129468Sru	if(ptr >= buf + sizeof(buf) - 1)
240129468Sru		errx(EX_UNAVAILABLE, "string buffer overflow near line %u, character '%c'",
241129468Sru		     line_no, *yytext);
242129468Sru	*ptr++ = *yytext;
243129468Sru}
244129468Sru<charmap>[^ \t\n]+	{
245129468Sru	strcat(map_name, "/");
246129468Sru	strcat(map_name, yytext);
247129468Sru	if((map_fp = fopen(map_name, "r")) == NULL)
248129468Sru		err(EX_UNAVAILABLE, "can't open 'charmap' file %s",
249129468Sru		    map_name);
250129468Sru	save_no = line_no;
251129468Sru	line_no = 1;
252129468Sru	map_buf = yy_new_buffer(map_fp, YY_BUF_SIZE);
253129468Sru	main_buf = YY_CURRENT_BUFFER;
254129468Sru	yy_switch_to_buffer(map_buf);
255129468Sru	ptr = buf;
256129468Sru	BEGIN(defn);
257129468Sru}
258129468Sru<charmap>\n             {
259129468Sru	errx(EX_UNAVAILABLE, "'charmap' file name expected near line %u",
260129468Sru	     line_no);
261129468Sru}
262129468Sru<charmap><<EOF>>        {
263129468Sru	errx(EX_UNAVAILABLE, "'charmap' file name expected near line %u",
264129468Sru	     line_no);
265129468Sru}
266129468Sru<INITIAL,defn><<EOF>>                 {
267129468Sru	if(map_fp != NULL) {
268129468Sru		if (ptr != buf)
269129468Sru			errx(EX_UNAVAILABLE, "premature EOF in the map near line %u of %s", line_no, map_name);
270129468Sru		yy_switch_to_buffer(main_buf);
271129468Sru		yy_delete_buffer(map_buf);
272129468Sru		fclose(map_fp);
273129468Sru		map_fp = NULL;
274129468Sru		line_no = save_no;
275129468Sru		BEGIN(INITIAL);
276129468Sru	} else
277129468Sru		yyterminate();
278129468Sru}
279129468Sru%%
280129468Sru#ifdef FLEX_DEBUG
281129468Srumain()
282129468Sru{
283129468Sru	while(yylex())
284129468Sru		;
285129468Sru	return 0;
286129468Sru}
287#endif /* FLEX_DEBUG */
288