.
[coreutils.git] / src / printf.c
blob7c5f338a96c56e351886c0278b3e4c3492007a47
1 /* printf - format and print data
2 Copyright (C) 90, 91, 92, 93, 94, 1995 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
18 /* Usage: printf format [argument...]
20 A front end to the printf function that lets it be used from the shell.
22 Backslash escapes:
24 \" = double quote
25 \\ = backslash
26 \a = alert (bell)
27 \b = backspace
28 \c = produce no further output
29 \f = form feed
30 \n = new line
31 \r = carriage return
32 \t = horizontal tab
33 \v = vertical tab
34 \0ooo = octal number (ooo is 0 to 3 digits)
35 \xhhh = hexadecimal number (hhh is 1 to 3 digits)
37 Additional directive:
39 %b = print an argument string, interpreting backslash escapes
41 The `format' argument is re-used as many times as necessary
42 to convert all of the given arguments.
44 David MacKenzie <djm@gnu.ai.mit.edu> */
46 #include <config.h>
47 #include <stdio.h>
48 #include <sys/types.h>
49 #include <getopt.h>
51 #include "system.h"
52 #include "version.h"
53 #include "long-options.h"
54 #include "error.h"
56 #ifndef STDC_HEADERS
57 double strtod ();
58 long strtol ();
59 unsigned long strtoul ();
60 #endif
62 #define isodigit(c) ((c) >= '0' && (c) <= '7')
63 #define hextobin(c) ((c)>='a'&&(c)<='f' ? (c)-'a'+10 : (c)>='A'&&(c)<='F' ? (c)-'A'+10 : (c)-'0')
64 #define octtobin(c) ((c) - '0')
66 char *xmalloc ();
68 static double xstrtod __P ((char *s));
69 static int print_esc __P ((char *escstart));
70 static int print_formatted __P ((char *format, int argc, char **argv));
71 static long xstrtol __P ((char *s));
72 static unsigned long xstrtoul __P ((char *s));
73 static void print_direc __P ((char *start, size_t length, int field_width, int precision, char *argument));
74 static void print_esc_char __P ((int c));
75 static void print_esc_string __P ((char *str));
76 static void verify __P ((char *s, char *end));
78 /* The value to return to the calling program. */
79 static int exit_status;
81 /* The name this program was run with. */
82 char *program_name;
84 static void
85 usage (int status)
87 if (status != 0)
88 fprintf (stderr, _("Try `%s --help' for more information.\n"),
89 program_name);
90 else
92 printf (_("\
93 Usage: %s FORMAT [ARGUMENT]...\n\
94 or: %s OPTION\n\
95 "),
96 program_name, program_name);
97 printf (_("\
98 Print ARGUMENT(s) according to FORMAT.\n\
99 \n\
100 --help display this help and exit\n\
101 --version output version information and exit\n\
103 FORMAT controls the output as in C printf. Interpreted sequences are:\n\
105 \\\" double quote\n\
106 \\0NNN character with octal value NNN (0 to 3 digits)\n\
107 \\\\ backslash\n\
108 \\a alert (BEL)\n\
109 \\b backspace\n\
110 \\c produce no further output\n\
111 \\f form feed\n\
112 \\n new line\n\
113 \\r carriage return\n\
114 \\t horizontal tab\n\
115 \\v vertical tab\n\
116 \\xNNN character with hexadecimal value NNN (1 to 3 digits)\n\
118 %%%% a single %%\n\
119 %%b ARGUMENT as a string with `\\' escapes interpreted\n\
121 and all C format specifications ending with one of diouxXfeEgGcs, with\n\
122 ARGUMENTs converted to proper type first. Variable widths are handled.\n\
123 "));
125 exit (status);
128 void
129 main (int argc, char **argv)
131 char *format;
132 int args_used;
134 program_name = argv[0];
135 setlocale (LC_ALL, "");
136 bindtextdomain (PACKAGE, LOCALEDIR);
137 textdomain (PACKAGE);
139 exit_status = 0;
141 parse_long_options (argc, argv, "printf", version_string, usage);
143 if (argc == 1)
145 fprintf (stderr, _("Usage: %s format [argument...]\n"), program_name);
146 exit (1);
149 format = argv[1];
150 argc -= 2;
151 argv += 2;
155 args_used = print_formatted (format, argc, argv);
156 argc -= args_used;
157 argv += args_used;
159 while (args_used > 0 && argc > 0);
161 exit (exit_status);
164 /* Print the text in FORMAT, using ARGV (with ARGC elements) for
165 arguments to any `%' directives.
166 Return the number of elements of ARGV used. */
168 static int
169 print_formatted (char *format, int argc, char **argv)
171 int save_argc = argc; /* Preserve original value. */
172 char *f; /* Pointer into `format'. */
173 char *direc_start; /* Start of % directive. */
174 size_t direc_length; /* Length of % directive. */
175 int field_width; /* Arg to first '*', or -1 if none. */
176 int precision; /* Arg to second '*', or -1 if none. */
178 for (f = format; *f; ++f)
180 switch (*f)
182 case '%':
183 direc_start = f++;
184 direc_length = 1;
185 field_width = precision = -1;
186 if (*f == '%')
188 putchar ('%');
189 break;
191 if (*f == 'b')
193 if (argc > 0)
195 print_esc_string (*argv);
196 ++argv;
197 --argc;
199 break;
201 if (strchr ("-+ #", *f))
203 ++f;
204 ++direc_length;
206 if (*f == '*')
208 ++f;
209 ++direc_length;
210 if (argc > 0)
212 field_width = xstrtoul (*argv);
213 ++argv;
214 --argc;
216 else
217 field_width = 0;
219 else
220 while (ISDIGIT (*f))
222 ++f;
223 ++direc_length;
225 if (*f == '.')
227 ++f;
228 ++direc_length;
229 if (*f == '*')
231 ++f;
232 ++direc_length;
233 if (argc > 0)
235 precision = xstrtoul (*argv);
236 ++argv;
237 --argc;
239 else
240 precision = 0;
242 else
243 while (ISDIGIT (*f))
245 ++f;
246 ++direc_length;
249 if (*f == 'l' || *f == 'L' || *f == 'h')
251 ++f;
252 ++direc_length;
254 if (!strchr ("diouxXfeEgGcs", *f))
255 error (1, 0, _("%%%c: invalid directive"), *f);
256 ++direc_length;
257 if (argc > 0)
259 print_direc (direc_start, direc_length, field_width,
260 precision, *argv);
261 ++argv;
262 --argc;
264 else
265 print_direc (direc_start, direc_length, field_width,
266 precision, "");
267 break;
269 case '\\':
270 f += print_esc (f);
271 break;
273 default:
274 putchar (*f);
278 return save_argc - argc;
281 /* Print a \ escape sequence starting at ESCSTART.
282 Return the number of characters in the escape sequence
283 besides the backslash. */
285 static int
286 print_esc (char *escstart)
288 register char *p = escstart + 1;
289 int esc_value = 0; /* Value of \nnn escape. */
290 int esc_length; /* Length of \nnn escape. */
292 /* \0ooo and \xhhh escapes have maximum length of 3 chars. */
293 if (*p == 'x')
295 for (esc_length = 0, ++p;
296 esc_length < 3 && ISXDIGIT (*p);
297 ++esc_length, ++p)
298 esc_value = esc_value * 16 + hextobin (*p);
299 if (esc_length == 0)
300 error (1, 0, _("missing hexadecimal number in escape"));
301 putchar (esc_value);
303 else if (*p == '0')
305 for (esc_length = 0, ++p;
306 esc_length < 3 && isodigit (*p);
307 ++esc_length, ++p)
308 esc_value = esc_value * 8 + octtobin (*p);
309 putchar (esc_value);
311 else if (strchr ("\"\\abcfnrtv", *p))
312 print_esc_char (*p++);
313 else
314 error (1, 0, _("\\%c: invalid escape"), *p);
315 return p - escstart - 1;
318 /* Output a single-character \ escape. */
320 static void
321 print_esc_char (int c)
323 switch (c)
325 case 'a': /* Alert. */
326 putchar (7);
327 break;
328 case 'b': /* Backspace. */
329 putchar (8);
330 break;
331 case 'c': /* Cancel the rest of the output. */
332 exit (0);
333 break;
334 case 'f': /* Form feed. */
335 putchar (12);
336 break;
337 case 'n': /* New line. */
338 putchar (10);
339 break;
340 case 'r': /* Carriage return. */
341 putchar (13);
342 break;
343 case 't': /* Horizontal tab. */
344 putchar (9);
345 break;
346 case 'v': /* Vertical tab. */
347 putchar (11);
348 break;
349 default:
350 putchar (c);
351 break;
355 /* Print string STR, evaluating \ escapes. */
357 static void
358 print_esc_string (char *str)
360 for (; *str; str++)
361 if (*str == '\\')
362 str += print_esc (str);
363 else
364 putchar (*str);
367 /* Output a % directive. START is the start of the directive,
368 LENGTH is its length, and ARGUMENT is its argument.
369 If FIELD_WIDTH or PRECISION is non-negative, they are args for
370 '*' values in those fields. */
372 static void
373 print_direc (char *start, size_t length, int field_width, int precision, char *argument)
375 char *p; /* Null-terminated copy of % directive. */
377 p = xmalloc ((unsigned) (length + 1));
378 strncpy (p, start, length);
379 p[length] = 0;
381 switch (p[length - 1])
383 case 'd':
384 case 'i':
385 if (field_width < 0)
387 if (precision < 0)
388 printf (p, xstrtol (argument));
389 else
390 printf (p, precision, xstrtol (argument));
392 else
394 if (precision < 0)
395 printf (p, field_width, xstrtol (argument));
396 else
397 printf (p, field_width, precision, xstrtol (argument));
399 break;
401 case 'o':
402 case 'u':
403 case 'x':
404 case 'X':
405 if (field_width < 0)
407 if (precision < 0)
408 printf (p, xstrtoul (argument));
409 else
410 printf (p, precision, xstrtoul (argument));
412 else
414 if (precision < 0)
415 printf (p, field_width, xstrtoul (argument));
416 else
417 printf (p, field_width, precision, xstrtoul (argument));
419 break;
421 case 'f':
422 case 'e':
423 case 'E':
424 case 'g':
425 case 'G':
426 if (field_width < 0)
428 if (precision < 0)
429 printf (p, xstrtod (argument));
430 else
431 printf (p, precision, xstrtod (argument));
433 else
435 if (precision < 0)
436 printf (p, field_width, xstrtod (argument));
437 else
438 printf (p, field_width, precision, xstrtod (argument));
440 break;
442 case 'c':
443 printf (p, *argument);
444 break;
446 case 's':
447 if (field_width < 0)
449 if (precision < 0)
450 printf (p, argument);
451 else
452 printf (p, precision, argument);
454 else
456 if (precision < 0)
457 printf (p, field_width, argument);
458 else
459 printf (p, field_width, precision, argument);
461 break;
464 free (p);
467 static unsigned long
468 xstrtoul (char *s)
470 char *end;
471 unsigned long val;
473 errno = 0;
474 val = strtoul (s, &end, 0);
475 verify (s, end);
476 return val;
479 static long
480 xstrtol (char *s)
482 char *end;
483 long val;
485 errno = 0;
486 val = strtol (s, &end, 0);
487 verify (s, end);
488 return val;
491 static double
492 xstrtod (char *s)
494 char *end;
495 double val;
497 errno = 0;
498 val = strtod (s, &end);
499 verify (s, end);
500 return val;
503 static void
504 verify (char *s, char *end)
506 if (errno)
508 error (0, errno, "%s", s);
509 exit_status = 1;
511 else if (*end)
513 if (s == end)
514 error (0, 0, _("%s: expected a numeric value"), s);
515 else
516 error (0, 0, _("%s: value not completely converted"), s);
517 exit_status = 1;