📄 jsprf.c
字号:
** BuildArgArray stands for Numbered Argument list Sprintf** for example,** fmp = "%4$i, %2$d, %3s, %1d";** the number must start from 1, and no gap among them*/static struct NumArgState* BuildArgArray( const char *fmt, va_list ap, int* rv, struct NumArgState* nasArray ){ int number = 0, cn = 0, i; const char *p; char c; struct NumArgState *nas; /* ** first pass: ** detemine how many legal % I have got, then allocate space */ p = fmt; *rv = 0; i = 0; while( ( c = *p++ ) != 0 ){ if( c != '%' ) continue; if( ( c = *p++ ) == '%' ) /* skip %% case */ continue; while( c != 0 ){ if( c > '9' || c < '0' ){ if( c == '$' ){ /* numbered argument csae */ if( i > 0 ){ *rv = -1; return NULL; } number++; } else { /* non-numbered argument case */ if( number > 0 ){ *rv = -1; return NULL; } i = 1; } break; } c = *p++; } } if( number == 0 ){ return NULL; } if( number > NAS_DEFAULT_NUM ){ nas = (struct NumArgState*)malloc( number * sizeof( struct NumArgState ) ); if( !nas ){ *rv = -1; return NULL; } } else { nas = nasArray; } for( i = 0; i < number; i++ ){ nas[i].type = TYPE_UNKNOWN; } /* ** second pass: ** set nas[].type */ p = fmt; while( ( c = *p++ ) != 0 ){ if( c != '%' ) continue; c = *p++; if( c == '%' ) continue; cn = 0; while( c && c != '$' ){ /* should improve error check later */ cn = cn*10 + c - '0'; c = *p++; } if( !c || cn < 1 || cn > number ){ *rv = -1; break; } /* nas[cn] starts from 0, and make sure nas[cn].type is not assigned */ cn--; if( nas[cn].type != TYPE_UNKNOWN ) continue; c = *p++; /* width */ if (c == '*') { /* not supported feature, for the argument is not numbered */ *rv = -1; break; } while ((c >= '0') && (c <= '9')) { c = *p++; } /* precision */ if (c == '.') { c = *p++; if (c == '*') { /* not supported feature, for the argument is not numbered */ *rv = -1; break; } while ((c >= '0') && (c <= '9')) { c = *p++; } } /* size */ nas[cn].type = TYPE_INTN; if (c == 'h') { nas[cn].type = TYPE_INT16; c = *p++; } else if (c == 'L') { /* XXX not quite sure here */ nas[cn].type = TYPE_INT64; c = *p++; } else if (c == 'l') { nas[cn].type = TYPE_INT32; c = *p++; if (c == 'l') { nas[cn].type = TYPE_INT64; c = *p++; } } /* format */ switch (c) { case 'd': case 'c': case 'i': case 'o': case 'u': case 'x': case 'X': break; case 'e': case 'f': case 'g': nas[ cn ].type = TYPE_DOUBLE; break; case 'p': /* XXX should use cpp */ if (sizeof(void *) == sizeof(JSInt32)) { nas[ cn ].type = TYPE_UINT32; } else if (sizeof(void *) == sizeof(JSInt64)) { nas[ cn ].type = TYPE_UINT64; } else if (sizeof(void *) == sizeof(JSIntn)) { nas[ cn ].type = TYPE_UINTN; } else { nas[ cn ].type = TYPE_UNKNOWN; } break; case 'C': case 'S': case 'E': case 'G': /* XXX not supported I suppose */ JS_ASSERT(0); nas[ cn ].type = TYPE_UNKNOWN; break; case 's': nas[ cn ].type = (nas[ cn ].type == TYPE_UINT16) ? TYPE_WSTRING : TYPE_STRING; break; case 'n': nas[ cn ].type = TYPE_INTSTR; break; default: JS_ASSERT(0); nas[ cn ].type = TYPE_UNKNOWN; break; } /* get a legal para. */ if( nas[ cn ].type == TYPE_UNKNOWN ){ *rv = -1; break; } } /* ** third pass ** fill the nas[cn].ap */ if( *rv < 0 ){ if( nas != nasArray ) free( nas ); return NULL; } cn = 0; while( cn < number ){ if( nas[cn].type == TYPE_UNKNOWN ){ cn++; continue; } VARARGS_ASSIGN(nas[cn].ap, ap); switch( nas[cn].type ){ case TYPE_INT16: case TYPE_UINT16: case TYPE_INTN: case TYPE_UINTN: (void)va_arg( ap, JSIntn ); break; case TYPE_INT32: (void)va_arg( ap, JSInt32 ); break; case TYPE_UINT32: (void)va_arg( ap, JSUint32 ); break; case TYPE_INT64: (void)va_arg( ap, JSInt64 ); break; case TYPE_UINT64: (void)va_arg( ap, JSUint64 ); break; case TYPE_STRING: (void)va_arg( ap, char* ); break; case TYPE_WSTRING: (void)va_arg( ap, jschar* ); break; case TYPE_INTSTR: (void)va_arg( ap, JSIntn* ); break; case TYPE_DOUBLE: (void)va_arg( ap, double ); break; default: if( nas != nasArray ) free( nas ); *rv = -1; return NULL; } cn++; } return nas;}/*** The workhorse sprintf code.*/static int dosprintf(SprintfState *ss, const char *fmt, va_list ap){ char c; int flags, width, prec, radix, type; union { char ch; jschar wch; int i; long l; JSInt64 ll; double d; const char *s; const jschar* ws; int *ip; } u; const char *fmt0; static char *hex = "0123456789abcdef"; static char *HEX = "0123456789ABCDEF"; char *hexp; int rv, i; struct NumArgState *nas = NULL; struct NumArgState nasArray[ NAS_DEFAULT_NUM ]; char pattern[20]; const char *dolPt = NULL; /* in "%4$.2f", dolPt will poiont to . */#ifdef JS_C_STRINGS_ARE_UTF8 char utf8buf[6]; int utf8len;#endif /* ** build an argument array, IF the fmt is numbered argument ** list style, to contain the Numbered Argument list pointers */ nas = BuildArgArray( fmt, ap, &rv, nasArray ); if( rv < 0 ){ /* the fmt contains error Numbered Argument format, jliu@netscape.com */ JS_ASSERT(0); return rv; } while ((c = *fmt++) != 0) { if (c != '%') { rv = (*ss->stuff)(ss, fmt - 1, 1); if (rv < 0) { return rv; } continue; } fmt0 = fmt - 1; /* ** Gobble up the % format string. Hopefully we have handled all ** of the strange cases! */ flags = 0; c = *fmt++; if (c == '%') { /* quoting a % with %% */ rv = (*ss->stuff)(ss, fmt - 1, 1); if (rv < 0) { return rv; } continue; } if( nas != NULL ){ /* the fmt contains the Numbered Arguments feature */ i = 0; while( c && c != '$' ){ /* should imporve error check later */ i = ( i * 10 ) + ( c - '0' ); c = *fmt++; } if( nas[i-1].type == TYPE_UNKNOWN ){ if( nas && ( nas != nasArray ) ) free( nas ); return -1; } ap = nas[i-1].ap; dolPt = fmt; c = *fmt++; } /* * Examine optional flags. Note that we do not implement the * '#' flag of sprintf(). The ANSI C spec. of the '#' flag is * somewhat ambiguous and not ideal, which is perhaps why * the various sprintf() implementations are inconsistent * on this feature. */ while ((c == '-') || (c == '+') || (c == ' ') || (c == '0')) { if (c == '-') flags |= FLAG_LEFT; if (c == '+') flags |= FLAG_SIGNED; if (c == ' ') flags |= FLAG_SPACED; if (c == '0') flags |= FLAG_ZEROS; c = *fmt++; } if (flags & FLAG_SIGNED) flags &= ~FLAG_SPACED; if (flags & FLAG_LEFT) flags &= ~FLAG_ZEROS; /* width */ if (c == '*') { c = *fmt++; width = va_arg(ap, int); } else { width = 0; while ((c >= '0') && (c <= '9')) { width = (width * 10) + (c - '0'); c = *fmt++; } } /* precision */ prec = -1; if (c == '.') { c = *fmt++; if (c == '*') { c = *fmt++; prec = va_arg(ap, int); } else { prec = 0; while ((c >= '0') && (c <= '9')) { prec = (prec * 10) + (c - '0'); c = *fmt++; } } } /* size */ type = TYPE_INTN; if (c == 'h') { type = TYPE_INT16; c = *fmt++; } else if (c == 'L') { /* XXX not quite sure here */ type = TYPE_INT64; c = *fmt++; } else if (c == 'l') { type = TYPE_INT32; c = *fmt++; if (c == 'l') { type = TYPE_INT64; c = *fmt++; } } /* format */ hexp = hex; switch (c) { case 'd': case 'i': /* decimal/integer */ radix = 10; goto fetch_and_convert; case 'o': /* octal */ radix = 8; type |= 1; goto fetch_and_convert;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -