Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

381 lines
7.8 KiB

  1. //
  2. // Copyright (c) Microsoft Corporation 1995
  3. //
  4. // codegen.c
  5. //
  6. // This file contains the code-generating functions.
  7. //
  8. // The "code" is actually just an intermediate representation.
  9. // Currently this is an array of ASTs.
  10. //
  11. // History:
  12. // 06-18-95 ScottH Created
  13. //
  14. #include "proj.h"
  15. #include "rcids.h"
  16. RES PRIVATE Stmt_Codegen(PSTMT this, PASTEXEC pastexec, PSYMTAB pst);
  17. /*----------------------------------------------------------
  18. Purpose: Generate code for the 'while' statement
  19. Returns: RES_OK
  20. or some error result
  21. Cond: --
  22. */
  23. RES PRIVATE WhileStmt_Codegen(
  24. PSTMT this,
  25. PASTEXEC pastexec,
  26. PSYMTAB pst)
  27. {
  28. RES res;
  29. LPSTR pszTop;
  30. LPSTR pszEnd;
  31. ASSERT(this);
  32. ASSERT(pastexec);
  33. ASSERT(AT_WHILE_STMT == Ast_GetType(this));
  34. pszTop = WhileStmt_GetTopLabel(this);
  35. pszEnd = WhileStmt_GetEndLabel(this);
  36. res = Astexec_InsertLabel(pastexec, pszTop, pst);
  37. if (RSUCCEEDED(res))
  38. {
  39. // add the 'while' statement for the test expression
  40. res = Astexec_Add(pastexec, this);
  41. if (RSUCCEEDED(res))
  42. {
  43. // add the statements in the statement block
  44. DWORD i;
  45. DWORD cstmts;
  46. HPA hpaStmts = WhileStmt_GetStmtBlock(this);
  47. res = RES_OK;
  48. cstmts = PAGetCount(hpaStmts);
  49. // Add each statement
  50. for (i = 0; i < cstmts; i++)
  51. {
  52. PSTMT pstmt = PAFastGetPtr(hpaStmts, i);
  53. res = Stmt_Codegen(pstmt, pastexec, pst);
  54. if (RFAILED(res))
  55. break;
  56. }
  57. if (RSUCCEEDED(res))
  58. {
  59. // add the end label
  60. res = Astexec_InsertLabel(pastexec, pszEnd, pst);
  61. }
  62. }
  63. }
  64. return res;
  65. }
  66. /*----------------------------------------------------------
  67. Purpose: Generate code for the 'if' statement
  68. Returns: RES_OK
  69. or some error result
  70. Cond: --
  71. */
  72. RES PRIVATE IfStmt_Codegen(
  73. PSTMT this,
  74. PASTEXEC pastexec,
  75. PSYMTAB pst)
  76. {
  77. RES res;
  78. LPSTR pszElse;
  79. LPSTR pszEnd;
  80. ASSERT(this);
  81. ASSERT(pastexec);
  82. ASSERT(AT_IF_STMT == Ast_GetType(this));
  83. pszElse = IfStmt_GetElseLabel(this);
  84. pszEnd = IfStmt_GetEndLabel(this);
  85. // add the 'if' statement for the test expression
  86. res = Astexec_Add(pastexec, this);
  87. if (RSUCCEEDED(res))
  88. {
  89. // add the statements in the 'then' statement block
  90. DWORD i;
  91. DWORD cstmts;
  92. HPA hpaStmts = IfStmt_GetStmtBlock(this);
  93. res = RES_OK;
  94. cstmts = PAGetCount(hpaStmts);
  95. // Add each statement
  96. for (i = 0; i < cstmts; i++)
  97. {
  98. PSTMT pstmt = PAFastGetPtr(hpaStmts, i);
  99. res = Stmt_Codegen(pstmt, pastexec, pst);
  100. if (RFAILED(res))
  101. break;
  102. }
  103. if (RSUCCEEDED(res))
  104. {
  105. // add the else label
  106. res = Astexec_InsertLabel(pastexec, pszElse, pst);
  107. }
  108. }
  109. return res;
  110. }
  111. /*----------------------------------------------------------
  112. Purpose: Generate code for the label statement
  113. Returns: RES_OK
  114. or some error result
  115. Cond: --
  116. */
  117. RES PRIVATE LabelStmt_Codegen(
  118. PSTMT this,
  119. PASTEXEC pastexec,
  120. PSYMTAB pst)
  121. {
  122. LPSTR pszIdent;
  123. ASSERT(this);
  124. ASSERT(pastexec);
  125. ASSERT(AT_LABEL_STMT == Ast_GetType(this));
  126. pszIdent = LabelStmt_GetIdent(this);
  127. return Astexec_InsertLabel(pastexec, pszIdent, pst);
  128. }
  129. /*----------------------------------------------------------
  130. Purpose: Generate code for the 'set' statement
  131. Returns: RES_OK
  132. or some error result
  133. Cond: --
  134. */
  135. RES PRIVATE SetStmt_Codegen(
  136. PSTMT this,
  137. PASTEXEC pastexec,
  138. PSYMTAB pst)
  139. {
  140. RES res = RES_OK;
  141. ASSERT(this);
  142. ASSERT(pastexec);
  143. ASSERT(AT_SET_STMT == Ast_GetType(this));
  144. switch (SetStmt_GetType(this))
  145. {
  146. case ST_IPADDR:
  147. case ST_PORT:
  148. case ST_SCREEN:
  149. res = Astexec_Add(pastexec, this);
  150. break;
  151. default:
  152. ASSERT(0);
  153. res = RES_E_INVALIDPARAM;
  154. break;
  155. }
  156. return res;
  157. }
  158. /*----------------------------------------------------------
  159. Purpose: Generate code for a statement
  160. Returns: RES_OK
  161. or some error result
  162. Cond: --
  163. */
  164. RES PRIVATE Stmt_Codegen(
  165. PSTMT this,
  166. PASTEXEC pastexec,
  167. PSYMTAB pst)
  168. {
  169. RES res;
  170. ASSERT(this);
  171. ASSERT(pastexec);
  172. switch (Ast_GetType(this))
  173. {
  174. case AT_ENTER_STMT:
  175. case AT_LEAVE_STMT:
  176. case AT_HALT_STMT:
  177. case AT_TRANSMIT_STMT:
  178. case AT_WAITFOR_STMT:
  179. case AT_DELAY_STMT:
  180. case AT_GOTO_STMT:
  181. case AT_ASSIGN_STMT:
  182. res = Astexec_Add(pastexec, this);
  183. break;
  184. case AT_WHILE_STMT:
  185. res = WhileStmt_Codegen(this, pastexec, pst);
  186. break;
  187. case AT_IF_STMT:
  188. res = IfStmt_Codegen(this, pastexec, pst);
  189. break;
  190. case AT_SET_STMT:
  191. res = SetStmt_Codegen(this, pastexec, pst);
  192. break;
  193. case AT_LABEL_STMT:
  194. res = LabelStmt_Codegen(this, pastexec, pst);
  195. break;
  196. default:
  197. ASSERT(0);
  198. res = RES_E_INVALIDPARAM;
  199. break;
  200. }
  201. return res;
  202. }
  203. /*----------------------------------------------------------
  204. Purpose: Generate code for a procedure declaration.
  205. Returns: RES_OK
  206. or some error result
  207. Cond: --
  208. */
  209. RES PRIVATE ProcDecl_Codegen(
  210. PPROCDECL this,
  211. PASTEXEC pastexec)
  212. {
  213. RES res = RES_OK;
  214. DWORD i;
  215. DWORD cstmts;
  216. ASSERT(this);
  217. ASSERT(pastexec);
  218. cstmts = PAGetCount(this->hpaStmts);
  219. // Generate for each statement
  220. for (i = 0; i < cstmts; i++)
  221. {
  222. PSTMT pstmt = PAFastGetPtr(this->hpaStmts, i);
  223. res = Stmt_Codegen(pstmt, pastexec, this->pst);
  224. if (RFAILED(res))
  225. break;
  226. }
  227. return res;
  228. }
  229. /*----------------------------------------------------------
  230. Purpose: Find the proc decl that has the given identifier.
  231. Returns: TRUE (if found)
  232. Cond: --
  233. */
  234. BOOL PRIVATE FindProc(
  235. PMODULEDECL pmd,
  236. LPCSTR pszIdent,
  237. PPROCDECL * ppprocdecl)
  238. {
  239. DWORD i;
  240. DWORD cprocs = PAGetCount(pmd->hpaProcs);
  241. *ppprocdecl = NULL;
  242. for (i = 0; i < cprocs; i++)
  243. {
  244. PPROCDECL pprocdecl = PAFastGetPtr(pmd->hpaProcs, i);
  245. if (IsSzEqualC(ProcDecl_GetIdent(pprocdecl), pszIdent))
  246. {
  247. *ppprocdecl = pprocdecl;
  248. break;
  249. }
  250. }
  251. return NULL != *ppprocdecl;
  252. }
  253. /*----------------------------------------------------------
  254. Purpose: Generate code for the module declaration.
  255. Returns: RES_OK
  256. or some error result
  257. Cond: --
  258. */
  259. RES PUBLIC ModuleDecl_Codegen(
  260. PMODULEDECL this,
  261. PASTEXEC pastexec)
  262. {
  263. RES res = RES_OK;
  264. DWORD i;
  265. DWORD cprocs;
  266. PPROCDECL ppdMain;
  267. ASSERT(this);
  268. ASSERT(pastexec);
  269. TRACE_MSG(TF_GENERAL, "Generating code...");
  270. cprocs = PAGetCount(this->hpaProcs);
  271. // Generate code for the main proc first.
  272. if (FindProc(this, "main", &ppdMain))
  273. {
  274. res = ProcDecl_Codegen(ppdMain, pastexec);
  275. if (RSUCCEEDED(res))
  276. {
  277. // Generate code for the rest of the procs
  278. for (i = 0; i < cprocs; i++)
  279. {
  280. PPROCDECL pprocdecl = PAFastGetPtr(this->hpaProcs, i);
  281. if (pprocdecl != ppdMain)
  282. {
  283. res = ProcDecl_Codegen(pprocdecl, pastexec);
  284. if (RFAILED(res))
  285. break;
  286. }
  287. }
  288. }
  289. }
  290. else
  291. {
  292. // Typechecking should have guaranteed that the main
  293. // proc was here
  294. ASSERT(0);
  295. res = RES_E_FAIL;
  296. }
  297. return res;
  298. }