ICALC: Infix Calculator for Un*x, VAX/VMS and PC/MS-DOS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Modified and made available by: Rao Akella Research Assistant, Colon Cancer Control Study University of Minnesota, Minneapolis Introduction: ~~~~~~~~~~~~ Ever wanted to do a quick calculation and didn't have a calculator handy? ICALC is a simple, portable and quickly-accessible program for doing INFIX computations. It is neither very sophisticated nor intended to provide enormous flexibility. It merely provides the functionality of a simple infix pocket calculator. In the words of the Bard: "'Tis not so deep as a well, nor so wide as a church-door; but 'tis enough, 'twill serve." Features: ~~~~~~~~ 1) Addition (+), Subtraction (-), Multiplication (*), Division (/) 2) Modulus (%), Power (^) 3) Bitwise logical operators: bitwise AND (&), bitwise inclusive OR (|), unary one's complement (~) 4) 20 Math/Trigonometric functions: sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, exp (exponentiation), ln (natural log), log (base 10 log), sqrt (square root), ceil (ceiling), floor, int/trunc (truncation), abs (absolute value), degtorad (degrees->radians), radtodeg (radians->degrees). Two Date functions to convert between calendar dates and julian days: caltojul (calendar->julian date) and jultocal (julian->calendar date). One '?'-for-help command to display a help screen of all supported commands and functions. 5) Temporary variables (as many as you want, with names as long as you want) to store intermediate computations. 6) This is a "portable" calculator in the sense that it's not specific to any operating system. The yacc output should be compilable by any C compiler; this program has been tested on Unix, VAX/VMS and PC/MS-DOS, and has required no changes to compile. 7) This program uses the simplest of input and output formats, and is in no way hardware dependent. So, as long as it compiles without any problems, there are no other requirements for it to work properly. 8) All numbers are of the C floating-point type "double", which, according to the VAX C manual, has a range of 0.29*10^-38 to 1.7*10^38, and has values precise to 16 decimal digits. 9) Allows any number of expressions on a line, separated by ';' 10) icalc can now be run either interactively (when it is invoked without any arguments, in which case the user is prompted for input) or in a command-line mode (when all expressions to be computed are passed to icalc via command-line "argv" arguments, in which case icalc computes and prints the result of each expression -- exactly as if it had been entered interactively -- and then exits). In the latter case, the user is supposed to delimit/ separate the expressions by ';' Availability: ~~~~~~~~~~~~ ICALC is available via Anonymous FTP from cccs.umn.edu (Internet Address 128.101.133.53) Just get the file ICALC.TXT (in ASCII mode), read it and follow the instructions contained therein. If you do not have FTP access, please contact me somehow with some form of e-mail/paper-mail address, and I'll post it to you personally. Installation Instructions: ~~~~~~~~~~~~~~~~~~~~~~~~~ The installation instructions for ICALC are extremely simple, and remain practically the same on Unix, VAX/VMS and PC/MS-DOS. At the end of this file, you will find a C program (it is actually the output from yacc; if you want the original yacc grammar, please ask me, and I'll post it to you)...anyway, as I was saying, you'll find a C program at the end of this file (after the "Cut here" line). Cut it out using an editor and save it in a separate file called "icalc.c". All you have to do now is to compile this program using a C compiler, and then link it (if necessary). To be more specific: In VMS: ------ 1) Compile this C program using the commands: $ DEFINE LNK$LIBRARY SYS$LIBRARY:VAXCCURSE $ DEFINE LNK$LIBRARY_1 SYS$LIBRARY:VAXCRTLG $ DEFINE LNK$LIBRARY_2 SYS$LIBRARY:VAXCRTL $ CC ICALC This should produce an object file called ICALC.OBJ. 2) Then link this object file using the command: $ LINK ICALC,SYS$INPUT/OPTIONS SYS$SHARE:VAXCRTL/SHAREABLE ^Z <-- this is a Ctrl-Z $ 3) Run the program using the command: $ RUN ICALC The program will then prompt you for input. If you want to pass the expressions you want to be computed on the command line, you must define a global symbol (foreign command) as follows: $ ICALC :== $dev:[dir]ICALC where "dev" and "dir" are your site-specific device and directory where ICALC.EXE resides. Then you can run ICALC interactively using the command: $ ICALC Alternatively, you can run ICALC in the commmand-line mode as follows: $ ICALC expression-1; expression-2; ... For example: $ ICALC 9+4; 9-4; 9*4; 9/4 13 5 36 2.25 $ To exit ICALC in the interactive mode in VMS, type: Ctrl-Z, Ctrl-Y or Ctrl-C. In Unix: ------- 1) Compile and link the C program "icalc.c" using the command: % cc icalc.c -lm -o icalc This should produce an executable file called "icalc". Note: On some Ultrix/4.3BSD systems, not all math functions are available in the regular math library; they may be in the mathV library. On such systems, the compilation command is changed to: % cc icalc.c -lm -lmV -o icalc So, if you have trouble compiling icalc.c, please check your system for any non-standard math libraries. 2) Run the program interactively using the command: % icalc To run icalc in the command-line mode, passing all the expressions you want to be computed on the command line: % icalc 'expression-1; expression-2; ... ' Note: You must enclose all expressions supplied on the command line within single quotes, because the Un*x shell interprets some characters (like ';', '(', ')', '*', etc.) instead of passing them on to icalc. For example: % icalc '9+4; 9-4; 9*4; 9/4' 13 5 36 2.25 % To exit icalc in Unix, type Ctrl-D or Ctrl-C. In PC/MS-DOS: ------------ The installations instructions remain basically the same: compile and link ICALC.C. The precise syntax for compiling and linking will depend on what compiler you're using, so I can't be any more specific than this. I have personally been able to get ICALC to work on a PC clone running MS-DOS Version 4.00, using the Microsoft QuickC Compiler Version 2.01 and the Microsoft QuickC Linker Version 4.07. In PC/MS-DOS, type Ctrl-C or Ctrl-Z+Return to exit the program. Examples: ~~~~~~~~ A short transcript of an ICALC session follows. This will demonstrate the majority of it's features. $ ICALC IC> 4 + 4.5 - (34/(8*3+-3)) 6.880952381 IC> -56 + 2 -54 IC> 3 ^ 2 9 IC> -3 ^ 2 -9 IC> 9 % 4 1 IC> 9.7 % 4.2 1.3 IC> pi = 3.141592653589 pi = 3.141592654 3.141592654 IC> sin(PI) <- Note: Variable names are case-INsensitive. 7.9326579347e-13 <- This is close enough to zero, don't you think? IC> x = (y = (z = 4.5)*2)*3 <- Note: Multiple variable assignments z = 4.5 y = 9 x = 27 27 IC> ln(y) 2.197224577 IC> exp(ln(y)) 9 IC> uninitialisedvariable <- Note: Uninitialised variables are automatically 0 <- initialised to zero. IC> 1 & 2 0 IC> ~3 -4 IC> 0 | 1 1 IC> 9+4; 9-4; 9*4; 9/4 13 5 36 2.25 IC> ? /* help screen will be displayed */ IC> sin(degtorad(90)) 1 IC> radtodeg(asin(1)) 90 IC> caltojul(1992, 3, 16) 149538 IC> jultocal(149538) 19920316 /* yyyymmdd format */ IC> caltojul(1582, 10,15) 1 /* October 15, 1582 is julian day 1 */ IC> jultocal(1) 15821015 IC> floor(56.789) 56 IC> int(56.789) /* trunc is an alias for int */ 56 IC> floor(-56.789) -57 IC> int(-56.789) -56 IC> ^C $ History: ~~~~~~~ Let me make one thing perfectly clear. I am NOT the author of this program. I merely copied the yacc grammar for an infix calculator verbatim out of the "Bison" manual (the "mfcalc" example) of the "Free Software Foundation, Inc.", made some cosmetic modifications to customize it to my particular taste, ran it through "yacc", compiled it with a C compiler, and voila! it works. If you would prefer to have the original yacc grammar (icalc.y; you would need it if you were planning to make further modifications yourself to the source code), please ask me, and I'll post it to you. All comments/suggestions/problems/questions/criticism/flames/etc. most welcome. If there's anything at all that you don't understand or would like futher clarified, please ask me (e-mail, paper-mail, phone, anything goes). Rao V. Akella Research Assistant, Colon Cancer Control Study University of Minnesota, Minneapolis Address: E-Mail: Internet: rao@cccs.umn.edu Bitnet: rao%moose@umnacvx Work: Home: 212 Ontario St. S.E. 2111, 21st Ave. S. Suite #202 #S-20 Minneapolis, MN 55414 Minneapolis, MN 55404 (612) 627-4151 (612) 339-9982 /*== Cut here == Cut here == Cut here == Cut here == Cut here == Cut here ==*/ # line 1 "icalc.y" /*== C declarations =================================================*/ /* ******************************************************************************* * * yacc grammar : icalc.y * * version : * 2.2 of 920317 * 2.1 of 920316 * 2.0 of 911214 * 1.1 of 900816 * 1.0 of 900708 * * author : Rao V. Akella * Research Assistant, Colon Cancer Control Study * University of Minnesota, Minneapolis * * Address: * E-Mail: * Internet: rao@cccs.umn.edu * Bitnet: rao%moose@umnacvx * Work: Home: * 212 Ontario St. S.E. 2111, 21st Ave. S. * Suite #202 #S-20 * Minneapolis, MN 55414 Minneapolis, MN 55404 * (612) 627-4151 (612) 339-9982 * * written on : 900708 * * purpose : * This program is a yacc grammar to parse an infix calculator. * * date(s) modified : 920317, 920316, 911214, 900816 * * modifications : * 920317: Fixed a bug in the definition of the "int" (truncation) function, * and added a new alias (trunc) for it. * 920316: Added 1 new command and 2 new pairs of functions. * 1) Added '?' command to display a help screen briefly describing all * operators and functions supported. * 2) Added 'degtorad' and 'radtodeg' functions to convert degrees to * radians and vice versa. This should be useful because trigonometric * functions usually take only radian arguments (which are difficult to * specify). Using these functions, sine of 90 degress can be easily * computed using sin(degtorad(90)). * 3) Added a pair of date functions 'caltojul' and 'jultocal'. This can * typically be used to determine the difference (in days) between two * given dates. These functions assume the base of the Gregorian * calendar is October 15, 1582 (=julian day #1). * The 'caltojul' function should be invoked as caltojul(yyyy, mm, dd) * where yyyy is the full 4-digit year number (eg. 1992), mm is the month * number (rane 1-12) and dd is the day number (range 1-31). caltojul * returns the number of days elapsed since October 15, 1582. * The 'jultocal' function takes a julian day as input and returns the * corresponding calendar date as an integer (in the format yyyymmdd). * So, jultocal(1) should return 15821015, which stands for Oct 15, 1582. * 911214: * Minor change: allow any number of expressions on a line, separated by ';' * Major change: icalc can now be run either interactively (when it is * invoked without any arguments, in which case the user is * prompted for input) or in a command-line mode (when all * expressions to be computed are passed to icalc via * command-line "argv" arguments, in which case icalc computes * and prints the result of each expression -- exactly as if * it had been entered interactively -- and then exits). * In the latter case, the user is supposed to delimit/ * separate the expressions by ';' * 900816: * Added a check to yylex() so that tolower() is invoked (to convert all * symbol names to lower case) only if the input character is in upper case. * Some systems have the isupper() check built into tolower(), and therefore * work OK even without this change, but other systems return unspecified * results if a lower-case character is fed to tolower(). * * invoked by : The user. * * functions called : * init_table: Puts math/trig functions in symbol table. * yyparse: Grammar Parser. * yyerror: Error Handler. * yylex: Lexical Analyzer to supply tokens by parsing input. * getsym: Look-up symbol in symbol table. * putsym: Install symbol in symbol table. * my_getchar: Return a single character to yylex(), either read from the * keyboard (in interactive mode) or from the command-line * "argv" arguments (in command-line mode). * help: Display the help screen. * caltojul: Convert calendar date to julian day. * jultocal: Convert julian day to calendar date. * degtorad: Convert degrees to radians. * radtodeg: Convert radians to degrees. * trunc: Returns its truncated argument. * * inputs : * Math expression to be calculated, input by the user at the keyboard (in * interactive mode) or supplied via command-line arguments (in command-line * mode). * * outputs : * The resultant computed value of the input expression. * * instructions for use : * This is an "infix" calculator, so any infix expression will be computed * and the result displayed. * In VAX/VMS, type Ctrl-Z, Ctrl-Y or Ctrl-C to exit the program. * In Unix, type Ctrl-D or Ctrl-C to exit the program. * In PC/MS-DOS, type Ctrl-C or Ctrl-Z+Return to exit the program. * * notes : * Let me make one thing perfectly clear. I am NOT the author of this * program. I merely copied it verbatim out of the "Bison" manual of the * "Free Software Foundation, Inc.", made some cosmetic changes to customize * it to my particular taste, ran it through "yacc", compiled it with a * C compiler, and voila! it works. * * Motivation: I wanted an "infix" calculator for my day-to-day work. There * is a plethora of Reverse Polish Notation calculators in Unix and the * public domain, but I haven't seen many infix calculators around * (presumably because they're a bit harder to program than RPN calculators? * Or maybe I haven't been looking hard enough). I remembered seeing a * bison/yacc grammar example to parse an infix calculator in the Bison * manual of FSF, Inc., and since the manual permits me to copy it * (provided FSF is given proper copyright and credit, and this resulting * code is placed in the public domain), I used it as a starting point, * and simply made a FEW modifications to suit my tastes. * * Since using the Bison manual example mandates me to include the FSF's * copyright, their permission notice, the "GNU General Public License" and * "Conditions for Using Bison" in the resulting derived work, here goes... Copyright (C) 1988, 1989 Free Software Foundation, Inc. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the sections entitled ``GNU General Public License'' and ``Conditions for Using Bison'' are included exactly as in the original, and provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions, except that the sections entitled ``GNU General Public License'', ``Conditions for Using Bison'' and this permission notice may be included in translations approved by the Free Software Foundation instead of in the original English. Conditions for Using Bison ************************** Bison grammars can be used only in programs that are free software. This is in contrast to what happens with the GNU C compiler and the other GNU programming tools. The reason Bison is special is that the output of the Bison utility--the Bison parser file--contains a verbatim copy of a sizable piece of Bison, which is the code for the `yyparse' function. (The actions from your grammar are inserted into this function at one point, but the rest of the function is not changed.) As a result, the Bison parser file is covered by the same copying conditions that cover Bison itself and the rest of the GNU system: any program containing it has to be distributed under the standard GNU copying conditions. Occasionally people who would like to use Bison to develop proprietary programs complain about this. We don't particularly sympathize with their complaints. The purpose of the GNU project is to promote the right to share software and the practice of sharing software; it is a means of changing society. The people who complain are planning to be uncooperative toward the rest of the world; why should they deserve our help in doing so? However, it's possible that a change in these conditions might encourage computer companies to use and distribute the GNU system. If so, then we might decide to change the terms on `yyparse' as a matter of the strategy of promoting the right to share. Such a change would be irrevocable. Since we stand by the copying permissions we have announced, we cannot withdraw them once given. We mustn't make an irrevocable change hastily. We have to wait until there is a complete GNU system and there has been time to learn how this issue affects its reception. GNU GENERAL PUBLIC LICENSE ************************** Version 1, February 1989 Copyright (C) 1989 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble ========= The license agreements of most software companies try to keep users at the mercy of those companies. By contrast, our General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. The General Public License applies to the Free Software Foundation's software and to any other program whose authors commit to using it. You can use it for your programs, too. When we speak of free software, we are referring to freedom, not price. Specifically, the General Public License is designed to make sure that you have the freedom to give away or sell copies of free software, that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of a such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must tell them their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 1. This License Agreement applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The ``Program'', below, refers to any such program or work, and a ``work based on the Program'' means either the Program or any work containing the Program or a portion of it, either verbatim or with modifications. Each licensee is addressed as ``you''. 2. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this General Public License and to the absence of any warranty; and give any other recipients of the Program a copy of this General Public License along with the Program. You may charge a fee for the physical act of transferring a copy. 3. You may modify your copy or copies of the Program or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following: * cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and * cause the whole of any work that you distribute or publish, that in whole or in part contains the Program or any part thereof, either with or without modifications, to be licensed at no charge to all third parties under the terms of this General Public License (except that you may choose to grant warranty protection to some or all third parties, at your option). * If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the simplest and most usual way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this General Public License. * You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. Mere aggregation of another independent work with the Program (or its derivative) on a volume of a storage or distribution medium does not bring the other work under the scope of these terms. 4. You may copy and distribute the Program (or a portion or derivative of it, under Paragraph 2) in object code or executable form under the terms of Paragraphs 1 and 2 above provided that you also do one of the following: * accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Paragraphs 1 and 2 above; or, * accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal charge for the cost of distribution) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or, * accompany it with the information you received as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form alone.) Source code for a work means the preferred form of the work for making modifications to it. For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard libraries that accompany the operating system on which the executable file runs, or for standard header files or definitions files that accompany that operating system. 5. You may not copy, modify, sublicense, distribute or transfer the Program except as expressly provided under this General Public License. Any attempt otherwise to copy, modify, sublicense, distribute or transfer the Program is void, and will automatically terminate your rights to use the Program under this License. However, parties who have received copies, or rights to use copies, from you under this General Public License will not have their licenses terminated so long as such parties remain in full compliance. 6. By copying, distributing or modifying the Program (or any work based on the Program) you indicate your acceptance of this license to do so, and all its terms and conditions. 7. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. 8. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of the license which applies to it and ``any later version'', you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the license, you may choose any version ever published by the Free Software Foundation. 9. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 10. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM ``AS IS'' WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 11. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Programs ======================================================= If you develop a new program, and you want it to be of the greatest possible use to humanity, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the ``copyright'' line and a pointer to where the full notice is found. ONE LINE TO GIVE THE PROGRAM'S NAME AND A BRIEF IDEA OF WHAT IT DOES. Copyright (C) 19YY NAME OF AUTHOR This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19YY NAME OF AUTHOR Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a ``copyright disclaimer'' for the program, if necessary. Here a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (a program to direct compilers to make passes at assemblers) written by James Hacker. SIGNATURE OF TY COON, 1 April 1989 Ty Coon, President of Vice That's all there is to it! * * There! I've done it, and now my conscience is clear! * * As the good license above says, folks, this code is in the public domain, * and is to be distributed under the terms of a permission notice identical * to the GNU license. So, here goes... * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 1, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * Now that that's done, let us on, let us on... * * features : * 1) Addition (+), Subtraction (-), Multiplication (*), Division (/) * 2) Modulus (%), Power (^) * 3) Bitwise logical operators: bitwise AND (&), bitwise inclusive OR (|), * unary one's complement (~) * 4) 20 Math/Trigonometric functions: sin, cos, tan, asin, acos, atan, * sinh, cosh, tanh, exp (exponential), ln (natural log), * log (base 10 log), sqrt (square root), ceil (ceiling), floor, * int/trunc (truncation), abs (absolute value), * degtorad (degrees->radians), radtodeg (radians->degrees). * Two Date functions to convert between calendar dates and julian days: * caltojul (calendar->julian) and jultocal (julian->calendar). * One '?'-for-help command to display a help screen. * 5) Temporary variables (as many as you want, with names as long as you * want) to store intermediate computations. * 6) This is a "portable" calculator in the sense that it's not specific to * any operating system. The yacc output should be compilable by any C * compiler; this program has been tested on Unix, VAX/VMS and PC/MS-DOS, * and has required no changes to compile. * 7) This program uses the simplest of input and output formats, and is in * no way hardware dependent. So, as long as it compiles and executes * without any problems, there are no other requirements for it to work * as advertised. * 8) All numbers are of the C floating-point type "double", which, * according to the VAX C manual, has a range of 0.29*10^-38 to * 1.7*10^38, and has values precise to 16 decimal digits. * 9) Allows any number of expressions on a line, separated by ';' * 10) icalc can now be run either interactively (when it is * invoked without any arguments, in which case the user is * prompted for input) or in a command-line mode (when all * expressions to be computed are passed to icalc via * command-line "argv" arguments, in which case icalc computes * and prints the result of each expression -- exactly as if * it had been entered interactively -- and then exits). * In the latter case, the user is supposed to delimit/ * separate the expressions by ';' * * limitations : * 1) This is a simple calculator that works only in character mode. * No jazzy graphics, no explanatory error messages, nothin' fancy. * 2) This calculator is only double precision and NOT infinite precision. * * references : * The "Bison" manual of the "Free Software Foundation, Inc." * ************************************************************************* */ #include /* For math functions, cos(), sin(), etc. */ /* #include "calc.h" */ /* Contains definition of `symrec' */ /* ^^^^^^^^^^^^^^^^^ instead of having another one-time-only include file, * the file itself has been physically included here */ /*-- calc.h -----------------------------------------------------------------*/ /* Data type for links in the chain of symbols. */ struct symrec { char *name; /* name of symbol */ int type; /* type of symbol: either VAR or FNCT */ union { double var; /* value of a VAR */ double (*fnctptr)(); /* value of a FNCT */ } value; struct symrec *next; /* link field */ }; typedef struct symrec symrec; /* The symbol table: a chain of `struct symrec'. */ extern symrec *sym_table; symrec *putsym (); symrec *getsym (); /*-- end of calc.h ----------------------------------------------------------*/ # line 565 "icalc.y" typedef union { double val; /* For returning numbers. */ symrec *tptr; /* For returning symbol-table pointers */ } YYSTYPE; # define NUM 257 # define VAR 258 # define FNCT 259 # define NEG 260 #define yyclearin yychar = -1 #define yyerrok yyerrflag = 0 extern int yychar; extern short yyerrflag; #ifndef YYMAXDEPTH #define YYMAXDEPTH 150 #endif YYSTYPE yylval, yyval; # define YYERRCODE 256 # line 628 "icalc.y" /*== additional C code ======================================================*/ #include int interactive; char *sargs; double caltojul(); /* calendar date -> julian day */ double jultocal(); /* julian day -> calendar date */ double degtorad(); /* degrees -> radians */ double radtodeg(); /* radians -> degrees */ double trunc(); /* truncate */ main(argc, argv) int argc; char **argv; { char *version = "2.2 of 17-MAR-1992"; /* char *version = "2.1 of 16-MAR-1992"; */ /* char *version = "2.0 of 14-DEC-1991"; */ /* char *version = "1.1 of 16-AUG-1990"; */ /* char *version = "1.0 of 8-JUL-1990"; */ init_table (); if (argc == 1) { interactive = 1; printf("IC> "); } else { interactive = 0; /* * contruct a single string "sargs" comprising all argv strings in order, * with a single space separating each argv element (this is not strictly * necessary since the user is supposed to separate all expressions passed * through argv with ';' already, but it may be useful in the future to * know this). * signal the end of the string with '\n' followed by NULL (the '\n' is * required for the way ICALC works, and the NULL will act as the * equivalent of an EOF in an interactive session). */ sargs = (char *) malloc(strlen(argv[1]) + 2); strcpy(sargs, argv[1]); argc--; argv++; while (--argc) { sargs = (char *) realloc(sargs, strlen(sargs)+1 + strlen(*++argv)+2); strcat(sargs, " "); /* argv separator -- not strictly necessary */ strcat(sargs, *argv); } sargs[strlen(sargs) + 1] = (char) NULL; sargs[strlen(sargs)] = '\n'; } yyparse (); } /*---------------------------------------------------------------------------*/ #define BEL 0x7 yyerror (s) /* Called by yyparse on error */ char *s; { printf ("%c%s\n", BEL, s); /* Beep! */ } /*---------------------------------------------------------------------------*/ struct init { char *fname; double (*fnct)(); }; struct init arith_fncts[] = { "sin", sin, "sinh", sinh, "asin", asin, "cos", cos, "cosh", cosh, "acos", acos, "tan", tan, "tanh", tanh, "atan", atan, "exp", exp, "ln", log, "log", log10, "sqrt", sqrt, "ceil", ceil, "floor", floor, "int", trunc, "trunc", trunc, "abs", fabs, "caltojul", caltojul, "jultocal", jultocal, "degtorad", degtorad, "radtodeg", radtodeg, 0, 0 }; /* The symbol table: a chain of `struct symrec'. */ symrec *sym_table = (symrec *)0; /*---------------------------------------------------------------------------*/ init_table () /* puts arithmetic functions in table. */ { int i; symrec *ptr; for (i = 0; arith_fncts[i].fname != 0; i++) { ptr = putsym (arith_fncts[i].fname, FNCT); ptr->value.fnctptr = arith_fncts[i].fnct; } } /*---------------------------------------------------------------------------*/ symrec * putsym (sym_name,sym_type) char *sym_name; int sym_type; { symrec *ptr; ptr = (symrec *) malloc (sizeof(symrec)); ptr->name = (char *) malloc (strlen(sym_name)+1); strcpy (ptr->name,sym_name); ptr->type = sym_type; ptr->value.var = 0; /* set value to 0 even if fctn. */ ptr->next = (struct symrec *)sym_table; sym_table = ptr; return ptr; } /*---------------------------------------------------------------------------*/ symrec * getsym (sym_name) char *sym_name; { symrec *ptr; for (ptr = sym_table; ptr != (symrec *) 0; ptr = (symrec *)ptr->next) if (strcmp (ptr->name,sym_name) == 0) return ptr; return 0; } /*---------------------------------------------------------------------------*/ #include /* * This lexical analyzer has been hand-coded, but in return for its simplicity, * it has the restriction that only single-character tokens are allowed. * For multiple-character tokens, you might consider replacing the following * 'yylex' with REAL lex-generated source. */ yylex() { int c; /* Ignore whitespace, get first nonwhite character. */ while ((c = my_getchar ()) == ' ' || c == '\t'); if (c == EOF) return 0; /* Char starts a number => parse the number. */ if (c == '.' || isdigit (c)) { if (interactive) { ungetc (c, stdin); scanf ("%lf", &yylval.val); } else { sargs--; sscanf (sargs, "%lf", &yylval.val); /* * move the sargs pointer to the spot where sscanf() left off scanning */ move_sargs(); } return NUM; } /* Char starts an identifier => read the name. */ if (isalpha (c)) { symrec *s; static char *symbuf = 0; static int length = 0; int i; /* Initially make the buffer long enough for a 40-character symbol name. */ if (length == 0) length = 40, symbuf = (char *)malloc (length + 1); i = 0; do { /* If buffer is full, make it bigger. */ if (i == length) { length *= 2; symbuf = (char *)realloc (symbuf, length + 1); } /* Add this character to the buffer. */ symbuf[i++] = isupper(c) ? tolower(c) : c; /* * "tolower" makes * variable names * case-INsensitive * by converting them * ALL to lower-case. */ /* Get another character. */ c = my_getchar (); } while (c != EOF && isalnum (c)); if (interactive) ungetc (c, stdin); else sargs--; symbuf[i] = '\0'; s = getsym (symbuf); if (s == 0) s = putsym (symbuf, VAR); yylval.tptr = s; return s->type; } /* Any other character is a token by itself. */ return c; } /*---------------------------------------------------------------------------*/ my_getchar() { int c; if (interactive) return getchar(); else { c = *sargs; if (c) { sargs++; return c; } else return EOF; } } /*---------------------------------------------------------------------------*/ move_sargs() { /* * At the point when this routine is called, the sargs pointer is * sitting at the beginning of a floating-point number (we also know * that the character at the head of this number is either a '.' or a * digit. * This routine should move the sargs pointer to the spot/point/char * on the string where the preceding sscanf() call should have stopped * scanning. */ /* * Floating-point number format: * [ + | - ] nnn [ . [ ddd ] ] [ { E | e } [ + | - ] nn ] */ /* * I'm starting with the assumption that *sargs is either a digit or * the character '.' */ while (isdigit(*sargs)) sargs++; switch (*sargs) { case '.': switch (*++sargs) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': while (isdigit(*sargs)) sargs++; switch (*sargs) { case 'E': case 'e': break; default: return; } case 'E': case 'e': break; default: return; } case 'E': case 'e': break; default: return; } /* If control has dropped to this point, *sargs is 'E' or 'e' */ switch (*++sargs) { case '+': case '-': switch (*++sargs) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': break; default: return; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': while (isdigit(*sargs)) sargs++; return; default: return; } } /*---------------------------------------------------------------------------*/ help() { /* display a help screen of all supported commands and functions */ printf("Arithmetic Operators: Trig Functions (take radian arguments):\n"); printf("+ Addition (plus) sin sine\n"); printf("- Subtraction (minus) sinh hyperbolic sine\n"); printf("* Multiplication (times) asin arc sine\n"); printf("/ Division (divided by) cos cosine\n"); printf("%% Modulus (remainder) cosh hyperbolic cosine\n"); printf("^ Power (raised to) acos arc cosine\n"); printf("Bitwise Logical Operators: tan tangent\n"); printf("& bitwise AND tanh hyperbolic tangent\n"); printf("| bitwise inclusive OR atan arc tangent\n"); printf("~ unary one's complement Math Functions:\n"); printf("Date Functions: exp exponentiation\n"); printf("caltojul calendar to julian date ln natural log\n"); printf(" Usage: caltojul(yyyy, mm, dd) log base 10 log\n"); printf(" Returns: #days elapsed since October 15, 1582 sqrt square root\n"); printf("jultocal julian to calendar date ceil ceiling\n"); printf(" Usage: jultocal(julian_date) floor floor\n"); printf(" Returns: date in yyyymmdd format int,trunc truncation\n"); printf(" Eg: caltojul(1989,12,31) <=> jultocal(148732) abs absolute value\n"); printf("Help Functions: degtorad degrees -> radians\n"); printf("? Help (print this screen) radtodeg radians -> degrees\n"); } /*---------------------------------------------------------------------------*/ /* * function to convert calender dates to julian dates. * (originally adapted from ACM, Oct '68, page 657). * This function assumes dayzero=yrmoda/julian/spss/sir => * assumes idayzer=2299160 (Oct 15, 1582). */ double caltojul(yyyy, mm, dd) double yyyy, mm, dd; { long idayzer, i, j, k, ci2j; /* DON'T use "unsigned"! * ci2j calculation will blow up */ idayzer = 2299160; i = yyyy; j = mm; k = dd; ci2j = k-32075+1461*(i+4800+(j-14)/12)/4+367*(j-2-(j-14)/12*12) /12-3*((i+4900+(j-14)/12)/100)/4 - idayzer; return( (double) ci2j ); } /*---------------------------------------------------------------------------*/ #ifndef abs #define abs(x) ((x) < 0 ? (-(x)) : (x)) /* absolute val */ #endif /*---------------------------------------------------------------------------*/ double jultocal(jd) double jd; { /* * function to convert julian days to calendar dates * (converse of caltojul) * idayzer -- julian day-one offset * i,j,k,l,n -- integer ease transcription of algorithm * dd,mm,yyyy -- day,month,year digits respectively * jd -- incoming integer julian date * jdz -- local integer julian date has dayzero addedon * converts julian date 'jd' with specifiable first day to * gregorian date with output format 'yyyymmdd'. * uses acm algorithm by hf fliegel, and tc van flandern acm vol 11, * #10,oct68. * dayone is a string indicating first julian day of calendar. * algorithm uses prehistoric day-one, so 2299161 is oct 15, 1582 * used by spss/sir for base date */ long idayzer, jdz, i, j, k, l, n, yyyy, mm, dd; idayzer = 2299160; jdz = abs((long) jd) + idayzer; /* i is julian year, j is month, k is day */ l = jdz + 68569; n = 4*l/146097; l = l - (146097*n + 3)/4; i = 4000*(l+1)/1461001; l = l - 1461*i/4 + 31; j = 80*l/2447; k = l - 2447*j/80; l = j/11; j = j + 2 - 12*l; i = 100*(n - 49) + i + l; yyyy = i; mm = j; dd = k; return( (double) (yyyy * 10000 + mm * 100 + dd) ); } /*---------------------------------------------------------------------------*/ #define PI 3.14159265358979323846 /*---------------------------------------------------------------------------*/ double degtorad(x) double x; { return( x * (PI / 180.0) ); /* deg->rad */ } /*---------------------------------------------------------------------------*/ double radtodeg(x) double x; { return( x * (180.0 / PI) ); /* rad->deg */ } /*---------------------------------------------------------------------------*/ double trunc(x) double x; { return( (long) x ); /* truncate */ } /*== end of additional C code ===============================================*/ short yyexca[] ={ -1, 1, 0, -1, -2, 0, }; # define YYNPROD 26 # define YYLAST 250 short yyact[]={ 3, 13, 25, 22, 23, 26, 11, 46, 20, 18, 47, 19, 27, 21, 22, 23, 14, 17, 43, 20, 18, 44, 19, 16, 21, 4, 2, 1, 22, 23, 13, 0, 49, 20, 18, 11, 19, 0, 21, 22, 23, 0, 0, 42, 20, 18, 0, 19, 0, 21, 0, 22, 23, 6, 0, 0, 20, 18, 0, 19, 25, 21, 22, 23, 22, 15, 0, 20, 18, 20, 19, 25, 21, 22, 21, 0, 0, 0, 20, 18, 0, 19, 0, 21, 0, 25, 0, 12, 0, 0, 24, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 25, 0, 0, 0, 0, 0, 0, 24, 12, 0, 0, 25, 7, 25, 0, 0, 0, 0, 24, 0, 0, 0, 25, 0, 28, 29, 30, 0, 31, 0, 24, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 9, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 8, 9, 10 }; short yypact[]={ -1000, -10,-1000,-1000, 6, 13, 7, 14,-1000, -56, -28, -39, -39, -39,-1000, -39,-1000,-1000, -39, -39, -39, -39, -39, -39, -39, -39, -39, -39, -92, -92, 2, 14, 27, 27, -92, -92, -92, 36, 25, -92, 14, -23,-1000,-1000, -39, -34,-1000, -39, -9,-1000 }; short yypgo[]={ 0, 120, 27, 26, 25 }; short yyr1[]={ 0, 2, 2, 3, 3, 3, 3, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; short yyr2[]={ 0, 0, 2, 1, 2, 2, 2, 1, 3, 1, 1, 3, 4, 6, 8, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 3 }; short yychk[]={ -1000, -2, -3, 10, -4, 256, 63, -1, 257, 258, 259, 45, 126, 40, 10, 59, 10, 10, 43, 45, 42, 47, 37, 38, 124, 94, 61, 40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 41, 41, 44, -1, 41, 44, -1, 41 }; short yydef[]={ 1, -2, 2, 3, 0, 0, 0, 7, 9, 10, 0, 0, 0, 0, 4, 0, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 23, 0, 8, 15, 16, 17, 18, 19, 20, 21, 24, 11, 0, 25, 12, 0, 0, 13, 0, 0, 14 }; #ifndef lint static char yaccpar_sccsid[] = "@(#)yaccpar 4.1 (Berkeley) 2/11/83"; #endif not lint # # define YYFLAG -1000 # define YYERROR goto yyerrlab # define YYACCEPT return(0) # define YYABORT return(1) /* parser for yacc output */ #ifdef YYDEBUG int yydebug = 0; /* 1 for debugging */ #endif YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */ int yychar = -1; /* current input token number */ int yynerrs = 0; /* number of errors */ short yyerrflag = 0; /* error recovery flag */ yyparse() { short yys[YYMAXDEPTH]; short yyj, yym; register YYSTYPE *yypvt; register short yystate, *yyps, yyn; register YYSTYPE *yypv; register short *yyxi; yystate = 0; yychar = -1; yynerrs = 0; yyerrflag = 0; yyps= &yys[-1]; yypv= &yyv[-1]; yystack: /* put a state and value onto the stack */ #ifdef YYDEBUG if( yydebug ) printf( "state %d, char 0%o\n", yystate, yychar ); #endif if( ++yyps> &yys[YYMAXDEPTH] ) { yyerror( "yacc stack overflow" ); return(1); } *yyps = yystate; ++yypv; *yypv = yyval; yynewstate: yyn = yypact[yystate]; if( yyn<= YYFLAG ) goto yydefault; /* simple state */ if( yychar<0 ) if( (yychar=yylex())<0 ) yychar=0; if( (yyn += yychar)<0 || yyn >= YYLAST ) goto yydefault; if( yychk[ yyn=yyact[ yyn ] ] == yychar ){ /* valid shift */ yychar = -1; yyval = yylval; yystate = yyn; if( yyerrflag > 0 ) --yyerrflag; goto yystack; } yydefault: /* default state action */ if( (yyn=yydef[yystate]) == -2 ) { if( yychar<0 ) if( (yychar=yylex())<0 ) yychar = 0; /* look through exception table */ for( yyxi=yyexca; (*yyxi!= (-1)) || (yyxi[1]!=yystate) ; yyxi += 2 ) ; /* VOID */ while( *(yyxi+=2) >= 0 ){ if( *yyxi == yychar ) break; } if( (yyn = yyxi[1]) < 0 ) return(0); /* accept */ } if( yyn == 0 ){ /* error */ /* error ... attempt to resume parsing */ switch( yyerrflag ){ case 0: /* brand new error */ yyerror( "syntax error" ); yyerrlab: ++yynerrs; case 1: case 2: /* incompletely recovered error ... try again */ yyerrflag = 3; /* find a state where "error" is a legal shift action */ while ( yyps >= yys ) { yyn = yypact[*yyps] + YYERRCODE; if( yyn>= 0 && yyn < YYLAST && yychk[yyact[yyn]] == YYERRCODE ){ yystate = yyact[yyn]; /* simulate a shift of "error" */ goto yystack; } yyn = yypact[*yyps]; /* the current yyps has no shift onn "error", pop stack */ #ifdef YYDEBUG if( yydebug ) printf( "error recovery pops state %d, uncovers %d\n", *yyps, yyps[-1] ); #endif --yyps; --yypv; } /* there is no state on the stack with an error shift ... abort */ yyabort: return(1); case 3: /* no shift yet; clobber input char */ #ifdef YYDEBUG if( yydebug ) printf( "error recovery discards char %d\n", yychar ); #endif if( yychar == 0 ) goto yyabort; /* don't discard EOF, quit */ yychar = -1; goto yynewstate; /* try again in the same state */ } } /* reduction by production yyn */ #ifdef YYDEBUG if( yydebug ) printf("reduce %d\n",yyn); #endif yyps -= yyr2[yyn]; yypvt = yypv; yypv -= yyr2[yyn]; yyval = yypv[1]; yym=yyn; /* consult goto table to find next state */ yyn = yyr1[yyn]; yyj = yypgo[yyn] + *yyps + 1; if( yyj>=YYLAST || yychk[ yystate = yyact[yyj] ] != -yyn ) yystate = yyact[yypgo[yyn]]; switch(yym){ case 3: # line 592 "icalc.y" { if (interactive) printf("IC> "); } break; case 4: # line 593 "icalc.y" { if (interactive) printf("IC> "); } break; case 5: # line 594 "icalc.y" { yyerrok; if (interactive) printf("IC> "); } break; case 6: # line 596 "icalc.y" { help(); /* display a help screen */ if (interactive) printf("IC> "); } break; case 7: # line 601 "icalc.y" { printf(" %.10g\n", yypvt[-0].val); } break; case 8: # line 602 "icalc.y" { printf(" %.10g\n", yypvt[-0].val); } break; case 9: # line 605 "icalc.y" { yyval.val = yypvt[-0].val; } break; case 10: # line 606 "icalc.y" { yyval.val = yypvt[-0].tptr->value.var; } break; case 11: # line 607 "icalc.y" { yyval.val = yypvt[-0].val; yypvt[-2].tptr->value.var = yypvt[-0].val; printf(" %s = %.10g\n", yypvt[-2].tptr->name, yypvt[-0].val); } break; case 12: # line 610 "icalc.y" { yyval.val = (*(yypvt[-3].tptr->value.fnctptr))(yypvt[-1].val); } break; case 13: # line 611 "icalc.y" { yyval.val = (*(yypvt[-5].tptr->value.fnctptr))(yypvt[-3].val, yypvt[-1].val); } break; case 14: # line 612 "icalc.y" { yyval.val = (*(yypvt[-7].tptr->value.fnctptr))(yypvt[-5].val, yypvt[-3].val, yypvt[-1].val); } break; case 15: # line 613 "icalc.y" { yyval.val = yypvt[-2].val + yypvt[-0].val; } break; case 16: # line 614 "icalc.y" { yyval.val = yypvt[-2].val - yypvt[-0].val; } break; case 17: # line 615 "icalc.y" { yyval.val = yypvt[-2].val * yypvt[-0].val; } break; case 18: # line 616 "icalc.y" { yyval.val = yypvt[-2].val / yypvt[-0].val; } break; case 19: # line 617 "icalc.y" { yyval.val = fmod(yypvt[-2].val, yypvt[-0].val); } break; case 20: # line 618 "icalc.y" { yyval.val = ((int) yypvt[-2].val) & ((int) yypvt[-0].val); } break; case 21: # line 619 "icalc.y" { yyval.val = ((int) yypvt[-2].val) | ((int) yypvt[-0].val); } break; case 22: # line 620 "icalc.y" { yyval.val = -yypvt[-0].val; } break; case 23: # line 621 "icalc.y" { yyval.val = ~((int) yypvt[-0].val); } break; case 24: # line 622 "icalc.y" { yyval.val = pow (yypvt[-2].val, yypvt[-0].val); } break; case 25: # line 623 "icalc.y" { yyval.val = yypvt[-1].val; } break; } goto yystack; /* stack new state and value */ } /*== End of ICALC.C == End of ICALC.C == End of ICALC.C == End of ICALC.C ==*/