Newsgroups: comp.sources.unix From: dbell@canb.auug.org.au (David I. Bell) Subject: v27i128: calc-2.9.0 - arbitrary precision C-like programmable calculator, Part01/19 References: <1.755316719.21314@gw.home.vix.com> Sender: unix-sources-moderator@gw.home.vix.com Approved: vixie@gw.home.vix.com Submitted-By: dbell@canb.auug.org.au (David I. Bell) Posting-Number: Volume 27, Issue 128 Archive-Name: calc-2.9.0/part01 #!/bin/sh # shar: Shell Archiver (v1.22) # # This is part 1 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # # Run the following text with /bin/sh to create: # calc2.9.0/README # calc2.9.0/CHANGES # calc2.9.0/LIBRARY # calc2.9.0/Makefile # calc2.9.0/addop.c # calc2.9.0/alloc.c # calc2.9.0/alloc.h # calc2.9.0/assocfunc.c # calc2.9.0/calc.c # calc2.9.0/calc.h # calc2.9.0/calc.man # calc2.9.0/cmath.h # calc2.9.0/codegen.c # calc2.9.0/comfunc.c # calc2.9.0/commath.c # calc2.9.0/config.c # calc2.9.0/const.c # calc2.9.0/endian.c # calc2.9.0/file.c # calc2.9.0/func.c # calc2.9.0/func.h # calc2.9.0/hist.c # calc2.9.0/hist.h # calc2.9.0/input.c # calc2.9.0/label.c # calc2.9.0/label.h # calc2.9.0/lint.sed # calc2.9.0/listfunc.c # calc2.9.0/matfunc.c # calc2.9.0/obj.c # calc2.9.0/opcodes.c # calc2.9.0/opcodes.h # calc2.9.0/qfunc.c # calc2.9.0/qio.c # calc2.9.0/qmath.c # calc2.9.0/qmath.h # calc2.9.0/qmod.c # calc2.9.0/qtrans.c # calc2.9.0/stdarg.h # calc2.9.0/string.c # calc2.9.0/string.h # calc2.9.0/symbol.c # calc2.9.0/symbol.h # calc2.9.0/token.c # calc2.9.0/token.h # calc2.9.0/value.c # calc2.9.0/value.h # calc2.9.0/version.c # calc2.9.0/zfunc.c # calc2.9.0/zio.c # calc2.9.0/zmath.c # calc2.9.0/zmath.h # calc2.9.0/zmod.c # calc2.9.0/zmul.c # calc2.9.0/help/Makefile # calc2.9.0/help/assoc # calc2.9.0/help/builtin # calc2.9.0/help/command # calc2.9.0/help/config # calc2.9.0/help/credit # calc2.9.0/help/define # calc2.9.0/help/environment # calc2.9.0/help/expression # calc2.9.0/help/file # calc2.9.0/help/help # calc2.9.0/help/history # calc2.9.0/help/interrupt # calc2.9.0/help/intro # calc2.9.0/help/list # calc2.9.0/help/mat # calc2.9.0/help/obj.file # calc2.9.0/help/operator # calc2.9.0/help/overview # calc2.9.0/help/statement # calc2.9.0/help/todo # calc2.9.0/help/types # calc2.9.0/help/usage # calc2.9.0/help/variable # calc2.9.0/lib/Makefile # calc2.9.0/lib/README # calc2.9.0/lib/bernoulli.cal # calc2.9.0/lib/bigprime.cal # calc2.9.0/lib/bindings # calc2.9.0/lib/chrem.cal # calc2.9.0/lib/cryrand.cal # calc2.9.0/lib/deg.cal # calc2.9.0/lib/ellip.cal # calc2.9.0/lib/lucas.cal # calc2.9.0/lib/lucas_chk.cal # calc2.9.0/lib/lucas_tbl.cal # calc2.9.0/lib/mersenne.cal # calc2.9.0/lib/mod.cal # calc2.9.0/lib/nextprim.cal # calc2.9.0/lib/pell.cal # calc2.9.0/lib/pi.cal # calc2.9.0/lib/pollard.cal # calc2.9.0/lib/poly.cal # calc2.9.0/lib/psqrt.cal # calc2.9.0/lib/quat.cal # calc2.9.0/lib/regress.cal # calc2.9.0/lib/solve.cal # calc2.9.0/lib/sumsq.cal # calc2.9.0/lib/surd.cal # calc2.9.0/lib/unitfrac.cal # calc2.9.0/lib/varargs.cal # if test -r s2_seq_.tmp then echo "Must unpack archives in sequence!" next=`cat s2_seq_.tmp`; echo "Please unpack part $next next" exit 1; fi mkdir calc2.9.0 mkdir calc2.9.0/help mkdir calc2.9.0/lib echo "x - extracting calc2.9.0/README (Text)" sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/README && X X# Copyright (c) 1993 David I. Bell X# Permission is granted to use, distribute, or modify this source, X# provided that this copyright notice remains intact. X# X# Arbitrary precision calculator. X XI am allowing this calculator to be freely distributed for personal uses. XLike all multi-precision programs, you should not depend absolutely on Xits results, since bugs in such programs can be insidious and only rarely Xshow up. X X-dbell- X Xp.s. By Landon Curt Noll X XTo build calc: X X 1) Look at the makefile, and adjust it to suit your needs. X X 2) build some calc documentation: X X (cd help; make full) <- after this, read the file help/full X X 3) build calc: X X make X X 4) test calc: X X After you have built calc, you can test it by running calc and X giving calc the following input: X X read lib/regress <- should produce no error messages X read lib/lucas X read lib/lucas_chk X lucas_chk(200) <- should produce no error messages X exit X XIf you find bugs, or better yet have bug fixes; or if you have suggested Xchanges, or better yet have patches, send them to both myself and DBell: X X dbell@canb.auug.org.au X chongo@toad.com {uunet,pyramid,sun}!hoptoad!chongo X XThe file doc/todo section points out some needs for calc. Suggestions Xon other enhancements, and help in doing these are welcome. SHAR_EOF chmod 0644 calc2.9.0/README || echo "restore of calc2.9.0/README fails" set `wc -c calc2.9.0/README`;Sum=$1 if test "$Sum" != "1304" then echo original size 1304, current size $Sum;fi echo "x - extracting calc2.9.0/CHANGES (Text)" sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/CHANGES && XFollowing is a list of visible changes to calc from version 1.27.0 to 2.9.0: X X Full prototypes have been provided for all C functions, and are used X if calc is compiled with an ANSI compiler. X X Newly defined variables are now initialized to the value of zero instead X of to the null value. The elements of new objects are also initialized X to the value of zero instead of null. X X The gcd, lcm, and ismult functions now work for fractional values. X X A major bug in the // division for fractions with a negative divisor X was fixed. X X A major bug in the calculation of ln for small values was fixed. X X A major bug in the calculation of the ln and power functions for complex X numbers was fixed. X X A major lack of precision for sin and tan for small values was fixed. X X A major lack of precision for complex square roots was fixed. X X The "static" keyword has been implemented for variables. So permanent X variables can be defined to have either file scope or function scope. X X Initialization of variables during their declaration are now allowed. X This is most convenient for the initialization of static variables. X X The matrix definition statement can now be used within a declaration X statement, to immediately define a variable as a matrix. X X Initializations of the elements of matrices are now allowed. One- X dimensional matrices may have implicit bounds when initialization is X used. X X The obj definition statement can now be used within a declaration X statement, to immediately define a variable as an object. X X Object definitions can be repeated as long as they are exactly the same X as the previous definition. This allows the rereading of files which X happen to define objects. X X The integer, rational, and complex routines have been made into a X 'libcalc.a' library so that they can be used in other programs besides X the calculator. The "math.h" include file has been split into three X include files: "zmath.h", "qmath.h", and "cmath.h". X XFollowing is a list of visible changes to calc from version 1.26.4 to 1.27.0: X X Added an assoc function to return a new type of value called an X association. Such values are indexed by one or more arbitrary values. X They are stored in a hash table for quick access. X X Added a hash() function which accepts one or more values and returns X a quickly calculated small non-negative hash value for those values. X XFollowing is a list of visible changes to calc from version 1.26.2 to 1.26.4: X X Misc fixes to Makefiles. X X Misc lint fixes. X X Misc portability fixes. X X Misc typo and working fixes to comments, help files and the man page. X XFollowing is a list of visible changes to calc from version 1.24.7 to 1.26.2: X X There is a new emacs-like command line editing and edit history X feature. The old history mechanism has been removed. The key X bindings for the new editing commands are slightly configurable X since they are read in from an initialization file. This file is X usually called /usr/lib/calc/bindings, but can be changed by the X CALCBINDINGS environment variable. All editing code is X self-contained in the new files hist.c and hist.h, which can be X easily extracted and used in other programs. X X Two new library files have been added: chrem.cal and cryrand.cal. X The first of these solves the chinese remainder problem for a set X of modulos and remainders. The second of these implements several X very good random number generators for large numbers. X X A small bug which allowed division by zero was fixed. X X A major bug in the mattrans function was fixed. X X A major bug in the acos function for negative arguments was fixed. X X A major bug in the strprintf function when objects were being printed X was fixed. X X A small bug in the library file regress.cal was fixed. SHAR_EOF chmod 0644 calc2.9.0/CHANGES || echo "restore of calc2.9.0/CHANGES fails" set `wc -c calc2.9.0/CHANGES`;Sum=$1 if test "$Sum" != "3906" then echo original size 3906, current size $Sum;fi echo "x - extracting calc2.9.0/LIBRARY (Text)" sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/LIBRARY && X USING THE ARBITRARY PRECISION ROUTINES IN A C PROGRAM X X XPart of the calc release consists of an arbitrary precision math library. XThis library is used by the calc program to perform its own calculations. XIf you wish, you can ignore the calc program entirely and call the arbitrary Xprecision math routines from your own C programs. X XThe library is called libmath.a, and provides routines to handle arbitrary Xprecision arithmetic with integers, rational numbers, or complex numbers. XThere are also many numeric functions such as factorial and gcd, along Xwith some transcendental functions such as sin and exp. X X------------- XINCLUDE FILES X------------- X XTo use any of these routines in your own programs, you need to include the Xappropriate include file. These include files are: X X zmath.h (for integer arithmetic) X qmath.h (for rational arithmetic) X cmath.h (for complex number arithmetic) X XYou never need to include more than one of the above files, even if you wish Xto use more than one type of arithmetic, since qmath.h automatically includes Xzmath.h, and cmath.h automatically includes qmath.h. X XThe prototypes for the available routines are listed in the above include Xfiles. Some of these routines are meant for internal use, and so aren't Xconvenient for outside use. So you should read the source for a routine Xto see if it really does what you think it does. I won't guarantee that Xobscure internal routines won't change or disappear in future releases! X XWhen calc is installed, all of the include files needed to build Xlibcalc.a along with the library itself (and the lint library Xllib-lcalc.ln, if made) are installed into ${LIBDIR}. X XExternal programgs may want to compile with: X X -I${LIBDIR} -L${LIBDIR} -lcalc X X-------------- XERROR HANDLING X-------------- X XYou program MUST provide a function called math_error. This is called by Xthe math routines on an error condition, such as malloc failures or a Xdivision by zero. The routine is called in the manner of printf, with a Xformat string and optional arguments. (However, none of the low level math Xroutines currently uses formatting, so if you are lazy you can simply use Xthe first argument as a simple error string.) For example, one of the Xerror calls you might expect to receive is: X X math_error("Division by zero"); X XYour program can handle errors in basically one of two ways. Firstly, it Xcan simply print the error message and then exit. Secondly, you can make Xuse of setjmp and longjmp in your program. Use setjmp at some appropriate Xlevel in your program, and use longjmp in the math_error routine to return Xto that level and so recover from the error. This is what the calc program Xdoes. X X--------------- XOUTPUT ROUTINES X--------------- X XThe output from the routines in the library normally goes to stdout. You Xcan divert that output to either another FILE handle, or else to a string. XRead the routines in zio.c to see what is available. Diversions can be Xnested. X XYou use math_setfp to divert output to another FILE handle. Calling Xmath_setfp with stdout restores output to stdout. X XUse math_divertio to begin diverting output into a string. Calling Xmath_getdivertedio will then return a string containing the output, and Xclears the diversion. The string is reallocated as necessary, but since Xit is in memory, there are obviously limits on the amount of data that can Xbe diverted into it. The string needs freeing when you are done with it. X XCalling math_cleardiversions will clear all the diversions to strings, and Xis useful on an error condition to restore output to a known state. You Xshould also call math_setfp on errors if you had changed that. X XIf you wish to mix your own output with numeric output from the math routines, Xthen you can call math_chr, math_str, math_fill, math_fmt, or math_flush. XThese routines output single characters, output null-terminated strings, Xoutput strings with space filling, output formatted strings like printf, and Xflush the output. Output from these routines is diverted as described above. X XYou can change the default output mode by calling math_setmode, and you can Xchange the default number of digits printed by calling math_setdigits. These Xroutines return the previous values. The possible modes are described in Xzmath.h. X X-------------- XUSING INTEGERS X-------------- X XThe arbitrary precision integer routines define a structure called a ZVALUE. XThis is defined in zmath.h. A ZVALUE contains a pointer to an array of Xintegers, the length of the array, and a sign flag. The array is allocated Xusing malloc, so you need to free this array when you are done with a XZVALUE. To do this, you should call zfree with the ZVALUE as an argument X(or call freeh with the pointer as an argument) and never try to free the Xarray yourself using free. The reason for this is that sometimes the pointer Xpoints to one of two statically allocated arrays which should NOT be freed. X XThe ZVALUE structures are passed to routines by value, and are returned Xthrough pointers. For example, to multiply two small integers together, Xyou could do the following: X X ZVALUE z1, z2, z3; X X itoz(3L, &z1); X itoz(4L, &z2); X zmul(z1, z2, &z3); X XUse zcopy to copy one ZVALUE to another. There is no sharing of arrays Xbetween different ZVALUEs even if they have the same value, so you MUST Xuse this routine. Simply assigning one value into another will cause Xproblems when one of the copies is freed. However, the special ZVALUE Xvalues _zero_ and _one_ CAN be assigned to variables directly, since their Xvalues of 0 and 1 are so common that special checks are made for them. X XFor initial values besides 0 or 1, you need to call itoz to convert a long Xvalue into a ZVALUE, as shown in the above example. Or alternatively, Xfor larger numbers you can use the atoz routine to convert a string which Xrepresents a number into a ZVALUE. The string can be in decimal, octal, Xhex, or binary according to the leading digits. X XAlways make sure you free a ZVALUE when you are done with it or when you Xare about to overwrite an old ZVALUE with another value by passing its Xaddress to a routine as a destination value, otherwise memory will be Xlost. The following shows an example of the correct way to free memory Xover a long sequence of operations. X X ZVALUE z1, z2, z3; X X z1 = _one_; X atoz("12345678987654321", &z2); X zadd(z1, z2, &z3); X zfree(z1); X zfree(z2); X zsquare(z3, &z1); X zfree(z3); X itoz(17L, &z2); X zsub(z1, z2, &z3); X zfree(z1); X zfree(z2); X zfree(z3); X XThere are some quick checks you can make on integers. For example, whether Xor not they are zero, negative, even, and so on. These are all macros Xdefined in zmath.h, and should be used instead of checking the parts of the XZVALUE yourself. Examples of such checks are: X X ziseven(z) (number is even) X zisodd(z) (number is odd) X ziszero(z) (number is zero) X zisneg(z) (number is negative) X zispos(z) (number is positive) X zisunit(z) (number is 1 or -1) X zisone(z) (number is 1) X XThere are two types of comparisons you can make on ZVALUEs. This is whether Xor not they are equal, or the ordering on size of the numbers. The zcmp Xfunction tests whether two ZVALUEs are equal, returning TRUE if they differ. XThe zrel function tests the relative sizes of two ZVALUEs, returning -1 if Xthe first one is smaller, 0 if they are the same, and 1 if the first one Xis larger. X X--------------- XUSING FRACTIONS X--------------- X XThe arbitrary precision fractional routines define a structure called NUMBER. XThis is defined in qmath.h. A NUMBER contains two ZVALUEs for the numerator Xand denominator of a fraction, and a count of the number of uses there are Xfor this NUMBER. The numerator and denominator are always in lowest terms, Xand the sign of the number is contained in the numerator. The denominator Xis always positive. If the NUMBER is an integer, the denominator has the Xvalue 1. X XUnlike ZVALUEs, NUMBERs are passed using pointers, and pointers to them are Xreturned by functions. So the basic type for using fractions is not really X(NUMBER), but is (NUMBER *). NUMBERs are allocated using the qalloc routine. XThis returns a pointer to a number which has the value 1. Because of the Xspecial property of a ZVALUE of 1, the numerator and denominator of this Xreturned value can simply be overwritten with new ZVALUEs without needing Xto free them first. The following illustrates this: X X NUMBER *q; X X q = qalloc(); X itoz(55L, &q->num); X XA better way to create NUMBERs with particular values is to use the itoq, Xiitoq, or atoq functions. Using itoq makes a long value into a NUMBER, Xusing iitoq makes a pair of longs into the numerator and denominator of a XNUMBER (reducing them first if needed), and atoq converts a string representing Xa number into the corresponding NUMBER. The atoq function accepts input in Xintegral, fractional, real, or exponential formats. Examples of allocating Xnumbers are: X X NUMBER *q1, *q2, *q3; X X q1 = itoq(66L); X q2 = iitoq(2L, 3L); X q3 = atoq("456.78"); X XAlso unlike ZVALUEs, NUMBERs are quickly copied. This is because they contain Xa link count, which is the number of pointers there are to the NUMBER. The Xqlink macro is used to copy a pointer to a NUMBER, and simply increments Xthe link count and returns the same pointer. Since it is a macro, the Xargument should not be a function call, but a real pointer variable. The Xqcopy routine will actually make a new copy of a NUMBER, with a new link Xcount of 1. This is not usually needed. X XNUMBERs are deleted using the qfree routine. This decrements the link count Xin the NUMBER, and if it reaches zero, then it will deallocate both of Xthe ZVALUEs contained within the NUMBER, and then puts the NUMBER structure Xonto a free list for quick reuse. The following is an example of allocating XNUMBERs, copying them, adding them, and finally deleting them again. X X NUMBER *q1, *q2, *q3; X X q1 = itoq(111L); X q2 = qlink(q1); X q3 = qadd(q1, q2); X qfree(q1); X qfree(q2); X qfree(q3); X XBecause of the passing of pointers and the ability to copy numbers easily, Xyou might wish to use the rational number routines even for integral Xcalculations. They might be slightly slower than the raw integral routines, Xbut are more convenient to program with. X XThe prototypes for the fractional routines are defined in qmath.h. XMany of the definitions for integer functions parallel the ones defined Xin zmath.h. But there are also functions used only for fractions. XExamples of these are qnum to return the numerator, qden to return the Xdenominator, qint to return the integer part of, qfrac to return the Xfractional part of, and qinv to invert a fraction. X XThere are some transcendental functions in the library, such as sin and cos. XThese cannot be evaluated exactly as fractions. Therefore, they accept Xanother argument which tells how accurate you want the result. This is an X"epsilon" value, and the returned value will be within that quantity of Xthe correct value. This is usually an absolute difference, but for some Xfunctions (such as exp), this is a relative difference. For example, to Xcalculate sin(0.5) to 100 decimal places, you could do: X X NUMBER *q, *ans, *epsilon; X X q = atoq("0.5"); X epsilon = atoq("1e-100"); X ans = qsin(q, epsilon); X XThere are many convenience macros similar to the ones for ZVALUEs which can Xgive quick information about NUMBERs. In addition, there are some new ones Xapplicable to fractions. These are all defined in qmath.h. Some of these Xmacros are: X X qiszero(q) (number is zero) X qisneg(q) (number is negative) X qispos(q) (number is positive) X qisint(q) (number is an integer) X qisfrac(q) (number is fractional) X qisunit(q) (number is 1 or -1) X qisone(q) (number is 1) X XThe comparisons for NUMBERs are similar to the ones for ZVALUEs. You use the Xqcmp and qrel functions. X XThere are four predefined values for fractions. You should qlink them when Xyou want to use them. These are _qzero_, _qone_, _qnegone_, and _qonehalf_. XThese have the values 0, 1, -1, and 1/2. An example of using them is: X X NUMBER *q1, *q2; X X q1 = qlink(&_qonehalf_); X q2 = qlink(&_qone_); X X--------------------- XUSING COMPLEX NUMBERS X--------------------- X XThe arbitrary precision complex arithmetic routines define a structure Xcalled COMPLEX. This is defined in cmath.h. This contains two NUMBERs Xfor the real and imaginary parts of a complex number, and a count of the Xnumber of links there are to this COMPLEX number. X XThe complex number routines work similarly to the fractional routines. XYou can allocate a COMPLEX structure using comalloc (NOT calloc!). XYou can construct a COMPLEX number with desired real and imaginary Xfractional parts using qqtoc. You can copy COMPLEX values using clink Xwhich increments the link count. And you free a COMPLEX value using cfree. XThe following example illustrates this: X X NUMBER *q1, *q2; X COMPLEX *c1, *c2, *c3; X X q1 = itoq(3L); X q2 = itoq(4L); X c1 = qqtoc(q1, q2); X qfree(q1); X qfree(q2); X c2 = clink(c1); X c3 = cmul(c1, c2); X cfree(c1); X cfree(c2); X cfree(c3); X XAs a shortcut, when you want to manipulate a COMPLEX value by a real value, Xyou can use the caddq, csubq, cmulq, and cdivq routines. These accept one XCOMPLEX value and one NUMBER value, and produce a COMPLEX value. X XThere is no direct routine to convert a string value into a COMPLEX value. XBut you can do this yourself by converting two strings into two NUMBERS, Xand then using the qqtoc routine. X XCOMPLEX values are always returned from these routines. To split out the Xreal and imaginary parts into normal NUMBERs, you can simply qlink the Xtwo components, as shown in the following example: X X COMPLEX *c; X NUMBER *rp, *ip; X X c = calloc(); X rp = qlink(c->real); X ip = qlink(c->imag); X XThere are many macros for checking quick things about complex numbers, Xsimilar to the ZVALUE and NUMBER macros. In addition, there are some Xonly used for complex numbers. Examples of macros are: X X cisreal(c) (number is real) X cisimag(c) (number is pure imaginary) X ciszero(c) (number is zero) X cisrunit(c) (number is 1 or -1) X cisiunit(c) (number is i or -i) X cisunit(c) (number is 1, -1, i, or -i) X XThere is only one comparison you can make for COMPLEX values, and that is Xfor equality. The ccmp function returns TRUE if two complex numbers differ. X XThere are three predefined values for complex numbers. You should clink Xthem when you want to use them. They are _czero_, _cone_, and _conei_. XThese have the values 0, 1, and i. SHAR_EOF chmod 0444 calc2.9.0/LIBRARY || echo "restore of calc2.9.0/LIBRARY fails" set `wc -c calc2.9.0/LIBRARY`;Sum=$1 if test "$Sum" != "14396" then echo original size 14396, current size $Sum;fi echo "x - extracting calc2.9.0/Makefile (Text)" sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/Makefile && X# X# Copyright (c) 1993 David I. Bell and Landon Curt Noll X# Permission is granted to use, distribute, or modify this source, X# provided that this copyright notice remains intact. X# X# Arbitrary precision calculator. X# X# calculator by David I. Bell X# makefile by Landon Curt Noll X X############################################################################## X#-=-=-=-=-=-=-=-=- You may want to change some values below -=-=-=-=-=-=-=-=-# X############################################################################## X X# Determine the type of terminal controls that you want to use X# X# VARARG value meaning X# ------------ ------- X# (nothing) let the makefile guess at what you need X# -DUSE_TERMIOS use struct termios from X# -DUSE_TERMIO use struct termios from X# -DUSE_SGTTY use struct sgttyb from X# XTERMCONTROL= X#TERMCONTROL= -DUSE_TERMIOS X#TERMCONTROL= -DUSE_TERMIO X#TERMCONTROL= -DUSE_SGTTY X X# Determine the type of varargs that you want to use X# X# VARARG value meaning X# ------------ ------- X# (nothing) let the makefile guess at what you need X# STDARG you have ANSI C and /usr/include/stdarg.h X# VARARGS you have /usr/include/varargs.h X# SIMULATE_STDARG use simulated ./stdarg.h X# X# Try defining VARARG to be nothing. The makefile will look for the X# needed .h files, trying for stdarg.h first. X# XVARARG= X#VARARG= STDARG X#VARARG= VARARGS X#VARARG= SIMULATE_STDARG X X# If your system does not have a vsprintf() function, you could be in trouble. X# X# vsprintf(stream, format, ap) X# X# This function works like sprintf except that the 3rd arg is a va_list X# strarg (or varargs) list. X# X# If you have vsprintf, then define DONT_HAVE_VSPRINTF to be an empty string. X# Some old systems do not have vsprintf(). If you do not have vsprintf() X# then define DONT_HAVE_VSPRINTF to be -DDONT_HAVE_VSPRINTF and hope for X# the best. X# XDONT_HAVE_VSPRINTF= X#DONT_HAVE_VSPRINTF= -DDONT_HAVE_VSPRINTF X X# Determine the byte order of your machine X# X# Big Endian: Amdahl, 68k, Pyramid, Mips, Sparc, ... X# Little Endian: Vax, 32k, Spim (Dec Mips), i386, i486, ... X# X# If in doubt, leave BYTE_ORDER empty. This makefile will attempt to X# use BYTE_ORDER in or it will attempt to run X# the endian program. If you get syntax errors when you compile, X# try forcing the value to be BIG_ENDIAN and run the calc regression X# tests. (see the README file) If the calc regression tests fail, do X# a make clobber and try LITTLE_ENDIAN. If that fails, ask a wizard X# for help. X# XBYTE_ORDER= X#BYTE_ORDER= BIG_ENDIAN X#BYTE_ORDER= LITTLE_ENDIAN X X# Determine whether to use the standard malloc or the alternative one X# included with the calculator. On some machines, the alternative malloc X# may be faster. It also can help to debug malloc problems. X# X# Define MALLOC to be -DCALC_MALLOC to use the internal malloc routines. X# X# If in doubt, leave MALLOC empty. X# XMALLOC= X#MALLOC= -DCALC_MALLOC X X# where to install binary files X# XBINDIR= /usr/bin X#BINDIR= /usr/local/bin X X# where to install the lib/*.cal files X# XLIBDIR= /usr/lib/calc X#LIBDIR= /usr/local/lib/calc X X# where to install help files X# X# The ${LIBDIR}/help is where the help files will be installed. X# XHELPDIR= ${LIBDIR}/help X X# where man pages are installed X# XMANDIR=/usr/man/man1 X#MANDIR=/usr/local/man/man1 X#MANDIR=/usr/share/man/man1 X#MANDIR=/usr/man/u_man/man1 X X# If the $CALCPATH environment variable is not defined, then the following X# path will be search for calc lib routines. X# XCALCPATH= .:./lib:~/lib:${LIBDIR} X X# If the $CALCRC environment variable is not defined, then the following X# path will be search for calc lib routines. X# XCALCRC= ${LIBDIR}/startup:~/.calcrc X X# If the $CALCBINDINGS environment variable is not defined, then the following X# file will be used for the command line and edit history key bindings. X# XCALCBINDINGS= ${LIBDIR}/bindings X X# If $PAGER is not set, use this program to display a help file X# XCALCPAGER= more X#CALCPAGER= less X#CALCPAGER= pg X#CALCPAGER= cat X X# Compile debug options X# X# Select -O, or empty string, if you don't want to debug XDEBUG= -O X#DEBUG= -O3 X#DEBUG= -g X#DEBUG= -gx X#DEBUG= -WM,-g X#DEBUG= X X# On systems that have dynamic shared libs, you want want to disable them X# for faster calc startup. X# XNO_SHARED= X#NO_SHARED= -dn X X# Some systems allow 'mkdir -p' to make a directory and any needed parent X# directories. X# X# If you system has 'mkdir -p', then: MKDIR=mkdir -p X# otherwise: MKDIR=mkdir X# X# If you do not have 'mkdir -p', then you must ensure that ${LIBDIR}, X# ${BINDIR} and ${HELPDIR} exist before you do an install. X# XMKDIR=mkdir -p X#MKDIR=mkdir X X# If you are running an an old BSD system, then you may not have X# the following functions: X# X# memcpy() strchr() memset() X# X# If you do not have these functions, define OLD_BSD to be -DOLD_BSD, X# otherwise define OLD_BSD to be an empty string. X# X# Modern BSD and BSD-like systems have these functions and thus don't X# need OLD_BSD. If you don't know, try using the empty string and if X# you get complaints, try -DOLD_BSD. X# XOLD_BSD= X#OLD_BSD= -DOLD_BSD X X# Some old systems don't know what a uid_t is. Define UID_T if you get X# an error regarding 'uid_t' when compiling files such as calc.c X# XUID_T= X#UID_T= -DUID_T X X# Some systems require one to use ranlib to add a symbol table to X# a *.a library. Set RANLIB to the utility that performs this action. X# Set RANLIB to : if your system does not need such a utility. X# X#RANLIB=ranlib XRANLIB=: X X# Some systems are able to form lint libs. How it is formed depends X# on your system. If you do not care about lint, use : as the X# LINTLIB value. X# X# System type LINTLIB recomendation X# X# BSD ${LINT} ${LCFLAGS} ${LINTFLAGS} -u -Ccalc X# SYSV ${LINT} ${LCFLAGS} ${LINTFLAGS} -u -o calc X# disable : X# XLINTLIB= ${LINT} ${LCFLAGS} ${LINTFLAGS} -u -Ccalc X#LINTLIB= ${LINT} ${LCFLAGS} ${LINTFLAGS} -u -o calc X#LINTLIB= : X X# The lint flags vary from system to system. Some systems have the X# opposite meaning for the flags below. Other systems change flag X# meaning altogether. X# X# System LINTFLAGS recomendation X# X# SunOs -a -h -v -z X# XLINTFLAGS= -a -h -v -z X#LINTFLAGS= X X############################################################################## X#-=-=-=-=-=-=-=-=- Be careful if you change something below -=-=-=-=-=-=-=-=-# X############################################################################## X X# standard utilities used during make X# XSHELL= /bin/sh XMAKE= make XSED= sed XTEE= tee XLINT= lint XCTAGS= ctags XCC= cc X#CC= gcc X X X# X# the source files which are built into a math library X# XLIBSRC = alloc.c comfunc.c commath.c qfunc.c qio.c qmath.c qmod.c qtrans.c \ X zfunc.c zio.c zmath.c zmod.c zmul.c X X X# X# the object files which are built into a math library X# XLIBOBJS = alloc.o comfunc.o commath.o qfunc.o qio.o qmath.o qmod.o qtrans.o \ X zfunc.o zio.o zmath.o zmod.o zmul.o X X# X# the calculator source files X# XCALCSRC = addop.c assocfunc.c calc.c codegen.c config.c const.c file.c \ X func.c hist.c input.c label.c listfunc.c matfunc.c obj.c opcodes.c \ X string.c symbol.c token.c value.c version.c X X X# X# we build these .o files for calc X# XCALCOBJS = addop.o assocfunc.o calc.o codegen.o config.o const.o file.o \ X func.o hist.o input.o label.o listfunc.o matfunc.o obj.o opcodes.o \ X string.o symbol.o token.o value.o version.o X X X# we build these .h files during the make X# XBUILD_H_SRC= config.h have_malloc.h have_stdlib.h have_string.h args.h \ X args.h terminal.h endian.h X X X# these .h files are needed by programs that use libcalc.a X# XLIB_H_SRC= qmath.h zmath.h cmath.h alloc.h have_stdlib.h have_malloc.h \ X have_string.h endian.h X X X# The code program is not part of the calc distribution, don't worry X# if you do not have it. X# XCODEOBJS= code.o X X X# LCFLAGS are flags that both ${CC} and ${LINT} can use X# CFLAGS are the default flags given to ${CC} X# XLCFLAGS= ${MALLOC} ${OLD_BSD} ${DONT_HAVE_VSPRINTF} ${UID_T} XCFLAGS= ${DEBUG} ${LCFLAGS} X Xall: calc calc.1 X Xcalc: libcalc.a ${CALCOBJS} X ${CC} ${CFLAGS} ${CALCOBJS} libcalc.a -o calc ${NO_SHARED} X Xhist.o: hist.c Makefile X ${CC} ${CFLAGS} ${DEBUG} ${TERMCONTROL} -c hist.c X Xlibcalc.a: ${LIBOBJS} Makefile X rm -f libcalc.a X ar qc libcalc.a ${LIBOBJS} X ${RANLIB} libcalc.a X Xendian: endian.c X -@rm -f endian.o endian X ${CC} ${CFLAGS} endian.c -o endian ${NO_SHARED} X Xconfig.h: Makefile X rm -f config.h X @echo 'forming config.h' X @echo '/*' > config.h X @echo ' * DO NOT EDIT -- generated by the Makefile' >> config.h X @echo ' */' >> config.h X @echo '' >> config.h X @echo '/* the default :-separated search path */' >> config.h X @echo '#ifndef DEFAULTCALCPATH' >> config.h X @echo '#define DEFAULTCALCPATH "${CALCPATH}"' >> config.h X @echo '#endif /* DEFAULTCALCPATH */' >> config.h X @echo '' >> config.h X @echo '/* the default :-separated startup file list */' >> config.h X @echo '#ifndef DEFAULTCALCRC' >> config.h X @echo '#define DEFAULTCALCRC "${CALCRC}"' >> config.h X @echo '#endif /* DEFAULTCALCRC */' >> config.h X @echo '' >> config.h X @echo '/* the default key bindings file */' >> config.h X @echo '#ifndef DEFAULTCALCBINDINGS' >> config.h X @echo '#define DEFAULTCALCBINDINGS "${CALCBINDINGS}"' >> config.h X @echo '#endif /* DEFAULTCALCBINDINGS */' >> config.h X @echo '' >> config.h X @echo '/* the location of the help directory */' >> config.h X @echo '#ifndef HELPDIR' >> config.h X @echo '#define HELPDIR "${HELPDIR}"' >> config.h X @echo '#endif /* HELPDIR */' >> config.h X @echo '' >> config.h X @echo '/* the default pager to use */' >> config.h X @echo '#ifndef DEFAULTCALCPAGER' >> config.h X @echo '#define DEFAULTCALCPAGER "${CALCPAGER}"' >> config.h X @echo '#endif /* DEFAULTCALCPAGER */' >> config.h X @echo 'config.h formed' X Xendian.h: endian X rm -f endian.h X @echo 'forming endian.h' X @echo '/*' > endian.h X @echo ' * DO NOT EDIT -- generated by the Makefile' >> endian.h X @echo ' */' >> endian.h X @echo '' >> endian.h X -@if [ X"${BYTE_ORDER}" = X ]; then \ X if [ -f /usr/include/machine/endian.h ]; then \ X echo '#include ' >> endian.h; \ X else \ X ./endian >> endian.h; \ X fi; \ X else \ X echo "#define BYTE_ORDER ${BYTE_ORDER}" >> endian.h; \ X fi X @echo 'endian.h formed' X Xhave_malloc.h: Makefile X rm -f have_malloc.h X @echo 'forming have_malloc.h' X @echo '/*' > have_malloc.h X @echo ' * DO NOT EDIT -- generated by the Makefile' >> have_malloc.h X @echo ' */' >> have_malloc.h X @echo '' >> have_malloc.h X @echo '/* do we have /usr/include/malloc.h? */' > have_malloc.h X -@if [ -f /usr/include/malloc.h ]; then \ X echo '#define HAVE_MALLOC_H /* yes */' >> have_malloc.h; \ X else \ X echo '#undef HAVE_MALLOC_H /* no */' >> have_malloc.h; \ X fi X @echo 'have_malloc.h formed' X Xhave_stdlib.h: Makefile X rm -f have_stdlib.h X @echo 'forming have_stdlib.h' X @echo '/*' > have_stdlib.h X @echo ' * DO NOT EDIT -- generated by the Makefile' >> have_stdlib.h X @echo ' */' >> have_stdlib.h X @echo '' >> have_stdlib.h X @echo '/* do we have /usr/include/stdlib.h? */' > have_stdlib.h X -@if [ -f /usr/include/stdlib.h ]; then \ X echo '#define HAVE_STDLIB_H /* yes */' >> have_stdlib.h; \ X else \ X echo '#undef HAVE_STDLIB_H /* no */' >> have_stdlib.h; \ X fi X @echo 'have_stdlib.h formed' X Xhave_string.h: Makefile X rm -f have_string.h X @echo 'forming have_string.h' X @echo '/*' > have_string.h X @echo ' * DO NOT EDIT -- generated by the Makefile' >> have_string.h X @echo ' */' >> have_string.h X @echo '' >> have_string.h X @echo '/* do we have /usr/include/string.h? */' > have_string.h X -@if [ -f /usr/include/string.h ]; then \ X echo '#define HAVE_STRING_H /* yes */' >> have_string.h; \ X else \ X echo '#undef HAVE_STRING_H /* no */' >> have_string.h; \ X fi X @echo 'have_string.h formed' X Xterminal.h: Makefile X rm -f terminal.h X @echo 'forming terminal.h' X @echo '/*' > terminal.h X @echo ' * DO NOT EDIT -- generated by the Makefile' >> terminal.h X @echo ' */' >> terminal.h X @echo '' >> terminal.h X @echo '#if !defined(USE_TERMIOS)' >> terminal.h X @echo '#if !defined(USE_TERMIO)' >> terminal.h X @echo '#if !defined(USE_SGTTY)' >> terminal.h X -@if [ -f /usr/include/termios.h ]; then \ X echo '#define USE_TERMIOS /* */' >> terminal.h; \ X echo '#undef USE_TERMIO /* */' >> terminal.h; \ X echo '#undef USE_SGTTY /* */' >> terminal.h; \ X elif [ -f /usr/include/termio.h ]; then \ X echo '#undef USE_TERMIOS /* */' >> terminal.h; \ X echo '#define USE_TERMIO /* */' >> terminal.h; \ X echo '#undef USE_SGTTY /* */' >> terminal.h; \ X else \ X echo '#undef USE_TERMIOS /* */' >> terminal.h; \ X echo '#undef USE_TERMIO /* */' >> terminal.h; \ X echo '#define USE_SGTTY /* */' >> terminal.h; \ X fi X @echo '#endif' >> terminal.h X @echo '#endif' >> terminal.h X @echo '#endif' >> terminal.h X @echo 'terminal.h formed' X Xargs.h: Makefile X rm -f args.h X @echo 'forming args.h' X @echo '/*' > args.h X @echo ' * DO NOT EDIT -- generated by the Makefile' >> args.h X @echo ' */' >> args.h X @echo '' >> args.h X @echo '/* what sort of variable args do we have? */' > args.h X -@if [ ! -z "${VARARG}" ]; then \ X echo '#define ${VARARG}' >> args.h; \ X elif [ -f /usr/include/stdarg.h ]; then \ X echo '#define STDARG' >> args.h; \ X elif [ -f /usr/include/varargs.h ]; then \ X echo '#define VARARGS' >> args.h; \ X else \ X echo '#define SIMULATE_STDARG' >> args.h; \ X fi X @echo 'args.h formed' X Xcalc.1: calc.man X rm -f calc.1 X ${SED} -e 's:$${LIBDIR}:${LIBDIR}:g' < calc.man > calc.1 X Xllib-lcalc.ln: ${BUILD_H_SRC} ${LIBSRC} Makefile X rm -f llib-lcalc.ln llib.out X -touch llib-lcalc.ln X ${LINTLIB} ${LIBSRC} 2>&1 | ${SED} -f lint.sed | ${TEE} llib.out X Xlint: ${BUILD_H_SRC} ${CALCSRC} llib-lcalc.ln lint.sed Makefile X rm -f lint.out X ${LINT} ${LINTFLAGS} ${LCFLAGS} llib-lcalc.ln ${CALCSRC} 2>&1 | \ X ${SED} -f lint.sed | ${TEE} lint.out X Xtags: ${CALCSRC} X ${CTAGS} ${CALCSRC} X Xlintclean: X rm -f llib-lcalc.ln llib.out lint.out X Xclean: X rm -f ${LIBOBJS} ${CALCOBJS} ${CODEOBJS} endian.o X cd help; ${MAKE} -f Makefile LIBDIR=${LIBDIR} HELPDIR=${HELPDIR} clean X Xclobber: lintclean X rm -f ${LIBOBJS} ${CALCOBJS} ${CODEOBJS} X rm -f tags calc code libcalc.a X rm -f ${BUILD_H_SRC} calc.1 endian X cd help; ${MAKE} -f Makefile LIBDIR=${LIBDIR} HELPDIR=${HELPDIR} clobber X Xinstall: calc libcalc.a ${LIB_H_SRC} calc.1 X -@if [ ! -d ${LIBDIR} ]; then \ X echo ${MKDIR} ${LIBDIR}; \ X ${MKDIR} ${LIBDIR}; \ X fi X -chmod 0755 ${LIBDIR} X -@if [ ! -d ${HELPDIR} ]; then \ X echo ${MKDIR} ${HELPDIR}; \ X ${MKDIR} ${HELPDIR}; \ X fi X -chmod 0755 ${HELPDIR} X -@if [ ! -d ${BINDIR} ]; then \ X echo ${MKDIR} ${BINDIR}; \ X ${MKDIR} ${BINDIR}; \ X fi X -chmod 0755 ${BINDIR} X rm -f ${BINDIR}/calc X cp calc ${BINDIR} X -chmod 0555 ${BINDIR}/calc X cd help; ${MAKE} -f Makefile LIBDIR=${LIBDIR} HELPDIR=${HELPDIR} install X cd lib; ${MAKE} -f Makefile LIBDIR=${LIBDIR} install X rm -f ${LIBDIR}/libcalc.a X cp libcalc.a ${LIBDIR}/libcalc.a X -chmod 0644 ${LIBDIR}/libcalc.a X ${RANLIB} ${LIBDIR}/libcalc.a X @for i in ${LIB_H_SRC}; do \ X echo rm -f ${LIBDIR}/$$i; \ X rm -f ${LIBDIR}/$$i; \ X echo cp $$i ${LIBDIR}; \ X cp $$i ${LIBDIR}; \ X echo chmod 0444 ${LIBDIR}/$$i; \ X chmod 0444 ${LIBDIR}/$$i; \ X done X @# If lint was made, install the lint library. X -@if [ -f llib-lcalc.ln ]; then \ X echo rm -f ${LIBDIR}/llib-lcalc.ln; \ X rm -f ${LIBDIR}/llib-lcalc.ln; \ X echo cp llib-lcalc.ln ${LIBDIR}; \ X cp llib-lcalc.ln ${LIBDIR}; \ X echo chmod 0444 ${LIBDIR}/llib-lcalc.ln; \ X chmod 0444 ${LIBDIR}/llib-lcalc.ln; \ X fi X rm -f ${MANDIR}/calc.1 X -cp calc.1 ${MANDIR} X -chmod 0444 ${MANDIR}/calc.1 X @# The code program is not part of the calc distribution, don't worry X @# if you do not have it. X -@if [ -f code ]; then \ X echo chmod +x code; \ X chmod +x code; \ X echo rm -f ${BINDIR}/code; \ X rm -f ${BINDIR}/code; \ X echo cp code ${BINDIR}; \ X cp code ${BINDIR}; \ X echo chmod 0555 ${BINDIR}/code; \ X chmod 0555 ${BINDIR}/code; \ X fi X X# The code program is not part of the calc distribution, don't worry X# if you do not have it. X# Xcode: ${CODEOBJS} ${LIBOBJS} X ${CC} ${CFLAGS} ${CODEOBJS} libcalc.a -o code ${NO_SHARED} X Xcode.o: code.c stdarg.h args.h qmath.h zmath.h alloc.h \ X have_malloc.h have_string.h have_stdlib.h endian.h X ${CC} ${CFLAGS} code.c -c X X X# make depend stuff X# Xaddop.o: addop.c calc.h value.h cmath.h qmath.h zmath.h alloc.h \ X have_malloc.h have_string.h have_stdlib.h opcodes.h string.h \ X func.h label.h token.h symbol.h endian.h Xalloc.o: alloc.c alloc.h have_malloc.h have_string.h have_stdlib.h Xassocfunc.o: assocfunc.c value.h cmath.h qmath.h zmath.h alloc.h \ X have_malloc.h have_string.h have_stdlib.h endian.h Xcalc.o: calc.c calc.h value.h cmath.h qmath.h zmath.h alloc.h \ X have_malloc.h have_string.h have_stdlib.h hist.h func.h \ X label.h opcodes.h config.h token.h symbol.h endian.h Xcodegen.o: codegen.c calc.h value.h cmath.h qmath.h zmath.h alloc.h \ X have_malloc.h have_string.h have_stdlib.h token.h symbol.h \ X label.h opcodes.h string.h func.h config.h endian.h Xcomfunc.o: comfunc.c cmath.h qmath.h zmath.h alloc.h have_malloc.h \ X have_string.h have_stdlib.h endian.h Xcommath.o: commath.c cmath.h qmath.h zmath.h alloc.h have_malloc.h \ X have_string.h have_stdlib.h endian.h Xconfig.o: config.c calc.h value.h cmath.h qmath.h zmath.h alloc.h \ X have_malloc.h have_string.h have_stdlib.h endian.h Xconst.o: const.c calc.h value.h cmath.h qmath.h zmath.h alloc.h \ X have_malloc.h have_string.h have_stdlib.h endian.h Xfile.o: file.c stdarg.h args.h calc.h value.h cmath.h qmath.h \ X zmath.h alloc.h have_malloc.h have_string.h have_stdlib.h \ X endian.h Xfunc.o: func.c calc.h value.h cmath.h qmath.h zmath.h alloc.h \ X have_malloc.h have_string.h have_stdlib.h opcodes.h token.h \ X func.h label.h string.h symbol.h endian.h Xhist.o: hist.c hist.h terminal.h Xinput.o: input.c calc.h value.h cmath.h qmath.h zmath.h alloc.h \ X have_malloc.h have_string.h have_stdlib.h config.h hist.h \ X endian.h Xlabel.o: label.c calc.h value.h cmath.h qmath.h zmath.h alloc.h \ X have_malloc.h have_string.h have_stdlib.h token.h label.h \ X string.h opcodes.h func.h endian.h Xlistfunc.o: listfunc.c value.h cmath.h qmath.h zmath.h alloc.h \ X have_malloc.h have_string.h have_stdlib.h endian.h Xmatfunc.o: matfunc.c value.h cmath.h qmath.h zmath.h alloc.h \ X have_malloc.h have_string.h have_stdlib.h endian.h Xobj.o: obj.c calc.h value.h cmath.h qmath.h zmath.h alloc.h \ X have_malloc.h have_string.h have_stdlib.h opcodes.h func.h \ X label.h symbol.h string.h endian.h Xopcodes.o: opcodes.c stdarg.h args.h calc.h value.h cmath.h qmath.h \ X zmath.h alloc.h have_malloc.h have_string.h have_stdlib.h \ X opcodes.h func.h label.h symbol.h hist.h endian.h Xqfunc.o: qfunc.c qmath.h zmath.h alloc.h have_malloc.h have_string.h \ X have_stdlib.h endian.h Xqio.o: qio.c stdarg.h args.h qmath.h zmath.h alloc.h have_malloc.h \ X have_string.h have_stdlib.h endian.h Xqmath.o: qmath.c qmath.h zmath.h alloc.h have_malloc.h have_string.h \ X have_stdlib.h endian.h Xqmod.o: qmod.c qmath.h zmath.h alloc.h have_malloc.h have_string.h \ X have_stdlib.h endian.h Xqtrans.o: qtrans.c qmath.h zmath.h alloc.h have_malloc.h have_string.h \ X have_stdlib.h endian.h Xstring.o: string.c calc.h value.h cmath.h qmath.h zmath.h alloc.h \ X have_malloc.h have_string.h have_stdlib.h string.h endian.h Xsymbol.o: symbol.c calc.h value.h cmath.h qmath.h zmath.h alloc.h \ X have_malloc.h have_string.h have_stdlib.h token.h symbol.h \ X string.h opcodes.h func.h label.h endian.h Xtoken.o: token.c stdarg.h args.h calc.h value.h cmath.h qmath.h \ X zmath.h alloc.h have_malloc.h have_string.h have_stdlib.h \ X token.h string.h endian.h Xvalue.o: value.c value.h cmath.h qmath.h zmath.h alloc.h \ X have_malloc.h have_string.h have_stdlib.h opcodes.h func.h \ X calc.h label.h symbol.h string.h endian.h Xversion.o: version.c calc.h value.h cmath.h qmath.h zmath.h alloc.h \ X have_malloc.h have_string.h have_stdlib.h endian.h Xzfunc.o: zfunc.c zmath.h alloc.h have_malloc.h have_string.h \ X have_stdlib.h endian.h Xzio.o: zio.c stdarg.h args.h zmath.h alloc.h have_malloc.h \ X have_string.h have_stdlib.h endian.h Xzmath.o: zmath.c zmath.h alloc.h have_malloc.h have_string.h \ X have_stdlib.h endian.h Xzmod.o: zmod.c zmath.h alloc.h have_malloc.h have_string.h \ X have_stdlib.h endian.h Xzmul.o: zmul.c zmath.h alloc.h have_malloc.h have_string.h \ X have_stdlib.h endian.h SHAR_EOF chmod 0644 calc2.9.0/Makefile || echo "restore of calc2.9.0/Makefile fails" set `wc -c calc2.9.0/Makefile`;Sum=$1 if test "$Sum" != "20426" then echo original size 20426, current size $Sum;fi echo "x - extracting calc2.9.0/addop.c (Text)" sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/addop.c && X/* X * Copyright (c) 1993 David I. Bell X * Permission is granted to use, distribute, or modify this source, X * provided that this copyright notice remains intact. X * X * Add opcodes to a function being compiled. X */ X X#include "calc.h" X#include "opcodes.h" X#include "string.h" X#include "func.h" X#include "token.h" X#include "label.h" X#include "symbol.h" X X X#define FUNCALLOCSIZE 20 /* reallocate size for functions */ X#define OPCODEALLOCSIZE 100 /* reallocate size for opcodes in functions */ X X Xstatic long maxopcodes; /* number of opcodes available */ Xstatic long newindex; /* index of new function */ Xstatic long oldop; /* previous opcode */ Xstatic long debugline; /* line number of latest debug opcode */ Xstatic long funccount; /* number of functions */ Xstatic long funcavail; /* available number of functions */ Xstatic FUNC *functemplate; /* function definition template */ Xstatic FUNC **functions; /* table of functions */ Xstatic STRINGHEAD funcnames; /* function names */ Xstatic int codeflag; X X X/* X * Initialize the table of user defined functions. X */ Xvoid Xinitfunctions() X{ X initstr(&funcnames); X maxopcodes = OPCODEALLOCSIZE; X functemplate = (FUNC *) malloc(funcsize(maxopcodes)); X if (functemplate == NULL) X math_error("Cannot allocate function template"); X functions = (FUNC **) malloc(sizeof(FUNC *) * FUNCALLOCSIZE); X if (functions == NULL) X math_error("Cannot allocate function table"); X funccount = 0; X funcavail = FUNCALLOCSIZE; X} X X X/* X * Show the list of user defined functions. X */ Xvoid Xshowfunctions() X{ X FUNC **fpp; /* pointer into function table */ X FUNC *fp; /* current function */ X X if (funccount == 0) { X printf("No user functions defined.\n"); X return; X } X printf("Name Arguments\n"); X printf("---- ---------\n"); X for (fpp = &functions[funccount - 1]; fpp >= functions; fpp--) { X fp = *fpp; X if (fp == NULL) X continue; X printf("%-12s %-2d\n", fp->f_name, fp->f_paramcount); X } X printf("\n"); X} X X X/* X * Initialize a function for definition. X * Newflag is TRUE if we should allocate a new function structure, X * instead of the usual overwriting of the template function structure. X * The new structure is returned in the global curfunc variable. X */ Xvoid Xbeginfunc(name, newflag) X char *name; /* name of function */ X BOOL newflag; /* TRUE if need new structure */ X{ X register FUNC *fp; /* current function */ X X newindex = adduserfunc(name); X maxopcodes = OPCODEALLOCSIZE; X fp = functemplate; X if (newflag) { X fp = (FUNC *) malloc(funcsize(maxopcodes)); X if (fp == NULL) X math_error("Cannot allocate temporary function"); X } X fp->f_next = NULL; X fp->f_localcount = 0; X fp->f_opcodecount = 0; X fp->f_savedvalue.v_type = V_NULL; X fp->f_name = namestr(&funcnames, newindex); X curfunc = fp; X initlocals(); X initlabels(); X oldop = OP_NOP; X debugline = 0; X errorcount = 0; X} X X X/* X * Commit the just defined function for use. X * This replaces any existing definition for the function. X * This should only be called for normal user-defined functions. X */ Xvoid Xendfunc() X{ X register FUNC *fp; /* function just finished */ X long size; /* size of just created function */ X X checklabels(); X if (errorcount) { X printf("\"%s\": %ld error%s\n", curfunc->f_name, errorcount, X ((errorcount == 1) ? "" : "s")); X return; X } X size = funcsize(curfunc->f_opcodecount); X fp = (FUNC *) malloc(size); X if (fp == NULL) X math_error("Cannot commit function"); X memcpy((char *) fp, (char *) curfunc, size); X if (curfunc != functemplate) X free(curfunc); X if (codeflag) { X for (size = 0; size < fp->f_opcodecount; ) { X printf("%ld: ", (long)size); X size += dumpop(&fp->f_opcodes[size]); X } X } X if (functions[newindex]) X free(functions[newindex]); X functions[newindex] = fp; X objuncache(); X if (inputisterminal()) X printf("\"%s\" defined\n", fp->f_name); X} X X X/* X * Find the user function with the specified name, and return its index. X * If the function does not exist, its name is added to the function table X * and an error will be generated when it is called if it is still undefined. X */ Xlong Xadduserfunc(name) X char *name; /* name of function */ X{ X long index; /* index of function */ X X index = findstr(&funcnames, name); X if (index >= 0) X return index; X if (funccount >= funcavail) { X functions = (FUNC **) realloc(functions, X sizeof(FUNC *) * (funcavail + FUNCALLOCSIZE)); X if (functions == NULL) X math_error("Failed to reallocate function table"); X funcavail += FUNCALLOCSIZE; X } X if (addstr(&funcnames, name) == NULL) X math_error("Cannot save function name"); X index = funccount++; X functions[index] = NULL; X return index; X} X X X/* X * Clear any optimization that may be done for the next opcode. X * This is used when defining a label. X */ Xvoid Xclearopt() X{ X oldop = OP_NOP; X debugline = 0; X} X X X/* X * Find a function structure given its index. X */ XFUNC * Xfindfunc(index) X long index; X{ X if ((unsigned long) index >= funccount) X math_error("Undefined function"); X return functions[index]; X} X X X/* X * Return the name of a function given its index. X */ Xchar * Xnamefunc(index) X long index; X{ X return namestr(&funcnames, index); X} X X X/* X * Let a matrix indexing operation know that it will be treated as a write X * reference instead of just as a read reference. X */ Xvoid Xwriteindexop() X{ X if (oldop == OP_INDEXADDR) X curfunc->f_opcodes[curfunc->f_opcodecount - 1] = TRUE; X} X X X/* X * Add an opcode to the current function being compiled. X * Note: This can change the curfunc global variable when the X * function needs expanding. X */ Xvoid Xaddop(op) X long op; X{ X register FUNC *fp; /* current function */ X NUMBER *q; X X fp = curfunc; X if ((fp->f_opcodecount + 5) >= maxopcodes) { X maxopcodes += OPCODEALLOCSIZE; X fp = (FUNC *) malloc(funcsize(maxopcodes)); X if (fp == NULL) X math_error("cannot reallocate function"); X memcpy((char *) fp, (char *) curfunc, X funcsize(curfunc->f_opcodecount)); X if (curfunc != functemplate) X free(curfunc); X curfunc = fp; X } X /* X * Check the current opcode against the previous opcode and try to X * slightly optimize the code depending on the various combinations. X */ X if (op == OP_GETVALUE) { X switch (oldop) { X X case OP_NUMBER: case OP_ZERO: case OP_ONE: case OP_IMAGINARY: X case OP_GETEPSILON: case OP_SETEPSILON: case OP_STRING: X case OP_UNDEF: case OP_GETCONFIG: case OP_SETCONFIG: X return; X case OP_DUPLICATE: X fp->f_opcodes[fp->f_opcodecount - 1] = OP_DUPVALUE; X oldop = OP_DUPVALUE; X return; X case OP_FIADDR: X fp->f_opcodes[fp->f_opcodecount - 1] = OP_FIVALUE; X oldop = OP_FIVALUE; X return; X case OP_GLOBALADDR: X fp->f_opcodes[fp->f_opcodecount - 2] = OP_GLOBALVALUE; X oldop = OP_GLOBALVALUE; X return; X case OP_LOCALADDR: X fp->f_opcodes[fp->f_opcodecount - 2] = OP_LOCALVALUE; X oldop = OP_LOCALVALUE; X return; X case OP_PARAMADDR: X fp->f_opcodes[fp->f_opcodecount - 2] = OP_PARAMVALUE; X oldop = OP_PARAMVALUE; X return; X case OP_ELEMADDR: X fp->f_opcodes[fp->f_opcodecount - 2] = OP_ELEMVALUE; X oldop = OP_ELEMVALUE; X return; X } X } X if ((op == OP_NEGATE) && (oldop == OP_NUMBER)) { X q = constvalue(fp->f_opcodes[fp->f_opcodecount - 1]); X fp->f_opcodes[fp->f_opcodecount - 1] = addqconstant(qneg(q)); X oldop = OP_NUMBER; X return; X } X if ((op == OP_POWER) && (oldop == OP_NUMBER)) { X if (qcmpi(constvalue(fp->f_opcodes[fp->f_opcodecount - 1]), 2L) == 0) { X fp->f_opcodecount--; X fp->f_opcodes[fp->f_opcodecount - 1] = OP_SQUARE; X oldop = OP_SQUARE; X return; X } X if (qcmpi(constvalue(fp->f_opcodes[fp->f_opcodecount - 1]), 4L) == 0) { X fp->f_opcodes[fp->f_opcodecount - 2] = OP_SQUARE; X fp->f_opcodes[fp->f_opcodecount - 1] = OP_SQUARE; X oldop = OP_SQUARE; X return; X } X } X if ((op == OP_POP) && (oldop == OP_ASSIGN)) { /* optimize */ X fp->f_opcodes[fp->f_opcodecount - 1] = OP_ASSIGNPOP; X oldop = OP_ASSIGNPOP; X return; X } X /* X * No optimization possible, so store the opcode. X */ X fp->f_opcodes[fp->f_opcodecount] = op; X fp->f_opcodecount++; X oldop = op; X} X X X/* X * Add an opcode and and one integer argument to the current function X * being compiled. X */ Xvoid Xaddopone(op, arg) X long op; X long arg; X{ X NUMBER *q; X X switch (op) { X case OP_NUMBER: X q = constvalue(arg); X if (q == NULL) X break; X if (qiszero(q)) { X addop(OP_ZERO); X return; X } X if (qisone(q)) { X addop(OP_ONE); X return; X } X break; X X case OP_DEBUG: X if ((traceflags & TRACE_NODEBUG) || (arg == debugline)) X return; X debugline = arg; X if (oldop == OP_DEBUG) { X curfunc->f_opcodes[curfunc->f_opcodecount - 1] = arg; X return; X } X break; X } X addop(op); X curfunc->f_opcodes[curfunc->f_opcodecount] = arg; X curfunc->f_opcodecount++; X} X X X/* X * Add an opcode and and two integer arguments to the current function X * being compiled. X */ Xvoid Xaddoptwo(op, arg1, arg2) X long op; X long arg1; X long arg2; X{ X addop(op); X curfunc->f_opcodes[curfunc->f_opcodecount++] = arg1; X curfunc->f_opcodes[curfunc->f_opcodecount++] = arg2; X} X X X/* X * Add an opcode and a character pointer to the function being compiled. X */ Xvoid Xaddopptr(op, ptr) X long op; X char *ptr; X{ X char **ptraddr; X X addop(op); X ptraddr = (char **) &curfunc->f_opcodes[curfunc->f_opcodecount]; X *ptraddr = ptr; X curfunc->f_opcodecount += PTR_SIZE; X} X X X/* X * Add an opcode and an index and an argument count for a function call. X */ Xvoid Xaddopfunction(op, index, count) X long op; X long index; X{ X long newop; X X if ((op == OP_CALL) && ((newop = builtinopcode(index)) != OP_NOP)) { X if ((newop == OP_SETCONFIG) && (count == 1)) X newop = OP_GETCONFIG; X if ((newop == OP_SETEPSILON) && (count == 0)) X newop = OP_GETEPSILON; X if ((newop == OP_ABS) && (count == 1)) X addop(OP_GETEPSILON); X addop(newop); X return; X } X addop(op); X curfunc->f_opcodes[curfunc->f_opcodecount++] = index; X curfunc->f_opcodes[curfunc->f_opcodecount++] = count; X} X X X/* X * Add a jump-type opcode and a label to the function being compiled. X */ Xvoid Xaddoplabel(op, label) X long op; X LABEL *label; /* label to be added */ X{ X addop(op); X uselabel(label); X} X X/* END CODE */ SHAR_EOF chmod 0644 calc2.9.0/addop.c || echo "restore of calc2.9.0/addop.c fails" set `wc -c calc2.9.0/addop.c`;Sum=$1 if test "$Sum" != "9951" then echo original size 9951, current size $Sum;fi echo "x - extracting calc2.9.0/alloc.c (Text)" sed 's/^X//' << 'SHAR_EOF' > calc2.9.0/alloc.c && X/* X * Copyright (c) 1993 David I. Bell X * Permission is granted to use, distribute, or modify this source, X * provided that this copyright notice remains intact. X * X * Description: X * This is a very fast storage allocator. It allocates blocks of a small X * number of different sizes, and keeps free lists of each size. Blocks X * that don't exactly fit are passed up to the next larger size. In this X * implementation, the available sizes are 2^n-4 (or 2^n-12) bytes long. X * This is designed for use in a program that uses vast quantities of X * memory, but bombs when it runs out. X * X * Abnormal Conditions X * This is a public domain storage allocator. X * X * Modifications: X * Date Programmer Description of modification X * 27-FEB-90 Landon Curt Noll most systems can ignore alloc.c X * 2-OCT-89 David I. Bell Add free list. Sbrk now optional X * 30-JUN-87 Peter Miller Made it work on Slimos. X * 21-FEB-82 Chris Kingsley Initial Coding X * kingsley@cit-20 Caltech X */ X X#include X#include "alloc.h" X#include "have_stdlib.h" X X#if 0 X#define DEBUG 1 /* defined if debugging code enabled */ X#define MSTATS 1 /* defined if memory statistics kept */ X#endif X#define NO_SBRK 1 /* defined if cannot use sbrk */ X X X#if defined(CALC_MALLOC) X/* X * Make these functions really accessible here. X */ X#undef malloc X#undef realloc X#undef free X X X#ifdef DEBUG X#define assert(x,v) if ((x)==0) assertfailed(v) X#else X#define assert(x,v) X#endif X Xtypedef unsigned char u_char; Xtypedef unsigned short u_short; Xtypedef unsigned int u_int; Xtypedef char * caddr_t; X X#ifdef NO_SBRK Xextern char * malloc(); Xextern char * realloc(); X#else Xextern char * sbrk(); X#endif X X X/* X * The overhead on a block is at least 4 bytes. When free, this space X * contains a pointer to the next free block, and the bottom two bits must X * be zero. When in use, the first byte is set to MAGIC, and the second X * byte is the size index. The remaining bytes are for alignment. X * If range checking (RCHECK) is enabled and the size of the block fits X * in two bytes, then the top two bytes hold the size of the requested block X * plus the range checking words, and the header word MINUS ONE. X */ X Xunion overhead X{ X union overhead * ov_next; /* when free */ X struct X { X u_char ovu_magic; /* magic number */ X u_char ovu_index; /* bucket # */ X#define ov_magic ovu.ovu_magic X#define ov_index ovu.ovu_index X#ifdef RCHECK X u_short ovu_size; /* actual block size */ X u_int ovu_rmagic; /* range magic number */ X#define ov_size ovu.ovu_size X#define ov_rmagic ovu.ovu_rmagic X#endif X } ovu; X}; X X#define QUANTUM_NBITS 4 X#define QUANTUM (1<ov_magic == MAGIC, 10); X} X X Xalloccheck() X{ X assert((watchloc == NULL) || (watchloc->ov_magic == MAGIC), 11); X} X X X/* X * NAME X * morecore - get more memory X * X * SYNOPSIS X * void X * morecore(bucket) X * int bucket; X * X * DESCRIPTION X * Morecore is used to allocate more memory to the indicated bucket. X * X * RETURNS X * void X */ Xstatic void Xmorecore(bucket) X register u_int bucket; X{ X register union overhead * op; X register u_int rnu; /* 2^rnu bytes will be requested */ X register u_int nblks; /* become nblks blocks of the desired size */ X register u_int siz; SHAR_EOF echo "End of part 1" echo "File calc2.9.0/alloc.c is continued in part 2" echo "2" > s2_seq_.tmp exit 0