Exemplo n.º 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);
}
Exemplo n.º 2
0
// Reads the scene file and stores the information as PolygonGroup and Polygon structures
bool ReadSceneFile(void) 
{
	FILE *SceneFile;				// File pointer for the scene file
	PolygonGroup *Head = NULL;		// Head of the linked list of polygon groups
	int nPolygons = 0;				// Number of polygons read from the scene file
	Coordinate MaxCoordinates;		// The maximum coordinates observed in the scene

	// Attempt to open the scene file
	if (fopen_s(&SceneFile, SceneFilename, "r") != 0) {
		printf("Could not open scene file '%s'\n", SceneFilename);
		return false;
	}
	else {
		// Flags used whilst reading scene file data
		bool EndOfFile;
		bool ReadingParameters;
		bool SuccessfulRead;
		bool FirstGroup;
		
		char *Buffer;				// Text buffer for reading strings from the scene file
		char *Context = NULL;		// Used for getting tokens from the buffer string
		char *Parameter;			// Stores the identifier letter at the start of each scene file string
		char *Comment;				// Used in removing comments from strings
		int LineCount;					// Used for monitoring the position of errors in the scene file
		Coordinate CoordinateBuffer;	// Stores coordinates read from the buffer
		Coordinate Offset;						// Stores the current coordinate offset
		PolygonGroup *PolygonGroupBuffer;		// Stores polygon group parameters as they are read from the file
		Polygon *PolygonBuffer;					// Stores polygon parameters as they are read from the file
		Polygon **PolygonListTail;				// Tail of the linked list of polygons

		// Allocate memory for a new polygon group and the coordinate buffer
		PolygonGroupBuffer = NewPolygonGroup(NULL);
		PolygonListTail = &PolygonGroupBuffer->PolygonList;
		
		// Initiate the buffers
		CoordinateBuffer.X = 0;
		CoordinateBuffer.Y = 0;
		CoordinateBuffer.Z = 0;
		Offset.X = 0;
		Offset.Y = 0;
		Offset.Z = 0;

		// Allocate memory for the buffer
		Buffer = (char*) malloc(200*sizeof(char));

		// Initialise the flags
		EndOfFile = false;
		ReadingParameters = false;
		SuccessfulRead = true;
		FirstGroup = true;

		// Initialise the line count to 0
		LineCount = 0;

		printf("\nReading polygon information from scene file '%s'\n\n", SceneFilename);

		// Read the scene file, one line at a time
		do {
			if (fgets(Buffer, 200, SceneFile) != NULL) {
								
				// Keep track of the line number
				LineCount++;
				// Search for and remove comments				
				Comment = strstr(Buffer, "//");
				if (Comment != NULL) {
					Comment[0] = NULL;	// Replace with 0 to mark a new end of the string
				}

				// Remove leading whitespace and read the parameter type character (p,t,z,o,h,v)
				Parameter = strtok_s(Buffer, "\t ", &Context);
				if (Parameter != NULL) {
					switch (Parameter[0]) {
						
						// Read the electrical parameters
						case 'p':
							// Set the reading parameters flag, create a new polygon group and add the old one to the list
							ReadingParameters = true;
							// Add the polygon buffer to the list if this is not the first read
							if (FirstGroup == true) {
								FirstGroup = false;
							}
							else {
								AddPolygonGroupToList(&Head, PolygonGroupBuffer);
								PolygonGroupBuffer = NewPolygonGroup(PolygonGroupBuffer);						
								PolygonListTail = &PolygonGroupBuffer->PolygonList;
								// FIXME: Should the offset be reset upon reading a 'p'?
								//Offset.X = 0;
								//Offset.Y = 0;
								//Offset.Z = 0;
							}
							SuccessfulRead = ReadParameters(&Context, PolygonGroupBuffer);
							break;
						
						// Read the wall thickness
						case 't':
							// If not currently reading parameters (i.e. not just read a p, z or t) create a new polygon group and add the old one to the list
							if (ReadingParameters == false) {
								ReadingParameters = true;
								AddPolygonGroupToList(&Head, PolygonGroupBuffer);
								PolygonGroupBuffer = NewPolygonGroup(PolygonGroupBuffer);
								PolygonListTail = &PolygonGroupBuffer->PolygonList;
								// FIXME: Should the offset be reset upon reading a 't'?
								//Offset.X = 0;
								//Offset.Y = 0;
								//Offset.Z = 0;
							}
							SuccessfulRead = ReadThickness(&Context, PolygonGroupBuffer);
							break;
						
						// Read the priority
						case 'z':
							// If not currently reading parameters (i.e. not just read a p, z or t) create a new polygon group and add the old one to the list
							if (ReadingParameters == false) {
								ReadingParameters = true;
								AddPolygonGroupToList(&Head, PolygonGroupBuffer);
								PolygonGroupBuffer = NewPolygonGroup(PolygonGroupBuffer);
								PolygonListTail = &PolygonGroupBuffer->PolygonList;
								// FIXME: Should the offset be reset upon reading a 'z'?
								//Offset.X = 0;
								//Offset.Y = 0;
								//Offset.Z = 0;
							}
							SuccessfulRead = ReadPriority(&Context, PolygonGroupBuffer);
							break;
						
						// Read the offset
						case 'o':
							SuccessfulRead = ReadCoordinates(&Context, &Offset);
							break;

						// Read a vertical polygon
						case 'v':
							// Ensure any previous polygons were also vertical
							if (ReadingParameters == false && PolygonGroupBuffer->Type != Vertical) {
								AddPolygonGroupToList(&Head, PolygonGroupBuffer);
								PolygonGroupBuffer = NewPolygonGroup(PolygonGroupBuffer);
								PolygonListTail = &PolygonGroupBuffer->PolygonList;
							}
							ReadingParameters = false;
							PolygonGroupBuffer->Type = Vertical;
							// Allocate memory for a new polygon structure with 2 vertices
							PolygonBuffer = NewPolygon();
							PolygonBuffer->Vertices = (Coordinate*)malloc(2*sizeof(Coordinate));
							// Read in 2 sets of coordinates
							while (ReadCoordinates(&Context, &CoordinateBuffer) == true) {
								// Increment the number of vertices and  ensure only 2 are read for a vertical polygon
								if (PolygonBuffer->nVertices < 2) {
									PolygonBuffer->Vertices[PolygonBuffer->nVertices].X = CoordinateBuffer.X + Offset.X;
									PolygonBuffer->Vertices[PolygonBuffer->nVertices].Y = CoordinateBuffer.Y + Offset.Y;
									PolygonBuffer->Vertices[PolygonBuffer->nVertices].Z = CoordinateBuffer.Z + Offset.Z;
								}	
								PolygonBuffer->nVertices++;
							}
							// Ensure both both vertices have been read
							if (PolygonBuffer->nVertices != 2) {
								SuccessfulRead = false;
							}
							else {
								nPolygons++;
								*PolygonListTail = PolygonBuffer;
								PolygonListTail = &(*PolygonListTail)->NextPolygon;
							}
							break;

						// Read a horizontal polygon
						case 'h':
							// Ensure any previous polygons were also horizontal
							if (ReadingParameters == false && PolygonGroupBuffer->Type != Horizontal) {
								AddPolygonGroupToList(&Head, PolygonGroupBuffer);
								PolygonGroupBuffer = NewPolygonGroup(PolygonGroupBuffer);
								PolygonListTail = &PolygonGroupBuffer->PolygonList;
							}
							ReadingParameters = false;
							PolygonGroupBuffer->Type = Horizontal;
							// Allocate memory for a new polygon structure with 2 vertices
							PolygonBuffer = NewPolygon();
							PolygonBuffer->Vertices = (Coordinate*)malloc(50*sizeof(Coordinate));
							// Read in at least 3 sets of coordinates
							while (ReadCoordinates(&Context, &CoordinateBuffer) == true) {
								// Increment the number of vertices and ensure there is enough memory for all of the vertices, reallocating 10 vertices at a time
								PolygonBuffer->Vertices[PolygonBuffer->nVertices].X = CoordinateBuffer.X + Offset.X;
								PolygonBuffer->Vertices[PolygonBuffer->nVertices].Y = CoordinateBuffer.Y + Offset.Y;
								PolygonBuffer->Vertices[PolygonBuffer->nVertices].Z = CoordinateBuffer.Z + Offset.Z;
								PolygonBuffer->nVertices++;
							}
							// Ensure at least 3 vertices have been read
							if (PolygonBuffer->nVertices < 3) {
								SuccessfulRead = false;
							}
							else {
								nPolygons++;
								*PolygonListTail = PolygonBuffer;
								PolygonListTail = &(*PolygonListTail)->NextPolygon;
							}
							PolygonBuffer->Vertices = (Coordinate*)realloc(PolygonBuffer->Vertices, PolygonBuffer->nVertices*sizeof(Coordinate));
							break;
					}
				}
			}
			else if (feof(SceneFile) != 0) {
				EndOfFile = true;
			}
		}
		while (EndOfFile == false && SuccessfulRead == true);

		// Add the final group to the list
		AddPolygonGroupToList(&Head, PolygonGroupBuffer);
								
		// Free allocated memory
		free(Buffer);
		fclose(SceneFile);

		// Check to see if there were any errors in the scene file
		if (SuccessfulRead == false) {
			printf("Error in scene file, line %d\n", LineCount);
			// Free memory allocated to the polygons
			FreePolygonGroupList(Head);
			return false;
		}
		else {
			printf("Scene file parsed successfully\nRead %d polygons\n\n", nPolygons);
		}
	}

	// Find the maximum coordinates in the system and allocate enough memory for a rectangle of this size
	MaxCoordinates = FindMaxSize(Head);
	// Print information on the polygons to the display
	if (InputData.DisplayPolygonInformation.Flag == true) {
		PrintPolygonGroupList(Head);
	}
	// Allocate memory for the TLM grid
	AllocateGridMemory(MaxCoordinates);
	// Add the polygons into the grid
	AddPolygonsToGrid(Head);
	// Free memory allocated to the polygons
	FreePolygonGroupList(Head);
	// Calculate the reflection and transmission coefficients based on their impedances
	CalculateReflectionTransmissionCoefficients();

	return true;
}