Compiler: Use in-memory buffers for reading files, and handle newlines better.
Imported from https://github.com/alliedmodders/sourcemod/pull/63.
This commit is contained in:
parent
c2ca5d857d
commit
a876962405
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "sc.h"
|
#include "sc.h"
|
||||||
|
@ -119,6 +120,14 @@ static char *prefix[3]={ "error", "fatal error", "warning" };
|
||||||
return 0;
|
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()
|
/* pc_opensrc()
|
||||||
* Opens a source file (or include file) for reading. The "file" does not have
|
* Opens a source file (or include file) for reading. The "file" does not have
|
||||||
* to be a physical file, one might compile from memory.
|
* to be a physical file, one might compile from memory.
|
||||||
|
@ -133,7 +142,45 @@ static char *prefix[3]={ "error", "fatal error", "warning" };
|
||||||
*/
|
*/
|
||||||
void *pc_opensrc(char *filename)
|
void *pc_opensrc(char *filename)
|
||||||
{
|
{
|
||||||
return fopen(filename,"rt");
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (S_ISDIR(fileInfo.st_mode)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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()
|
/* pc_createsrc()
|
||||||
|
@ -150,7 +197,23 @@ void *pc_opensrc(char *filename)
|
||||||
*/
|
*/
|
||||||
void *pc_createsrc(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;
|
||||||
|
return src;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pc_closesrc()
|
/* pc_closesrc()
|
||||||
|
@ -159,8 +222,15 @@ void *pc_createsrc(char *filename)
|
||||||
*/
|
*/
|
||||||
void pc_closesrc(void *handle)
|
void pc_closesrc(void *handle)
|
||||||
{
|
{
|
||||||
assert(handle!=NULL);
|
src_file_t *src = (src_file_t *)handle;
|
||||||
fclose((FILE*)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_resetsrc()
|
/* pc_resetsrc()
|
||||||
|
@ -169,8 +239,12 @@ void pc_closesrc(void *handle)
|
||||||
*/
|
*/
|
||||||
void pc_resetsrc(void *handle,void *position)
|
void pc_resetsrc(void *handle,void *position)
|
||||||
{
|
{
|
||||||
assert(handle!=NULL);
|
src_file_t *src = (src_file_t *)handle;
|
||||||
fsetpos((FILE*)handle,(fpos_t *)position);
|
ptrdiff_t pos = (ptrdiff_t)position;
|
||||||
|
|
||||||
|
assert(!src->fp);
|
||||||
|
assert(pos >= 0 && src->buffer + pos <= src->end);
|
||||||
|
src->pos = src->buffer + pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* pc_readsrc()
|
/* pc_readsrc()
|
||||||
|
@ -179,7 +253,35 @@ void pc_resetsrc(void *handle,void *position)
|
||||||
*/
|
*/
|
||||||
char *pc_readsrc(void *handle,unsigned char *target,int maxchars)
|
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()
|
/* pc_writesrc()
|
||||||
|
@ -188,20 +290,51 @@ char *pc_readsrc(void *handle,unsigned char *target,int maxchars)
|
||||||
*/
|
*/
|
||||||
int pc_writesrc(void *handle,unsigned char *source)
|
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;
|
||||||
|
|
||||||
|
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 *pc_getpossrc(void *handle)
|
||||||
{
|
{
|
||||||
static fpos_t lastpos; /* may need to have a LIFO stack of such positions */
|
src_file_t *src = (src_file_t *)handle;
|
||||||
|
|
||||||
fgetpos((FILE*)handle,&lastpos);
|
assert(!src->fp);
|
||||||
return &lastpos;
|
return (void *)(ptrdiff_t)(src->pos - src->buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
int pc_eofsrc(void *handle)
|
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
|
/* should return a pointer, which is used as a "magic cookie" to all I/O
|
||||||
|
|
|
@ -508,7 +508,7 @@ int pc_compile(int argc, char *argv[])
|
||||||
if (get_sourcefile(1)!=NULL) {
|
if (get_sourcefile(1)!=NULL) {
|
||||||
/* there are at least two or more source files */
|
/* there are at least two or more source files */
|
||||||
char *tname,*sname;
|
char *tname,*sname;
|
||||||
FILE *ftmp,*fsrc;
|
void *ftmp,*fsrc;
|
||||||
int fidx;
|
int fidx;
|
||||||
#if defined __WIN32__ || defined _WIN32
|
#if defined __WIN32__ || defined _WIN32
|
||||||
tname=_tempnam(NULL,"pawn");
|
tname=_tempnam(NULL,"pawn");
|
||||||
|
@ -524,10 +524,10 @@ int pc_compile(int argc, char *argv[])
|
||||||
close(mkstemp(buffer));
|
close(mkstemp(buffer));
|
||||||
tname=buffer;
|
tname=buffer;
|
||||||
#endif
|
#endif
|
||||||
ftmp=(FILE*)pc_createsrc(tname);
|
ftmp=(void*)pc_createsrc(tname);
|
||||||
for (fidx=0; (sname=get_sourcefile(fidx))!=NULL; fidx++) {
|
for (fidx=0; (sname=get_sourcefile(fidx))!=NULL; fidx++) {
|
||||||
unsigned char tstring[128];
|
unsigned char tstring[128];
|
||||||
fsrc=(FILE*)pc_opensrc(sname);
|
fsrc=(void*)pc_opensrc(sname);
|
||||||
if (fsrc==NULL)
|
if (fsrc==NULL)
|
||||||
error(100,sname);
|
error(100,sname);
|
||||||
pc_writesrc(ftmp,(unsigned char*)"#file ");
|
pc_writesrc(ftmp,(unsigned char*)"#file ");
|
||||||
|
@ -545,7 +545,7 @@ int pc_compile(int argc, char *argv[])
|
||||||
} else {
|
} else {
|
||||||
strcpy(inpfname,get_sourcefile(0));
|
strcpy(inpfname,get_sourcefile(0));
|
||||||
} /* if */
|
} /* if */
|
||||||
inpf_org=(FILE*)pc_opensrc(inpfname);
|
inpf_org=(void*)pc_opensrc(inpfname);
|
||||||
if (inpf_org==NULL)
|
if (inpf_org==NULL)
|
||||||
error(100,inpfname);
|
error(100,inpfname);
|
||||||
freading=TRUE;
|
freading=TRUE;
|
||||||
|
|
|
@ -120,18 +120,18 @@ SC_FUNC void clearstk(void)
|
||||||
SC_FUNC int plungequalifiedfile(char *name)
|
SC_FUNC int plungequalifiedfile(char *name)
|
||||||
{
|
{
|
||||||
static char *extensions[] = { ".inc", ".p", ".pawn" };
|
static char *extensions[] = { ".inc", ".p", ".pawn" };
|
||||||
FILE *fp;
|
void *fp;
|
||||||
char *ext;
|
char *ext;
|
||||||
int ext_idx;
|
int ext_idx;
|
||||||
|
|
||||||
ext_idx=0;
|
ext_idx=0;
|
||||||
do {
|
do {
|
||||||
fp=(FILE*)pc_opensrc(name);
|
fp=(void*)pc_opensrc(name);
|
||||||
ext=strchr(name,'\0'); /* save position */
|
ext=strchr(name,'\0'); /* save position */
|
||||||
if (fp==NULL) {
|
if (fp==NULL) {
|
||||||
/* try to append an extension */
|
/* try to append an extension */
|
||||||
strcpy(ext,extensions[ext_idx]);
|
strcpy(ext,extensions[ext_idx]);
|
||||||
fp=(FILE*)pc_opensrc(name);
|
fp=(void*)pc_opensrc(name);
|
||||||
if (fp==NULL)
|
if (fp==NULL)
|
||||||
*ext='\0'; /* on failure, restore filename */
|
*ext='\0'; /* on failure, restore filename */
|
||||||
} /* if */
|
} /* if */
|
||||||
|
|
Loading…
Reference in New Issue
Block a user