summaryrefslogtreecommitdiff
path: root/ext/standard/scanf.c
diff options
context:
space:
mode:
authorJani Taskinen <jani@php.net>2007-07-26 14:30:22 +0000
committerJani Taskinen <jani@php.net>2007-07-26 14:30:22 +0000
commit9fe59f509c0958513f2f28d029b132314adb44e0 (patch)
tree90fc646becf64b64f68cb3f757edfa3080488207 /ext/standard/scanf.c
parentdcc62b53bfacb712ca3c6299b25bd4399cc11101 (diff)
downloadphp-git-9fe59f509c0958513f2f28d029b132314adb44e0.tar.gz
MFH: cs + ws fixes
Diffstat (limited to 'ext/standard/scanf.c')
-rw-r--r--ext/standard/scanf.c272
1 files changed, 115 insertions, 157 deletions
diff --git a/ext/standard/scanf.c b/ext/standard/scanf.c
index baddeb24b2..b299a3ed1d 100644
--- a/ext/standard/scanf.c
+++ b/ext/standard/scanf.c
@@ -1,4 +1,4 @@
-/*
+/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
@@ -19,13 +19,11 @@
/* $Id$ */
/*
- scanf.c --
-
+ scanf.c --
+
This file contains the base code which implements sscanf and by extension
- fscanf. Original code is from TCL8.3.0 and bears the following copyright
-
-
-
+ fscanf. Original code is from TCL8.3.0 and bears the following copyright:
+
This software is copyrighted by the Regents of the University of
California, Sun Microsystems, Inc., Scriptics Corporation,
and other parties. The following terms apply to all files associated
@@ -46,7 +44,7 @@
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
-
+
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
@@ -56,7 +54,7 @@
GOVERNMENT USE: If you are acquiring this software on behalf of the
U.S. government, the Government shall have only "Restricted Rights"
- in the software and related documentation as defined in the Federal
+ in the software and related documentation as defined in the Federal
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
are acquiring the software on behalf of the Department of Defense, the
software shall be classified as "Commercial Computer Software" and the
@@ -64,17 +62,16 @@
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
authors grant the U.S. Government and others acting in its behalf
permission to use and distribute the software in accordance with the
- terms specified in this license.
-
- */
-
+ terms specified in this license.
+*/
+
#include <stdio.h>
#include <limits.h>
#include <ctype.h>
#include "php.h"
#include "php_variables.h"
#ifdef HAVE_LOCALE_H
-#include <locale.h>
+#include <locale.h>
#endif
#include "zend_execute.h"
#include "zend_operators.h"
@@ -86,7 +83,6 @@
/*
* Flag values used internally by [f|s]canf.
*/
-
#define SCAN_NOSKIP 0x1 /* Don't skip blanks. */
#define SCAN_SUPPRESS 0x2 /* Suppress assignment. */
#define SCAN_UNSIGNED 0x4 /* Read an unsigned value. */
@@ -101,13 +97,10 @@
#define UCHAR(x) (zend_uchar)(x)
-
-
/*
* The following structure contains the information associated with
* a character set.
*/
-
typedef struct CharSet {
int exclude; /* 1 if this is an exclusion set. */
int nchars;
@@ -122,7 +115,6 @@ typedef struct CharSet {
/*
* Declarations for functions used only in this file.
*/
-
static char *BuildCharSet(CharSet *cset, char *format);
static int CharInSet(CharSet *cset, int ch);
static void ReleaseCharSet(CharSet *cset);
@@ -153,18 +145,17 @@ static char * BuildCharSet(CharSet *cset, char *format)
char *end;
memset(cset, 0, sizeof(CharSet));
-
+
ch = format;
if (*ch == '^') {
cset->exclude = 1;
ch = ++format;
}
- end = format + 1; /* verify this - cc */
+ end = format + 1; /* verify this - cc */
/*
* Find the close bracket so we can overallocate the set.
*/
-
if (*ch == ']') {
ch = end++;
}
@@ -186,7 +177,6 @@ static char * BuildCharSet(CharSet *cset, char *format)
/*
* Now build the character set.
*/
-
cset->nchars = cset->nranges = 0;
ch = format++;
start = *ch;
@@ -200,7 +190,6 @@ static char * BuildCharSet(CharSet *cset, char *format)
* This may be the first character of a range, so don't add
* it yet.
*/
-
start = *ch;
} else if (*ch == '-') {
/*
@@ -208,7 +197,6 @@ static char * BuildCharSet(CharSet *cset, char *format)
* case it is not a range and we should add the previous character
* as well as the dash.
*/
-
if (*format == ']') {
cset->chars[cset->nchars++] = start;
cset->chars[cset->nchars++] = *ch;
@@ -218,7 +206,6 @@ static char * BuildCharSet(CharSet *cset, char *format)
/*
* Check to see if the range is in reverse order.
*/
-
if (start < *ch) {
cset->ranges[cset->nranges].start = start;
cset->ranges[cset->nranges].end = *ch;
@@ -227,7 +214,7 @@ static char * BuildCharSet(CharSet *cset, char *format)
cset->ranges[cset->nranges].end = start;
}
cset->nranges++;
- }
+ }
} else {
cset->chars[cset->nchars++] = *ch;
}
@@ -272,7 +259,7 @@ static int CharInSet(CharSet *cset, int c)
}
}
}
- return (cset->exclude ? !match : match);
+ return (cset->exclude ? !match : match);
}
/* }}} */
@@ -336,7 +323,6 @@ PHPAPI int ValidateFormat(char *format, int numVars, int *totalSubs)
* is assigned to by the format string. We use this to detect if
* a variable is multiply assigned or left unassigned.
*/
-
if (numVars > nspace) {
nassign = (int*)safe_emalloc(sizeof(int), numVars, 0);
nspace = numVars;
@@ -364,14 +350,13 @@ PHPAPI int ValidateFormat(char *format, int numVars, int *totalSubs)
goto xpgCheckDone;
}
- if ( isdigit( (int)*ch ) ) {
+ if ( isdigit( (int)*ch ) ) {
/*
* Check for an XPG3-style %n$ specification. Note: there
* must not be a mixture of XPG3 specs and non-XPG3 specs
* in the same format string.
*/
-
- value = strtoul(format-1, &end, 10);
+ value = strtoul(format-1, &end, 10);
if (*end != '$') {
goto notXpg;
}
@@ -405,20 +390,19 @@ PHPAPI int ValidateFormat(char *format, int numVars, int *totalSubs)
goto xpgCheckDone;
}
- notXpg:
+notXpg:
gotSequential = 1;
if (gotXpg) {
- mixedXPG:
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", "cannot mix \"%\" and \"%n$\" conversion specifiers");
+mixedXPG:
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", "cannot mix \"\%\" and \"\%n$\" conversion specifiers");
goto error;
}
- xpgCheckDone:
+xpgCheckDone:
/*
* Parse any width specifier.
*/
-
- if (isdigit(UCHAR(*ch))) {
+ if (isdigit(UCHAR(*ch))) {
value = strtoul(format-1, &format, 10);
flags |= SCAN_WIDTH;
ch = format++;
@@ -427,7 +411,6 @@ PHPAPI int ValidateFormat(char *format, int numVars, int *totalSubs)
/*
* Ignore size specifier.
*/
-
if ((*ch == 'l') || (*ch == 'L') || (*ch == 'h')) {
ch = format++;
}
@@ -439,22 +422,22 @@ PHPAPI int ValidateFormat(char *format, int numVars, int *totalSubs)
/*
* Handle the various field types.
*/
-
switch (*ch) {
case 'n':
case 'd':
- case 'D':
+ case 'D':
case 'i':
case 'o':
case 'x':
- case 'X':
+ case 'X':
case 'u':
case 'f':
case 'e':
- case 'E':
+ case 'E':
case 'g':
case 's':
- break;
+ break;
+
case 'c':
/* we differ here with the TCL implementation in allowing for */
/* a character width specification, to be more consistent with */
@@ -467,6 +450,7 @@ PHPAPI int ValidateFormat(char *format, int numVars, int *totalSubs)
}
*/
break;
+
case '[':
if (*format == '\0') {
goto badSet;
@@ -491,15 +475,16 @@ PHPAPI int ValidateFormat(char *format, int numVars, int *totalSubs)
ch = format++;
}
break;
- badSet:
+badSet:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unmatched [ in format string");
goto error;
- default:
- {
+
+ default: {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad scan conversion character \"%c\"", *ch);
goto error;
- }
+ }
}
+
if (!(flags & SCAN_SUPPRESS)) {
if (objIndex >= nspace) {
/*
@@ -528,12 +513,11 @@ PHPAPI int ValidateFormat(char *format, int numVars, int *totalSubs)
nassign[objIndex]++;
objIndex++;
}
- } /* while (*format != '\0') */
+ } /* while (*format != '\0') */
/*
* Verify that all of the variable were assigned exactly once.
*/
-
if (numVars == 0) {
if (xpgSize) {
numVars = xpgSize;
@@ -582,7 +566,7 @@ error:
/* {{{ php_sscanf_internal
* This is the internal function which does processing on behalf of
* both sscanf() and fscanf()
- *
+ *
* parameters :
* string literal string to be processed
* format format string
@@ -592,7 +576,7 @@ error:
* return_value set with the results of the scan
*/
-PHPAPI int php_sscanf_internal( char *string, char *format,
+PHPAPI int php_sscanf_internal( char *string, char *format,
int argCount, zval ***args,
int varStart, zval **return_value TSRMLS_DC)
{
@@ -608,59 +592,59 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
long (*fn)() = NULL;
char *ch, sch;
int flags;
- char buf[64]; /* Temporary buffer to hold scanned
- * number strings before they are
- * passed to strtoul. */
+ char buf[64]; /* Temporary buffer to hold scanned number
+ * strings before they are passed to strtoul() */
-
/* do some sanity checking */
if ((varStart > argCount) || (varStart < 0)){
varStart = SCAN_MAX_ARGS + 1;
}
- numVars = argCount - varStart;
+ numVars = argCount - varStart;
if (numVars < 0) {
numVars = 0;
}
-
-#if 0
+
+#if 0
zend_printf("<br>in sscanf_internal : <br> string is \"%s\", format = \"%s\"<br> NumVars = %d. VarStart = %d<br>-------------------------<br>",
- string, format, numVars, varStart);
-#endif
+ string, format, numVars, varStart);
+#endif
/*
* Check for errors in the format string.
*/
if (ValidateFormat(format, numVars, &totalVars) != SCAN_SUCCESS) {
- scan_set_error_return( numVars, return_value );
+ scan_set_error_return( numVars, return_value );
return SCAN_ERROR_INVALID_FORMAT;
}
- objIndex = numVars ? varStart : 0;
+ objIndex = numVars ? varStart : 0;
/*
* If any variables are passed, make sure they are all passed by reference
- */
+ */
if (numVars) {
for (i = varStart;i < argCount;i++){
- if ( ! PZVAL_IS_REF( *args[ i ] ) ) {
+ if ( ! PZVAL_IS_REF( *args[ i ] ) ) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter %d must be passed by reference", i);
scan_set_error_return(numVars, return_value);
return SCAN_ERROR_VAR_PASSED_BYVAL;
}
}
}
-
-
+
/*
* Allocate space for the result objects. Only happens when no variables
* are specified
*/
-
if (!numVars) {
+ zval *tmp;
+
/* allocate an array for return */
array_init(*return_value);
for (i = 0; i < totalVars; i++) {
- if (add_next_index_null(*return_value) == FAILURE) {
+ MAKE_STD_ZVAL(tmp);
+ ZVAL_NULL(tmp);
+ if (add_next_index_zval(*return_value, tmp) == FAILURE) {
scan_set_error_return(0, return_value);
return FAILURE;
}
@@ -674,20 +658,16 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
* we reach the end of input, the end of the format string, or there
* is a mismatch.
*/
-
nconversions = 0;
/* note ! - we need to limit the loop for objIndex to keep it in bounds */
while (*format != '\0') {
-
ch = format++;
-
flags = 0;
/*
* If we see whitespace in the format, skip whitespace in the string.
*/
-
if ( isspace( (int)*ch ) ) {
sch = *string;
while ( isspace( (int)sch ) ) {
@@ -699,9 +679,9 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
}
continue;
}
-
+
if (*ch != '%') {
- literal:
+literal:
if (*string == '\0') {
underflow = 1;
goto done;
@@ -723,12 +703,11 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
* Check for assignment suppression ('*') or an XPG3-style
* assignment ('%n$').
*/
-
if (*ch == '*') {
flags |= SCAN_SUPPRESS;
ch = format++;
- } else if ( isdigit(UCHAR(*ch))) {
- value = strtoul(format-1, &end, 10);
+ } else if ( isdigit(UCHAR(*ch))) {
+ value = strtoul(format-1, &end, 10);
if (*end == '$') {
format = end+1;
ch = format++;
@@ -739,9 +718,8 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
/*
* Parse any width specifier.
*/
-
- if ( isdigit(UCHAR(*ch))) {
- width = strtoul(format-1, &format, 10);
+ if ( isdigit(UCHAR(*ch))) {
+ width = strtoul(format-1, &format, 10);
ch = format++;
} else {
width = 0;
@@ -750,7 +728,6 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
/*
* Ignore size specifier.
*/
-
if ((*ch == 'l') || (*ch == 'L') || (*ch == 'h')) {
ch = format++;
}
@@ -758,7 +735,6 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
/*
* Handle the various field types.
*/
-
switch (*ch) {
case 'n':
if (!(flags & SCAN_SUPPRESS)) {
@@ -781,7 +757,7 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
continue;
case 'd':
- case 'D':
+ case 'D':
op = 'i';
base = 10;
fn = (long (*)())strtol;
@@ -811,7 +787,7 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
case 'f':
case 'e':
- case 'E':
+ case 'E':
case 'g':
op = 'f';
break;
@@ -839,17 +815,15 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
* At this point, we will need additional characters from the
* string to proceed.
*/
-
if (*string == '\0') {
underflow = 1;
goto done;
}
-
+
/*
* Skip any leading whitespace at the beginning of a field unless
* the format suppresses this behavior.
*/
-
if (!(flags & SCAN_NOSKIP)) {
while (*string != '\0') {
sch = *string;
@@ -867,14 +841,12 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
/*
* Perform the requested scanning operation.
*/
-
switch (op) {
- case 'c':
+ case 'c':
case 's':
- /*
- * Scan a string up to width characters or whitespace.
- */
-
+ /*
+ * Scan a string up to width characters or whitespace.
+ */
if (width == 0) {
width = (size_t) ~0;
}
@@ -930,9 +902,9 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
ReleaseCharSet(&cset);
if (string == end) {
- /*
- * Nothing matched the range, stop processing
- */
+ /*
+ * Nothing matched the range, stop processing
+ */
goto done;
}
if (!(flags & SCAN_SUPPRESS)) {
@@ -947,10 +919,9 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
}
}
string = end;
-
break;
}
- /*
+/*
case 'c':
/ Scan a single character./
@@ -969,32 +940,31 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
}
}
break;
- */
+*/
case 'i':
- /*
- * Scan an unsigned or signed integer.
- */
-
- /*-cc-*/
+ /*
+ * Scan an unsigned or signed integer.
+ */
+ /*-cc-*/
buf[0] = '\0';
- /*-cc-*/
+ /*-cc-*/
if ((width == 0) || (width > sizeof(buf) - 1)) {
width = sizeof(buf) - 1;
}
-
+
flags |= SCAN_SIGNOK | SCAN_NODIGITS | SCAN_NOZERO;
for (end = buf; width > 0; width--) {
switch (*string) {
- /*
- * The 0 digit has special meaning at the beginning of
- * a number. If we are unsure of the base, it
- * indicates that we are in base 8 or base 16 (if it is
- * followed by an 'x').
- */
+ /*
+ * The 0 digit has special meaning at the beginning of
+ * a number. If we are unsure of the base, it
+ * indicates that we are in base 8 or base 16 (if it is
+ * followed by an 'x').
+ */
case '0':
/*-cc-*/
if (base == 16) {
- flags |= SCAN_XOK;
+ flags |= SCAN_XOK;
}
/*-cc-*/
if (base == 0) {
@@ -1052,16 +1022,15 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
break;
}
- /*
- * We got an illegal character so we are done accumulating.
- */
-
+ /*
+ * We got an illegal character so we are done accumulating.
+ */
break;
- addToInt:
- /*
- * Add the character to the temporary buffer.
- */
+addToInt:
+ /*
+ * Add the character to the temporary buffer.
+ */
*end++ = *string++;
if (*string == '\0') {
break;
@@ -1072,7 +1041,6 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
* Check to see if we need to back up because we only got a
* sign or a trailing x after a 0.
*/
-
if (flags & SCAN_NODIGITS) {
if (*string == '\0') {
underflow = 1;
@@ -1083,13 +1051,11 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
string--;
}
-
/*
* Scan the value from the temporary buffer. If we are
* returning a large unsigned value, we have to convert it back
* to a string since PHP only supports signed values.
*/
-
if (!(flags & SCAN_SUPPRESS)) {
*end = '\0';
value = (int) (*fn)(buf, NULL, base);
@@ -1117,13 +1083,12 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
}
}
}
-
break;
case 'f':
- /*
- * Scan a floating point number
- */
+ /*
+ * Scan a floating point number
+ */
buf[0] = '\0'; /* call me pedantic */
if ((width == 0) || (width > sizeof(buf) - 1)) {
width = sizeof(buf) - 1;
@@ -1136,7 +1101,8 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
case '8': case '9':
flags &= ~(SCAN_SIGNOK | SCAN_NODIGITS);
goto addToFloat;
- case '+': case '-':
+ case '+':
+ case '-':
if (flags & SCAN_SIGNOK) {
flags &= ~SCAN_SIGNOK;
goto addToFloat;
@@ -1148,12 +1114,12 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
goto addToFloat;
}
break;
- case 'e': case 'E':
- /*
- * An exponent is not allowed until there has
- * been at least one digit.
- */
-
+ case 'e':
+ case 'E':
+ /*
+ * An exponent is not allowed until there has
+ * been at least one digit.
+ */
if ((flags & (SCAN_NODIGITS | SCAN_EXPOK)) == SCAN_EXPOK) {
flags = (flags & ~(SCAN_EXPOK|SCAN_PTOK))
| SCAN_SIGNOK | SCAN_NODIGITS;
@@ -1165,14 +1131,12 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
/*
* We got an illegal character so we are done accumulating.
*/
-
break;
- addToFloat:
- /*
- * Add the character to the temporary buffer.
- */
-
+addToFloat:
+ /*
+ * Add the character to the temporary buffer.
+ */
*end++ = *string++;
if (*string == '\0') {
break;
@@ -1183,7 +1147,6 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
* Check to see if we need to back up because we saw a
* trailing 'e' or sign.
*/
-
if (flags & SCAN_NODIGITS) {
if (flags & SCAN_EXPOK) {
/*
@@ -1199,7 +1162,6 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
/*
* We got a bad exponent ('e' and maybe a sign).
*/
-
end--;
string--;
if (*end != 'e' && *end != 'E') {
@@ -1211,7 +1173,6 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
/*
* Scan the value from the temporary buffer.
*/
-
if (!(flags & SCAN_SUPPRESS)) {
double dvalue;
*end = '\0';
@@ -1227,9 +1188,9 @@ PHPAPI int php_sscanf_internal( char *string, char *format,
}
}
break;
- } /* switch (op) */
+ } /* switch (op) */
nconversions++;
- } /* while (*format != '\0') */
+ } /* while (*format != '\0') */
done:
result = SCAN_SUCCESS;
@@ -1241,27 +1202,24 @@ done:
convert_to_long( *return_value );
Z_LVAL_PP(return_value) = nconversions;
} else if (nconversions < totalVars) {
- /* to do : not all elements converted. we need to prune the list - cc
- */
+ /* TODO: not all elements converted. we need to prune the list - cc */
}
-
return result;
}
/* }}} */
/* the compiler choked when i tried to make this a macro */
-static inline void scan_set_error_return(int numVars, zval **return_value)
+static inline void scan_set_error_return(int numVars, zval **return_value) /* {{{ */
{
if (numVars) {
Z_TYPE_PP(return_value) = IS_LONG;
Z_LVAL_PP(return_value) = SCAN_ERROR_EOF; /* EOF marker */
- } else {
- /* zval_dtor( *return_value ); */
- /* convert_to_null calls destructor */
- convert_to_null( *return_value );
- }
+ } else {
+ /* convert_to_null calls destructor */
+ convert_to_null( *return_value );
+ }
}
-
+/* }}} */
/*
* Local variables: