what you give them. Help stamp out software-hoarding!
-------------------------------------------------------------------------*/
-D [0-9]
-L [a-zA-Z_]
-H [a-fA-F0-9]
-E [Ee][+-]?{D}+
-FS (f|F|l|L)
-IS (u|U|l|L)*
-%{
+D [0-9]
+L [a-zA-Z_]
+H [a-fA-F0-9]
+E [Ee][+-]?{D}+
+FS (f|F|l|L)
+IS (u|U|l|L)*
+%{
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "common.h"
#include "newalloc.h"
-
-char *stringLiteral();
-char *currFname;
+#include "dbuf.h"
-extern int lineno, column;
-extern char *filename ;
-int yylineno = 1 ;
-void count() ;
-int process_pragma(char *);
-#undef yywrap
-
-int yywrap YY_PROTO((void))
-{
- return(1);
-}
#define TKEYWORD(token) return (isTargetKeyword(yytext) ? token :\
- check_type(yytext))
-char *asmbuff=NULL;
-int asmbuffSize=0;
-char *asmp ;
-extern int check_type ();
- extern int isTargetKeyword ();
-extern int checkCurrFile (char *);
-extern int processPragma (char *);
-extern int printListing (int );
-struct optimize save_optimize ;
-struct options save_options ;
-
- enum {
- P_SAVE = 1,
- P_RESTORE ,
- P_NOINDUCTION,
- P_NOINVARIANT,
- P_INDUCTION ,
- P_STACKAUTO ,
- P_NOJTBOUND ,
- P_NOOVERLAY ,
- P_NOGCSE ,
- P_CALLEE_SAVES,
- P_EXCLUDE ,
- P_NOIV ,
- P_LOOPREV ,
- P_OVERLAY_ /* I had a strange conflict with P_OVERLAY while */
- /* cross-compiling for MINGW32 with gcc 3.2 */
- };
+ check_type())
+extern int lineno, column;
+extern char *filename;
+
+/* global definitions */
+char *currFname;
+int mylineno = 1;
+
+/* local definitions */
+static struct dbuf_s asmbuff;
+
+/* forward declarations */
+static char *stringLiteral(void);
+static void count(void);
+static int process_pragma(char *);
+static int check_type(void);
+static int isTargetKeyword(char *s);
+static int checkCurrFile(char *s);
%}
+
%x asm
%%
-"_asm" {
- count();
- asmp = asmbuff = realloc (asmbuff, INITIAL_INLINEASM);
- asmbuffSize=INITIAL_INLINEASM;
- BEGIN(asm) ;
+"_asm" {
+ count();
+ assert(asmbuff.alloc == 0 && asmbuff.len == 0 && asmbuff.buf == NULL);
+ dbuf_init(&asmbuff, INITIAL_INLINEASM);
+ BEGIN(asm);
}
-<asm>"_endasm" {
+<asm>"_endasm" {
count();
- *asmp = '\0';
- yylval.yyinline = malloc (strlen(asmbuff)+1);
- strcpy(yylval.yyinline,asmbuff);
+ yylval.yyinline = dbuf_c_str(&asmbuff);
+ dbuf_detach(&asmbuff);
BEGIN(INITIAL);
return (INLINEASM);
}
-<asm>. {
- if (asmp-asmbuff >= asmbuffSize-2) {
- // increase the buffersize with 50%
- int size=asmp-asmbuff;
- asmbuffSize=asmbuffSize*3/2;
- asmbuff = realloc (asmbuff, asmbuffSize);
- asmp=asmbuff+size;
- }
- *asmp++ = yytext[0];
+<asm>\n {
+ count();
+ dbuf_append(&asmbuff, yytext, 1);
}
-<asm>\n {
- count();
- if (asmp-asmbuff >= asmbuffSize-3) {
- // increase the buffersize with 50%
- int size=asmp-asmbuff;
- asmbuffSize=asmbuffSize*3/2;
- asmbuff = realloc (asmbuff, asmbuffSize);
- asmp=asmbuff+size;
- }
- *asmp++ = '\n' ;
+<asm>. {
+ dbuf_append(&asmbuff, yytext, 1);
}
"at" { count(); TKEYWORD(AT) ; }
"auto" { count(); return(AUTO); }
"\n" { count(); }
[ \t\v\f] { count(); }
\\ {
- char ch=input();
- if (ch!='\n') {
- // that could have been removed by the preprocessor anyway
+ int ch = input();
+ if (ch != '\n') {
+ /* that could have been removed by the preprocessor anyway */
werror (W_STRAY_BACKSLASH, column);
unput(ch);
}
. { count() ; }
%%
-int checkCurrFile ( char *s)
+static int checkCurrFile (char *s)
{
char lineNum[10] ;
int lNum ;
/* set the current line number to */
/* line number if printFlag is on */
if (!*s) {
- lineno = yylineno = lNum ;
+ lineno = mylineno = lNum ;
return 0;
}
/* in c1mode fullSrcFileName is NULL */
if ( fullSrcFileName &&
strncmp(s,fullSrcFileName,strlen(fullSrcFileName)) == 0) {
- lineno = yylineno = lNum;
+ lineno = mylineno = lNum;
currFname = fullSrcFileName ;
} else {
char *sb = s;
/* mark the end of the filename */
while (*s != '"') s++;
*s = '\0';
- currFname = malloc (strlen(sb)+1);
- strcpy(currFname,sb);
- lineno = yylineno = lNum;
+ currFname = strdup (sb);
+ lineno = mylineno = lNum;
}
filename = currFname ;
return 0;
}
int column = 0;
-int plineIdx=0;
+int plineIdx =0;
-void count()
+static void count(void)
{
int i;
for (i = 0; yytext[i] != '\0'; i++) {
if (yytext[i] == '\n') {
column = 0;
- lineno = ++yylineno ;
+ lineno = ++mylineno ;
}
else
if (yytext[i] == '\t')
/* ECHO; */
}
-int check_type()
+static int check_type(void)
{
/* check if it is in the typedef table */
if (findSym(TypedefTab,NULL,yytext)) {
- strcpy(yylval.yychar,yytext);
+ strncpyz(yylval.yychar,yytext, SDCC_NAME_MAX);
return (TYPE_NAME) ;
}
else {
- strcpy (yylval.yychar,yytext);
+ strncpyz (yylval.yychar,yytext, SDCC_NAME_MAX);
return(IDENTIFIER);
}
}
-char strLitBuff[2048]; // TODO: this is asking for the next bug :)
-
/*
* Change by JTV 2001-05-19 to not concantenate strings
* to support ANSI hex and octal escape sequences in string liteals
*/
-char *stringLiteral () {
+static char *stringLiteral(void)
+{
+#define STR_BUF_CHUNCK_LEN 1024
int ch;
- char *str = strLitBuff;
-
- *str++ = '\"';
+ static struct dbuf_s dbuf;
+ char buf[2];
+
+ if (dbuf.alloc == 0)
+ dbuf_init(&dbuf, STR_BUF_CHUNCK_LEN);
+ else
+ dbuf_set_size(&dbuf, 0);
+
+
+ dbuf_append(&dbuf, "\"", 1);
/* put into the buffer till we hit the first \" */
-
- while (1) {
- ch = input();
-
- if (!ch)
- break; /* end of input */
-
- /* if it is a \ then escape char's are allowed */
- if (ch == '\\') {
- ch=input();
- if (ch=='\n') {
- /* \<newline> is a continuator */
- lineno=++yylineno;
- column=0;
- continue;
+
+ while ((ch = input()) != 0) {
+ switch (ch) {
+ case '\\':
+ /* if it is a \ then escape char's are allowed */
+ ch = input();
+ if (ch == '\n') {
+ /* \<newline> is a continuator */
+ lineno = ++mylineno;
+ column = 0;
}
- *str++ = '\\'; /* backslash in place */
- *str++ = ch; /* get the escape char, no further check */
- continue; /* carry on */
- }
-
- /* if new line we have a new line break, which is illegal */
- if (ch == '\n') {
- werror (W_NEWLINE_IN_STRING);
- *str++ = '\n';
- lineno=++yylineno;
- column=0;
- continue;
- }
-
- /* if this is a quote then we have work to do */
- /* find the next non whitespace character */
- /* if that is a double quote then carry on */
- if (ch == '\"') {
- *str++ = ch ; /* Pass end of this string or substring to evaluator */
- while ((ch = input()) && (isspace(ch) || ch=='\\')) {
- switch (ch) {
- case '\\':
- if ((ch=input())!='\n') {
- werror (W_STRAY_BACKSLASH, column);
- unput(ch);
- } else {
- lineno=++yylineno;
- column=0;
- }
- break;
- case '\n':
- yylineno++;
- break;
- }
+ else {
+ buf[0] = '\\';
+ buf[1] = ch;
+ dbuf_append(&dbuf, buf, 2); /* get the escape char, no further check */
+ }
+ break; /* carry on */
+
+ case '\n':
+ /* if new line we have a new line break, which is illegal */
+ werror(W_NEWLINE_IN_STRING);
+ dbuf_append(&dbuf, "\n", 1);
+ lineno = ++mylineno;
+ column = 0;
+ break;
+
+ case '"':
+ /* if this is a quote then we have work to do */
+ /* find the next non whitespace character */
+ /* if that is a double quote then carry on */
+ dbuf_append(&dbuf, "\"", 1); /* Pass end of this string or substring to evaluator */
+ while ((ch = input()) && (isspace(ch) || ch == '\\')) {
+ switch (ch) {
+ case '\\':
+ if ((ch = input()) != '\n') {
+ werror(W_STRAY_BACKSLASH, column);
+ unput(ch);
+ }
+ else {
+ lineno = ++mylineno;
+ column = 0;
+ }
+ break;
+
+ case '\n':
+ mylineno++;
+ break;
+ }
}
if (!ch)
- break;
+ goto out;
if (ch != '\"') {
- unput(ch) ;
- break ;
+ unput(ch) ;
+ goto out;
}
+ break;
+
+ default:
+ buf[0] = ch;
+ dbuf_append(&dbuf, buf, 1); /* Put next substring introducer into output string */
}
- *str++ = ch; /* Put next substring introducer into output string */
- }
- *str = '\0';
-
- return strLitBuff;
+ }
+
+out:
+ return (char *)dbuf_c_str(&dbuf);
}
-void doPragma (int op, char *cp)
+
+enum pragma_id {
+ P_SAVE = 1,
+ P_RESTORE ,
+ P_NOINDUCTION,
+ P_NOINVARIANT,
+ P_INDUCTION ,
+ P_STACKAUTO ,
+ P_NOJTBOUND ,
+ P_NOOVERLAY ,
+ P_LESSPEDANTIC,
+ P_NOGCSE ,
+ P_CALLEE_SAVES,
+ P_EXCLUDE ,
+ P_NOIV ,
+ P_LOOPREV ,
+ P_OVERLAY_ /* I had a strange conflict with P_OVERLAY while */
+ /* cross-compiling for MINGW32 with gcc 3.2 */
+};
+
+
+/* SAVE/RESTORE stack */
+#define SAVE_RESTORE_SIZE 128
+
+STACK_DCL(options_stack, struct options *, SAVE_RESTORE_SIZE)
+STACK_DCL(optimize_stack, struct optimize *, SAVE_RESTORE_SIZE)
+
+/*
+ * cloneXxx functions should be updated every time a new set is
+ * added to the options or optimize structure!
+ */
+
+static struct options *cloneOptions(struct options *opt)
{
- switch (op) {
- case P_SAVE:
- memcpy(&save_options,&options,sizeof(options));
- memcpy(&save_optimize,&optimize,sizeof(optimize));
- break;
- case P_RESTORE:
- memcpy(&options,&save_options,sizeof(options));
- memcpy(&optimize,&save_optimize,sizeof(optimize));
- break;
- case P_NOINDUCTION:
- optimize.loopInduction = 0 ;
- break;
- case P_NOINVARIANT:
- optimize.loopInvariant = 0 ;
- break;
- case P_INDUCTION:
- optimize.loopInduction = 1 ;
- break;
- case P_STACKAUTO:
- options.stackAuto = 1;
- break;
- case P_NOJTBOUND:
- optimize.noJTabBoundary = 1;
- break;
- case P_NOGCSE:
- optimize.global_cse = 0;
- break;
- case P_NOOVERLAY:
- options.noOverlay = 1;
- break;
- case P_CALLEE_SAVES:
- {
- int i=0;
- /* append to the functions already listed
- in callee-saves */
- for (; options.calleeSaves[i] ;i++);
- parseWithComma(&options.calleeSaves[i], Safe_strdup(cp));
- }
- break;
- case P_EXCLUDE:
- parseWithComma(options.excludeRegs, Safe_strdup(cp));
- break;
- case P_NOIV:
- options.noiv = 1;
- break;
- case P_LOOPREV:
- optimize.noLoopReverse = 1;
- break;
- case P_OVERLAY_:
- break; /* notyet */
- }
+ struct options *new_opt;
+
+ new_opt = Safe_malloc(sizeof (struct options));
+
+ /* clone scalar values */
+ *new_opt = *opt;
+
+ /* clone sets */
+ new_opt->calleeSavesSet = setFromSetNonRev(opt->calleeSavesSet);
+ new_opt->excludeRegsSet = setFromSetNonRev(opt->excludeRegsSet);
+ /* not implemented yet: */
+ /* new_opt->olaysSet = setFromSetNonRev(opt->olaysSet); */
+
+ return new_opt;
}
-int process_pragma(char *s)
+static struct optimize *cloneOptimize(struct optimize *opt)
{
- char *cp ;
- /* find the pragma */
- while (strncmp(s,"#pragma",7))
- s++;
- s += 7;
-
- /* look for the directive */
- while(isspace(*s)) s++;
+ struct optimize *new_opt;
- cp = s;
- /* look for the end of the directive */
- while ((! isspace(*s)) &&
- (*s != '\n'))
- s++ ;
+ new_opt = Safe_malloc(sizeof (struct options));
- /* First give the port a chance */
- if (port->process_pragma && !port->process_pragma(cp))
- return 0;
+ /* clone scalar values */
+ *new_opt = *opt;
- /* now compare and do what needs to be done */
- if (strncmp(cp,PRAGMA_SAVE,strlen(PRAGMA_SAVE)) == 0) {
- doPragma(P_SAVE,cp+strlen(PRAGMA_SAVE));
- return 0;
- }
+ return new_opt;
+}
- if (strncmp(cp,PRAGMA_RESTORE,strlen(PRAGMA_RESTORE)) == 0) {
- doPragma (P_RESTORE,cp+strlen(PRAGMA_RESTORE));
- return 0;
- }
+static void copyAndFreeOptions(struct options *dest, struct options *src)
+{
+ /* delete dest sets */
+ deleteSet(&dest->calleeSavesSet);
+ deleteSet(&dest->excludeRegsSet);
+ /* not implemented yet: */
+ /* deleteSet(&dest->olaysSet); */
- if (strncmp(cp,PRAGMA_NOINDUCTION,strlen(PRAGMA_NOINDUCTION)) == 0) {
- doPragma (P_NOINDUCTION,cp+strlen(PRAGMA_NOINDUCTION)) ;
- return 0;
- }
+ /* dopy src to dest */
+ *dest = *src;
- if (strncmp(cp,PRAGMA_NOINVARIANT,strlen(PRAGMA_NOINVARIANT)) == 0) {
- doPragma (P_NOINVARIANT,NULL) ;
- return 0;
- }
+ Safe_free(src);
+}
- if (strncmp(cp,PRAGMA_INDUCTION,strlen(PRAGMA_INDUCTION)) == 0) {
- doPragma (P_INDUCTION,NULL) ;
- return 0;
- }
+static void copyAndFreeOptimize(struct optimize *dest, struct optimize *src)
+{
+ /* dopy src to dest */
+ *dest = *src;
- if (strncmp(cp,PRAGMA_STACKAUTO,strlen(PRAGMA_STACKAUTO)) == 0) {
- doPragma (P_STACKAUTO,NULL);
- return 0;
- }
+ Safe_free(src);
+}
- if (strncmp(cp,PRAGMA_NOJTBOUND,strlen(PRAGMA_NOJTBOUND)) == 0) {
- doPragma (P_NOJTBOUND,NULL);
- return 0;
+static void doPragma(int op, char *cp)
+{
+ switch (op) {
+ case P_SAVE:
+ {
+ STACK_PUSH(options_stack, cloneOptions(&options));
+ STACK_PUSH(optimize_stack, cloneOptimize(&optimize));
}
+ break;
- if (strncmp(cp,PRAGMA_NOGCSE,strlen(PRAGMA_NOGCSE)) == 0) {
- doPragma (P_NOGCSE,NULL);
- return 0;
- }
+ case P_RESTORE:
+ {
+ struct options *optionsp;
+ struct optimize *optimizep;
- if (strncmp(cp,PRAGMA_NOOVERLAY,strlen(PRAGMA_NOOVERLAY)) == 0) {
- doPragma (P_NOOVERLAY,NULL);
- return 0;
+ optionsp = STACK_POP(options_stack);
+ copyAndFreeOptions(&options, optionsp);
+
+ optimizep = STACK_POP(optimize_stack);
+ copyAndFreeOptimize(&optimize, optimizep);
}
-
- if (strncmp(cp,PRAGMA_CALLEESAVES,strlen(PRAGMA_CALLEESAVES)) == 0) {
- doPragma(P_CALLEE_SAVES,cp+strlen(PRAGMA_CALLEESAVES));
- return 0;
+ break;
+
+ case P_NOINDUCTION:
+ optimize.loopInduction = 0 ;
+ break;
+
+ case P_NOINVARIANT:
+ optimize.loopInvariant = 0 ;
+ break;
+
+ case P_INDUCTION:
+ optimize.loopInduction = 1 ;
+ break;
+
+ case P_STACKAUTO:
+ options.stackAuto = 1;
+ break;
+
+ case P_NOJTBOUND:
+ optimize.noJTabBoundary = 1;
+ break;
+
+ case P_NOGCSE:
+ optimize.global_cse = 0;
+ break;
+
+ case P_NOOVERLAY:
+ options.noOverlay = 1;
+ break;
+
+ case P_LESSPEDANTIC:
+ options.lessPedantic = 1;
+ break;
+
+ case P_CALLEE_SAVES:
+ /* append to the functions already listed
+ in callee-saves */
+ setParseWithComma(&options.calleeSavesSet, cp);
+ break;
+
+ case P_EXCLUDE:
+ {
+ deleteSet(&options.excludeRegsSet);
+ setParseWithComma(&options.excludeRegsSet, cp);
}
+ break;
+
+ case P_NOIV:
+ options.noiv = 1;
+ break;
+
+ case P_LOOPREV:
+ optimize.noLoopReverse = 1;
+ break;
+
+ case P_OVERLAY_:
+ break; /* notyet */
+ }
+}
+
+static int process_pragma(char *s)
+{
+#define NELEM(x) (sizeof (x) / sizeof (x)[0])
+#define PRAGMA "#pragma"
+
+ static struct pragma_s {
+ const char *name;
+ enum pragma_id id;
+ } pragma_tbl[] = {
+ { "SAVE", P_SAVE },
+ { "RESTORE", P_RESTORE },
+ { "NOINDUCTION", P_NOINDUCTION },
+ { "NOINVARIANT", P_NOINVARIANT },
+ { "NOLOOPREVERSE", P_LOOPREV },
+ { "INDUCTION", P_INDUCTION },
+ { "STACKAUTO", P_STACKAUTO },
+ { "NOJTBOUND", P_NOJTBOUND },
+ { "NOGCSE", P_NOGCSE },
+ { "NOOVERLAY", P_NOOVERLAY },
+ { "CALLEE-SAVES", P_CALLEE_SAVES },
+ { "EXCLUDE", P_EXCLUDE },
+ { "NOIV", P_NOIV },
+ { "OVERLAY", P_OVERLAY_ },
+ { "LESS_PEDANTIC", P_LESSPEDANTIC },
+ };
+ char *cp ;
+ int i;
+
+ /* find the pragma */
+ while (strncmp(s, PRAGMA, (sizeof PRAGMA) - 1))
+ s++;
+ s += (sizeof PRAGMA) - 1;
- if (strncmp(cp,PRAGMA_EXCLUDE,strlen(PRAGMA_EXCLUDE)) == 0) {
- doPragma(P_EXCLUDE,cp+strlen(PRAGMA_EXCLUDE));
- return 0;
- }
+ /* look for the directive */
+ while(isspace(*s))
+ s++;
- if (strncmp(cp,PRAGMA_NOIV,strlen(PRAGMA_NOIV)) == 0) {
- doPragma(P_NOIV,cp+strlen(PRAGMA_NOIV));
- return 0;
- }
+ cp = s;
+ /* look for the end of the directive */
+ while ((!isspace(*s)) && (*s != '\n'))
+ s++ ;
- if (strncmp(cp,PRAGMA_NOLOOPREV,strlen(PRAGMA_NOLOOPREV)) == 0) {
- doPragma(P_LOOPREV,NULL);
- return 0;
+ /* First give the port a chance */
+ if (port->process_pragma && !port->process_pragma(cp))
+ return 0;
+
+ for (i = 0; i < NELEM(pragma_tbl); i++) {
+ /* now compare and do what needs to be done */
+ size_t len = strlen(pragma_tbl[i].name);
+
+ if (strncmp(cp, pragma_tbl[i].name, len) == 0) {
+ doPragma(pragma_tbl[i].id, cp + len);
+ return 0;
}
+ }
- werror(W_UNKNOWN_PRAGMA,cp);
- return 0;
+ werror(W_UNKNOWN_PRAGMA,cp);
+ return 0;
}
/* will return 1 if the string is a part
of a target specific keyword */
-int isTargetKeyword(char *s)
+static int isTargetKeyword(char *s)
{
int i;
return 0;
}
-extern int fatalError;
+int yywrap(void)
+{
+ if (!STACK_EMPTY(options_stack) || !STACK_EMPTY(optimize_stack))
+ werror(W_SAVE_RESTORE);
+
+ return 1;
+}
int yyerror(char *s)
{
fflush(stdout);
- if (yylineno && filename) {
- fprintf(stdout,"\n%s:%d: %s: token -> '%s' ; column %d\n",
- filename,yylineno,
- s,yytext,column);
+ if (mylineno && filename) {
+ if(options.vc_err_style)
+ fprintf(stderr,"\n%s(%d) : %s: token -> '%s' ; column %d\n",
+ filename,mylineno,
+ s,yytext,column);
+ else
+ fprintf(stderr,"\n%s:%d: %s: token -> '%s' ; column %d\n",
+ filename,mylineno,
+ s,yytext,column);
fatalError++;
} else {
- // this comes from an empy file, no problem
+ /* this comes from an empy file, no problem */
}
return 0;
}