Source code of Windows XP (NT5)
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.

1963 lines
65 KiB

  1. /*
  2. * MODIFICATION HISTORY
  3. *
  4. * M001 07/08/87 rlb
  5. * - Added NOIOPL recognition (PTM 6075).
  6. * - Version number changed to 1.00.01.
  7. * M002 10/05/87 rlb
  8. * - Added REALMODE
  9. * - Version number ==> 1.00.02
  10. */
  11. %token T_FALIAS
  12. %token T_KCLASS
  13. %token T_KNAME
  14. %token T_KLIBRARY
  15. %token T_KBASE
  16. %token T_KDEVICE
  17. %token T_KPHYSICAL
  18. %token T_KVIRTUAL
  19. %token T_ID
  20. %token T_NUMBER
  21. %token T_KDESCRIPTION
  22. %token T_KHEAPSIZE
  23. %token T_KSTACKSIZE
  24. %token T_KMAXVAL
  25. %token T_KCODE
  26. %token T_KCONSTANT
  27. %token <_wd> T_FDISCARDABLE T_FNONDISCARDABLE
  28. %token T_FEXEC
  29. %token T_FFIXED
  30. %token T_FMOVABLE
  31. %token T_FSWAPPABLE
  32. %token T_FSHARED
  33. %token T_FMIXED
  34. %token T_FNONSHARED
  35. %token T_FPRELOAD
  36. %token T_FINVALID
  37. %token T_FLOADONCALL
  38. %token T_FRESIDENT
  39. %token T_FPERM
  40. %token T_FCONTIG
  41. %token T_FDYNAMIC
  42. %token T_FNONPERM
  43. %token T_KDATA
  44. %token T_FNONE
  45. %token T_FSINGLE
  46. %token T_FMULTIPLE
  47. %token T_KSEGMENTS
  48. %token T_KOBJECTS
  49. %token T_KSECTIONS
  50. %token T_KSTUB
  51. %token T_KEXPORTS
  52. %token T_KEXETYPE
  53. %token T_KSUBSYSTEM
  54. %token T_FDOS
  55. %token T_FOS2
  56. %token T_FUNKNOWN
  57. %token T_FWINDOWS
  58. %token T_FDEV386
  59. %token T_FMACINTOSH
  60. %token T_FWINDOWSNT
  61. %token T_FWINDOWSCHAR
  62. %token T_FPOSIX
  63. %token T_FNT
  64. %token T_FUNIX
  65. %token T_KIMPORTS
  66. %token T_KNODATA
  67. %token T_KOLD
  68. %token T_KCONFORM
  69. %token T_KNONCONFORM
  70. %token T_KEXPANDDOWN T_KNOEXPANDDOWN
  71. %token T_EQ
  72. %token T_AT
  73. %token T_KRESIDENTNAME
  74. %token T_KNONAME
  75. %token T_STRING
  76. %token T_DOT
  77. %token T_COLON
  78. %token T_COMA
  79. %token T_ERROR
  80. %token T_FHUGE T_FIOPL T_FNOIOPL
  81. %token T_PROTMODE
  82. %token T_FEXECREAD T_FRDWR
  83. %token T_FRDONLY
  84. %token T_FINITGLOB T_FINITINST T_FTERMINST
  85. %token T_FWINAPI T_FWINCOMPAT T_FNOTWINCOMPAT T_FPRIVATE T_FNEWFILES
  86. %token T_REALMODE
  87. %token T_FUNCTIONS
  88. %token T_APPLOADER
  89. %token T_OVL
  90. %token T_KVERSION
  91. %{ /* SCCSID = %W% %E% */
  92. #if _M_IX86 >= 300
  93. #define M_I386 1
  94. #define HOST32
  95. #ifndef _WIN32
  96. #define i386
  97. #endif
  98. #endif
  99. #ifdef _WIN32
  100. #ifndef HOST32
  101. #define HOST32
  102. #endif
  103. #endif
  104. #include <basetsd.h>
  105. #include <stdio.h>
  106. #include <string.h>
  107. #include <malloc.h>
  108. #include <stdlib.h>
  109. #include <process.h>
  110. #include <stdarg.h>
  111. #include <io.h>
  112. #include "impliber.h"
  113. #include "verimp.h" /* VERSION_STRING header */
  114. #ifdef _MBCS
  115. #define _CRTVAR1
  116. #include <mbctype.h>
  117. #include <mbstring.h>
  118. #endif
  119. #define EXE386 0
  120. #define NOT !
  121. #define AND &&
  122. #define OR ||
  123. #define NEAR
  124. #include <newexe.h>
  125. typedef unsigned char BYTE; /* Byte */
  126. #ifdef HOST32
  127. #define FAR
  128. #define HUGE
  129. #define NEAR
  130. #define FSTRICMP _stricmp
  131. #define PASCAL
  132. #else
  133. #define FAR far
  134. #define HUGE huge
  135. #define FSTRICMP _fstricmp
  136. #define PASCAL __pascal
  137. #endif
  138. #ifndef TRUE
  139. #define TRUE 1
  140. #endif
  141. #ifndef FALSE
  142. #define FALSE 0
  143. #endif
  144. #define C8_IDE TRUE
  145. #ifndef LOCAL
  146. #ifndef _WIN32
  147. #define LOCAL static
  148. #else
  149. #define LOCAL
  150. #endif
  151. #endif
  152. #define WRBIN "wb" /* Write only binary mode */
  153. #define RDBIN "rb" /* Read only binary mode */
  154. #define UPPER(c) (((c)>='a' && (c)<='z')? (c) - 'a' + 'A': (c))
  155. /* Raise char to upper case */
  156. #define YYS_WD(x) (x)._wd /* Access macro */
  157. #define YYS_BP(x) (x)._bp /* Access macro */
  158. #define SBMAX 255 /* Max. of length-prefixed string */
  159. #define MAXDICLN 997 /* Max. no. of pages in dictionary */
  160. #define PAGLEN 512 /* 512 bytes per page */
  161. #define THEADR 0x80 /* THEADR record type */
  162. #define COMENT 0x88 /* COMENT record type */
  163. #define MODEND 0x8A /* MODEND record type */
  164. #define PUBDEF 0x90 /* PUBDEF record type */
  165. #define LIBHDR 0xF0 /* Library header recod */
  166. #define DICHDR 0xF1 /* Dictionary header record */
  167. #define MSEXT 0xA0 /* OMF extension comment class */
  168. #define IMPDEF 0x01 /* IMPort DEFinition record */
  169. #define NBUCKETS 37 /* Thirty-seven buckets per page */
  170. #define PAGEFULL ((char)(0xFF)) /* Page full flag */
  171. #define FREEWD 19 /* Word index of first free word */
  172. #define WPP (PAGLEN >> 1) /* Number of words per page */
  173. #define pagout(pb) fwrite(pb,1,PAGLEN,fo)
  174. /* Write dictionary page to library */
  175. #define INCLUDE_DIR 0xffff /* Include directive for the lexer */
  176. #define MAX_NEST 7
  177. #define IO_BUF_SIZE 512
  178. typedef struct import /* Import record */
  179. {
  180. struct import *i_next; /* Link to next in list */
  181. char *i_extnam; /* Pointer to external name */
  182. char *i_internal; /* Pointer to internal name */
  183. unsigned short i_ord; /* Ordinal number */
  184. unsigned short i_flags; /* Extra flags */
  185. }
  186. IMPORT; /* Import record */
  187. #define I_NEXT(x) (x).i_next
  188. #define I_EXTNAM(x) (x).i_extnam
  189. #define I_INTNAM(x) (x).i_internal
  190. #define I_ORD(x) (x).i_ord
  191. #define I_FLAGS(x) (x).i_flags
  192. typedef unsigned char byte;
  193. typedef unsigned short word;
  194. #ifdef M68000
  195. #define strrchr rindex
  196. #endif
  197. LOCAL int fIgnorecase = 1;/* True if ignoring case - default */
  198. LOCAL int fBannerOnScreen;/* True if banner on screen */
  199. LOCAL int fFileNameExpected = 1;
  200. LOCAL int fNTdll; /* If true add file name extension to module names */
  201. LOCAL int fIgnorewep = 0; /* True if ignoring multiple WEPs */
  202. LOCAL FILE *includeDisp[MAX_NEST];
  203. // Include file stack
  204. LOCAL short curLevel; // Current include nesting level
  205. // Zero means main .DEF file
  206. char prognam[] = "IMPLIB";
  207. FILE *fi; /* Input file */
  208. FILE *fo; /* Output file */
  209. int yylineno = 1; /* Line number */
  210. char rgbid[SBMAX]; /* I.D. buffer */
  211. char sbModule[SBMAX];/* Module name */
  212. IMPORT *implist; /* List of importable symbols */
  213. IMPORT *lastimp; /* Pointer to end of list */
  214. IMPORT *newimps; /* List of importable symbols */
  215. word csyms; /* Symbol count */
  216. word csymsmod; /* Per-module symbol count */
  217. long cbsyms; /* Symbol byte count */
  218. word diclength; /* Dictionary length in PAGEs */
  219. char *mpdpnpag[MAXDICLN];
  220. /* Page buffer array */
  221. char *defname; /* Name of definitions file */
  222. int exitCode; /* code returned to OS */
  223. #if C8_IDE
  224. int fC8IDE = FALSE;
  225. char msgBuf[_MAX_PATH];
  226. #endif
  227. LOCAL char moduleEXE[] = ".exe";
  228. LOCAL char moduleDLL[] = ".dll";
  229. word prime[] = /* Array of primes */
  230. {
  231. 2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
  232. 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
  233. 73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
  234. 127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
  235. 179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
  236. 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
  237. 283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
  238. 353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
  239. 419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
  240. 467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
  241. 547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
  242. 607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
  243. 661, 673, 677, 683, 691, 701, 709, 719, 727, 733,
  244. 739, 743, 751, 757, 761, 769, 773, 787, 797, 809,
  245. 811, 821, 823, 827, 829, 839, 853, 857, 859, 863,
  246. 877, 881, 883, 887, 907, 911, 919, 929, 937, 941,
  247. 947, 953, 961, 967, 971, 977, 983, 991, MAXDICLN,
  248. 0
  249. };
  250. LOCAL void MOVE(int cb, char *src, char *dst);
  251. LOCAL void DefaultModule(char *defaultExt);
  252. LOCAL void NewModule(char *sbNew, char *defaultExt);
  253. LOCAL char *alloc(word cb);
  254. LOCAL void export(char *sbEntry, char *sbInternal, word ordno, word flags);
  255. LOCAL word theadr(char *sbName);
  256. LOCAL void outimpdefs(void);
  257. LOCAL short symeq(char *ps1,char *ps2);
  258. LOCAL void initsl(void);
  259. LOCAL word rol(word x, word n);
  260. LOCAL word ror(word x, word n);
  261. LOCAL void hashsym(char *pf, word *pdpi, word *pdpid,word *pdpo, word *pdpod);
  262. LOCAL void nullfill(char *pbyte, word length);
  263. LOCAL int pagesearch(char *psym, char *dicpage, word *pdpo, word dpod);
  264. LOCAL word instsym(IMPORT *psym);
  265. LOCAL void nulpagout(void);
  266. LOCAL void writedic(void);
  267. LOCAL int IsPrefix(char *prefix, char *s);
  268. LOCAL void DisplayBanner(void);
  269. int NEAR yyparse(void);
  270. LOCAL void yyerror(char *);
  271. char *keywds[] = /* Keyword array */
  272. {
  273. "ALIAS", (char *) T_FALIAS,
  274. "APPLOADER", (char *) T_APPLOADER,
  275. "BASE", (char *) T_KBASE,
  276. "CLASS", (char *) T_KCLASS,
  277. "CODE", (char *) T_KCODE,
  278. "CONFORMING", (char *) T_KCONFORM,
  279. "CONSTANT", (char *) T_KCONSTANT,
  280. "CONTIGUOUS", (char *) T_FCONTIG,
  281. "DATA", (char *) T_KDATA,
  282. "DESCRIPTION", (char *) T_KDESCRIPTION,
  283. "DEV386", (char *) T_FDEV386,
  284. "DEVICE", (char *) T_KDEVICE,
  285. "DISCARDABLE", (char *) T_FDISCARDABLE,
  286. "DOS", (char *) T_FDOS,
  287. "DYNAMIC", (char *) T_FDYNAMIC,
  288. "EXECUTE-ONLY", (char *) T_FEXEC,
  289. "EXECUTEONLY", (char *) T_FEXEC,
  290. "EXECUTEREAD", (char *) T_FEXECREAD,
  291. "EXETYPE", (char *) T_KEXETYPE,
  292. "EXPANDDOWN", (char *) T_KEXPANDDOWN,
  293. "EXPORTS", (char *) T_KEXPORTS,
  294. "FIXED", (char *) T_FFIXED,
  295. "FUNCTIONS", (char *) T_FUNCTIONS,
  296. "HEAPSIZE", (char *) T_KHEAPSIZE,
  297. "HUGE", (char *) T_FHUGE,
  298. "IMPORTS", (char *) T_KIMPORTS,
  299. "IMPURE", (char *) T_FNONSHARED,
  300. "INCLUDE", (char *) INCLUDE_DIR,
  301. "INITGLOBAL", (char *) T_FINITGLOB,
  302. "INITINSTANCE", (char *) T_FINITINST,
  303. "INVALID", (char *) T_FINVALID,
  304. "IOPL", (char *) T_FIOPL,
  305. "LIBRARY", (char *) T_KLIBRARY,
  306. "LOADONCALL", (char *) T_FLOADONCALL,
  307. "LONGNAMES", (char *) T_FNEWFILES,
  308. "MACINTOSH", (char *) T_FMACINTOSH,
  309. "MAXVAL", (char *) T_KMAXVAL,
  310. "MIXED1632", (char *) T_FMIXED,
  311. "MOVABLE", (char *) T_FMOVABLE,
  312. "MOVEABLE", (char *) T_FMOVABLE,
  313. "MULTIPLE", (char *) T_FMULTIPLE,
  314. "NAME", (char *) T_KNAME,
  315. "NEWFILES", (char *) T_FNEWFILES,
  316. "NODATA", (char *) T_KNODATA,
  317. "NOEXPANDDOWN", (char *) T_KNOEXPANDDOWN,
  318. "NOIOPL", (char *) T_FNOIOPL,
  319. "NONAME", (char *) T_KNONAME,
  320. "NONCONFORMING", (char *) T_KNONCONFORM,
  321. "NONDISCARDABLE", (char *) T_FNONDISCARDABLE,
  322. "NONE", (char *) T_FNONE,
  323. "NONPERMANENT", (char *) T_FNONPERM,
  324. "NONSHARED", (char *) T_FNONSHARED,
  325. "NOTWINDOWCOMPAT", (char *) T_FNOTWINCOMPAT,
  326. "NT", (char *) T_FNT,
  327. "OBJECTS", (char *) T_KOBJECTS,
  328. "OLD", (char *) T_KOLD,
  329. "OS2", (char *) T_FOS2,
  330. "OVERLAY", (char *) T_OVL,
  331. "OVL", (char *) T_OVL,
  332. "PERMANENT", (char *) T_FPERM,
  333. "PHYSICAL", (char *) T_KPHYSICAL,
  334. "POSIX", (char *) T_FPOSIX,
  335. "PRELOAD", (char *) T_FPRELOAD,
  336. "PRIVATE", (char *) T_FPRIVATE,
  337. "PRIVATELIB", (char *) T_FPRIVATE,
  338. "PROTMODE", (char *) T_PROTMODE,
  339. "PURE", (char *) T_FSHARED,
  340. "READONLY", (char *) T_FRDONLY,
  341. "READWRITE", (char *) T_FRDWR,
  342. "REALMODE", (char *) T_REALMODE,
  343. "RESIDENT", (char *) T_FRESIDENT,
  344. "RESIDENTNAME", (char *) T_KRESIDENTNAME,
  345. "SECTIONS", (char *) T_KSECTIONS,
  346. "SEGMENTS", (char *) T_KSEGMENTS,
  347. "SHARED", (char *) T_FSHARED,
  348. "SINGLE", (char *) T_FSINGLE,
  349. "STACKSIZE", (char *) T_KSTACKSIZE,
  350. "STUB", (char *) T_KSTUB,
  351. "SUBSYSTEM", (char *) T_KSUBSYSTEM,
  352. "SWAPPABLE", (char *) T_FSWAPPABLE,
  353. "TERMINSTANCE", (char *) T_FTERMINST,
  354. "UNIX", (char *) T_FUNIX,
  355. "UNKNOWN", (char *) T_FUNKNOWN,
  356. "VERSION", (char *) T_KVERSION,
  357. "VIRTUAL", (char *) T_KVIRTUAL,
  358. "WINDOWAPI", (char *) T_FWINAPI,
  359. "WINDOWCOMPAT", (char *) T_FWINCOMPAT,
  360. "WINDOWS", (char *) T_FWINDOWS,
  361. "WINDOWSCHAR", (char *) T_FWINDOWSCHAR,
  362. "WINDOWSNT", (char *) T_FWINDOWSNT,
  363. NULL
  364. };
  365. %}
  366. %union
  367. {
  368. word _wd;
  369. char *_bp;
  370. }
  371. %type <_bp> T_ID
  372. %type <_bp> T_STRING
  373. %type <_bp> Idname
  374. %type <_bp> Internal
  375. %type <_wd> T_NUMBER
  376. %type <_wd> Exportopts
  377. %type <_wd> ExportOtherFlags
  378. %type <_wd> ScopeFlag
  379. %%
  380. Definitions : Name Options
  381. | Name
  382. |
  383. {
  384. DefaultModule(moduleEXE);
  385. }
  386. Options
  387. ;
  388. Name : T_KNAME Idname
  389. {
  390. fFileNameExpected = 0;
  391. }
  392. Apptype OtherFlags VirtBase
  393. {
  394. NewModule($2, moduleEXE);
  395. }
  396. | T_KNAME
  397. {
  398. fFileNameExpected = 0;
  399. }
  400. Apptype OtherFlags VirtBase
  401. {
  402. DefaultModule(moduleEXE);
  403. }
  404. | T_KLIBRARY Idname
  405. {
  406. fFileNameExpected = 0;
  407. }
  408. Libflags OtherFlags VirtBase
  409. {
  410. NewModule($2, moduleDLL);
  411. }
  412. | T_KLIBRARY
  413. {
  414. fFileNameExpected = 0;
  415. }
  416. Libflags OtherFlags VirtBase
  417. {
  418. DefaultModule(moduleDLL);
  419. }
  420. | T_KPHYSICAL T_KDEVICE Idname
  421. {
  422. fFileNameExpected = 0;
  423. }
  424. Libflags VirtBase
  425. {
  426. NewModule($3, moduleDLL);
  427. }
  428. | T_KPHYSICAL T_KDEVICE
  429. {
  430. fFileNameExpected = 0;
  431. }
  432. Libflags VirtBase
  433. {
  434. DefaultModule(moduleDLL);
  435. }
  436. | T_KVIRTUAL T_KDEVICE Idname
  437. {
  438. fFileNameExpected = 0;
  439. }
  440. Libflags VirtBase
  441. {
  442. NewModule($3, moduleDLL);
  443. }
  444. | T_KVIRTUAL T_KDEVICE
  445. {
  446. fFileNameExpected = 0;
  447. }
  448. Libflags VirtBase
  449. {
  450. DefaultModule(moduleDLL);
  451. }
  452. ;
  453. Libflags : T_FINITGLOB
  454. {
  455. }
  456. | InstanceFlags
  457. |
  458. ;
  459. InstanceFlags : InstanceFlags InstanceFlag
  460. | InstanceFlag
  461. ;
  462. InstanceFlag : T_FINITINST
  463. | T_FTERMINST
  464. ;
  465. VirtBase : T_KBASE T_EQ T_NUMBER
  466. |
  467. ;
  468. Apptype : T_FWINAPI
  469. | T_FWINCOMPAT
  470. | T_FNOTWINCOMPAT
  471. | T_FPRIVATE
  472. |
  473. ;
  474. OtherFlags : T_FNEWFILES
  475. |
  476. ;
  477. Options : Options Option
  478. | Option
  479. ;
  480. Option : T_KDESCRIPTION T_STRING
  481. | T_KOLD T_STRING
  482. | T_KSTUB T_FNONE
  483. | T_KSTUB T_STRING
  484. | T_KHEAPSIZE SizeSpec
  485. | T_KSTACKSIZE SizeSpec
  486. | T_PROTMODE
  487. | T_REALMODE
  488. | T_APPLOADER Idname
  489. | Codeflags
  490. | Dataflags
  491. | Segments
  492. | Exports
  493. | Imports
  494. | ExeType
  495. | SubSystem
  496. | ProcOrder
  497. | UserVersion
  498. ;
  499. SizeSpec : T_NUMBER T_COMA T_NUMBER
  500. | T_NUMBER
  501. | T_KMAXVAL
  502. ;
  503. Codeflags : T_KCODE Codeflaglist
  504. ;
  505. Codeflaglist : Codeflaglist Codeflag
  506. | Codeflag
  507. ;
  508. Codeflag : Baseflag
  509. | Codeonly
  510. ;
  511. Codeonly : T_FEXEC
  512. | T_FEXECREAD
  513. | T_FDISCARDABLE
  514. | T_FNONDISCARDABLE
  515. | T_KCONFORM
  516. | T_KNONCONFORM
  517. ;
  518. Dataflags : T_KDATA Dataflaglist
  519. ;
  520. Dataflaglist : Dataflaglist Dataflag
  521. | Dataflag
  522. ;
  523. Dataflag : Baseflag
  524. | Dataonly
  525. | T_FNONE
  526. | T_FSINGLE
  527. | T_FMULTIPLE
  528. | T_FDISCARDABLE
  529. | T_FNONDISCARDABLE
  530. ;
  531. Dataonly : T_FRDONLY
  532. | T_FRDWR
  533. | T_KEXPANDDOWN
  534. | T_KNOEXPANDDOWN
  535. ;
  536. Segments : T_KSEGMENTS Segattrlist
  537. | T_KSEGMENTS
  538. | T_KOBJECTS Segattrlist
  539. | T_KOBJECTS
  540. | T_KSECTIONS Segattrlist
  541. | T_KSECTIONS
  542. ;
  543. Segattrlist : Segattrlist Segattr
  544. | Segattr
  545. ;
  546. Segattr : SegIdname Class Segflags
  547. ;
  548. SegIdname : T_ID
  549. | T_STRING
  550. ;
  551. Class : T_KCLASS T_STRING
  552. |
  553. ;
  554. Segflag : Baseflag
  555. | Codeonly
  556. | Dataonly
  557. ;
  558. ;
  559. Segflaglist : Segflaglist Segflag
  560. | Segflag
  561. ;
  562. Segflags : Segflaglist
  563. |
  564. ;
  565. Baseflag : T_FSHARED
  566. | T_FNONSHARED
  567. | T_FINVALID
  568. | T_FIOPL
  569. | T_FNOIOPL
  570. | T_FFIXED
  571. | T_FMOVABLE
  572. | T_FPRELOAD
  573. | T_FLOADONCALL
  574. | T_FHUGE
  575. | T_FSWAPPABLE
  576. | T_FRESIDENT
  577. | T_FALIAS
  578. | T_FMIXED
  579. | T_FNONPERM
  580. | T_FPERM
  581. | T_FCONTIG
  582. | T_FDYNAMIC
  583. ;
  584. Exports : T_KEXPORTS Exportlist
  585. | T_KEXPORTS
  586. ;
  587. Exportlist : Exportlist Export
  588. | Export
  589. ;
  590. Export : Idname Internal Exportopts Exportflags ExportOtherFlags ScopeFlag
  591. {
  592. if ($6)
  593. {
  594. // Skip private exports
  595. free($1);
  596. free($2);
  597. }
  598. else
  599. export($1,$2,$3,$5);
  600. }
  601. ;
  602. Internal : T_EQ Idname
  603. {
  604. $$ = $2;
  605. }
  606. |
  607. {
  608. $$ = NULL;
  609. }
  610. ;
  611. Exportopts : T_AT T_NUMBER T_KRESIDENTNAME
  612. {
  613. $$ = $2;
  614. }
  615. | T_AT T_NUMBER T_KNONAME
  616. {
  617. $$ = $2;
  618. }
  619. | T_AT T_NUMBER
  620. {
  621. $$ = $2;
  622. }
  623. |
  624. {
  625. $$ = 0;
  626. }
  627. ;
  628. Exportflags : Nodata Parmwds
  629. ;
  630. Nodata : T_KNODATA
  631. |
  632. ;
  633. Parmwds : T_NUMBER
  634. |
  635. ;
  636. ExportOtherFlags: T_KCONSTANT
  637. {
  638. $$ = 0x1;
  639. }
  640. |
  641. {
  642. $$ = 0;
  643. }
  644. ;
  645. ScopeFlag : T_FPRIVATE
  646. {
  647. $$ = 1;
  648. }
  649. |
  650. {
  651. $$ = 0;
  652. }
  653. ;
  654. Imports : T_KIMPORTS Importlist
  655. | T_KIMPORTS
  656. ;
  657. Importlist : Importlist Import
  658. | Import
  659. ;
  660. Import : Idname Internal T_DOT Idname ImportFlags
  661. | Idname Internal T_DOT T_NUMBER ImportFlags
  662. ;
  663. Idname : T_ID
  664. {
  665. $$ = _strdup(rgbid);
  666. }
  667. | T_STRING
  668. {
  669. $$ = _strdup(rgbid);
  670. }
  671. ;
  672. ImportFlags : T_KCONSTANT
  673. |
  674. ;
  675. ExeType : T_KEXETYPE ExeFlags ExeVersion
  676. | T_KEXETYPE
  677. ;
  678. ExeFlags : T_FDOS
  679. | T_FOS2
  680. | T_FUNKNOWN
  681. | T_FWINDOWS
  682. | T_FDEV386
  683. | T_FNT
  684. | T_FUNIX
  685. | T_FMACINTOSH T_FSWAPPABLE
  686. | T_FMACINTOSH
  687. ;
  688. ExeVersion : MajorVer T_DOT MinorVer
  689. | MajorVer
  690. ;
  691. MajorVer : T_NUMBER
  692. |
  693. ;
  694. MinorVer : T_NUMBER
  695. |
  696. ;
  697. UserVersion : T_KVERSION ExeVersion
  698. ;
  699. SubSystem : T_KSUBSYSTEM SubSystemFlags
  700. ;
  701. SubSystemFlags : T_FUNKNOWN
  702. | T_FOS2
  703. | T_FWINDOWS
  704. | T_FWINDOWSNT
  705. | T_FWINDOWSCHAR
  706. | T_FPOSIX
  707. ;
  708. ProcOrder : T_FUNCTIONS SegOrOvl ProcList
  709. ;
  710. SegOrOvl : T_COLON NameOrNumber
  711. |
  712. ;
  713. NameOrNumber : Idname
  714. | T_NUMBER
  715. ;
  716. ProcList : ProcList Idname
  717. | Idname
  718. ;
  719. %%
  720. #ifndef M_I386
  721. extern char * PASCAL __FMSG_TEXT ( unsigned );
  722. #else
  723. #ifdef _WIN32
  724. extern char * PASCAL __FMSG_TEXT ( unsigned );
  725. #endif
  726. #endif
  727. /*** Error - display error message
  728. *
  729. * Purpose:
  730. * Display error message.
  731. *
  732. * Input:
  733. * errNo - error number
  734. *
  735. * Output:
  736. * No explicit value is returned. Error message written out to stderr.
  737. *
  738. * Exceptions:
  739. * None.
  740. *
  741. * Notes:
  742. * This function takes variable number of parameters. MUST be in
  743. * C calling convention.
  744. *
  745. *************************************************************************/
  746. LOCAL void cdecl Error(unsigned errNo,...)
  747. {
  748. va_list pArgList;
  749. if (!fBannerOnScreen)
  750. DisplayBanner();
  751. va_start(pArgList, errNo); /* Get start of argument list */
  752. /* Write out standard error prefix */
  753. fprintf(stderr, "%s : %s IM%d: ", prognam, GET_MSG(M_error), errNo);
  754. /* Write out error message */
  755. vfprintf(stderr, GET_MSG(errNo), pArgList);
  756. fprintf(stderr, "\n");
  757. if (!exitCode)
  758. exitCode = (errNo >= ER_Min && errNo <= ER_Max)
  759. || (errNo >= ER_MinFatal && errNo <= ER_MaxFatal);
  760. }
  761. /*** Fatal - display error message
  762. *
  763. * Purpose:
  764. * Display error message and exit to operating system.
  765. *
  766. * Input:
  767. * errNo - error number
  768. *
  769. * Output:
  770. * No explicit value is returned. Error message written out to stderr.
  771. *
  772. * Exceptions:
  773. * None.
  774. *
  775. * Notes:
  776. * This function takes variable number of parameters. MUST be in
  777. * C calling convention.
  778. *
  779. *************************************************************************/
  780. LOCAL void cdecl Fatal(unsigned errNo,...)
  781. {
  782. va_list pArgList;
  783. if (!fBannerOnScreen)
  784. DisplayBanner();
  785. va_start(pArgList, errNo); /* Get start of argument list */
  786. /* Write out standard error prefix */
  787. fprintf(stderr, "%s : %s %s IM%d: ", prognam, GET_MSG(M_fatal), GET_MSG(M_error),errNo);
  788. /* Write out fatal error message */
  789. vfprintf(stderr, GET_MSG(errNo), pArgList);
  790. fprintf(stderr, "\n");
  791. exit(1);
  792. }
  793. /*
  794. * Check if error in output file, abort if there is.
  795. */
  796. void chkerror ()
  797. {
  798. if(ferror(fo))
  799. {
  800. Fatal(ER_outfull, strerror(errno));
  801. }
  802. }
  803. LOCAL void MOVE(int cb, char *src, char *dst)
  804. {
  805. while(cb--) *dst++ = *src++;
  806. }
  807. LOCAL char *alloc(word cb)
  808. {
  809. char *cp; /* Pointer */
  810. if((cp = malloc(cb)) != NULL) return(cp);
  811. /* Call malloc() to get the space */
  812. Fatal(ER_nomem, "far");
  813. return 0;
  814. }
  815. LOCAL int lookup() /* Keyword lookup */
  816. {
  817. char **pcp; /* Pointer to character pointer */
  818. int i; /* Comparison value */
  819. for(pcp = keywds; *pcp != NULL; pcp += 2)
  820. { /* Look through keyword table */
  821. if(!(i = FSTRICMP(&rgbid[1],*pcp)))
  822. return((int)(INT_PTR) pcp[1]); /* If found, return token type */
  823. if(i < 0) break; /* Break if we've gone too far */
  824. }
  825. return(T_ID); /* Just your basic identifier */
  826. }
  827. LOCAL int GetChar(void)
  828. {
  829. int c; /* A character */
  830. c = getc(fi);
  831. if (c == EOF && curLevel > 0)
  832. {
  833. fclose(fi);
  834. fi = includeDisp[curLevel];
  835. curLevel--;
  836. c = GetChar();
  837. }
  838. return(c);
  839. }
  840. LOCAL int yylex() /* Lexical analyzer */
  841. {
  842. int c = 0; /* A character */
  843. word x; /* Numeric token value */
  844. int state; /* State variable */
  845. char *cp; /* Character pointer */
  846. char *sz; /* Zero-terminated string */
  847. static int lastc; /* Previous character */
  848. int fFileNameSave;
  849. state = 0; /* Assume we're not in a comment */
  850. for(;;) /* Loop to skip white space */
  851. {
  852. lastc = c;
  853. if((c = GetChar()) == EOF || c == '\032' || c == '\377') return(EOF);
  854. /* Get a character */
  855. if(c == ';') state = 1; /* If comment, set flag */
  856. else if(c == '\n') /* If end of line */
  857. {
  858. state = 0; /* End of comment */
  859. if(!curLevel)
  860. ++yylineno; /* Increment line number count */
  861. }
  862. else if(state == 0 && c != ' ' && c != '\t' && c != '\r') break;
  863. /* Break on non-white space */
  864. }
  865. switch(c) /* Handle one-character tokens */
  866. {
  867. case '.': /* Name separator */
  868. if (fFileNameExpected)
  869. break;
  870. return(T_DOT);
  871. case '@': /* Ordinal specifier */
  872. /*
  873. * Require that whitespace precede '@' if introducing an
  874. * ordinal, to allow '@' in identifiers.
  875. */
  876. if(lastc == ' ' || lastc == '\t' || lastc == '\r')
  877. return(T_AT);
  878. break;
  879. case '=': /* Name assignment */
  880. return(T_EQ);
  881. case ':':
  882. return(T_COLON);
  883. case ',':
  884. return(T_COMA);
  885. }
  886. if(c >= '0' && c <= '9' && !fFileNameExpected)
  887. { /* If token is a number */
  888. x = c - '0'; /* Get first digit */
  889. c = GetChar(); /* Get next character */
  890. if(x == 0) /* If octal or hex */
  891. {
  892. if(c == 'x' || c == 'X')/* If it is an 'x' */
  893. {
  894. state = 16; /* Base is hexadecimal */
  895. c = GetChar(); /* Get next character */
  896. }
  897. else state = 8; /* Else octal */
  898. }
  899. else state = 10; /* Else decimal */
  900. for(;;)
  901. {
  902. if(c >= '0' && c <= '9') c -= '0';
  903. else if(c >= 'A' && c <= 'F') c -= 'A' - 10;
  904. else if(c >= 'a' && c <= 'f') c -= 'a' - 10;
  905. else break;
  906. if(c >= state) break;
  907. x = x*state + c;
  908. c = GetChar();
  909. }
  910. ungetc(c,fi);
  911. YYS_WD(yylval) = x;
  912. return(T_NUMBER);
  913. }
  914. if(c == '\'' || c == '"') /* If token is a string */
  915. {
  916. sz = &rgbid[1]; /* Initialize */
  917. for(state = 0; state != 2;) /* State machine loop */
  918. {
  919. if((c = GetChar()) == EOF) return(EOF);
  920. /* Check for EOF */
  921. if (sz >= &rgbid[sizeof(rgbid)])
  922. {
  923. Error(ER_linemax, yylineno, sizeof(rgbid)-1);
  924. state = 2;
  925. }
  926. switch(state) /* Transitions */
  927. {
  928. case 0: /* Inside quote */
  929. if(c == '\'' || c == '"') state = 1;
  930. /* Change state if quote found */
  931. else *sz++ = (char) c;/* Else save character */
  932. break;
  933. case 1: /* Inside quote with quote */
  934. if(c == '\'' || c == '"')/* If consecutive quotes */
  935. {
  936. *sz++ = (char) c;/* Quote inside string */
  937. state = 0; /* Back to state 0 */
  938. }
  939. else state = 2; /* Else end of string */
  940. break;
  941. }
  942. }
  943. ungetc(c,fi); /* Put back last character */
  944. *sz = '\0'; /* Null-terminate the string */
  945. rgbid[0] = (char)(sz - &rgbid[1]);
  946. /* Set length of string */
  947. YYS_BP(yylval) = rgbid; /* Save ptr. to identifier */
  948. return(T_STRING); /* String found */
  949. }
  950. sz = &rgbid[1]; /* Initialize */
  951. for(;;) /* Loop to get i.d.'s */
  952. {
  953. if (fFileNameExpected)
  954. cp = " \t\r\n\f";
  955. else
  956. cp = " \t\r\n.=';\032";
  957. while(*cp && *cp != (char) c)
  958. ++cp;
  959. /* Check for end of identifier */
  960. if(*cp) break; /* Break if end of identifier found */
  961. if (sz >= &rgbid[sizeof(rgbid)])
  962. Fatal(ER_linemax, yylineno, sizeof(rgbid)-1);
  963. *sz++ = (byte) c; /* Save the character */
  964. if((c = GetChar()) == EOF) break;
  965. /* Get next character */
  966. }
  967. ungetc(c,fi); /* Put character back */
  968. *sz = '\0'; /* Null-terminate the string */
  969. rgbid[0] = (char)(sz - &rgbid[1]); /* Set length of string */
  970. YYS_BP(yylval) = rgbid; /* Save ptr. to identifier */
  971. state = lookup(); /* Look up the identifier */
  972. if (state == INCLUDE_DIR)
  973. {
  974. // Process include directive
  975. fFileNameSave = fFileNameExpected;
  976. fFileNameExpected = 1;
  977. state = yylex();
  978. fFileNameExpected = fFileNameSave;
  979. if (state == T_ID || state == T_STRING)
  980. {
  981. if (curLevel < MAX_NEST - 1)
  982. {
  983. curLevel++;
  984. includeDisp[curLevel] = fi;
  985. fi = fopen(&rgbid[1], RDBIN);
  986. if (fi == NULL)
  987. Fatal(ER_badopen, &rgbid[1], strerror(errno));
  988. return(yylex());
  989. }
  990. else
  991. Fatal(ER_toomanyincl);
  992. }
  993. else
  994. Fatal(ER_badinclname);
  995. return (0);
  996. }
  997. else
  998. return(state);
  999. }
  1000. LOCAL void yyerror(s) /* Error routine */
  1001. char *s; /* Error message */
  1002. {
  1003. fprintf(stderr, "%s(%d) : %s %s IM%d: %s %s\n",
  1004. defname, yylineno, GET_MSG(M_fatal), GET_MSG(M_error),
  1005. ER_syntax, s, GET_MSG(ER_syntax));
  1006. exit(1);
  1007. }
  1008. /*
  1009. * Use the basename of the current .DEF file name as the module name.
  1010. */
  1011. LOCAL void DefaultModule(char *defaultExt)
  1012. {
  1013. char drive[_MAX_DRIVE];
  1014. char dir[_MAX_DIR];
  1015. char fname[_MAX_FNAME];
  1016. char ext[_MAX_EXT];
  1017. _splitpath(defname, drive, dir, fname, ext);
  1018. if (fNTdll)
  1019. {
  1020. if (ext[0] == '\0')
  1021. _makepath(&sbModule[1], NULL, NULL, fname, defaultExt);
  1022. else if (ext[0] == '.' && ext[1] == '\0')
  1023. strcpy(&sbModule[1], fname);
  1024. else
  1025. _makepath(&sbModule[1], NULL, NULL, fname, ext);
  1026. }
  1027. else
  1028. _makepath(&sbModule[1], NULL, NULL, fname, NULL);
  1029. sbModule[0] = (unsigned char) strlen(&sbModule[1]);
  1030. }
  1031. LOCAL void NewModule(char *sbNew, char *defaultExt)
  1032. {
  1033. char drive[_MAX_DRIVE];
  1034. char dir[_MAX_DIR];
  1035. char fname[_MAX_FNAME];
  1036. char ext[_MAX_EXT];
  1037. sbNew[sbNew[0]+1] = '\0';
  1038. _splitpath(&sbNew[1], drive, dir, fname, ext);
  1039. if (fNTdll)
  1040. {
  1041. if (ext[0] == '\0')
  1042. _makepath(&sbModule[1], NULL, NULL, fname, defaultExt);
  1043. else if (ext[0] == '.' && ext[1] == '\0')
  1044. strcpy(&sbModule[1], fname);
  1045. else
  1046. _makepath(&sbModule[1], NULL, NULL, fname, ext);
  1047. }
  1048. else
  1049. strcpy(&sbModule[1], fname);
  1050. sbModule[0] = (unsigned char) strlen(&sbModule[1]);
  1051. }
  1052. LOCAL void export(char *sbEntry, char *sbInternal, word ordno, word flags)
  1053. {
  1054. IMPORT *imp; /* Import definition */
  1055. if(fIgnorewep && strcmp(sbEntry+1, "WEP") == 0)
  1056. return;
  1057. imp = (IMPORT *) alloc(sizeof(IMPORT));
  1058. /* Allocate a cell */
  1059. if (newimps == NULL) /* If list empty */
  1060. newimps = imp; /* Define start of list */
  1061. else
  1062. I_NEXT(*lastimp) = imp; /* Append it to list */
  1063. I_NEXT(*imp) = NULL;
  1064. I_EXTNAM(*imp) = sbEntry; /* Save the external name */
  1065. I_INTNAM(*imp) = sbInternal; /* Save the internal name */
  1066. I_ORD(*imp) = ordno; /* Save the ordinal number */
  1067. I_FLAGS(*imp) = flags; /* Save extra flags */
  1068. lastimp = imp; /* Save pointer to end of list */
  1069. }
  1070. /* Output a THEADR record */
  1071. LOCAL word theadr(char *sbName)
  1072. {
  1073. fputc(THEADR,fo);
  1074. fputc(sbName[0] + 2,fo);
  1075. fputc(0,fo);
  1076. fwrite(sbName,sizeof(char),sbName[0] + 1,fo);
  1077. fputc(0,fo);
  1078. chkerror();
  1079. return(sbName[0] + 5);
  1080. }
  1081. word modend() /* Output a MODEND record */
  1082. {
  1083. fwrite("\212\002\0\0\0",sizeof(char),5,fo);
  1084. /* Write a MODEND record */
  1085. chkerror();
  1086. return(5); /* It is 5 bytes long */
  1087. }
  1088. LOCAL void outimpdefs(void)/* Output import definitions */
  1089. {
  1090. IMPORT *imp; /* Pointer to import record */
  1091. word reclen; /* Record length */
  1092. word ord; /* Ordinal number */
  1093. long lfa; /* File address */
  1094. word tlen; /* Length of THEADR */
  1095. byte impFlags;
  1096. for (imp = newimps; imp != NULL; imp = I_NEXT(*imp))
  1097. { /* Traverse the list */
  1098. lfa = ftell(fo); /* Find out where we are */
  1099. tlen = theadr(I_EXTNAM(*imp));
  1100. /* Output a THEADR record */
  1101. // 1 1 1 1 n + 1 n + 1 n + 1 or 2 1
  1102. // +---+----+---+-----+-----------+-----------+------------------+---+
  1103. // | 0 | A0 | 1 | Flg | Ext. Name | Mod. Name | Int. Name or Ord | 0 |
  1104. // +---+----+---+-----+-----------+-----------+------------------+---+
  1105. reclen = 4 + sbModule[0] + 1 + I_EXTNAM(*imp)[0] + 1 + 1;
  1106. /* Initialize */
  1107. ord = I_ORD(*imp);
  1108. if (ord != 0)
  1109. reclen +=2; /* Two bytes for ordinal number */
  1110. else if (I_INTNAM(*imp))
  1111. reclen += I_INTNAM(*imp)[0] + 1;
  1112. /* Length of internal name */
  1113. else
  1114. reclen++;
  1115. I_ORD(*imp) = (word)(lfa >> 4);
  1116. /* Save page number */
  1117. ++csymsmod; /* Increment symbol count */
  1118. cbsyms += (long) I_EXTNAM(*imp)[0] + 4;
  1119. /* Increment symbol space count */
  1120. fputc(COMENT,fo); /* Comment record */
  1121. fputc(reclen & 0xFF,fo); /* Lo-byte of record length */
  1122. fputc(reclen >> 8,fo); /* Hi-byte of length */
  1123. fputc(0,fo); /* Purgable, listable */
  1124. fputc(MSEXT,fo); /* Microsoft OMF extension class */
  1125. fputc(IMPDEF,fo); /* IMPort DEFinition record */
  1126. impFlags = 0;
  1127. if (ord != 0)
  1128. impFlags |= 0x1;
  1129. if (I_FLAGS(*imp) & 0x1)
  1130. impFlags |= 0x2;
  1131. fputc(impFlags, fo); /* Import type (name or ordinal or constant) */
  1132. fwrite(I_EXTNAM(*imp),sizeof(char),I_EXTNAM(*imp)[0] + 1,fo);
  1133. /* Write the external name */
  1134. fwrite(sbModule,sizeof(char),sbModule[0] + 1,fo);
  1135. /* Write the module name */
  1136. if (ord != 0) /* If import by ordinal */
  1137. {
  1138. fputc(ord & 0xFF,fo); /* Lo-byte of ordinal */
  1139. fputc(ord >> 8,fo); /* Hi-byte of ordinal */
  1140. }
  1141. else if (I_INTNAM(*imp))
  1142. fwrite(I_INTNAM(*imp), sizeof(char), I_INTNAM(*imp)[0] + 1, fo);
  1143. /* Write internal name */
  1144. else
  1145. fputc(0, fo); /* No internal name */
  1146. fputc(0,fo); /* Checksum byte */
  1147. reclen += tlen + modend() + 3; /* Output a MODEND record */
  1148. if(reclen &= 0xF) /* If padding needed */
  1149. {
  1150. reclen = 0x10 - reclen; /* Calculate needed padding */
  1151. while(reclen--) fputc(0,fo);/* Pad to page boundary */
  1152. }
  1153. chkerror();
  1154. }
  1155. }
  1156. /* Compare two symbols */
  1157. LOCAL short symeq(char *ps1,char *ps2)
  1158. {
  1159. int length; /* No. of char.s to compare */
  1160. length = *ps1 + 1; /* Take length of first symbol */
  1161. if (length != *ps2 + 1)
  1162. return(0); /* Length must match */
  1163. while(length--) /* While not at end of symbol */
  1164. if (fIgnorecase)
  1165. {
  1166. if (UPPER(*ps1) != UPPER(*ps2))
  1167. return(0); /* If not equal, return zero */
  1168. ++ps1;
  1169. ++ps2;
  1170. }
  1171. else if (*ps1++ != *ps2++)
  1172. return(0); /* If not equal, return zero */
  1173. return(1); /* Symbols match */
  1174. }
  1175. LOCAL word calclen() /* Calculate dictionary length */
  1176. {
  1177. word avglen; /* Average entry length */
  1178. word avgentries; /* Average no. of entries per page */
  1179. word minpages; /* Min. no. of pages in dictionary */
  1180. register word i; /* Index variable */
  1181. if(!csyms) return(1); /* One page for an empty dictionary */
  1182. avglen = (word)(cbsyms/csyms) + 1;
  1183. /* Average entry length */
  1184. avgentries = (PAGLEN - NBUCKETS - 1)/avglen;
  1185. /* Average no. of entries per page */
  1186. minpages = (word) csyms/avgentries + 1;
  1187. /* Minimum no. of pages in dict. */
  1188. if(minpages < (i = (word) csyms/NBUCKETS + 1))
  1189. {
  1190. minpages = i;
  1191. }
  1192. else
  1193. {
  1194. /* Add some extra pages if there is a lot long symbol names */
  1195. #define MAXOVERHEAD 10
  1196. i = (word)(((avglen+5L) * minpages *4)/(3*PAGLEN)); // The more symbols the larger increase...
  1197. if(i>MAXOVERHEAD)
  1198. i = MAXOVERHEAD; /* Do not add more than MAXOVERHEAD pages */
  1199. minpages += i;
  1200. }
  1201. /* Insure enough buckets allotted */
  1202. i = 0; /* Initialize index */
  1203. do /* Look through prime array */
  1204. {
  1205. if(minpages <= prime[i]) return(prime[i]);
  1206. /* Return smallest prime >= minpages */
  1207. }
  1208. while(prime[i++]); /* Until end of table found */
  1209. return(0); /* Too many symbols */
  1210. }
  1211. /* Initialize Symbol Lookup */
  1212. LOCAL void initsl(void)
  1213. {
  1214. register word i; /* Index variable */
  1215. diclength = calclen(); /* Calculate dictionaly length */
  1216. for(i = 0; i < diclength; ++i) mpdpnpag[i] = NULL;
  1217. /* Initialize page table */
  1218. }
  1219. LOCAL word ror(word x, word n) /* Rotate right */
  1220. {
  1221. #if ODDWORDLN
  1222. return(((x << (16 - n)) | ((x >> n) & ~(~0 << (16 - n))))
  1223. & ~(~0 << 16));
  1224. #else
  1225. return((x << (16 - n)) | ((x >> n) & ~(~0 << (16 - n))));
  1226. #endif
  1227. }
  1228. LOCAL word rol(word x, word n) /* Rotate left */
  1229. {
  1230. #if ODDWORDLN
  1231. return(((x << n) | ((x >> (16 - n)) & ~(~0 << n))) & ~(~0 << 16));
  1232. #else
  1233. return((x << n) | ((x >> (16 - n)) & ~(~0 << n)));
  1234. #endif
  1235. }
  1236. LOCAL void hashsym(char *pf, word *pdpi, word *pdpid,word *pdpo, word *pdpod)
  1237. {
  1238. char *pb; /* Pointer to back of symbol */
  1239. register word len; /* Length of symbol */
  1240. register word ch; /* Character */
  1241. len = *pf; /* Get length */
  1242. pb = &pf[len]; /* Get pointer to back */
  1243. *pdpi = 0; /* Initialize */
  1244. *pdpid = 0; /* Initialize */
  1245. *pdpo = 0; /* Initialize */
  1246. *pdpod = 0; /* Initialize */
  1247. while(len--) /* Loop */
  1248. {
  1249. ch = *pf++ | 32; /* Force char to lower case */
  1250. *pdpi = rol(*pdpi,2) ^ ch; /* Hash */
  1251. *pdpod = ror(*pdpod,2) ^ ch; /* Hash */
  1252. ch = *pb-- | 32; /* Force char to lower case */
  1253. *pdpo = ror(*pdpo,2) ^ ch; /* Hash */
  1254. *pdpid = rol(*pdpid,2) ^ ch; /* Hash */
  1255. }
  1256. *pdpi %= diclength; /* Calculate page index */
  1257. if(!(*pdpid %= diclength)) *pdpid = 1;
  1258. /* Calculate page index delta */
  1259. *pdpo %= NBUCKETS; /* Calculate page bucket no. */
  1260. if(!(*pdpod %= NBUCKETS)) *pdpod = 1;
  1261. /* Calculate page bucket delta */
  1262. }
  1263. LOCAL void nullfill(char *pbyte, word length)
  1264. {
  1265. while(length--) *pbyte++ = '\0'; /* Load with nulls */
  1266. }
  1267. /*
  1268. * Returns:
  1269. * -1 Symbol not in dictionary
  1270. * 0 Search inconclusive
  1271. * 1 Symbol on this page
  1272. */
  1273. LOCAL int pagesearch(char *psym, char *dicpage, word *pdpo, word dpod)
  1274. {
  1275. register word i; /* Index variable */
  1276. word dpo; /* Initial bucket number */
  1277. dpo = *pdpo; /* Remember starting position */
  1278. for(;;) /* Forever */
  1279. {
  1280. if(i = ((word) dicpage[*pdpo] & 0xFF) << 1)
  1281. { /* If bucket is not empty */
  1282. if(symeq(psym,&dicpage[i])) /* If we've found a match */
  1283. return(1); /* Found */
  1284. else /* Otherwise */
  1285. {
  1286. if((*pdpo += dpod) >= NBUCKETS) *pdpo -= NBUCKETS;
  1287. /* Try next bucket */
  1288. if(*pdpo == dpo) return(0);
  1289. /* Symbol not on this page */
  1290. }
  1291. }
  1292. else if(dicpage[NBUCKETS] == PAGEFULL) return(0);
  1293. /* Search inconclusive */
  1294. else return(-1); /* Symbol not in dictionary */
  1295. }
  1296. }
  1297. /* Install symbol in dictionary */
  1298. LOCAL word instsym(IMPORT *psym)
  1299. {
  1300. word dpi; /* Dictionary page index */
  1301. word dpid; /* Dictionary page index delta */
  1302. word dpo; /* Dictionary page offset */
  1303. word dpod; /* Dict. page offset delta */
  1304. word dpii; /* Initial dict. page index */
  1305. register int erc; /* Error code */
  1306. char *dicpage; /* Pointer to dictionary page */
  1307. hashsym(I_EXTNAM(*psym),&dpi,&dpid,&dpo,&dpod);
  1308. /* Hash the symbol */
  1309. dpii = dpi; /* Save initial page index */
  1310. for(;;) /* Forever */
  1311. {
  1312. if(mpdpnpag[dpi] == NULL) /* If page unallocated */
  1313. {
  1314. mpdpnpag[dpi] = alloc(PAGLEN);
  1315. /* Allocate a page */
  1316. nullfill(mpdpnpag[dpi],PAGLEN);
  1317. /* Fill it with nulls */
  1318. mpdpnpag[dpi][NBUCKETS] = FREEWD;
  1319. /* Initialize pointer to free space */
  1320. }
  1321. dicpage = mpdpnpag[dpi]; /* Set pointer to page */
  1322. if((erc = pagesearch(I_EXTNAM(*psym),dicpage,&dpo,dpod)) > 0)
  1323. return(1); /* Return 1 if symbol in table */
  1324. if(erc == -1) /* If empty bucket found */
  1325. {
  1326. if(((I_EXTNAM(*psym)[0] + 4) >> 1) <
  1327. WPP - ((int) dicpage[NBUCKETS] & 0xFF))
  1328. { /* If enough free space on page */
  1329. dicpage[dpo] = dicpage[NBUCKETS];
  1330. /* Load bucket with pointer */
  1331. erc = ((int) dicpage[NBUCKETS] & 0xFF) << 1;
  1332. /* Get byte index to free space */
  1333. dpi = I_EXTNAM(*psym)[0];
  1334. /* Get symbol length */
  1335. for(dpo = 0; dpo <= dpi;)
  1336. dicpage[erc++] = I_EXTNAM(*psym)[dpo++];
  1337. /* Install the symbol text */
  1338. dicpage[erc++] = (char)(I_ORD(*psym) & 0xFF);
  1339. /* Load low-order byte */
  1340. dicpage[erc++] = (char)(I_ORD(*psym) >> 8);
  1341. /* Load high-order byte */
  1342. if(++erc >= PAGLEN) dicpage[NBUCKETS] = PAGEFULL;
  1343. else dicpage[NBUCKETS] = (char)(erc >> 1);
  1344. /* Update free word pointer */
  1345. return(0); /* Mission accomplished */
  1346. }
  1347. else dicpage[NBUCKETS] = PAGEFULL;
  1348. /* Mark page as full */
  1349. }
  1350. if((dpi += dpid) >= diclength) dpi -= diclength;
  1351. /* Try next page */
  1352. if(dpi == dpii) return(2); /* Once around without finding it */
  1353. }
  1354. }
  1355. /* Output empty dictionary page */
  1356. LOCAL void nulpagout(void)
  1357. {
  1358. register word i; /* Counter */
  1359. char temp[PAGLEN]; /* Page buffer */
  1360. i = 0; /* Initialize */
  1361. while(i < NBUCKETS) temp[i++] = '\0';
  1362. /* Empty hash table */
  1363. temp[i++] = FREEWD; /* Set free word pointer */
  1364. while(i < PAGLEN) temp[i++] = '\0'; /* Clear rest of page */
  1365. fwrite(temp,1,PAGLEN,fo); /* Write empty page */
  1366. chkerror();
  1367. }
  1368. /* Write dictionary to library */
  1369. LOCAL void writedic(void)
  1370. {
  1371. register IMPORT *imp; /* Symbol record */
  1372. word i; /* Index variable */
  1373. initsl(); /* Initialize */
  1374. for(imp = implist; imp != NULL; imp = I_NEXT(*imp))
  1375. {
  1376. if(instsym(imp)) /* If symbol already in dictionary */
  1377. Error(ER_multdef, &I_EXTNAM(*imp)[1]);
  1378. /* Issue error message */
  1379. }
  1380. for(i = 0; i < diclength; ++i) /* Look through mapping table */
  1381. {
  1382. if(mpdpnpag[i] != NULL) pagout(mpdpnpag[i]);
  1383. /* Write page if it exists */
  1384. else nulpagout(); /* Else write an empty page */
  1385. }
  1386. chkerror();
  1387. }
  1388. LOCAL void DisplayBanner(void)
  1389. {
  1390. if (!fBannerOnScreen)
  1391. {
  1392. fprintf( stdout, "\nMicrosoft (R) Import Library Manager NtGroup "VERSION_STRING );
  1393. fputs("\nCopyright (C) Microsoft Corp 1984-1996. All rights reserved.\n\n", stdout);
  1394. fflush(stdout);
  1395. fBannerOnScreen = 1;
  1396. #if C8_IDE
  1397. if(fC8IDE)
  1398. { sprintf(msgBuf, "@I0\r\n");
  1399. _write(_fileno(stderr), msgBuf, strlen(msgBuf));
  1400. sprintf(msgBuf, "@I1Microsoft (R) Import Library Manager "VERSION_STRING"\r\n" );
  1401. _write(_fileno(stderr), msgBuf, strlen(msgBuf));
  1402. sprintf(msgBuf, "@I2Copyright (C) Microsoft Corp 1984-1992. All rights reserved.\r\n");
  1403. _write(_fileno(stderr), msgBuf, strlen(msgBuf));
  1404. }
  1405. #endif
  1406. }
  1407. }
  1408. /****************************************************************
  1409. * *
  1410. * IsPrefix: *
  1411. * *
  1412. * This function takes as its arguments a pointer to a *
  1413. * null-terminated character string and a pointer to a second *
  1414. * null-terminated character string. The function returns *
  1415. * true if the first string is a prefix of the second; *
  1416. * otherwise, it returns false. *
  1417. * *
  1418. ****************************************************************/
  1419. LOCAL int IsPrefix(char *prefix, char *s)
  1420. {
  1421. while(*prefix) /* While not at end of prefix */
  1422. {
  1423. if(UPPER(*prefix) != UPPER(*s)) return(0);
  1424. /* Return zero if mismatch */
  1425. ++prefix; /* Increment pointer */
  1426. ++s; /* Increment pointer */
  1427. }
  1428. return(1); /* We have a prefix */
  1429. }
  1430. /*** ScanTable - build list of exports
  1431. *
  1432. * Purpose:
  1433. * Scans Resident or Nonresident Name Table, Entry Table and
  1434. * builds list of exported entries.
  1435. *
  1436. * Input:
  1437. * pbTable - pointer to Name Table
  1438. * cbTable - size of Name Table
  1439. * fNoRes - TRUE if non resident name table
  1440. *
  1441. * Output:
  1442. * List of exported entries by DLL.
  1443. *
  1444. * Exceptions:
  1445. * None.
  1446. *
  1447. * Notes:
  1448. * None.
  1449. *
  1450. *************************************************************************/
  1451. LOCAL void ScanTable(word cbTable, int fNoRes)
  1452. {
  1453. word eno;
  1454. char buffer[256];
  1455. register char *pch;
  1456. register byte *pb;
  1457. byte *pTable;
  1458. pb = alloc(cbTable);
  1459. pTable = pb;
  1460. fread(pb, sizeof(char), cbTable, fi);
  1461. while(cbTable != 0)
  1462. {
  1463. /* Get exported name length - if zero continue */
  1464. --cbTable;
  1465. if (!(eno = (word) *pb++ & 0xff))
  1466. break;
  1467. cbTable -= eno + 2;
  1468. /* Copy name - length prefixed */
  1469. pch = &buffer[1];
  1470. buffer[0] = (byte) eno;
  1471. while(eno--)
  1472. *pch++ = *pb++;
  1473. *pch = '\0';
  1474. /* Get ordinal */
  1475. eno = ((word) pb[0] & 0xff) + (((word) pb[1] & 0xff) << 8);
  1476. pb += 2;
  1477. /* If WEP and fIgnorewep is TRUE, ignore this symbol */
  1478. if(fIgnorewep && strcmp(&buffer[1], "WEP") == 0)
  1479. continue;
  1480. if (eno != 0)
  1481. {
  1482. pch = alloc((word)(buffer[0] + 1));
  1483. strncpy(pch, buffer, buffer[0] + 1);
  1484. // If Implib is run on a DLL, it exports symbols:
  1485. // - by names for symbols in the resident name table
  1486. // - by ordinal for symbols in the non-resident name table
  1487. export(pch, pch, (word)(fNoRes ? eno : 0), (word)0);
  1488. }
  1489. else if (!fNoRes)
  1490. strncpy(sbModule, buffer, buffer[0] + 1);
  1491. /* eno == 0 && !fNoRes --> module name */
  1492. }
  1493. if (cbTable != 0)
  1494. Error(ER_baddll);
  1495. free(pTable);
  1496. }
  1497. /*** ProcessDLL - extract information about exports from DLL
  1498. *
  1499. * Purpose:
  1500. * Read in header of DLL and create list of exported entries.
  1501. *
  1502. * Input:
  1503. * lfahdr - seek offset to segmented executable header.
  1504. *
  1505. * Output:
  1506. * List of exported entries by DLL.
  1507. *
  1508. * Exceptions:
  1509. * None.
  1510. *
  1511. * Notes:
  1512. * None.
  1513. *
  1514. *************************************************************************/
  1515. LOCAL void ProcessDLL(long lfahdr)
  1516. {
  1517. struct new_exe hdr; /* .EXE header */
  1518. fseek(fi, lfahdr, SEEK_SET);
  1519. fread(&hdr, sizeof(char), sizeof(struct new_exe), fi);
  1520. if(NE_CSEG(hdr) != 0)
  1521. {
  1522. /* If there are segments - read in tables */
  1523. if (NE_MODTAB(hdr) > NE_RESTAB(hdr))
  1524. {
  1525. /* Process resident names table */
  1526. fseek(fi, lfahdr + NE_RESTAB(hdr), SEEK_SET);
  1527. ScanTable((word)(NE_MODTAB(hdr) - NE_RESTAB(hdr)), 0);
  1528. }
  1529. if (NE_CBNRESTAB(hdr) != 0)
  1530. {
  1531. /* Process non-resident names table */
  1532. fseek(fi, (long) NE_NRESTAB(hdr), SEEK_SET);
  1533. ScanTable(NE_CBNRESTAB(hdr), 1);
  1534. }
  1535. }
  1536. }
  1537. /* Print usage message */
  1538. void usage(int fShortHelp)
  1539. {
  1540. int nRetCode;
  1541. #if NOT C8_IDE
  1542. // in C8 implib /? == /HELP
  1543. if (!fShortHelp)
  1544. {
  1545. nRetCode = spawnlp(P_WAIT, "qh", "qh", "/u implib.exe", NULL);
  1546. fShortHelp = nRetCode<0 || nRetCode==3;
  1547. }
  1548. if (fShortHelp)
  1549. #endif
  1550. {
  1551. DisplayBanner();
  1552. fprintf(stderr,"%s\n", GET_MSG(M_usage1));
  1553. fprintf(stderr,"%s\n", GET_MSG(M_usage2));
  1554. fprintf(stderr," %s\n", GET_MSG(M_usage3));
  1555. // fprintf(stderr," %s\n", GET_MSG(M_usage4));
  1556. fprintf(stderr," %s\n", GET_MSG(M_usage8));
  1557. fprintf(stderr," %s\n", GET_MSG(M_usage5));
  1558. fprintf(stderr," %s\n", GET_MSG(M_usage6));
  1559. fprintf(stderr," %s\n", GET_MSG(M_usage7));
  1560. }
  1561. exit(0);
  1562. }
  1563. void cdecl main(int argc, char *argv[]) /* Parse the definitions file */
  1564. {
  1565. int i; /* Counter */
  1566. long lfadic; /* File address of dictionary */
  1567. int iArg; /* Argument index */
  1568. word magic; /* Magic number */
  1569. struct exe_hdr exe; /* Old .EXE header */
  1570. int fNologo;
  1571. char drive[_MAX_DRIVE], dir[_MAX_DIR]; /* Needed for _splitpath */
  1572. char fname[_MAX_FNAME], ext[_MAX_EXT];
  1573. int fDefdllfound = 0; /* Flag will be set if the user
  1574. specifies dll/def file */
  1575. #if C8_IDE
  1576. char *pIDE = getenv("_MSC_IDE_FLAGS");
  1577. #endif
  1578. exitCode = 0;
  1579. fNologo = 0;
  1580. iArg = 1;
  1581. #if C8_IDE
  1582. if(pIDE)
  1583. {
  1584. if(strstr(pIDE, "FEEDBACK"))
  1585. {
  1586. fC8IDE = TRUE;
  1587. #if DEBUG_IDE
  1588. fprintf(stdout, "\r\nIDE ACTIVE - FEEDBACK is ON");
  1589. #endif
  1590. }
  1591. }
  1592. #endif
  1593. if (argc > 1)
  1594. {
  1595. while (iArg < argc && (argv[iArg][0] == '-' || argv[iArg][0] == '/'))
  1596. {
  1597. if (argv[iArg][1] == '?')
  1598. usage(1);
  1599. else if (IsPrefix(&argv[iArg][1], "help"))
  1600. usage(0);
  1601. else if(IsPrefix(&argv[iArg][1], "ignorecase"))
  1602. fIgnorecase = 1;
  1603. else if(IsPrefix(&argv[iArg][1], "noignorecase"))
  1604. fIgnorecase = 0;
  1605. else if(IsPrefix(&argv[iArg][1], "nologo"))
  1606. fNologo = 1;
  1607. else if(IsPrefix(&argv[iArg][1], "ntdll"))
  1608. fNTdll = 1;
  1609. else if(IsPrefix(&argv[iArg][1], "nowep"))
  1610. fIgnorewep = 1;
  1611. else
  1612. Error(ER_badoption, argv[iArg]);
  1613. iArg++;
  1614. }
  1615. }
  1616. else
  1617. {
  1618. DisplayBanner();
  1619. exit(exitCode); /* All done */
  1620. }
  1621. if (!fNologo)
  1622. DisplayBanner();
  1623. _splitpath( argv[iArg], drive, dir, fname, ext );
  1624. if(!_stricmp(ext,".DEF")||!_stricmp(ext,".DLL")) /* Ext. not allowed-bug #3*/
  1625. {
  1626. Fatal(ER_badtarget, ext);
  1627. }
  1628. #if C8_IDE
  1629. if(fC8IDE)
  1630. {
  1631. sprintf(msgBuf, "@I3%s\r\n", GET_MSG(M_IDEco));
  1632. _write(_fileno(stderr), msgBuf, strlen(msgBuf));
  1633. sprintf(msgBuf, "@I4%s\r\n", argv[iArg]);
  1634. _write(_fileno(stderr), msgBuf, strlen(msgBuf));
  1635. }
  1636. #endif
  1637. if((fo = fopen(argv[iArg],WRBIN)) == NULL)
  1638. { /* If open fails */
  1639. Fatal(ER_badcreate, argv[iArg], strerror(errno));
  1640. }
  1641. for(i = 0; i < 16; ++i) fputc(0,fo);/* Skip zeroth page for now */
  1642. chkerror();
  1643. implist = NULL; /* Initialize */
  1644. csyms = 0;
  1645. cbsyms = 0L;
  1646. #if C8_IDE
  1647. if(fC8IDE)
  1648. {
  1649. sprintf(msgBuf, "@I3%s\r\n", GET_MSG(M_IDEri));
  1650. _write(_fileno(stderr), msgBuf, strlen(msgBuf));
  1651. }
  1652. #endif
  1653. for(iArg++; iArg < argc; ++iArg)
  1654. {
  1655. if (argv[iArg][0] == '-' || argv[iArg][0] == '/')
  1656. {
  1657. fIgnorecase = IsPrefix(&argv[iArg][1], "ignorecase");
  1658. iArg++;
  1659. continue;
  1660. }
  1661. #if C8_IDE
  1662. if(fC8IDE)
  1663. {
  1664. sprintf(msgBuf, "@I4%s\r\n",argv[iArg]);
  1665. _write(_fileno(stderr), msgBuf, strlen(msgBuf));
  1666. }
  1667. #endif
  1668. if((fi = fopen(defname = argv[iArg],RDBIN)) == NULL)
  1669. { /* If open fails */
  1670. Fatal(ER_badopen, argv[iArg], strerror(errno));
  1671. /* Print error message */
  1672. }
  1673. fDefdllfound = 1;
  1674. newimps = NULL; /* Initialize */
  1675. lastimp = NULL; /* Initialize */
  1676. csymsmod = 0; /* Initialize */
  1677. fread(&exe, 1, sizeof(struct exe_hdr), fi);
  1678. /* Read old .EXE header */
  1679. if(E_MAGIC(exe) == EMAGIC) /* If old header found */
  1680. {
  1681. if(E_LFARLC(exe) == sizeof(struct exe_hdr))
  1682. {
  1683. fseek(fi, E_LFANEW(exe), 0);
  1684. /* Read magic number */
  1685. magic = (word) (getc(fi) & 0xff);
  1686. magic += (word) ((getc(fi) & 0xff) << 8);
  1687. if (magic == NEMAGIC)
  1688. ProcessDLL(E_LFANEW(exe));
  1689. /* Scan .DLL */
  1690. else
  1691. {
  1692. Error(ER_baddll1, argv[iArg]);
  1693. }
  1694. }
  1695. else
  1696. {
  1697. Error(ER_baddll1, argv[iArg]);
  1698. }
  1699. }
  1700. else
  1701. {
  1702. fseek(fi, 0L, SEEK_SET);
  1703. yyparse(); /* Parse the definitions file */
  1704. }
  1705. fclose(fi); /* Close the definitions file */
  1706. if(newimps != NULL) /* If at least one new IMPDEF */
  1707. {
  1708. outimpdefs(); /* Output the library modules */
  1709. I_NEXT(*lastimp) = implist; /* Concatenate lists */
  1710. implist = newimps; /* New head of list */
  1711. csyms += csymsmod; /* Increment symbol count */
  1712. }
  1713. }
  1714. if (!fDefdllfound) /* No .def or .dll source was given */
  1715. Fatal(ER_nosource);
  1716. if(i = (int)((ftell(fo) + 4) & (PAGLEN - 1))) i = PAGLEN - i;
  1717. /* Calculate padding needed */
  1718. ++i; /* One for the checksum */
  1719. fputc(DICHDR,fo); /* Dictionary header */
  1720. fputc(i & 0xFF,fo); /* Lo-byte */
  1721. fputc(i >> 8,fo); /* Hi-byte */
  1722. while(i--) fputc(0,fo); /* Padding */
  1723. lfadic = ftell(fo); /* Get dictionary offset */
  1724. writedic(); /* Write the dictionary */
  1725. fseek(fo,0L,0); /* Seek to header */
  1726. fputc(LIBHDR,fo); /* Library header */
  1727. fputc(13,fo); /* Length */
  1728. fputc(0,fo); /* Length */
  1729. fputc((int)(lfadic & 0xFF),fo); /* Dictionary offset */
  1730. fputc((int)((lfadic >> 8) & 0xFF),fo);
  1731. /* Dictionary offset */
  1732. fputc((int)((lfadic >> 16) & 0xFF),fo);
  1733. /* Dictionary offset */
  1734. fputc((int)(lfadic >> 24),fo); /* Dictionary offset */
  1735. fputc(diclength & 0xFF,fo); /* Dictionary length */
  1736. fputc(diclength >> 8,fo); /* Dictionary length */
  1737. if (fIgnorecase) /* Dictionary case sensivity */
  1738. fputc(0, fo);
  1739. else
  1740. fputc(1, fo);
  1741. chkerror();
  1742. fclose(fo); /* Close the library */
  1743. exit(exitCode); /* All done */
  1744. }