Use in-memory buffers for reading files, and handle newlines better.
This commit is contained in:
		
							parent
							
								
									e6f6e6df70
								
							
						
					
					
						commit
						10c8b78a16
					
				| @ -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 <assert.h> | ||||
| #include <stdio.h> | ||||
| #include <stddef.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #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; | ||||
| 	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 && srcposalloc[i]!=0; i++) | ||||
| 			/* nothing */; | ||||
| 		assert(i<MAXPOSITIONS); /* if not, there is a queue overrun */ | ||||
| 		if (i>=MAXPOSITIONS) | ||||
| 			return NULL; | ||||
| 		position=&srcpositions[i]; | ||||
| 		srcposalloc[i]=1; | ||||
| 	} else { | ||||
| 		/* use the gived slot */ | ||||
| 		assert((fpos_t*)position>=srcpositions && (fpos_t*)position<srcpositions+sizeof(srcpositions)); | ||||
| 	} /* if */ | ||||
| 	fgetpos((FILE*)handle,(fpos_t*)position); | ||||
| 	return position; | ||||
| 	src_file_t *src = (src_file_t *)handle; | ||||
| 
 | ||||
| 	assert(!src->fp); | ||||
| 	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
 | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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 */ | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user