286 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			286 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*	LIBPAWNC.C
 | |
|  *
 | |
|  *	A "glue file" for building the Pawn compiler as a DLL or shared library.
 | |
|  *
 | |
|  *	Copyright (c) ITB CompuPhase, 2000-2006
 | |
|  *
 | |
|  *	This software is provided "as-is", without any express or implied warranty.
 | |
|  *	In no event will the authors be held liable for any damages arising from
 | |
|  *	the use of this software.
 | |
|  *
 | |
|  *	Permission is granted to anyone to use this software for any purpose,
 | |
|  *	including commercial applications, and to alter it and redistribute it
 | |
|  *	freely, subject to the following restrictions:
 | |
|  *
 | |
|  *	1.	The origin of this software must not be misrepresented; you must not
 | |
|  *			claim that you wrote the original software. If you use this software in
 | |
|  *			a product, an acknowledgment in the product documentation would be
 | |
|  *			appreciated but is not required.
 | |
|  *	2.	Altered source versions must be plainly marked as such, and must not be
 | |
|  *			misrepresented as being the original software.
 | |
|  *	3.	This notice may not be removed or altered from any source distribution.
 | |
|  *
 | |
|  *  Version: $Id$
 | |
|  */
 | |
| #include <assert.h>
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| #include "sc.h"
 | |
| #include "memfile.h"
 | |
| 
 | |
| #if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined DARWIN
 | |
| #include <sys/types.h>
 | |
| #include <sys/stat.h>
 | |
| #endif
 | |
| 
 | |
| /* pc_printf()
 | |
|  * Called for general purpose "console" output. This function prints general
 | |
|  * purpose messages; errors go through pc_error(). The function is modelled
 | |
|  * after printf().
 | |
|  */
 | |
| int pc_printf(const char *message,...)
 | |
| {
 | |
| 	int ret;
 | |
| 	va_list argptr;
 | |
| 
 | |
| 	va_start(argptr,message);
 | |
| 	ret=vprintf(message,argptr);
 | |
| 	va_end(argptr);
 | |
| 
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| /* pc_error()
 | |
|  * Called for producing error output.
 | |
|  *		number			the error number (as documented in the manual)
 | |
|  *		message		 a string describing the error with embedded %d and %s tokens
 | |
|  *		filename		the name of the file currently being parsed
 | |
|  *		firstline	 the line number at which the expression started on which
 | |
|  *								the error was found, or -1 if there is no "starting line"
 | |
|  *		lastline		the line number at which the error was detected
 | |
|  *		argptr			a pointer to the first of a series of arguments (for macro
 | |
|  *								"va_arg")
 | |
|  * Return:
 | |
|  *		If the function returns 0, the parser attempts to continue compilation.
 | |
|  *		On a non-zero return value, the parser aborts.
 | |
|  */
 | |
| int pc_error(int number,char *message,char *filename,int firstline,int lastline,va_list argptr)
 | |
| {
 | |
| static char *prefix[3]={ "error", "fatal error", "warning" };
 | |
| 
 | |
| 	if (number!=0) {
 | |
| 		char *pre;
 | |
| 		int idx;
 | |
| 
 | |
| 		if (number < 120)
 | |
| 			idx = 0;
 | |
| 		else if (number < 200)
 | |
| 			idx = 1;
 | |
| 		else
 | |
| 			idx = 2;
 | |
| 
 | |
| 		pre=prefix[idx];
 | |
| 		if (firstline>=0)
 | |
| 			fprintf(stdout,"%s(%d -- %d) : %s %03d: ",filename,firstline,lastline,pre,number);
 | |
| 		else
 | |
| 			fprintf(stdout,"%s(%d) : %s %03d: ",filename,lastline,pre,number);
 | |
| 	} /* if */
 | |
| 	vfprintf(stdout,message,argptr);
 | |
| 	fflush(stdout);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /* 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.
 | |
|  *		filename		the name of the "file" to read from
 | |
|  * Return:
 | |
|  *		The function must return a pointer, which is used as a "magic cookie" to
 | |
|  *		all I/O functions. When failing to open the file for reading, the
 | |
|  *		function must return NULL.
 | |
|  * Note:
 | |
|  *		Several "source files" may be open at the same time. Specifically, one
 | |
|  *		file can be open for reading and another for writing.
 | |
|  */
 | |
| void *pc_opensrc(char *filename)
 | |
| {
 | |
| 	#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
 | |
| 
 | |
| 	return fopen(filename,"rt");
 | |
| }
 | |
| 
 | |
| /* pc_createsrc()
 | |
|  * Creates/overwrites a source file for writing. The "file" does not have
 | |
|  * to be a physical file, one might compile from memory.
 | |
|  *		filename		the name of the "file" to create
 | |
|  * Return:
 | |
|  *		The function must return a pointer which is used as a "magic cookie" to
 | |
|  *		all I/O functions. When failing to open the file for reading, the
 | |
|  *		function must return NULL.
 | |
|  * Note:
 | |
|  *		Several "source files" may be open at the same time. Specifically, one
 | |
|  *		file can be open for reading and another for writing.
 | |
|  */
 | |
| void *pc_createsrc(char *filename)
 | |
| {
 | |
| 	return fopen(filename,"wt");
 | |
| }
 | |
| 
 | |
| /* pc_closesrc()
 | |
|  * Closes a source file (or include file). The "handle" parameter has the
 | |
|  * value that pc_opensrc() returned in an earlier call.
 | |
|  */
 | |
| void pc_closesrc(void *handle)
 | |
| {
 | |
| 	assert(handle!=NULL);
 | |
| 	fclose((FILE*)handle);
 | |
| }
 | |
| 
 | |
| /* pc_resetsrc()
 | |
|  * "position" may only hold a pointer that was previously obtained from
 | |
|  * pc_getpossrc()
 | |
|  */
 | |
| void pc_resetsrc(void *handle,void *position)
 | |
| {
 | |
| 	assert(handle!=NULL);
 | |
| 	fsetpos((FILE*)handle,(fpos_t *)position);
 | |
| }
 | |
| 
 | |
| /* pc_readsrc()
 | |
|  * Reads a single line from the source file (or up to a maximum number of
 | |
|  * characters if the line in the input file is too long).
 | |
|  */
 | |
| char *pc_readsrc(void *handle,unsigned char *target,int maxchars)
 | |
| {
 | |
| 	return fgets((char*)target,maxchars,(FILE*)handle);
 | |
| }
 | |
| 
 | |
| /* pc_writesrc()
 | |
|  * Writes to to the source file. There is no automatic line ending; to end a
 | |
|  * line, write a "\n".
 | |
|  */
 | |
| int pc_writesrc(void *handle,unsigned char *source)
 | |
| {
 | |
| 	return fputs((char*)source,(FILE*)handle) >= 0;
 | |
| }
 | |
| 
 | |
| void *pc_getpossrc(void *handle)
 | |
| {
 | |
| 	static fpos_t lastpos;	/* may need to have a LIFO stack of such positions */
 | |
| 
 | |
| 	fgetpos((FILE*)handle,&lastpos);
 | |
| 	return &lastpos;
 | |
| }
 | |
| 
 | |
| int pc_eofsrc(void *handle)
 | |
| {
 | |
| 	return feof((FILE*)handle);
 | |
| }
 | |
| 
 | |
| /* should return a pointer, which is used as a "magic cookie" to all I/O
 | |
|  * functions; return NULL for failure
 | |
|  */
 | |
| void *pc_openasm(char *filename)
 | |
| {
 | |
| 	#if defined __MSDOS__ || defined SC_LIGHT
 | |
| 		return fopen(filename,"w+t");
 | |
| 	#else
 | |
| 		return mfcreate(filename);
 | |
| 	#endif
 | |
| }
 | |
| 
 | |
| void pc_closeasm(void *handle, int deletefile)
 | |
| {
 | |
| 	#if defined __MSDOS__ || defined SC_LIGHT
 | |
| 		if (handle!=NULL)
 | |
| 			fclose((FILE*)handle);
 | |
| 		if (deletefile)
 | |
| 			remove(outfname);
 | |
| 	#else
 | |
| 		if (handle!=NULL) {
 | |
| 			if (!deletefile)
 | |
| 				mfdump((MEMFILE*)handle);
 | |
| 			mfclose((MEMFILE*)handle);
 | |
| 		} /* if */
 | |
| 	#endif
 | |
| }
 | |
| 
 | |
| void pc_resetasm(void *handle)
 | |
| {
 | |
| 	assert(handle!=NULL);
 | |
| 	#if defined __MSDOS__ || defined SC_LIGHT
 | |
| 		fflush((FILE*)handle);
 | |
| 		fseek((FILE*)handle,0,SEEK_SET);
 | |
| 	#else
 | |
| 		mfseek((MEMFILE*)handle,0,SEEK_SET);
 | |
| 	#endif
 | |
| }
 | |
| 
 | |
| int pc_writeasm(void *handle,char *string)
 | |
| {
 | |
| 	#if defined __MSDOS__ || defined SC_LIGHT
 | |
| 		return fputs(string,(FILE*)handle) >= 0;
 | |
| 	#else
 | |
| 		return mfputs((MEMFILE*)handle,string);
 | |
| 	#endif
 | |
| }
 | |
| 
 | |
| char *pc_readasm(void *handle, char *string, int maxchars)
 | |
| {
 | |
| 	#if defined __MSDOS__ || defined SC_LIGHT
 | |
| 		return fgets(string,maxchars,(FILE*)handle);
 | |
| 	#else
 | |
| 		return mfgets((MEMFILE*)handle,string,maxchars);
 | |
| 	#endif
 | |
| }
 | |
| 
 | |
| extern memfile_t *bin_file;
 | |
| 
 | |
| /* Should return a pointer, which is used as a "magic cookie" to all I/O
 | |
|  * functions; return NULL for failure.
 | |
|  */
 | |
| void *pc_openbin(char *filename)
 | |
| {
 | |
| 	return memfile_creat(filename, 1);
 | |
| }
 | |
| 
 | |
| void pc_closebin(void *handle,int deletefile)
 | |
| {
 | |
| 	if (deletefile)
 | |
| 	{
 | |
| 		memfile_destroy((memfile_t *)handle);
 | |
| 		bin_file = NULL;
 | |
| 	} else {
 | |
| 		bin_file = (memfile_t *)handle;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /* pc_resetbin()
 | |
|  * Can seek to any location in the file.
 | |
|  * The offset is always from the start of the file.
 | |
|  */
 | |
| void pc_resetbin(void *handle,long offset)
 | |
| {
 | |
| 	memfile_seek((memfile_t *)handle, offset);
 | |
| }
 | |
| 
 | |
| int pc_writebin(void *handle,void *buffer,int size)
 | |
| {
 | |
| 	return memfile_write((memfile_t *)handle, buffer, size);
 | |
| }
 | |
| 
 | |
| long pc_lengthbin(void *handle)
 | |
| {
 | |
| 	return memfile_tell((memfile_t *)handle);
 | |
| }
 |