A68kmain.c 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126
  1. /*------------------------------------------------------------------*/
  2. /* */
  3. /* MC68000 Cross Assembler */
  4. /* */
  5. /* Copyright 1985 by Brian R. Anderson */
  6. /* */
  7. /* Main program - May 23, 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. #define PRIMARY
  23. #include "A68kdef.h"
  24. #include "A68kglb.h"
  25. char *Version = "2.71.F3z (July 29, 2009)";
  26. int main (argc,argv) int argc; char *argv[];
  27. {
  28. char ListFN[MAXFN], EquateFN[MAXFN]; /* File names */
  29. int makeequ; /* Make an equate file. */
  30. int keepobj; /* Keep object file with errors. */
  31. int endfile; /* End-of-file flag */
  32. long maxheap2; /* Maximum secondary heap size */
  33. /* int cmderror, dummy; */
  34. int cmderror; /* using now void in v.2.71.F3d - Kevin Kofler */
  35. long codesize, datasize, bsssize;
  36. int *intptr;
  37. long templong;
  38. char tempchar[MAXLINE];
  39. register int i, j;
  40. struct SymTab **hashptr, **fsp;
  41. struct FwdBr *fp1, *fp2, *fp3;
  42. char *vopt[16]; int vopt_num; /* added by Paul Froissart in v.2.71.F3c
  43. variables for the -v switch */
  44. char *p; /* Temporary - added by Paul Froissart in v.2.71.F3c
  45. variable for the -r switch */
  46. /* dummy = 0; */ /* using now void in v.2.71.F3d - Kevin Kofler */
  47. Hash = NULL; /* Clear all memory pointers - */
  48. SymStart = NULL; /* we haven't allocated anything yet. */
  49. NameStart = NULL;
  50. RelStart = NULL;
  51. Heap2 = NULL;
  52. SymSort = NULL;
  53. vopt_num=0; /* number of -v switches - added by Paul Froissart
  54. in v.2.71.F3c */
  55. optim=-1; /* All optimizations are allowed (variable for the -r switch)
  56. added by Paul Froissart in v.2.71.F3c*/
  57. In.fd = Eq.fd = List.fd = Srec.fd = NOFD; /* No files are open yet. */
  58. In.Buf = Eq.Buf = List.Buf = Srec.Buf = NULL;
  59. cmderror = FALSE; /* Clear command-line error flag. */
  60. InclErrs = FALSE;
  61. SourceFN[0] = '\0'; /* We don't have source name yet. */
  62. HeaderFN[0] = EquateFN[0] = '\0'; /* No header or equate files yet */
  63. makeequ = FALSE;
  64. ListFN[0] = SrecFN[0] = '\0'; /* Indicate default file names. */
  65. InclList[0] = '\0'; /* Clear the include directory list. */
  66. IdntName[0] = '\0'; /* Clear program unit name. */
  67. DataOffset = 32768L; /* Default small data offset */
  68. LnMax = 60; /* Default page size */
  69. Quiet = 100; /* Show progress every 100 lines. */
  70. strcpy (MacSize, "W"); /* Macro call size (\0) */
  71. XrefList = DumpSym = GotEqur = KeepTabs = keepobj = FALSE;
  72. Unaligned = FALSE; /* added by Kevin Kofler in v.2.71.F3k */
  73. AllRelocs = FALSE; /* added by Kevin Kofler in v.2.71.F3l */
  74. SuppList = TRUE; /* Default to no listing file. */
  75. HashStats = FALSE; /* Default to no hashing statistics. */
  76. HashSize = DEFHASH; /* Hash table size default */
  77. maxheap2 = DEFHEAP2; /* Secondary heap size default */
  78. DebugStart = NODEF /*32767*/; DebugEnd = 0; /* Disable debug displays. */
  79. isError = FALSE; /* bugfix by Kevin Kofler for the TIGCC team in v.2.71.F3a */
  80. for (i = 0; i < 256; i++)
  81. OpPrec[i] = '\0'; /* Set up the operator precedence table. */
  82. i = (unsigned int) '('; OpPrec[i] = 1;
  83. i = (unsigned int) ')'; OpPrec[i] = 2;
  84. i = (unsigned int) '+'; OpPrec[i] = 3;
  85. i = (unsigned int) '-'; OpPrec[i] = 3;
  86. i = (unsigned int) '*'; OpPrec[i] = 4;
  87. i = (unsigned int) '/'; OpPrec[i] = 4;
  88. i = (unsigned int) '&'; OpPrec[i] = 5;
  89. i = (unsigned int) '!'; OpPrec[i] = 5;
  90. i = (unsigned int) '|'; OpPrec[i] = 5;
  91. i = (unsigned int) '<'; OpPrec[i] = 6;
  92. i = (unsigned int) '>'; OpPrec[i] = 6;
  93. for (i = 1; i < argc; i++) { /* Analyze the command line. */
  94. if (argv[i][0] != '-') {
  95. if (SourceFN[0] == '\0')
  96. strcpy (SourceFN, argv[i]); /* Source file name */
  97. else if (SrecFN[0] == '\0')
  98. strcpy (SrecFN, argv[i]); /* Object file name */
  99. else if (ListFN[0] == '\0')
  100. strcpy (ListFN, argv[i]); /* Listing file name */
  101. else {
  102. fprintf (stderr, "Too many file names.\n");
  103. cmderror = TRUE;
  104. }
  105. } else {
  106. switch (toupper(argv[i][1])) {
  107. case 'A': /* Output all relocs. */
  108. AllRelocs = TRUE;
  109. cmderror |= checkswitch (argv[i], "all relocs");
  110. break;
  111. case 'D': /* Dump the symbol table. */
  112. DumpSym = TRUE;
  113. strcpy (DumpSymList, &argv[i][2]); /* Selections */
  114. break;
  115. case 'E': /* Equate file name */
  116. makeequ = TRUE;
  117. if (getfilename (EquateFN, &argv[i][2], "Equate", FALSE))
  118. cmderror = keepobj = TRUE;
  119. break;
  120. case 'F': /* Dump the symbol table. */
  121. FwdProc = TRUE;
  122. cmderror |= checkswitch (argv[i], "forward reference");
  123. break;
  124. case 'G': /* XREF all unknown globals */
  125. GlobalXREF = TRUE;
  126. cmderror |= checkswitch (argv[i], "automatic XREF");
  127. break;
  128. case 'H': /* Header file name */
  129. if (getfilename (HeaderFN, &argv[i][2], "Header", TRUE))
  130. cmderror = keepobj = TRUE;
  131. break;
  132. case 'I': /* Include directories */
  133. if (argv[i][2]) {
  134. if (InclList[0])
  135. strcat (InclList, ","); /* Add to previous list */
  136. strcat (InclList, &argv[i][2]);
  137. } else {
  138. fprintf (stderr, "Include directory list is missing.\n");
  139. cmderror = keepobj = TRUE;
  140. }
  141. break;
  142. case 'K': /* Keep object code file. */
  143. keepobj = TRUE;
  144. cmderror |= checkswitch (argv[i], "object file keep");
  145. break;
  146. case 'X': /* Cross-reference listing */
  147. XrefList = TRUE; /* Falls through to case 'L': */
  148. case 'L': /* Produce a listing file. */
  149. SuppList = FALSE;
  150. if (getfilename (ListFN, &argv[i][2], "List", FALSE))
  151. cmderror = keepobj = TRUE;
  152. break;
  153. case 'M': /* Offset to small data base */
  154. if (argv[i][2] == '\0') {
  155. fprintf (stderr, "Small data offset is missing.\n");
  156. cmderror = keepobj = TRUE;
  157. break;
  158. }
  159. if (!isdigit (argv[i][2])) {
  160. fprintf (stderr, "Small data offset is invalid.\n");
  161. cmderror = TRUE;
  162. break;
  163. }
  164. DataOffset = CalcValue (&argv[i][2], 0);
  165. break;
  166. case 'N': /* Suppress optimization. */
  167. NoOpt = TRUE;
  168. cmderror |= checkswitch (argv[i], "optimization suppress");
  169. break;
  170. case 'O': /* Object file name */
  171. if (getfilename (SrecFN, &argv[i][2], "Object", TRUE))
  172. cmderror = keepobj = TRUE;
  173. break;
  174. case 'P': /* Page depth */
  175. if (argv[i][2] == '\0') {
  176. fprintf (stderr, "Page depth is missing.\n");
  177. cmderror = keepobj = TRUE;
  178. break;
  179. }
  180. if (!isdigit (argv[i][2])) {
  181. fprintf (stderr, "Page depth is invalid.\n");
  182. cmderror = TRUE;
  183. break;
  184. }
  185. if ((LnMax = CalcValue (&argv[i][2], 0)) < 10) {
  186. fprintf (stderr, "Page depth is invalid.\n");
  187. cmderror = TRUE;
  188. }
  189. break;
  190. case 'Q': /* Quiet console display */
  191. if (argv[i][2] == '\0') {
  192. Quiet = 0;
  193. break;
  194. }
  195. if (!isdigit (argv[i][2])) {
  196. fprintf (stderr, "Quiet interval is invalid.\n");
  197. cmderror = TRUE;
  198. break;
  199. }
  200. Quiet = CalcValue (&argv[i][2], 0);
  201. break;
  202. case 'R': /* Remove optimization - added by Paul Froissart
  203. in v.2.71.F3c */
  204. p=&argv[i][2];
  205. while (*p) switch (tolower(*p++)) {
  206. case 'a': optim &= ~OPTIM_ADDA; break;
  207. case 'l': optim &= ~OPTIM_LEA; break;
  208. case 'm': optim &= ~OPTIM_MOVEM; break;
  209. default: cmderror |= checkswitch (argv[i],"optimization removal");
  210. /* a slightly dirty, but correct way to catch invalid options */
  211. }
  212. break;
  213. case 'S': /* Motorola S-format */
  214. SFormat = TRUE;
  215. cmderror |= checkswitch (argv[i], "S-format");
  216. break;
  217. case 'T': /* Keep tabs in listing. */
  218. KeepTabs = TRUE;
  219. cmderror |= checkswitch (argv[i], "tab");
  220. break;
  221. case 'U': /* Allow unaligned DC/DCB/DS.W/L and code. */
  222. Unaligned = TRUE;
  223. cmderror |= checkswitch (argv[i], "unaligned");
  224. break;
  225. case 'V': /* Set value - added by Paul Froissart in v.2.71.F3c
  226. also checks if more than 16 -v switches (Kevin
  227. Kofler) */
  228. if (vopt_num<=15) {
  229. vopt[vopt_num++]=&argv[i][2];
  230. if (!argv[i][2]) { cmderror=TRUE; fprintf(stderr,"Invalid SET value switch (-v).\n"); }
  231. } else {
  232. cmderror=TRUE; fprintf(stderr,"Too many SET value switches (-v).\n");
  233. }
  234. break;
  235. case 'W': /* Work storage size(s) */
  236. if (argv[i][2] == '\0') {
  237. fprintf (stderr, "Work storage size is missing.\n");
  238. cmderror = keepobj = TRUE;
  239. break;
  240. }
  241. /* if (argv[i][2] != ',') {*/
  242. if ((argv[i][2] != ',') && (argv[i][2] != ';')) {
  243. /* also allow ; as separator - Kevin Kofler, v.2.71.F3f */
  244. GetField (argv[i]+2, tempchar);
  245. if (!isdigit (tempchar[0])) {
  246. fprintf (stderr, "Hash table size is invalid.\n");
  247. cmderror = TRUE;
  248. break;
  249. }
  250. HashSize = CalcValue (tempchar, 0);
  251. if (HashSize >= 16384) {
  252. fprintf (stderr, "Hash table size is too big.\n");
  253. cmderror = TRUE;
  254. }
  255. }
  256. for (j = 2; argv[i][j]; j++) {
  257. /* if (argv[i][j] == ',') {*/
  258. if ((argv[i][j] == ',') || (argv[i][j] == ';')) {
  259. /* also allow ; as separator - Kevin Kofler, v.2.71.F3f */
  260. /* Find secondary size. */
  261. if (!isdigit (argv[i][j+1])) {
  262. fprintf (stderr, "Secondary size is invalid.\n");
  263. cmderror = TRUE;
  264. break;
  265. }
  266. maxheap2 = CalcValue (&argv[i][j+1], 0);
  267. if (maxheap2 < MAXLINE)
  268. maxheap2 = MAXLINE;
  269. maxheap2 &= ~3L;
  270. break;
  271. }
  272. }
  273. break;
  274. case 'Y': /* Display hashing statistics. */
  275. HashStats = TRUE;
  276. cmderror |= checkswitch (argv[i], "hash statistics");
  277. break;
  278. case 'Z': /* Debug option */
  279. DebugStart = 0;
  280. DebugEnd = NODEF /*32767*/;
  281. /* if (argv[i][2] != ',') {*/
  282. if ((argv[i][2] != ',') && (argv[i][2] != ';')) {
  283. /* also allow ; as separator - Kevin Kofler, v.2.71.F3f */
  284. /* Debug dump starts here. */
  285. GetField (argv[i]+2, tempchar);
  286. if (!isdigit (tempchar[0])) {
  287. fprintf (stderr, "Debug start line is invalid.\n");
  288. cmderror = TRUE;
  289. break;
  290. }
  291. DebugStart = CalcValue (tempchar, 0);
  292. }
  293. for (j = 2; argv[i][j]; j++) {
  294. /* if (argv[i][j] == ',') {*/
  295. if ((argv[i][j] == ',') || (argv[i][j] == ';')) {
  296. /* also allow ; as separator - Kevin Kofler, v.2.71.F3f */
  297. /* Debug dump ends here. */
  298. if (!isdigit (argv[i][j+1])) {
  299. fprintf (stderr, "Debug end line is invalid.\n");
  300. cmderror = TRUE;
  301. break;
  302. }
  303. DebugEnd = CalcValue (&argv[i][j+1], 0);
  304. if (DebugEnd == 0)
  305. DebugEnd = NODEF /*32767*/;
  306. }
  307. }
  308. break;
  309. default:
  310. fprintf (stderr, "Unrecognized switch: %c\n", argv[i][1]);
  311. cmderror = TRUE;
  312. break;
  313. }
  314. }
  315. }
  316. if (makeequ)
  317. defaultfile (EquateFN, ".equ"); /* Default equate file name */
  318. if (!SuppList)
  319. defaultfile (ListFN, ".lst"); /* Default list file name */
  320. else /* If there's no listing, don't bother */
  321. KeepTabs = TRUE; /* expanding tabs - it's faster. */
  322. if (SFormat)
  323. defaultfile (SrecFN, ".s"); /* Default S-format file name */
  324. else
  325. defaultfile (SrecFN, ".o"); /* Default object file name */
  326. /* Check for duplicate file names. */
  327. if (SourceFN[0]) {
  328. cmderror |= checkdupfile (SourceFN, "Source", EquateFN, "equate");
  329. cmderror |= checkdupfile (SourceFN, "Source", ListFN, "listing");
  330. cmderror |= checkdupfile (SourceFN, "Source", SrecFN, "object");
  331. } else {
  332. fprintf (stderr, "Source file name is missing.\n");
  333. cmderror = TRUE;
  334. }
  335. if (EquateFN[0]) {
  336. cmderror |= checkdupfile (EquateFN, "Equate", ListFN, "listing");
  337. cmderror |= checkdupfile (EquateFN, "Equate", SrecFN, "object");
  338. }
  339. if (ListFN[0]) {
  340. cmderror |= checkdupfile (ListFN, "Listing", SrecFN, "object");
  341. }
  342. /* Open files. */
  343. if (!cmderror) { /* Source file */
  344. if ((In.Buf = (char *) malloc (BUFFSIZE)) == NULL)
  345. quit_cleanup ("Out of memory!\n");
  346. #ifdef MSDOS
  347. _fmode = O_BINARY;
  348. #endif
  349. if ((In.fd = open (SourceFN, 0)) < 0) {
  350. fprintf (stderr, "Unable to open source file.\n");
  351. In.fd = NOFD;
  352. cmderror = TRUE;
  353. }
  354. In.Ptr = In.Lim = In.Buf;
  355. }
  356. #ifdef MSDOS
  357. _fmode = O_TEXT;
  358. #endif
  359. if (!cmderror && EquateFN[0]) /* Equate file */
  360. cmderror |= xopen (EquateFN, &Eq, "equate");
  361. if (!cmderror && !SuppList) /* Listing file */
  362. cmderror |= xopen (ListFN, &List, "listing");
  363. #ifdef MSDOS
  364. if (!SFormat)
  365. _fmode = O_BINARY;
  366. #endif
  367. if (!cmderror) /* Object code file */
  368. cmderror |= xopen (SrecFN, &Srec, "object code");
  369. #ifdef MSDOS
  370. _fmode = O_BINARY;
  371. #endif
  372. if (cmderror) {
  373. fprintf (stderr, "\n");
  374. fprintf (stderr, "68000 Assembler - version %s\n", Version);
  375. fprintf (stderr,
  376. "Copyright 1985 by Brian R. Anderson\n"
  377. "AmigaDOS conversion copyright 1991 by Charlie Gibbs.\n"
  378. "Adapted for use with Fargo by David Ellsworth.\n"
  379. #ifdef ST_VERSION
  380. "Atari ST conversion copyright 1990 by Colin Fox and Darren Schebek\n\n"
  381. #endif ST_VERSION
  382. #ifdef WIN32
  383. "Win32 port copyright 2001-2005 by Kevin Kofler for the TIGCC project\n"
  384. #endif
  385. "Bugfixes and additions by Julien Muchembled, Paul Froissart and Kevin Kofler\n\n"
  386. "Usage: a68k <source file>\n"
  387. " [-a] [-p<page depth>]\n"
  388. " [-d[[!]<prefix>]] [-q[<quiet interval>]]\n"
  389. " [-e[<equate file>]] [-r[a][l][m]]\n"
  390. " [-f] [-s]\n"
  391. " [-g] [-t]\n"
  392. " [-h<header file>] [-u]\n"
  393. " [-i<include dirlist>] [-v<name>[,<value>]]\n"
  394. " [-k] "
  395. "[-w[<hash size>][,<heap size>]]\n"
  396. " [-l[<listing file>]] [-x]\n"
  397. " [-m<small data offset>] [-y]\n"
  398. " [-n] "
  399. "[-z[<debug start>][,<debug end>]]\n"
  400. " [-o<object file>]\n\n"
  401. "Heap size default: -w"
  402. "%ld,%ld\n", (long) DEFHASH, (long) DEFHEAP2);
  403. SrecFN[0] = '\0'; /* Don't scratch the object file! */
  404. quit_cleanup ("\n");
  405. }
  406. if (Quiet != 0) {
  407. printf ("68000 Assembler - version %s\n", Version);
  408. printf ("Copyright 1985 by Brian R. Anderson\n"
  409. "AmigaDOS conversion copyright 1991 by Charlie Gibbs.\n"
  410. "Adapted for use with Fargo by David Ellsworth.\n"
  411. #ifdef ST_VERSION
  412. "Atari ST conversion copyright 1990 by Colin Fox and Darren Schebek\n\n"
  413. #endif ST_VERSION
  414. #ifdef WIN32
  415. "Win32 port copyright 2001-2005 by Kevin Kofler for the TIGCC project\n"
  416. #endif
  417. "Bugfixes and additions by Julien Muchembled, Paul Froissart and Kevin Kofler\n\n"
  418. "Assembling %s\n\n", SourceFN);
  419. }
  420. /* Allocate initial symbol table chunks. */
  421. templong = sizeof (struct SymTab *) * HashSize;
  422. Hash = (struct SymTab **) malloc ((unsigned) templong);
  423. if (Hash == NULL)
  424. quit_cleanup ("Out of memory!\n");
  425. for (hashptr = Hash, i = 0; i < HashSize; hashptr++, i++)
  426. *hashptr = NULL; /* Clear the hash table. */
  427. SymStart = (struct SymTab *) malloc ((unsigned) CHUNKSIZE);
  428. if (SymStart == NULL)
  429. quit_cleanup ("Out of memory!\n");
  430. SymCurr = SymStart; /* Make the first chunk current. */
  431. SymCurr->Link = NULL; /* Clear forward pointer. */
  432. SymLim = SymCurr;
  433. SymLim++; /* Start of names */
  434. NameStart = (struct NameChunk *) malloc ((unsigned) CHUNKSIZE);
  435. if (NameStart == NULL)
  436. quit_cleanup ("Out of memory!\n");
  437. NameCurr = NameStart; /* Make the first chunk current. */
  438. NameCurr->Link = NULL; /* Clear forward pointer. */
  439. NameLim = (char *) NameCurr + sizeof (char *); /* Start of names */
  440. /* Allocate the relocation attribute table. */
  441. RelStart = (struct RelTab *) malloc ((unsigned) CHUNKSIZE);
  442. if (RelStart == NULL)
  443. quit_cleanup ("Out of memory!\n");
  444. RelCurr = RelStart; /* Relocation table */
  445. RelCurr->Link = NULL; /* No additional chunks */
  446. RelLast = NULL; /* There are no entries yet. */
  447. RelLim = RelStart;
  448. RelLim++; /* First unused space */
  449. /* Allocate the secondary heap (input files and parser stack). */
  450. Heap2 = malloc ((unsigned) maxheap2);
  451. if (Heap2 == NULL)
  452. quit_cleanup ("Out of memory!\n");
  453. /* Allocate the INCLUDE skip table. */
  454. SkipLim = (struct SkipEnt *) malloc ((unsigned) INCSKSIZ);
  455. if (SkipLim == NULL)
  456. quit_cleanup ("Out of memory!\n");
  457. SkipIdx = SkipLim;
  458. SetFixLim = (struct SetFixup *) ((char *) SkipLim + INCSKSIZ);
  459. IncStart = 0;
  460. /* Allocate the forward branch optimization log. */
  461. if (NoOpt) {
  462. FwdStart = NULL;
  463. } else {
  464. FwdStart = (struct FwdTable *) malloc ((unsigned) FWDSIZE);
  465. if (FwdStart == NULL)
  466. quit_cleanup ("Out of memory!\n");
  467. FwdCurr = FwdStart; /* Make the first chunk current. */
  468. FwdCurr->Link = NULL; /* Clear forward pointer. */
  469. FwdLim2 = (int *) ((char *) FwdCurr + sizeof (struct FwdTable *));
  470. FwdPtr = FwdLim2; /* Current position in pass 2 */
  471. }
  472. /*-------------------------------------------------------------------
  473. Begin Pass 1.
  474. */
  475. Pass2 = FALSE;
  476. startpass ('1', maxheap2);
  477. NumSyms = 0; /* There's nothing in the symbol table yet. */
  478. NextHunk = 0L; /* Start in hunk zero. */
  479. LowInF = InF; /* Initialize secondary heap usage pointers. */
  480. High2 = NextFNS;
  481. Low2 = (char *) LowInF;
  482. FwdLim1 = FwdBranch; /* Forward branch controls */
  483. FwdFixLimit = FwdBranchFix;
  484. /* Define ".A68K" as a SET symbol with an absolute value of 1.
  485. This allows programs to identify this assembler. */
  486. AddSymTab (".A68K", 1L, (long) ABSHUNK, 0, 4); /* All spellings */
  487. AddSymTab (".A68k", 1L, (long) ABSHUNK, 0, 4);
  488. AddSymTab (".a68K", 1L, (long) ABSHUNK, 0, 4);
  489. AddSymTab (".a68k", 1L, (long) ABSHUNK, 0, 4);
  490. /* If -a is given, define "__ld_all_relocs" as an XDEF symbol to a dummy label.
  491. This allows linkers to identify such object files. -- Kevin Kofler, v.2.71.F3l */
  492. if (AllRelocs) AddSymTab ("__ld_all_relocs", 0L, 0L, 1, 2);
  493. /* Add -v variables - added by Paul Froissart in 2.71.F3c: */
  494. while (vopt_num) {
  495. char *s=vopt[--vopt_num]; long val; /* decrement vopt_num at the
  496. beginning - Kevin Kofler, v.2.71.F3c */
  497. /* while (*s && *s!=',') s++;*/
  498. while ((*s) && (*s!=',') && (*s!=';') && (*s!='=')) s++;
  499. /* also allow ; and = as separators - Kevin Kofler, v.2.71.F3f */
  500. if (s==vopt[vopt_num]) /* exit(0x39); */
  501. quit_cleanup ("Invalid SET value switch (-v).\n");
  502. /* exit cleanly and with an error message - Kevin Kofler, v.2.71.F3c */
  503. if (!*s) val=1; else { *s++=0; val=CalcValue(s,0); }
  504. AddSymTab(vopt[vopt_num],val,(long)ABSHUNK,0,4);
  505. /* vopt_num--; */ /* see above - Kevin Kofler, v.2.71.F3c */
  506. }
  507. endfile = FALSE;
  508. Dir = None;
  509. while (!endfile && (Dir != End)) {
  510. PrevDir = Dir; /* Save previous directive. */
  511. endfile = LineParts (/*dummy*/ /*(using now void in v.2.71.F3d - Kevin Kofler)*/); /* Get a statement. */
  512. pass1cont: /* necessary for optional END - Paul Froissart, v.2.71.F3c */
  513. GetObjectCode (/*dummy*/ /*(using now void in v.2.71.F3d - Kevin Kofler)*/); /* Process the statement. */
  514. if (IncStart != 0) {
  515. if ((OpCode[0] != '\0') && (Dir < SkipDir)) {
  516. IncStart = 0; /* We can't */
  517. if (SkipLim->Set1 != NULL) { /* skip this */
  518. SetFixLim = SkipLim->Set1; /* INCLUDE file */
  519. SetFixLim++; /* in pass 2. */
  520. }
  521. }
  522. }
  523. if ((HunkType == HunkNone) && (AddrAdv != 0)) {
  524. DoSection ("", 0, "", 0, "", 0); /* Start unnamed CODE section. */
  525. MakeHunk = TRUE;
  526. }
  527. if ((Label[0] != '\0') /* If the statement is labeled */
  528. && (Dir != Set) && (Dir != Equr) && (Dir != Reg)) {
  529. if (!ReadSymTab (Label)) { /* Make a new entry. */
  530. AddSymTab (Label, AddrCnt, CurrHunk, LineCount, 0);
  531. } else if ((Sym->Flags & 1) /* If dup., ignore... */
  532. || (Sym->Defn == NODEF)) { /* else fill in... */
  533. Sym->Val = AddrCnt; /* Current loc. */
  534. Sym->Hunk = CurrHunk; /* Hunk number */
  535. Sym->Defn = LineCount; /* Statement number */
  536. Sym->Flags &= ~1; /* Clear XREF flag. */
  537. if (Sym->Flags & 0x80) { /* If it's PUBLIC, */
  538. Sym->Flags |= 2; /* make it XDEF. */
  539. }
  540. }
  541. else isError=TRUE; /* bugfix by Kevin Kofler for the TIGCC team in
  542. v.2.71.F3a
  543. if duplicate, set "error detected" flag */
  544. if (Dir == Equ) {
  545. Sym->Val = ObjSrc; /* Equated value */
  546. Sym->Hunk = Src.Hunk; /* Hunk number */
  547. }
  548. if (!NoOpt && (Dir != Equ)) { /* Forward optimization */
  549. PackFwdBranch (/*dummy*/ /*(using now void in v.2.71.F3d - Kevin Kofler)*/); /* Drop expired entries. */
  550. fp1 = FwdBranch;
  551. while (fp1 < FwdLim1) { /* Scan forward branches. */
  552. if (fp1->FwdSym == Sym) { /* It branched here. */
  553. if (fp1->Loc != (AddrCnt-4)) { /* Don't make zero displacement! */
  554. if (fp1->Line < LineCount)
  555. Sym->Val -= 2; /* Move the label back. */
  556. AddrCnt -= 2; /* Shorten the program. */
  557. for (fsp = FwdBranchFix; fsp < FwdFixLimit; fsp++) {
  558. if (fp1->Loc<(*fsp)->Val) { /* Adjust labels */
  559. (*fsp)->Val -= 2; /* within range. */
  560. }
  561. }
  562. if ((char *) FwdLim2 >= ((char *) FwdCurr + FWDSIZE)) {
  563. FwdCurr->Link = /* Get a new chunk. */
  564. (struct FwdTable *) malloc ((unsigned) FWDSIZE);
  565. if (FwdCurr->Link == NULL)
  566. quit_cleanup ("Out of memory!\n");
  567. FwdCurr = FwdCurr->Link;
  568. FwdCurr->Link = NULL; /* Make sure it does not link to anything
  569. It is a freshly allocated block AT THE END of the linked list!
  570. bugfix submitted by [Pollux] (Paul Froissart) for 2.71.F3a */
  571. FwdLim2 = (int *)
  572. ((char *) FwdCurr + sizeof (struct FwdTable *));
  573. }
  574. *FwdLim2++ = fp1->Line; /* Flag this branch in pass 2. */
  575. }
  576. fp3 = fp2 = fp1;
  577. fp3++;
  578. while (fp3 < FwdLim1) { /* Remove processed entry. */
  579. fp2->Loc = fp3->Loc - 2; /* Locations shifted too! */
  580. fp2->FwdSym = fp3->FwdSym;
  581. fp2->Line = fp3->Line;
  582. fp2++;
  583. fp3++;
  584. }
  585. FwdLim1--; /* Decrement table limit pointer. */
  586. fp1--; /* Offset increment below. */
  587. }
  588. fp1++; /* Check the next entry. */
  589. }
  590. if (FwdLim1 > FwdBranch) { /* Store labels within */
  591. *FwdFixLimit++ = Sym; /* range of fwd. branch. */
  592. }
  593. }
  594. }
  595. AddrCnt += AddrAdv * DupFact; /* Advance the location counter. */
  596. if (endfile) { /* END is now optional */
  597. strcpy(Line," end"); endfile=0; /* Enhancement by Paul Froissart */
  598. SubArgs(/*dummy*/ /*(using now void in v.2.71.F3d - Kevin Kofler)*/); GetParts(/*dummy*/ /*(using now void in v.2.71.F3d - Kevin Kofler)*/); /* in version v2.71.F3c */
  599. goto pass1cont;
  600. }
  601. }
  602. if ((HunkType == HunkNone) && (NumSyms != 0)) { /* Dummy section */
  603. DoSection ("", 0, "", 0, "", 0); /* to get XDEF */
  604. MakeHunk = TRUE; /* symbols if any */
  605. }
  606. if (HunkType != HunkNone)
  607. if (AddrCnt > OrgHigh)
  608. Sect->Val = AddrCnt; /* End of the last section */
  609. else
  610. Sect->Val = OrgHigh; /* We've ORGed higher. */
  611. if (InclErrs)
  612. quit_cleanup ("Fatal errors - assembly aborted\n");
  613. if (Quiet > 0)
  614. fprintf (stderr, "%d\n", LineCount);
  615. else if (Quiet < 0)
  616. fprintf (stderr, "%d\n\n", InF->Line);
  617. /*----------------------------------------------------------------
  618. Begin Pass 2.
  619. */
  620. Pass2 = TRUE;
  621. lseek (In.fd, 0L, 0); /* "Rewind" the source file. */
  622. In.Ptr = In.Lim = In.Buf;
  623. startpass ('2', maxheap2);
  624. /* RefLim = (struct Ref *) SymLim; */ /* Cross-reference table */
  625. RefLim = (struct Ref *) (SymLim+1);
  626. /* don't overwrite the last symbol - Kevin Kofler, v.2.71.F3h */
  627. /* Calculate the total size of each section type,
  628. reset all section pointers to the beginning, and
  629. write all absolute symbols to an equate file if desired. */
  630. codesize = datasize = bsssize = 0;
  631. if (EquateFN[0]) {
  632. xputs (&Eq, "* Equate file for ");
  633. xputs (&Eq, SourceFN);
  634. xputs (&Eq, "\n* Created by");
  635. xputs (&Eq, " A68k version ");
  636. xputs (&Eq, Version);
  637. xputs (&Eq, "\n");
  638. }
  639. Sym = SymChunk = SymStart;
  640. Sym++;
  641. SymChLim = (struct SymTab *) ((char *) SymChunk + CHUNKSIZE);
  642. while (Sym) {
  643. if (Sym->Flags & 0x10) {
  644. templong = (Sym->Val + 3) & ~3L; /* Hunk size */
  645. j = (Sym->Hunk & 0x3FFF0000L) >> 16; /* Hunk type */
  646. if (j == HunkCode) /* Accumulate sizes by type. */
  647. codesize += templong;
  648. else if (j == HunkData)
  649. datasize += templong;
  650. else
  651. bsssize += templong;
  652. Sym->Val = 0L; /* Back to start of all sections */
  653. }
  654. if (EquateFN[0]) {
  655. if (((Sym->Hunk & 0x00007FFFL) == ABSHUNK)
  656. && ((Sym->Flags == 0) || (Sym->Flags == 2))) {
  657. xputs (&Eq, Sym->Nam);
  658. xputs (&Eq, "\tEQU\t$");
  659. LongPut (&Eq, Sym->Val, 4);
  660. xputs (&Eq, "\n");
  661. }
  662. }
  663. Sym = NextSym (Sym); /* Try for another symbol table entry. */
  664. }
  665. if (EquateFN[0])
  666. xclose (&Eq);
  667. /* Write sign-on messages for listing file. */
  668. LnCnt = LnMax;
  669. PgCnt = 0;
  670. if (!SuppList) {
  671. CheckPage (&List, FALSE); /* Print headings. */
  672. xputs (&List, "68000 Assembler - version ");
  673. xputs (&List, Version);
  674. xputs (&List, "\nCopyright 1985 by Brian R. Anderson.\n");
  675. xputs (&List, "AmigaDOS conversion copyright 1991");
  676. xputs (&List, " by Charlie Gibbs.\n\n");
  677. LnCnt += 4;
  678. }
  679. StartSrec (&Srec, IdntName); /* Write object header record. */
  680. /* Process the second pass. */
  681. endfile = FALSE;
  682. Dir = None;
  683. while (!endfile && (Dir != End)) {
  684. PrevDir = Dir; /* Save previous directive. */
  685. endfile = LineParts (/*dummy*/ /*(using now void in v.2.71.F3d - Kevin Kofler)*/); /* Get a statement. */
  686. /* if (!endfile) { */
  687. pass2cont: /* necessary for optional END - Paul Froissart, v.2.71.F3c */
  688. GetObjectCode (/*dummy*/ /*(using now void in v.2.71.F3d - Kevin Kofler)*/); /* Process the statement. */
  689. if (Label[0] != '\0') { /* If statement is labeled, */
  690. ReadSymTab (Label); /* check for duplicate defn. */
  691. if (Sym) /* Check if Sym actually exists -- bugfix by Kevin Kofler for
  692. the TIGCC Team in v.2.71.F3a. */
  693. { /* (TIGCC) */
  694. if (Sym->Defn != LineCount) {
  695. AddRef (LineCount); /* Got one - flag as reference. */
  696. if (Dir == Set) {
  697. if ((Sym->Flags & 4) == 0)
  698. Error (LabLoc, SymDup); /* Can't SET normal label. */
  699. } else {
  700. Error (LabLoc, SymDup); /* Ordinary duplicate */
  701. }
  702. } else if (Dir == Set) {
  703. AddRef (LineCount); /* Flag all SETs as references. */
  704. } else {
  705. if (Sym->Val != AddrCnt)
  706. if ((Dir != Equ) && (Dir != Equr) && (Dir != Reg))
  707. Error (0, Phase); /* Assembler error */
  708. }
  709. } /* (TIGCC) */
  710. else /* (TIGCC) */
  711. Error (0, Phase); /* (TIGCC) */
  712. }
  713. WriteListLine (&List);
  714. /* WriteSrecLine (&Srec); */
  715. WriteSrecLine (); /* removed useless parameter - Kevin Kofler, v.2.71.F3d */
  716. AddrCnt += AddrAdv * DupFact; /* Advance the location counter. */
  717. /* } else {
  718. Error (0, EndErr); ** END statement is missing. **
  719. WriteListLine (&List); */
  720. if (endfile) { /* END is now optional */
  721. strcpy(Line," end"); endfile=0; /* Enhancement by Paul Froissart */
  722. SubArgs(/*dummy*/ /*(using now void in v.2.71.F3d - Kevin Kofler)*/); GetParts(/*dummy*/ /*(using now void in v.2.71.F3d - Kevin Kofler)*/); /* in version v2.71.F3c */
  723. goto pass2cont;
  724. }
  725. }
  726. if ((HunkType == HunkNone) && (NumSyms != 0)) { /* Dummy section */
  727. DoSection ("", 0, "", 0, "", 0); /* to get XDEF */
  728. MakeHunk = TRUE; /* symbols if any */
  729. }
  730. /*----------------------------------------------------------------
  731. Clean up.
  732. */
  733. if (HunkType != HunkNone)
  734. if (AddrCnt > OrgHigh)
  735. Sect->Val = AddrCnt; /* End of the last section */
  736. else
  737. Sect->Val = OrgHigh; /* We've ORGed higher. */
  738. if (Quiet > 0)
  739. fprintf (stderr, "%d", LineCount); /* Final line number */
  740. else if (Quiet < 0)
  741. fprintf (stderr, "%d\n", InF->Line);
  742. fflush (stderr); /* Make sure it gets out. */
  743. close (In.fd); /* We're finished with the source file. */
  744. In.fd = NOFD;
  745. free (In.Buf);
  746. In.Buf = NULL;
  747. EndSdata (&Srec, EndAddr); /* Write remaining data and end record. */
  748. xclose (&Srec); /* We're finished with the object file. */
  749. if ((ErrorCount != 0) && (!keepobj))
  750. unlink (SrecFN); /* Scratch it if there were errors. */
  751. RelCurr = RelStart;
  752. RelStart = NULL;
  753. while (RelCurr != NULL) {
  754. RelLim = RelCurr;
  755. RelCurr = RelCurr->Link;
  756. free (RelLim); /* Free the relocation table. */
  757. }
  758. if (Heap2 != NULL) {
  759. free (Heap2); /* Free the secondary heap. */
  760. Heap2 = NULL;
  761. }
  762. if (XrefList)
  763. WriteSymTab (&List); /* List the symbol table. */
  764. /* Display final error count. */
  765. if (Quiet != 0)
  766. fprintf (stderr, "\nEnd of assembly - ");
  767. if (!SuppList)
  768. xputs (&List, "\nEnd of assembly - ");
  769. if (ErrorCount == 0) {
  770. if (Quiet != 0)
  771. fprintf (stderr, "no errors were found.\n");
  772. if (!SuppList)
  773. xputs (&List, "no errors were found.\n");
  774. } else if (ErrorCount == 1) {
  775. if (Quiet != 0)
  776. fprintf (stderr, "1 error was found.\n");
  777. if (!SuppList)
  778. xputs (&List, "1 error was found.\n");
  779. } else {
  780. if (Quiet != 0)
  781. fprintf (stderr, "%d errors were found.\n", ErrorCount);
  782. if (!SuppList) {
  783. sprintf (tempchar, "%d errors were found.\n", ErrorCount);
  784. xputs (&List, tempchar);
  785. }
  786. }
  787. /* Display heap usage. */
  788. if (Quiet != 0)
  789. fprintf (stderr, "Heap usage: -w%ld", HashSize);
  790. if (!SuppList) {
  791. sprintf (tempchar, "Heap usage: -w%ld", HashSize);
  792. xputs (&List, tempchar);
  793. }
  794. templong = (long) (High2 - Heap2);
  795. if (Low2 < (char *) LowInF)
  796. templong += (long) (Heap2 + maxheap2 - Low2);
  797. else
  798. templong += (long) (Heap2 + maxheap2 - (char *) LowInF);
  799. if (Quiet != 0)
  800. fprintf (stderr, ",%ld\n", templong);
  801. if (!SuppList) {
  802. sprintf (tempchar, ",%ld\n", templong);
  803. xputs (&List, tempchar);
  804. }
  805. /* Display the total size of all section types. */
  806. if (Quiet != 0) {
  807. fprintf (stderr, "Total hunk sizes: %lx code, ", codesize);
  808. fprintf (stderr, "%lx data, %lx BSS\n", datasize, bsssize);
  809. }
  810. if (!SuppList) {
  811. sprintf (tempchar, "Total hunk sizes: %lx code, ", codesize);
  812. xputs (&List, tempchar);
  813. sprintf (tempchar, "%lx data, %lx BSS\n", datasize, bsssize);
  814. xputs (&List, tempchar);
  815. }
  816. /* Display hashing statistics if required. */
  817. if (HashStats && (NumSyms != 0)) {
  818. printf ("\n");
  819. printf ("HASH CHAIN STATISTICS - %d symbols\n\n", NumSyms);
  820. templong = (NumSyms + 1) * sizeof (int);
  821. HashCount = (int *) malloc ((unsigned) templong);
  822. if (HashCount == NULL)
  823. quit_cleanup ("Out of memory!\n");
  824. printf ("Length No. of chains\n");
  825. printf ("------ -------------\n");
  826. intptr = HashCount;
  827. for (i = 0; i <= NumSyms; i++)
  828. *(intptr++) = 0; /* Clear hash chain length counters. */
  829. hashptr = Hash;
  830. for (i = 0; i < HashSize; i++) {
  831. j = 0;
  832. if ((Sym = *hashptr) != NULL) {
  833. j++; /* This chain has at least one entry. */
  834. while ((Sym = Sym->Link) != NULL) {
  835. j++; /* Count entries in the chain. */
  836. }
  837. }
  838. intptr = HashCount + j;
  839. (*intptr)++; /* Bump counter by chain length. */
  840. hashptr++;
  841. }
  842. intptr = HashCount;
  843. for (i = 0; i <= NumSyms; i++) {
  844. if (*intptr)
  845. printf ("%4d %4d\n", i, *intptr);
  846. intptr++;
  847. }
  848. free (HashCount); /* Free hash statistics table. */
  849. HashCount = NULL;
  850. }
  851. /* All done! */
  852. if (!SuppList) {
  853. xputs (&List, "\f"); /* One last page eject */
  854. xclose (&List); /* We're finished with the listing file. */
  855. }
  856. quit_cleanup (""); /* Normal termination */
  857. }
  858. /*======================================================================*/
  859. /* */
  860. /* Subroutines used by the main program */
  861. /* */
  862. /*======================================================================*/
  863. int getfilename (name, arg, desc, needit)
  864. char *name, *arg, *desc;
  865. int needit;
  866. /* If "name" is not a duplicate, copies "arg" to it, else flags
  867. duplicate using "desc". If "needit" is TRUE, also flags
  868. an error if "arg" is a null string.
  869. Returns TRUE if an error is found, FALSE otherwise. */
  870. {
  871. if (*name) {
  872. fprintf (stderr, "%s file is declared more than once.\n", desc);
  873. return (TRUE);
  874. }
  875. if (*arg) {
  876. strcpy (name, arg);
  877. return (FALSE);
  878. }
  879. if (needit) {
  880. fprintf (stderr, "%s file name is missing\n", desc);
  881. return (TRUE);
  882. }
  883. return (FALSE);
  884. }
  885. int checkswitch (sw, name) char *sw, *name;
  886. /* Displays an error message and returns TRUE if the argument
  887. pointed to by "s" is more than two characters long.
  888. Just returns FALSE otherwise. */
  889. {
  890. if (strlen (sw) > 2) {
  891. fprintf (stderr, "Invalid %s switch (%s).\n", name, sw);
  892. return (TRUE);
  893. } else {
  894. return (FALSE);
  895. }
  896. }
  897. void defaultfile (name, ext) char *name, *ext;
  898. /* If "name" is a null string, search for the last period in "name"
  899. (if any) and append "ext".
  900. If "name" doesn't contain a period, append a period and "ext". */
  901. {
  902. char *s;
  903. if (*name == '\0') { /* If name isn't specified... */
  904. strcpy (name,SourceFN); /* Start with source file name. */
  905. s = name+strlen(name); /* Scan backwards for period. */
  906. while (--s > name) {
  907. if (*s == '.') {
  908. *s = '\0'; /* Chop off name extension. */
  909. break;
  910. }
  911. }
  912. strcat (name, ext); /* Add name extension. */
  913. }
  914. }
  915. int checkdupfile (name1, desc1, name2, desc2)
  916. char *name1, *desc1, *name2, *desc2;
  917. /* If "name1" is the same as "name2", display an error message using
  918. "desc1" and "desc2" and return TRUE. Otherwise, return FALSE. */
  919. {
  920. if (strcmp (name1, name2) == 0) {
  921. fprintf (stderr,
  922. "%s and %s file names are the same.\n", desc1, desc2);
  923. return (TRUE);
  924. } else {
  925. return (FALSE);
  926. }
  927. }
  928. void startpass (pchar, maxheap2) char pchar; long maxheap2;
  929. /* Set up to start the next pass. */
  930. {
  931. if (Quiet > 0) {
  932. fprintf (stderr, "PASS %c line ", pchar);
  933. fflush (stderr);
  934. } else if (Quiet < 0) {
  935. fprintf (stderr, "PASS %c\n", pchar);
  936. }
  937. NextFNS = Heap2;
  938. InF = (struct InFCtl *) (Heap2 + maxheap2);
  939. InF--;
  940. InFNum = OuterMac = SkipNest = InF->Pos = InF->MCnt = 0;
  941. InF->Line = 0;
  942. InF->UPtr = 0;
  943. InF->NPtr = NextFNS;
  944. InF->NArg = -1;
  945. InF->MCnt = 0;
  946. strcpy (NextFNS, SourceFN);
  947. ShowFile (FALSE); /* Show source file name. */
  948. NextFNS += strlen (SourceFN) + 1;
  949. LineCount = LabLine = MacCount = ErrorCount = 0;
  950. AddrCnt = CurrHunk = SectStart = EndAddr = 0L;
  951. HunkType = HunkNone; /* We're not in a hunk yet. */
  952. HunkFlags = SectLine = HunkSeq = 0;
  953. ListOff = MakeHunk = InnrFMac = FALSE;
  954. SmallData = -1;
  955. TTLstring[0] = '\0'; /* Clear the title string. */
  956. }
  957. void quit_cleanup (s) char *s;
  958. /* Clean up and exit. If "s" doesn't point to a null string, print the
  959. string as an error message, remove the partially-formed object
  960. file if it exists, and exit with an error code. */
  961. {
  962. if (In.fd != NOFD) /* Close all files... */
  963. close (In.fd);
  964. if (In.Buf != NULL) /* and free buffers. */
  965. free (In.Buf);
  966. if (Srec.fd != NOFD)
  967. xclose (&Srec);
  968. if (List.fd != NOFD)
  969. xclose (&List);
  970. if (Eq.fd != NOFD)
  971. xclose (&Eq);
  972. if (Hash != NULL)
  973. free (Hash); /* Free the hash table. */
  974. SymCurr = SymStart;
  975. while (SymCurr != NULL) {
  976. SymLim = SymCurr;
  977. SymCurr = SymCurr->Link;
  978. free (SymLim); /* Free the symbol table. */
  979. }
  980. NameCurr = NameStart;
  981. while (NameCurr != NULL) {
  982. NameLim = (char *) NameCurr;
  983. NameCurr = NameCurr->Link;
  984. free (NameLim); /* Free the name table. */
  985. }
  986. RelCurr = RelStart;
  987. while (RelCurr != NULL) {
  988. RelLim = RelCurr;
  989. RelCurr = RelCurr->Link;
  990. free (RelLim); /* Free the relocation table. */
  991. }
  992. FwdCurr = FwdStart;
  993. while (FwdCurr != NULL) {
  994. FwdLim2 = (int *) FwdCurr;
  995. FwdCurr = FwdCurr->Link;
  996. free (FwdLim2); /* Free the forward branch log. */
  997. }
  998. if (Heap2 != NULL)
  999. free (Heap2); /* Free the secondary heap. */
  1000. if (SymSort != NULL)
  1001. free (SymSort); /* Free symbol table sort area. */
  1002. if (HashCount != NULL)
  1003. free (HashCount); /* Free hash statistics table. */
  1004. /* Get rid of leftover AddrDiffs list -- Kevin Kofler, v.2.71.F3l */
  1005. while (AddrDiffs) {
  1006. struct AddrDiff *next=AddrDiffs->Link;
  1007. free(AddrDiffs);
  1008. AddrDiffs=next;
  1009. }
  1010. if (*s) { /* If we have an error message, */
  1011. if (SrecFN[0])
  1012. unlink (SrecFN); /* scratch the object file, */
  1013. fprintf (stderr, "%s", s); /* display the error message, */
  1014. exit (20); /* and die. */
  1015. } else {
  1016. exit (ErrorCount ? 10 : 0); /* Normal termination */
  1017. }
  1018. }