fudgedata.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /* fudgedata.c A C Norman 2018 */
  2. /* BSD licensed */
  3. /*
  4. * This code is to alter main.s to put read-only data in the
  5. * data segment.
  6. *
  7. * Input Output
  8. *
  9. * <in data mode> .text
  10. * Lab: <record that in text mode>
  11. * .quad nn Lab: [maybe several labels]
  12. * # stuff .quad nn
  13. * # stuff
  14. *
  15. * <in text mode> .data
  16. * Lab: <record that in data mode>
  17. * .quad .. Lab: [maybe several labels]
  18. * or .byte .. .quad .. [or .byte]
  19. *
  20. * Lab: Lab: [unchanged]
  21. * other material other material
  22. */
  23. /*
  24. * I also intend to put in trace calls.
  25. * If I find "# (*entry NAME expr NARGS)"
  26. * then just before the next line that is NOT a .globl directive and
  27. * not a label setting I will insert
  28. * call _acn
  29. * .asciz "NAME %Q %Q"
  30. * where the number of instances of %Q will match the number of arguments
  31. * up to 3.
  32. * and before any "ret" I will insert
  33. * call _acn
  34. * .asciz "NAME = %Q"
  35. *
  36. * This should call a trace routine for every function in the file. If
  37. * I do not want to see all of it I will arrange that some of those calls
  38. * detect that the function involved is not of interest and ignore the
  39. * call, not printing anything.
  40. */
  41. /*
  42. * Strategy:
  43. * if in data mode...
  44. * read labels
  45. * read line - if not .quad then flush and restart
  46. * read line - if # then output " .text", flush and restart
  47. * flush all but most recent line and restart analysis with it.
  48. *
  49. * if in text mode
  50. * read labels
  51. * if next line is .quad or .byte then
  52. * output ".text" and flush
  53. * flush and keep going
  54. */
  55. #include <stdio.h>
  56. #include <string.h>
  57. char fname[250];
  58. int nargs = 0;
  59. char line[250];
  60. int entrydone = 0;
  61. char lines[10][250];
  62. int nlines = 0;
  63. int read_line(char *b, FILE *f)
  64. { int c;
  65. char *b1 = b;
  66. while ((c = getc(f)) != EOF && c != '\n') *b++ = c;
  67. *b = 0;
  68. if (b1[0] == '#')
  69. { if (sscanf(b1, "# (*entry %s expr %d)", fname, &nargs) == 2)
  70. entrydone = 0;
  71. else nargs = -1;
  72. }
  73. return c != EOF;
  74. }
  75. void write_lines(FILE *f2)
  76. { int i, j;
  77. for (i=0; i<nlines; i++)
  78. { const char *l = lines[i];
  79. if (nargs >= 0 && i == nlines-1)
  80. { if (strstr(l, " ret") != NULL)
  81. { fprintf(f2, " call _acn\n");
  82. fprintf(f2, " .asciz \"%s = %%Q\"\n", fname);
  83. }
  84. else if (nargs >= 0 &&
  85. entrydone == 0 &&
  86. l[0] != '#' &&
  87. strchr(l, ':') == NULL &&
  88. strstr(l, ".quad") == NULL &&
  89. strstr(l, ".byte") == NULL &&
  90. strstr(l, ".globl") == NULL)
  91. { fprintf(f2, " call _acn\n");
  92. fprintf(f2, " .asciz \"%s", fname);
  93. for (j=0; j<nargs && j<3; j++)
  94. fprintf(f2, " %%Q");
  95. fprintf(f2, "\"\n");
  96. entrydone = 1;
  97. }
  98. }
  99. fprintf(f2, "%s\n", l);
  100. }
  101. nlines = 0;
  102. }
  103. int main(int argc, char *argv[])
  104. { FILE *f1 = fopen(argv[1], "r");
  105. FILE *f2 = fopen(argv[2], "w");
  106. if (f1 == NULL || f2 == NULL)
  107. { printf("Failed\n");
  108. return 1;
  109. }
  110. int isdata = 0;
  111. int eof = 0;
  112. top:
  113. if (eof) goto finished;
  114. eof = !read_line(line, f1);
  115. top1:
  116. if (isdata)
  117. { if (strchr(line, ':') != NULL)
  118. { strcpy(lines[nlines++], line);
  119. /* Just absorb labels */
  120. goto top;
  121. }
  122. strcpy(lines[nlines++], line);
  123. if (strstr(line, ".quad") == NULL)
  124. {
  125. /*
  126. * If I am in data mode and I see something other than .quad then
  127. * I will just print it and start scanning again after it.
  128. */
  129. write_lines(f2);
  130. goto top;
  131. }
  132. /*
  133. * Here I am in data mode and may have had some labels but I have then
  134. * definitly got .quad. I need to see if the next line starts with "#".
  135. */
  136. if (eof) strcpy(line, "");
  137. else eof = !read_line(line, f1);
  138. if (line[0] != '#')
  139. {
  140. /*
  141. * If it does not I just print everything out EXCEPT that last line,
  142. * and go back so I consider that line again. Eg this would arise in
  143. * L1:
  144. * .quad first
  145. * .quad second
  146. * # ...
  147. * where the first .quad had been processed but the second one might be
  148. * moving me back into text mode.
  149. */
  150. write_lines(f2);
  151. goto top1;
  152. }
  153. /*
  154. * Here I switch back into text mode.
  155. */
  156. strcpy(lines[nlines++], line);
  157. fprintf(f2, " .text\n");
  158. isdata = 0;
  159. write_lines(f2);
  160. goto top;
  161. }
  162. else
  163. { if (strchr(line, ':') != NULL)
  164. { strcpy(lines[nlines++], line);
  165. goto top;
  166. }
  167. strcpy(lines[nlines++], line);
  168. /*
  169. * If I am in text mode and I see .byte (perhaps with some labels
  170. * ahead of it) I need to slip into data mode.
  171. */
  172. if (strstr(line, ".byte") != NULL)
  173. { strcpy(lines[nlines++], line);
  174. fprintf(f2, " .data\n");
  175. isdata = 1;
  176. write_lines(f2);
  177. goto top;
  178. }
  179. if (strstr(line, ".quad") == NULL)
  180. { write_lines(f2);
  181. goto top;
  182. }
  183. /*
  184. * If I am in text mode and I see .quad I need to look ahead to see if
  185. * the line after it starts with "#".
  186. */
  187. if (eof) strcpy(line, "");
  188. else eof = !read_line(line, f1);
  189. if (line[0] != '#')
  190. { fprintf(f2, " .data\n");
  191. isdata = 1;
  192. write_lines(f2);
  193. goto top1;
  194. }
  195. write_lines(f2);
  196. goto top1;
  197. }
  198. /* There may be some pending lines right at the end of the input. */
  199. finished:
  200. write_lines(f2);
  201. fclose(f1);
  202. fclose(f2);
  203. return 0;
  204. }
  205. /* end of fudgedata.c */