📄 scriplib.c
字号:
/* * scriplib.c * MACT library Script file parsing and writing * * by Jonathon Fowler * * Since we weren't given the source for MACT386.LIB so I've had to do some * creative interpolation here. * * This all should be rewritten in a much much cleaner fashion. * *///-------------------------------------------------------------------------/*Duke Nukem Copyright (C) 1996, 2003 3D Realms EntertainmentThis file is part of Duke Nukem 3D version 1.5 - Atomic EditionDuke Nukem 3D is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of 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 ofMERCHANTABILITY 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 Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*///-------------------------------------------------------------------------#include "compat.h"#include "types.h"#include "scriplib.h"#include "util_lib.h"#include "file_lib.h"#include "_scrplib.h"#include <string.h>#include <stdio.h>#include <ctype.h>#ifdef __WATCOMC__#include <malloc.h>#endifstatic script_t *scriptfiles[MAXSCRIPTFILES];#define SC(s) scriptfiles[s]int32 SCRIPT_New(void){ int32 i; for (i=0; i<MAXSCRIPTFILES; i++) { if (!SC(i)) { SC(i) = (script_t *)SafeMalloc(sizeof(script_t)); if (!SC(i)) return -1; memset(SC(i), 0, sizeof(script_t)); return i; } } return -1;}void SCRIPT_Delete(int32 scripthandle){ ScriptSectionType *s; if (scripthandle < 0 || scripthandle >= MAXSCRIPTFILES) return; if (!SC(scripthandle)) return; if (SCRIPT(scripthandle,script)) { while (SCRIPT(scripthandle,script)->nextsection != SCRIPT(scripthandle,script)) { s = SCRIPT(scripthandle,script)->nextsection; SCRIPT_FreeSection(SCRIPT(scripthandle,script)); SafeFree(SCRIPT(scripthandle,script)); SCRIPT(scripthandle,script) = s; } SafeFree(SCRIPT(scripthandle,script)); } SafeFree(SC(scripthandle)); SC(scripthandle) = 0;}void SCRIPT_FreeSection(ScriptSectionType * section){ ScriptEntryType *e; if (!section) return; if (!section->entries) return; while (section->entries->nextentry != section->entries) { e = section->entries->nextentry; SafeFree(section->entries); section->entries = e; } SafeFree(section->entries); free(section->name);}#define AllocSection(s) \ { \ (s) = SafeMalloc(sizeof(ScriptSectionType)); \ (s)->name = NULL; \ (s)->entries = NULL; \ (s)->lastline = NULL; \ (s)->nextsection = (s); \ (s)->prevsection = (s); \ }#define AllocEntry(e) \ { \ (e) = SafeMalloc(sizeof(ScriptEntryType)); \ (e)->name = NULL; \ (e)->value = NULL; \ (e)->nextentry = (e); \ (e)->preventry = (e); \ }ScriptSectionType * SCRIPT_SectionExists(int32 scripthandle, char * sectionname){ ScriptSectionType *s, *ls=NULL; if (scripthandle < 0 || scripthandle >= MAXSCRIPTFILES) return NULL; if (!sectionname) return NULL; if (!SC(scripthandle)) return NULL; if (!SCRIPT(scripthandle,script)) return NULL; for (s = SCRIPT(scripthandle,script); ls != s; ls=s,s=s->nextsection) if (!Bstrcasecmp(s->name, sectionname)) return s; return NULL;}ScriptSectionType * SCRIPT_AddSection(int32 scripthandle, char * sectionname){ ScriptSectionType *s,*s2; if (scripthandle < 0 || scripthandle >= MAXSCRIPTFILES) return NULL; if (!sectionname) return NULL; if (!SC(scripthandle)) return NULL; s = SCRIPT_SectionExists(scripthandle, sectionname); if (s) return s; AllocSection(s); s->name = strdup(sectionname); if (!SCRIPT(scripthandle,script)) { SCRIPT(scripthandle,script) = s; } else { s2 = SCRIPT(scripthandle,script); while (s2->nextsection != s2) s2=s2->nextsection; s2->nextsection = s; s->prevsection = s2; } return s;}ScriptEntryType * SCRIPT_EntryExists(ScriptSectionType * section, char * entryname){ ScriptEntryType *e,*le=NULL; if (!section) return NULL; if (!entryname) return NULL; if (!section->entries) return NULL; for (e = section->entries; le != e; le=e,e=e->nextentry) if (!Bstrcasecmp(e->name, entryname)) return e; return NULL;}void SCRIPT_AddEntry(int32 scripthandle, char * sectionname, char * entryname, char * entryvalue){ ScriptSectionType *s; ScriptEntryType *e,*e2; if (scripthandle < 0 || scripthandle >= MAXSCRIPTFILES) return; if (!sectionname || !entryname || !entryvalue) return; if (!SC(scripthandle)) return;// s = SCRIPT_SectionExists(scripthandle, sectionname);// if (!s) { s = SCRIPT_AddSection(scripthandle, sectionname); if (!s) return;// } e = SCRIPT_EntryExists(s, entryname); if (!e) { AllocEntry(e); e->name = strdup(entryname); if (!s->entries) { s->entries = e; } else { e2 = s->entries; while (e2->nextentry != e2) e2=e2->nextentry; e2->nextentry = e; e->preventry = e2; } } if (e->value) free(e->value); e->value = strdup(entryvalue);}int32 SCRIPT_ParseBuffer(int32 scripthandle, char *data, int32 length){ char *fence = data + length; char *dp, *sp, ch=0, lastch=0; char *currentsection = ""; char *currententry = NULL; char *currentvalue = NULL; enum { ParsingIdle, ParsingSectionBegin, ParsingSectionName, ParsingEntry, ParsingValueBegin, ParsingValue }; enum { ExpectingSection = 1, ExpectingEntry = 2, ExpectingAssignment = 4, ExpectingValue = 8, ExpectingComment = 16 }; int32_t state; int32_t expect; int32_t linenum=1; int32_t rv = 0;#define SETRV(v) if (v>rv||rv==0) rv=v if (!data) return 1; if (length < 0) return 1; dp = sp = data; state = ParsingIdle; expect = ExpectingSection | ExpectingEntry;#define EATLINE(p) while (length > 0 && *p != '\n' && *p != '\r') { p++; length--; }#define LETTER() { lastch = ch; ch = *(sp++); length--; } while (length > 0) { switch (state) { case ParsingIdle: LETTER(); switch (ch) { // whitespace case ' ': case '\t': continue; case '\n': if (lastch == '\r') continue; linenum++; continue; case '\r': linenum++; continue; case ';': /*case '#':*/ EATLINE(sp); continue; case '[': if (!(expect & ExpectingSection)) { // Unexpected section start printf("Unexpected start of section on line %d.\n", linenum); SETRV(-1); EATLINE(sp); continue; } else { state = ParsingSectionBegin; continue; } default: if (isalpha(ch)) { if (!(expect & ExpectingEntry)) { // Unexpected name start printf("Unexpected entry LabelText on line %d.\n", linenum); SETRV(-1); EATLINE(sp); continue; } else { currententry = dp = sp-1; state = ParsingEntry; continue; } } else { // Unexpected character printf("Illegal character (ASCII %d) on line %d.\n", ch, linenum); SETRV(-1); EATLINE(sp); continue; } } case ParsingSectionBegin: currentsection = dp = sp; state = ParsingSectionName; case ParsingSectionName: LETTER(); switch (ch) { case '\n': case '\r': // Unexpected newline printf("Unexpected newline on line %d.\n", linenum); SETRV(-1); state = ParsingIdle; linenum++; continue; case ']': *(dp) = 0; // Add new section expect = ExpectingSection | ExpectingEntry; state = ParsingIdle; EATLINE(sp); continue; default: dp++; continue; } case ParsingEntry: LETTER(); switch (ch) { case ';': /*case '#':*/ // unexpected comment EATLINE(sp); printf("Unexpected comment on line %d.\n", linenum); SETRV(-1); case '\n': case '\r': // Unexpected newline printf("Unexpected newline on line %d.\n", linenum); SETRV(-1); expect = ExpectingSection | ExpectingEntry; state = ParsingIdle; linenum++; continue; case '=': // Entry name finished, now for the value while (*dp == ' ' || *dp == '\t') dp--; *(++dp) = 0; state = ParsingValueBegin; continue; default: dp++; continue; } case ParsingValueBegin: currentvalue = dp = sp; state = ParsingValue; case ParsingValue: LETTER(); switch (ch) { case '\n': case '\r': // value complete, add it using parsed name while (*dp == ' ' && *dp == '\t') dp--; *(dp) = 0; while (*currentvalue == ' ' || *currentvalue == '\t') currentvalue++; state = ParsingIdle; linenum++; SCRIPT_AddSection(scripthandle,currentsection); SCRIPT_AddEntry(scripthandle,currentsection,currententry,currentvalue); continue; default: dp++; continue; } default: length=0; continue; } } if (sp > fence) printf("Stepped outside the fence!\n"); return rv;}//---int32 SCRIPT_Init(char * name){ int32 h = SCRIPT_New(); if (h >= 0) Bstrncpy(SCRIPT(h,scriptfilename), name, 127); return h;}void SCRIPT_Free(int32 scripthandle){ SCRIPT_Delete(scripthandle);}int32 SCRIPT_Load(char * filename){ int32 s,h,l; char *b; h = SafeOpenRead(filename, filetype_binary); l = SafeFileLength(h)+1; b = (char *)SafeMalloc(l); SafeRead(h,b,l-1); b[l-1] = '\n'; // JBF 20040111: evil nasty hack to trick my evil nasty parser SafeClose(h); s = SCRIPT_Init(filename); if (s<0) { SafeFree(b); return -1; } SCRIPT_ParseBuffer(s,b,l); SafeFree(b); return s;}void SCRIPT_Save(int32 scripthandle, char * filename){ char *section, *entry, *value; int32_t sec, ent, numsect, nument; FILE *fp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -