a68k.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /* A68k compatibility wrapper for GNU as.
  2. * Copyright (C) 2005 Kevin Kofler
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  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. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <unistd.h>
  22. #ifdef __WIN32__
  23. #include <windows.h>
  24. #undef IGNORE
  25. #endif
  26. #define fatal(s) ({fprintf(stderr,(s)); return 1;})
  27. #ifdef __WIN32__
  28. static int run_cmdline(const char *cmdline)
  29. {
  30. long exitcode;
  31. STARTUPINFO startupinfo={.cb=sizeof(startupinfo)};
  32. PROCESS_INFORMATION processinfo;
  33. if (!CreateProcess(NULL,(char *)cmdline,NULL,NULL,FALSE,0,NULL,NULL,
  34. &startupinfo,&processinfo)) return 1;
  35. if (WaitForSingleObject(processinfo.hProcess,INFINITE)==WAIT_FAILED) return 1;
  36. if (!GetExitCodeProcess(processinfo.hProcess,&exitcode)) return 1;
  37. CloseHandle(processinfo.hProcess);
  38. CloseHandle(processinfo.hThread);
  39. return exitcode;
  40. }
  41. #else
  42. #define run_cmdline system
  43. #endif
  44. __attribute__((noreturn)) static void outofmem(void)
  45. {
  46. fprintf(stderr,"Fatal error: not enough free memory\n");
  47. exit(1);
  48. }
  49. static char *dynstrcat(char *s, const char *t)
  50. {
  51. char *p;
  52. size_t l = strlen(s) + strlen(t) + 1;
  53. p = realloc(s,l);
  54. if (p) {
  55. strcat(p,t);
  56. return p;
  57. } else {
  58. free(s);
  59. outofmem();
  60. }
  61. }
  62. #ifndef __WIN32__
  63. static inline void escape_arg(char *escaped_arg, const char *unescaped_arg)
  64. {
  65. char *p;
  66. strcpy(escaped_arg,unescaped_arg);
  67. for (p=escaped_arg; *p; p++) {
  68. switch(*p) {
  69. /* The following characters are shell characters and need to be escaped! */
  70. case ' ':
  71. case '\\':
  72. case '\"':
  73. case '\'':
  74. case '$':
  75. case '!':
  76. case '^':
  77. case '&':
  78. case '*':
  79. case '(':
  80. case ')':
  81. case '~':
  82. case '[':
  83. case ']':
  84. case '|':
  85. case '{':
  86. case '}':
  87. case ';':
  88. case '<':
  89. case '>':
  90. case '?':
  91. memmove(p+1,p,strlen(p)+1);
  92. *(p++)='\\';
  93. default:
  94. break;
  95. }
  96. }
  97. }
  98. #endif
  99. static char *dynargcat(char *s, const char *t)
  100. {
  101. char *p;
  102. #ifdef __WIN32__
  103. size_t l = strlen(s)+strlen(t)+3;
  104. #else
  105. size_t l = strlen(s)+2*strlen(t)+1;
  106. #endif
  107. p = realloc(s,l);
  108. if (p) {
  109. #ifdef __WIN32__
  110. strcat(p,"\"");
  111. strcat(p,t);
  112. strcat(p,"\"");
  113. #else
  114. escape_arg(p+strlen(p),t);
  115. char *q = realloc(p,strlen(p)+1);
  116. if (q) p=q;
  117. #endif
  118. return p;
  119. } else {
  120. free(s);
  121. outofmem();
  122. }
  123. }
  124. int main(int argc, char *argv[])
  125. {
  126. /* Find GNU as */
  127. #ifdef __WIN32__
  128. HMODULE module_h = GetModuleHandle("a68k.exe");
  129. if (!module_h) fatal("Fatal error: Can't obtain module handle.");
  130. char path_to_as[MAX_PATH];
  131. if (!GetModuleFileName(module_h,path_to_as,MAX_PATH)) fatal("Fatal error: GetModuleFileName failed.");
  132. char *p=strrchr(path_to_as,'\\');
  133. if (!p) fatal("Fatal error: No backslash in module file name.");
  134. strcpy(p+1,"as.exe");
  135. #else
  136. const char *tigcc_base=getenv("TIGCC");
  137. if (!tigcc_base) fatal("Fatal error: $TIGCC not defined in the environment.\n");
  138. char path_to_as[strlen(tigcc_base)+8];
  139. sprintf(path_to_as,"%s/bin/as",tigcc_base);
  140. #endif
  141. /* Allocate argument string */
  142. char *argstr=calloc(1,1);
  143. argstr=dynargcat(argstr,path_to_as);
  144. argstr=dynstrcat(argstr," --a68k");
  145. /* Translate arguments */
  146. int i, ogiven=0, filearg=0, quiet=0;
  147. for (i=1; i<argc; i++) {
  148. #define IGNORE(a) if (!strncmp(argv[i],(a),2)) continue;
  149. #define FAIL(a) if (!strncmp(argv[i],a,2)) {free(argstr);fatal("switch " a " not supported");}
  150. #define CONVERT(a,b) if (!strcmp(argv[i],(a))) argstr=dynstrcat(argstr,(b)); else
  151. #define PARSE(a) else if (!strncmp(argv[i],(a),2)) {char *arg=argv[i]+2;
  152. IGNORE("-e")
  153. IGNORE("-f")
  154. IGNORE("-g")
  155. IGNORE("-n")
  156. IGNORE("-p")
  157. IGNORE("-q")
  158. IGNORE("-r")
  159. IGNORE("-s")
  160. IGNORE("-t")
  161. IGNORE("-w")
  162. IGNORE("-z")
  163. if (!strcmp(argv[i],"-q")) {quiet=1; continue;}
  164. FAIL("-h");
  165. FAIL("-m");
  166. argstr=dynstrcat(argstr," ");
  167. CONVERT("-a","--all-relocs")
  168. CONVERT("-k","-Z")
  169. CONVERT("-u","--unaligned")
  170. CONVERT("-y","--statistics")
  171. if (!strncmp(argv[i],"-d",2)) argstr=dynstrcat(argstr,"-L");
  172. PARSE("-i")
  173. const char *incpath=strtok(arg,",;");
  174. argstr=dynstrcat(argstr,"-I ");
  175. argstr=dynargcat(argstr,incpath);
  176. while ((incpath=strtok(NULL,",;"))) {
  177. argstr=dynstrcat(argstr," -I ");
  178. argstr=dynargcat(argstr,incpath);
  179. }
  180. }
  181. PARSE("-o")
  182. ogiven=1;
  183. argstr=dynstrcat(argstr,"-o ");
  184. argstr=dynargcat(argstr,arg);
  185. }
  186. PARSE("-l")
  187. argstr=dynstrcat(argstr,"-ahl=");
  188. argstr=dynargcat(argstr,arg);
  189. }
  190. PARSE("-x")
  191. argstr=dynstrcat(argstr,"-a=");
  192. argstr=dynargcat(argstr,arg);
  193. }
  194. PARSE("-v")
  195. char *p;
  196. argstr=dynstrcat(argstr,"--defsym ");
  197. if ((p=strchr(arg,','))) *p='=';
  198. if ((p=strchr(arg,';'))) *p='=';
  199. argstr=dynargcat(argstr,arg);
  200. } else {
  201. if (filearg) {free(argstr); fatal("too many file names");}
  202. filearg=i;
  203. argstr=dynargcat(argstr,argv[i]);
  204. }
  205. }
  206. /* Name a default output file */
  207. if (!ogiven && filearg) {
  208. char ofile[strlen(argv[filearg])+1];
  209. strcpy(ofile,argv[filearg]);
  210. char *p=strrchr(ofile,'.');
  211. if (!p || !p[1]) {free(argstr); fatal("invalid file name");}
  212. strcpy(p+1,"o");
  213. argstr=dynstrcat(argstr," -o ");
  214. argstr=dynargcat(argstr,ofile);
  215. }
  216. /* Run GNU as */
  217. if (!quiet) printf("A68k compatibility wrapper Copyright 2005 Kevin Kofler\n\nAssembling ...\n");
  218. int exitcode=run_cmdline(argstr);
  219. free(argstr);
  220. return exitcode;
  221. }