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); }
/* ================ 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; }