Introduction
Introduction Statistics Contact Development Disclaimer Help
fmt.c - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
LICENSE
---
fmt.c (3575B)
---
1 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
2 #include <stdarg.h>
3 #include <string.h>
4 #include "plan9.h"
5 #include "fmt.h"
6 #include "fmtdef.h"
7
8 enum
9 {
10 Maxfmt = 64
11 };
12
13 typedef struct Convfmt Convfmt;
14 struct Convfmt
15 {
16 int c;
17 volatile Fmts fmt; /* for spin lock in fmtf…
18 };
19
20 static struct
21 {
22 /* lock by calling __fmtlock, __fmtunlock */
23 int nfmt;
24 Convfmt fmt[Maxfmt];
25 } fmtalloc;
26
27 static Convfmt knownfmt[] = {
28 ' ', __flagfmt,
29 '#', __flagfmt,
30 '%', __percentfmt,
31 '\'', __flagfmt,
32 '+', __flagfmt,
33 ',', __flagfmt,
34 '-', __flagfmt,
35 'C', __runefmt, /* Plan 9 addition */
36 'E', __efgfmt,
37 #ifndef PLAN9PORT
38 'F', __efgfmt, /* ANSI only */
39 #endif
40 'G', __efgfmt,
41 #ifndef PLAN9PORT
42 'L', __flagfmt, /* ANSI only */
43 #endif
44 'S', __runesfmt, /* Plan 9 addition */
45 'X', __ifmt,
46 'b', __ifmt, /* Plan 9 addition */
47 'c', __charfmt,
48 'd', __ifmt,
49 'e', __efgfmt,
50 'f', __efgfmt,
51 'g', __efgfmt,
52 'h', __flagfmt,
53 #ifndef PLAN9PORT
54 'i', __ifmt, /* ANSI only */
55 #endif
56 'l', __flagfmt,
57 'n', __countfmt,
58 'o', __ifmt,
59 'p', __ifmt,
60 'r', __errfmt,
61 's', __strfmt,
62 #ifdef PLAN9PORT
63 'u', __flagfmt,
64 #else
65 'u', __ifmt,
66 #endif
67 'x', __ifmt,
68 0, nil,
69 };
70
71
72 int (*fmtdoquote)(int);
73
74 /*
75 * __fmtlock() must be set
76 */
77 static int
78 __fmtinstall(int c, Fmts f)
79 {
80 Convfmt *p, *ep;
81
82 if(c<=0 || c>=65536)
83 return -1;
84 if(!f)
85 f = __badfmt;
86
87 ep = &fmtalloc.fmt[fmtalloc.nfmt];
88 for(p=fmtalloc.fmt; p<ep; p++)
89 if(p->c == c)
90 break;
91
92 if(p == &fmtalloc.fmt[Maxfmt])
93 return -1;
94
95 p->fmt = f;
96 if(p == ep){ /* installing a new format character */
97 fmtalloc.nfmt++;
98 p->c = c;
99 }
100
101 return 0;
102 }
103
104 int
105 fmtinstall(int c, int (*f)(Fmt*))
106 {
107 int ret;
108
109 __fmtlock();
110 ret = __fmtinstall(c, f);
111 __fmtunlock();
112 return ret;
113 }
114
115 static Fmts
116 fmtfmt(int c)
117 {
118 Convfmt *p, *ep;
119
120 ep = &fmtalloc.fmt[fmtalloc.nfmt];
121 for(p=fmtalloc.fmt; p<ep; p++)
122 if(p->c == c){
123 while(p->fmt == nil) /* loop until value …
124 ;
125 return p->fmt;
126 }
127
128 /* is this a predefined format char? */
129 __fmtlock();
130 for(p=knownfmt; p->c; p++)
131 if(p->c == c){
132 __fmtinstall(p->c, p->fmt);
133 __fmtunlock();
134 return p->fmt;
135 }
136 __fmtunlock();
137
138 return __badfmt;
139 }
140
141 void*
142 __fmtdispatch(Fmt *f, void *fmt, int isrunes)
143 {
144 Rune rune, r;
145 int i, n;
146
147 f->flags = 0;
148 f->width = f->prec = 0;
149
150 for(;;){
151 if(isrunes){
152 r = *(Rune*)fmt;
153 fmt = (Rune*)fmt + 1;
154 }else{
155 fmt = (char*)fmt + chartorune(&rune, (char*)fmt);
156 r = rune;
157 }
158 f->r = r;
159 switch(r){
160 case '\0':
161 return nil;
162 case '.':
163 f->flags |= FmtWidth|FmtPrec;
164 continue;
165 case '0':
166 if(!(f->flags & FmtWidth)){
167 f->flags |= FmtZero;
168 continue;
169 }
170 /* fall through */
171 case '1': case '2': case '3': case '4':
172 case '5': case '6': case '7': case '8': case '9':
173 i = 0;
174 while(r >= '0' && r <= '9'){
175 i = i * 10 + r - '0';
176 if(isrunes){
177 r = *(Rune*)fmt;
178 fmt = (Rune*)fmt + 1;
179 }else{
180 r = *(char*)fmt;
181 fmt = (char*)fmt + 1;
182 }
183 }
184 if(isrunes)
185 fmt = (Rune*)fmt - 1;
186 else
187 fmt = (char*)fmt - 1;
188 numflag:
189 if(f->flags & FmtWidth){
190 f->flags |= FmtPrec;
191 f->prec = i;
192 }else{
193 f->flags |= FmtWidth;
194 f->width = i;
195 }
196 continue;
197 case '*':
198 i = va_arg(f->args, int);
199 if(i < 0){
200 /*
201 * negative precision =>
202 * ignore the precision.
203 */
204 if(f->flags & FmtPrec){
205 f->flags &= ~FmtPrec;
206 f->prec = 0;
207 continue;
208 }
209 i = -i;
210 f->flags |= FmtLeft;
211 }
212 goto numflag;
213 }
214 n = (*fmtfmt(r))(f);
215 if(n < 0)
216 return nil;
217 if(n == 0)
218 return fmt;
219 }
220 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.