📄 scanf.c
字号:
flags |= SCAN_WIDTH; ch = format++; } /* * Ignore size specifier. */ if ((*ch == 'l') || (*ch == 'L') || (*ch == 'h')) { ch = format++; } if (!(flags & SCAN_SUPPRESS) && numVars && (objIndex >= numVars)) { goto badIndex; } /* * Handle the various field types. */ switch (*ch) { case 'n': case 'd': case 'D': case 'i': case 'o': case 'x': case 'X': case 'u': case 'f': case 'e': case 'E': case 'g': case 's': break; case 'c': /* we differ here with the TCL implementation in allowing for */ /* a character width specification, to be more consistent with */ /* ANSI. since Zend auto allocates space for vars, this is no */ /* problem - cc */ /* if (flags & SCAN_WIDTH) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field width may not be specified in %c conversion"); goto error; } */ break; case '[': if (*format == '\0') { goto badSet; } ch = format++; if (*ch == '^') { if (*format == '\0') { goto badSet; } ch = format++; } if (*ch == ']') { if (*format == '\0') { goto badSet; } ch = format++; } while (*ch != ']') { if (*format == '\0') { goto badSet; } ch = format++; } break; badSet: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unmatched [ in format string"); goto error; default: { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad scan conversion character \"%c\"", *ch); goto error; } } if (!(flags & SCAN_SUPPRESS)) { if (objIndex >= nspace) { /* * Expand the nassign buffer. If we are using XPG specifiers, * make sure that we grow to a large enough size. xpgSize is * guaranteed to be at least one larger than objIndex. */ value = nspace; if (xpgSize) { nspace = xpgSize; } else { nspace += STATIC_LIST_SIZE; } if (nassign == staticAssign) { nassign = (void *)safe_emalloc(nspace, sizeof(int), 0); for (i = 0; i < STATIC_LIST_SIZE; ++i) { nassign[i] = staticAssign[i]; } } else { nassign = (void *)erealloc((void *)nassign, nspace * sizeof(int)); } for (i = value; i < nspace; i++) { nassign[i] = 0; } } nassign[objIndex]++; objIndex++; } } /* while (*format != '\0') */ /* * Verify that all of the variable were assigned exactly once. */ if (numVars == 0) { if (xpgSize) { numVars = xpgSize; } else { numVars = objIndex; } } if (totalSubs) { *totalSubs = numVars; } for (i = 0; i < numVars; i++) { if (nassign[i] > 1) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", "Variable is assigned by multiple \"%n$\" conversion specifiers"); goto error; } else if (!xpgSize && (nassign[i] == 0)) { /* * If the space is empty, and xpgSize is 0 (means XPG wasn't * used, and/or numVars != 0), then too many vars were given */ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Variable is not assigned by any conversion specifiers"); goto error; } } if (nassign != staticAssign) { efree((char *)nassign); } return SCAN_SUCCESS; badIndex: if (gotXpg) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", "\"%n$\" argument index out of range"); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Different numbers of variable names and field specifiers"); } error: if (nassign != staticAssign) { efree((char *)nassign); } return SCAN_ERROR_INVALID_FORMAT;#undef STATIC_LIST_SIZE}/* }}} *//* {{{ 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 * argCount total number of elements in the args array * args arguments passed in from user function (f|s)scanf * varStart offset (in args) of 1st variable passed in to (f|s)scanf * return_value set with the results of the scan */PHPAPI int php_sscanf_internal( char *string, char *format, int argCount, zval ***args, int varStart, pval **return_value TSRMLS_DC){ int numVars, nconversions, totalVars = -1; int i, value, result; int objIndex; char *end, *baseString; zval **current; char op = 0; int base = 0; int underflow = 0; size_t width; long (*fn)() = NULL; char *ch, sch; int flags; 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; if (numVars < 0) { numVars = 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 /* * Check for errors in the format string. */ if (ValidateFormat(format, numVars, &totalVars) != SCAN_SUCCESS) { scan_set_error_return( numVars, return_value ); return SCAN_ERROR_INVALID_FORMAT; } 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 ] ) ) { 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) { /* allocate an array for return */ array_init(*return_value); for (i = 0; i < totalVars; i++) { if (add_next_index_null(*return_value) == FAILURE) { scan_set_error_return(0, return_value); return FAILURE; } } } baseString = string; /* * Iterate over the format string filling in the result objects until * 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 ) ) { if (*string == '\0') { goto done; } string++; sch = *string; } continue; } if (*ch != '%') { literal: if (*string == '\0') { underflow = 1; goto done; } sch = *string; string++; if (*ch != sch) { goto done; } continue; } ch = format++; if (*ch == '%') { goto literal; } /* * 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); if (*end == '$') { format = end+1; ch = format++; objIndex = varStart + value - 1; } } /* * Parse any width specifier. */ if ( isdigit(UCHAR(*ch))) { width = strtoul(format-1, &format, 10); ch = format++; } else { width = 0; } /* * Ignore size specifier. */ if ((*ch == 'l') || (*ch == 'L') || (*ch == 'h')) { ch = format++; } /* * Handle the various field types. */ switch (*ch) { case 'n': if (!(flags & SCAN_SUPPRESS)) { if (numVars && objIndex >= argCount) { break; } else if (numVars) { current = args[objIndex++]; zval_dtor( *current ); ZVAL_LONG( *current, (long)(string - baseString) ); } else { add_index_long(*return_value, objIndex++, string - baseString); } } nconversions++; continue; case 'd': case 'D': op = 'i'; base = 10; fn = (long (*)())strtol; break; case 'i': op = 'i'; base = 0; fn = (long (*)())strtol; break; case 'o': op = 'i'; base = 8; fn = (long (*)())strtol; break; case 'x': case 'X': op = 'i'; base = 16; fn = (long (*)())strtol; break; case 'u': op = 'i'; base = 10; flags |= SCAN_UNSIGNED; fn = (long (*)())strtoul; break; case 'f': case 'e': case 'E': case 'g': op = 'f'; break; case 's': op = 's'; break; case 'c': op = 's'; flags |= SCAN_NOSKIP; /*-cc-*/ if (0 == width) { width = 1; } /*-cc-*/ break; case '[': op = '['; flags |= SCAN_NOSKIP; break; } /* switch */ /* * 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -