cc_reader.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /* Copyright (C) 2016 Jeremiah Orians
  2. * This file is part of M2-Planet.
  3. *
  4. * M2-Planet 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 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * M2-Planet 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 M2-Planet. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #include "cc.h"
  18. /* Globals */
  19. FILE* input;
  20. struct token_list* token;
  21. int line;
  22. char* file;
  23. int clearWhiteSpace(int c)
  24. {
  25. if((32 == c) || (9 == c)) return clearWhiteSpace(fgetc(input));
  26. else if (10 == c)
  27. {
  28. line = line + 1;
  29. return clearWhiteSpace(fgetc(input));
  30. }
  31. return c;
  32. }
  33. int consume_byte(int c)
  34. {
  35. hold_string[string_index] = c;
  36. string_index = string_index + 1;
  37. require(MAX_STRING > string_index, "Token exceeded MAX_STRING char limit\nuse --max-string number to increase\n");
  38. return fgetc(input);
  39. }
  40. int preserve_string(int c)
  41. {
  42. int frequent = c;
  43. int escape = FALSE;
  44. do
  45. {
  46. if(!escape && '\\' == c ) escape = TRUE;
  47. else escape = FALSE;
  48. c = consume_byte(c);
  49. require(EOF != c, "Unterminated string\n");
  50. } while(escape || (c != frequent));
  51. return fgetc(input);
  52. }
  53. void fixup_label()
  54. {
  55. int hold = ':';
  56. int prev;
  57. int i = 0;
  58. do
  59. {
  60. prev = hold;
  61. hold = hold_string[i];
  62. hold_string[i] = prev;
  63. i = i + 1;
  64. } while(0 != hold);
  65. }
  66. int preserve_keyword(int c, char* S)
  67. {
  68. while(in_set(c, S))
  69. {
  70. c = consume_byte(c);
  71. }
  72. return c;
  73. }
  74. int purge_macro(int ch)
  75. {
  76. while(10 != ch)
  77. {
  78. ch = fgetc(input);
  79. require(EOF != ch, "Hit EOF inside macro\n");
  80. }
  81. return ch;
  82. }
  83. void reset_hold_string()
  84. {
  85. int i = string_index + 2;
  86. while(0 != i)
  87. {
  88. hold_string[i] = 0;
  89. i = i - 1;
  90. }
  91. }
  92. int get_token(int c)
  93. {
  94. struct token_list* current = calloc(1, sizeof(struct token_list));
  95. require(NULL != current, "Exhusted memory while getting token\n");
  96. reset:
  97. reset_hold_string();
  98. string_index = 0;
  99. c = clearWhiteSpace(c);
  100. if(c == EOF)
  101. {
  102. free(current);
  103. return c;
  104. }
  105. else if('#' == c)
  106. {
  107. c = purge_macro(c);
  108. goto reset;
  109. }
  110. else if(in_set(c, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"))
  111. {
  112. c = preserve_keyword(c, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_");
  113. if(':' == c)
  114. {
  115. fixup_label();
  116. c = ' ';
  117. }
  118. }
  119. else if(in_set(c, "<=>|&!-"))
  120. {
  121. c = preserve_keyword(c, "<=>|&!-");
  122. }
  123. else if(in_set(c, "'\""))
  124. {
  125. c = preserve_string(c);
  126. }
  127. else if(c == '/')
  128. {
  129. c = consume_byte(c);
  130. if(c == '*')
  131. {
  132. c = fgetc(input);
  133. while(c != '/')
  134. {
  135. while(c != '*')
  136. {
  137. c = fgetc(input);
  138. require(EOF != c, "Hit EOF inside of block comment\n");
  139. if('\n' == c) line = line + 1;
  140. }
  141. c = fgetc(input);
  142. require(EOF != c, "Hit EOF inside of block comment\n");
  143. if('\n' == c) line = line + 1;
  144. }
  145. c = fgetc(input);
  146. goto reset;
  147. }
  148. else if(c == '/')
  149. {
  150. c = fgetc(input);
  151. goto reset;
  152. }
  153. }
  154. else
  155. {
  156. c = consume_byte(c);
  157. }
  158. /* More efficiently allocate memory for string */
  159. current->s = calloc(string_index + 2, sizeof(char));
  160. require(NULL != current->s, "Exhusted memory while trying to copy a token\n");
  161. copy_string(current->s, hold_string, MAX_STRING);
  162. current->prev = token;
  163. current->next = token;
  164. current->linenumber = line;
  165. current->filename = file;
  166. token = current;
  167. return c;
  168. }
  169. struct token_list* reverse_list(struct token_list* head)
  170. {
  171. struct token_list* root = NULL;
  172. struct token_list* next;
  173. while(NULL != head)
  174. {
  175. next = head->next;
  176. head->next = root;
  177. root = head;
  178. head = next;
  179. }
  180. return root;
  181. }
  182. struct token_list* read_all_tokens(FILE* a, struct token_list* current, char* filename)
  183. {
  184. input = a;
  185. line = 1;
  186. file = filename;
  187. token = current;
  188. int ch =fgetc(input);
  189. while(EOF != ch) ch = get_token(ch);
  190. return token;
  191. }