-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 */
{
/* Get the opcode description */
CodeEntry* E = xmalloc (sizeof (CodeEntry));
/* Initialize the fields */
- E->OPC = D->OPC;
- E->AM = AM;
- E->Size = GetInsnSize (E->OPC, E->AM);
- E->Hints = 0;
- E->Arg = GetArgCopy (Arg);
- if (NumArg (E->Arg, &E->Num)) {
- E-> Flags = CEF_NUMARG;
- } else {
- E->Flags = 0;
- }
+ E->OPC = D->OPC;
+ E->AM = AM;
+ E->Arg = GetArgCopy (Arg);
+ E->Flags = NumArg (E->Arg, &E->Num)? CEF_NUMARG : 0;
+ E->Size = GetInsnSize (E->OPC, E->AM);
E->Info = D->Info;
E->JumpTo = JumpTo;
+ E->LI = UseLineInfo (LI);
SetUseChgInfo (E, D);
InitCollection (&E->Labels);
/* Cleanup the collection */
DoneCollection (&E->Labels);
+ /* Release the line info */
+ ReleaseLineInfo (E->LI);
+
/* Free the entry */
xfree (E);
}
/* Print usage info if requested by the debugging flag */
// if (Debug) {
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, "",
(E->Use & REG_A)? 'A' : '_',
(E->Use & REG_X)? 'X' : '_',
+
/* cc65 */
#include "codelab.h"
+#include "lineinfo.h"
#include "opcodes.h"
/*****************************************************************************/
-/* Data */
+/* Data */
/*****************************************************************************/
/* Flags used */
-#define CEF_USERMARK 0x0001U /* Generic mark by user functions */
-#define CEF_NUMARG 0x0002U /* Insn has numerical argument */
+#define CEF_USERMARK 0x0001U /* Generic mark by user functions */
+#define CEF_NUMARG 0x0002U /* Insn has numerical argument */
/* Code entry structure */
typedef struct CodeEntry CodeEntry;
struct CodeEntry {
- opc_t OPC; /* Opcode */
- am_t AM; /* Adressing mode */
- unsigned char Size; /* Estimated size */
- unsigned char Hints; /* Hints for this entry */
+ opc_t OPC; /* Opcode */
+ am_t AM; /* Adressing mode */
char* Arg; /* Argument as string */
- unsigned long Num; /* Numeric argument */
- unsigned short Flags; /* Flags */
- unsigned char Info; /* Additional code info */
- unsigned char Use; /* Registers used */
- unsigned char Chg; /* Registers changed/destroyed */
- CodeLabel* JumpTo; /* Jump label */
- Collection Labels; /* Labels for this instruction */
+ unsigned long Num; /* Numeric argument */
+ unsigned short Flags; /* Flags */
+ unsigned char Size; /* Estimated size */
+ unsigned char Info; /* Additional code info */
+ unsigned char Use; /* Registers used */
+ unsigned char Chg; /* Registers changed/destroyed */
+ CodeLabel* JumpTo; /* Jump label */
+ Collection Labels; /* Labels for this instruction */
+ LineInfo* LI; /* Source line info for this insn */
};
-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 */
void FreeCodeEntry (CodeEntry* E);
Internal ("Invalid program flow");
}
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);
ReplaceOPC (E, OPC_JPL);
break;
*/
ReplaceOPC (E, OPC_JMI);
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);
break;
Internal ("Invalid program flow");
}
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);
ReplaceOPC (E, OPC_JCS);
break;
*/
ReplaceOPC (E, OPC_JCC);
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);
break;
DelCodeEntries (S, I+1, 2);
/* 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 */
++Changes;
}
/* Replace the subroutine call. */
+ E = NewCodeEntry (OPC_JSR, AM_ABS, "tosicmp", 0, E->LI);
+ InsertCodeEntry (S, E, I+1);
DelCodeEntry (S, I);
- E = NewCodeEntry (OPC_JSR, AM_ABS, "tosicmp", 0);
- InsertCodeEntry (S, E, I);
/* Replace the conditional branch */
ReplaceCmp (S, I+1, Cond);
!CodeEntryHasLabel (L[0]) &&
(L[1]->Info & OF_ZBRA) != 0) {
+ CodeEntry* X;
+
/* Check if we're calling bnega or bnegax */
int ByteSized = (strcmp (L[0]->Arg, "bnega") == 0);
- /* Delete the subroutine call */
- DelCodeEntry (S, I+1);
-
/* Insert apropriate test code */
if (ByteSized) {
/* 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 {
/* Test words */
- InsertCodeEntry (S, NewCodeEntry (OPC_STX, AM_ZP, "tmp1", 0), I+1);
- InsertCodeEntry (S, NewCodeEntry (OPC_ORA, AM_ZP, "tmp1", 0), I+2);
+ X = NewCodeEntry (OPC_STX, AM_ZP, "tmp1", 0, L[0]->LI);
+ 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 */
ReplaceOPC (L[1], GetInverseBranch (L[1]->OPC));
/* common */
#include "chartype.h"
#include "check.h"
+#include "global.h"
#include "hashstr.h"
#include "strutil.h"
#include "xmalloc.h"
-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
* errors, output an error message and return NULL.
* For simplicity, we don't accept the broad range of input a "real" assembler
/* We do now have the addressing mode in AM. Allocate a new CodeEntry
* 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 E;
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
-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 */
{
const char* L;
break;
default:
- E = ParseInsn (S, L);
+ E = ParseInsn (S, LI, L);
break;
}
-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)
/* Delete all entries including the given one */
{
/* Output the code segment data to a file */
{
unsigned I;
+ const LineInfo* LI;
/* Get the number of entries in this segment */
unsigned Count = GetCodeEntryCount (S);
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) {
-
- unsigned char Use;
-
- OutputCodeEntry (CollConstAt (&S->Entries, I), F);
-
-#if 0
- /* Print usage info */
- Use = GetRegInfo ((CodeSeg*) S, I+1);
- fprintf (F,
- " Use: %c%c%c\n",
- (Use & REG_A)? 'A' : '_',
- (Use & REG_X)? 'X' : '_',
- (Use & REG_Y)? 'Y' : '_');
-#else
- fprintf (F, "\n");
-#endif
+ /* Get the next entry */
+ const CodeEntry* E = CollConstAt (&S->Entries, I);
+ /* Check if the line info has changed. If so, output the source line
+ * if the option is enabled.
+ */
+ if (E->LI != LI) {
+ LI = E->LI;
+ if (AddSource) {
+ /* Skip spaces to make the output somewhat more readable */
+ const char* Line = LI->Line;
+ while (IsBlank (*Line)) {
+ ++Line;
+ }
+ fprintf (F, ";\n; %s\n;\n", Line);
+ }
+ }
+ /* Output the code */
+ OutputCodeEntry (E, F);
}
/* If this is a segment for a function, leave the function */
/* cc65 */
#include "codelab.h"
+#include "lineinfo.h"
#include "symentry.h"
CodeSeg* NewCodeSeg (const char* SegName, SymEntry* Func);
/* 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 */
void InsertCodeEntry (CodeSeg* S, struct CodeEntry* E, unsigned Index);
* deleted.
*/
-void AddCodeSegHint (CodeSeg* S, unsigned Hint);
-/* Add a hint for the preceeding instruction */
-
void DelCodeSegAfter (CodeSeg* S, unsigned Last);
/* Delete all entries including the given one */
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
int comma;
SymEntry* Entry;
- NextToken (); /* "prime" the pump */
+ /* Go... */
NextToken ();
- while (curtok != TOK_CEOF) {
+ NextToken ();
+
+ /* Parse until end of input */
+ while (CurTok.Tok != TOK_CEOF) {
DeclSpec Spec;
Declaration Decl;
int NeedStorage;
/* Check for empty statements */
- if (curtok == TOK_SEMI) {
+ if (CurTok.Tok == TOK_SEMI) {
NextToken ();
continue;
}
/* Check for an ASM statement (which is allowed also on global level) */
- if (curtok == TOK_ASM) {
+ if (CurTok.Tok == TOK_ASM) {
doasm ();
ConsumeSemi ();
continue;
}
/* Check for a #pragma */
- if (curtok == TOK_PRAGMA) {
+ if (CurTok.Tok == TOK_PRAGMA) {
DoPragma ();
continue;
}
}
/* Check if this is only a type declaration */
- if (curtok == TOK_SEMI) {
+ if (CurTok.Tok == TOK_SEMI) {
CheckEmptyDecl (&Spec);
NextToken ();
continue;
unsigned Size = SizeOf (Decl.Type);
/* Allow initialization */
- if (curtok == TOK_ASSIGN) {
+ if (CurTok.Tok == TOK_ASSIGN) {
/* We cannot initialize types of unknown size, or
* void types in non ANSI mode.
}
/* Check for end of declaration list */
- if (curtok == TOK_COMMA) {
+ if (CurTok.Tok == TOK_COMMA) {
NextToken ();
comma = 1;
} else {
/* Function */
if (!comma) {
- if (curtok == TOK_SEMI) {
+ if (CurTok.Tok == TOK_SEMI) {
/* Prototype only */
NextToken ();
E->JumpTo != 0 &&
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 */
DelCodeEntry (S, I);
- /* Insert an RTS instruction instead */
- InsertCodeEntry (S, NewCodeEntry (OPC_RTS, AM_IMP, 0, 0), I);
-
/* Remember, we had changes */
++Changes;
/* This is a jump cascade and we may jump to the final target.
* 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 */
InsertCodeEntry (S, X, I+1);
goto NextEntry;
}
- /* We may jump behind this conditional branch. Get the
- * pointer to the next instruction
+ /* We may jump behind this conditional branch. Get the
+ * pointer to the next instruction
*/
if ((X = GetNextCodeEntry (S, GetCodeEntryIndex (S, N))) == 0) {
/* N is the last entry, bail out */
static type OptionalQualifiers (type Q)
/* 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:
if (Q & T_QUAL_CONST) {
static void optionalint (void)
/* Eat an optional "int" token */
{
- if (curtok == TOK_INT) {
+ if (CurTok.Tok == TOK_INT) {
/* Skip it */
NextToken ();
}
static void optionalsigned (void)
/* Eat an optional "signed" token */
{
- if (curtok == TOK_SIGNED) {
+ if (CurTok.Tok == TOK_SIGNED) {
/* Skip it */
NextToken ();
}
D->Flags &= ~DS_DEF_STORAGE;
/* Check the storage class given */
- switch (curtok) {
+ switch (CurTok.Tok) {
case TOK_EXTERN:
D->StorageClass = SC_EXTERN | SC_STATIC;
ident Ident;
/* Accept forward definitions */
- if (curtok != TOK_LCURLY) {
+ if (CurTok.Tok != TOK_LCURLY) {
return;
}
/* Read the enum tags */
EnumVal = 0;
- while (curtok != TOK_RCURLY) {
+ while (CurTok.Tok != TOK_RCURLY) {
/* We expect an identifier */
- if (curtok != TOK_IDENT) {
+ if (CurTok.Tok != TOK_IDENT) {
Error ("Identifier expected");
continue;
}
NextToken ();
/* Check for an assigned value */
- if (curtok == TOK_ASSIGN) {
+ if (CurTok.Tok == TOK_ASSIGN) {
struct expent lval;
NextToken ();
constexpr (&lval);
AddConstSym (Ident, type_int, SC_ENUM, EnumVal++);
/* Check for end of definition */
- if (curtok != TOK_COMMA)
+ if (CurTok.Tok != TOK_COMMA)
break;
NextToken ();
}
SymEntry* Entry;
- if (curtok != TOK_LCURLY) {
+ if (CurTok.Tok != TOK_LCURLY) {
/* Just a forward declaration. Try to find a struct with the given
* name. If there is none, insert a forward declaration into the
* current lexical level.
/* Parse struct fields */
Size = 0;
- while (curtok != TOK_RCURLY) {
+ while (CurTok.Tok != TOK_RCURLY) {
/* Get the type of the entry */
DeclSpec Spec;
}
}
- if (curtok != TOK_COMMA)
+ if (CurTok.Tok != TOK_COMMA)
break;
NextToken ();
}
Qualifiers = OptionalQualifiers (T_QUAL_NONE);
/* Look at the data type */
- switch (curtok) {
+ switch (CurTok.Tok) {
case TOK_VOID:
NextToken ();
case TOK_LONG:
NextToken ();
- if (curtok == TOK_UNSIGNED) {
+ if (CurTok.Tok == TOK_UNSIGNED) {
NextToken ();
optionalint ();
D->Type[0] = T_ULONG;
case TOK_SHORT:
NextToken ();
- if (curtok == TOK_UNSIGNED) {
+ if (CurTok.Tok == TOK_UNSIGNED) {
NextToken ();
optionalint ();
D->Type[0] = T_USHORT;
case TOK_SIGNED:
NextToken ();
- switch (curtok) {
+ switch (CurTok.Tok) {
case TOK_CHAR:
NextToken ();
case TOK_UNSIGNED:
NextToken ();
- switch (curtok) {
+ switch (CurTok.Tok) {
case TOK_CHAR:
NextToken ();
case TOK_STRUCT:
case TOK_UNION:
- StructType = (curtok == TOK_STRUCT)? T_STRUCT : T_UNION;
+ StructType = (CurTok.Tok == TOK_STRUCT)? T_STRUCT : T_UNION;
NextToken ();
/* */
- if (curtok == TOK_IDENT) {
+ if (CurTok.Tok == TOK_IDENT) {
strcpy (Ident, CurTok.Ident);
NextToken ();
} else {
case TOK_ENUM:
NextToken ();
- if (curtok != TOK_LCURLY) {
+ if (CurTok.Tok != TOK_LCURLY) {
/* Named enum */
- if (curtok == TOK_IDENT) {
+ if (CurTok.Tok == TOK_IDENT) {
/* Find an entry with this name */
Entry = FindTagSym (CurTok.Ident);
if (Entry) {
/* Parse an old style (K&R) parameter list */
{
/* Parse params */
- while (curtok != TOK_RPAREN) {
+ while (CurTok.Tok != TOK_RPAREN) {
/* List of identifiers expected */
- if (curtok != TOK_IDENT) {
+ if (CurTok.Tok != TOK_IDENT) {
Error ("Identifier expected");
}
NextToken ();
/* Check for more parameters */
- if (curtok == TOK_COMMA) {
+ if (CurTok.Tok == TOK_COMMA) {
NextToken ();
} else {
break;
ConsumeRParen ();
/* An optional list of type specifications follows */
- while (curtok != TOK_LCURLY) {
+ while (CurTok.Tok != TOK_LCURLY) {
DeclSpec Spec;
}
}
- if (curtok == TOK_COMMA) {
+ if (CurTok.Tok == TOK_COMMA) {
NextToken ();
} else {
break;
/* Parse a new style (ANSI) parameter list */
{
/* Parse params */
- while (curtok != TOK_RPAREN) {
+ while (CurTok.Tok != TOK_RPAREN) {
DeclSpec Spec;
Declaration Decl;
DeclAttr Attr;
/* Allow an ellipsis as last parameter */
- if (curtok == TOK_ELLIPSIS) {
+ if (CurTok.Tok == TOK_ELLIPSIS) {
NextToken ();
F->Flags |= FD_VARIADIC;
break;
++F->ParamCount;
/* Check for more parameters */
- if (curtok == TOK_COMMA) {
+ if (CurTok.Tok == TOK_COMMA) {
NextToken ();
} else {
break;
ConsumeRParen ();
/* 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
* parameters.
*/
EnterFunctionLevel ();
/* Check for several special parameter lists */
- if (curtok == TOK_RPAREN) {
+ if (CurTok.Tok == TOK_RPAREN) {
/* Parameter list is empty */
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 */
NextToken ();
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 it's some other identifier, it's an old style parameter list.
*/
/* Recursively process declarators. Build a type array in reverse order. */
{
- if (curtok == TOK_STAR) {
+ if (CurTok.Tok == TOK_STAR) {
type T = T_PTR;
NextToken ();
/* Allow optional const or volatile qualifiers */
Decl (D, Mode);
*D->T++ = T;
return;
- } else if (curtok == TOK_LPAREN) {
+ } else if (CurTok.Tok == TOK_LPAREN) {
NextToken ();
Decl (D, Mode);
ConsumeRParen ();
- } else if (curtok == TOK_FASTCALL) {
+ } else if (CurTok.Tok == TOK_FASTCALL) {
/* Remember the current type pointer */
type* T = D->T;
/* Skip the fastcall token */
*/
if (Mode == DM_NO_IDENT) {
D->Ident[0] = '\0';
- } else if (curtok == TOK_IDENT) {
+ } else if (CurTok.Tok == TOK_IDENT) {
strcpy (D->Ident, CurTok.Ident);
NextToken ();
} else {
}
}
- while (curtok == TOK_LBRACK || curtok == TOK_LPAREN) {
- if (curtok == TOK_LPAREN) {
+ while (CurTok.Tok == TOK_LBRACK || CurTok.Tok == TOK_LPAREN) {
+ if (CurTok.Tok == TOK_LPAREN) {
/* Function declaration */
FuncDesc* F;
NextToken ();
unsigned long Size = 0;
NextToken ();
/* Read the size if it is given */
- if (curtok != TOK_RBRACK) {
+ if (CurTok.Tok != TOK_RBRACK) {
struct expent lval;
constexpr (&lval);
Size = lval.e_const;
}
- if (curtok != TOK_COMMA) {
+ if (CurTok.Tok != TOK_COMMA) {
break;
}
NextToken ();
- } while (curtok != TOK_RCURLY);
+ } while (CurTok.Tok != TOK_RCURLY);
ConsumeRCurly ();
}
/* Get a pointer to the list of symbols */
Entry = Tab->SymHead;
- while (curtok != TOK_RCURLY) {
+ while (CurTok.Tok != TOK_RCURLY) {
if (Entry == 0) {
Error ("Too many initializers");
return;
}
ParseInit (Entry->Type);
Entry = Entry->NextSym;
- if (curtok != TOK_COMMA)
+ if (CurTok.Tok != TOK_COMMA)
break;
NextToken ();
}
case T_ARRAY:
Size = Decode (T + 1);
t = T + DECODE_SIZE + 1;
- if (IsTypeChar(t) && curtok == TOK_SCONST) {
- str = GetLiteral (curval);
+ if (IsTypeChar(t) && CurTok.Tok == TOK_SCONST) {
+ str = GetLiteral (CurTok.IVal);
Count = strlen (str) + 1;
- TranslateLiteralPool (curval); /* Translate into target charset */
+ TranslateLiteralPool (CurTok.IVal); /* Translate into target charset */
g_defbytes (str, Count);
- ResetLiteralPoolOffs (curval); /* Remove string from pool */
+ ResetLiteralPoolOffs (CurTok.IVal); /* Remove string from pool */
NextToken ();
} else {
ConsumeLCurly ();
Count = 0;
- while (curtok != TOK_RCURLY) {
+ while (CurTok.Tok != TOK_RCURLY) {
ParseInit (T + DECODE_SIZE + 1);
++Count;
- if (curtok != TOK_COMMA)
+ if (CurTok.Tok != TOK_COMMA)
break;
NextToken ();
}
/* cc65 */
#include "global.h"
#include "input.h"
+#include "lineinfo.h"
#include "scanner.h"
#include "stmt.h"
#include "error.h"
{
va_list ap;
va_start (ap, Format);
- IntWarning (GetCurrentFile(), curpos, Format, ap);
+ IntWarning (GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Format, ap);
va_end (ap);
}
{
va_list ap;
va_start (ap, Format);
- IntError (GetCurrentFile(), curpos, Format, ap);
+ IntError (GetInputName (CurTok.LI), GetInputLine (CurTok.LI), Format, ap);
va_end (ap);
}
/* Print a message about a fatal error and die */
{
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);
vfprintf (stderr, Format, 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",
- GetCurrentFile(), curpos);
+ FileName, LineNum);
va_start (ap, Format);
vfprintf (stderr, Format, ap);
+
{
SymEntry* Entry;
- return curtok == TOK_LPAREN && (
- (nxttok >= TOK_FIRSTTYPE && nxttok <= TOK_LASTTYPE) ||
- (nxttok == TOK_CONST) ||
- (nxttok == TOK_IDENT &&
- (Entry = FindSym (NextTok.Ident)) != 0 &&
- IsTypeDef (Entry))
- );
+ return CurTok.Tok == TOK_LPAREN && (
+ (NextTok.Tok >= TOK_FIRSTTYPE && NextTok.Tok <= TOK_LASTTYPE) ||
+ (NextTok.Tok == TOK_CONST) ||
+ (NextTok.Tok == TOK_IDENT &&
+ (Entry = FindSym (NextTok.Ident)) != 0 &&
+ IsTypeDef (Entry)));
}
}
/* Parse the actual parameter list */
- while (curtok != TOK_RPAREN) {
+ while (CurTok.Tok != TOK_RPAREN) {
unsigned CFlags;
unsigned Flags;
}
/* Check for end of argument list */
- if (curtok != TOK_COMMA) {
+ if (CurTok.Tok != TOK_COMMA) {
break;
}
NextToken ();
ConsumeLParen ();
/* String literal */
- if (curtok != TOK_SCONST) {
+ if (CurTok.Tok != TOK_SCONST) {
Error ("String literal expected");
} else {
/* The string literal may consist of more than one line of assembler
* code. Separate the single lines and output the code.
*/
- const char* S = GetLiteral (curval);
+ const char* S = GetLiteral (CurTok.IVal);
while (*S) {
/* Allow lines up to 256 bytes */
* will fail if the next token is also a string token, but that's a
* syntax error anyway, because we expect a right paren.
*/
- ResetLiteralPoolOffs (curval);
+ ResetLiteralPoolOffs (CurTok.IVal);
}
/* Skip the string token */
lval->e_test = 0;
/* 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_tptr = curtype;
- lval->e_const = curval;
+ lval->e_tptr = CurTok.Type;
+ lval->e_const = CurTok.IVal;
NextToken ();
return 0;
}
/* Process parenthesized subexpression by calling the whole parser
* recursively.
*/
- if (curtok == TOK_LPAREN) {
+ if (CurTok.Tok == TOK_LPAREN) {
NextToken ();
memset (lval, 0, sizeof (*lval)); /* Remove any attributes */
k = hie0 (lval);
}
/* Identifier? */
- if (curtok == TOK_IDENT) {
+ if (CurTok.Tok == TOK_IDENT) {
SymEntry* Sym;
ident Ident;
NextToken ();
/* 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
* function signature for a function having an empty param list
* and returning int.
}
/* String literal? */
- if (curtok == TOK_SCONST) {
+ if (CurTok.Tok == TOK_SCONST) {
lval->e_flags = E_MCONST | E_TLIT;
- lval->e_const = curval;
- lval->e_tptr = GetCharArrayType (strlen (GetLiteral (curval)));
+ lval->e_const = CurTok.IVal;
+ lval->e_tptr = GetCharArrayType (strlen (GetLiteral (CurTok.IVal)));
NextToken ();
return 0;
}
/* ASM statement? */
- if (curtok == TOK_ASM) {
+ if (CurTok.Tok == TOK_ASM) {
doasm ();
lval->e_tptr = type_void;
lval->e_flags = E_MEXPR;
}
/* __AX__ and __EAX__ pseudo values? */
- if (curtok == TOK_AX || curtok == TOK_EAX) {
- lval->e_tptr = (curtok == TOK_AX)? type_uint : type_ulong;
+ if (CurTok.Tok == TOK_AX || CurTok.Tok == TOK_EAX) {
+ lval->e_tptr = (CurTok.Tok == TOK_AX)? type_uint : type_ulong;
lval->e_flags = E_MREG;
lval->e_test &= ~E_CC;
lval->e_const = 0;
/* Skip the token and check for an identifier */
NextToken ();
- if (curtok != TOK_IDENT) {
+ if (CurTok.Tok != TOK_IDENT) {
Error ("Identifier expected");
lval->e_tptr = type_int;
return 0;
k = primary (lval);
- if (curtok < TOK_LBRACK || curtok > TOK_PTR_REF) {
+ if (CurTok.Tok < TOK_LBRACK || CurTok.Tok > TOK_PTR_REF) {
/* Not for us */
return k;
}
while (1) {
- if (curtok == TOK_LBRACK) {
+ if (CurTok.Tok == TOK_LBRACK) {
/* Array reference */
k = arrayref (k, lval);
- } else if (curtok == TOK_LPAREN) {
+ } else if (CurTok.Tok == TOK_LPAREN) {
/* Function call. Skip the opening parenthesis */
NextToken ();
}
k = 0;
- } else if (curtok == TOK_DOT) {
+ } else if (CurTok.Tok == TOK_DOT) {
if (!IsClassStruct (lval->e_tptr)) {
Error ("Struct expected");
}
k = structref (0, lval);
- } else if (curtok == TOK_PTR_REF) {
+ } else if (CurTok.Tok == TOK_PTR_REF) {
tptr = lval->e_tptr;
if (tptr[0] != T_PTR || (tptr[1] & T_STRUCT) == 0) {
int k;
type* t;
- switch (curtok) {
+ switch (CurTok.Tok) {
case TOK_INC:
pre_incdec (lval, g_inc);
case TOK_PLUS:
case TOK_MINUS:
case TOK_COMP:
- unaryop (curtok, lval);
+ unaryop (CurTok.Tok, lval);
return 0;
case TOK_BOOL_NOT:
}
k = hie11 (lval);
- switch (curtok) {
+ switch (CurTok.Tok) {
case TOK_INC:
post_incdec (lval, k, g_inc);
return 0;
k = hienext (lval);
*UsedGen = 0;
- while ((Gen = FindGen (curtok, ops)) != 0) {
+ while ((Gen = FindGen (CurTok.Tok, ops)) != 0) {
/* Tell the caller that we handled it's ops */
*UsedGen = 1;
}
/* Remember the operator token, then skip it */
- tok = curtok;
+ tok = CurTok.Tok;
NextToken ();
/* Get the lhs on stack */
k = hienext (lval);
- while ((Gen = FindGen (curtok, ops)) != 0) {
+ while ((Gen = FindGen (CurTok.Tok, ops)) != 0) {
/* Remember the operator token, then skip it */
- tok = curtok;
+ tok = CurTok.Tok;
NextToken ();
/* Get the lhs on stack */
/* Process + and - binary operators. */
{
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);
} else {
parsesub (k, lval);
struct expent lval2;
k = hie2 (lval);
- if (curtok == TOK_BOOL_AND) {
+ if (CurTok.Tok == TOK_BOOL_AND) {
/* Tell our caller that we're evaluating a boolean */
*BoolOp = 1;
g_falsejump (CF_NONE, lab);
/* Parse more boolean and's */
- while (curtok == TOK_BOOL_AND) {
+ while (CurTok.Tok == TOK_BOOL_AND) {
/* Skip the && */
NextToken ();
exprhs (CF_FORCECHAR, k, &lval2);
/* Do short circuit evaluation */
- if (curtok == TOK_BOOL_AND) {
+ if (CurTok.Tok == TOK_BOOL_AND) {
g_falsejump (CF_NONE, lab);
} else {
/* Last expression - will evaluate to true */
k = hieAnd (lval, TrueLab, &BoolOp);
/* 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 ((lval->e_test & E_CC) == 0) {
BoolOp = 1;
/* while there's more expr */
- while (curtok == TOK_BOOL_OR) {
+ while (CurTok.Tok == TOK_BOOL_OR) {
/* skip the || */
NextToken ();
*/
#if 0
/* Seems this sometimes generates wrong code */
- if (curtok == TOK_BOOL_OR && !AndOp) {
+ if (CurTok.Tok == TOK_BOOL_OR && !AndOp) {
g_truejump (CF_NONE, TrueLab);
}
#else
k = hieOr (lval);
- if (curtok == TOK_QUEST) {
+ if (CurTok.Tok == TOK_QUEST) {
NextToken ();
if ((lval->e_test & E_CC) == 0) {
/* Condition codes not set, force a test */
int k;
k = hieQuest (lval);
- switch (curtok) {
+ switch (CurTok.Tok) {
case TOK_RPAREN:
case TOK_SEMI:
int k;
k = hie1 (lval);
- while (curtok == TOK_COMMA) {
+ while (CurTok.Tok == TOK_COMMA) {
NextToken ();
k = hie1 (lval);
}
* compiler itself is one big hack...): If a semicolon follows, we
* don't have a statement and may omit the jump.
*/
- if (curtok != TOK_SEMI) {
+ if (CurTok.Tok != TOK_SEMI) {
g_falsejump (CF_NONE, label);
}
}
/* Now process statements in this block */
HadReturn = 0;
- while (curtok != TOK_RCURLY) {
- if (curtok != TOK_CEOF) {
+ while (CurTok.Tok != TOK_RCURLY) {
+ if (CurTok.Tok != TOK_CEOF) {
HadReturn = Statement ();
} else {
break;
NextToken ();
/* Label name must follow */
- if (curtok != TOK_IDENT) {
+ if (CurTok.Tok != TOK_IDENT) {
Error ("Label name expected");
/* cc65 */
#include "asmcode.h"
#include "error.h"
-#include "global.h"
#include "incpath.h"
+#include "lineinfo.h"
#include "input.h"
/* Maximum count of nested includes */
#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 */
typedef struct AFile AFile;
struct AFile {
unsigned Line; /* Line number for this file */
FILE* F; /* Input file stream */
- const char* Name; /* Points to corresponding IFile name */
+ IFile* Input; /* Points to corresponding IFile */
};
/* List of all input files */
/* Initialize the fields */
AF->Line = 0;
AF->F = F;
- AF->Name = IF->Name;
+ AF->Input = IF;
/* Increment the usage counter of the corresponding IFile */
++IF->Usage;
--Len;
}
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,
* we're done.
/* Got a line. Initialize the current and next characters. */
InitLine (line);
+ /* Create line information for this line */
+ UpdateLineInfo (Input->Input, Input->Line, line);
+
/* Done */
return 1;
}
unsigned AFileCount = CollCount (&AFiles);
if (AFileCount > 0) {
const AFile* AF = (const AFile*) CollAt (&AFiles, AFileCount-1);
- return AF->Name;
+ return AF->Input->Name;
} else {
/* No open file. Use the main file if we have one. */
unsigned IFileCount = CollCount (&IFiles);
+#include <stdio.h>
+
+
+
/*****************************************************************************/
/* data */
/*****************************************************************************/
extern char CurC;
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) */
+};
+
/*****************************************************************************/
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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;
+}
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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
+
+
+
+
/* Change SC in case it was register */
SC = (SC & ~SC_REGISTER) | SC_AUTO;
- if (curtok == TOK_ASSIGN) {
+ if (CurTok.Tok == TOK_ASSIGN) {
struct expent lval;
g_res (Size);
/* Allow assignments */
- if (curtok == TOK_ASSIGN) {
+ if (CurTok.Tok == TOK_ASSIGN) {
struct expent lval;
} else if ((SC & SC_STATIC) == SC_STATIC) {
/* Static data */
- if (curtok == TOK_ASSIGN) {
+ if (CurTok.Tok == TOK_ASSIGN) {
/* Initialization ahead, switch to data segment */
if (IsQualConst (Decl.Type)) {
}
/* Accept type only declarations */
- if (curtok == TOK_SEMI) {
+ if (CurTok.Tok == TOK_SEMI) {
/* Type declaration only */
CheckEmptyDecl (&Spec);
NextToken ();
ParseOneDecl (&Spec);
/* Check if there is more */
- if (curtok == TOK_COMMA) {
+ if (CurTok.Tok == TOK_COMMA) {
/* More to come */
NextToken ();
} else {
ident.o \
incpath.o \
input.o \
+ lineinfo.o \
litpool.o \
locals.o \
loop.o \
static void StringPragma (void (*Func) (const char*))
/* Handle a pragma that expects a string parameter */
{
- if (curtok != TOK_SCONST) {
+ if (CurTok.Tok != TOK_SCONST) {
Error ("String literal expected");
} else {
/* Get the string */
- const char* Name = GetLiteral (curval);
+ const char* Name = GetLiteral (CurTok.IVal);
/* Call the given function with the string argument */
Func (Name);
/* Reset the string pointer, removing the string from the pool */
- ResetLiteralPoolOffs (curval);
+ ResetLiteralPoolOffs (CurTok.IVal);
}
/* Skip the string (or error) token */
static void SegNamePragma (segment_t Seg)
/* Handle a pragma that expects a segment name parameter */
{
- if (curtok != TOK_SCONST) {
+ if (CurTok.Tok != TOK_SCONST) {
Error ("String literal expected");
} else {
/* Get the segment name */
- const char* Name = GetLiteral (curval);
+ const char* Name = GetLiteral (CurTok.IVal);
/* Check if the name is valid */
if (ValidSegName (Name)) {
}
/* Reset the string pointer, removing the string from the pool */
- ResetLiteralPoolOffs (curval);
+ ResetLiteralPoolOffs (CurTok.IVal);
}
/* Skip the string (or error) token */
NextToken ();
/* Identifier must follow */
- if (curtok != TOK_IDENT) {
+ if (CurTok.Tok != TOK_IDENT) {
Error ("Identifier expected");
return;
}
-/*
- * scanner.c
- *
- * Ullrich von Bassewitz, 07.06.1998
- */
+/*****************************************************************************/
+/* */
+/* scanner.c */
+/* */
+/* 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. */
+/* */
+/*****************************************************************************/
-static void unknown (char C)
+static void UnknownChar (char C)
/* Error message for unknown character */
{
Error ("Invalid input character with code %02X", C & 0xFF);
static void SetTok (int tok)
-/* set nxttok and bump line ptr */
+/* Set NextTok.Tok and bump line ptr */
{
- nxttok = tok;
+ NextTok.Tok = tok;
NextChar ();
}
i = 0;
C = CurC - '0';
while (NextC >= '0' && NextC <= '7' && i++ < 4) {
- NextChar ();
+ NextChar ();
C = (C << 3) | (CurC - '0');
}
break;
}
/* Setup values and attributes */
- nxttok = TOK_CCONST;
+ NextTok.Tok = TOK_CCONST;
/* Translate into target charset */
- nxtval = SignExtendChar (TgtTranslateChar (C));
+ NextTok.IVal = SignExtendChar (TgtTranslateChar (C));
/* Character constants have type int */
- nxttype = type_int;
+ NextTok.Type = type_int;
}
static void StringConst (void)
/* Parse a quoted string */
{
- nxtval = GetLiteralPoolOffs ();
- nxttok = TOK_SCONST;
+ NextTok.IVal = GetLiteralPoolOffs ();
+ NextTok.Tok = TOK_SCONST;
/* Be sure to concatenate strings */
while (CurC == '\"') {
{
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 */
+ if (CurTok.LI) {
+ ReleaseLineInfo (CurTok.LI);
+ }
CurTok = NextTok;
/* Remember the starting position of the next token */
- NextTok.Pos = GetCurrentLine();
+ NextTok.LI = UseLineInfo (GetCurLineInfo ());
- /* Skip spaces and read the next line if needed */
- if (SkipWhite () == 0) {
+ /* Now handle end of input. */
+ if (GotEOF) {
/* End of file reached */
- nxttok = TOK_CEOF;
+ NextTok.Tok = TOK_CEOF;
return;
}
NextChar ();
if (toupper (CurC) == 'X') {
base = 16;
- nxttype = type_uint;
+ NextTok.Type = type_uint;
NextChar (); /* gobble "x" */
} else {
base = 8;
/* Now set the type string to the smallest type in types */
if (types & IT_INT) {
- nxttype = type_int;
+ NextTok.Type = type_int;
} else if (types & IT_UINT) {
- nxttype = type_uint;
+ NextTok.Type = type_uint;
} else if (types & IT_LONG) {
- nxttype = type_long;
+ NextTok.Type = type_long;
} else {
- nxttype = type_ulong;
+ NextTok.Type = type_ulong;
}
/* Set the value and the token */
- nxtval = k;
- nxttok = TOK_ICONST;
+ NextTok.IVal = k;
+ NextTok.Tok = TOK_ICONST;
return;
}
if (IsSym (token)) {
/* Check for a keyword */
- if ((nxttok = FindKey (token)) != TOK_IDENT) {
+ if ((NextTok.Tok = FindKey (token)) != TOK_IDENT) {
/* Reserved word found */
return;
}
if (token [0] == '_') {
/* Special symbols */
if (strcmp (token, "__FILE__") == 0) {
- nxtval = AddLiteral (GetCurrentFile());
- nxttok = TOK_SCONST;
+ NextTok.IVal = AddLiteral (GetCurrentFile());
+ NextTok.Tok = TOK_SCONST;
return;
} else if (strcmp (token, "__LINE__") == 0) {
- nxttok = TOK_ICONST;
- nxtval = GetCurrentLine();
- nxttype = type_int;
+ NextTok.Tok = TOK_ICONST;
+ NextTok.IVal = GetCurrentLine();
+ NextTok.Type = type_int;
return;
} else if (strcmp (token, "__func__") == 0) {
/* __func__ is only defined in functions */
if (CurrentFunc) {
- nxtval = AddLiteral (GetFuncName (CurrentFunc));
- nxttok = TOK_SCONST;
+ NextTok.IVal = AddLiteral (GetFuncName (CurrentFunc));
+ NextTok.Tok = TOK_SCONST;
return;
}
}
if (CurC == '=') {
SetTok (TOK_NE);
} else {
- nxttok = TOK_BOOL_NOT;
+ NextTok.Tok = TOK_BOOL_NOT;
}
break;
if (CurC == '=') {
SetTok (TOK_MOD_ASSIGN);
} else {
- nxttok = TOK_MOD;
+ NextTok.Tok = TOK_MOD;
}
break;
SetTok (TOK_AND_ASSIGN);
break;
default:
- nxttok = TOK_AND;
+ NextTok.Tok = TOK_AND;
}
break;
if (CurC == '=') {
SetTok (TOK_MUL_ASSIGN);
} else {
- nxttok = TOK_STAR;
+ NextTok.Tok = TOK_STAR;
}
break;
SetTok (TOK_PLUS_ASSIGN);
break;
default:
- nxttok = TOK_PLUS;
+ NextTok.Tok = TOK_PLUS;
}
break;
SetTok (TOK_PTR_REF);
break;
default:
- nxttok = TOK_MINUS;
+ NextTok.Tok = TOK_MINUS;
}
break;
if (CurC == '.') {
SetTok (TOK_ELLIPSIS);
} else {
- unknown (CurC);
+ UnknownChar (CurC);
}
} else {
- nxttok = TOK_DOT;
+ NextTok.Tok = TOK_DOT;
}
break;
if (CurC == '=') {
SetTok (TOK_DIV_ASSIGN);
} else {
- nxttok = TOK_DIV;
+ NextTok.Tok = TOK_DIV;
}
break;
if (CurC == '=') {
SetTok (TOK_SHL_ASSIGN);
} else {
- nxttok = TOK_SHL;
+ NextTok.Tok = TOK_SHL;
}
break;
default:
- nxttok = TOK_LT;
+ NextTok.Tok = TOK_LT;
}
break;
if (CurC == '=') {
SetTok (TOK_EQ);
} else {
- nxttok = TOK_ASSIGN;
+ NextTok.Tok = TOK_ASSIGN;
}
break;
if (CurC == '=') {
SetTok (TOK_SHR_ASSIGN);
} else {
- nxttok = TOK_SHR;
+ NextTok.Tok = TOK_SHR;
}
break;
default:
- nxttok = TOK_GT;
+ NextTok.Tok = TOK_GT;
}
break;
if (CurC == '=') {
SetTok (TOK_XOR_ASSIGN);
} else {
- nxttok = TOK_XOR;
+ NextTok.Tok = TOK_XOR;
}
break;
SetTok (TOK_OR_ASSIGN);
break;
default:
- nxttok = TOK_OR;
+ NextTok.Tok = TOK_OR;
}
break;
/* OOPS - should not happen */
Error ("Preprocessor directive expected");
}
- nxttok = TOK_PRAGMA;
+ NextTok.Tok = TOK_PRAGMA;
break;
default:
- unknown (CurC);
+ UnknownChar (CurC);
}
* message.
*/
{
- if (curtok == Token) {
+ if (CurTok.Tok == Token) {
NextToken ();
} else {
Error (ErrorMsg);
/* Check for a semicolon and skip it. */
{
/* Try do be smart about typos... */
- if (curtok == TOK_SEMI) {
+ if (CurTok.Tok == TOK_SEMI) {
NextToken ();
} else {
Error ("`;' expected");
- if (curtok == TOK_COLON || curtok == TOK_COMMA) {
+ if (CurTok.Tok == TOK_COLON || CurTok.Tok == TOK_COMMA) {
NextToken ();
}
}
-/*
- * scanner.h
- *
- * Ullrich von Bassewitz, 07.06.1998
- */
+/*****************************************************************************/
+/* */
+/* scanner.h */
+/* */
+/* 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. */
+/* */
+/*****************************************************************************/
+/* cc65 */
#include "datatype.h"
#include "ident.h"
+#include "lineinfo.h"
/* Token stuff */
-typedef struct Token_ Token;
-struct Token_ {
- token_t Tok; /* The token itself */
- long IVal; /* The integer attribute */
- double FVal; /* The float attribute */
- ident Ident; /* Identifier if IDENT */
- unsigned Pos; /* Source line where the token comes from */
+typedef struct Token Token;
+struct Token {
+ token_t Tok; /* The token itself */
+ long IVal; /* The integer attribute */
+ double FVal; /* The float attribute */
+ ident Ident; /* Identifier if IDENT */
+ LineInfo* LI; /* Source line where the token comes from */
type* Type; /* Type if integer or float constant */
};
extern Token CurTok; /* The current 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
-
/*****************************************************************************/
#include "chartype.h"
#include "check.h"
#include "coll.h"
+#include "scanner.h"
#include "xmalloc.h"
/* cc65 */
va_list ap;
va_start (ap, Format);
CHECK (CS != 0);
- AddCodeEntry (CS->Code, Format, ap);
+ AddCodeEntry (CS->Code, CurTok.LI, Format, ap);
va_end (ap);
}
gotbreak = Statement ();
/* Else clause present? */
- if (curtok != TOK_ELSE) {
+ if (CurTok.Tok != TOK_ELSE) {
g_defcodelabel (flab1);
/* Since there's no else clause, we're not sure, if the a break
* do another small optimization here, and use a conditional jump
* instead an absolute one.
*/
- if (curtok == TOK_SEMI) {
+ if (CurTok.Tok == TOK_SEMI) {
/* Shortcut */
NextToken ();
/* Use a conditional jump */
struct expent lval;
NextToken ();
- if (curtok != TOK_SEMI) {
+ if (CurTok.Tok != TOK_SEMI) {
if (HasVoidReturn (CurrentFunc)) {
Error ("Returning a value in function with return type void");
}
/* Parse the labels */
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
* break statement, we must jump over the next selector test.
NextLab = 0;
}
- while (curtok == TOK_CASE || curtok == TOK_DEFAULT) {
+ while (CurTok.Tok == TOK_CASE || CurTok.Tok == TOK_DEFAULT) {
/* Parse the selector */
- if (curtok == TOK_CASE) {
+ if (CurTok.Tok == TOK_CASE) {
/* Count labels */
++lcount;
case T_SCHAR:
/* Signed char */
if (Val < -128 || Val > 127) {
- Error ("Range error");
+ Error ("Range error");
}
break;
case T_UCHAR:
if (Val < 0 || Val > 255) {
- Error ("Range error");
+ Error ("Range error");
}
break;
case T_INT:
if (Val < -32768 || Val > 32767) {
- Error ("Range error");
+ Error ("Range error");
}
break;
case T_UINT:
if (Val < 0 || Val > 65535) {
- Error ("Range error");
+ Error ("Range error");
}
break;
Internal ("Invalid type: %02X", *eval->e_tptr & 0xFF);
}
- /* Skip the colon */
- ConsumeColon ();
-
/* Emit a compare */
g_cmp (Flags, Val);
/* If another case follows, we will jump to the code if
* the condition is true.
*/
- if (curtok == TOK_CASE) {
+ if (CurTok.Tok == TOK_CASE) {
/* Create a code label if needed */
if (CodeLab == 0) {
CodeLab = GetLocalLabel ();
}
g_falsejump (CF_NONE, CodeLab);
- } else if (curtok != TOK_DEFAULT) {
+ } else if (CurTok.Tok != TOK_DEFAULT) {
/* No case follows, jump to next selector */
if (NextLab == 0) {
NextLab = GetLocalLabel ();
g_truejump (CF_NONE, NextLab);
}
+ /* Skip the colon */
+ ConsumeColon ();
+
} else {
/* Default case */
NextToken ();
- /* Skip the colon */
- ConsumeColon ();
-
/* Handle the pathologic case: DEFAULT followed by CASE */
- if (curtok == TOK_CASE) {
+ if (CurTok.Tok == TOK_CASE) {
if (CodeLab == 0) {
CodeLab = GetLocalLabel ();
}
g_jump (CodeLab);
}
+ /* Skip the colon */
+ ConsumeColon ();
+
/* Remember that we had a default label */
HaveDefault = 1;
}
}
/* Parse statements */
- if (curtok != TOK_RCURLY) {
+ if (CurTok.Tok != TOK_RCURLY) {
HaveBreak = Statement ();
}
}
Warning ("No case labels");
}
- /* Eat the closing curly brace */
- NextToken ();
-
/* Define the exit label and, if there's a next label left, create this
* one, too.
*/
}
g_defcodelabel (ExitLab);
+ /* Eat the closing curly brace */
+ NextToken ();
+
/* End the loop */
DelLoop ();
}
/* Jump behind the code for the CASE labels */
g_jump (lcase = GetLocalLabel ());
lcount = 0;
- while (curtok != TOK_RCURLY) {
- if (curtok == TOK_CASE || curtok == TOK_DEFAULT) {
+ while (CurTok.Tok != TOK_RCURLY) {
+ if (CurTok.Tok == TOK_CASE || CurTok.Tok == TOK_DEFAULT) {
if (lcount >= CASE_MAX) {
Fatal ("Too many case labels");
}
label = GetLocalLabel ();
do {
- if (curtok == TOK_CASE) {
+ if (CurTok.Tok == TOK_CASE) {
NextToken ();
constexpr (&lval);
if (!IsClassInt (lval.e_tptr)) {
HaveDefault = 1;
}
ConsumeColon ();
- } while (curtok == TOK_CASE || curtok == TOK_DEFAULT);
+ } while (CurTok.Tok == TOK_CASE || CurTok.Tok == TOK_DEFAULT);
g_defcodelabel (label);
HaveBreak = 0;
}
- if (curtok != TOK_RCURLY) {
+ if (CurTok.Tok != TOK_RCURLY) {
HaveBreak = Statement ();
}
}
lstat = GetLocalLabel ();
AddLoop (oursp, loop, lab, linc, lstat);
ConsumeLParen ();
- if (curtok != TOK_SEMI) { /* exp1 */
+ if (CurTok.Tok != TOK_SEMI) { /* exp1 */
expression (&lval1);
}
ConsumeSemi ();
g_defcodelabel (loop);
- if (curtok != TOK_SEMI) { /* exp2 */
+ if (CurTok.Tok != TOK_SEMI) { /* exp2 */
boolexpr (&lval2);
g_truejump (CF_NONE, lstat);
g_jump (lab);
}
ConsumeSemi ();
g_defcodelabel (linc);
- if (curtok != TOK_RPAREN) { /* exp3 */
+ if (CurTok.Tok != TOK_RPAREN) { /* exp3 */
expression (&lval3);
}
ConsumeRParen ();
/* Now process statements in this block */
isbrk = 0;
- while (curtok != TOK_RCURLY) {
- if (curtok != TOK_CEOF) {
+ while (CurTok.Tok != TOK_RCURLY) {
+ if (CurTok.Tok != TOK_CEOF) {
isbrk = Statement ();
} else {
break;
struct expent lval;
/* */
- if (curtok == TOK_IDENT && nxttok == TOK_COLON) {
+ if (CurTok.Tok == TOK_IDENT && NextTok.Tok == TOK_COLON) {
/* Special handling for a label */
DoLabel ();
} else {
- switch (curtok) {
+ switch (CurTok.Tok) {
case TOK_LCURLY:
return CompoundStatement ();