├── .travis.yml ├── COPYRIGHT.md ├── LICENSE.md ├── README.md ├── makefile ├── mini_printf.c ├── sys.h └── testprog.c /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | compiler: 3 | - clang 4 | - gcc 5 | os: 6 | - linux 7 | - os 8 | script: 9 | - make 10 | - make stresstest 11 | -------------------------------------------------------------------------------- /COPYRIGHT.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Wojciech Adam Koszek 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions 6 | are met: 7 | 1. Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 | ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 | SUCH DAMAGE. 24 | 25 | 26 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Wojciech A. Koszek 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## mini_printf - minimal, self-contained and tested printf() 2 | 3 | [![Build Status](https://travis-ci.org/wkoszek/mini_printf.svg)](https://travis-ci.org/wkoszek/mini_printf) 4 | 5 | This is a minimal `printf()` implementation that doesn't depend on any other 6 | libraries. It's meant to be used for early bootstrapping of DSLs and 7 | embeddable programs, as well as bare-metal software. It supports `%x` and 8 | `%d` format string specifiers only. One can easily extend `mini_printf.c` 9 | for additional format strings. 10 | 11 | # How to use it 12 | 13 | The `mini_printf` comes in 1 C file called `mini_printf.c`. It has a 14 | function called `pf(const char *fmt, ...)` which works exactly how `printf` 15 | does. It's named `pf()` to prevent from eventual collisions with other 16 | printf-alike API you may have in your programs. 17 | 18 | To use it, include `mini_printf.c` in your program. It only wants one thing 19 | from you: you must provide it a `io_putc(int c)` function, which is used 20 | internally to do an actual I/O. You should be able to later call: 21 | 22 | pf("sample"); 23 | 24 | and get yours `io_putc` routine called for each character. 25 | 26 | # How it was tested 27 | 28 | The biggest effort went into verification. Testing of `printf` is very 29 | important, since failure of `printf` can lead to many hours of frustration 30 | and debugging, so I tried to make it less likely. 31 | 32 | The `testprog.c` has a randomized stress test suite proving my `pf()` is 33 | fairly robust. Stress test basically generates random format strings in a 34 | smart way and plays them against system `printf()` and `mini_printf` and 35 | then tries to compare the results. Mismatch means a failure of the test. 36 | 37 | To start stress-testing, type: 38 | 39 | make stresstest 40 | 41 | It'll try to generate 1,000,000 random settings and play them against 42 | `mini_printf`. 43 | 44 | Several other useful targets are: 45 | 46 | - make test.vv 47 | - very verbose and slow test. Mostly for development. 48 | - make test.v 49 | - less verbose test. Slightly slower due to not all test data printed out. 50 | - make test 51 | - long-running test for very stressful testing. Can make your MacBook Air 52 | boil 53 | - make unittest 54 | - unit-testing, for the cases when bugs are found 55 | 56 | Underlying program for all tests is `testprog`. Its usage: 57 | 58 | Flag | Description 59 | :-------|:------------------------------------------------- 60 | d | turn debugging on. Can be specified more than once 61 | l | how many loops to run. 1 loop = 1 chunk of format string. Default: 6. 62 | m | print mask: frequency of printouts after each test execution 63 | t | start only unit test. 64 | w | wait nanoseconds after each test. For debugging only. 65 | p | print generated format strings 66 | s | stop after tests. 67 | v | verbose mode. 68 | 69 | # Examples 70 | 71 | You've looked at the source and want to run only unit test number 11: 72 | 73 | ./testprog -d -t 11 74 | 75 | You want to run all unit tests: 76 | 77 | ./testprog -d 78 | 79 | You want to figure out what's going on: random format strings need to be 80 | short (`-l 1`), output must be slow (`-w 500000`) and verbose (`-d -v -p`), and 81 | every generated test must be printed out (`-m 0`): 82 | 83 | ./testprog -w 500000 -l 1 -d -v -m 0 -p 84 | 85 | # Author 86 | 87 | - Wojciech Adam Koszek, [wojciech@koszek.com](mailto:wojciech@koszek.com) 88 | - [http://www.koszek.com](http://www.koszek.com) 89 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | all: testprog mini_printf.so 2 | 3 | SRC= mini_printf.c testprog.c 4 | 5 | CFLAGS+= -Wall -pedantic -std=c99 6 | LIBFLAGS+= -fno-stack-protector -fPIC -fpic 7 | 8 | UNAME := $(shell uname -s) 9 | ifeq ($(UNAME),Darwin) 10 | CFLAGS+=-DMACOSX_PRINTF 11 | endif 12 | 13 | testprog: $(SRC) sys.h 14 | $(CC) $(CFLAGS) -DTESTPROG $(SRC) -o testprog 15 | mini_printf.so: $(SRC) sys.h 16 | $(CC) $(CFLAGS) $(LIBFLAGS) -nostdlib -o mini_printf.so -shared $(SRC) 17 | analyze: 18 | scan-build -o /tmp/_.mini_printf make -j4 19 | 20 | test.vv: 21 | ./testprog -m 0 -v 22 | test.v: 23 | ./testprog -m 15 -v 24 | test: 25 | ./testprog -m 4095 -v 26 | unittest: 27 | ./testprog -d 28 | stresstest: 29 | ./testprog -v -s 1000000 -m 16383 $$RANDOM 30 | 31 | clean: 32 | rm -rf testprog 33 | rm -rf mini_printf.so 34 | -------------------------------------------------------------------------------- /mini_printf.c: -------------------------------------------------------------------------------- 1 | #include "sys.h" 2 | 3 | extern void io_putc(int c); 4 | 5 | typedef unsigned int u32; 6 | typedef unsigned long u64; 7 | 8 | /* 9 | * String to number conversion 10 | */ 11 | int 12 | vpf_str_to_num(const char *fmtstr, int *resnum) 13 | { 14 | const char *cptr; 15 | int res, digit, is_digit; 16 | 17 | res = 0; 18 | for (cptr = fmtstr; *fmtstr != '\0'; cptr++) { 19 | is_digit = (*cptr >= '0' && *cptr <= '9'); 20 | if (!is_digit) { 21 | break; 22 | } 23 | digit = *cptr - '0'; 24 | res *= 10; 25 | res += digit; 26 | } 27 | *resnum = res; 28 | return ((int)(cptr - fmtstr)); 29 | } 30 | 31 | /* 32 | * Number to string conversion 33 | */ 34 | void 35 | vpf_num_to_str(u32 a, int is_hex, int pad_len, int pad_char) 36 | { 37 | char buf[32]; 38 | u32 base; 39 | int bufidx, i; 40 | 41 | for (i = 0; i < sizeof(buf); i++) { 42 | buf[i] = pad_char; 43 | } 44 | base = 10; 45 | if (is_hex) { 46 | base = 16; 47 | } 48 | dprintf(stderr, "a=%08x, base=%d\n", a, base); 49 | bufidx = 0; 50 | do { 51 | dprintf(stderr, "a %% base = %d\n", a % base); 52 | buf[bufidx] = "0123456789abcdef" [ a % base ]; 53 | dprintf(stderr, "buf=%c, bufidx=%d\n", buf[bufidx], bufidx); 54 | a /= base; 55 | bufidx++; 56 | } while (a > 0); 57 | 58 | if (pad_len > 0) { 59 | if (pad_len >= sizeof(buf)) { 60 | pad_len = sizeof(buf) - 1; 61 | } 62 | if (bufidx < pad_len) { 63 | bufidx = pad_len; 64 | } 65 | } 66 | buf[bufidx] = '\0'; 67 | 68 | for (i = bufidx - 1; i >= 0; i--) { 69 | io_putc(buf[i]); 70 | } 71 | } 72 | 73 | /* 74 | * Main body of vpf() routine. Main parsing of the print format happens here 75 | */ 76 | int 77 | vpf(const char *fmtstr, va_list va) 78 | { 79 | const char *cptr, *prefmtptr; 80 | int fmt, c, va_int, pad_len, pad_char, i; 81 | 82 | pad_char = ' '; 83 | for (cptr = fmtstr; *cptr != '\0'; cptr++) { 84 | fmt = 0; 85 | pad_len = 0; 86 | c = *cptr; 87 | prefmtptr = cptr; 88 | if (*cptr == '%') { 89 | prefmtptr = cptr; 90 | cptr++; 91 | if (*cptr >= '0' && *cptr <= '9') { 92 | dprintf(stderr, "PAD *cptr = %c\n", *cptr); 93 | cptr += vpf_str_to_num(cptr, &pad_len); 94 | } 95 | fmt = *cptr; 96 | dprintf(stderr, "fmt=%c\n", fmt); 97 | } 98 | if ((fmt == 'd') || (fmt == 'x')) { 99 | va_int = va_arg(va, int); 100 | dprintf(stderr, "va_int=%08x, pad_len=%d\n", va_int, 101 | pad_len); 102 | vpf_num_to_str(va_int, fmt == 'x', pad_len, pad_char); 103 | } else { 104 | #ifndef MACOSX_PRINTF 105 | for (i = 0; i < (cptr - prefmtptr); i++) { 106 | dprintf(stderr, "C=%c\n", prefmtptr[i]); 107 | io_putc(prefmtptr[i]); 108 | } 109 | #else 110 | for (i = 0; i < pad_len - 1; i++) { 111 | io_putc(pad_char); 112 | } 113 | #endif 114 | io_putc(fmt != 0 ? fmt : c); 115 | } 116 | } 117 | return 0; 118 | } 119 | 120 | /* 121 | * Mini printf called "pf" 122 | */ 123 | int 124 | pf(const char *fmt, ...) 125 | { 126 | va_list va; 127 | 128 | va_start(va, fmt); 129 | vpf(fmt, va); 130 | va_end(va); 131 | return 0; 132 | } 133 | -------------------------------------------------------------------------------- /sys.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef TESTPROG 4 | #include 5 | #endif 6 | 7 | #ifdef TESTPROG 8 | extern int g_debug; 9 | #define dprintf if (g_debug) fprintf 10 | #else 11 | #define dprintf(...) 12 | #endif 13 | 14 | extern int pf(const char *fmt, ...); 15 | -------------------------------------------------------------------------------- /testprog.c: -------------------------------------------------------------------------------- 1 | /* 2 | * mini_printf (c) 2012 Wojciech A. Koszek 3 | * 4 | * Along with the main function included is a testbench for verification 5 | * that mini_printf() is as close and accurate as possible with the main 6 | * stdlib's function printf(). 7 | * 8 | * lcg_* routines use Lehmer random number generator, and the code is 9 | * inspired by: 10 | * 11 | * http://en.wikipedia.org/wiki/Park–Miller_random_number_generator 12 | */ 13 | #define _BSD_SOURCE 14 | #include 15 | #include 16 | #ifndef __APPLE__ 17 | #include 18 | #endif 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "sys.h" 28 | 29 | #define TMPBUF_LEN 1024 30 | 31 | typedef uint32_t u32; 32 | typedef uint64_t u64; 33 | 34 | /* Knobs */ 35 | int g_knob_no_minus = 1; 36 | 37 | /* Settings */ 38 | u64 g_test_print_mask = 0; 39 | int g_loops = 6; 40 | int g_print = 0; 41 | u32 g_stop_after_test = -1; 42 | 43 | /* Debugging */ 44 | int g_debug = 0; 45 | 46 | /* 47 | * I/O buffer which will immitate stdio's underlying (read: setvbuf()) 48 | * buffer. 49 | */ 50 | char io_putc_buf[10*TMPBUF_LEN]; 51 | int io_putc_buf_idx = 0; 52 | 53 | /* Sample I/O routine with no buffering for now. */ 54 | void 55 | io_putc(int c) 56 | { 57 | 58 | io_putc_buf[io_putc_buf_idx] = c; 59 | io_putc_buf_idx++; 60 | 61 | #ifdef TESTPROG 62 | assert(io_putc_buf_idx < sizeof(io_putc_buf)); 63 | #endif 64 | } 65 | 66 | #ifdef TESTPROG 67 | /* 68 | * Delay between generating vectors 69 | */ 70 | static int g_delay = 0; 71 | 72 | /* 73 | * lcg_* is a bit awkward, but I wanted to make these two functions 74 | * self-contained, and not depending on any global variables. 75 | */ 76 | u32 77 | lcg_getset(u32 seed, int is_set) 78 | { 79 | static int lcg_seed; 80 | 81 | if (is_set) { 82 | lcg_seed = seed; 83 | } 84 | return lcg_seed; 85 | } 86 | 87 | u32 88 | lcg_rand(void) 89 | { 90 | int is_set; 91 | u32 val, ret32; 92 | u64 ret64; 93 | 94 | val = lcg_getset(0, is_set=0); /* get internal seed */ 95 | if (val == 0) { /* first invocatoin? */ 96 | lcg_getset(123, is_set=1); /* initialize 123 */ 97 | val = lcg_getset(0, is_set=0); 98 | } 99 | ret64 = ((uint64_t)val * 279470273UL) % 4294967291UL; 100 | ret32 = (u32)ret64; 101 | (void)lcg_getset(ret32, is_set=1); 102 | return ret32; 103 | } 104 | 105 | void 106 | verif(int argc, char **argv) 107 | { 108 | u32 seed, test_num; 109 | char fmtstr[TMPBUF_LEN]; 110 | char *cptr; 111 | int i, j; 112 | u32 args[6]; 113 | int (*f_printf)(char *, const char *fmt, ...); 114 | int (*f_pf)(const char *fmt, ...); 115 | char cmp_sys[TMPBUF_LEN], cmp_mini_pf[TMPBUF_LEN], 116 | diffbuf[TMPBUF_LEN]; 117 | 118 | printf(" verif() is starting..\n"); 119 | printf(" g_test_print_mask=%llx, g_delay=%d, g_debug=%d g_print=%d\n", 120 | (long long)g_test_print_mask, g_delay, g_debug, g_print); 121 | 122 | f_printf = sprintf; // stay away from compiler warnings 123 | f_pf = pf; 124 | 125 | seed = 13; 126 | if (argc == 1) { 127 | seed = (u32)strtol(argv[0], (char **) NULL, 16); 128 | lcg_getset(seed, 1); 129 | } 130 | printf(" seed=%#08x, argv[0]=%s\n", seed, argv[0]); 131 | for (test_num = 0; ;test_num++) { 132 | if ((test_num & g_test_print_mask) == g_test_print_mask) { 133 | fprintf(stderr, "TEST 0x%016lx SEED 0x%08x\n", 134 | (unsigned long)test_num, lcg_getset(0, 0)); 135 | } 136 | if ((g_stop_after_test != -1) && 137 | (test_num >= g_stop_after_test)) { 138 | fprintf(stderr, " Requested stop after %d tests\n" 139 | "Terminating!\n", g_stop_after_test); 140 | break; 141 | } 142 | 143 | cptr = fmtstr; 144 | u32 loop_num = 1 + (lcg_rand() % 0x7); 145 | if (loop_num > g_loops) { 146 | loop_num = g_loops; 147 | } 148 | for (j = 0; j < loop_num; j++) { 149 | u32 pre_str_has = lcg_rand() & 1; 150 | u32 pre_str_len = lcg_rand() & 0xf; 151 | u32 is_correct = lcg_rand() & 1; 152 | u32 has_pad = lcg_rand() & 1; 153 | u32 pad_len = lcg_rand() & 0x7; 154 | u32 has_hex = lcg_rand() & 1; 155 | u32 has_d = lcg_rand() & 0xff; 156 | u32 post_str_has = lcg_rand() & 1; 157 | u32 post_str_len = lcg_rand() & 0xf; 158 | 159 | /* Fill the arguments array so we can use it later */ 160 | for (i = 0; i < 6; i++) { 161 | args[i] = lcg_rand(); 162 | if (g_knob_no_minus) { 163 | /* very simple workaround */ 164 | args[i] &= 0x7fffffff; 165 | } 166 | } 167 | if (pre_str_has) { 168 | for (i = 0; i < pre_str_len; i++) { 169 | *cptr++ = 'a' + (lcg_rand() % 30); 170 | } 171 | } 172 | if (is_correct) { 173 | *cptr++ = '%'; 174 | } 175 | if (has_pad) { 176 | *cptr++ = "123456789"[pad_len]; 177 | } 178 | if (has_hex) { 179 | *cptr++ = 'x'; 180 | } 181 | if (has_d) { 182 | *cptr++ = 'd'; 183 | } 184 | if (!has_hex || has_d) { 185 | /* 186 | * make sure we don't insert sprintf() 187 | * valid format, which isn't supported by 188 | * mini_printf 189 | */ 190 | *cptr++ = 'W'; 191 | } 192 | 193 | if (post_str_has) { 194 | for (i = 0; i < post_str_len; i++) { 195 | *cptr = 'a' + (lcg_rand() % 20); 196 | cptr++; 197 | } 198 | } 199 | } 200 | 201 | *cptr++ = 0; 202 | 203 | /* C library printf() puts value to cmp_sys */ 204 | f_printf(cmp_sys, fmtstr, args[0], args[1], args[2], args[3], 205 | args[4], args[5]); 206 | 207 | /* Reset the test buffer */ 208 | memset(io_putc_buf, 0, sizeof(io_putc_buf)); 209 | io_putc_buf_idx = 0; 210 | 211 | f_pf(fmtstr, args[0], args[1], args[2], args[3], args[4], 212 | args[5]); 213 | strcpy(cmp_mini_pf, io_putc_buf); 214 | 215 | if (g_print > 0) { 216 | fprintf(stderr, " SYS : '%s'\n", cmp_sys); 217 | fprintf(stderr, " PF : '%s'\n", cmp_mini_pf); 218 | } 219 | if (strcmp(cmp_sys, cmp_mini_pf) != 0) { 220 | printf("==== printf() != mini_printf() mismatch ====\n"); 221 | printf("fmtstr='%s'\n", fmtstr); 222 | memset(diffbuf, '.', sizeof(diffbuf)); 223 | for (i = 0; i < strlen(cmp_sys); i++) { 224 | if (cmp_sys[i] != cmp_mini_pf[i]) { 225 | diffbuf[i] = '^'; 226 | } 227 | } 228 | diffbuf[i] = 0; 229 | 230 | printf(" SYS_PF:%s\n", cmp_sys); 231 | printf("MINI_PF:%s\n", cmp_mini_pf); 232 | printf(" diff:%s\n", diffbuf); 233 | printf("=====\n"); 234 | printf("pf(\"%s\", %08x, %08x, %08x, %08x, %08x, %08x);\n", 235 | fmtstr, 236 | args[0], args[1], args[2], args[3], args[4], 237 | args[5]); 238 | printf("=====\n"); 239 | exit(1); 240 | } 241 | usleep(g_delay); 242 | } 243 | } 244 | 245 | static void 246 | usage(const char *progname) 247 | { 248 | fprintf(stderr, "%s usage:\n", progname); 249 | fprintf(stderr, "-d increase debug level\n"); 250 | fprintf(stderr, "-m test print mask\n"); 251 | fprintf(stderr, "-l loops for format creation " 252 | "(lower=shorter format string\n"); 253 | fprintf(stderr, "-t run just unit test\n"); 254 | fprintf(stderr, "-w delay test execution by seconds\n"); 255 | fprintf(stderr, "-v start verification\n"); 256 | } 257 | 258 | int 259 | main(int argc, char **argv) 260 | { 261 | int o, flag_v, flag_debug, arg_mask, arg_delay, arg_loops; 262 | int test_num; 263 | 264 | memset(io_putc_buf, 0, sizeof(io_putc_buf)); 265 | 266 | if (argc == 1) { 267 | usage(argv[0]); 268 | exit(64); 269 | } 270 | 271 | flag_v = flag_debug = arg_mask = arg_delay = arg_loops = test_num = 0; 272 | while ((o = getopt(argc, argv, "dn:m:vw:l:t:ps:")) != -1) { 273 | switch (o) { 274 | case 'd': 275 | flag_debug++; 276 | break; 277 | case 'l': 278 | arg_loops = atoi(optarg); 279 | break; 280 | case 'm': 281 | arg_mask = atoi(optarg); 282 | break; 283 | case 't': 284 | test_num = atoi(optarg); 285 | break; 286 | case 'w': 287 | arg_delay = atoi(optarg); 288 | break; 289 | case 'p': 290 | g_print++; 291 | break; 292 | case 's': 293 | g_stop_after_test = atoi(optarg); 294 | break; 295 | case 'v': 296 | flag_v = 1; 297 | break; 298 | default: 299 | abort(); 300 | } 301 | } 302 | 303 | argc -= optind; 304 | argv += optind; 305 | 306 | if (!flag_v && ((arg_mask + arg_delay + arg_loops) > 0)) { 307 | fprintf(stderr, "-d/-m/-w only make sense with -v\n"); 308 | exit(1); 309 | } 310 | 311 | g_debug = flag_debug; 312 | g_test_print_mask = arg_mask; 313 | g_delay = arg_delay; 314 | if (arg_loops) { 315 | g_loops = arg_loops; 316 | } 317 | 318 | if (!flag_v) { 319 | if (test_num == 0 || test_num == 1) pf("wojtek\n"); 320 | if (test_num == 0 || test_num == 2) pf("wojtek'\n"); 321 | if (test_num == 0 || test_num == 3) pf("zero '%d'\n", 0); 322 | if (test_num == 0 || test_num == 4) pf("wojtek %d'\n", 123); 323 | if (test_num == 0 || test_num == 5) pf("'wojtek %d %d'\n", 123, 789); 324 | if (test_num == 0 || test_num == 6) pf("'wojtek %x %x'\n", 123, 789); 325 | if (test_num == 0 || test_num == 7) pf("len8 == '%08x'\n", 0x123); 326 | if (test_num == 0 || test_num == 8) pf("len8 == '%08x'\n", 0x0); 327 | if (test_num == 0 || test_num == 9) pf("len2 == '%012x'\n", 0x123); 328 | if (test_num == 0 || test_num == 10) pf("%7d\n", 123); 329 | if (test_num == 0 || test_num == 11) pf("%k%k", 1, 1); 330 | if (test_num == 0 || test_num == 12) pf("woj%6Wtek", 1); 331 | printf("buf='%s'\n", io_putc_buf); 332 | } else { 333 | printf("Verifying mini_printf.c\n"); 334 | verif(argc, argv); 335 | } 336 | return 0; 337 | } 338 | #endif 339 | --------------------------------------------------------------------------------