summaryrefslogtreecommitdiffstats
path: root/usr.bin/bc/scan.l
diff options
context:
space:
mode:
authorgabor <gabor@FreeBSD.org>2010-01-20 21:30:52 +0000
committergabor <gabor@FreeBSD.org>2010-01-20 21:30:52 +0000
commitbc4e1f6f87a770761be30eb708cbef88bc4d9536 (patch)
tree96e08d56eaa68b31f8e98a726fe2be11d38299d2 /usr.bin/bc/scan.l
parent572c61752a99c8182ee368efb49e8fe0498abafa (diff)
downloadFreeBSD-src-bc4e1f6f87a770761be30eb708cbef88bc4d9536.zip
FreeBSD-src-bc4e1f6f87a770761be30eb708cbef88bc4d9536.tar.gz
Replace GNU bc/dc with BSDL versions ported from OpenBSD. They have a good
compatibility level with the GNU counterparts and have shown to be mature enough. For now, the GNU versions aren't removed from the tree, just detached from the build. Sponsored by: Google Summer of Code 2008 Portbuild run by: erwin Approved by: delphij
Diffstat (limited to 'usr.bin/bc/scan.l')
-rw-r--r--usr.bin/bc/scan.l288
1 files changed, 288 insertions, 0 deletions
diff --git a/usr.bin/bc/scan.l b/usr.bin/bc/scan.l
new file mode 100644
index 0000000..9c21fc2
--- /dev/null
+++ b/usr.bin/bc/scan.l
@@ -0,0 +1,288 @@
+%{
+/* $OpenBSD: scan.l,v 1.23 2009/10/27 23:59:36 deraadt Exp $ */
+
+/*
+ * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <err.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "extern.h"
+#include "bc.h"
+#include "pathnames.h"
+
+int lineno;
+
+static char *strbuf = NULL;
+static size_t strbuf_sz = 1;
+static bool dot_seen;
+
+static void init_strbuf(void);
+static void add_str(const char *);
+
+%}
+
+%option always-interactive
+
+DIGIT [0-9A-F]
+ALPHA [a-z_]
+ALPHANUM [a-z_0-9]
+
+%x comment string number
+
+%%
+
+"/*" BEGIN(comment);
+<comment>{
+ "*/" BEGIN(INITIAL);
+ \n lineno++;
+ \* ;
+ [^*\n]+ ;
+ <<EOF>> fatal("end of file in comment");
+}
+
+\" BEGIN(string); init_strbuf();
+<string>{
+ [^"\n\\\[\]]+ add_str(yytext);
+ \[ add_str("\\[");
+ \] add_str("\\]");
+ \\ add_str("\\\\");
+ \n add_str("\n"); lineno++;
+ \" BEGIN(INITIAL); yylval.str = strbuf; return STRING;
+ <<EOF>> fatal("end of file in string");
+}
+
+{DIGIT}+ {
+ BEGIN(number);
+ dot_seen = false;
+ init_strbuf();
+ add_str(yytext);
+ }
+\. {
+ BEGIN(number);
+ dot_seen = true;
+ init_strbuf();
+ add_str(".");
+ }
+<number>{
+ {DIGIT}+ add_str(yytext);
+ \. {
+ if (dot_seen) {
+ BEGIN(INITIAL);
+ yylval.str = strbuf;
+ unput('.');
+ return (NUMBER);
+ } else {
+ dot_seen = true;
+ add_str(".");
+ }
+ }
+ \\\n[ \t]* lineno++;
+ [^0-9A-F\.] {
+ BEGIN(INITIAL);
+ unput(yytext[0]);
+ if (strcmp(strbuf, ".") == 0)
+ return (DOT);
+ else {
+ yylval.str = strbuf;
+ return (NUMBER);
+ }
+ }
+}
+
+"auto" return (AUTO);
+"break" return (BREAK);
+"continue" return (CONTINUE);
+"define" return (DEFINE);
+"else" return (ELSE);
+"ibase" return (IBASE);
+"if" return (IF);
+"last" return (DOT);
+"for" return (FOR);
+"length" return (LENGTH);
+"obase" return (OBASE);
+"print" return (PRINT);
+"quit" return (QUIT);
+"return" return (RETURN);
+"scale" return (SCALE);
+"sqrt" return (SQRT);
+"while" return (WHILE);
+
+"^" return (EXPONENT);
+"*" return (MULTIPLY);
+"/" return (DIVIDE);
+"%" return (REMAINDER);
+
+"!" return (BOOL_NOT);
+"&&" return (BOOL_AND);
+"||" return (BOOL_OR);
+
+"+" return (PLUS);
+"-" return (MINUS);
+
+"++" return (INCR);
+"--" return (DECR);
+
+"=" yylval.str = ""; return (ASSIGN_OP);
+"+=" yylval.str = "+"; return (ASSIGN_OP);
+"-=" yylval.str = "-"; return (ASSIGN_OP);
+"*=" yylval.str = "*"; return (ASSIGN_OP);
+"/=" yylval.str = "/"; return (ASSIGN_OP);
+"%=" yylval.str = "%"; return (ASSIGN_OP);
+"^=" yylval.str = "^"; return (ASSIGN_OP);
+
+"==" return (EQUALS);
+"<=" return (LESS_EQ);
+">=" return (GREATER_EQ);
+"!=" return (UNEQUALS);
+"<" return (LESS);
+">" return (GREATER);
+
+"," return (COMMA);
+";" return (SEMICOLON);
+
+"(" return (LPAR);
+")" return (RPAR);
+
+"[" return (LBRACKET);
+"]" return (RBRACKET);
+
+"{" return (LBRACE);
+"}" return (RBRACE);
+
+{ALPHA}{ALPHANUM}* {
+ /* alloc an extra byte for the type marker */
+ char *p = malloc(yyleng + 2);
+ if (p == NULL)
+ err(1, NULL);
+ strlcpy(p, yytext, yyleng + 1);
+ yylval.astr = p;
+ return (LETTER);
+ }
+
+\\\n lineno++;
+\n lineno++; return (NEWLINE);
+
+#[^\n]* ;
+[ \t] ;
+<<EOF>> return (QUIT);
+. yyerror("illegal character");
+
+%%
+
+static void
+init_strbuf(void)
+{
+ if (strbuf == NULL) {
+ strbuf = malloc(strbuf_sz);
+ if (strbuf == NULL)
+ err(1, NULL);
+ }
+ strbuf[0] = '\0';
+}
+
+static void
+add_str(const char *str)
+{
+ size_t arglen;
+
+ arglen = strlen(str);
+
+ if (strlen(strbuf) + arglen + 1 > strbuf_sz) {
+ size_t newsize;
+ char *p;
+
+ newsize = strbuf_sz + arglen + 1;
+ p = realloc(strbuf, newsize);
+ if (p == NULL) {
+ free(strbuf);
+ err(1, NULL);
+ }
+ strbuf_sz = newsize;
+ strbuf = p;
+ }
+ strlcat(strbuf, str, strbuf_sz);
+}
+
+/* ARGSUSED */
+void
+abort_line(int sig)
+{
+ static const char str[] = "[\n]P\n";
+ int save_errno;
+
+ switch (sig) {
+ default:
+ save_errno = errno;
+ YY_FLUSH_BUFFER; /* XXX signal race? */
+ write(STDOUT_FILENO, str, sizeof(str) - 1);
+ errno = save_errno;
+ }
+}
+
+int
+yywrap(void)
+{
+ static int state;
+ static YY_BUFFER_STATE buf;
+
+ if (fileindex == 0 && sargc > 0 && strcmp(sargv[0], _PATH_LIBB) == 0) {
+ filename = sargv[fileindex++];
+ yyin = fopen(filename, "r");
+ lineno = 1;
+ if (yyin == NULL)
+ err(1, "cannot open %s", filename);
+ return (0);
+ }
+ if (state == 0 && cmdexpr[0] != '\0') {
+ buf = yy_scan_string(cmdexpr);
+ state++;
+ lineno = 1;
+ filename = "command line";
+ return (0);
+ } else if (state == 1) {
+ yy_delete_buffer(buf);
+ free(cmdexpr);
+ state++;
+ }
+ if (yyin != NULL && yyin != stdin)
+ fclose(yyin);
+ if (fileindex < sargc) {
+ filename = sargv[fileindex++];
+ yyin = fopen(filename, "r");
+ lineno = 1;
+ if (yyin == NULL)
+ err(1, "cannot open %s", filename);
+ return (0);
+ } else if (fileindex == sargc) {
+ fileindex++;
+ yyin = stdin;
+ if (interactive)
+ signal(SIGINT, abort_line);
+ lineno = 1;
+ filename = "stdin";
+ return (0);
+ }
+ return (1);
+}
+
OpenPOWER on IntegriCloud