.
[coreutils.git] / src / printf.c
blob59b5801ebab7a619bececc2bdf1440e3cdc746fb
1 /* printf - format and print data
2 Copyright (C) 90, 91, 92, 93, 94, 95, 1996 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 Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "long-options.h"
53 #include "error.h"
55 #ifndef STDC_HEADERS
56 double strtod ();
57 long strtol ();
58 unsigned long strtoul ();
59 #endif
61 #define isodigit(c) ((c) >= '0' && (c) <= '7')
62 #define hextobin(c) ((c)>='a'&&(c)<='f' ? (c)-'a'+10 : (c)>='A'&&(c)<='F' ? (c)-'A'+10 : (c)-'0')
63 #define octtobin(c) ((c) - '0')
65 char *xmalloc ();
67 static double xstrtod __P ((char *s));
68 static int print_esc __P ((char *escstart));
69 static int print_formatted __P ((char *format, int argc, char **argv));
70 static long xstrtol __P ((char *s));
71 static unsigned long xstrtoul __P ((char *s));
72 static void print_direc __P ((char *start, size_t length, int field_width, int precision, char *argument));
73 static void print_esc_char __P ((int c));
74 static void print_esc_string __P ((char *str));
75 static void verify __P ((char *s, char *end));
77 /* The value to return to the calling program. */
78 static int exit_status;
80 /* The name this program was run with. */
81 char *program_name;
83 static void
84 usage (int status)
86 if (status != 0)
87 fprintf (stderr, _("Try `%s --help' for more information.\n"),
88 program_name);
89 else
91 printf (_("\
92 Usage: %s FORMAT [ARGUMENT]...\n\
93 or: %s OPTION\n\
94 "),
95 program_name, program_name);
96 printf (_("\
97 Print ARGUMENT(s) according to FORMAT.\n\
98 \n\
99 --help display this help and exit\n\
100 --version output version information and exit\n\
102 FORMAT controls the output as in C printf. Interpreted sequences are:\n\
104 \\\" double quote\n\
105 \\0NNN character with octal value NNN (0 to 3 digits)\n\
106 \\\\ backslash\n\
107 \\a alert (BEL)\n\
108 \\b backspace\n\
109 \\c produce no further output\n\
110 \\f form feed\n\
111 \\n new line\n\
112 \\r carriage return\n\
113 \\t horizontal tab\n\
114 \\v vertical tab\n\
115 \\xNNN character with hexadecimal value NNN (1 to 3 digits)\n\
117 %%%% a single %%\n\
118 %%b ARGUMENT as a string with `\\' escapes interpreted\n\
120 and all C format specifications ending with one of diouxXfeEgGcs, with\n\
121 ARGUMENTs converted to proper type first. Variable widths are handled.\n\
122 "));
124 exit (status);
128 main (int argc, char **argv)
130 char *format;
131 int args_used;
133 program_name = argv[0];
134 setlocale (LC_ALL, "");
135 bindtextdomain (PACKAGE, LOCALEDIR);
136 textdomain (PACKAGE);
138 exit_status = 0;
140 /* Don't recognize --help or --version if POSIXLY_CORRECT is set. */
141 if (getenv ("POSIXLY_CORRECT") == NULL)
142 parse_long_options (argc, argv, "printf", PACKAGE_VERSION, usage);
144 if (argc == 1)
146 fprintf (stderr, _("Usage: %s format [argument...]\n"), program_name);
147 exit (1);
150 format = argv[1];
151 argc -= 2;
152 argv += 2;
156 args_used = print_formatted (format, argc, argv);
157 argc -= args_used;
158 argv += args_used;
160 while (args_used > 0 && argc > 0);
162 exit (exit_status);
165 /* Print the text in FORMAT, using ARGV (with ARGC elements) for
166 arguments to any `%' directives.
167 Return the number of elements of ARGV used. */
169 static int
170 print_formatted (char *format, int argc, char **argv)
172 int save_argc = argc; /* Preserve original value. */
173 char *f; /* Pointer into `format'. */
174 char *direc_start; /* Start of % directive. */
175 size_t direc_length; /* Length of % directive. */
176 int field_width; /* Arg to first '*', or -1 if none. */
177 int precision; /* Arg to second '*', or -1 if none. */
179 for (f = format; *f; ++f)
181 switch (*f)
183 case '%':
184 direc_start = f++;
185 direc_length = 1;
186 field_width = precision = -1;
187 if (*f == '%')
189 putchar ('%');
190 break;
192 if (*f == 'b')
194 if (argc > 0)
196 print_esc_string (*argv);
197 ++argv;
198 --argc;
200 break;
202 if (strchr ("-+ #", *f))
204 ++f;
205 ++direc_length;
207 if (*f == '*')
209 ++f;
210 ++direc_length;
211 if (argc > 0)
213 field_width = xstrtoul (*argv);
214 ++argv;
215 --argc;
217 else
218 field_width = 0;
220 else
221 while (ISDIGIT (*f))
223 ++f;
224 ++direc_length;
226 if (*f == '.')
228 ++f;
229 ++direc_length;
230 if (*f == '*')
232 ++f;
233 ++direc_length;
234 if (argc > 0)
236 precision = xstrtoul (*argv);
237 ++argv;
238 --argc;
240 else
241 precision = 0;
243 else
244 while (ISDIGIT (*f))
246 ++f;
247 ++direc_length;
250 if (*f == 'l' || *f == 'L' || *f == 'h')
252 ++f;
253 ++direc_length;
255 if (!strchr ("diouxXfeEgGcs", *f))
256 error (1, 0, _("%%%c: invalid directive"), *f);
257 ++direc_length;
258 if (argc > 0)
260 print_direc (direc_start, direc_length, field_width,
261 precision, *argv);
262 ++argv;
263 --argc;
265 else
266 print_direc (direc_start, direc_length, field_width,
267 precision, "");
268 break;
270 case '\\':
271 f += print_esc (f);
272 break;
274 default:
275 putchar (*f);
279 return save_argc - argc;
282 /* Print a \ escape sequence starting at ESCSTART.
283 Return the number of characters in the escape sequence
284 besides the backslash. */
286 static int
287 print_esc (char *escstart)
289 register char *p = escstart + 1;
290 int esc_value = 0; /* Value of \nnn escape. */
291 int esc_length; /* Length of \nnn escape. */
293 /* \0ooo and \xhhh escapes have maximum length of 3 chars. */
294 if (*p == 'x')
296 for (esc_length = 0, ++p;
297 esc_length < 3 && ISXDIGIT (*p);
298 ++esc_length, ++p)
299 esc_value = esc_value * 16 + hextobin (*p);
300 if (esc_length == 0)
301 error (1, 0, _("missing hexadecimal number in escape"));
302 putchar (esc_value);
304 else if (*p == '0')
306 for (esc_length = 0, ++p;
307 esc_length < 3 && isodigit (*p);
308 ++esc_length, ++p)
309 esc_value = esc_value * 8 + octtobin (*p);
310 putchar (esc_value);
312 else if (strchr ("\"\\abcfnrtv", *p))
313 print_esc_char (*p++);
314 else
315 error (1, 0, _("\\%c: invalid escape"), *p);
316 return p - escstart - 1;
319 /* Output a single-character \ escape. */
321 static void
322 print_esc_char (int c)
324 switch (c)
326 case 'a': /* Alert. */
327 putchar (7);
328 break;
329 case 'b': /* Backspace. */
330 putchar (8);
331 break;
332 case 'c': /* Cancel the rest of the output. */
333 exit (0);
334 break;
335 case 'f': /* Form feed. */
336 putchar (12);
337 break;
338 case 'n': /* New line. */
339 putchar (10);
340 break;
341 case 'r': /* Carriage return. */
342 putchar (13);
343 break;
344 case 't': /* Horizontal tab. */
345 putchar (9);
346 break;
347 case 'v': /* Vertical tab. */
348 putchar (11);
349 break;
350 default:
351 putchar (c);
352 break;
356 /* Print string STR, evaluating \ escapes. */
358 static void
359 print_esc_string (char *str)
361 for (; *str; str++)
362 if (*str == '\\')
363 str += print_esc (str);
364 else
365 putchar (*str);
368 /* Output a % directive. START is the start of the directive,
369 LENGTH is its length, and ARGUMENT is its argument.
370 If FIELD_WIDTH or PRECISION is non-negative, they are args for
371 '*' values in those fields. */
373 static void
374 print_direc (char *start, size_t length, int field_width, int precision, char *argument)
376 char *p; /* Null-terminated copy of % directive. */
378 p = xmalloc ((unsigned) (length + 1));
379 strncpy (p, start, length);
380 p[length] = 0;
382 switch (p[length - 1])
384 case 'd':
385 case 'i':
386 if (field_width < 0)
388 if (precision < 0)
389 printf (p, xstrtol (argument));
390 else
391 printf (p, precision, xstrtol (argument));
393 else
395 if (precision < 0)
396 printf (p, field_width, xstrtol (argument));
397 else
398 printf (p, field_width, precision, xstrtol (argument));
400 break;
402 case 'o':
403 case 'u':
404 case 'x':
405 case 'X':
406 if (field_width < 0)
408 if (precision < 0)
409 printf (p, xstrtoul (argument));
410 else
411 printf (p, precision, xstrtoul (argument));
413 else
415 if (precision < 0)
416 printf (p, field_width, xstrtoul (argument));
417 else
418 printf (p, field_width, precision, xstrtoul (argument));
420 break;
422 case 'f':
423 case 'e':
424 case 'E':
425 case 'g':
426 case 'G':
427 if (field_width < 0)
429 if (precision < 0)
430 printf (p, xstrtod (argument));
431 else
432 printf (p, precision, xstrtod (argument));
434 else
436 if (precision < 0)
437 printf (p, field_width, xstrtod (argument));
438 else
439 printf (p, field_width, precision, xstrtod (argument));
441 break;
443 case 'c':
444 printf (p, *argument);
445 break;
447 case 's':
448 if (field_width < 0)
450 if (precision < 0)
451 printf (p, argument);
452 else
453 printf (p, precision, argument);
455 else
457 if (precision < 0)
458 printf (p, field_width, argument);
459 else
460 printf (p, field_width, precision, argument);
462 break;
465 free (p);
468 static unsigned long
469 xstrtoul (char *s)
471 char *end;
472 unsigned long val;
474 errno = 0;
475 val = strtoul (s, &end, 0);
476 verify (s, end);
477 return val;
480 static long
481 xstrtol (char *s)
483 char *end;
484 long val;
486 errno = 0;
487 val = strtol (s, &end, 0);
488 verify (s, end);
489 return val;
492 static double
493 xstrtod (char *s)
495 char *end;
496 double val;
498 errno = 0;
499 val = strtod (s, &end);
500 verify (s, end);
501 return val;
504 static void
505 verify (char *s, char *end)
507 if (errno)
509 error (0, errno, "%s", s);
510 exit_status = 1;
512 else if (*end)
514 if (s == end)
515 error (0, 0, _("%s: expected a numeric value"), s);
516 else
517 error (0, 0, _("%s: value not completely converted"), s);
518 exit_status = 1;