main_opt.inc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. /* main_opt.inc: Option parser for ld-tigcc command-line program
  2. Copyright (C) 2002-2004 Sebastian Reichelt
  3. Copyright (C) 2004 Billy Charvet
  4. Copyright (C) 2004-2007 Kevin Kofler
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software Foundation,
  15. Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  16. // This file is included by main.c.
  17. {
  18. const char *Arg;
  19. BOOLEAN ArgMatches (const char *Name)
  20. {
  21. return (!(strcmp (Arg, Name)));
  22. }
  23. // For each argument...
  24. for (CurArg = 1; CurArg < ArgCount; CurArg++)
  25. {
  26. // Get pointer to arg.
  27. Arg = Args [CurArg];
  28. // Check whether it is empty.
  29. if (Arg && *Arg)
  30. {
  31. // Check whether it is an option.
  32. if (Arg [0] == '-')
  33. {
  34. // Skip this dash and possibly a second one.
  35. Arg++;
  36. if (Arg [0] == '-')
  37. Arg++;
  38. // Handle the option.
  39. #ifdef ENABLE_HELP
  40. if (ArgMatches ("version"))
  41. {
  42. printf ("ld-tigcc Version " PROGRAM_VERSION_STRING "\n"
  43. COPYRIGHT_NOTICE_STRING "\n"
  44. "ld-tigcc is free software; see the source code for details.\n");
  45. goto Cleanup;
  46. }
  47. else if ((ArgMatches ("help")) || (ArgMatches ("h")))
  48. {
  49. printf ("Usage: ld-tigcc [options] <file> [<file> ...]\n"
  50. "Options:\n"
  51. " -h --help Display this message\n"
  52. " --version Display version number\n"
  53. #ifdef ENABLE_STATS
  54. " -v --verbose Display program statistics\n"
  55. #endif /* ENABLE_STATS */
  56. #ifdef ENABLE_DUMP
  57. " --dump[n] Display [n-th] dump of the program contents\n"
  58. #endif /* ENABLE_DUMP */
  59. " --native Link in TIGCC native mode\n"
  60. #ifdef FLASH_OS_SUPPORT
  61. " --flash-os Create (unsigned) Flash OS\n"
  62. " --flash-os-bss-start=<start> Start of the BSS Section in RAM (For Flash OS)\n"
  63. #endif /* FLASH_OS_SUPPORT */
  64. #ifdef FARGO_SUPPORT
  65. " --fargo Create Fargo II program\n"
  66. #endif /* FARGO_SUPPORT */
  67. " --remove-unused Remove unused sections\n"
  68. " --optimize-relocs Update relocs to point to the closest symbol\n"
  69. " --optimize-code Perform all MC68000 code optimizations (!)\n"
  70. " --optimize-nops Remove format-specific NOP instructions\n"
  71. " --optimize-returns Optimize function return sequences (!)\n"
  72. " --optimize-branches Optimize branch instructions\n"
  73. " --optimize-moves Optimize move/load/push instructions (!)\n"
  74. " --optimize-tests Optimize compare/test instructions (!)\n"
  75. " --optimize-calcs Optimize calculation instructions (!)\n"
  76. " --cut-ranges Cut unneeded section ranges when optimizing (!)\n"
  77. " (ignored for files not assembled in all-relocs mode)\n"
  78. " --reorder-sections Reorder sections to make references shorter\n"
  79. " --merge-constants Merge constants and strings to avoid duplication\n"
  80. " --omit-bss-init Do not initialize BSS data to zero\n"
  81. " --outputbin Create program image without PC header\n"
  82. " --outputbin-main-only\n"
  83. " Create main file w/o PC header (but data file with)\n"
  84. " -o --output <file> Write output to <file>.???\n"
  85. " -output-data-var <file> Write data variable (if any) to <file>.???\n"
  86. " -n --varname <[folder\\]name>\n"
  87. " Name output variable <folder\\name>\n"
  88. #ifdef DATA_VAR_SUPPORT
  89. " -d --data-var <[folder\\]name>\n"
  90. " Use data variable named <folder\\name>\n"
  91. " --data-var-copy={never|archived|always}\n"
  92. " Work on original data variable or copy\n"
  93. #endif /* DATA_VAR_SUPPORT */
  94. #ifdef PUCRUNCH_SUPPORT
  95. " --pack Compress main file with pucrunch\n"
  96. #endif /* PUCRUNCH_SUPPORT */
  97. "<file> can be an archive or an object file.\n"
  98. "Options marked with `(!)' are likely to cause errors in binary code.\n");
  99. goto Cleanup;
  100. }
  101. else
  102. #endif /* ENABLE_HELP */
  103. #ifdef ENABLE_STATS
  104. if ((ArgMatches ("verbose")) || (ArgMatches ("v")))
  105. DisplayStats = TRUE;
  106. else
  107. #endif /* ENABLE_STATS */
  108. #ifdef ENABLE_DUMP
  109. if (!(strncmp (Arg, "dump", sizeof ("dump") - 1)))
  110. {
  111. Arg += sizeof ("dump") - 1;
  112. if (*Arg)
  113. {
  114. int DumpIdx = atoi (Arg);
  115. if ((DumpIdx >= 0) && (DumpIdx < DUMP_COUNT))
  116. Dump [DumpIdx] = TRUE;
  117. }
  118. else
  119. memset (Dump, -1, sizeof (Dump));
  120. }
  121. else
  122. #endif /* ENABLE_DUMP */
  123. if (ArgMatches ("native"))
  124. Program.Type = PT_NATIVE;
  125. else
  126. #ifdef FLASH_OS_SUPPORT
  127. if (ArgMatches ("flash-os"))
  128. {
  129. Program.Type = PT_FLASH_OS;
  130. Warning (NULL, "Flash OS support in TIGCC is experimental.");
  131. }
  132. else
  133. if (!(strncmp (Arg, "flash-os-bss-start=", sizeof ("flash-os-bss-start=") - 1)))
  134. {
  135. char *End;
  136. Arg += sizeof ("flash-os-bss-start=") - 1;
  137. OptInfo->FlashOSBSSStart = strtoul (Arg, &End, 0);
  138. if (End == Arg)
  139. Error (NULL, "Invalid number for flash-os-bss-start");
  140. }
  141. else
  142. #endif /* FLASH_OS_SUPPORT */
  143. #ifdef FARGO_SUPPORT
  144. if (ArgMatches ("fargo"))
  145. {
  146. Program.Type = PT_FARGO;
  147. Program.Calcs |= CALC_TI92;
  148. Warning (NULL, "Fargo support in TIGCC is experimental.");
  149. }
  150. else
  151. #endif /* FARGO_SUPPORT */
  152. if (ArgMatches ("remove-unused"))
  153. OptInfo->RemoveUnused = TRUE;
  154. else if (ArgMatches ("optimize-relocs"))
  155. OptInfo->OptimizeRelocs = TRUE;
  156. else if (ArgMatches ("optimize-code"))
  157. {
  158. OptInfo->OptimizeNOPs = TRUE;
  159. OptInfo->OptimizeReturns = TRUE;
  160. OptInfo->OptimizeBranches = TRUE;
  161. OptInfo->OptimizeMoves = TRUE;
  162. OptInfo->OptimizeTests = TRUE;
  163. OptInfo->OptimizeCalcs = TRUE;
  164. }
  165. else if (ArgMatches ("optimize-nops"))
  166. OptInfo->OptimizeNOPs = TRUE;
  167. else if (ArgMatches ("optimize-returns"))
  168. OptInfo->OptimizeReturns = TRUE;
  169. else if (ArgMatches ("optimize-branches"))
  170. OptInfo->OptimizeBranches = TRUE;
  171. else if (ArgMatches ("optimize-moves"))
  172. OptInfo->OptimizeMoves = TRUE;
  173. else if (ArgMatches ("optimize-tests"))
  174. OptInfo->OptimizeTests = TRUE;
  175. else if (ArgMatches ("optimize-calcs"))
  176. OptInfo->OptimizeCalcs = TRUE;
  177. else if (ArgMatches ("cut-ranges"))
  178. OptInfo->CutRanges = TRUE;
  179. else if (ArgMatches ("reorder-sections"))
  180. OptInfo->ReorderSections = TRUE;
  181. else if (ArgMatches ("merge-constants"))
  182. OptInfo->MergeConstants = TRUE;
  183. else if (ArgMatches ("omit-bss-init"))
  184. OmitBSSInitialization = TRUE;
  185. else if (ArgMatches ("outputbin"))
  186. OutputBin = TRUE;
  187. else if (ArgMatches ("outputbin-main-only"))
  188. OutputBinMainOnly = TRUE;
  189. else if ((ArgMatches ("output")) || (ArgMatches ("o")))
  190. {
  191. if ((++CurArg) < ArgCount)
  192. {
  193. DestFile = Args [CurArg];
  194. DestFileSize = strlen (DestFile);
  195. // Adjust the program's name if it isn't set yet.
  196. if (!(*ProgramName))
  197. {
  198. // Start at the last separator.
  199. const char *Name = strrchr (DestFile, '/');
  200. if (!Name)
  201. Name = strrchr (DestFile, '\\');
  202. if (Name)
  203. Name++;
  204. else
  205. Name = DestFile;
  206. // Copy into name field.
  207. strncpy (ProgramName, Name, MAX_NAME_LEN);
  208. {
  209. // Cut at first dot.
  210. char *S = strchr (ProgramName, '.');
  211. if (S)
  212. *S = 0;
  213. // Cut at first space.
  214. S = strchr (ProgramName, ' ');
  215. if (S)
  216. *S = 0;
  217. // Convert to lowercase.
  218. for (S = ProgramName; *S; S++)
  219. *S = CalcTolower (*S);
  220. }
  221. }
  222. }
  223. else
  224. Error (NULL, "`--output' option must be followed by a name.");
  225. }
  226. else if (ArgMatches ("output-data-var"))
  227. {
  228. if ((++CurArg) < ArgCount)
  229. {
  230. DestDataFile = Args [CurArg];
  231. DestDataFileSize = strlen (DestDataFile);
  232. }
  233. else
  234. Error (NULL, "`--output-data-var' option must be followed by a name.");
  235. }
  236. else if ((ArgMatches ("varname")) || (ArgMatches ("n")))
  237. {
  238. if ((++CurArg) < ArgCount)
  239. {
  240. // Extract variable name.
  241. const char *Name = strchr (Args [CurArg], '/');
  242. if (!Name)
  243. Name = strchr (Args [CurArg], '\\');
  244. if (Name)
  245. {
  246. Name++;
  247. // Extract folder name.
  248. DecodeOnCalcName (ProgramFolder, Args [CurArg]);
  249. {
  250. char *S;
  251. for (S = ProgramFolder; *S; S++)
  252. {
  253. if (*S == '/' || *S == '\\')
  254. {
  255. *S = 0;
  256. break;
  257. }
  258. else
  259. *S = CalcTolower (*S);
  260. }
  261. }
  262. }
  263. else
  264. Name = Args [CurArg];
  265. DecodeOnCalcName (ProgramName, Name);
  266. {
  267. char *S;
  268. for (S = ProgramName; *S; S++)
  269. *S = CalcTolower (*S);
  270. }
  271. }
  272. else
  273. Error (NULL, "`--varname' option must be followed by a name.");
  274. }
  275. #ifdef DATA_VAR_SUPPORT
  276. else if (ArgMatches ("data-var") || ArgMatches ("d"))
  277. {
  278. if ((++CurArg) < ArgCount)
  279. {
  280. // Extract variable name.
  281. const char *Name = strchr (Args [CurArg], '/');
  282. if (!Name)
  283. Name = strchr (Args [CurArg], '\\');
  284. if (Name)
  285. {
  286. Name++;
  287. // Extract folder name.
  288. DecodeOnCalcName (DataFolder, Args [CurArg]);
  289. {
  290. char *S;
  291. for (S = DataFolder; *S; S++)
  292. {
  293. if (*S == '/' || *S == '\\')
  294. {
  295. *S = 0;
  296. break;
  297. }
  298. else
  299. *S = CalcTolower (*S);
  300. }
  301. }
  302. sprintf (DataVarString, "%s\\", DataFolder);
  303. }
  304. else
  305. {
  306. Name = Args [CurArg];
  307. *DataVarString = 0;
  308. }
  309. DecodeOnCalcName (DataName, Name);
  310. {
  311. char *S;
  312. for (S = DataName; *S; S++)
  313. *S = CalcTolower (*S);
  314. }
  315. strcat (DataVarString, DataName);
  316. DatVarInfo->Name = DataVarString;
  317. DatVarInfo->CreateCopy = TRUE;
  318. DatVarInfo->CopyOnlyIfArchived = TRUE;
  319. }
  320. else
  321. Error (NULL, "`--data-var' option must be followed by a name.");
  322. }
  323. else if (!(strncmp (Arg, "data-var-copy=", sizeof ("data-var-copy=") - 1)))
  324. {
  325. Arg += sizeof ("data-var-copy=") - 1;
  326. if (ArgMatches ("always"))
  327. {
  328. DatVarInfo->CreateCopy = TRUE;
  329. DatVarInfo->CopyOnlyIfArchived = FALSE;
  330. }
  331. else if (ArgMatches ("archived"))
  332. {
  333. DatVarInfo->CreateCopy = TRUE;
  334. DatVarInfo->CopyOnlyIfArchived = TRUE;
  335. }
  336. else if (ArgMatches ("never"))
  337. {
  338. DatVarInfo->CreateCopy = FALSE;
  339. DatVarInfo->CopyOnlyIfArchived = FALSE;
  340. }
  341. else
  342. Error (NULL, "Unrecognized copying condition `%s'.", Arg);
  343. }
  344. #endif /* DATA_VAR_SUPPORT */
  345. #ifdef PUCRUNCH_SUPPORT
  346. else if (ArgMatches ("pack"))
  347. Pack = TRUE;
  348. #endif /* PUCRUNCH_SUPPORT */
  349. else
  350. Error (NULL, "Unrecognized option `%s'.", Args [CurArg]);
  351. }
  352. else
  353. {
  354. // Treat it as a file name.
  355. // Open the file and load it into memory.
  356. {
  357. FILE *File = fopen (Arg, "rb");
  358. if (File)
  359. {
  360. SIZE Size;
  361. fseek (File, 0, SEEK_END);
  362. Size = ftell (File);
  363. rewind (File);
  364. {
  365. I1 *Data = malloc (Size);
  366. if (Data)
  367. {
  368. BOOLEAN IsArchive = FALSE;
  369. if (fread (Data, Size, 1, File) == 1)
  370. {
  371. // Act differently depending on the
  372. // file type.
  373. IsArchive = IsArchiveFile (Data, Size);
  374. if (IsArchive)
  375. {
  376. // Add the file to the list of
  377. // available archives.
  378. AddArchiveFile (&Program, Data, Size, Arg);
  379. }
  380. else
  381. {
  382. // Adjust the destination file
  383. // name if it isn't set yet.
  384. if (!DestFile)
  385. {
  386. const char *DotPos, *SlashPos;
  387. // Assign the destination file name.
  388. DestFile = Arg;
  389. DestFileSize = strlen (Arg);
  390. // Cut it at the last dot.
  391. DotPos = strrchr (Arg, '.');
  392. if (DotPos)
  393. {
  394. SlashPos = strrchr (Arg, '/');
  395. if (!SlashPos)
  396. SlashPos = strrchr (Arg, '\\');
  397. if ((!SlashPos) || (DotPos > SlashPos))
  398. DestFileSize = DotPos - Arg;
  399. }
  400. }
  401. // Import the file.
  402. ImportObjectFile (&Program, Data, Size, Arg);
  403. }
  404. }
  405. else
  406. Error (Arg, "Unable to read file.");
  407. // Archives are not imported; they keep
  408. // their data until they are freed.
  409. if (!IsArchive)
  410. free (Data);
  411. }
  412. else
  413. Error (Arg, "Not enough memory to load file.");
  414. }
  415. fclose (File);
  416. }
  417. else
  418. Error (Arg, "Unable to open file.");
  419. }
  420. }
  421. }
  422. }
  423. // Adjust the program's name if it isn't set yet.
  424. if (DestFile && (!(*ProgramName)))
  425. {
  426. // Start at the last separator.
  427. const char *Name = strrchr (DestFile, '/');
  428. if (!Name)
  429. Name = strrchr (DestFile, '\\');
  430. if (Name)
  431. Name++;
  432. else
  433. Name = DestFile;
  434. // Copy into name field.
  435. strncpy (ProgramName, Name, MAX_NAME_LEN);
  436. {
  437. // Cut at first dot.
  438. char *S = strchr (ProgramName, '.');
  439. if (S)
  440. *S = 0;
  441. // Cut at first space.
  442. S = strchr (ProgramName, ' ');
  443. if (S)
  444. *S = 0;
  445. // Convert to lowercase.
  446. for (S = ProgramName; *S; S++)
  447. *S = CalcTolower (*S);
  448. }
  449. }
  450. }