hex2.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /* -*- c-file-style: "linux";indent-tabs-mode:t -*- */
  2. /* Copyright (C) 2017 Jeremiah Orians
  3. * Copyright (C) 2017 Jan Nieuwenhuizen <janneke@gnu.org>
  4. * This file is part of mescc-tools
  5. *
  6. * mescc-tools is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * mescc-tools is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with mescc-tools. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <unistd.h>
  23. #include <sys/stat.h>
  24. #define max_string 4096
  25. #define TRUE 1
  26. #define FALSE 0
  27. void file_print(char* s, FILE* f);
  28. int match(char* a, char* b);
  29. struct entry
  30. {
  31. struct entry* next;
  32. unsigned target;
  33. char* name;
  34. };
  35. FILE* output;
  36. FILE* input;
  37. struct entry* jump_table;
  38. int ip;
  39. char* scratch;
  40. int in_set(int c, char* s)
  41. {
  42. while(0 != s[0])
  43. {
  44. if(c == s[0]) return TRUE;
  45. s = s + 1;
  46. }
  47. return FALSE;
  48. }
  49. int consume_token()
  50. {
  51. int i = 0;
  52. int c = fgetc(input);
  53. while(!in_set(c, " \t\n>"))
  54. {
  55. scratch[i] = c;
  56. i = i + 1;
  57. c = fgetc(input);
  58. }
  59. return c;
  60. }
  61. int Throwaway_token()
  62. {
  63. int c;
  64. do
  65. {
  66. c = fgetc(input);
  67. } while(!in_set(c, " \t\n>"));
  68. return c;
  69. }
  70. int length(char* s)
  71. {
  72. int i = 0;
  73. while(0 != s[i]) i = i + 1;
  74. return i;
  75. }
  76. void Clear_Scratch(char* s)
  77. {
  78. do
  79. {
  80. s[0] = 0;
  81. s = s + 1;
  82. } while(0 != s[0]);
  83. }
  84. void Copy_String(char* a, char* b)
  85. {
  86. while(0 != a[0])
  87. {
  88. b[0] = a[0];
  89. a = a + 1;
  90. b = b + 1;
  91. }
  92. }
  93. unsigned GetTarget(char* c)
  94. {
  95. struct entry* i;
  96. for(i = jump_table; NULL != i; i = i->next)
  97. {
  98. if(match(c, i->name))
  99. {
  100. return i->target;
  101. }
  102. }
  103. exit(EXIT_FAILURE);
  104. }
  105. int storeLabel()
  106. {
  107. struct entry* entry = calloc(1, sizeof(struct entry));
  108. /* Ensure we have target address */
  109. entry->target = ip;
  110. /* Prepend to list */
  111. entry->next = jump_table;
  112. jump_table = entry;
  113. /* Store string */
  114. int c = consume_token();
  115. entry->name = calloc(length(scratch) + 1, sizeof(char));
  116. Copy_String(scratch, entry->name);
  117. Clear_Scratch(scratch);
  118. return c;
  119. }
  120. void outputPointer(int displacement, int number_of_bytes)
  121. {
  122. unsigned value = displacement;
  123. while(number_of_bytes > 0)
  124. {
  125. unsigned byte = value % 256;
  126. value = value / 256;
  127. fputc(byte, output);
  128. number_of_bytes = number_of_bytes - 1;
  129. }
  130. }
  131. void Update_Pointer(char ch)
  132. {
  133. /* Calculate pointer size*/
  134. if(in_set(ch, "%&")) ip = ip + 4; /* Deal with % and & */
  135. else if(in_set(ch, "@$")) ip = ip + 2; /* Deal with @ and $ */
  136. else if('!' == ch) ip = ip + 1; /* Deal with ! */
  137. }
  138. void storePointer(char ch)
  139. {
  140. /* Get string of pointer */
  141. Clear_Scratch(scratch);
  142. Update_Pointer(ch);
  143. int base_sep_p = consume_token();
  144. /* Lookup token */
  145. int target = GetTarget(scratch);
  146. int displacement;
  147. int base = ip;
  148. /* Change relative base address to :<base> */
  149. if ('>' == base_sep_p)
  150. {
  151. Clear_Scratch(scratch);
  152. consume_token();
  153. base = GetTarget (scratch);
  154. }
  155. displacement = (target - base);
  156. /* output calculated difference */
  157. if('!' == ch) outputPointer(displacement, 1); /* Deal with ! */
  158. else if('$' == ch) outputPointer(target, 2); /* Deal with $ */
  159. else if('@' == ch) outputPointer(displacement, 2); /* Deal with @ */
  160. else if('&' == ch) outputPointer(target, 4); /* Deal with & */
  161. else if('%' == ch) outputPointer(displacement, 4); /* Deal with % */
  162. }
  163. void line_Comment()
  164. {
  165. int c = fgetc(input);
  166. while(!in_set(c, "\n\r"))
  167. {
  168. c = fgetc(input);
  169. }
  170. }
  171. int hex(int c)
  172. {
  173. if (in_set(c, "0123456789")) return (c - 48);
  174. else if (in_set(c, "abcdef")) return (c - 87);
  175. else if (in_set(c, "ABCDEF")) return (c - 55);
  176. else if (in_set(c, "#;")) line_Comment();
  177. return -1;
  178. }
  179. int hold;
  180. int toggle;
  181. void process_byte(char c, int write)
  182. {
  183. if(0 <= hex(c))
  184. {
  185. if(toggle)
  186. {
  187. if(write) fputc(((hold * 16)) + hex(c), output);
  188. ip = ip + 1;
  189. hold = 0;
  190. }
  191. else
  192. {
  193. hold = hex(c);
  194. }
  195. toggle = !toggle;
  196. }
  197. }
  198. void first_pass()
  199. {
  200. int c;
  201. for(c = fgetc(input); EOF != c; c = fgetc(input))
  202. {
  203. /* Check for and deal with label */
  204. if(':' == c)
  205. {
  206. c = storeLabel();
  207. }
  208. /* check for and deal with relative/absolute pointers to labels */
  209. if(in_set(c, "!@$%&"))
  210. { /* deal with 1byte pointer !; 2byte pointers (@ and $); 4byte pointers (% and &) */
  211. Update_Pointer(c);
  212. c = Throwaway_token();
  213. if ('>' == c)
  214. { /* deal with label>base */
  215. c = Throwaway_token();
  216. }
  217. }
  218. else process_byte(c, FALSE);
  219. }
  220. fclose(input);
  221. }
  222. void second_pass()
  223. {
  224. int c;
  225. for(c = fgetc(input); EOF != c; c = fgetc(input))
  226. {
  227. if(':' == c) c = Throwaway_token(); /* Deal with : */
  228. else if(in_set(c, "!@$%&")) storePointer(c); /* Deal with !, @, $, % and & */
  229. else process_byte(c, TRUE);
  230. }
  231. fclose(input);
  232. }
  233. /* Standard C main program */
  234. int main(int argc, char **argv)
  235. {
  236. jump_table = NULL;
  237. input = fopen(argv[1], "r");
  238. output = fopen(argv[2], "w");
  239. scratch = calloc(max_string + 1, sizeof(char));
  240. /* Get all of the labels */
  241. ip = 0x8048000;
  242. toggle = FALSE;
  243. hold = 0;
  244. first_pass();
  245. /* Fix all the references*/
  246. rewind(input);
  247. ip = 0x8048000;
  248. toggle = FALSE;
  249. hold = 0;
  250. second_pass();
  251. return EXIT_SUCCESS;
  252. }