scan.l revision 215704
1168054Sflz%{
2168054Sflz/*      $OpenBSD: scan.l,v 1.23 2009/10/27 23:59:36 deraadt Exp $	*/
3168266Sgabor
4168266Sgabor/*
5168266Sgabor * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
6168266Sgabor *
7168266Sgabor * Permission to use, copy, modify, and distribute this software for any
8168266Sgabor * purpose with or without fee is hereby granted, provided that the above
9168266Sgabor * copyright notice and this permission notice appear in all copies.
10168266Sgabor *
11168054Sflz * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12168054Sflz * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13168064Sflz * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14168064Sflz * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15168064Sflz * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16168064Sflz * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17168064Sflz * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18168064Sflz */
19168064Sflz
20168064Sflz#include <sys/cdefs.h>
21168064Sflz__FBSDID("$FreeBSD: head/usr.bin/bc/scan.l 215704 2010-11-22 20:10:48Z brucec $");
22168064Sflz
23168064Sflz#include <err.h>
24168064Sflz#include <errno.h>
25168064Sflz#include <histedit.h>
26168064Sflz#include <stdbool.h>
27168054Sflz#include <string.h>
28168054Sflz#include <unistd.h>
29168064Sflz
30168054Sflz#include "extern.h"
31168188Sgabor#include "bc.h"
32168357Syar#include "pathnames.h"
33168673Sjulian
34168188Sgaborint		 lineno;
35168263Sru
36168194Simpbool		 interactive;
37168357SyarHistEvent	 he;
38168188SgaborEditLine	*el;
39168188SgaborHistory		*hist;
40168188Sgabor
41168188Sgaborstatic char	*strbuf = NULL;
42168188Sgaborstatic size_t	 strbuf_sz = 1;
43168188Sgaborstatic bool	 dot_seen;
44168188Sgabor
45168202Sumestatic void	 init_strbuf(void);
46168188Sgaborstatic void	 add_str(const char *);
47168188Sgaborstatic int	 bc_yyinput(char *, int);
48168202Sume
49168188Sgabor#define YY_NO_INPUT
50168127Sdwmalone#undef YY_INPUT
51168054Sflz#define YY_INPUT(buf,retval,max) \
52168054Sflz	(retval = bc_yyinput(buf, max))
53168054Sflz%}
54168054Sflz
55168215Sache%option always-interactive
56208793Sae
57168149SimpDIGIT		[0-9A-F]
58168149SimpALPHA		[a-z_]
59207017SanchieALPHANUM	[a-z_0-9]
60168179Sgabor
61212260Sandreast%x		comment string number
62210361Sandrew
63168083Sjkim%%
64176001Santoine
65168123Snetchild"/*"		BEGIN(comment);
66188752Savg<comment>{
67168080Smlaier	"*/"	BEGIN(INITIAL);
68168195Sbenno	\n	lineno++;
69168131Sbmah	\*	;
70168183Sgabor	[^*\n]+	;
71168080Smlaier	<<EOF>>	fatal("end of file in comment");
72168309Sbrian}
73168308Sbrian
74203168Sbrucec\"		BEGIN(string); init_strbuf();
75168150Srwatson<string>{
76168149Simp	[^"\n\\\[\]]+	add_str(yytext);
77203555Sbschmidt	\[	add_str("\\[");
78168150Srwatson	\]	add_str("\\]");
79168263Sru	\\	add_str("\\\\");
80180232Scokane	\n	add_str("\n"); lineno++;
81168054Sflz	\"	BEGIN(INITIAL); yylval.str = strbuf; return STRING;
82168183Sgabor	<<EOF>>	fatal("end of file in string");
83168674Sjulian}
84168060Sdds
85168108Srafan{DIGIT}+	{
86168083Sjkim			BEGIN(number);
87168153Simp			dot_seen = false;
88168080Smlaier			init_strbuf();
89212025Sdim			add_str(yytext);
90168149Simp		}
91168127Sdwmalone\.		{
92179207Sed			BEGIN(number);
93175201Sedwin			dot_seen = true;
94168263Sru			init_strbuf();
95168180Srwatson			add_str(".");
96168149Simp		}
97179830Seri<number>{
98189932Sfabient	{DIGIT}+	add_str(yytext);
99168127Sdwmalone	\.	{
100169252Sfjoe			if (dot_seen) {
101168054Sflz				BEGIN(INITIAL);
102203370Sgabor				yylval.str = strbuf;
103168370Sgad				unput('.');
104168631Sticso				return (NUMBER);
105200313Sgavin			} else {
106168183Sgabor				dot_seen = true;
107168672Smav				add_str(".");
108168150Srwatson			}
109168195Sbenno		}
110168081Sle	\\\n[ \t]*	lineno++;
111168154Sgshapiro	[^0-9A-F\.]	{
112168127Sdwmalone			BEGIN(INITIAL);
113168144Simp			unput(yytext[0]);
114179767Sivoras			if (strcmp(strbuf, ".") == 0)
115168308Sbrian				return (DOT);
116187937Sjamie			else {
117168183Sgabor				yylval.str = strbuf;
118208394Sjchandra				return (NUMBER);
119208394Sjchandra			}
120197776Sjh		}
121208394Sjchandra}
122192607Sjilles
123168150Srwatson"auto"		return (AUTO);
124168153Simp"break"		return (BREAK);
125168083Sjkim"continue"	return (CONTINUE);
126172389Skaiw"define"	return (DEFINE);
127168111Smatteo"else"		return (ELSE);
128168149Simp"ibase"		return (IBASE);
129168151Sphk"if"		return (IF);
130168149Simp"last"		return (DOT);
131168673Sjulian"for"		return (FOR);
132172389Skaiw"length"	return (LENGTH);
133168180Srwatson"obase"		return (OBASE);
134168535Skevlo"print"		return (PRINT);
135200356Skib"quit"		return (QUIT);
136168150Srwatson"return"	return (RETURN);
137168081Sle"scale"		return (SCALE);
138168180Srwatson"sqrt"		return (SQRT);
139183643Slstewart"while"		return (WHILE);
140172984Slulf
141180222Smarcel"^"		return (EXPONENT);
142192775Smarkm"*"		return (MULTIPLY);
143168167Sphilip"/"		return (DIVIDE);
144168918Sbrueffer"%"		return (REMAINDER);
145168142Srwatson
146168672Smav"!"		return (BOOL_NOT);
147168263Sru"&&"		return (BOOL_AND);
148208807Smdf"||"		return (BOOL_OR);
149168143Smjacob
150168080Smlaier"+"		return (PLUS);
151168149Simp"-"		return (MINUS);
152168130Sdelphij
153198183Sneel"++"		return (INCR);
154168123Snetchild"--"		return (DECR);
155168171Sphilip
156194197Snork"="		yylval.str = ""; return (ASSIGN_OP);
157193775Snp"+="		yylval.str = "+"; return (ASSIGN_OP);
158180227Snwhitehorn"-="		yylval.str = "-"; return (ASSIGN_OP);
159168097Sle"*="		yylval.str = "*"; return (ASSIGN_OP);
160176318Solli"/="		yylval.str = "/"; return (ASSIGN_OP);
161168149Simp"%="		yylval.str = "%"; return (ASSIGN_OP);
162168127Sdwmalone"^="		yylval.str = "^"; return (ASSIGN_OP);
163168183Sgabor
164168111Smatteo"=="		return (EQUALS);
165168151Sphk"<="		return (LESS_EQ);
166203610Sbrueffer">="		return (GREATER_EQ);
167168321Spjd"!="		return (UNEQUALS);
168168183Sgabor"<"		return (LESS);
169168101Sandre">"		return (GREATER);
170168108Srafan
171206988Srandi","		return (COMMA);
172168149Simp";"		return (SEMICOLON);
173168149Simp
174168149Simp"("		return (LPAR);
175183282Srnoland")"		return (RPAR);
176182009Sroberto
177172343Srpaulo"["		return (LBRACKET);
178168140Srwatson"]"		return (RBRACKET);
179168118Srse
180206945Srstone"{"		return (LBRACE);
181168263Sru"}"		return (RBRACE);
182168140Srwatson
183168080Smlaier{ALPHA}{ALPHANUM}* {
184168149Simp			/* alloc an extra byte for the type marker */
185171026Sscf			char *p = malloc(yyleng + 2);
186168081Sle			if (p == NULL)
187168167Sphilip				err(1, NULL);
188168149Simp			strlcpy(p, yytext, yyleng + 1);
189168115Ssimon			yylval.astr = p;
190168263Sru			return (LETTER);
191191822Ssnb		}
192180366Ssson
193168198Sume\\\n		lineno++;
194168150Srwatson\n		lineno++; return (NEWLINE);
195168149Simp
196168080Smlaier#[^\n]*		;
197168631Sticso[ \t]		;
198210200Stijl<<EOF>>		return (QUIT);
199182006Strasz.		yyerror("illegal character");
200168180Srwatson
201193759Stuexen%%
202168198Sume
203203126Suqsstatic void
204180705Svanhuinit_strbuf(void)
205184913Sversus{
206175039Sweongyo
207168271Swes	if (strbuf == NULL) {
208168141Swilko		strbuf = malloc(strbuf_sz);
209168180Srwatson		if (strbuf == NULL)
210168356Syar			err(1, NULL);
211168238Syongari	}
212183150Szec	strbuf[0] = '\0';
213168054Sflz}
214168151Sphk
215168151Sphkstatic void
216168151Sphkadd_str(const char *str)
217168054Sflz{
218168064Sflz	size_t arglen;
219168064Sflz
220168054Sflz	arglen = strlen(str);
221168151Sphk
222168151Sphk	if (strlen(strbuf) + arglen + 1 > strbuf_sz) {
223168151Sphk		size_t	 newsize;
224168151Sphk		char	*p;
225168151Sphk
226168151Sphk		newsize = strbuf_sz + arglen + 1;
227168151Sphk		p = realloc(strbuf, newsize);
228168101Sandre		if (p == NULL) {
229168101Sandre			free(strbuf);
230168083Sjkim			err(1, NULL);
231168083Sjkim		}
232168195Sbenno		strbuf_sz = newsize;
233168195Sbenno		strbuf = p;
234168152Srwatson	}
235168152Srwatson	strlcat(strbuf, str, strbuf_sz);
236168152Srwatson}
237168152Srwatson
238168152Srwatsonint
239168152Srwatsonyywrap(void)
240168152Srwatson{
241168152Srwatson	static YY_BUFFER_STATE buf;
242168352Sru	static int state;
243168080Smlaier
244168080Smlaier	if (fileindex == 0 && sargc > 0 && strcmp(sargv[0], _PATH_LIBB) == 0) {
245168080Smlaier		filename = sargv[fileindex++];
246168309Sbrian		yyin = fopen(filename, "r");
247168309Sbrian		lineno = 1;
248168152Srwatson		if (yyin == NULL)
249187937Sjamie			err(1, "cannot open %s", filename);
250168152Srwatson		return (0);
251206904Sanchie	}
252187937Sjamie	if (state == 0 && cmdexpr[0] != '\0') {
253168140Srwatson		buf = yy_scan_string(cmdexpr);
254168140Srwatson		state++;
255168101Sandre		lineno = 1;
256206988Srandi		filename = "command line";
257168115Ssimon		return (0);
258168101Sandre	} else if (state == 1) {
259168152Srwatson		yy_delete_buffer(buf);
260168152Srwatson		free(cmdexpr);
261203370Sgabor		state++;
262168108Srafan	}
263168108Srafan	if (yyin != NULL && yyin != stdin)
264168083Sjkim		fclose(yyin);
265168147Sdes	if (fileindex < sargc) {
266168147Sdes		filename = sargv[fileindex++];
267176318Solli		yyin = fopen(filename, "r");
268168263Sru		lineno = 1;
269168083Sjkim		if (yyin == NULL)
270184913Sversus			err(1, "cannot open %s", filename);
271184913Sversus		return (0);
272168352Sru	} else if (fileindex == sargc) {
273168352Sru		fileindex++;
274191822Ssnb		yyin = stdin;
275168352Sru		lineno = 1;
276212025Sdim		filename = "stdin";
277200313Sgavin		return (0);
278192607Sjilles	}
279200356Skib	return (1);
280203953Suqs}
281192607Sjilles
282168147Sdesstatic int
283168140Srwatsonbc_yyinput(char *buf, int maxlen)
284168140Srwatson{
285206945Srstone	int num;
286206945Srstone	if (yyin == stdin && interactive) {
287168918Sbrueffer		const char *bp;
288168918Sbrueffer
289168631Sticso		if ((bp = el_gets(el, &num)) == NULL || num == 0)
290168631Sticso			return (0);
291168352Sru		if (num > maxlen) {
292168352Sru			el_push(el, (char *)(uintptr_t)(bp) + maxlen);
293168127Sdwmalone			num = maxlen;
294168672Smav		}
295168672Smav		memcpy(buf, bp, num);
296168140Srwatson		history(hist, &he, H_ENTER, bp);
297168140Srwatson	} else {
298179767Sivoras		int c = '*';
299180705Svanhu		for (num = 0; num < maxlen &&
300183643Slstewart		    (c = getc(yyin)) != EOF && c != '\n'; ++num)
301193775Snp			buf[num] = (char) c;
302168140Srwatson		if (c == '\n')
303175205Sedwin			buf[num++] = (char) c;
304168352Sru		if (c == EOF && ferror(yyin))
305168352Sru			YY_FATAL_ERROR( "input in flex scanner failed" );
306168149Simp	}
307168149Simp	return (num);
308168156Sbmah}
309168149Simp
310168149Simp