| 
									
										
										
										
											2006-04-04 16:03:14 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2006-10-12 14:36:25 +00:00
										 |  |  |  * $Id: misc.c,v 1.28 2006-10-12 14:36:25 bacon Exp $ | 
					
						
							| 
									
										
										
										
											2006-04-04 16:03:14 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <xp/awk/awk_i.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-25 06:17:19 +00:00
										 |  |  | void* xp_awk_memcpy  (void* dst, const void* src, xp_size_t n) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	void* p = dst; | 
					
						
							|  |  |  | 	void* e = (xp_byte_t*)dst + n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (dst < e)  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		*(xp_byte_t*)dst = *(xp_byte_t*)src; | 
					
						
							|  |  |  | 		dst = (xp_byte_t*)dst + 1; | 
					
						
							|  |  |  | 		src = (xp_byte_t*)src + 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return p; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void* xp_awk_memset (void* dst, int val, xp_size_t n) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	void* p = dst; | 
					
						
							|  |  |  | 	void* e = (xp_byte_t*)p + n; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (p < e)  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		*(xp_byte_t*)p = (xp_byte_t)val; | 
					
						
							|  |  |  | 		p = (xp_byte_t*)p + 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return dst; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | xp_long_t xp_awk_strxtolong ( | 
					
						
							|  |  |  | 	xp_awk_t* awk, const xp_char_t* str, xp_size_t len, | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 	int base, const xp_char_t** endptr) | 
					
						
							| 
									
										
										
										
											2006-04-04 16:03:14 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	xp_long_t n = 0; | 
					
						
							|  |  |  | 	const xp_char_t* p; | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 	const xp_char_t* end; | 
					
						
							|  |  |  | 	xp_size_t rem; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 	int digit, negative = 0; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:03:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-12 04:17:58 +00:00
										 |  |  | 	xp_awk_assert (awk, base < 37);  | 
					
						
							| 
									
										
										
										
											2006-04-04 16:03:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 	p = str;  | 
					
						
							| 
									
										
										
										
											2006-10-06 03:37:40 +00:00
										 |  |  | 	end = str + len; | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2006-10-06 03:37:40 +00:00
										 |  |  | 	/* strip off leading spaces */ | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 	/*while (XP_AWK_ISSPACE(awk,*p)) p++;*/ | 
					
						
							| 
									
										
										
										
											2006-04-04 16:03:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-06 03:37:40 +00:00
										 |  |  | 	/* check for a sign */ | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 	/*while (*p != XP_T('\0')) */ | 
					
						
							|  |  |  | 	while (p < end) | 
					
						
							| 
									
										
										
										
											2006-04-04 16:03:14 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-05-06 12:52:36 +00:00
										 |  |  | 		if (*p == XP_T('-'))  | 
					
						
							| 
									
										
										
										
											2006-04-04 16:03:14 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 			negative = ~negative; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:03:14 +00:00
										 |  |  | 			p++; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-05-06 12:52:36 +00:00
										 |  |  | 		else if (*p == XP_T('+')) p++; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:03:14 +00:00
										 |  |  | 		else break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-06 03:37:40 +00:00
										 |  |  | 	/* check for a binary/octal/hexadecimal notation */ | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 	rem = end - p; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:03:14 +00:00
										 |  |  | 	if (base == 0)  | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 		if (rem >= 1 && *p == XP_T('0'))  | 
					
						
							| 
									
										
										
										
											2006-04-04 16:03:14 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			p++; | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if (rem == 1) base = 8; | 
					
						
							|  |  |  | 			else if (*p == XP_T('x') || *p == XP_T('X')) | 
					
						
							| 
									
										
										
										
											2006-04-04 16:03:14 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				p++; base = 16; | 
					
						
							|  |  |  | 			}  | 
					
						
							| 
									
										
										
										
											2006-05-06 12:52:36 +00:00
										 |  |  | 			else if (*p == XP_T('b') || *p == XP_T('B')) | 
					
						
							| 
									
										
										
										
											2006-04-04 16:22:01 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				p++; base = 2; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2006-04-04 16:03:14 +00:00
										 |  |  | 			else base = 8; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else base = 10; | 
					
						
							|  |  |  | 	}  | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 	else if (rem >= 2 && base == 16) | 
					
						
							| 
									
										
										
										
											2006-04-04 16:03:14 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-05-06 12:52:36 +00:00
										 |  |  | 		if (*p == XP_T('0') &&  | 
					
						
							|  |  |  | 		    (*(p+1) == XP_T('x') || *(p+1) == XP_T('X'))) p += 2;  | 
					
						
							| 
									
										
										
										
											2006-04-04 16:22:01 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 	else if (rem >= 2 && base == 2) | 
					
						
							| 
									
										
										
										
											2006-04-04 16:22:01 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-05-06 12:52:36 +00:00
										 |  |  | 		if (*p == XP_T('0') &&  | 
					
						
							|  |  |  | 		    (*(p+1) == XP_T('b') || *(p+1) == XP_T('B'))) p += 2;  | 
					
						
							| 
									
										
										
										
											2006-04-04 16:03:14 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-06 03:37:40 +00:00
										 |  |  | 	/* process the digits */ | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 	/*while (*p != XP_T('\0'))*/ | 
					
						
							|  |  |  | 	while (p < end) | 
					
						
							| 
									
										
										
										
											2006-04-04 16:03:14 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-05-06 12:52:36 +00:00
										 |  |  | 		if (*p >= XP_T('0') && *p <= XP_T('9')) | 
					
						
							|  |  |  | 			digit = *p - XP_T('0'); | 
					
						
							|  |  |  | 		else if (*p >= XP_T('A') && *p <= XP_T('Z')) | 
					
						
							|  |  |  | 			digit = *p - XP_T('A') + 10; | 
					
						
							|  |  |  | 		else if (*p >= XP_T('a') && *p <= XP_T('z')) | 
					
						
							|  |  |  | 			digit = *p - XP_T('a') + 10; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:03:14 +00:00
										 |  |  | 		else break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (digit >= base) break; | 
					
						
							|  |  |  | 		n = n * base + digit; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		p++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-16 04:31:38 +00:00
										 |  |  | 	if (endptr != XP_NULL) *endptr = p; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 	return (negative)? -n: n; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:03:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * xp_awk_strtoreal is almost a replica of strtod. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * strtod.c -- | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *      Source code for the "strtod" library procedure. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 1988-1993 The Regents of the University of California. | 
					
						
							|  |  |  |  * Copyright (c) 1994 Sun Microsystems, Inc. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Permission to use, copy, modify, and distribute this | 
					
						
							|  |  |  |  * software and its documentation for any purpose and without | 
					
						
							|  |  |  |  * fee is hereby granted, provided that the above copyright | 
					
						
							|  |  |  |  * notice appear in all copies.  The University of California | 
					
						
							|  |  |  |  * makes no representations about the suitability of this | 
					
						
							|  |  |  |  * software for any purpose.  It is provided "as is" without | 
					
						
							|  |  |  |  * express or implied warranty. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define MAX_EXPONENT 511
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | xp_real_t xp_awk_strtoreal (xp_awk_t* awk, const xp_char_t* str) | 
					
						
							| 
									
										
										
										
											2006-04-04 16:03:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 	/* 
 | 
					
						
							|  |  |  | 	 * Table giving binary powers of 10. Entry is 10^2^i.   | 
					
						
							|  |  |  | 	 * Used to convert decimal exponents into floating-point numbers. | 
					
						
							|  |  |  | 	 */  | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 	static xp_real_t powers_of_10[] =  | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 		10.,    100.,   1.0e4,   1.0e8,   1.0e16, | 
					
						
							|  |  |  | 		1.0e32, 1.0e64, 1.0e128, 1.0e256 | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 	xp_real_t fraction, dbl_exp, * d; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 	const xp_char_t* p; | 
					
						
							|  |  |  | 	xp_cint_t c; | 
					
						
							| 
									
										
										
										
											2006-04-10 14:53:48 +00:00
										 |  |  | 	int exp = 0;		/* Exponent read from "EX" field */ | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* 
 | 
					
						
							|  |  |  | 	 * Exponent that derives from the fractional part.  Under normal  | 
					
						
							|  |  |  | 	 * circumstatnces, it is the negative of the number of digits in F. | 
					
						
							|  |  |  | 	 * However, if I is very long, the last digits of I get dropped  | 
					
						
							|  |  |  | 	 * (otherwise a long I with a large negative exponent could cause an | 
					
						
							| 
									
										
										
										
											2006-04-26 15:53:17 +00:00
										 |  |  | 	 * unnecessary overflow on I alone).  In this case, frac_exp is  | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 	 * incremented one for each dropped digit.  | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-26 15:53:17 +00:00
										 |  |  | 	int frac_exp; | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 	int mant_size; /* Number of digits in mantissa. */ | 
					
						
							|  |  |  | 	int dec_pt;    /* Number of mantissa digits BEFORE decimal point */ | 
					
						
							|  |  |  | 	const xp_char_t *pexp;  /* Temporarily holds location of exponent in string */ | 
					
						
							| 
									
										
										
										
											2006-10-06 03:37:40 +00:00
										 |  |  | 	int negative = 0, exp_negative = 0; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	p = str; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-06 03:37:40 +00:00
										 |  |  | 	/* strip off leading blanks */  | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 	/*while (XP_AWK_ISSPACE(awk,*p)) p++;*/ | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-06 03:37:40 +00:00
										 |  |  | 	/* check for a sign */ | 
					
						
							| 
									
										
										
										
											2006-05-06 12:52:36 +00:00
										 |  |  | 	while (*p != XP_T('\0'))  | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-05-06 12:52:36 +00:00
										 |  |  | 		if (*p == XP_T('-'))  | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2006-10-06 03:37:40 +00:00
										 |  |  | 			negative = ~negative; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 			p++; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-05-06 12:52:36 +00:00
										 |  |  | 		else if (*p == XP_T('+')) p++; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 		else break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-10 14:53:48 +00:00
										 |  |  | 	/* Count the number of digits in the mantissa (including the decimal
 | 
					
						
							|  |  |  | 	 * point), and also locate the decimal point. */ | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 	dec_pt = -1; | 
					
						
							|  |  |  | 	for (mant_size = 0; ; mant_size++)  | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 		c = *p; | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 		if (!XP_AWK_ISDIGIT (awk, c))  | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if ((c != XP_T('.')) || (dec_pt >= 0)) break; | 
					
						
							|  |  |  | 			dec_pt = mant_size; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		p++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Now suck up the digits in the mantissa.  Use two integers to | 
					
						
							|  |  |  | 	 * collect 9 digits each (this is faster than using floating-point). | 
					
						
							|  |  |  | 	 * If the mantissa has more than 18 digits, ignore the extras, since | 
					
						
							|  |  |  | 	 * they can't affect the value anyway. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 	pexp = p; | 
					
						
							|  |  |  | 	p -= mant_size; | 
					
						
							|  |  |  | 	if (dec_pt < 0)  | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 		dec_pt = mant_size; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 	}  | 
					
						
							|  |  |  | 	else  | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 		mant_size--;	/* One of the digits was the point */ | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-04-26 15:53:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 	if (mant_size > 18)  | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 		frac_exp = dec_pt - 18; | 
					
						
							|  |  |  | 		mant_size = 18; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 	}  | 
					
						
							|  |  |  | 	else  | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 		frac_exp = dec_pt - mant_size; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 	if (mant_size == 0)  | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		fraction = 0.0; | 
					
						
							| 
									
										
										
										
											2006-04-26 15:53:17 +00:00
										 |  |  | 		/*p = str;*/ | 
					
						
							| 
									
										
										
										
											2006-10-06 14:35:17 +00:00
										 |  |  | 		p = pexp; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 		goto done; | 
					
						
							|  |  |  | 	}  | 
					
						
							|  |  |  | 	else  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		int frac1, frac2; | 
					
						
							|  |  |  | 		frac1 = 0; | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 		for ( ; mant_size > 9; mant_size--)  | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			c = *p; | 
					
						
							|  |  |  | 			p++; | 
					
						
							| 
									
										
										
										
											2006-05-06 12:52:36 +00:00
										 |  |  | 			if (c == XP_T('.'))  | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				c = *p; | 
					
						
							|  |  |  | 				p++; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2006-05-06 12:52:36 +00:00
										 |  |  | 			frac1 = 10 * frac1 + (c - XP_T('0')); | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		frac2 = 0; | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 		for (; mant_size > 0; mant_size--) { | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 			c = *p; | 
					
						
							|  |  |  | 			p++; | 
					
						
							| 
									
										
										
										
											2006-05-06 12:52:36 +00:00
										 |  |  | 			if (c == XP_T('.'))  | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				c = *p; | 
					
						
							|  |  |  | 				p++; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2006-05-06 12:52:36 +00:00
										 |  |  | 			frac2 = 10*frac2 + (c - XP_T('0')); | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		fraction = (1.0e9 * frac1) + frac2; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-04-10 14:53:48 +00:00
										 |  |  | 	/* Skim off the exponent */ | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 	p = pexp; | 
					
						
							| 
									
										
										
										
											2006-05-06 12:52:36 +00:00
										 |  |  | 	if ((*p == XP_T('E')) || (*p == XP_T('e')))  | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		p++; | 
					
						
							| 
									
										
										
										
											2006-05-06 12:52:36 +00:00
										 |  |  | 		if (*p == XP_T('-'))  | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2006-10-06 03:37:40 +00:00
										 |  |  | 			exp_negative = 1; | 
					
						
							|  |  |  | 			p++; | 
					
						
							|  |  |  | 		}  | 
					
						
							|  |  |  | 		else  | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if (*p == XP_T('+')) p++; | 
					
						
							|  |  |  | 			exp_negative = 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (!XP_AWK_ISDIGIT (awk, *p))  | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			/* p = pexp; */ | 
					
						
							| 
									
										
										
										
											2006-10-06 14:35:17 +00:00
										 |  |  | 			/* goto done; */ | 
					
						
							|  |  |  | 			goto no_exp; | 
					
						
							| 
									
										
										
										
											2006-10-06 03:37:40 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		while (XP_AWK_ISDIGIT (awk, *p))  | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			exp = exp * 10 + (*p - XP_T('0')); | 
					
						
							|  |  |  | 			p++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-06 14:35:17 +00:00
										 |  |  | no_exp: | 
					
						
							| 
									
										
										
										
											2006-10-06 03:37:40 +00:00
										 |  |  | 	if (exp_negative) exp = frac_exp - exp; | 
					
						
							|  |  |  | 	else exp = frac_exp + exp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Generate a floating-point number that represents the exponent. | 
					
						
							|  |  |  | 	 * Do this by processing the exponent one bit at a time to combine | 
					
						
							|  |  |  | 	 * many powers of 2 of 10. Then combine the exponent with the | 
					
						
							|  |  |  | 	 * fraction. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	if (exp < 0)  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		exp_negative = 1; | 
					
						
							|  |  |  | 		exp = -exp; | 
					
						
							|  |  |  | 	}  | 
					
						
							|  |  |  | 	else exp_negative = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (exp > MAX_EXPONENT) exp = MAX_EXPONENT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	dbl_exp = 1.0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for (d = powers_of_10; exp != 0; exp >>= 1, d++)  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (exp & 01) dbl_exp *= *d; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (exp_negative) fraction /= dbl_exp; | 
					
						
							|  |  |  | 	else fraction *= dbl_exp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | done: | 
					
						
							|  |  |  | 	return (negative)? -fraction: fraction; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | xp_real_t xp_awk_strxtoreal ( | 
					
						
							|  |  |  | 	xp_awk_t* awk, const xp_char_t* str, xp_size_t len,  | 
					
						
							|  |  |  | 	const xp_char_t** endptr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* 
 | 
					
						
							|  |  |  | 	 * Table giving binary powers of 10. Entry is 10^2^i.   | 
					
						
							|  |  |  | 	 * Used to convert decimal exponents into floating-point numbers. | 
					
						
							|  |  |  | 	 */  | 
					
						
							|  |  |  | 	static xp_real_t powers_of_10[] =  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		10.,    100.,   1.0e4,   1.0e8,   1.0e16, | 
					
						
							|  |  |  | 		1.0e32, 1.0e64, 1.0e128, 1.0e256 | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	xp_real_t fraction, dbl_exp, * d; | 
					
						
							|  |  |  | 	const xp_char_t* p, * end; | 
					
						
							|  |  |  | 	xp_cint_t c; | 
					
						
							|  |  |  | 	int exp = 0; /* Exponent read from "EX" field */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* 
 | 
					
						
							|  |  |  | 	 * Exponent that derives from the fractional part.  Under normal  | 
					
						
							|  |  |  | 	 * circumstatnces, it is the negative of the number of digits in F. | 
					
						
							|  |  |  | 	 * However, if I is very long, the last digits of I get dropped  | 
					
						
							|  |  |  | 	 * (otherwise a long I with a large negative exponent could cause an | 
					
						
							|  |  |  | 	 * unnecessary overflow on I alone).  In this case, frac_exp is  | 
					
						
							|  |  |  | 	 * incremented one for each dropped digit.  | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int frac_exp; | 
					
						
							|  |  |  | 	int mant_size; /* Number of digits in mantissa. */ | 
					
						
							|  |  |  | 	int dec_pt;    /* Number of mantissa digits BEFORE decimal point */ | 
					
						
							|  |  |  | 	const xp_char_t *pexp;  /* Temporarily holds location of exponent in string */ | 
					
						
							|  |  |  | 	int negative = 0, exp_negative = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	p = str; | 
					
						
							|  |  |  | 	end = str + len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Strip off leading blanks and check for a sign */ | 
					
						
							|  |  |  | 	/*while (XP_AWK_ISSPACE(awk,*p)) p++;*/ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*while (*p != XP_T('\0')) */ | 
					
						
							|  |  |  | 	while (p < end) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (*p == XP_T('-'))  | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			negative = ~negative; | 
					
						
							|  |  |  | 			p++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else if (*p == XP_T('+')) p++; | 
					
						
							|  |  |  | 		else break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Count the number of digits in the mantissa (including the decimal
 | 
					
						
							|  |  |  | 	 * point), and also locate the decimal point. */ | 
					
						
							|  |  |  | 	dec_pt = -1; | 
					
						
							|  |  |  | 	/*for (mant_size = 0; ; mant_size++) */ | 
					
						
							|  |  |  | 	for (mant_size = 0; p < end; mant_size++)  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		c = *p; | 
					
						
							|  |  |  | 		if (!XP_AWK_ISDIGIT (awk, c))  | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2006-10-06 14:35:17 +00:00
										 |  |  | 			if (c != XP_T('.') || dec_pt >= 0) break; | 
					
						
							| 
									
										
										
										
											2006-10-06 03:37:40 +00:00
										 |  |  | 			dec_pt = mant_size; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		p++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Now suck up the digits in the mantissa.  Use two integers to | 
					
						
							|  |  |  | 	 * collect 9 digits each (this is faster than using floating-point). | 
					
						
							|  |  |  | 	 * If the mantissa has more than 18 digits, ignore the extras, since | 
					
						
							|  |  |  | 	 * they can't affect the value anyway. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	pexp = p; | 
					
						
							|  |  |  | 	p -= mant_size; | 
					
						
							|  |  |  | 	if (dec_pt < 0)  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		dec_pt = mant_size; | 
					
						
							|  |  |  | 	}  | 
					
						
							|  |  |  | 	else  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		mant_size--;	/* One of the digits was the point */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (mant_size > 18)  /* TODO: is 18 correct for xp_real_t??? */ | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		frac_exp = dec_pt - 18; | 
					
						
							|  |  |  | 		mant_size = 18; | 
					
						
							|  |  |  | 	}  | 
					
						
							|  |  |  | 	else  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		frac_exp = dec_pt - mant_size; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (mant_size == 0)  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		fraction = 0.0; | 
					
						
							|  |  |  | 		/*p = str;*/ | 
					
						
							| 
									
										
										
										
											2006-10-06 14:35:17 +00:00
										 |  |  | 		p = pexp; | 
					
						
							| 
									
										
										
										
											2006-10-06 03:37:40 +00:00
										 |  |  | 		goto done; | 
					
						
							|  |  |  | 	}  | 
					
						
							|  |  |  | 	else  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		int frac1, frac2; | 
					
						
							| 
									
										
										
										
											2006-10-06 14:35:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-06 03:37:40 +00:00
										 |  |  | 		frac1 = 0; | 
					
						
							|  |  |  | 		for ( ; mant_size > 9; mant_size--)  | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			c = *p; | 
					
						
							|  |  |  | 			p++; | 
					
						
							|  |  |  | 			if (c == XP_T('.'))  | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				c = *p; | 
					
						
							|  |  |  | 				p++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			frac1 = 10 * frac1 + (c - XP_T('0')); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-10-06 14:35:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-06 03:37:40 +00:00
										 |  |  | 		frac2 = 0; | 
					
						
							|  |  |  | 		for (; mant_size > 0; mant_size--) { | 
					
						
							| 
									
										
										
										
											2006-10-06 14:35:17 +00:00
										 |  |  | 			c = *p++; | 
					
						
							| 
									
										
										
										
											2006-10-06 03:37:40 +00:00
										 |  |  | 			if (c == XP_T('.'))  | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				c = *p; | 
					
						
							|  |  |  | 				p++; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2006-10-06 14:35:17 +00:00
										 |  |  | 			frac2 = 10 * frac2 + (c - XP_T('0')); | 
					
						
							| 
									
										
										
										
											2006-10-06 03:37:40 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		fraction = (1.0e9 * frac1) + frac2; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Skim off the exponent */ | 
					
						
							|  |  |  | 	p = pexp; | 
					
						
							| 
									
										
										
										
											2006-10-06 14:35:17 +00:00
										 |  |  | 	if (p < end && (*p == XP_T('E') || *p == XP_T('e')))  | 
					
						
							| 
									
										
										
										
											2006-10-06 03:37:40 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		p++; | 
					
						
							| 
									
										
										
										
											2006-10-06 14:35:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (p < end)  | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2006-10-06 14:35:17 +00:00
										 |  |  | 			if (*p == XP_T('-'))  | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				exp_negative = 1; | 
					
						
							|  |  |  | 				p++; | 
					
						
							|  |  |  | 			}  | 
					
						
							|  |  |  | 			else  | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				if (*p == XP_T('+')) p++; | 
					
						
							|  |  |  | 				exp_negative = 0; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-10-06 14:35:17 +00:00
										 |  |  | 		else exp_negative = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!(p < end && XP_AWK_ISDIGIT (awk, *p)))  | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2006-10-06 14:35:17 +00:00
										 |  |  | 			/*p = pexp;*/ | 
					
						
							|  |  |  | 			/*goto done;*/ | 
					
						
							|  |  |  | 			goto no_exp; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-10-06 14:35:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		while (p < end && XP_AWK_ISDIGIT (awk, *p))  | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2006-05-06 12:52:36 +00:00
										 |  |  | 			exp = exp * 10 + (*p - XP_T('0')); | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 			p++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-06 14:35:17 +00:00
										 |  |  | no_exp: | 
					
						
							| 
									
										
										
										
											2006-10-06 03:37:40 +00:00
										 |  |  | 	if (exp_negative) exp = frac_exp - exp; | 
					
						
							| 
									
										
										
										
											2006-04-26 15:53:17 +00:00
										 |  |  | 	else exp = frac_exp + exp; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Generate a floating-point number that represents the exponent. | 
					
						
							|  |  |  | 	 * Do this by processing the exponent one bit at a time to combine | 
					
						
							|  |  |  | 	 * many powers of 2 of 10. Then combine the exponent with the | 
					
						
							|  |  |  | 	 * fraction. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	if (exp < 0)  | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-10-06 03:37:40 +00:00
										 |  |  | 		exp_negative = 1; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 		exp = -exp; | 
					
						
							|  |  |  | 	}  | 
					
						
							| 
									
										
										
										
											2006-10-06 03:37:40 +00:00
										 |  |  | 	else exp_negative = 0; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (exp > MAX_EXPONENT) exp = MAX_EXPONENT; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 	dbl_exp = 1.0; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 	for (d = powers_of_10; exp != 0; exp >>= 1, d++)  | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 		if (exp & 01) dbl_exp *= *d; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-06 03:37:40 +00:00
										 |  |  | 	if (exp_negative) fraction /= dbl_exp; | 
					
						
							| 
									
										
										
										
											2006-10-05 14:20:57 +00:00
										 |  |  | 	else fraction *= dbl_exp; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:45:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | done: | 
					
						
							| 
									
										
										
										
											2006-10-06 14:35:17 +00:00
										 |  |  | 	if (endptr != XP_NULL) *endptr = p; | 
					
						
							| 
									
										
										
										
											2006-10-06 03:37:40 +00:00
										 |  |  | 	return (negative)? -fraction: fraction; | 
					
						
							| 
									
										
										
										
											2006-04-04 16:03:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-01 16:31:13 +00:00
										 |  |  | xp_size_t xp_awk_longtostr ( | 
					
						
							|  |  |  | 	xp_long_t value, int radix, const xp_char_t* prefix,  | 
					
						
							|  |  |  | 	xp_char_t* buf, xp_size_t size) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xp_long_t t, rem; | 
					
						
							|  |  |  | 	xp_size_t len, ret, i; | 
					
						
							|  |  |  | 	xp_size_t prefix_len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	prefix_len = (prefix != XP_NULL)? xp_awk_strlen(prefix): 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t = value; | 
					
						
							|  |  |  | 	if (t == 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* zero */ | 
					
						
							|  |  |  | 		if (buf == XP_NULL) return prefix_len + 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (size < prefix_len+1)  | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			/* buffer too small */ | 
					
						
							|  |  |  | 			return (xp_size_t)-1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for (i = 0; i < prefix_len; i++) buf[i] = prefix[i]; | 
					
						
							|  |  |  | 		buf[prefix_len] = XP_T('0'); | 
					
						
							|  |  |  | 		if (size > prefix_len+1) buf[prefix_len+1] = XP_T('\0'); | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* non-zero values */ | 
					
						
							|  |  |  | 	len = prefix_len; | 
					
						
							|  |  |  | 	if (t < 0) { t = -t; len++; } | 
					
						
							|  |  |  | 	while (t > 0) { len++; t /= radix; } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (buf == XP_NULL) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* if buf is not given, return the number of bytes required */ | 
					
						
							|  |  |  | 		return len; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (size < len) return (xp_size_t)-1; /* buffer too small */ | 
					
						
							|  |  |  | 	if (size > len) buf[len] = XP_T('\0'); | 
					
						
							|  |  |  | 	ret = len; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t = value; | 
					
						
							|  |  |  | 	if (t < 0) t = -t; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (t > 0)  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		rem = t % radix; | 
					
						
							|  |  |  | 		if (rem >= 10) | 
					
						
							|  |  |  | 			buf[--len] = (xp_char_t)rem + XP_T('a') - 10; | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			buf[--len] = (xp_char_t)rem + XP_T('0'); | 
					
						
							|  |  |  | 		t /= radix; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (value < 0)  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		for (i = 1; i <= prefix_len; i++)  | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			buf[i] = prefix[i-1]; | 
					
						
							|  |  |  | 			len--; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		buf[--len] = XP_T('-'); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		for (i = 0; i < prefix_len; i++) buf[i] = prefix[i]; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-01 03:44:51 +00:00
										 |  |  | xp_char_t* xp_awk_strdup (xp_awk_t* awk, const xp_char_t* str) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xp_char_t* tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tmp = (xp_char_t*) XP_AWK_MALLOC ( | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 		awk, (xp_awk_strlen(str) + 1) * xp_sizeof(xp_char_t)); | 
					
						
							| 
									
										
										
										
											2006-09-01 03:44:51 +00:00
										 |  |  | 	if (tmp == XP_NULL) return XP_NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 	xp_awk_strcpy (tmp, str); | 
					
						
							| 
									
										
										
										
											2006-09-01 03:44:51 +00:00
										 |  |  | 	return tmp; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | xp_char_t* xp_awk_strxdup (xp_awk_t* awk, const xp_char_t* str, xp_size_t len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xp_char_t* tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tmp = (xp_char_t*) XP_AWK_MALLOC ( | 
					
						
							|  |  |  | 		awk, (len + 1) * xp_sizeof(xp_char_t)); | 
					
						
							|  |  |  | 	if (tmp == XP_NULL) return XP_NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 	xp_awk_strncpy (tmp, str, len); | 
					
						
							| 
									
										
										
										
											2006-09-01 03:44:51 +00:00
										 |  |  | 	return tmp; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | xp_char_t* xp_awk_strxdup2 ( | 
					
						
							|  |  |  | 	xp_awk_t* awk, | 
					
						
							|  |  |  | 	const xp_char_t* str1, xp_size_t len1, | 
					
						
							|  |  |  | 	const xp_char_t* str2, xp_size_t len2) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xp_char_t* tmp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tmp = (xp_char_t*) XP_AWK_MALLOC ( | 
					
						
							|  |  |  | 		awk, (len1 + len2 + 1) * xp_sizeof(xp_char_t)); | 
					
						
							|  |  |  | 	if (tmp == XP_NULL) return XP_NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 	xp_awk_strncpy (tmp, str1, len1); | 
					
						
							|  |  |  | 	xp_awk_strncpy (tmp + len1, str2, len2); | 
					
						
							|  |  |  | 	return tmp; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | xp_size_t xp_awk_strlen (const xp_char_t* str) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const xp_char_t* p = str; | 
					
						
							|  |  |  | 	while (*p != XP_T('\0')) p++; | 
					
						
							|  |  |  | 	return p - str; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | xp_size_t xp_awk_strcpy (xp_char_t* buf, const xp_char_t* str) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xp_char_t* org = buf; | 
					
						
							|  |  |  | 	while ((*buf++ = *str++) != XP_T('\0')); | 
					
						
							|  |  |  | 	return buf - org - 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | xp_size_t xp_awk_strncpy (xp_char_t* buf, const xp_char_t* str, xp_size_t len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const xp_char_t* end = str + len; | 
					
						
							|  |  |  | 	while (str < end) *buf++ = *str++; | 
					
						
							|  |  |  | 	*buf = XP_T('\0'); | 
					
						
							|  |  |  | 	return len; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int xp_awk_strcmp (const xp_char_t* s1, const xp_char_t* s2) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	while (*s1 == *s2)  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		if (*s1 == XP_C('\0')) return 0; | 
					
						
							|  |  |  | 		s1++, s2++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return (*s1 > *s2)? 1: -1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int xp_awk_strxncmp ( | 
					
						
							|  |  |  | 	const xp_char_t* s1, xp_size_t len1,  | 
					
						
							|  |  |  | 	const xp_char_t* s2, xp_size_t len2) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-10-09 14:37:42 +00:00
										 |  |  | 	xp_char_t c1, c2; | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 	const xp_char_t* end1 = s1 + len1; | 
					
						
							|  |  |  | 	const xp_char_t* end2 = s2 + len2; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-09 14:37:42 +00:00
										 |  |  | 	while (s1 < end1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		c1 = *s1; | 
					
						
							|  |  |  | 		if (s2 < end2)  | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			c2 = *s2; | 
					
						
							|  |  |  | 			if (c1 > c2) return 1; | 
					
						
							|  |  |  | 			if (c1 < c2) return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else return 1; | 
					
						
							|  |  |  | 		s1++; s2++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return (s2 < end2)? -1: 0; | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-10 15:50:34 +00:00
										 |  |  | int xp_awk_strxncasecmp ( | 
					
						
							|  |  |  | 	xp_awk_t* awk, | 
					
						
							|  |  |  | 	const xp_char_t* s1, xp_size_t len1,  | 
					
						
							|  |  |  | 	const xp_char_t* s2, xp_size_t len2) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	xp_char_t c1, c2; | 
					
						
							|  |  |  | 	const xp_char_t* end1 = s1 + len1; | 
					
						
							|  |  |  | 	const xp_char_t* end2 = s2 + len2; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-09 14:37:42 +00:00
										 |  |  | 	while (s1 < end1) | 
					
						
							| 
									
										
										
										
											2006-09-10 15:50:34 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		c1 = XP_AWK_TOUPPER (awk, *s1);  | 
					
						
							| 
									
										
										
										
											2006-10-09 14:37:42 +00:00
										 |  |  | 		if (s2 < end2)  | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			c2 = XP_AWK_TOUPPER (awk, *s2); | 
					
						
							|  |  |  | 			if (c1 > c2) return 1; | 
					
						
							|  |  |  | 			if (c1 < c2) return -1; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else return 1; | 
					
						
							|  |  |  | 		s1++; s2++; | 
					
						
							| 
									
										
										
										
											2006-09-10 15:50:34 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-10-09 14:37:42 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return (s2 < end2)? -1: 0; | 
					
						
							| 
									
										
										
										
											2006-09-10 15:50:34 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | xp_char_t* xp_awk_strxnstr ( | 
					
						
							|  |  |  | 	const xp_char_t* str, xp_size_t strsz,  | 
					
						
							|  |  |  | 	const xp_char_t* sub, xp_size_t subsz) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const xp_char_t* end, * subp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (subsz == 0) return (xp_char_t*)str; | 
					
						
							|  |  |  | 	if (strsz < subsz) return XP_NULL; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	end = str + strsz - subsz; | 
					
						
							|  |  |  | 	subp = sub + subsz; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while (str <= end) { | 
					
						
							|  |  |  | 		const xp_char_t* x = str; | 
					
						
							|  |  |  | 		const xp_char_t* y = sub; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		while (xp_true) { | 
					
						
							|  |  |  | 			if (y >= subp) return (xp_char_t*)str; | 
					
						
							|  |  |  | 			if (*x != *y) break; | 
					
						
							|  |  |  | 			x++; y++; | 
					
						
							|  |  |  | 		}	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		str++; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	return XP_NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | xp_char_t* xp_awk_strtok ( | 
					
						
							| 
									
										
										
										
											2006-09-08 15:26:49 +00:00
										 |  |  | 	xp_awk_run_t* run, const xp_char_t* s,  | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 	const xp_char_t* delim, xp_char_t** tok, xp_size_t* tok_len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return xp_awk_strxntok ( | 
					
						
							| 
									
										
										
										
											2006-09-08 15:26:49 +00:00
										 |  |  | 		run, s, xp_awk_strlen(s),  | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 		delim, xp_awk_strlen(delim), tok, tok_len); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | xp_char_t* xp_awk_strxtok ( | 
					
						
							| 
									
										
										
										
											2006-09-08 15:26:49 +00:00
										 |  |  | 	xp_awk_run_t* run, const xp_char_t* s, xp_size_t len, | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 	const xp_char_t* delim, xp_char_t** tok, xp_size_t* tok_len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return xp_awk_strxntok ( | 
					
						
							| 
									
										
										
										
											2006-09-08 15:26:49 +00:00
										 |  |  | 		run, s, len,  | 
					
						
							| 
									
										
										
										
											2006-09-03 15:47:11 +00:00
										 |  |  | 		delim, xp_awk_strlen(delim), tok, tok_len); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | xp_char_t* xp_awk_strntok ( | 
					
						
							| 
									
										
										
										
											2006-09-08 15:26:49 +00:00
										 |  |  | 	xp_awk_run_t* run, const xp_char_t* s,  | 
					
						
							| 
									
										
										
										
											2006-09-03 15:47:11 +00:00
										 |  |  | 	const xp_char_t* delim, xp_size_t delim_len, | 
					
						
							|  |  |  | 	xp_char_t** tok, xp_size_t* tok_len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return xp_awk_strxntok ( | 
					
						
							| 
									
										
										
										
											2006-09-08 15:26:49 +00:00
										 |  |  | 		run, s, xp_awk_strlen(s),  | 
					
						
							| 
									
										
										
										
											2006-09-03 15:47:11 +00:00
										 |  |  | 		delim, delim_len, tok, tok_len); | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | xp_char_t* xp_awk_strxntok ( | 
					
						
							| 
									
										
										
										
											2006-09-08 15:26:49 +00:00
										 |  |  | 	xp_awk_run_t* run, const xp_char_t* s, xp_size_t len, | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 	const xp_char_t* delim, xp_size_t delim_len,  | 
					
						
							|  |  |  | 	xp_char_t** tok, xp_size_t* tok_len) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	const xp_char_t* p = s, *d; | 
					
						
							|  |  |  | 	const xp_char_t* end = s + len;	 | 
					
						
							|  |  |  | 	const xp_char_t* sp = XP_NULL, * ep = XP_NULL; | 
					
						
							|  |  |  | 	const xp_char_t* delim_end = delim + delim_len; | 
					
						
							|  |  |  | 	xp_char_t c;  | 
					
						
							|  |  |  | 	int delim_mode; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-03 15:47:11 +00:00
										 |  |  | #define __DELIM_NULL      0
 | 
					
						
							|  |  |  | #define __DELIM_EMPTY     1
 | 
					
						
							|  |  |  | #define __DELIM_SPACES    2
 | 
					
						
							|  |  |  | #define __DELIM_NOSPACES  3
 | 
					
						
							|  |  |  | #define __DELIM_COMPOSITE 4
 | 
					
						
							|  |  |  | 	if (delim == XP_NULL) delim_mode = __DELIM_NULL; | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 	else  | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-09-03 15:47:11 +00:00
										 |  |  | 		delim_mode = __DELIM_EMPTY; | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-03 15:47:11 +00:00
										 |  |  | 		for (d = delim; d < delim_end; d++)  | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2006-09-08 15:26:49 +00:00
										 |  |  | 			if (XP_AWK_ISSPACE(run->awk,*d))  | 
					
						
							| 
									
										
										
										
											2006-09-03 15:47:11 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				if (delim_mode == __DELIM_EMPTY) | 
					
						
							|  |  |  | 					delim_mode = __DELIM_SPACES; | 
					
						
							|  |  |  | 				else if (delim_mode == __DELIM_NOSPACES) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					delim_mode = __DELIM_COMPOSITE; | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				if (delim_mode == __DELIM_EMPTY) | 
					
						
							|  |  |  | 					delim_mode = __DELIM_NOSPACES; | 
					
						
							|  |  |  | 				else if (delim_mode == __DELIM_SPACES) | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					delim_mode = __DELIM_COMPOSITE; | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}		 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (delim_mode == __DELIM_NULL)  | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 	{  | 
					
						
							| 
									
										
										
										
											2006-09-03 15:47:11 +00:00
										 |  |  | 		/* when XP_NULL is given as "delim", it trims off the 
 | 
					
						
							|  |  |  | 		 * leading and trailing spaces characters off the source | 
					
						
							|  |  |  | 		 * string "s" eventually. */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-08 15:26:49 +00:00
										 |  |  | 		while (p < end && XP_AWK_ISSPACE(run->awk,*p)) p++; | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 		while (p < end)  | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			c = *p; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-08 15:26:49 +00:00
										 |  |  | 			if (!XP_AWK_ISSPACE(run->awk,c))  | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				if (sp == XP_NULL) sp = p; | 
					
						
							|  |  |  | 				ep = p; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			p++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-09-03 15:47:11 +00:00
										 |  |  | 	else if (delim_mode == __DELIM_EMPTY) | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-09-03 15:47:11 +00:00
										 |  |  | 		/* each character in the source string "s" becomes a token. */ | 
					
						
							|  |  |  | 		if (p < end) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			c = *p; | 
					
						
							|  |  |  | 			sp = p; | 
					
						
							|  |  |  | 			ep = p++; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (delim_mode == __DELIM_SPACES)  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		/* each token is delimited by space characters. all leading
 | 
					
						
							|  |  |  | 		 * and trailing spaces are removed. */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-08 15:26:49 +00:00
										 |  |  | 		while (p < end && XP_AWK_ISSPACE(run->awk,*p)) p++; | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 		while (p < end)  | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			c = *p; | 
					
						
							| 
									
										
										
										
											2006-09-08 15:26:49 +00:00
										 |  |  | 			if (XP_AWK_ISSPACE(run->awk,c)) break; | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 			if (sp == XP_NULL) sp = p; | 
					
						
							|  |  |  | 			ep = p++; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-09-08 15:26:49 +00:00
										 |  |  | 		while (p < end && XP_AWK_ISSPACE(run->awk,*p)) p++; | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-09-03 15:47:11 +00:00
										 |  |  | 	else if (delim_mode == __DELIM_NOSPACES) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-09-05 04:11:11 +00:00
										 |  |  | 		/* each token is delimited by one of charaters 
 | 
					
						
							|  |  |  | 		 * in the delimeter set "delim". */ | 
					
						
							| 
									
										
										
										
											2006-09-22 14:05:30 +00:00
										 |  |  | 		if (run->global.ignorecase) | 
					
						
							| 
									
										
										
										
											2006-09-03 15:47:11 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2006-09-09 04:52:40 +00:00
										 |  |  | 			while (p < end)  | 
					
						
							| 
									
										
										
										
											2006-09-03 15:47:11 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2006-09-09 04:52:40 +00:00
										 |  |  | 				c = XP_AWK_TOUPPER(run->awk, *p); | 
					
						
							|  |  |  | 				for (d = delim; d < delim_end; d++)  | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					if (c == XP_AWK_TOUPPER(run->awk,*d)) goto exit_loop; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (sp == XP_NULL) sp = p; | 
					
						
							|  |  |  | 				ep = p++; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			while (p < end)  | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				c = *p; | 
					
						
							|  |  |  | 				for (d = delim; d < delim_end; d++)  | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					if (c == *d) goto exit_loop; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (sp == XP_NULL) sp = p; | 
					
						
							|  |  |  | 				ep = p++; | 
					
						
							| 
									
										
										
										
											2006-09-03 15:47:11 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else /* if (delim_mode == __DELIM_COMPOSITE) */  | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-09-05 04:11:11 +00:00
										 |  |  | 		/* each token is delimited by one of non-space charaters
 | 
					
						
							|  |  |  | 		 * in the delimeter set "delim". however, all space characters | 
					
						
							|  |  |  | 		 * surrounding the token are removed */ | 
					
						
							| 
									
										
										
										
											2006-09-08 15:26:49 +00:00
										 |  |  | 		while (p < end && XP_AWK_ISSPACE(run->awk,*p)) p++; | 
					
						
							| 
									
										
										
										
											2006-09-22 14:05:30 +00:00
										 |  |  | 		if (run->global.ignorecase) | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2006-09-09 04:52:40 +00:00
										 |  |  | 			while (p < end)  | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2006-09-09 04:52:40 +00:00
										 |  |  | 				c = XP_AWK_TOUPPER(run->awk, *p); | 
					
						
							|  |  |  | 				if (XP_AWK_ISSPACE(run->awk,c))  | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					p++; | 
					
						
							|  |  |  | 					continue; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				for (d = delim; d < delim_end; d++)  | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					if (c == XP_AWK_TOUPPER(run->awk,*d)) goto exit_loop; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if (sp == XP_NULL) sp = p; | 
					
						
							|  |  |  | 				ep = p++; | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2006-09-09 04:52:40 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			while (p < end)  | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2006-09-09 04:52:40 +00:00
										 |  |  | 				c = *p; | 
					
						
							|  |  |  | 				if (XP_AWK_ISSPACE(run->awk,c))  | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					p++; | 
					
						
							|  |  |  | 					continue; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				for (d = delim; d < delim_end; d++)  | 
					
						
							|  |  |  | 				{ | 
					
						
							|  |  |  | 					if (c == *d) goto exit_loop; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if (sp == XP_NULL) sp = p; | 
					
						
							|  |  |  | 				ep = p++; | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | exit_loop: | 
					
						
							|  |  |  | 	if (sp == XP_NULL)  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		*tok = XP_NULL; | 
					
						
							|  |  |  | 		*tok_len = (xp_size_t)0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else  | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		*tok = (xp_char_t*)sp; | 
					
						
							|  |  |  | 		*tok_len = ep - sp + 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-03 15:47:11 +00:00
										 |  |  | 	/* if XP_NULL is returned, this function should not be called anymore */ | 
					
						
							| 
									
										
										
										
											2006-09-05 04:11:11 +00:00
										 |  |  | 	if (p >= end) return XP_NULL; | 
					
						
							|  |  |  | 	if (delim_mode == __DELIM_EMPTY ||  | 
					
						
							|  |  |  | 	    delim_mode == __DELIM_SPACES) return (xp_char_t*)p; | 
					
						
							|  |  |  | 	return (xp_char_t*)++p; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | xp_char_t* xp_awk_strxntokbyrex ( | 
					
						
							| 
									
										
										
										
											2006-09-08 15:26:49 +00:00
										 |  |  | 	xp_awk_run_t* run, const xp_char_t* s, xp_size_t len, | 
					
						
							| 
									
										
										
										
											2006-09-05 04:11:11 +00:00
										 |  |  | 	void* rex, xp_char_t** tok, xp_size_t* tok_len, int* errnum) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int n; | 
					
						
							|  |  |  | 	xp_char_t* match_ptr; | 
					
						
							| 
									
										
										
										
											2006-09-05 15:18:36 +00:00
										 |  |  | 	xp_size_t match_len, i; | 
					
						
							|  |  |  | 	xp_size_t left = len; | 
					
						
							| 
									
										
										
										
											2006-09-08 14:51:15 +00:00
										 |  |  | 	const xp_char_t* ptr = s; | 
					
						
							|  |  |  | 	const xp_char_t* str_ptr = s; | 
					
						
							|  |  |  | 	xp_size_t str_len = len; | 
					
						
							| 
									
										
										
										
											2006-09-05 04:11:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-08 14:51:15 +00:00
										 |  |  | 	while (len > 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		n = xp_awk_matchrex ( | 
					
						
							| 
									
										
										
										
											2006-09-10 15:50:34 +00:00
										 |  |  | 			run->awk, rex,  | 
					
						
							| 
									
										
										
										
											2006-09-22 14:05:30 +00:00
										 |  |  | 			((run->global.ignorecase)? XP_AWK_REX_IGNORECASE: 0), | 
					
						
							| 
									
										
										
										
											2006-09-10 16:04:34 +00:00
										 |  |  | 			ptr, left, (const xp_char_t**)&match_ptr, &match_len,  | 
					
						
							|  |  |  | 			errnum); | 
					
						
							| 
									
										
										
										
											2006-09-08 14:51:15 +00:00
										 |  |  | 		if (n == -1) return XP_NULL; | 
					
						
							|  |  |  | 		if (n == 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			/* no match has been found. 
 | 
					
						
							|  |  |  | 			 * return the entire string as a token */ | 
					
						
							|  |  |  | 			*tok = (xp_char_t*)str_ptr; | 
					
						
							|  |  |  | 			*tok_len = str_len; | 
					
						
							|  |  |  | 			*errnum = XP_AWK_ENOERR; | 
					
						
							|  |  |  | 			return XP_NULL;  | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-09-05 15:18:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-12 04:17:58 +00:00
										 |  |  | 		xp_awk_assert (run->awk, n == 1); | 
					
						
							| 
									
										
										
										
											2006-09-05 15:18:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-08 14:51:15 +00:00
										 |  |  | 		if (match_len == 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			ptr++; | 
					
						
							|  |  |  | 			left--; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2006-09-08 15:26:49 +00:00
										 |  |  | 		else if (run->awk->option & XP_AWK_STRIPSPACES) | 
					
						
							| 
									
										
										
										
											2006-09-08 14:51:15 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			/* match at the beginning of the input string */ | 
					
						
							|  |  |  | 			if (match_ptr == s)  | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				for (i = 0; i < match_len; i++) | 
					
						
							|  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2006-09-08 15:26:49 +00:00
										 |  |  | 					if (!XP_AWK_ISSPACE(run->awk, match_ptr[i])) | 
					
						
							| 
									
										
										
										
											2006-09-08 14:51:15 +00:00
										 |  |  | 						goto exit_loop; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2006-09-05 15:18:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-08 14:51:15 +00:00
										 |  |  | 				/* the match that are all spaces at the 
 | 
					
						
							|  |  |  | 				 * beginning of the input string is skipped */ | 
					
						
							|  |  |  | 				ptr += match_len; | 
					
						
							|  |  |  | 				left -= match_len; | 
					
						
							|  |  |  | 				str_ptr = s + match_len; | 
					
						
							|  |  |  | 				str_len -= match_len; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else  break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else break; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-09-05 15:18:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-08 14:51:15 +00:00
										 |  |  | exit_loop: | 
					
						
							|  |  |  | 	if (len == 0) | 
					
						
							| 
									
										
										
										
											2006-09-05 15:18:36 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-09-08 14:51:15 +00:00
										 |  |  | 		*tok = (xp_char_t*)str_ptr; | 
					
						
							|  |  |  | 		*tok_len = str_len; | 
					
						
							|  |  |  | 		*errnum = XP_AWK_ENOERR; | 
					
						
							|  |  |  | 		return XP_NULL;  | 
					
						
							| 
									
										
										
										
											2006-09-05 15:18:36 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-08 14:51:15 +00:00
										 |  |  | 	*tok = (xp_char_t*)str_ptr; | 
					
						
							|  |  |  | 	*tok_len = match_ptr - str_ptr; | 
					
						
							| 
									
										
										
										
											2006-09-05 04:11:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-05 15:18:36 +00:00
										 |  |  | 	for (i = 0; i < match_len; i++) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2006-09-08 15:26:49 +00:00
										 |  |  | 		if (!XP_AWK_ISSPACE(run->awk, match_ptr[i])) | 
					
						
							| 
									
										
										
										
											2006-09-05 15:18:36 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			*errnum = XP_AWK_ENOERR; | 
					
						
							|  |  |  | 			return match_ptr+match_len; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-05 04:11:11 +00:00
										 |  |  | 	*errnum = XP_AWK_ENOERR; | 
					
						
							| 
									
										
										
										
											2006-09-08 14:51:15 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-09-08 15:26:49 +00:00
										 |  |  | 	if (run->awk->option & XP_AWK_STRIPSPACES) | 
					
						
							| 
									
										
										
										
											2006-09-08 14:51:15 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		return (match_ptr+match_len >= s+len)?  | 
					
						
							|  |  |  | 			XP_NULL: (match_ptr+match_len); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		return (match_ptr+match_len > s+len)?  | 
					
						
							|  |  |  | 			XP_NULL: (match_ptr+match_len); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2006-09-01 06:23:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2006-10-12 04:17:58 +00:00
										 |  |  | int xp_awk_abort (xp_awk_t* awk,  | 
					
						
							|  |  |  | 	const xp_char_t* expr, const xp_char_t* file, int line) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2006-10-12 14:36:25 +00:00
										 |  |  | 	awk->syscas.dprintf ( | 
					
						
							| 
									
										
										
										
											2006-10-12 04:17:58 +00:00
										 |  |  | 		XP_T("ASSERTION FAILURE AT FILE %s, LINE %d\n%s\n"), | 
					
						
							|  |  |  | 		file, line, expr); | 
					
						
							| 
									
										
										
										
											2006-10-12 14:36:25 +00:00
										 |  |  | 	awk->syscas.abort (); | 
					
						
							| 
									
										
										
										
											2006-10-12 04:17:58 +00:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } |