2018-02-13 23:16:23 +00:00
|
|
|
/*************************************
|
|
|
|
* C02 Include File Parsing Routines *
|
|
|
|
*************************************/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
#include "common.h"
|
|
|
|
#include "files.h"
|
|
|
|
#include "asm.h"
|
|
|
|
#include "parse.h"
|
|
|
|
#include "label.h"
|
|
|
|
#include "vars.h"
|
|
|
|
#include "stmnt.h"
|
|
|
|
#include "dclrtn.h"
|
|
|
|
#include "include.h"
|
|
|
|
|
|
|
|
/* Read next include file name from Source File *
|
|
|
|
* Sets: incnam - the include file name */
|
2018-03-04 03:32:39 +00:00
|
|
|
void pincnm(void) {
|
2021-12-19 00:28:47 +00:00
|
|
|
DEBUG("include.pincnm: Parsing include file name", 0)
|
2018-02-13 23:16:23 +00:00
|
|
|
char dlmtr;
|
|
|
|
int inclen = 0;
|
2019-03-29 23:09:41 +00:00
|
|
|
int sublen[SUBMAX];
|
2018-02-13 23:16:23 +00:00
|
|
|
skpspc();
|
|
|
|
dlmtr = getnxt();
|
2020-09-24 16:12:39 +00:00
|
|
|
DETAIL(" with delimiter '%c'\n", dlmtr)
|
2018-02-13 23:16:23 +00:00
|
|
|
if (dlmtr == '<') {
|
|
|
|
strcpy(incnam, incdir);
|
|
|
|
inclen = strlen(incnam);
|
2019-03-29 23:09:41 +00:00
|
|
|
if (subcnt) {
|
|
|
|
for (subidx = 0; subidx < subcnt; subidx++) {
|
|
|
|
sublen[subidx] = 0;
|
|
|
|
strcpy(subnam[subidx], incdir);
|
|
|
|
strcat(subnam[subidx], subdir[subidx]);
|
|
|
|
sublen[subidx] = strlen(subnam[subidx]);
|
|
|
|
subnam[subidx][sublen[subidx]++] = '/';
|
|
|
|
}
|
|
|
|
}
|
2019-11-14 16:13:45 +00:00
|
|
|
dlmtr = '>';
|
2018-02-13 23:16:23 +00:00
|
|
|
}
|
|
|
|
else if (dlmtr != '"')
|
2018-03-04 18:38:40 +00:00
|
|
|
ERROR("Unexpected character '%c' after include\n", dlmtr, EXIT_FAILURE)
|
2018-02-13 23:16:23 +00:00
|
|
|
while (!match(dlmtr))
|
|
|
|
{
|
|
|
|
incnam[inclen++] = nxtchr;
|
2019-03-29 23:09:41 +00:00
|
|
|
for (int subidx = 0; subidx < subcnt; subidx++) {
|
|
|
|
if (sublen[subidx]) subnam[subidx][sublen[subidx]++] = nxtchr;
|
|
|
|
}
|
2018-02-13 23:16:23 +00:00
|
|
|
skpchr();
|
|
|
|
}
|
|
|
|
skpchr(); //skip end dlmtr
|
|
|
|
incnam[inclen] = 0;
|
2021-12-19 00:28:47 +00:00
|
|
|
DEBUG("include.pincnm: Set INCNAM to '%s'\n", incnam);
|
2019-03-29 23:09:41 +00:00
|
|
|
for (int subidx = 0; subidx < subcnt; subidx++) {
|
|
|
|
subnam[subidx][sublen[subidx]] = 0;
|
2021-12-19 00:28:47 +00:00
|
|
|
DEBUG("include.pincnm: Set SUBNAM[%d] ", subidx)
|
|
|
|
DETAIL("to '%s'\n", subnam[subidx]);
|
2019-03-29 23:09:41 +00:00
|
|
|
}
|
2018-02-13 23:16:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Process assembly language include file */
|
2019-03-29 23:09:41 +00:00
|
|
|
void incasm(int chksub) {
|
|
|
|
opninc(chksub);
|
2018-02-13 23:16:23 +00:00
|
|
|
setcmt("======== Assembler File ");
|
|
|
|
addcmt(incnam);
|
|
|
|
addcmt(" =======");
|
|
|
|
cmtlin();
|
|
|
|
while (fgets(line, sizeof line, incfil) != NULL) {
|
2021-12-19 00:28:47 +00:00
|
|
|
DEBUG("include.incasm: Writing line: %s", line)
|
2018-02-13 23:16:23 +00:00
|
|
|
fputs(line, outfil);
|
|
|
|
}
|
|
|
|
setcmt("==========================================");
|
|
|
|
cmtlin();
|
|
|
|
clsinc();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Process define directive */
|
2018-03-04 03:32:39 +00:00
|
|
|
void pdefin(void) {
|
2021-12-19 00:28:47 +00:00
|
|
|
DEBUG("include.pdefin: Processing DEFINE directive\n", 0)
|
2018-08-03 15:22:12 +00:00
|
|
|
getwrd(); //Get constant name
|
|
|
|
strncpy(defnam, word, CONLEN);
|
|
|
|
addcon(prsbyt()); //Get Value and Add Constant
|
2018-02-27 04:21:01 +00:00
|
|
|
}
|
|
|
|
|
2018-02-13 23:16:23 +00:00
|
|
|
/* Parse ASCII Subdirective */
|
2018-03-04 03:32:39 +00:00
|
|
|
void pascii(void) {
|
2019-10-28 02:44:13 +00:00
|
|
|
getwrd(); //Get Subdirective Argument
|
2021-12-19 00:28:47 +00:00
|
|
|
DEBUG("include.pascii: Parsing subdirective '%s'\n", word)
|
2018-02-15 04:40:57 +00:00
|
|
|
if (wordis("INVERT"))
|
2018-02-13 23:16:23 +00:00
|
|
|
invasc = TRUE;
|
2018-08-14 18:51:04 +00:00
|
|
|
else if (wordis("HIGH"))
|
2018-02-15 04:40:57 +00:00
|
|
|
mskasc = TRUE;
|
2018-03-04 19:12:42 +00:00
|
|
|
else
|
|
|
|
ERROR("Unrecognized option '%s'\n", word, EXIT_FAILURE)
|
2018-02-13 23:16:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Parse Origin Subdirective */
|
2018-03-04 03:32:39 +00:00
|
|
|
void porign(void) {
|
2018-02-13 23:16:23 +00:00
|
|
|
prsnum(0xFFFF); //Get Origin Address
|
|
|
|
asmlin(ORGOP, value); //Emit Origin Instruction
|
2021-12-19 00:28:47 +00:00
|
|
|
DEBUG("include.poirgn: Set origin to %s\n", value)
|
2018-02-13 23:16:23 +00:00
|
|
|
}
|
|
|
|
|
2018-07-24 04:30:00 +00:00
|
|
|
/* Parse Padding Subdirective */
|
|
|
|
void ppddng(void) {
|
|
|
|
padcnt = prsnum(0xFF); //Get Number of Padding Bytes
|
2021-12-19 00:28:47 +00:00
|
|
|
DEBUG("include.ppddng: Set padding to %d\n", padcnt)
|
2018-07-24 04:30:00 +00:00
|
|
|
}
|
|
|
|
|
2018-08-16 20:26:44 +00:00
|
|
|
/* Parse RamBase Subdirective */
|
|
|
|
void prambs(void) {
|
|
|
|
rambas = prsnum(0xFFFF); //Set Ram Base Address to Literal
|
2021-12-19 00:28:47 +00:00
|
|
|
DEBUG("include.prambs: Set ram base address to %d\n", rambas)
|
2018-08-16 20:26:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Parse WriteBase Subdirective */
|
|
|
|
void pwrtbs(void) {
|
|
|
|
if (!rambas) ERROR("RAM Base must be set prior to Write Base\n", 0, EXIT_FAILURE);
|
|
|
|
wrtbas = prsnum(0xFFFF); //Set Ram Base Address to Literal
|
2021-12-19 00:28:47 +00:00
|
|
|
DEBUG("include.pwrtbs: Set write base address to %d ", wrtbas)
|
2018-08-16 20:26:44 +00:00
|
|
|
if (rambas && wrtbas) sprintf(wrtofs, "%+d", wrtbas - rambas);
|
|
|
|
else wrtofs[0] = 0;
|
|
|
|
DETAIL("and write offset to '%s'\n", wrtofs)
|
|
|
|
}
|
|
|
|
|
2018-02-13 23:16:23 +00:00
|
|
|
/* Parse Zeropage Subdirective */
|
2018-08-16 20:26:44 +00:00
|
|
|
void pzropg(void) {
|
2020-10-22 16:33:26 +00:00
|
|
|
zpgbgn = prsnum(0xFF); //Set Zero Page Address to Literal
|
|
|
|
zpgend = prsnum(0xFF); //Set Zero Page Address to Literal
|
|
|
|
zpaddr = zpgbgn;
|
2021-12-19 00:28:47 +00:00
|
|
|
DEBUG("include.pzropg: Set free zero page to %d ", zpgbgn)
|
2020-10-22 16:33:26 +00:00
|
|
|
DETAIL("through %d ", zpgend)
|
|
|
|
DETAIL("and zero page address to %d\n", zpaddr)
|
2018-02-13 23:16:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Process Vartable Subdirective */
|
2018-03-04 03:32:39 +00:00
|
|
|
void pvrtbl(void) {
|
2018-08-03 15:22:12 +00:00
|
|
|
if (vrwrtn) ERROR("Variable table already written", 0, EXIT_FAILURE)
|
2019-05-05 22:37:19 +00:00
|
|
|
wvrtbl(); //Write Variable Table
|
2018-02-13 23:16:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Parse Pragma Directive */
|
2018-03-04 03:32:39 +00:00
|
|
|
void pprgma(void) {
|
2018-02-13 23:16:23 +00:00
|
|
|
getwrd(); //Get Pragma Subdirective
|
2021-12-19 00:28:47 +00:00
|
|
|
DEBUG("include.pprgma: Parsing pragma directive '%s'\n", word)
|
2018-02-13 23:16:23 +00:00
|
|
|
if (wordis("ASCII"))
|
|
|
|
pascii(); //Parse Ascii
|
|
|
|
else if (wordis("ORIGIN"))
|
|
|
|
porign(); //Parse Origin
|
2018-07-24 04:30:00 +00:00
|
|
|
else if (wordis("PADDING"))
|
2019-11-14 16:13:45 +00:00
|
|
|
ppddng(); //Parse Padding
|
2018-08-16 20:26:44 +00:00
|
|
|
else if (wordis("RAMBASE"))
|
|
|
|
prambs(); //Parse RamBase
|
2018-02-13 23:16:23 +00:00
|
|
|
else if (wordis("VARTABLE"))
|
2018-08-16 20:26:44 +00:00
|
|
|
pvrtbl(); //Parse VarTable
|
|
|
|
else if (wordis("WRITEBASE"))
|
|
|
|
pwrtbs(); //Parse RamBase
|
2018-02-13 23:16:23 +00:00
|
|
|
else if (wordis("ZEROPAGE"))
|
2018-08-16 20:26:44 +00:00
|
|
|
pzropg(); //Parse ZeroPage
|
2018-02-13 23:16:23 +00:00
|
|
|
else
|
2018-03-04 18:38:40 +00:00
|
|
|
ERROR("Illegal pragma subdirective '%s'\n", word, EXIT_FAILURE)
|
2018-08-16 20:26:44 +00:00
|
|
|
cmtlin(); //Write Comment Line
|
2018-02-13 23:16:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Process Include File Directive */
|
2018-03-04 03:32:39 +00:00
|
|
|
void pincdr(void) {
|
2018-02-13 23:16:23 +00:00
|
|
|
skpchr(); //skip '#'
|
|
|
|
getwrd(); //read directive into word
|
2021-12-19 00:28:47 +00:00
|
|
|
DEBUG("include.pincdr: Processing include file directive '%s'\n", word)
|
2018-02-13 23:16:23 +00:00
|
|
|
if (wordis("DEFINE"))
|
|
|
|
pdefin();
|
2018-02-27 04:21:01 +00:00
|
|
|
else if (wordis("PRAGMA"))
|
2018-02-13 23:16:23 +00:00
|
|
|
pprgma();
|
2018-03-04 19:12:42 +00:00
|
|
|
else
|
|
|
|
ERROR("Unrecognized directive '%s'\n", word, EXIT_FAILURE)
|
2018-02-13 23:16:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Parse Header Word */
|
2018-03-04 03:32:39 +00:00
|
|
|
void phdwrd(void) {
|
2018-02-13 23:16:23 +00:00
|
|
|
getwrd();
|
2019-05-19 02:24:30 +00:00
|
|
|
if (match(':')) prslab();
|
2019-11-15 04:57:49 +00:00
|
|
|
else if (!pmodfr() && !ptype(MTNONE))
|
2018-03-04 19:12:42 +00:00
|
|
|
ERROR("Unexpected word '%s' in header\n", word, EXIT_FAILURE)
|
2018-02-13 23:16:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Save Source File Information */
|
2018-03-04 03:32:39 +00:00
|
|
|
void savsrc(void) {
|
2018-02-13 23:16:23 +00:00
|
|
|
savchr = nxtchr;
|
|
|
|
savcol = curcol;
|
|
|
|
savlin = curlin;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Set Include File Information */
|
2018-03-04 03:32:39 +00:00
|
|
|
void setinc(void) {
|
2018-02-13 23:16:23 +00:00
|
|
|
curcol = 0;
|
|
|
|
curlin = 0;
|
|
|
|
inpfil = incfil;
|
|
|
|
strcpy(inpnam, incnam);
|
|
|
|
alcvar = FALSE;
|
|
|
|
}
|
|
|
|
|
2018-02-17 19:50:43 +00:00
|
|
|
/* Set Include File Name */
|
|
|
|
void setinm(char* filext) {
|
|
|
|
strcpy(incnam, incdir);
|
|
|
|
strcat(incnam, hdrnam);
|
|
|
|
strcat(incnam, filext);
|
|
|
|
}
|
|
|
|
|
2018-03-03 18:49:34 +00:00
|
|
|
/* Set Input to Source File */
|
2018-03-04 03:32:39 +00:00
|
|
|
void setsrc(void) {
|
2018-02-17 19:50:43 +00:00
|
|
|
inpfil = srcfil;
|
|
|
|
strcpy(inpnam, srcnam);
|
|
|
|
}
|
|
|
|
|
2018-02-13 23:16:23 +00:00
|
|
|
/* Restore Source File Pointer*/
|
2018-03-04 03:32:39 +00:00
|
|
|
void rstsrc(void) {
|
2018-02-13 23:16:23 +00:00
|
|
|
nxtchr = savchr;
|
|
|
|
nxtupc = toupper(nxtchr);
|
|
|
|
curcol = savcol;
|
|
|
|
curlin = savlin;
|
2018-02-17 19:50:43 +00:00
|
|
|
setsrc();
|
2018-02-13 23:16:23 +00:00
|
|
|
alcvar = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Process header include file */
|
2019-03-29 23:09:41 +00:00
|
|
|
void inchdr(int chksub) {
|
2018-02-13 23:16:23 +00:00
|
|
|
savsrc(); //Save Source File Information
|
2019-03-29 23:09:41 +00:00
|
|
|
opninc(chksub); //Open Include File
|
2018-02-13 23:16:23 +00:00
|
|
|
setinc(); //Set Include File Information
|
|
|
|
skpchr();
|
|
|
|
while (TRUE)
|
|
|
|
{
|
|
|
|
skpspc();
|
|
|
|
if (match(EOF)) break;
|
2021-12-19 00:28:47 +00:00
|
|
|
DEBUG("include.inchdr: Checking next character '%c'\n", nxtchr)
|
2018-02-13 23:16:23 +00:00
|
|
|
if (match('#'))
|
|
|
|
pincdr();
|
|
|
|
else if (match('/'))
|
2019-05-05 22:10:26 +00:00
|
|
|
skpcmt(TRUE);
|
2018-02-13 23:16:23 +00:00
|
|
|
else if (isalph())
|
|
|
|
phdwrd();
|
|
|
|
else {
|
2018-03-04 19:12:42 +00:00
|
|
|
ERROR("Unexpected character '%c'\n", nxtchr, EXIT_FAILURE)
|
2018-02-13 23:16:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
clsinc();
|
|
|
|
rstsrc();
|
|
|
|
nxtchr = savchr;
|
|
|
|
}
|
|
|
|
|
2018-02-17 19:50:43 +00:00
|
|
|
/* Process Header File specified on Command Line */
|
2018-03-04 03:32:39 +00:00
|
|
|
void phdrfl(void) {
|
2018-02-17 19:50:43 +00:00
|
|
|
if (hdrnam[0] == 0) return;
|
2021-12-19 00:28:47 +00:00
|
|
|
DEBUG("include.phdrfl: Processing Header '%s'\n", hdrnam)
|
2018-02-17 19:50:43 +00:00
|
|
|
setinm(".h02");
|
2019-03-29 23:09:41 +00:00
|
|
|
inchdr(TRUE);
|
2018-02-17 19:50:43 +00:00
|
|
|
setinm(".a02");
|
2019-03-29 23:09:41 +00:00
|
|
|
incasm(FALSE);
|
2018-02-17 19:50:43 +00:00
|
|
|
}
|
|
|
|
|
2018-02-13 23:16:23 +00:00
|
|
|
/* Process include file */
|
2018-03-04 03:32:39 +00:00
|
|
|
void pincfl(void) {
|
2018-02-13 23:16:23 +00:00
|
|
|
pincnm(); //Parse Include File Name
|
2021-12-19 00:28:47 +00:00
|
|
|
DEBUG("include.pincfl: Processing include file '%s'\n", incnam)
|
2018-02-13 23:16:23 +00:00
|
|
|
char *dot = strrchr(incnam, '.'); //find extension
|
|
|
|
if (dot == NULL) {
|
2018-03-04 19:12:42 +00:00
|
|
|
ERROR("Invalid include file name '%sn", incnam, EXIT_FAILURE)
|
2018-02-13 23:16:23 +00:00
|
|
|
}
|
|
|
|
if (strcmp(dot, ".a02") == 0)
|
2019-03-29 23:09:41 +00:00
|
|
|
incasm(TRUE);
|
2018-02-13 23:16:23 +00:00
|
|
|
if (strcmp(dot, ".asm") == 0)
|
2019-03-29 23:09:41 +00:00
|
|
|
incasm(TRUE);
|
2018-02-13 23:16:23 +00:00
|
|
|
else if (strcmp(dot, ".h02") == 0) {
|
2019-03-29 23:09:41 +00:00
|
|
|
inchdr(TRUE); //Process Header File
|
2018-09-09 20:10:21 +00:00
|
|
|
dot = strrchr(incnam, '.'); //find extension
|
2018-02-13 23:16:23 +00:00
|
|
|
strcpy(dot, ".a02");
|
2021-12-19 00:28:47 +00:00
|
|
|
DEBUG("include.pincfl: INCNAM set to '%s'\n", incnam)
|
2019-03-29 23:09:41 +00:00
|
|
|
incasm(FALSE); //Process Assembly File with Same Name
|
2018-02-13 23:16:23 +00:00
|
|
|
}
|
|
|
|
else {
|
2018-03-04 19:12:42 +00:00
|
|
|
ERROR("Unrecognized include file extension '%s'\n'", dot, EXIT_FAILURE)
|
2018-02-13 23:16:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-07 17:32:08 +00:00
|
|
|
/* Print Constant Table to Log File */
|
|
|
|
void logcon(void) {
|
2018-02-13 23:16:23 +00:00
|
|
|
int i;
|
2018-03-08 14:39:32 +00:00
|
|
|
fprintf(logfil, "\n%-10s %5s\n", "Constant", "Value");
|
|
|
|
for (i=0; i<concnt; i++) {
|
|
|
|
fprintf(logfil, "%-10s %5d\n", connam[i], conval[i]);
|
2018-02-13 23:16:23 +00:00
|
|
|
}
|
|
|
|
}
|