447 lines
8.3 KiB
C
447 lines
8.3 KiB
C
/* assym.c */
|
|
|
|
/*
|
|
* (C) Copyright 1989-1995
|
|
* All Rights Reserved
|
|
*
|
|
* Alan R. Baldwin
|
|
* 721 Berkeley St.
|
|
* Kent, Ohio 44240
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <setjmp.h>
|
|
#include <string.h>
|
|
#if defined(__APPLE__) && defined(__MACH__)
|
|
#include <sys/types.h>
|
|
#include <sys/malloc.h>
|
|
#else
|
|
#include <malloc.h>
|
|
#endif
|
|
#include "asm.h"
|
|
|
|
/*)Module assym.c
|
|
*
|
|
* The module assym.c contains the functions that operate
|
|
* on the mnemonic/directive and symbol structures.
|
|
*
|
|
* assym.c contains the following functions:
|
|
* VOID allglob()
|
|
* area * alookup()
|
|
* int hash()
|
|
* sym * lookup()
|
|
* mne * mlookup()
|
|
* VOID * new()
|
|
* int symeq()
|
|
* VOID syminit()
|
|
* VOID symglob()
|
|
*
|
|
* assym.c contains no local/static variables.
|
|
*/
|
|
|
|
/*)Function VOID syminit()
|
|
*
|
|
* The function syminit() is called early in the game
|
|
* to set up the hashtables. First all buckets in a
|
|
* table are cleared. Then a pass is made through
|
|
* the respective symbol lists, linking them into
|
|
* their hash buckets. Finally the base area pointer
|
|
* is set to 'dca'.
|
|
*
|
|
* local variables:
|
|
* int h computed hash value
|
|
* mne * mp pointer to a mne structure
|
|
* mne ** mpp pointer to an array of
|
|
* mne structure pointers
|
|
* sym * sp pointer to a sym structure
|
|
* sym ** spp pointer to an array of
|
|
* sym structure pointers
|
|
*
|
|
* global variables:
|
|
* area area[] single elememt area array
|
|
* area dca defined as area[0]
|
|
* mne * mnehash[] array of pointers to NHASH
|
|
* linked mnemonic/directive lists
|
|
* sym * symhash[] array of pointers to NHASH
|
|
* linked symbol lists
|
|
*
|
|
* functions called:
|
|
* none
|
|
*
|
|
* side effects:
|
|
* (1) The symbol hash tables are initialized,
|
|
* the only defined symbol is '.'.
|
|
* (2) The mnemonic/directive hash tables are
|
|
* initialized with the assembler directives
|
|
* and mnemonics found in the machine dependent
|
|
* file ___pst.c.
|
|
* (3) The area pointer is initialized to dca (area[0]).
|
|
*/
|
|
|
|
VOID
|
|
syminit()
|
|
{
|
|
register struct mne *mp;
|
|
struct mne **mpp;
|
|
register struct sym *sp;
|
|
struct sym **spp;
|
|
register int h;
|
|
|
|
mpp = &mnehash[0];
|
|
while (mpp < &mnehash[NHASH])
|
|
*mpp++ = NULL;
|
|
mp = &mne[0];
|
|
for (;;) {
|
|
h = hash(mp->m_id);
|
|
mp->m_mp = mnehash[h];
|
|
mnehash[h] = mp;
|
|
if (mp->m_flag&S_END)
|
|
break;
|
|
++mp;
|
|
}
|
|
|
|
spp = &symhash[0];
|
|
while (spp < &symhash[NHASH])
|
|
*spp++ = NULL;
|
|
sp = &sym[0];
|
|
for (;;) {
|
|
h = hash(sp->s_id);
|
|
sp->s_sp = symhash[h];
|
|
symhash[h] = sp;
|
|
if (sp->s_flag&S_END)
|
|
break;
|
|
++sp;
|
|
}
|
|
|
|
areap = &dca;
|
|
}
|
|
|
|
/*)Function area * alookup(id)
|
|
*
|
|
* char * id area name string
|
|
*
|
|
* The function alookup() searches the area list for a
|
|
* match with id. If the area is defined then a pointer
|
|
* to this area is returned else a NULL is returned.
|
|
*
|
|
* local variables:
|
|
* area * ap pointer to area structure
|
|
*
|
|
* global variables:
|
|
* area * areap pointer to an area structure
|
|
*
|
|
* functions called:
|
|
* int symeq() assym.c
|
|
*
|
|
* side effects:
|
|
* none
|
|
*/
|
|
|
|
struct area *
|
|
alookup(id)
|
|
char *id;
|
|
{
|
|
register struct area *ap;
|
|
|
|
ap = areap;
|
|
while (ap) {
|
|
if (symeq(id, ap->a_id)) {
|
|
return (ap);
|
|
}
|
|
ap = ap->a_ap;
|
|
}
|
|
return(NULL);
|
|
}
|
|
|
|
/*)Function mne * mlookup(id)
|
|
*
|
|
* char * id mnemonic/directive name string
|
|
*
|
|
* The function mlookup() searches the mnemonic/directive
|
|
* hash tables for a match returning a pointer to the
|
|
* mne structure else it returns a NULL.
|
|
*
|
|
* local variables:
|
|
* mne * mp pointer to mne structure
|
|
* int h calculated hash value
|
|
*
|
|
* global variables:
|
|
* mne * mnehash[] array of pointers to NHASH
|
|
* linked mnemonic/directive lists
|
|
*
|
|
* functions called:
|
|
* none
|
|
*
|
|
* side effects:
|
|
* none
|
|
*/
|
|
|
|
struct mne *
|
|
mlookup(id)
|
|
char *id;
|
|
{
|
|
register struct mne *mp;
|
|
register int h;
|
|
|
|
h = hash(id);
|
|
mp = mnehash[h];
|
|
while (mp) {
|
|
if (symeq(id, mp->m_id))
|
|
return (mp);
|
|
mp = mp->m_mp;
|
|
}
|
|
return (NULL);
|
|
}
|
|
|
|
/*)Function sym * lookup(id)
|
|
*
|
|
* char * id symbol name string
|
|
*
|
|
* The function lookup() searches the symbol hash tables for
|
|
* a symbol name match returning a pointer to the sym structure.
|
|
* If the symbol is not found then a sym structure is created,
|
|
* initialized, and linked to the appropriate hash table.
|
|
* A pointer to this new sym structure is returned.
|
|
*
|
|
* local variables:
|
|
* int h computed hash value
|
|
* sym * sp pointer to a sym structure
|
|
*
|
|
* global varaibles:
|
|
* sym * symhash[] array of pointers to NHASH
|
|
* linked symbol lists
|
|
*
|
|
* functions called:
|
|
* int hash() assym.c
|
|
* VOID * new() assym.c
|
|
* int symeq() assym.c
|
|
*
|
|
* side effects:
|
|
* If the function new() fails to allocate space
|
|
* for the new sym structure the assembly terminates.
|
|
*/
|
|
|
|
struct sym *
|
|
lookup(id)
|
|
char *id;
|
|
{
|
|
register struct sym *sp;
|
|
register int h;
|
|
|
|
h = hash(id);
|
|
sp = symhash[h];
|
|
while (sp) {
|
|
if (symeq(id, sp->s_id))
|
|
return (sp);
|
|
sp = sp->s_sp;
|
|
}
|
|
sp = (struct sym *) new (sizeof(struct sym));
|
|
sp->s_sp = symhash[h];
|
|
symhash[h] = sp;
|
|
sp->s_tsym = NULL;
|
|
strncpy(sp->s_id, id, NCPS);
|
|
sp->s_type = S_NEW;
|
|
sp->s_flag = 0;
|
|
sp->s_area = NULL;
|
|
sp->s_ref = 0;
|
|
sp->s_addr = 0;
|
|
return (sp);
|
|
}
|
|
|
|
/*)Function VOID symglob()
|
|
*
|
|
* The function symglob() will mark all symbols of
|
|
* type S_NEW as global. Called at the beginning of pass 1
|
|
* if the assembly option -g was specified.
|
|
*
|
|
* local variables:
|
|
* sym * sp pointer to a sym structure
|
|
* int i loop index
|
|
*
|
|
* global variables:
|
|
* sym * symhash[] array of pointers to NHASH
|
|
* linked symbol lists
|
|
*
|
|
* functions called:
|
|
* none
|
|
*
|
|
* side effects:
|
|
* Symbol types changed.
|
|
*/
|
|
|
|
VOID
|
|
symglob()
|
|
{
|
|
register struct sym *sp;
|
|
register int i;
|
|
|
|
for (i=0; i<NHASH; ++i) {
|
|
sp = symhash[i];
|
|
while (sp != NULL) {
|
|
if (sp->s_type == S_NEW)
|
|
sp->s_flag |= S_GBL;
|
|
sp = sp->s_sp;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*)Function VOID allglob()
|
|
*
|
|
* The function allglob() will mark all symbols of
|
|
* type S_USER as global. Called at the beginning of pass 1
|
|
* if the assembly option -a was specified.
|
|
*
|
|
* local variables:
|
|
* sym * sp pointer to a sym structure
|
|
* int i loop index
|
|
*
|
|
* global variables:
|
|
* sym * symhash[] array of pointers to NHASH
|
|
* linked symbol lists
|
|
*
|
|
* functions called:
|
|
* none
|
|
*
|
|
* side effects:
|
|
* Symbol types changed.
|
|
*/
|
|
|
|
VOID
|
|
allglob()
|
|
{
|
|
register struct sym *sp;
|
|
register int i;
|
|
|
|
for (i=0; i<NHASH; ++i) {
|
|
sp = symhash[i];
|
|
while (sp != NULL) {
|
|
if (sp != &dot && sp->s_type == S_USER)
|
|
sp->s_flag |= S_GBL;
|
|
sp = sp->s_sp;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*)Function int symeq(p1, p2)
|
|
*
|
|
* char * p1 name string
|
|
* char * p2 name string
|
|
*
|
|
* The function symeq() compares the two name strings for a match.
|
|
* The return value is 1 for a match and 0 for no match.
|
|
*
|
|
* local variables:
|
|
* int h loop counter
|
|
*
|
|
* global variables:
|
|
* char ccase[] an array of characters which
|
|
* perform the case translation function
|
|
*
|
|
* functions called:
|
|
* none
|
|
*
|
|
* side effects:
|
|
* none
|
|
*
|
|
*/
|
|
|
|
int
|
|
symeq(p1, p2)
|
|
register char *p1, *p2;
|
|
{
|
|
register int n;
|
|
|
|
n = NCPS;
|
|
do {
|
|
|
|
#if CASE_SENSITIVE
|
|
if (*p1++ != *p2++)
|
|
return (0);
|
|
#else
|
|
if (ccase[(unsigned char)(*p1++)] != ccase[(unsigned char)(*p2++)])
|
|
return (0);
|
|
#endif
|
|
|
|
} while (--n);
|
|
return (1);
|
|
}
|
|
|
|
/*)Function int hash(p)
|
|
*
|
|
* char * p pointer to string to hash
|
|
*
|
|
* The function hash() computes a hash code using the sum
|
|
* of all characters mod table size algorithm.
|
|
*
|
|
* local variables:
|
|
* int h accumulated character sum
|
|
* int n loop counter
|
|
*
|
|
* global variables:
|
|
* char ccase[] an array of characters which
|
|
* perform the case translation function
|
|
*
|
|
* functions called:
|
|
* none
|
|
*
|
|
* side effects:
|
|
* none
|
|
*/
|
|
|
|
int
|
|
hash(p)
|
|
register char *p;
|
|
{
|
|
register int h, n;
|
|
|
|
h = 0;
|
|
n = NCPS;
|
|
do {
|
|
|
|
#if CASE_SENSITIVE
|
|
h += *p++;
|
|
#else
|
|
h += ccase[(unsigned char)(*p++)];
|
|
#endif
|
|
|
|
} while (--n);
|
|
return (h&HMASK);
|
|
}
|
|
|
|
/*)Function VOID * new(n)
|
|
*
|
|
* unsigned int n allocation size in bytes
|
|
*
|
|
* The function new() allocates n bytes of space and returns
|
|
* a pointer to this memory. If no space is available the
|
|
* assembly is terminated.
|
|
*
|
|
* local variables:
|
|
* VOID * p a general pointer
|
|
*
|
|
* global variables:
|
|
* none
|
|
*
|
|
* functions called:
|
|
* VOID asexit() asmain.c
|
|
* int fprintf() c_library
|
|
* VOID * malloc() c_library
|
|
*
|
|
* side effects:
|
|
* Memory is allocated, if allocation fails
|
|
* the assembly is terminated.
|
|
*/
|
|
|
|
VOID *
|
|
new(n)
|
|
unsigned int n;
|
|
{
|
|
register VOID *p;
|
|
|
|
if ((p = (VOID *) malloc(n)) == NULL) {
|
|
fprintf(stderr, "Out of space!\n");
|
|
asexit(1);
|
|
}
|
|
return (p);
|
|
}
|