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

//
// Copyright (c) Microsoft Corporation 1995
//
// codegen.c
//
// This file contains the code-generating functions.
//
// The "code" is actually just an intermediate representation.
// Currently this is an array of ASTs.
//
// History:
// 06-18-95 ScottH Created
//
#include "proj.h"
#include "rcids.h"
RES PRIVATE Stmt_Codegen(PSTMT this, PASTEXEC pastexec, PSYMTAB pst);
/*----------------------------------------------------------
Purpose: Generate code for the 'while' statement
Returns: RES_OK
or some error result
Cond: --
*/
RES PRIVATE WhileStmt_Codegen(
PSTMT this,
PASTEXEC pastexec,
PSYMTAB pst)
{
RES res;
LPSTR pszTop;
LPSTR pszEnd;
ASSERT(this);
ASSERT(pastexec);
ASSERT(AT_WHILE_STMT == Ast_GetType(this));
pszTop = WhileStmt_GetTopLabel(this);
pszEnd = WhileStmt_GetEndLabel(this);
res = Astexec_InsertLabel(pastexec, pszTop, pst);
if (RSUCCEEDED(res))
{
// add the 'while' statement for the test expression
res = Astexec_Add(pastexec, this);
if (RSUCCEEDED(res))
{
// add the statements in the statement block
DWORD i;
DWORD cstmts;
HPA hpaStmts = WhileStmt_GetStmtBlock(this);
res = RES_OK;
cstmts = PAGetCount(hpaStmts);
// Add each statement
for (i = 0; i < cstmts; i++)
{
PSTMT pstmt = PAFastGetPtr(hpaStmts, i);
res = Stmt_Codegen(pstmt, pastexec, pst);
if (RFAILED(res))
break;
}
if (RSUCCEEDED(res))
{
// add the end label
res = Astexec_InsertLabel(pastexec, pszEnd, pst);
}
}
}
return res;
}
/*----------------------------------------------------------
Purpose: Generate code for the 'if' statement
Returns: RES_OK
or some error result
Cond: --
*/
RES PRIVATE IfStmt_Codegen(
PSTMT this,
PASTEXEC pastexec,
PSYMTAB pst)
{
RES res;
LPSTR pszElse;
LPSTR pszEnd;
ASSERT(this);
ASSERT(pastexec);
ASSERT(AT_IF_STMT == Ast_GetType(this));
pszElse = IfStmt_GetElseLabel(this);
pszEnd = IfStmt_GetEndLabel(this);
// add the 'if' statement for the test expression
res = Astexec_Add(pastexec, this);
if (RSUCCEEDED(res))
{
// add the statements in the 'then' statement block
DWORD i;
DWORD cstmts;
HPA hpaStmts = IfStmt_GetStmtBlock(this);
res = RES_OK;
cstmts = PAGetCount(hpaStmts);
// Add each statement
for (i = 0; i < cstmts; i++)
{
PSTMT pstmt = PAFastGetPtr(hpaStmts, i);
res = Stmt_Codegen(pstmt, pastexec, pst);
if (RFAILED(res))
break;
}
if (RSUCCEEDED(res))
{
// add the else label
res = Astexec_InsertLabel(pastexec, pszElse, pst);
}
}
return res;
}
/*----------------------------------------------------------
Purpose: Generate code for the label statement
Returns: RES_OK
or some error result
Cond: --
*/
RES PRIVATE LabelStmt_Codegen(
PSTMT this,
PASTEXEC pastexec,
PSYMTAB pst)
{
LPSTR pszIdent;
ASSERT(this);
ASSERT(pastexec);
ASSERT(AT_LABEL_STMT == Ast_GetType(this));
pszIdent = LabelStmt_GetIdent(this);
return Astexec_InsertLabel(pastexec, pszIdent, pst);
}
/*----------------------------------------------------------
Purpose: Generate code for the 'set' statement
Returns: RES_OK
or some error result
Cond: --
*/
RES PRIVATE SetStmt_Codegen(
PSTMT this,
PASTEXEC pastexec,
PSYMTAB pst)
{
RES res = RES_OK;
ASSERT(this);
ASSERT(pastexec);
ASSERT(AT_SET_STMT == Ast_GetType(this));
switch (SetStmt_GetType(this))
{
case ST_IPADDR:
case ST_PORT:
case ST_SCREEN:
res = Astexec_Add(pastexec, this);
break;
default:
ASSERT(0);
res = RES_E_INVALIDPARAM;
break;
}
return res;
}
/*----------------------------------------------------------
Purpose: Generate code for a statement
Returns: RES_OK
or some error result
Cond: --
*/
RES PRIVATE Stmt_Codegen(
PSTMT this,
PASTEXEC pastexec,
PSYMTAB pst)
{
RES res;
ASSERT(this);
ASSERT(pastexec);
switch (Ast_GetType(this))
{
case AT_ENTER_STMT:
case AT_LEAVE_STMT:
case AT_HALT_STMT:
case AT_TRANSMIT_STMT:
case AT_WAITFOR_STMT:
case AT_DELAY_STMT:
case AT_GOTO_STMT:
case AT_ASSIGN_STMT:
res = Astexec_Add(pastexec, this);
break;
case AT_WHILE_STMT:
res = WhileStmt_Codegen(this, pastexec, pst);
break;
case AT_IF_STMT:
res = IfStmt_Codegen(this, pastexec, pst);
break;
case AT_SET_STMT:
res = SetStmt_Codegen(this, pastexec, pst);
break;
case AT_LABEL_STMT:
res = LabelStmt_Codegen(this, pastexec, pst);
break;
default:
ASSERT(0);
res = RES_E_INVALIDPARAM;
break;
}
return res;
}
/*----------------------------------------------------------
Purpose: Generate code for a procedure declaration.
Returns: RES_OK
or some error result
Cond: --
*/
RES PRIVATE ProcDecl_Codegen(
PPROCDECL this,
PASTEXEC pastexec)
{
RES res = RES_OK;
DWORD i;
DWORD cstmts;
ASSERT(this);
ASSERT(pastexec);
cstmts = PAGetCount(this->hpaStmts);
// Generate for each statement
for (i = 0; i < cstmts; i++)
{
PSTMT pstmt = PAFastGetPtr(this->hpaStmts, i);
res = Stmt_Codegen(pstmt, pastexec, this->pst);
if (RFAILED(res))
break;
}
return res;
}
/*----------------------------------------------------------
Purpose: Find the proc decl that has the given identifier.
Returns: TRUE (if found)
Cond: --
*/
BOOL PRIVATE FindProc(
PMODULEDECL pmd,
LPCSTR pszIdent,
PPROCDECL * ppprocdecl)
{
DWORD i;
DWORD cprocs = PAGetCount(pmd->hpaProcs);
*ppprocdecl = NULL;
for (i = 0; i < cprocs; i++)
{
PPROCDECL pprocdecl = PAFastGetPtr(pmd->hpaProcs, i);
if (IsSzEqualC(ProcDecl_GetIdent(pprocdecl), pszIdent))
{
*ppprocdecl = pprocdecl;
break;
}
}
return NULL != *ppprocdecl;
}
/*----------------------------------------------------------
Purpose: Generate code for the module declaration.
Returns: RES_OK
or some error result
Cond: --
*/
RES PUBLIC ModuleDecl_Codegen(
PMODULEDECL this,
PASTEXEC pastexec)
{
RES res = RES_OK;
DWORD i;
DWORD cprocs;
PPROCDECL ppdMain;
ASSERT(this);
ASSERT(pastexec);
TRACE_MSG(TF_GENERAL, "Generating code...");
cprocs = PAGetCount(this->hpaProcs);
// Generate code for the main proc first.
if (FindProc(this, "main", &ppdMain))
{
res = ProcDecl_Codegen(ppdMain, pastexec);
if (RSUCCEEDED(res))
{
// Generate code for the rest of the procs
for (i = 0; i < cprocs; i++)
{
PPROCDECL pprocdecl = PAFastGetPtr(this->hpaProcs, i);
if (pprocdecl != ppdMain)
{
res = ProcDecl_Codegen(pprocdecl, pastexec);
if (RFAILED(res))
break;
}
}
}
}
else
{
// Typechecking should have guaranteed that the main
// proc was here
ASSERT(0);
res = RES_E_FAIL;
}
return res;
}