Exemple #1
0
void read_PEP_file(char *filename, char **types,
		   t_blockinfo *blocks, t_blockdest *dest)
{
	FILE *infile;
	t_lookup *tbl;
	t_fieldinfo *fld;
	t_dest *dst;
	t_blockdest *sdest = dest;
	int i, len = 0, ch, num, num2, ralloc;
	char *restptr, *rtmp;

	HLinput_file = filename;
	HLinput_line = 1;

	/* Open the file, read the header. */
	if (!(infile = fopen(filename, "r")))
		nc_error("could not open file for reading");

	ReadCmdToken(infile);
	if (strcmp(sbuf, "PEP")) nc_error("keyword `PEP' expected");

	/* Check if the file's type (second line of file) is one of those
	   that are allowed. */
	ReadNewline(infile);
	ReadCmdToken(infile);
	for (; *types && strcmp(sbuf,*types); types++);
	if (!*types) nc_error("unexpected format identifier '%s'",sbuf);
	filetype = MYstrdup(sbuf);

	ReadNewline(infile);
	ReadCmdToken(infile);
	if (strncmp(sbuf, "FORMAT_N", 8))
		nc_error("keyword 'FORMAT_N' or 'FORMAT_N2' expected");

	tbl = (t_lookup*) MYmalloc(sizeof(t_lookup)*(128-' ')) - ' ';
	ReadNewline(infile);

	while (!feof(infile))
	{
		/* Read next block id. */
		ReadCmdToken(infile);

		blocktype = MYstrdup(sbuf);

		/* Identify block. */
		for (; blocks->name && strcmp(blocks->name,sbuf); blocks++)
		    if (!blocks->optional)
			nc_error("keyword '%s' expected",blocks->name);

		if (!blocks->name) nc_error("unknown keyword '%s'",sbuf);

		for (dest = sdest; dest->name; dest++)
			if (!strcmp(blocks->name,dest->name)) break;

		/* Set up tbl. */
		for (i=' '; i<128; tbl[i++].type = 0);
		for (i=' '; i<128; tbl[i++].ptr = NULL);

		for (fld = blocks->field; fld->c; fld++)
			tbl[(int)fld->c].type = fld->type;

		if (!blocks->line) ReadNewline(infile);

		/* Read lines until next block begins. Every line yields one
		   new entity of the type determined by the current block. */
		for(;;)
		{
		    if (isupper(ch = ReadCharComment(infile)))
		    {
			char ch2 = getc(infile);
			ungetc(ch2,infile);
			/* We assume that uppercase letters at the start of
			   a line always indicates a new block. */
			if (isupper((int)ch2)) break;
		    }

		    if (feof(infile)) break;
		    if (ch == '\n') continue;

		    *(rtmp = restptr = MYmalloc(ralloc = 64)) = '\0';

		    /* If information about this block is wanted, take
		       the information where to store data from dest. */
		    if (dest->name)
			for (dst = dest->destarray; dst->c; dst++)
			{
			    t_lookup *l = tbl + dst->c;
			    l->ptr = dst->ptr;
			    switch(l->type)
			    {
				case FT_STRING:
				case FT_COORDS:
					*(char**)(l->ptr) = NULL;
					break;
				case FT_NUMBER:
				case FT_FLAG:
					*(int*)(l->ptr) = 0;
					break;
				default:
					nc_error("internal error: don't "
					"know the type of field '%c'",dst->c);
				break;
			    }
			}

		    /* Parse until end of line. We assume that all information
		       about an entity (place, transition etc.) is stored in
		       one single line. */
		    while (ch != '\n')
		    {
			if (isdigit(ch) || ch == '-')
			{
				/* Numbers are treated specially.
				   x@y gets stored in the '@' field, and
				   plain numbers are stored in the '0' field. */
				ungetc(ch,infile);
				ReadNumber(infile,&num);
				if ((ch=ReadWhiteSpace(infile)) == '@'
						  || ch == '<' || ch == '>')
				{
					ch = '@';
					ReadNumber(infile,&num2);
					len = 24;
				}
				else
				{
					ungetc(ch,infile);
					ch = '0';
					len = 12;
				}
			}
			else
			{
				if (ch == '\'' || ch == '"') ungetc(ch,infile);
				switch(tbl[ch].type)
				{
				    case FT_STRING:
					ReadEnclString(infile);
					len = 3+strlen(sbuf);
					break;
				    case FT_NUMBER:
					ReadNumber(infile,&num);
					len = 12;
					break;
				    case FT_COORDS:
					ReadCoordinates(infile, &num, &num2);
					len = 24;
					break;
				    case FT_FLAG:
					len = 1;
					break;
				    default:
					nc_error("unknown token '%c'",ch);
					break;
				}
			}

			/* Store data in the memory locations specified by
			   the dest array. If no location is given for a
			   particular field, its contents are written to
			   a 'rest' string. */
			while (!tbl[ch].ptr && rtmp-restptr+len >= ralloc)
			{
				restptr = MYrealloc(restptr, ralloc += 64);
				rtmp = restptr + strlen(restptr);
			}
			switch(tbl[ch].type)
			{
			    case FT_STRING:
				if (tbl[ch].ptr)
					*(char**)(tbl[ch].ptr) = MYstrdup(sbuf);
				else if (strchr("'\"",ch))
					sprintf(rtmp,"\"%s\"",sbuf);
				else
					sprintf(rtmp,"%c\"%s\"",ch,sbuf);
				break;
			    case FT_NUMBER:
				if (tbl[ch].ptr)
					*(int*)(tbl[ch].ptr) = num;
				else if (ch == '0')
					sprintf(rtmp,"%d ",num);
				else
					sprintf(rtmp,"%c%d",ch,num);
				break;
			    case FT_COORDS:
				if (tbl[ch].ptr)
				{
				    *((t_coords**)(tbl[ch].ptr)) =
						MYmalloc(sizeof(t_coords));
				    (*(t_coords**)(tbl[ch].ptr))->x = num;
				    (*(t_coords**)(tbl[ch].ptr))->y = num2;
				}
				else if (ch == '@')
					sprintf(rtmp,"%d@%d ",num,num2);
				else
					sprintf(rtmp,"%c%d@%d",ch,num,num2);
				break;
			    case FT_FLAG:
				if (tbl[ch].ptr)
					(*(int*)(tbl[ch].ptr))++;
				else
					sprintf(rtmp,"%c",ch);
				break;
			}
			if (!tbl[ch].ptr) rtmp += strlen(rtmp);
			ch = ReadCharComment(infile);
		    } /* end of while */

		    /* When the whole line has been read, see if information
		       about the current block is wanted - if so, call the
		       corresponding hook function. */
		    if (dest->name)
		    {
			if (dest->restptr) *(dest->restptr) = restptr;
			if (dest->hookfunc()) nc_error("read aborted");
		    }
		    else
			free(restptr);

		    HLinput_line++;
		}

		free(blocktype);
		if (!feof(infile)) ungetc(ch,infile);
		blocks++;
	}

	/* Check for mandatory blocks that didn't occur in the file. */
	for (; blocks->name; blocks++)
	    if (!blocks->optional)
		nc_error("section '%s' not found",blocks->name);

	free(tbl+' ');
	fclose(infile);
}
Exemple #2
0
/*
================
idLexer::ReadPunctuation
================
*/
int idLexer::ReadPunctuation( idToken *token ) {
	int l, n, i;
	char *p;
	const punctuation_t *punc;

#ifdef PUNCTABLE
	for (n = idLexer::punctuationtable[(unsigned int)*(idLexer::script_p)]; n >= 0; n = idLexer::nextpunctuation[n])
	{
		punc = &(idLexer::punctuations[n]);
#else
//	int i;

	for (i = 0; idLexer::punctuations[i].p; i++) {
		punc = &idLexer::punctuations[i];
#endif
		p = punc->p;
		// check for this punctuation in the script
		for ( l = 0; p[l] && idLexer::script_p[l]; l++ ) {
			if ( idLexer::script_p[l] != p[l] ) {
				break;
			}
		}
		if ( !p[l] ) {
			//
			token->EnsureAlloced( l+1, false );
			for ( i = 0; i <= l; i++ ) {
				token->data[i] = p[i];
			}
			token->len = l;
			//
			idLexer::script_p += l;
			token->type = TT_PUNCTUATION;
			// sub type is the punctuation id
			token->subtype = punc->n;
			token->flags = 0;
			return 1;
		}
	}
	return 0;
}

/*
================
idLexer::ReadToken
================
*/
int idLexer::ReadToken( idToken *token ) {
	int c;

	if ( !loaded ) {
		idLib::common->Error( "idLexer::ReadToken: no file loaded" );
		return 0;
	}

	// if there is a token available (from unreadToken)
	if ( tokenavailable ) {
		tokenavailable = 0;
		*token = idLexer::token;
		return 1;
	}
	// save script pointer
	lastScript_p = script_p;
	// save line counter
	lastline = line;
	// clear the token stuff
	token->data[0] = '\0';
	token->len = 0;
	// start of the white space
	whiteSpaceStart_p = script_p;
	token->whiteSpaceStart_p = script_p;
	// read white space before token
	if ( !ReadWhiteSpace() ) {
		return 0;
	}
	// end of the white space
	idLexer::whiteSpaceEnd_p = script_p;
	token->whiteSpaceEnd_p = script_p;
	// line the token is on
	token->line = line;
	// number of lines crossed before token
	token->linesCrossed = line - lastline;
	// clear token flags
	token->flags = 0;

	c = *idLexer::script_p;

	// if we're keeping everything as whitespace deliminated strings
	if ( idLexer::flags & LEXFL_ONLYSTRINGS ) {
		// if there is a leading quote
		if ( c == '\"' || c == '\'' ) {
			if (!idLexer::ReadString( token, c )) {
				return 0;
			}
		} else if ( !idLexer::ReadName( token ) ) {
			return 0;
		}
	}
	// if there is a number
	else if ( (c >= '0' && c <= '9') ||
			(c == '.' && (*(idLexer::script_p + 1) >= '0' && *(idLexer::script_p + 1) <= '9')) ) {
		if ( !idLexer::ReadNumber( token ) ) {
			return 0;
		}
		// if names are allowed to start with a number
		if ( idLexer::flags & LEXFL_ALLOWNUMBERNAMES ) {
			c = *idLexer::script_p;
			if ( (c >= 'a' && c <= 'z') ||	(c >= 'A' && c <= 'Z') || c == '_' ) {
				if ( !idLexer::ReadName( token ) ) {
					return 0;
				}
			}
		}
	}
	// if there is a leading quote
	else if ( c == '\"' || c == '\'' ) {
		if (!idLexer::ReadString( token, c )) {
			return 0;
		}
	}
	// if there is a name
	else if ( (c >= 'a' && c <= 'z') ||	(c >= 'A' && c <= 'Z') || c == '_' ) {
		if ( !idLexer::ReadName( token ) ) {
			return 0;
		}
	}
	// names may also start with a slash when pathnames are allowed
	else if ( ( idLexer::flags & LEXFL_ALLOWPATHNAMES ) && ( (c == '/' || c == '\\') || c == '.' ) ) {
		if ( !idLexer::ReadName( token ) ) {
			return 0;
		}
	}
	// check for punctuations
	else if ( !idLexer::ReadPunctuation( token ) ) {
		idLexer::Error( "unknown punctuation %c", c );
		return 0;
	}
	// succesfully read a token
	return 1;
}