mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2350 lines
72 KiB
2350 lines
72 KiB
/* 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
|
|
}
|