/** * Skips the opening "{" or "{#" depending upon the ending flag * @param str Pointer to a string structure * @param ending Flag indicating if it is an ending structure to expect a '#' * @return Returns 0 on failure, 1 on success **/ int skipOpen( pstring str, int ending ) { if (str == NULL ) { return 0; } skipWhiteSpace(str); if ( !atChar( str, '{' ) ) { return 0; } /// Skip the opening brace if ( incChar(str) == -1 ) { return 0; } /// Skip to the element id value or '#' if it is an end skipWhiteSpace(str); if ( ending ) { if (!atChar( str, '#') ) { return 0; } if ( incChar( str ) == -1 ) { return 0; } } return 1; }
void writec(char c) { switch(c) { case '\r': case '\n': newLine(); return; case '\t': incChar(4); return; case '\b': backspace(); return; } volatile unsigned short *where; where = (unsigned short*)(VIDMEMSTART + (currentColumn + (currentLine * CHARSPERLINE)) * 2); *where = c | (attrib << 8); incChar(1); }
/** * Parse the planet string and its sub elements * @param topLevel Pointer to the string structure to be parsed * @return Returns a pointer to a planet structure with associated data. Null on failure **/ pPlanet planetTopLevel( pstring topLevel ) { int endIndex = 0; int temp_index = 0; pPlanet newPlanet = NULL; element el; char *fl = NULL; int lastGood = 0; if ( topLevel == NULL ) { goto end; } /// Skip any leading spaces skipWhiteSpace( topLevel ); lastGood = topLevel->index; if ( topLevel->maxlength < 9 ) { goto end; } char *c = "{Planet}"; for ( int i = 0; i < 8; i++ ) { if ( topLevel->buffer[ topLevel->index + i ] != c[i] ) { goto end; } } /// Skip 8 bytes of top level then any whitespace topLevel->index += 8; skipWhiteSpace( topLevel ); /// Allocate a new planet structure if ( allocate( sizeof(Planet), 0, (void**)&newPlanet) != 0 ) { goto end; } initPlanet( newPlanet ); /// Extract the next element name fl = pullNextElementName( topLevel ); getIndex( topLevel, &lastGood); while ( fl != NULL ) { /// Convert the element name el = elementNameToEnum( fl ); /// The name is no longer needed so free it deallocate( fl, strlen(fl) + 1 ); switch (el) { case name: fl = extractName( topLevel ); if ( fl == NULL ) { goto error; } bzero( newPlanet->name, 20 ); strncpy( newPlanet->name, fl, 19 ); deallocate(fl, strlen(fl) + 1 ); fl = NULL; break; case population: newPlanet->population = extractPopulation( topLevel ); if ( newPlanet->population < 0 ) { goto error; } break; case period: /// Extract period and check result newPlanet->period = extractPeriod( topLevel ); if ( newPlanet->period < 0.0 ) { goto error; } break; case orbitspeed: newPlanet->orbitspeed = extractOrbitSpeed( topLevel ); if ( newPlanet->orbitspeed < 0.0 ) { goto error; } break; case aphelion: newPlanet->aphelion = extractAphelion( topLevel ); if ( newPlanet->aphelion < 0.0 ) { goto error; } break; case perihelion: newPlanet->perihelion = extractPerihelion( topLevel ); if ( newPlanet->perihelion < 0.0 ) { goto error; } break; case radius: newPlanet->radius = extractRadius( topLevel ); if ( newPlanet->radius < 0.0 ) { goto error; } break; case eradius: newPlanet->eradius = extractERadius( topLevel ); if ( newPlanet->eradius < 0.0 ) { goto error; } break; case mass: newPlanet->mass = extractMass( topLevel ); if ( newPlanet->mass < 0.0 ) { goto error; } break; case gravity: newPlanet->gravity = extractGravity( topLevel ); if ( newPlanet->gravity < 0.0 ) { goto error; } break; case country: if ( newPlanet->country_count >= COUNTRYMAX ) { printf("!!Only @d countries allowed\n", COUNTRYMAX); goto error; } newPlanet->countries[ newPlanet->country_count] = countryTopLevel(topLevel); if (newPlanet->countries[ newPlanet->country_count ] == NULL ) { goto error; } newPlanet->country_count++; break; default: printf("Not allowed under Planet\n", fl); goto error; break; }; getIndex( topLevel, &lastGood ); fl = pullNextElementName( topLevel ); } /// Since no more valid elements need to be parsed, check the closing element skipWhiteSpace( topLevel ); if ( !atChar( topLevel, '{' ) ) { printf("!!Closing value failed for Planet\n"); goto error; } /// Skip the open brace if ( incChar( topLevel ) < 0 ) { goto error; } skipWhiteSpace( topLevel ); if ( !atChar( topLevel, '#' ) ) { printf("!!Malformed closing element\n"); goto error; } /// Skip past # if ( incChar( topLevel ) == -1 ) { goto error; } getIndex( topLevel, &temp_index ); endIndex = skipAlpha( topLevel ); if ( endIndex == -1 ) { endIndex = 0; goto error; } if ( temp_index == endIndex ) { goto error; } fl = copyData( topLevel, temp_index, endIndex ); if ( fl == NULL ) { goto error; } if ( strcmp( fl, "Planet") != 0 ) { printf("!!Closing element malformed\n"); deallocate( fl, (endIndex-temp_index) + 1 ); goto error; } deallocate(fl, (endIndex-temp_index) + 1 ); skipWhiteSpace( topLevel ); if ( !atChar( topLevel, '}' ) ) { printf("!!Failed to find final closing brace\n"); goto error; } incChar(topLevel); goto end; error: topLevel->index = lastGood; printf("!!Error at: @s\n", topLevel->buffer + topLevel->index); if ( newPlanet != NULL ) { freePlanet( newPlanet ); newPlanet = NULL; } end: return newPlanet; }
/** * Parse the Gravity element and return the stored value * @param str Pointer to a string structure * @return Returns the double value or -1.0 on failure. Gravity should never be negative. **/ double extractGravity( pstring str ) { char *temp = NULL; double gravity = -1.0; int start = 0; int end = 0; /// These will be used specifically for the data int es = 0; int ee = 0; if (str == NULL ) { return -1.0; } start = skipWhiteSpace(str); if ( !atChar( str, '{' ) ) { printf("!!Failed to locate opening brace\n"); return gravity; } /// Skip past the curly brace if ( skipLength( str, 1 ) == -1 ) { printf("!!Failed to skip opening brace\n"); return gravity; } /// Skip any additional whitespace start = skipWhiteSpace(str); /// This should skip any to either whitespace or a closing '}' end = skipToNonAlphaNum( str ); if ( end == -1 ) { printf("!!Failed to locate the end of the element id\n"); return gravity; } /// Copy the element id from the string temp = copyData( str, start, end ); if ( temp == NULL ) { printf("!!Copy from @d to @d failed\n", start, end); return -1.0; } /// If the element id is not "Gravity" then this is the wrong function if ( strcmp( temp, "Gravity") != 0 ) { printf("!!Element id is not \"Gravity\"\n"); deallocate( temp, strlen(temp) + 1 ); temp = NULL; return gravity; } /// The buffer is no longer needed so free it deallocate(temp, strlen(temp) + 1); /// Skip to the end of the element id skipWhiteSpace( str ); /// If it is not a closing brace then this is improperly formatted. if ( !atChar( str, '}' ) ) { printf("!!Failed to locate initial closing brace\n"); return -1.0; } /// Skip the closing brace as well as any whitespace if ( skipLength( str, 1 ) == -1 ) { printf("!!Failed to skip initial closing brace\n"); return gravity; } skipWhiteSpace( str ); /// Copy the start index to store the data getIndex( str, &es ); /// The gravity data must be a float ee = skipFloat( str ); if ( ee == -1 ) { printf("!!Failed to locate the end of the gravity data\n"); return gravity; } /// The rest of this code is a check to ensure proper formatting except for the copy data skipWhiteSpace( str ); /// If this is not an opening curly brace then fail if ( !atChar( str, '{' ) ) { printf("!!Failed to locate the final opening brace\n"); return -1.0; } /// Skip past the brace if ( incChar( str) == -1 ) { printf("!!Failed to skip the final opening brace\n"); return gravity; } skipWhiteSpace(str); /// If this is not a # indicating the closing brace then fail if ( !atChar( str, '#' ) ) { printf("!!Failed to locate the closing mark\n"); return -1.0; } /// Skip past the # but save the start start = skipLength( str, 1 ); if ( start == -1 ) { printf("!!Failed to skip closing mark\n"); return gravity; } end = skipToNonAlphaNum( str ); if ( end == -1 ) { printf("!!Failed to locate the end of the closing element id\n"); return -1.0; } temp = copyData( str, start, end ); if ( strcmp( temp, "Gravity") != 0 ) { printf("!!Invalid closing element id: @s\n", temp); deallocate(temp, strlen(temp)+1); return gravity; } deallocate(temp, strlen(temp)+1); skipWhiteSpace( str ); /// Check the final curly brace if ( !atChar( str, '}' ) ) { printf("!!Failed to locate final closing brace\n"); return -1.0; } /// Skip past the closing brace skipLength( str, 1 ); /// Copy the gravity element data temp = copyData( str, es, ee ); if ( temp == NULL ) { printf("!!Failed to copy gravity data\n"); return -1; } gravity = atof( temp ); deallocate( temp, strlen(temp) + 1 ); return gravity; }
/** * Extract the data from the Url element. * This can be something such as http://www.rome.com * @param str Pointer to a string structure * @return Returns the element data or NULL on failure * The caller is responsible for freeing the pointer **/ char *extractUrl( pstring str ) { char *url = NULL; int startIndex = 0; char *temp = NULL; if ( str == NULL ) { goto end; } if ( skipOpen( str, 0 ) == 0 ) { goto end; } getIndex( str, &startIndex ); skipAlpha(str); url = copyData( str, startIndex, str->index); if ( url == NULL ) { goto end; } if ( strcmp( url, "Url" ) ) { freeCharPtr( &url ); goto end; } skipWhiteSpace( str ); if (!atChar( str, '}') ) { goto end; } incChar(str); skipWhiteSpace(str); getIndex( str, &startIndex); skipUrl( str ); url = copyData( str, startIndex, str->index ); if ( url == NULL ) { goto end; } skipWhiteSpace(str); if ( skipOpen( str, 1 ) == 0 ) { goto error; } getIndex( str, &startIndex ); skipAlpha(str); temp = copyData( str, startIndex, str->index); if ( temp == NULL ) { goto error; } if ( strcmp( temp, "Url") != 0 ) { freeCharPtr( &temp ); goto error; } freeCharPtr( &temp ); skipWhiteSpace(str); if ( !atChar( str, '}') ) { goto error; } incChar(str); goto end; error: if ( url ) { freeCharPtr( &url ); } end: return url; }
/** * Extracts the data from the Mayor element id * @param str Pointer to a string structure * @return Returns a pointer to the data or NULL on failure * The caller must free the pointer **/ char *extractMayor( pstring str ) { char *mayor = NULL; register int startIndex = 0; register int endIndex = 0; char *temp = NULL; if ( !str ) { return NULL; } /// This skips any whitespace and opening '{ ' if (skipOpen(str, 0 ) == 0 ) { return NULL; } startIndex = str->index; endIndex = skipAlpha(str); if ( endIndex == -1 || startIndex == endIndex ) { return NULL; } mayor = copyData( str, startIndex, endIndex ); if ( mayor == NULL ) { return NULL; } if ( strcmp( mayor, "Mayor") != 0 ) { freeCharPtr( &mayor ); return NULL; } freeCharPtr( &mayor ); skipWhiteSpace( str ); if (!atChar( str, '}') ) { return NULL; } /// Skip the Closing brace incChar( str ); startIndex = skipWhiteSpace(str); /// Using this function allows things like Sir Winston Churchill 3rd endIndex = skipToNonAlphaNumSpace( str ); if ( endIndex < 0 || startIndex == endIndex ) { return NULL; } while ( isspace( str->buffer[endIndex-1] ) ) { endIndex--; } mayor = copyData( str, startIndex, endIndex ); if ( mayor == NULL ) { return NULL; } skipWhiteSpace(str); /// Skip the opening brace and '#' if ( skipOpen( str, 1 ) == 0 ) { goto error; } startIndex = str->index; endIndex = skipAlpha( str ); if ( endIndex == -1 || startIndex == endIndex ) { goto error; } temp = copyData( str, startIndex, endIndex ); if ( temp == NULL ) { goto error; } if ( strcmp( temp, "Mayor") != 0 ) { freeCharPtr( &temp ); goto error; } skipWhiteSpace(str); if ( !atChar( str, '}' ) ) { goto error; } incChar(str); goto end; error: freeCharPtr( &mayor ); end: return mayor; }
/** * Top level function for parsing a City PML element * @param str Pointer to a string structure * @return Returns a pointer to a filled in city structure or NULL on failure **/ pCity cityTopLevel( pstring str ) { int lastGood = 0; pCity newCity = NULL; int startIndex = 0; int endIndex = 0; char *temp = NULL; int tempInt = 0; element el; if ( str == NULL ) { goto end; } /// Skip the opening "{" if ( skipOpen( str, 0 ) == 0 ) { goto end; } /// Get the start and end index of the element id getIndex( str, &startIndex); endIndex = skipAlpha(str); if ( endIndex == -1 ) { goto end; } if ( startIndex == endIndex ) { goto end; } temp = copyData( str, startIndex, endIndex ); if ( temp == NULL ) { goto end; } if ( strcmp( temp, "City") != 0 ) { deallocate(temp, cgc_strlen(temp) + 1 ); goto end; } deallocate(temp, cgc_strlen(temp) + 1 ); skipWhiteSpace( str ); if ( !atChar( str, '}') ) { goto end; } incChar( str ); skipWhiteSpace(str); lastGood = str->index; if ( allocate( sizeof(City), 0, (void**)&newCity) != 0 ) { newCity = NULL; goto error; } initCity( newCity ); temp = pullNextElementName( str ); while ( temp != NULL ) { el = elementNameToEnum( temp ); deallocate(temp, cgc_strlen(temp) + 1 ); switch (el) { case name: temp = extractName( str ); if ( temp == NULL ) { goto error; } /// Clear it out bzero( newCity->name, 20 ); /// Copy the name data. It has already been filtered /// for invalid characters. strncpy( newCity->name, temp, 19); /// Free the buffer deallocate( temp, cgc_strlen(temp) + 1 ); temp = NULL; break; case mayor: temp = extractMayor( str ); if ( temp == NULL ) { goto error; } bzero( newCity->mayor, 30 ); #ifdef PATCHED strncpy( newCity->mayor, temp, 29 ); #else strcpy( newCity->mayor, temp ); #endif freeCharPtr( &temp ); break; case url: temp = extractUrl( str ); if ( temp == NULL ) { goto error; } bzero( newCity->url, 30 ); strncpy( newCity->url, temp, 29 ); freeCharPtr( &temp ); break; case border: if ( newCity->border_count >= CITYBORDERMAX) { goto error; } tempInt = newCity->border_count; newCity->borders[ tempInt ] = extractBorder(str); if ( newCity->borders[ tempInt] == NULL ) { goto error; } newCity->border_count++; break; case population: newCity->population = extractPopulation( str ); if ( newCity->population < 0 ) { goto error; } break; default: printf("!!Invalid element ID for City\n"); goto error; break; }; lastGood = str->index; temp = pullNextElementName(str); } if ( skipOpen( str, 1) == 0 ) { goto error; } getIndex( str, &startIndex); endIndex = skipAlpha( str ); if ( endIndex == -1 ) { goto error; } else if ( startIndex == endIndex ) { goto error; } temp = copyData( str, startIndex, endIndex ); if ( temp == NULL ) { goto error; } if ( strcmp( temp, "City") != 0 ) { deallocate(temp, cgc_strlen(temp) + 1 ); goto error; } deallocate( temp, cgc_strlen(temp) + 1 ); skipWhiteSpace(str); if ( !atChar( str, '}') ) { goto error; } incChar(str); goto end; error: if ( newCity ) { freeCity( newCity ); newCity = NULL; } printf("!!Error at: @s\n", str->buffer + lastGood); str->index = lastGood; end: return newCity; }
/** * Extract the next element name without affecting the string * This buffer must be freed by the caller * @param str Pointer to a string structure * @return Returns a new pointer to the name of the element or NULL on failure **/ char *pullNextElementName( pstring str ) { char * elementId = NULL; int reset = 0; int index = 0; unsigned int length = 0; if ( str == NULL ) { return NULL; } /// This will be used to reset the buffer at the end reset = str->index; /// This shouldn't be necessary but just in case skipWhiteSpace( str ); /// The first character should be an open curly brace if (str->buffer[ str->index ] != '{' ) { printf("!!Invalid opening element: @s\n", str->buffer ); goto end; } /// Increment beyond the initial '{' if ( incChar( str ) == -1 ) { goto end; } /// Skip past any whitespace skipWhiteSpace(str); /// Store the index to the start of the element name index = str->index; /// Loop until the end of the buffer, a null, or a non-alpha, white space, or '}' character is encountered while ( index < str->maxlength ) { /// If we hit a NULL then it is improperly formatted. /// Just skip to the end if ( str->buffer[index] == '\x00' ) { printf("!!Null character hit. Improperly formatted element\n"); goto end; } /// If it is a closing brace or a white space then the name is passed if ( str->buffer[ index ] == '}' || isspace( str->buffer[index] ) ) { length = index-str->index; /// Copy the name for the return if ( allocate( length + 1, 0, (void*)&elementId ) != 0 ) { elementId = NULL; goto end; } bzero( elementId, length + 1 ); strncpy( elementId, str->buffer + str->index, length ); /// Check for a properly formatted name. Start by updating /// the string index to the end of the string /// Then skip any proceeding whitespace str->index = index; skipWhiteSpace(str); /// If the current character is not '}' then it invalid is /// invalid since only whitespace is allowed between the /// element id and the closing brace if (str->buffer[ str->index ] != '}' ) { printf("!!Improperly formatted element name\n"); deallocate( elementId, length + 1 ); elementId = NULL; } /// Work here is done. Skip to the end goto end; } /// Non alpha characters are not allowed as element names if ( !isalpha( str->buffer[index] ) ) { goto end; } index++; } end: /// Revert the string to the beginning str->index = reset; return elementId; }