[GNU Manual] [POSIX requirement] [Linux man] [FreeBSD man]
Summary
expr - evaluate expressions
Lines of code: 1118
Principal syscall: None
Support syscalls: None
Options: 2 (--help and --version)
Descended from expr introduced in Version 7 UNIX (1979)
Added to Shellutils in November 1992 [First version]
Number of revisions: 173
The expr performs minimal parsing since the execution step is already a custom parser and expression evaluator. The utility makes use of the GNU Multiple Precision Library (GMP) during evaluation of numerical values
Helpers:docolon()
- Procedure for string and pattern matchingeval()
- Handles the '|' binary operatoreval1()
- Handles the '&' binary operatoreval2()
- Handles comparison binary operatorseval3()
- Handles addition and subtraction binary operatorseval4()
- Handles multiplication, division, and moduluseval5()
- Handles colon matching (wrapper fordocolon()
eval6()
- Handles keyword operationseval7()
- Handles atomic operands and recursive expressionsfreev()
- Frees a value (VALUE type)getsize()
- Checks the size of an input numberint_value()
- Gets a VALUE type for an input integerlooks_like_integer()
- Tests an input string as a possible integer valuenextarg()
- Advances argument pointer to the next argumentmbs_logical_cspn()
- Seaches a string for a matching substringmbs_logical_substr()
- Gets a substring using an input position and lengthmbs_offset_to_chars()
- Gets the number of logical characters in a stringnomoreargs()
- Checks if arguments are exhaustednull()
- Tests if an input value is null or zeroprintv()
- Prints a value (VALUE type)require_more_args()
- Tests for and throws error for missing argumentsstr_value()
- Gets a VALUE type for an input stringtoarith()
- Forces an input value to an integertostring()
- Forces an input value to a stringtrace()
- Evaluation trace (may be excluded)
mpz_add()
- mpz_t type additionmpz_fits_ulong_p()
- Tests if an mpz_t will fit in to an unsigned intmpz_get_ui()
- Casts mpz_t to unsigned intmpz_get_str()
- Returns a pointer to a string from an mpz_tmpz_mul()
- mpz_t type multiplicationmpz_out_str()
- Outputs a string using an mpz_t typempz_sign()
- Test the sign of an mpz_t typempz_sub()
- mpz_t type subtractionmpz_tdiv_r()
- Returns the remainder of a divisionmpz_tdiv_q()
- Returns the result of a division
die()
- Exit with mandatory non-zero error and message to stderrerror()
- Outputs error message to standard error with possible process termination
Setup
expr
defines aVALUE
structure to manage the variety of atomic types that an expression may evaluate to. The key idea is that the values are either integers or strings. The former is stored using a GMP type while the latter is a generic pointer.
main()
introduces one variable, v
of type VALUE that holds the final return value of the operation
Parsing
The parsing stage for expr
is nearly nonexistent since checking the command line is part of execution. The only serious check is the number of arguments - there must be at least one argument (an expression to evaluate)
Execution
The expr utility is conceptually simple. It attempts recursive evalution of expressions with 8 levels of operator precendence and left-associative behavior. Evaluating expressions may lead to more expression (subexpressions). There will be at least an lvalue, possibly an operator and rvalue if the lvalue isn't terminal. The process flow is thus:
- Get the next expression
- Evaluate the lvalue with the next level of precedence
- Evaluate the operator
- Evaluate the rvalue
- Repeat until we run out of expressions
Failure cases:
- Integer overflow
- Mismatched argument types/counts
- Arguments out of range
- Regular expression failure
- Unbalanced parenthese
- String comparison failures
- Non-integer arguments
- Division by zero
All failures at this stage output an error message to STDERR and return without displaying usage help