Leaked source code of windows server 2003
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.

407 lines
15 KiB

  1. #include <minlit.h> /* Types and constants */
  2. #include <bndtrn.h> /* More of the same */
  3. #include <bndrel.h> /* More of the same */
  4. #include <lnkio.h> /* Linker I/O definitions */
  5. #include <lnkmsg.h> /* Error messages */
  6. #include <extern.h> /* External declarations */
  7. RBTYPE rhteBlank;
  8. RBTYPE rhteBc_vars;
  9. RBTYPE rhteFarData;
  10. RBTYPE rhteFarBss;
  11. SEGTYPE segFD1st;
  12. SEGTYPE segFDLast;
  13. SEGTYPE segFB1st;
  14. SEGTYPE segFBLast;
  15. SNTYPE gsnComBl;
  16. SEGTYPE segQCode;
  17. LOCAL RBTYPE *psymrb; /* pointer to table of sym addr's */
  18. LOCAL WORD symCodeMac; /* # of code symbols */
  19. LOCAL RATYPE raNames; /* offset into $name_list */
  20. LOCAL RATYPE raQbSym; /* offset into SYMBOL segment */
  21. LOCAL SEGTYPE segQbSym; /* segment number of SYMBOL segment */
  22. LOCAL WORD symQbMac; /* count of all symbols */
  23. LOCAL RBTYPE rbQbstart; /* Property address of __aulstart */
  24. #define CBQBHDR sizeof(QBHDRTYPE)
  25. #define CBSYMENTRY (4*sizeof(WORD))
  26. #define QBTYP_CODE 1 /* code symbol */
  27. #define QBTYP_DATA 2 /* data symbol */
  28. #define QBTYP_SEG 3 /* segment symbol */
  29. #define QBTYP_BCSEG 4 /* class BC_VARS, or name COMMON
  30. * and class BLANK */
  31. #define QBTYP_ABS 5 /* absolute symbol */
  32. #define QBMAGIC 0x6c75 /* "ul" */
  33. #define JMPFAR 0xea /* JMP FAR */
  34. #define QB_RACODELST CBQBHDR
  35. #define QBVER 2
  36. /* QB symbol table header */
  37. typedef struct qbhdr
  38. {
  39. BYTE jmpstart[5]; /* JMP FAR __aulstart */
  40. BYTE version; /* version number */
  41. WORD magic; /* Magic word */
  42. WORD raCodeLst; /* Start of code symbols */
  43. WORD raDataLst; /* Start of data symbols */
  44. WORD raSegLst; /* Start of segment symbols */
  45. WORD saCode; /* Segment addr of seg _CODE */
  46. WORD saData; /* Segment addr of seg DGROUP */
  47. WORD saSymbol; /* Segment addr of seg SYMBOL (us) */
  48. WORD cbSymbol; /* Size of seg SYMBOL */
  49. WORD saFarData; /* Segment addr of 1st 'FAR_DATA' seg */
  50. long cbFarData; /* Total size of 'FAR_DATA' segs */
  51. WORD saFarBss; /* Segment addr of 1st 'FAR_BSS' seg */
  52. long cbFarBss; /* Total size of 'FAR_BSS' segs */
  53. } QBHDRTYPE;
  54. /* Offsets into qbhdr */
  55. #define QH_SAQBSTART 3 /* Segment part of __aulstart */
  56. #define QH_SACODE 14 /* saCode */
  57. #define QH_SADATA 16 /* saData */
  58. #define QH_SASYMBOL 18 /* saSymbol */
  59. #define QH_SAFARDATA 22 /* saFarData */
  60. #define QH_SAFARBSS 28 /* saFarBss */
  61. typedef struct qbsym
  62. {
  63. WORD flags; /* symbol type (code, data, segment) */
  64. WORD raName; /* offset into name_list */
  65. WORD ra; /* symbol address offset */
  66. SATYPE sa; /* symbol address segment base */
  67. } QBSYMTYPE;
  68. /*
  69. * LOCAL FUNCTION PROTOTYPES
  70. */
  71. LOCAL void QbSaveSym(APROPNAMEPTR prop,
  72. RBTYPE rhte,
  73. RBTYPE rprop,
  74. WORD fNewHte);
  75. LOCAL void NEAR MoveToQbSym(unsigned short cb,void *pData);
  76. LOCAL void NEAR BldQbHdr(void);
  77. LOCAL void NEAR QbAddName(AHTEPTR ahte);
  78. LOCAL void NEAR BldSegSym(unsigned short gsn);
  79. LOCAL void NEAR BldSym(void FAR *prop);
  80. /*
  81. * Initializes items for Quick Basic symbol table.
  82. */
  83. void NEAR InitQbLib ()
  84. {
  85. SBTYPE sb; /* String buffer */
  86. BYTE *psbRunfile; /* Name of runfile */
  87. #if OVERLAYS
  88. /* If overlays are specified, issue fatal error. */
  89. if(fOverlays)
  90. Fatal(ER_swbadovl, "/QUICKLIB");
  91. #endif
  92. PropSymLookup("\005BLANK",ATTRNIL,TRUE);
  93. rhteBlank = vrhte;
  94. PropSymLookup("\007BC_VARS",ATTRNIL,TRUE);
  95. rhteBc_vars = vrhte;
  96. PropSymLookup("\012__aulstart",ATTRUND,TRUE);
  97. rbQbstart = vrprop;
  98. PropSymLookup("\010FAR_DATA",ATTRNIL,TRUE);
  99. rhteFarData = vrhte;
  100. PropSymLookup("\007FAR_BSS",ATTRNIL,TRUE);
  101. rhteFarBss = vrhte;
  102. /* Assign default runfile extension, as appropriate.
  103. * First, make sb contain .QLB updated with user-supplied
  104. * name and extension, if any.
  105. */
  106. memcpy(sb,sbDotQlb,sizeof(sbDotQlb));
  107. UpdateFileParts(sb,bufg);
  108. /* Next, get the name of the runfile and update it with sb.
  109. */
  110. psbRunfile = GetFarSb(((AHTEPTR) FetchSym(rhteRunfile,FALSE))->cch);
  111. memcpy(bufg,psbRunfile,1 + B2W(*psbRunfile));
  112. UpdateFileParts(bufg,sb);
  113. /* If the name has changed, issue a warning and update rhteRunfile.
  114. */
  115. if(!SbCompare(bufg,psbRunfile,TRUE))
  116. {
  117. bufg[1 + B2W(*bufg)] = 0;
  118. OutWarn(ER_outputname, bufg + 1);
  119. PropSymLookup(bufg,ATTRNIL,TRUE);
  120. rhteRunfile = vrhte;
  121. }
  122. }
  123. void NEAR PrintQbStart(void)
  124. {
  125. fprintf(bsLst,"\r\nProgram entry point at %04x:%04x\r\n",
  126. mpsegsa[segStart],(WORD)raStart); /* Print entry point */
  127. }
  128. LOCAL void QbSaveSym(APROPNAMEPTR prop,
  129. RBTYPE rhte,
  130. RBTYPE rprop,
  131. WORD fNewHte)
  132. {
  133. AHTEPTR hte = (AHTEPTR) rhte;
  134. /* Omit nonprintable symbols from the symbol table */
  135. if (!(prop->an_flags & FPRINT)) return;
  136. /* Omit printable symbols which starts with "B$..." or "b$..." */
  137. if(hte->cch[2] == '$' && hte->cch[0] >= 2 &&
  138. (hte->cch[1] == 'b' || hte->cch[1] == 'B'))
  139. return;
  140. if (prop->an_gsn != SNNIL && mpsegFlags[mpgsnseg[prop->an_gsn]] & FCODE)
  141. symCodeMac++;
  142. psymrb[symQbMac++] = rprop; /* Save the prop addr */
  143. }
  144. LOCAL void NEAR MoveToQbSym (cb, pData)
  145. WORD cb;
  146. char *pData;
  147. {
  148. MoveToVm(cb, pData, segQbSym, raQbSym);
  149. raQbSym += cb;
  150. }
  151. LOCAL void NEAR BldQbHdr ()
  152. {
  153. QBHDRTYPE hdr; /* QB symbol table headr */
  154. APROPNAMEPTR aprop;
  155. SATYPE sa;
  156. memset(&hdr,0,sizeof(hdr)); /* Clear all header fields */
  157. hdr.jmpstart[0] = JMPFAR;
  158. aprop = (APROPNAMEPTR ) FetchSym(rbQbstart,FALSE);
  159. if(aprop == PROPNIL || aprop->an_attr != ATTRPNM)
  160. OutError(ER_qlib);
  161. else
  162. {
  163. hdr.jmpstart[1] = (BYTE) aprop->an_ra;
  164. hdr.jmpstart[2] = (BYTE) (aprop->an_ra >> 8);
  165. sa = mpsegsa[mpgsnseg[aprop->an_gsn]];
  166. hdr.jmpstart[3] = (BYTE) sa;
  167. hdr.jmpstart[4] = (BYTE) (sa >> 8);
  168. RecordSegmentReference(segQbSym,(long)QH_SAQBSTART,1);
  169. }
  170. hdr.raCodeLst = QB_RACODELST; /* $code_list starts at known offset */
  171. hdr.raDataLst = (symCodeMac * CBSYMENTRY) + hdr.raCodeLst + 2;
  172. hdr.raSegLst = ((symQbMac - symCodeMac) * CBSYMENTRY) + hdr.raDataLst + 2;
  173. if(segQCode != SEGNIL)
  174. {
  175. hdr.saCode = mpsegsa[segQCode]; /* 1st code segment */
  176. RecordSegmentReference(segQbSym,(long)QH_SACODE,1);
  177. }
  178. if(ggrDGroup != GRNIL)
  179. {
  180. hdr.saData = mpsegsa[mpgsnseg[mpggrgsn[ggrDGroup]]];
  181. RecordSegmentReference(segQbSym,(long)QH_SADATA,1);
  182. }
  183. hdr.saSymbol = mpsegsa[segQbSym]; /* segment base of SYMBOL (us) */
  184. RecordSegmentReference(segQbSym,(long)QH_SASYMBOL,1);
  185. /* Get starting segment and size of FAR_DATA */
  186. if(segFD1st != SEGNIL)
  187. {
  188. hdr.saFarData = mpsegsa[segFD1st];
  189. RecordSegmentReference(segQbSym,(long)QH_SAFARDATA,1);
  190. hdr.cbFarData = mpsegcb[segFDLast] +
  191. ((long)(mpsegsa[segFDLast] - mpsegsa[segFD1st]) << 4);
  192. }
  193. /* Get starting segment and size of FAR_BSS */
  194. if(segFB1st != SEGNIL)
  195. {
  196. hdr.saFarBss = mpsegsa[segFB1st];
  197. RecordSegmentReference(segQbSym,(long)QH_SAFARBSS,1);
  198. hdr.cbFarBss = mpsegcb[segFBLast] +
  199. ((long)(mpsegsa[segFBLast] - mpsegsa[segFB1st]) << 4);
  200. }
  201. hdr.version = QBVER;
  202. hdr.magic = QBMAGIC;
  203. hdr.cbSymbol = (WORD) raQbSym;
  204. raQbSym = 0;
  205. MoveToQbSym(sizeof hdr, &hdr);
  206. }
  207. int cdecl QbCompSym (const RBTYPE *prb1, const RBTYPE *prb2)
  208. {
  209. APROPNAMEPTR prop;
  210. SNTYPE gsn1, gsn2;
  211. FTYPE fCode1, fCode2;
  212. RBTYPE rb1, rb2;
  213. gsn1 = ((APROPNAMEPTR ) FetchSym(*prb1, FALSE))->an_gsn;
  214. gsn2 = ((APROPNAMEPTR ) FetchSym(*prb2, FALSE))->an_gsn;
  215. if (gsn1 == gsn2)
  216. {
  217. prop = (APROPNAMEPTR ) FetchSym(*prb1,FALSE);
  218. while(prop->an_attr != ATTRNIL)
  219. prop = (APROPNAMEPTR ) FetchSym(rb1 = prop->an_next,FALSE);
  220. prop = (APROPNAMEPTR ) FetchSym(*prb2,FALSE);
  221. while(prop->an_attr != ATTRNIL)
  222. prop = (APROPNAMEPTR ) FetchSym(rb2 = prop->an_next,FALSE);
  223. return(FGtName(&rb1, &rb2));
  224. }
  225. /* For sorting, absolute symbols are treated as data */
  226. /* 1 code, 2 data: 1 < 2 : -1
  227. * 1 data, 2 code: 1 > 2 : 1
  228. * same: 1 = 2 : 0
  229. */
  230. fCode1 = (FTYPE) (gsn1 != SNNIL && mpsegFlags[mpgsnseg[gsn1]] & FCODE);
  231. fCode2 = (FTYPE) (gsn2 != SNNIL && mpsegFlags[mpgsnseg[gsn2]] & FCODE);
  232. if(fCode1 && !fCode2)
  233. return(-1);
  234. if(!fCode1 && fCode2)
  235. return(1);
  236. return(0);
  237. }
  238. LOCAL void NEAR QbAddName (ahte)
  239. AHTEPTR ahte;
  240. {
  241. SBTYPE sbName;
  242. WORD cbName;
  243. BYTE *sb;
  244. sb = GetPropName(ahte);
  245. cbName = B2W(sb[0]);
  246. memcpy(sbName,sb+1,cbName); /* Copy name sans length byte */
  247. sbName[cbName] = '\0'; /* Terminate with null */
  248. MoveToVm((short)(cbName + 1), sbName, segQbSym, raNames);
  249. raNames += cbName + 1; /* Update the name_list offset */
  250. }
  251. LOCAL void NEAR BldSegSym (gsn)
  252. SNTYPE gsn;
  253. {
  254. APROPSNPTR apropSn;
  255. QBSYMTYPE entry;
  256. apropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[gsn], FALSE);
  257. if(apropSn->as_rCla == rhteBc_vars || gsn == gsnComBl)
  258. entry.flags = QBTYP_BCSEG;
  259. else
  260. entry.flags = QBTYP_SEG; /* other segment */
  261. entry.raName = (WORD) raNames; /* offset to name string */
  262. entry.ra = (WORD) mpsegraFirst[mpgsnseg[gsn]];
  263. entry.sa = mpsegsa[mpgsnseg[gsn]];
  264. RecordSegmentReference(segQbSym, (long) (raQbSym + 6), 1);
  265. MoveToQbSym(sizeof entry, &entry); /* Move to symbol segment */
  266. QbAddName((AHTEPTR) apropSn); /* Append name to name_list */
  267. }
  268. /*
  269. * BldSym : Build a Quick symbol table entry for a given symbol prop addr
  270. */
  271. LOCAL void NEAR BldSym (prop)
  272. APROPNAMEPTR prop; /* Symbol property cell */
  273. {
  274. QBSYMTYPE entry; /* Quick symbol entry structure */
  275. SNTYPE seg; /* Segment number */
  276. SATYPE saGroup; /* Group base */
  277. APROPSNPTR papropSn; /* Segment property cell */
  278. #if NOT NEWSYM
  279. prop = (APROPNAMEPTR ) FetchSym((RBTYPE) prop, FALSE);
  280. #endif
  281. /* Set the symbol type in the flags field */
  282. if(prop->an_gsn == SNNIL)
  283. entry.flags = QBTYP_ABS;
  284. else if (mpsegFlags[mpgsnseg[prop->an_gsn]] & FCODE)
  285. entry.flags = QBTYP_CODE;
  286. else
  287. entry.flags = QBTYP_DATA;
  288. entry.raName = (WORD) raNames; /* offset to name string */
  289. entry.ra = (WORD) prop->an_ra; /* symbol address offset */
  290. if(entry.flags == QBTYP_ABS)
  291. entry.sa = 0;
  292. else
  293. {
  294. entry.sa = mpsegsa[seg = mpgsnseg[prop->an_gsn]];
  295. /* symbol address segment */
  296. if(seg <= segLast)
  297. {
  298. /* If segment is member of a group, adjust symbol offset
  299. * to be group-relative.
  300. */
  301. papropSn = (APROPSNPTR ) FetchSym(mpgsnrprop[prop->an_gsn],
  302. FALSE);
  303. if(papropSn->as_ggr != GRNIL)
  304. {
  305. saGroup = mpsegsa[mpgsnseg[mpggrgsn[papropSn->as_ggr]]];
  306. entry.ra = (WORD)((entry.ra + ((entry.sa - saGroup) << 4)) & ~(~0 << WORDLN));
  307. /* Fix offset */
  308. entry.sa = saGroup; /* Set base to base of group */
  309. }
  310. }
  311. RecordSegmentReference(segQbSym, (long) (raQbSym + 6), 1);
  312. }
  313. MoveToQbSym(sizeof entry, &entry); /* Move to SYMBOL segment */
  314. QbAddName((AHTEPTR) prop); /* Append name to name_list */
  315. }
  316. void NEAR BldQbSymbols (gsnQbSym)
  317. SNTYPE gsnQbSym;
  318. {
  319. SNTYPE seg;
  320. SNTYPE gsn;
  321. WORD zero = 0;
  322. APROPSNPTR apropSn;
  323. WORD sym;
  324. extern WORD pubMac;
  325. psymrb = (RBTYPE FAR *) GetMem((pubMac+1) * sizeof(RBTYPE));
  326. segStart = segQbSym = mpgsnseg[gsnQbSym];
  327. raStart = 0;
  328. mpsegFlags[segQbSym] |= FNOTEMPTY; /* Make sure it is output */
  329. if (mpsegMem[segQbSym])
  330. FFREE(mpsegMem[segQbSym]); // Initial allocation was incorrect
  331. mpsegMem[segQbSym] = GetMem(LXIVK); // Allocate 64k
  332. mpsegcb[segQbSym] = LXIVK;
  333. raQbSym = CBQBHDR; /* Skip header for now */
  334. EnSyms(QbSaveSym, ATTRPNM); /* Save the symbol addr's in symrb */
  335. qsort(psymrb, symQbMac, sizeof(RBTYPE),
  336. (int (__cdecl *)(const void *, const void *)) QbCompSym);
  337. /* Sort into code, data, & by name */
  338. raNames = raQbSym + ((symQbMac + segLast) * CBSYMENTRY) + 6;
  339. for (sym = 0; sym < symCodeMac; sym++)
  340. BldSym(psymrb[sym]);
  341. MoveToQbSym(2, &zero);
  342. for (; sym < symQbMac; sym++)
  343. BldSym(psymrb[sym]);
  344. MoveToQbSym(2, &zero);
  345. /* Look for segment COMMON class BLANK */
  346. apropSn = (APROPSNPTR ) PropSymLookup("\006COMMON",ATTRPSN,FALSE);
  347. if(apropSn != PROPNIL)
  348. {
  349. while(apropSn->as_attr != ATTRNIL)
  350. {
  351. if(apropSn->as_attr == ATTRPSN && apropSn->as_rCla == rhteBlank)
  352. break;
  353. apropSn = (APROPSNPTR ) FetchSym(apropSn->as_next,FALSE);
  354. }
  355. if(apropSn->as_attr != ATTRNIL)
  356. gsnComBl = apropSn->as_gsn;
  357. }
  358. for (seg = 1; seg <= segLast; seg++)
  359. {
  360. for (gsn = 1; gsn <= gsnMac && seg != mpgsnseg[gsn]; gsn++);
  361. BldSegSym(gsn);
  362. if(segQCode == SEGNIL && (mpsegFlags[seg] & FCODE))
  363. segQCode = seg;
  364. }
  365. raQbSym = raNames;
  366. MoveToQbSym(2, &zero);
  367. mpsegcb[segQbSym] = (long) raQbSym;
  368. ((APROPSNPTR ) FetchSym(mpgsnrprop[gsnQbSym], TRUE))->as_cbMx = raQbSym;
  369. BldQbHdr();
  370. }