⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pack.c

📁 CBS(小区广播)程序实现手稿
💻 C
📖 第 1 页 / 共 5 页
字号:
		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 + -