Files
cc65/src/ca65/token.c
Kugel Fuhr bcd29de443 Much improved error messages for ca65. For most errors it will now say what
was expected and what was found instead. Also improved error recovery in a few
places.
2025-07-06 08:40:05 +02:00

357 lines
14 KiB
C

/*****************************************************************************/
/* */
/* token.c */
/* */
/* Token list for the ca65 macro assembler */
/* */
/* */
/* */
/* (C) 2007-2011, Ullrich von Bassewitz */
/* Roemerstrasse 52 */
/* D-70794 Filderstadt */
/* EMail: uz@cc65.org */
/* */
/* */
/* 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 <stdio.h>
/* ca65 */
#include "token.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Use a struct so we can extend it if required */
typedef struct TokDescEntry TokDescEntry;
struct TokDescEntry {
const char* Desc;
};
static const TokDescEntry TokDesc[] = {
{ "none", },
{ "end-of-file", },
{ "end-of-line", },
{ "{s}", },
{ "{s}", },
{ "{i}", },
{ "'{c}'", },
{ "\"{s}\"", },
{ "A", },
{ "Q", },
{ "S", },
{ "X", },
{ "Y", },
{ "Z", },
{ "R{i}", },
{ ":=", },
{ "unnamed label", },
{ "=", },
{ "<>", },
{ "<", },
{ ">", },
{ "<=", },
{ ">=", },
{ ".AND", },
{ ".OR", },
{ ".XOR", },
{ ".NOT", },
{ "+", },
{ "-", },
{ "*", },
{ "/", },
{ "!", },
{ "|", },
{ "^", },
{ "&", },
{ "<<", },
{ ">>", },
{ "~", },
{ "$", },
{ "::", },
{ ".", },
{ ",", },
{ "#", },
{ ":", },
{ "(", },
{ ")", },
{ "[", },
{ "]", },
{ "{", },
{ "}", },
{ "@", },
{ "z:", },
{ "a:", },
{ "f:", },
{ "macro parameter", },
{ "repeat counter", },
{ ".A16" },
{ ".A8" },
{ ".ADDR" },
{ ".ADDRSIZE" },
{ ".ALIGN" },
{ ".ASCIIZ" },
{ ".ASIZE" },
{ ".ASSERT" },
{ ".AUTOIMPORT" },
{ ".BANK" },
{ ".BANKBYTE" },
{ ".BANKBYTES" },
{ ".BLANK" },
{ ".BSS" },
{ ".BYTE" },
{ ".CAP" },
{ ".CASE" },
{ ".CHARMAP" },
{ ".CODE" },
{ ".CONCAT" },
{ ".CONDES" },
{ ".CONST" },
{ ".CONSTRUCTOR" },
{ ".CPU" },
{ ".DATA" },
{ ".DBG" },
{ ".DBYT" },
{ ".DEBUGINFO" },
{ ".DEFINE" },
{ ".DEFINED" },
{ ".DEFINEDMACRO" },
{ ".DELMAC" },
{ ".DESTRUCTOR" },
{ ".DWORD" },
{ ".ELSE" },
{ ".ELSEIF" },
{ ".END" },
{ ".ENDENUM" },
{ ".ENDIF" },
{ ".ENDMACRO" },
{ ".ENDPROC" },
{ ".ENDREP" },
{ ".ENDSCOPE" },
{ ".ENDSTRUCT" },
{ ".ENDUNION" },
{ ".ENUM" },
{ ".ERROR" },
{ ".EXITMACRO" },
{ ".EXPORT" },
{ ".EXPORTZP" },
{ ".FARADDR" },
{ ".FATAL" },
{ ".FEATURE" },
{ ".FILEOPT" },
{ ".FORCEIMPORT" },
{ ".FORCEWORD" },
{ ".GLOBAL" },
{ ".GLOBALZP" },
{ ".HIBYTE" },
{ ".HIBYTES" },
{ ".HIWORD" },
{ ".I16" },
{ ".I8" },
{ ".MAKEIDENT" },
{ ".IF" },
{ ".IFBLANK" },
{ ".IFCONST" },
{ ".IFDEF" },
{ ".IFNBLANK" },
{ ".IFNCONST" },
{ ".IFNDEF" },
{ ".IFNREF" },
{ ".IFP02" },
{ ".IFP02X" },
{ ".IFP4510" },
{ ".IFP45GS02" },
{ ".IFP6280" },
{ ".IFP816" },
{ ".IFPC02" },
{ ".IFPCE02" },
{ ".IFPDTV" },
{ ".IFPM740" },
{ ".IFPSC02" },
{ ".IFPSWEET16" },
{ ".IFPWC02" },
{ ".IFREF" },
{ ".IMPORT" },
{ ".IMPORTZP" },
{ ".INCBIN" },
{ ".INCLUDE" },
{ ".INTERRUPTOR" },
{ ".ISIZE" },
{ ".ISMNEMONIC" },
{ ".LEFT" },
{ ".LINECONT" },
{ ".LIST" },
{ ".LISTBYTES" },
{ ".LITERAL" },
{ ".LOBYTE" },
{ ".LOBYTES" },
{ ".LOCAL" },
{ ".LOCALCHAR" },
{ ".LOWORD" },
{ ".MACPACK" },
{ ".MACRO" },
{ ".MATCH" },
{ ".MAX" },
{ ".MID" },
{ ".MIN" },
{ ".NULL" },
{ ".ORG" },
{ ".OUT" },
{ ".P02" },
{ ".P02X" },
{ ".P4510" },
{ ".P45GS02" },
{ ".P6280" },
{ ".P816" },
{ ".PAGELENGTH" },
{ ".PARAMCOUNT" },
{ ".PC02" },
{ ".PCE02" },
{ ".PDTV" },
{ ".PM740" },
{ ".POPCHARMAP" },
{ ".POPCPU" },
{ ".POPSEG" },
{ ".PROC" },
{ ".PSC02" },
{ ".PSWEET16" },
{ ".PUSHCHARMAP" },
{ ".PUSHCPU" },
{ ".PUSHSEG" },
{ ".PWC02" },
{ ".REFERENCED" },
{ ".REFERTO" },
{ ".RELOC" },
{ ".REPEAT" },
{ ".RES" },
{ ".RIGHT" },
{ ".RODATA" },
{ ".SCOPE" },
{ ".SEGMENT" },
{ ".SET" },
{ ".SETCPU" },
{ ".SIZEOF" },
{ ".SMART" },
{ ".SPRINTF" },
{ ".STRAT" },
{ ".STRING" },
{ ".STRLEN" },
{ ".STRUCT" },
{ ".TAG" },
{ ".TCOUNT" },
{ ".TIME" },
{ ".UNDEF" },
{ ".UNION" },
{ ".VERSION" },
{ ".WARNING" },
{ ".WORD" },
{ ".XMATCH" },
{ ".ZEROPAGE" },
};
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void CopyToken (Token* Dst, const Token* Src)
/* Copy a token from Src to Dst. The current value of Dst.SVal is free'd,
** so Dst must be initialized.
*/
{
/* Copy the fields */
Dst->Tok = Src->Tok;
Dst->WS = Src->WS;
Dst->IVal = Src->IVal;
SB_Copy (&Dst->SVal, &Src->SVal);
Dst->Pos = Src->Pos;
}
StrBuf* TokenDesc (const Token* T, StrBuf* S)
/* Place a textual description of the given token into S. */
{
PRECONDITION (sizeof (TokDesc) / sizeof (TokDesc[0]) == TOK_COUNT);
/* Clear the target buffer */
SB_Clear (S);
/* Get the description for the token */
const char* Desc = TokDesc[T->Tok].Desc;
/* Repeatedly replace {c}, {i} and {s} */
size_t Start = 0;
while (1) {
const char* P = strchr (Desc + Start, '{');
if (P) {
/* Check if this is really {c}, {i} or {s} */
if ((P[1] != 'c' &&
P[1] != 'i' &&
P[1] != 's') ||
P[2] != '}') {
++Start;
continue;
}
/* Append the text before the replacement token */
SB_AppendBuf (S, Desc + Start, P - (Desc + Start));
Start += P - (Desc + Start) + 3;
/* Append the replacement text */
if (P[1] == 'c') {
SB_AppendChar (S, (char)T->IVal);
} else if (P[1] == 'i') {
char Buf[64];
snprintf (Buf, sizeof (Buf), "%ld", T->IVal);
SB_AppendStr (S, Buf);
} else {
SB_Append (S, &T->SVal);
}
} else {
/* No more replacements found, append remainder */
SB_AppendStr (S, Desc + Start);
break;
}
}
/* Zero-terminate the buffer and return it */
SB_Terminate (S);
return S;
}