github.com/tcnksm/go@v0.0.0-20141208075154-439b32936367/src/lib9/fmt/vsmprint.c (about) 1 /* 2 * The authors of this software are Rob Pike and Ken Thompson, 3 * with contributions from Mike Burrows and Sean Dorward. 4 * 5 * Copyright (c) 2002-2006 by Lucent Technologies. 6 * Portions Copyright (c) 2004 Google Inc. 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose without fee is hereby granted, provided that this entire notice 10 * is included in all copies of any software which is or includes a copy 11 * or modification of this software and in all copies of the supporting 12 * documentation for such software. 13 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED 14 * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES 15 * NOR GOOGLE INC MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING 16 * THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. 17 */ 18 19 #include <u.h> 20 #include <libc.h> 21 #include "fmtdef.h" 22 23 static int 24 fmtStrFlush(Fmt *f) 25 { 26 char *s; 27 int n; 28 29 if(f->start == nil) 30 return 0; 31 n = (int)(uintptr)f->farg; 32 n *= 2; 33 s = (char*)f->start; 34 f->start = realloc(s, (size_t)n); 35 if(f->start == nil){ 36 f->farg = nil; 37 f->to = nil; 38 f->stop = nil; 39 free(s); 40 return 0; 41 } 42 f->farg = (void*)(uintptr)n; 43 f->to = (char*)f->start + ((char*)f->to - s); 44 f->stop = (char*)f->start + n - 1; 45 return 1; 46 } 47 48 int 49 fmtstrinit(Fmt *f) 50 { 51 int n; 52 53 memset(f, 0, sizeof *f); 54 f->runes = 0; 55 n = 32; 56 f->start = malloc((size_t)n); 57 if(f->start == nil) 58 return -1; 59 f->to = f->start; 60 f->stop = (char*)f->start + n - 1; 61 f->flush = fmtStrFlush; 62 f->farg = (void*)(uintptr)n; 63 f->nfmt = 0; 64 fmtlocaleinit(f, nil, nil, nil); 65 return 0; 66 } 67 68 /* 69 * print into an allocated string buffer 70 */ 71 char* 72 vsmprint(char *fmt, va_list args) 73 { 74 Fmt f; 75 int n; 76 77 if(fmtstrinit(&f) < 0) 78 return nil; 79 VA_COPY(f.args,args); 80 n = dofmt(&f, fmt); 81 VA_END(f.args); 82 if(n < 0){ 83 free(f.start); 84 return nil; 85 } 86 return fmtstrflush(&f); 87 }