📄 prprf.c
字号:
if( nas[ cn ].type == TYPE_UNKNOWN ){ if( l10n_debug ) printf( "unknown type \"%s\"\n", fmt ); *rv = -1; break; } } /* ** third pass ** fill the nas[cn].ap */ if( *rv < 0 ){ if( nas != nasArray ) PR_DELETE( 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, PRIntn ); break; case TYPE_INT32: (void)va_arg( ap, PRInt32 ); break; case TYPE_UINT32: (void)va_arg( ap, PRUint32 ); break; case TYPE_INT64: (void)va_arg( ap, PRInt64 ); break; case TYPE_UINT64: (void)va_arg( ap, PRUint64 ); break; case TYPE_STRING: (void)va_arg( ap, char* ); break; case TYPE_INTSTR: (void)va_arg( ap, PRIntn* ); break; case TYPE_DOUBLE: (void)va_arg( ap, double ); break; default: if( nas != nasArray ) PR_DELETE( 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; int i; long l; PRInt64 ll; double d; const char *s; 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 . */ /* ** 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 */ PR_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( l10n_debug ) printf( "numbered argument type unknown\n" ); if( nas && ( nas != nasArray ) ) PR_DELETE( 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 |= _LEFT; if (c == '+') flags |= _SIGNED; if (c == ' ') flags |= _SPACED; if (c == '0') flags |= _ZEROS; c = *fmt++; } if (flags & _SIGNED) flags &= ~_SPACED; if (flags & _LEFT) flags &= ~_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; case 'u': /* unsigned decimal */ radix = 10; type |= 1; goto fetch_and_convert; case 'x': /* unsigned hex */ radix = 16; type |= 1; goto fetch_and_convert; case 'X': /* unsigned HEX */ radix = 16; hexp = HEX; type |= 1; goto fetch_and_convert; fetch_and_convert: switch (type) { case TYPE_INT16: u.l = va_arg(ap, int); if (u.l < 0) { u.l = -u.l; flags |= _NEG; } goto do_long; case TYPE_UINT16: u.l = va_arg(ap, int) & 0xffff; goto do_long; case TYPE_INTN: u.l = va_arg(ap, int); if (u.l < 0) { u.l = -u.l; flags |= _NEG; } goto do_long; case TYPE_UINTN: u.l = (long)va_arg(ap, unsigned int); goto do_long; case TYPE_INT32: u.l = va_arg(ap, PRInt32); if (u.l < 0) { u.l = -u.l; flags |= _NEG; } goto do_long; case TYPE_UINT32: u.l = (long)va_arg(ap, PRUint32); do_long: rv = cvt_l(ss, u.l, width, prec, radix, type, flags, hexp); if (rv < 0) { return rv; } break; case TYPE_INT64: u.ll = va_arg(ap, PRInt64); if (!LL_GE_ZERO(u.ll)) { LL_NEG(u.ll, u.ll); flags |= _NEG; } goto do_longlong; case TYPE_UINT64: u.ll = va_arg(ap, PRUint64); do_longlong: rv = cvt_ll(ss, u.ll, width, prec, radix, type, flags, hexp); if (rv < 0) { return rv; } break; } break; case 'e': case 'E': case 'f': case 'g': u.d = va_arg(ap, double); if( nas != NULL ){ i = fmt - dolPt; if( i < sizeof( pattern ) ){ pattern[0] = '%'; memcpy( &pattern[1], dolPt, i ); rv = cvt_f(ss, u.d, pattern, &pattern[i+1] ); } } else rv = cvt_f(ss, u.d, fmt0, fmt); if (rv < 0) { return rv; } break; case 'c': u.ch = va_arg(ap, int); if ((flags & _LEFT) == 0) { while (width-- > 1) { rv = (*ss->stuff)(ss, " ", 1); if (rv < 0) { return rv; } } } rv = (*ss->stuff)(ss, &u.ch, 1); if (rv < 0) { return rv; } if (flags & _LEFT) { while (width-- > 1) { rv = (*ss->stuff)(ss, " ", 1); if (rv < 0) { return rv; } } } break; case 'p': if (sizeof(void *) == sizeof(PRInt32)) { type = TYPE_UINT32; } else if (sizeof(void *) == sizeof(PRInt64)) { type = TYPE_UINT64; } else if (sizeof(void *) == sizeof(int)) { type = TYPE_UINTN; } else { PR_ASSERT(0); break; } radix = 16; goto fetch_and_convert;#if 0 case 'C': case 'S': case 'E': case 'G': /* XXX not supported I suppose */ PR_ASSERT(0); break;#endif case 's': u.s = va_arg(ap, const char*); rv = cvt_s(ss, u.s, width, prec, flags); if (rv < 0) { return rv; } break; case 'n': u.ip = va_arg(ap, int*); if (u.ip) { *u.ip = ss->cur - ss->base; } break; default: /* Not a % token after all... skip it */#if 0 PR_ASSERT(0);#endif rv = (*ss->stuff)(ss, "%", 1); if (rv < 0) { return rv; } rv = (*ss->stuff)(ss, fmt - 1, 1); if (rv < 0) { return rv; } } } /* Stuff trailing NUL */ rv = (*ss->stuff)(ss, "\0", 1); if( nas && ( nas != nasArray ) ){ PR_DELETE( nas ); } return rv;}/************************************************************************/static int FuncStuff(SprintfState *ss, const char *sp, PRUint32 len){ int rv; rv = (*ss->func)(ss->arg, sp, len); if (rv < 0) { return rv; } ss->maxlen += len; return 0;}PR_IMPLEMENT(PRUint32) PR_sxprintf(PRStuffFunc func, void *arg, const char *fmt, ...){ va_list ap; int rv; va_start(ap, fmt); rv = PR_vsxprintf(func, arg, fmt, ap); va_end(ap); return rv;}PR_IMPLEMENT(PRUint32) PR_vsxprintf(PRStuffFunc func, void *arg, const char *fmt, va_list ap){ SprintfState ss; int rv; ss.stuff = FuncStuff; ss.func = func; ss.arg = arg; ss.maxlen = 0; rv = dosprintf(&ss, fmt, ap); return (rv < 0) ? (PRUint32)-1 : ss.maxlen;}/*** Stuff routine that automatically grows the malloc'd output buffer** before it overflows.*/static int GrowStuff(SprintfState *ss, const char *sp, PRUint32 len){ ptrdiff_t off; char *newbase; PRUint32 newlen; off = ss->cur - ss->base; if (off + len >= ss->maxlen) { /* Grow the buffer */ newlen = ss->maxlen + ((len > 32) ? len : 32); if (ss->base) { newbase = (char*) PR_REALLOC(ss->base, newlen); } else { newbase = (char*) PR_MALLOC(newlen); } if (!newbase) { /* Ran out of memory */ return -1; } ss->base = newbase; ss->maxlen = newlen; ss->cur = ss->base + off; } /* Copy data */ while (len) { --len; *ss->cur++ = *sp++; } PR_ASSERT((PRUint32)(ss->cur - ss->base) <= ss->maxlen); return 0;}/*** sprintf into a malloc'd buffer*/PR_IMPLEMENT(char *) PR_smprintf(const char *fmt, ...){ va_list ap; char *rv; va_start(ap, fmt); rv = PR_vsmprintf(fmt, ap); va_end(ap); return rv;}/*** Free memory allocated, for the caller, by PR_smprintf*/PR_IMPLEMENT(void) PR_smprintf_free(char *mem){ PR_DELETE(mem);}PR_IMPLEMENT(char *) PR_vsmprintf(const char *fmt, va_list ap){ SprintfState ss; int rv; ss.stuff = GrowStuff; ss.base = 0; ss.cur = 0; ss.maxlen = 0; rv = dosprintf(&ss, fmt, ap); if (rv < 0) { if (ss.base) { PR_DELETE(ss.base); } return 0; } return ss.base;}/*** Stuff routine that discards overflow data*/static int LimitStuff(SprintfState *ss, const char *sp, PRUint32 len){ PRUint32 limit = ss->maxlen - (ss->cur - ss->base); if (len > limit) { len = limit; } while (len) { --len; *ss->cur++ = *sp++; } return 0;}/*** sprintf into a fixed size buffer. Make sure there is a NUL at the end** when finished.*/PR_IMPLEMENT(PRUint32) PR_snprintf(char *out, PRUint32 outlen, const char *fmt, ...){ va_list ap; int rv; PR_ASSERT((PRInt32)outlen > 0); if ((PRInt32)outlen <= 0) { return 0; } va_start(ap, fmt); rv = PR_vsnprintf(out, outlen, fmt, ap); va_end(ap); return rv;}PR_IMPLEMENT(PRUint32) PR_vsnprintf(char *out, PRUint32 outlen,const char *fmt, va_list ap){ SprintfState ss; PRUint32 n; PR_ASSERT((PRInt32)outlen > 0); if ((PRInt32)outlen <= 0) { return 0; } ss.stuff = LimitStuff; ss.base = out; ss.cur = out; ss.maxlen = outlen; (void) dosprintf(&ss, fmt, ap); /* If we added chars, and we didn't append a null, do it now. */ if( (ss.cur != ss.base) && (*(ss.cur - 1) != '\0') ) *(--ss.cur) = '\0'; n = ss.cur - ss.base; return n ? n - 1 : n;}PR_IMPLEMENT(char *) PR_sprintf_append(char *last, const char *fmt, ...){ va_list ap; char *rv; va_start(ap, fmt); rv = PR_vsprintf_append(last, fmt, ap); va_end(ap); return rv;}PR_IMPLEMENT(char *) PR_vsprintf_append(char *last, const char *fmt, va_list ap){ SprintfState ss; int rv; ss.stuff = GrowStuff; if (last) { int lastlen = strlen(last); ss.base = last; ss.cur = last + lastlen; ss.maxlen = lastlen; } else { ss.base = 0; ss.cur = 0; ss.maxlen = 0; } rv = dosprintf(&ss, fmt, ap); if (rv < 0) { if (ss.base) { PR_DELETE(ss.base); } return 0; } return ss.base;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -