format = Z_STRVAL_PP(argv[0]);
formatlen = Z_STRLEN_PP(argv[0]);
/* We have a maximum of <formatlen> format codes to deal with */
formatcodes = safe_emalloc(formatlen, sizeof(*formatcodes), 0);
formatargs = safe_emalloc(formatlen, sizeof(*formatargs), 0);
currentarg = 1;
/* Preprocess format into formatcodes and formatargs */
for (i = 0; i < formatlen; formatcount++) {
char code = format[i++];
int arg = 1;
/* Handle format arguments if any */
if (i < formatlen) {
char c = format[i];
if (c == '*') {
arg = -1;
i++;
}
else if (c >= '0' && c <= '9') {
arg = atoi(&format[i]);
while (format[i] >= '0' && format[i] <= '9' && i < formatlen) {
i++;
}
}
}
/* Handle special arg '*' for all codes and check argv overflows */
switch ((int) code) {
/* Always uses one arg */
case 'h':
case 'H':
if (currentarg >= num_args) {
efree(argv);
efree(formatcodes);
efree(formatargs);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Type %c: not enough arguments", code);
RETURN_FALSE;
}
if (arg < 0) {
convert_to_string_ex(argv[currentarg]);
arg = Z_STRLEN_PP(argv[currentarg]);
}
/* Calculate output length and upper bound while processing*/
for (i = 0; i < formatcount; i++) {
int code = (int) formatcodes[i];
int arg = formatargs[i];
switch ((int) code) {
case 'h':
case 'H':
INC_OUTPUTPOS((arg + (arg % 2)) / 2,1) /* 4 bit per arg */
break;
}
if (outputsize < outputpos) {
outputsize = outputpos;
}
}