| 
									
										
										
										
											2008-08-04 08:14:52 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * $Id$ | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-21 03:17:25 +00:00
										 |  |  | #include "awk.h"
 | 
					
						
							| 
									
										
										
										
											2008-08-04 08:13:03 +00:00
										 |  |  | #include <ase/utl/stdio.h>
 | 
					
						
							| 
									
										
										
										
											2008-08-04 08:14:52 +00:00
										 |  |  | #include <math.h>
 | 
					
						
							| 
									
										
										
										
											2008-08-04 08:13:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef struct ext_t | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ase_awk_prmfns_t prmfns; | 
					
						
							|  |  |  | }  | 
					
						
							|  |  |  | ext_t; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ase_real_t custom_awk_pow (void* custom, ase_real_t x, ase_real_t y) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return pow (x, y); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int custom_awk_sprintf ( | 
					
						
							|  |  |  | 	void* custom, ase_char_t* buf, ase_size_t size,  | 
					
						
							|  |  |  | 	const ase_char_t* fmt, ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	va_list ap; | 
					
						
							|  |  |  | 	va_start (ap, fmt); | 
					
						
							|  |  |  | 	n = ase_vsprintf (buf, size, fmt, ap); | 
					
						
							|  |  |  | 	va_end (ap); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return n; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void custom_awk_dprintf (void* custom, const ase_char_t* fmt, ...) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	va_list ap; | 
					
						
							|  |  |  | 	va_start (ap, fmt); | 
					
						
							| 
									
										
										
										
											2008-10-14 05:32:58 +00:00
										 |  |  | 	ase_vfprintf (ASE_STDERR, fmt, ap); | 
					
						
							| 
									
										
										
										
											2008-08-04 08:13:03 +00:00
										 |  |  | 	va_end (ap); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ase_awk_t* ase_awk_openstd (void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	ase_awk_t* awk; | 
					
						
							| 
									
										
										
										
											2008-08-04 08:14:52 +00:00
										 |  |  | 	ext_t* ext; | 
					
						
							| 
									
										
										
										
											2008-08-04 08:13:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-27 09:30:49 +00:00
										 |  |  | 	awk = ase_awk_open (ASE_MMGR_GETDFL(), ASE_SIZEOF(ext_t)); | 
					
						
							| 
									
										
										
										
											2008-08-21 04:58:19 +00:00
										 |  |  | 	ase_awk_setccls (awk, ASE_CCLS_GETDFL()); | 
					
						
							| 
									
										
										
										
											2008-08-04 08:13:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-28 03:51:23 +00:00
										 |  |  | 	ext = (ext_t*)ase_awk_getextension(awk); | 
					
						
							| 
									
										
										
										
											2008-08-19 05:21:48 +00:00
										 |  |  | 	ext->prmfns.pow     = custom_awk_pow; | 
					
						
							|  |  |  | 	ext->prmfns.sprintf = custom_awk_sprintf; | 
					
						
							|  |  |  | 	ext->prmfns.dprintf = custom_awk_dprintf; | 
					
						
							|  |  |  | 	ext->prmfns.data    = ASE_NULL; | 
					
						
							| 
									
										
										
										
											2008-08-04 08:13:03 +00:00
										 |  |  | 	ase_awk_setprmfns (awk, &ext->prmfns); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ase_awk_setoption (awk,  | 
					
						
							|  |  |  | 		ASE_AWK_IMPLICIT | ASE_AWK_EXTIO | ASE_AWK_NEWLINE |  | 
					
						
							|  |  |  | 		ASE_AWK_BASEONE | ASE_AWK_PABLOCK); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*ase_awk_addfunction ();*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return awk; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-10-01 05:14:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | typedef struct sf_t sf_t; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct sf_t | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct  | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2008-10-14 05:32:58 +00:00
										 |  |  | 		const ase_char_t*const* files;  | 
					
						
							|  |  |  | 		ase_size_t              count;  /* the number of files */ | 
					
						
							|  |  |  | 		ase_size_t              index;  /* current file index */ | 
					
						
							|  |  |  | 		ASE_FILE*               handle; /* the handle to an open file */ | 
					
						
							| 
									
										
										
										
											2008-10-01 05:14:20 +00:00
										 |  |  | 	} in; | 
					
						
							| 
									
										
										
										
											2008-10-13 09:08:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	struct | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2008-10-14 05:32:58 +00:00
										 |  |  | 		const ase_char_t*       file; | 
					
						
							|  |  |  | 		ASE_FILE*               handle; | 
					
						
							| 
									
										
										
										
											2008-10-13 09:08:26 +00:00
										 |  |  | 	} out; | 
					
						
							| 
									
										
										
										
											2008-10-01 05:14:20 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ase_ssize_t sf_in (int cmd, void* arg, ase_char_t* data, ase_size_t size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	sf_t* sf = (sf_t*)arg; | 
					
						
							|  |  |  | 	ase_cint_t c; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (cmd == ASE_AWK_IO_OPEN) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (sf->in.index >= sf->in.count) return 0; | 
					
						
							| 
									
										
										
										
											2008-10-14 05:32:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (sf->in.files[sf->in.index][0] == ASE_T('\0')) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			sf->in.handle = ASE_STDIN; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			sf->in.handle = ase_fopen (sf->in.files[sf->in.index], ASE_T("r")); | 
					
						
							|  |  |  | 			if (sf->in.handle == ASE_NULL) return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-10-01 05:14:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		/*
 | 
					
						
							|  |  |  | 		ase_awk_setsinname (); | 
					
						
							|  |  |  | 		*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (cmd == ASE_AWK_IO_CLOSE) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (sf->in.index >= sf->in.count) return 0; | 
					
						
							| 
									
										
										
										
											2008-10-14 05:32:58 +00:00
										 |  |  | 		if (sf->in.handle != ASE_STDIN) ase_fclose (sf->in.handle); | 
					
						
							| 
									
										
										
										
											2008-10-01 05:14:20 +00:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (cmd == ASE_AWK_IO_READ) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ase_ssize_t n = 0; | 
					
						
							|  |  |  | 		ASE_FILE* fp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	retry: | 
					
						
							|  |  |  | 		fp = sf->in.handle; | 
					
						
							|  |  |  | 		while (!ase_feof(fp) && n < size) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			ase_cint_t c = ase_fgetc (fp); | 
					
						
							|  |  |  | 			if (c == ASE_CHAR_EOF)  | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				if (ase_ferror(fp)) n = -1; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			data[n++] = c; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (n == 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			sf->in.index++; | 
					
						
							|  |  |  | 			if (sf->in.index < sf->in.count) | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2008-10-14 05:32:58 +00:00
										 |  |  | 				if (fp != ASE_STDIN) ase_fclose (fp); | 
					
						
							|  |  |  | 				if (sf->in.files[sf->in.index][0] == ASE_T('\0')) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					sf->in.handle = ASE_STDIN; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					sf->in.handle = ase_fopen (sf->in.files[sf->in.index], ASE_T("r")); | 
					
						
							|  |  |  | 					if (sf->in.handle == ASE_NULL) return -1; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2008-10-01 05:14:20 +00:00
										 |  |  | 				/* TODO: reset internal line counters...
 | 
					
						
							|  |  |  | 					ase_awk_setsinname (); | 
					
						
							|  |  |  | 				*/ | 
					
						
							|  |  |  | 				goto retry; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return n; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-14 05:32:58 +00:00
										 |  |  | static ase_ssize_t sf_out (int cmd, void* arg, ase_char_t* data, ase_size_t size) | 
					
						
							| 
									
										
										
										
											2008-10-01 05:14:20 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-10-14 05:32:58 +00:00
										 |  |  | 	sf_t* sf = (sf_t*)arg; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (cmd == ASE_AWK_IO_OPEN)  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (sf->out.file[0] == ASE_T('\0')) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			sf->out.handle = ASE_STDOUT; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else  | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2008-12-10 03:01:58 +00:00
										 |  |  | 			sf->out.handle = ase_fopen (sf->out.file, ASE_T("w")); | 
					
						
							| 
									
										
										
										
											2008-10-14 05:32:58 +00:00
										 |  |  | 			if (sf->out.handle == ASE_NULL) return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2008-10-01 05:14:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-14 05:32:58 +00:00
										 |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-10-01 05:14:20 +00:00
										 |  |  | 	else if (cmd == ASE_AWK_IO_CLOSE)  | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2008-10-14 05:32:58 +00:00
										 |  |  | 		ase_fflush (sf->out.handle); | 
					
						
							|  |  |  | 		if (sf->out.handle != ASE_STDOUT && | 
					
						
							|  |  |  | 		    sf->out.handle != ASE_STDERR) ase_fclose (sf->out.handle); | 
					
						
							| 
									
										
										
										
											2008-10-01 05:14:20 +00:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (cmd == ASE_AWK_IO_WRITE) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ase_size_t left = size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		while (left > 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if (*data == ASE_T('\0'))  | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2008-10-14 05:32:58 +00:00
										 |  |  | 				if (ase_fputc (*data, sf->out.handle) == ASE_CHAR_EOF) return -1; | 
					
						
							| 
									
										
										
										
											2008-10-01 05:14:20 +00:00
										 |  |  | 				left -= 1; data += 1; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				int chunk = (left > ASE_TYPE_MAX(int))? ASE_TYPE_MAX(int): (int)left; | 
					
						
							| 
									
										
										
										
											2008-10-14 05:32:58 +00:00
										 |  |  | 				int n = ase_fprintf (sf->out.handle, ASE_T("%.*s"), chunk, data); | 
					
						
							| 
									
										
										
										
											2008-10-01 05:14:20 +00:00
										 |  |  | 				if (n < 0) return -1; | 
					
						
							|  |  |  | 				left -= n; data += n; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return size; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-14 05:32:58 +00:00
										 |  |  | int ase_awk_parsefiles (ase_awk_t* awk, const ase_char_t*const* isf, ase_size_t isfl, const ase_char_t* osf) | 
					
						
							| 
									
										
										
										
											2008-10-01 05:14:20 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	sf_t sf; | 
					
						
							|  |  |  | 	ase_awk_srcios_t sio; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-14 05:32:58 +00:00
										 |  |  | 	if (isf == ASE_NULL || isfl == 0)  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		ase_awk_seterrnum (awk, ASE_AWK_EINVAL); | 
					
						
							|  |  |  | 		return -1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-13 09:08:26 +00:00
										 |  |  | 	sf.in.files = isf; | 
					
						
							|  |  |  | 	sf.in.count = isfl; | 
					
						
							| 
									
										
										
										
											2008-10-01 05:14:20 +00:00
										 |  |  | 	sf.in.index = 0; | 
					
						
							|  |  |  | 	sf.in.handle = ASE_NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-13 09:08:26 +00:00
										 |  |  | 	sf.out.file = osf; | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-10-01 05:14:20 +00:00
										 |  |  |         sio.in = sf_in; | 
					
						
							| 
									
										
										
										
											2008-10-14 05:32:58 +00:00
										 |  |  |         sio.out = (osf == ASE_NULL)? ASE_NULL: sf_out; | 
					
						
							| 
									
										
										
										
											2008-10-01 05:14:20 +00:00
										 |  |  |         sio.data = &sf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ase_awk_parse (awk, &sio); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  | int ase_awk_parsestring (ase_awk_t* awk, const ase_char_t* str, ase_size_t len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 |