/* * ALESSANDRO: copy and paste of ReadCmdToken that sets sbuf to NULL instead of aborting * is something goes wrong. I know this is a terrible practice but I need this done the day * before yesterday =) */ void ReadToken (FILE *file){ register int len = 0; char *string = sbuf; if (!string) sbuf = string = gl_malloc (sballoc = 512); if (!isalnum((int)(*string++ = ReadCharComment(file)))){ sbuf=NULL; return; } len++; while (isalnum((int)(*string = getc(file))) || *string == '_') { string++; len++; if (len >= sballoc) { sbuf = gl_realloc (sbuf,sballoc += 512); string = sbuf + len; } } ungetc(*string, file); *string = '\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); }