app.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. /* This is the Assembler Pre-Processor
  2. Copyright (C) 1987 Free Software Foundation, Inc.
  3. This file is part of GAS, the GNU Assembler.
  4. GAS 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 1, or (at your option)
  7. any later version.
  8. GAS is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GAS; see the file COPYING. If not, write to
  14. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  15. /* App, the assembler pre-processor. This pre-processor strips out excess
  16. spaces, turns single-quoted characters into a decimal constant, and turns
  17. # <number> <filename> <garbage> into a .line <number>;.file <filename> pair.
  18. This needs better error-handling.
  19. */
  20. #include <stdio.h>
  21. #ifdef USG
  22. #define bzero(s,n) memset(s,0,n)
  23. #endif
  24. static char lex [256];
  25. static char symbol_chars[] =
  26. "$._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  27. extern char comment_chars[];
  28. extern char line_comment_chars[];
  29. #define LEX_IS_SYMBOL_COMPONENT (1)
  30. #define LEX_IS_WHITESPACE (2)
  31. #define LEX_IS_LINE_SEPERATOR (4)
  32. #define LEX_IS_COMMENT_START (8) /* JF added these two */
  33. #define LEX_IS_LINE_COMMENT_START (16)
  34. #define IS_SYMBOL_COMPONENT(c) (lex [c] & LEX_IS_SYMBOL_COMPONENT)
  35. #define IS_WHITESPACE(c) (lex [c] & LEX_IS_WHITESPACE)
  36. #define IS_LINE_SEPERATOR(c) (lex [c] & LEX_IS_LINE_SEPERATOR)
  37. #define IS_COMMENT(c) (lex [c] & LEX_IS_COMMENT_START)
  38. #define IS_LINE_COMMENT(c) (lex [c] & LEX_IS_LINE_COMMENT_START)
  39. void
  40. do_scrub_begin()
  41. {
  42. char *p;
  43. bzero (lex, sizeof(lex)); /* Trust NOBODY! */
  44. lex [' '] |= LEX_IS_WHITESPACE;
  45. lex ['\t'] |= LEX_IS_WHITESPACE;
  46. for (p =symbol_chars;*p;++p)
  47. lex [*p] |= LEX_IS_SYMBOL_COMPONENT;
  48. lex ['\n'] |= LEX_IS_LINE_SEPERATOR;
  49. #ifdef DONTDEF
  50. lex [':'] |= LEX_IS_LINE_SEPERATOR;
  51. #endif
  52. lex [';'] |= LEX_IS_LINE_SEPERATOR;
  53. for (p=comment_chars;*p;p++)
  54. lex[*p] |= LEX_IS_COMMENT_START;
  55. for (p=line_comment_chars;*p;p++)
  56. lex[*p] |= LEX_IS_LINE_COMMENT_START;
  57. }
  58. FILE *scrub_file;
  59. int
  60. scrub_from_file()
  61. {
  62. return getc(scrub_file);
  63. }
  64. void
  65. scrub_to_file(ch)
  66. int ch;
  67. {
  68. ungetc(ch,scrub_file);
  69. }
  70. char *scrub_string;
  71. char *scrub_last_string;
  72. int
  73. scrub_from_string()
  74. {
  75. return scrub_string == scrub_last_string ? EOF : *scrub_string++;
  76. }
  77. void
  78. scrub_to_string(ch)
  79. int ch;
  80. {
  81. *--scrub_string=ch;
  82. }
  83. int
  84. do_scrub_next_char(get,unget)
  85. int (*get)();
  86. void (*unget)();
  87. /* FILE *fp; */
  88. {
  89. /* State 0: beginning of normal line
  90. 1: After first whitespace on normal line (flush more white)
  91. 2: After first non-white on normal line (keep 1white)
  92. 3: after second white on normal line (flush white)
  93. 4: after putting out a .line, put out digits
  94. 5: parsing a string, then go to old-state
  95. 6: putting out \ escape in a "d string.
  96. 7: After putting out a .file string, flush until newline.
  97. -1: output string in out_string and go to the state in old_state
  98. -2: flush text until a '*' '/' is seen, then go to tate old_state
  99. */
  100. static state;
  101. static old_state;
  102. static char *out_string;
  103. static char out_buf[20];
  104. static add_newlines = 0;
  105. int ch;
  106. if(state==-1) {
  107. ch= *out_string++;
  108. if(*out_string==0) {
  109. state=old_state;
  110. old_state=3;
  111. }
  112. return ch;
  113. }
  114. if(state==-2) {
  115. do ch=(*get)();
  116. while(ch!=EOF && ch!='\n' && (ch!='*' || (*get)()!='/'));
  117. if(ch=='\n' || ch==EOF)
  118. return ch;
  119. else {
  120. state=old_state;
  121. return ' ';
  122. }
  123. }
  124. if(state==4) {
  125. ch=(*get)();
  126. if(ch==EOF || (ch>='0' && ch<='9'))
  127. return ch;
  128. else {
  129. while(ch!=EOF && IS_WHITESPACE(ch))
  130. ch=(*get)();
  131. if(ch=='"') {
  132. (*unget)(ch);
  133. out_string="; .file ";
  134. old_state=7;
  135. state= -1;
  136. return *out_string++;
  137. } else {
  138. while(ch!=EOF && ch!='\n')
  139. ch=(*get)();
  140. return ch;
  141. }
  142. }
  143. }
  144. if(state==5) {
  145. ch=(*get)();
  146. if(ch=='"') {
  147. state=old_state;
  148. return '"';
  149. } else if(ch=='\\') {
  150. state=6;
  151. return ch;
  152. } else if(ch==EOF) {
  153. as_warn("End of file in string: inserted '\"'");
  154. state=old_state;
  155. (*unget)('\n');
  156. return '"';
  157. } else {
  158. return ch;
  159. }
  160. }
  161. if(state==6) {
  162. state=5;
  163. ch=(*get)();
  164. switch(ch) {
  165. /* This is neet. Turn "string
  166. more string" into "string\n more string"
  167. */
  168. case '\n':
  169. (*unget)('n');
  170. add_newlines++;
  171. return '\\';
  172. case '"':
  173. case '\\':
  174. case 'b':
  175. case 'f':
  176. case 'n':
  177. case 'r':
  178. case 't':
  179. case '0':
  180. case '1':
  181. case '2':
  182. case '3':
  183. case '4':
  184. case '5':
  185. case '6':
  186. case '7':
  187. break;
  188. default:
  189. as_warn("Unknown escape '\\%c' in string",ch);
  190. break;
  191. case EOF:
  192. as_warn("End of file in string: '\"' inserted");
  193. return '"';
  194. }
  195. return ch;
  196. }
  197. if(state==7) {
  198. do ch= (*get)();
  199. while(ch!='\n');
  200. state=0;
  201. return ch;
  202. }
  203. flushchar:
  204. ch=(*get)();
  205. switch(ch) {
  206. case ' ':
  207. case '\t':
  208. do ch=(*get)();
  209. while(ch!=EOF && IS_WHITESPACE(ch));
  210. if(ch==EOF)
  211. return ch;
  212. if(IS_COMMENT(ch) || (state==0 && IS_LINE_COMMENT(ch)) || ch=='/' || IS_LINE_SEPERATOR(ch)) {
  213. (*unget)(ch);
  214. goto flushchar;
  215. }
  216. (*unget)(ch);
  217. if(state==0 || state==2) {
  218. state++;
  219. return ' ';
  220. } else goto flushchar;
  221. case '/':
  222. ch=(*get)();
  223. if(ch=='*') {
  224. do {
  225. ch=(*get)();
  226. if(ch=='\n')
  227. add_newlines++;
  228. } while(ch!=EOF && (ch!='*' || (*get)()!='/'));
  229. if(ch==EOF)
  230. as_warn("End of file in '/' '*' string");
  231. (*unget)(' ');
  232. goto flushchar;
  233. } else {
  234. if(IS_COMMENT('/') || (state==0 && IS_LINE_COMMENT('/'))) {
  235. ch='/';
  236. goto deal_misc;
  237. }
  238. if(ch!=EOF)
  239. (*unget)(ch);
  240. return '/';
  241. }
  242. break;
  243. case '"':
  244. old_state=state;
  245. state=5;
  246. return '"';
  247. break;
  248. case '\'':
  249. ch=(*get)();
  250. if(ch==EOF) {
  251. as_warn("End-of-file after a '");
  252. ch=0;
  253. }
  254. sprintf(out_buf,"(%d)",ch&0xff);
  255. old_state=state;
  256. state= -1;
  257. out_string=out_buf;
  258. return *out_string++;
  259. case ':':
  260. if(state!=3)
  261. state=0;
  262. return ch;
  263. case '\n':
  264. if(add_newlines) {
  265. --add_newlines;
  266. (*unget)(ch);
  267. }
  268. case ';':
  269. state=0;
  270. return ch;
  271. default:
  272. deal_misc:
  273. if(state==0 && IS_LINE_COMMENT(ch)) {
  274. do ch=(*get)();
  275. while(ch!=EOF && IS_WHITESPACE(ch));
  276. if(ch==EOF) {
  277. as_warn("Unexpected EOF in comment");
  278. return '\n';
  279. }
  280. if(ch<'0' || ch>'9') {
  281. do ch=(*get)();
  282. while(ch!=EOF && ch!='\n');
  283. if(ch==EOF)
  284. as_warn("Unexpected EOF in Comment");
  285. state=0;
  286. return '\n';
  287. }
  288. (*unget)(ch);
  289. old_state=4;
  290. state= -1;
  291. out_string=".line ";
  292. return *out_string++;
  293. } else if(IS_COMMENT(ch)) {
  294. do ch=(*get)();
  295. while(ch!=EOF && ch!='\n');
  296. if(ch==EOF)
  297. as_warn("Unexpected EOF in comment");
  298. state=0;
  299. return '\n';
  300. } else if(state==0) {
  301. state=2;
  302. return ch;
  303. } else if(state==1) {
  304. state=2;
  305. return ch;
  306. } else {
  307. return ch;
  308. }
  309. case EOF:
  310. if(state==0)
  311. return ch;
  312. as_warn("End-of-File not at end of a line");
  313. }
  314. return -1;
  315. }
  316. #ifdef TEST
  317. char comment_chars[] = "|";
  318. char line_comment_chars[] = "#";
  319. main()
  320. {
  321. int ch;
  322. app_begin();
  323. while((ch=do_scrub_next_char(stdin))!=EOF)
  324. putc(ch,stdout);
  325. }
  326. as_warn(str)
  327. char *str;
  328. {
  329. fputs(str,stderr);
  330. putc('\n',stderr);
  331. }
  332. #endif