xref: /titanic_50/usr/src/lib/libshell/common/scripts/shcalc.sh (revision 015a6ef6781cc3ceba8ad3bfbae98449b6002a1f)
1#!/usr/bin/ksh93
2
3#
4# CDDL HEADER START
5#
6# The contents of this file are subject to the terms of the
7# Common Development and Distribution License (the "License").
8# You may not use this file except in compliance with the License.
9#
10# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11# or http://www.opensolaris.org/os/licensing.
12# See the License for the specific language governing permissions
13# and limitations under the License.
14#
15# When distributing Covered Code, include this CDDL HEADER in each
16# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17# If applicable, add the following below this CDDL HEADER, with the
18# fields enclosed by brackets "[]" replaced with your own identifying
19# information: Portions Copyright [yyyy] [name of copyright owner]
20#
21# CDDL HEADER END
22#
23
24#
25# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
26# Use is subject to license terms.
27#
28
29#
30# shcalc - small shell-based calculator
31#
32
33# Solaris needs /usr/xpg6/bin:/usr/xpg4/bin because the tools in /usr/bin are not POSIX-conformant
34export PATH=/usr/xpg6/bin:/usr/xpg4/bin:/bin:/usr/bin
35
36# Make sure all math stuff runs in the "C" locale to avoid problems
37# with alternative # radix point representations (e.g. ',' instead of
38# '.' in de_DE.*-locales). This needs to be set _before_ any
39# floating-point constants are defined in this script).
40if [[ "${LC_ALL}" != "" ]] ; then
41    export \
42        LC_MONETARY="${LC_ALL}" \
43        LC_MESSAGES="${LC_ALL}" \
44        LC_COLLATE="${LC_ALL}" \
45        LC_CTYPE="${LC_ALL}"
46        unset LC_ALL
47fi
48export LC_NUMERIC=C
49
50function fatal_error
51{
52	print -u2 "${progname}: $*"
53	exit 1
54}
55
56function do_calculate
57{
58	typeset calcline="$1"
59	float x=0.0
60
61	printf "(( x=( %s ) ))\n" "${calcline}" | source /dev/stdin
62	if (( $? != 0 )) ; then
63		print -f $"%s: Syntax error in %s\n" "${progname}" "${calcline}"
64		return 1
65	fi
66
67	printf "%s == %.40g\n" "${calcline}" x
68
69	return 0
70}
71
72function usage
73{
74	OPTIND=0
75	getopts -a "${progname}" "${shcalc_usage}" OPT '-?'
76	exit 2
77}
78
79# program start
80# (be carefull with builtins here - they are unconditionally available
81# in the shell's "restricted" mode)
82builtin basename
83builtin sum
84
85typeset progname="${ basename "${0}" ; }"
86
87typeset -r shcalc_usage=$'+
88[-?\n@(#)\$Id: shcalc (Roland Mainz) 2008-11-03 \$\n]
89[-author?Roland Mainz <roland.mainz@nrubsig.org>]
90[+NAME?shcalc - simple shell calculator]
91[+DESCRIPTION?\bsshcalc\b is a small calculator application which
92	prints the results of ISO C99 math expressions read from either
93	arguments or stdin if no arguments are given.]
94[+SEE ALSO?\bksh93\b(1),\bceil\b(3M), \bcopysign\b(3M), \bcos\b(3M),
95	\bcosh\b(3M), \berf\b(3M), \berfc\b(3M), \bexp\b(3M),
96	\bexp2\b(3M), \bexpm1\b(3M), \bfabs abs\b(3M), \bfdim\b(3M),
97	\bfinite\b(3M), \bfloor int\b(3M), \bfma\b(3M), \bfmax\b(3M), \bfmin\b(3M),
98	\bfmod\b(3M), \bfpclassify\b(3M), \bhypot\b(3M), \bilogb\b(3M),
99	\bisfinite\b(3M), \bisgreater\b(3M), \bisgreaterequal\b(3M), \bisinf\b(3M),
100	\bisless\b(3M), \bislessequal\b(3M), \bislessgreater\b(3M), \bisnan\b(3M),
101	\bisnormal\b(3M), \bissubnormal\b(3M), \bisunordered\b(3M), \biszero\b(3M),
102	\blgamma\b(3M), \blog\b(3M), \blog1p\b(3M), \blog2\b(3M),
103	\blogb\b(3M), \bnearbyint\b(3M), \bnextafter\b(3M), \bnexttoward\b(3M),
104	\bpow\b(3M), \bremainder\b(3M), \brint\b(3M), \bround\b(3M),
105	\bscalb\b(3M), \bscalbn\b(3M), \bsignbit\b(3M), \bsin\b(3M),
106	\bsinh\b(3M), \bsqrt\b(3M), \btan\b(3M), \btanh\b(3M),
107	\btgamma\b(3M), \btrunc\b(3M)]
108'
109while getopts -a "${progname}" "${shcalc_usage}" OPT ; do
110#	printmsg "## OPT=|${OPT}|, OPTARG=|${OPTARG}|"
111	case ${OPT} in
112		*)	usage ;;
113	esac
114done
115shift $((OPTIND-1))
116
117integer res
118
119if (( $# == 0 )) ; then
120	# No arguments ? Switch to interactive mode...
121
122	# make sure "read" below uses "gmacs"-like editor keys and "multiline" mode
123
124	set -o gmacs
125	set -o multiline
126
127	while read "calcline?calc> " ; do
128		# quit ?
129		[[ "${calcline}" == ~(Elri)(exit|quit|eof) ]] && break
130
131		# empty line ?
132		[[ "${calcline}" == ~(Elri)([[:space:]]*) ]] && continue
133
134		do_calculate "$calcline"
135		(( res=$? ))
136	done
137
138	exit ${res}
139else
140	while (( $# > 0 )) ; do
141		do_calculate "$1"
142		(( res=$? ))
143		shift
144	done
145
146	exit ${res}
147fi
148
149# not reached
150
151# EOF.
152