wsstree.c

来自「The Kannel Open Source WAP and SMS gatew」· C语言 代码 · 共 1,501 行 · 第 1/4 页

C
1,501
字号
/********************* Statements ***************************************//* Linearize the variable declaration list `list'. */static void linearize_variable_init(WsCompiler *compiler, WsList *list,                                    WsUInt32 line){    WsNamespace *ns;    WsListItem *li;    /* For each variable, declared with this list. */    for (li = list->head; li; li = li->next) {        WsVarDec *vardec = li->data;        ns = ws_variable_define(compiler, line, WS_TRUE, vardec->name);        if (ns && vardec->expr) {            ws_expr_linearize(compiler, vardec->expr);            /* Emit an instruction to store the initialization               value to the variable. */            ws_asm_link(compiler,                        ws_asm_variable(compiler, line, WS_ASM_P_STORE_VAR,                                        ns->vindex));        }    }}void ws_stmt_linearize(WsCompiler *compiler, WsStatement *stmt){    WsListItem *li;    WsAsmIns *ins;    switch (stmt->type) {    case WS_STMT_BLOCK:        for (li = stmt->u.block->head; li; li = li->next)            ws_stmt_linearize(compiler, li->data);        break;    case WS_STMT_VARIABLE:        linearize_variable_init(compiler, stmt->u.var, stmt->first_line);        break;    case WS_STMT_EMPTY:        /* Nothing here. */        break;    case WS_STMT_EXPR:        ws_expr_linearize(compiler, stmt->u.expr);        /* Pop the expressions result from the stack.  Otherwise loops           could eventually cause stack overflows. */        ws_asm_link(compiler, ws_asm_ins(compiler, stmt->last_line, WS_ASM_POP));        break;    case WS_STMT_IF:        {            WsAsmIns *l_else = ws_asm_label(compiler,                                            (stmt->u.s_if.s_else                                             ? stmt->u.s_if.s_else->first_line                                             : stmt->last_line));            WsAsmIns *l_end = ws_asm_label(compiler, stmt->last_line);            /* Linearize the expression. */            ws_expr_linearize(compiler, stmt->u.s_if.expr);            /* If the result is false, jump to the else-branch. */            ws_asm_link(compiler, ws_asm_branch(compiler, stmt->first_line,                                                WS_ASM_P_TJUMP, l_else));            /* Else, execute the then-branch and jump to the end. */            ws_stmt_linearize(compiler, stmt->u.s_if.s_then);            ws_asm_link(compiler, ws_asm_branch(compiler, stmt->last_line,                                                WS_ASM_P_JUMP, l_end));            /* Then else-branch. */            ws_asm_link(compiler, l_else);            /* Linearize the else-branch if it is present. */            if (stmt->u.s_if.s_else)                ws_stmt_linearize(compiler, stmt->u.s_if.s_else);            /* Insert the end label. */            ws_asm_link(compiler, l_end);        }        break;    case WS_STMT_FOR:        {            WsAsmIns *l_loop = ws_asm_label(compiler, stmt->first_line);            WsAsmIns *l_cont = ws_asm_label(compiler, stmt->first_line);            WsAsmIns *l_break = ws_asm_label(compiler, stmt->first_line);            WsContBreak *cb;            /* Store the labels to the compiler. */            cb = ws_f_calloc(compiler->pool_stree, 1, sizeof(*cb));            if (cb == NULL) {                ws_error_memory(compiler);                return;            }            cb->next = compiler->cont_break;            compiler->cont_break = cb;            cb->l_cont = l_cont;            cb->l_break = l_break;            /* Linearize the possible init code. */            if (stmt->u.s_for.init)                linearize_variable_init(compiler, stmt->u.s_for.init,                                        stmt->first_line);            else if (stmt->u.s_for.e1) {                /* Linearize the init. */                ws_expr_linearize(compiler, stmt->u.s_for.e1);                /* Pop the result. */                ws_asm_link(compiler, ws_asm_ins(compiler, stmt->first_line,                                                 WS_ASM_POP));            }            /* Insert the loop label. */            ws_asm_link(compiler, l_loop);            /* Linearize the condition. */            if (stmt->u.s_for.e2) {                ws_expr_linearize(compiler, stmt->u.s_for.e2);                /* If false, jump out. */                ws_asm_link(compiler, ws_asm_branch(compiler, stmt->first_line,                                                    WS_ASM_P_TJUMP, l_break));            }            /* Linearize the body statement. */            ws_stmt_linearize(compiler, stmt->u.s_for.stmt);            /* Link the continue label. */            ws_asm_link(compiler, l_cont);            /* Linearize the update expression. */            if (stmt->u.s_for.e3) {                ws_expr_linearize(compiler, stmt->u.s_for.e3);                /* Pop the result. */                ws_asm_link(compiler, ws_asm_ins(compiler, stmt->first_line,                                                 WS_ASM_POP));            }            /* Jump to the loop label to check the condition. */            ws_asm_link(compiler, ws_asm_branch(compiler, stmt->last_line,                                                WS_ASM_P_JUMP, l_loop));            /* Insert the break label. */            ws_asm_link(compiler, l_break);            /* Pop the cont-break block. */            compiler->cont_break = compiler->cont_break->next;        }        break;    case WS_STMT_WHILE:        {            WsAsmIns *l_cont = ws_asm_label(compiler, stmt->first_line);            WsAsmIns *l_break = ws_asm_label(compiler,                                             stmt->u.s_while.stmt->last_line);            WsContBreak *cb;            /* Store the labels to the compiler. */            cb = ws_f_calloc(compiler->pool_stree, 1, sizeof(*cb));            if (cb == NULL) {                ws_error_memory(compiler);                return;            }            cb->next = compiler->cont_break;            compiler->cont_break = cb;            cb->l_cont = l_cont;            cb->l_break = l_break;            /* Insert the continue label. */            ws_asm_link(compiler, l_cont);            /* Linearize the expression. */            ws_expr_linearize(compiler, stmt->u.s_while.expr);            /* If false, jump out. */            ws_asm_link(compiler, ws_asm_branch(compiler, stmt->first_line,                                                WS_ASM_P_TJUMP, l_break));            /* Linearize the body statement. */            ws_stmt_linearize(compiler, stmt->u.s_while.stmt);            /* And jump to the continue label to check the expression. */            ws_asm_link(compiler, ws_asm_branch(compiler, stmt->last_line,                                                WS_ASM_P_JUMP, l_cont));            /* Insert the break label. */            ws_asm_link(compiler, l_break);            /* Pop the cont-break block. */            compiler->cont_break = compiler->cont_break->next;        }        break;    case WS_STMT_CONTINUE:        if (compiler->cont_break == NULL)            ws_src_error(compiler, stmt->first_line,                         "continue statement not within a loop");        ws_asm_link(compiler, ws_asm_branch(compiler, stmt->first_line,                                            WS_ASM_P_JUMP,                                            compiler->cont_break->l_cont));        break;    case WS_STMT_BREAK:        if (compiler->cont_break == NULL)            ws_src_error(compiler, stmt->first_line,                         "break statement not within a loop");        ws_asm_link(compiler, ws_asm_branch(compiler, stmt->first_line,                                            WS_ASM_P_JUMP,                                            compiler->cont_break->l_break));        break;    case WS_STMT_RETURN:        if (stmt->u.expr) {            /* Linearize the return value and return it. */            ws_expr_linearize(compiler, stmt->u.expr);            ins = ws_asm_ins(compiler, stmt->first_line, WS_ASM_RETURN);        } else            /* Return an empty string. */            ins = ws_asm_ins(compiler, stmt->first_line, WS_ASM_RETURN_ES);        ws_asm_link(compiler, ins);        break;    }}/* Constructors. */static WsStatement *stmt_alloc(WsCompiler *compiler, WsStatementType type,                               WsUInt32 first_line, WsUInt32 last_line){    WsStatement *stmt = ws_f_calloc(compiler->pool_stree, 1, sizeof(*stmt));    if (stmt == NULL)        ws_error_memory(compiler);    else {        stmt->type = type;        stmt->first_line = first_line;        stmt->last_line = last_line;    }    return stmt;}WsStatement *ws_stmt_block(WsCompiler *compiler, WsUInt32 fline,                           WsUInt32 lline, WsList *block){    WsStatement *stmt = stmt_alloc(compiler, WS_STMT_BLOCK, fline, lline);    if (stmt)        stmt->u.block = block;    return stmt;}WsStatement *ws_stmt_variable(WsCompilerPtr compiler, WsUInt32 line,                              WsList *variables){    WsStatement *stmt = stmt_alloc(compiler, WS_STMT_VARIABLE, line, line);    if (stmt)        stmt->u.var = variables;    return stmt;}WsStatement *ws_stmt_empty(WsCompiler *compiler, WsUInt32 line){    return stmt_alloc(compiler, WS_STMT_EMPTY, line, line);}WsStatement *ws_stmt_expr(WsCompiler *compiler, WsUInt32 line,                          WsExpression *expr){    WsStatement *stmt = stmt_alloc(compiler, WS_STMT_EXPR, line, line);    if (stmt)        stmt->u.expr = expr;    return stmt;}WsStatement *ws_stmt_if(WsCompiler *compiler, WsUInt32 line,                        WsExpression *expr, WsStatement *s_then,                        WsStatement *s_else){    WsStatement *stmt = stmt_alloc(compiler, WS_STMT_IF, line, line);    if (stmt) {        stmt->u.s_if.expr = expr;        stmt->u.s_if.s_then = s_then;        stmt->u.s_if.s_else = s_else;    }    return stmt;}WsStatement *ws_stmt_for(WsCompilerPtr compiler, WsUInt32 line, WsList *init,                         WsExpression *e1, WsExpression *e2, WsExpression *e3,                         WsStatement *stmt_body){    WsStatement *stmt = stmt_alloc(compiler, WS_STMT_FOR, line, line);    if (stmt) {        stmt->u.s_for.init = init;        stmt->u.s_for.e1 = e1;        stmt->u.s_for.e2 = e2;        stmt->u.s_for.e3 = e3;        stmt->u.s_for.stmt = stmt_body;    }    return stmt;}WsStatement *ws_stmt_while(WsCompiler *compiler, WsUInt32 line,                           WsExpression *expr, WsStatement *stmt_arg){    WsStatement *stmt = stmt_alloc(compiler, WS_STMT_WHILE, line, line);    if (stmt) {        stmt->u.s_while.expr = expr;        stmt->u.s_while.stmt = stmt_arg;    }    return stmt;}WsStatement *ws_stmt_continue(WsCompiler *compiler, WsUInt32 line){    return stmt_alloc(compiler, WS_STMT_CONTINUE, line, line);}WsStatement *ws_stmt_break(WsCompiler *compiler, WsUInt32 line){    return stmt_alloc(compiler, WS_STMT_BREAK, line, line);}WsStatement *ws_stmt_return(WsCompilerPtr compiler, WsUInt32 line,                            WsExpression *expr){    WsStatement *stmt = stmt_alloc(compiler, WS_STMT_RETURN, line, line);    if (stmt)        stmt->u.expr = expr;    return stmt;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?