Symtab.c 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361
  1. /*------------------------------------------------------------------*/
  2. /* */
  3. /* MC68000 Cross Assembler */
  4. /* */
  5. /* Copyright 1985 by Brian R. Anderson */
  6. /* */
  7. /* Symbol table manipulation - May 24, 1992 */
  8. /* */
  9. /* This program may be copied for personal, non-commercial use */
  10. /* only, provided that the above copyright notice is included */
  11. /* on all copies of the source code. Copying for any other use */
  12. /* without the consent of the author is prohibited. */
  13. /* */
  14. /*------------------------------------------------------------------*/
  15. /* */
  16. /* Originally published (in Modula-2) in */
  17. /* Dr. Dobb's Journal, April, May, and June 1986. */
  18. /* */
  19. /* AmigaDOS conversion copyright 1991 by Charlie Gibbs. */
  20. /* */
  21. /*------------------------------------------------------------------*/
  22. #include "A68kdef.h"
  23. #include "A68kglb.h"
  24. long Value; /* Passed from ReadSymTab to CalcValue */
  25. int OpenIncl (name, dirlist) char *name, *dirlist;
  26. /* Opens the file whose name is in "name". The current
  27. directory is tried first. If that fails, the directory
  28. names in "dirlist" (separated by commas) are then tried
  29. until either a file is found or the list is exhausted.
  30. If the file is found in a subdirectory, "name" is
  31. modified to include the entire path specification.
  32. If another input file is open when this routine is called,
  33. it is closed first; if the specified file cannot be opened,
  34. the original input file is re-opened and the current position
  35. within that file is restored. This routine Returns TRUE if
  36. it successfully opens the specified file, FALSE if not. */
  37. /* NOTE: Semicolons are also accepted as separators. - Kevin Kofler (v.2.71.F3f) */
  38. {
  39. register char *s, *t;
  40. char dirname[MAXLINE];
  41. if (InF->UPtr == 0) { /* If we're reading from a file */
  42. InF->Pos = lseek (In.fd, 0L,1); /* remember where we are. */
  43. InF->Pos -= In.Lim - In.Ptr;
  44. }
  45. if (In.fd != NOFD)
  46. close (In.fd); /* Close the inner file. */
  47. if ((In.fd = open (name, 0)) >= 0) {
  48. In.Ptr = In.Lim = In.Buf;
  49. if (Quiet < 0)
  50. fprintf (stderr, "\n%s line ", name);
  51. return (TRUE); /* We found it in the current directory. */
  52. }
  53. s = dirlist;
  54. while (*s) {
  55. s = GetField (s, dirname);
  56. t = dirname + strlen (dirname) - 1;
  57. if ((*t != '/') && (*t != ':'))
  58. strcat (dirname, "/"); /* Slash after directory name */
  59. strcat (dirname, name);
  60. if ((In.fd = open (dirname, 0)) >= 0) {
  61. In.Ptr = In.Lim = In.Buf;
  62. strcpy (name, dirname); /* Return entire path. */
  63. if (Quiet < 0)
  64. fprintf (stderr, "\n%s line ", name);
  65. return (TRUE); /* We found it in a subdirectory. */
  66. }
  67. if (*s)
  68. s++; /* Skip over separator and try again. */
  69. }
  70. if (InF->UPtr == 0) { /* We couldn't find it anywhere. */
  71. In.fd = open (InF->NPtr, 0); /* Re-open the outer file, */
  72. lseek (In.fd, InF->Pos, 0); /* and restore current position. */
  73. In.Ptr = In.Lim = In.Buf;
  74. } else {
  75. In.fd = NOFD;
  76. }
  77. return (FALSE);
  78. }
  79. int LineParts (__NO_PARAMS__) /* using now void in v.2.71.F3d - Kevin Kofler */
  80. /* Gets the next statement and extracts its component parts.
  81. If end of file is reached, and we're in a macro or include
  82. file, the file is closed and the next outermost file is
  83. continued. If we have reached the end of the source file, or
  84. encounter an ENDM or MEXIT directive within a macro expansion,
  85. the current input file is closed and TRUE is returned.
  86. If we're in a user macro (indicated by UPtr being nonzero),
  87. we'll get the next statement from the save area in memory instead.
  88. Macro arguments, if any, are substituted.
  89. LineCount is incremented if a statement was successfully read.
  90. If this is the first call of this routine (i.e. LineCount is zero)
  91. and HeaderFN is not a null string, we'll return an INCLUDE statement
  92. requesting the specified header file, rather than reading the first
  93. statement from the source file.
  94. The following fields are set up:
  95. Line - statement line image
  96. Label - instruction label (without trailing colon)
  97. OpCode - instruction mnemonic (converted to upper case)
  98. SrcOp - first (source) operand
  99. DestOp - second (destination) operand
  100. Size - size from OpCode
  101. LabLoc - displacement to start of instruction label
  102. OpLoc - displacement to start of instruction mnemonic
  103. SrcLoc - displacement to start of source operand
  104. DestLoc - displacement to start of destination operand
  105. InFNum - decremented if end of file is reached
  106. InF - incremented if end of file is reached
  107. LabLine - set to LineCount if this line is labeled
  108. (unless it's a local label)
  109. */
  110. {
  111. register int i;
  112. int eofflag;
  113. char *x;
  114. while (1) { /* Repeat until we get something (not end of INCLUDE). */
  115. Line[0] = Label[0] = OpCode[0] = SrcOp[0] = DestOp[0] = '\0';
  116. LabLoc = OpLoc = SrcLoc = DestLoc = 0;
  117. Src.Mode = Dest.Mode = NOMODE;
  118. ErrLim = AddrAdv = InstSize = nO = nS = nD = nX = 0;
  119. PrntAddr = FwdShort = FALSE;
  120. DupFact = 1;
  121. if ((LineCount==0) && (HeaderFN[0])) { /* Header file */
  122. strcpy (Line, " INCLUDE "); /* Make an INCLUDE stmt. */
  123. strcat (Line, HeaderFN);
  124. strcat (Line, " ;Generated for header file");
  125. strcpy (OpCode, "INCLUDE"); /* Dummy op code */
  126. OpLoc = 8;
  127. strcpy (SrcOp, HeaderFN); /* Dummy source operand */
  128. SrcLoc = 16;
  129. LineCount++;
  130. return (FALSE);
  131. }
  132. if (InF->UPtr != 0) { /* User macro input */
  133. GetMacLine (/*dummy*/ /*(using now void in v.2.71.F3d - Kevin Kofler)*/);
  134. eofflag = FALSE;
  135. } else { /* Normal file input */
  136. eofflag = GetLine (/*dummy*/ /*(using now void in v.2.71.F3d - Kevin Kofler)*/);
  137. }
  138. if ((Line[0] != '\0') && (Line[0] != '*') && (Line[0] != ';')) {
  139. SubArgs (/*dummy*/ /*(using now void in v.2.71.F3d - Kevin Kofler)*/); /* Substitute macro arguments. */
  140. GetParts (/*dummy*/ /*(using now void in v.2.71.F3d - Kevin Kofler)*/); /* Break Line into its component parts. */
  141. }
  142. /* ------ If we have reached the end of a macro or ------ */
  143. /* ------ include file, return to the calling file. ----- */
  144. i = eofflag; /* End of file */
  145. if (i) {
  146. if (SkipNest != 0) {
  147. Error (OpLoc, NoENDC); /* ENDC is missing! */
  148. WriteListLine (&List); /* It's not normally listed. */
  149. SkipNest = 0;
  150. }
  151. } else if ((InF->NArg != -1)&&(Dir != Macro)) { /* Macro exits */
  152. if (strcasecmp (OpCode, "ENDM") == 0) {
  153. i = TRUE;
  154. (InF->Line)++; /* Count ENDM directive. */
  155. if (SkipNest != 0) {
  156. Error (OpLoc, NoENDC); /* ENDC is missing! */
  157. WriteListLine (&List); /* It's not normally listed. */
  158. SkipNest = 0;
  159. }
  160. } else if (SkipNest == 0) {
  161. if (strcasecmp (OpCode, "MEXIT") == 0) {
  162. i = TRUE;
  163. (InF->Line)++; /* Count MEXIT directive. */
  164. }
  165. }
  166. }
  167. if (!i) { /* Not end of file or macro */
  168. if (PrevDir == MacCall) {
  169. if (strcasecmp (OpCode, "MACRO") == 0) {
  170. (InF->Line)++; /* Count macro header */
  171. continue; /* and ignore it. */
  172. }
  173. }
  174. if (SkipNest == 0) { /* If we're not skipping, */
  175. break; /* we got something. */
  176. } else {
  177. (InF->Line)++; /* Count skipped lines. */
  178. SkipNest += CountNest (OpCode); /* Adjust SkipNest. */
  179. continue;
  180. }
  181. }
  182. if (!Pass2 && (IncStart != 0) && (IncPtr == InF)) {
  183. SkipLim->Start = IncStart; /* End of skippable INCLUDE */
  184. SkipLim->Finish=LineCount; /* Save line numbers for pass 2. */
  185. SkipLim->MCount = MacCount; /* Save macro counter too. */
  186. SkipLim->LLine = LabLine; /* Save LabLine too -- bugfix by Kevin Kofler
  187. in v.2.71.F3i */
  188. if (SkipLim->Set1 != NULL) {
  189. SetFixLim--;
  190. x = (char *) SkipLim + sizeof (struct SkipEnt);
  191. if (x > (char *) SetFixLim) {
  192. SetFixLim++; /* No room for final entry */
  193. } else {
  194. SetFixLim->Sym = NULL; /* Null entry */
  195. SetFixLim->Val = 0; /* indicates end of */
  196. SetFixLim->Hunk = 0; /* SET symbol list. */
  197. }
  198. }
  199. SkipLim++;
  200. IncStart = 0;
  201. }
  202. if (InFNum == 0)
  203. break; /* End of source file */
  204. if (i = (InF->UPtr == 0)) {
  205. if (Quiet < 0)
  206. fprintf (stderr, "%d\n", InF->Line);
  207. close (In.fd); /* Close inner file. */
  208. In.fd = NOFD;
  209. }
  210. NextFNS = InF->NPtr; /* Release space on name stack. */
  211. InFNum--; /* Return to outer file. */
  212. InF++;
  213. if (InFNum < OuterMac)
  214. OuterMac = 0; /* End of outer macro */
  215. if (InF->UPtr == 0) {
  216. if (i)
  217. ShowFile (FALSE); /* Inner file -> outer file */
  218. else if (InnrFMac) {
  219. ShowFile (FALSE); /* Inner user macro -> file */
  220. InnrFMac = FALSE;
  221. }
  222. if (In.fd == NOFD) {
  223. In.fd = open (InF->NPtr, 0);
  224. lseek (In.fd, InF->Pos, 0);
  225. In.Ptr = In.Lim = In.Buf;
  226. }
  227. } else if (i) {
  228. InnrFMac = TRUE; /* Inner file -> outer user macro */
  229. }
  230. }
  231. LineCount++; /* Bump line counter. */
  232. (InF->Line)++;
  233. if ((Label[0] != '\0') && (Label[0] != '\\'))
  234. if ((Label[0] < '0') || (Label[0] > '9'))
  235. LabLine = LineCount; /* Save line number of label. */
  236. if (Quiet != 0) {
  237. i = (Quiet < 0 ? InF->Line : LineCount);
  238. if ((i % Quiet) == 0) { /* Display progress. */
  239. ShowLine (i);
  240. }
  241. }
  242. if (LineCount == DebugStart)
  243. fprintf (stderr, "%d\n", LineCount);
  244. if ((LineCount >= DebugStart) && (LineCount <= DebugEnd))
  245. printf ("%9lx %5d %s\n", AddrCnt, LineCount, Line);
  246. return (eofflag);
  247. }
  248. void GetMacLine (__NO_PARAMS__) /* using now void in v.2.71.F3d - Kevin Kofler */
  249. /* Gets the next stored user macro line. */
  250. {
  251. register char *s, *t;
  252. register struct NameChunk *np;
  253. s = InF->UPtr;
  254. if (*s == '\n') { /* Continue in next chunk. */
  255. np = NameStart;
  256. while ((s < (char *) np)
  257. || (s > ((char *) np + CHUNKSIZE)))
  258. np = np->Link; /* Find the chunk we're in. */
  259. InF->UPtr = (char *) (np->Link) + sizeof (struct NameChunk *);
  260. s = InF->UPtr;
  261. }
  262. t = Line;
  263. while (*t++ = *s++) /* Copy InF->UPtr to Line, then bump InF->UPtr. */
  264. ; /* (It's faster than doing a strcpy followed */
  265. InF->UPtr = s; /* by a strlen to bump the pointer.) */
  266. }
  267. int GetLine (__NO_PARAMS__) /* using now void in v.2.71.F3d - Kevin Kofler */
  268. /* Gets the next line from the current input file and leaves it in Line.
  269. Returns TRUE if end of file has been reached, FALSE otherwise. */
  270. {
  271. register char *s;
  272. register int c;
  273. register char *t, *m, *l;
  274. s = Line;
  275. t = In.Ptr; /* Use a register for speed. */
  276. m = Line + MAXLINE - 1; /* Limit of "Line" */
  277. while (1) { /* Get Line, expanding tabs. */
  278. if (t >= In.Lim) {
  279. t = In.Buf; /* Re-fill the buffer. */
  280. In.Lim = In.Buf + read (In.fd, In.Buf, BUFFSIZE);
  281. if (In.Lim == In.Buf) {
  282. *s = '\0'; /* End of file */
  283. In.Ptr = t;
  284. return (s <= Line); /* Last line might have no \n. */
  285. }
  286. }
  287. if ((c = *t++) == '\n') {
  288. break;
  289. }
  290. #ifdef MSDOS
  291. if (c == 26) {
  292. *s = '\0'; /* Catch MS-DOS EOF char. */
  293. In.Ptr = t;
  294. return (s <= Line);
  295. }
  296. if ((s < m) && (c != 13)) { /* Ignore excess. */
  297. #else
  298. if (s < m) { /* Ignore excess. */
  299. #endif
  300. if ((c == '\t') && !KeepTabs) {
  301. l = Line + (((s - Line) + 8) & ~7);
  302. if (l > m)
  303. l = m; /* We tabbed off the end. */
  304. while (s < l)
  305. *s++ = ' '; /* Expand tabs. */
  306. } else {
  307. *s++ = c; /* Normal character */
  308. }
  309. }
  310. }
  311. *s = '\0'; /* Terminate the string in Line. */
  312. In.Ptr = t;
  313. return (FALSE);
  314. }
  315. void SubArgs (__NO_PARAMS__) /* using now void in v.2.71.F3d - Kevin Kofler */
  316. /* Macro argument substitution routine */
  317. {
  318. int j;
  319. register char *s, *t, *x;
  320. char subline[MAXLINE];
  321. if (InF->NArg == -1)
  322. return; /* Not a macro - leave Line alone. */
  323. s = Line;
  324. t = subline;
  325. while (*s) {
  326. if ((*t++ = *s++) != '\\') {
  327. continue;
  328. }
  329. x = s--;
  330. t--;
  331. if (*x == '@') { /* \@ - substitute macro number. */
  332. x = t;
  333. *t++ = '.';
  334. /* *t++ = '_'; C.W. Fox - I replaced a . because of named locals */
  335. j = InF->MCnt % 1000;
  336. *t++ = j / 100 + '0';
  337. j = j % 100;
  338. *t++ = j / 10 + '0';
  339. *t++ = j % 10 + '0';
  340. strcpy (t, s+2); /* Remainder of Line */
  341. strcpy (Line, subline); /* Replace Line. */
  342. while (*t != '\\') /* Check for more substitutions. */
  343. if (*t)
  344. t++;
  345. else
  346. return; /* All done */
  347. s = t - subline + Line; /* Do the next substitution. */
  348. continue;
  349. }
  350. if ((*x < '0') || (*x > '9')) {
  351. s++; /* False alarm - it's a */
  352. t++; /* named local variable. */
  353. continue;
  354. }
  355. s++;
  356. *t = '\0';
  357. j = 0; /* Get argument index. */
  358. while ((*s >= '0') && (*s <= '9')) {
  359. j *= 10;
  360. j += *s++ - '0'; /* Current digit */
  361. }
  362. if (j == 0)
  363. strcpy (t, MacSize); /* Macro call size */
  364. else if ((j > 0) && (j <= InF->NArg)) {
  365. x = InF->NPtr;
  366. while (j > 0) { /* Find argument. */
  367. x += strlen (x) + 1;
  368. j--;
  369. }
  370. strcpy (t, x); /* Insert it. */
  371. }
  372. while (*t)
  373. t++; /* Skip over replacement. */
  374. strcpy (t, s); /* Remainder of Line */
  375. strcpy (Line, subline); /* Replace Line. */
  376. while (*t != '\\') /* Check for more substitutions. */
  377. if (*t)
  378. t++;
  379. else
  380. return; /* All done */
  381. s = t - subline + Line; /* Do the next substitution. */
  382. }
  383. }
  384. void GetParts (__NO_PARAMS__) /* using now void in v.2.71.F3d - Kevin Kofler */
  385. /* Break up Line into its component parts. */
  386. {
  387. register char *s, *x;
  388. Size = S0;
  389. s = Line;
  390. if (!isspace (*s)) {
  391. x = Label;
  392. while (!isspace (*s) && (*s != ';') && (*s != '\0'))
  393. *x++ = *s++; /* Get the label. */
  394. *x-- = '\0';
  395. while (*x == ':') {
  396. *x-- = '\0'; /* Strip trailing colon(s). */
  397. if (x < Label)
  398. break;
  399. }
  400. }
  401. while (OpLoc == 0) {
  402. while (isspace (*s))
  403. s++; /* Skip over to opcode. */
  404. if ((*s == ';') || (*s == '\0'))
  405. return; /* End of statement image */
  406. OpLoc = s - Line;
  407. x = OpCode;
  408. while (!isspace (*s) && (*s != ';') && (*s != '\0'))
  409. *x++ = *s++; /* Get the opcode. */
  410. *x-- = '\0';
  411. if (*x == ':') { /* It's actually a label. */
  412. if (Label[0]) {
  413. Error (OpLoc, MultLab); /* Multiple labels */
  414. } else {
  415. while ((x >= OpCode) && (*x == ':'))
  416. *x-- = '\0';
  417. strcpy (Label, OpCode); /* Get the label. */
  418. }
  419. OpLoc = 0; /* Try again for opcode. */
  420. OpCode[0] = '\0';
  421. }
  422. }
  423. #if 0
  424. for (x = OpCode; *x; x++) /* Convert OpCode */
  425. *x = toupper(*x); /* to upper case. */
  426. x -= 2;
  427. #endif
  428. x = OpCode + strlen(OpCode) - 2;
  429. if ((x < OpCode) || (*x != '.')) /* If no explicit size is given */
  430. /* Size = Word; */ /* default to Word (16 bits). */
  431. /* bugfix by Kevin Kofler for the TIGCC team in v.2.71.F3b: */
  432. {
  433. Size = Word; /* default to Word (16 bits). */
  434. noExplicitSize=TRUE; /* remember that no explicit size was given! */
  435. }
  436. else {
  437. /* bugfix by Kevin Kofler for the TIGCC team in v.2.71.F3b: */
  438. noExplicitSize=FALSE; /* remember that an explicit size was given! */
  439. *x++ = '\0'; /* Chop off size extension. */
  440. switch (toupper(*x)) {
  441. case 'B': /* Byte */
  442. case 'S': /* Short Branch */
  443. Size = Byte;
  444. break;
  445. case 'W': /* Word */
  446. Size = Word;
  447. break;
  448. case 'L': /* Long */
  449. Size = Long;
  450. break;
  451. default:
  452. Error (OpLoc+x-OpCode, SizeErr); /* Invalid size */
  453. Size = Word; /* Default to Word. */
  454. break;
  455. }
  456. }
  457. while (isspace(*s))
  458. s++; /* Skip over to operands. */
  459. if ((*s == ';') || (*s == '\0'))
  460. return; /* There are no operands. */
  461. SrcLoc = s - Line;
  462. s = GetField (s, SrcOp); /* Op1 (source) */
  463. if (*s == ',')
  464. s++;
  465. if (!isspace (*s) && (*s != '\0') && (*s != ';')) {
  466. DestLoc = s - Line;
  467. s = GetField (s, DestOp); /* Op2 (destination) */
  468. }
  469. }
  470. void ShowFile (newline) int newline;
  471. /* Shows the current file name if we're displaying all input modules.
  472. If "newline" is TRUE, go to a new line before displaying the name. */
  473. {
  474. if ((Quiet < 0) && (InF->UPtr == 0))
  475. if (newline)
  476. fprintf (stderr, "\n%s line ", InF->NPtr);
  477. else
  478. fprintf (stderr, "%s line ", InF->NPtr);
  479. }
  480. void ShowLine (i) register int i;
  481. /* Shows the current line number and backs up over it. */
  482. {
  483. if (i >= 10000)
  484. fprintf (stderr, "%5d\b\b\b\b\b", i);
  485. else if (i >= 1000)
  486. fprintf (stderr, "%4d\b\b\b\b", i);
  487. else if (i >= 100)
  488. fprintf (stderr, "%3d\b\b\b", i);
  489. else if (i >= 10)
  490. fprintf (stderr, "%2d\b\b", i);
  491. else
  492. fprintf (stderr, "%1d\b", i);
  493. fflush (stderr); /* Make sure it gets out. */
  494. }
  495. char *GetField (s, d) register char *s, *d;
  496. /* Gets a field from "s", returns result in "d".
  497. Stops on the first comma, semicolon, or white space not
  498. enclosed within apostrophes or parentheses.
  499. Returns stopping location.
  500. If already at end of "s", "d" is set to null string. */
  501. {
  502. register char c;
  503. register int parncnt, instring;
  504. instring = FALSE;
  505. parncnt = 0;
  506. while (c = *s) {
  507. if (instring) {
  508. *d++ = c;
  509. } else {
  510. if (isspace(c) || (c == ';'))
  511. break;
  512. else if ((c == ',') && (parncnt == 0))
  513. break;
  514. else {
  515. *d++ = c;
  516. if (c == '(')
  517. parncnt++;
  518. else if (c == ')')
  519. parncnt--;
  520. }
  521. }
  522. if (c == '\'')
  523. instring = !instring;
  524. s++;
  525. }
  526. *d = '\0';
  527. return (s);
  528. }
  529. long GetValue (operand, loc) char *operand; int loc;
  530. /* Determines value of expression. */
  531. /* Hunk2 is set to hunk number of result (ABSHUNK if absolute).
  532. If the expression consists solely of self-defining terms,
  533. DefLine2 is set to zero. Otherwise, DefLine2 is set
  534. to the highest statement number in which any symbol in
  535. the expression was defined. If the expression contains
  536. any undefined symbols, DefLine2 is set to NODEF.
  537. SingleFlag is set to TRUE if the expression consists of a
  538. single term, FALSE otherwise.
  539. The following code is based on a regular-to-Polish expression
  540. converter described in "A Guide to FORTRAN IV Programming"
  541. by Daniel D. McCracken (John Wiley & Sons, Inc. 1965,
  542. 3rd printing August 1968). However, rather than generating
  543. the entire Polish expression, this routine will evaluate
  544. and combine two terms as soon as an operator of lower
  545. precedence is encountered. */
  546. {
  547. register char *o, *s;
  548. char tempop[MAXLINE];
  549. int oloc, parncnt, nextprec, instring;
  550. struct TermStack *origterm;
  551. /* Get rid of leftover AddrDiffs list -- Kevin Kofler, v.2.71.F3l */
  552. while (AddrDiffs) {
  553. struct AddrDiff *next=AddrDiffs->Link;
  554. free(AddrDiffs);
  555. AddrDiffs=next;
  556. }
  557. instring = (unsigned int) '~';
  558. OpPrec[instring] = 9; /* Fudge IsOperator for speed. */
  559. SingleFlag = TRUE; /* Assume there's only a single term. */
  560. for (o = operand; *o; o++) {
  561. if (IsOperator (o)) {
  562. SingleFlag = FALSE; /* It's not a single term. */
  563. break;
  564. }
  565. }
  566. instring = (unsigned int) '~';
  567. OpPrec[instring] = '\0'; /* Restore IsOperator. */
  568. if (SingleFlag)
  569. return(CalcValue(operand,loc)); /* Short cut for single term */
  570. Hunk2 = ABSHUNK;
  571. parncnt = DefLine2 = 0;
  572. o = (char *) (((long) NextFNS + 3L) & ~3L);
  573. origterm = Term = (struct TermStack *) o; /* Term stack */
  574. Ops = (struct OpStack *) InF; /* Operator stack */
  575. Ops--;
  576. ParseSpace (0);
  577. Ops->chr = ' '; /* Prime the operator stack. */
  578. Ops->prec = -1;
  579. if ((char *) Ops < Low2)
  580. Low2 = (char *) Ops;
  581. /* Get all tokens.
  582. Terms are evaluated, and operator precedence is determined.
  583. Left and right parentheses are given a precedence of
  584. 1 and 2 respectively.
  585. Binary operators are given precedence values starting at 3.
  586. Unary plus is ignored.
  587. Unary minus is converted to zero minus the remainder of
  588. of the expression - its precedence is set to 9 to
  589. ensure that the simulated unary operator is evaluated
  590. before the remainder of the expression.
  591. Logical not (~), being another unary operator, is converted
  592. to -1 exclusive-ORed with the remainder of the expression.
  593. Its precedence is also set to 9. */
  594. o = operand; /* Current position in operand */
  595. while (1) {
  596. while (*o == '(') { /* Left parenthesis */
  597. Ops--;
  598. ParseSpace (0);
  599. Ops->chr = '(';
  600. Ops->prec = 1;
  601. if ((char *) Ops < Low2)
  602. Low2 = (char *) Ops;
  603. parncnt++;
  604. o++;
  605. }
  606. if ((*o == '+') || (*o == '-') || (*o == '~')) { /* Unary op */
  607. if (*o != '+') { /* Ignore unary plus. */
  608. Ops--;
  609. ParseSpace (sizeof (struct TermStack));
  610. Term->value = (*o == '-') ? 0 : -1; /* Dummy value */
  611. Term->hunk = ABSHUNK;
  612. Term->oploc = loc + (o - operand);
  613. Term->defline = 0;
  614. Term->isaddrdiff=0; /* added by Kevin Kofler in v.2.71.F3l */
  615. Term++;
  616. if ((char *) Term > High2)
  617. High2 = (char *) Term;
  618. Ops->chr = *o; /* Now get the operator itself. */
  619. Ops->prec = 9; /* Do it ASAP. */
  620. if ((char *) Ops < Low2)
  621. Low2 = (char *) Ops;
  622. }
  623. o++;
  624. if (*o == '(')
  625. continue; /* Inner parenthesized expression */
  626. }
  627. oloc = loc + (o - operand);
  628. s = tempop; /* Get a term. */
  629. if (*o == '*') { /* It's a location counter reference, */
  630. *s++ = *o++; /* not a multiplication operator! */
  631. } else {
  632. if (IsOperator (o) || (*o == '\0')) {
  633. Error (oloc, OperErr); /* Unexpected operator or no terms */
  634. return (0L);
  635. }
  636. instring = (unsigned int) '~';
  637. OpPrec[instring] = 9; /* Fudge IsOperator for speed. */
  638. instring = FALSE;
  639. while (*o) {
  640. if (*o == '\'')
  641. instring=!instring; /* String delimiter */
  642. if (!instring && IsOperator (o))
  643. break; /* Found an operator - stop. */
  644. *s++ = *o++; /* Get a character. */
  645. }
  646. instring = (unsigned int) '~';
  647. OpPrec[instring] = '\0'; /* Restore IsOperator. */
  648. }
  649. *s = '\0';
  650. ParseSpace (sizeof (struct TermStack));
  651. Term->value = CalcValue (tempop, oloc);
  652. Term->hunk = Hunk2;
  653. Term->oploc = oloc;
  654. Term->defline = DefLine2;
  655. Term->isaddrdiff=0; /* added by Kevin Kofler in v.2.71.F3l */
  656. Term++;
  657. if ((char *) Term > High2)
  658. High2 = (char *) Term;
  659. Hunk2 = DefLine2 = 0;
  660. while (*o == ')') { /* Right parenthesis */
  661. if (parncnt == 0) {
  662. Error ((int) (loc + (o - operand)), OperErr);
  663. return (0L);
  664. }
  665. CondCalc (2); /* Unstack what we can. */
  666. if (Ops->chr == '(')
  667. Ops++; /* Drop paired parentheses. */
  668. else {
  669. Ops--;
  670. ParseSpace (0);
  671. Ops->chr = ')'; /* Stack parenthesis for now. */
  672. Ops->prec = 2;
  673. if ((char *) Ops < Low2)
  674. Low2 = (char *) Ops;
  675. }
  676. parncnt--;
  677. o++;
  678. }
  679. if (*o) {
  680. nextprec = IsOperator (o);
  681. if ((nextprec == 0) || (*o == '(')) {
  682. Error ((int) (loc + (o - operand)), OperErr);
  683. return (0L); /* We expected an operator. */
  684. }
  685. CondCalc (nextprec); /* Unstack what we can. */
  686. Ops--;
  687. ParseSpace (0);
  688. Ops->chr = *o; /* Stack the next operator. */
  689. Ops->prec = nextprec;
  690. if ((char *) Ops < Low2)
  691. Low2 = (char *) Ops;
  692. if ((*o == '<') || (*o == '>'))
  693. o++; /* Skip over two-character operator. */
  694. o++;
  695. } else {
  696. if (parncnt) {
  697. Error ((int) (loc + (o - operand)), OperErr);
  698. return (0L); /* Too many left parentheses */
  699. }
  700. CondCalc (0); /* Unstack what's left. */
  701. if (--Term != origterm) /* Should be only one term left */
  702. Error (Term->oploc, OperErr); /* Parser bug? */
  703. Hunk2 = Term->hunk;
  704. DefLine2 = Term->defline;
  705. return (Term->value); /* Final value */
  706. }
  707. }
  708. }
  709. void CondCalc (newprec) int newprec;
  710. /* As long as the top operator on the operator stack has a precedence
  711. greater than or equal to the contents of "newprec", this routine
  712. will pop the two top terms from the term stack, combine them
  713. according to the operator on the top of the operator stack (which
  714. is also popped), and push the result back onto the term stack. */
  715. {
  716. while (Ops->prec >= newprec) { /* Unstack an operator. */
  717. Term -= 2;
  718. if (Ops->chr == '+') { /* Relocatable addition */
  719. if (Term->hunk == ABSHUNK)
  720. Term->hunk = (Term+1)->hunk; /* A+R */
  721. else if ((Term+1)->hunk != ABSHUNK) {
  722. Error ((Term+1)->oploc,RelErr); /* R+R - error */
  723. Term->hunk = ABSHUNK; /* Make it absolute. */
  724. }
  725. } else if (Ops->chr == '-') { /* Subtraction */
  726. if (Term->hunk == (Term+1)->hunk)
  727. Term->hunk = ABSHUNK; /* R-R - absolute */
  728. else if ((Term+1)->hunk != ABSHUNK) { /* R-R across hunks */
  729. Error ((Term+1)->oploc, RelErr); /* is an error - */
  730. Term->hunk = ABSHUNK; /* make it absolute. */
  731. }
  732. } else if ((Term->hunk != ABSHUNK)
  733. || ((Term+1)->hunk != ABSHUNK)
  734. || (Term->isaddrdiff)||((Term+1)->isaddrdiff) /* added by Kevin Kofler in
  735. v.2.71.F3l */
  736. ) {
  737. Error (Term->oploc,RelErr); /* All other operations */
  738. Term->hunk = ABSHUNK; /* must be absolute. */
  739. }
  740. if ((Term+1)->defline > Term->defline) /* Definition */
  741. Term->defline = (Term+1)->defline; /* line nos. */
  742. switch (Ops->chr) { /* Perform the operation. */
  743. case '+':
  744. Term->value += (Term+1)->value;
  745. break;
  746. case '-':
  747. /* In AllReloc-mode, emit a pair of extended relocs here
  748. -- Kevin Kofler, v.2.71.F3l */
  749. /* ...unless the 2 addresses are actually the same.
  750. -- Kevin Kofler, v.2.71.F3q */
  751. if (AllRelocs && !SFormat && (Term+1)->hunk!=ABSHUNK
  752. && Term->value!=(Term+1)->value) {
  753. struct AddrDiff *next=AddrDiffs;
  754. AddrDiffs=malloc(sizeof(struct AddrDiff));
  755. AddrDiffs->Link=next;
  756. AddrDiffs->phunk=AddrDiffs->nhunk=(Term+1)->hunk;
  757. AddrDiffs->paddr=Term->value;
  758. AddrDiffs->naddr=(Term+1)->value;
  759. Term->value=0;
  760. Term->isaddrdiff=1;
  761. break;
  762. }
  763. Term->value -= (Term+1)->value;
  764. break;
  765. case '*':
  766. Term->value *= (Term+1)->value;
  767. break;
  768. case '/':
  769. if ((Term+1)->value)
  770. Term->value /= (Term+1)->value;
  771. else
  772. Term->value = 0; /* Don't divide by zero. */
  773. break;
  774. case '&':
  775. Term->value &= (Term+1)->value;
  776. break;
  777. case '!':
  778. case '|':
  779. Term->value |= (Term+1)->value;
  780. break;
  781. case '<':
  782. Term->value <<= (Term+1)->value;
  783. break;
  784. case '>':
  785. Term->value >>= (Term+1)->value;
  786. break;
  787. case '~':
  788. Term->value ^= (Term+1)->value;
  789. break;
  790. default:
  791. Error (Term->oploc, OperErr); /* Parser bug? */
  792. break;
  793. }
  794. Term++;
  795. Ops++;
  796. }
  797. }
  798. int IsOperator (o) register char *o;
  799. /* Tests whether "o" points to a valid operator or parenthesis.
  800. Returns the precedence of the operator, or 0 if it isn't one. */
  801. {
  802. register unsigned int i;
  803. i = (unsigned int) *o;
  804. i = (unsigned int) OpPrec[i];
  805. if (i != 6)
  806. return ((int) i);
  807. if (*(o+1) == *o)
  808. return ((int) i); /* << or >> */
  809. else
  810. return (0); /* False alarm */
  811. }
  812. long CalcValue (operand, loc) char *operand; int loc;
  813. /* Evaluates a single term (called by GetValue).
  814. Hunk2 receives relative hunk number (ABSHUNK if absolute).
  815. If the value is a symbol, DefLine2 is set to the line number
  816. where it was defined, or NODEF if it is undefined.
  817. For self-defining terms, DefLine2 is set to zero. */
  818. {
  819. register long result; /* Result is calculated here. */
  820. register char *s, *numstart;
  821. register int radix;
  822. int neg, overflow;
  823. char maxdig; /* Highest valid digit in current radix */
  824. char delim; /* String delimiter (' or ") */
  825. Hunk2 = ABSHUNK; /* Assume value is absolute */
  826. DefLine2 = 0; /* and self-defining. */
  827. result = 0;
  828. overflow = FALSE;
  829. if (neg = (*operand == '-'))
  830. numstart = operand + 1; /* Negative value */
  831. else
  832. numstart = operand; /* Positive value */
  833. if ((*numstart >= '0') && (*numstart <= '9')) {
  834. radix = 10; /* Decimal number */
  835. maxdig = '9';
  836. } else if (*numstart == '$') {
  837. radix = 16; /* Hexadecimal number */
  838. maxdig = '9';
  839. } else if ((*numstart == '@') && (isdigit(*(numstart+1)))) {
  840. radix = 8; /* Octal number */
  841. maxdig = '7';
  842. } else if (*numstart == '%') {
  843. radix = 2; /* Binary number */
  844. maxdig = '1';
  845. } else
  846. radix = 0; /* Not a number */
  847. if (radix != 0) { /* Some sort of number */
  848. result = 0;
  849. if (radix != 10)
  850. numstart++; /* Allow for type character. */
  851. for (s = numstart; *s; s++) {
  852. if (!overflow) { /* If we haven't overflowed yet... */
  853. if (radix == 2) { /* Check for binary overflow. */
  854. if (result & 0x80000000L) {
  855. Error (loc, SizeErr);
  856. overflow = TRUE;
  857. }
  858. } else if (radix == 8) { /* Check for octal overflow. */
  859. if (result & 0xE0000000L) {
  860. Error (loc, SizeErr);
  861. overflow = TRUE;
  862. }
  863. } else if (radix == 16) { /* Check for hex overflow. */
  864. if (result & 0xF0000000L) {
  865. Error (loc, SizeErr);
  866. overflow = TRUE;
  867. }
  868. } else { /* Check for decimal overflow. */
  869. if ((result > 429496729L)
  870. || ((result == 429496729L) && (*s > '5'))) {
  871. Error (loc, SizeErr);
  872. overflow = TRUE;
  873. }
  874. }
  875. }
  876. result *= radix;
  877. if ((*s >= '0') && (*s <= maxdig)) {
  878. result += (*s - '0');
  879. } else if (radix == 16) {
  880. if ((*s >= 'A') && (*s <= 'F'))
  881. result += (*s - 'A' + 10);
  882. else if ((*s >= 'a') && (*s <= 'f'))
  883. result += (*s - 'a' + 10);
  884. else
  885. Error (loc + s - operand, OperErr);
  886. } else if (!neg && (radix==10) && (*s=='$') && (*(s+1)=='\0')) {
  887. if (ReadSymTab (operand)) { /* Look up local label. */
  888. result = Value; /* Get its value. */
  889. AddRef (LineCount); /* Add reference. */
  890. if (Sym->Flags & 0x60)
  891. Error (loc, AddrErr); /* Can't use a register equate! */
  892. } else {
  893. Error (loc, Undef); /* Undefined */
  894. }
  895. break;
  896. } else {
  897. Error (loc + s - operand, OperErr);
  898. }
  899. }
  900. } else if ((*operand == '\'') || (*operand == '"')) {
  901. delim = *operand; /* Character value delimiter */
  902. result = 0;
  903. s = operand + 1;
  904. while (1) {
  905. if (*s == '\0') {
  906. Error (loc+s-operand,NoStrEnd); /* End is missing! */
  907. result = 0;
  908. break;
  909. }
  910. if (*s == delim) { /* End of string? */
  911. if (*(++s) != delim) /* Check next character. */
  912. break; /* End of string */
  913. } /* Otherwise it's an apostrophe in the string. */
  914. if ((result & 0xFF000000L) && !overflow) {
  915. Error (loc+s-operand, SizeErr); /* Result overflowed! */
  916. overflow = TRUE;
  917. result = 0;
  918. }
  919. if (!overflow)
  920. result = (result << 8) + *s;
  921. s++;
  922. }
  923. } else if ((*operand == '*') && (*(operand+1) == '\0')) {
  924. result = AddrCnt; /* Value of location counter */
  925. Hunk2 = CurrHunk; /* Use current section's hunk number. */
  926. } else {
  927. if (ReadSymTab (operand)) { /* Look up symbol. */
  928. result = Value; /* Get its value. */
  929. if (Pass2 && (Sym->Defn == NODEF)) {
  930. if (GlobalXREF) {
  931. Sym->Hunk = ~((long) Sym->Nam);
  932. Sym->Defn = LineCount;
  933. Sym->Flags |= 1;
  934. result = Value;
  935. AddRef (LineCount);
  936. } else
  937. Error (loc, Undef);
  938. }
  939. else if (Sym->Flags & 0x60)
  940. Error (loc, AddrErr); /* Can't use a register equate! */
  941. /* Avoid a segfault on invalid code. -- Kevin Kofler, v.2.71.F3v */
  942. while (Sym && Sym->Hunk < 0) { /* Make sure we're */
  943. operand = (void *) ~((long) Sym->Hunk); /* referencing the */
  944. if (operand == Sym->Nam) break; /* real operand, not */
  945. ReadSymTab (operand); /* an equate */
  946. }
  947. if (Sym)
  948. AddRef (LineCount); /* Add reference. */
  949. else
  950. {result = 0; Error (loc, RelErr);}
  951. } else if (strcasecmp (operand, "NARG") == 0) {
  952. result = InF->NArg; /* Number of arguments */
  953. if (result == -1)
  954. result = 0; /* No arguments outside macros */
  955. } else {
  956. if (Pass2 && GlobalXREF) { /* Make all undefined symbols XREF. */
  957. AddSymTab(operand, 0L, 0L, LineCount, 1);
  958. Sym->Hunk = ~((long) Sym->Nam);
  959. ReadSymTab (operand); /* Look up symbol. */
  960. result = Value; /* Get its value. */
  961. AddRef (LineCount); /* Add reference. */
  962. } else {
  963. Error (loc, Undef); /* Undefined */
  964. }
  965. }
  966. }
  967. if (neg) {
  968. result = -result; /* Negative value */
  969. if (Hunk2 != ABSHUNK)
  970. Error (loc, RelErr); /* Must be absolute! */
  971. }
  972. return (result);
  973. }
  974. void AddSymTab (label, value, hunk, line, flags)
  975. char label[];
  976. long value, hunk;
  977. int line, flags;
  978. /* Inserts a new entry to the symbol table and increments NumSyms.
  979. "Sym" will be set to point to the new entry.
  980. If the label is a local label (i.e. the first character is
  981. a numeric digit or a backslash), the current contents of LabLine
  982. will be converted to characters and appended to the label before
  983. it is added. If the first character of the label is a backslash
  984. (i.e. a named local variable) a dollar sign will be appended
  985. to the label ahead of the value of LabLine. */
  986. {
  987. char wlab[MAXLINE], wnum[6];
  988. register struct SymTab *chainsym, **hashindex;
  989. strcpy (wlab, label);
  990. if (((label[0] >= '0') && (label[0] <= '9')) || (label[0] == '\\')) {
  991. if (label[0] == '\\')
  992. /* if ((label[0] == '\\') || (label[0] == '.')) */
  993. strcat (wlab, "$");
  994. sprintf (wnum, "%d", LabLine); /* If it's a local label, */
  995. strcat (wlab, wnum); /* append LabLine. */
  996. }
  997. Sym = SymLim; /* Pointer to new entry */
  998. SymLim++; /* Bump limit pointer. */
  999. if (((char *) SymLim - (char *) SymCurr) > CHUNKSIZE) {
  1000. Sym = (struct SymTab *) malloc ((unsigned) CHUNKSIZE);
  1001. if (Sym == NULL)
  1002. quit_cleanup ("Out of memory!\n");
  1003. SymCurr->Link = Sym; /* Link from previous chunk */
  1004. SymCurr = Sym; /* Make the new chunk current. */
  1005. SymCurr->Link = NULL; /* Clear forward pointer. */
  1006. Sym++; /* Skip over pointer entry. */
  1007. SymLim = Sym; /* New table limit */
  1008. SymLim++; /* Bump it. */
  1009. }
  1010. Sym->Link = NULL; /* Clear hash chain link. */
  1011. Sym->Nam = AddName(wlab,0); /* Pointer to symbol */
  1012. Sym->Val = value; /* Value */
  1013. Sym->Hunk = hunk; /* Hunk number */
  1014. Sym->Defn = line; /* Statement number */
  1015. Sym->Flags = flags; /* Flags */
  1016. Sym->Ref1 = NULL; /* Reference pointer */
  1017. NumSyms++; /* Count symbols. */
  1018. hashindex = HashIt (wlab); /* Get hash index. */
  1019. if (*hashindex == NULL) {
  1020. *hashindex = Sym; /* First entry in this hash chain */
  1021. return;
  1022. }
  1023. chainsym = *hashindex;
  1024. while (chainsym->Link != NULL)
  1025. chainsym = chainsym->Link; /* Scan for end of hash chain. */
  1026. chainsym->Link = Sym; /* Insert new entry at the end. */
  1027. }
  1028. char *AddName (name, macflag) char *name; int macflag;
  1029. /* Adds the name in "name" to the name heap.
  1030. "macflag" can take any of the following values:
  1031. 0 - normal name
  1032. 1 - first line of macro text - there must be room on the
  1033. name heap for at least one character following "name".
  1034. 2 - additional lines of macro text - make sure there's room
  1035. for an addition character (as in 1 above). Also,
  1036. if it is necessary to allocate a new chunk of memory,
  1037. first place a newline character after the last entry
  1038. in the old chunk. This acts as a flag when retrieving
  1039. lines of macro text during an expansion.
  1040. This function returns a pointer to "name" on the name heap. */
  1041. {
  1042. register char *s, *t;
  1043. struct NameChunk *n;
  1044. s = NameLim + strlen(name) + 1; /* The new entry ends here. */
  1045. if (macflag) /* If this is a macro, */
  1046. s++; /* allow for continuation flag. */
  1047. if ((s - (char *) NameCurr) > CHUNKSIZE) { /* If this chunk is full */
  1048. if (macflag == 2) /* If this is more macro text */
  1049. *NameLim = '\n'; /* insert continuation flag. */
  1050. n = (struct NameChunk *) malloc ((unsigned) CHUNKSIZE);
  1051. if (n == NULL)
  1052. quit_cleanup ("Out of memory!\n");
  1053. NameCurr->Link = n; /* Link from previous chunk */
  1054. NameCurr = n; /* Make the new chunk current. */
  1055. NameCurr->Link = NULL; /* Clear forward pointer. */
  1056. s = (char *) NameCurr;
  1057. NameLim = s + sizeof (char *); /* Skip over pointer entry. */
  1058. }
  1059. s = NameLim;
  1060. t = name;
  1061. while ((*s++ = *t++) != '\0') /* Store name. */
  1062. ;
  1063. t = NameLim;
  1064. NameLim = s; /* Update table limit. */
  1065. return (t);
  1066. }
  1067. int ReadSymTab (label) char label[];
  1068. /* Searches the symbol table for the given label.
  1069. If not found, points Sym to NULL and returns FALSE.
  1070. If found, points Sym to the proper table entry,
  1071. and sets up the following fields:
  1072. Value - value of symbol
  1073. Hunk2 - hunk number in which symbol resides
  1074. ABSHUNK if value is absolute
  1075. ones complement of symbol table index if external
  1076. DefLine2 - statement number in which symbol was defined
  1077. (NODEF if undefined )
  1078. If the label is a local label (i.e. the first character is
  1079. numeric), the current contents of LabLine will be converted
  1080. to characters and appended to the label before it is searched.
  1081. (This matches the way AddSymTab added the label to the table.)
  1082. If the first character of the label is a backslash (i.e. a
  1083. named local variable) a dollar sign will be appended to the
  1084. label ahead of the value of LabLine. */
  1085. {
  1086. char wlab[MAXLINE], wnum[6];
  1087. register struct SymTab **hashindex;
  1088. strcpy (wlab, label);
  1089. if (((label[0] >= '0') && (label[0] <= '9')) || (label[0] == '\\')) {
  1090. if (label[0] == '\\')
  1091. /* if ((label[0] == '\\') || (label[0] == '.')) */
  1092. strcat (wlab, "$");
  1093. sprintf (wnum, "%d", LabLine); /* If it's a local label, */
  1094. strcat (wlab, wnum); /* append LabLine. */
  1095. }
  1096. hashindex = HashIt (wlab); /* Get hash index. */
  1097. Sym = *hashindex;
  1098. while (Sym != NULL) {
  1099. if (strcmp (Sym->Nam, wlab) == 0) {
  1100. Value = Sym->Val; /* We found it. */
  1101. Hunk2 = Sym->Hunk;
  1102. if (!(Sym->Flags & 9))
  1103. Hunk2 &= 0x0000FFFFL; /* Isolate hunk number. */
  1104. DefLine2 = Sym->Defn;
  1105. return (TRUE);
  1106. }
  1107. Sym = Sym->Link;
  1108. }
  1109. Value = 0; /* We didn't find it - */
  1110. Hunk2 = ABSHUNK; /* set value to absolute zero. */
  1111. DefLine2 = NODEF;
  1112. return (FALSE);
  1113. }
  1114. struct SymTab **HashIt (label) register char *label;
  1115. /* Returns a pointer to the hash table entry corresponding to "label". */
  1116. {
  1117. register unsigned i;
  1118. i = 0;
  1119. while (*label) {
  1120. i = ((i << 3) - i + *label++) % HashSize;
  1121. }
  1122. return (Hash + i);
  1123. }
  1124. struct SymTab *NextSym (sym) register struct SymTab *sym;
  1125. /* Returns a pointer to the next symbol table entry in memory,
  1126. or NULL if there are no more symbol table entries.
  1127. SymChunk and SymChLim must be properly set up. */
  1128. {
  1129. register struct SymTab *sp;
  1130. if (sym == NULL)
  1131. return (NULL); /* We're nowhere - get out. */
  1132. sym++;
  1133. sp = sym;
  1134. sp++;
  1135. if ((SymLim >= SymChunk) && (SymLim <= SymChLim))
  1136. if (sym >= SymLim)
  1137. return (NULL); /* End of symbol table entries */
  1138. if (sp > SymChLim) {
  1139. if ((SymChunk = SymChunk->Link) == NULL)
  1140. return (NULL); /* End of the last chunk */
  1141. SymChLim = (struct SymTab *) ((char *) SymChunk + CHUNKSIZE);
  1142. sym = SymChunk;
  1143. sym++; /* First entry in the new chunk */
  1144. }
  1145. return (sym);
  1146. }
  1147. void AddRef (linenum) int linenum;
  1148. /* Adds "linenum" to the list of references
  1149. for the symbol pointed to by Sym. */
  1150. {
  1151. register int i;
  1152. register struct Ref *ref, *prevref;
  1153. if (!Pass2)
  1154. return; /* Pass 2 only! */
  1155. if (!XrefList)
  1156. return; /* No cross-reference */
  1157. prevref = NULL;
  1158. ref = Sym->Ref1;
  1159. while (ref) { /* Chase pointers. */
  1160. for (i = 0; i < MAXREF; i++) { /* Scan reference entry */
  1161. if (ref->RefNum[i] == 0) { /* for an empty slot. */
  1162. ref->RefNum[i]=linenum; /* Insert new line number. */
  1163. return;
  1164. }
  1165. }
  1166. prevref = ref; /* Remember where we were. */
  1167. ref = ref->NextRef; /* Link to the next entry. */
  1168. }
  1169. ref = RefLim; /* Pointer to new entry */
  1170. RefLim++; /* Bump limit pointer. */
  1171. if (((char *) RefLim - (char *) SymCurr) > CHUNKSIZE) {
  1172. ref = (struct Ref *) malloc ((unsigned) CHUNKSIZE);
  1173. if (ref == NULL) {
  1174. fprintf (stderr, " \nOut of memory");
  1175. fprintf (stderr, " - cross-reference disabled.\n");
  1176. XrefList = FALSE;
  1177. return;
  1178. }
  1179. SymCurr->Link = (struct SymTab *) ref; /* Link from prev. chunk */
  1180. SymCurr = (struct SymTab *)ref; /* Make the new chunk current. */
  1181. SymCurr->Link = NULL; /* Clear forward pointer. */
  1182. ref++; /* Skip over pointer entry. */
  1183. RefLim = ref; /* New table limit */
  1184. RefLim++; /* Bump it. */
  1185. }
  1186. ref->NextRef = NULL; /* Pointer to next entry */
  1187. ref->RefNum[0] = linenum; /* First reference in new entry */
  1188. for (i = 1; i < MAXREF; i++)
  1189. ref->RefNum[i] = 0; /* Clear remaining slots. */
  1190. if (prevref == NULL)
  1191. Sym->Ref1 = ref; /* Link to first entry */
  1192. else
  1193. prevref->NextRef = ref; /* Link to next entry */
  1194. }
  1195. int CountNest (s) register char *s;
  1196. /* Returns 1 if "s" contains any IF statement (i.e. IFEQ, etc.).
  1197. Returns -1 if "s" contains "ENDC" or "ENDIF".
  1198. Returns 0 in all other cases. */
  1199. {
  1200. if (strcasecmp (s, "ENDC") == 0)
  1201. return (-1);
  1202. else if (strcasecmp (s, "ENDIF") == 0)
  1203. return (-1);
  1204. else if (toupper(*s++) != 'I')
  1205. return (0);
  1206. else if (toupper(*s++) != 'F')
  1207. return (0);
  1208. else if (strcasecmp (s, "EQ") == 0)
  1209. return (1);
  1210. else if (strcasecmp (s, "NE") == 0)
  1211. return (1);
  1212. else if (strcasecmp (s, "GT") == 0)
  1213. return (1);
  1214. else if (strcasecmp (s, "GE") == 0)
  1215. return (1);
  1216. else if (strcasecmp (s, "LT") == 0)
  1217. return (1);
  1218. else if (strcasecmp (s, "LE") == 0)
  1219. return (1);
  1220. else if (strcasecmp (s, "C" ) == 0)
  1221. return (1);
  1222. else if (strcasecmp (s, "NC") == 0)
  1223. return (1);
  1224. else if (strcasecmp (s, "D" ) == 0)
  1225. return (1);
  1226. else if (strcasecmp (s, "ND") == 0)
  1227. return (1);
  1228. else
  1229. return (0);
  1230. }
  1231. void Heap2Space (n) int n;
  1232. /* Die if we can't find "n" bytes on the secondary heap. */
  1233. {
  1234. if ((NextFNS + n) > (char *) InF) {
  1235. printf ("\n%5d %s\n", LineCount, Line);
  1236. quit_cleanup ("Secondary heap overflow - assembly terminated.\n");
  1237. }
  1238. }
  1239. void ParseSpace (n) int n;
  1240. /* Special version of Heap2Space for the expression parser */
  1241. {
  1242. if (((char *) Term + n) > (char *) Ops) {
  1243. printf ("\n%5d %s\n", LineCount, Line);
  1244. quit_cleanup ("Secondary heap overflow - assembly terminated.\n");
  1245. }
  1246. }