void parse_texture(FILE *fp, World *w) { char texture_name[STRING_TOKEN_MAX_LENGTH]; char filename[STRING_TOKEN_MAX_LENGTH]; char texture_path[PATH_MAX + STRING_TOKEN_MAX_LENGTH]; Texture *t; Texture_node *tn; if (get_string_token(fp, texture_name) != Token_string) parse_error("texture name expected"); if (strlen(texture_name) >= TEXTURE_NAME_MAX_LENGTH) parse_error("texture name too long"); if (get_string_token(fp, filename) != Token_string) parse_error("texture file name expected"); #ifdef WIN32 sprintf(texture_path, "%s%s/%s", szWTpath, TEXTURE_PATH, filename); #else sprintf(texture_path, "%s/%s", TEXTURE_PATH, filename); #endif t = read_texture_file(texture_path); tn = wtmalloc(sizeof(Texture_node)); strcpy(tn->name, texture_name); tn->index = TABLE_SIZE(w->textures); add_node(texture_list, tn); add_texture(w, t); }
void parse_region(FILE *fp, World *w) { char texture_name[STRING_TOKEN_MAX_LENGTH]; int texture_index; Region r; if (get_real_token(fp, &r.floor) != Token_real) parse_error("number expected"); if (get_real_token(fp, &r.ceiling) != Token_real) parse_error("number expected"); /* floor texture */ if (get_string_token(fp, texture_name) != Token_string) parse_error("texture name expected"); texture_index = get_texture_index(texture_name); if (texture_index < 0 || texture_index > TABLE_SIZE(w->textures)) parse_error("non-existent texture"); else r.floor_tex = WORLD_TEXTURE(w, texture_index); /* ceiling texture */ if (get_string_token(fp, texture_name) != Token_string) parse_error("texture name expected"); if (strcmp(texture_name, "sky") == 0) r.ceiling_tex = NULL; else { texture_index = get_texture_index(texture_name); if (texture_index < 0 || texture_index > TABLE_SIZE(w->textures)) parse_error("non-existent texture"); else r.ceiling_tex = WORLD_TEXTURE(w, texture_index); } add_region(w, &r); }
MODULE get_next_token (void) { char thisch; while (condition [column] == ' ') /* Skip leading spaces */ column++; thisch = condition [column]; token_len = 0; token_posn = column; if (is_valid (thisch)) { get_normal_token (); the_next_event = normal_event; } else if (is_relat (thisch)) { get_relator_token (); the_next_event = relator_event; } else if (is_quote (thisch)) { get_string_token (); the_next_event = string_event; } else if (thisch == 0) the_next_event = finished_event; else signal_error (MSG_EVAL_INVALID_TOKEN); }
void parse_world(FILE *fp, World *w) { char tokenbuf[STRING_TOKEN_MAX_LENGTH]; while (get_string_token(fp, tokenbuf) != Token_EOF) { if (strcmp(tokenbuf, "texture") == 0) parse_texture(fp, w); else if (strcmp(tokenbuf, "wall") == 0) parse_wall(fp, w); else if (strcmp(tokenbuf, "region") == 0) parse_region(fp, w); else if (strcmp(tokenbuf, "vertex") == 0) parse_vertex(fp, w); else parse_error("unknown structure type"); } }
static void field_instruction_end(ParserContext *ctx) { FieldInstructionState *state = get_state(ctx); gchar *field_type, *buffer; GSList *switches = NULL, *formatswitches = NULL, *iter; const FieldInfo *field_info = fields; GScanner *tokenizer = g_scanner_new(&field_parser); g_scanner_input_text(tokenizer, state->scanbuffer->str, strlen(state->scanbuffer->str)); /* Get field type */ if(!(field_type = get_string_token(tokenizer))) return; /* Determine if field type is supported and get switches and arguments */ while(field_info->name != NULL) { if(g_ascii_strcasecmp(field_type, field_info->name) == 0) { state->type = field_info->type; switches = get_switches(tokenizer, switches, field_info->switches, field_info->argswitches, field_info->wideswitches, field_info->wideargswitches); if(field_info->has_argument) { if(!(buffer = get_string_token(tokenizer))) return; state->argument = g_strdup(buffer); switches = get_switches(tokenizer, switches, field_info->switches, field_info->argswitches, field_info->wideswitches, field_info->wideargswitches); } break; } field_info++; } if(field_info->name == NULL) /* Field name wasn't found in list */ { g_warning(_("'%s' field not supported"), field_type); g_scanner_destroy(tokenizer); return; } formatswitches = get_switches(tokenizer, formatswitches, "", "@#*", "", ""); for(iter = formatswitches; iter; iter = g_slist_next(iter)) { SwitchInfo *info = (SwitchInfo *)iter->data; /* Parse a date format consisting of \@ and a string */ if(strcmp(info->switchname, "@") == 0) state->date_format = g_strdup(info->switcharg); /* Parse a numeric format consisting of \# and a string */ else if(strcmp(info->switchname, "#") == 0) state->numeric_format = g_strdup(info->switcharg); /* Parse a general format consisting of \* and a keyword */ else if(strcmp(info->switchname, "*") == 0) { if(strcmp(info->switcharg, "ALPHABETIC") == 0) state->general_number_format = NUMBER_ALPHABETIC; else if(strcmp(info->switcharg, "alphabetic") == 0) state->general_number_format = NUMBER_alphabetic; else if(strcmp(info->switcharg, "Arabic") == 0) state->general_number_format = NUMBER_ARABIC; else if(strcmp(info->switcharg, "ArabicDash") == 0) state->general_number_format = NUMBER_ARABIC_DASH; else if(strcmp(info->switcharg, "CIRCLENUM") == 0) state->general_number_format = NUMBER_CIRCLENUM; else if(strcmp(info->switcharg, "GB1") == 0) state->general_number_format = NUMBER_DECIMAL_ENCLOSED_PERIOD; else if(strcmp(info->switcharg, "GB2") == 0) state->general_number_format = NUMBER_DECIMAL_ENCLOSED_PARENTHESES; else if(strcmp(info->switcharg, "Hex") == 0) state->general_number_format = NUMBER_HEX; else if(strcmp(info->switcharg, "MERGEFORMATINET") == 0) ; /* ignore */ else if(strcmp(info->switcharg, "Ordinal") == 0) state->general_number_format = NUMBER_ORDINAL; else if(strcmp(info->switcharg, "Roman") == 0) state->general_number_format = NUMBER_ROMAN; else if(strcmp(info->switcharg, "roman") == 0) state->general_number_format = NUMBER_roman; else g_warning(_("Format '%s' not supported"), info->switcharg); /* Just continue */ } } Destination *fielddest = g_queue_peek_nth(ctx->destination_stack, 1); FieldState *fieldstate = g_queue_peek_tail(fielddest->state_stack); switch(state->type) { case FIELD_TYPE_HYPERLINK: /* Actually inserting hyperlinks into the text buffer is a whole security can of worms I don't want to open! Just use field result */ fieldstate->ignore_field_result = FALSE; break; case FIELD_TYPE_INCLUDEPICTURE: { GError *error = NULL; gchar **pathcomponents = g_strsplit(state->argument, "\\", 0); gchar *realfilename = g_build_filenamev(pathcomponents); g_strfreev(pathcomponents); GdkPixbuf *picture = gdk_pixbuf_new_from_file(realfilename, &error); if(!picture) g_warning(_("Error loading picture from file '%s': %s"), realfilename, error->message); else { /* Insert picture into text buffer */ GtkTextIter iter; gtk_text_buffer_get_iter_at_mark(ctx->textbuffer, &iter, ctx->endmark); gtk_text_buffer_insert_pixbuf(ctx->textbuffer, &iter, picture); g_object_unref(picture); } g_free(realfilename); } /* Don't use calculated field result */ fieldstate->ignore_field_result = TRUE; break; case FIELD_TYPE_PAGE: { gchar *output = format_integer(1, state->general_number_format); GtkTextIter iter; gtk_text_buffer_get_iter_at_mark(ctx->textbuffer, &iter, ctx->endmark); gtk_text_buffer_insert(ctx->textbuffer, &iter, output, -1); g_free(output); } /* Don't use calculated field result */ fieldstate->ignore_field_result = TRUE; break; default: g_assert_not_reached(); } g_free(state->argument); g_free(state->date_format); g_free(state->numeric_format); g_slist_foreach(switches, (GFunc)free_switch_info, NULL); g_slist_foreach(formatswitches, (GFunc)free_switch_info, NULL); g_scanner_destroy(tokenizer); }
/* Consume all the tokens belonging to the switches named here */ static GSList * get_switches(GScanner *tokenizer, GSList *switcheslist, const gchar *switches, const gchar *argswitches, const gchar *wideswitches, const gchar *wideargswitches) { gboolean found = FALSE; g_assert(strlen(wideswitches) % 2 == 0); g_assert(strlen(wideargswitches) % 2 == 0); /* Parse switches until an argument without '\' or unexpected switch */ while(!g_scanner_eof(tokenizer)) { GTokenType token = g_scanner_peek_next_token(tokenizer); found = FALSE; if(token != G_TOKEN_STRING) break; if(tokenizer->next_value.v_string[0] == '\\') { const gchar *ptr; for(ptr = switches; *ptr && !found; ptr++) if(tokenizer->next_value.v_string[1] == ptr[0] && tokenizer->next_value.v_string[2] == '\0') { SwitchInfo *info = g_slice_new0(SwitchInfo); info->switchname = g_strdup(tokenizer->next_value.v_string + 1); info->switcharg = NULL; g_scanner_get_next_token(tokenizer); switcheslist = g_slist_prepend(switcheslist, info); found = TRUE; } for(ptr = argswitches; *ptr && !found; ptr++) if(tokenizer->next_value.v_string[1] == ptr[0] && tokenizer->next_value.v_string[2] == '\0') { SwitchInfo *info = g_slice_new0(SwitchInfo); info->switchname = g_strdup(tokenizer->next_value.v_string + 1); g_scanner_get_next_token(tokenizer); info->switcharg = g_strdup(get_string_token(tokenizer)); switcheslist = g_slist_prepend(switcheslist, info); found = TRUE; } for(ptr = wideswitches; *ptr && !found; ptr++) if(tokenizer->next_value.v_string[1] == ptr[0] && tokenizer->next_value.v_string[2] == ptr[1] && tokenizer->next_value.v_string[3] == '\0') { SwitchInfo *info = g_slice_new0(SwitchInfo); info->switchname = g_strdup(tokenizer->next_value.v_string + 1); info->switcharg = NULL; g_scanner_get_next_token(tokenizer); switcheslist = g_slist_prepend(switcheslist, info); found = TRUE; } for(ptr = wideargswitches; *ptr && !found; ptr += 2) if(tokenizer->next_value.v_string[1] == ptr[0] && tokenizer->next_value.v_string[2] == ptr[1] && tokenizer->next_value.v_string[3] == '\0') { SwitchInfo *info = g_slice_new0(SwitchInfo); info->switchname = g_strdup(tokenizer->next_value.v_string + 1); g_scanner_get_next_token(tokenizer); info->switcharg = g_strdup(get_string_token(tokenizer)); switcheslist = g_slist_prepend(switcheslist, info); found = TRUE; } } else break; if(!found) break; /* Unexpected switch, so it must belong to the next part of the field */ } return switcheslist; }
void parse_wall(FILE *fp, World *w) { Wall wall; char texture_name[STRING_TOKEN_MAX_LENGTH]; int texture_index; int front_region, back_region; int vertex1, vertex2; fixed wall_length; /* vertices */ if (get_integer_token(fp, &vertex1) != Token_integer) parse_error("integer expected"); if (get_integer_token(fp, &vertex2) != Token_integer) parse_error("integer expected"); if (vertex1 < 0 || vertex1 > TABLE_SIZE(w->vertices)) parse_error("invalid vertex number"); if (vertex2 < 0 || vertex2 > TABLE_SIZE(w->vertices)) parse_error("invalid vertex number"); wall.vertex1 = &WORLD_VERTEX(w, vertex1); wall.vertex2 = &WORLD_VERTEX(w, vertex2); /* texture */ if (get_string_token(fp, texture_name) != Token_string) parse_error("texture name expected"); texture_index = get_texture_index(texture_name); if (texture_index < 0 || texture_index > TABLE_SIZE(w->textures)) parse_error("non-existent texture"); else wall.surface_texture = WORLD_TEXTURE(w, texture_index); if (strcmp(texture_name, "sky") == 0) wall.sky = True; else wall.sky = False; /* front and back regions */ if (get_integer_token(fp, &front_region) != Token_integer) fatal_error("non-existent region"); if (get_integer_token(fp, &back_region) != Token_integer) fatal_error("non-existent region"); if (front_region < 0 || front_region > TABLE_SIZE(w->regions)) fatal_error("non-existent region"); if (back_region < 0 || back_region > TABLE_SIZE(w->regions)) fatal_error("non-existent region"); wall.front = &WORLD_REGION(w, front_region); wall.back = &WORLD_REGION(w, back_region); /* Texture phase and scale. This code is somewhat more complicated than ** you'd expect, since the texture scale must be normalized to the ** wall length. */ if (get_real_token(fp, &wall.xscale) != Token_real) parse_error("number expected"); if (get_real_token(fp, &wall.yscale) != Token_real) parse_error("number expected"); if (get_real_token(fp, &wall.xphase) != Token_real) parse_error("number expected"); if (get_real_token(fp, &wall.yphase) != Token_real) parse_error("number expected"); wall_length = FLOAT_TO_FIXED(sqrt(FIXED_TO_FLOAT(wall.vertex2->x - wall.vertex1->x) * FIXED_TO_FLOAT(wall.vertex2->x - wall.vertex1->x) + FIXED_TO_FLOAT(wall.vertex2->y - wall.vertex1->y) * FIXED_TO_FLOAT(wall.vertex2->y - wall.vertex1->y))); wall.yscale = fixmul(wall.yscale, INT_TO_FIXED(wall.surface_texture->height)); wall.xscale = fixmul(fixmul(wall.xscale, INT_TO_FIXED(wall.surface_texture->width)), wall_length); add_wall(w, &wall); }