mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 00:14:25 +00:00
570 lines
15 KiB
C
570 lines
15 KiB
C
/********************************************************/
|
|
/* */
|
|
/* Usual filename: SIDFUN.C */
|
|
/* Remarks: Functions specific to SID68K */
|
|
/* Author: Timothy M. Benson */
|
|
/* Control: 19 MAY 83 17:36 (TMB) */
|
|
/* */
|
|
/********************************************************/
|
|
|
|
#include "lgcdef.h"
|
|
#include "siddef.h"
|
|
#include "ddtinc.h"
|
|
#include "stdio.h"
|
|
#include "bdosfunc.h"
|
|
#include "disas.h"
|
|
|
|
/************************************************/
|
|
/* Load and initialize symbol table, returning */
|
|
/* int sized index to last valid symbol aut */
|
|
/* negative error code. */
|
|
/************************************************/
|
|
|
|
simz(fcbp,hwer)
|
|
struct fcb *fcbp;
|
|
long hwer;
|
|
{
|
|
/**temp** Next line to be deleted eventually */
|
|
extern struct lmhedr klops;
|
|
|
|
extern struct lmhedr *caput;
|
|
extern int nomo;
|
|
U32 rano(); /* Returns second argument incremented by one */
|
|
struct asymbl *icon;
|
|
int goods; /* # symbol bytes in first symbol record */
|
|
int i;
|
|
int irate; /* Zero iff no input errors */
|
|
int junk; /* # bytes preceding symbols in first symbol record */
|
|
register long kount; /* Scratch loop counter */
|
|
char *oint; /* Scratch byte pointer */
|
|
U32 randy; /* Current random record number */
|
|
int zulu; /* Index to last symbol in current table */
|
|
|
|
/**temp** Next line to be replaced eventually by dynamic allocation */
|
|
caput = &klops;
|
|
|
|
randy = 0;
|
|
BDOS(SETDMA,caput);
|
|
rano(fcbp,&randy);
|
|
irate = BDOS(OPEN,fcbp) AND 0xFFFFFFFCL;
|
|
irate ORWITH (int) BDOS(READRND,fcbp);
|
|
caput AT tceps = hwer;
|
|
If caput AT lmkind EQ CONTIG then BEGIN
|
|
caput AT dceps = caput AT tceps;
|
|
caput AT dceps INCBY caput AT lmtlen;
|
|
caput AT bceps = caput AT dceps;
|
|
caput AT bceps INCBY caput AT lmdlen;
|
|
randy = 28; /* # bytes in contiguous header */
|
|
END
|
|
otherwise randy = 36; /* # bytes in noncontiguous header */
|
|
If NOT(caput AT symlen) then BEGIN
|
|
stout("No symbols\n");
|
|
/**temp** Need to allot space for added symbols */
|
|
/**temp** Need to deallocate extra space */
|
|
nomo = -1;
|
|
return(-1);
|
|
END
|
|
randy INCBY caput AT lmtlen + caput AT lmdlen;
|
|
/* I.e., compute # bytes preceding symbols */
|
|
junk = randy % 128;
|
|
goods = 128 - junk;
|
|
randy /= 128;
|
|
oint = caput AT sump;
|
|
icon = oint; /* Save addr of symbol table. */
|
|
BDOS(SETDMA,icon);
|
|
randy = rano(fcbp,&randy);
|
|
irate ORWITH (int) BDOS(READRND,fcbp);
|
|
/* Move wanted info to head of array. */
|
|
for (i = 0; i LT goods; i++) *oint++ = *(oint + junk);
|
|
/* Now oint points to icon + goods. */
|
|
zulu = HMSYMS * sizeof(struct asymbl);
|
|
If caput AT symlen GT zulu then BEGIN
|
|
kount = (zulu - goods) / 128;
|
|
If (zulu - goods) % 128 then ++kount;
|
|
zulu = HMSYMS - 1;
|
|
END
|
|
otherwise BEGIN
|
|
kount = (caput AT symlen - goods) / 128;
|
|
If (caput AT symlen - goods) % 128 then ++kount;
|
|
zulu = caput AT symlen / sizeof(struct asymbl) - 1;
|
|
END
|
|
|
|
/**temp** May want to compute end of symbol table here */
|
|
/**temp** and/or deallocate unused storage */
|
|
|
|
while (kount-- GT 0) BEGIN
|
|
BDOS(SETDMA,oint);
|
|
randy = rano(fcbp,&randy);
|
|
If (i = BDOS(READRND,fcbp)) then
|
|
If i EQ 1 or i EQ 4 then kount = 0;
|
|
else irate ORWITH i;
|
|
oint INCBY 128;
|
|
END
|
|
If irate then BEGIN
|
|
stout("Symbol table disaster\n");
|
|
return(-1);
|
|
END
|
|
|
|
|
|
/**temp** When symbol table allocated dynamically, make */
|
|
/**temp** sure zulu still reflects subscript of */
|
|
/**temp** last symbol at this point in program */
|
|
|
|
If caput AT lmkind EQ CONTIG then
|
|
for(i = 0; i LE zulu; i++)
|
|
If (icon+i) AT symtyp IS SEGREF then
|
|
(icon+i) AT symval INCBY caput AT tceps;
|
|
|
|
|
|
/**temp** May later need different test for full symbol table */
|
|
If zulu GE HMSYMS - 1 then stout("Symbol table full\n");
|
|
return(zulu);
|
|
}
|
|
|
|
|
|
/************************************************/
|
|
/* Install random record number in fcb and */
|
|
/* return next higher random record number */
|
|
/************************************************/
|
|
|
|
U32 rano(fcbp,rand)
|
|
struct fcb *fcbp;
|
|
union slimy BLOCK
|
|
U32 recno;
|
|
char tail[4];
|
|
UNBLOCK *rand;
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i LE 2; i++)
|
|
fcbp AT r[i] = rand AT tail[i+1];
|
|
return(rand AT recno + 1);
|
|
}
|
|
|
|
deluge(tabula,zulu)
|
|
struct asymbl tabula[];
|
|
register int zulu;
|
|
{
|
|
register int i;
|
|
register int j;
|
|
register char litt;
|
|
register int reply;
|
|
U16 simbl;
|
|
|
|
for(i = 0, reply = 2; i LE zulu and reply; i++) BEGIN
|
|
putchar('\n');
|
|
puthexw(i);
|
|
putchar('(');
|
|
If (simbl = tabula[i].symtyp) IS TREL then putchar('T');
|
|
else If simbl IS DREL then putchar('D');
|
|
else If simbl IS BREL then putchar('B');
|
|
else putchar('A');
|
|
stout(")(");
|
|
If simbl IS GONE then putchar('H');
|
|
otherwise putchar('V');
|
|
stout("): ");
|
|
puthexl(tabula[i].symval);
|
|
stout(" = ");
|
|
/**temp** Call to kobold in next line may need parameters */
|
|
If simbl IS TLONG then kobold();
|
|
otherwise for(j = 0; j LT 8; j++)
|
|
If litt = tabula[i].namae[j] then putchar(litt);
|
|
else putchar(' ');
|
|
If reply EQ 2 then reply = 1;
|
|
otherwise If NOT (i % 10) then reply = pause();
|
|
END
|
|
putchar('\n');
|
|
}
|
|
|
|
kobold()
|
|
{
|
|
/* Will handle printing long symbols here; for now print message */
|
|
stout("** Long COBOL-style symbol **");
|
|
}
|
|
|
|
pause()
|
|
{
|
|
register char mor;
|
|
|
|
stout("\n Continue listing? (y/n)");
|
|
mor = getchar();
|
|
mor = toupper(mor);
|
|
putchar('\n');
|
|
return(mor NE 'N');
|
|
}
|
|
|
|
/****************************************************************/
|
|
/* For a given numerical value, find and print corresponding */
|
|
/* symbols in indicated table, with certain options. Return */
|
|
/* int number of symbols found. */
|
|
/****************************************************************/
|
|
|
|
spell(value,table,scope,class,orient)
|
|
U32 value;
|
|
struct asymbl table[];
|
|
int scope; /* If zero, then find all; otherwise find first. */
|
|
char class; /* 'm' implies only want segment references. */
|
|
char orient; /* 'h' or 'H' horizontal, anything else vertical: */
|
|
/* If 'H' then prefix '.'; if 'h' then append ':'.*/
|
|
{
|
|
extern int omega;
|
|
int hmany; /* Counter for # of symbols with given value */
|
|
register int i;
|
|
char it; /* Hold char while deciding what to do. */
|
|
register int j;
|
|
register U16 simbol; /* Hold symtyp here for inspection. */
|
|
|
|
hmany = 0; /* Alcyon compiler does not allow this */
|
|
/* to be initialized in declaration: */
|
|
/* I protest! */
|
|
for(i = 0; i LE omega; i++) BEGIN
|
|
If table[i].symval NE value then IGNORE;
|
|
simbol = table[i].symtyp;
|
|
If class EQ 'm' and NOT (simbol IS SEGREF)
|
|
then IGNORE;
|
|
/* I.e. ignore e.g. stack references */
|
|
If simbol IS GONE then IGNORE;
|
|
/* I.e. ignore hidden symbol */
|
|
/* Next line is dummy call to routine to handle long symbols */
|
|
If simbol IS TLONG then roam();
|
|
If orient EQ 'H' then putchar('.');
|
|
for(j = 0; j LT 8 and (it = table[i].namae[j]); j++)
|
|
putchar(it);
|
|
If orient NE 'H' then putchar(':');
|
|
If orient EQ 'H' or orient EQ 'h' then putchar(' ');
|
|
otherwise putchar('\n');
|
|
hmany++;
|
|
If scope then break;
|
|
END
|
|
If hmany and orient EQ 'h' then putchar('\n');
|
|
return(hmany);
|
|
}
|
|
|
|
roam()
|
|
{
|
|
/* dummy routine: will later handle symbols longer than 8 chars */
|
|
}
|
|
|
|
/************************************************/
|
|
/* For given string of given length find first */
|
|
/* corresponding symbol table entry, updating */
|
|
/* value and putting subscript at *whence. */
|
|
/* Return int 1 if found, 0 if not found, */
|
|
/* -1 if the bizarre happens, and -2 if an */
|
|
/* attempt is made to utilize a feature not */
|
|
/* yet implemented. */
|
|
/************************************************/
|
|
|
|
indica(leqth,logos,tesoro,phylum,value,whence)
|
|
int leqth;
|
|
char logos[]; /* String containing name */
|
|
struct asymbl tesoro[]; /* Short symbol table */
|
|
char phylum; /* Type of symbol wanted */
|
|
U32 *value; /* Place to stick value if and when found */
|
|
int *whence; /* Place to stick subscript to symbol table */
|
|
{
|
|
extern int omega;
|
|
register int i; /* To sweep symbol table */
|
|
register int j; /* To sweep string */
|
|
register short match; /* 1 iff strings equivalent */
|
|
register char nxch; /* Next char in logos */
|
|
U16 symbol; /* Type of last symbol considered */
|
|
|
|
for(i = 0; i LE omega; i++) BEGIN
|
|
symbol = tesoro[i].symtyp;
|
|
switch(phylum) BLOCK
|
|
case 'M': /* Address value wanted */
|
|
If NOT (symbol IS SEGREF) then IGNORE;
|
|
break;
|
|
case 'A': /* Nonaddress numerical value wanted */
|
|
If symbol IS SEGREF then IGNORE;
|
|
break;
|
|
case 'B':
|
|
break; /* Accept any kind of symbol */
|
|
default:
|
|
return(-1); /* This shouldn't happen */
|
|
UNBLOCK
|
|
If symbol IS GONE then IGNORE;
|
|
/**temp** Call in next statement will require parameters. */
|
|
/**temp** For now just returns (int) -2. */
|
|
If symbol IS TLONG then return(trek());
|
|
for(j = 0, match = 1; j LT 8 and match; j++) BLOCK
|
|
If j LT leqth then nxch = logos[j];
|
|
otherwise nxch = '\0';
|
|
If nxch NE toupper(tesoro[i].namae[j]) then match = 0;
|
|
UNBLOCK
|
|
If match then BLOCK
|
|
*whence = i;
|
|
*value = tesoro[i].symval;
|
|
return(1);
|
|
UNBLOCK
|
|
END
|
|
return(0);
|
|
}
|
|
|
|
trek()
|
|
{
|
|
/* dummy routine: will later handle symbols longer than 8 chars */
|
|
|
|
return(-2);
|
|
|
|
}
|
|
|
|
/****************************************/
|
|
/* K command: Play with symbol table */
|
|
/****************************************/
|
|
|
|
koax(cx)
|
|
char *cx;
|
|
{
|
|
extern struct lmhedr *caput;
|
|
extern int omega;
|
|
extern int main();
|
|
struct asymbl *galaxy;
|
|
int seqno; /* Subscript to symbol table */
|
|
long spot; /* Symbol value input */
|
|
char task;
|
|
char uppr; /* For entering new name */
|
|
|
|
galaxy = caput AT sump;
|
|
If nomore(cx) then BEGIN
|
|
stout("SID begins at: ");
|
|
puthexl(main);
|
|
putchar('\n');
|
|
stout("Symbol table at: ");
|
|
puthexl(galaxy);
|
|
putchar('\n');
|
|
If omega LT 0 then BLOCK
|
|
stout("No symbols");
|
|
If caput then begin
|
|
stout("; file header at: ");
|
|
puthexl(caput);
|
|
end
|
|
putchar('\n');
|
|
UNBLOCK
|
|
return;
|
|
END
|
|
deblank(&cx);
|
|
task = *++cx;
|
|
switch(task) BEGIN
|
|
case 'A':
|
|
/* Add a symbol; e.g. KAname,value,type */
|
|
/* where name is converted to upper case and */
|
|
/* comma after it is obligatory, as is value. */
|
|
If nomore(cx) then BLOCK bad(); return; UNBLOCK
|
|
otherwise BLOCK
|
|
If omega GE HMSYMS then begin
|
|
stout("\nSymbol table full\n");
|
|
return;
|
|
end
|
|
deblank(&cx);
|
|
uppr = *++cx;
|
|
If uppr EQ ',' then begin bad(); return; end
|
|
++omega;
|
|
for(seqno = 0; seqno LT 8; seqno++) begin
|
|
(galaxy+omega) AT namae[seqno] = uppr;
|
|
If *++cx NE ',' and uppr then uppr = *cx;
|
|
else uppr = '\0';
|
|
end
|
|
cx--;
|
|
If NOT (getsep(&cx) and gethex(&cx,&spot)) then begin
|
|
omega--;
|
|
bad();
|
|
return;
|
|
end
|
|
(galaxy+omega) AT symval = spot;
|
|
If getsep(&cx) and gethex(&cx,&spot) then
|
|
seqno = (int)spot;
|
|
else seqno = 0xA700; /* Default symbol type */
|
|
If NOT nomore(cx) then begin
|
|
omega--;
|
|
bad();
|
|
return;
|
|
end
|
|
(galaxy+omega) AT symtyp = seqno;
|
|
UNBLOCK
|
|
break;
|
|
case 'H': /* Hide symbols */
|
|
/* KH hide symbol most recently sought by name*/
|
|
/* KHvalue hide first symbol with given value */
|
|
/* KH*value hide symbol with sequence number equal */
|
|
/* to given value, if in range */
|
|
seqno = findsn(cx,omega,galaxy);
|
|
If seqno LT 0 then begin bad(); return; end
|
|
otherwise (galaxy+seqno) AT symtyp ORWITH GONE;
|
|
break;
|
|
case 'R': /* Recover hidden symbols */
|
|
/* KR recover all hidden symbols */
|
|
/* KRvalue recover first symbol with given value */
|
|
/* KR*value recover symbol with sequence number */
|
|
/* equal to given value, if in range */
|
|
If nomore(cx) then
|
|
for(seqno = 0; seqno LE omega; seqno++)
|
|
(galaxy+seqno) AT symtyp ANDWITH ~GONE;
|
|
otherwise BLOCK
|
|
seqno = findsn(cx,omega,galaxy);
|
|
If seqno LT 0 then begin bad(); return; end
|
|
else (galaxy+seqno) AT symtyp ANDWITH ~GONE;
|
|
UNBLOCK
|
|
break;
|
|
default:
|
|
bad();
|
|
return;
|
|
break;
|
|
END
|
|
putchar('\n');
|
|
}
|
|
|
|
/************************************************/
|
|
/* Find serial number of symbol entry, parsing */
|
|
/* rest of command line */
|
|
/************************************************/
|
|
|
|
findsn(spear,zedd,arcade)
|
|
char *spear; /* Scanner for command line */
|
|
int zedd; /* Highest symbol table subscript */
|
|
struct asymbl *arcade; /* Addr of symbol table */
|
|
{
|
|
extern int nomo; /* Last entry sought by name */
|
|
int ix; /* To sweep symbol table */
|
|
int script; /* Int subscript to be returned */
|
|
long werth; /* Numerical value of symbol */
|
|
|
|
script = -1; /* Preset to illegal value */
|
|
If nomore(spear) then script = nomo;
|
|
otherwise BLOCK
|
|
deblank(&spear);
|
|
If *(spear+1) EQ '*' then begin
|
|
++spear;
|
|
If gethex(&spear,&werth) and nomore(spear) then
|
|
script = (int) werth;
|
|
end
|
|
else If gethex(&spear,&werth) and nomore(spear)
|
|
then for(ix = 0; ix LE zedd and script LT 0; ix++)
|
|
If (arcade+ix) AT symval EQ werth then script = ix;
|
|
UNBLOCK
|
|
If script GT zedd then script = -1;
|
|
return(script);
|
|
}
|
|
|
|
passpt(pcx)
|
|
char *pcx;
|
|
{
|
|
extern U16 pkawnt[HMPPTS];
|
|
extern U16 *plocus[HMPPTS];
|
|
extern U16 ancien[HMPPTS];
|
|
extern int minus;
|
|
extern int omega;
|
|
extern int scope;
|
|
extern struct lmhedr *caput;
|
|
int jp;
|
|
int reply; /* Operator's response */
|
|
int plain; /* plain iff no tail */
|
|
char *nupt; /* Value of new pass point */
|
|
/* N.b.: "char" required so bitwise "&" */
|
|
/* will work properly. */
|
|
long cntdn; /* New pass count (initially long) */
|
|
|
|
cntdn = 1; /* Set to default pass count */
|
|
If NOT (plain = nomore(pcx)) then BEGIN
|
|
If NOT gethex(&pcx,&nupt) then goto chide;
|
|
/* Warning: The following bitwise "&" statement */
|
|
/* requires nupt to be declared "char" pointer.*/
|
|
If nupt & 1 then BLOCK
|
|
stout("\nNo change--Address must be even!\n");
|
|
return;
|
|
UNBLOCK
|
|
If getsep(&pcx) then If NOT gethex(&pcx,&cntdn)
|
|
or minus then goto chide;
|
|
If NOT nomore(pcx) then goto chide;
|
|
END
|
|
If NOT cntdn then goto chide;
|
|
If minus then BEGIN
|
|
If plain then zappas();
|
|
else BLOCK
|
|
for (jp = 0; jp LT HMPPTS; jp++)
|
|
If pkawnt[jp] and plocus[jp] EQ nupt then begin
|
|
pkawnt[jp] = 0;
|
|
minus = 0;
|
|
end
|
|
If minus then goto chide;
|
|
UNBLOCK
|
|
END
|
|
otherwise BEGIN
|
|
If plain then BLOCK
|
|
for(jp=0,reply=1;jp LT HMPPTS and reply;jp++) begin
|
|
If pkawnt[jp] then {
|
|
If ++minus GT 16 and jp LT HMPPTS then BEGIN
|
|
reply = pause();
|
|
minus = 0;
|
|
END
|
|
If reply then BEGIN
|
|
putchar('\n');
|
|
puthexw(pkawnt[jp]);
|
|
stout(" ");
|
|
puthexl(plocus[jp]);
|
|
stout(" ");
|
|
If omega GE 0 then
|
|
spell((U32) plocus[jp],caput AT sump
|
|
,scope,'m','H');
|
|
END
|
|
}
|
|
end
|
|
putchar('\n');
|
|
UNBLOCK
|
|
else BLOCK
|
|
for (jp = 0; jp LT HMPPTS; jp++)
|
|
If pkawnt[jp] and plocus[jp] EQ nupt then begin
|
|
If pkawnt[jp] EQ cntdn then stout("\nAlready set\n");
|
|
otherwise pkawnt[jp] = cntdn;
|
|
return;
|
|
end
|
|
minus = 1;
|
|
for (jp = 0; jp LT HMPPTS; jp++)
|
|
If NOT pkawnt[jp] then begin
|
|
pkawnt[jp] = (U16) cntdn;
|
|
plocus[jp] = nupt;
|
|
jp = HMPPTS;
|
|
minus = 0;
|
|
end
|
|
If minus then begin
|
|
stout("\nToo many pass points--limit is: ");
|
|
SAYMAX
|
|
end
|
|
UNBLOCK
|
|
END
|
|
return;
|
|
chide:
|
|
bad();
|
|
}
|
|
|
|
qotbyt(nnnn)
|
|
long nnnn;
|
|
{
|
|
If nnnn LT 0x20 or nnnn GT 0x7E then return(0);
|
|
putchar('\'');
|
|
BDOS(CONOUT,nnnn);
|
|
putchar('\'');
|
|
return(1);
|
|
}
|
|
|
|
vecina(cxp,sought)
|
|
char **cxp;
|
|
char sought;
|
|
{
|
|
/* Check if next char in command is a specified char, advancing */
|
|
/* pointer if it is. */
|
|
++*cxp;
|
|
If **cxp EQ sought then return(1);
|
|
--*cxp;
|
|
return(0);
|
|
}
|
|
|
|
zappas()
|
|
{
|
|
extern U16 pkawnt[HMPPTS];
|
|
int jz;
|
|
|
|
for (jz = 0; jz LT HMPPTS; jz++) pkawnt[jz] = 0;
|
|
}
|