📄 t_prepro.c
字号:
// Emacs style mode select -*- C++ -*-//----------------------------------------------------------------------------//// $Id: t_prepro.c,v 1.1 2000/11/02 17:57:28 stroggonmeth Exp $//// Copyright(C) 2000 Simon Howard//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.// // This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.// // You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA//// $Log: t_prepro.c,v $// Revision 1.1 2000/11/02 17:57:28 stroggonmeth// FraggleScript files...//////--------------------------------------------------------------------------//// Preprocessor.//// The preprocessor must be called when the script is first loaded.// It performs 2 functions:// 1: blank out comments (which could be misinterpreted)// 2: makes a list of all the sections held within {} braces// 3: 'dry' runs the script: goes thru each statement and// sets the types of all the section_t's in the script// 4: Saves locations of all goto() labels//// the system of section_t's is pretty horrible really, but it works// and its probably the only way i can think of of saving scripts// half-way thru running//// By Simon Howard////---------------------------------------------------------------------------/* includes ************************/#include <stdio.h>#include <string.h>#include "command.h"#include "doomstat.h"#include "w_wad.h"#include "z_zone.h"#include "t_parse.h"#include "t_spec.h"#include "t_oper.h"#include "t_vari.h"#include "t_func.h"// clear the script: section and variable slotsvoid clear_script(){ int i; for(i=0; i<SECTIONSLOTS; i++) current_script->sections[i] = NULL; for(i=0; i<VARIABLESLOTS; i++) current_script->variables[i] = NULL; // clear child scripts for(i=0; i<MAXSCRIPTS; i++) current_script->children[i] = NULL;}/*********** {} sections *************/// during preprocessing all of the {} sections// are found. these are stored in a hash table// according to their offset in the script. // functions here deal with creating new section_t's// and finding them from a given offset.#define section_hash(b) \ ( (int) ( (b) - current_script->data) % SECTIONSLOTS)section_t *new_section(char *brace){ int n; section_t *newsec; // create section // make level so its cleared at start of new level newsec = Z_Malloc(sizeof(section_t), PU_LEVEL, 0); newsec->start = brace; // hook it into the hashchain n = section_hash(brace); newsec->next = current_script->sections[n]; current_script->sections[n] = newsec; return newsec;} // find a section_t from the location of the starting { bracesection_t *find_section_start(char *brace){ int n = section_hash(brace); section_t *current; current = current_script->sections[n]; // use the hash table: check the appropriate hash chain while(current) { if(current->start == brace) return current; current = current->next; } return NULL; // not found} // find a section_t from the location of the ending } bracesection_t *find_section_end(char *brace){ int n; // hash table is no use, they are hashed according to // the offset of the starting brace // we have to go through every entry to find from the // ending brace for(n=0; n<SECTIONSLOTS; n++) // check all sections in all chains { section_t *current = current_script->sections[n]; while(current) { if(current->end == brace) return current; // found it current = current->next; } } return NULL; // not found}/********** labels ****************/// labels are also found during the// preprocessing. these are of the form//// label_name://// and are used for the goto function.// goto labels are stored as variables. // from parse.c#define isop(c) !( ( (c)<='Z' && (c)>='A') || ( (c)<='z' && (c)>='a') || \ ( (c)<='9' && (c)>='0') || ( (c)=='_') ) // create a new label. pass the location inside the scriptsvariable_t *new_label(char *labelptr){ svariable_t *newlabel; // labels are stored as variables char labelname[256]; char *temp, *temp2; // copy the label name from the script up to ':' for(temp=labelptr, temp2 = labelname; *temp!=':'; temp++, temp2++) *temp2 = *temp; *temp2 = '\0'; // end string newlabel = new_variable(current_script, labelname, svt_label); // put neccesary data in the label newlabel->value.labelptr = labelptr; return newlabel;}/*********** main loop **************/// This works by recursion. when a { opening// brace is found, another instance of the// function is called for the data inside// the {} section.// At the same time, the sections are noted// down and hashed. Goto() labels are noted// down, and comments are blanked outchar *process_find_char(char *data, char find){ while(*data) { if(*data==find) return data; if(*data=='\"') // found a quote: ignore stuff in it { data++; while(*data && *data != '\"') { // escape sequence ? if(*data=='\\') data++; data++; } // error: end of script in a constant if(!*data) return NULL; } // comments: blank out if(*data=='/' && *(data+1)=='*') // /* -- */ comment { while(*data && (*data != '*' || *(data+1) != '/') ) { *data=' '; data++; } if(*data) *data = *(data+1) = ' '; // blank the last bit else { rover = data; // script terminated in comment script_error("script terminated inside comment\n"); } } if(*data=='/' && *(data+1)=='/') // // -- comment while(*data != '\n') { *data=' '; data++; // blank out } // labels if(*data==':' // ':' -- a label && current_script->scriptnum != -1) // not levelscript { char *labelptr = data-1; while(!isop(*labelptr)) labelptr--; new_label(labelptr+1); } if(*data=='{') // { -- } sections: add 'em { section_t *newsec = new_section(data); newsec->type = st_empty; // find the ending } and save newsec->end = process_find_char(data+1, '}'); if(!newsec->end) { // brace not found rover = data; script_error("section error: no ending brace\n"); return NULL; } // continue from the end of the section data = newsec->end; } data++; } return NULL;}/*********** second stage parsing ************/// second stage preprocessing considers the script// in terms of tokens rather than as plain data.//// we 'dry' run the script: go thru each statement and// collect types for section_t//// this is an important thing to do, it cannot be done// at runtime for 2 reasons:// 1. gotos() jumping inside loops will pass thru// the end of the loop// 2. savegames. loading a script saved inside a// loop will let it pass thru the loop//// this is basically a cut-down version of the normal// parsing loop.void get_tokens(char *); // t_parse.cvoid dry_run_script(){ // save some stuff char *old_rover = rover; section_t *old_current_section = current_section; char *end = current_script->data + current_script->len; char *token_alloc; killscript = false; // allocate space for the tokens token_alloc = Z_Malloc(current_script->len + T_MAXTOKENS, PU_STATIC, 0); rover = current_script->data; while(rover < end && *rover) { tokens[0] = token_alloc; get_tokens(rover); if(killscript) break; if(!num_tokens) continue; if(current_section && tokentype[0] == function) { if(!strcmp(tokens[0], "if")) { current_section->type = st_if; continue; } else if(!strcmp(tokens[0], "elseif")) { current_section->type = st_elseif; continue; } else if(!strcmp(tokens[0], "else")) { current_section->type = st_else; continue; } else if(!strcmp(tokens[0], "while") || !strcmp(tokens[0], "for")) { current_section->type = st_loop; current_section->data.data_loop.loopstart = linestart; continue; } } } Z_Free(token_alloc); // restore stuff current_section = old_current_section; rover = old_rover;}/***************** main preprocess function ******************/// set up current_script, script->len// just call all the other functionsvoid preprocess(script_t *script){ if(debugfile) fprintf(debugfile," preprocess script %i\n", script->scriptnum); current_script = script; script->len = strlen(script->data); clear_script(); if(debugfile) fprintf(debugfile, " run thru script\n"); process_find_char(script->data, 0); // fill in everything if(debugfile) fprintf(debugfile, " dry run script\n"); dry_run_script();}/************ includes ******************/// FraggleScript allows 'including' of other lumps.// we divert input from the current_script (normally// levelscript) to a seperate lump. This of course// first needs to be preprocessed to remove comments// etc.void parse_data(char *data, char *end); // t_parse.c// parse an 'include' lumpvoid parse_include(char *lumpname){ int lumpnum; char *temp; char *lump, *end; char *saved_rover; if(-1 == (lumpnum = W_GetNumForName(lumpname)) ) { script_error("include lump '%s' not found!\n", lumpname); return; } lump = W_CacheLumpNum(lumpnum, PU_STATIC); // realloc bigger for NULL at end // SoM: REALLOC does not seem to work! So we alloc here and copy.... //lump = Z_Realloc(lump, W_LumpLength(lumpnum)+10, PU_STATIC, NULL); temp = lump; lump = Z_Malloc(W_LumpLength(lumpnum) + 10, PU_STATIC, NULL); memcpy(lump, temp, W_LumpLength(lumpnum)); saved_rover = rover; // save rover during include rover = lump; end = lump+W_LumpLength(lumpnum); *end = 0; // preprocess the include // we assume that it does not include sections or labels or // other nasty things process_find_char(lump, 0); // now parse the lump parse_data(lump, end); // restore rover rover = saved_rover; // free the lump Z_Free(lump); Z_Free(temp);}//---------------------------------------------------------------------------//// $Log: t_prepro.c,v $// Revision 1.1 2000/11/02 17:57:28 stroggonmeth// FraggleScript files...//// Revision 1.1.1.1 2000/04/30 19:12:08 fraggle// initial import//////---------------------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -