runevsmprint.c (2109B)
1 /* 2 * The authors of this software are Rob Pike and Ken Thompson. 3 * Copyright (c) 2002 by Lucent Technologies. 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose without fee is hereby granted, provided that this entire notice 6 * is included in all copies of any software which is or includes a copy 7 * or modification of this software and in all copies of the supporting 8 * documentation for such software. 9 * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED 10 * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE 11 * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY 12 * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. 13 */ 14 /* 15 * Plan 9 port version must include libc.h in order to 16 * get Plan 9 debugging malloc, which sometimes returns 17 * different pointers than the standard malloc. 18 */ 19 #include <stdlib.h> 20 #include <string.h> 21 #include "plan9.h" 22 #include "fmt.h" 23 #include "fmtdef.h" 24 25 static int 26 runeFmtStrFlush(Fmt *f) 27 { 28 Rune *s; 29 int n; 30 31 if(f->start == nil) 32 return 0; 33 n = (uintptr_t)f->farg; 34 n *= 2; 35 s = (Rune*)f->start; 36 f->start = realloc(s, sizeof(Rune)*n); 37 if(f->start == nil){ 38 f->farg = nil; 39 f->to = nil; 40 f->stop = nil; 41 free(s); 42 return 0; 43 } 44 f->farg = (void*)(uintptr_t)n; 45 f->to = (Rune*)f->start + ((Rune*)f->to - s); 46 f->stop = (Rune*)f->start + n - 1; 47 return 1; 48 } 49 50 int 51 runefmtstrinit(Fmt *f) 52 { 53 int n; 54 55 memset(f, 0, sizeof *f); 56 f->runes = 1; 57 n = 32; 58 f->start = malloc(sizeof(Rune)*n); 59 if(f->start == nil) 60 return -1; 61 f->to = f->start; 62 f->stop = (Rune*)f->start + n - 1; 63 f->flush = runeFmtStrFlush; 64 f->farg = (void*)(uintptr_t)n; 65 f->nfmt = 0; 66 fmtlocaleinit(f, nil, nil, nil); 67 return 0; 68 } 69 70 /* 71 * print into an allocated string buffer 72 */ 73 Rune* 74 runevsmprint(const char *fmt, va_list args) 75 { 76 Fmt f; 77 int n; 78 79 if(runefmtstrinit(&f) < 0) 80 return nil; 81 va_copy(f.args,args); 82 n = dofmt(&f, fmt); 83 va_end(f.args); 84 if(f.start == nil) 85 return nil; 86 if(n < 0){ 87 free(f.start); 88 return nil; 89 } 90 *(Rune*)f.to = '\0'; 91 return (Rune*)f.start; 92 }