/* asmutl.c -- microsoft 80x86 assembler
**
** microsoft (r) macro assembler
** copyright (c) microsoft corp 1986. all rights reserved
**
** randy nevin
**
** 10/90 - Quick conversion to 32 bit by Jeff Spencer
*/
#include <stdio.h>
#include <string.h>
#include "asm86.h"
#include "asmfcn.h"
#include "asmctype.h"
#include "asmindex.h"
#include "asmmsg.h"
extern char *fname;
extern char hexchar[];
/* put a bunch of registers into the symbol table */
VOID initregs(
struct mreg *makreg
){
register struct mreg *index;
register char *p;
char * savelbufp;
savelbufp = lbufp;
for (index = makreg; *index->nm; index++)
{
lbufp = index->nm;
getatom();
if (symsearch())
/* register already defined */
errorn(E_RAD);
symcreate( M_NOCREF | M_BACKREF | M_DEFINED, REGISTER);
symptr->offset = index->val;
symptr->symu.regsym.regtype = index->rt;
symbolcnt--;
}
lbufp = savelbufp;
}
/*** scanorder - process symbol list in order
*
* scanorder (root, fcn);
*
* Entry root = root of symbol list
* fcn = pointer to function to be executed
* Exit none
* Returns none
* Calls
*/
#if !defined XENIX286 && !defined FLATMODEL
# pragma alloc_text (FA_TEXT, scanorder)
#endif
VOID PASCAL
scanorder (
SYMBOL FARSYM *root,
SHORT (PASCAL *item) (SYMBOL FARSYM *)
){
register SYMBOL FARSYM *p;
for (p = root; p; p = p->next) {
symptr = p;
(*item) (p);
}
}
/*** scanSorted - process symbol sorted order
*
* Entry root = root of symbol list
* fcn = pointer to function to be executed
* Exit none
* Returns none
* Calls
*/
#if !defined XENIX286 && !defined FLATMODEL
# pragma alloc_text (FA_TEXT, scanSorted)
#endif
VOID PASCAL
scanSorted (
SYMBOL FARSYM *root,
SHORT (PASCAL *item) (SYMBOL FARSYM *)
){
register SYMBOL FARSYM *p;
for (p = root; p; p = p->alpha) {
symptr = p;
if (!(M_PASSED & p->attr))
(*item) (p);
}
}
/*** assignemitsylinknum - assign link number
*
* assignlinknum (sym);
*
* Entry *sym = symbol
* Exit
* Returns
* Calls
* Note Turn off BACKREF and PASSED bits in symbol attributes and
* if symbol is segment, group, public or external give it a
* link dictionary number
*/
VOID PASCAL
assignlinknum (
register SYMBOL FARSYM *sym
){
switch (sym->symkind) {
case MACRO: /* make symbol unknown at start of p2 */
case STRUC:
case REC:
sym->attr &= ~M_BACKREF;
return;
case SEGMENT:
sym->symu.segmnt.lnameIndex = lnameIndex++;
goto creatLname;
case CLASS:
sym->symu.ext.extIndex = lnameIndex++;
goto creatLname;
/* group indexs holds lname index temporary */
case GROUP:
sym->symu.grupe.groupIndex = lnameIndex++;
creatLname:
emitlname (sym);
}
if (sym->symkind == REGISTER)
sym->attr &= ~(M_PASSED);
else
sym->attr &= ~(M_PASSED | M_BACKREF);
}
/*** scansegment - output segment names
*
* scansegment (sym);
*
* Entry *sym = segment symbol chain
* Exit
* Returns
* Calls
*/
VOID PASCAL
scansegment (
register SYMBOL FARSYM *sym
){
if (sym->symu.segmnt.align == (char)-1)
/* PARA default */
sym->symu.segmnt.align = 3;
if (sym->symu.segmnt.combine == 7)
/* Default no combine */
sym->symu.segmnt.combine = 0;
sym->symu.segmnt.lastseg = NULL;
/* Output segment def */
emitsegment (sym);
/* Clear Offset( current segment PC ) for pass 2 */
sym->offset = 0;
sym->symu.segmnt.seglen = 0;
}
/*** scangroup - output group names
*
* scangroup (sym);
*
* Entry *sym = group chain
* Exit
* Returns
* Calls
*/
VOID PASCAL
scangroup (
SYMBOL FARSYM *sym
){
if (sym->symkind == GROUP)
emitgroup (sym);
}
/*** scanextern - output external names
*
* scanextern (sym);
*
* Entry *sym = chain of external names
* Exit
* Returns
* Calls
*/
VOID PASCAL
scanextern (
SYMBOL FARSYM *sym
){
if (M_XTERN & sym->attr)
emitextern (sym);
}
/*** scanglobal - output global names
*
* scanglobal (sym);
*
* Entry *sym = chain of external names
* Exit
* Returns
* Calls
*/
VOID PASCAL
scanglobal (
SYMBOL FARSYM *sym
){
if (M_GLOBAL & sym->attr)
emitglobal (sym);
}
/*** dumpname - output module name
*
* dumpname ();
*
* Entry
* Exit
* Returns
* Calls
*/
VOID PASCAL
dumpname ()
{
moduleflag = TRUE;
/* put file name instead of the usual */
emodule(createname(fname));
}
/*** showresults - display final assembly results
*
* showresults (fil, verbose, mbytes);
*
* Entry fil = file to print statistics to
* verbose = TRUE if all statistics to be displayed
* FALSE if only error messages to be displayed
* mbytes = number of free bytes in symbol space
* Exit statistics written to file
* Returns none
* Calls fprintf
*/
VOID PASCAL
showresults (
FILE *fil,
char verbose,
char *pFreeBytes
){
if (verbose) {
fprintf (fil, __NMSG_TEXT(ER_SOU), linessrc, linestot);
fprintf (fil, __NMSG_TEXT(ER_SY2), symbolcnt);
}
fprintf (fil, pFreeBytes);
fprintf (fil, "%7hd%s\n%7hd%s\n",
warnnum, __NMSG_TEXT(ER_EM1),
errornum, __NMSG_TEXT(ER_EM2));
#ifdef BUF_STATS
if (verbose) {
extern long DEBUGtl, DEBUGlb, DEBUGbp, DEBUGbl, DEBUGcs, DEBUGca;
fprintf (fil, "\nTotal lines: %ld\n", DEBUGtl);
fprintf (fil, "Lines buffered: %ld\n", DEBUGlb);
fprintf (fil, "Stored as blank: %ld\n", DEBUGbl);
fprintf (fil, "Bad lbufp: %ld\n", DEBUGbp);
fprintf (fil, "Total Characters: %ld\n", DEBUGca);
fprintf (fil, "Characters buffered: %ld\n", DEBUGcs);
}
#endif
#ifdef EXPR_STATS
if (verbose) {
extern long cExpr, cHardExpr;
fprintf(fil, "\nTotal Expressions(%ld), Simple(%ld): %hd%%\n",
cExpr, cExpr - cHardExpr, (SHORT)((cExpr - cHardExpr)*100 / (cExpr+1)));
}
#endif
}
/*** resetobjidx - reset listindex to correct column
*
* resetobjidx ();
*
* Entry
* Exit
* Returns
* Calls
*/
VOID PASCAL CODESIZE
resetobjidx ()
{
listindex = LSTDATA;
if (!emittext && duplevel)
listindex += 3 + ((duplevel <= 8)? duplevel: 8);
if (highWord(pcoffset)) /* check for 32 bit listing */
listindex += 4;
#ifdef BCBOPT
if (fNotStored)
storelinepb ();
#endif
listline ();
linebuffer[0] = 0;
}
/*** copyascii - copy ASCII into list buffer
*
* copyascii ();
*
* Entry objectascii = data to be copied
* listindex = position for copy
* Exit
* Returns
* Calls
*/
VOID PASCAL CODESIZE
copyascii ()
{
register char *p2;
register char *p1;
if (listindex >= LSTMAX)
resetobjidx ();
if (!fNeedList)
return;
for (p1 = listbuffer + listindex, p2 = objectascii; *p2; )
*p1++ = *p2++;
listindex = p1 - listbuffer;
}
/*** copystring - copy ASCII into list buffer
*
* copystring ();
*
* Entry objectascii = data to be copied
* listindex = position for copy
* Exit
* Returns
* Calls
*/
VOID PASCAL CODESIZE
copystring (
register char *strng
){
register char *p1;
if (!fNeedList || fSkipList)
return;
goto firstTime;
while (*strng) {
*p1++ = *strng++;
if (*strng && ++listindex > LSTMAX + 2) {
resetobjidx ();
firstTime:
listindex = 3;
p1 = listbuffer + 3;
}
}
}
/*** copytext - copy two characters to text line
*
* copytext (chrs)
*
* Entry
* Exit
* Returns
* Calls
*/
VOID PASCAL CODESIZE
copytext (
char *chrs
){
if (listindex > LSTMAX+1)
resetobjidx ();
listbuffer[listindex++] = *chrs++;
listbuffer[listindex++] = *chrs;
}
/*** pcdisplay - display program counter
*
* pcdisplay();
*
* Entry pcoffset = value to display
* Exit hex or octal value of pc interted in list buffer
* Returns none
* Calls copyascii, wordascii
*/
VOID PASCAL CODESIZE
pcdisplay ()
{
listindex = 1;
if (!fNeedList)
return;
offsetAscii (pcoffset);
copyascii ();
listindex = LSTDATA;
if (objectascii[4]) /* was a 32bit number */
listindex += 4;
}
/*** opdisplay - display program counter and opcode
*
* opdisplay(v);
*
* Entry v = opcode to display
* Exit none
* Returns none
* Calls
*/
VOID PASCAL CODESIZE
opdisplay (
UCHAR v
){
if (!fNeedList)
return;
if (listindex == 1)
pcdisplay ();
objectascii[1] = hexchar[v & 0xf];
objectascii[0] = hexchar[v >> 4];
objectascii[2] = 0;
copyascii ();
listindex++;
}
#ifndef M8086OPT
/*** inset - check for value in a set of values
*
* flag = inset (val, set);
*
* Entry val = value to check
* set = array of values to check for
* set[0] = number of entries in set
* Exit none
* Returns TRUE if val is in set
* FALSE if val is not in set
* Calls
*/
char CODESIZE
inset (
register char v,
char *s
){
register USHORT i;
register char *p;
for (i = *s, p = ++s; i; i--)
if (v == *p++)
return (TRUE);
return (FALSE);
}
#endif /* M8086OPT */
/*** outofmem - issue an out of memory error message
*
* outofmem (text);
*
* Entry *text = text to append to message
* Exit doesn't
* Returns none
* Calls endblk, parse
* Note if not end of PROC, parse line as normal. Otherwise,
* terminate block.
*/
VOID PASCAL
outofmem ()
{
closeOpenFiles();
terminate((SHORT)((EX_MEME<<12) | ER_MEM), pFCBCur->fname, errorlineno, NULL );
}
SHORT PASCAL CODESIZE
tokenIS(
char *pLiteral
){
return(_stricmp(naim.pszName, pLiteral) == 0);
}
#ifdef M8086
/*** strnfcpy - copy string to near buffer
*
* strnfcpy (dest, src);
*
* Entry dest = pointer to near buffer
* src = pointer to far source buffer
* Exit source copied to destination
* Returns none
* Calls none
*/
VOID PASCAL
strnfcpy (
register char *dest,
register char FAR *src
){
while(*src)
*dest++ = *src++;
*dest = NULL;
}
/*** strflen - compute length of far buffer
*
* strnflen (s1);
*
* Entry s1 = pointer to far buffer
* Exit none
* Returns number of characters in buffer
* Calls none
*/
USHORT PASCAL
strflen (
register char FAR *s1
){
register USHORT i = 0;
while (*s1++)
i++;
return(i);
}
#endif /* M8086 */