/src/compiler/compiler.c

https://bitbucket.org/adrisr/avm · C · 337 lines · 274 code · 62 blank · 1 comment · 51 complexity · 0628ec0b78d9626801aea4aade6e133b MD5 · raw file

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <inttypes.h>
  5. #include "args.h"
  6. #include "buffer.h"
  7. #include "parser.h"
  8. #include <avm/avm.h>
  9. #include <avm/generated/opcodes.h>
  10. #include <avm/generated/opcode-name-table.h>
  11. static AVM g_avm;
  12. int compile_integer(Buffer *output, long long rval)
  13. {
  14. unsigned char buf[5];
  15. if (rval < INT32_MIN || rval > INT32_MAX )
  16. {
  17. fprintf(stderr, "Integer value %lld doesn't fit a 32 bit integer\n",
  18. rval);
  19. }
  20. if (rval >= 0 && rval <= 7)
  21. {
  22. buf[0] = AVMOpcode0 + rval;
  23. buffer_append(output, (const char*)buf, 1);
  24. }
  25. else if(rval >= -7 && rval <= -1)
  26. {
  27. buf[0] = AVMOpcodeN1 - rval - 1;
  28. buffer_append(output,(const char*) buf, 1);
  29. }
  30. else if(rval >= -128 && rval <= 127)
  31. {
  32. buf[0] = AVMOpcodeInt8;
  33. buf[1] = rval & 0xff;
  34. buffer_append(output, (const char*)buf, 2);
  35. }
  36. else if(rval >= INT16_MIN && rval <= INT16_MAX)
  37. {
  38. buf[0] = AVMOpcodeInt16;
  39. buf[1] = (rval>>8) & 0xff;
  40. buf[2] = rval & 0xff;
  41. buffer_append(output, (const char*)buf, 3);
  42. }
  43. else if(rval >= -(1<<23) && rval <= (1<<23)-1)
  44. {
  45. buf[0] = AVMOpcodeInt24;
  46. buf[1] = 0xff & (rval>>16);
  47. buf[2] = 0xff & (rval>>8);
  48. buf[3] = 0xff & rval;
  49. buffer_append(output, (const char*)buf, 4);
  50. }
  51. else if(rval >= INT32_MIN && rval <= INT32_MAX)
  52. {
  53. buf[0] = AVMOpcodeInt32;
  54. buf[1] = 0xff & (rval>>24);
  55. buf[2] = 0xff & (rval>>16);
  56. buf[3] = 0xff & (rval>>8);
  57. buf[4] = 0xff & rval;
  58. buffer_append(output, (const char*)buf, 5);
  59. }
  60. return 0;
  61. }
  62. int compile_number(Buffer *output, Buffer *token)
  63. {
  64. long long rval;
  65. char *endp;
  66. rval = strtoll(buffer_get_data(token), &endp, 0);
  67. if (*endp != '\0')
  68. {
  69. fprintf(stderr, "Invalid number '%s'\n", buffer_get_data(token));
  70. return 9;
  71. }
  72. return compile_integer(output, rval);
  73. }
  74. int compile_char(Buffer *output, Buffer *token)
  75. {
  76. if (buffer_get_size(token) != 1)
  77. {
  78. fprintf(stderr, "Chars must have length 1: '%s'\n",
  79. buffer_get_data(token));
  80. return 1;
  81. }
  82. return compile_integer(output, buffer_get_data(token)[0]);
  83. }
  84. int compile_string(Buffer *output, Buffer *token)
  85. {
  86. unsigned char buf[3];
  87. size_t len = buffer_get_size(token);
  88. if (len > UINT16_MAX)
  89. {
  90. fprintf(stderr, "String is too long!");
  91. return 1;
  92. }
  93. if (len < UINT8_MAX)
  94. {
  95. buf[0] = AVMOpcodeStr8;
  96. buf[1] = len;
  97. buffer_append(output, (const char*)buf, 2);
  98. buffer_append(output, buffer_get_data(token), buffer_get_size(token));
  99. }
  100. else
  101. {
  102. buf[0] = AVMOpcodeStr16;
  103. buf[1] = 0xff & (len>>8);
  104. buf[2] = 0xff & len;
  105. buffer_append(output, (const char*)buf, 3);
  106. buffer_append(output, buffer_get_data(token), buffer_get_size(token));
  107. }
  108. return 0;
  109. }
  110. int compile_op(Buffer *output, Buffer *token)
  111. {
  112. char buf[1];
  113. const char *op = buffer_get_data(token);
  114. size_t i;
  115. for (i=0;OPCODE_TABLE[i].name != NULL;++i)
  116. {
  117. if (!strcasecmp(OPCODE_TABLE[i].name,op))
  118. {
  119. buf[0] = OPCODE_TABLE[i].op;
  120. buffer_append(output,buf,1);
  121. return 0;
  122. }
  123. }
  124. fprintf(stderr, "Invalid opcode: %s\n", op);
  125. return 0;
  126. }
  127. int compile_code(Buffer *output, Buffer *code)
  128. {
  129. char buf[5];
  130. uint32_t len = buffer_get_size(code);
  131. if (len<256)
  132. {
  133. buf[0] = AVMOpcodeCode8;
  134. buf[1] = len & 0xff;
  135. buffer_append(output, buf, 2);
  136. }
  137. else if (len<65536)
  138. {
  139. buf[0] = AVMOpcodeCode16;
  140. buf[1] = 0xff & (len>>8);
  141. buf[2] = 0xff & len;
  142. buffer_append(output, buf, 3);
  143. }
  144. else if (len<0x1000000)
  145. {
  146. buf[0] = AVMOpcodeCode24;
  147. buf[1] = 0xff & (len>>16);
  148. buf[2] = 0xff & (len>>8);
  149. buf[3] = 0xff & len;
  150. buffer_append(output, buf, 4);
  151. }
  152. else
  153. {
  154. buf[0] = AVMOpcodeCode32;
  155. buf[1] = 0xff & (len>>24);
  156. buf[2] = 0xff & (len>>16);
  157. buf[3] = 0xff & (len>>8);
  158. buf[4] = 0xff & len;
  159. buffer_append(output, buf, 5);
  160. }
  161. buffer_append_buffer(output,code);
  162. return 0;
  163. }
  164. int compile_ref(Buffer *output, Buffer *token, TokenType type)
  165. {
  166. char buf[5];
  167. AVMHash hash;
  168. buf[0] = (type == TokenRef)? AVMOpcodeRef : AVMOpcodeRefVal;
  169. hash = avm_hash(g_avm, buffer_get_data(token), buffer_get_size(token));
  170. buf[1] = 0xff & (hash>>24);
  171. buf[2] = 0xff & (hash>>16);
  172. buf[3] = 0xff & (hash>>8);
  173. buf[4] = 0xff & (hash);
  174. buffer_append(output,buf,5);
  175. return 0;
  176. }
  177. int compile_nested(Buffer *output, FILE *input, int nestlvl)
  178. {
  179. TokenType type;
  180. Buffer *token = buffer_init();
  181. int rv = 0;
  182. while (rv==0 && parse_input(token, &type, input)
  183. && type != TokenError
  184. && type != TokenEOF)
  185. {
  186. buffer_zero_terminate(token);
  187. switch (type)
  188. {
  189. case TokenNumber:
  190. rv = compile_number(output,token);
  191. break;
  192. case TokenString:
  193. rv = compile_string(output,token);
  194. break;
  195. case TokenChar:
  196. rv = compile_char(output, token);
  197. break;
  198. case TokenRef:
  199. case TokenDeref:
  200. rv = compile_ref(output, token, type);
  201. break;
  202. case TokenCodeBegin:
  203. {
  204. Buffer *subroutine = buffer_init();
  205. rv = compile_nested(subroutine, input, nestlvl+1);
  206. if (!rv)
  207. {
  208. rv = compile_code(output, subroutine);
  209. }
  210. }
  211. break;
  212. case TokenCodeEnd:
  213. if (nestlvl<1)
  214. {
  215. fprintf(stderr,"Close brace (}) found with no matching open brace\n");
  216. rv = 1;
  217. }
  218. goto term;
  219. break;
  220. case TokenOp:
  221. rv = compile_op(output, token);
  222. break;
  223. case TokenError:
  224. case TokenEOF:
  225. /* impossible, but avoid warning */
  226. break;
  227. }
  228. }
  229. term:
  230. return rv? rv : type != TokenError ? 0 : 9;
  231. }
  232. int compile(Args *args)
  233. {
  234. int ret = 0;
  235. FILE *fin = fopen(args->inputName, "rb"),
  236. *fout = fopen(args->outputName, "wb");
  237. if (!fin)
  238. {
  239. fprintf(stderr,"%s: Unable to open input '%s' for reading\n",
  240. args->exeName, args->inputName);
  241. return 3;
  242. }
  243. if (!fout)
  244. {
  245. fprintf(stderr,"%s: Unable to open output '%s' for writing\n",
  246. args->exeName, args->outputName);
  247. fclose(fin);
  248. return 4;
  249. }
  250. g_avm = avm_init();
  251. if (!g_avm)
  252. {
  253. return 12;
  254. }
  255. Buffer *buf = buffer_init();
  256. ret = compile_nested(buf, fin, 0);
  257. if (!ret)
  258. {
  259. size_t nbytes = buffer_get_size(buf);
  260. if (nbytes)
  261. {
  262. if (nbytes != fwrite(buffer_get_data(buf), 1, nbytes, fout))
  263. {
  264. fprintf(stderr,"Error writting %lu bytes to output file\n",
  265. nbytes);
  266. return 8;
  267. }
  268. }
  269. fprintf(stderr,"Generated output of %lu bytes\n",
  270. nbytes);
  271. }
  272. fclose(fin);
  273. fclose(fout);
  274. return ret;
  275. }