Fixed a bug
git-svn-id: svn://svn.cc65.org/cc65/trunk@91 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -800,7 +800,7 @@ static int primary (struct expent* lval)
|
|||||||
* and returning int.
|
* and returning int.
|
||||||
*/
|
*/
|
||||||
Warning (WARN_FUNC_WITHOUT_PROTO);
|
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_tptr = Sym->Type;
|
||||||
lval->e_flags = E_MGLOBAL | E_MCONST | E_TGLAB;
|
lval->e_flags = E_MGLOBAL | E_MCONST | E_TGLAB;
|
||||||
lval->e_name = (unsigned long) Sym->Name;
|
lval->e_name = (unsigned long) Sym->Name;
|
||||||
|
|||||||
133
src/cc65/input.c
133
src/cc65/input.c
@@ -49,7 +49,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Data */
|
/* Data */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
@@ -57,32 +57,39 @@
|
|||||||
/* Input line stuff */
|
/* Input line stuff */
|
||||||
static char LineBuf [LINESIZE];
|
static char LineBuf [LINESIZE];
|
||||||
char* line = LineBuf;
|
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 */
|
/* Maximum count of nested includes */
|
||||||
#define MAX_INC_NESTING 20
|
#define MAX_INC_NESTING 16
|
||||||
|
|
||||||
/* Struct that describes an input file */
|
/* Struct that describes an input file */
|
||||||
typedef struct IFile IFile;
|
typedef struct IFile IFile;
|
||||||
struct 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 */
|
IFile* Active; /* Next file in list of active includes */
|
||||||
unsigned Index; /* File index */
|
unsigned Index; /* File index */
|
||||||
unsigned Line; /* Line number for this file */
|
unsigned Line; /* Line number for this file */
|
||||||
FILE* F; /* Input file stream */
|
FILE* F; /* Input file stream */
|
||||||
char Name[1]; /* Name of file (dynamically allocated) */
|
char Name[1]; /* Name of file (dynamically allocated) */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Main file input data */
|
||||||
|
static const IFile* MainFile = 0;
|
||||||
|
|
||||||
/* List of input files */
|
/* List of input files */
|
||||||
static unsigned IFileTotal = 0; /* Total number of 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 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;
|
IF->Active = Input;
|
||||||
Input = IF;
|
Input = IF;
|
||||||
++IFileCount;
|
++IFileCount;
|
||||||
|
++IFileTotal;
|
||||||
|
|
||||||
/* Return the new struct */
|
/* Return the new struct */
|
||||||
return IF;
|
return IF;
|
||||||
@@ -132,7 +140,7 @@ void OpenMainFile (const char* Name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Setup a new IFile structure */
|
/* 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 */
|
/* Make this file inactive and the last one active again */
|
||||||
Input = Input->Active;
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ClearLine (void)
|
|
||||||
/* Clear the current input line */
|
|
||||||
{
|
|
||||||
line [0] = '\0';
|
|
||||||
lptr = line;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const char* GetCurrentFile (void)
|
const char* GetCurrentFile (void)
|
||||||
/* Return the name of the current input file */
|
/* Return the name of the current input file */
|
||||||
{
|
{
|
||||||
if (Input == 0) {
|
if (Input == 0) {
|
||||||
return "(outside file scope)";
|
if (MainFile) {
|
||||||
|
return MainFile->Name;
|
||||||
|
} else {
|
||||||
|
return "(outside file scope)";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return Input->Name;
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,11 @@
|
|||||||
|
|
||||||
/* Input line stuff */
|
/* Input line stuff */
|
||||||
extern char* line;
|
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);
|
void OpenIncludeFile (const char* Name, unsigned DirSpec);
|
||||||
/* Open an include file and insert it into the tables. */
|
/* 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);
|
void ClearLine (void);
|
||||||
/* Clear the current input line */
|
/* 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);
|
const char* GetCurrentFile (void);
|
||||||
/* Return the name of the current input file */
|
/* Return the name of the current input file */
|
||||||
|
|
||||||
unsigned GetCurrentLine (void);
|
unsigned GetCurrentLine (void);
|
||||||
/* Return the line number in the current input file */
|
/* 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 */
|
/* End of input.h */
|
||||||
|
|||||||
@@ -40,7 +40,6 @@
|
|||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "litpool.h"
|
#include "litpool.h"
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
#include "preproc.h"
|
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "codegen.h"
|
#include "codegen.h"
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
@@ -55,7 +54,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/* Tokens for the #pragmas */
|
/* Tokens for the #pragmas */
|
||||||
enum {
|
typedef enum {
|
||||||
PR_BSSSEG,
|
PR_BSSSEG,
|
||||||
PR_CODESEG,
|
PR_CODESEG,
|
||||||
PR_DATASEG,
|
PR_DATASEG,
|
||||||
@@ -65,16 +64,54 @@ enum {
|
|||||||
PR_STATICLOCALS,
|
PR_STATICLOCALS,
|
||||||
PR_ZPSYM,
|
PR_ZPSYM,
|
||||||
PR_ILLEGAL
|
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*))
|
static void StringPragma (void (*Func) (const char*))
|
||||||
/* Handle a pragma that expects a string parameter */
|
/* Handle a pragma that expects a string parameter */
|
||||||
{
|
{
|
||||||
@@ -113,19 +150,7 @@ static void FlagPragma (unsigned char* Flag)
|
|||||||
void DoPragma (void)
|
void DoPragma (void)
|
||||||
/* Handle pragmas */
|
/* Handle pragmas */
|
||||||
{
|
{
|
||||||
static const struct tok_elt Pragmas [] = {
|
pragma_t Pragma;
|
||||||
{ "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;
|
|
||||||
|
|
||||||
/* Skip the token itself */
|
/* Skip the token itself */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
@@ -137,7 +162,7 @@ void DoPragma (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Do we know this pragma? */
|
/* Do we know this pragma? */
|
||||||
Pragma = searchtok (CurTok.Ident, Pragmas);
|
Pragma = FindPragma (CurTok.Ident);
|
||||||
if (Pragma == PR_ILLEGAL) {
|
if (Pragma == PR_ILLEGAL) {
|
||||||
/* According to the ANSI standard, we're not allowed to generate errors
|
/* According to the ANSI standard, we're not allowed to generate errors
|
||||||
* for unknown pragmas, however, we're allowed to warn - and we will
|
* for unknown pragmas, however, we're allowed to warn - and we will
|
||||||
|
|||||||
@@ -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;
|
unsigned char Preprocessing = 0;
|
||||||
|
|
||||||
/* Management data for #if */
|
/* Management data for #if */
|
||||||
#define N_IFDEF 16
|
#define N_IFDEF 16
|
||||||
static int i_ifdef = -1;
|
static int i_ifdef = -1;
|
||||||
static char s_ifdef[N_IFDEF];
|
static char s_ifdef[N_IFDEF];
|
||||||
|
|
||||||
@@ -81,63 +82,76 @@ static void keepstr (const char* S)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void comment (void)
|
static void Comment (void)
|
||||||
/* Remove comment from line. */
|
/* 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();
|
unsigned StartingLine = GetCurrentLine();
|
||||||
|
|
||||||
gch ();
|
/* Skip the start of comment chars */
|
||||||
gch ();
|
NextChar ();
|
||||||
while (*lptr != '*' || nch () != '/') {
|
NextChar ();
|
||||||
if (*lptr == '\0') {
|
|
||||||
|
/* Skip the comment */
|
||||||
|
while (CurC != '*' || NextC != '/') {
|
||||||
|
if (CurC == '\0') {
|
||||||
if (NextLine () == 0) {
|
if (NextLine () == 0) {
|
||||||
PPError (ERR_EOF_IN_COMMENT, StartingLine);
|
PPError (ERR_EOF_IN_COMMENT, StartingLine);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (*lptr == '/' && nch() == '*') {
|
if (CurC == '/' && NextC == '*') {
|
||||||
PPWarning (WARN_NESTED_COMMENT);
|
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. */
|
/* Skip blanks and tabs in the input stream. */
|
||||||
{
|
{
|
||||||
while (IsBlank (*lptr)) {
|
while (IsBlank (CurC)) {
|
||||||
++lptr;
|
NextChar ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static char* CopyQuotedString (int Quote, char* Target)
|
static char* CopyQuotedString (char* Target)
|
||||||
/* Copy a single or double quoted string from lptr to Target. Return the
|
/* 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.
|
* new target pointer. Target will not be terminated after the copy.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
/* Copy the starting quote */
|
/* Remember the quote character, copy it to the target buffer and skip it */
|
||||||
*Target++ = gch();
|
char Quote = CurC;
|
||||||
|
*Target++ = CurC;
|
||||||
|
NextChar ();
|
||||||
|
|
||||||
/* Copy the characters inside the string */
|
/* Copy the characters inside the string */
|
||||||
while (*lptr != '\0' && *lptr != Quote) {
|
while (CurC != '\0' && CurC != Quote) {
|
||||||
/* Keep an escaped char */
|
/* Keep an escaped char */
|
||||||
if (*lptr == '\\') {
|
if (CurC == '\\') {
|
||||||
*Target++ = gch();
|
*Target++ = CurC;
|
||||||
|
NextChar ();
|
||||||
}
|
}
|
||||||
/* Copy the character */
|
/* Copy the character */
|
||||||
*Target++ = cgch();
|
*Target++ = CurC;
|
||||||
|
NextChar ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we had a terminating quote, copy it */
|
/* If we had a terminating quote, copy it */
|
||||||
if (*lptr) {
|
if (CurC != '\0') {
|
||||||
*Target++ = gch();
|
*Target++ = CurC;
|
||||||
|
NextChar ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the new target pointer */
|
/* 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. */
|
/* Get macro symbol name. If error, print message and clear line. */
|
||||||
{
|
{
|
||||||
if (issym (sname) == 0) {
|
if (IsSym (Ident) == 0) {
|
||||||
PPError (ERR_IDENT_EXPECTED);
|
PPError (ERR_IDENT_EXPECTED);
|
||||||
ClearLine ();
|
ClearLine ();
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
@@ -169,20 +183,19 @@ static int macname (char *sname)
|
|||||||
static void ExpandMacroArgs (Macro* M)
|
static void ExpandMacroArgs (Macro* M)
|
||||||
/* Preprocessor pass 2. Perform macro substitution. */
|
/* Preprocessor pass 2. Perform macro substitution. */
|
||||||
{
|
{
|
||||||
int C;
|
|
||||||
ident Ident;
|
ident Ident;
|
||||||
const char* Replacement;
|
const char* Replacement;
|
||||||
char* SavePtr;
|
const char* SavePtr;
|
||||||
|
|
||||||
/* Save the current line pointer and setup the new ones */
|
/* Save the current line pointer and setup the new ones */
|
||||||
SavePtr = lptr;
|
SavePtr = lptr;
|
||||||
lptr = M->Replacement;
|
InitLine (M->Replacement);
|
||||||
|
|
||||||
/* Copy the macro replacement checking for parameters to replace */
|
/* 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 the next token is an identifier, check for a macro arg */
|
||||||
if (IsIdent (C)) {
|
if (IsIdent (CurC)) {
|
||||||
symname (Ident);
|
SymName (Ident);
|
||||||
Replacement = FindMacroArg (M, Ident);
|
Replacement = FindMacroArg (M, Ident);
|
||||||
if (Replacement) {
|
if (Replacement) {
|
||||||
/* Macro arg, keep the replacement */
|
/* Macro arg, keep the replacement */
|
||||||
@@ -191,9 +204,9 @@ static void ExpandMacroArgs (Macro* M)
|
|||||||
/* No macro argument, keep the original identifier */
|
/* No macro argument, keep the original identifier */
|
||||||
keepstr (Ident);
|
keepstr (Ident);
|
||||||
}
|
}
|
||||||
} else if (C == '#' && IsIdent (nch ())) {
|
} else if (CurC == '#' && IsIdent (NextC)) {
|
||||||
++lptr;
|
NextChar ();
|
||||||
symname (Ident);
|
SymName (Ident);
|
||||||
Replacement = FindMacroArg (M, Ident);
|
Replacement = FindMacroArg (M, Ident);
|
||||||
if (Replacement) {
|
if (Replacement) {
|
||||||
keepch ('\"');
|
keepch ('\"');
|
||||||
@@ -203,15 +216,16 @@ static void ExpandMacroArgs (Macro* M)
|
|||||||
keepch ('#');
|
keepch ('#');
|
||||||
keepstr (Ident);
|
keepstr (Ident);
|
||||||
}
|
}
|
||||||
} else if (IsQuoteChar(C)) {
|
} else if (IsQuoteChar (CurC)) {
|
||||||
mptr = CopyQuotedString (C, mptr);
|
mptr = CopyQuotedString (mptr);
|
||||||
} else {
|
} else {
|
||||||
*mptr++ = *lptr++;
|
*mptr++ = CurC;
|
||||||
|
NextChar ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the line pointer */
|
/* Reset the line pointer */
|
||||||
lptr = SavePtr;
|
InitLine (SavePtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -219,22 +233,21 @@ static void ExpandMacroArgs (Macro* M)
|
|||||||
static int MacroCall (Macro* M)
|
static int MacroCall (Macro* M)
|
||||||
/* Process a function like macro */
|
/* Process a function like macro */
|
||||||
{
|
{
|
||||||
unsigned ArgCount; /* Macro argument count */
|
unsigned ArgCount; /* Macro argument count */
|
||||||
unsigned ParCount; /* Number of open parenthesis */
|
unsigned ParCount; /* Number of open parenthesis */
|
||||||
char Buf[LINESIZE]; /* Argument buffer */
|
char Buf[LINESIZE]; /* Argument buffer */
|
||||||
char C;
|
|
||||||
const char* ArgStart;
|
const char* ArgStart;
|
||||||
char* B;
|
char* B;
|
||||||
|
|
||||||
/* Expect an argument list */
|
/* Expect an argument list */
|
||||||
skipblank ();
|
SkipBlank ();
|
||||||
if (*lptr != '(') {
|
if (CurC != '(') {
|
||||||
PPError (ERR_ILLEGAL_MACRO_CALL);
|
PPError (ERR_ILLEGAL_MACRO_CALL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Eat the left paren */
|
/* Eat the left paren */
|
||||||
++lptr;
|
NextChar ();
|
||||||
|
|
||||||
/* Read the actual macro arguments and store pointers to these arguments
|
/* Read the actual macro arguments and store pointers to these arguments
|
||||||
* into the array of actual arguments in the macro definition.
|
* into the array of actual arguments in the macro definition.
|
||||||
@@ -244,52 +257,59 @@ static int MacroCall (Macro* M)
|
|||||||
ArgStart = Buf;
|
ArgStart = Buf;
|
||||||
B = Buf;
|
B = Buf;
|
||||||
while (1) {
|
while (1) {
|
||||||
C = *lptr;
|
if (CurC == '(') {
|
||||||
if (C == '(') {
|
/* Nested parenthesis */
|
||||||
*B++ = gch ();
|
*B++ = CurC;
|
||||||
|
NextChar ();
|
||||||
++ParCount;
|
++ParCount;
|
||||||
} else if (IsQuoteChar(C)) {
|
} else if (IsQuoteChar (CurC)) {
|
||||||
B = CopyQuotedString (C, B);
|
B = CopyQuotedString (B);
|
||||||
} else if (C == ',' || C == ')') {
|
} else if (CurC == ',' || CurC == ')') {
|
||||||
if (ParCount == 0) {
|
if (ParCount == 0) {
|
||||||
/* End of actual argument */
|
/* End of actual argument */
|
||||||
gch ();
|
|
||||||
*B++ = '\0';
|
*B++ = '\0';
|
||||||
while (IsBlank(*ArgStart)) {
|
while (IsBlank(*ArgStart)) {
|
||||||
++ArgStart;
|
++ArgStart;
|
||||||
}
|
}
|
||||||
if (ArgCount < M->ArgCount) {
|
if (ArgCount < M->ArgCount) {
|
||||||
M->ActualArgs[ArgCount++] = ArgStart;
|
M->ActualArgs[ArgCount++] = ArgStart;
|
||||||
} else if (C != ')' || *ArgStart != '\0' || M->ArgCount > 0) {
|
} else if (CurC != ')' || *ArgStart != '\0' || M->ArgCount > 0) {
|
||||||
/* Be sure not to count the single empty argument for a
|
/* Be sure not to count the single empty argument for a
|
||||||
* macro that does not have arguments.
|
* macro that does not have arguments.
|
||||||
*/
|
*/
|
||||||
++ArgCount;
|
++ArgCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for end of macro param list */
|
||||||
|
if (CurC == ')') {
|
||||||
|
NextChar ();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Start the next one */
|
/* Start the next param */
|
||||||
ArgStart = B;
|
ArgStart = B;
|
||||||
if (C == ')') {
|
NextChar ();
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
*B++ = gch ();
|
/* Comma or right paren inside nested parenthesis */
|
||||||
if (C == ')') {
|
if (CurC == ')') {
|
||||||
--ParCount;
|
--ParCount;
|
||||||
}
|
}
|
||||||
|
*B++ = CurC;
|
||||||
|
NextChar ();
|
||||||
}
|
}
|
||||||
} else if (IsBlank (C)) {
|
} else if (IsBlank (CurC)) {
|
||||||
/* Squeeze runs of blanks */
|
/* Squeeze runs of blanks */
|
||||||
*B++ = ' ';
|
*B++ = ' ';
|
||||||
skipblank ();
|
SkipBlank ();
|
||||||
} else if (C == '\0') {
|
} else if (CurC == '\0') {
|
||||||
/* End of line inside macro argument list - read next line */
|
/* End of line inside macro argument list - read next line */
|
||||||
if (NextLine () == 0) {
|
if (NextLine () == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Just copy the character */
|
/* Just copy the character */
|
||||||
*B++ = *lptr++;
|
*B++ = CurC;
|
||||||
|
NextChar ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,14 +351,14 @@ static void ExpandMacro (Macro* M)
|
|||||||
static void addmac (void)
|
static void addmac (void)
|
||||||
/* Add a macro to the macro table. */
|
/* Add a macro to the macro table. */
|
||||||
{
|
{
|
||||||
char* saveptr;
|
char* saveptr;
|
||||||
ident Ident;
|
ident Ident;
|
||||||
char Buf[LINESIZE];
|
char Buf[LINESIZE];
|
||||||
Macro* M;
|
Macro* M;
|
||||||
|
|
||||||
/* Read the macro name */
|
/* Read the macro name */
|
||||||
skipblank ();
|
SkipBlank ();
|
||||||
if (!macname (Ident)) {
|
if (!MacName (Ident)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,34 +366,36 @@ static void addmac (void)
|
|||||||
M = NewMacro (Ident);
|
M = NewMacro (Ident);
|
||||||
|
|
||||||
/* Check if this is a function like macro */
|
/* Check if this is a function like macro */
|
||||||
if (*lptr == '(') {
|
if (CurC == '(') {
|
||||||
|
|
||||||
/* Skip the left paren */
|
/* Skip the left paren */
|
||||||
gch ();
|
NextChar ();
|
||||||
|
|
||||||
/* Set the marker that this is a function like macro */
|
/* Set the marker that this is a function like macro */
|
||||||
M->ArgCount = 0;
|
M->ArgCount = 0;
|
||||||
|
|
||||||
/* Read the formal parameter list */
|
/* Read the formal parameter list */
|
||||||
while (1) {
|
while (1) {
|
||||||
skipblank ();
|
SkipBlank ();
|
||||||
if (*lptr == ')')
|
if (CurC == ')')
|
||||||
break;
|
break;
|
||||||
if (macname (Ident) == 0) {
|
if (MacName (Ident) == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AddMacroArg (M, Ident);
|
AddMacroArg (M, Ident);
|
||||||
skipblank ();
|
SkipBlank ();
|
||||||
if (*lptr != ',')
|
if (CurC != ',')
|
||||||
break;
|
break;
|
||||||
gch ();
|
NextChar ();
|
||||||
}
|
}
|
||||||
if (*lptr != ')') {
|
|
||||||
|
/* Check for a right paren and eat it if we find one */
|
||||||
|
if (CurC != ')') {
|
||||||
PPError (ERR_RPAREN_EXPECTED);
|
PPError (ERR_RPAREN_EXPECTED);
|
||||||
ClearLine ();
|
ClearLine ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
gch ();
|
NextChar ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Insert the macro into the macro table and allocate the ActualArgs array */
|
/* 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
|
/* Remove whitespace and comments from the line, store the preprocessed
|
||||||
* line into Buf.
|
* line into Buf.
|
||||||
*/
|
*/
|
||||||
skipblank ();
|
SkipBlank ();
|
||||||
saveptr = mptr;
|
saveptr = mptr;
|
||||||
Pass1 (lptr, Buf);
|
Pass1 (lptr, Buf);
|
||||||
mptr = saveptr;
|
mptr = saveptr;
|
||||||
@@ -399,59 +421,63 @@ static void addmac (void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int Pass1 (char* from, char* to)
|
static int Pass1 (const char* From, char* To)
|
||||||
/* Preprocessor pass 1. Remove whitespace and comments. */
|
/* Preprocessor pass 1. Remove whitespace and comments. */
|
||||||
{
|
{
|
||||||
int c;
|
int done;
|
||||||
int done;
|
ident Ident;
|
||||||
ident Ident;
|
int HaveParen;
|
||||||
int HaveParen;
|
|
||||||
|
|
||||||
lptr = from;
|
/* Initialize reading from "From" */
|
||||||
mptr = to;
|
InitLine (From);
|
||||||
|
|
||||||
|
/* Target is "To" */
|
||||||
|
mptr = To;
|
||||||
|
|
||||||
|
/* Loop removing ws and comments */
|
||||||
done = 1;
|
done = 1;
|
||||||
while ((c = *lptr) != 0) {
|
while (CurC != '\0') {
|
||||||
if (IsBlank (c)) {
|
if (IsBlank (CurC)) {
|
||||||
keepch (' ');
|
keepch (' ');
|
||||||
skipblank ();
|
SkipBlank ();
|
||||||
} else if (IsIdent (c)) {
|
} else if (IsIdent (CurC)) {
|
||||||
symname (Ident);
|
SymName (Ident);
|
||||||
if (Preprocessing && strcmp(Ident, "defined") == 0) {
|
if (Preprocessing && strcmp(Ident, "defined") == 0) {
|
||||||
/* Handle the "defined" operator */
|
/* Handle the "defined" operator */
|
||||||
skipblank();
|
SkipBlank();
|
||||||
HaveParen = 0;
|
HaveParen = 0;
|
||||||
if (*lptr == '(') {
|
if (CurC == '(') {
|
||||||
HaveParen = 1;
|
HaveParen = 1;
|
||||||
++lptr;
|
NextChar ();
|
||||||
skipblank();
|
SkipBlank();
|
||||||
}
|
}
|
||||||
if (!IsIdent(c)) {
|
if (!IsIdent (CurC)) {
|
||||||
PPError (ERR_IDENT_EXPECTED);
|
PPError (ERR_IDENT_EXPECTED);
|
||||||
*mptr++ = '0';
|
*mptr++ = '0';
|
||||||
} else {
|
} else {
|
||||||
symname (Ident);
|
SymName (Ident);
|
||||||
*mptr++ = IsMacro(Ident)? '1' : '0';
|
*mptr++ = IsMacro (Ident)? '1' : '0';
|
||||||
if (HaveParen) {
|
if (HaveParen) {
|
||||||
skipblank();
|
SkipBlank();
|
||||||
if (*lptr != ')') {
|
if (CurC != ')') {
|
||||||
PPError (ERR_RPAREN_EXPECTED);
|
PPError (ERR_RPAREN_EXPECTED);
|
||||||
} else {
|
} else {
|
||||||
++lptr;
|
NextChar ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (MaybeMacro(c)) {
|
if (MaybeMacro (Ident[0])) {
|
||||||
done = 0;
|
done = 0;
|
||||||
}
|
}
|
||||||
keepstr (Ident);
|
keepstr (Ident);
|
||||||
}
|
}
|
||||||
} else if (IsQuoteChar(c)) {
|
} else if (IsQuoteChar (CurC)) {
|
||||||
mptr = CopyQuotedString (c, mptr);
|
mptr = CopyQuotedString (mptr);
|
||||||
} else if (c == '/' && nch () == '*') {
|
} else if (CurC == '/' && NextC == '*') {
|
||||||
keepch (' ');
|
keepch (' ');
|
||||||
comment ();
|
Comment ();
|
||||||
} else if (ANSI == 0 && c == '/' && nch () == '/') {
|
} else if (ANSI == 0 && CurC == '/' && NextC == '/') {
|
||||||
keepch (' ');
|
keepch (' ');
|
||||||
/* Beware: Because line continuation chars are handled when reading
|
/* Beware: Because line continuation chars are handled when reading
|
||||||
* lines, we may only skip til the end of the source line, which
|
* 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.
|
* source line is denoted by a lf (\n) character.
|
||||||
*/
|
*/
|
||||||
do {
|
do {
|
||||||
++lptr;
|
NextChar ();
|
||||||
} while (*lptr != '\n' && *lptr != '\0');
|
} while (CurC != '\n' && CurC != '\0');
|
||||||
if (*lptr == '\n') {
|
if (CurC == '\n') {
|
||||||
++lptr;
|
NextChar ();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
*mptr++ = *lptr++;
|
*mptr++ = CurC;
|
||||||
|
NextChar ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
keepch ('\0');
|
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. */
|
/* Preprocessor pass 2. Perform macro substitution. */
|
||||||
{
|
{
|
||||||
int C;
|
int no_chg;
|
||||||
int no_chg;
|
ident Ident;
|
||||||
ident Ident;
|
Macro* M;
|
||||||
Macro* M;
|
|
||||||
|
|
||||||
lptr = from;
|
/* Initialize reading from "From" */
|
||||||
mptr = to;
|
InitLine (From);
|
||||||
|
|
||||||
|
/* Target is "To" */
|
||||||
|
mptr = To;
|
||||||
|
|
||||||
|
/* Loop substituting macros */
|
||||||
no_chg = 1;
|
no_chg = 1;
|
||||||
while ((C = *lptr) != '\0') {
|
while (CurC != '\0') {
|
||||||
/* If we have an identifier, check if it's a macro */
|
/* If we have an identifier, check if it's a macro */
|
||||||
if (IsIdent (C)) {
|
if (IsIdent (CurC)) {
|
||||||
symname (Ident);
|
SymName (Ident);
|
||||||
M = FindMacro (Ident);
|
M = FindMacro (Ident);
|
||||||
if (M) {
|
if (M) {
|
||||||
ExpandMacro (M);
|
ExpandMacro (M);
|
||||||
no_chg = 0;
|
no_chg = 0;
|
||||||
} else {
|
} else {
|
||||||
keepstr (Ident);
|
keepstr (Ident);
|
||||||
}
|
}
|
||||||
} else if (IsQuoteChar(C)) {
|
} else if (IsQuoteChar(CurC)) {
|
||||||
mptr = CopyQuotedString (C, mptr);
|
mptr = CopyQuotedString (mptr);
|
||||||
} else {
|
} else {
|
||||||
*mptr++ = *lptr++;
|
*mptr++ = CurC;
|
||||||
|
NextChar ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return no_chg;
|
return no_chg;
|
||||||
@@ -512,7 +544,6 @@ static void xlateline (void)
|
|||||||
{
|
{
|
||||||
int cnt;
|
int cnt;
|
||||||
int Done;
|
int Done;
|
||||||
char *p;
|
|
||||||
|
|
||||||
Done = Pass1 (line, mline);
|
Done = Pass1 (line, mline);
|
||||||
if (ExpandMacros == 0) {
|
if (ExpandMacros == 0) {
|
||||||
@@ -521,7 +552,8 @@ static void xlateline (void)
|
|||||||
}
|
}
|
||||||
cnt = 5;
|
cnt = 5;
|
||||||
do {
|
do {
|
||||||
p = line;
|
/* Swap mline and line */
|
||||||
|
char* p = line;
|
||||||
line = mline;
|
line = mline;
|
||||||
mline = p;
|
mline = p;
|
||||||
if (Done)
|
if (Done)
|
||||||
@@ -529,7 +561,9 @@ static void xlateline (void)
|
|||||||
Done = Pass2 (line, mline);
|
Done = Pass2 (line, mline);
|
||||||
keepch ('\0');
|
keepch ('\0');
|
||||||
} while (--cnt);
|
} while (--cnt);
|
||||||
lptr = line;
|
|
||||||
|
/* Reinitialize line parsing */
|
||||||
|
InitLine (line);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -539,8 +573,8 @@ static void doundef (void)
|
|||||||
{
|
{
|
||||||
ident Ident;
|
ident Ident;
|
||||||
|
|
||||||
skipblank ();
|
SkipBlank ();
|
||||||
if (macname (Ident)) {
|
if (MacName (Ident)) {
|
||||||
UndefineMacro (Ident);
|
UndefineMacro (Ident);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -574,11 +608,18 @@ static int doiff (int skip)
|
|||||||
Token sv2 = NextTok;
|
Token sv2 = NextTok;
|
||||||
|
|
||||||
/* Remove the #if from the line and add two semicolons as sentinels */
|
/* Remove the #if from the line and add two semicolons as sentinels */
|
||||||
skipblank ();
|
SkipBlank ();
|
||||||
S = line;
|
S = line;
|
||||||
while ((*S++ = *lptr++) != '\0') ;
|
while (CurC != '\0') {
|
||||||
strcpy (S-1, ";;");
|
*S++ = CurC;
|
||||||
lptr = line;
|
NextChar ();
|
||||||
|
}
|
||||||
|
*S++ = ';';
|
||||||
|
*S++ = ';';
|
||||||
|
*S = '\0';
|
||||||
|
|
||||||
|
/* Start over parsing from line */
|
||||||
|
InitLine (line);
|
||||||
|
|
||||||
/* Switch into special preprocessing mode */
|
/* Switch into special preprocessing mode */
|
||||||
Preprocessing = 1;
|
Preprocessing = 1;
|
||||||
@@ -611,8 +652,8 @@ static int doifdef (int skip, int flag)
|
|||||||
{
|
{
|
||||||
ident Ident;
|
ident Ident;
|
||||||
|
|
||||||
skipblank ();
|
SkipBlank ();
|
||||||
if (macname (Ident) == 0) {
|
if (MacName (Ident) == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
return setmflag (skip, flag, IsMacro(Ident));
|
return setmflag (skip, flag, IsMacro(Ident));
|
||||||
@@ -624,60 +665,57 @@ static int doifdef (int skip, int flag)
|
|||||||
static void doinclude (void)
|
static void doinclude (void)
|
||||||
/* Open an include file. */
|
/* Open an include file. */
|
||||||
{
|
{
|
||||||
unsigned Length;
|
|
||||||
char* End;
|
|
||||||
char* Name;
|
|
||||||
char RTerm;
|
char RTerm;
|
||||||
unsigned DirSpec;
|
unsigned DirSpec;
|
||||||
|
|
||||||
|
|
||||||
/* Skip blanks */
|
/* Skip blanks */
|
||||||
mptr = mline;
|
SkipBlank ();
|
||||||
skipblank ();
|
|
||||||
|
|
||||||
/* Get the next char and check for a valid file name terminator. Setup
|
/* Get the next char and check for a valid file name terminator. Setup
|
||||||
* the include directory spec (SYS/USR) by looking at the terminator.
|
* the include directory spec (SYS/USR) by looking at the terminator.
|
||||||
*/
|
*/
|
||||||
switch (cgch()) {
|
switch (CurC) {
|
||||||
|
|
||||||
case '\"':
|
case '\"':
|
||||||
RTerm = '\"';
|
RTerm = '\"';
|
||||||
DirSpec = INC_USER;
|
DirSpec = INC_USER;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '<':
|
case '<':
|
||||||
RTerm = '>';
|
RTerm = '>';
|
||||||
DirSpec = INC_SYS;
|
DirSpec = INC_SYS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
PPError (ERR_INCLUDE_LTERM_EXPECTED);
|
PPError (ERR_INCLUDE_LTERM_EXPECTED);
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
NextChar ();
|
||||||
|
|
||||||
/* Search for the right terminator */
|
/* Copy the filename into mline. Since mline has the same size as the
|
||||||
End = strchr (lptr, RTerm);
|
* input line, we don't need to check for an overflow here.
|
||||||
if (End == 0) {
|
*/
|
||||||
/* No terminator found */
|
mptr = mline;
|
||||||
PPError (ERR_INCLUDE_RTERM_EXPECTED);
|
while (CurC != '\0' && CurC != RTerm) {
|
||||||
goto Done;
|
*mptr++ = CurC;
|
||||||
|
NextChar ();
|
||||||
}
|
}
|
||||||
|
*mptr = '\0';
|
||||||
|
|
||||||
/* Create a temp copy of the filename */
|
/* Check if we got a terminator */
|
||||||
Length = End - lptr;
|
if (CurC != RTerm) {
|
||||||
Name = xmalloc (Length + 1);
|
/* No terminator found */
|
||||||
memcpy (Name, lptr, Length);
|
PPError (ERR_INCLUDE_RTERM_EXPECTED);
|
||||||
Name[Length] = '\0';
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
/* Open the include file */
|
/* Open the include file */
|
||||||
OpenIncludeFile (Name, DirSpec);
|
OpenIncludeFile (mline, DirSpec);
|
||||||
|
|
||||||
/* Delete the temp filename copy */
|
|
||||||
xfree (Name);
|
|
||||||
|
|
||||||
Done:
|
Done:
|
||||||
/* Clear the remaining line so the next input will come from the new
|
/* Clear the remaining line so the next input will come from the new
|
||||||
* file (if open)
|
* file (if open)
|
||||||
*/
|
*/
|
||||||
ClearLine ();
|
ClearLine ();
|
||||||
}
|
}
|
||||||
@@ -687,8 +725,8 @@ Done:
|
|||||||
static void doerror (void)
|
static void doerror (void)
|
||||||
/* Print an error */
|
/* Print an error */
|
||||||
{
|
{
|
||||||
skipblank ();
|
SkipBlank ();
|
||||||
if (*lptr == '\0') {
|
if (CurC == '\0') {
|
||||||
PPError (ERR_INVALID_USER_ERROR);
|
PPError (ERR_INVALID_USER_ERROR);
|
||||||
} else {
|
} else {
|
||||||
PPError (ERR_USER_ERROR, lptr);
|
PPError (ERR_USER_ERROR, lptr);
|
||||||
@@ -704,38 +742,38 @@ static void doerror (void)
|
|||||||
|
|
||||||
/* stuff used to bum the keyword dispatching stuff */
|
/* stuff used to bum the keyword dispatching stuff */
|
||||||
enum {
|
enum {
|
||||||
D_DEFINE,
|
PP_DEFINE,
|
||||||
D_ELSE,
|
PP_ELSE,
|
||||||
D_ENDIF,
|
PP_ENDIF,
|
||||||
D_ERROR,
|
PP_ERROR,
|
||||||
D_IF,
|
PP_IF,
|
||||||
D_IFDEF,
|
PP_IFDEF,
|
||||||
D_IFNDEF,
|
PP_IFNDEF,
|
||||||
D_INCLUDE,
|
PP_INCLUDE,
|
||||||
D_LINE,
|
PP_LINE,
|
||||||
D_PRAGMA,
|
PP_PRAGMA,
|
||||||
D_UNDEF,
|
PP_UNDEF,
|
||||||
D_ILLEGAL,
|
PP_ILLEGAL,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct tok_elt pre_toks[] = {
|
static const struct tok_elt pre_toks[] = {
|
||||||
{ "define", D_DEFINE },
|
{ "define", PP_DEFINE },
|
||||||
{ "else", D_ELSE },
|
{ "else", PP_ELSE },
|
||||||
{ "endif", D_ENDIF },
|
{ "endif", PP_ENDIF },
|
||||||
{ "error", D_ERROR },
|
{ "error", PP_ERROR },
|
||||||
{ "if", D_IF },
|
{ "if", PP_IF },
|
||||||
{ "ifdef", D_IFDEF },
|
{ "ifdef", PP_IFDEF },
|
||||||
{ "ifndef", D_IFNDEF },
|
{ "ifndef", PP_IFNDEF },
|
||||||
{ "include", D_INCLUDE },
|
{ "include", PP_INCLUDE },
|
||||||
{ "line", D_LINE },
|
{ "line", PP_LINE },
|
||||||
{ "pragma", D_PRAGMA },
|
{ "pragma", PP_PRAGMA },
|
||||||
{ "undef", D_UNDEF },
|
{ "undef", PP_UNDEF },
|
||||||
{ 0, D_ILLEGAL }
|
{ 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 */
|
/* Search a token in a table */
|
||||||
{
|
{
|
||||||
while (toks->toknam && strcmp (toks->toknam, sym))
|
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 */
|
/* Preprocess a line */
|
||||||
{
|
{
|
||||||
int c;
|
|
||||||
int Skip;
|
int Skip;
|
||||||
ident sname;
|
ident Directive;
|
||||||
|
|
||||||
/* Process compiler directives, skip empty lines */
|
|
||||||
lptr = line;
|
|
||||||
|
|
||||||
/* Skip white space at the beginning of the line */
|
/* Skip white space at the beginning of the line */
|
||||||
skipblank ();
|
SkipBlank ();
|
||||||
|
|
||||||
/* Check for stuff to skip */
|
/* Check for stuff to skip */
|
||||||
Skip = 0;
|
Skip = 0;
|
||||||
while ((c = *lptr) == '\0' || c == '#' || Skip) {
|
while (CurC == '\0' || CurC == '#' || Skip) {
|
||||||
|
|
||||||
/* Check for preprocessor lines lines */
|
/* Check for preprocessor lines lines */
|
||||||
if (c == '#') {
|
if (CurC == '#') {
|
||||||
++lptr;
|
NextChar ();
|
||||||
skipblank ();
|
SkipBlank ();
|
||||||
if (*lptr == '\0') {
|
if (CurC == '\0') {
|
||||||
/* ignore the empty preprocessor directive */
|
/* Ignore the empty preprocessor directive */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!issym (sname)) {
|
if (!IsSym (Directive)) {
|
||||||
PPError (ERR_CPP_DIRECTIVE_EXPECTED);
|
PPError (ERR_CPP_DIRECTIVE_EXPECTED);
|
||||||
ClearLine ();
|
ClearLine ();
|
||||||
} else {
|
} else {
|
||||||
switch (searchtok (sname, pre_toks)) {
|
switch (searchtok (Directive, pre_toks)) {
|
||||||
|
|
||||||
case D_DEFINE:
|
case PP_DEFINE:
|
||||||
if (!Skip) {
|
if (!Skip) {
|
||||||
addmac ();
|
addmac ();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D_ELSE:
|
case PP_ELSE:
|
||||||
if (s_ifdef[i_ifdef] & 2) {
|
if (s_ifdef[i_ifdef] & 2) {
|
||||||
if (s_ifdef[i_ifdef] & 4) {
|
if (s_ifdef[i_ifdef] & 4) {
|
||||||
Skip = !Skip;
|
Skip = !Skip;
|
||||||
}
|
}
|
||||||
s_ifdef[i_ifdef] ^= 2;
|
s_ifdef[i_ifdef] ^= 2;
|
||||||
} else {
|
} else {
|
||||||
PPError (ERR_UNEXPECTED_CPP_ELSE);
|
PPError (ERR_UNEXPECTED_CPP_ELSE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D_ENDIF:
|
case PP_ENDIF:
|
||||||
if (i_ifdef >= 0) {
|
if (i_ifdef >= 0) {
|
||||||
Skip = s_ifdef[i_ifdef--] & 1;
|
Skip = s_ifdef[i_ifdef--] & 1;
|
||||||
} else {
|
} else {
|
||||||
PPError (ERR_UNEXPECTED_CPP_ENDIF);
|
PPError (ERR_UNEXPECTED_CPP_ENDIF);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D_ERROR:
|
case PP_ERROR:
|
||||||
if (!Skip) {
|
if (!Skip) {
|
||||||
doerror ();
|
doerror ();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D_IF:
|
case PP_IF:
|
||||||
Skip = doiff (Skip);
|
Skip = doiff (Skip);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D_IFDEF:
|
case PP_IFDEF:
|
||||||
Skip = doifdef (Skip, 1);
|
Skip = doifdef (Skip, 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D_IFNDEF:
|
case PP_IFNDEF:
|
||||||
Skip = doifdef (Skip, 0);
|
Skip = doifdef (Skip, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D_INCLUDE:
|
case PP_INCLUDE:
|
||||||
if (!Skip) {
|
if (!Skip) {
|
||||||
doinclude ();
|
doinclude ();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D_LINE:
|
case PP_LINE:
|
||||||
/* Not allowed in strict ANSI mode */
|
/* Not allowed in strict ANSI mode */
|
||||||
if (ANSI) {
|
if (ANSI) {
|
||||||
PPError (ERR_CPP_DIRECTIVE_EXPECTED);
|
PPError (ERR_CPP_DIRECTIVE_EXPECTED);
|
||||||
ClearLine ();
|
ClearLine ();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D_PRAGMA:
|
case PP_PRAGMA:
|
||||||
if (!Skip) {
|
if (!Skip) {
|
||||||
/* Don't expand macros in this line */
|
/* Don't expand macros in this line */
|
||||||
ExpandMacros = 0;
|
ExpandMacros = 0;
|
||||||
/* #pragma is handled on the scanner level */
|
/* #pragma is handled on the scanner level */
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case D_UNDEF:
|
case PP_UNDEF:
|
||||||
if (!Skip) {
|
if (!Skip) {
|
||||||
doundef ();
|
doundef ();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
PPError (ERR_CPP_DIRECTIVE_EXPECTED);
|
PPError (ERR_CPP_DIRECTIVE_EXPECTED);
|
||||||
ClearLine ();
|
ClearLine ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (NextLine () == 0) {
|
if (NextLine () == 0) {
|
||||||
if (i_ifdef >= 0) {
|
if (i_ifdef >= 0) {
|
||||||
PPError (ERR_CPP_ENDIF_EXPECTED);
|
PPError (ERR_CPP_ENDIF_EXPECTED);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
skipblank ();
|
SkipBlank ();
|
||||||
}
|
}
|
||||||
|
|
||||||
Done:
|
Done:
|
||||||
|
|||||||
@@ -34,10 +34,7 @@ extern unsigned char Preprocessing;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int searchtok (const char *sym, const struct tok_elt* toks);
|
void Preprocess (void);
|
||||||
/* Search a token in a table */
|
|
||||||
|
|
||||||
void preprocess (void);
|
|
||||||
/* Preprocess a line */
|
/* Preprocess a line */
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ Token NextTok; /* The next token */
|
|||||||
#define TT_EXT 1 /* cc65 extension */
|
#define TT_EXT 1 /* cc65 extension */
|
||||||
|
|
||||||
/* Token table */
|
/* Token table */
|
||||||
static struct Keyword {
|
static const struct Keyword {
|
||||||
char* Key; /* Keyword name */
|
char* Key; /* Keyword name */
|
||||||
unsigned char Tok; /* The token */
|
unsigned char Tok; /* The token */
|
||||||
unsigned char Type; /* Token type */
|
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
|
/* Find a keyword and return the token. Return IDENT if the token is not a
|
||||||
* keyword.
|
* 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
|
/* 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.
|
* if necessary. Return 0 if end of file is reached, return 1 otherwise.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
while (1) {
|
while (1) {
|
||||||
while (*lptr == 0) {
|
while (CurC == 0) {
|
||||||
if (NextLine () == 0) {
|
if (NextLine () == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
preprocess ();
|
Preprocess ();
|
||||||
}
|
}
|
||||||
if (*lptr == ' ' || *lptr == '\r') {
|
if (CurC == ' ' || CurC == '\r') {
|
||||||
++lptr;
|
NextChar ();
|
||||||
} else {
|
} else {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -152,27 +152,27 @@ static int skipwhite (void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void symname (char *s)
|
void SymName (char* s)
|
||||||
/* Get symbol from input stream */
|
/* Get symbol from input stream */
|
||||||
{
|
{
|
||||||
unsigned k = 0;
|
unsigned k = 0;
|
||||||
do {
|
do {
|
||||||
if (k != MAX_IDENTLEN) {
|
if (k != MAX_IDENTLEN) {
|
||||||
++k;
|
++k;
|
||||||
*s++ = *lptr;
|
*s++ = CurC;
|
||||||
}
|
}
|
||||||
++lptr;
|
NextChar ();
|
||||||
} while (IsIdent (*lptr) || isdigit (*lptr));
|
} while (IsIdent (CurC) || isdigit (CurC));
|
||||||
*s = '\0';
|
*s = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int issym (char *s)
|
int IsSym (char *s)
|
||||||
/* Get symbol from input stream or return 0 if not a symbol. */
|
/* Get symbol from input stream or return 0 if not a symbol. */
|
||||||
{
|
{
|
||||||
if (IsIdent (*lptr)) {
|
if (IsIdent (CurC)) {
|
||||||
symname (s);
|
SymName (s);
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
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 message for unknown character */
|
||||||
{
|
{
|
||||||
Error (ERR_INVALID_CHAR, c);
|
Error (ERR_INVALID_CHAR, C);
|
||||||
gch (); /* Skip */
|
NextChar (); /* Skip */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -209,7 +209,7 @@ static void SetTok (int tok)
|
|||||||
/* set nxttok and bump line ptr */
|
/* set nxttok and bump line ptr */
|
||||||
{
|
{
|
||||||
nxttok = tok;
|
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. */
|
/* Parse a character. Converts \n into EOL, etc. */
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int val;
|
unsigned val;
|
||||||
|
int C;
|
||||||
|
|
||||||
/* Check for escape chars */
|
/* Check for escape chars */
|
||||||
if (c == '\\') {
|
if (CurC == '\\') {
|
||||||
switch (c = gch ()) {
|
NextChar ();
|
||||||
|
switch (CurC) {
|
||||||
case 'b':
|
case 'b':
|
||||||
c = '\b';
|
C = '\b';
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
c = '\f';
|
C = '\f';
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
c = '\r';
|
C = '\r';
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
c = '\n';
|
C = '\n';
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
c = '\t';
|
C = '\t';
|
||||||
break;
|
break;
|
||||||
case '\"':
|
case '\"':
|
||||||
c = '\"';
|
C = '\"';
|
||||||
break;
|
break;
|
||||||
case '\'':
|
case '\'':
|
||||||
c = '\'';
|
C = '\'';
|
||||||
break;
|
break;
|
||||||
case '\\':
|
case '\\':
|
||||||
c = '\\';
|
C = '\\';
|
||||||
break;
|
break;
|
||||||
case 'x':
|
case 'x':
|
||||||
case 'X':
|
case 'X':
|
||||||
/* Hex character constant */
|
/* Hex character constant */
|
||||||
val = hexval (gch ()) << 4;
|
NextChar ();
|
||||||
c = val | hexval (gch ()); /* Do not translate */
|
val = hexval (CurC) << 4;
|
||||||
|
NextChar ();
|
||||||
|
C = val | hexval (CurC); /* Do not translate */
|
||||||
break;
|
break;
|
||||||
case '0':
|
case '0':
|
||||||
case '1':
|
case '1':
|
||||||
/* Octal constant */
|
/* Octal constant */
|
||||||
i = 0;
|
i = 0;
|
||||||
val = c - '0';
|
C = CurC - '0';
|
||||||
while ((c = *lptr) >= '0' && c <= '7' && i++ < 4) {
|
while (NextC >= '0' && NextC <= '7' && i++ < 4) {
|
||||||
val = (val << 3) | (c - '0');
|
NextChar ();
|
||||||
gch ();
|
C = (C << 3) | (CurC - '0');
|
||||||
}
|
}
|
||||||
c = val; /* Do not translate */
|
break;
|
||||||
|
default:
|
||||||
|
Error (ERR_ILLEGAL_CHARCONST);
|
||||||
|
C = ' ';
|
||||||
break;
|
break;
|
||||||
default:
|
}
|
||||||
Error (ERR_ILLEGAL_CHARCONST);
|
} else {
|
||||||
}
|
C = CurC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Skip the character read */
|
||||||
|
NextChar ();
|
||||||
|
|
||||||
/* Do correct sign extension */
|
/* Do correct sign extension */
|
||||||
return SignExtendChar (c);
|
return SignExtendChar (C);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -290,22 +300,25 @@ static int parsechar (int c)
|
|||||||
static void CharConst (void)
|
static void CharConst (void)
|
||||||
/* Parse a character constant. */
|
/* Parse a character constant. */
|
||||||
{
|
{
|
||||||
int c;
|
int C;
|
||||||
|
|
||||||
/* Skip the quote */
|
/* Skip the quote */
|
||||||
++lptr;
|
NextChar ();
|
||||||
|
|
||||||
/* Get character */
|
/* Get character */
|
||||||
c = parsechar (cgch ());
|
C = ParseChar ();
|
||||||
|
|
||||||
/* Check for closing quote */
|
/* Check for closing quote */
|
||||||
if (cgch () != '\'') {
|
if (CurC != '\'') {
|
||||||
Error (ERR_QUOTE_EXPECTED);
|
Error (ERR_QUOTE_EXPECTED);
|
||||||
|
} else {
|
||||||
|
/* Skip the quote */
|
||||||
|
NextChar ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Setup values and attributes */
|
/* Setup values and attributes */
|
||||||
nxttok = TOK_CCONST;
|
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 */
|
nxttype = type_int; /* Character constants have type int */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,24 +331,24 @@ static void StringConst (void)
|
|||||||
nxttok = TOK_SCONST;
|
nxttok = TOK_SCONST;
|
||||||
|
|
||||||
/* Be sure to concatenate strings */
|
/* Be sure to concatenate strings */
|
||||||
while (*lptr == '\"') {
|
while (CurC == '\"') {
|
||||||
|
|
||||||
/* Skip the quote char */
|
/* Skip the quote char */
|
||||||
++lptr;
|
NextChar ();
|
||||||
|
|
||||||
while (*lptr != '\"') {
|
while (CurC != '\"') {
|
||||||
if (*lptr == 0) {
|
if (CurC == '\0') {
|
||||||
Error (ERR_UNEXPECTED_NEWLINE);
|
Error (ERR_UNEXPECTED_NEWLINE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
AddLiteralChar (parsechar (gch()));
|
AddLiteralChar (ParseChar ());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip closing quote char if there was one */
|
/* Skip closing quote char if there was one */
|
||||||
cgch ();
|
NextChar ();
|
||||||
|
|
||||||
/* Skip white space, read new input */
|
/* Skip white space, read new input */
|
||||||
skipwhite ();
|
SkipWhite ();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,7 +361,6 @@ static void StringConst (void)
|
|||||||
void NextToken (void)
|
void NextToken (void)
|
||||||
/* Get next token from input stream */
|
/* Get next token from input stream */
|
||||||
{
|
{
|
||||||
char c;
|
|
||||||
ident token;
|
ident token;
|
||||||
|
|
||||||
/* Current token is the lookahead token */
|
/* Current token is the lookahead token */
|
||||||
@@ -358,15 +370,14 @@ void NextToken (void)
|
|||||||
NextTok.Pos = GetCurrentLine();
|
NextTok.Pos = GetCurrentLine();
|
||||||
|
|
||||||
/* Skip spaces and read the next line if needed */
|
/* Skip spaces and read the next line if needed */
|
||||||
if (skipwhite () == 0) {
|
if (SkipWhite () == 0) {
|
||||||
/* End of file reached */
|
/* End of file reached */
|
||||||
nxttok = TOK_CEOF;
|
nxttok = TOK_CEOF;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine the next token from the lookahead */
|
/* Determine the next token from the lookahead */
|
||||||
c = *lptr;
|
if (isdigit (CurC)) {
|
||||||
if (isdigit (c)) {
|
|
||||||
|
|
||||||
/* A number */
|
/* A number */
|
||||||
int HaveSuffix; /* True if we have a type suffix */
|
int HaveSuffix; /* True if we have a type suffix */
|
||||||
@@ -378,49 +389,48 @@ void NextToken (void)
|
|||||||
base = 10;
|
base = 10;
|
||||||
types = IT_INT | IT_LONG | IT_ULONG;
|
types = IT_INT | IT_LONG | IT_ULONG;
|
||||||
|
|
||||||
if (c == '0') {
|
if (CurC == '0') {
|
||||||
/* Octal or hex constants may also be of type unsigned int */
|
/* Octal or hex constants may also be of type unsigned int */
|
||||||
types = IT_INT | IT_UINT | IT_LONG | IT_ULONG;
|
types = IT_INT | IT_UINT | IT_LONG | IT_ULONG;
|
||||||
/* gobble 0 and examin next char */
|
/* gobble 0 and examin next char */
|
||||||
if (toupper (*++lptr) == 'X') {
|
NextChar ();
|
||||||
|
if (toupper (CurC) == 'X') {
|
||||||
base = 16;
|
base = 16;
|
||||||
nxttype = type_uint;
|
nxttype = type_uint;
|
||||||
++lptr; /* gobble "x" */
|
NextChar (); /* gobble "x" */
|
||||||
} else {
|
} else {
|
||||||
base = 8;
|
base = 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (1) {
|
while (1) {
|
||||||
c = *lptr;
|
if (isdigit (CurC)) {
|
||||||
if (isdigit (c)) {
|
k = k * base + (CurC - '0');
|
||||||
k = k * base + (c - '0');
|
} else if (base == 16 && isxdigit (CurC)) {
|
||||||
} else if (base == 16 && isxdigit (c)) {
|
k = (k << 4) + hexval (CurC);
|
||||||
k = (k << 4) + hexval (c);
|
|
||||||
} else {
|
} else {
|
||||||
break; /* not digit */
|
break; /* not digit */
|
||||||
}
|
}
|
||||||
++lptr; /* gobble char */
|
NextChar (); /* gobble char */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for a suffix */
|
/* Check for a suffix */
|
||||||
HaveSuffix = 1;
|
HaveSuffix = 1;
|
||||||
c = toupper (*lptr);
|
if (CurC == 'u' || CurC == 'U') {
|
||||||
if (c == 'U') {
|
|
||||||
/* Unsigned type */
|
/* Unsigned type */
|
||||||
++lptr;
|
NextChar ();
|
||||||
if (toupper (*lptr) != 'L') {
|
if (toupper (CurC) != 'L') {
|
||||||
types = IT_UINT | IT_ULONG;
|
types = IT_UINT | IT_ULONG;
|
||||||
} else {
|
} else {
|
||||||
++lptr;
|
NextChar ();
|
||||||
types = IT_ULONG;
|
types = IT_ULONG;
|
||||||
}
|
}
|
||||||
} else if (c == 'L') {
|
} else if (CurC == 'l' || CurC == 'L') {
|
||||||
/* Long type */
|
/* Long type */
|
||||||
++lptr;
|
NextChar ();
|
||||||
if (toupper (*lptr) != 'U') {
|
if (toupper (CurC) != 'U') {
|
||||||
types = IT_LONG | IT_ULONG;
|
types = IT_LONG | IT_ULONG;
|
||||||
} else {
|
} else {
|
||||||
++lptr;
|
NextChar ();
|
||||||
types = IT_ULONG;
|
types = IT_ULONG;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -465,7 +475,7 @@ void NextToken (void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (issym (token)) {
|
if (IsSym (token)) {
|
||||||
|
|
||||||
/* Check for a keyword */
|
/* Check for a keyword */
|
||||||
if ((nxttok = FindKey (token)) != TOK_IDENT) {
|
if ((nxttok = FindKey (token)) != TOK_IDENT) {
|
||||||
@@ -506,10 +516,11 @@ void NextToken (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Monstrous switch statement ahead... */
|
/* Monstrous switch statement ahead... */
|
||||||
switch (c) {
|
switch (CurC) {
|
||||||
|
|
||||||
case '!':
|
case '!':
|
||||||
if (*++lptr == '=') {
|
NextChar ();
|
||||||
|
if (CurC == '=') {
|
||||||
SetTok (TOK_NE);
|
SetTok (TOK_NE);
|
||||||
} else {
|
} else {
|
||||||
nxttok = TOK_BOOL_NOT;
|
nxttok = TOK_BOOL_NOT;
|
||||||
@@ -521,7 +532,8 @@ void NextToken (void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '%':
|
case '%':
|
||||||
if (*++lptr == '=') {
|
NextChar ();
|
||||||
|
if (CurC == '=') {
|
||||||
SetTok (TOK_MOD_ASSIGN);
|
SetTok (TOK_MOD_ASSIGN);
|
||||||
} else {
|
} else {
|
||||||
nxttok = TOK_MOD;
|
nxttok = TOK_MOD;
|
||||||
@@ -529,7 +541,8 @@ void NextToken (void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '&':
|
case '&':
|
||||||
switch (*++lptr) {
|
NextChar ();
|
||||||
|
switch (CurC) {
|
||||||
case '&':
|
case '&':
|
||||||
SetTok (TOK_BOOL_AND);
|
SetTok (TOK_BOOL_AND);
|
||||||
break;
|
break;
|
||||||
@@ -554,7 +567,8 @@ void NextToken (void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '*':
|
case '*':
|
||||||
if (*++lptr == '=') {
|
NextChar ();
|
||||||
|
if (CurC == '=') {
|
||||||
SetTok (TOK_MUL_ASSIGN);
|
SetTok (TOK_MUL_ASSIGN);
|
||||||
} else {
|
} else {
|
||||||
nxttok = TOK_STAR;
|
nxttok = TOK_STAR;
|
||||||
@@ -562,7 +576,8 @@ void NextToken (void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '+':
|
case '+':
|
||||||
switch (*++lptr) {
|
NextChar ();
|
||||||
|
switch (CurC) {
|
||||||
case '+':
|
case '+':
|
||||||
SetTok (TOK_INC);
|
SetTok (TOK_INC);
|
||||||
break;
|
break;
|
||||||
@@ -579,7 +594,8 @@ void NextToken (void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '-':
|
case '-':
|
||||||
switch (*++lptr) {
|
NextChar ();
|
||||||
|
switch (CurC) {
|
||||||
case '-':
|
case '-':
|
||||||
SetTok (TOK_DEC);
|
SetTok (TOK_DEC);
|
||||||
break;
|
break;
|
||||||
@@ -595,11 +611,13 @@ void NextToken (void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '.':
|
case '.':
|
||||||
if (*++lptr == '.') {
|
NextChar ();
|
||||||
if (*++lptr == '.') {
|
if (CurC == '.') {
|
||||||
|
NextChar ();
|
||||||
|
if (CurC == '.') {
|
||||||
SetTok (TOK_ELLIPSIS);
|
SetTok (TOK_ELLIPSIS);
|
||||||
} else {
|
} else {
|
||||||
unknown (*lptr);
|
unknown (CurC);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nxttok = TOK_DOT;
|
nxttok = TOK_DOT;
|
||||||
@@ -607,7 +625,8 @@ void NextToken (void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '/':
|
case '/':
|
||||||
if (*++lptr == '=') {
|
NextChar ();
|
||||||
|
if (CurC == '=') {
|
||||||
SetTok (TOK_DIV_ASSIGN);
|
SetTok (TOK_DIV_ASSIGN);
|
||||||
} else {
|
} else {
|
||||||
nxttok = TOK_DIV;
|
nxttok = TOK_DIV;
|
||||||
@@ -623,12 +642,14 @@ void NextToken (void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '<':
|
case '<':
|
||||||
switch (*++lptr) {
|
NextChar ();
|
||||||
|
switch (CurC) {
|
||||||
case '=':
|
case '=':
|
||||||
SetTok (TOK_LE);
|
SetTok (TOK_LE);
|
||||||
break;
|
break;
|
||||||
case '<':
|
case '<':
|
||||||
if (*++lptr == '=') {
|
NextChar ();
|
||||||
|
if (CurC == '=') {
|
||||||
SetTok (TOK_SHL_ASSIGN);
|
SetTok (TOK_SHL_ASSIGN);
|
||||||
} else {
|
} else {
|
||||||
nxttok = TOK_SHL;
|
nxttok = TOK_SHL;
|
||||||
@@ -640,7 +661,8 @@ void NextToken (void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '=':
|
case '=':
|
||||||
if (*++lptr == '=') {
|
NextChar ();
|
||||||
|
if (CurC == '=') {
|
||||||
SetTok (TOK_EQ);
|
SetTok (TOK_EQ);
|
||||||
} else {
|
} else {
|
||||||
nxttok = TOK_ASSIGN;
|
nxttok = TOK_ASSIGN;
|
||||||
@@ -648,12 +670,14 @@ void NextToken (void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '>':
|
case '>':
|
||||||
switch (*++lptr) {
|
NextChar ();
|
||||||
|
switch (CurC) {
|
||||||
case '=':
|
case '=':
|
||||||
SetTok (TOK_GE);
|
SetTok (TOK_GE);
|
||||||
break;
|
break;
|
||||||
case '>':
|
case '>':
|
||||||
if (*++lptr == '=') {
|
NextChar ();
|
||||||
|
if (CurC == '=') {
|
||||||
SetTok (TOK_SHR_ASSIGN);
|
SetTok (TOK_SHR_ASSIGN);
|
||||||
} else {
|
} else {
|
||||||
nxttok = TOK_SHR;
|
nxttok = TOK_SHR;
|
||||||
@@ -677,7 +701,8 @@ void NextToken (void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '^':
|
case '^':
|
||||||
if (*++lptr == '=') {
|
NextChar ();
|
||||||
|
if (CurC == '=') {
|
||||||
SetTok (TOK_XOR_ASSIGN);
|
SetTok (TOK_XOR_ASSIGN);
|
||||||
} else {
|
} else {
|
||||||
nxttok = TOK_XOR;
|
nxttok = TOK_XOR;
|
||||||
@@ -689,7 +714,8 @@ void NextToken (void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '|':
|
case '|':
|
||||||
switch (*++lptr) {
|
NextChar ();
|
||||||
|
switch (CurC) {
|
||||||
case '|':
|
case '|':
|
||||||
SetTok (TOK_BOOL_OR);
|
SetTok (TOK_BOOL_OR);
|
||||||
break;
|
break;
|
||||||
@@ -710,8 +736,11 @@ void NextToken (void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case '#':
|
case '#':
|
||||||
while (*++lptr == ' ') ; /* Skip it and following whitespace */
|
/* Skip it and following whitespace */
|
||||||
if (!issym (token) || strcmp (token, "pragma") != 0) {
|
do {
|
||||||
|
NextChar ();
|
||||||
|
} while (CurC == ' ');
|
||||||
|
if (!IsSym (token) || strcmp (token, "pragma") != 0) {
|
||||||
/* OOPS - should not happen */
|
/* OOPS - should not happen */
|
||||||
Error (ERR_CPP_DIRECTIVE_EXPECTED);
|
Error (ERR_CPP_DIRECTIVE_EXPECTED);
|
||||||
}
|
}
|
||||||
@@ -719,7 +748,7 @@ void NextToken (void)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
unknown (c);
|
unknown (CurC);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -172,13 +172,13 @@ extern Token NextTok; /* The next token */
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void symname (char* s);
|
void SymName (char* s);
|
||||||
/* Get symbol from input stream */
|
/* 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. */
|
/* Get symbol from input stream or return 0 if not a symbol. */
|
||||||
|
|
||||||
void NextToken (void);
|
void NextToken (void);
|
||||||
/* Get next token from input stream */
|
/* Get next token from input stream */
|
||||||
|
|
||||||
void Consume (token_t Token, unsigned ErrNum);
|
void Consume (token_t Token, unsigned ErrNum);
|
||||||
|
|||||||
Reference in New Issue
Block a user