📄 pack.c
字号:
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
width=*(format+ScanPos[0])-'0';
for(ScanPos[0]++;*(format+ScanPos[0])>='0'&&(*(format+ScanPos[0])<='9');
ScanPos[0]++)
width=width*10+(*(format+ScanPos[0])-'0');
Token.Class=PACK_KEY_NUMBER;
Token.Value=width;
return Token;
case ',':
Token.Class=PACK_KEY_COMMA;
ScanPos[0]++;
return Token;
case 'D':
case 'd':
Token.Class=PACK_KEY_D;
ScanPos[0]++;
return Token;
case '[':
Token.Class=PACK_KEY_LEFTA;
ScanPos[0]++;
return Token;
case ']':
Token.Class=PACK_KEY_RIGHTA;
ScanPos[0]++;
return Token;
case '{':
Token.Class=PACK_KEY_LEFTB;
ScanPos[0]++;
return Token;
case '}':
Token.Class=PACK_KEY_RIGHTB;
ScanPos[0]++;
return Token;
case 'P':
case 'p':
Token.Class=PACK_KEY_P;
ScanPos[0]++;
return Token;
case 'C':
case 'c':
Token.Class=PACK_KEY_C;
ScanPos[0]++;
return Token;
case 'N':
case 'n':
Token.Class=PACK_KEY_N;
ScanPos[0]++;
return Token;
case '&':
Token.Class=PACK_KEY_ADDRESS;
ScanPos[0]++;
return Token;
//从ScanPos+1开始向右寻找'>'或串尾,
//使ScanPos指向>之后的字符
case '<':
Token.Value=ScanPos[0]+1;
for(ScanPos[0]++;*(format+ScanPos[0])!='>'&&(*(format+ScanPos[0])!='\0');)
ScanPos[0]++;
Token.Len=ScanPos[0]-Token.Value; //记录F类描述串的串长
Token.Class=PACK_KEY_FLATF;
ScanPos[0]++;
return Token;
case ' ':
break;
default:
Token.Class=PACK_KEY_BAD;
ScanPos[0]++;
return Token;
}
}
if(*(format+ScanPos[0])=='\0')
{
Token.Class=PACK_KEY_EOI;
return Token;
}
Token.Value=0;
return Token;
}
//*******************************************************************
// 读标签码函数 *
// 读入由[...]描述的标签码 *
//buf:缓冲区,format:描述串,p:各编程数据,finish[] 记录格式串位置 *
//ScanPos:描述串工作指针,BufPos:缓冲区工作指针 *
//返回值:标签码长度 ,失败:0 *
//*******************************************************************
int ReadHead(BYTE * buf,BYTE *format,int *ScanPos,int *BufPos,int p[],int finish[])
{
int flag;
unsigned int j,k;
BYTE i;
struct Token_t token,tokenf;
flag=0;k=0;
token=GetToken(format,ScanPos); //取第一个数
switch(token.Class) //置Class字段
{
case PACK_KEY_NUMBER: //如遇数字,直接填写前两比特
i=token.Value;
i<<=6;
*(buf+BufPos[0])=i;
break;
case PACK_KEY_D: //如遇D or d,则取编程数据填写
i=(BYTE)(*p++);
i<<=6;
*(buf+BufPos[0])=i;
break;
case PACK_KEY_COMMA: //如遇逗号填缺省类别码
flag=1;
*(buf+BufPos[0])=0;
break;
default:
return 0;
}
//取逗号,如不是逗号则出错
finish[0]=(int)p;
if(!flag) token=GetToken(format,ScanPos);
if(token.Class!=PACK_KEY_COMMA) return 0;
//取后一个数,置TagCode字段
//TagCode字段<0x10000000
token=GetToken(format,ScanPos);
tokenf=GetToken(format,ScanPos);
if(tokenf.Class==PACK_KEY_RIGHTA) //如标签码不以']'结束,则出错返0
{
if(token.Class==PACK_KEY_D) //判断后一个标识为'd''D'或数字
{ //并做相应处理
j=*p++; //记录TagCode
finish[0]=(int)p;
}
else j=token.Value;
//根据TagCode大小置TagCode字段
if(j<31) //分为五种情况
{
j<<=3;
j>>=3;
*(buf+BufPos[0])|=j;
BufPos[0]++;
BufPos[0]++; //指针前移,预留一个字节的长度字段
return 1;
}
//如标签码部分大于一个字节
//按TC格式要求七比特一组
//由高到低顺次填写
else if(j<128)
{
*(buf+BufPos[0])|=0x1f; //填写第一个字节
BufPos[0]++; //指针后移
j&=0x7f; //填写下一个字节
*(buf+BufPos[0])=j;
BufPos[0]++;
BufPos[0]++; //指针前移,预留一个字节的长度字段
return 2;
}
else if(j<0x4000) //以下填法与上类似
{
*(buf+BufPos[0])|=0x1f;
BufPos[0]++;
k=j;
j>>=7;
j&=0x7f;
j|=0x80;
*(buf+BufPos[0])=j;
BufPos[0]++;
k&=0x7f;
*(buf+BufPos[0])=k;
BufPos[0]++;
BufPos[0]++;
return 3;
}
else if(j<0x200000)
{
*(buf+BufPos[0])|=0x1f;
BufPos[0]++;
k=j;
j>>=14;
j&=0x7f;
j|=0x80;
*(buf+BufPos[0])=j;
BufPos[0]++;
j=k;
j>>=7;
j&=0x7f;
j|=0x80;
*(buf+BufPos[0])=j;
BufPos[0]++;
k&=0x7f;
*(buf+BufPos[0])=k;
BufPos[0]++;
BufPos[0]++;
return 4;
}
else
{
*(buf+BufPos[0])|=0x1f;
BufPos[0]++;
k=j;
j>>=21;
j&=0x7f;
j|=0x80;
*(buf+BufPos[0])=j;
BufPos[0]++;
j=k;
j>>=14;
j&=0x7f;
j|=0x80;
*(buf+BufPos[0])=j;
BufPos[0]++;
j=k;
j>>=7;
j&=0x7f;
j|=0x80;
*(buf+BufPos[0])=j;
BufPos[0]++;
k&=0x7f;
*(buf+BufPos[0])=k;
BufPos[0]++;
BufPos[0]++;
return 5;
}
}
else return 0;
}
//*******************************************************************
// 读叶子函数 *
//读入一个由<F类描述符>或n&p之类的描述符描述的叶子 *
//buf:缓冲区,format:描述串,p:各编程数据,finish[] 记录格式串位置 *
//ScanPos:描述串工作指针,BufPos:缓冲区工作指针 *
//FlagOfFBit:form比特描述符,token:传入一个标识 *
//返回值:体长度 ,失败:0 *
//*******************************************************************
int ReadLeaf(BYTE * buf,BYTE *format,int *ScanPos,int *BufPos,
struct Token_t token,int p[],int finish[],int *FlagOfFBit)
{
int width,ads;
int len;
//注意:本函数只处理一个F类描述符
// 一个P类描述符
// 一个C类描述符
if(token.Class==PACK_KEY_FLATF) //遇到一个F类描述符
{ //调用基本处理函数
len=SubCommonSubFlatPack(buf+BufPos[0],format+token.Value,token.Len,p,finish);
(int)p=finish[0];
BufPos[0]+=len;
*FlagOfFBit=0;
}
else //如不是F类描述符,处理P类,C类描述符
{
width=1;
ads=0; //如未取到所需的描述符
//则不断取值并进行记录
while(token.Class!=PACK_KEY_P&&(token.Class!=PACK_KEY_C)&&(token.Class!=PACK_KEY_EOI))
{
if(token.Class==PACK_KEY_N) width=*p++;
else if(token.Class==PACK_KEY_ADDRESS) ads=1;
else width=token.Value;
token=GetToken(format,ScanPos);
}
if(token.Class==PACK_KEY_EOI) return 0; //如描述符有错,返回零。否则,进行相应处理
else if(token.Class==PACK_KEY_P) //处理 P 类描述符
{
*FlagOfFBit=0; //标识本层打入的体为本原体
//如有指针描述符,则提取串地址进行串拷贝
if(ads) memcpy(buf+BufPos[0],(BYTE *)*p++,width);
//否则直接提取编程数据进行拷贝
else memcpy(buf+BufPos[0],(BYTE *)p++,width);
//工作指针移动相应的位置
BufPos[0]+=width;
}
else //处理 C 类描述符
{
*FlagOfFBit=1; //标识本层打入的体为结构体
//提取串地址进行串拷贝
memcpy(buf+BufPos[0],(BYTE*)*p++,width);
//工作指针移动相应的位置
BufPos[0]+=width;
}
len=width;
}
finish[0]=(int)p; //记录提取编程数据的当前位置
return len;
}
//***********************************************************************
// 填写长度字段函数 *
//填写长度字段,若长度小于127,就直接填写,若大于127,要把体向后挪若干字节*
//buf:缓冲区,SteamPtr:标签码起始地址 *
//LenOfHead:标签码长度,LenOfBody:体长度 *
//返回值:长度字段长度 *
//***********************************************************************
int FillLenField(BYTE * buf,int StreamPtr,int LenOfHead,int LenOfBody)
{
int i,k,j;
i=StreamPtr+LenOfHead; //计算体的开始地址
if(LenOfBody<128) //若体长<128,直接填写长度
{
*(buf+i)=(BYTE)(LenOfBody&0x7f);
return 1;
}
else if(LenOfBody<256) //若体长<256
{ //体先向后移1个字节
for(k=i+LenOfBody+1,j=k-1;j>i;k--,j--)
*(buf+k)=*(buf+j);
*(buf+i)=0x81; //再依TC格式填写长度
*(buf+i+1)=(BYTE)LenOfBody;
return 2;
}
else if(LenOfBody<0x10000) //若体长<0x10000
{ //体先向后移2个字节
for(k=i+LenOfBody+2,j=k-2;j>i;k--,j--)
*(buf+k)=*(buf+j);
*(buf+i)=0x82; //再依TC格式填写长度
*(buf+i+2)=(BYTE)LenOfBody;
*(buf+i+1)=(BYTE)(LenOfBody>>8);
return 3;
}
else if(LenOfBody<0x1000000) //若体长<0x10000000
{ //体先向后移3个字节
for(k=i+LenOfBody+3,j=k-3;j>i;k--,j--)
*(buf+k)=*(buf+j);
*(buf+i)=0x83; //再依TC格式填写长度
*(buf+i+3)=(BYTE)LenOfBody;
*(buf+i+2)=(BYTE)(LenOfBody>>8);
*(buf+i+1)=(BYTE)(LenOfBody>>16);
return 4;
}
else //体先向后移4个字节
{
for(k=i+LenOfBody+4,j=k-4;j>i;k--,j--)
*(buf+k)=*(buf+j);
*(buf+i)=0x84; //再依TC格式填写长度
*(buf+i+4)=(BYTE)LenOfBody;
*(buf+i+3)=(BYTE)(LenOfBody>>8);
*(buf+i+2)=(BYTE)(LenOfBody>>16);
*(buf+i+1)=(BYTE)(LenOfBody>>24);
return 5;
}
}
//*******************************
// 读森林函数 *
//依拒BNF范式,读入一个森林 *
//返回值:读入缓冲区的长度 *
//*******************************
int ReadForest(int p[])
{
int x;
int flagoffbit,i,j,k;
struct Token_t token;
tree_control1.ScanPos=0; //将输入描述符位移置零
//取描述串的标识 直至取完
for(token=GetToken(tree_control1.format,&tree_control1.ScanPos);token.Class!=PACK_KEY_EOI;
token=GetToken(tree_control1.format,&tree_control1.ScanPos))
{
//根据堆栈中记录的当前打包状态,进行下一步打包
switch(tree_control1.Env[(tree_control1.level)].State)
{
case 0: //期望同层子树的开始 [ 或本层结束 }
if(token.Class==PACK_KEY_LEFTA) //遇到同层树
{
//记录树的起始地址
L: tree_control1.Env[(tree_control1.level)].StreamPtr=tree_control1.BufPos;
//调用ReadHead函数,读入头标,记录头标长度
tree_control1.Env[(tree_control1.level)].TagLen=ReadHead(tree_control1.buf,
tree_control1.format,&tree_control1.ScanPos,
&tree_control1.BufPos,p,&x);
(int)p=x; //调整编程数据指针
//为长度指示语预留一个字节
tree_control1.Env[(tree_control1.level)].LenLen=1;
//状态转入1,即期望收到一个{
tree_control1.Env[(tree_control1.level)].State=1;
}
//遇到本层结束
else if(token.Class==PACK_KEY_RIGHTB)
{ //顶层不能结束,不理睬,记错一次
if(!tree_control1.level) tree_control1.ErrCount++;
else
{
tree_control1.level--; //回退一层
//求出子树总长度
i=tree_control1.BufPos-
tree_control1.Env[(tree_control1.level)].StreamPtr;
//从中减去标签码长度,长度字段长度,得体长
k=i-tree_control1.Env[(tree_control1.level)].TagLen-
tree_control1.Env[(tree_control1.level)].LenLen;
//填写体长
tree_control1.Env[(tree_control1.level)].BodyLen=k;
j=tree_control1.Env[(tree_control1.level)].TagLen;
//调用FillLenField填写长度字段
tree_control1.Env[(tree_control1.level)].LenLen=
FillLenField(tree_control1.buf,
tree_control1.Env[(tree_control1.level)].StreamPtr,j,k);
//调整当前工作指针
if(tree_control1.Env[(tree_control1.level)].LenLen!=1)
tree_control1.BufPos+=tree_control1.Env[(tree_control1.level)].LenLen-1;
//置标签码的F比特为1,表示复合体
*(tree_control1.buf+tree_control1.Env[(tree_control1.level)].StreamPtr)|=0x20;
//期望同层子树或本层结束
tree_control1.Env[(tree_control1.level)].State=0;
}
}
//遇到一个不期望的输入,记错一次
else tree_control1.ErrCount++;
break;
case 1: //期望体的开始符{
//遇到一个不期望的输入,记错一次
if(token.Class!=PACK_KEY_LEFTB) tree_control1.ErrCount++;
//状态转入2
//即期望受到一个叶子或子树
tree_control1.Env[(tree_control1.level)].State=2;
break;
case 2: //期望一个叶子或子树
if(token.Class==PACK_KEY_LEFTA) //遇到下一层子树
{
tree_control1.level++; //层数计数器加一
/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -