void runClock() { unsigned long now = millis(); unsigned long dt = now - getVar(v_epoch); if (dt < 1000) return; // nothing to see while (dt >= 1000) { // tally the full seconds dt -= 1000; incVar(v_second); if (getValue("onsecond") >= 0) doCommand("onsecond"); while (getVar(v_second) >= 60) { assignVar(v_second, getVar(v_second) - 60); incVar(v_minute); if (getValue("onminute") >= 0) doCommand("onminute"); while (getVar(v_minute) >= 60) { assignVar(v_minute, getVar(v_minute) - 60); incVar(v_hour); if (getValue("onhour") >= 0) doCommand("onhour"); while (getVar(v_hour) >= 24) { incVar(v_day); if (getValue("onday") >= 0) doCommand("onday"); assignVar(v_hour, getVar(v_hour) - 24); } } } } assignVar(v_epoch, now - dt); // put back remainder }
void continue_break_begin(TknKind stmnt) /* CB開始処理 */ { incVar(&loopNest_ct, LOOP_SIZ, "制御文ネストが%d回を超えました。"); loopNest[loopNest_ct].stkind = stmnt; /* 文の種類 */ loopNest[loopNest_ct].looptop = nextCodeCt(); /* 先頭番地 */ loopNest[loopNest_ct].break_flg = FALSE; /* break文有無管理 */ }
static bool increments (/*@observer@*/ constraint c, /*@observer@*/ constraintExpr var) { llassert (constraint_isDefined (c) ); if (constraint_isUndefined (c) ) { return FALSE; } llassert (incVar (c)); if (constraintExpr_similar (c->lexpr, var) ) return TRUE; else return FALSE; }
void swch_begin(void) /* switch文の開始 */ { incVar(&swchNest_ct, SWTCH_SIZ, "switchネストが%d回を超えました。"); swchNest[swchNest_ct].def_adrs = -1; /* default番地未設定 */ swchNest[swchNest_ct].startCaseList = caseList_ct+1; }
/* この関数内のラベル処理(飛先処理)の明快さのために以下のマクロを使用する */ #define UPLABEL(pos) pos=nextCodeCt() /* 上ジャンプ用ラベル機能 */ #define JMP_UP(pos) gencode2(JMP,pos) /* JMPでUPLABELへ */ #define JPT_UP(pos) gencode2(JPT,pos) /* JPTでUPLABELへ */ #define JMP_DOWN(pos) pos=gencode2(JMP,0) /* JMPでDWNLABELへ */ #define JPF_DOWN(pos) pos=gencode2(JPF,0) /* JPFでDWNLABELへ */ #define DWNLABEL(pos) backPatch(pos,nextCodeCt()) /* 下ジャンプ用ラベル機能 */ void statement(void) /* 文の処理 */ { TknKind kd; SymTbl *tp; DtType ret_typ = fncPt->dtTyp; int i, val; int LB_TOP, LB_EXP2, LB_EXP3, LB_BODY, LB_ELSE, LB_END, LB_TBL; kd = token.kind; if (kd==While || kd==Do || kd==Switch) continue_break_begin(kd); switch (kd) { case Break: if (loopNest_ct == 0) err_s("不正なbreak"); else { gencode2(JMP, NO_FIX_BREAK_ADRS); /* 該当末尾位置へ */ loopNest[loopNest_ct].break_flg = TRUE; /* breakありを記憶 */ } token = chk_nextTkn(nextTkn(), ';'); /* ; のはず */ break; case Continue: gencode2(JMP, get_loopTop()); /* ループ開始行へジャンプ */ token = chk_nextTkn(nextTkn(), ';'); /* ; のはず */ break; case Case: token = nextTkn(); get_const(NULL); /* 定数判定準備 */ expr_with_chk(0, ':'); /* [式]の処理 */ if (!get_const(&val)) err_s("case式が定数式でない"); else if (swchNest_ct == 0) err_s("対応するswitch文がない"); else { for (i=swchNest[swchNest_ct].startCaseList; i<=caseList_ct; i++) { if (caseList[i].value == val) { err_s("case式の値が重複している"); break; } } incVar(&caseList_ct, CASE_SIZ, "case句が%d個を超えました。"); caseList[caseList_ct].value = val; /* case値設定 */ caseList[caseList_ct].adrs = nextCodeCt(); /* 対応番地設定 */ } statement(); /* 文の処理 */ break; case Default: if (swchNest_ct == 0) err_s("対応するswitch文がない"); else if (swchNest[swchNest_ct].def_adrs != -1) err_s("defaultが重複している"); else swchNest[swchNest_ct].def_adrs = nextCodeCt(); /* 番地設定 */ token = chk_nextTkn(nextTkn(), ':'); /* : のはず */ statement(); /* 文の処理 */ break; case For: /*[式1]*/ token = chk_nextTkn(nextTkn(), '('); /* ( のはず */ if (token.kind == ';') token = nextTkn(); /* 式1なし */ else { expr_with_chk(0, ';'); /* [式1]の処理 */ remove_val(); /* 式値不要 */ } /*[式2]*/ UPLABEL(LB_EXP2); /* ←┐ */ if (token.kind == ';') { /* │式2なし */ gencode2(LDI, 1); /* │真(1)にする */ token = nextTkn(); /* │ */ } else { /* │ */ expr_with_chk(0, ';'); /* │[式2]の処理 */ } /* │ */ JPF_DOWN(LB_END); /* ─┼┐ false時 */ JMP_DOWN(LB_BODY); /* ─┼┼┐true時 */ /* │││ */ /*[式3]*/ /* │││ */ continue_break_begin(kd); /* │││ */ UPLABEL(LB_EXP3); /* ←┼┼┼┐ */ if (token.kind == ')') /* ││││ */ token = nextTkn(); /* ││││式3なし */ else { /* ││││ */ expr_with_chk(0, ')'); /* ││││[式3]の処理 */ remove_val(); /* ││││式値不要 */ } /* ││││ */ JMP_UP(LB_EXP2); /* ─┘│││ */ /* │││ */ /*[本体]*/ /* │││ */ DWNLABEL(LB_BODY); /* ←─┼┘│ */ statement(); /* │ │[文]の処理 */ JMP_UP(LB_EXP3); /* ──┼─┘繰り返し */ /* │ */ /*[末尾]*/ /* │ */ DWNLABEL(LB_END); /* ←─┘終端 */ break; case If: token = nextTkn(); expr_with_chk('(', ')'); /* [式]の処理 */ JPF_DOWN(LB_ELSE); /* ─┐ false時 */ statement(); /* │ [文1]の処理 */ if (token.kind != Else) { /* │ */ DWNLABEL(LB_ELSE); /* ←┘elseない時の終端 */ break; /* │ */ } /* │elseある時 */ JMP_DOWN(LB_END); /* ─┼┐ */ DWNLABEL(LB_ELSE); /* ←┘│ */ token = nextTkn(); /* │ */ statement(); /* │[文2]の処理 */ DWNLABEL(LB_END); /* ←─┘ */ break; case While: token = nextTkn(); UPLABEL(LB_TOP); /* ←┐ */ expr_with_chk('(', ')'); /* │ [式]の処理 */ JPF_DOWN(LB_END); /* ─┼┐false時 */ statement(); /* ││[文]の処理 */ JMP_UP(LB_TOP); /* ─┘│繰り返し */ DWNLABEL(LB_END); /* ←─┘ */ break; case Do: token = nextTkn(); UPLABEL(LB_TOP); /* ←┐ */ statement(); /* │[文]の処理 */ if (token.kind == While) { /* │ */ token = nextTkn(); /* │ */ expr_with_chk('(', ')'); /* │[式]の処理 */ token = chk_nextTkn(token, ';'); /* │; のはず */ JPT_UP(LB_TOP); /* ─┘true時 */ } else { err_s("do終端のwhileがない"); } break; case Switch: token = nextTkn(); expr_with_chk('(', ')'); /* [式]の処理 */ JMP_DOWN(LB_TBL); /* ─┐ テーブル処理へ */ swch_begin(); /* │ */ statement(); /* case,default文の処理. */ JMP_DOWN(LB_END); /* ─┼┐末尾へ */ DWNLABEL(LB_TBL); /* ←┘│ */ swch_end(); /* │テーブル処理 */ DWNLABEL(LB_END); /* ←─┘ */ break; case Return: token = nextTkn(); if (token.kind == ';') { /* 戻値なし */ if (ret_typ != VOID_T) err_s("return文に戻り値がない"); } else { /* 戻値あり */ expression(); /* 戻値作成 */ if (ret_typ == VOID_T) err_s("void型関数に値を返すreturn文がある"); } gencode2(JMP, NO_FIX_RET_ADRS); /* 関数出口処理へ */ token = chk_nextTkn(token, ';'); /* ; のはず */ break; case Printf: case Exit: /* void型組込関数 */ sys_fncCall(kd); token = chk_nextTkn(token, ';'); /* printf() + b; を防止 */ break; case Input: /* 非void型組込関数 */ expr_with_chk(0, ';'); /* 通常の式解析 */ remove_val(); /* 式値不要 */ break; case Incre: case Decre: /* ++var --var */ expr_with_chk(0, ';'); remove_val(); /* 式値不要 */ break; case Ident: /* 識別子(関数か変数) */ tp = search(token.text); /* 記号表位置 */ if ((tp->nmKind==fncId || tp->nmKind==protId) && tp->dtTyp==VOID_T) { fncCall(tp); /* void型関数はここで処理 */ token = chk_nextTkn(token, ';'); /* ; のはず */ } else { expr_with_chk(0, ';'); /* 通常の式解析 */ remove_val(); /* 式値不要 */ } break; case Lbrace: /* 複合文{} */ block(0); /* 0:非関数ブロック */ break; case Semicolon: /* 空文,forの実行文等で出現 */ token = nextTkn(); break; case EofTkn: /* 最後の } を忘れた場合などに発生 */ err_s("意図しない終了。'}'不足? "); exit(1); default: err_ss("不正な記述", token.text); token = nextTkn(); } if (kd==For || kd==While || kd==Do || kd==Switch) continue_break_end(); }