scriplib.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. #include "cmdlib.h"
  2. #include "filelib.h"
  3. #include "messages.h"
  4. #include "log.h"
  5. #include "scriplib.h"
  6. char g_token[MAXTOKEN];
  7. char g_TXcommand;
  8. typedef struct
  9. {
  10. char filename[_MAX_PATH];
  11. char* buffer;
  12. char* script_p;
  13. char* end_p;
  14. int line;
  15. }
  16. script_t;
  17. #define MAX_INCLUDES 8
  18. static script_t s_scriptstack[MAX_INCLUDES];
  19. script_t* s_script;
  20. int s_scriptline;
  21. bool s_endofscript;
  22. bool s_tokenready; // only true if UnGetToken was just called
  23. // AddScriptToStack
  24. // LoadScriptFile
  25. // ParseFromMemory
  26. // UnGetToken
  27. // EndOfScript
  28. // GetToken
  29. // TokenAvailable
  30. // =====================================================================================
  31. // AddScriptToStack
  32. // =====================================================================================
  33. static void AddScriptToStack(const char* const filename)
  34. {
  35. int size;
  36. s_script++;
  37. if (s_script == &s_scriptstack[MAX_INCLUDES])
  38. Error("s_script file exceeded MAX_INCLUDES");
  39. strcpy_s(s_script->filename, filename);
  40. size = LoadFile(s_script->filename, (char**)&s_script->buffer);
  41. Log("Entering %s\n", s_script->filename);
  42. s_script->line = 1;
  43. s_script->script_p = s_script->buffer;
  44. s_script->end_p = s_script->buffer + size;
  45. }
  46. // =====================================================================================
  47. // LoadScriptFile
  48. // =====================================================================================
  49. void LoadScriptFile(const char* const filename)
  50. {
  51. s_script = s_scriptstack;
  52. AddScriptToStack(filename);
  53. s_endofscript = false;
  54. s_tokenready = false;
  55. }
  56. // =====================================================================================
  57. // ParseFromMemory
  58. // =====================================================================================
  59. void ParseFromMemory(char* buffer, const int size)
  60. {
  61. s_script = s_scriptstack;
  62. s_script++;
  63. if (s_script == &s_scriptstack[MAX_INCLUDES])
  64. Error("s_script file exceeded MAX_INCLUDES");
  65. strcpy_s(s_script->filename, "memory buffer");
  66. s_script->buffer = buffer;
  67. s_script->line = 1;
  68. s_script->script_p = s_script->buffer;
  69. s_script->end_p = s_script->buffer + size;
  70. s_endofscript = false;
  71. s_tokenready = false;
  72. }
  73. // =====================================================================================
  74. // UnGetToken
  75. /*
  76. * Signals that the current g_token was not used, and should be reported
  77. * for the next GetToken. Note that
  78. *
  79. * GetToken (true);
  80. * UnGetToken ();
  81. * GetToken (false);
  82. *
  83. * could cross a line boundary.
  84. */
  85. // =====================================================================================
  86. void UnGetToken()
  87. {
  88. s_tokenready = true;
  89. }
  90. // =====================================================================================
  91. // EndOfScript
  92. // =====================================================================================
  93. bool EndOfScript(const bool crossline)
  94. {
  95. if (!crossline)
  96. Error("Line %i is incomplete (did you place a \" inside an entity string?) \n", s_scriptline);
  97. if (!strcmp(s_script->filename, "memory buffer"))
  98. {
  99. s_endofscript = true;
  100. return false;
  101. }
  102. free(s_script->buffer);
  103. if (s_script == s_scriptstack + 1)
  104. {
  105. s_endofscript = true;
  106. return false;
  107. }
  108. s_script--;
  109. s_scriptline = s_script->line;
  110. Log("returning to %s\n", s_script->filename);
  111. return GetToken(crossline);
  112. }
  113. // =====================================================================================
  114. // GetToken
  115. // =====================================================================================
  116. bool GetToken(const bool crossline)
  117. {
  118. char *token_p;
  119. if (s_tokenready) // is a g_token allready waiting?
  120. {
  121. s_tokenready = false;
  122. return true;
  123. }
  124. if (s_script->script_p >= s_script->end_p)
  125. return EndOfScript(crossline);
  126. // skip space
  127. skipspace:
  128. while (*s_script->script_p <= 32)
  129. {
  130. if (s_script->script_p >= s_script->end_p)
  131. return EndOfScript(crossline);
  132. if (*s_script->script_p++ == '\n')
  133. {
  134. if (!crossline)
  135. Error("Line %i is incomplete (did you place a \" inside an entity string?) \n", s_scriptline);
  136. s_scriptline = s_script->line++;
  137. }
  138. }
  139. if (s_script->script_p >= s_script->end_p)
  140. return EndOfScript(crossline);
  141. // comment fields
  142. if (*s_script->script_p == ';' || *s_script->script_p == '#' || // semicolon and # is comment field
  143. (*s_script->script_p == '/' && *((s_script->script_p) + 1) == '/')) // also make // a comment field
  144. {
  145. if (!crossline)
  146. Error("Line %i is incomplete (did you place a \" inside an entity string?) \n", s_scriptline);
  147. //ets+++
  148. if (*s_script->script_p == '/')
  149. s_script->script_p++;
  150. if (s_script->script_p[1] == 'T' && s_script->script_p[2] == 'X')
  151. g_TXcommand = s_script->script_p[3]; // AR: "//TX#"-style comment
  152. //ets---
  153. while (*s_script->script_p++ != '\n')
  154. {
  155. if (s_script->script_p >= s_script->end_p)
  156. return EndOfScript(crossline);
  157. }
  158. //ets+++
  159. s_scriptline = s_script->line++; // AR: this line was missing
  160. //ets---
  161. goto skipspace;
  162. }
  163. // copy g_token
  164. token_p = g_token;
  165. if (*s_script->script_p == '"')
  166. {
  167. // quoted token
  168. s_script->script_p++;
  169. while (*s_script->script_p != '"')
  170. {
  171. *token_p++ = *s_script->script_p++;
  172. if (s_script->script_p == s_script->end_p)
  173. break;
  174. if (token_p == &g_token[MAXTOKEN])
  175. Error("Token too large on line %i\n", s_scriptline);
  176. }
  177. s_script->script_p++;
  178. }
  179. else
  180. {
  181. // regular token
  182. while (*s_script->script_p > 32 && *s_script->script_p != ';')
  183. {
  184. *token_p++ = *s_script->script_p++;
  185. if (s_script->script_p == s_script->end_p)
  186. break;
  187. if (token_p == &g_token[MAXTOKEN])
  188. Error("Token too large on line %i\n", s_scriptline);
  189. }
  190. }
  191. *token_p = 0;
  192. if (!strcmp(g_token, "$include"))
  193. {
  194. GetToken(false);
  195. AddScriptToStack(g_token);
  196. return GetToken(crossline);
  197. }
  198. return true;
  199. }
  200. #if 0
  201. // AJM: THIS IS REDUNDANT
  202. // =====================================================================================
  203. // ParseWadToken
  204. // basically the same as gettoken, except it isnt limited by MAXTOKEN and is
  205. // specificaly designed to parse out the wadpaths from the wad keyvalue and dump
  206. // them into the wadpaths list
  207. // this was implemented as a hack workaround for Token Too Large errors caused by
  208. // having long wadpaths or lots of wads in the map editor.
  209. extern void PushWadPath(const char* const path, bool inuse);
  210. // =====================================================================================
  211. void ParseWadToken(const bool crossline)
  212. {
  213. // code somewhat copied from GetToken()
  214. int i, j;
  215. char* token_p;
  216. char temp[_MAX_PATH];
  217. if (s_script->script_p >= s_script->end_p)
  218. return;
  219. // skip space
  220. while (*s_script->script_p <= 32)
  221. {
  222. if (s_script->script_p >= s_script->end_p)
  223. return;
  224. if (*s_script->script_p++ == '\n')
  225. {
  226. if (!crossline)
  227. Error("Line %i is incomplete (did you place a \" inside an entity string?) \n", s_scriptline);
  228. s_scriptline = s_script->line++;
  229. }
  230. }
  231. // EXPECT A QUOTE
  232. if (*s_script->script_p++ != '"')
  233. Error("Line %i: Expected a wadpaths definition, got '%s'\n", s_scriptline, *--s_script->script_p);
  234. // load wadpaths manually
  235. bool endoftoken = false;
  236. for (i = 0; !endoftoken; i++)
  237. {
  238. // get the path
  239. for (j = 0; ; j++)
  240. {
  241. token_p = ++s_script->script_p;
  242. // assert max path length
  243. if (j > _MAX_PATH)
  244. Error("Line %i: Wadpath definition %i is too long (%s)\n", s_scriptline, temp);
  245. if (*token_p == '\n')
  246. Error("Line %i: Expected a wadpaths definition, got linebreak\n", s_scriptline);
  247. if (*token_p == '"') // end of wadpath definition
  248. {
  249. if (i == 0 && j == 0) // no wadpaths!
  250. {
  251. Warning("No wadpaths specified.\n");
  252. return;
  253. }
  254. endoftoken = true;
  255. break;
  256. }
  257. if (*token_p == ';') // end of this wadpath
  258. break;
  259. temp[j] = *token_p;
  260. temp[j + 1] = 0;
  261. }
  262. // push it into the list
  263. PushWadPath(temp, true);
  264. temp[0] = 0;
  265. }
  266. for (; *s_script->script_p != '\n'; s_script->script_p++)
  267. {
  268. }
  269. }
  270. #endif
  271. // =====================================================================================
  272. // TokenAvailable
  273. // returns true if there is another token on the line
  274. // =====================================================================================
  275. bool TokenAvailable()
  276. {
  277. char *search_p;
  278. search_p = s_script->script_p;
  279. if (search_p >= s_script->end_p)
  280. return false;
  281. while (*search_p <= 32)
  282. {
  283. if (*search_p == '\n')
  284. return false;
  285. search_p++;
  286. if (search_p == s_script->end_p)
  287. return false;
  288. }
  289. if (*search_p == ';')
  290. return false;
  291. return true;
  292. }