Пример #1
0
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;
}
Пример #2
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));
  }
}
Пример #3
0
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;
		}		
	}
}