windows-nt/Source/XPSP1/NT/sdktools/link16/newdef.y

2351 lines
72 KiB
Plaintext
Raw Normal View History

2020-09-26 03:20:57 -05:00
/* DEF file syntax - yacc */
%token T_FALIAS
%token T_KCLASS
%token T_KNAME
%token T_KLIBRARY
%token T_KBASE
%token T_KDEVICE
%token T_KPHYSICAL
%token T_KVIRTUAL
%token T_ID
%token T_NUMBER
%token T_KDESCRIPTION
%token T_KHEAPSIZE
%token T_KSTACKSIZE
%token T_KMAXVAL
%token T_KCODE
%token T_KCONSTANT
%token <_wd> T_FDISCARDABLE T_FNONDISCARDABLE
%token T_FEXEC
%token <_wd> T_FFIXED
%token <_wd> T_FMOVABLE
%token T_FSWAPPABLE
%token T_FSHARED
%token T_FMIXED
%token <_wd> T_FNONSHARED
%token <_wd> T_FPRELOAD
%token <_wd> T_FINVALID
%token <_wd> T_FLOADONCALL
%token <_wd> T_FRESIDENT
%token <_wd> T_FPERM
%token <_wd> T_FCONTIG
%token <_wd> T_FDYNAMIC
%token T_FNONPERM
%token T_KDATA
%token <_wd> T_FNONE
%token <_wd> T_FSINGLE
%token <_wd> T_FMULTIPLE
%token T_KSEGMENTS
%token T_KOBJECTS
%token T_KSECTIONS
%token T_KSTUB
%token T_KEXPORTS
%token T_KEXETYPE
%token T_KSUBSYSTEM
%token T_FDOS
%token T_FOS2
%token T_FUNKNOWN
%token T_FWINDOWS
%token T_FDEV386
%token T_FMACINTOSH
%token T_FWINDOWSNT
%token T_FWINDOWSCHAR
%token T_FPOSIX
%token T_FNT
%token T_FUNIX
%token T_KIMPORTS
%token <_wd> T_KNODATA
%token T_KOLD
%token T_KCONFORM
%token T_KNONCONFORM
%token T_KEXPANDDOWN T_KNOEXPANDDOWN
%token T_EQ
%token T_AT
%token T_KRESIDENTNAME
%token T_KNONAME
%token T_STRING
%token T_DOT
%token T_COLON
%token T_COMA
%token T_ERROR
%token T_FHUGE T_FIOPL T_FNOIOPL
%token T_PROTMODE
%token <_wd> T_FEXECREAD T_FRDWR
%token T_FRDONLY
%token T_FINITGLOB T_FINITINST T_FTERMINST
%token T_FWINAPI T_FWINCOMPAT T_FNOTWINCOMPAT T_FPRIVATE T_FNEWFILES
%token T_REALMODE
%token T_FUNCTIONS
%token T_APPLOADER
%token T_OVL
%token T_KVERSION
%{ /* SCCSID = %W% %E% */
#include <minlit.h>
#include <bndtrn.h>
#include <bndrel.h>
#include <lnkio.h>
#include <newexe.h>
#if EXE386
#include <exe386.h>
#endif
#include <lnkmsg.h>
#include <extern.h>
#include <string.h>
#include <impexp.h>
#define YYS_WD(x) (x)._wd /* Access macro */
#define YYS_BP(x) (x)._bp /* Access macro */
#define INCLUDE_DIR 0xffff /* Include directive for the lexer */
#define MAX_NEST 7
#define IO_BUF_SIZE 512
/*
* FUNCTION PROTOTYPES
*/
LOCAL int NEAR lookup(void);
LOCAL int NEAR yylex(void);
LOCAL void NEAR yyerror(char *str);
LOCAL void NEAR ProcNamTab(long lfa,unsigned short cb,unsigned short fres);
LOCAL void NEAR NewProc(char *szName);
#if NOT EXE386
LOCAL void NEAR SetExpOrds(void);
#endif
LOCAL void NEAR NewDescription(unsigned char *sbDesc);
LOCAL APROPIMPPTR NEAR GetImport(unsigned char *sb);
#if EXE386
LOCAL void NEAR NewModule(unsigned char *sbModnam, unsigned char *defaultExt);
LOCAL void NEAR DefaultModule(unsigned char *defaultExt);
#else
LOCAL void NEAR NewModule(unsigned char *sbModnam);
LOCAL void NEAR DefaultModule(void);
#endif
#if AUTOVM
BYTE FAR * NEAR FetchSym1(RBTYPE rb, WORD Dirty);
#define FETCHSYM FetchSym1
#define PROPSYMLOOKUP EnterName
#else
#define FETCHSYM FetchSym
#define PROPSYMLOOKUP EnterName
#endif
int yylineno = -1; /* Line number */
LOCAL FTYPE fFileNameExpected;
LOCAL FTYPE fMixed;
LOCAL FTYPE fNoExeVer;
LOCAL FTYPE fHeapSize;
LOCAL BYTE *sbOldver; /* Old version of the .EXE */
LOCAL FTYPE vfAutodata;
LOCAL FTYPE vfShrattr;
LOCAL BYTE cDigits;
#if EXE386
LOCAL DWORD offmask; /* Seg flag bits to turn off */
LOCAL BYTE fUserVersion = 0;
LOCAL WORD expOtherFlags = 0;
LOCAL BYTE moduleEXE[] = "\007A:\\.exe";
LOCAL BYTE moduleDLL[] = "\007A:\\.dll";
#else
LOCAL WORD offmask; /* Seg flag bits to turn off */
#endif
#if OVERLAYS
LOCAL WORD iOvl = NOTIOVL; // Overlay assigned to functions
#endif
LOCAL char *szSegName; // Segment assigned to functions
LOCAL WORD nameFlags; /* Flags associated with exported name */
LOCAL BSTYPE includeDisp[MAX_NEST];
// Include file stack
LOCAL short curLevel; // Current include nesting level
// Zero means main .DEF file
LOCAL char *keywds[] = /* Keyword array */
{
"ALIAS", (char *) T_FALIAS,
"APPLOADER", (char *) T_APPLOADER,
"BASE", (char *) T_KBASE,
"CLASS", (char *) T_KCLASS,
"CODE", (char *) T_KCODE,
"CONFORMING", (char *) T_KCONFORM,
"CONSTANT", (char *) T_KCONSTANT,
"CONTIGUOUS", (char *) T_FCONTIG,
"DATA", (char *) T_KDATA,
"DESCRIPTION", (char *) T_KDESCRIPTION,
"DEV386", (char *) T_FDEV386,
"DEVICE", (char *) T_KDEVICE,
"DISCARDABLE", (char *) T_FDISCARDABLE,
"DOS", (char *) T_FDOS,
"DYNAMIC", (char *) T_FDYNAMIC,
"EXECUTE-ONLY", (char *) T_FEXEC,
"EXECUTEONLY", (char *) T_FEXEC,
"EXECUTEREAD", (char *) T_FEXECREAD,
"EXETYPE", (char *) T_KEXETYPE,
"EXPANDDOWN", (char *) T_KEXPANDDOWN,
"EXPORTS", (char *) T_KEXPORTS,
"FIXED", (char *) T_FFIXED,
"FUNCTIONS", (char *) T_FUNCTIONS,
"HEAPSIZE", (char *) T_KHEAPSIZE,
"HUGE", (char *) T_FHUGE,
"IMPORTS", (char *) T_KIMPORTS,
"IMPURE", (char *) T_FNONSHARED,
"INCLUDE", (char *) INCLUDE_DIR,
"INITGLOBAL", (char *) T_FINITGLOB,
"INITINSTANCE", (char *) T_FINITINST,
"INVALID", (char *) T_FINVALID,
"IOPL", (char *) T_FIOPL,
"LIBRARY", (char *) T_KLIBRARY,
"LOADONCALL", (char *) T_FLOADONCALL,
"LONGNAMES", (char *) T_FNEWFILES,
"MACINTOSH", (char *) T_FMACINTOSH,
"MAXVAL", (char *) T_KMAXVAL,
"MIXED1632", (char *) T_FMIXED,
"MOVABLE", (char *) T_FMOVABLE,
"MOVEABLE", (char *) T_FMOVABLE,
"MULTIPLE", (char *) T_FMULTIPLE,
"NAME", (char *) T_KNAME,
"NEWFILES", (char *) T_FNEWFILES,
"NODATA", (char *) T_KNODATA,
"NOEXPANDDOWN", (char *) T_KNOEXPANDDOWN,
"NOIOPL", (char *) T_FNOIOPL,
"NONAME", (char *) T_KNONAME,
"NONCONFORMING", (char *) T_KNONCONFORM,
"NONDISCARDABLE", (char *) T_FNONDISCARDABLE,
"NONE", (char *) T_FNONE,
"NONPERMANENT", (char *) T_FNONPERM,
"NONSHARED", (char *) T_FNONSHARED,
"NOTWINDOWCOMPAT", (char *) T_FNOTWINCOMPAT,
"NT", (char *) T_FNT,
"OBJECTS", (char *) T_KOBJECTS,
"OLD", (char *) T_KOLD,
"OS2", (char *) T_FOS2,
"OVERLAY", (char *) T_OVL,
"OVL", (char *) T_OVL,
"PERMANENT", (char *) T_FPERM,
"PHYSICAL", (char *) T_KPHYSICAL,
"POSIX", (char *) T_FPOSIX,
"PRELOAD", (char *) T_FPRELOAD,
"PRIVATE", (char *) T_FPRIVATE,
"PRIVATELIB", (char *) T_FPRIVATE,
"PROTMODE", (char *) T_PROTMODE,
"PURE", (char *) T_FSHARED,
"READONLY", (char *) T_FRDONLY,
"READWRITE", (char *) T_FRDWR,
"REALMODE", (char *) T_REALMODE,
"RESIDENT", (char *) T_FRESIDENT,
"RESIDENTNAME", (char *) T_KRESIDENTNAME,
"SECTIONS", (char *) T_KSECTIONS,
"SEGMENTS", (char *) T_KSEGMENTS,
"SHARED", (char *) T_FSHARED,
"SINGLE", (char *) T_FSINGLE,
"STACKSIZE", (char *) T_KSTACKSIZE,
"STUB", (char *) T_KSTUB,
"SUBSYSTEM", (char *) T_KSUBSYSTEM,
"SWAPPABLE", (char *) T_FSWAPPABLE,
"TERMINSTANCE", (char *) T_FTERMINST,
"UNIX", (char *) T_FUNIX,
"UNKNOWN", (char *) T_FUNKNOWN,
"VERSION", (char *) T_KVERSION,
"VIRTUAL", (char *) T_KVIRTUAL,
"WINDOWAPI", (char *) T_FWINAPI,
"WINDOWCOMPAT", (char *) T_FWINCOMPAT,
"WINDOWS", (char *) T_FWINDOWS,
"WINDOWSCHAR", (char *) T_FWINDOWSCHAR,
"WINDOWSNT", (char *) T_FWINDOWSNT,
NULL
};
%}
%union
{
#if EXE386
DWORD _wd;
#else
WORD _wd;
#endif
BYTE *_bp;
}
%type <_bp> T_ID
%type <_bp> T_STRING
%type <_bp> Idname
%type <_bp> Internal
%type <_bp> Class
%type <_wd> T_NUMBER
%type <_wd> Codeflaglist
%type <_wd> Codeflag
%type <_wd> Dataflaglist
%type <_wd> Dataflag
%type <_wd> Exportflags
%type <_wd> Exportopts
%type <_wd> Nodata
%type <_wd> Segflags
%type <_wd> Segflag
%type <_wd> Segflaglist
%type <_wd> Baseflag
%type <_wd> Dataonly
%type <_wd> Codeonly
%type <_wd> MajorVer
%type <_wd> MinorVer
%type <_wd> Overlay
%type <_wd> ImportFlags
%%
Definitions : Name Options
| Name
|
{
#if EXE386
DefaultModule(moduleEXE);
#else
DefaultModule();
#endif
}
Options
;
Name : T_KNAME Idname Apptype OtherFlags VirtBase
{
#if EXE386
NewModule($2, moduleEXE);
#else
NewModule($2);
#endif
}
| T_KNAME Apptype OtherFlags VirtBase
{
#if EXE386
DefaultModule(moduleEXE);
#else
DefaultModule();
#endif
}
| T_KLIBRARY Idname Libflags OtherFlags VirtBase
{
#if EXE386
SetDLL(vFlags);
NewModule($2, moduleDLL);
#else
vFlags = NENOTP | (vFlags & ~NEINST) | NESOLO;
dfData |= NSSHARED;
NewModule($2);
#endif
}
| T_KLIBRARY Libflags OtherFlags VirtBase
{
#if EXE386
SetDLL(vFlags);
DefaultModule(moduleDLL);
#else
vFlags = NENOTP | (vFlags & ~NEINST) | NESOLO;
dfData |= NSSHARED;
DefaultModule();
#endif
}
| T_KPHYSICAL T_KDEVICE Idname Libflags VirtBase
{
#if EXE386
SetDLL(vFlags);
NewModule($3, moduleDLL);
#endif
}
| T_KPHYSICAL T_KDEVICE Libflags VirtBase
{
#if EXE386
SetDLL(vFlags);
DefaultModule(moduleDLL);
#endif
}
| T_KVIRTUAL T_KDEVICE Idname Libflags VirtBase
{
#if EXE386
SetDLL(vFlags);
NewModule($3, moduleDLL);
#endif
}
| T_KVIRTUAL T_KDEVICE Libflags VirtBase
{
#if EXE386
SetDLL(vFlags);
DefaultModule(moduleDLL);
#endif
}
;
Libflags : T_FINITGLOB
{
#if EXE386
dllFlags &= ~E32_PROCINIT;
#else
vFlags &= ~NEPPLI;
#endif
}
| T_FPRIVATE
{
vFlags |= NEPRIVLIB;
}
| InstanceFlags
|
;
InstanceFlags : InstanceFlags InstanceFlag
| InstanceFlag
;
InstanceFlag : T_FINITINST
{
#if EXE386
SetINSTINIT(dllFlags);
#else
vFlags |= NEPPLI;
#endif
}
| T_FTERMINST
{
#if EXE386
SetINSTTERM(dllFlags);
#endif
}
;
VirtBase : T_KBASE T_EQ T_NUMBER
{
#if EXE386
virtBase = $3;
virtBase = RoundTo64k(virtBase);
#endif
}
|
{
}
;
Apptype : T_FWINAPI
{
#if EXE386
SetGUI(TargetSubsys);
#else
vFlags |= NEWINAPI;
#endif
}
| T_FWINCOMPAT
{
#if EXE386
SetGUICOMPAT(TargetSubsys);
#else
vFlags |= NEWINCOMPAT;
#endif
}
| T_FNOTWINCOMPAT
{
#if EXE386
SetNOTGUI(TargetSubsys);
#else
vFlags |= NENOTWINCOMPAT;
#endif
}
| T_FPRIVATE
{
vFlags |= NEPRIVLIB;
}
|
{
}
;
OtherFlags : T_FNEWFILES
{
#if NOT EXE386
vFlagsOthers |= NENEWFILES;
#endif
}
|
{
}
;
Options : Options Option
| Option
;
Option : T_KDESCRIPTION T_STRING
{
NewDescription($2);
}
| T_KOLD T_STRING
{
if(sbOldver == NULL) sbOldver = _strdup(bufg);
}
| T_KSTUB T_FNONE
{
if(rhteStub == RHTENIL) fStub = (FTYPE) FALSE;
}
| T_KSTUB T_STRING
{
if(fStub && rhteStub == RHTENIL)
{
PROPSYMLOOKUP($2,ATTRNIL, TRUE);
rhteStub = vrhte;
}
}
| T_KHEAPSIZE
{
fHeapSize = (FTYPE) TRUE;
}
SizeSpec
| T_KSTACKSIZE
{
fHeapSize = (FTYPE) FALSE;
}
SizeSpec
| T_PROTMODE
{
#if NOT EXE386
vFlags |= NEPROT;
#endif
}
| T_REALMODE
{
fRealMode = (FTYPE) TRUE;
vFlags &= ~NEPROT;
}
| T_APPLOADER Idname
{
#if NOT EXE386
AppLoader($2);
#endif
}
| Codeflags
| Dataflags
| Segments
| Exports
| Imports
| ExeType
| SubSystem
| ProcOrder
| UserVersion
;
SizeSpec : T_NUMBER T_COMA T_NUMBER
{
if (fHeapSize)
{
cbHeap = $1;
#if EXE386
cbHeapCommit = $3;
#endif
}
else
{
if(cbStack)
OutWarn(ER_stackdb, $1);
cbStack = $1;
#if EXE386
cbStackCommit = $3;
#endif
}
}
| T_NUMBER
{
if (fHeapSize)
{
cbHeap = $1;
#if EXE386
cbHeapCommit = cbHeap;
#endif
}
else
{
if(cbStack)
OutWarn(ER_stackdb, $1);
cbStack = $1;
#if EXE386
cbStackCommit = cbStack;
#endif
}
}
| T_KMAXVAL
{
if (fHeapSize)
fHeapMax = (FTYPE) TRUE;
}
;
Codeflags : T_KCODE Codeflaglist
{
// Set dfCode to specified flags; for any unspecified attributes
// use the defaults. Then reset offmask.
dfCode = $2 | (dfCode & ~offmask);
offmask = 0;
vfShrattr = (FTYPE) FALSE; /* Reset for DATA */
}
;
Codeflaglist : Codeflaglist Codeflag
{
$$ |= $2;
}
| Codeflag
;
Codeflag : Baseflag
| Codeonly
;
Codeonly : T_FEXEC
{
#if EXE386
$$ = OBJ_EXEC;
#else
$$ = NSEXRD;
#endif
}
| T_FEXECREAD
| T_FDISCARDABLE
{
#if EXE386
offmask |= OBJ_RESIDENT;
#else
$$ = NSDISCARD | NSMOVE;
#endif
}
| T_FNONDISCARDABLE
{
#if EXE386
#else
offmask |= NSDISCARD;
#endif
}
| T_KCONFORM
{
#if EXE386
#else
$$ = NSCONFORM;
#endif
}
| T_KNONCONFORM
{
#if EXE386
#else
offmask |= NSCONFORM;
#endif
}
;
Dataflags : T_KDATA Dataflaglist
{
// Set dfData to specified flags; for any unspecified
// attribute use the defaults. Then reset offmask.
#if EXE386
dfData = ($2 | (dfData & ~offmask));
#else
dfData = $2 | (dfData & ~offmask);
#endif
offmask = 0;
#if NOT EXE386
if (vfShrattr && !vfAutodata)
{
// If share-attribute and no autodata attribute, share-
// attribute controls autodata.
if ($2 & NSSHARED)
vFlags = (vFlags & ~NEINST) | NESOLO;
else
vFlags = (vFlags & ~NESOLO) | NEINST;
}
else if(!vfShrattr)
{
// Else if no share-attribute, autodata attribute
// controls share-attribute.
if (vFlags & NESOLO)
dfData |= NSSHARED;
else if(vFlags & NEINST)
dfData &= ~NSSHARED;
}
#endif
}
;
Dataflaglist : Dataflaglist Dataflag
{
$$ |= $2;
}
| Dataflag
;
Dataflag : Baseflag
| Dataonly
| T_FNONE
{
#if NOT EXE386
vFlags &= ~(NESOLO | NEINST);
#endif
}
| T_FSINGLE
{
#if NOT EXE386
vFlags = (vFlags & ~NEINST) | NESOLO;
#endif
vfAutodata = (FTYPE) TRUE;
}
| T_FMULTIPLE
{
#if NOT EXE386
vFlags = (vFlags & ~NESOLO) | NEINST;
#endif
vfAutodata = (FTYPE) TRUE;
}
| T_FDISCARDABLE
{
#if NOT EXE386
// This ONLY for compatibility with JDA IBM LINK
$$ = NSDISCARD | NSMOVE;
#endif
}
| T_FNONDISCARDABLE
{
#if NOT EXE386
// This ONLY for compatibility with JDA IBM LINK
offmask |= NSDISCARD;
#endif
}
;
Dataonly : T_FRDONLY
{
#if EXE386
$$ = OBJ_READ;
offmask |= OBJ_WRITE;
#else
$$ = NSEXRD;
#endif
}
| T_FRDWR
| T_KEXPANDDOWN
{
#if FALSE AND NOT EXE386
$$ = NSEXPDOWN;
#endif
}
| T_KNOEXPANDDOWN
{
#if FALSE AND NOT EXE386
offmask |= NSEXPDOWN;
#endif
}
;
Segments : T_KSEGMENTS Segattrlist
| T_KSEGMENTS
| T_KOBJECTS Segattrlist
| T_KOBJECTS
| T_KSECTIONS Segattrlist
| T_KSECTIONS
;
Segattrlist : Segattrlist Segattr
| Segattr
;
Segattr : Idname Class Overlay Segflags
{
NewSeg($1, $2, $3, $4);
}
;
Class : T_KCLASS T_STRING
{
$$ = _strdup($2);
}
|
{
$$ = _strdup("\004CODE");
}
;
Overlay : T_OVL T_COLON T_NUMBER
{
$$ = $3;
}
|
{
#if OVERLAYS
$$ = NOTIOVL;
#endif
}
;
Segflag : Baseflag
| Codeonly
| Dataonly
;
Segflaglist : Segflaglist Segflag
{
$$ |= $2;
}
| Segflag
;
Segflags : Segflaglist
{
$$ = $1;
}
|
{
$$ = 0;
}
;
Baseflag : T_FSHARED
{
#if EXE386
$$ = OBJ_SHARED;
#else
$$ = NSSHARED;
#endif
vfShrattr = (FTYPE) TRUE;
}
| T_FNONSHARED
{
vfShrattr = (FTYPE) TRUE;
#if EXE386
offmask |= OBJ_SHARED;
#else
offmask |= NSSHARED;
#endif
}
| T_FINVALID
{
#if EXE386
#endif
}
| T_FIOPL
{
#if EXE386
#else
$$ = (2 << SHIFTDPL) | NSMOVE;
offmask |= NSDPL;
#endif
}
| T_FNOIOPL
{
#if EXE386
#else
$$ = (3 << SHIFTDPL);
#endif
}
| T_FFIXED
{
#if NOT EXE386
offmask |= NSMOVE | NSDISCARD;
#endif
}
| T_FMOVABLE
{
#if NOT EXE386
$$ = NSMOVE;
#endif
}
| T_FPRELOAD
{
#if NOT EXE386
$$ = NSPRELOAD;
#endif
}
| T_FLOADONCALL
{
#if NOT EXE386
offmask |= NSPRELOAD;
#endif
}
| T_FHUGE
{
}
| T_FSWAPPABLE
{
}
| T_FRESIDENT
{
}
| T_FALIAS
{
}
| T_FMIXED
{
}
| T_FNONPERM
{
}
| T_FPERM
{
}
| T_FCONTIG
{
}
| T_FDYNAMIC
{
}
;
Exports : T_KEXPORTS Exportlist
| T_KEXPORTS
;
Exportlist : Exportlist Export
| Export
;
Export : Idname Internal Exportopts Exportflags ExportOtherFlags ScopeFlag
{
NewExport($1,$2,$3,$4);
}
;
Internal : T_EQ Idname
{
$$ = $2;
}
|
{
$$ = NULL;
}
;
Exportopts : T_AT T_NUMBER T_KRESIDENTNAME
{
$$ = $2;
nameFlags |= RES_NAME;
}
| T_AT T_NUMBER T_KNONAME
{
$$ = $2;
nameFlags |= NO_NAME;
}
| T_AT T_NUMBER
{
$$ = $2;
}
|
{
$$ = 0;
}
;
Exportflags : Nodata Parmwds
{
$$ = $1 | 1;
}
;
Nodata : T_KNODATA
{
/* return 0 */
}
|
{
$$ = 2;
}
;
Parmwds : T_NUMBER
{
}
|
{
}
;
ExportOtherFlags: T_KCONSTANT
{
#if EXE386
expOtherFlags |= 0x1;
#endif
}
|
{
}
;
ScopeFlag : T_FPRIVATE
|
;
Imports : T_KIMPORTS Importlist
| T_KIMPORTS
;
Importlist : Importlist Import
| Import
;
Import : Idname Internal T_DOT Idname ImportFlags
/*
* We'd like to have something like "Alias Idname T_DOT Idname" instead
* of using Internal, since Internal looks for =internal and we're
* looking for internal=. However, that would make this rule ambiguous
* with the next rule, and the 2nd would never be reduced. So we use
* Internal here as a kludge.
*/
{
if($2 != NULL)
{
#if EXE386
NewImport($4,0,$2,$1,$5);
#else
NewImport($4,0,$2,$1);
#endif
free($2);
}
else
#if EXE386
NewImport($4,0,$1,$4,$5);
#else
NewImport($4,0,$1,$4);
#endif
free($1);
free($4);
}
| Idname Internal T_DOT T_NUMBER ImportFlags
{
if ($2 == NULL)
Fatal(ER_dfimport);
#if EXE386
NewImport(NULL,$4,$2,$1,$5);
#else
NewImport(NULL,$4,$2,$1);
#endif
free($1);
free($2);
}
;
Idname : T_ID
{
$$ = _strdup(bufg);
}
| T_STRING
{
$$ = _strdup(bufg);
}
;
ImportFlags : T_KCONSTANT
{
$$ = 1;
}
|
{
$$ = 0;
}
;
ExeType : T_KEXETYPE
{
#if EXE386
fUserVersion = (FTYPE) FALSE;
#endif
}
ExeFlags ExeVersion
;
ExeFlags : T_FDOS
{
TargetOs = NE_DOS;
#if ODOS3EXE
fNewExe = FALSE;
#endif
}
| T_FOS2
{
TargetOs = NE_OS2;
}
| T_FUNKNOWN
{
TargetOs = NE_UNKNOWN;
}
| T_FWINDOWS
{
#if EXE386
TargetSubsys = E32_SSWINGUI;
#endif
TargetOs = NE_WINDOWS;// PROTMODE is default for WINDOWS
fRealMode = (FTYPE) FALSE;
#if NOT EXE386
vFlags |= NEPROT;
#endif
}
| T_FDEV386
{
TargetOs = NE_DEV386;
}
| T_FNT
{
#if EXE386
TargetSubsys = E32_SSWINGUI;
#endif
}
| T_FUNIX
{
#if EXE386
TargetSubsys = E32_SSPOSIXCHAR;
#endif
}
| T_FMACINTOSH T_FSWAPPABLE
{
#if O68K
iMacType = MAC_SWAP;
f68k = fTBigEndian = fNewExe = (FTYPE) TRUE;
/* If we are packing code to the default value, change the
default. */
if (fPackSet && packLim == LXIVK - 36)
packLim = LXIVK / 2;
#endif
}
| T_FMACINTOSH
{
#if O68K
iMacType = MAC_NOSWAP;
f68k = fTBigEndian = fNewExe = (FTYPE) TRUE;
/* If we are packing code to the default value, change the
default. */
if (fPackSet && packLim == LXIVK - 36)
packLim = LXIVK / 2;
#endif
}
;
ExeVersion : MajorVer T_DOT MinorVer
{
#if EXE386
if (fUserVersion)
{
UserMajorVer = (BYTE) $1;
UserMinorVer = (BYTE) $3;
}
else
#endif
{
ExeMajorVer = (BYTE) $1;
ExeMinorVer = (BYTE) $3;
}
}
| MajorVer
{
#if EXE386
if (fUserVersion)
{
UserMajorVer = (BYTE) $1;
UserMinorVer = 0;
}
else
#endif
{
ExeMajorVer = (BYTE) $1;
if(fNoExeVer)
ExeMinorVer = DEF_EXETYPE_WINDOWS_MINOR;
else
ExeMinorVer = 0;
}
}
;
MajorVer : T_NUMBER
{
$$ = $1;
}
|
{
$$ = ExeMajorVer;
fNoExeVer = TRUE;
}
;
MinorVer : T_NUMBER
{
if (cDigits >= 2)
$$ = $1;
else
$$ = 10 * $1;
}
|
{
$$ = ExeMinorVer;
}
;
UserVersion : T_KVERSION
{
#if EXE386
fUserVersion = (FTYPE) TRUE;
#endif
}
ExeVersion
;
SubSystem : T_KSUBSYSTEM SubSystemFlags
;
SubSystemFlags : T_FUNKNOWN
{
#if EXE386
TargetSubsys = E32_SSUNKNOWN;
#endif
}
| T_FWINDOWSNT
{
#if EXE386
TargetSubsys = E32_SSNATIVE;
#endif
}
| T_FOS2
{
#if EXE386
TargetSubsys = E32_SSOS2CHAR;
#endif
}
| T_FWINDOWS
{
#if EXE386
TargetSubsys = E32_SSWINGUI;
#endif
}
| T_FWINDOWSCHAR
{
#if EXE386
TargetSubsys = E32_SSWINCHAR;
#endif
}
| T_FPOSIX
{
#if EXE386
TargetSubsys = E32_SSPOSIXCHAR;
#endif
}
;
ProcOrder : T_FUNCTIONS
{
if (szSegName != NULL)
{
free(szSegName);
szSegName = NULL;
}
#if OVERLAYS
iOvl = NOTIOVL;
#endif
}
SegOrOvl ProcList
;
SegOrOvl : T_COLON NameOrNumber
|
;
NameOrNumber : Idname
{
if (szSegName == NULL)
szSegName = $1;
#if OVERLAYS
iOvl = NOTIOVL;
#endif
}
| T_NUMBER
{
#if OVERLAYS
iOvl = $1;
fOverlays = (FTYPE) TRUE;
fNewExe = FALSE;
TargetOs = NE_DOS;
#endif
}
;
ProcList : ProcList ProcName
| ProcName
;
ProcName : Idname
{
NewProc($1);
}
;
%%
LOCAL int NEAR GetChar(void)
{
int c; /* A character */
c = GetTxtChr(bsInput);
if ((c == EOF || c == CTRL_Z) && curLevel > 0)
{
free(bsInput->_base);
fclose(bsInput);
bsInput = includeDisp[curLevel];
curLevel--;
c = GetChar();
}
return(c);
}
LOCAL int NEAR lookup() /* Keyword lookup */
{
char **pcp; /* Pointer to character pointer */
int i; /* Comparison value */
for(pcp = keywds; *pcp != NULL; pcp += 2)
{ /* Look through keyword table */
/* If found, return token type */
if(!(i = _stricmp(&bufg[1],*pcp)))
{
YYS_WD(yylval) = 0;
return((int) (__int64) pcp[1]);
}
if(i < 0) break; /* Break if we've gone too far */
}
return(T_ID); /* Just your basic identifier */
}
LOCAL int NEAR yylex() /* Lexical analyzer */
{
int c; /* A character */
int StrBegChr; /* What kind of quotte found at the begin of string */
#if EXE386
DWORD x; /* Numeric token value */
#else
WORD x; /* Numeric token value */
#endif
int state; /* State variable */
BYTE *cp; /* Character pointer */
BYTE *sz; /* Zero-terminated string */
static int lastc = 0; /* Previous character */
char *fileBuf;
FTYPE fFileNameSave;
static int NameLineNo;
state = 0; /* Assume we're not in a comment */
c = '\0';
/* Loop to skip white space */
for(;;)
{
lastc = c;
if (((c = GetChar()) == EOF) || c == '\032' || c == '\377')
return(EOF); /* Get a character */
if (c == ';')
state = TRUE; /* If comment, set flag */
else if(c == '\n') /* If end of line */
{
state = FALSE; /* End of comment */
if(!curLevel)
++yylineno; /* Increment line number count */
}
else if (state == FALSE && c != ' ' && c != '\t' && c != '\r')
break; /* Break on non-white space */
}
/* Handle one-character tokens */
switch(c)
{
case '.': /* Name separator */
if (fFileNameExpected)
break;
return(T_DOT);
case '@': /* Ordinal specifier */
/*
* Require that whitespace precede '@' if introducing an
* ordinal, to allow '@' in identifiers.
*/
if (lastc == ' ' || lastc == '\t' || lastc == '\r')
return(T_AT);
break;
case '=': /* Name assignment */
return(T_EQ);
case ':':
return(T_COLON);
case ',':
return(T_COMA);
}
/* See if token is a number */
if (c >= '0' && c <= '9' && !fFileNameExpected)
{ /* If token is a number */
x = c - '0'; /* Get first digit */
c = GetChar(); /* Get next character */
if(x == 0) /* If octal or hex */
{
if(c == 'x' || c == 'X') /* If it is an 'x' */
{
state = 16; /* Base is hexadecimal */
c = GetChar(); /* Get next character */
}
else state = 8; /* Else octal */
cDigits = 0;
}
else
{
state = 10; /* Else decimal */
cDigits = 1;
}
for(;;)
{
if(c >= '0' && c <= '9' && c < (state + '0')) c -= '0';
else if(state == 16 && c >= 'A' && c <= 'F') c -= 'A' - 10;
else if(state == 16 && c >= 'a' && c <= 'f') c -= 'a' - 10;
else break;
cDigits++;
x = x*state + c;
c = (BYTE) GetChar();
}
ungetc(c,bsInput);
YYS_WD(yylval) = x;
return(T_NUMBER);
}
/* See if token is a string */
if (c == '\'' || c == '"') /* If token is a string */
{
StrBegChr = c;
sz = &bufg[1]; /* Initialize */
for(state = 0; state != 2;) /* State machine loop */
{
if ((c = GetChar()) == EOF)
return(EOF); /* Check for EOF */
if (sz >= &bufg[sizeof(bufg)])
Fatal(ER_dflinemax, sizeof(bufg));
switch(state) /* Transitions */
{
case 0: /* Inside quote */
if ((c == '\'' || c == '"') && c == StrBegChr)
state = 1; /* Change state if quote found */
else
*sz++ = (BYTE) c; /* Else save character */
break;
case 1: /* Inside quote with quote */
if ((c == '\'' || c == '"'))
{ /* If consecutive quotes */
*sz++ = (BYTE) c; /* Quote inside string */
state = 0; /* Back to state 0 */
}
else
state = 2; /* Else end of string */
break;
}
}
ungetc(c,bsInput); /* Put back last character */
*sz = '\0'; /* Null-terminate the string */
x = (WORD)(sz - &bufg[1]);
if (x >= SBLEN) /* Set length of string */
{
bufg[0] = 0xff;
bufg[0x100] = '\0';
OutWarn(ER_dfnamemax, &bufg[1]);
}
else
bufg[0] = (BYTE) x;
YYS_BP(yylval) = bufg; /* Save ptr. to identifier */
return(T_STRING); /* String found */
}
/* Assume we have identifier */
sz = &bufg[1]; /* Initialize */
if (fFileNameExpected && NameLineNo && NameLineNo != yylineno)
{
NameLineNo = 0; /* To avoid interference with INCLUDE */
fFileNameExpected = FALSE;
}
for(;;) /* Loop to get i.d.'s */
{
if (fFileNameExpected)
cp = " \t\r\n\f";
else
cp = " \t\r\n:.=';\032";
while (*cp && *cp != (BYTE) c)
++cp; /* Check for end of identifier */
if(*cp) break; /* Break if end of identifier found */
if (sz >= &bufg[sizeof(bufg)])
Fatal(ER_dflinemax, sizeof(bufg));
*sz++ = (BYTE) c; /* Save the character */
if ((c = GetChar()) == EOF)
break; /* Get next character */
}
ungetc(c,bsInput); /* Put character back */
*sz = '\0'; /* Null-terminate the string */
x = (WORD)(sz - &bufg[1]);
if (x >= SBLEN) /* Set length of string */
{
bufg[0] = 0xff;
bufg[0x100] = '\0';
OutWarn(ER_dfnamemax, &bufg[1]);
}
else
bufg[0] = (BYTE) x;
YYS_BP(yylval) = bufg; /* Save ptr. to identifier */
state = lookup();
if (state == T_KNAME || state == T_KLIBRARY)
{
fFileNameExpected = TRUE;
NameLineNo = yylineno;
}
if (state == INCLUDE_DIR)
{
// Process include directive
fFileNameSave = fFileNameExpected;
fFileNameExpected = (FTYPE) TRUE;
state = yylex();
fFileNameExpected = fFileNameSave;
if (state == T_ID || state == T_STRING)
{
if (curLevel < MAX_NEST - 1)
{
curLevel++;
includeDisp[curLevel] = bsInput;
// Because LINK uses customized version of stdio
// for every file we have not only open the file
// but also allocate i/o buffer.
bsInput = fopen(&bufg[1], RDBIN);
if (bsInput == NULL)
Fatal(ER_badinclopen, &bufg[1], strerror(errno));
fileBuf = GetMem(IO_BUF_SIZE);
#if OSMSDOS
setvbuf(bsInput, fileBuf, _IOFBF, IO_BUF_SIZE);
#endif
return(yylex());
}
else
Fatal(ER_toomanyincl);
}
else
Fatal(ER_badinclname);
}
else
return(state);
}
LOCAL void NEAR yyerror(str)
char *str;
{
Fatal(ER_dfsyntax, str);
}
#if NOT EXE386
/*** AppLoader - define aplication specific loader
*
* Purpose:
* Define application specific loader. Feature available only under
* Windows. Linker will create logical segment LOADER_<name> where
* <name> is specified in APPLOADER statement. The LOADER_<name>
* segment forms separate physical segment, which is placed by the linker
* as the first segment in the .EXE file. Whithin the loader segment,
* the linker will create an EXTDEF of the name <name>.
*
* Input:
* - sbName - pointer to lenght prefixed loader name
*
* Output:
* No explicit value is returned. As a side effect the SEGDEF and
* EXTDEF definitions are entered into linker symbol table.
*
* Exceptions:
* None.
*
* Notes:
* None.
*
*************************************************************************/
LOCAL void NEAR AppLoader(char *sbName)
{
APROPSNPTR apropSn;
APROPUNDEFPTR apropUndef;
SBTYPE segName;
WORD strLen;
// Create loader segment name
strcpy(&segName[1], "LOADER_");
strcat(&segName[1], &sbName[1]);
strLen = strlen(&segName[1]);
if (strLen >= SBLEN)
{
segName[0] = SBLEN - 1;
segName[SBLEN] = '\0';
OutWarn(ER_dfnamemax, &segName[1]);
}
else
segName[0] = (BYTE) strLen;
// Define loader logical segment and remember its GSN
apropSn = GenSeg(segName, "\004CODE", GRNIL, (FTYPE) TRUE);
gsnAppLoader = apropSn->as_gsn;
apropSn->as_flags = dfCode | NSMOVE | NSPRELOAD;
MARKVP();
// Define EXTDEF
apropUndef = (APROPUNDEFPTR ) PROPSYMLOOKUP(sbName, ATTRUND, TRUE);
vpropAppLoader = vrprop;
apropUndef->au_flags |= STRONGEXT;
apropUndef->au_len = -1L;
MARKVP();
free(sbName);
}
#endif
/*** NewProc - fill in the COMDAT descriptor for ordered procedure
*
* Purpose:
* Fill in the linkers symbol table COMDAT descriptor. This function
* is called for new descriptors generated by FUNCTIONS list in the .DEF
* file. All COMDAT descriptors entered by this function form one
* list linked via ac_order field. The head of this list is global
* variable procOrder;
*
* Input:
* szName - pointer to procedure name
* iOvl - overlay number - global variable
* szSegName - segment name - global variable
*
* Output:
* No explicit value is returned. As a side effect symbol table entry
* is updated.
*
* Exceptions:
* Procedure already known - warning
*
* Notes:
* None.
*
*************************************************************************/
LOCAL void NEAR NewProc(char *szName)
{
RBTYPE vrComdat; // Virtual pointer to COMDAT symbol table entry
APROPCOMDATPTR apropComdat; // Real pointer to COMDAT symbol table descriptor
static RBTYPE lastProc; // Last procedure on the list
APROPSNPTR apropSn;
apropComdat = (APROPCOMDATPTR ) PROPSYMLOOKUP(szName, ATTRCOMDAT, FALSE);
if ((apropComdat != NULL) && (apropComdat->ac_flags & ORDER_BIT))
OutWarn(ER_duporder, &szName[1]);
else
{
apropComdat = (APROPCOMDATPTR ) PROPSYMLOOKUP(szName, ATTRCOMDAT, TRUE);
vrComdat = vrprop;
// Fill in the COMDAT descriptor
apropComdat->ac_flags = ORDER_BIT;
#if OVERLAYS
apropComdat->ac_iOvl = iOvl;
// Set the maximum overlay index
if (iOvl != NOTIOVL)
{
fOverlays = (FTYPE) TRUE;
fNewExe = FALSE;
if (iOvl >= iovMac)
iovMac = iOvl + 1;
}
#endif
if (szSegName != NULL)
{
apropSn = GenSeg(szSegName, "\004CODE", GRNIL, (FTYPE) TRUE);
apropSn->as_flags = dfCode;
// Allocate COMDAT in the segment
apropComdat->ac_gsn = apropSn->as_gsn;
apropComdat->ac_selAlloc = PICK_FIRST | EXPLICIT;
AttachComdat(vrComdat, apropSn->as_gsn);
}
else
apropComdat->ac_selAlloc = ALLOC_UNKNOWN;
MARKVP(); // Page has been changed
// Attach this COMDAT to the ordered procedure list
if (procOrder == VNIL)
procOrder = vrComdat;
else
{
apropComdat = (APROPCOMDATPTR ) FETCHSYM(lastProc, TRUE);
apropComdat->ac_order = vrComdat;
}
lastProc = vrComdat;
}
free(szName);
}
LOCAL void NEAR ProcNamTab(lfa,cb,fres)
long lfa; /* Table starting address */
WORD cb; /* Length of table */
WORD fres; /* Resident name flag */
{
SBTYPE sbExport; /* Exported symbol name */
WORD ordExport; /* Export ordinal */
APROPEXPPTR exp; /* Export symbol table entry */
fseek(bsInput,lfa,0); /* Seek to start of table */
for(cbRec = cb; cbRec != 0; ) /* Loop through table */
{
sbExport[0] = (BYTE) getc(bsInput);/* Get length of name */
fread(&sbExport[1], sizeof(char), B2W(sbExport[0]), bsInput);
/* Get export name */
ordExport = getc(bsInput) | (getc(bsInput) << BYTELN);
if (ordExport == 0) continue;
/* Skip if no ordinal assigned */
exp = (APROPEXPPTR ) PROPSYMLOOKUP(sbExport, ATTREXP, FALSE);
/* Look the export up */
if(exp == PROPNIL || exp->ax_ord != 0) continue;
/* Must exist and be unassigned */
exp->ax_ord = ordExport; /* Assign ordinal */
if (fres)
exp->ax_nameflags |= RES_NAME;
/* Set flag if from resident table */
MARKVP(); /* Page has been changed */
}
}
#if NOT EXE386
LOCAL void NEAR SetExpOrds(void)/* Set export ordinals */
{
struct exe_hdr ehdr; /* Old .EXE header */
struct new_exe hdr; /* New .EXE header */
long lfahdr; /* File offset of header */
if((bsInput = LinkOpenExe(sbOldver)) == NULL)
{ /* If old version can't be opened */
/* Error message and return */
OutWarn(ER_oldopn);
return;
}
SETRAW(bsInput); /* Dec 20 hack */
xread(&ehdr,CBEXEHDR,1,bsInput); /* Read old header */
if(E_MAGIC(ehdr) == EMAGIC) /* If old header found */
{
if(E_LFARLC(ehdr) != sizeof(struct exe_hdr))
{ /* If no new .EXE in this file */
/* Error message and return */
OutWarn(ER_oldbad);
return;
}
lfahdr = E_LFANEW(ehdr); /* Get file address of new header */
}
else lfahdr = 0L; /* Else no old header */
fseek(bsInput,lfahdr,0); /* Seek to new header */
xread(&hdr,CBNEWEXE,1,bsInput); /* Read the header */
if(NE_MAGIC(hdr) == NEMAGIC) /* If correct magic number */
{
ProcNamTab(lfahdr+NE_RESTAB(hdr),(WORD)(NE_MODTAB(hdr) - NE_RESTAB(hdr)),(WORD)TRUE);
/* Process Resident Name table */
ProcNamTab(NE_NRESTAB(hdr),NE_CBNRESTAB(hdr),FALSE);
/* Process Non-resident Name table */
}
else OutWarn(ER_oldbad);
fclose(bsInput); /* Close old file */
}
#endif
LOCAL void NEAR NewDescription(BYTE *sbDesc)
{
#if NOT EXE386
if (NonResidentName.byteMac > 3)
Fatal(ER_dfdesc); /* Should be first time */
AddName(&NonResidentName, sbDesc, 0);
/* Description 1st in non-res table */
#endif
}
#if EXE386
LOCAL void NEAR NewModule(BYTE *sbModnam, BYTE *defaultExt)
#else
LOCAL void NEAR NewModule(BYTE *sbModnam)
#endif
{
WORD length; /* Length of symbol */
#if EXE386
SBTYPE sbModule;
BYTE *pName;
#endif
if(rhteModule != RHTENIL) Fatal(ER_dfname);
/* Check for redefinition */
PROPSYMLOOKUP(sbModnam, ATTRNIL, TRUE);
/* Create hash table entry */
rhteModule = vrhte; /* Save virtual hash table address */
#if EXE386
memcpy(sbModule, sbModnam, sbModnam[0] + 1);
if (sbModule[sbModule[0]] == '.')
{
sbModule[sbModule[0]] = '\0';
length = sbModule[0];
pName = &sbModule[1];
}
else
{
UpdateFileParts(sbModule, defaultExt);
length = sbModule[0] - 2;
pName = &sbModule[4];
}
if (TargetOs == NE_WINDOWS)
SbUcase(sbModule); /* Make upper case */
vmmove(length, pName, AREAEXPNAME, TRUE);
/* Module name 1st in Export Name Table */
cbExpName = length;
#else
if (TargetOs == NE_WINDOWS)
SbUcase(sbModnam); /* Make upper case */
AddName(&ResidentName, sbModnam, 0);/* Module name 1st in resident table */
#endif
fFileNameExpected = (FTYPE) FALSE;
}
void NewExport(sbEntry,sbInternal,ordno,flags)
BYTE *sbEntry; /* Entry name */
BYTE *sbInternal; /* Internal name */
WORD ordno; /* Ordinal number */
WORD flags; /* Flag byte */
{
APROPEXPPTR export; /* Export record */
APROPUNDEFPTR undef; /* Undefined symbol */
APROPNAMEPTR PubName; /* Defined name */
BYTE *sb; /* Internal name */
BYTE ParWrds; /* # of parameter words */
RBTYPE rbSymdef; /* Virtual addr of symbol definition */
#if EXE386
RBTYPE vExport; /* Virtual pointer to export descriptor */
APROPNAMEPTR public; /* Matching public symbol */
#endif
#if DEBUG
fprintf(stdout,"\r\nEXPORT: ");
OutSb(stdout,sbEntry);
NEWLINE(stdout);
if(sbInternal != NULL)
{
fprintf(stdout,"INTERNAL NAME: ");
OutSb(stdout,sbInternal);
NEWLINE(stdout);
}
fprintf(stdout, " ordno %u, flags %u ", (unsigned)ordno, (unsigned)flags);
fflush(stdout);
#endif
sb = (sbInternal != NULL)? sbInternal: sbEntry;
/* Get pointer to internal name */
PubName = (APROPNAMEPTR ) PROPSYMLOOKUP(sb, ATTRPNM, FALSE);
#if NOT EXE386
if(PubName != PROPNIL && !fDrivePass)
/* If internal name already exists as a public symbol
* and we are parsing definition file, issue
* export internal name conflict warning.
*/
OutWarn(ER_expcon,sbEntry+1,sb+1);
else /* Else if no conflict */
{
#endif
if (PubName == PROPNIL) /* If no matching name exists */
undef = (APROPUNDEFPTR ) PROPSYMLOOKUP(sb,ATTRUND, TRUE);
/* Make undefined symbol entry */
#if TCE
#if TCE_DEBUG
fprintf(stdout, "\r\nNewExport adds UNDEF %s ", 1+GetPropName(undef));
#endif
undef->au_fAlive = TRUE; /* all exports are potential entry points */
#endif
rbSymdef = vrprop; /* Save virtual address */
if (PubName == PROPNIL) /* If this is a new symbol */
undef->au_len = -1L; /* Make no type assumptions */
export = (APROPEXPPTR ) PROPSYMLOOKUP(sbEntry,ATTREXP, TRUE);
/* Create export record */
#if EXE386
vExport = vrprop;
#endif
if(vfCreated) /* If this is a new entry */
{
export->ax_symdef = rbSymdef;
/* Save virt addr of symbol def */
export->ax_ord = ordno;
/* Save ordinal number */
if (nameFlags & RES_NAME)
export->ax_nameflags |= RES_NAME;
/* Remember if resident */
else if (nameFlags & NO_NAME)
export->ax_nameflags |= NO_NAME;
/* Remember to discard name */
export->ax_flags = (BYTE) flags;
/* Save flags */
++expMac; /* One more exported symbol */
}
else
{
if (!fDrivePass) /* Else if parsing definition file */
/* multiple definitions */
OutWarn(ER_expmul,sbEntry + 1);
/* Output error message */
else
{ /* We were called for EXPDEF object */
/* record, so we merge information */
ParWrds = (BYTE) (export->ax_flags & 0xf8);
if (ParWrds && (ParWrds != (BYTE) (flags & 0xf8)))
Fatal(ER_badiopl);
/* If the iopl_parmwords field in the */
/* .DEF file is not 0 and does not match */
/* value in the EXPDEF exactly issue error */
else if (!ParWrds)
{ /* Else set value from EXPDEF record */
ParWrds = (BYTE) (flags & 0xf8);
export->ax_flags |= ParWrds;
}
}
}
#if EXE386
if (PubName != NULL)
{
if (expOtherFlags & 0x1)
{
export->ax_nameflags |= CONSTANT;
expOtherFlags = 0;
}
}
#endif
#if NOT EXE386
}
#endif
if(!(flags & 0x8000))
{
free(sbEntry); /* Free space */
if(sbInternal != NULL) free(sbInternal);
}
/* Free space */
nameFlags = 0;
}
LOCAL APROPIMPPTR NEAR GetImport(sb) /* Get name in Imported Names Table */
BYTE *sb; /* Length-prefixed names */
{
APROPIMPPTR import; /* Pointer to imported name */
#if EXE386
DWORD cbTemp; /* Temporary value */
#else
WORD cbTemp; /* Temporary value */
#endif
RBTYPE rprop; /* Property cell virtual address */
import = (APROPIMPPTR ) PROPSYMLOOKUP(sb,ATTRIMP, TRUE);
/* Look up module name */
if(vfCreated) /* If no offset assigned yet */
{
rprop = vrprop; /* Save the virtual address */
/*
* WARNING: We must store name in virtual memory now, otherwise
* if an EXTDEF was seen first, fIgnoreCase is false, and the
* cases do not match between the imported name and the EXTDEF,
* then the name will not go in the table exactly as given.
*/
import = (APROPIMPPTR) FETCHSYM(rprop,TRUE);
/* Retrieve from symbol table */
import->am_offset = AddImportedName(sb);
/* Save offset */
}
return(import); /* Return offset in table */
}
#if NOT EXE386
void NewImport(sbEntry,ordEntry,sbModule,sbInternal)
BYTE *sbEntry; /* Entry point name */
WORD ordEntry; /* Entry point ordinal */
BYTE *sbModule; /* Module name */
BYTE *sbInternal; /* Internal name */
{
APROPNAMEPTR public; /* Public symbol */
APROPIMPPTR import; /* Imported symbol */
BYTE *sb; /* Symbol pointer */
WORD module; /* Module name offset */
FTYPE flags; /* Import flags */
WORD modoff; /* module name offset */
WORD entry; /* Entry name offset */
BYTE *cp; /* Char pointer */
RBTYPE rpropundef; /* Address of undefined symbol */
char buf[32]; /* Buffer for error sgring */
#if DEBUG
fprintf(stderr,"\r\nIMPORT: ");
OutSb(stderr,sbModule);
fputc('.',stderr);
if(!ordEntry)
{
OutSb(stderr,sbEntry);
}
else fprintf(stderr,"%u",ordEntry);
if(sbInternal != sbEntry)
{
fprintf(stderr," ALIAS: ");
OutSb(stderr,sbInternal);
}
fprintf(stdout," ordEntry %u ", (unsigned)ordEntry);
fflush(stdout);
#endif
if((public = (APROPNAMEPTR ) PROPSYMLOOKUP(sbInternal, ATTRUND, FALSE)) !=
PROPNIL && !fDrivePass) /* If internal names conflict */
{
if(sbEntry != NULL)
sb = sbEntry;
else
{
sprintf(buf + 1,"%u",ordEntry);
sb = buf;
}
OutWarn(ER_impcon,sbModule + 1,sb + 1,sbInternal + 1);
}
else /* Else if no conflicts */
{
rpropundef = vrprop; /* Save virtual address of extern */
flags = FIMPORT; /* We have an imported symbol */
if (TargetOs == NE_WINDOWS)
SbUcase(sbModule); /* Force module name to upper case */
import = GetImport(sbModule); /* Get pointer to import record */
if((module = import->am_mod) == 0)
{
// If not in Module Reference Table
import->am_mod = WordArrayPut(&ModuleRefTable, import->am_offset) + 1;
/* Save offset of name in table */
module = import->am_mod;
}
if(vrhte == rhteModule) /* If importing from this module */
{
if(sbEntry != NULL)
sb = sbEntry;
else
{
sprintf(buf+1,"%u",ordEntry);
sb = buf;
}
if (TargetOs == NE_OS2)
OutWarn(ER_impself,sbModule + 1,sb + 1,sbInternal + 1);
else
OutError(ER_impself,sbModule + 1,sb + 1,sbInternal + 1);
}
if(sbEntry == NULL) /* If entry by ordinal */
{
flags |= FIMPORD; /* Set flag bit */
entry = ordEntry; /* Get ordinal number */
}
else /* Else if import by name */
{
if(fIgnoreCase) SbUcase(sbEntry);
/* Upper case the name if flag set */
import = GetImport(sbEntry);
entry = import->am_offset;
/* Get offset of name in table */
}
if(public == PROPNIL) /* If no undefined symbol */
{
public = (APROPNAMEPTR )
PROPSYMLOOKUP(sbInternal,ATTRPNM, TRUE);
/* Make a public symbol */
if(!vfCreated) /* If not new */
/* Output error message */
OutWarn(ER_impmul,sbInternal + 1);
else ++pubMac; /* Else increment public count */
}
else /* Else if symbol is undefined */
{
public = (APROPNAMEPTR ) FETCHSYM(rpropundef,TRUE);
/* Look up external symbol */
++pubMac; /* Increment public symbol count */
}
flags |= FPRINT; /* Symbol is printable */
public->an_attr = ATTRPNM; /* This is a public symbol */
public->an_gsn = SNNIL; /* Not a segment member */
public->an_ra = 0; /* No known offset */
public->an_ggr = GRNIL; /* Not a group member */
public->an_flags = flags; /* Set flags */
public->an_entry = entry; /* Save entry specification */
public->an_module = module; /* Save Module Reference Table index */
#if SYMDEB AND FALSE
if (fSymdeb) /* If debugger support on */
{
if (flags & FIMPORD)
import = GetImport(sbInternal);
else /* Add internal name to Imported Name Table */
import = GetImport(sbEntry);
import->am_public = public;
/* Remember public symbol */
if (cbImpSeg < LXIVK-1)
cbImpSeg += sizeof(CVIMP);
}
#endif
}
}
#endif
#if OVERLAYS
extern void NEAR GetName(AHTEPTR ahte, BYTE *pBuf);
#endif
/*** NewSeg - new segment definition
*
* Purpose:
* Create new segment definition based on the module definition
* file segment description. Check for duplicate definitions and
* overlay index inconsistency between attached COMDATs (if any)
* and segment itself.
*
* Input:
* sbName - segment name
* sbClass - segment class
* iOvl - segment overlay index
* flags - segment attributes
*
* Output:
* No explicit value is returned. The segment descriptor in
* symbol table is created or updated.
*
* Exceptions:
* Multiple segment definitions - warning and continue
* Change in overlay index - warning and continue
*
* Notes:
* None.
*
*************************************************************************/
void NEAR NewSeg(BYTE *sbName, BYTE *sbClass, WORD iOvl,
#if EXE386
DWORD flags)
#else
WORD flags)
#endif
{
APROPSNPTR apropSn; // Pointer to segment descriptor
#if OVERLAYS
RBTYPE vrComdat; // Virtual pointer to COMDAT descriptor
APROPCOMDATPTR apropComdat; // Symbol table entry for COMDAT symbol
SBTYPE sbComdat; // Name buffer
#endif
// Set segment attributes based on the class
if (SbSuffix(sbClass,"\004CODE",TRUE))
flags |= dfCode & ~offmask;
else
flags |= dfData & ~offmask;
#if O68K
if (f68k)
flags |= NS32BIT;
#endif
#if OVERLAYS
if (iOvl != NOTIOVL)
{
fOverlays = (FTYPE) TRUE;
fNewExe = FALSE;
if (iOvl >= iovMac) // Set the maximum overlay index
iovMac = iOvl + 1;
}
#endif
// Generate new segment definition
apropSn = GenSeg(sbName, sbClass, GRNIL, (FTYPE) TRUE);
if (vfCreated)
{
apropSn->as_flags = (WORD) flags;
// Save flags
mpgsndra[apropSn->as_gsn] = 0; // Initialize
#if OVERLAYS
apropSn->as_iov = iOvl; // Save overlay index
if (fOverlays)
CheckOvl(apropSn, iOvl);
#endif
apropSn->as_fExtra |= (BYTE) FROM_DEF_FILE;
// Remember defined in def file
if (fMixed)
{
apropSn->as_fExtra |= (BYTE) MIXED1632;
fMixed = (FTYPE) FALSE;
}
}
else
{
apropSn = CheckClass(apropSn, apropSn->as_rCla);
// Check if previous definition had the same class
OutWarn(ER_segdup,sbName + 1); // Warn about multiple definition
#if OVERLAYS
if (fOverlays && apropSn->as_iov != iOvl)
{
if (apropSn->as_iov != NOTIOVL)
OutWarn(ER_badsegovl, 1 + GetPropName(apropSn), apropSn->as_iov, iOvl);
apropSn->as_iov = iOvl; // Save new overlay index
CheckOvl(apropSn, iOvl);
// Check if segment has any COMDATs and if it has
// then check theirs overlay numbers
for (vrComdat = apropSn->as_ComDat;
vrComdat != VNIL;
vrComdat = apropComdat->ac_sameSeg)
{
apropComdat = (APROPCOMDATPTR ) FetchSym(vrComdat, FALSE);
if (apropComdat->ac_iOvl != NOTIOVL && apropComdat->ac_iOvl != iOvl)
{
GetName((AHTEPTR) apropComdat, sbComdat);
OutWarn(ER_badcomdatovl, &sbComdat[1], apropComdat->ac_iOvl, iOvl);
}
apropComdat->ac_iOvl = iOvl;
}
}
#endif
}
free(sbClass); // Free class name
free(sbName); // Free segment name
offmask = 0;
// Unless packing limit already set, disable default code packing
if (!fPackSet)
{
fPackSet = (FTYPE) TRUE; // Remember packLim was set
packLim = 0L;
}
}
/*
* Assign module name to be default, which is run file name.
*
* SIDE EFFECTS
* Assigns rhteModule
*/
#if EXE386
LOCAL void NEAR DefaultModule (unsigned char *defaultExt)
#else
LOCAL void NEAR DefaultModule (void)
#endif
{
SBTYPE sbModname; /* Module name */
AHTEPTR ahte; /* Pointer to hash table entry */
#if OSXENIX
int i;
#endif
ahte = (AHTEPTR ) FETCHSYM(rhteRunfile,FALSE);
/* Get executable file name */
#if OSMSDOS
memcpy(sbModname,GetFarSb(ahte->cch),B2W(ahte->cch[0]) + 1);
/* Copy file name */
#if EXE386
NewModule(sbModname, defaultExt); /* Use run file name as module name */
#else
UpdateFileParts(sbModname,"\005A:\\.X");
/* Force path, ext with known length */
sbModname[0] -= 2; /* Remove extension from name */
sbModname[3] = (BYTE) (sbModname[0] - 3);
/* Remove path and drive from name */
NewModule(&sbModname[3]); /* Use run file name as module name */
#endif
#endif
#if OSXENIX
for(i = B2W(ahte->cch[0]); i > 0 && ahte->cch[i] != '/'; i--)
sbModname[0] = B2W(ahte->cch[0]) - i;
memcpy(sbModname+1,&GetFarSb(ahte->cch)[i+1],B2W(sbModname[0]));
for(i = B2W(ahte->cch[0]); i > 1 && sbModname[i] != '.'; i--);
if(i > 1)
sbModname[0] = i - 1;
NewModule(sbModname); /* Use run file name as module name */
#endif
}
void ParseDeffile(void)
{
SBTYPE sbDeffile; /* Definitions file name */
AHTEPTR ahte; /* Pointer to hash table entry */
#if OSMSDOS
char buf[512]; /* File buffer */
#endif
if(rhteDeffile == RHTENIL) /* If no definitions file */
#if EXE386
DefaultModule(moduleEXE);
#else
DefaultModule();
#endif
else /* Else if there is a file to parse */
{
#if ODOS3EXE
fNewExe = (FTYPE) TRUE; /* Def file forces new-format exe */
#endif
ahte = (AHTEPTR ) FETCHSYM(rhteDeffile,FALSE);
/* Fetch file name */
memcpy(sbDeffile,GetFarSb(ahte->cch),B2W(ahte->cch[0]) + 1);
/* Copy file name */
sbDeffile[B2W(sbDeffile[0]) + 1] = '\0';
/* Null-terminate the name */
if((bsInput = fopen(&sbDeffile[1],RDTXT)) == NULL)
{ /* If open fails */
Fatal(ER_opndf, &sbDeffile[1]);/* Fatal error */
}
#if OSMSDOS
setvbuf(bsInput,buf,_IOFBF,sizeof(buf));
#endif
includeDisp[0] = bsInput; // Initialize include stack
sbOldver = NULL; /* Assume no old version */
yylineno = 1;
fFileNameExpected = (FTYPE) FALSE;
// HACK ALERT !!!
// Don't allocate to much page buffers
yyparse(); /* Parse the definitions file */
yylineno = -1;
fclose(bsInput); /* Close the definitions file */
#if NOT EXE386
if(sbOldver != NULL) /* If old version given */
{
SetExpOrds(); /* Use old version to set ordinals */
free(sbOldver); /* Release the space */
}
#endif
}
#if OSMSDOS
#endif /* OSMSDOS */
#if NOT EXE386
if (NonResidentName.byteMac == 0)
{
ahte = (AHTEPTR ) FETCHSYM(rhteRunfile,FALSE);
/* Get executable file name */
memcpy(sbDeffile,GetFarSb(ahte->cch),B2W(ahte->cch[0]) + 1);
/* Copy file name */
#if OSXENIX
SbUcase(sbDeffile); /* For identical executables */
#endif
if ((vFlags & NENOTP) && TargetOs == NE_OS2)
UpdateFileParts(sbDeffile, sbDotDll);
else
UpdateFileParts(sbDeffile, sbDotExe);
NewDescription(sbDeffile); /* Use run file name as description */
}
#endif
}