void HuffmanDecoder::Initialize(const unsigned int *codeBits, unsigned int nCodes) { // the Huffman codes are represented in 3 ways in this code: // // 1. most significant code bit (i.e. top of code tree) in the least significant bit position // 2. most significant code bit (i.e. top of code tree) in the most significant bit position // 3. most significant code bit (i.e. top of code tree) in n-th least significant bit position, // where n is the maximum code length for this code tree // // (1) is the way the codes come in from the deflate stream // (2) is used to sort codes so they can be binary searched // (3) is used in this function to compute codes from code lengths // // a code in representation (2) is called "normalized" here // The BitReverse() function is used to convert between (1) and (2) // The NormalizeCode() function is used to convert from (3) to (2) if (nCodes == 0) throw Err("null code"); m_maxCodeBits = *std::max_element(codeBits, codeBits+nCodes); if (m_maxCodeBits > MAX_CODE_BITS) throw Err("code length exceeds maximum"); if (m_maxCodeBits == 0) throw Err("null code"); // count number of codes of each length SecBlockWithHint<unsigned int, 15+1> blCount(m_maxCodeBits+1); std::fill(blCount.begin(), blCount.end(), 0); unsigned int i; for (i=0; i<nCodes; i++) blCount[codeBits[i]]++; // compute the starting code of each length code_t code = 0; SecBlockWithHint<code_t, 15+1> nextCode(m_maxCodeBits+1); nextCode[1] = 0; for (i=2; i<=m_maxCodeBits; i++) { // compute this while checking for overflow: code = (code + blCount[i-1]) << 1 if (code > code + blCount[i-1]) throw Err("codes oversubscribed"); code += blCount[i-1]; if (code > (code << 1)) throw Err("codes oversubscribed"); code <<= 1; nextCode[i] = code; } if (code > (1 << m_maxCodeBits) - blCount[m_maxCodeBits]) throw Err("codes oversubscribed"); else if (m_maxCodeBits != 1 && code < (1 << m_maxCodeBits) - blCount[m_maxCodeBits]) throw Err("codes incomplete"); // compute a vector of <code, length, value> triples sorted by code m_codeToValue.resize(nCodes - blCount[0]); unsigned int j=0; for (i=0; i<nCodes; i++) { unsigned int len = codeBits[i]; if (len != 0) { code = NormalizeCode(nextCode[len]++, len); m_codeToValue[j].code = code; m_codeToValue[j].len = len; m_codeToValue[j].value = i; j++; } } std::sort(m_codeToValue.begin(), m_codeToValue.end()); // initialize the decoding cache m_cacheBits = STDMIN(9U, m_maxCodeBits); m_cacheMask = (1 << m_cacheBits) - 1; m_normalizedCacheMask = NormalizeCode(m_cacheMask, m_cacheBits); CRYPTOPP_ASSERT(m_normalizedCacheMask == BitReverse(m_cacheMask)); if (m_cache.size() != size_t(1) << m_cacheBits) m_cache.resize(1 << m_cacheBits); for (i=0; i<m_cache.size(); i++) m_cache[i].type = 0; }
void statement() /* 문 */ { CodeSet save; int top_line, end_line, varAdrs; double wkVal, endDt, stepDt; if (Pc>maxLine || exit_Flg) return; /* 프로그램 종료 */ code = save = firstCode(Pc); top_line = Pc; end_line = code.jmpAdrs; /* 제어 범위의 시작과 끝 */ if (code.kind == If ) end_line = endline_of_If(Pc); /* if문일 때의 끝 */ switch (code.kind) { case If: // if if (get_expression(If, 0)) { /* 참(TRUE)이면 */ ++Pc; block(); Pc = end_line + 1; /* 실행하고 */ return; /* 종료 */ } Pc = save.jmpAdrs; /* 다음으로 */ // elif while (lookCode(Pc) == Elif) { save = firstCode(Pc); code = nextCode(); if (get_expression()) { /* 참(TRUE)이면 */ ++Pc; block(); Pc = end_line + 1; /* 실행하고 */ return; /* 종료 */ } Pc = save.jmpAdrs; /* 다음으로 */ } // else if (lookCode(Pc) == Else) { /* else를 */ ++Pc; block(); Pc = end_line + 1; /* 실행하고 */ return; /* 종료 */ } // end ++Pc; break; case While: for (;;) { /* */ if (!get_expression(While, 0)) break; /* false 종료 */ ++Pc; block(); /* [실행] */ if (break_Flg || return_Flg || exit_Flg) { /* */ break_Flg = false; break; /* 중단 */ } /* */ Pc = top_line; code = firstCode(Pc); /* 맨 앞으로 */ } /* */ Pc = end_line + 1; /* */ break; case For: /* for 제어변수, 초깃값, 최종값, 증분식 */ save = nextCode(); varAdrs = get_memAdrs(save); /* 제이변수 주소 구하기 */ expression('=', 0); /* 초깃값 */ set_dtTyp(save, DBL_T); /* 형 확정 */ Dmem.set(varAdrs, stk.pop()); /* 초깃값을 설정 */ endDt = get_expression(To, 0); /* 최종값을 보존 */ /* 증분값을 보존 */ if (code.kind == Step) stepDt = get_expression(Step, 0); else stepDt = 1.0; for (;; Pc=top_line) { /* */ if (stepDt >= 0) { /* 증가 루프 */ if (Dmem.get(varAdrs) > endDt) break; /* 거짓이면 종료 */ } else { /* 감소 루프 */ if (Dmem.get(varAdrs) < endDt) break; /* 거짓이면 종료 */ } /* */ ++Pc; block(); /* [ 실행 ] */ if (break_Flg || return_Flg || exit_Flg) { /* */ break_Flg = false; break; /* 중단 */ } /* */ Dmem.add(varAdrs, stepDt); /* 값 갱신 */ } /* */ Pc = end_line + 1; /* */ break; case Fcall: /* 대입이 없는 함수 호출 */ fncCall(code.symNbr); (void)stk.pop(); /* 반환 값 불필요 */ ++Pc; break; case Func: /* 함수 정의는 건너뀜 */ Pc = end_line + 1; break; case Print: case Println: sysFncExec(code.kind); ++Pc; break; case Gvar: case Lvar: /* 대입문 */ varAdrs = get_memAdrs(code); expression('=', 0); set_dtTyp(save, DBL_T); /* 대입할 때 형 확정*/ Dmem.set(varAdrs, stk.pop()); ++Pc; break; case Return: wkVal = returnValue; code = nextCode(); if (code.kind!='?' && code.kind!=EofLine) /* '식'이 있으면 반환 값을 계산 */ wkVal = get_expression(); post_if_set(return_Flg); /* ?가 있으면 처리 */ if (return_Flg) returnValue = wkVal; if (!return_Flg) ++Pc; break; case Break: code = nextCode(); post_if_set(break_Flg); /* ? 가 있으면 처리 */ if (!break_Flg) ++Pc; break; case Exit: code = nextCode(); exit_Flg = true; break; case Option: case Var: case EofLine: /* 실행 시는 무시 */ ++Pc; break; default: err_exit("잘못된 기술입니다: ", kind_to_s(code.kind)); } }
void statement() /* 文のコンパイル */ { int tIndex; KindT k; int backP, backP2,backP3; /* バックパッチ用 */ while(1) { switch (token.kind) { case Id: /* 代入文のコンパイル */ tIndex = searchT(token.u.id, varId); /* 左辺の変数のインデックス */ setIdKind(k=kindT(tIndex)); /* 印字のための情報のセット */ if (k != varId && k != parId) /* 変数名かパラメタ名のはず */ errorType("var/par"); token = checkGet(nextToken(), Assign); /* ":="のはず */ expression(); /* 式のコンパイル */ genCodeT(sto, tIndex); /* 左辺への代入命令 */ return; case If: /* if文のコンパイル */ token = nextToken(); condition(); /* 条件式のコンパイル */ token = checkGet(token, Then); /* "then"のはず */ backP = genCodeV(jpc, 0); /* jpc命令 */ statement(); /* 文のコンパイル */ /*-------------*/ token = checkGet(token,Else); backP2 = genCodeV(jmp,0); backP3 = nextCode(); statement(); /*変更部分*/ backChange(backP,backP3); backPatch(backP2);/* 上のjmp命令にバックパッチ */ return; /*-------------------- 変更部分 ----------------------*/ case Do: token = nextToken(); /**/ backP2 = nextCode(); /*while分のconditionが真だった時の飛び先*/ statement(); /*文のコンパイル*/ token = checkGet(nextToken(),While);/*"while"の筈*/ condition(); backP = genCodeV(jpc,0); /*偽の時飛び出すjpc命令*/ genCodeV(jmp,backP2); backPatch(backP); return; case Repeat: token = nextToken(); backP2 = nextCode(); statement(); token = checkGet(nextToken(),Until);/*untilの筈*/ condition(); genCodeV(jpc,backP2); backP = genCodeV(jmp,0); backPatch(backP); return; case Ret: /* return文のコンパイル */ token = nextToken(); expression(); /* 式のコンパイル */ genCodeR(); /* ret命令 */ return; case Begin: /* begin . . end文のコンパイル */ token = nextToken(); while(1){ statement(); /* 文のコンパイル */ while(1){ if (token.kind==Semicolon){ /* 次が";"なら文が続く */ token = nextToken(); break; } if (token.kind==End){ /* 次がendなら終り */ token = nextToken(); return; } if (isStBeginKey(token)){ /* 次が文の先頭記号なら */ errorInsert(Semicolon); /* ";"を忘れたことにする */ break; } errorDelete(); /* それ以外ならエラーとして読み捨てる */ token = nextToken(); } } case While: /* while文のコンパイル */ token = nextToken(); backP2 = nextCode(); /* while文の最後のjmp命令の飛び先 */ condition(); /* 条件式のコンパイル */ token = checkGet(token, Do); /* "do"のはず */ backP = genCodeV(jpc, 0); /* 条件式が偽のとき飛び出すjpc命令 */ statement(); /* 文のコンパイル */ genCodeV(jmp, backP2); /* while文の先頭へのジャンプ命令 */ backPatch(backP); /* 偽のとき飛び出すjpc命令へのバックパッチ */ return; case Write: /* write文のコンパイル */ token = nextToken(); expression(); /* 式のコンパイル */ genCodeO(wrt); /* その値を出力するwrt命令 */ return; case WriteLn: /* writeln文のコンパイル */ token = nextToken(); genCodeO(wrl); /* 改行を出力するwrl命令 */ return; case End: case Semicolon: /* 空文を読んだことにして終り */ return; default: /* 文の先頭のキーまで読み捨てる */ errorDelete(); /* 今読んだトークンを読み捨てる */ token = nextToken(); continue; } } }