scan.l revision 23012
138774Snsouch%x string name charmap defn nchar subs
293023Snsouch%{
338774Snsouch/*-
438774Snsouch * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
538774Snsouch *		at Electronni Visti IA, Kiev, Ukraine.
638774Snsouch *			All rights reserved.
738774Snsouch *
838774Snsouch * Redistribution and use in source and binary forms, with or without
938774Snsouch * modification, are permitted provided that the following conditions
1038774Snsouch * are met:
1138774Snsouch * 1. Redistributions of source code must retain the above copyright
1238774Snsouch *    notice, this list of conditions and the following disclaimer.
1338774Snsouch * 2. Redistributions in binary form must reproduce the above copyright
1438774Snsouch *    notice, this list of conditions and the following disclaimer in the
1538774Snsouch *    documentation and/or other materials provided with the distribution.
1638774Snsouch *
1738774Snsouch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
1838774Snsouch * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1938774Snsouch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2038774Snsouch * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
2138774Snsouch * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2238774Snsouch * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2338774Snsouch * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2438774Snsouch * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2538774Snsouch * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2638774Snsouch * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27119418Sobrien * SUCH DAMAGE.
28119418Sobrien *
29119418Sobrien * $Id$
3038774Snsouch */
3138774Snsouch
3238774Snsouch#include <ctype.h>
3338774Snsouch#include <err.h>
3438774Snsouch#include <unistd.h>
3538774Snsouch#include <string.h>
3638774Snsouch#include <sysexits.h>
3738774Snsouch#include "collate.h"
3838774Snsouch#include "y.tab.h"
3938774Snsouch
4038774Snsouchint line_no = 1, save_no;
4138774Snsouchu_char buf[STR_LEN], *ptr;
4238774SnsouchFILE *map_fp;
4338774Snsouchextern char map_name[];
4438774Snsouchextern u_char charmap_table[UCHAR_MAX + 1][STR_LEN];
4538774SnsouchYY_BUFFER_STATE main_buf, map_buf;
4638774Snsouch#ifdef FLEX_DEBUG
4738774SnsouchYYSTYPE yylval;
4838774Snsouch#endif /* FLEX_DEBUG */
4938774Snsouch%}
5038774Snsouch%%
5138774Snsouch<INITIAL,charmap,nchar,subs>[ \t]+      ;
5238774Snsouch<subs>\"                { ptr = buf; BEGIN(string); }
5338774Snsouch<INITIAL>\<             { ptr = buf; BEGIN(name); }
5438774Snsouch^#.*\n			line_no++;
5538774Snsouch^\n			line_no++;
5638774Snsouch<INITIAL>\\\n           line_no++;
5738774Snsouch<INITIAL,nchar>\\t      { yylval.ch = '\t'; return CHAR; }
5838774Snsouch<INITIAL,nchar>\\n      { yylval.ch = '\n'; return CHAR; }
5938774Snsouch<INITIAL,nchar>\\b      { yylval.ch = '\b'; return CHAR; }
6038774Snsouch<INITIAL,nchar>\\f      { yylval.ch = '\f'; return CHAR; }
6138774Snsouch<INITIAL,nchar>\\v      { yylval.ch = '\v'; return CHAR; }
6238774Snsouch<INITIAL,nchar>\\r      { yylval.ch = '\r'; return CHAR; }
6338774Snsouch<INITIAL,nchar>\\a      { yylval.ch = '\a'; return CHAR; }
6438774Snsouch<INITIAL,nchar>\\.      { yylval.ch = yytext[1]; return CHAR; }
6538774Snsouch<subs>\n                {
6638774Snsouch	line_no++;
6793023Snsouch	BEGIN(INITIAL);
6893023Snsouch	return '\n';
69123922Ssam}
7038774Snsouch<INITIAL,nchar>\n       {
7138774Snsouch	line_no++;
7238774Snsouch	if (map_fp != NULL) {
73147256Sbrooks		ptr = buf;
7438774Snsouch		BEGIN(defn);
7538774Snsouch	}
7638774Snsouch	return '\n';
7738774Snsouch}
7838774Snsouch<INITIAL>[;,{}()]       return *yytext;
7938774Snsouch<INITIAL>substitute     { BEGIN(subs); return SUBSTITUTE; }
8038774Snsouch<subs>with              return WITH;
8138774Snsouch<INITIAL>order          return ORDER;
8238774Snsouch<INITIAL>charmap        BEGIN(charmap);
8338774Snsouch<INITIAL>;[ \t]*\.\.\.[ \t]*;   return RANGE;
8438774Snsouch<INITIAL,nchar>\\[0-7]{3}       {
8538774Snsouch	u_int v;
8638774Snsouch
8738774Snsouch	sscanf(&yytext[1], "%o", &v);
8838774Snsouch	yylval.ch = (u_char)v;
8938774Snsouch	return CHAR;
9038774Snsouch}
9138774Snsouch<INITIAL,nchar>\\x[0-9a-z]{2}   {
9238774Snsouch	u_int v;
9338774Snsouch
9438774Snsouch	sscanf(&yytext[2], "%x", &v);
9538774Snsouch	yylval.ch = (u_char)v;
9638774Snsouch	return CHAR;
9738774Snsouch}
9838774Snsouch<INITIAL>[^;,{}() \t\n"<]+      {
9938774Snsouch	if(yyleng == 1) {
10038774Snsouch		yylval.ch = *yytext;
10138774Snsouch		return CHAR;
10238774Snsouch	}
10338774Snsouch	if(yyleng > STR_LEN - 1)
10438774Snsouch		errx(EX_UNAVAILABLE, "chain buffer overflaw near line %u",
10538774Snsouch		     line_no);
10638774Snsouch	strcpy(yylval.str, yytext);
10738774Snsouch	return CHAIN;
10838774Snsouch}
10938774Snsouch<nchar>.                {
11038774Snsouch	yylval.ch = *yytext;
11138774Snsouch	return CHAR;
11238774Snsouch}
11338774Snsouch<defn>[ \t]+            {
11438774Snsouch	if (ptr == buf)
11538774Snsouch		errx(EX_UNAVAILABLE, "map expected near line %u of %s",
11638774Snsouch		     line_no, map_name);
11738774Snsouch	*ptr = '\0';
11838774Snsouch	strcpy(yylval.str, buf);
11938774Snsouch	BEGIN(nchar);
12038774Snsouch	return DEFN;
12138774Snsouch}
12238774Snsouch<name>\/\/              {
12338774Snsouch	if(ptr >= buf + sizeof(buf) - 1)
12438774Snsouch		errx(EX_UNAVAILABLE, "name buffer overflaw near line %u, character '/'",
12538774Snsouch		     line_no);
12638774Snsouch	*ptr++ = '/';
12738774Snsouch}
12838774Snsouch<name>\/\>              {
12938774Snsouch	if(ptr >= buf + sizeof(buf) - 1)
13038774Snsouch		errx(EX_UNAVAILABLE, "name buffer overflaw near line %u, character '>'",
13138774Snsouch		     line_no);
132147256Sbrooks	*ptr++ = '>';
13338774Snsouch}
134147256Sbrooks<string>\\\"		{
135147256Sbrooks	if(ptr >= buf + sizeof(buf) - 1)
136147256Sbrooks		errx(EX_UNAVAILABLE, "string buffer overflaw near line %u, character '\"'",
137147256Sbrooks		     line_no);
138147256Sbrooks	*ptr++ = '"';
13993023Snsouch}
14038774Snsouch<name>\>		{
14138774Snsouch	u_int i;
142121816Sbrooks
14338774Snsouch	if (ptr == buf)
144133690Srwatson		errx(EX_UNAVAILABLE, "non-empty name expected near line %u",
145133690Srwatson		     line_no);
14638774Snsouch	*ptr = '\0';
14738774Snsouch	for (i = 0; i <= UCHAR_MAX; i++)
14838774Snsouch		if (strcmp(charmap_table[i], buf) == 0)
14938774Snsouch			goto findit;
15038774Snsouch	errx(EX_UNAVAILABLE, "name <%s> not 'charmap'-defined near line %u",
15138774Snsouch		buf, line_no);
15238774Snsouch	findit:
15338774Snsouch	yylval.ch = i;
15438774Snsouch	BEGIN(INITIAL);
15538774Snsouch	return CHAR;
15638774Snsouch}
15738774Snsouch<string>\"		{
15838774Snsouch	*ptr = '\0';
15938774Snsouch	strcpy(yylval.str, buf);
16038774Snsouch	BEGIN(subs);
16138774Snsouch	return STRING;
16238774Snsouch}
16338774Snsouch<name,defn>.            {
16438774Snsouch	char *s = (map_fp != NULL) ? map_name : "input";
165121816Sbrooks
16638774Snsouch	if (!isascii(*yytext) || !isprint(*yytext))
16738774Snsouch		errx(EX_UNAVAILABLE, "non-ASCII or non-printable character 0x%02x not allowed in the map/name near line %u of %s",
16838774Snsouch		     *yytext, line_no, s);
16938774Snsouch	if(ptr >= buf + sizeof(buf) - 1)
17038774Snsouch		errx(EX_UNAVAILABLE, "map/name buffer overflaw near line %u of %s, character '%c'",
17138774Snsouch		     line_no, s, *yytext);
17238774Snsouch	*ptr++ = *yytext;
17338774Snsouch}
17438774Snsouch<string>\\t             {
17538774Snsouch	if(ptr >= buf + sizeof(buf) - 1)
17638774Snsouch		errx(EX_UNAVAILABLE, "string buffer overflaw near line %u, character '\\t'",
17738774Snsouch		     line_no);
17838774Snsouch	*ptr++ = '\t';
17938774Snsouch}
18038774Snsouch<string>\\b             {
18138774Snsouch	if(ptr >= buf + sizeof(buf) - 1)
18238774Snsouch		errx(EX_UNAVAILABLE, "string buffer overflaw near line %u, character '\\b'",
18338774Snsouch		     line_no);
18438774Snsouch	*ptr++ = '\b';
18538774Snsouch}
18638774Snsouch<string>\\f             {
18738774Snsouch	if(ptr >= buf + sizeof(buf) - 1)
18838774Snsouch		errx(EX_UNAVAILABLE, "string buffer overflaw near line %u, character '\\f'",
18938774Snsouch		     line_no);
19038774Snsouch	*ptr++ = '\f';
19138774Snsouch}
19238774Snsouch<string>\\v             {
19338774Snsouch	if(ptr >= buf + sizeof(buf) - 1)
19438774Snsouch		errx(EX_UNAVAILABLE, "string buffer overflaw near line %u, character '\\v'",
19538774Snsouch		     line_no);
19638774Snsouch	*ptr++ = '\v';
19738774Snsouch}
19838774Snsouch<string>\\n             {
199147256Sbrooks	if(ptr >= buf + sizeof(buf) - 1)
200111119Simp		errx(EX_UNAVAILABLE, "string buffer overflaw near line %u, character '\\n'",
20138774Snsouch		     line_no);
20238774Snsouch	*ptr++ = '\n';
20338774Snsouch}
20438774Snsouch<string>\\r             {
20538774Snsouch	if(ptr >= buf + sizeof(buf) - 1)
206147256Sbrooks		errx(EX_UNAVAILABLE, "string buffer overflaw near line %u, character '\\r'",
207111119Simp		     line_no);
20838774Snsouch	*ptr++ = '\r';
20938774Snsouch}
21038774Snsouch<string>\\a             {
21138774Snsouch	if(ptr >= buf + sizeof(buf) - 1)
21238774Snsouch		errx(EX_UNAVAILABLE, "string buffer overflaw near line %u, character '\\a'",
21340782Snsouch		     line_no);
21438774Snsouch	*ptr++ = '\a';
21538774Snsouch}
21638774Snsouch<name,string,defn>\n            {
21738774Snsouch	char *s = (map_fp != NULL) ? map_name : "input";
21838774Snsouch
21938774Snsouch	errx(EX_UNAVAILABLE, "unterminated map/name/string near line %u of %s", line_no, s);
22038774Snsouch}
22138774Snsouch<name,string,nchar><<EOF>>      {
22238774Snsouch	char *s = (map_fp != NULL) ? map_name : "input";
22338774Snsouch
22438774Snsouch	errx(EX_UNAVAILABLE, "premature EOF in the name/string/char near line %u of %s", line_no, s);
22538774Snsouch}
22638774Snsouch<string>\\x[0-9a-f]{2}          {
22738774Snsouch	u_int v;
22838774Snsouch
22938774Snsouch	sscanf(&yytext[2], "%x", &v);
23038774Snsouch	*ptr++ = (u_char)v;
23138774Snsouch}
23238774Snsouch<string>\\[0-7]{3}              {
23338774Snsouch	u_int v;
23438774Snsouch
23538774Snsouch	sscanf(&yytext[1], "%o", &v);
23638774Snsouch	*ptr++ = (u_char)v;
23738774Snsouch}
23838774Snsouch<string>\\.             {
23938774Snsouch	if(ptr >= buf + sizeof(buf) - 1)
24038774Snsouch		errx(EX_UNAVAILABLE, "string buffer overflaw near line %u, character '%c'",
24138774Snsouch		     line_no, yytext[1]);
24238774Snsouch	*ptr++ = yytext[1];
24338774Snsouch}
24438774Snsouch<string>.               {
24538774Snsouch	if(ptr >= buf + sizeof(buf) - 1)
24638774Snsouch		errx(EX_UNAVAILABLE, "string buffer overflaw near line %u, character '%c'",
24738774Snsouch		     line_no, *yytext);
24838774Snsouch	*ptr++ = *yytext;
24938774Snsouch}
25038774Snsouch<charmap>[^ \t\n]+	{
25138774Snsouch	strcat(map_name, "/");
252147256Sbrooks	strcat(map_name, yytext);
25338774Snsouch	if((map_fp = fopen(map_name, "r")) == NULL)
25438774Snsouch		err(EX_UNAVAILABLE, "can't open 'charmap' file %s",
25538774Snsouch		    map_name);
256147256Sbrooks	save_no = line_no;
25738774Snsouch	line_no = 1;
25838774Snsouch	map_buf = yy_new_buffer(map_fp, YY_BUF_SIZE);
25938774Snsouch	main_buf = YY_CURRENT_BUFFER;
26038774Snsouch	yy_switch_to_buffer(map_buf);
26138774Snsouch	ptr = buf;
26238774Snsouch	BEGIN(defn);
26338774Snsouch}
26438774Snsouch<charmap>\n             {
26538774Snsouch	errx(EX_UNAVAILABLE, "'charmap' file name expected near line %u",
26638774Snsouch	     line_no);
26738774Snsouch}
26838774Snsouch<charmap><<EOF>>        {
26938774Snsouch	errx(EX_UNAVAILABLE, "'charmap' file name expected near line %u",
27038774Snsouch	     line_no);
27138774Snsouch}
27238774Snsouch<INITIAL,defn><<EOF>>                 {
27338774Snsouch	if(map_fp != NULL) {
27438774Snsouch		if (ptr != buf)
27538774Snsouch			errx(EX_UNAVAILABLE, "premature EOF in the map near line %u of %s", line_no, map_name);
27638774Snsouch		yy_switch_to_buffer(main_buf);
27738774Snsouch		yy_delete_buffer(map_buf);
27838774Snsouch		fclose(map_fp);
27938774Snsouch		map_fp = NULL;
28038774Snsouch		line_no = save_no;
28138774Snsouch		BEGIN(INITIAL);
28238774Snsouch	} else
28338774Snsouch		yyterminate();
28438774Snsouch}
28538774Snsouch%%
28638774Snsouch#ifdef FLEX_DEBUG
28738774Snsouchmain()
28838774Snsouch{
28938774Snsouch	while(yylex())
29038774Snsouch		;
29138774Snsouch	return 0;
29238774Snsouch}
29338774Snsouch#endif /* FLEX_DEBUG */
29438774Snsouch