Fixed a bug

git-svn-id: svn://svn.cc65.org/cc65/trunk@91 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2000-06-21 21:02:44 +00:00
parent e27fafbea3
commit 04ee693c00
8 changed files with 619 additions and 517 deletions

View file

@ -800,7 +800,7 @@ static int primary (struct expent* lval)
* and returning int.
*/
Warning (WARN_FUNC_WITHOUT_PROTO);
Sym = AddGlobalSym (Ident, GetImplicitFuncType(), SC_EXTERN | SC_REF);
Sym = AddGlobalSym (Ident, GetImplicitFuncType(), SC_EXTERN | SC_REF | SC_FUNC);
lval->e_tptr = Sym->Type;
lval->e_flags = E_MGLOBAL | E_MCONST | E_TGLAB;
lval->e_name = (unsigned long) Sym->Name;

View file

@ -49,7 +49,7 @@
/*****************************************************************************/
/* Data */
/* Data */
/*****************************************************************************/
@ -57,32 +57,39 @@
/* Input line stuff */
static char LineBuf [LINESIZE];
char* line = LineBuf;
char* lptr = LineBuf;
const char* lptr = LineBuf;
/* Current and next input character */
char CurC = '\0';
char NextC = '\0';
/* Maximum count of nested includes */
#define MAX_INC_NESTING 20
#define MAX_INC_NESTING 16
/* Struct that describes an input file */
typedef struct IFile IFile;
struct IFile {
IFile* Next; /* Next file in single linked list */
IFile* Next; /* Next file in single linked list */
IFile* Active; /* Next file in list of active includes */
unsigned Index; /* File index */
unsigned Line; /* Line number for this file */
FILE* F; /* Input file stream */
unsigned Line; /* Line number for this file */
FILE* F; /* Input file stream */
char Name[1]; /* Name of file (dynamically allocated) */
};
/* Main file input data */
static const IFile* MainFile = 0;
/* List of input files */
static unsigned IFileTotal = 0; /* Total number of files */
static IFile* IFileList = 0; /* Single linked list of all files */
static IFile* IFileList = 0; /* Single linked list of all files */
static unsigned IFileCount = 0; /* Number of active input files */
static IFile* Input = 0; /* Single linked list of active files */
static IFile* Input = 0; /* Single linked list of active files */
/*****************************************************************************/
/* struct IFile */
/* struct IFile */
/*****************************************************************************/
@ -108,6 +115,7 @@ static IFile* NewIFile (const char* Name, FILE* F)
IF->Active = Input;
Input = IF;
++IFileCount;
++IFileTotal;
/* Return the new struct */
return IF;
@ -132,7 +140,7 @@ void OpenMainFile (const char* Name)
}
/* Setup a new IFile structure */
NewIFile (Name, F);
MainFile = NewIFile (Name, F);
}
@ -187,6 +195,55 @@ static void CloseIncludeFile (void)
/* Make this file inactive and the last one active again */
Input = Input->Active;
/* Adjust the counter */
--IFileCount;
}
void ClearLine (void)
/* Clear the current input line */
{
line[0] = '\0';
lptr = line;
CurC = '\0';
NextC = '\0';
}
void InitLine (const char* Buf)
/* Initialize lptr from Buf and read CurC and NextC from the new input line */
{
lptr = Buf;
CurC = lptr[0];
if (CurC != '\0') {
NextC = lptr[1];
} else {
NextC = '\0';
}
}
void NextChar (void)
/* Read the next character from the input stream and make CurC and NextC
* valid. If end of line is reached, both are set to NUL, no more lines
* are read by this function.
*/
{
if (lptr[0] != '\0') {
++lptr;
CurC = lptr[0];
if (CurC != '\0') {
NextC = lptr[1];
} else {
NextC = '\0';
}
} else {
CurC = NextC = '\0';
}
}
@ -255,26 +312,24 @@ int NextLine (void)
}
}
/* Got a line */
/* Got a line. Initialize the current and next characters. */
InitLine (line);
/* Done */
return 1;
}
void ClearLine (void)
/* Clear the current input line */
{
line [0] = '\0';
lptr = line;
}
const char* GetCurrentFile (void)
/* Return the name of the current input file */
{
if (Input == 0) {
return "(outside file scope)";
if (MainFile) {
return MainFile->Name;
} else {
return "(outside file scope)";
}
} else {
return Input->Name;
}
@ -290,39 +345,3 @@ unsigned GetCurrentLine (void)
int nch (void)
/* Get the next char in input stream (the one behind the current one) */
{
if (*lptr == '\0') {
return 0;
} else {
return lptr[1] & 0xFF;
}
}
int cgch (void)
/* Get the current character in the input stream and advance line
* pointer (unless already at end of line).
*/
{
if (*lptr == '\0') {
return (0);
} else {
return (*lptr++ & 0xFF);
}
}
int gch (void)
/* Get the current character in the input stream and advance line
* pointer (no end of line check is performed).
*/
{
return (*lptr++ & 0xFF);
}

View file

@ -50,7 +50,11 @@
/* Input line stuff */
extern char* line;
extern char* lptr;
extern const char* lptr; /* ### Remove this */
/* Current and next input character */
extern char CurC;
extern char NextC;
@ -66,33 +70,27 @@ void OpenMainFile (const char* Name);
void OpenIncludeFile (const char* Name, unsigned DirSpec);
/* Open an include file and insert it into the tables. */
int NextLine (void);
/* Get a line from the current input. Returns 0 on end of file. */
void ClearLine (void);
/* Clear the current input line */
void InitLine (const char* Buf);
/* Initialize lptr from Buf and read CurC and NextC from the new input line */
void NextChar (void);
/* Read the next character from the input stream and make CurC and NextC
* valid. If end of line is reached, both are set to NUL, no more lines
* are read by this function.
*/
int NextLine (void);
/* Get a line from the current input. Returns 0 on end of file. */
const char* GetCurrentFile (void);
/* Return the name of the current input file */
unsigned GetCurrentLine (void);
/* Return the line number in the current input file */
int nch (void);
/* Get the next char in input stream (the one behind the current one) */
int cgch (void);
/* Get the current character in the input stream and advance line
* pointer (unless already at end of line).
*/
int gch (void);
/* Get the current character in the input stream and advance line
* pointer (no end of line check is performed).
*/
/* End of input.h */

View file

@ -40,7 +40,6 @@
#include "error.h"
#include "litpool.h"
#include "symtab.h"
#include "preproc.h"
#include "scanner.h"
#include "codegen.h"
#include "expr.h"
@ -55,7 +54,7 @@
/* Tokens for the #pragmas */
enum {
typedef enum {
PR_BSSSEG,
PR_CODESEG,
PR_DATASEG,
@ -65,16 +64,54 @@ enum {
PR_STATICLOCALS,
PR_ZPSYM,
PR_ILLEGAL
} pragma_t;
/* Pragma table */
static const struct Pragma {
const char* Key; /* Keyword */
pragma_t Tok; /* Token */
} Pragmas[] = {
{ "bssseg", PR_BSSSEG },
{ "codeseg", PR_CODESEG },
{ "dataseg", PR_DATASEG },
{ "regvaraddr", PR_REGVARADDR },
{ "rodataseg", PR_RODATASEG },
{ "signedchars", PR_SIGNEDCHARS },
{ "staticlocals", PR_STATICLOCALS },
{ "zpsym", PR_ZPSYM },
};
/* Number of pragmas */
#define PRAGMA_COUNT (sizeof(Pragmas) / sizeof(Pragmas[0]))
/*****************************************************************************/
/* code */
/* Code */
/*****************************************************************************/
static int CmpKey (const void* Key, const void* Elem)
/* Compare function for bsearch */
{
return strcmp ((const char*) Key, ((const struct Pragma*) Elem)->Key);
}
static pragma_t FindPragma (const char* Key)
/* Find a pragma and return the token. Return PR_ILLEGAL if the keyword is
* not a valid pragma.
*/
{
struct Pragma* P;
P = bsearch (Key, Pragmas, PRAGMA_COUNT, sizeof (Pragmas[0]), CmpKey);
return P? P->Tok : PR_ILLEGAL;
}
static void StringPragma (void (*Func) (const char*))
/* Handle a pragma that expects a string parameter */
{
@ -113,19 +150,7 @@ static void FlagPragma (unsigned char* Flag)
void DoPragma (void)
/* Handle pragmas */
{
static const struct tok_elt Pragmas [] = {
{ "bssseg", PR_BSSSEG },
{ "codeseg", PR_CODESEG },
{ "dataseg", PR_DATASEG },
{ "regvaraddr", PR_REGVARADDR },
{ "rodataseg", PR_RODATASEG },
{ "signedchars", PR_SIGNEDCHARS },
{ "staticlocals", PR_STATICLOCALS },
{ "zpsym", PR_ZPSYM },
{ 0, PR_ILLEGAL },
};
int Pragma;
pragma_t Pragma;
/* Skip the token itself */
NextToken ();
@ -137,7 +162,7 @@ void DoPragma (void)
}
/* Do we know this pragma? */
Pragma = searchtok (CurTok.Ident, Pragmas);
Pragma = FindPragma (CurTok.Ident);
if (Pragma == PR_ILLEGAL) {
/* According to the ANSI standard, we're not allowed to generate errors
* for unknown pragmas, however, we're allowed to warn - and we will

View file

@ -29,7 +29,8 @@
static int Pass1 (char* from, char* to);
static int Pass1 (const char* From, char* To);
/* Preprocessor pass 1. Remove whitespace and comments. */
@ -43,7 +44,7 @@ static int Pass1 (char* from, char* to);
unsigned char Preprocessing = 0;
/* Management data for #if */
#define N_IFDEF 16
#define N_IFDEF 16
static int i_ifdef = -1;
static char s_ifdef[N_IFDEF];
@ -81,63 +82,76 @@ static void keepstr (const char* S)
static void comment (void)
/* Remove comment from line. */
static void Comment (void)
/* Remove a C comment from line. */
{
/* Remember the current line number, so we can output better error
* messages if the comment is not terminated in the current file.
*/
unsigned StartingLine = GetCurrentLine();
gch ();
gch ();
while (*lptr != '*' || nch () != '/') {
if (*lptr == '\0') {
/* Skip the start of comment chars */
NextChar ();
NextChar ();
/* Skip the comment */
while (CurC != '*' || NextC != '/') {
if (CurC == '\0') {
if (NextLine () == 0) {
PPError (ERR_EOF_IN_COMMENT, StartingLine);
return;
}
} else {
if (*lptr == '/' && nch() == '*') {
if (CurC == '/' && NextC == '*') {
PPWarning (WARN_NESTED_COMMENT);
}
++lptr;
NextChar ();
}
}
gch ();
gch ();
/* Skip the end of comment chars */
NextChar ();
NextChar ();
}
static void skipblank (void)
static void SkipBlank (void)
/* Skip blanks and tabs in the input stream. */
{
while (IsBlank (*lptr)) {
++lptr;
while (IsBlank (CurC)) {
NextChar ();
}
}
static char* CopyQuotedString (int Quote, char* Target)
/* Copy a single or double quoted string from lptr to Target. Return the
static char* CopyQuotedString (char* Target)
/* Copy a single or double quoted string from the input to Target. Return the
* new target pointer. Target will not be terminated after the copy.
*/
{
/* Copy the starting quote */
*Target++ = gch();
/* Remember the quote character, copy it to the target buffer and skip it */
char Quote = CurC;
*Target++ = CurC;
NextChar ();
/* Copy the characters inside the string */
while (*lptr != '\0' && *lptr != Quote) {
while (CurC != '\0' && CurC != Quote) {
/* Keep an escaped char */
if (*lptr == '\\') {
*Target++ = gch();
if (CurC == '\\') {
*Target++ = CurC;
NextChar ();
}
/* Copy the character */
*Target++ = cgch();
*Target++ = CurC;
NextChar ();
}
/* If we had a terminating quote, copy it */
if (*lptr) {
*Target++ = gch();
if (CurC != '\0') {
*Target++ = CurC;
NextChar ();
}
/* Return the new target pointer */
@ -152,12 +166,12 @@ static char* CopyQuotedString (int Quote, char* Target)
static int macname (char *sname)
static int MacName (char* Ident)
/* Get macro symbol name. If error, print message and clear line. */
{
if (issym (sname) == 0) {
if (IsSym (Ident) == 0) {
PPError (ERR_IDENT_EXPECTED);
ClearLine ();
ClearLine ();
return 0;
} else {
return 1;
@ -169,20 +183,19 @@ static int macname (char *sname)
static void ExpandMacroArgs (Macro* M)
/* Preprocessor pass 2. Perform macro substitution. */
{
int C;
ident Ident;
const char* Replacement;
char* SavePtr;
const char* SavePtr;
/* Save the current line pointer and setup the new ones */
SavePtr = lptr;
lptr = M->Replacement;
InitLine (M->Replacement);
/* Copy the macro replacement checking for parameters to replace */
while ((C = *lptr) != '\0') {
while (CurC != '\0') {
/* If the next token is an identifier, check for a macro arg */
if (IsIdent (C)) {
symname (Ident);
if (IsIdent (CurC)) {
SymName (Ident);
Replacement = FindMacroArg (M, Ident);
if (Replacement) {
/* Macro arg, keep the replacement */
@ -191,9 +204,9 @@ static void ExpandMacroArgs (Macro* M)
/* No macro argument, keep the original identifier */
keepstr (Ident);
}
} else if (C == '#' && IsIdent (nch ())) {
++lptr;
symname (Ident);
} else if (CurC == '#' && IsIdent (NextC)) {
NextChar ();
SymName (Ident);
Replacement = FindMacroArg (M, Ident);
if (Replacement) {
keepch ('\"');
@ -203,15 +216,16 @@ static void ExpandMacroArgs (Macro* M)
keepch ('#');
keepstr (Ident);
}
} else if (IsQuoteChar(C)) {
mptr = CopyQuotedString (C, mptr);
} else if (IsQuoteChar (CurC)) {
mptr = CopyQuotedString (mptr);
} else {
*mptr++ = *lptr++;
*mptr++ = CurC;
NextChar ();
}
}
/* Reset the line pointer */
lptr = SavePtr;
InitLine (SavePtr);
}
@ -219,22 +233,21 @@ static void ExpandMacroArgs (Macro* M)
static int MacroCall (Macro* M)
/* Process a function like macro */
{
unsigned ArgCount; /* Macro argument count */
unsigned ArgCount; /* Macro argument count */
unsigned ParCount; /* Number of open parenthesis */
char Buf[LINESIZE]; /* Argument buffer */
char C;
const char* ArgStart;
char* B;
/* Expect an argument list */
skipblank ();
if (*lptr != '(') {
SkipBlank ();
if (CurC != '(') {
PPError (ERR_ILLEGAL_MACRO_CALL);
return 0;
}
/* Eat the left paren */
++lptr;
NextChar ();
/* Read the actual macro arguments and store pointers to these arguments
* into the array of actual arguments in the macro definition.
@ -244,52 +257,59 @@ static int MacroCall (Macro* M)
ArgStart = Buf;
B = Buf;
while (1) {
C = *lptr;
if (C == '(') {
*B++ = gch ();
if (CurC == '(') {
/* Nested parenthesis */
*B++ = CurC;
NextChar ();
++ParCount;
} else if (IsQuoteChar(C)) {
B = CopyQuotedString (C, B);
} else if (C == ',' || C == ')') {
} else if (IsQuoteChar (CurC)) {
B = CopyQuotedString (B);
} else if (CurC == ',' || CurC == ')') {
if (ParCount == 0) {
/* End of actual argument */
gch ();
/* End of actual argument */
*B++ = '\0';
while (IsBlank(*ArgStart)) {
++ArgStart;
}
while (IsBlank(*ArgStart)) {
++ArgStart;
}
if (ArgCount < M->ArgCount) {
M->ActualArgs[ArgCount++] = ArgStart;
} else if (C != ')' || *ArgStart != '\0' || M->ArgCount > 0) {
/* Be sure not to count the single empty argument for a
* macro that does not have arguments.
*/
} else if (CurC != ')' || *ArgStart != '\0' || M->ArgCount > 0) {
/* Be sure not to count the single empty argument for a
* macro that does not have arguments.
*/
++ArgCount;
}
/* Check for end of macro param list */
if (CurC == ')') {
NextChar ();
break;
}
/* Start the next one */
/* Start the next param */
ArgStart = B;
if (C == ')') {
break;
}
NextChar ();
} else {
*B++ = gch ();
if (C == ')') {
/* Comma or right paren inside nested parenthesis */
if (CurC == ')') {
--ParCount;
}
*B++ = CurC;
NextChar ();
}
} else if (IsBlank (C)) {
} else if (IsBlank (CurC)) {
/* Squeeze runs of blanks */
*B++ = ' ';
skipblank ();
} else if (C == '\0') {
SkipBlank ();
} else if (CurC == '\0') {
/* End of line inside macro argument list - read next line */
if (NextLine () == 0) {
return 0;
}
} else {
/* Just copy the character */
*B++ = *lptr++;
*B++ = CurC;
NextChar ();
}
}
@ -331,14 +351,14 @@ static void ExpandMacro (Macro* M)
static void addmac (void)
/* Add a macro to the macro table. */
{
char* saveptr;
ident Ident;
char Buf[LINESIZE];
Macro* M;
char* saveptr;
ident Ident;
char Buf[LINESIZE];
Macro* M;
/* Read the macro name */
skipblank ();
if (!macname (Ident)) {
SkipBlank ();
if (!MacName (Ident)) {
return;
}
@ -346,34 +366,36 @@ static void addmac (void)
M = NewMacro (Ident);
/* Check if this is a function like macro */
if (*lptr == '(') {
if (CurC == '(') {
/* Skip the left paren */
gch ();
NextChar ();
/* Set the marker that this is a function like macro */
M->ArgCount = 0;
/* Read the formal parameter list */
while (1) {
skipblank ();
if (*lptr == ')')
SkipBlank ();
if (CurC == ')')
break;
if (macname (Ident) == 0) {
if (MacName (Ident) == 0) {
return;
}
AddMacroArg (M, Ident);
skipblank ();
if (*lptr != ',')
SkipBlank ();
if (CurC != ',')
break;
gch ();
NextChar ();
}
if (*lptr != ')') {
/* Check for a right paren and eat it if we find one */
if (CurC != ')') {
PPError (ERR_RPAREN_EXPECTED);
ClearLine ();
return;
}
gch ();
NextChar ();
}
/* Insert the macro into the macro table and allocate the ActualArgs array */
@ -382,7 +404,7 @@ static void addmac (void)
/* Remove whitespace and comments from the line, store the preprocessed
* line into Buf.
*/
skipblank ();
SkipBlank ();
saveptr = mptr;
Pass1 (lptr, Buf);
mptr = saveptr;
@ -399,59 +421,63 @@ static void addmac (void)
static int Pass1 (char* from, char* to)
/* Preprocessor pass 1. Remove whitespace and comments. */
static int Pass1 (const char* From, char* To)
/* Preprocessor pass 1. Remove whitespace and comments. */
{
int c;
int done;
ident Ident;
int HaveParen;
int done;
ident Ident;
int HaveParen;
lptr = from;
mptr = to;
/* Initialize reading from "From" */
InitLine (From);
/* Target is "To" */
mptr = To;
/* Loop removing ws and comments */
done = 1;
while ((c = *lptr) != 0) {
if (IsBlank (c)) {
while (CurC != '\0') {
if (IsBlank (CurC)) {
keepch (' ');
skipblank ();
} else if (IsIdent (c)) {
symname (Ident);
SkipBlank ();
} else if (IsIdent (CurC)) {
SymName (Ident);
if (Preprocessing && strcmp(Ident, "defined") == 0) {
/* Handle the "defined" operator */
skipblank();
HaveParen = 0;
if (*lptr == '(') {
HaveParen = 1;
++lptr;
skipblank();
}
if (!IsIdent(c)) {
PPError (ERR_IDENT_EXPECTED);
*mptr++ = '0';
} else {
symname (Ident);
*mptr++ = IsMacro(Ident)? '1' : '0';
if (HaveParen) {
skipblank();
if (*lptr != ')') {
PPError (ERR_RPAREN_EXPECTED);
} else {
++lptr;
}
}
}
/* Handle the "defined" operator */
SkipBlank();
HaveParen = 0;
if (CurC == '(') {
HaveParen = 1;
NextChar ();
SkipBlank();
}
if (!IsIdent (CurC)) {
PPError (ERR_IDENT_EXPECTED);
*mptr++ = '0';
} else {
SymName (Ident);
*mptr++ = IsMacro (Ident)? '1' : '0';
if (HaveParen) {
SkipBlank();
if (CurC != ')') {
PPError (ERR_RPAREN_EXPECTED);
} else {
NextChar ();
}
}
}
} else {
if (MaybeMacro(c)) {
done = 0;
}
keepstr (Ident);
if (MaybeMacro (Ident[0])) {
done = 0;
}
keepstr (Ident);
}
} else if (IsQuoteChar(c)) {
mptr = CopyQuotedString (c, mptr);
} else if (c == '/' && nch () == '*') {
} else if (IsQuoteChar (CurC)) {
mptr = CopyQuotedString (mptr);
} else if (CurC == '/' && NextC == '*') {
keepch (' ');
comment ();
} else if (ANSI == 0 && c == '/' && nch () == '/') {
Comment ();
} else if (ANSI == 0 && CurC == '/' && NextC == '/') {
keepch (' ');
/* Beware: Because line continuation chars are handled when reading
* lines, we may only skip til the end of the source line, which
@ -459,13 +485,14 @@ static int Pass1 (char* from, char* to)
* source line is denoted by a lf (\n) character.
*/
do {
++lptr;
} while (*lptr != '\n' && *lptr != '\0');
if (*lptr == '\n') {
++lptr;
NextChar ();
} while (CurC != '\n' && CurC != '\0');
if (CurC == '\n') {
NextChar ();
}
} else {
*mptr++ = *lptr++;
*mptr++ = CurC;
NextChar ();
}
}
keepch ('\0');
@ -474,32 +501,37 @@ static int Pass1 (char* from, char* to)
static int Pass2 (char *from, char *to)
static int Pass2 (const char* From, char* To)
/* Preprocessor pass 2. Perform macro substitution. */
{
int C;
int no_chg;
ident Ident;
Macro* M;
int no_chg;
ident Ident;
Macro* M;
lptr = from;
mptr = to;
/* Initialize reading from "From" */
InitLine (From);
/* Target is "To" */
mptr = To;
/* Loop substituting macros */
no_chg = 1;
while ((C = *lptr) != '\0') {
while (CurC != '\0') {
/* If we have an identifier, check if it's a macro */
if (IsIdent (C)) {
symname (Ident);
if (IsIdent (CurC)) {
SymName (Ident);
M = FindMacro (Ident);
if (M) {
ExpandMacro (M);
no_chg = 0;
ExpandMacro (M);
no_chg = 0;
} else {
keepstr (Ident);
keepstr (Ident);
}
} else if (IsQuoteChar(C)) {
mptr = CopyQuotedString (C, mptr);
} else if (IsQuoteChar(CurC)) {
mptr = CopyQuotedString (mptr);
} else {
*mptr++ = *lptr++;
*mptr++ = CurC;
NextChar ();
}
}
return no_chg;
@ -512,7 +544,6 @@ static void xlateline (void)
{
int cnt;
int Done;
char *p;
Done = Pass1 (line, mline);
if (ExpandMacros == 0) {
@ -521,7 +552,8 @@ static void xlateline (void)
}
cnt = 5;
do {
p = line;
/* Swap mline and line */
char* p = line;
line = mline;
mline = p;
if (Done)
@ -529,7 +561,9 @@ static void xlateline (void)
Done = Pass2 (line, mline);
keepch ('\0');
} while (--cnt);
lptr = line;
/* Reinitialize line parsing */
InitLine (line);
}
@ -539,8 +573,8 @@ static void doundef (void)
{
ident Ident;
skipblank ();
if (macname (Ident)) {
SkipBlank ();
if (MacName (Ident)) {
UndefineMacro (Ident);
}
}
@ -574,11 +608,18 @@ static int doiff (int skip)
Token sv2 = NextTok;
/* Remove the #if from the line and add two semicolons as sentinels */
skipblank ();
SkipBlank ();
S = line;
while ((*S++ = *lptr++) != '\0') ;
strcpy (S-1, ";;");
lptr = line;
while (CurC != '\0') {
*S++ = CurC;
NextChar ();
}
*S++ = ';';
*S++ = ';';
*S = '\0';
/* Start over parsing from line */
InitLine (line);
/* Switch into special preprocessing mode */
Preprocessing = 1;
@ -611,8 +652,8 @@ static int doifdef (int skip, int flag)
{
ident Ident;
skipblank ();
if (macname (Ident) == 0) {
SkipBlank ();
if (MacName (Ident) == 0) {
return 0;
} else {
return setmflag (skip, flag, IsMacro(Ident));
@ -624,60 +665,57 @@ static int doifdef (int skip, int flag)
static void doinclude (void)
/* Open an include file. */
{
unsigned Length;
char* End;
char* Name;
char RTerm;
unsigned DirSpec;
/* Skip blanks */
mptr = mline;
skipblank ();
SkipBlank ();
/* Get the next char and check for a valid file name terminator. Setup
* the include directory spec (SYS/USR) by looking at the terminator.
*/
switch (cgch()) {
switch (CurC) {
case '\"':
RTerm = '\"';
DirSpec = INC_USER;
break;
case '\"':
RTerm = '\"';
DirSpec = INC_USER;
break;
case '<':
RTerm = '>';
DirSpec = INC_SYS;
break;
case '<':
RTerm = '>';
DirSpec = INC_SYS;
break;
default:
PPError (ERR_INCLUDE_LTERM_EXPECTED);
goto Done;
default:
PPError (ERR_INCLUDE_LTERM_EXPECTED);
goto Done;
}
NextChar ();
/* Search for the right terminator */
End = strchr (lptr, RTerm);
if (End == 0) {
/* No terminator found */
PPError (ERR_INCLUDE_RTERM_EXPECTED);
goto Done;
/* Copy the filename into mline. Since mline has the same size as the
* input line, we don't need to check for an overflow here.
*/
mptr = mline;
while (CurC != '\0' && CurC != RTerm) {
*mptr++ = CurC;
NextChar ();
}
*mptr = '\0';
/* Create a temp copy of the filename */
Length = End - lptr;
Name = xmalloc (Length + 1);
memcpy (Name, lptr, Length);
Name[Length] = '\0';
/* Check if we got a terminator */
if (CurC != RTerm) {
/* No terminator found */
PPError (ERR_INCLUDE_RTERM_EXPECTED);
goto Done;
}
/* Open the include file */
OpenIncludeFile (Name, DirSpec);
/* Delete the temp filename copy */
xfree (Name);
OpenIncludeFile (mline, DirSpec);
Done:
/* Clear the remaining line so the next input will come from the new
* file (if open)
/* Clear the remaining line so the next input will come from the new
* file (if open)
*/
ClearLine ();
}
@ -687,8 +725,8 @@ Done:
static void doerror (void)
/* Print an error */
{
skipblank ();
if (*lptr == '\0') {
SkipBlank ();
if (CurC == '\0') {
PPError (ERR_INVALID_USER_ERROR);
} else {
PPError (ERR_USER_ERROR, lptr);
@ -704,38 +742,38 @@ static void doerror (void)
/* stuff used to bum the keyword dispatching stuff */
enum {
D_DEFINE,
D_ELSE,
D_ENDIF,
D_ERROR,
D_IF,
D_IFDEF,
D_IFNDEF,
D_INCLUDE,
D_LINE,
D_PRAGMA,
D_UNDEF,
D_ILLEGAL,
PP_DEFINE,
PP_ELSE,
PP_ENDIF,
PP_ERROR,
PP_IF,
PP_IFDEF,
PP_IFNDEF,
PP_INCLUDE,
PP_LINE,
PP_PRAGMA,
PP_UNDEF,
PP_ILLEGAL,
};
static const struct tok_elt pre_toks[] = {
{ "define", D_DEFINE },
{ "else", D_ELSE },
{ "endif", D_ENDIF },
{ "error", D_ERROR },
{ "if", D_IF },
{ "ifdef", D_IFDEF },
{ "ifndef", D_IFNDEF },
{ "include", D_INCLUDE },
{ "line", D_LINE },
{ "pragma", D_PRAGMA },
{ "undef", D_UNDEF },
{ 0, D_ILLEGAL }
{ "define", PP_DEFINE },
{ "else", PP_ELSE },
{ "endif", PP_ENDIF },
{ "error", PP_ERROR },
{ "if", PP_IF },
{ "ifdef", PP_IFDEF },
{ "ifndef", PP_IFNDEF },
{ "include", PP_INCLUDE },
{ "line", PP_LINE },
{ "pragma", PP_PRAGMA },
{ "undef", PP_UNDEF },
{ 0, PP_ILLEGAL }
};
int searchtok (const char *sym, const struct tok_elt *toks)
static int searchtok (const char *sym, const struct tok_elt *toks)
/* Search a token in a table */
{
while (toks->toknam && strcmp (toks->toknam, sym))
@ -745,123 +783,119 @@ int searchtok (const char *sym, const struct tok_elt *toks)
void preprocess (void)
void Preprocess (void)
/* Preprocess a line */
{
int c;
int Skip;
ident sname;
/* Process compiler directives, skip empty lines */
lptr = line;
ident Directive;
/* Skip white space at the beginning of the line */
skipblank ();
SkipBlank ();
/* Check for stuff to skip */
Skip = 0;
while ((c = *lptr) == '\0' || c == '#' || Skip) {
while (CurC == '\0' || CurC == '#' || Skip) {
/* Check for preprocessor lines lines */
if (c == '#') {
++lptr;
skipblank ();
if (*lptr == '\0') {
/* ignore the empty preprocessor directive */
continue;
}
if (!issym (sname)) {
PPError (ERR_CPP_DIRECTIVE_EXPECTED);
ClearLine ();
} else {
switch (searchtok (sname, pre_toks)) {
/* Check for preprocessor lines lines */
if (CurC == '#') {
NextChar ();
SkipBlank ();
if (CurC == '\0') {
/* Ignore the empty preprocessor directive */
continue;
}
if (!IsSym (Directive)) {
PPError (ERR_CPP_DIRECTIVE_EXPECTED);
ClearLine ();
} else {
switch (searchtok (Directive, pre_toks)) {
case D_DEFINE:
if (!Skip) {
addmac ();
}
break;
case PP_DEFINE:
if (!Skip) {
addmac ();
}
break;
case D_ELSE:
if (s_ifdef[i_ifdef] & 2) {
if (s_ifdef[i_ifdef] & 4) {
Skip = !Skip;
}
s_ifdef[i_ifdef] ^= 2;
} else {
PPError (ERR_UNEXPECTED_CPP_ELSE);
}
break;
case PP_ELSE:
if (s_ifdef[i_ifdef] & 2) {
if (s_ifdef[i_ifdef] & 4) {
Skip = !Skip;
}
s_ifdef[i_ifdef] ^= 2;
} else {
PPError (ERR_UNEXPECTED_CPP_ELSE);
}
break;
case D_ENDIF:
if (i_ifdef >= 0) {
Skip = s_ifdef[i_ifdef--] & 1;
} else {
PPError (ERR_UNEXPECTED_CPP_ENDIF);
}
break;
case PP_ENDIF:
if (i_ifdef >= 0) {
Skip = s_ifdef[i_ifdef--] & 1;
} else {
PPError (ERR_UNEXPECTED_CPP_ENDIF);
}
break;
case D_ERROR:
if (!Skip) {
doerror ();
}
break;
case PP_ERROR:
if (!Skip) {
doerror ();
}
break;
case D_IF:
Skip = doiff (Skip);
break;
case PP_IF:
Skip = doiff (Skip);
break;
case D_IFDEF:
Skip = doifdef (Skip, 1);
break;
case PP_IFDEF:
Skip = doifdef (Skip, 1);
break;
case D_IFNDEF:
Skip = doifdef (Skip, 0);
break;
case PP_IFNDEF:
Skip = doifdef (Skip, 0);
break;
case D_INCLUDE:
if (!Skip) {
doinclude ();
}
break;
case PP_INCLUDE:
if (!Skip) {
doinclude ();
}
break;
case D_LINE:
/* Not allowed in strict ANSI mode */
if (ANSI) {
PPError (ERR_CPP_DIRECTIVE_EXPECTED);
ClearLine ();
}
break;
case PP_LINE:
/* Not allowed in strict ANSI mode */
if (ANSI) {
PPError (ERR_CPP_DIRECTIVE_EXPECTED);
ClearLine ();
}
break;
case D_PRAGMA:
if (!Skip) {
/* Don't expand macros in this line */
ExpandMacros = 0;
/* #pragma is handled on the scanner level */
goto Done;
}
break;
case PP_PRAGMA:
if (!Skip) {
/* Don't expand macros in this line */
ExpandMacros = 0;
/* #pragma is handled on the scanner level */
goto Done;
}
break;
case D_UNDEF:
if (!Skip) {
doundef ();
}
break;
case PP_UNDEF:
if (!Skip) {
doundef ();
}
break;
default:
PPError (ERR_CPP_DIRECTIVE_EXPECTED);
ClearLine ();
}
default:
PPError (ERR_CPP_DIRECTIVE_EXPECTED);
ClearLine ();
}
}
}
if (NextLine () == 0) {
if (i_ifdef >= 0) {
PPError (ERR_CPP_ENDIF_EXPECTED);
PPError (ERR_CPP_ENDIF_EXPECTED);
}
return;
}
skipblank ();
SkipBlank ();
}
Done:

View file

@ -34,10 +34,7 @@ extern unsigned char Preprocessing;
int searchtok (const char *sym, const struct tok_elt* toks);
/* Search a token in a table */
void preprocess (void);
void Preprocess (void);
/* Preprocess a line */

View file

@ -43,7 +43,7 @@ Token NextTok; /* The next token */
#define TT_EXT 1 /* cc65 extension */
/* Token table */
static struct Keyword {
static const struct Keyword {
char* Key; /* Keyword name */
unsigned char Tok; /* The token */
unsigned char Type; /* Token type */
@ -114,7 +114,7 @@ static int CmpKey (const void* Key, const void* Elem)
static int FindKey (char* Key)
static int FindKey (const char* Key)
/* Find a keyword and return the token. Return IDENT if the token is not a
* keyword.
*/
@ -129,21 +129,21 @@ static int FindKey (char* Key)
}
static int skipwhite (void)
static int SkipWhite (void)
/* Skip white space in the input stream, reading and preprocessing new lines
* if necessary. Return 0 if end of file is reached, return 1 otherwise.
*/
{
while (1) {
while (*lptr == 0) {
while (CurC == 0) {
if (NextLine () == 0) {
return 0;
}
preprocess ();
Preprocess ();
}
if (*lptr == ' ' || *lptr == '\r') {
++lptr;
if (CurC == ' ' || CurC == '\r') {
NextChar ();
} else {
return 1;
}
@ -152,27 +152,27 @@ static int skipwhite (void)
void symname (char *s)
void SymName (char* s)
/* Get symbol from input stream */
{
unsigned k = 0;
do {
if (k != MAX_IDENTLEN) {
++k;
*s++ = *lptr;
if (k != MAX_IDENTLEN) {
++k;
*s++ = CurC;
}
++lptr;
} while (IsIdent (*lptr) || isdigit (*lptr));
NextChar ();
} while (IsIdent (CurC) || isdigit (CurC));
*s = '\0';
}
int issym (char *s)
int IsSym (char *s)
/* Get symbol from input stream or return 0 if not a symbol. */
{
if (IsIdent (*lptr)) {
symname (s);
if (IsIdent (CurC)) {
SymName (s);
return 1;
} else {
return 0;
@ -181,11 +181,11 @@ int issym (char *s)
static void unknown (unsigned char c)
static void unknown (char C)
/* Error message for unknown character */
{
Error (ERR_INVALID_CHAR, c);
gch (); /* Skip */
Error (ERR_INVALID_CHAR, C);
NextChar (); /* Skip */
}
@ -209,7 +209,7 @@ static void SetTok (int tok)
/* set nxttok and bump line ptr */
{
nxttok = tok;
++lptr;
NextChar ();
}
@ -226,63 +226,73 @@ static int SignExtendChar (int C)
static int parsechar (int c)
static int ParseChar (void)
/* Parse a character. Converts \n into EOL, etc. */
{
int i;
int val;
unsigned val;
int C;
/* Check for escape chars */
if (c == '\\') {
switch (c = gch ()) {
if (CurC == '\\') {
NextChar ();
switch (CurC) {
case 'b':
c = '\b';
C = '\b';
break;
case 'f':
c = '\f';
case 'f':
C = '\f';
break;
case 'r':
c = '\r';
C = '\r';
break;
case 'n':
c = '\n';
C = '\n';
break;
case 't':
c = '\t';
C = '\t';
break;
case '\"':
c = '\"';
C = '\"';
break;
case '\'':
c = '\'';
C = '\'';
break;
case '\\':
c = '\\';
C = '\\';
break;
case 'x':
case 'X':
/* Hex character constant */
val = hexval (gch ()) << 4;
c = val | hexval (gch ()); /* Do not translate */
NextChar ();
val = hexval (CurC) << 4;
NextChar ();
C = val | hexval (CurC); /* Do not translate */
break;
case '0':
case '1':
/* Octal constant */
i = 0;
val = c - '0';
while ((c = *lptr) >= '0' && c <= '7' && i++ < 4) {
val = (val << 3) | (c - '0');
gch ();
}
c = val; /* Do not translate */
C = CurC - '0';
while (NextC >= '0' && NextC <= '7' && i++ < 4) {
NextChar ();
C = (C << 3) | (CurC - '0');
}
break;
default:
Error (ERR_ILLEGAL_CHARCONST);
C = ' ';
break;
default:
Error (ERR_ILLEGAL_CHARCONST);
}
}
} else {
C = CurC;
}
/* Skip the character read */
NextChar ();
/* Do correct sign extension */
return SignExtendChar (c);
return SignExtendChar (C);
}
@ -290,22 +300,25 @@ static int parsechar (int c)
static void CharConst (void)
/* Parse a character constant. */
{
int c;
int C;
/* Skip the quote */
++lptr;
NextChar ();
/* Get character */
c = parsechar (cgch ());
C = ParseChar ();
/* Check for closing quote */
if (cgch () != '\'') {
if (CurC != '\'') {
Error (ERR_QUOTE_EXPECTED);
} else {
/* Skip the quote */
NextChar ();
}
/* Setup values and attributes */
nxttok = TOK_CCONST;
nxtval = SignExtendChar (ctrans (c)); /* Translate into target charset */
nxtval = SignExtendChar (ctrans (C)); /* Translate into target charset */
nxttype = type_int; /* Character constants have type int */
}
@ -318,24 +331,24 @@ static void StringConst (void)
nxttok = TOK_SCONST;
/* Be sure to concatenate strings */
while (*lptr == '\"') {
while (CurC == '\"') {
/* Skip the quote char */
++lptr;
NextChar ();
while (*lptr != '\"') {
if (*lptr == 0) {
while (CurC != '\"') {
if (CurC == '\0') {
Error (ERR_UNEXPECTED_NEWLINE);
break;
}
AddLiteralChar (parsechar (gch()));
AddLiteralChar (ParseChar ());
}
/* Skip closing quote char if there was one */
cgch ();
NextChar ();
/* Skip white space, read new input */
skipwhite ();
SkipWhite ();
}
@ -348,7 +361,6 @@ static void StringConst (void)
void NextToken (void)
/* Get next token from input stream */
{
char c;
ident token;
/* Current token is the lookahead token */
@ -358,15 +370,14 @@ void NextToken (void)
NextTok.Pos = GetCurrentLine();
/* Skip spaces and read the next line if needed */
if (skipwhite () == 0) {
if (SkipWhite () == 0) {
/* End of file reached */
nxttok = TOK_CEOF;
return;
}
/* Determine the next token from the lookahead */
c = *lptr;
if (isdigit (c)) {
if (isdigit (CurC)) {
/* A number */
int HaveSuffix; /* True if we have a type suffix */
@ -378,49 +389,48 @@ void NextToken (void)
base = 10;
types = IT_INT | IT_LONG | IT_ULONG;
if (c == '0') {
if (CurC == '0') {
/* Octal or hex constants may also be of type unsigned int */
types = IT_INT | IT_UINT | IT_LONG | IT_ULONG;
/* gobble 0 and examin next char */
if (toupper (*++lptr) == 'X') {
NextChar ();
if (toupper (CurC) == 'X') {
base = 16;
nxttype = type_uint;
++lptr; /* gobble "x" */
NextChar (); /* gobble "x" */
} else {
base = 8;
}
}
while (1) {
c = *lptr;
if (isdigit (c)) {
k = k * base + (c - '0');
} else if (base == 16 && isxdigit (c)) {
k = (k << 4) + hexval (c);
if (isdigit (CurC)) {
k = k * base + (CurC - '0');
} else if (base == 16 && isxdigit (CurC)) {
k = (k << 4) + hexval (CurC);
} else {
break; /* not digit */
}
++lptr; /* gobble char */
NextChar (); /* gobble char */
}
/* Check for a suffix */
HaveSuffix = 1;
c = toupper (*lptr);
if (c == 'U') {
if (CurC == 'u' || CurC == 'U') {
/* Unsigned type */
++lptr;
if (toupper (*lptr) != 'L') {
NextChar ();
if (toupper (CurC) != 'L') {
types = IT_UINT | IT_ULONG;
} else {
++lptr;
NextChar ();
types = IT_ULONG;
}
} else if (c == 'L') {
} else if (CurC == 'l' || CurC == 'L') {
/* Long type */
++lptr;
if (toupper (*lptr) != 'U') {
NextChar ();
if (toupper (CurC) != 'U') {
types = IT_LONG | IT_ULONG;
} else {
++lptr;
NextChar ();
types = IT_ULONG;
}
} else {
@ -465,7 +475,7 @@ void NextToken (void)
return;
}
if (issym (token)) {
if (IsSym (token)) {
/* Check for a keyword */
if ((nxttok = FindKey (token)) != TOK_IDENT) {
@ -506,10 +516,11 @@ void NextToken (void)
}
/* Monstrous switch statement ahead... */
switch (c) {
switch (CurC) {
case '!':
if (*++lptr == '=') {
NextChar ();
if (CurC == '=') {
SetTok (TOK_NE);
} else {
nxttok = TOK_BOOL_NOT;
@ -521,7 +532,8 @@ void NextToken (void)
break;
case '%':
if (*++lptr == '=') {
NextChar ();
if (CurC == '=') {
SetTok (TOK_MOD_ASSIGN);
} else {
nxttok = TOK_MOD;
@ -529,7 +541,8 @@ void NextToken (void)
break;
case '&':
switch (*++lptr) {
NextChar ();
switch (CurC) {
case '&':
SetTok (TOK_BOOL_AND);
break;
@ -554,7 +567,8 @@ void NextToken (void)
break;
case '*':
if (*++lptr == '=') {
NextChar ();
if (CurC == '=') {
SetTok (TOK_MUL_ASSIGN);
} else {
nxttok = TOK_STAR;
@ -562,7 +576,8 @@ void NextToken (void)
break;
case '+':
switch (*++lptr) {
NextChar ();
switch (CurC) {
case '+':
SetTok (TOK_INC);
break;
@ -579,7 +594,8 @@ void NextToken (void)
break;
case '-':
switch (*++lptr) {
NextChar ();
switch (CurC) {
case '-':
SetTok (TOK_DEC);
break;
@ -595,11 +611,13 @@ void NextToken (void)
break;
case '.':
if (*++lptr == '.') {
if (*++lptr == '.') {
NextChar ();
if (CurC == '.') {
NextChar ();
if (CurC == '.') {
SetTok (TOK_ELLIPSIS);
} else {
unknown (*lptr);
unknown (CurC);
}
} else {
nxttok = TOK_DOT;
@ -607,7 +625,8 @@ void NextToken (void)
break;
case '/':
if (*++lptr == '=') {
NextChar ();
if (CurC == '=') {
SetTok (TOK_DIV_ASSIGN);
} else {
nxttok = TOK_DIV;
@ -623,12 +642,14 @@ void NextToken (void)
break;
case '<':
switch (*++lptr) {
NextChar ();
switch (CurC) {
case '=':
SetTok (TOK_LE);
break;
case '<':
if (*++lptr == '=') {
NextChar ();
if (CurC == '=') {
SetTok (TOK_SHL_ASSIGN);
} else {
nxttok = TOK_SHL;
@ -640,7 +661,8 @@ void NextToken (void)
break;
case '=':
if (*++lptr == '=') {
NextChar ();
if (CurC == '=') {
SetTok (TOK_EQ);
} else {
nxttok = TOK_ASSIGN;
@ -648,12 +670,14 @@ void NextToken (void)
break;
case '>':
switch (*++lptr) {
NextChar ();
switch (CurC) {
case '=':
SetTok (TOK_GE);
break;
case '>':
if (*++lptr == '=') {
NextChar ();
if (CurC == '=') {
SetTok (TOK_SHR_ASSIGN);
} else {
nxttok = TOK_SHR;
@ -677,7 +701,8 @@ void NextToken (void)
break;
case '^':
if (*++lptr == '=') {
NextChar ();
if (CurC == '=') {
SetTok (TOK_XOR_ASSIGN);
} else {
nxttok = TOK_XOR;
@ -689,7 +714,8 @@ void NextToken (void)
break;
case '|':
switch (*++lptr) {
NextChar ();
switch (CurC) {
case '|':
SetTok (TOK_BOOL_OR);
break;
@ -710,8 +736,11 @@ void NextToken (void)
break;
case '#':
while (*++lptr == ' ') ; /* Skip it and following whitespace */
if (!issym (token) || strcmp (token, "pragma") != 0) {
/* Skip it and following whitespace */
do {
NextChar ();
} while (CurC == ' ');
if (!IsSym (token) || strcmp (token, "pragma") != 0) {
/* OOPS - should not happen */
Error (ERR_CPP_DIRECTIVE_EXPECTED);
}
@ -719,7 +748,7 @@ void NextToken (void)
break;
default:
unknown (c);
unknown (CurC);
}

View file

@ -172,13 +172,13 @@ extern Token NextTok; /* The next token */
void symname (char* s);
void SymName (char* s);
/* Get symbol from input stream */
int issym (char* s);
int IsSym (char* s);
/* Get symbol from input stream or return 0 if not a symbol. */
void NextToken (void);
void NextToken (void);
/* Get next token from input stream */
void Consume (token_t Token, unsigned ErrNum);