Added the lineinfo module. Changed the complete code generation to use the
supplied data structures. Re-added the -T option which is much more exact now because of the better line info stuff. Cleanups in the scanner (remove old #defines). git-svn-id: svn://svn.cc65.org/cc65/trunk@740 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -160,7 +160,8 @@ static void SetUseChgInfo (CodeEntry* E, const OPCDesc* D)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg, CodeLabel* JumpTo)
|
CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg,
|
||||||
|
CodeLabel* JumpTo, LineInfo* LI)
|
||||||
/* Create a new code entry, initialize and return it */
|
/* Create a new code entry, initialize and return it */
|
||||||
{
|
{
|
||||||
/* Get the opcode description */
|
/* Get the opcode description */
|
||||||
@@ -170,18 +171,14 @@ CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg, CodeLabel* JumpTo)
|
|||||||
CodeEntry* E = xmalloc (sizeof (CodeEntry));
|
CodeEntry* E = xmalloc (sizeof (CodeEntry));
|
||||||
|
|
||||||
/* Initialize the fields */
|
/* Initialize the fields */
|
||||||
E->OPC = D->OPC;
|
E->OPC = D->OPC;
|
||||||
E->AM = AM;
|
E->AM = AM;
|
||||||
E->Size = GetInsnSize (E->OPC, E->AM);
|
E->Arg = GetArgCopy (Arg);
|
||||||
E->Hints = 0;
|
E->Flags = NumArg (E->Arg, &E->Num)? CEF_NUMARG : 0;
|
||||||
E->Arg = GetArgCopy (Arg);
|
E->Size = GetInsnSize (E->OPC, E->AM);
|
||||||
if (NumArg (E->Arg, &E->Num)) {
|
|
||||||
E-> Flags = CEF_NUMARG;
|
|
||||||
} else {
|
|
||||||
E->Flags = 0;
|
|
||||||
}
|
|
||||||
E->Info = D->Info;
|
E->Info = D->Info;
|
||||||
E->JumpTo = JumpTo;
|
E->JumpTo = JumpTo;
|
||||||
|
E->LI = UseLineInfo (LI);
|
||||||
SetUseChgInfo (E, D);
|
SetUseChgInfo (E, D);
|
||||||
InitCollection (&E->Labels);
|
InitCollection (&E->Labels);
|
||||||
|
|
||||||
@@ -205,6 +202,9 @@ void FreeCodeEntry (CodeEntry* E)
|
|||||||
/* Cleanup the collection */
|
/* Cleanup the collection */
|
||||||
DoneCollection (&E->Labels);
|
DoneCollection (&E->Labels);
|
||||||
|
|
||||||
|
/* Release the line info */
|
||||||
|
ReleaseLineInfo (E->LI);
|
||||||
|
|
||||||
/* Free the entry */
|
/* Free the entry */
|
||||||
xfree (E);
|
xfree (E);
|
||||||
}
|
}
|
||||||
@@ -359,7 +359,7 @@ void OutputCodeEntry (const CodeEntry* E, FILE* F)
|
|||||||
/* Print usage info if requested by the debugging flag */
|
/* Print usage info if requested by the debugging flag */
|
||||||
// if (Debug) {
|
// if (Debug) {
|
||||||
Chars += fprintf (F,
|
Chars += fprintf (F,
|
||||||
"%*s; USE: %c%c%c CHG: %c%c%c SIZE: %u",
|
"%*s; USE: %c%c%c CHG: %c%c%c SIZE: %u\n",
|
||||||
30-Chars, "",
|
30-Chars, "",
|
||||||
(E->Use & REG_A)? 'A' : '_',
|
(E->Use & REG_A)? 'A' : '_',
|
||||||
(E->Use & REG_X)? 'X' : '_',
|
(E->Use & REG_X)? 'X' : '_',
|
||||||
@@ -375,3 +375,4 @@ void OutputCodeEntry (const CodeEntry* E, FILE* F)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -46,35 +46,36 @@
|
|||||||
|
|
||||||
/* cc65 */
|
/* cc65 */
|
||||||
#include "codelab.h"
|
#include "codelab.h"
|
||||||
|
#include "lineinfo.h"
|
||||||
#include "opcodes.h"
|
#include "opcodes.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Data */
|
/* Data */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Flags used */
|
/* Flags used */
|
||||||
#define CEF_USERMARK 0x0001U /* Generic mark by user functions */
|
#define CEF_USERMARK 0x0001U /* Generic mark by user functions */
|
||||||
#define CEF_NUMARG 0x0002U /* Insn has numerical argument */
|
#define CEF_NUMARG 0x0002U /* Insn has numerical argument */
|
||||||
|
|
||||||
/* Code entry structure */
|
/* Code entry structure */
|
||||||
typedef struct CodeEntry CodeEntry;
|
typedef struct CodeEntry CodeEntry;
|
||||||
struct CodeEntry {
|
struct CodeEntry {
|
||||||
opc_t OPC; /* Opcode */
|
opc_t OPC; /* Opcode */
|
||||||
am_t AM; /* Adressing mode */
|
am_t AM; /* Adressing mode */
|
||||||
unsigned char Size; /* Estimated size */
|
|
||||||
unsigned char Hints; /* Hints for this entry */
|
|
||||||
char* Arg; /* Argument as string */
|
char* Arg; /* Argument as string */
|
||||||
unsigned long Num; /* Numeric argument */
|
unsigned long Num; /* Numeric argument */
|
||||||
unsigned short Flags; /* Flags */
|
unsigned short Flags; /* Flags */
|
||||||
unsigned char Info; /* Additional code info */
|
unsigned char Size; /* Estimated size */
|
||||||
unsigned char Use; /* Registers used */
|
unsigned char Info; /* Additional code info */
|
||||||
unsigned char Chg; /* Registers changed/destroyed */
|
unsigned char Use; /* Registers used */
|
||||||
CodeLabel* JumpTo; /* Jump label */
|
unsigned char Chg; /* Registers changed/destroyed */
|
||||||
Collection Labels; /* Labels for this instruction */
|
CodeLabel* JumpTo; /* Jump label */
|
||||||
|
Collection Labels; /* Labels for this instruction */
|
||||||
|
LineInfo* LI; /* Source line info for this insn */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -85,7 +86,8 @@ struct CodeEntry {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg, CodeLabel* JumpTo);
|
CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg,
|
||||||
|
CodeLabel* JumpTo, LineInfo* LI);
|
||||||
/* Create a new code entry, initialize and return it */
|
/* Create a new code entry, initialize and return it */
|
||||||
|
|
||||||
void FreeCodeEntry (CodeEntry* E);
|
void FreeCodeEntry (CodeEntry* E);
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ static void ReplaceCmp (CodeSeg* S, unsigned I, cmp_t Cond)
|
|||||||
Internal ("Invalid program flow");
|
Internal ("Invalid program flow");
|
||||||
}
|
}
|
||||||
L = GenCodeLabel (S, N);
|
L = GenCodeLabel (S, N);
|
||||||
N = NewCodeEntry (OPC_BEQ, AM_BRA, L->Name, L);
|
N = NewCodeEntry (OPC_BEQ, AM_BRA, L->Name, L, E->LI);
|
||||||
InsertCodeEntry (S, N, I);
|
InsertCodeEntry (S, N, I);
|
||||||
ReplaceOPC (E, OPC_JPL);
|
ReplaceOPC (E, OPC_JPL);
|
||||||
break;
|
break;
|
||||||
@@ -205,7 +205,7 @@ static void ReplaceCmp (CodeSeg* S, unsigned I, cmp_t Cond)
|
|||||||
*/
|
*/
|
||||||
ReplaceOPC (E, OPC_JMI);
|
ReplaceOPC (E, OPC_JMI);
|
||||||
L = E->JumpTo;
|
L = E->JumpTo;
|
||||||
N = NewCodeEntry (OPC_JEQ, AM_BRA, L->Name, L);
|
N = NewCodeEntry (OPC_JEQ, AM_BRA, L->Name, L, E->LI);
|
||||||
InsertCodeEntry (S, N, I+1);
|
InsertCodeEntry (S, N, I+1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -220,7 +220,7 @@ static void ReplaceCmp (CodeSeg* S, unsigned I, cmp_t Cond)
|
|||||||
Internal ("Invalid program flow");
|
Internal ("Invalid program flow");
|
||||||
}
|
}
|
||||||
L = GenCodeLabel (S, N);
|
L = GenCodeLabel (S, N);
|
||||||
N = NewCodeEntry (OPC_BEQ, AM_BRA, L->Name, L);
|
N = NewCodeEntry (OPC_BEQ, AM_BRA, L->Name, L, E->LI);
|
||||||
InsertCodeEntry (S, N, I);
|
InsertCodeEntry (S, N, I);
|
||||||
ReplaceOPC (E, OPC_JCS);
|
ReplaceOPC (E, OPC_JCS);
|
||||||
break;
|
break;
|
||||||
@@ -240,7 +240,7 @@ static void ReplaceCmp (CodeSeg* S, unsigned I, cmp_t Cond)
|
|||||||
*/
|
*/
|
||||||
ReplaceOPC (E, OPC_JCC);
|
ReplaceOPC (E, OPC_JCC);
|
||||||
L = E->JumpTo;
|
L = E->JumpTo;
|
||||||
N = NewCodeEntry (OPC_JEQ, AM_BRA, L->Name, L);
|
N = NewCodeEntry (OPC_JEQ, AM_BRA, L->Name, L, E->LI);
|
||||||
InsertCodeEntry (S, N, I+1);
|
InsertCodeEntry (S, N, I+1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -645,7 +645,7 @@ static unsigned OptCmp1 (CodeSeg* S)
|
|||||||
DelCodeEntries (S, I+1, 2);
|
DelCodeEntries (S, I+1, 2);
|
||||||
|
|
||||||
/* Insert the ora instead */
|
/* Insert the ora instead */
|
||||||
InsertCodeEntry (S, NewCodeEntry (OPC_ORA, E->AM, E->Arg, 0), I+1);
|
InsertCodeEntry (S, NewCodeEntry (OPC_ORA, E->AM, E->Arg, 0, E->LI), I+1);
|
||||||
|
|
||||||
/* Remember, we had changes */
|
/* Remember, we had changes */
|
||||||
++Changes;
|
++Changes;
|
||||||
@@ -893,9 +893,9 @@ static unsigned OptCmp5 (CodeSeg* S)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Replace the subroutine call. */
|
/* Replace the subroutine call. */
|
||||||
|
E = NewCodeEntry (OPC_JSR, AM_ABS, "tosicmp", 0, E->LI);
|
||||||
|
InsertCodeEntry (S, E, I+1);
|
||||||
DelCodeEntry (S, I);
|
DelCodeEntry (S, I);
|
||||||
E = NewCodeEntry (OPC_JSR, AM_ABS, "tosicmp", 0);
|
|
||||||
InsertCodeEntry (S, E, I);
|
|
||||||
|
|
||||||
/* Replace the conditional branch */
|
/* Replace the conditional branch */
|
||||||
ReplaceCmp (S, I+1, Cond);
|
ReplaceCmp (S, I+1, Cond);
|
||||||
@@ -1197,22 +1197,27 @@ static unsigned OptNegAX3 (CodeSeg* S)
|
|||||||
!CodeEntryHasLabel (L[0]) &&
|
!CodeEntryHasLabel (L[0]) &&
|
||||||
(L[1]->Info & OF_ZBRA) != 0) {
|
(L[1]->Info & OF_ZBRA) != 0) {
|
||||||
|
|
||||||
|
CodeEntry* X;
|
||||||
|
|
||||||
/* Check if we're calling bnega or bnegax */
|
/* Check if we're calling bnega or bnegax */
|
||||||
int ByteSized = (strcmp (L[0]->Arg, "bnega") == 0);
|
int ByteSized = (strcmp (L[0]->Arg, "bnega") == 0);
|
||||||
|
|
||||||
/* Delete the subroutine call */
|
|
||||||
DelCodeEntry (S, I+1);
|
|
||||||
|
|
||||||
/* Insert apropriate test code */
|
/* Insert apropriate test code */
|
||||||
if (ByteSized) {
|
if (ByteSized) {
|
||||||
/* Test bytes */
|
/* Test bytes */
|
||||||
InsertCodeEntry (S, NewCodeEntry (OPC_TAX, AM_IMP, 0, 0), I+1);
|
X = NewCodeEntry (OPC_TAX, AM_IMP, 0, 0, L[0]->LI);
|
||||||
|
InsertCodeEntry (S, X, I+2);
|
||||||
} else {
|
} else {
|
||||||
/* Test words */
|
/* Test words */
|
||||||
InsertCodeEntry (S, NewCodeEntry (OPC_STX, AM_ZP, "tmp1", 0), I+1);
|
X = NewCodeEntry (OPC_STX, AM_ZP, "tmp1", 0, L[0]->LI);
|
||||||
InsertCodeEntry (S, NewCodeEntry (OPC_ORA, AM_ZP, "tmp1", 0), I+2);
|
InsertCodeEntry (S, X, I+2);
|
||||||
|
X = NewCodeEntry (OPC_ORA, AM_ZP, "tmp1", 0, L[0]->LI);
|
||||||
|
InsertCodeEntry (S, X, I+3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Delete the subroutine call */
|
||||||
|
DelCodeEntry (S, I+1);
|
||||||
|
|
||||||
/* Invert the branch */
|
/* Invert the branch */
|
||||||
ReplaceOPC (L[1], GetInverseBranch (L[1]->OPC));
|
ReplaceOPC (L[1], GetInverseBranch (L[1]->OPC));
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
/* common */
|
/* common */
|
||||||
#include "chartype.h"
|
#include "chartype.h"
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
|
#include "global.h"
|
||||||
#include "hashstr.h"
|
#include "hashstr.h"
|
||||||
#include "strutil.h"
|
#include "strutil.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
@@ -184,7 +185,7 @@ static const char* ReadToken (const char* L, const char* Term,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
|
static CodeEntry* ParseInsn (CodeSeg* S, LineInfo* LI, const char* L)
|
||||||
/* Parse an instruction nnd generate a code entry from it. If the line contains
|
/* Parse an instruction nnd generate a code entry from it. If the line contains
|
||||||
* errors, output an error message and return NULL.
|
* errors, output an error message and return NULL.
|
||||||
* For simplicity, we don't accept the broad range of input a "real" assembler
|
* For simplicity, we don't accept the broad range of input a "real" assembler
|
||||||
@@ -356,7 +357,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
|
|||||||
/* We do now have the addressing mode in AM. Allocate a new CodeEntry
|
/* We do now have the addressing mode in AM. Allocate a new CodeEntry
|
||||||
* structure and initialize it.
|
* structure and initialize it.
|
||||||
*/
|
*/
|
||||||
E = NewCodeEntry (OPC->OPC, AM, Arg, Label);
|
E = NewCodeEntry (OPC->OPC, AM, Arg, Label, LI);
|
||||||
|
|
||||||
/* Return the new code entry */
|
/* Return the new code entry */
|
||||||
return E;
|
return E;
|
||||||
@@ -365,7 +366,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
|
|||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Code */
|
/* Code */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
@@ -402,7 +403,7 @@ CodeSeg* NewCodeSeg (const char* SegName, SymEntry* Func)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void AddCodeEntry (CodeSeg* S, const char* Format, va_list ap)
|
void AddCodeEntry (CodeSeg* S, LineInfo* LI, const char* Format, va_list ap)
|
||||||
/* Add a line to the given code segment */
|
/* Add a line to the given code segment */
|
||||||
{
|
{
|
||||||
const char* L;
|
const char* L;
|
||||||
@@ -435,7 +436,7 @@ void AddCodeEntry (CodeSeg* S, const char* Format, va_list ap)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
E = ParseInsn (S, L);
|
E = ParseInsn (S, LI, L);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -855,26 +856,6 @@ void MoveCodeLabelRef (CodeSeg* S, struct CodeEntry* E, CodeLabel* L)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void AddCodeSegHint (CodeSeg* S, unsigned Hint)
|
|
||||||
/* Add a hint for the preceeding instruction */
|
|
||||||
{
|
|
||||||
CodeEntry* E;
|
|
||||||
|
|
||||||
/* Get the number of entries in this segment */
|
|
||||||
unsigned EntryCount = GetCodeEntryCount (S);
|
|
||||||
|
|
||||||
/* Must have at least one entry */
|
|
||||||
CHECK (EntryCount > 0);
|
|
||||||
|
|
||||||
/* Get the last entry */
|
|
||||||
E = GetCodeEntry (S, EntryCount-1);
|
|
||||||
|
|
||||||
/* Add the hint */
|
|
||||||
E->Hints |= Hint;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void DelCodeSegAfter (CodeSeg* S, unsigned Last)
|
void DelCodeSegAfter (CodeSeg* S, unsigned Last)
|
||||||
/* Delete all entries including the given one */
|
/* Delete all entries including the given one */
|
||||||
{
|
{
|
||||||
@@ -939,6 +920,7 @@ void OutputCodeSeg (const CodeSeg* S, FILE* F)
|
|||||||
/* Output the code segment data to a file */
|
/* Output the code segment data to a file */
|
||||||
{
|
{
|
||||||
unsigned I;
|
unsigned I;
|
||||||
|
const LineInfo* LI;
|
||||||
|
|
||||||
/* Get the number of entries in this segment */
|
/* Get the number of entries in this segment */
|
||||||
unsigned Count = GetCodeEntryCount (S);
|
unsigned Count = GetCodeEntryCount (S);
|
||||||
@@ -956,24 +938,27 @@ void OutputCodeSeg (const CodeSeg* S, FILE* F)
|
|||||||
fprintf (F, ".proc\t_%s\n\n", S->Func->Name);
|
fprintf (F, ".proc\t_%s\n\n", S->Func->Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Output all entries */
|
/* Output all entries, prepended by the line information if it has changed */
|
||||||
|
LI = 0;
|
||||||
for (I = 0; I < Count; ++I) {
|
for (I = 0; I < Count; ++I) {
|
||||||
|
/* Get the next entry */
|
||||||
unsigned char Use;
|
const CodeEntry* E = CollConstAt (&S->Entries, I);
|
||||||
|
/* Check if the line info has changed. If so, output the source line
|
||||||
OutputCodeEntry (CollConstAt (&S->Entries, I), F);
|
* if the option is enabled.
|
||||||
|
*/
|
||||||
#if 0
|
if (E->LI != LI) {
|
||||||
/* Print usage info */
|
LI = E->LI;
|
||||||
Use = GetRegInfo ((CodeSeg*) S, I+1);
|
if (AddSource) {
|
||||||
fprintf (F,
|
/* Skip spaces to make the output somewhat more readable */
|
||||||
" Use: %c%c%c\n",
|
const char* Line = LI->Line;
|
||||||
(Use & REG_A)? 'A' : '_',
|
while (IsBlank (*Line)) {
|
||||||
(Use & REG_X)? 'X' : '_',
|
++Line;
|
||||||
(Use & REG_Y)? 'Y' : '_');
|
}
|
||||||
#else
|
fprintf (F, ";\n; %s\n;\n", Line);
|
||||||
fprintf (F, "\n");
|
}
|
||||||
#endif
|
}
|
||||||
|
/* Output the code */
|
||||||
|
OutputCodeEntry (E, F);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this is a segment for a function, leave the function */
|
/* If this is a segment for a function, leave the function */
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
|
|
||||||
/* cc65 */
|
/* cc65 */
|
||||||
#include "codelab.h"
|
#include "codelab.h"
|
||||||
|
#include "lineinfo.h"
|
||||||
#include "symentry.h"
|
#include "symentry.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -93,7 +94,7 @@ struct CodeSeg {
|
|||||||
CodeSeg* NewCodeSeg (const char* SegName, SymEntry* Func);
|
CodeSeg* NewCodeSeg (const char* SegName, SymEntry* Func);
|
||||||
/* Create a new code segment, initialize and return it */
|
/* Create a new code segment, initialize and return it */
|
||||||
|
|
||||||
void AddCodeEntry (CodeSeg* S, const char* Format, va_list ap) attribute ((format(printf,2,0)));
|
void AddCodeEntry (CodeSeg* S, LineInfo* LI, const char* Format, va_list ap) attribute ((format(printf,3,0)));
|
||||||
/* Add a line to the given code segment */
|
/* Add a line to the given code segment */
|
||||||
|
|
||||||
void InsertCodeEntry (CodeSeg* S, struct CodeEntry* E, unsigned Index);
|
void InsertCodeEntry (CodeSeg* S, struct CodeEntry* E, unsigned Index);
|
||||||
@@ -177,9 +178,6 @@ void MoveCodeLabelRef (CodeSeg* S, struct CodeEntry* E, CodeLabel* L);
|
|||||||
* deleted.
|
* deleted.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void AddCodeSegHint (CodeSeg* S, unsigned Hint);
|
|
||||||
/* Add a hint for the preceeding instruction */
|
|
||||||
|
|
||||||
void DelCodeSegAfter (CodeSeg* S, unsigned Last);
|
void DelCodeSegAfter (CodeSeg* S, unsigned Last);
|
||||||
/* Delete all entries including the given one */
|
/* Delete all entries including the given one */
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Code */
|
/* Code */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
@@ -67,29 +67,32 @@ static void Parse (void)
|
|||||||
int comma;
|
int comma;
|
||||||
SymEntry* Entry;
|
SymEntry* Entry;
|
||||||
|
|
||||||
NextToken (); /* "prime" the pump */
|
/* Go... */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
while (curtok != TOK_CEOF) {
|
NextToken ();
|
||||||
|
|
||||||
|
/* Parse until end of input */
|
||||||
|
while (CurTok.Tok != TOK_CEOF) {
|
||||||
|
|
||||||
DeclSpec Spec;
|
DeclSpec Spec;
|
||||||
Declaration Decl;
|
Declaration Decl;
|
||||||
int NeedStorage;
|
int NeedStorage;
|
||||||
|
|
||||||
/* Check for empty statements */
|
/* Check for empty statements */
|
||||||
if (curtok == TOK_SEMI) {
|
if (CurTok.Tok == TOK_SEMI) {
|
||||||
NextToken ();
|
NextToken ();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for an ASM statement (which is allowed also on global level) */
|
/* Check for an ASM statement (which is allowed also on global level) */
|
||||||
if (curtok == TOK_ASM) {
|
if (CurTok.Tok == TOK_ASM) {
|
||||||
doasm ();
|
doasm ();
|
||||||
ConsumeSemi ();
|
ConsumeSemi ();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for a #pragma */
|
/* Check for a #pragma */
|
||||||
if (curtok == TOK_PRAGMA) {
|
if (CurTok.Tok == TOK_PRAGMA) {
|
||||||
DoPragma ();
|
DoPragma ();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -104,7 +107,7 @@ static void Parse (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check if this is only a type declaration */
|
/* Check if this is only a type declaration */
|
||||||
if (curtok == TOK_SEMI) {
|
if (CurTok.Tok == TOK_SEMI) {
|
||||||
CheckEmptyDecl (&Spec);
|
CheckEmptyDecl (&Spec);
|
||||||
NextToken ();
|
NextToken ();
|
||||||
continue;
|
continue;
|
||||||
@@ -155,7 +158,7 @@ static void Parse (void)
|
|||||||
unsigned Size = SizeOf (Decl.Type);
|
unsigned Size = SizeOf (Decl.Type);
|
||||||
|
|
||||||
/* Allow initialization */
|
/* Allow initialization */
|
||||||
if (curtok == TOK_ASSIGN) {
|
if (CurTok.Tok == TOK_ASSIGN) {
|
||||||
|
|
||||||
/* We cannot initialize types of unknown size, or
|
/* We cannot initialize types of unknown size, or
|
||||||
* void types in non ANSI mode.
|
* void types in non ANSI mode.
|
||||||
@@ -210,7 +213,7 @@ static void Parse (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check for end of declaration list */
|
/* Check for end of declaration list */
|
||||||
if (curtok == TOK_COMMA) {
|
if (CurTok.Tok == TOK_COMMA) {
|
||||||
NextToken ();
|
NextToken ();
|
||||||
comma = 1;
|
comma = 1;
|
||||||
} else {
|
} else {
|
||||||
@@ -224,7 +227,7 @@ static void Parse (void)
|
|||||||
/* Function */
|
/* Function */
|
||||||
if (!comma) {
|
if (!comma) {
|
||||||
|
|
||||||
if (curtok == TOK_SEMI) {
|
if (CurTok.Tok == TOK_SEMI) {
|
||||||
|
|
||||||
/* Prototype only */
|
/* Prototype only */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
|
|||||||
@@ -67,12 +67,13 @@ unsigned OptRTSJumps (CodeSeg* S)
|
|||||||
E->JumpTo != 0 &&
|
E->JumpTo != 0 &&
|
||||||
E->JumpTo->Owner->OPC == OPC_RTS) {
|
E->JumpTo->Owner->OPC == OPC_RTS) {
|
||||||
|
|
||||||
|
/* Insert an RTS instruction */
|
||||||
|
CodeEntry* X = NewCodeEntry (OPC_RTS, AM_IMP, 0, 0, E->LI);
|
||||||
|
InsertCodeEntry (S, X, I+1);
|
||||||
|
|
||||||
/* Delete the jump */
|
/* Delete the jump */
|
||||||
DelCodeEntry (S, I);
|
DelCodeEntry (S, I);
|
||||||
|
|
||||||
/* Insert an RTS instruction instead */
|
|
||||||
InsertCodeEntry (S, NewCodeEntry (OPC_RTS, AM_IMP, 0, 0), I);
|
|
||||||
|
|
||||||
/* Remember, we had changes */
|
/* Remember, we had changes */
|
||||||
++Changes;
|
++Changes;
|
||||||
|
|
||||||
@@ -248,7 +249,7 @@ unsigned OptJumpCascades (CodeSeg* S)
|
|||||||
/* This is a jump cascade and we may jump to the final target.
|
/* This is a jump cascade and we may jump to the final target.
|
||||||
* Insert a new instruction, then remove the old one
|
* Insert a new instruction, then remove the old one
|
||||||
*/
|
*/
|
||||||
CodeEntry* X = NewCodeEntry (E->OPC, E->AM, N->Arg, N->JumpTo);
|
CodeEntry* X = NewCodeEntry (E->OPC, E->AM, N->Arg, N->JumpTo, E->LI);
|
||||||
|
|
||||||
/* Insert it behind E */
|
/* Insert it behind E */
|
||||||
InsertCodeEntry (S, X, I+1);
|
InsertCodeEntry (S, X, I+1);
|
||||||
@@ -284,8 +285,8 @@ unsigned OptJumpCascades (CodeSeg* S)
|
|||||||
goto NextEntry;
|
goto NextEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We may jump behind this conditional branch. Get the
|
/* We may jump behind this conditional branch. Get the
|
||||||
* pointer to the next instruction
|
* pointer to the next instruction
|
||||||
*/
|
*/
|
||||||
if ((X = GetNextCodeEntry (S, GetCodeEntryIndex (S, N))) == 0) {
|
if ((X = GetNextCodeEntry (S, GetCodeEntryIndex (S, N))) == 0) {
|
||||||
/* N is the last entry, bail out */
|
/* N is the last entry, bail out */
|
||||||
|
|||||||
@@ -78,9 +78,9 @@ static void ParseTypeSpec (DeclSpec* D, int Default);
|
|||||||
static type OptionalQualifiers (type Q)
|
static type OptionalQualifiers (type Q)
|
||||||
/* Read type qualifiers if we have any */
|
/* Read type qualifiers if we have any */
|
||||||
{
|
{
|
||||||
while (curtok == TOK_CONST || curtok == TOK_VOLATILE) {
|
while (CurTok.Tok == TOK_CONST || CurTok.Tok == TOK_VOLATILE) {
|
||||||
|
|
||||||
switch (curtok) {
|
switch (CurTok.Tok) {
|
||||||
|
|
||||||
case TOK_CONST:
|
case TOK_CONST:
|
||||||
if (Q & T_QUAL_CONST) {
|
if (Q & T_QUAL_CONST) {
|
||||||
@@ -115,7 +115,7 @@ static type OptionalQualifiers (type Q)
|
|||||||
static void optionalint (void)
|
static void optionalint (void)
|
||||||
/* Eat an optional "int" token */
|
/* Eat an optional "int" token */
|
||||||
{
|
{
|
||||||
if (curtok == TOK_INT) {
|
if (CurTok.Tok == TOK_INT) {
|
||||||
/* Skip it */
|
/* Skip it */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
}
|
}
|
||||||
@@ -126,7 +126,7 @@ static void optionalint (void)
|
|||||||
static void optionalsigned (void)
|
static void optionalsigned (void)
|
||||||
/* Eat an optional "signed" token */
|
/* Eat an optional "signed" token */
|
||||||
{
|
{
|
||||||
if (curtok == TOK_SIGNED) {
|
if (CurTok.Tok == TOK_SIGNED) {
|
||||||
/* Skip it */
|
/* Skip it */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
}
|
}
|
||||||
@@ -161,7 +161,7 @@ static void ParseStorageClass (DeclSpec* D, unsigned DefStorage)
|
|||||||
D->Flags &= ~DS_DEF_STORAGE;
|
D->Flags &= ~DS_DEF_STORAGE;
|
||||||
|
|
||||||
/* Check the storage class given */
|
/* Check the storage class given */
|
||||||
switch (curtok) {
|
switch (CurTok.Tok) {
|
||||||
|
|
||||||
case TOK_EXTERN:
|
case TOK_EXTERN:
|
||||||
D->StorageClass = SC_EXTERN | SC_STATIC;
|
D->StorageClass = SC_EXTERN | SC_STATIC;
|
||||||
@@ -205,7 +205,7 @@ static void ParseEnumDecl (void)
|
|||||||
ident Ident;
|
ident Ident;
|
||||||
|
|
||||||
/* Accept forward definitions */
|
/* Accept forward definitions */
|
||||||
if (curtok != TOK_LCURLY) {
|
if (CurTok.Tok != TOK_LCURLY) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,10 +214,10 @@ static void ParseEnumDecl (void)
|
|||||||
|
|
||||||
/* Read the enum tags */
|
/* Read the enum tags */
|
||||||
EnumVal = 0;
|
EnumVal = 0;
|
||||||
while (curtok != TOK_RCURLY) {
|
while (CurTok.Tok != TOK_RCURLY) {
|
||||||
|
|
||||||
/* We expect an identifier */
|
/* We expect an identifier */
|
||||||
if (curtok != TOK_IDENT) {
|
if (CurTok.Tok != TOK_IDENT) {
|
||||||
Error ("Identifier expected");
|
Error ("Identifier expected");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -227,7 +227,7 @@ static void ParseEnumDecl (void)
|
|||||||
NextToken ();
|
NextToken ();
|
||||||
|
|
||||||
/* Check for an assigned value */
|
/* Check for an assigned value */
|
||||||
if (curtok == TOK_ASSIGN) {
|
if (CurTok.Tok == TOK_ASSIGN) {
|
||||||
struct expent lval;
|
struct expent lval;
|
||||||
NextToken ();
|
NextToken ();
|
||||||
constexpr (&lval);
|
constexpr (&lval);
|
||||||
@@ -238,7 +238,7 @@ static void ParseEnumDecl (void)
|
|||||||
AddConstSym (Ident, type_int, SC_ENUM, EnumVal++);
|
AddConstSym (Ident, type_int, SC_ENUM, EnumVal++);
|
||||||
|
|
||||||
/* Check for end of definition */
|
/* Check for end of definition */
|
||||||
if (curtok != TOK_COMMA)
|
if (CurTok.Tok != TOK_COMMA)
|
||||||
break;
|
break;
|
||||||
NextToken ();
|
NextToken ();
|
||||||
}
|
}
|
||||||
@@ -257,7 +257,7 @@ static SymEntry* ParseStructDecl (const char* Name, type StructType)
|
|||||||
SymEntry* Entry;
|
SymEntry* Entry;
|
||||||
|
|
||||||
|
|
||||||
if (curtok != TOK_LCURLY) {
|
if (CurTok.Tok != TOK_LCURLY) {
|
||||||
/* Just a forward declaration. Try to find a struct with the given
|
/* Just a forward declaration. Try to find a struct with the given
|
||||||
* name. If there is none, insert a forward declaration into the
|
* name. If there is none, insert a forward declaration into the
|
||||||
* current lexical level.
|
* current lexical level.
|
||||||
@@ -283,7 +283,7 @@ static SymEntry* ParseStructDecl (const char* Name, type StructType)
|
|||||||
|
|
||||||
/* Parse struct fields */
|
/* Parse struct fields */
|
||||||
Size = 0;
|
Size = 0;
|
||||||
while (curtok != TOK_RCURLY) {
|
while (CurTok.Tok != TOK_RCURLY) {
|
||||||
|
|
||||||
/* Get the type of the entry */
|
/* Get the type of the entry */
|
||||||
DeclSpec Spec;
|
DeclSpec Spec;
|
||||||
@@ -310,7 +310,7 @@ static SymEntry* ParseStructDecl (const char* Name, type StructType)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curtok != TOK_COMMA)
|
if (CurTok.Tok != TOK_COMMA)
|
||||||
break;
|
break;
|
||||||
NextToken ();
|
NextToken ();
|
||||||
}
|
}
|
||||||
@@ -345,7 +345,7 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
|
|||||||
Qualifiers = OptionalQualifiers (T_QUAL_NONE);
|
Qualifiers = OptionalQualifiers (T_QUAL_NONE);
|
||||||
|
|
||||||
/* Look at the data type */
|
/* Look at the data type */
|
||||||
switch (curtok) {
|
switch (CurTok.Tok) {
|
||||||
|
|
||||||
case TOK_VOID:
|
case TOK_VOID:
|
||||||
NextToken ();
|
NextToken ();
|
||||||
@@ -361,7 +361,7 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
|
|||||||
|
|
||||||
case TOK_LONG:
|
case TOK_LONG:
|
||||||
NextToken ();
|
NextToken ();
|
||||||
if (curtok == TOK_UNSIGNED) {
|
if (CurTok.Tok == TOK_UNSIGNED) {
|
||||||
NextToken ();
|
NextToken ();
|
||||||
optionalint ();
|
optionalint ();
|
||||||
D->Type[0] = T_ULONG;
|
D->Type[0] = T_ULONG;
|
||||||
@@ -376,7 +376,7 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
|
|||||||
|
|
||||||
case TOK_SHORT:
|
case TOK_SHORT:
|
||||||
NextToken ();
|
NextToken ();
|
||||||
if (curtok == TOK_UNSIGNED) {
|
if (CurTok.Tok == TOK_UNSIGNED) {
|
||||||
NextToken ();
|
NextToken ();
|
||||||
optionalint ();
|
optionalint ();
|
||||||
D->Type[0] = T_USHORT;
|
D->Type[0] = T_USHORT;
|
||||||
@@ -397,7 +397,7 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
|
|||||||
|
|
||||||
case TOK_SIGNED:
|
case TOK_SIGNED:
|
||||||
NextToken ();
|
NextToken ();
|
||||||
switch (curtok) {
|
switch (CurTok.Tok) {
|
||||||
|
|
||||||
case TOK_CHAR:
|
case TOK_CHAR:
|
||||||
NextToken ();
|
NextToken ();
|
||||||
@@ -432,7 +432,7 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
|
|||||||
|
|
||||||
case TOK_UNSIGNED:
|
case TOK_UNSIGNED:
|
||||||
NextToken ();
|
NextToken ();
|
||||||
switch (curtok) {
|
switch (CurTok.Tok) {
|
||||||
|
|
||||||
case TOK_CHAR:
|
case TOK_CHAR:
|
||||||
NextToken ();
|
NextToken ();
|
||||||
@@ -467,10 +467,10 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
|
|||||||
|
|
||||||
case TOK_STRUCT:
|
case TOK_STRUCT:
|
||||||
case TOK_UNION:
|
case TOK_UNION:
|
||||||
StructType = (curtok == TOK_STRUCT)? T_STRUCT : T_UNION;
|
StructType = (CurTok.Tok == TOK_STRUCT)? T_STRUCT : T_UNION;
|
||||||
NextToken ();
|
NextToken ();
|
||||||
/* */
|
/* */
|
||||||
if (curtok == TOK_IDENT) {
|
if (CurTok.Tok == TOK_IDENT) {
|
||||||
strcpy (Ident, CurTok.Ident);
|
strcpy (Ident, CurTok.Ident);
|
||||||
NextToken ();
|
NextToken ();
|
||||||
} else {
|
} else {
|
||||||
@@ -488,9 +488,9 @@ static void ParseTypeSpec (DeclSpec* D, int Default)
|
|||||||
|
|
||||||
case TOK_ENUM:
|
case TOK_ENUM:
|
||||||
NextToken ();
|
NextToken ();
|
||||||
if (curtok != TOK_LCURLY) {
|
if (CurTok.Tok != TOK_LCURLY) {
|
||||||
/* Named enum */
|
/* Named enum */
|
||||||
if (curtok == TOK_IDENT) {
|
if (CurTok.Tok == TOK_IDENT) {
|
||||||
/* Find an entry with this name */
|
/* Find an entry with this name */
|
||||||
Entry = FindTagSym (CurTok.Ident);
|
Entry = FindTagSym (CurTok.Ident);
|
||||||
if (Entry) {
|
if (Entry) {
|
||||||
@@ -561,10 +561,10 @@ static void ParseOldStyleParamList (FuncDesc* F)
|
|||||||
/* Parse an old style (K&R) parameter list */
|
/* Parse an old style (K&R) parameter list */
|
||||||
{
|
{
|
||||||
/* Parse params */
|
/* Parse params */
|
||||||
while (curtok != TOK_RPAREN) {
|
while (CurTok.Tok != TOK_RPAREN) {
|
||||||
|
|
||||||
/* List of identifiers expected */
|
/* List of identifiers expected */
|
||||||
if (curtok != TOK_IDENT) {
|
if (CurTok.Tok != TOK_IDENT) {
|
||||||
Error ("Identifier expected");
|
Error ("Identifier expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -578,7 +578,7 @@ static void ParseOldStyleParamList (FuncDesc* F)
|
|||||||
NextToken ();
|
NextToken ();
|
||||||
|
|
||||||
/* Check for more parameters */
|
/* Check for more parameters */
|
||||||
if (curtok == TOK_COMMA) {
|
if (CurTok.Tok == TOK_COMMA) {
|
||||||
NextToken ();
|
NextToken ();
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
@@ -591,7 +591,7 @@ static void ParseOldStyleParamList (FuncDesc* F)
|
|||||||
ConsumeRParen ();
|
ConsumeRParen ();
|
||||||
|
|
||||||
/* An optional list of type specifications follows */
|
/* An optional list of type specifications follows */
|
||||||
while (curtok != TOK_LCURLY) {
|
while (CurTok.Tok != TOK_LCURLY) {
|
||||||
|
|
||||||
DeclSpec Spec;
|
DeclSpec Spec;
|
||||||
|
|
||||||
@@ -625,7 +625,7 @@ static void ParseOldStyleParamList (FuncDesc* F)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curtok == TOK_COMMA) {
|
if (CurTok.Tok == TOK_COMMA) {
|
||||||
NextToken ();
|
NextToken ();
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
@@ -644,14 +644,14 @@ static void ParseAnsiParamList (FuncDesc* F)
|
|||||||
/* Parse a new style (ANSI) parameter list */
|
/* Parse a new style (ANSI) parameter list */
|
||||||
{
|
{
|
||||||
/* Parse params */
|
/* Parse params */
|
||||||
while (curtok != TOK_RPAREN) {
|
while (CurTok.Tok != TOK_RPAREN) {
|
||||||
|
|
||||||
DeclSpec Spec;
|
DeclSpec Spec;
|
||||||
Declaration Decl;
|
Declaration Decl;
|
||||||
DeclAttr Attr;
|
DeclAttr Attr;
|
||||||
|
|
||||||
/* Allow an ellipsis as last parameter */
|
/* Allow an ellipsis as last parameter */
|
||||||
if (curtok == TOK_ELLIPSIS) {
|
if (CurTok.Tok == TOK_ELLIPSIS) {
|
||||||
NextToken ();
|
NextToken ();
|
||||||
F->Flags |= FD_VARIADIC;
|
F->Flags |= FD_VARIADIC;
|
||||||
break;
|
break;
|
||||||
@@ -695,7 +695,7 @@ static void ParseAnsiParamList (FuncDesc* F)
|
|||||||
++F->ParamCount;
|
++F->ParamCount;
|
||||||
|
|
||||||
/* Check for more parameters */
|
/* Check for more parameters */
|
||||||
if (curtok == TOK_COMMA) {
|
if (CurTok.Tok == TOK_COMMA) {
|
||||||
NextToken ();
|
NextToken ();
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
@@ -708,7 +708,7 @@ static void ParseAnsiParamList (FuncDesc* F)
|
|||||||
ConsumeRParen ();
|
ConsumeRParen ();
|
||||||
|
|
||||||
/* Check if this is a function definition */
|
/* Check if this is a function definition */
|
||||||
if (curtok == TOK_LCURLY) {
|
if (CurTok.Tok == TOK_LCURLY) {
|
||||||
/* Print an error if in strict ANSI mode and we have unnamed
|
/* Print an error if in strict ANSI mode and we have unnamed
|
||||||
* parameters.
|
* parameters.
|
||||||
*/
|
*/
|
||||||
@@ -733,14 +733,15 @@ static FuncDesc* ParseFuncDecl (void)
|
|||||||
EnterFunctionLevel ();
|
EnterFunctionLevel ();
|
||||||
|
|
||||||
/* Check for several special parameter lists */
|
/* Check for several special parameter lists */
|
||||||
if (curtok == TOK_RPAREN) {
|
if (CurTok.Tok == TOK_RPAREN) {
|
||||||
/* Parameter list is empty */
|
/* Parameter list is empty */
|
||||||
F->Flags |= (FD_EMPTY | FD_VARIADIC);
|
F->Flags |= (FD_EMPTY | FD_VARIADIC);
|
||||||
} else if (curtok == TOK_VOID && nxttok == TOK_RPAREN) {
|
} else if (CurTok.Tok == TOK_VOID && NextTok.Tok == TOK_RPAREN) {
|
||||||
/* Parameter list declared as void */
|
/* Parameter list declared as void */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
F->Flags |= FD_VOID_PARAM;
|
F->Flags |= FD_VOID_PARAM;
|
||||||
} else if (curtok == TOK_IDENT && (nxttok == TOK_COMMA || nxttok == TOK_RPAREN)) {
|
} else if (CurTok.Tok == TOK_IDENT &&
|
||||||
|
(NextTok.Tok == TOK_COMMA || NextTok.Tok == TOK_RPAREN)) {
|
||||||
/* If the identifier is a typedef, we have a new style parameter list,
|
/* If the identifier is a typedef, we have a new style parameter list,
|
||||||
* if it's some other identifier, it's an old style parameter list.
|
* if it's some other identifier, it's an old style parameter list.
|
||||||
*/
|
*/
|
||||||
@@ -786,7 +787,7 @@ static void Decl (Declaration* D, unsigned Mode)
|
|||||||
/* Recursively process declarators. Build a type array in reverse order. */
|
/* Recursively process declarators. Build a type array in reverse order. */
|
||||||
{
|
{
|
||||||
|
|
||||||
if (curtok == TOK_STAR) {
|
if (CurTok.Tok == TOK_STAR) {
|
||||||
type T = T_PTR;
|
type T = T_PTR;
|
||||||
NextToken ();
|
NextToken ();
|
||||||
/* Allow optional const or volatile qualifiers */
|
/* Allow optional const or volatile qualifiers */
|
||||||
@@ -794,11 +795,11 @@ static void Decl (Declaration* D, unsigned Mode)
|
|||||||
Decl (D, Mode);
|
Decl (D, Mode);
|
||||||
*D->T++ = T;
|
*D->T++ = T;
|
||||||
return;
|
return;
|
||||||
} else if (curtok == TOK_LPAREN) {
|
} else if (CurTok.Tok == TOK_LPAREN) {
|
||||||
NextToken ();
|
NextToken ();
|
||||||
Decl (D, Mode);
|
Decl (D, Mode);
|
||||||
ConsumeRParen ();
|
ConsumeRParen ();
|
||||||
} else if (curtok == TOK_FASTCALL) {
|
} else if (CurTok.Tok == TOK_FASTCALL) {
|
||||||
/* Remember the current type pointer */
|
/* Remember the current type pointer */
|
||||||
type* T = D->T;
|
type* T = D->T;
|
||||||
/* Skip the fastcall token */
|
/* Skip the fastcall token */
|
||||||
@@ -828,7 +829,7 @@ static void Decl (Declaration* D, unsigned Mode)
|
|||||||
*/
|
*/
|
||||||
if (Mode == DM_NO_IDENT) {
|
if (Mode == DM_NO_IDENT) {
|
||||||
D->Ident[0] = '\0';
|
D->Ident[0] = '\0';
|
||||||
} else if (curtok == TOK_IDENT) {
|
} else if (CurTok.Tok == TOK_IDENT) {
|
||||||
strcpy (D->Ident, CurTok.Ident);
|
strcpy (D->Ident, CurTok.Ident);
|
||||||
NextToken ();
|
NextToken ();
|
||||||
} else {
|
} else {
|
||||||
@@ -840,8 +841,8 @@ static void Decl (Declaration* D, unsigned Mode)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (curtok == TOK_LBRACK || curtok == TOK_LPAREN) {
|
while (CurTok.Tok == TOK_LBRACK || CurTok.Tok == TOK_LPAREN) {
|
||||||
if (curtok == TOK_LPAREN) {
|
if (CurTok.Tok == TOK_LPAREN) {
|
||||||
/* Function declaration */
|
/* Function declaration */
|
||||||
FuncDesc* F;
|
FuncDesc* F;
|
||||||
NextToken ();
|
NextToken ();
|
||||||
@@ -855,7 +856,7 @@ static void Decl (Declaration* D, unsigned Mode)
|
|||||||
unsigned long Size = 0;
|
unsigned long Size = 0;
|
||||||
NextToken ();
|
NextToken ();
|
||||||
/* Read the size if it is given */
|
/* Read the size if it is given */
|
||||||
if (curtok != TOK_RBRACK) {
|
if (CurTok.Tok != TOK_RBRACK) {
|
||||||
struct expent lval;
|
struct expent lval;
|
||||||
constexpr (&lval);
|
constexpr (&lval);
|
||||||
Size = lval.e_const;
|
Size = lval.e_const;
|
||||||
@@ -995,12 +996,12 @@ static void ParseVoidInit (void)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (curtok != TOK_COMMA) {
|
if (CurTok.Tok != TOK_COMMA) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
NextToken ();
|
NextToken ();
|
||||||
|
|
||||||
} while (curtok != TOK_RCURLY);
|
} while (CurTok.Tok != TOK_RCURLY);
|
||||||
|
|
||||||
ConsumeRCurly ();
|
ConsumeRCurly ();
|
||||||
}
|
}
|
||||||
@@ -1031,14 +1032,14 @@ static void ParseStructInit (type* Type)
|
|||||||
|
|
||||||
/* Get a pointer to the list of symbols */
|
/* Get a pointer to the list of symbols */
|
||||||
Entry = Tab->SymHead;
|
Entry = Tab->SymHead;
|
||||||
while (curtok != TOK_RCURLY) {
|
while (CurTok.Tok != TOK_RCURLY) {
|
||||||
if (Entry == 0) {
|
if (Entry == 0) {
|
||||||
Error ("Too many initializers");
|
Error ("Too many initializers");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ParseInit (Entry->Type);
|
ParseInit (Entry->Type);
|
||||||
Entry = Entry->NextSym;
|
Entry = Entry->NextSym;
|
||||||
if (curtok != TOK_COMMA)
|
if (CurTok.Tok != TOK_COMMA)
|
||||||
break;
|
break;
|
||||||
NextToken ();
|
NextToken ();
|
||||||
}
|
}
|
||||||
@@ -1105,20 +1106,20 @@ void ParseInit (type* T)
|
|||||||
case T_ARRAY:
|
case T_ARRAY:
|
||||||
Size = Decode (T + 1);
|
Size = Decode (T + 1);
|
||||||
t = T + DECODE_SIZE + 1;
|
t = T + DECODE_SIZE + 1;
|
||||||
if (IsTypeChar(t) && curtok == TOK_SCONST) {
|
if (IsTypeChar(t) && CurTok.Tok == TOK_SCONST) {
|
||||||
str = GetLiteral (curval);
|
str = GetLiteral (CurTok.IVal);
|
||||||
Count = strlen (str) + 1;
|
Count = strlen (str) + 1;
|
||||||
TranslateLiteralPool (curval); /* Translate into target charset */
|
TranslateLiteralPool (CurTok.IVal); /* Translate into target charset */
|
||||||
g_defbytes (str, Count);
|
g_defbytes (str, Count);
|
||||||
ResetLiteralPoolOffs (curval); /* Remove string from pool */
|
ResetLiteralPoolOffs (CurTok.IVal); /* Remove string from pool */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
} else {
|
} else {
|
||||||
ConsumeLCurly ();
|
ConsumeLCurly ();
|
||||||
Count = 0;
|
Count = 0;
|
||||||
while (curtok != TOK_RCURLY) {
|
while (CurTok.Tok != TOK_RCURLY) {
|
||||||
ParseInit (T + DECODE_SIZE + 1);
|
ParseInit (T + DECODE_SIZE + 1);
|
||||||
++Count;
|
++Count;
|
||||||
if (curtok != TOK_COMMA)
|
if (CurTok.Tok != TOK_COMMA)
|
||||||
break;
|
break;
|
||||||
NextToken ();
|
NextToken ();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
/* cc65 */
|
/* cc65 */
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
|
#include "lineinfo.h"
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "stmt.h"
|
#include "stmt.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
@@ -87,7 +88,7 @@ void Warning (const char* Format, ...)
|
|||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start (ap, Format);
|
va_start (ap, Format);
|
||||||
IntWarning (GetCurrentFile(), curpos, Format, ap);
|
IntWarning (GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Format, ap);
|
||||||
va_end (ap);
|
va_end (ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +126,7 @@ void Error (const char* Format, ...)
|
|||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start (ap, Format);
|
va_start (ap, Format);
|
||||||
IntError (GetCurrentFile(), curpos, Format, ap);
|
IntError (GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Format, ap);
|
||||||
va_end (ap);
|
va_end (ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,8 +147,18 @@ void Fatal (const char* Format, ...)
|
|||||||
/* Print a message about a fatal error and die */
|
/* Print a message about a fatal error and die */
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
|
const char* FileName;
|
||||||
|
unsigned LineNum;
|
||||||
|
if (CurTok.LI) {
|
||||||
|
FileName = GetInputName (CurTok.LI);
|
||||||
|
LineNum = GetInputLine (CurTok.LI);
|
||||||
|
} else {
|
||||||
|
FileName = GetCurrentFile ();
|
||||||
|
LineNum = GetCurrentLine ();
|
||||||
|
}
|
||||||
|
|
||||||
fprintf (stderr, "%s(%u): Fatal: ", GetCurrentFile(), curpos);
|
fprintf (stderr, "%s(%u): Fatal: ", FileName, LineNum);
|
||||||
|
|
||||||
va_start (ap, Format);
|
va_start (ap, Format);
|
||||||
vfprintf (stderr, Format, ap);
|
vfprintf (stderr, Format, ap);
|
||||||
@@ -165,8 +176,18 @@ void Internal (char* Format, ...)
|
|||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
|
||||||
|
const char* FileName;
|
||||||
|
unsigned LineNum;
|
||||||
|
if (CurTok.LI) {
|
||||||
|
FileName = GetInputName (CurTok.LI);
|
||||||
|
LineNum = GetInputLine (CurTok.LI);
|
||||||
|
} else {
|
||||||
|
FileName = GetCurrentFile ();
|
||||||
|
LineNum = GetCurrentLine ();
|
||||||
|
}
|
||||||
|
|
||||||
fprintf (stderr, "%s(%u): Internal compiler error:\n",
|
fprintf (stderr, "%s(%u): Internal compiler error:\n",
|
||||||
GetCurrentFile(), curpos);
|
FileName, LineNum);
|
||||||
|
|
||||||
va_start (ap, Format);
|
va_start (ap, Format);
|
||||||
vfprintf (stderr, Format, ap);
|
vfprintf (stderr, Format, ap);
|
||||||
@@ -190,3 +211,4 @@ void ErrorReport (void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -431,13 +431,12 @@ static int istypeexpr (void)
|
|||||||
{
|
{
|
||||||
SymEntry* Entry;
|
SymEntry* Entry;
|
||||||
|
|
||||||
return curtok == TOK_LPAREN && (
|
return CurTok.Tok == TOK_LPAREN && (
|
||||||
(nxttok >= TOK_FIRSTTYPE && nxttok <= TOK_LASTTYPE) ||
|
(NextTok.Tok >= TOK_FIRSTTYPE && NextTok.Tok <= TOK_LASTTYPE) ||
|
||||||
(nxttok == TOK_CONST) ||
|
(NextTok.Tok == TOK_CONST) ||
|
||||||
(nxttok == TOK_IDENT &&
|
(NextTok.Tok == TOK_IDENT &&
|
||||||
(Entry = FindSym (NextTok.Ident)) != 0 &&
|
(Entry = FindSym (NextTok.Ident)) != 0 &&
|
||||||
IsTypeDef (Entry))
|
IsTypeDef (Entry)));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -563,7 +562,7 @@ static unsigned FunctionParamList (FuncDesc* Func)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Parse the actual parameter list */
|
/* Parse the actual parameter list */
|
||||||
while (curtok != TOK_RPAREN) {
|
while (CurTok.Tok != TOK_RPAREN) {
|
||||||
|
|
||||||
unsigned CFlags;
|
unsigned CFlags;
|
||||||
unsigned Flags;
|
unsigned Flags;
|
||||||
@@ -656,7 +655,7 @@ static unsigned FunctionParamList (FuncDesc* Func)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check for end of argument list */
|
/* Check for end of argument list */
|
||||||
if (curtok != TOK_COMMA) {
|
if (CurTok.Tok != TOK_COMMA) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
NextToken ();
|
NextToken ();
|
||||||
@@ -745,14 +744,14 @@ void doasm (void)
|
|||||||
ConsumeLParen ();
|
ConsumeLParen ();
|
||||||
|
|
||||||
/* String literal */
|
/* String literal */
|
||||||
if (curtok != TOK_SCONST) {
|
if (CurTok.Tok != TOK_SCONST) {
|
||||||
Error ("String literal expected");
|
Error ("String literal expected");
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* The string literal may consist of more than one line of assembler
|
/* The string literal may consist of more than one line of assembler
|
||||||
* code. Separate the single lines and output the code.
|
* code. Separate the single lines and output the code.
|
||||||
*/
|
*/
|
||||||
const char* S = GetLiteral (curval);
|
const char* S = GetLiteral (CurTok.IVal);
|
||||||
while (*S) {
|
while (*S) {
|
||||||
|
|
||||||
/* Allow lines up to 256 bytes */
|
/* Allow lines up to 256 bytes */
|
||||||
@@ -773,7 +772,7 @@ void doasm (void)
|
|||||||
* will fail if the next token is also a string token, but that's a
|
* will fail if the next token is also a string token, but that's a
|
||||||
* syntax error anyway, because we expect a right paren.
|
* syntax error anyway, because we expect a right paren.
|
||||||
*/
|
*/
|
||||||
ResetLiteralPoolOffs (curval);
|
ResetLiteralPoolOffs (CurTok.IVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip the string token */
|
/* Skip the string token */
|
||||||
@@ -794,10 +793,10 @@ static int primary (struct expent* lval)
|
|||||||
lval->e_test = 0;
|
lval->e_test = 0;
|
||||||
|
|
||||||
/* Character and integer constants. */
|
/* Character and integer constants. */
|
||||||
if (curtok == TOK_ICONST || curtok == TOK_CCONST) {
|
if (CurTok.Tok == TOK_ICONST || CurTok.Tok == TOK_CCONST) {
|
||||||
lval->e_flags = E_MCONST | E_TCONST;
|
lval->e_flags = E_MCONST | E_TCONST;
|
||||||
lval->e_tptr = curtype;
|
lval->e_tptr = CurTok.Type;
|
||||||
lval->e_const = curval;
|
lval->e_const = CurTok.IVal;
|
||||||
NextToken ();
|
NextToken ();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -805,7 +804,7 @@ static int primary (struct expent* lval)
|
|||||||
/* Process parenthesized subexpression by calling the whole parser
|
/* Process parenthesized subexpression by calling the whole parser
|
||||||
* recursively.
|
* recursively.
|
||||||
*/
|
*/
|
||||||
if (curtok == TOK_LPAREN) {
|
if (CurTok.Tok == TOK_LPAREN) {
|
||||||
NextToken ();
|
NextToken ();
|
||||||
memset (lval, 0, sizeof (*lval)); /* Remove any attributes */
|
memset (lval, 0, sizeof (*lval)); /* Remove any attributes */
|
||||||
k = hie0 (lval);
|
k = hie0 (lval);
|
||||||
@@ -825,7 +824,7 @@ static int primary (struct expent* lval)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Identifier? */
|
/* Identifier? */
|
||||||
if (curtok == TOK_IDENT) {
|
if (CurTok.Tok == TOK_IDENT) {
|
||||||
|
|
||||||
SymEntry* Sym;
|
SymEntry* Sym;
|
||||||
ident Ident;
|
ident Ident;
|
||||||
@@ -915,7 +914,7 @@ static int primary (struct expent* lval)
|
|||||||
NextToken ();
|
NextToken ();
|
||||||
|
|
||||||
/* IDENT is either an auto-declared function or an undefined variable. */
|
/* IDENT is either an auto-declared function or an undefined variable. */
|
||||||
if (curtok == TOK_LPAREN) {
|
if (CurTok.Tok == TOK_LPAREN) {
|
||||||
/* Declare a function returning int. For that purpose, prepare a
|
/* Declare a function returning int. For that purpose, prepare a
|
||||||
* function signature for a function having an empty param list
|
* function signature for a function having an empty param list
|
||||||
* and returning int.
|
* and returning int.
|
||||||
@@ -942,16 +941,16 @@ static int primary (struct expent* lval)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* String literal? */
|
/* String literal? */
|
||||||
if (curtok == TOK_SCONST) {
|
if (CurTok.Tok == TOK_SCONST) {
|
||||||
lval->e_flags = E_MCONST | E_TLIT;
|
lval->e_flags = E_MCONST | E_TLIT;
|
||||||
lval->e_const = curval;
|
lval->e_const = CurTok.IVal;
|
||||||
lval->e_tptr = GetCharArrayType (strlen (GetLiteral (curval)));
|
lval->e_tptr = GetCharArrayType (strlen (GetLiteral (CurTok.IVal)));
|
||||||
NextToken ();
|
NextToken ();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ASM statement? */
|
/* ASM statement? */
|
||||||
if (curtok == TOK_ASM) {
|
if (CurTok.Tok == TOK_ASM) {
|
||||||
doasm ();
|
doasm ();
|
||||||
lval->e_tptr = type_void;
|
lval->e_tptr = type_void;
|
||||||
lval->e_flags = E_MEXPR;
|
lval->e_flags = E_MEXPR;
|
||||||
@@ -960,8 +959,8 @@ static int primary (struct expent* lval)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* __AX__ and __EAX__ pseudo values? */
|
/* __AX__ and __EAX__ pseudo values? */
|
||||||
if (curtok == TOK_AX || curtok == TOK_EAX) {
|
if (CurTok.Tok == TOK_AX || CurTok.Tok == TOK_EAX) {
|
||||||
lval->e_tptr = (curtok == TOK_AX)? type_uint : type_ulong;
|
lval->e_tptr = (CurTok.Tok == TOK_AX)? type_uint : type_ulong;
|
||||||
lval->e_flags = E_MREG;
|
lval->e_flags = E_MREG;
|
||||||
lval->e_test &= ~E_CC;
|
lval->e_test &= ~E_CC;
|
||||||
lval->e_const = 0;
|
lval->e_const = 0;
|
||||||
@@ -1220,7 +1219,7 @@ static int structref (int k, struct expent* lval)
|
|||||||
|
|
||||||
/* Skip the token and check for an identifier */
|
/* Skip the token and check for an identifier */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
if (curtok != TOK_IDENT) {
|
if (CurTok.Tok != TOK_IDENT) {
|
||||||
Error ("Identifier expected");
|
Error ("Identifier expected");
|
||||||
lval->e_tptr = type_int;
|
lval->e_tptr = type_int;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1264,19 +1263,19 @@ static int hie11 (struct expent *lval)
|
|||||||
|
|
||||||
|
|
||||||
k = primary (lval);
|
k = primary (lval);
|
||||||
if (curtok < TOK_LBRACK || curtok > TOK_PTR_REF) {
|
if (CurTok.Tok < TOK_LBRACK || CurTok.Tok > TOK_PTR_REF) {
|
||||||
/* Not for us */
|
/* Not for us */
|
||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
if (curtok == TOK_LBRACK) {
|
if (CurTok.Tok == TOK_LBRACK) {
|
||||||
|
|
||||||
/* Array reference */
|
/* Array reference */
|
||||||
k = arrayref (k, lval);
|
k = arrayref (k, lval);
|
||||||
|
|
||||||
} else if (curtok == TOK_LPAREN) {
|
} else if (CurTok.Tok == TOK_LPAREN) {
|
||||||
|
|
||||||
/* Function call. Skip the opening parenthesis */
|
/* Function call. Skip the opening parenthesis */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
@@ -1296,14 +1295,14 @@ static int hie11 (struct expent *lval)
|
|||||||
}
|
}
|
||||||
k = 0;
|
k = 0;
|
||||||
|
|
||||||
} else if (curtok == TOK_DOT) {
|
} else if (CurTok.Tok == TOK_DOT) {
|
||||||
|
|
||||||
if (!IsClassStruct (lval->e_tptr)) {
|
if (!IsClassStruct (lval->e_tptr)) {
|
||||||
Error ("Struct expected");
|
Error ("Struct expected");
|
||||||
}
|
}
|
||||||
k = structref (0, lval);
|
k = structref (0, lval);
|
||||||
|
|
||||||
} else if (curtok == TOK_PTR_REF) {
|
} else if (CurTok.Tok == TOK_PTR_REF) {
|
||||||
|
|
||||||
tptr = lval->e_tptr;
|
tptr = lval->e_tptr;
|
||||||
if (tptr[0] != T_PTR || (tptr[1] & T_STRUCT) == 0) {
|
if (tptr[0] != T_PTR || (tptr[1] & T_STRUCT) == 0) {
|
||||||
@@ -1612,7 +1611,7 @@ static int hie10 (struct expent* lval)
|
|||||||
int k;
|
int k;
|
||||||
type* t;
|
type* t;
|
||||||
|
|
||||||
switch (curtok) {
|
switch (CurTok.Tok) {
|
||||||
|
|
||||||
case TOK_INC:
|
case TOK_INC:
|
||||||
pre_incdec (lval, g_inc);
|
pre_incdec (lval, g_inc);
|
||||||
@@ -1625,7 +1624,7 @@ static int hie10 (struct expent* lval)
|
|||||||
case TOK_PLUS:
|
case TOK_PLUS:
|
||||||
case TOK_MINUS:
|
case TOK_MINUS:
|
||||||
case TOK_COMP:
|
case TOK_COMP:
|
||||||
unaryop (curtok, lval);
|
unaryop (CurTok.Tok, lval);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case TOK_BOOL_NOT:
|
case TOK_BOOL_NOT:
|
||||||
@@ -1702,7 +1701,7 @@ static int hie10 (struct expent* lval)
|
|||||||
}
|
}
|
||||||
|
|
||||||
k = hie11 (lval);
|
k = hie11 (lval);
|
||||||
switch (curtok) {
|
switch (CurTok.Tok) {
|
||||||
case TOK_INC:
|
case TOK_INC:
|
||||||
post_incdec (lval, k, g_inc);
|
post_incdec (lval, k, g_inc);
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1737,7 +1736,7 @@ static int hie_internal (GenDesc** ops, /* List of generators */
|
|||||||
k = hienext (lval);
|
k = hienext (lval);
|
||||||
|
|
||||||
*UsedGen = 0;
|
*UsedGen = 0;
|
||||||
while ((Gen = FindGen (curtok, ops)) != 0) {
|
while ((Gen = FindGen (CurTok.Tok, ops)) != 0) {
|
||||||
|
|
||||||
/* Tell the caller that we handled it's ops */
|
/* Tell the caller that we handled it's ops */
|
||||||
*UsedGen = 1;
|
*UsedGen = 1;
|
||||||
@@ -1748,7 +1747,7 @@ static int hie_internal (GenDesc** ops, /* List of generators */
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Remember the operator token, then skip it */
|
/* Remember the operator token, then skip it */
|
||||||
tok = curtok;
|
tok = CurTok.Tok;
|
||||||
NextToken ();
|
NextToken ();
|
||||||
|
|
||||||
/* Get the lhs on stack */
|
/* Get the lhs on stack */
|
||||||
@@ -1845,10 +1844,10 @@ static int hie_compare (GenDesc** ops, /* List of generators */
|
|||||||
|
|
||||||
k = hienext (lval);
|
k = hienext (lval);
|
||||||
|
|
||||||
while ((Gen = FindGen (curtok, ops)) != 0) {
|
while ((Gen = FindGen (CurTok.Tok, ops)) != 0) {
|
||||||
|
|
||||||
/* Remember the operator token, then skip it */
|
/* Remember the operator token, then skip it */
|
||||||
tok = curtok;
|
tok = CurTok.Tok;
|
||||||
NextToken ();
|
NextToken ();
|
||||||
|
|
||||||
/* Get the lhs on stack */
|
/* Get the lhs on stack */
|
||||||
@@ -2305,9 +2304,9 @@ static int hie8 (struct expent* lval)
|
|||||||
/* Process + and - binary operators. */
|
/* Process + and - binary operators. */
|
||||||
{
|
{
|
||||||
int k = hie9 (lval);
|
int k = hie9 (lval);
|
||||||
while (curtok == TOK_PLUS || curtok == TOK_MINUS) {
|
while (CurTok.Tok == TOK_PLUS || CurTok.Tok == TOK_MINUS) {
|
||||||
|
|
||||||
if (curtok == TOK_PLUS) {
|
if (CurTok.Tok == TOK_PLUS) {
|
||||||
parseadd (k, lval);
|
parseadd (k, lval);
|
||||||
} else {
|
} else {
|
||||||
parsesub (k, lval);
|
parsesub (k, lval);
|
||||||
@@ -2401,7 +2400,7 @@ static int hieAnd (struct expent* lval, unsigned TrueLab, int* BoolOp)
|
|||||||
struct expent lval2;
|
struct expent lval2;
|
||||||
|
|
||||||
k = hie2 (lval);
|
k = hie2 (lval);
|
||||||
if (curtok == TOK_BOOL_AND) {
|
if (CurTok.Tok == TOK_BOOL_AND) {
|
||||||
|
|
||||||
/* Tell our caller that we're evaluating a boolean */
|
/* Tell our caller that we're evaluating a boolean */
|
||||||
*BoolOp = 1;
|
*BoolOp = 1;
|
||||||
@@ -2421,7 +2420,7 @@ static int hieAnd (struct expent* lval, unsigned TrueLab, int* BoolOp)
|
|||||||
g_falsejump (CF_NONE, lab);
|
g_falsejump (CF_NONE, lab);
|
||||||
|
|
||||||
/* Parse more boolean and's */
|
/* Parse more boolean and's */
|
||||||
while (curtok == TOK_BOOL_AND) {
|
while (CurTok.Tok == TOK_BOOL_AND) {
|
||||||
|
|
||||||
/* Skip the && */
|
/* Skip the && */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
@@ -2434,7 +2433,7 @@ static int hieAnd (struct expent* lval, unsigned TrueLab, int* BoolOp)
|
|||||||
exprhs (CF_FORCECHAR, k, &lval2);
|
exprhs (CF_FORCECHAR, k, &lval2);
|
||||||
|
|
||||||
/* Do short circuit evaluation */
|
/* Do short circuit evaluation */
|
||||||
if (curtok == TOK_BOOL_AND) {
|
if (CurTok.Tok == TOK_BOOL_AND) {
|
||||||
g_falsejump (CF_NONE, lab);
|
g_falsejump (CF_NONE, lab);
|
||||||
} else {
|
} else {
|
||||||
/* Last expression - will evaluate to true */
|
/* Last expression - will evaluate to true */
|
||||||
@@ -2472,7 +2471,7 @@ static int hieOr (struct expent *lval)
|
|||||||
k = hieAnd (lval, TrueLab, &BoolOp);
|
k = hieAnd (lval, TrueLab, &BoolOp);
|
||||||
|
|
||||||
/* Any boolean or's? */
|
/* Any boolean or's? */
|
||||||
if (curtok == TOK_BOOL_OR) {
|
if (CurTok.Tok == TOK_BOOL_OR) {
|
||||||
|
|
||||||
/* If the expr hasn't set condition codes, set the force-test flag */
|
/* If the expr hasn't set condition codes, set the force-test flag */
|
||||||
if ((lval->e_test & E_CC) == 0) {
|
if ((lval->e_test & E_CC) == 0) {
|
||||||
@@ -2493,7 +2492,7 @@ static int hieOr (struct expent *lval)
|
|||||||
BoolOp = 1;
|
BoolOp = 1;
|
||||||
|
|
||||||
/* while there's more expr */
|
/* while there's more expr */
|
||||||
while (curtok == TOK_BOOL_OR) {
|
while (CurTok.Tok == TOK_BOOL_OR) {
|
||||||
|
|
||||||
/* skip the || */
|
/* skip the || */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
@@ -2512,7 +2511,7 @@ static int hieOr (struct expent *lval)
|
|||||||
*/
|
*/
|
||||||
#if 0
|
#if 0
|
||||||
/* Seems this sometimes generates wrong code */
|
/* Seems this sometimes generates wrong code */
|
||||||
if (curtok == TOK_BOOL_OR && !AndOp) {
|
if (CurTok.Tok == TOK_BOOL_OR && !AndOp) {
|
||||||
g_truejump (CF_NONE, TrueLab);
|
g_truejump (CF_NONE, TrueLab);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
@@ -2555,7 +2554,7 @@ static int hieQuest (struct expent *lval)
|
|||||||
|
|
||||||
|
|
||||||
k = hieOr (lval);
|
k = hieOr (lval);
|
||||||
if (curtok == TOK_QUEST) {
|
if (CurTok.Tok == TOK_QUEST) {
|
||||||
NextToken ();
|
NextToken ();
|
||||||
if ((lval->e_test & E_CC) == 0) {
|
if ((lval->e_test & E_CC) == 0) {
|
||||||
/* Condition codes not set, force a test */
|
/* Condition codes not set, force a test */
|
||||||
@@ -2901,7 +2900,7 @@ int hie1 (struct expent* lval)
|
|||||||
int k;
|
int k;
|
||||||
|
|
||||||
k = hieQuest (lval);
|
k = hieQuest (lval);
|
||||||
switch (curtok) {
|
switch (CurTok.Tok) {
|
||||||
|
|
||||||
case TOK_RPAREN:
|
case TOK_RPAREN:
|
||||||
case TOK_SEMI:
|
case TOK_SEMI:
|
||||||
@@ -2970,7 +2969,7 @@ int hie0 (struct expent *lval)
|
|||||||
int k;
|
int k;
|
||||||
|
|
||||||
k = hie1 (lval);
|
k = hie1 (lval);
|
||||||
while (curtok == TOK_COMMA) {
|
while (CurTok.Tok == TOK_COMMA) {
|
||||||
NextToken ();
|
NextToken ();
|
||||||
k = hie1 (lval);
|
k = hie1 (lval);
|
||||||
}
|
}
|
||||||
@@ -3140,7 +3139,7 @@ void test (unsigned label, int cond)
|
|||||||
* compiler itself is one big hack...): If a semicolon follows, we
|
* compiler itself is one big hack...): If a semicolon follows, we
|
||||||
* don't have a statement and may omit the jump.
|
* don't have a statement and may omit the jump.
|
||||||
*/
|
*/
|
||||||
if (curtok != TOK_SEMI) {
|
if (CurTok.Tok != TOK_SEMI) {
|
||||||
g_falsejump (CF_NONE, label);
|
g_falsejump (CF_NONE, label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -294,8 +294,8 @@ void NewFunc (SymEntry* Func)
|
|||||||
|
|
||||||
/* Now process statements in this block */
|
/* Now process statements in this block */
|
||||||
HadReturn = 0;
|
HadReturn = 0;
|
||||||
while (curtok != TOK_RCURLY) {
|
while (CurTok.Tok != TOK_RCURLY) {
|
||||||
if (curtok != TOK_CEOF) {
|
if (CurTok.Tok != TOK_CEOF) {
|
||||||
HadReturn = Statement ();
|
HadReturn = Statement ();
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ void DoGoto (void)
|
|||||||
NextToken ();
|
NextToken ();
|
||||||
|
|
||||||
/* Label name must follow */
|
/* Label name must follow */
|
||||||
if (curtok != TOK_IDENT) {
|
if (CurTok.Tok != TOK_IDENT) {
|
||||||
|
|
||||||
Error ("Label name expected");
|
Error ("Label name expected");
|
||||||
|
|
||||||
|
|||||||
@@ -45,8 +45,8 @@
|
|||||||
/* cc65 */
|
/* cc65 */
|
||||||
#include "asmcode.h"
|
#include "asmcode.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "global.h"
|
|
||||||
#include "incpath.h"
|
#include "incpath.h"
|
||||||
|
#include "lineinfo.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -69,20 +69,12 @@ char NextC = '\0';
|
|||||||
/* Maximum count of nested includes */
|
/* Maximum count of nested includes */
|
||||||
#define MAX_INC_NESTING 16
|
#define MAX_INC_NESTING 16
|
||||||
|
|
||||||
/* Struct that describes an input file */
|
|
||||||
typedef struct IFile IFile;
|
|
||||||
struct IFile {
|
|
||||||
unsigned Index; /* File index */
|
|
||||||
unsigned Usage; /* Usage counter */
|
|
||||||
char Name[1]; /* Name of file (dynamically allocated) */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Struct that describes an active input file */
|
/* Struct that describes an active input file */
|
||||||
typedef struct AFile AFile;
|
typedef struct AFile AFile;
|
||||||
struct AFile {
|
struct AFile {
|
||||||
unsigned Line; /* Line number for this file */
|
unsigned Line; /* Line number for this file */
|
||||||
FILE* F; /* Input file stream */
|
FILE* F; /* Input file stream */
|
||||||
const char* Name; /* Points to corresponding IFile name */
|
IFile* Input; /* Points to corresponding IFile */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* List of all input files */
|
/* List of all input files */
|
||||||
@@ -137,7 +129,7 @@ static AFile* NewAFile (IFile* IF, FILE* F)
|
|||||||
/* Initialize the fields */
|
/* Initialize the fields */
|
||||||
AF->Line = 0;
|
AF->Line = 0;
|
||||||
AF->F = F;
|
AF->F = F;
|
||||||
AF->Name = IF->Name;
|
AF->Input = IF;
|
||||||
|
|
||||||
/* Increment the usage counter of the corresponding IFile */
|
/* Increment the usage counter of the corresponding IFile */
|
||||||
++IF->Usage;
|
++IF->Usage;
|
||||||
@@ -378,16 +370,6 @@ int NextLine (void)
|
|||||||
--Len;
|
--Len;
|
||||||
}
|
}
|
||||||
line [Len] = '\0';
|
line [Len] = '\0';
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* ######### */
|
|
||||||
/* Output the source line in the generated assembler file
|
|
||||||
* if requested.
|
|
||||||
*/
|
|
||||||
if (AddSource && line[Start] != '\0') {
|
|
||||||
AddCodeLine ("; %s", line+Start);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Check if we have a line continuation character at the end. If not,
|
/* Check if we have a line continuation character at the end. If not,
|
||||||
* we're done.
|
* we're done.
|
||||||
@@ -402,6 +384,9 @@ int NextLine (void)
|
|||||||
/* Got a line. Initialize the current and next characters. */
|
/* Got a line. Initialize the current and next characters. */
|
||||||
InitLine (line);
|
InitLine (line);
|
||||||
|
|
||||||
|
/* Create line information for this line */
|
||||||
|
UpdateLineInfo (Input->Input, Input->Line, line);
|
||||||
|
|
||||||
/* Done */
|
/* Done */
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -414,7 +399,7 @@ const char* GetCurrentFile (void)
|
|||||||
unsigned AFileCount = CollCount (&AFiles);
|
unsigned AFileCount = CollCount (&AFiles);
|
||||||
if (AFileCount > 0) {
|
if (AFileCount > 0) {
|
||||||
const AFile* AF = (const AFile*) CollAt (&AFiles, AFileCount-1);
|
const AFile* AF = (const AFile*) CollAt (&AFiles, AFileCount-1);
|
||||||
return AF->Name;
|
return AF->Input->Name;
|
||||||
} else {
|
} else {
|
||||||
/* No open file. Use the main file if we have one. */
|
/* No open file. Use the main file if we have one. */
|
||||||
unsigned IFileCount = CollCount (&IFiles);
|
unsigned IFileCount = CollCount (&IFiles);
|
||||||
|
|||||||
@@ -38,6 +38,10 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* data */
|
/* data */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -56,6 +60,14 @@ extern const char* lptr; /* ### Remove this */
|
|||||||
extern char CurC;
|
extern char CurC;
|
||||||
extern char NextC;
|
extern char NextC;
|
||||||
|
|
||||||
|
/* Struct that describes an input file */
|
||||||
|
typedef struct IFile IFile;
|
||||||
|
struct IFile {
|
||||||
|
unsigned Index; /* File index */
|
||||||
|
unsigned Usage; /* Usage counter */
|
||||||
|
char Name[1]; /* Name of file (dynamically allocated) */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|||||||
159
src/cc65/lineinfo.c
Normal file
159
src/cc65/lineinfo.c
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* */
|
||||||
|
/* lineinfo.c */
|
||||||
|
/* */
|
||||||
|
/* Source file line info structure */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* (C) 2001 Ullrich von Bassewitz */
|
||||||
|
/* Wacholderweg 14 */
|
||||||
|
/* D-70597 Stuttgart */
|
||||||
|
/* EMail: uz@musoftware.de */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
|
/* warranty. In no event will the authors be held liable for any damages */
|
||||||
|
/* arising from the use of this software. */
|
||||||
|
/* */
|
||||||
|
/* Permission is granted to anyone to use this software for any purpose, */
|
||||||
|
/* including commercial applications, and to alter it and redistribute it */
|
||||||
|
/* freely, subject to the following restrictions: */
|
||||||
|
/* */
|
||||||
|
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||||
|
/* claim that you wrote the original software. If you use this software */
|
||||||
|
/* in a product, an acknowledgment in the product documentation would be */
|
||||||
|
/* appreciated but is not required. */
|
||||||
|
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||||
|
/* be misrepresented as being the original software. */
|
||||||
|
/* 3. This notice may not be removed or altered from any source */
|
||||||
|
/* distribution. */
|
||||||
|
/* */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* common */
|
||||||
|
#include "check.h"
|
||||||
|
#include "xmalloc.h"
|
||||||
|
|
||||||
|
/* cc65 */
|
||||||
|
#include "input.h"
|
||||||
|
#include "lineinfo.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Data */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Global pointer to line information for the current line */
|
||||||
|
static LineInfo* CurLineInfo = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Code */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static LineInfo* NewLineInfo (struct IFile* F, unsigned LineNum, const char* Line)
|
||||||
|
/* Create and return a new line info. Ref count will be 1. */
|
||||||
|
{
|
||||||
|
/* Calculate the length of the line */
|
||||||
|
unsigned Len = strlen (Line);
|
||||||
|
|
||||||
|
/* Allocate memory */
|
||||||
|
LineInfo* LI = xmalloc (sizeof (LineInfo) + Len);
|
||||||
|
|
||||||
|
/* Initialize the fields */
|
||||||
|
LI->RefCount = 1;
|
||||||
|
LI->InputFile = F;
|
||||||
|
LI->LineNum = LineNum;
|
||||||
|
memcpy (LI->Line, Line, Len+1);
|
||||||
|
|
||||||
|
/* Return the new struct */
|
||||||
|
return LI;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void FreeLineInfo (LineInfo* LI)
|
||||||
|
/* Free a LineInfo structure */
|
||||||
|
{
|
||||||
|
xfree (LI);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
LineInfo* UseLineInfo (LineInfo* LI)
|
||||||
|
/* Increase the reference count of the given line info and return it. */
|
||||||
|
{
|
||||||
|
CHECK (LI != 0);
|
||||||
|
++LI->RefCount;
|
||||||
|
return LI;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void ReleaseLineInfo (LineInfo* LI)
|
||||||
|
/* Release a reference to the given line info, free the structure if the
|
||||||
|
* reference count drops to zero.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
CHECK (LI && LI->RefCount > 0);
|
||||||
|
if (--LI->RefCount == 0) {
|
||||||
|
/* No more references, free it */
|
||||||
|
FreeLineInfo (LI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
LineInfo* GetCurLineInfo (void)
|
||||||
|
/* Return a pointer to the current line info. The reference count is NOT
|
||||||
|
* increased, use UseLineInfo for that purpose.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
return CurLineInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void UpdateLineInfo (struct IFile* F, unsigned LineNum, const char* Line)
|
||||||
|
/* Update the line info - called if a new line is read */
|
||||||
|
{
|
||||||
|
/* If a current line info exists, release it */
|
||||||
|
if (CurLineInfo) {
|
||||||
|
ReleaseLineInfo (CurLineInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a new line info */
|
||||||
|
CurLineInfo = NewLineInfo (F, LineNum, Line);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const char* GetInputName (const LineInfo* LI)
|
||||||
|
/* Return the file name from a line info */
|
||||||
|
{
|
||||||
|
PRECONDITION (LI != 0);
|
||||||
|
return LI->InputFile->Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
unsigned GetInputLine (const LineInfo* LI)
|
||||||
|
/* Return the line number from a line info */
|
||||||
|
{
|
||||||
|
PRECONDITION (LI != 0);
|
||||||
|
return LI->LineNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
106
src/cc65/lineinfo.h
Normal file
106
src/cc65/lineinfo.h
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/* */
|
||||||
|
/* lineinfo.h */
|
||||||
|
/* */
|
||||||
|
/* Source file line info structure */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* (C) 2001 Ullrich von Bassewitz */
|
||||||
|
/* Wacholderweg 14 */
|
||||||
|
/* D-70597 Stuttgart */
|
||||||
|
/* EMail: uz@musoftware.de */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
|
/* warranty. In no event will the authors be held liable for any damages */
|
||||||
|
/* arising from the use of this software. */
|
||||||
|
/* */
|
||||||
|
/* Permission is granted to anyone to use this software for any purpose, */
|
||||||
|
/* including commercial applications, and to alter it and redistribute it */
|
||||||
|
/* freely, subject to the following restrictions: */
|
||||||
|
/* */
|
||||||
|
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||||
|
/* claim that you wrote the original software. If you use this software */
|
||||||
|
/* in a product, an acknowledgment in the product documentation would be */
|
||||||
|
/* appreciated but is not required. */
|
||||||
|
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||||
|
/* be misrepresented as being the original software. */
|
||||||
|
/* 3. This notice may not be removed or altered from any source */
|
||||||
|
/* distribution. */
|
||||||
|
/* */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef LINEINFO_H
|
||||||
|
#define LINEINFO_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Forwards */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Input file structure */
|
||||||
|
struct IFile;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Data */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* The text for the actual line is allocated at the end of the structure, so
|
||||||
|
* the size of the structure varies.
|
||||||
|
*/
|
||||||
|
typedef struct LineInfo LineInfo;
|
||||||
|
struct LineInfo {
|
||||||
|
unsigned RefCount; /* Reference counter */
|
||||||
|
struct IFile* InputFile; /* Input file for this line */
|
||||||
|
unsigned LineNum; /* Line number */
|
||||||
|
char Line[1]; /* Source code line */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Code */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
LineInfo* UseLineInfo (LineInfo* LI);
|
||||||
|
/* Increase the reference count of the given line info and return it. */
|
||||||
|
|
||||||
|
void ReleaseLineInfo (LineInfo* LI);
|
||||||
|
/* Release a reference to the given line info, free the structure if the
|
||||||
|
* reference count drops to zero.
|
||||||
|
*/
|
||||||
|
|
||||||
|
LineInfo* GetCurLineInfo (void);
|
||||||
|
/* Return a pointer to the current line info. The reference count is NOT
|
||||||
|
* increased, use UseLineInfo for that purpose.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void UpdateLineInfo (struct IFile* F, unsigned LineNum, const char* Line);
|
||||||
|
/* Update the line info - called if a new line is read */
|
||||||
|
|
||||||
|
const char* GetInputName (const LineInfo* LI);
|
||||||
|
/* Return the file name from a line info */
|
||||||
|
|
||||||
|
unsigned GetInputLine (const LineInfo* LI);
|
||||||
|
/* Return the line number from a line info */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* End of lineinfo.h */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -178,7 +178,7 @@ static void ParseOneDecl (const DeclSpec* Spec)
|
|||||||
|
|
||||||
/* Change SC in case it was register */
|
/* Change SC in case it was register */
|
||||||
SC = (SC & ~SC_REGISTER) | SC_AUTO;
|
SC = (SC & ~SC_REGISTER) | SC_AUTO;
|
||||||
if (curtok == TOK_ASSIGN) {
|
if (CurTok.Tok == TOK_ASSIGN) {
|
||||||
|
|
||||||
struct expent lval;
|
struct expent lval;
|
||||||
|
|
||||||
@@ -233,7 +233,7 @@ static void ParseOneDecl (const DeclSpec* Spec)
|
|||||||
g_res (Size);
|
g_res (Size);
|
||||||
|
|
||||||
/* Allow assignments */
|
/* Allow assignments */
|
||||||
if (curtok == TOK_ASSIGN) {
|
if (CurTok.Tok == TOK_ASSIGN) {
|
||||||
|
|
||||||
struct expent lval;
|
struct expent lval;
|
||||||
|
|
||||||
@@ -263,7 +263,7 @@ static void ParseOneDecl (const DeclSpec* Spec)
|
|||||||
} else if ((SC & SC_STATIC) == SC_STATIC) {
|
} else if ((SC & SC_STATIC) == SC_STATIC) {
|
||||||
|
|
||||||
/* Static data */
|
/* Static data */
|
||||||
if (curtok == TOK_ASSIGN) {
|
if (CurTok.Tok == TOK_ASSIGN) {
|
||||||
|
|
||||||
/* Initialization ahead, switch to data segment */
|
/* Initialization ahead, switch to data segment */
|
||||||
if (IsQualConst (Decl.Type)) {
|
if (IsQualConst (Decl.Type)) {
|
||||||
@@ -335,7 +335,7 @@ void DeclareLocals (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Accept type only declarations */
|
/* Accept type only declarations */
|
||||||
if (curtok == TOK_SEMI) {
|
if (CurTok.Tok == TOK_SEMI) {
|
||||||
/* Type declaration only */
|
/* Type declaration only */
|
||||||
CheckEmptyDecl (&Spec);
|
CheckEmptyDecl (&Spec);
|
||||||
NextToken ();
|
NextToken ();
|
||||||
@@ -349,7 +349,7 @@ void DeclareLocals (void)
|
|||||||
ParseOneDecl (&Spec);
|
ParseOneDecl (&Spec);
|
||||||
|
|
||||||
/* Check if there is more */
|
/* Check if there is more */
|
||||||
if (curtok == TOK_COMMA) {
|
if (CurTok.Tok == TOK_COMMA) {
|
||||||
/* More to come */
|
/* More to come */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ OBJS = anonname.o \
|
|||||||
ident.o \
|
ident.o \
|
||||||
incpath.o \
|
incpath.o \
|
||||||
input.o \
|
input.o \
|
||||||
|
lineinfo.o \
|
||||||
litpool.o \
|
litpool.o \
|
||||||
locals.o \
|
locals.o \
|
||||||
loop.o \
|
loop.o \
|
||||||
|
|||||||
@@ -119,17 +119,17 @@ static pragma_t FindPragma (const char* Key)
|
|||||||
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 */
|
||||||
{
|
{
|
||||||
if (curtok != TOK_SCONST) {
|
if (CurTok.Tok != TOK_SCONST) {
|
||||||
Error ("String literal expected");
|
Error ("String literal expected");
|
||||||
} else {
|
} else {
|
||||||
/* Get the string */
|
/* Get the string */
|
||||||
const char* Name = GetLiteral (curval);
|
const char* Name = GetLiteral (CurTok.IVal);
|
||||||
|
|
||||||
/* Call the given function with the string argument */
|
/* Call the given function with the string argument */
|
||||||
Func (Name);
|
Func (Name);
|
||||||
|
|
||||||
/* Reset the string pointer, removing the string from the pool */
|
/* Reset the string pointer, removing the string from the pool */
|
||||||
ResetLiteralPoolOffs (curval);
|
ResetLiteralPoolOffs (CurTok.IVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip the string (or error) token */
|
/* Skip the string (or error) token */
|
||||||
@@ -141,11 +141,11 @@ static void StringPragma (void (*Func) (const char*))
|
|||||||
static void SegNamePragma (segment_t Seg)
|
static void SegNamePragma (segment_t Seg)
|
||||||
/* Handle a pragma that expects a segment name parameter */
|
/* Handle a pragma that expects a segment name parameter */
|
||||||
{
|
{
|
||||||
if (curtok != TOK_SCONST) {
|
if (CurTok.Tok != TOK_SCONST) {
|
||||||
Error ("String literal expected");
|
Error ("String literal expected");
|
||||||
} else {
|
} else {
|
||||||
/* Get the segment name */
|
/* Get the segment name */
|
||||||
const char* Name = GetLiteral (curval);
|
const char* Name = GetLiteral (CurTok.IVal);
|
||||||
|
|
||||||
/* Check if the name is valid */
|
/* Check if the name is valid */
|
||||||
if (ValidSegName (Name)) {
|
if (ValidSegName (Name)) {
|
||||||
@@ -161,7 +161,7 @@ static void SegNamePragma (segment_t Seg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the string pointer, removing the string from the pool */
|
/* Reset the string pointer, removing the string from the pool */
|
||||||
ResetLiteralPoolOffs (curval);
|
ResetLiteralPoolOffs (CurTok.IVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip the string (or error) token */
|
/* Skip the string (or error) token */
|
||||||
@@ -192,7 +192,7 @@ void DoPragma (void)
|
|||||||
NextToken ();
|
NextToken ();
|
||||||
|
|
||||||
/* Identifier must follow */
|
/* Identifier must follow */
|
||||||
if (curtok != TOK_IDENT) {
|
if (CurTok.Tok != TOK_IDENT) {
|
||||||
Error ("Identifier expected");
|
Error ("Identifier expected");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,35 @@
|
|||||||
/*
|
/*****************************************************************************/
|
||||||
* scanner.c
|
/* */
|
||||||
*
|
/* scanner.c */
|
||||||
* Ullrich von Bassewitz, 07.06.1998
|
/* */
|
||||||
*/
|
/* Source file line info structure */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* (C) 1998-2001 Ullrich von Bassewitz */
|
||||||
|
/* Wacholderweg 14 */
|
||||||
|
/* D-70597 Stuttgart */
|
||||||
|
/* EMail: uz@musoftware.de */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
|
/* warranty. In no event will the authors be held liable for any damages */
|
||||||
|
/* arising from the use of this software. */
|
||||||
|
/* */
|
||||||
|
/* Permission is granted to anyone to use this software for any purpose, */
|
||||||
|
/* including commercial applications, and to alter it and redistribute it */
|
||||||
|
/* freely, subject to the following restrictions: */
|
||||||
|
/* */
|
||||||
|
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||||
|
/* claim that you wrote the original software. If you use this software */
|
||||||
|
/* in a product, an acknowledgment in the product documentation would be */
|
||||||
|
/* appreciated but is not required. */
|
||||||
|
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||||
|
/* be misrepresented as being the original software. */
|
||||||
|
/* 3. This notice may not be removed or altered from any source */
|
||||||
|
/* distribution. */
|
||||||
|
/* */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -190,7 +217,7 @@ int IsSym (char *s)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void unknown (char C)
|
static void UnknownChar (char C)
|
||||||
/* Error message for unknown character */
|
/* Error message for unknown character */
|
||||||
{
|
{
|
||||||
Error ("Invalid input character with code %02X", C & 0xFF);
|
Error ("Invalid input character with code %02X", C & 0xFF);
|
||||||
@@ -215,9 +242,9 @@ static unsigned hexval (int c)
|
|||||||
|
|
||||||
|
|
||||||
static void SetTok (int tok)
|
static void SetTok (int tok)
|
||||||
/* set nxttok and bump line ptr */
|
/* Set NextTok.Tok and bump line ptr */
|
||||||
{
|
{
|
||||||
nxttok = tok;
|
NextTok.Tok = tok;
|
||||||
NextChar ();
|
NextChar ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,7 +311,7 @@ static int ParseChar (void)
|
|||||||
i = 0;
|
i = 0;
|
||||||
C = CurC - '0';
|
C = CurC - '0';
|
||||||
while (NextC >= '0' && NextC <= '7' && i++ < 4) {
|
while (NextC >= '0' && NextC <= '7' && i++ < 4) {
|
||||||
NextChar ();
|
NextChar ();
|
||||||
C = (C << 3) | (CurC - '0');
|
C = (C << 3) | (CurC - '0');
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -326,13 +353,13 @@ static void CharConst (void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Setup values and attributes */
|
/* Setup values and attributes */
|
||||||
nxttok = TOK_CCONST;
|
NextTok.Tok = TOK_CCONST;
|
||||||
|
|
||||||
/* Translate into target charset */
|
/* Translate into target charset */
|
||||||
nxtval = SignExtendChar (TgtTranslateChar (C));
|
NextTok.IVal = SignExtendChar (TgtTranslateChar (C));
|
||||||
|
|
||||||
/* Character constants have type int */
|
/* Character constants have type int */
|
||||||
nxttype = type_int;
|
NextTok.Type = type_int;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -340,8 +367,8 @@ static void CharConst (void)
|
|||||||
static void StringConst (void)
|
static void StringConst (void)
|
||||||
/* Parse a quoted string */
|
/* Parse a quoted string */
|
||||||
{
|
{
|
||||||
nxtval = GetLiteralPoolOffs ();
|
NextTok.IVal = GetLiteralPoolOffs ();
|
||||||
nxttok = TOK_SCONST;
|
NextTok.Tok = TOK_SCONST;
|
||||||
|
|
||||||
/* Be sure to concatenate strings */
|
/* Be sure to concatenate strings */
|
||||||
while (CurC == '\"') {
|
while (CurC == '\"') {
|
||||||
@@ -376,16 +403,26 @@ void NextToken (void)
|
|||||||
{
|
{
|
||||||
ident token;
|
ident token;
|
||||||
|
|
||||||
|
/* We have to skip white space here before shifting tokens, since the
|
||||||
|
* tokens and the current line info is invalid at startup and will get
|
||||||
|
* initialized by reading the first time from the file. Remember if
|
||||||
|
* we were at end of input and handle that later.
|
||||||
|
*/
|
||||||
|
int GotEOF = (SkipWhite() == 0);
|
||||||
|
|
||||||
/* Current token is the lookahead token */
|
/* Current token is the lookahead token */
|
||||||
|
if (CurTok.LI) {
|
||||||
|
ReleaseLineInfo (CurTok.LI);
|
||||||
|
}
|
||||||
CurTok = NextTok;
|
CurTok = NextTok;
|
||||||
|
|
||||||
/* Remember the starting position of the next token */
|
/* Remember the starting position of the next token */
|
||||||
NextTok.Pos = GetCurrentLine();
|
NextTok.LI = UseLineInfo (GetCurLineInfo ());
|
||||||
|
|
||||||
/* Skip spaces and read the next line if needed */
|
/* Now handle end of input. */
|
||||||
if (SkipWhite () == 0) {
|
if (GotEOF) {
|
||||||
/* End of file reached */
|
/* End of file reached */
|
||||||
nxttok = TOK_CEOF;
|
NextTok.Tok = TOK_CEOF;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,7 +446,7 @@ void NextToken (void)
|
|||||||
NextChar ();
|
NextChar ();
|
||||||
if (toupper (CurC) == 'X') {
|
if (toupper (CurC) == 'X') {
|
||||||
base = 16;
|
base = 16;
|
||||||
nxttype = type_uint;
|
NextTok.Type = type_uint;
|
||||||
NextChar (); /* gobble "x" */
|
NextChar (); /* gobble "x" */
|
||||||
} else {
|
} else {
|
||||||
base = 8;
|
base = 8;
|
||||||
@@ -473,25 +510,25 @@ void NextToken (void)
|
|||||||
|
|
||||||
/* Now set the type string to the smallest type in types */
|
/* Now set the type string to the smallest type in types */
|
||||||
if (types & IT_INT) {
|
if (types & IT_INT) {
|
||||||
nxttype = type_int;
|
NextTok.Type = type_int;
|
||||||
} else if (types & IT_UINT) {
|
} else if (types & IT_UINT) {
|
||||||
nxttype = type_uint;
|
NextTok.Type = type_uint;
|
||||||
} else if (types & IT_LONG) {
|
} else if (types & IT_LONG) {
|
||||||
nxttype = type_long;
|
NextTok.Type = type_long;
|
||||||
} else {
|
} else {
|
||||||
nxttype = type_ulong;
|
NextTok.Type = type_ulong;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the value and the token */
|
/* Set the value and the token */
|
||||||
nxtval = k;
|
NextTok.IVal = k;
|
||||||
nxttok = TOK_ICONST;
|
NextTok.Tok = TOK_ICONST;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsSym (token)) {
|
if (IsSym (token)) {
|
||||||
|
|
||||||
/* Check for a keyword */
|
/* Check for a keyword */
|
||||||
if ((nxttok = FindKey (token)) != TOK_IDENT) {
|
if ((NextTok.Tok = FindKey (token)) != TOK_IDENT) {
|
||||||
/* Reserved word found */
|
/* Reserved word found */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -499,19 +536,19 @@ void NextToken (void)
|
|||||||
if (token [0] == '_') {
|
if (token [0] == '_') {
|
||||||
/* Special symbols */
|
/* Special symbols */
|
||||||
if (strcmp (token, "__FILE__") == 0) {
|
if (strcmp (token, "__FILE__") == 0) {
|
||||||
nxtval = AddLiteral (GetCurrentFile());
|
NextTok.IVal = AddLiteral (GetCurrentFile());
|
||||||
nxttok = TOK_SCONST;
|
NextTok.Tok = TOK_SCONST;
|
||||||
return;
|
return;
|
||||||
} else if (strcmp (token, "__LINE__") == 0) {
|
} else if (strcmp (token, "__LINE__") == 0) {
|
||||||
nxttok = TOK_ICONST;
|
NextTok.Tok = TOK_ICONST;
|
||||||
nxtval = GetCurrentLine();
|
NextTok.IVal = GetCurrentLine();
|
||||||
nxttype = type_int;
|
NextTok.Type = type_int;
|
||||||
return;
|
return;
|
||||||
} else if (strcmp (token, "__func__") == 0) {
|
} else if (strcmp (token, "__func__") == 0) {
|
||||||
/* __func__ is only defined in functions */
|
/* __func__ is only defined in functions */
|
||||||
if (CurrentFunc) {
|
if (CurrentFunc) {
|
||||||
nxtval = AddLiteral (GetFuncName (CurrentFunc));
|
NextTok.IVal = AddLiteral (GetFuncName (CurrentFunc));
|
||||||
nxttok = TOK_SCONST;
|
NextTok.Tok = TOK_SCONST;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -531,7 +568,7 @@ void NextToken (void)
|
|||||||
if (CurC == '=') {
|
if (CurC == '=') {
|
||||||
SetTok (TOK_NE);
|
SetTok (TOK_NE);
|
||||||
} else {
|
} else {
|
||||||
nxttok = TOK_BOOL_NOT;
|
NextTok.Tok = TOK_BOOL_NOT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -544,7 +581,7 @@ void NextToken (void)
|
|||||||
if (CurC == '=') {
|
if (CurC == '=') {
|
||||||
SetTok (TOK_MOD_ASSIGN);
|
SetTok (TOK_MOD_ASSIGN);
|
||||||
} else {
|
} else {
|
||||||
nxttok = TOK_MOD;
|
NextTok.Tok = TOK_MOD;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -558,7 +595,7 @@ void NextToken (void)
|
|||||||
SetTok (TOK_AND_ASSIGN);
|
SetTok (TOK_AND_ASSIGN);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
nxttok = TOK_AND;
|
NextTok.Tok = TOK_AND;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -579,7 +616,7 @@ void NextToken (void)
|
|||||||
if (CurC == '=') {
|
if (CurC == '=') {
|
||||||
SetTok (TOK_MUL_ASSIGN);
|
SetTok (TOK_MUL_ASSIGN);
|
||||||
} else {
|
} else {
|
||||||
nxttok = TOK_STAR;
|
NextTok.Tok = TOK_STAR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -593,7 +630,7 @@ void NextToken (void)
|
|||||||
SetTok (TOK_PLUS_ASSIGN);
|
SetTok (TOK_PLUS_ASSIGN);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
nxttok = TOK_PLUS;
|
NextTok.Tok = TOK_PLUS;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -614,7 +651,7 @@ void NextToken (void)
|
|||||||
SetTok (TOK_PTR_REF);
|
SetTok (TOK_PTR_REF);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
nxttok = TOK_MINUS;
|
NextTok.Tok = TOK_MINUS;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -625,10 +662,10 @@ void NextToken (void)
|
|||||||
if (CurC == '.') {
|
if (CurC == '.') {
|
||||||
SetTok (TOK_ELLIPSIS);
|
SetTok (TOK_ELLIPSIS);
|
||||||
} else {
|
} else {
|
||||||
unknown (CurC);
|
UnknownChar (CurC);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nxttok = TOK_DOT;
|
NextTok.Tok = TOK_DOT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -637,7 +674,7 @@ void NextToken (void)
|
|||||||
if (CurC == '=') {
|
if (CurC == '=') {
|
||||||
SetTok (TOK_DIV_ASSIGN);
|
SetTok (TOK_DIV_ASSIGN);
|
||||||
} else {
|
} else {
|
||||||
nxttok = TOK_DIV;
|
NextTok.Tok = TOK_DIV;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -660,11 +697,11 @@ void NextToken (void)
|
|||||||
if (CurC == '=') {
|
if (CurC == '=') {
|
||||||
SetTok (TOK_SHL_ASSIGN);
|
SetTok (TOK_SHL_ASSIGN);
|
||||||
} else {
|
} else {
|
||||||
nxttok = TOK_SHL;
|
NextTok.Tok = TOK_SHL;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
nxttok = TOK_LT;
|
NextTok.Tok = TOK_LT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -673,7 +710,7 @@ void NextToken (void)
|
|||||||
if (CurC == '=') {
|
if (CurC == '=') {
|
||||||
SetTok (TOK_EQ);
|
SetTok (TOK_EQ);
|
||||||
} else {
|
} else {
|
||||||
nxttok = TOK_ASSIGN;
|
NextTok.Tok = TOK_ASSIGN;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -688,11 +725,11 @@ void NextToken (void)
|
|||||||
if (CurC == '=') {
|
if (CurC == '=') {
|
||||||
SetTok (TOK_SHR_ASSIGN);
|
SetTok (TOK_SHR_ASSIGN);
|
||||||
} else {
|
} else {
|
||||||
nxttok = TOK_SHR;
|
NextTok.Tok = TOK_SHR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
nxttok = TOK_GT;
|
NextTok.Tok = TOK_GT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -713,7 +750,7 @@ void NextToken (void)
|
|||||||
if (CurC == '=') {
|
if (CurC == '=') {
|
||||||
SetTok (TOK_XOR_ASSIGN);
|
SetTok (TOK_XOR_ASSIGN);
|
||||||
} else {
|
} else {
|
||||||
nxttok = TOK_XOR;
|
NextTok.Tok = TOK_XOR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -731,7 +768,7 @@ void NextToken (void)
|
|||||||
SetTok (TOK_OR_ASSIGN);
|
SetTok (TOK_OR_ASSIGN);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
nxttok = TOK_OR;
|
NextTok.Tok = TOK_OR;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -752,11 +789,11 @@ void NextToken (void)
|
|||||||
/* OOPS - should not happen */
|
/* OOPS - should not happen */
|
||||||
Error ("Preprocessor directive expected");
|
Error ("Preprocessor directive expected");
|
||||||
}
|
}
|
||||||
nxttok = TOK_PRAGMA;
|
NextTok.Tok = TOK_PRAGMA;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
unknown (CurC);
|
UnknownChar (CurC);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -769,7 +806,7 @@ void Consume (token_t Token, const char* ErrorMsg)
|
|||||||
* message.
|
* message.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
if (curtok == Token) {
|
if (CurTok.Tok == Token) {
|
||||||
NextToken ();
|
NextToken ();
|
||||||
} else {
|
} else {
|
||||||
Error (ErrorMsg);
|
Error (ErrorMsg);
|
||||||
@@ -790,11 +827,11 @@ void ConsumeSemi (void)
|
|||||||
/* Check for a semicolon and skip it. */
|
/* Check for a semicolon and skip it. */
|
||||||
{
|
{
|
||||||
/* Try do be smart about typos... */
|
/* Try do be smart about typos... */
|
||||||
if (curtok == TOK_SEMI) {
|
if (CurTok.Tok == TOK_SEMI) {
|
||||||
NextToken ();
|
NextToken ();
|
||||||
} else {
|
} else {
|
||||||
Error ("`;' expected");
|
Error ("`;' expected");
|
||||||
if (curtok == TOK_COLON || curtok == TOK_COMMA) {
|
if (CurTok.Tok == TOK_COLON || CurTok.Tok == TOK_COMMA) {
|
||||||
NextToken ();
|
NextToken ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,35 @@
|
|||||||
/*
|
/*****************************************************************************/
|
||||||
* scanner.h
|
/* */
|
||||||
*
|
/* scanner.h */
|
||||||
* Ullrich von Bassewitz, 07.06.1998
|
/* */
|
||||||
*/
|
/* Source file line info structure */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* (C) 1998-2001 Ullrich von Bassewitz */
|
||||||
|
/* Wacholderweg 14 */
|
||||||
|
/* D-70597 Stuttgart */
|
||||||
|
/* EMail: uz@musoftware.de */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
|
/* warranty. In no event will the authors be held liable for any damages */
|
||||||
|
/* arising from the use of this software. */
|
||||||
|
/* */
|
||||||
|
/* Permission is granted to anyone to use this software for any purpose, */
|
||||||
|
/* including commercial applications, and to alter it and redistribute it */
|
||||||
|
/* freely, subject to the following restrictions: */
|
||||||
|
/* */
|
||||||
|
/* 1. The origin of this software must not be misrepresented; you must not */
|
||||||
|
/* claim that you wrote the original software. If you use this software */
|
||||||
|
/* in a product, an acknowledgment in the product documentation would be */
|
||||||
|
/* appreciated but is not required. */
|
||||||
|
/* 2. Altered source versions must be plainly marked as such, and must not */
|
||||||
|
/* be misrepresented as being the original software. */
|
||||||
|
/* 3. This notice may not be removed or altered from any source */
|
||||||
|
/* distribution. */
|
||||||
|
/* */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -11,8 +38,10 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* cc65 */
|
||||||
#include "datatype.h"
|
#include "datatype.h"
|
||||||
#include "ident.h"
|
#include "ident.h"
|
||||||
|
#include "lineinfo.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -146,30 +175,19 @@ typedef enum token_t {
|
|||||||
|
|
||||||
|
|
||||||
/* Token stuff */
|
/* Token stuff */
|
||||||
typedef struct Token_ Token;
|
typedef struct Token Token;
|
||||||
struct Token_ {
|
struct Token {
|
||||||
token_t Tok; /* The token itself */
|
token_t Tok; /* The token itself */
|
||||||
long IVal; /* The integer attribute */
|
long IVal; /* The integer attribute */
|
||||||
double FVal; /* The float attribute */
|
double FVal; /* The float attribute */
|
||||||
ident Ident; /* Identifier if IDENT */
|
ident Ident; /* Identifier if IDENT */
|
||||||
unsigned Pos; /* Source line where the token comes from */
|
LineInfo* LI; /* Source line where the token comes from */
|
||||||
type* Type; /* Type if integer or float constant */
|
type* Type; /* Type if integer or float constant */
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Token CurTok; /* The current token */
|
extern Token CurTok; /* The current token */
|
||||||
extern Token NextTok; /* The next token */
|
extern Token NextTok; /* The next token */
|
||||||
|
|
||||||
/* Defines to make the old code work */
|
|
||||||
#define curtok CurTok.Tok
|
|
||||||
#define curval CurTok.IVal
|
|
||||||
#define curpos CurTok.Pos
|
|
||||||
#define curtype CurTok.Type
|
|
||||||
|
|
||||||
#define nxttok NextTok.Tok
|
|
||||||
#define nxtval NextTok.IVal
|
|
||||||
#define nxtpos NextTok.Pos
|
|
||||||
#define nxttype NextTok.Type
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
#include "chartype.h"
|
#include "chartype.h"
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
#include "coll.h"
|
#include "coll.h"
|
||||||
|
#include "scanner.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
|
||||||
/* cc65 */
|
/* cc65 */
|
||||||
@@ -210,7 +211,7 @@ void AddCodeLine (const char* Format, ...)
|
|||||||
va_list ap;
|
va_list ap;
|
||||||
va_start (ap, Format);
|
va_start (ap, Format);
|
||||||
CHECK (CS != 0);
|
CHECK (CS != 0);
|
||||||
AddCodeEntry (CS->Code, Format, ap);
|
AddCodeEntry (CS->Code, CurTok.LI, Format, ap);
|
||||||
va_end (ap);
|
va_end (ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ static int doif (void)
|
|||||||
gotbreak = Statement ();
|
gotbreak = Statement ();
|
||||||
|
|
||||||
/* Else clause present? */
|
/* Else clause present? */
|
||||||
if (curtok != TOK_ELSE) {
|
if (CurTok.Tok != TOK_ELSE) {
|
||||||
|
|
||||||
g_defcodelabel (flab1);
|
g_defcodelabel (flab1);
|
||||||
/* Since there's no else clause, we're not sure, if the a break
|
/* Since there's no else clause, we're not sure, if the a break
|
||||||
@@ -130,7 +130,7 @@ static void dowhile (char wtype)
|
|||||||
* do another small optimization here, and use a conditional jump
|
* do another small optimization here, and use a conditional jump
|
||||||
* instead an absolute one.
|
* instead an absolute one.
|
||||||
*/
|
*/
|
||||||
if (curtok == TOK_SEMI) {
|
if (CurTok.Tok == TOK_SEMI) {
|
||||||
/* Shortcut */
|
/* Shortcut */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
/* Use a conditional jump */
|
/* Use a conditional jump */
|
||||||
@@ -163,7 +163,7 @@ static void DoReturn (void)
|
|||||||
struct expent lval;
|
struct expent lval;
|
||||||
|
|
||||||
NextToken ();
|
NextToken ();
|
||||||
if (curtok != TOK_SEMI) {
|
if (CurTok.Tok != TOK_SEMI) {
|
||||||
if (HasVoidReturn (CurrentFunc)) {
|
if (HasVoidReturn (CurrentFunc)) {
|
||||||
Error ("Returning a value in function with return type void");
|
Error ("Returning a value in function with return type void");
|
||||||
}
|
}
|
||||||
@@ -280,9 +280,9 @@ static void cascadeswitch (struct expent* eval)
|
|||||||
|
|
||||||
/* Parse the labels */
|
/* Parse the labels */
|
||||||
lcount = 0;
|
lcount = 0;
|
||||||
while (curtok != TOK_RCURLY) {
|
while (CurTok.Tok != TOK_RCURLY) {
|
||||||
|
|
||||||
if (curtok == TOK_CASE || curtok == TOK_DEFAULT) {
|
if (CurTok.Tok == TOK_CASE || CurTok.Tok == TOK_DEFAULT) {
|
||||||
|
|
||||||
/* If the code for the previous selector did not end with a
|
/* If the code for the previous selector did not end with a
|
||||||
* break statement, we must jump over the next selector test.
|
* break statement, we must jump over the next selector test.
|
||||||
@@ -301,10 +301,10 @@ static void cascadeswitch (struct expent* eval)
|
|||||||
NextLab = 0;
|
NextLab = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (curtok == TOK_CASE || curtok == TOK_DEFAULT) {
|
while (CurTok.Tok == TOK_CASE || CurTok.Tok == TOK_DEFAULT) {
|
||||||
|
|
||||||
/* Parse the selector */
|
/* Parse the selector */
|
||||||
if (curtok == TOK_CASE) {
|
if (CurTok.Tok == TOK_CASE) {
|
||||||
|
|
||||||
/* Count labels */
|
/* Count labels */
|
||||||
++lcount;
|
++lcount;
|
||||||
@@ -325,25 +325,25 @@ static void cascadeswitch (struct expent* eval)
|
|||||||
case T_SCHAR:
|
case T_SCHAR:
|
||||||
/* Signed char */
|
/* Signed char */
|
||||||
if (Val < -128 || Val > 127) {
|
if (Val < -128 || Val > 127) {
|
||||||
Error ("Range error");
|
Error ("Range error");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_UCHAR:
|
case T_UCHAR:
|
||||||
if (Val < 0 || Val > 255) {
|
if (Val < 0 || Val > 255) {
|
||||||
Error ("Range error");
|
Error ("Range error");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_INT:
|
case T_INT:
|
||||||
if (Val < -32768 || Val > 32767) {
|
if (Val < -32768 || Val > 32767) {
|
||||||
Error ("Range error");
|
Error ("Range error");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_UINT:
|
case T_UINT:
|
||||||
if (Val < 0 || Val > 65535) {
|
if (Val < 0 || Val > 65535) {
|
||||||
Error ("Range error");
|
Error ("Range error");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -351,22 +351,19 @@ static void cascadeswitch (struct expent* eval)
|
|||||||
Internal ("Invalid type: %02X", *eval->e_tptr & 0xFF);
|
Internal ("Invalid type: %02X", *eval->e_tptr & 0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Skip the colon */
|
|
||||||
ConsumeColon ();
|
|
||||||
|
|
||||||
/* Emit a compare */
|
/* Emit a compare */
|
||||||
g_cmp (Flags, Val);
|
g_cmp (Flags, Val);
|
||||||
|
|
||||||
/* If another case follows, we will jump to the code if
|
/* If another case follows, we will jump to the code if
|
||||||
* the condition is true.
|
* the condition is true.
|
||||||
*/
|
*/
|
||||||
if (curtok == TOK_CASE) {
|
if (CurTok.Tok == TOK_CASE) {
|
||||||
/* Create a code label if needed */
|
/* Create a code label if needed */
|
||||||
if (CodeLab == 0) {
|
if (CodeLab == 0) {
|
||||||
CodeLab = GetLocalLabel ();
|
CodeLab = GetLocalLabel ();
|
||||||
}
|
}
|
||||||
g_falsejump (CF_NONE, CodeLab);
|
g_falsejump (CF_NONE, CodeLab);
|
||||||
} else if (curtok != TOK_DEFAULT) {
|
} else if (CurTok.Tok != TOK_DEFAULT) {
|
||||||
/* No case follows, jump to next selector */
|
/* No case follows, jump to next selector */
|
||||||
if (NextLab == 0) {
|
if (NextLab == 0) {
|
||||||
NextLab = GetLocalLabel ();
|
NextLab = GetLocalLabel ();
|
||||||
@@ -374,22 +371,25 @@ static void cascadeswitch (struct expent* eval)
|
|||||||
g_truejump (CF_NONE, NextLab);
|
g_truejump (CF_NONE, NextLab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Skip the colon */
|
||||||
|
ConsumeColon ();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* Default case */
|
/* Default case */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
|
|
||||||
/* Skip the colon */
|
|
||||||
ConsumeColon ();
|
|
||||||
|
|
||||||
/* Handle the pathologic case: DEFAULT followed by CASE */
|
/* Handle the pathologic case: DEFAULT followed by CASE */
|
||||||
if (curtok == TOK_CASE) {
|
if (CurTok.Tok == TOK_CASE) {
|
||||||
if (CodeLab == 0) {
|
if (CodeLab == 0) {
|
||||||
CodeLab = GetLocalLabel ();
|
CodeLab = GetLocalLabel ();
|
||||||
}
|
}
|
||||||
g_jump (CodeLab);
|
g_jump (CodeLab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Skip the colon */
|
||||||
|
ConsumeColon ();
|
||||||
|
|
||||||
/* Remember that we had a default label */
|
/* Remember that we had a default label */
|
||||||
HaveDefault = 1;
|
HaveDefault = 1;
|
||||||
}
|
}
|
||||||
@@ -405,7 +405,7 @@ static void cascadeswitch (struct expent* eval)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Parse statements */
|
/* Parse statements */
|
||||||
if (curtok != TOK_RCURLY) {
|
if (CurTok.Tok != TOK_RCURLY) {
|
||||||
HaveBreak = Statement ();
|
HaveBreak = Statement ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -415,9 +415,6 @@ static void cascadeswitch (struct expent* eval)
|
|||||||
Warning ("No case labels");
|
Warning ("No case labels");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Eat the closing curly brace */
|
|
||||||
NextToken ();
|
|
||||||
|
|
||||||
/* Define the exit label and, if there's a next label left, create this
|
/* Define the exit label and, if there's a next label left, create this
|
||||||
* one, too.
|
* one, too.
|
||||||
*/
|
*/
|
||||||
@@ -426,6 +423,9 @@ static void cascadeswitch (struct expent* eval)
|
|||||||
}
|
}
|
||||||
g_defcodelabel (ExitLab);
|
g_defcodelabel (ExitLab);
|
||||||
|
|
||||||
|
/* Eat the closing curly brace */
|
||||||
|
NextToken ();
|
||||||
|
|
||||||
/* End the loop */
|
/* End the loop */
|
||||||
DelLoop ();
|
DelLoop ();
|
||||||
}
|
}
|
||||||
@@ -467,14 +467,14 @@ static void tableswitch (struct expent* eval)
|
|||||||
/* Jump behind the code for the CASE labels */
|
/* Jump behind the code for the CASE labels */
|
||||||
g_jump (lcase = GetLocalLabel ());
|
g_jump (lcase = GetLocalLabel ());
|
||||||
lcount = 0;
|
lcount = 0;
|
||||||
while (curtok != TOK_RCURLY) {
|
while (CurTok.Tok != TOK_RCURLY) {
|
||||||
if (curtok == TOK_CASE || curtok == TOK_DEFAULT) {
|
if (CurTok.Tok == TOK_CASE || CurTok.Tok == TOK_DEFAULT) {
|
||||||
if (lcount >= CASE_MAX) {
|
if (lcount >= CASE_MAX) {
|
||||||
Fatal ("Too many case labels");
|
Fatal ("Too many case labels");
|
||||||
}
|
}
|
||||||
label = GetLocalLabel ();
|
label = GetLocalLabel ();
|
||||||
do {
|
do {
|
||||||
if (curtok == TOK_CASE) {
|
if (CurTok.Tok == TOK_CASE) {
|
||||||
NextToken ();
|
NextToken ();
|
||||||
constexpr (&lval);
|
constexpr (&lval);
|
||||||
if (!IsClassInt (lval.e_tptr)) {
|
if (!IsClassInt (lval.e_tptr)) {
|
||||||
@@ -490,11 +490,11 @@ static void tableswitch (struct expent* eval)
|
|||||||
HaveDefault = 1;
|
HaveDefault = 1;
|
||||||
}
|
}
|
||||||
ConsumeColon ();
|
ConsumeColon ();
|
||||||
} while (curtok == TOK_CASE || curtok == TOK_DEFAULT);
|
} while (CurTok.Tok == TOK_CASE || CurTok.Tok == TOK_DEFAULT);
|
||||||
g_defcodelabel (label);
|
g_defcodelabel (label);
|
||||||
HaveBreak = 0;
|
HaveBreak = 0;
|
||||||
}
|
}
|
||||||
if (curtok != TOK_RCURLY) {
|
if (CurTok.Tok != TOK_RCURLY) {
|
||||||
HaveBreak = Statement ();
|
HaveBreak = Statement ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -586,12 +586,12 @@ static void dofor (void)
|
|||||||
lstat = GetLocalLabel ();
|
lstat = GetLocalLabel ();
|
||||||
AddLoop (oursp, loop, lab, linc, lstat);
|
AddLoop (oursp, loop, lab, linc, lstat);
|
||||||
ConsumeLParen ();
|
ConsumeLParen ();
|
||||||
if (curtok != TOK_SEMI) { /* exp1 */
|
if (CurTok.Tok != TOK_SEMI) { /* exp1 */
|
||||||
expression (&lval1);
|
expression (&lval1);
|
||||||
}
|
}
|
||||||
ConsumeSemi ();
|
ConsumeSemi ();
|
||||||
g_defcodelabel (loop);
|
g_defcodelabel (loop);
|
||||||
if (curtok != TOK_SEMI) { /* exp2 */
|
if (CurTok.Tok != TOK_SEMI) { /* exp2 */
|
||||||
boolexpr (&lval2);
|
boolexpr (&lval2);
|
||||||
g_truejump (CF_NONE, lstat);
|
g_truejump (CF_NONE, lstat);
|
||||||
g_jump (lab);
|
g_jump (lab);
|
||||||
@@ -600,7 +600,7 @@ static void dofor (void)
|
|||||||
}
|
}
|
||||||
ConsumeSemi ();
|
ConsumeSemi ();
|
||||||
g_defcodelabel (linc);
|
g_defcodelabel (linc);
|
||||||
if (curtok != TOK_RPAREN) { /* exp3 */
|
if (CurTok.Tok != TOK_RPAREN) { /* exp3 */
|
||||||
expression (&lval3);
|
expression (&lval3);
|
||||||
}
|
}
|
||||||
ConsumeRParen ();
|
ConsumeRParen ();
|
||||||
@@ -634,8 +634,8 @@ static int CompoundStatement (void)
|
|||||||
|
|
||||||
/* Now process statements in this block */
|
/* Now process statements in this block */
|
||||||
isbrk = 0;
|
isbrk = 0;
|
||||||
while (curtok != TOK_RCURLY) {
|
while (CurTok.Tok != TOK_RCURLY) {
|
||||||
if (curtok != TOK_CEOF) {
|
if (CurTok.Tok != TOK_CEOF) {
|
||||||
isbrk = Statement ();
|
isbrk = Statement ();
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
@@ -672,14 +672,14 @@ int Statement (void)
|
|||||||
struct expent lval;
|
struct expent lval;
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
if (curtok == TOK_IDENT && nxttok == TOK_COLON) {
|
if (CurTok.Tok == TOK_IDENT && NextTok.Tok == TOK_COLON) {
|
||||||
|
|
||||||
/* Special handling for a label */
|
/* Special handling for a label */
|
||||||
DoLabel ();
|
DoLabel ();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
switch (curtok) {
|
switch (CurTok.Tok) {
|
||||||
|
|
||||||
case TOK_LCURLY:
|
case TOK_LCURLY:
|
||||||
return CompoundStatement ();
|
return CompoundStatement ();
|
||||||
|
|||||||
Reference in New Issue
Block a user