
/*	Copyright (c) 1984 AT&T	*/
/*	  All Rights Reserved  	*/

/*	THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T	*/
/*	The copyright notice above does not evidence any   	*/
/*	actual or intended publication of such source code.	*/

#ident "$Header: scan.l 1.1 89/10/09 $@(#)nls:scan.l	1.1 88/01/06 AT&T UEL"

%{
/* Preprocessor Statements */
#include "colltbl.h"
#define ESIZE		BUFSIZ
#define INIT		register char *sp = instring;
#define GETC()		(*sp++)
#define PEEKC()		(*sp)
#define UNGETC(c)	(--sp)
#define RETURN(c)	return(c)
#define ERROR(c)	{ regerr(c); return((char *) NULL); }
#include <regexp.h>

#define SAVE(x)	{ s = (char *) malloc(strlen(x)+1); strcpy(s,x); yylval = (int) s; }
#define SAVE_RE(x) { s = (char *) malloc(re_len + 1); memcpy(s, x, re_len); s[re_len] = '\0'; yylval = (int) s; }
#define RET(x)		{ DEBUG((stderr,"yytext=%s\tyylval=%d (%s) return=%d\n",yytext,yylval,yylval,x)); return(x); }
#define CADD(x)		{ DEBUG((stderr,"Adding %c to cbuf\n", x)); cbuf[clen++]=x; if(clen>=BUFSIZ){error(TOO_LONG,cbuf);BEGIN A;} }
#define IADD		CADD((int) strtol(yytext, (char **) NULL, 0));

/* External Variables */
extern	int Lineno, yylval, yydebug;
extern	int	regexp_flag;

/* Global Variables */
char	cbuf[BUFSIZ], ebuf[ESIZE], *s;
int	clen;
int	re_len;
char	*rep;
%}
%Start A STR RE1 RE2 LIST LIST1 LC

AL	[a-zA-Z]
D	[0-9]
O	[0-7]
ALN	[a-zA-Z0-9]
WS	[ \t]
H	[a-fA-F0-9]

%%
"\\"\n			{ Lineno++; }

<A>\n			{ Lineno++; }
<A>{WS}+		{ ; }
<A>#.*			{ Lineno++; }
<A>"order"		{ RET(ORDER); }
<A>"with"		{ RET(WITH); }
<A>"codeset"		{ BEGIN LC; RET(CODESET); }
<A>"replace"		{ BEGIN RE1; RET(REPLACE); }
<A>"substitute"		{ BEGIN RE1; RET(REPLACE); }
<A>"is"			{ BEGIN LIST; RET(IS); }
<A>\"			{ BEGIN STR; clen = 0; }
<A>. 			{ RET(yytext[0]); }

<LC>{WS}+		{ ; }
<LC>[a-zA-Z0-9_]+	{ SAVE(yytext); BEGIN A; RET(ID); }

<LIST>;			{
			cbuf[clen] ='\0';
			if(clen == 0)
				RET(SEPARATOR);
			if(EQ(cbuf, "...")) {
				cbuf[(clen = 0)] = '\0';
				BEGIN LIST;
				unput(yytext[0]);
				RET(ELLIPSES);
			}
			if(clen > 2) {
				error(TOO_LONG, "symbol", cbuf);
				clen = 2;
			}
			SAVE(cbuf);
			cbuf[(clen = 0)] = '\0';
			unput(yytext[0]);
			RET(SYMBOL);
			}
<LIST>[({]		{
			cbuf[clen] = '\0';
			if (clen == 0) {
				RET(yytext[0]);
				}
			else {
			     error(INVALID, "symbol", cbuf);
			     }
			}
<LIST>[)}]		{
			cbuf[clen] = '\0';
			if (clen == 0) {
				BEGIN LIST1;
				RET(yytext[0]);
				}
			else {
				SAVE(cbuf);
				clen = 0;
				unput(yytext[0]);
				RET(SYMBOL);
				}
			}
<LIST>{WS}+		{
			if(clen == 1)
				error(INVALID, "whitespace in symbol");
			}
<LIST>\n		{
			cbuf[clen] = '\0';
			if(clen == 0)
				error(INVALID, "symbol", cbuf);
			if(clen > 2) {
				error(TOO_LONG, "symbol", cbuf);
				cbuf[2] = '\0';
			}
			SAVE(cbuf);
			cbuf[(clen = 0)] = '\0';
			BEGIN A;
			RET(SYMBOL);
			}
<LIST>[0\\][xX]({H}{H}{H}|{H}{H}|{H})	{ yytext[0] = '0'; IADD; }
<LIST>[0\\]({O}{O}{O}|{O}{O}|{O})	{ yytext[0] = '0'; IADD; }
<LIST>.			{ CADD(yytext[0]); }

<LIST1>\n		{
			BEGIN A;
			}

<LIST1>[^\n]		{
			unput(yytext[0]);
			BEGIN LIST;
			}

<RE1>\"			{ BEGIN RE2; }
<RE1>{WS}+		{ ; }
<RE1>.			{ yytext[1] = '\0'; error(INVALID, "character", yytext); };
<RE2>\\.		{ CADD('\\'); CADD('.'); }
<RE2>"\\\""		{ CADD('"'); }
<RE2>\n			{
			error(NEWLINE, "regular expression", cbuf);
			Lineno++;
			BEGIN A;
			}
<RE2>\"			{
			BEGIN A;
			cbuf[clen] = '\0';
			if (regexp_flag) {
				if(compile(cbuf, &ebuf[0], &ebuf[ESIZE], '\0') != (char *) NULL) {
					rep = ebuf;
					while (*rep++ != 026)
						re_len++;
					re_len++;
					SAVE_RE(ebuf);
					re_len = 0;
					RET(REGEXP);
				}
			}	
			else {
				SAVE(cbuf);
				cbuf[(clen = 0)] = ebuf[0] = '\0';
				RET(REGEXP);
			}
			}
<RE2>"\\"({O}{O}{O}|{O}{O}|{O})	{ yytext[0] = '0'; IADD; }
<RE2>.			{ CADD(yytext[0]); }

<STR>\"			{
			BEGIN A;
			cbuf[clen] = '\0';
			if(clen == 0) {
				yytext[0] = '\0';
				yylval = (int) yytext;
			}
			else {
				SAVE(cbuf);
				cbuf[(clen = 0)] = '\0';
			}
			RET(STRING);
			}
<STR>\n			{ error(NEWLINE, "string", cbuf); Lineno++; BEGIN A; }
<STR>"\\\""		{ CADD('"'); }
<STR>"\\"n		{ CADD('\n'); }
<STR>"\\"t		{ CADD('\t'); }
<STR>"\\"f		{ CADD('\f'); }
<STR>"\\"r		{ CADD('\r'); }
<STR>"\\"b		{ CADD('\b'); }
<STR>"\\\\"		{ CADD('\\'); }
<STR>"\\"({O}{O}{O}|{O}{O}|{O})	{ yytext[0] = '0'; IADD; }
<STR>.			{ CADD(yytext[0]); }

%%
lexinit()
{
	BEGIN A;
}
