FileTokens.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. #include <errno.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include "tokenizer/FileTokens.h"
  6. #include "utils/SnuviUtils.h"
  7. /*typedef char String[64];
  8. #define STRING_LENGTH ((int)sizeof(String))
  9. #define END_IF "#endif"
  10. #define END_IF_LENGTH ((int)sizeof(END_IF) - 1)*/
  11. static Error* error;
  12. static const char* ftGetPath(const FileTokens* ft, int line) {
  13. if(ft->capacity < (2 + (int)sizeof(int)) || ft->data[0] != FT_PATH) {
  14. eInitError(error, line, "path not set");
  15. return "";
  16. }
  17. return (const char*)(ft->data + 1 + sizeof(int));
  18. }
  19. static void ftSystemError(const char* msg, int line, const FileTokens* ft) {
  20. eInitError(error, line, "%s '%s': %s", msg, ftGetPath(ft, line),
  21. strerror(errno));
  22. }
  23. static void ftAddData(FileTokens* ft, const void* data, int dataSize) {
  24. if(ft->writeIndex + dataSize > ft->capacity) {
  25. int newSize = ft->capacity;
  26. while(ft->writeIndex + dataSize > newSize) {
  27. newSize += 1024;
  28. }
  29. ft->data = realloc(ft->data, newSize);
  30. ft->capacity = newSize;
  31. }
  32. memcpy(ft->data + ft->writeIndex, data, dataSize);
  33. ft->writeIndex += dataSize;
  34. }
  35. static void ftAddToken(FileTokens* ft, FileToken t) {
  36. unsigned char c = t;
  37. ftAddData(ft, &c, 1);
  38. }
  39. static void ftAddInt(FileTokens* ft, int i) {
  40. ftAddData(ft, &i, sizeof(int));
  41. }
  42. static void ftAddString(FileTokens* ft, const void* s, int length) {
  43. ftAddInt(ft, length + 1);
  44. ftAddData(ft, s, length);
  45. const char c = '\0';
  46. ftAddData(ft, &c, 1);
  47. }
  48. static void ftAddTerminatedString(FileTokens* ft, const char* s) {
  49. ftAddString(ft, s, strlen(s));
  50. }
  51. /*typedef struct {
  52. String name;
  53. } Define;
  54. #define DEFINES 256
  55. static Define defines[DEFINES];
  56. static int defineIndex = 0;
  57. static bool frHasError() {
  58. return error->message[0] != '\0';
  59. }
  60. static bool frStringCompare(const String a, const char* b) {
  61. return strcmp(a, b) == 0;
  62. }*/
  63. static void ftInitFileTokens(FileTokens* ft, const char* path) {
  64. ft->data = NULL;
  65. ft->capacity = 0;
  66. ft->writeIndex = 0;
  67. ft->readIndex = 0;
  68. ftAddToken(ft, FT_PATH);
  69. ftAddTerminatedString(ft, path);
  70. }
  71. static void ftTokenize(FileTokens* ft, unsigned char* data) {
  72. int index = 0;
  73. int oldIndex = 0;
  74. bool inString = false;
  75. int line = 1;
  76. while(true) {
  77. unsigned char c = data[index];
  78. if(isAllowedInName(c) || (inString && c != '"' && c != '\0')) {
  79. index++;
  80. continue;
  81. }
  82. if(oldIndex < index) {
  83. ftAddToken(ft, FT_LITERAL);
  84. ftAddString(ft, data + oldIndex, index - oldIndex);
  85. }
  86. if(c == '"') {
  87. inString = !inString;
  88. }
  89. if(c == '\0') {
  90. break;
  91. } else if(c == '\n') {
  92. line++;
  93. ftAddToken(ft, FT_NEWLINE);
  94. } else if(c == ' ') {
  95. ftAddToken(ft, FT_SPACE);
  96. } else if(c == '/' && data[index + 1] == '/') {
  97. while(data[index] != '\0' && data[index] != '\n') {
  98. index++;
  99. }
  100. ftAddToken(ft, FT_NEWLINE);
  101. } else if(c == '/' && data[index + 1] == '*') {
  102. int startLine = line;
  103. index += 2;
  104. while(true) {
  105. if(data[index] == '\0') {
  106. eInitError(error, startLine, "unclosed multiline comment");
  107. return;
  108. } else if(data[index] == '\n') {
  109. ftAddToken(ft, FT_NEWLINE);
  110. line++;
  111. } else if(data[index] == '*' && data[index + 1] == '/') {
  112. index++;
  113. break;
  114. }
  115. index++;
  116. }
  117. } else {
  118. ftAddToken(ft, FT_SINGLE);
  119. ftAddData(ft, &c, 1);
  120. }
  121. index++;
  122. oldIndex = index;
  123. }
  124. }
  125. static void ftReadFull(FILE* file, FileTokens* ft, int line) {
  126. if(fseek(file, 0, SEEK_END)) {
  127. ftSystemError("cannot seek end of file", line, ft);
  128. return;
  129. }
  130. long length = ftell(file);
  131. if(length < 0) {
  132. ftSystemError("cannot tell end of file", line, ft);
  133. return;
  134. }
  135. rewind(file);
  136. unsigned char* data = malloc(length + 1);
  137. int readValues = fread(data, 1, length, file);
  138. if(readValues != length) {
  139. ftSystemError("cannot read file", line, ft);
  140. free(data);
  141. return;
  142. }
  143. data[length] = '\0';
  144. ftTokenize(ft, data);
  145. free(data);
  146. }
  147. static void ftReadFullFile(FileTokens* ft, int line) {
  148. FILE* file = fopen(ftGetPath(ft, line), "r");
  149. if(file == NULL) {
  150. ftSystemError("cannot open file", 1, ft);
  151. return;
  152. }
  153. ftReadFull(file, ft, line);
  154. if(fclose(file) < 0) {
  155. ftSystemError("cannot close file", 1, ft);
  156. }
  157. }
  158. /*static int frReadUntil(int from, char end, String s, FileReader* fr) {
  159. int index = 0;
  160. while(from < fr->length && index < STRING_LENGTH - 1 &&
  161. fr->data[from] != end) {
  162. s[index++] = fr->data[from];
  163. from++;
  164. }
  165. s[index] = '\0';
  166. return index;
  167. }
  168. static int frReadUntilOrLine(int from, char end, String s, FileReader* fr) {
  169. int index = 0;
  170. while(from < fr->length && index < STRING_LENGTH - 1 &&
  171. fr->data[from] != end && fr->data[from] != '\n') {
  172. s[index++] = fr->data[from];
  173. from++;
  174. }
  175. s[index] = '\0';
  176. return index;
  177. }
  178. static void frMakePath(String fullPath, const char* parent, String name) {
  179. int i = 0;
  180. int lastSlash = 0;
  181. while(i < STRING_LENGTH - 1 && parent[i] != '\0') {
  182. fullPath[i] = parent[i];
  183. lastSlash = parent[i] == '/' ? i : lastSlash;
  184. i++;
  185. }
  186. i = lastSlash + 1;
  187. int nameI = 0;
  188. while(i < STRING_LENGTH - 1 && name[nameI] != '\0') {
  189. fullPath[i] = name[nameI];
  190. i++;
  191. nameI++;
  192. }
  193. fullPath[i] = '\0';
  194. }
  195. static void frReplace(int from, int to, FileReader* fr,
  196. FileReader* replacement) {
  197. int replaceLength = replacement->length - 1;
  198. replaceLength = replaceLength < 0 ? 0 : replaceLength;
  199. int newLength = fr->length + replaceLength - (to - from);
  200. unsigned char* newData = malloc(newLength + 1);
  201. memcpy(newData, fr->data, from);
  202. memcpy(newData + from, replacement->data, replaceLength);
  203. memcpy(newData + from + replaceLength, fr->data + to, fr->length - to);
  204. newData[newLength] = '\0';
  205. free(fr->data);
  206. fr->data = newData;
  207. fr->length = newLength;
  208. }
  209. static int skipSpaces(int index, FileReader* fr) {
  210. while(index < fr->length && fr->data[index] == ' ') {
  211. index++;
  212. }
  213. return index;
  214. }
  215. static void frHandleInclude(int from, int length, FileReader* fr) {
  216. int index = from + length;
  217. index = skipSpaces(index, fr);
  218. if(index >= fr->length || fr->data[index] != '"') {
  219. eInitError(error, fr->line, "expected '\"' and not '%c' in '%s'",
  220. fr->data[index], fr->path);
  221. return;
  222. }
  223. index++;
  224. String s;
  225. int pathLength = frReadUntil(index, '"', s, fr) + 1;
  226. String fullPath;
  227. frMakePath(fullPath, fr->path, s);
  228. FileReader include;
  229. ftInitFileTokens(&include, fullPath);
  230. ftReadFullFile(&include);
  231. if(frHasError()) {
  232. frDelete(&include);
  233. return;
  234. }
  235. frReplace(from, index + pathLength, fr, &include);
  236. frDelete(&include);
  237. }
  238. static int frReadWord(String s, int from, FileReader* fr) {
  239. int index = skipSpaces(from, fr);
  240. int wordLength = frReadUntilOrLine(index, ' ', s, fr);
  241. return index + wordLength;
  242. }
  243. static bool frIsDefined(String s) {
  244. for(int i = 0; i < defineIndex; i++) {
  245. if(frStringCompare(defines[i].name, s)) {
  246. return true;
  247. }
  248. }
  249. return false;
  250. }
  251. static bool frIsMatching(int from, FileReader* fr, const char* s) {
  252. int i = 0;
  253. while(true) {
  254. if(s[i] == '\0') {
  255. return true;
  256. } else if(from >= fr->length || fr->data[from] != s[i]) {
  257. return false;
  258. }
  259. from++;
  260. i++;
  261. }
  262. }
  263. static int frFindEndIf(int from, FileReader* fr) {
  264. int layer = 0;
  265. for(int i = from; i < fr->length; i++) {
  266. if(frIsMatching(i, fr, END_IF)) {
  267. if(layer == 0) {
  268. return i;
  269. }
  270. layer--;
  271. } else if(frIsMatching(i, fr, "#ifndef")) {
  272. layer++;
  273. }
  274. }
  275. return -1;
  276. }
  277. static void frHandleIfNotDefined(int from, int length, FileReader* fr) {
  278. String s;
  279. int end = frReadWord(s, from + length, fr);
  280. int endIf = frFindEndIf(end, fr);
  281. if(endIf == -1) {
  282. eInitError(error, fr->line, "cannot find #endif in '%s'", fr->path);
  283. return;
  284. }
  285. if(frIsDefined(s)) {
  286. memset(fr->data + from, ' ', endIf - from + END_IF_LENGTH);
  287. } else {
  288. memset(fr->data + from, ' ', end - from);
  289. memset(fr->data + endIf, ' ', END_IF_LENGTH);
  290. }
  291. }
  292. static void frHandleDefine(int from, int length, FileReader* fr) {
  293. if(defineIndex >= DEFINES) {
  294. eInitError(error, fr->line, "too much defines in '%s'", fr->path);
  295. return;
  296. }
  297. String s;
  298. int end = frReadWord(s, from + length, fr);
  299. if(frIsDefined(s)) {
  300. puts("already defined");
  301. return;
  302. }
  303. strncpy(defines[defineIndex].name, s, STRING_LENGTH);
  304. defineIndex++;
  305. printf("defined '%s'\n", s);
  306. memset(fr->data + from, ' ', end - from);
  307. }
  308. static void frParseInstruction(int from, FileReader* fr) {
  309. String s;
  310. int length = frReadUntil(from, ' ', s, fr);
  311. if(frStringCompare(s, "#include")) {
  312. frHandleInclude(from, length, fr);
  313. } else if(frStringCompare(s, "#ifndef")) {
  314. frHandleIfNotDefined(from, length, fr);
  315. } else if(frStringCompare(s, "#define")) {
  316. frHandleDefine(from, length, fr);
  317. } else {
  318. eInitError(error, fr->line, "unknown preprocessor token '%s' in '%s'",
  319. s, fr->path);
  320. }
  321. }
  322. static void frSearchInstruction(FileReader* fr) {
  323. if(fr->data == NULL) {
  324. return;
  325. }
  326. for(int i = 0; i < fr->length && !frHasError(); i++) {
  327. unsigned char c = fr->data[i];
  328. if(c == '#') {
  329. frParseInstruction(i, fr);
  330. i--;
  331. } else if(c == '\n') {
  332. fr->line++;
  333. }
  334. }
  335. }*/
  336. void ftInit(const char* path, FileTokens* ft, Error* e) {
  337. // defineIndex = 0;
  338. error = e;
  339. eInitSuccess(error);
  340. ftInitFileTokens(ft, path);
  341. ftReadFullFile(ft, 1);
  342. // frSearchInstruction(fr);
  343. // if(fr->data != NULL) {
  344. // printf((char*)fr->data);
  345. // }
  346. }
  347. void ftDelete(FileTokens* ft) {
  348. free(ft->data);
  349. ft->data = NULL;
  350. ft->capacity = 0;
  351. ft->writeIndex = 0;
  352. ft->readIndex = 0;
  353. }
  354. FileToken ftRead(FileTokens* ft) {
  355. if(ft->readIndex < ft->writeIndex) {
  356. return ft->data[ft->readIndex++];
  357. }
  358. return FT_END;
  359. }
  360. bool ftReadSingleIf(FileTokens* ft, char c) {
  361. if(ft->readIndex + 1 >= ft->writeIndex) {
  362. return false;
  363. } else if(ft->data[ft->readIndex] != FT_SINGLE) {
  364. return false;
  365. } else if(ft->data[ft->readIndex + 1] != c) {
  366. return false;
  367. }
  368. ft->readIndex += 2;
  369. return true;
  370. }
  371. char ftReadSingle(FileTokens* ft) {
  372. if(ft->readIndex < ft->writeIndex) {
  373. return ft->data[ft->readIndex++];
  374. }
  375. return -1;
  376. }
  377. const char* ftReadString(FileTokens* ft, int* length) {
  378. *length = 0;
  379. if(ft->readIndex + ((int)sizeof(int)) + 1 >= ft->writeIndex) {
  380. return NULL;
  381. }
  382. memcpy(length, ft->data + ft->readIndex, sizeof(int));
  383. const char* s = (const char*)(ft->data + ft->readIndex + sizeof(int));
  384. ft->readIndex += *length + sizeof(int);
  385. return s;
  386. }