402 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			402 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * $Id: Awk.cpp,v 1.1 2006-12-09 11:50:07 bacon Exp $
 | |
|  */
 | |
| 
 | |
| #include "stdafx.h"
 | |
| #include "ase.h"
 | |
| #include "Awk.h"
 | |
| #include "Buffer.h"
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| #include <math.h>
 | |
| #include <wctype.h>
 | |
| #include <stdio.h>
 | |
| 
 | |
| STDMETHODIMP CAwk::InterfaceSupportsErrorInfo(REFIID riid)
 | |
| {
 | |
| 	static const IID* arr[] = 
 | |
| 	{
 | |
| 		&IID_IAwk,
 | |
| 	};
 | |
| 
 | |
| 	for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
 | |
| 	{
 | |
| 		if (/*Inline*/IsEqualGUID(*arr[i],riid))
 | |
| 			return S_OK;
 | |
| 	}
 | |
| 	return S_FALSE;
 | |
| }
 | |
| 
 | |
| CAwk::CAwk (): handle(NULL), 
 | |
| 	read_source_buf(NULL), write_source_buf(NULL)
 | |
| {
 | |
| #ifdef _DEBUG
 | |
| 	TCHAR x[128];
 | |
| 	_sntprintf (x, 128, _T("CAwk::CAwk %p"), this);
 | |
| 	MessageBox (NULL, x, x, MB_OK);
 | |
| #endif
 | |
| }
 | |
| 
 | |
| CAwk::~CAwk ()
 | |
| {
 | |
| #ifdef _DEBUG
 | |
| 	TCHAR x[128];
 | |
| 	_sntprintf (x, 128, _T("CAwk::~CAwk %p"), this);
 | |
| 	MessageBox (NULL, x, x, MB_OK);
 | |
| #endif
 | |
| 
 | |
| 	if (write_source_buf != NULL)
 | |
| 	{
 | |
| 		write_source_buf->Release ();
 | |
| 	}
 | |
| 
 | |
| 	if (read_source_buf != NULL)
 | |
| 	{
 | |
| 		read_source_buf->Release ();
 | |
| 	}
 | |
| 
 | |
| 	if (handle != NULL) 
 | |
| 	{
 | |
| 		ase_awk_close (handle);
 | |
| 		handle = NULL;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| static void* __awk_malloc (ase_size_t n, void* custom_data)
 | |
| {
 | |
| 	return malloc (n);
 | |
| }
 | |
| 
 | |
| static void* __awk_realloc (void* ptr, ase_size_t n, void* custom_data)
 | |
| {
 | |
| 	return realloc (ptr, n);
 | |
| }
 | |
| 
 | |
| static void __awk_free (void* ptr, void* custom_data)
 | |
| {
 | |
| 	free (ptr);
 | |
| }
 | |
| 
 | |
| static ase_real_t __awk_pow (ase_real_t x, ase_real_t y)
 | |
| {
 | |
| 	return pow (x, y);
 | |
| }
 | |
| 
 | |
| static int __awk_sprintf (
 | |
| 	ase_char_t* buf, ase_size_t len, const ase_char_t* fmt, ...)
 | |
| {
 | |
| 	int n;
 | |
| 	va_list ap;
 | |
| 
 | |
| 	va_start (ap, fmt);
 | |
| #if defined(_WIN32)
 | |
| 	n = _vsntprintf (buf, len, fmt, ap);
 | |
| 	if (n < 0 || (ase_size_t)n >= len)
 | |
| 	{
 | |
| 		if (len > 0) buf[len-1] = ASE_T('\0');
 | |
| 		n = -1;
 | |
| 	}
 | |
| #elif defined(__MSDOS__)
 | |
| 	/* TODO: check buffer overflow */
 | |
| 	n = vsprintf (buf, fmt, ap);
 | |
| #else
 | |
| 	n = xp_vsprintf (buf, len, fmt, ap);
 | |
| #endif
 | |
| 	va_end (ap);
 | |
| 	return n;
 | |
| }
 | |
| 
 | |
| static void __awk_aprintf (const ase_char_t* fmt, ...)
 | |
| {
 | |
| 	va_list ap;
 | |
| #ifdef _WIN32
 | |
| 	int n;
 | |
| 	ase_char_t buf[1024];
 | |
| #endif
 | |
| 
 | |
| 	va_start (ap, fmt);
 | |
| #if defined(_WIN32)
 | |
| 	n = _vsntprintf (buf, ASE_COUNTOF(buf), fmt, ap);
 | |
| 	if (n < 0) buf[ASE_COUNTOF(buf)-1] = ASE_T('\0');
 | |
| 
 | |
| 	#if defined(_MSC_VER) && (_MSC_VER<1400)
 | |
| 	MessageBox (NULL, buf, 
 | |
| 		ASE_T("Assertion Failure"), MB_OK|MB_ICONERROR);
 | |
| 	#else
 | |
| 	MessageBox (NULL, buf, 
 | |
| 		ASE_T("\uB2DD\uAE30\uB9AC \uC870\uB610"), MB_OK|MB_ICONERROR);
 | |
| 	#endif
 | |
| #elif defined(__MSDOS__)
 | |
| 	vprintf (fmt, ap);
 | |
| #else
 | |
| 	xp_vprintf (fmt, ap);
 | |
| #endif
 | |
| 	va_end (ap);
 | |
| }
 | |
| 
 | |
| static void __awk_dprintf (const ase_char_t* fmt, ...)
 | |
| {
 | |
| 	va_list ap;
 | |
| 	va_start (ap, fmt);
 | |
| 
 | |
| #if defined(_WIN32)
 | |
| 	_vftprintf (stderr, fmt, ap);
 | |
| #elif defined(__MSDOS__)
 | |
| 	vfprintf (stderr, fmt, ap);
 | |
| #else
 | |
| 	xp_vfprintf (stderr, fmt, ap);
 | |
| #endif
 | |
| 
 | |
| 	va_end (ap);
 | |
| }
 | |
| 
 | |
| static ase_ssize_t __read_source (
 | |
| 	int cmd, void* arg, ase_char_t* data, ase_size_t count)
 | |
| {
 | |
| 	CAwk* awk = (CAwk*)arg;
 | |
| 
 | |
| 	if (cmd == ASE_AWK_IO_OPEN) 
 | |
| 	{
 | |
| 		return (ase_ssize_t)awk->Fire_OpenSource (0);
 | |
| 	}
 | |
| 	else if (cmd == ASE_AWK_IO_CLOSE)
 | |
| 	{
 | |
| 		return (ase_ssize_t)awk->Fire_CloseSource (0);
 | |
| 	}
 | |
| 	else if (cmd == ASE_AWK_IO_READ)
 | |
| 	{
 | |
| 		HRESULT hr;
 | |
| 		CComBSTR val;
 | |
| 
 | |
| 		if (awk->read_source_buf == NULL)
 | |
| 		{
 | |
| 			hr = CoCreateInstance (
 | |
| 				CLSID_Buffer, NULL, CLSCTX_ALL, 
 | |
| 				IID_IBuffer, (void**)&awk->read_source_buf);
 | |
| 			if (FAILED(hr))
 | |
| 			{	
 | |
| MessageBox (NULL, _T("COCREATEINSTANCE FAILED"), _T("FUCK"), MB_OK);
 | |
| 				return -1;
 | |
| 			}
 | |
| 
 | |
| 			awk->read_source_pos = 0;
 | |
| 			awk->read_source_len = 0;
 | |
| 		}
 | |
| 
 | |
| 		if (awk->read_source_pos >= awk->read_source_len)
 | |
| 		{
 | |
| 			LONG n = awk->Fire_ReadSource (awk->read_source_buf);
 | |
| 			if (n <= 0) return (ase_ssize_t)n;
 | |
| 
 | |
| 			awk->read_source_buf->get_Value (&val);
 | |
| 			if (n > (LONG)val.Length()) return -1;
 | |
| 
 | |
| 			awk->read_source_pos = 0;
 | |
| 			awk->read_source_len = n;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			awk->read_source_buf->get_Value (&val);
 | |
| 		}
 | |
| 
 | |
| 		ASE_AWK_ASSERT (awk->handle, 
 | |
| 			awk->read_source_pos < awk->read_source_len);
 | |
| 
 | |
| 		LONG left = awk->read_source_len - awk->read_source_pos;
 | |
| 		if (left > (ase_ssize_t)count)
 | |
| 		{
 | |
| 			memcpy (data,
 | |
| 				((TCHAR*)(BSTR)val)+awk->read_source_pos, 
 | |
| 				count * ASE_SIZEOF(ase_char_t));
 | |
| 			awk->read_source_pos += count;
 | |
| 			return count;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			memcpy (data, 
 | |
| 				((TCHAR*)(BSTR)val)+awk->read_source_pos, 
 | |
| 				left * ASE_SIZEOF(ase_char_t));
 | |
| 			awk->read_source_pos = 0;
 | |
| 			awk->read_source_len = 0;
 | |
| 			return (ase_ssize_t)left;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	return -1;
 | |
| }
 | |
| 
 | |
| static ase_ssize_t __write_source (
 | |
| 	int cmd, void* arg, ase_char_t* data, ase_size_t count)
 | |
| {
 | |
| 	CAwk* awk = (CAwk*)arg;
 | |
| 
 | |
| 	if (cmd == ASE_AWK_IO_OPEN) 
 | |
| 	{
 | |
| 		return (ase_ssize_t)awk->Fire_OpenSource (1);
 | |
| 	}
 | |
| 	else if (cmd == ASE_AWK_IO_CLOSE)
 | |
| 	{
 | |
| 		return (ase_ssize_t)awk->Fire_CloseSource (1);
 | |
| 	}
 | |
| 	else if (cmd == ASE_AWK_IO_WRITE)
 | |
| 	{
 | |
| 		HRESULT hr;
 | |
| 
 | |
| 		if (awk->write_source_buf == NULL)
 | |
| 		{
 | |
| 			hr = CoCreateInstance (
 | |
| 				CLSID_Buffer, NULL, CLSCTX_ALL, 
 | |
| 				IID_IBuffer, (void**)&awk->write_source_buf);
 | |
| 			if (FAILED(hr))
 | |
| 			{	
 | |
| MessageBox (NULL, _T("COCREATEINSTANCE FAILED"), _T("FUCK"), MB_OK);
 | |
| 				return -1;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		awk->write_source_buf->put_Value (CComBSTR(count,data));
 | |
| 		LONG n = awk->Fire_WriteSource (awk->write_source_buf);
 | |
| 
 | |
| 		/*
 | |
| 		ASE_AWK_ASSERTX (
 | |
| 			awk->handle, n <= (LONG)count, 
 | |
| 			"the source code output stream should not return more than requested");
 | |
| 		*/
 | |
| 		if (n > (LONG)count) return -1; 
 | |
| 
 | |
| 		return (ase_ssize_t)n;
 | |
| 	}
 | |
| 
 | |
| 	return -1;
 | |
| }
 | |
| 
 | |
| HRESULT CAwk::Parse (int* ret)
 | |
| {
 | |
|  	if (handle == NULL)
 | |
| 	{
 | |
| 		ase_awk_syscas_t syscas;
 | |
| 
 | |
| 		memset (&syscas, 0, sizeof(syscas));
 | |
| 		syscas.malloc = __awk_malloc;
 | |
| 		syscas.realloc = __awk_realloc;
 | |
| 		syscas.free = __awk_free;
 | |
| 
 | |
| 		syscas.is_upper  = iswupper;
 | |
| 		syscas.is_lower  = iswlower;
 | |
| 		syscas.is_alpha  = iswalpha;
 | |
| 		syscas.is_digit  = iswdigit;
 | |
| 		syscas.is_xdigit = iswxdigit;
 | |
| 		syscas.is_alnum  = iswalnum;
 | |
| 		syscas.is_space  = iswspace;
 | |
| 		syscas.is_print  = iswprint;
 | |
| 		syscas.is_graph  = iswgraph;
 | |
| 		syscas.is_cntrl  = iswcntrl;
 | |
| 		syscas.is_punct  = iswpunct;
 | |
| 		syscas.to_upper  = towupper;
 | |
| 		syscas.to_lower  = towlower;
 | |
| 
 | |
| 		syscas.memcpy = memcpy;
 | |
| 		syscas.memset = memset;
 | |
| 		syscas.pow = __awk_pow;
 | |
| 		syscas.sprintf = __awk_sprintf;
 | |
| 		syscas.aprintf = __awk_aprintf;
 | |
| 		syscas.dprintf = __awk_dprintf;
 | |
| 		syscas.abort = abort;
 | |
| 
 | |
| 		handle = ase_awk_open (&syscas);
 | |
| 		if (handle == NULL)
 | |
| 		{
 | |
| 			*ret = -1;
 | |
| 			return S_OK;
 | |
| 		}
 | |
| 
 | |
| 		int opt = /*ASE_AWK_IMPLICIT | 
 | |
| 		      ASE_AWK_EXPLICIT | 
 | |
| 			  ASE_AWK_UNIQUEAFN | 
 | |
| 		      ASE_AWK_HASHSIGN | 
 | |
| 		      ASE_AWK_IDIV |
 | |
| 		      ASE_AWK_SHADING | 
 | |
| 		      ASE_AWK_SHIFT | */
 | |
| 		      ASE_AWK_EXTIO /*| 
 | |
| 		      ASE_AWK_BLOCKLESS | 
 | |
| 		      ASE_AWK_STRINDEXONE | 
 | |
| 		      ASE_AWK_STRIPSPACES | 
 | |
| 		      ASE_AWK_NEXTOFILE*/;
 | |
| 
 | |
| 		ase_awk_setopt (handle, opt);
 | |
| 	}
 | |
| 
 | |
| 	ase_awk_srcios_t srcios;
 | |
| 
 | |
| 	srcios.in = __read_source;
 | |
| 	srcios.out = __write_source;
 | |
| 	srcios.custom_data = this;
 | |
| 
 | |
| 	
 | |
| 	if (ase_awk_parse (handle, &srcios) == -1)
 | |
| 	{
 | |
| 		*ret = -1;
 | |
| 		return S_OK;
 | |
| 	}
 | |
| 
 | |
| 	*ret = 0;
 | |
| 	return S_OK;
 | |
| }
 | |
| 
 | |
| static ase_ssize_t __process_extio (
 | |
| 	int cmd, void* arg, ase_char_t* data, ase_size_t size)
 | |
| {
 | |
| 	ase_awk_extio_t* epa = (ase_awk_extio_t*)arg;
 | |
| 	CAwk* awk = (CAwk*)epa->custom_data;
 | |
| 
 | |
| 	if (cmd == ASE_AWK_IO_OPEN)
 | |
| 	{
 | |
| 				
 | |
| 	}
 | |
| 	else if (cmd == ASE_AWK_IO_CLOSE)
 | |
| 	{
 | |
| 	}
 | |
| 	else if (cmd == ASE_AWK_IO_READ)
 | |
| 	{
 | |
| 	}
 | |
| 	else if (cmd == ASE_AWK_IO_WRITE)
 | |
| 	{
 | |
| 	}
 | |
| 	else if (cmd == ASE_AWK_IO_FLUSH)
 | |
| 	{
 | |
| 	}
 | |
| 	else if (cmd == ASE_AWK_IO_NEXT)
 | |
| 	{
 | |
| 	}
 | |
| 
 | |
| 	return -1;
 | |
| }
 | |
| 
 | |
| HRESULT CAwk::Run (int* ret)
 | |
| {
 | |
| 	if (handle == NULL)
 | |
| 	{
 | |
| 		/* TODO: better error handling... */
 | |
| 		/* call parse first... */
 | |
| 		*ret = -1;
 | |
| 		return S_OK;
 | |
| 	}
 | |
| 
 | |
| 	ase_awk_runios_t runios;
 | |
| 	runios.pipe = __process_extio;
 | |
| 	runios.coproc = NULL;
 | |
| 	runios.file = NULL;
 | |
| 	runios.console = NULL;
 | |
| 	runios.custom_data = this;
 | |
| 
 | |
| 	if (ase_awk_run (handle, NULL, &runios, NULL, NULL, this) == -1)
 | |
| 	{
 | |
| 		*ret = -1;
 | |
| 		return S_OK;
 | |
| 	}
 | |
| 
 | |
| 	*ret = 0;
 | |
| 	return S_OK;
 | |
| }
 |