Introduction
Introduction Statistics Contact Development Disclaimer Help
printf.c - sbase - suckless unix tools
git clone git://git.suckless.org/sbase
Log
Files
Refs
README
LICENSE
---
printf.c (4127B)
---
1 /* See LICENSE file for copyright and license details. */
2 #include <ctype.h>
3 #include <errno.h>
4 #include <limits.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8
9 #include "utf.h"
10 #include "util.h"
11
12 static void
13 usage(void)
14 {
15 eprintf("usage: %s format [arg ...]\n", argv0);
16 }
17
18 int
19 main(int argc, char *argv[])
20 {
21 Rune *rarg;
22 size_t i, j, f, argi, lastargi, formatlen, blen, nflags;
23 long long num;
24 double dou;
25 int cooldown = 0, width, precision, ret = 0;
26 char *format, *tmp, *arg, *fmt;
27
28 argv0 = argv[0];
29 if (argc < 2)
30 usage();
31
32 format = argv[1];
33 if ((tmp = strstr(format, "\\c"))) {
34 *tmp = 0;
35 cooldown = 1;
36 }
37 formatlen = unescape(format);
38 if (formatlen == 0)
39 return 0;
40 lastargi = 0;
41 for (i = 0, argi = 2; !cooldown || i < formatlen; i++, i = coold…
42 if (i == 0) {
43 if (lastargi == argi)
44 break;
45 lastargi = argi;
46 }
47
48 if (format[i] != '%') {
49 putchar(format[i]);
50 continue;
51 }
52
53 /* flag */
54 f = ++i;
55 nflags = strspn(&format[f], "#-+ 0");
56 i += nflags;
57
58 if (nflags > INT_MAX)
59 eprintf("Too many flags in format\n");
60
61 /* field width */
62 width = -1;
63 if (format[i] == '*') {
64 if (argi < argc)
65 width = estrtonum(argv[argi++], 0, INT_M…
66 else
67 cooldown = 1;
68 i++;
69 } else {
70 j = i;
71 i += strspn(&format[i], "+-0123456789");
72 if (j != i) {
73 tmp = estrndup(format + j, i - j);
74 width = estrtonum(tmp, 0, INT_MAX);
75 free(tmp);
76 } else {
77 width = 0;
78 }
79 }
80
81 /* field precision */
82 precision = -1;
83 if (format[i] == '.') {
84 if (format[++i] == '*') {
85 if (argi < argc)
86 precision = estrtonum(argv[argi+…
87 else
88 cooldown = 1;
89 i++;
90 } else {
91 j = i;
92 i += strspn(&format[i], "+-0123456789");
93 if (j != i) {
94 tmp = estrndup(format + j, i - j…
95 precision = estrtonum(tmp, 0, IN…
96 free(tmp);
97 } else {
98 precision = 0;
99 }
100 }
101 }
102
103 if (format[i] != '%') {
104 if (argi < argc)
105 arg = argv[argi++];
106 else {
107 arg = "";
108 cooldown = 1;
109 }
110 } else {
111 putchar('%');
112 continue;
113 }
114
115 switch (format[i]) {
116 case 'b':
117 if ((tmp = strstr(arg, "\\c"))) {
118 *tmp = 0;
119 blen = unescape(arg);
120 fwrite(arg, sizeof(*arg), blen, stdout);
121 return 0;
122 }
123 blen = unescape(arg);
124 fwrite(arg, sizeof(*arg), blen, stdout);
125 break;
126 case 'c':
127 unescape(arg);
128 rarg = ereallocarray(NULL, utflen(arg) + 1, size…
129 utftorunestr(arg, rarg);
130 efputrune(rarg, stdout, "<stdout>");
131 free(rarg);
132 break;
133 case 's':
134 fmt = emalloc(sizeof("%*.*s") + nflags);
135 sprintf(fmt, "%%%.*s*.*s", (int)nflags, &format[…
136 printf(fmt, width, precision, arg);
137 free(fmt);
138 break;
139 case 'd': case 'i': case 'o': case 'u': case 'x': case '…
140 for (j = 0; isspace(arg[j]); j++);
141 if (arg[j] == '\'' || arg[j] == '\"') {
142 arg += j + 1;
143 unescape(arg);
144 rarg = ereallocarray(NULL, utflen(arg) +…
145 utftorunestr(arg, rarg);
146 num = rarg[0];
147 } else if (arg[0]) {
148 errno = 0;
149 if (format[i] == 'd' || format[i] == 'i')
150 num = strtol(arg, &tmp, 0);
151 else
152 num = strtoul(arg, &tmp, 0);
153
154 if (tmp == arg || *tmp != '\0') {
155 ret = 1;
156 weprintf("%%%c %s: conversion er…
157 format[i], arg);
158 }
159 if (errno == ERANGE) {
160 ret = 1;
161 weprintf("%%%c %s: out of range\…
162 format[i], arg);
163 }
164 } else {
165 num = 0;
166 }
167 fmt = emalloc(sizeof("%*.*ll#") + nflags);
168 sprintf(fmt, "%%%.*s*.*ll%c", (int)nflags, &form…
169 printf(fmt, width, precision, num);
170 free(fmt);
171 break;
172 case 'a': case 'A': case 'e': case 'E': case 'f': case '…
173 fmt = emalloc(sizeof("%*.*#") + nflags);
174 sprintf(fmt, "%%%.*s*.*%c", (int)nflags, &format…
175 dou = (strlen(arg) > 0) ? estrtod(arg) : 0;
176 printf(fmt, width, precision, dou);
177 free(fmt);
178 break;
179 case '\0':
180 eprintf("Missing format specifier.\n");
181 default:
182 eprintf("Invalid format specifier '%c'.\n", form…
183 }
184 if (argi >= argc)
185 cooldown = 1;
186 }
187
188 return fshut(stdout, "<stdout>") | ret;
189 }
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.