Decoded: seq (coreutils)

[Back to Project Main Page]

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

Logical flow of seq command (coreutils)

Summary

seq - print numeric sequences

[Source] [Code Walkthrough]

Lines of code: 707
Principal syscall: write()
Support syscalls: None
Options: 2 (3 short, 5 long)

Decended from the UNIX 8th ed seq utility (1985)
Added to Shellutils in December 1994 [First version]
Number of revisions: 157 [Code Evolution]

The most complicated consideration for the seq utility is supporting user-specified output formats. Default usage has a separate 'fast' implementation built-in.

Helpers:
  • all_digits_p() - Verifies that string is all numbers
  • cmp() - Compares two strings and identifies the lesser/greater
  • get_default_format() - Returns a format string based on operands
  • incr() - Increments a numeric value stored as string
  • io_error() - Invokes an I/O error
  • long_double_format() - Converts a input format to a long double equivalent
  • print_numbers() - The full-featured seq procedure
  • scan_arg() - Parses a user input value and returns an operand long double
  • seq_fast() - The fast 'seq' procedure with default options
  • trim_leading_zeros() - Remove all non-significant zeroes from a string of numbers
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

Setup

seq keeps a flag and two global variables:

  • equal_width - Flag to set all numbers to equal widths
  • *separator - The character between output numbers
  • terminator - The end of the output character

Additionally, seq defines two structures:

  • operand - Holds a numberic value read from the command line
  • layout - Defines the format around a number (prefix & suffix)
  • main() introduces several local variables for processing:

    • first - Operand for the starting number
    • format - The user-provided format string
    • last - Operand for the last number
    • layout - The format for each output number
    • optc - The character for the next option to process
    • step - Operand for the increment between numbers

    Parsing

    The parsing stage of seq discovers the nature of the number sequence desired to include:

    • The starting and ending numbers
    • The interval between each number
    • The width (number of characters) of each number
    • The symbol separating the numbers
    • The custom output format desired

    Parsing failures

    These failure cases are explicitly checked:

    • No information provided (need at least a stop number)
    • More than 3 provided operands
    • Providing a custom format with equal widths

    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

    seq exeucution is divided in to two procedures, one very simple which handles default (common) cases, and the other handles the other features.

    The fast case is used if there is no custom formatting and only increments numbers by 1.

    Fast execution (seq_fast()):

    • Remove all leading zeros from the input start/end numbers (for cmp()compatibility)
    • Allocate a new buffer with the first number
    • While there are still numbers to write, add a separator and the next number
    • Test buffer usage then write contents if necessary. Update buffer pointers.
    • No more output? Write the terminator

    Normal execution (print_numbers()):

    • Get the user provided format or the default format string
    • Verify number ranges are not empty (there is work to do)
    • Get the next number
    • Test the next number for valid range
    • Format print the number (or the last element if it's beyond the end)
    • Print a separator
    • Repeat process for all numbers
    • Print the terminator

    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]