sq_mix.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. #include "squirrel.h"
  2. #include "sqstdblobimpl.h"
  3. #define MixInteger SQInteger
  4. #include "code_mix_prep.c"
  5. /* Generic loader function. Load the data found in the state in the lua engine
  6. */
  7. static SQRESULT mix_loadbuffer(HSQUIRRELVM sqvm, mix_state_t *S, const SQChar *name, int isParseOnly) {
  8. SQRESULT res;
  9. S->pos = 0;
  10. if (S->size > 0 && S->buffer[0] == '#') {
  11. while (S->pos < S->size && S->buffer[S->pos] != '\n')
  12. ++S->pos;
  13. ++S->pos;
  14. S->token = tok_sh;
  15. } else {
  16. S->token = tok_code_end;
  17. }
  18. S->error = NULL;
  19. if(isParseOnly){
  20. SQBlob blob(0, BLOB_BUFSIZE);
  21. MixInteger ch;
  22. while((ch = sq_mix_reader_char(S))) blob.WriteChar(ch);
  23. if (S->error != NULL) {
  24. return sq_throwerror(sqvm, S->error);
  25. }
  26. sq_pushstring(sqvm, (const SQChar*)blob.GetBuf(), blob.Len());
  27. }
  28. else
  29. {
  30. res = sq_compile(sqvm, sq_mix_reader_char, S, name, SQTrue);
  31. if (S->error != NULL) {
  32. return sq_throwerror(sqvm, S->error);
  33. } else if (res != 0) {
  34. sq_pushnull(sqvm);
  35. }
  36. }
  37. return 1;
  38. }
  39. SQ_OPT_STRING_STRLEN();
  40. /* Read the options common to mix_loadbuffer and mix_loadfile and store them in
  41. * the state.
  42. */
  43. static SQRESULT mix_stateopt(HSQUIRRELVM sqvm, mix_state_t *S) {
  44. SQ_FUNC_VARS(sqvm);
  45. SQ_OPT_STRING(sqvm, 3, code_start, "<?");
  46. S->code_start = code_start;
  47. S->code_startsize = code_start_size;
  48. if (S->code_startsize == 0)
  49. return sq_throwerror(sqvm, _SC("code_start separator cannot be empty"));
  50. SQ_OPT_STRING(sqvm, 4, code_end, "?>");
  51. S->code_end = code_end;
  52. S->code_endsize = code_end_size;
  53. if (S->code_endsize == 0)
  54. return sq_throwerror(sqvm, _SC("code_end separator cannot be empty"));
  55. SQ_OPT_STRING(sqvm, 5, expr_code, "=");
  56. S->expr = expr_code;
  57. S->exprsize = expr_code_size;
  58. if (S->exprsize == 0)
  59. return sq_throwerror(sqvm, _SC("expr separator cannot be empty"));
  60. SQ_OPT_STRING(sqvm, 6, print_code, "mix_write");
  61. if (print_code_size == 0)
  62. return sq_throwerror(sqvm, _SC("mix_write function name cannot be empty"));
  63. snprintf(S->print_out, sizeof(S->print_out), "%s(\"", print_code);
  64. S->print_outsize = strlen(S->print_out);
  65. S->result_size = 0;
  66. return 0;
  67. }
  68. static SQRESULT mix_load_parse_file(HSQUIRRELVM sqvm, int isParse) {
  69. const SQChar *filename;
  70. FILE *file;
  71. mix_state_t S;
  72. sq_mix_init(&S, 0, 0, 0,0,0,0);
  73. sq_getstring(sqvm, 2, &filename);
  74. SQRESULT rc = mix_stateopt(sqvm, &S);
  75. if(rc) return rc;
  76. file = fopen(filename, _SC("r"));
  77. if (file == NULL) {
  78. return sq_throwerror(sqvm, _SC("cannot open file <%s>"), filename);
  79. }
  80. fseek(file, 0, SEEK_END);
  81. S.size = ftell(file);
  82. fseek(file, 0, SEEK_SET);
  83. SQBlob buffer(0, S.size);
  84. if (fread(buffer.GetBuf(), S.size, 1, file) != 1) {
  85. fclose(file);
  86. return sq_throwerror(sqvm, _SC("cannot read file <%s>"), filename);
  87. }
  88. S.buffer = (const char*)buffer.GetBuf();
  89. fclose(file);
  90. return mix_loadbuffer(sqvm, &S, filename, isParse);
  91. }
  92. static SQRESULT mix_loadfile(HSQUIRRELVM sqvm) {
  93. return mix_load_parse_file(sqvm, 0);
  94. }
  95. static SQRESULT mix_parsefile(HSQUIRRELVM sqvm) {
  96. return mix_load_parse_file(sqvm, 1);
  97. }
  98. static SQRESULT mix_load_parse_string(HSQUIRRELVM sqvm, int isParse) {
  99. mix_state_t S;
  100. sq_mix_init(&S, 0, 0, 0,0,0,0);
  101. sq_getstring(sqvm, 2, &S.buffer);
  102. S.size = sq_getsize(sqvm, 2);
  103. mix_stateopt(sqvm, &S);
  104. return mix_loadbuffer(sqvm, &S, "chunk", isParse);
  105. }
  106. static SQRESULT mix_loadstring(HSQUIRRELVM sqvm) {
  107. return mix_load_parse_string(sqvm, 0);
  108. }
  109. static SQRESULT mix_parsestring(HSQUIRRELVM sqvm) {
  110. return mix_load_parse_string(sqvm, 1);
  111. }
  112. const SQChar validate_format_mask[] = _SC(".s s|o s|o s|o s");
  113. #define _DECL_MIX_FUNC(name,nparams,pmask) {_SC(#name), mix_##name,nparams,pmask}
  114. static SQRegFunction mix_obj_funcs[]={
  115. _DECL_MIX_FUNC(parsefile,-2,validate_format_mask),
  116. _DECL_MIX_FUNC(parsestring,-2,validate_format_mask),
  117. _DECL_MIX_FUNC(loadfile,-2,validate_format_mask),
  118. _DECL_MIX_FUNC(loadstring,-2,validate_format_mask),
  119. {0,0}
  120. };
  121. #undef _DECL_MIX_FUNC
  122. #ifdef __cplusplus
  123. extern "C" {
  124. #endif
  125. /* This defines a function that opens up your library. */
  126. SQRESULT sqext_register_mix (HSQUIRRELVM sqvm) {
  127. //add a namespace sqmix
  128. sq_pushstring(sqvm,_SC("sqmix"),-1);
  129. sq_newclass(sqvm,SQFalse);
  130. sq_insert_reg_funcs(sqvm, mix_obj_funcs);
  131. sq_newslot(sqvm,-3,SQTrue); //add sqmix table to the root table
  132. return SQ_OK;
  133. }
  134. #ifdef __cplusplus
  135. }
  136. #endif