Blame


1 91c13e54 2004-02-29 devnull /*
2 91c13e54 2004-02-29 devnull * The authors of this software are Rob Pike and Ken Thompson.
3 91c13e54 2004-02-29 devnull * Copyright (c) 2002 by Lucent Technologies.
4 91c13e54 2004-02-29 devnull * Permission to use, copy, modify, and distribute this software for any
5 91c13e54 2004-02-29 devnull * purpose without fee is hereby granted, provided that this entire notice
6 91c13e54 2004-02-29 devnull * is included in all copies of any software which is or includes a copy
7 91c13e54 2004-02-29 devnull * or modification of this software and in all copies of the supporting
8 91c13e54 2004-02-29 devnull * documentation for such software.
9 91c13e54 2004-02-29 devnull * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
10 c90dd38f 2004-12-29 devnull * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE
11 c90dd38f 2004-12-29 devnull * ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
12 91c13e54 2004-02-29 devnull * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
13 91c13e54 2004-02-29 devnull */
14 91c13e54 2004-02-29 devnull #include <stdarg.h>
15 91c13e54 2004-02-29 devnull #include <string.h>
16 e5aa96ac 2004-12-26 devnull #include "plan9.h"
17 91c13e54 2004-02-29 devnull #include "fmt.h"
18 91c13e54 2004-02-29 devnull #include "fmtdef.h"
19 91c13e54 2004-02-29 devnull
20 91c13e54 2004-02-29 devnull enum
21 91c13e54 2004-02-29 devnull {
22 91c13e54 2004-02-29 devnull Maxfmt = 64
23 91c13e54 2004-02-29 devnull };
24 91c13e54 2004-02-29 devnull
25 91c13e54 2004-02-29 devnull typedef struct Convfmt Convfmt;
26 91c13e54 2004-02-29 devnull struct Convfmt
27 91c13e54 2004-02-29 devnull {
28 91c13e54 2004-02-29 devnull int c;
29 91c13e54 2004-02-29 devnull volatile Fmts fmt; /* for spin lock in fmtfmt; avoids race due to write order */
30 91c13e54 2004-02-29 devnull };
31 91c13e54 2004-02-29 devnull
32 91c13e54 2004-02-29 devnull struct
33 91c13e54 2004-02-29 devnull {
34 91c13e54 2004-02-29 devnull /* lock by calling __fmtlock, __fmtunlock */
35 91c13e54 2004-02-29 devnull int nfmt;
36 91c13e54 2004-02-29 devnull Convfmt fmt[Maxfmt];
37 91c13e54 2004-02-29 devnull } fmtalloc;
38 91c13e54 2004-02-29 devnull
39 91c13e54 2004-02-29 devnull static Convfmt knownfmt[] = {
40 91c13e54 2004-02-29 devnull ' ', __flagfmt,
41 91c13e54 2004-02-29 devnull '#', __flagfmt,
42 91c13e54 2004-02-29 devnull '%', __percentfmt,
43 91c13e54 2004-02-29 devnull '+', __flagfmt,
44 91c13e54 2004-02-29 devnull ',', __flagfmt,
45 91c13e54 2004-02-29 devnull '-', __flagfmt,
46 91c13e54 2004-02-29 devnull 'C', __runefmt, /* Plan 9 addition */
47 91c13e54 2004-02-29 devnull 'E', __efgfmt,
48 df121a00 2004-12-26 devnull #ifndef PLAN9PORT
49 91c13e54 2004-02-29 devnull 'F', __efgfmt, /* ANSI only */
50 df121a00 2004-12-26 devnull #endif
51 91c13e54 2004-02-29 devnull 'G', __efgfmt,
52 df121a00 2004-12-26 devnull #ifndef PLAN9PORT
53 91c13e54 2004-02-29 devnull 'L', __flagfmt, /* ANSI only */
54 df121a00 2004-12-26 devnull #endif
55 91c13e54 2004-02-29 devnull 'S', __runesfmt, /* Plan 9 addition */
56 91c13e54 2004-02-29 devnull 'X', __ifmt,
57 91c13e54 2004-02-29 devnull 'b', __ifmt, /* Plan 9 addition */
58 91c13e54 2004-02-29 devnull 'c', __charfmt,
59 91c13e54 2004-02-29 devnull 'd', __ifmt,
60 91c13e54 2004-02-29 devnull 'e', __efgfmt,
61 91c13e54 2004-02-29 devnull 'f', __efgfmt,
62 91c13e54 2004-02-29 devnull 'g', __efgfmt,
63 91c13e54 2004-02-29 devnull 'h', __flagfmt,
64 df121a00 2004-12-26 devnull #ifndef PLAN9PORT
65 91c13e54 2004-02-29 devnull 'i', __ifmt, /* ANSI only */
66 df121a00 2004-12-26 devnull #endif
67 91c13e54 2004-02-29 devnull 'l', __flagfmt,
68 91c13e54 2004-02-29 devnull 'n', __countfmt,
69 91c13e54 2004-02-29 devnull 'o', __ifmt,
70 91c13e54 2004-02-29 devnull 'p', __ifmt,
71 91c13e54 2004-02-29 devnull 'r', __errfmt,
72 91c13e54 2004-02-29 devnull 's', __strfmt,
73 e5aa96ac 2004-12-26 devnull #ifdef PLAN9PORT
74 e5aa96ac 2004-12-26 devnull 'u', __flagfmt,
75 e5aa96ac 2004-12-26 devnull #else
76 e5aa96ac 2004-12-26 devnull 'u', __ifmt,
77 e5aa96ac 2004-12-26 devnull #endif
78 91c13e54 2004-02-29 devnull 'x', __ifmt,
79 91c13e54 2004-02-29 devnull 0, nil,
80 91c13e54 2004-02-29 devnull };
81 91c13e54 2004-02-29 devnull
82 91c13e54 2004-02-29 devnull
83 91c13e54 2004-02-29 devnull int (*fmtdoquote)(int);
84 91c13e54 2004-02-29 devnull
85 91c13e54 2004-02-29 devnull /*
86 91c13e54 2004-02-29 devnull * __fmtlock() must be set
87 91c13e54 2004-02-29 devnull */
88 91c13e54 2004-02-29 devnull static int
89 91c13e54 2004-02-29 devnull __fmtinstall(int c, Fmts f)
90 91c13e54 2004-02-29 devnull {
91 91c13e54 2004-02-29 devnull Convfmt *p, *ep;
92 91c13e54 2004-02-29 devnull
93 91c13e54 2004-02-29 devnull if(c<=0 || c>=65536)
94 91c13e54 2004-02-29 devnull return -1;
95 91c13e54 2004-02-29 devnull if(!f)
96 91c13e54 2004-02-29 devnull f = __badfmt;
97 91c13e54 2004-02-29 devnull
98 91c13e54 2004-02-29 devnull ep = &fmtalloc.fmt[fmtalloc.nfmt];
99 91c13e54 2004-02-29 devnull for(p=fmtalloc.fmt; p<ep; p++)
100 91c13e54 2004-02-29 devnull if(p->c == c)
101 91c13e54 2004-02-29 devnull break;
102 91c13e54 2004-02-29 devnull
103 91c13e54 2004-02-29 devnull if(p == &fmtalloc.fmt[Maxfmt])
104 91c13e54 2004-02-29 devnull return -1;
105 91c13e54 2004-02-29 devnull
106 91c13e54 2004-02-29 devnull p->fmt = f;
107 91c13e54 2004-02-29 devnull if(p == ep){ /* installing a new format character */
108 91c13e54 2004-02-29 devnull fmtalloc.nfmt++;
109 91c13e54 2004-02-29 devnull p->c = c;
110 91c13e54 2004-02-29 devnull }
111 91c13e54 2004-02-29 devnull
112 91c13e54 2004-02-29 devnull return 0;
113 91c13e54 2004-02-29 devnull }
114 91c13e54 2004-02-29 devnull
115 91c13e54 2004-02-29 devnull int
116 e5aa96ac 2004-12-26 devnull fmtinstall(int c, int (*f)(Fmt*))
117 91c13e54 2004-02-29 devnull {
118 91c13e54 2004-02-29 devnull int ret;
119 91c13e54 2004-02-29 devnull
120 91c13e54 2004-02-29 devnull __fmtlock();
121 91c13e54 2004-02-29 devnull ret = __fmtinstall(c, f);
122 91c13e54 2004-02-29 devnull __fmtunlock();
123 91c13e54 2004-02-29 devnull return ret;
124 91c13e54 2004-02-29 devnull }
125 91c13e54 2004-02-29 devnull
126 91c13e54 2004-02-29 devnull static Fmts
127 91c13e54 2004-02-29 devnull fmtfmt(int c)
128 91c13e54 2004-02-29 devnull {
129 91c13e54 2004-02-29 devnull Convfmt *p, *ep;
130 91c13e54 2004-02-29 devnull
131 91c13e54 2004-02-29 devnull ep = &fmtalloc.fmt[fmtalloc.nfmt];
132 91c13e54 2004-02-29 devnull for(p=fmtalloc.fmt; p<ep; p++)
133 91c13e54 2004-02-29 devnull if(p->c == c){
134 91c13e54 2004-02-29 devnull while(p->fmt == nil) /* loop until value is updated */
135 91c13e54 2004-02-29 devnull ;
136 91c13e54 2004-02-29 devnull return p->fmt;
137 91c13e54 2004-02-29 devnull }
138 91c13e54 2004-02-29 devnull
139 91c13e54 2004-02-29 devnull /* is this a predefined format char? */
140 91c13e54 2004-02-29 devnull __fmtlock();
141 91c13e54 2004-02-29 devnull for(p=knownfmt; p->c; p++)
142 91c13e54 2004-02-29 devnull if(p->c == c){
143 91c13e54 2004-02-29 devnull __fmtinstall(p->c, p->fmt);
144 91c13e54 2004-02-29 devnull __fmtunlock();
145 91c13e54 2004-02-29 devnull return p->fmt;
146 91c13e54 2004-02-29 devnull }
147 91c13e54 2004-02-29 devnull __fmtunlock();
148 91c13e54 2004-02-29 devnull
149 91c13e54 2004-02-29 devnull return __badfmt;
150 91c13e54 2004-02-29 devnull }
151 91c13e54 2004-02-29 devnull
152 91c13e54 2004-02-29 devnull void*
153 91c13e54 2004-02-29 devnull __fmtdispatch(Fmt *f, void *fmt, int isrunes)
154 91c13e54 2004-02-29 devnull {
155 91c13e54 2004-02-29 devnull Rune rune, r;
156 91c13e54 2004-02-29 devnull int i, n;
157 91c13e54 2004-02-29 devnull
158 91c13e54 2004-02-29 devnull f->flags = 0;
159 91c13e54 2004-02-29 devnull f->width = f->prec = 0;
160 91c13e54 2004-02-29 devnull
161 91c13e54 2004-02-29 devnull for(;;){
162 91c13e54 2004-02-29 devnull if(isrunes){
163 91c13e54 2004-02-29 devnull r = *(Rune*)fmt;
164 91c13e54 2004-02-29 devnull fmt = (Rune*)fmt + 1;
165 91c13e54 2004-02-29 devnull }else{
166 91c13e54 2004-02-29 devnull fmt = (char*)fmt + chartorune(&rune, (char*)fmt);
167 91c13e54 2004-02-29 devnull r = rune;
168 91c13e54 2004-02-29 devnull }
169 91c13e54 2004-02-29 devnull f->r = r;
170 91c13e54 2004-02-29 devnull switch(r){
171 91c13e54 2004-02-29 devnull case '\0':
172 91c13e54 2004-02-29 devnull return nil;
173 91c13e54 2004-02-29 devnull case '.':
174 91c13e54 2004-02-29 devnull f->flags |= FmtWidth|FmtPrec;
175 91c13e54 2004-02-29 devnull continue;
176 91c13e54 2004-02-29 devnull case '0':
177 91c13e54 2004-02-29 devnull if(!(f->flags & FmtWidth)){
178 91c13e54 2004-02-29 devnull f->flags |= FmtZero;
179 91c13e54 2004-02-29 devnull continue;
180 91c13e54 2004-02-29 devnull }
181 91c13e54 2004-02-29 devnull /* fall through */
182 91c13e54 2004-02-29 devnull case '1': case '2': case '3': case '4':
183 91c13e54 2004-02-29 devnull case '5': case '6': case '7': case '8': case '9':
184 91c13e54 2004-02-29 devnull i = 0;
185 91c13e54 2004-02-29 devnull while(r >= '0' && r <= '9'){
186 91c13e54 2004-02-29 devnull i = i * 10 + r - '0';
187 91c13e54 2004-02-29 devnull if(isrunes){
188 91c13e54 2004-02-29 devnull r = *(Rune*)fmt;
189 91c13e54 2004-02-29 devnull fmt = (Rune*)fmt + 1;
190 91c13e54 2004-02-29 devnull }else{
191 91c13e54 2004-02-29 devnull r = *(char*)fmt;
192 91c13e54 2004-02-29 devnull fmt = (char*)fmt + 1;
193 91c13e54 2004-02-29 devnull }
194 91c13e54 2004-02-29 devnull }
195 91c13e54 2004-02-29 devnull if(isrunes)
196 91c13e54 2004-02-29 devnull fmt = (Rune*)fmt - 1;
197 91c13e54 2004-02-29 devnull else
198 91c13e54 2004-02-29 devnull fmt = (char*)fmt - 1;
199 91c13e54 2004-02-29 devnull numflag:
200 91c13e54 2004-02-29 devnull if(f->flags & FmtWidth){
201 91c13e54 2004-02-29 devnull f->flags |= FmtPrec;
202 91c13e54 2004-02-29 devnull f->prec = i;
203 91c13e54 2004-02-29 devnull }else{
204 91c13e54 2004-02-29 devnull f->flags |= FmtWidth;
205 91c13e54 2004-02-29 devnull f->width = i;
206 91c13e54 2004-02-29 devnull }
207 91c13e54 2004-02-29 devnull continue;
208 91c13e54 2004-02-29 devnull case '*':
209 91c13e54 2004-02-29 devnull i = va_arg(f->args, int);
210 91c13e54 2004-02-29 devnull if(i < 0){
211 91c13e54 2004-02-29 devnull /*
212 91c13e54 2004-02-29 devnull * negative precision =>
213 91c13e54 2004-02-29 devnull * ignore the precision.
214 91c13e54 2004-02-29 devnull */
215 91c13e54 2004-02-29 devnull if(f->flags & FmtPrec){
216 91c13e54 2004-02-29 devnull f->flags &= ~FmtPrec;
217 91c13e54 2004-02-29 devnull f->prec = 0;
218 91c13e54 2004-02-29 devnull continue;
219 91c13e54 2004-02-29 devnull }
220 91c13e54 2004-02-29 devnull i = -i;
221 91c13e54 2004-02-29 devnull f->flags |= FmtLeft;
222 91c13e54 2004-02-29 devnull }
223 91c13e54 2004-02-29 devnull goto numflag;
224 91c13e54 2004-02-29 devnull }
225 91c13e54 2004-02-29 devnull n = (*fmtfmt(r))(f);
226 91c13e54 2004-02-29 devnull if(n < 0)
227 91c13e54 2004-02-29 devnull return nil;
228 91c13e54 2004-02-29 devnull if(n == 0)
229 91c13e54 2004-02-29 devnull return fmt;
230 91c13e54 2004-02-29 devnull }
231 91c13e54 2004-02-29 devnull }