[GNU Manual] [No POSIX requirement] [Linux man] [FreeBSD man]
Summary
seq - print numeric sequences
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 numberscmp()
- Compares two strings and identifies the lesser/greaterget_default_format()
- Returns a format string based on operandsincr()
- Increments a numeric value stored as stringio_error()
- Invokes an I/O errorlong_double_format()
- Converts a input format to a long double equivalentprint_numbers()
- The full-featured seq procedurescan_arg()
- Parses a user input value and returns an operand long doubleseq_fast()
- The fast 'seq' procedure with default optionstrim_leading_zeros()
- Remove all non-significant zeroes from a string of numbers
die()
- Exit with mandatory non-zero error and message to stderrerror()
- 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 numbersterminator
- The end of the output character
Additionally, seq defines two structures:
operand
- Holds a numberic value read from the command linelayout
- Defines the format around a number (prefix & suffix)main()
introduces several local variables for processing:
first
- Operand for the starting numberformat
- The user-provided format stringlast
- Operand for the last numberlayout
- The format for each output numberoptc
- The character for the next option to processstep
- 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