Decoded: printf (coreutils)

[Back to Project Main Page]

Note: This page explores the design of command-line utilities. It is not a user guide.
[GNU Manual] [POSIX requirement] [Linux man] [FreeBSD man]

Logical flow of printf command (coreutils)

Summary

printf - format and print data

[Source] [Code Walkthrough]

Lines of code: 716
Principal syscall: write()
Support syscalls: None
Options: 2 (0 short, 2 long)

Originated with printf in 43BSD (1986)
Added to Shellutils in November 1992 [First version]
Number of revisions: 149

The printf utility design departs from most core utilities by not using getopt (no specific options needed).

Helpers:
  • print_direc() - Evaluates a single formatting substitution
  • print_esc() - Prints an escape sequence
  • print_esc_char() - Prints a single escape character
  • print_esc_string() - Implements the %b string-escape directive
  • print_formatted() - The top level printf procedure
  • verify_numeric() - Error checking for a pointer to a numeral character
External non-standard helpers:
  • die() - Exit with mandatory non-zero error and message to stderr
  • error() - Outputs error message to standard error with possible process termination
  • vstrtoimax() - Converts a string to an integer (gnulib implementation of strtoimax() )
  • xprintf() - Error detection wrapper for printf() (from gnulib)

Setup

printf keeps a flag and global integer variables:

  • exit_status - The final exit status of the utility
  • posixly_correct - Flag if the environment variable of the same name is set

main() introduces two local variables for processing:

  • args_used - The number of arguments that have already been evaluated
  • *format - The output format that we're resolving

Parsing

The parsing stage of printf is limited because there are no meaningful options that impact execution. Thus, we don't see any usage of getopt. In truth, the entire execute phase of the utility is an exercise in parsing arguments from the command line.

Nonethless, we do explicitly check for --help and version --requests.

Parsing failures

These failure cases are explicitly checked:

  • No operands provided (no work to do!)
  • Excess arguments for substitution (warning)

User specified parsing failures result in a short error message followed by the usage instructions. Access related parsing errors die with an error message.


Execution

printf executes as you would expect: Check each format symbol and replace with the provided arguments. Naturally, the edge cases make the problem seem more complex than it is. Overall the process looks like this:

  • Find the format string and position pointers at the arguments to process
  • While there are still arugments to substitute, process the format string:
    • Check the type of the next format character:
      • A '%' implies that we evaluate the next argument:
      • A '\' means we print an escape character:
      • All other characters are normal, just putchar():
    • Deduct the number of used arguments from the total count
    • Repeat format processing until no arguments remain
  • Return exit status

Failure cases:

  • Unable to determine the width of a field
  • Unable to determine the value of a string
  • Unknown format conversion requested
  • Excess arguments (warning only)

All failures at this stage output an error message to STDERR and return without displaying usage help


[Back to Project Main Page]