diff --git a/sourcepawn/compiler/libpawnc.c b/sourcepawn/compiler/libpawnc.c index fed7f800..2751a284 100644 --- a/sourcepawn/compiler/libpawnc.c +++ b/sourcepawn/compiler/libpawnc.c @@ -1,3 +1,4 @@ +// vim: set sts=8 ts=4 sw=4 tw=99 noet: /* LIBPAWNC.C * * A "glue file" for building the Pawn compiler as a DLL or shared library. @@ -24,6 +25,7 @@ */ #include #include +#include #include #include #include "sc.h" @@ -91,6 +93,14 @@ static char *prefix[3]={ "error", "fatal error", "warning" }; return 0; } +typedef struct src_file_s { + FILE *fp; // Set if writing. + char *buffer; // IO buffer. + char *pos; // IO position. + char *end; // End of buffer. + size_t maxlength; // Maximum length of the writable buffer. +} src_file_t; + /* pc_opensrc() * Opens a source file (or include file) for reading. The "file" does not have * to be a physical file, one might compile from memory. @@ -105,7 +115,11 @@ static char *prefix[3]={ "error", "fatal error", "warning" }; */ void *pc_opensrc(char *filename) { - #if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined DARWIN + FILE *fp = NULL; + long length; + src_file_t *src = NULL; + +#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined DARWIN struct stat fileInfo; if (stat(filename, &fileInfo) != 0) { return NULL; @@ -114,9 +128,32 @@ void *pc_opensrc(char *filename) if (S_ISDIR(fileInfo.st_mode)) { return NULL; } - #endif +#endif - return fopen(filename,"rt"); + if ((fp = fopen(filename, "rb")) == NULL) + return NULL; + if (fseek(fp, 0, SEEK_END) == -1) + goto err; + if ((length = ftell(fp)) == -1) + goto err; + if (fseek(fp, 0, SEEK_SET) == -1) + goto err; + + if ((src = (src_file_t *)calloc(1, sizeof(src_file_t))) == NULL) + goto err; + if ((src->buffer = (char *)calloc(length, sizeof(char))) == NULL) + goto err; + if (fread(src->buffer, length, 1, fp) != 1) + goto err; + + src->pos = src->buffer; + src->end = src->buffer + length; + return src; + +err: + pc_closesrc(src); + fclose(fp); + return NULL; } /* pc_createsrc() @@ -133,7 +170,23 @@ void *pc_opensrc(char *filename) */ void *pc_createsrc(char *filename) { - return fopen(filename,"wt"); + src_file_t *src = (src_file_t *)calloc(1, sizeof(src_file_t)); + if (!src) + return NULL; + if ((src->fp = fopen(filename, "wt")) == NULL) { + pc_closesrc(src); + return NULL; + } + + src->maxlength = 1024; + if ((src->buffer = (char *)calloc(1, src->maxlength)) == NULL) { + pc_closesrc(src); + return NULL; + } + + src->pos = src->buffer; + src->end = src->buffer + src->maxlength; + return src; } /* pc_closesrc() @@ -142,8 +195,15 @@ void *pc_createsrc(char *filename) */ void pc_closesrc(void *handle) { - assert(handle!=NULL); - fclose((FILE*)handle); + src_file_t *src = (src_file_t *)handle; + if (!src) + return; + if (src->fp) { + fwrite(src->buffer, src->pos - src->buffer, 1, src->fp); + fclose(src->fp); + } + free(src->buffer); + free(src); } /* pc_readsrc() @@ -152,7 +212,35 @@ void pc_closesrc(void *handle) */ char *pc_readsrc(void *handle,unsigned char *target,int maxchars) { - return fgets((char*)target,maxchars,(FILE*)handle); + src_file_t *src = (src_file_t *)handle; + char *outptr = (char *)target; + char *outend = outptr + maxchars; + + assert(!src->fp); + + if (src->pos == src->end) + return NULL; + + while (outptr < outend && src->pos < src->end) { + char c = *src->pos++; + *outptr++ = c; + + if (c == '\n') + break; + if (c == '\r') { + // Handle CRLF. + if (src->pos < src->end && *src->pos == '\n') { + src->pos++; + if (outptr < outend) + *outptr++ = '\n'; + } + break; + } + } + + // Caller passes in a buffer of size >= maxchars+1. + *outptr = '\0'; + return (char *)target; } /* pc_writesrc() @@ -161,31 +249,43 @@ char *pc_readsrc(void *handle,unsigned char *target,int maxchars) */ int pc_writesrc(void *handle,unsigned char *source) { - return fputs((char*)source,(FILE*)handle) >= 0; -} + char *str = (char *)source; + size_t len = strlen(str); + src_file_t *src = (src_file_t *)handle; -#define MAXPOSITIONS 4 -static fpos_t srcpositions[MAXPOSITIONS]; -static unsigned char srcposalloc[MAXPOSITIONS]; + assert(src->fp && src->maxlength); + + if (src->pos + len > src->end) { + char *newbuf; + size_t newmax = src->maxlength; + size_t newlen = (src->pos - src->buffer) + len; + while (newmax < newlen) { + // Grow by 1.5X + newmax += newmax + newmax / 2; + if (newmax < src->maxlength) + abort(); + } + + newbuf = (char *)realloc(src->buffer, newmax); + if (!newbuf) + abort(); + src->pos = newbuf + (src->pos - src->buffer); + src->end = newbuf + newmax; + src->buffer = newbuf; + src->maxlength = newmax; + } + + strcpy(src->pos, str); + src->pos += len; + return 0; +} void *pc_getpossrc(void *handle,void *position) { - if (position==NULL) { - /* allocate a new slot */ - int i; - for (i=0; i=MAXPOSITIONS) - return NULL; - position=&srcpositions[i]; - srcposalloc[i]=1; - } else { - /* use the gived slot */ - assert((fpos_t*)position>=srcpositions && (fpos_t*)positionfp); + return (void *)(ptrdiff_t)(src->pos - src->buffer); } /* pc_resetsrc() @@ -194,15 +294,20 @@ void *pc_getpossrc(void *handle,void *position) */ void pc_resetsrc(void *handle,void *position) { - assert(handle!=NULL); - assert(position!=NULL); - fsetpos((FILE*)handle,(fpos_t *)position); - /* note: the item is not cleared from the pool */ + src_file_t *src = (src_file_t *)handle; + ptrdiff_t pos = (ptrdiff_t)position; + + assert(!src->fp); + assert(pos >= 0 && src->buffer + pos <= src->end); + src->pos = src->buffer + pos; } int pc_eofsrc(void *handle) { - return feof((FILE*)handle); + src_file_t *src = (src_file_t *)handle; + + assert(!src->fp); + return src->pos == src->end; } /* should return a pointer, which is used as a "magic cookie" to all I/O diff --git a/sourcepawn/compiler/sc1.c b/sourcepawn/compiler/sc1.c index f74aee8d..7f63f9ac 100644 --- a/sourcepawn/compiler/sc1.c +++ b/sourcepawn/compiler/sc1.c @@ -267,7 +267,7 @@ int pc_compile(int argc, char *argv[]) if (get_sourcefile(1)!=NULL) { /* there are at least two or more source files */ char *tname,*sname; - FILE *ftmp,*fsrc; + void *ftmp,*fsrc; int fidx; #if defined __WIN32__ || defined _WIN32 tname=_tempnam(NULL,"pawn"); @@ -283,10 +283,10 @@ int pc_compile(int argc, char *argv[]) close(mkstemp(buffer)); tname=buffer; #endif - ftmp=(FILE*)pc_createsrc(tname); + ftmp=pc_createsrc(tname); for (fidx=0; (sname=get_sourcefile(fidx))!=NULL; fidx++) { unsigned char tstring[128]; - fsrc=(FILE*)pc_opensrc(sname); + fsrc=pc_opensrc(sname); if (fsrc==NULL) { pc_closesrc(ftmp); remove(tname); @@ -303,12 +303,12 @@ int pc_compile(int argc, char *argv[]) } /* for */ pc_closesrc(ftmp); strcpy(inpfname,tname); - strcpy(g_tmpfile,tname); + strcpy(g_tmpfile,tname); free(tname); } else { strcpy(inpfname,get_sourcefile(0)); } /* if */ - inpf_org=(FILE*)pc_opensrc(inpfname); + inpf_org=pc_opensrc(inpfname); if (inpf_org==NULL) error(160,inpfname); freading=TRUE; diff --git a/sourcepawn/compiler/sc2.c b/sourcepawn/compiler/sc2.c index 5024904b..e06af8cb 100644 --- a/sourcepawn/compiler/sc2.c +++ b/sourcepawn/compiler/sc2.c @@ -135,18 +135,18 @@ SC_FUNC void clearstk(void) SC_FUNC int plungequalifiedfile(char *name) { static char *extensions[] = { ".inc", ".p", ".pawn" }; - FILE *fp; + void *fp; char *ext; int ext_idx; ext_idx=0; do { - fp=(FILE*)pc_opensrc(name); + fp=pc_opensrc(name); ext=strchr(name,'\0'); /* save position */ if (fp==NULL) { /* try to append an extension */ strcpy(ext,extensions[ext_idx]); - fp=(FILE*)pc_opensrc(name); + fp=pc_opensrc(name); if (fp==NULL) *ext='\0'; /* on failure, restore filename */ } /* if */ @@ -326,7 +326,7 @@ static void readline(unsigned char *line) curlibrary=(constvalue *)POPSTK_P(); free(inpfname); /* return memory allocated for the include file name */ inpfname=(char *)POPSTK_P(); - inpf=(FILE *)POPSTK_P(); + inpf=POPSTK_P(); insert_dbgfile(inpfname); setfiledirect(inpfname); listline=-1; /* force a #line directive when changing the file */