main.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include "symtable.h"
  4. #include "ast_node.h"
  5. #include "parser.h"
  6. #include <unistd.h>
  7. #include <stdlib.h>
  8. #include <sys/stat.h>
  9. #include <time.h>
  10. #include "struct_table.h"
  11. #include "agc_commands.h"
  12. #include <errno.h>
  13. #include "file_op.h"
  14. #include "lexer.h"
  15. #include "semantic_analyser.h"
  16. extern float parsing_float;
  17. char included_files[10][100];
  18. int included_files_num = 0;
  19. // buffer for general use
  20. #define DD_BUFFER_SIZE 1000
  21. char buffer[DD_BUFFER_SIZE];
  22. // game node, parent of all nodes
  23. struct ast_node *game_node;
  24. #define MAX_INPUT_FILES 10
  25. enum AVDL_PLATFORM avdl_platform = AVDL_PLATFORM_NATIVE;
  26. const char *dependencies[] = {
  27. "GLEW",
  28. "m",
  29. "glut",
  30. "SDL2-2.0",
  31. "SDL2_mixer-2.0",
  32. };
  33. unsigned int dependencies_count = sizeof(dependencies) /sizeof(char *);
  34. char *includePath = 0;
  35. char *installLocation = "";
  36. // init data, parse, exit
  37. int main(int argc, char *argv[])
  38. {
  39. /* tweakable data
  40. */
  41. int show_ast = 0;
  42. int show_struct_table = 0;
  43. char filename[MAX_INPUT_FILES][100];
  44. int input_file_total = 0;
  45. char *outname = 0;
  46. int getDependencies = 0;
  47. /*
  48. * phases
  49. *
  50. * translate: translate `.dd` files to `.c`
  51. * compile: compile `.c` files to `.o`
  52. * link: link all `.o` files to an executable
  53. *
  54. */
  55. int translate = 1;
  56. int compile = 1;
  57. int link = 1;
  58. // parse arguments
  59. for (int i = 1; i < argc; i++) {
  60. // dash argument
  61. if (strlen(argv[i]) > 0 && argv[i][0] == '-') {
  62. // double dash argument
  63. if (strlen(argv[i]) > 1 && argv[i][1] == '-') {
  64. // temp
  65. if (strcmp(argv[i], "--dependencies") == 0) {
  66. getDependencies = 1;
  67. }
  68. else
  69. // print abstract syntax tree
  70. if (strcmp(argv[i], "--print-ast") == 0) {
  71. show_ast = 1;
  72. }
  73. else
  74. // print struct table
  75. if (strcmp(argv[i], "--print-struct-table") == 0) {
  76. show_struct_table = 1;
  77. }
  78. else
  79. // compiling for android
  80. if (strcmp(argv[i], "--android") == 0) {
  81. avdl_platform = AVDL_PLATFORM_ANDROID;
  82. link = 0;
  83. }
  84. else
  85. // show version number
  86. if (strcmp(argv[i], "--version") == 0) {
  87. printf("avdl v0.0.1\n");
  88. return -1;
  89. }
  90. else
  91. // custom install location
  92. if (strcmp(argv[i], "--install-loc") == 0) {
  93. if (argc > i+1) {
  94. installLocation = argv[i+1];
  95. i++;
  96. }
  97. else {
  98. printf("avdl error: --install-loc expects a path\n");
  99. return -1;
  100. }
  101. }
  102. // unknown double dash argument
  103. else {
  104. printf("avdl error: cannot understand double dash argument '%s'\n", argv[i]);
  105. return -1;
  106. }
  107. }
  108. else
  109. /* phase arguments
  110. * -t: translate only
  111. * -c: skip linking
  112. */
  113. if (strcmp(argv[i], "-t") == 0) {
  114. compile = 0;
  115. link = 0;
  116. }
  117. else
  118. if (strcmp(argv[i], "-c") == 0) {
  119. link = 0;
  120. }
  121. else
  122. // output filename
  123. if (strcmp(argv[i], "-o") == 0) {
  124. if (argc > i+1) {
  125. outname = argv[i+1];
  126. i++;
  127. }
  128. else {
  129. printf("avdl error: name is expected after `-o`\n");
  130. return -1;
  131. }
  132. }
  133. else
  134. // add include path
  135. if (strcmp(argv[i], "-I") == 0) {
  136. if (argc > i+1) {
  137. includePath = argv[i+1];
  138. i++;
  139. }
  140. else {
  141. printf("avdl error: include path is expected after `-I`\n");
  142. return -1;
  143. }
  144. }
  145. // unknown single dash argument
  146. else {
  147. printf("avdl error: cannot understand dash argument '%s'\n", argv[i]);
  148. return -1;
  149. }
  150. }
  151. // non-dash argument - input file?
  152. else {
  153. // input file
  154. if (input_file_total < MAX_INPUT_FILES) {
  155. strncpy(filename[input_file_total], argv[i], 100);
  156. filename[input_file_total][99] = '\0';
  157. input_file_total++;
  158. }
  159. // error argument
  160. else {
  161. printf("avdl error: '%s': Only %d input files can be provided at a time\n", argv[i], MAX_INPUT_FILES);
  162. return -1;
  163. }
  164. }
  165. }
  166. // make sure the minimum to parse exists
  167. if (input_file_total <= 0) {
  168. printf("avdl error: No filename given\n");
  169. return -1;
  170. }
  171. if (getDependencies) {
  172. for (unsigned int i = 0; i < dependencies_count; i++) {
  173. strcpy(buffer, "ldd ");
  174. strcat(buffer, filename[0]);
  175. strcat(buffer, " | grep 'lib");
  176. strcat(buffer, dependencies[i]);
  177. strcat(buffer, "\\.' | sed 's/^.*=> \\(.*\\) .*$/\\1/'");
  178. //printf("command: %s\n", buffer);
  179. system(buffer);
  180. }
  181. return 0;
  182. }
  183. if (outname && !link && input_file_total > 1) {
  184. printf("avdl error: cannot supply `-o` with `-c` and multiple input files\n");
  185. return -1;
  186. }
  187. if (translate) {
  188. //printf("~~~ translation phase ~~~\n");
  189. }
  190. // translate all given input files
  191. for (int i = 0; i < input_file_total && translate; i++) {
  192. // check if file is meant to be compiled, or is already compiled
  193. if (strcmp(filename[i] +strlen(filename[i]) -3, ".dd") != 0) {
  194. continue;
  195. }
  196. included_files_num = 0;
  197. // initialise the parent node
  198. game_node = ast_create(AST_GAME, 0);
  199. semanticAnalyser_convertToAst(game_node, filename[i]);
  200. /*
  201. * if only transpiling, check output file
  202. */
  203. //printf("transpiling: %s", filename[i]);
  204. // parse resulting ast tree to a file
  205. if (!compile && !link && outname) {
  206. strcpy(buffer, outname);
  207. }
  208. else {
  209. filename[i][strlen(filename[i]) -2] = 'c';
  210. filename[i][strlen(filename[i]) -1] = '\0';
  211. strcpy(buffer, filename[i]);
  212. }
  213. //printf(" to %s\n", buffer);
  214. if (transpile_cglut(buffer, game_node) != 0) {
  215. printf("avdl: transpilation failed to file: %s\n", buffer);
  216. return -1;
  217. }
  218. // print debug data
  219. if (show_ast) {
  220. ast_print(game_node);
  221. }
  222. if (show_struct_table) {
  223. struct_table_print();
  224. }
  225. }
  226. if (compile) {
  227. //printf("~~~ compilation phase ~~~\n");
  228. }
  229. // compile all given input files
  230. for (int i = 0; i < input_file_total && compile; i++) {
  231. // check if file is meant to be compiled, or is already compiled
  232. if (strcmp(filename[i] +strlen(filename[i]) -2, ".c") != 0) {
  233. continue;
  234. }
  235. //printf("compiling: %s\n", filename[i]);
  236. // compile
  237. strcpy(buffer, "gcc -DDD_PLATFORM_NATIVE -c -w ");
  238. strcat(buffer, filename[i]);
  239. strcat(buffer, " -o ");
  240. if (outname && !link) {
  241. strcat(buffer, outname);
  242. }
  243. else {
  244. filename[i][strlen(filename[i]) -1] = 'o';
  245. strcat(buffer, filename[i]);
  246. }
  247. strcat(buffer, " -O3 -lGL -lGLU -lGLEW -lglut -lavdl-cengine -lm -w -lSDL2 -lSDL2_mixer");
  248. if (includePath) {
  249. strcat(buffer, " -I ");
  250. strcat(buffer, includePath);
  251. }
  252. //printf("command: %s\n", buffer);
  253. if (system(buffer)) {
  254. printf("avdl: error compiling file: %s\n", filename[i]);
  255. exit(-1);
  256. }
  257. }
  258. if (1) {
  259. //printf("~~~ asset phase ~~~\n");
  260. }
  261. // compile all given input files
  262. for (int i = 0; i < input_file_total && compile; i++) {
  263. // check if file is asset
  264. if (strcmp(filename[i] +strlen(filename[i]) -4, ".ply") != 0
  265. && strcmp(filename[i] +strlen(filename[i]) -4, ".bmp") != 0
  266. && strcmp(filename[i] +strlen(filename[i]) -4, ".wav") != 0
  267. && strcmp(filename[i] +strlen(filename[i]) -4, ".ogg") != 0) {
  268. continue;
  269. }
  270. if (outname) {
  271. strcpy(buffer, outname);
  272. }
  273. else {
  274. strcpy(buffer, filename[i]);
  275. buffer[strlen(buffer) -4] = '\0';
  276. strcat(buffer, ".asset");
  277. }
  278. //printf("compiling asset: %s to %s\n", filename[i], buffer);
  279. file_copy(filename[i], buffer, 0);
  280. }
  281. // compile the final executable
  282. if (link) {
  283. //printf("~~~ link phase ~~~\n");
  284. buffer[0] = '\0';
  285. sprintf(buffer, "gcc -DDD_PLATFORM_NATIVE ");
  286. for (int i = 0; i < input_file_total; i++) {
  287. strcat(buffer, filename[i]);
  288. strcat(buffer, " ");
  289. }
  290. strcat(buffer, "-O3 -lGL -lGLU -lGLEW -lglut -lavdl-cengine -lm -w -lSDL2 -lSDL2_mixer -lpthread -o ");
  291. if (outname) {
  292. strcat(buffer, outname);
  293. }
  294. else {
  295. strcat(buffer, "game");
  296. }
  297. //printf("command: %s\n", buffer);
  298. if (system(buffer)) {
  299. printf("avdl: error linking files\n");
  300. exit(-1);
  301. }
  302. }
  303. // success!
  304. return 0;
  305. }