diff --git a/include/asm/fstack.h b/include/asm/fstack.h index c77dda4c..3d5b909a 100644 --- a/include/asm/fstack.h +++ b/include/asm/fstack.h @@ -41,6 +41,8 @@ extern void fstk_RunRept(ULONG count); FILE * fstk_FindFile(char *); +int fstk_GetLine(void); + extern int yywrap(void); #endif diff --git a/include/asm/symbol.h b/include/asm/symbol.h index 5c2ee729..1099730a 100644 --- a/include/asm/symbol.h +++ b/include/asm/symbol.h @@ -15,7 +15,9 @@ struct sSymbol { struct Section *pSection; ULONG ulMacroSize; char *pMacro; - SLONG(*Callback) (struct sSymbol *); + SLONG(*Callback) (struct sSymbol *); + char tzFileName[_MAX_PATH + 1]; /* File where the symbol was defined. */ + ULONG nFileLine; /* Line where the symbol was defined. */ }; #define SYMF_RELOC 0x001 /* symbol will be reloc'ed during * linking, it's absolute value is diff --git a/include/common.h b/include/common.h new file mode 100644 index 00000000..8c4bd395 --- /dev/null +++ b/include/common.h @@ -0,0 +1,6 @@ +#ifndef RGBDS_COMMON_H +#define RGBDS_COMMON_H + +#define RGBDS_OBJECT_VERSION_STRING "RGB5" + +#endif /* RGBDS_COMMON_H */ diff --git a/include/link/mylink.h b/include/link/mylink.h index 8fc9da1f..36be7ae2 100644 --- a/include/link/mylink.h +++ b/include/link/mylink.h @@ -89,6 +89,9 @@ struct sSymbol { SLONG nSectionID; /* internal to object.c */ struct sSection *pSection; SLONG nOffset; + char *pzObjFileName; /* Object file where the symbol is located. */ + char *pzFileName; /* Source file where the symbol was defined. */ + ULONG nFileLine; /* Line where the symbol was defined. */ }; enum ePatchType { diff --git a/include/link/symbol.h b/include/link/symbol.h index 29fdfdcf..806b12da 100644 --- a/include/link/symbol.h +++ b/include/link/symbol.h @@ -4,7 +4,8 @@ #include "types.h" void sym_Init(void); -void sym_CreateSymbol(char *tzName, SLONG nValue, SLONG nBank); +void sym_CreateSymbol(char *tzName, SLONG nValue, SLONG nBank, + char *tzObjFileName, char *tzFileName, ULONG nFileLine); SLONG sym_GetValue(char *tzName); SLONG sym_GetBank(char *tzName); diff --git a/src/asm/fstack.c b/src/asm/fstack.c index c15c0eb1..7b4edede 100644 --- a/src/asm/fstack.c +++ b/src/asm/fstack.c @@ -42,8 +42,8 @@ extern FILE *dependfile; /* * defines for nCurrentStatus */ -#define STAT_isInclude 0 -#define STAT_isMacro 1 +#define STAT_isInclude 0 /* 'Normal' state as well */ +#define STAT_isMacro 1 #define STAT_isMacroArg 2 #define STAT_isREPTBlock 3 @@ -151,6 +151,37 @@ popcontext(void) return (1); } +int +fstk_GetLine(void) +{ + struct sContext *pLastFile, **ppLastFile; + + switch (nCurrentStatus) { + case STAT_isInclude: + /* This is the normal mode, also used when including a file. */ + return nLineNo; + case STAT_isMacro: + break; /* Peek top file of the stack */ + case STAT_isMacroArg: + return nLineNo; /* ??? */ + case STAT_isREPTBlock: + break; /* Peek top file of the stack */ + } + + if ((pLastFile = pFileStack) != NULL) { + ppLastFile = &pFileStack; + while (pLastFile->pNext) { + ppLastFile = &(pLastFile->pNext); + pLastFile = *ppLastFile; + } + return pLastFile->nLine; + } + + /* This is only reached if the lexer is in REPT or MACRO mode but there + * are no saved contexts with the origin of said REPT or MACRO. */ + fatalerror("fstk_GetLine: Internal error."); +} + int yywrap(void) { diff --git a/src/asm/output.c b/src/asm/output.c index 34501f78..ff0a1a30 100644 --- a/src/asm/output.c +++ b/src/asm/output.c @@ -15,6 +15,7 @@ #include "asm/main.h" #include "asm/rpn.h" #include "asm/fstack.h" +#include "common.h" #include "extern/err.h" void out_SetCurrentSection(struct Section * pSect); @@ -282,6 +283,9 @@ writesymbol(struct sSymbol * pSym, FILE * f) fputc(type, f); if (type != SYM_IMPORT) { + fputstring(pSym->tzFileName, f); + fputlong(pSym->nFileLine, f); + fputlong(sectid, f); fputlong(offset, f); } @@ -501,7 +505,9 @@ out_WriteObject(void) struct PatchSymbol *pSym; struct Section *pSect; - fwrite("RGB4", 1, 4, f); + fwrite(RGBDS_OBJECT_VERSION_STRING, 1, + strlen(RGBDS_OBJECT_VERSION_STRING), f); + fputlong(countsymbols(), f); fputlong(countsections(), f); diff --git a/src/asm/rgbasm.5 b/src/asm/rgbasm.5 index c9469890..047ae5ff 100644 --- a/src/asm/rgbasm.5 +++ b/src/asm/rgbasm.5 @@ -12,7 +12,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd April 17, 2017 +.Dd July 22, 2017 .Dt RGBASM 5 .Os RGBDS Manual .Sh NAME diff --git a/src/asm/symbol.c b/src/asm/symbol.c index 23d59b38..856826db 100644 --- a/src/asm/symbol.c +++ b/src/asm/symbol.c @@ -8,6 +8,7 @@ #include #include "asm/asm.h" +#include "asm/fstack.h" #include "asm/symbol.h" #include "asm/main.h" #include "asm/mymath.h" @@ -109,6 +110,8 @@ createsymbol(char *s) (*ppsym)->pMacro = NULL; (*ppsym)->pSection = NULL; (*ppsym)->Callback = NULL; + strcpy((*ppsym)->tzFileName, tzCurrentFileName); + (*ppsym)->nFileLine = fstk_GetLine(); return (*ppsym); } else { fatalerror("No memory for symbol"); @@ -518,7 +521,8 @@ sym_AddEqu(char *tzSym, SLONG value) if ((nsym = findsymbol(tzSym, NULL)) != NULL) { if (nsym->nType & SYMF_DEFINED) { - yyerror("'%s' already defined", tzSym); + yyerror("'%s' already defined in %s(%d)", + tzSym, nsym->tzFileName, nsym->nFileLine); } } else nsym = createsymbol(tzSym); @@ -550,7 +554,8 @@ sym_AddString(char *tzSym, char *tzValue) if ((nsym = findsymbol(tzSym, NULL)) != NULL) { if (nsym->nType & SYMF_DEFINED) { - yyerror("'%s' already defined", tzSym); + yyerror("'%s' already defined in %s(%d)", + tzSym, nsym->tzFileName, nsym->nFileLine); } } else nsym = createsymbol(tzSym); @@ -653,7 +658,8 @@ sym_AddReloc(char *tzSym) if ((nsym = findsymbol(tzSym, scope)) != NULL) { if (nsym->nType & SYMF_DEFINED) { - yyerror("'%s' already defined", tzSym); + yyerror("'%s' already defined in %s(%d)", + tzSym, nsym->tzFileName, nsym->nFileLine); } } else nsym = createsymbol(tzSym); @@ -782,7 +788,8 @@ sym_AddMacro(char *tzSym) if ((nsym = findsymbol(tzSym, NULL)) != NULL) { if (nsym->nType & SYMF_DEFINED) { - yyerror("'%s' already defined", tzSym); + yyerror("'%s' already defined in %s(%d)", + tzSym, nsym->tzFileName, nsym->nFileLine); } } else nsym = createsymbol(tzSym); diff --git a/src/link/assign.c b/src/link/assign.c index 61481265..35f8759f 100644 --- a/src/link/assign.c +++ b/src/link/assign.c @@ -566,16 +566,21 @@ CreateSymbolTable(void) ((pSect->tSymbols[i]->pSection == pSect) || (pSect->tSymbols[i]->pSection == NULL))) { if (pSect->tSymbols[i]->pSection == NULL) - sym_CreateSymbol(pSect->tSymbols[i]-> - pzName, - pSect->tSymbols[i]-> - nOffset, -1); + sym_CreateSymbol( + pSect->tSymbols[i]->pzName, + pSect->tSymbols[i]->nOffset, + -1, + pSect->tSymbols[i]->pzObjFileName, + pSect->tSymbols[i]->pzFileName, + pSect->tSymbols[i]->nFileLine); else - sym_CreateSymbol(pSect->tSymbols[i]-> - pzName, - pSect->nOrg + - pSect->tSymbols[i]-> - nOffset, pSect->nBank); + sym_CreateSymbol( + pSect->tSymbols[i]->pzName, + pSect->nOrg + pSect->tSymbols[i]->nOffset, + pSect->nBank, + pSect->tSymbols[i]->pzObjFileName, + pSect->tSymbols[i]->pzFileName, + pSect->tSymbols[i]->nFileLine); } } pSect = pSect->pNext; diff --git a/src/link/object.c b/src/link/object.c index 9da981ac..5b2fd8cf 100644 --- a/src/link/object.c +++ b/src/link/object.c @@ -3,11 +3,13 @@ * */ +#include #include #include #include #include +#include "common.h" #include "extern/err.h" #include "link/assign.h" #include "link/mylink.h" @@ -116,7 +118,7 @@ AllocSection(void) */ struct sSymbol * -obj_ReadSymbol(FILE * f) +obj_ReadSymbol(FILE * f, char *tzObjectfile) { struct sSymbol *pSym; @@ -126,7 +128,14 @@ obj_ReadSymbol(FILE * f) } readasciiz(&pSym->pzName, f); - if ((pSym->Type = (enum eSymbolType) fgetc(f)) != SYM_IMPORT) { + pSym->Type = (enum eSymbolType)fgetc(f); + + pSym->pzObjFileName = tzObjectfile; + + if (pSym->Type != SYM_IMPORT) { + readasciiz(&pSym->pzFileName, f); + pSym->nFileLine = readlong(f); + pSym->nSectionID = readlong(f); pSym->nOffset = readlong(f); } @@ -263,7 +272,7 @@ obj_ReadRGBSection(FILE * f) } void -obj_ReadRGB(FILE * pObjfile) +obj_ReadRGB(FILE * pObjfile, char *tzObjectfile) { struct sSection *pFirstSection; SLONG nNumberOfSymbols, nNumberOfSections, i; @@ -280,7 +289,7 @@ obj_ReadRGB(FILE * pObjfile) } for (i = 0; i < nNumberOfSymbols; i += 1) - tSymbols[i] = obj_ReadSymbol(pObjfile); + tSymbols[i] = obj_ReadSymbol(pObjfile, tzObjectfile); } else tSymbols = (struct sSymbol **) & dummymem; @@ -325,21 +334,22 @@ obj_ReadRGB(FILE * pObjfile) void obj_ReadOpenFile(FILE * pObjfile, char *tzObjectfile) { - char tzHeader[8]; + char tzHeader[strlen(RGBDS_OBJECT_VERSION_STRING) + 1]; - fread(tzHeader, sizeof(char), 4, pObjfile); - tzHeader[4] = 0; - if (strncmp(tzHeader, "RGB", 3) == 0) { - switch (tzHeader[3]) { - case '3': - case '4': // V4 supports OAM sections, but is otherwise identical - obj_ReadRGB(pObjfile); - break; - default: - errx(1, "'%s' uses an unsupported object file version (%s). Please reassemble it.", tzObjectfile, tzHeader); - } + fread(tzHeader, sizeof(char), strlen(RGBDS_OBJECT_VERSION_STRING), + pObjfile); + + tzHeader[strlen(RGBDS_OBJECT_VERSION_STRING)] = 0; + + if (strncmp(tzHeader, RGBDS_OBJECT_VERSION_STRING, + strlen(RGBDS_OBJECT_VERSION_STRING)) == 0) { + obj_ReadRGB(pObjfile, tzObjectfile); } else { - errx(1, "'%s' is not a valid object", tzObjectfile); + for (int i = 0; i < strlen(RGBDS_OBJECT_VERSION_STRING); i++) + if (!isprint(tzHeader[i])) + tzHeader[i] = '?'; + errx(1, "%s: Invalid file or object file version [%s]", + tzObjectfile, tzHeader); } } diff --git a/src/link/symbol.c b/src/link/symbol.c index b53cbb67..10e51c49 100644 --- a/src/link/symbol.c +++ b/src/link/symbol.c @@ -12,8 +12,10 @@ struct ISymbol { char *pzName; SLONG nValue; - SLONG nBank; - //-1 = const + SLONG nBank; /* -1 = constant */ + char tzObjFileName[_MAX_PATH + 1]; /* Object file where the symbol was defined. */ + char tzFileName[_MAX_PATH + 1]; /* Source file where the symbol was defined. */ + ULONG nFileLine; /* Line where the symbol was defined. */ struct ISymbol *pNext; }; @@ -76,7 +78,8 @@ sym_GetBank(char *tzName) } void -sym_CreateSymbol(char *tzName, SLONG nValue, SLONG nBank) +sym_CreateSymbol(char *tzName, SLONG nValue, SLONG nBank, char *tzObjFileName, + char *tzFileName, ULONG nFileLine) { if (strcmp(tzName, "@") == 0) return; @@ -92,7 +95,10 @@ sym_CreateSymbol(char *tzName, SLONG nValue, SLONG nBank) if (nBank == -1) return; - errx(1, "Symbol '%s' defined more than once", tzName); + errx(1, "'%s' in both %s : %s(%d) and %s : %s(%d)", + tzName, tzObjFileName, tzFileName, nFileLine, + (*ppSym)->tzObjFileName, + (*ppSym)->tzFileName, (*ppSym)->nFileLine); } } @@ -102,6 +108,11 @@ sym_CreateSymbol(char *tzName, SLONG nValue, SLONG nBank) (*ppSym)->nValue = nValue; (*ppSym)->nBank = nBank; (*ppSym)->pNext = NULL; + strncpy((*ppSym)->tzObjFileName, tzObjFileName, + sizeof((*ppSym)->tzObjFileName)); + strncpy((*ppSym)->tzFileName, tzFileName, + sizeof((*ppSym)->tzFileName)); + (*ppSym)->nFileLine = nFileLine; } } } diff --git a/src/rgbds.5 b/src/rgbds.5 index 781a1eb0..81b87d52 100644 --- a/src/rgbds.5 +++ b/src/rgbds.5 @@ -12,7 +12,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd April 17, 2017 +.Dd July 22, 2017 .Dt RGBDS 5 .Os RGBDS Manual .Sh NAME @@ -42,7 +42,7 @@ is a 0‐terminated string of .Bd -literal ; Header -BYTE ID[4] ; "RGB4" +BYTE ID[4] ; "RGB5" LONG NumberOfSymbols ; The number of symbols used in this file LONG NumberOfSections ; The number of sections used in this file @@ -59,6 +59,10 @@ REPT NumberOfSymbols ; Number of symbols defined in this object file. IF Type != 1 ; If symbol is defined in this object file. + STRING FileName ; File where the symbol is defined. + + LONG LineNum ; Line number in the file where the symbol is defined. + LONG SectionID ; The section number (of this object file) in which ; this symbol is defined.