├── DEVDOCS.md ├── EnderCalc.exe ├── EnderCalc.gif ├── LICENSE.txt ├── Makefile ├── README.md ├── THIRD-PARTY.txt ├── build.cmd ├── dist ├── EnderCalc.msi ├── EnderCalc.wxs ├── appdir │ ├── EnderCalc.150x150.png │ ├── EnderCalc.70x70.png │ ├── EnderCalc.exe │ ├── EnderCalc.visualelementsmanifest.xml │ ├── LICENSE.txt │ ├── THIRD-PARTY.txt │ └── reference.pdf ├── build.cmd └── license.rtf ├── distlinux ├── build.sh ├── endercalc_1.3_amd64.deb └── staging │ ├── DEBIAN │ └── control │ ├── opt │ └── endercalc │ │ ├── endercalc │ │ └── reference.pdf │ └── usr │ ├── bin │ └── endercalc │ └── share │ ├── applications │ └── endercalc.desktop │ ├── doc │ └── endercalc │ │ ├── README │ │ ├── THIRD-PARTY │ │ ├── changelog.gz │ │ └── copyright │ ├── icons │ └── hicolor │ │ ├── 16x16 │ │ └── apps │ │ │ └── endercalc.png │ │ ├── 24x24 │ │ └── apps │ │ │ └── endercalc.png │ │ ├── 256x256 │ │ └── apps │ │ │ └── endercalc.png │ │ ├── 32x32 │ │ └── apps │ │ │ └── endercalc.png │ │ ├── 48x48 │ │ └── apps │ │ │ └── endercalc.png │ │ └── 64x64 │ │ └── apps │ │ └── endercalc.png │ ├── man │ └── man1 │ │ └── endercalc.1.gz │ └── pixmaps │ └── endercalc.png ├── include ├── calc.h ├── command.h ├── engine.h ├── eval.h ├── expr.h ├── libbf.h ├── mem.h ├── minGlue.h ├── minini.h ├── parse.h ├── readline.h ├── stats.h ├── symbols.h └── vector.h ├── lib ├── libbf │ ├── LICENSE.txt │ ├── Makefile │ ├── cutils.c │ ├── cutils.h │ ├── libbf.c │ └── libbf.h ├── libedit │ ├── LICENSE.txt │ ├── Makefile │ ├── editline.c │ ├── editline │ │ ├── readline.h │ │ └── wineditline.h │ ├── el_globals.h │ ├── fn_complete.c │ ├── histedit.h │ └── history.c └── libminini │ ├── LICENSE.txt │ ├── Makefile │ ├── minGlue.h │ ├── minIni.c │ ├── minIni.h │ └── minIni.pdf ├── reference.odt ├── reference.pdf ├── rsrc ├── EnderCalc.ico ├── icon.rc └── version.rc └── src ├── calc.c ├── command.c ├── engine.c ├── engine ├── engine_basic.c ├── engine_hyperbolic.c ├── engine_stats.c └── engine_trig.c ├── eval.c ├── expr.c ├── mem.c ├── parse.c ├── parse_ezpass.c ├── parse_match_brackets.c ├── parse_tokenize.c ├── stats.c ├── symbols.c └── vector.c /DEVDOCS.md: -------------------------------------------------------------------------------- 1 | # EnderCalc Dev Docs 2 | 3 | A quick look at what goes in to making a calculator. Organized as a tour through the code, with subsequent modules building on previous ones. 4 | 5 | ## Vector 6 | 7 | (File [vector.c](src/vector.c)) 8 | 9 | EnderCalc manipulates expressions as a *vector* of *tokens*⁠—worry about tokens later, let's figure out the vector part. A vector is a contiguously allocated list of elements, the trick being you can add and remove elements without worrying about memory allocation. Most languages ship with one of these; in the prototype design I used a Python `list`. C doesn't, of course, so I made one. I'm very happy with the code quality of `vector.c` and might re-use it in other projects. 10 | 11 | ## Expressions 12 | 13 | (File [expr.c](src/expr.c)) 14 | 15 | - An *expression* is a vector of *tokens*. 16 | - A *token* is a [tagged pointer](https://en.wikipedia.org/wiki/Tagged_pointer), the tag is the type and the rest is a pointer type or a *symbol*. 17 | - My particular implementation of tagged pointers is for amd64 and required no allocator changes. An alternate implementation may need to be used for ports. 18 | - *Symbols* are constants, `#define`d from the void and imbued with meaning. 19 | 20 | Let's double click. The types are: 21 | 22 | - `TOKEN_EXPR` - the token is a pointer to a subexpression. Used for brackets: `3 * (5 + 2).` 23 | - `TOKEN_STR` - the token is a pointer to a string slice. 24 | - `TOKEN_NUM` - the token is a pointer to a big float number (a `bf_t`, if you really care). 25 | - `TOKEN_SYM` - last but certainly not least, the token is a symbol (**not** a pointer at all). `ADD`, `ANS`, `ATANH` are all symbols. 26 | 27 | I started with routines for printing and freeing expressions. Debuggability and memory management are very important considerations in C99. 28 | 29 | ## Parser 30 | 31 | (File [parse.c](src/parse.c), parse_*.c) 32 | 33 | The parser's job is to turn a string, like `"sin pi (34 ) + - 5(2*2)"`, into an expression, like `SIN 3.14 MUL (34) ADD NEG 5 MUL (2 MUL 2)`. The second is, obviously (at least if you're a programmer), much easier to evaluate than the first. The parser is written as a sequence of passes that operate on expressions and emit expressions (except the first one, which operates on a string). 34 | 35 | Let's look over the passes. I'll use `((3^4)(e^-3))/4!` as an example. 36 | 37 | 1. `match_brackets`: convert a string into a expression composed entirely of subexpressions and string slices. This can fail if there are too many opening or closing braces. It's hard to demonstrate visually, but the output is `((3^4) (e^-3)) /4!`. 38 | 2. `tokenize`: recursively split any string slice token into a series of number and symbol tokens. This can fail if the user enters input not composed of valid symbols. This step ignores whitespace. Output: `((3 POW 4)) (E POW SUB 3)) DIV 4 FAC`. 39 | 3. `constants`: recursively replace constant symbols with number constants. Output: `((3 POW 4) (2.7182 POW SUB 3)) DIV 4 FAC`. (the astute among you have noted that I could've used `exp-3` instead of `e^-3`. this is, of course, correct—but not useful for the demo) 40 | 4. `implicit_multply`: recursively add implicit multiplication operators; for example `4(3)` should be `4 MUL (3)`. The rule used here is "replace every subexpression preceded by a subexpression, number, postfix operator symbol, or non-operator symbol with a `MUL` symbol followed by that subexpression". Bit of a mouthful. Output: `((3 POW 4) MUL (2.7182 POW SUB 3)) DIV 4 FAC`. 41 | 5. `unary_neg`: recursively replace `SUB` with `NEG` in situations where `SUB` isn't valid. Basically, `4 + -3` should be 1 and not a syntax error—we need to disambiguate between `-` as `SUB` and `-` as `NEG`. The rule used here is "replace `SUB` with `NEG` when it is preceded by nothing or a operator symbol that is not unary postfix". Output: `((3 POW 4) MUL (2.7182 POW NEG 3)) DIV 4 FAC`. 42 | 43 | ## Evaluator 44 | 45 | The evaluator accepts a parsed expression and tried to evaluate it to a single numerical answer. There are a myriad of ways this can go wrong—for example, `ADD 2` is not an evaluable expression (missing argument). The design is fairly simple, but first, a quick tangent: 46 | 47 | ### Argument Resolver 48 | 49 | `resolve_arg` attempts to coerce a token into a number than can be used as input to an operator. 50 | 51 | 1. If the token is of type `TOKEN_NUM`, return it. 52 | 2. If the token is of type `TOKEN_EXPR`, evaluate it and return the result. 53 | 3. If the token if of type `TOKEN_SYM`: 54 | 1. If the token is `SYM_ANS`, return the saved last answer. 55 | 2. If the token is `SYM_RCLx`, return a value from memory. 56 | 3. Otherwise, error. 57 | 58 | Okay, now that we've got that out of the way, onwards to the evaluator proper. The evaluator first attempts to reduce the expression to a single value. It does so using the following algorithm: 59 | 60 | - Find the next operator to execute, using precedence and associativity rules. The operator with the lowest precedence wins. 61 | - Collect the arguments for the operator using `resolve_arg`. 62 | - Perform the operation proper using a function pointer. 63 | - Return the results to the expression. 64 | 65 | (for example, `3 ADD 2 MUL 4` will be reduced to `3 ADD 8` then `11`) 66 | 67 | Once a single value is left, it is resolved and returned. 68 | 69 | -------------------------------------------------------------------------------- /EnderCalc.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startrekdude/EnderCalc/a6fbbd8c85ddeb47c555183d9b09752aecbf3f83/EnderCalc.exe -------------------------------------------------------------------------------- /EnderCalc.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startrekdude/EnderCalc/a6fbbd8c85ddeb47c555183d9b09752aecbf3f83/EnderCalc.gif -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | DEBUG= 2 | DEBUG=-D NDEBUG 3 | 4 | CC=gcc 5 | CFLAGS=-pie -std=c99 -flto -fno-asynchronous-unwind-tables -O2 -I include $(DEBUG) 6 | LDFLAGS=-pie -Wl,--gc-sections -Wl,-s -std=c99 -flto -O2 7 | 8 | ifeq ($(OS),Windows_NT) 9 | CFLAGS+=-D HELP_USE_WIN32 10 | LDFLAGS+=-Wl,-emainCRTStartup -Wl,--dynamicbase 11 | LDLIBS=-lshlwapi 12 | BINARY_NAME=EnderCalc.exe 13 | DIR_GUARD=@if not exist build mkdir build 14 | PLATFORM_RMDIR=rd /q /s 15 | PLATFORM_RM=del 16 | else 17 | LDLIBS=-ledit 18 | BINARY_NAME=endercalc 19 | DIR_GUARD=@mkdir -p build 20 | PLATFORM_RMDIR=rm -rf 21 | PLATFORM_RM=rm -f 22 | endif 23 | 24 | .DEFAULT_GOAL := $(BINARY_NAME) 25 | 26 | I_VECTOR_H=include/vector.h 27 | I_SYMBOLS_H=include/symbols.h 28 | I_LIBBF_H=include/libbf.h 29 | I_CALC_H=include/calc.h 30 | I_COMMAND_H=include/command.h 31 | I_MINGLUE_H=include/minGlue.h 32 | I_STATS_H=include/stats.h 33 | I_READLINE_H=include/readline.h 34 | I_MININI_H=include/minini.h $(I_MINGLUE_H) 35 | I_EXPR_H=include/expr.h $(I_VECTOR_H) 36 | I_ENGINE_H=include/engine.h $(I_LIBBF_H) 37 | I_PARSE_H=include/parse.h $(I_VECTOR_H) 38 | I_MEM_H=include/mem.h $(I_LIBBF_H) 39 | I_EVAL_H=include/eval.h $(I_LIBBF_H) $(I_VECTOR_H) 40 | 41 | ALL_OBJECTS=build/vector.o build/expr.o build/symbols.o build/parse.o build/parse_match_brackets.o\ 42 | build/parse_tokenize.o build/parse_ezpass.o build/mem.o build/eval.o build/engine.o build/engine_basic.o\ 43 | build/engine_trig.o build/engine_hyperbolic.o build/engine_stats.o build/command.o build/stats.o build/calc.o 44 | 45 | ifeq ($(OS),Windows_NT) 46 | ALL_RESOURCES=build/version.o build/icon.o 47 | endif 48 | 49 | ifeq ($(OS),Windows_NT) 50 | ALL_LIBRARIES=lib\libbf\libbf.a lib\libminini\libminini.a lib\libedit\libedit.a 51 | else 52 | ALL_LIBRARIES=lib/libbf/libbf.a lib/libminini/libminini.a 53 | endif 54 | 55 | build/vector.o : src/vector.c $(I_VECTOR_H) 56 | build/expr.o : src/expr.c $(I_EXPR_H) $(I_ENGINE_H) $(I_SYMBOLS_H) $(I_LIBBF_H) 57 | build/symbols.o : src/symbols.c $(I_SYMBOLS_H) $(I_ENGINE_H) 58 | build/parse.o : src/parse.c $(I_PARSE_H) $(I_EXPR_H) 59 | build/parse_match_brackets.o : src/parse_match_brackets.c $(I_PARSE_H) $(I_EXPR_H) 60 | build/parse_tokenize.o : src/parse_tokenize.c $(I_PARSE_H) $(I_ENGINE_H) $(I_EXPR_H) $(I_SYMBOLS_H) $(I_LIBBF_H) 61 | build/parse_ezpass.o : src/parse_ezpass.c $(I_PARSE_H) $(I_ENGINE_H) $(I_EXPR_H) $(I_SYMBOLS_H) 62 | build/mem.o : src/mem.c $(I_MEM_H) $(I_CALC_H) $(I_COMMAND_H) $(I_ENGINE_H) $(I_EVAL_H) $(I_MININI_H) 63 | build/eval.o : src/eval.c $(I_EVAL_H) $(I_ENGINE_H) $(I_EXPR_H) $(I_MEM_H) $(I_SYMBOLS_H) 64 | build/engine.o : src/engine.c $(I_ENGINE_H) $(I_EVAL_H) 65 | build/engine_basic.o : src/engine/engine_basic.c $(I_ENGINE_H) $(I_EVAL_H) 66 | build/engine_trig.o : src/engine/engine_trig.c $(I_ENGINE_H) $(I_EVAL_H) 67 | build/engine_hyperbolic.o : src/engine/engine_hyperbolic.c $(I_ENGINE_H) $(I_EVAL_H) 68 | build/engine_stats.o : src/engine/engine_stats.c $(I_ENGINE_H) $(I_EVAL_H) 69 | build/command.o : src/command.c $(I_COMMAND_H) $(I_CALC_H) $(I_ENGINE_H) $(I_EVAL_H) $(I_MEM_H) $(I_PARSE_H)\ 70 | $(I_STATS_H) $(I_MININI_H) 71 | build/stats.o : src/stats.c $(I_STATS_H) $(I_CALC_H) $(I_ENGINE_H) $(I_VECTOR_H) $(I_LIBBF_H) $(I_READLINE_H) 72 | build/calc.o : src/calc.c $(I_CALC_H) $(I_COMMAND_H) $(I_ENGINE_H) $(I_EVAL_H) $(I_EXPR_H) $(I_MEM_H)\ 73 | $(I_PARSE_H) $(I_READLINE_H) 74 | 75 | $(ALL_OBJECTS) : 76 | $(DIR_GUARD) 77 | $(CC) $(CFLAGS) -o $@ -c $< 78 | 79 | build/version.o : rsrc/version.rc 80 | build/icon.o : rsrc/icon.rc rsrc/EnderCalc.ico 81 | 82 | $(ALL_RESOURCES) : 83 | $(DIR_GUARD) 84 | windres $< $@ 85 | 86 | $(ALL_LIBRARIES) : 87 | $(MAKE) -C $(@D) 88 | $(MAKE) -C $(@D) clean 89 | 90 | $(BINARY_NAME) : $(ALL_OBJECTS) $(ALL_RESOURCES) $(ALL_LIBRARIES) 91 | $(CC) $(LDFLAGS) -o $@ $(ALL_OBJECTS) $(ALL_RESOURCES) $(ALL_LIBRARIES) $(LDLIBS) 92 | 93 | .PHONY : clean 94 | clean : 95 | $(PLATFORM_RMDIR) build 96 | $(PLATFORM_RM) $(ALL_LIBRARIES) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EnderCalc 2 | 3 | ### A powerful, text-driven scientific calculator 4 | 5 | *'Cause sometimes the Windows Calculator just isn't good enough* 6 | 7 | ![](EnderCalc.gif) 8 | 9 | EnderCalc is a fast, powerful, arbitrary precision, text-driven scientific calculator written in (almost) pure C99. It supports basic arithmetic, logarithms and roots, trigonometric functions, hyperbolic functions, statistics functions, and much more (a full reference is available in [reference.pdf](reference.pdf)). 10 | 11 | ## Download 12 | 13 | Please see the releases section for x64 Windows binaries or DEB packages. 14 | 15 | To build on Linux: 16 | 17 | ```bash 18 | make 19 | ``` 20 | 21 | (has `libedit-dev` as a dependency, run `sudo apt install libedit-dev` first) 22 | 23 | ## Documentation 24 | 25 | Please see [reference.pdf](reference.pdf), shipped with EnderCalc, for user-facing documentation. 26 | 27 | For a whirlwind introduction to how EnderCalc works internally, have a look at [DEVDOCS.md](DEVDOCS.md). 28 | 29 | ## License 30 | 31 | [GNU General Public License, version 3](https://choosealicense.com/licenses/gpl-3.0/) 32 | 33 | ## Open Source Libraries 34 | 35 | - [libbf](https://bellard.org/libbf/) 20200119 by [Fabrice Bellard](https://bellard.org) 36 | - [WinEditLine](http://mingweditline.sourceforge.net/) 2.206 by Paolo Tosco 37 | - [minIni](https://www.compuphase.com/minini.htm) 1.2b by Thiadmer Riemersma -------------------------------------------------------------------------------- /THIRD-PARTY.txt: -------------------------------------------------------------------------------- 1 | EnderCalc uses the following open-source libraries: 2 | - libbf 20200119 by Fabrice Bellard, licensed under the MIT License 3 | - WinEditLine 2.206 by Paolo Tosco, licensed under the BSD 3-clause License 4 | - minIni 1.2b by Thiadmer Riemersma, licensed under the Apache License w/ Linking Exception 5 | 6 | License full texts follow: 7 | 8 | libbf 9 | Copyright 2020 Fabrice Bellard 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining 12 | a copy of this software and associated documentation files (the 13 | "Software"), to deal in the Software without restriction, including 14 | without limitation the rights to use, copy, modify, merge, publish, 15 | distribute, sublicense, and/or sell copies of the Software, and to 16 | permit persons to whom the Software is furnished to do so, subject to 17 | the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be 20 | included in all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 25 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 26 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 27 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 28 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | WinEditLine 31 | Copyright (c) 2010-2016, Paolo Tosco 32 | All rights reserved. 33 | 34 | Redistribution and use in source and binary forms, with or without 35 | modification, are permitted provided that the following conditions are met: 36 | 37 | 1. Redistributions of source code must retain the above copyright notice, this 38 | list of conditions and the following disclaimer. 39 | 40 | 2. Redistributions in binary form must reproduce the above copyright notice, 41 | this list of conditions and the following disclaimer in the documentation 42 | and/or other materials provided with the distribution. 43 | 44 | 3. Neither the name of MinGWEditLine nor the names of its 45 | contributors may be used to endorse or promote products derived from 46 | this software without specific prior written permission. 47 | 48 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 49 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 51 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 52 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 54 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 55 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 56 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 57 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 58 | 59 | libminIni 60 | 61 | Apache License 62 | Version 2.0, January 2004 63 | http://www.apache.org/licenses/ 64 | 65 | 66 | EXCEPTION TO THE APACHE 2.0 LICENSE 67 | 68 | As a special exception to the Apache License 2.0 (and referring to the 69 | definitions in Section 1 of this license), you may link, statically or 70 | dynamically, the "Work" to other modules to produce an executable file 71 | containing portions of the "Work", and distribute that executable file 72 | in "Object" form under the terms of your choice, without any of the 73 | additional requirements listed in Section 4 of the Apache License 2.0. 74 | This exception applies only to redistributions in "Object" form (not 75 | "Source" form) and only if no modifications have been made to the "Work". 76 | 77 | 78 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 79 | 80 | 1. Definitions. 81 | 82 | "License" shall mean the terms and conditions for use, reproduction, 83 | and distribution as defined by Sections 1 through 9 of this document. 84 | 85 | "Licensor" shall mean the copyright owner or entity authorized by 86 | the copyright owner that is granting the License. 87 | 88 | "Legal Entity" shall mean the union of the acting entity and all 89 | other entities that control, are controlled by, or are under common 90 | control with that entity. For the purposes of this definition, 91 | "control" means (i) the power, direct or indirect, to cause the 92 | direction or management of such entity, whether by contract or 93 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 94 | outstanding shares, or (iii) beneficial ownership of such entity. 95 | 96 | "You" (or "Your") shall mean an individual or Legal Entity 97 | exercising permissions granted by this License. 98 | 99 | "Source" form shall mean the preferred form for making modifications, 100 | including but not limited to software source code, documentation 101 | source, and configuration files. 102 | 103 | "Object" form shall mean any form resulting from mechanical 104 | transformation or translation of a Source form, including but 105 | not limited to compiled object code, generated documentation, 106 | and conversions to other media types. 107 | 108 | "Work" shall mean the work of authorship, whether in Source or 109 | Object form, made available under the License, as indicated by a 110 | copyright notice that is included in or attached to the work 111 | (an example is provided in the Appendix below). 112 | 113 | "Derivative Works" shall mean any work, whether in Source or Object 114 | form, that is based on (or derived from) the Work and for which the 115 | editorial revisions, annotations, elaborations, or other modifications 116 | represent, as a whole, an original work of authorship. For the purposes 117 | of this License, Derivative Works shall not include works that remain 118 | separable from, or merely link (or bind by name) to the interfaces of, 119 | the Work and Derivative Works thereof. 120 | 121 | "Contribution" shall mean any work of authorship, including 122 | the original version of the Work and any modifications or additions 123 | to that Work or Derivative Works thereof, that is intentionally 124 | submitted to Licensor for inclusion in the Work by the copyright owner 125 | or by an individual or Legal Entity authorized to submit on behalf of 126 | the copyright owner. For the purposes of this definition, "submitted" 127 | means any form of electronic, verbal, or written communication sent 128 | to the Licensor or its representatives, including but not limited to 129 | communication on electronic mailing lists, source code control systems, 130 | and issue tracking systems that are managed by, or on behalf of, the 131 | Licensor for the purpose of discussing and improving the Work, but 132 | excluding communication that is conspicuously marked or otherwise 133 | designated in writing by the copyright owner as "Not a Contribution." 134 | 135 | "Contributor" shall mean Licensor and any individual or Legal Entity 136 | on behalf of whom a Contribution has been received by Licensor and 137 | subsequently incorporated within the Work. 138 | 139 | 2. Grant of Copyright License. Subject to the terms and conditions of 140 | this License, each Contributor hereby grants to You a perpetual, 141 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 142 | copyright license to reproduce, prepare Derivative Works of, 143 | publicly display, publicly perform, sublicense, and distribute the 144 | Work and such Derivative Works in Source or Object form. 145 | 146 | 3. Grant of Patent License. Subject to the terms and conditions of 147 | this License, each Contributor hereby grants to You a perpetual, 148 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 149 | (except as stated in this section) patent license to make, have made, 150 | use, offer to sell, sell, import, and otherwise transfer the Work, 151 | where such license applies only to those patent claims licensable 152 | by such Contributor that are necessarily infringed by their 153 | Contribution(s) alone or by combination of their Contribution(s) 154 | with the Work to which such Contribution(s) was submitted. If You 155 | institute patent litigation against any entity (including a 156 | cross-claim or counterclaim in a lawsuit) alleging that the Work 157 | or a Contribution incorporated within the Work constitutes direct 158 | or contributory patent infringement, then any patent licenses 159 | granted to You under this License for that Work shall terminate 160 | as of the date such litigation is filed. 161 | 162 | 4. Redistribution. You may reproduce and distribute copies of the 163 | Work or Derivative Works thereof in any medium, with or without 164 | modifications, and in Source or Object form, provided that You 165 | meet the following conditions: 166 | 167 | (a) You must give any other recipients of the Work or 168 | Derivative Works a copy of this License; and 169 | 170 | (b) You must cause any modified files to carry prominent notices 171 | stating that You changed the files; and 172 | 173 | (c) You must retain, in the Source form of any Derivative Works 174 | that You distribute, all copyright, patent, trademark, and 175 | attribution notices from the Source form of the Work, 176 | excluding those notices that do not pertain to any part of 177 | the Derivative Works; and 178 | 179 | (d) If the Work includes a "NOTICE" text file as part of its 180 | distribution, then any Derivative Works that You distribute must 181 | include a readable copy of the attribution notices contained 182 | within such NOTICE file, excluding those notices that do not 183 | pertain to any part of the Derivative Works, in at least one 184 | of the following places: within a NOTICE text file distributed 185 | as part of the Derivative Works; within the Source form or 186 | documentation, if provided along with the Derivative Works; or, 187 | within a display generated by the Derivative Works, if and 188 | wherever such third-party notices normally appear. The contents 189 | of the NOTICE file are for informational purposes only and 190 | do not modify the License. You may add Your own attribution 191 | notices within Derivative Works that You distribute, alongside 192 | or as an addendum to the NOTICE text from the Work, provided 193 | that such additional attribution notices cannot be construed 194 | as modifying the License. 195 | 196 | You may add Your own copyright statement to Your modifications and 197 | may provide additional or different license terms and conditions 198 | for use, reproduction, or distribution of Your modifications, or 199 | for any such Derivative Works as a whole, provided Your use, 200 | reproduction, and distribution of the Work otherwise complies with 201 | the conditions stated in this License. 202 | 203 | 5. Submission of Contributions. Unless You explicitly state otherwise, 204 | any Contribution intentionally submitted for inclusion in the Work 205 | by You to the Licensor shall be under the terms and conditions of 206 | this License, without any additional terms or conditions. 207 | Notwithstanding the above, nothing herein shall supersede or modify 208 | the terms of any separate license agreement you may have executed 209 | with Licensor regarding such Contributions. 210 | 211 | 6. Trademarks. This License does not grant permission to use the trade 212 | names, trademarks, service marks, or product names of the Licensor, 213 | except as required for reasonable and customary use in describing the 214 | origin of the Work and reproducing the content of the NOTICE file. 215 | 216 | 7. Disclaimer of Warranty. Unless required by applicable law or 217 | agreed to in writing, Licensor provides the Work (and each 218 | Contributor provides its Contributions) on an "AS IS" BASIS, 219 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 220 | implied, including, without limitation, any warranties or conditions 221 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 222 | PARTICULAR PURPOSE. You are solely responsible for determining the 223 | appropriateness of using or redistributing the Work and assume any 224 | risks associated with Your exercise of permissions under this License. 225 | 226 | 8. Limitation of Liability. In no event and under no legal theory, 227 | whether in tort (including negligence), contract, or otherwise, 228 | unless required by applicable law (such as deliberate and grossly 229 | negligent acts) or agreed to in writing, shall any Contributor be 230 | liable to You for damages, including any direct, indirect, special, 231 | incidental, or consequential damages of any character arising as a 232 | result of this License or out of the use or inability to use the 233 | Work (including but not limited to damages for loss of goodwill, 234 | work stoppage, computer failure or malfunction, or any and all 235 | other commercial damages or losses), even if such Contributor 236 | has been advised of the possibility of such damages. 237 | 238 | 9. Accepting Warranty or Additional Liability. While redistributing 239 | the Work or Derivative Works thereof, You may choose to offer, 240 | and charge a fee for, acceptance of support, warranty, indemnity, 241 | or other liability obligations and/or rights consistent with this 242 | License. However, in accepting such obligations, You may act only 243 | on Your own behalf and on Your sole responsibility, not on behalf 244 | of any other Contributor, and only if You agree to indemnify, 245 | defend, and hold each Contributor harmless for any liability 246 | incurred by, or claims asserted against, such Contributor by reason 247 | of your accepting any such warranty or additional liability. -------------------------------------------------------------------------------- /build.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | mingw32-make %* -------------------------------------------------------------------------------- /dist/EnderCalc.msi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startrekdude/EnderCalc/a6fbbd8c85ddeb47c555183d9b09752aecbf3f83/dist/EnderCalc.msi -------------------------------------------------------------------------------- /dist/EnderCalc.wxs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 35 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 53 | 58 | 61 | 62 | 63 | 64 | 65 | 66 | 68 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | Privileged 80 | 81 | 82 | VersionNT64 >= 603 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /dist/appdir/EnderCalc.150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startrekdude/EnderCalc/a6fbbd8c85ddeb47c555183d9b09752aecbf3f83/dist/appdir/EnderCalc.150x150.png -------------------------------------------------------------------------------- /dist/appdir/EnderCalc.70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startrekdude/EnderCalc/a6fbbd8c85ddeb47c555183d9b09752aecbf3f83/dist/appdir/EnderCalc.70x70.png -------------------------------------------------------------------------------- /dist/appdir/EnderCalc.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startrekdude/EnderCalc/a6fbbd8c85ddeb47c555183d9b09752aecbf3f83/dist/appdir/EnderCalc.exe -------------------------------------------------------------------------------- /dist/appdir/EnderCalc.visualelementsmanifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | -------------------------------------------------------------------------------- /dist/appdir/THIRD-PARTY.txt: -------------------------------------------------------------------------------- 1 | EnderCalc uses the following open-source libraries: 2 | - libbf 20200119 by Fabrice Bellard, licensed under the MIT License 3 | - WinEditLine 2.206 by Paolo Tosco, licensed under the BSD 3-clause License 4 | - minIni 1.2b by Thiadmer Riemersma, licensed under the Apache License w/ Linking Exception 5 | 6 | License full texts follow: 7 | 8 | libbf 9 | Copyright 2020 Fabrice Bellard 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining 12 | a copy of this software and associated documentation files (the 13 | "Software"), to deal in the Software without restriction, including 14 | without limitation the rights to use, copy, modify, merge, publish, 15 | distribute, sublicense, and/or sell copies of the Software, and to 16 | permit persons to whom the Software is furnished to do so, subject to 17 | the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be 20 | included in all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 25 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 26 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 27 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 28 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | WinEditLine 31 | Copyright (c) 2010-2016, Paolo Tosco 32 | All rights reserved. 33 | 34 | Redistribution and use in source and binary forms, with or without 35 | modification, are permitted provided that the following conditions are met: 36 | 37 | 1. Redistributions of source code must retain the above copyright notice, this 38 | list of conditions and the following disclaimer. 39 | 40 | 2. Redistributions in binary form must reproduce the above copyright notice, 41 | this list of conditions and the following disclaimer in the documentation 42 | and/or other materials provided with the distribution. 43 | 44 | 3. Neither the name of MinGWEditLine nor the names of its 45 | contributors may be used to endorse or promote products derived from 46 | this software without specific prior written permission. 47 | 48 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 49 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 51 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 52 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 54 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 55 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 56 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 57 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 58 | 59 | libminIni 60 | 61 | Apache License 62 | Version 2.0, January 2004 63 | http://www.apache.org/licenses/ 64 | 65 | 66 | EXCEPTION TO THE APACHE 2.0 LICENSE 67 | 68 | As a special exception to the Apache License 2.0 (and referring to the 69 | definitions in Section 1 of this license), you may link, statically or 70 | dynamically, the "Work" to other modules to produce an executable file 71 | containing portions of the "Work", and distribute that executable file 72 | in "Object" form under the terms of your choice, without any of the 73 | additional requirements listed in Section 4 of the Apache License 2.0. 74 | This exception applies only to redistributions in "Object" form (not 75 | "Source" form) and only if no modifications have been made to the "Work". 76 | 77 | 78 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 79 | 80 | 1. Definitions. 81 | 82 | "License" shall mean the terms and conditions for use, reproduction, 83 | and distribution as defined by Sections 1 through 9 of this document. 84 | 85 | "Licensor" shall mean the copyright owner or entity authorized by 86 | the copyright owner that is granting the License. 87 | 88 | "Legal Entity" shall mean the union of the acting entity and all 89 | other entities that control, are controlled by, or are under common 90 | control with that entity. For the purposes of this definition, 91 | "control" means (i) the power, direct or indirect, to cause the 92 | direction or management of such entity, whether by contract or 93 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 94 | outstanding shares, or (iii) beneficial ownership of such entity. 95 | 96 | "You" (or "Your") shall mean an individual or Legal Entity 97 | exercising permissions granted by this License. 98 | 99 | "Source" form shall mean the preferred form for making modifications, 100 | including but not limited to software source code, documentation 101 | source, and configuration files. 102 | 103 | "Object" form shall mean any form resulting from mechanical 104 | transformation or translation of a Source form, including but 105 | not limited to compiled object code, generated documentation, 106 | and conversions to other media types. 107 | 108 | "Work" shall mean the work of authorship, whether in Source or 109 | Object form, made available under the License, as indicated by a 110 | copyright notice that is included in or attached to the work 111 | (an example is provided in the Appendix below). 112 | 113 | "Derivative Works" shall mean any work, whether in Source or Object 114 | form, that is based on (or derived from) the Work and for which the 115 | editorial revisions, annotations, elaborations, or other modifications 116 | represent, as a whole, an original work of authorship. For the purposes 117 | of this License, Derivative Works shall not include works that remain 118 | separable from, or merely link (or bind by name) to the interfaces of, 119 | the Work and Derivative Works thereof. 120 | 121 | "Contribution" shall mean any work of authorship, including 122 | the original version of the Work and any modifications or additions 123 | to that Work or Derivative Works thereof, that is intentionally 124 | submitted to Licensor for inclusion in the Work by the copyright owner 125 | or by an individual or Legal Entity authorized to submit on behalf of 126 | the copyright owner. For the purposes of this definition, "submitted" 127 | means any form of electronic, verbal, or written communication sent 128 | to the Licensor or its representatives, including but not limited to 129 | communication on electronic mailing lists, source code control systems, 130 | and issue tracking systems that are managed by, or on behalf of, the 131 | Licensor for the purpose of discussing and improving the Work, but 132 | excluding communication that is conspicuously marked or otherwise 133 | designated in writing by the copyright owner as "Not a Contribution." 134 | 135 | "Contributor" shall mean Licensor and any individual or Legal Entity 136 | on behalf of whom a Contribution has been received by Licensor and 137 | subsequently incorporated within the Work. 138 | 139 | 2. Grant of Copyright License. Subject to the terms and conditions of 140 | this License, each Contributor hereby grants to You a perpetual, 141 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 142 | copyright license to reproduce, prepare Derivative Works of, 143 | publicly display, publicly perform, sublicense, and distribute the 144 | Work and such Derivative Works in Source or Object form. 145 | 146 | 3. Grant of Patent License. Subject to the terms and conditions of 147 | this License, each Contributor hereby grants to You a perpetual, 148 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 149 | (except as stated in this section) patent license to make, have made, 150 | use, offer to sell, sell, import, and otherwise transfer the Work, 151 | where such license applies only to those patent claims licensable 152 | by such Contributor that are necessarily infringed by their 153 | Contribution(s) alone or by combination of their Contribution(s) 154 | with the Work to which such Contribution(s) was submitted. If You 155 | institute patent litigation against any entity (including a 156 | cross-claim or counterclaim in a lawsuit) alleging that the Work 157 | or a Contribution incorporated within the Work constitutes direct 158 | or contributory patent infringement, then any patent licenses 159 | granted to You under this License for that Work shall terminate 160 | as of the date such litigation is filed. 161 | 162 | 4. Redistribution. You may reproduce and distribute copies of the 163 | Work or Derivative Works thereof in any medium, with or without 164 | modifications, and in Source or Object form, provided that You 165 | meet the following conditions: 166 | 167 | (a) You must give any other recipients of the Work or 168 | Derivative Works a copy of this License; and 169 | 170 | (b) You must cause any modified files to carry prominent notices 171 | stating that You changed the files; and 172 | 173 | (c) You must retain, in the Source form of any Derivative Works 174 | that You distribute, all copyright, patent, trademark, and 175 | attribution notices from the Source form of the Work, 176 | excluding those notices that do not pertain to any part of 177 | the Derivative Works; and 178 | 179 | (d) If the Work includes a "NOTICE" text file as part of its 180 | distribution, then any Derivative Works that You distribute must 181 | include a readable copy of the attribution notices contained 182 | within such NOTICE file, excluding those notices that do not 183 | pertain to any part of the Derivative Works, in at least one 184 | of the following places: within a NOTICE text file distributed 185 | as part of the Derivative Works; within the Source form or 186 | documentation, if provided along with the Derivative Works; or, 187 | within a display generated by the Derivative Works, if and 188 | wherever such third-party notices normally appear. The contents 189 | of the NOTICE file are for informational purposes only and 190 | do not modify the License. You may add Your own attribution 191 | notices within Derivative Works that You distribute, alongside 192 | or as an addendum to the NOTICE text from the Work, provided 193 | that such additional attribution notices cannot be construed 194 | as modifying the License. 195 | 196 | You may add Your own copyright statement to Your modifications and 197 | may provide additional or different license terms and conditions 198 | for use, reproduction, or distribution of Your modifications, or 199 | for any such Derivative Works as a whole, provided Your use, 200 | reproduction, and distribution of the Work otherwise complies with 201 | the conditions stated in this License. 202 | 203 | 5. Submission of Contributions. Unless You explicitly state otherwise, 204 | any Contribution intentionally submitted for inclusion in the Work 205 | by You to the Licensor shall be under the terms and conditions of 206 | this License, without any additional terms or conditions. 207 | Notwithstanding the above, nothing herein shall supersede or modify 208 | the terms of any separate license agreement you may have executed 209 | with Licensor regarding such Contributions. 210 | 211 | 6. Trademarks. This License does not grant permission to use the trade 212 | names, trademarks, service marks, or product names of the Licensor, 213 | except as required for reasonable and customary use in describing the 214 | origin of the Work and reproducing the content of the NOTICE file. 215 | 216 | 7. Disclaimer of Warranty. Unless required by applicable law or 217 | agreed to in writing, Licensor provides the Work (and each 218 | Contributor provides its Contributions) on an "AS IS" BASIS, 219 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 220 | implied, including, without limitation, any warranties or conditions 221 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 222 | PARTICULAR PURPOSE. You are solely responsible for determining the 223 | appropriateness of using or redistributing the Work and assume any 224 | risks associated with Your exercise of permissions under this License. 225 | 226 | 8. Limitation of Liability. In no event and under no legal theory, 227 | whether in tort (including negligence), contract, or otherwise, 228 | unless required by applicable law (such as deliberate and grossly 229 | negligent acts) or agreed to in writing, shall any Contributor be 230 | liable to You for damages, including any direct, indirect, special, 231 | incidental, or consequential damages of any character arising as a 232 | result of this License or out of the use or inability to use the 233 | Work (including but not limited to damages for loss of goodwill, 234 | work stoppage, computer failure or malfunction, or any and all 235 | other commercial damages or losses), even if such Contributor 236 | has been advised of the possibility of such damages. 237 | 238 | 9. Accepting Warranty or Additional Liability. While redistributing 239 | the Work or Derivative Works thereof, You may choose to offer, 240 | and charge a fee for, acceptance of support, warranty, indemnity, 241 | or other liability obligations and/or rights consistent with this 242 | License. However, in accepting such obligations, You may act only 243 | on Your own behalf and on Your sole responsibility, not on behalf 244 | of any other Contributor, and only if You agree to indemnify, 245 | defend, and hold each Contributor harmless for any liability 246 | incurred by, or claims asserted against, such Contributor by reason 247 | of your accepting any such warranty or additional liability. -------------------------------------------------------------------------------- /dist/appdir/reference.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startrekdude/EnderCalc/a6fbbd8c85ddeb47c555183d9b09752aecbf3f83/dist/appdir/reference.pdf -------------------------------------------------------------------------------- /dist/build.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | set WIX=C:\Users\Ender\Desktop\Archives\dist\wix 4 | 5 | echo Building EnderCalc installer.. 6 | 7 | copy ..\EnderCalc.exe appdir 8 | copy ..\LICENSE.txt appdir 9 | copy ..\reference.pdf appdir 10 | copy ..\THIRD-PARTY.txt appdir 11 | 12 | "%WIX%\heat.exe" dir appdir -ag -srd -cg EnderCalcProgram -dr INSTALLDIR -out EnderCalcProgram.wxs -swall 13 | "%WIX%\candle.exe" -arch x64 EnderCalcProgram.wxs 14 | 15 | "%WIX%\candle.exe" -arch x64 EnderCalc.wxs 16 | 17 | "%WIX%\light.exe" -b appdir -ext WixUIExtension EnderCalc.wixobj EnderCalcProgram.wixobj -o EnderCalc.msi 18 | 19 | del EnderCalc.wixobj EnderCalcProgram.wixobj EnderCalcProgram.wxs EnderCalc.wixpdb -------------------------------------------------------------------------------- /distlinux/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cp ../endercalc staging/opt/endercalc 4 | cp ../reference.pdf staging/opt/endercalc 5 | rm staging/usr/bin/endercalc 6 | cp ../README.md staging/usr/share/doc/endercalc/README 7 | cp ../THIRD-PARTY.txt staging/usr/share/doc/endercalc/THIRD-PARTY 8 | 9 | find staging -type d -exec chmod 0755 {} \; 10 | find staging -type f -exec chmod 0644 {} \; 11 | chmod +x staging/opt/endercalc/endercalc 12 | ln -s /opt/endercalc/endercalc staging/usr/bin/endercalc 13 | 14 | dpkg-deb --root-owner-group --build staging endercalc_1.3_amd64.deb 15 | lintian endercalc_1.3_amd64.deb --info --suppress-tags dir-or-file-in-opt 16 | -------------------------------------------------------------------------------- /distlinux/endercalc_1.3_amd64.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startrekdude/EnderCalc/a6fbbd8c85ddeb47c555183d9b09752aecbf3f83/distlinux/endercalc_1.3_amd64.deb -------------------------------------------------------------------------------- /distlinux/staging/DEBIAN/control: -------------------------------------------------------------------------------- 1 | Package: endercalc 2 | Version: 1.3 3 | Homepage: https://github.com/startrekdude/EnderCalc 4 | Architecture: amd64 5 | Maintainer: Sam Haskins 6 | Depends: libc6 (>= 2.27), libedit2 (>= 3.1) 7 | Section: math 8 | Priority: optional 9 | Description: Fast, powerful, arbitrary precision, text-driven scientific calculator. 10 | EnderCalc is a fast, powerful, arbitrary precision, text-driven scientific 11 | calculator written in (almost) pure C99. It supports basic arithmetic, 12 | logarithms and roots, trigonometric functions, hyperbolic functions, statistics 13 | functions, and much more. 14 | -------------------------------------------------------------------------------- /distlinux/staging/opt/endercalc/endercalc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startrekdude/EnderCalc/a6fbbd8c85ddeb47c555183d9b09752aecbf3f83/distlinux/staging/opt/endercalc/endercalc -------------------------------------------------------------------------------- /distlinux/staging/opt/endercalc/reference.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startrekdude/EnderCalc/a6fbbd8c85ddeb47c555183d9b09752aecbf3f83/distlinux/staging/opt/endercalc/reference.pdf -------------------------------------------------------------------------------- /distlinux/staging/usr/bin/endercalc: -------------------------------------------------------------------------------- 1 | /opt/endercalc/endercalc -------------------------------------------------------------------------------- /distlinux/staging/usr/share/applications/endercalc.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=EnderCalc 3 | Comment=Fast, powerful, arbitrary precision, text-driven scientific calculator. 4 | Icon=endercalc 5 | Exec=endercalc 6 | Terminal=true 7 | Type=Application 8 | Categories=Utility;Math; 9 | GenericName=EnderCalc 10 | -------------------------------------------------------------------------------- /distlinux/staging/usr/share/doc/endercalc/README: -------------------------------------------------------------------------------- 1 | # EnderCalc 2 | 3 | ### A powerful, text-driven scientific calculator 4 | 5 | *'Cause sometimes the Windows Calculator just isn't good enough* 6 | 7 | ![](EnderCalc.gif) 8 | 9 | EnderCalc is a fast, powerful, arbitrary precision, text-driven scientific calculator written in (almost) pure C99. It supports basic arithmetic, logarithms and roots, trigonometric functions, hyperbolic functions, statistics functions, and much more (a full reference is available in [reference.pdf](reference.pdf)). 10 | 11 | ## Download 12 | 13 | Please see the releases section for x64 Windows binaries or DEB packages. 14 | 15 | To build on Linux: 16 | 17 | ```bash 18 | make 19 | ``` 20 | 21 | (has `libedit-dev` as a dependency, run `sudo apt install libedit-dev` first) 22 | 23 | ## Documentation 24 | 25 | Please see [reference.pdf](reference.pdf), shipped with EnderCalc, for user-facing documentation. 26 | 27 | For a whirlwind introduction to how EnderCalc works internally, have a look at [DEVDOCS.md](DEVDOCS.md). 28 | 29 | ## License 30 | 31 | [GNU General Public License, version 3](https://choosealicense.com/licenses/gpl-3.0/) 32 | 33 | ## Open Source Libraries 34 | 35 | - [libbf](https://bellard.org/libbf/) 20200119 by [Fabrice Bellard](https://bellard.org) 36 | - [WinEditLine](http://mingweditline.sourceforge.net/) 2.206 by Paolo Tosco 37 | - [minIni](https://www.compuphase.com/minini.htm) 1.2b by Thiadmer Riemersma -------------------------------------------------------------------------------- /distlinux/staging/usr/share/doc/endercalc/THIRD-PARTY: -------------------------------------------------------------------------------- 1 | EnderCalc uses the following open-source libraries: 2 | - libbf 20200119 by Fabrice Bellard, licensed under the MIT License 3 | - WinEditLine 2.206 by Paolo Tosco, licensed under the BSD 3-clause License 4 | - minIni 1.2b by Thiadmer Riemersma, licensed under the Apache License w/ Linking Exception 5 | 6 | License full texts follow: 7 | 8 | libbf 9 | Copyright 2020 Fabrice Bellard 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining 12 | a copy of this software and associated documentation files (the 13 | "Software"), to deal in the Software without restriction, including 14 | without limitation the rights to use, copy, modify, merge, publish, 15 | distribute, sublicense, and/or sell copies of the Software, and to 16 | permit persons to whom the Software is furnished to do so, subject to 17 | the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be 20 | included in all copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 25 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 26 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 27 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 28 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29 | 30 | WinEditLine 31 | Copyright (c) 2010-2016, Paolo Tosco 32 | All rights reserved. 33 | 34 | Redistribution and use in source and binary forms, with or without 35 | modification, are permitted provided that the following conditions are met: 36 | 37 | 1. Redistributions of source code must retain the above copyright notice, this 38 | list of conditions and the following disclaimer. 39 | 40 | 2. Redistributions in binary form must reproduce the above copyright notice, 41 | this list of conditions and the following disclaimer in the documentation 42 | and/or other materials provided with the distribution. 43 | 44 | 3. Neither the name of MinGWEditLine nor the names of its 45 | contributors may be used to endorse or promote products derived from 46 | this software without specific prior written permission. 47 | 48 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 49 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 51 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 52 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 54 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 55 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 56 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 57 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 58 | 59 | libminIni 60 | 61 | Apache License 62 | Version 2.0, January 2004 63 | http://www.apache.org/licenses/ 64 | 65 | 66 | EXCEPTION TO THE APACHE 2.0 LICENSE 67 | 68 | As a special exception to the Apache License 2.0 (and referring to the 69 | definitions in Section 1 of this license), you may link, statically or 70 | dynamically, the "Work" to other modules to produce an executable file 71 | containing portions of the "Work", and distribute that executable file 72 | in "Object" form under the terms of your choice, without any of the 73 | additional requirements listed in Section 4 of the Apache License 2.0. 74 | This exception applies only to redistributions in "Object" form (not 75 | "Source" form) and only if no modifications have been made to the "Work". 76 | 77 | 78 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 79 | 80 | 1. Definitions. 81 | 82 | "License" shall mean the terms and conditions for use, reproduction, 83 | and distribution as defined by Sections 1 through 9 of this document. 84 | 85 | "Licensor" shall mean the copyright owner or entity authorized by 86 | the copyright owner that is granting the License. 87 | 88 | "Legal Entity" shall mean the union of the acting entity and all 89 | other entities that control, are controlled by, or are under common 90 | control with that entity. For the purposes of this definition, 91 | "control" means (i) the power, direct or indirect, to cause the 92 | direction or management of such entity, whether by contract or 93 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 94 | outstanding shares, or (iii) beneficial ownership of such entity. 95 | 96 | "You" (or "Your") shall mean an individual or Legal Entity 97 | exercising permissions granted by this License. 98 | 99 | "Source" form shall mean the preferred form for making modifications, 100 | including but not limited to software source code, documentation 101 | source, and configuration files. 102 | 103 | "Object" form shall mean any form resulting from mechanical 104 | transformation or translation of a Source form, including but 105 | not limited to compiled object code, generated documentation, 106 | and conversions to other media types. 107 | 108 | "Work" shall mean the work of authorship, whether in Source or 109 | Object form, made available under the License, as indicated by a 110 | copyright notice that is included in or attached to the work 111 | (an example is provided in the Appendix below). 112 | 113 | "Derivative Works" shall mean any work, whether in Source or Object 114 | form, that is based on (or derived from) the Work and for which the 115 | editorial revisions, annotations, elaborations, or other modifications 116 | represent, as a whole, an original work of authorship. For the purposes 117 | of this License, Derivative Works shall not include works that remain 118 | separable from, or merely link (or bind by name) to the interfaces of, 119 | the Work and Derivative Works thereof. 120 | 121 | "Contribution" shall mean any work of authorship, including 122 | the original version of the Work and any modifications or additions 123 | to that Work or Derivative Works thereof, that is intentionally 124 | submitted to Licensor for inclusion in the Work by the copyright owner 125 | or by an individual or Legal Entity authorized to submit on behalf of 126 | the copyright owner. For the purposes of this definition, "submitted" 127 | means any form of electronic, verbal, or written communication sent 128 | to the Licensor or its representatives, including but not limited to 129 | communication on electronic mailing lists, source code control systems, 130 | and issue tracking systems that are managed by, or on behalf of, the 131 | Licensor for the purpose of discussing and improving the Work, but 132 | excluding communication that is conspicuously marked or otherwise 133 | designated in writing by the copyright owner as "Not a Contribution." 134 | 135 | "Contributor" shall mean Licensor and any individual or Legal Entity 136 | on behalf of whom a Contribution has been received by Licensor and 137 | subsequently incorporated within the Work. 138 | 139 | 2. Grant of Copyright License. Subject to the terms and conditions of 140 | this License, each Contributor hereby grants to You a perpetual, 141 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 142 | copyright license to reproduce, prepare Derivative Works of, 143 | publicly display, publicly perform, sublicense, and distribute the 144 | Work and such Derivative Works in Source or Object form. 145 | 146 | 3. Grant of Patent License. Subject to the terms and conditions of 147 | this License, each Contributor hereby grants to You a perpetual, 148 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 149 | (except as stated in this section) patent license to make, have made, 150 | use, offer to sell, sell, import, and otherwise transfer the Work, 151 | where such license applies only to those patent claims licensable 152 | by such Contributor that are necessarily infringed by their 153 | Contribution(s) alone or by combination of their Contribution(s) 154 | with the Work to which such Contribution(s) was submitted. If You 155 | institute patent litigation against any entity (including a 156 | cross-claim or counterclaim in a lawsuit) alleging that the Work 157 | or a Contribution incorporated within the Work constitutes direct 158 | or contributory patent infringement, then any patent licenses 159 | granted to You under this License for that Work shall terminate 160 | as of the date such litigation is filed. 161 | 162 | 4. Redistribution. You may reproduce and distribute copies of the 163 | Work or Derivative Works thereof in any medium, with or without 164 | modifications, and in Source or Object form, provided that You 165 | meet the following conditions: 166 | 167 | (a) You must give any other recipients of the Work or 168 | Derivative Works a copy of this License; and 169 | 170 | (b) You must cause any modified files to carry prominent notices 171 | stating that You changed the files; and 172 | 173 | (c) You must retain, in the Source form of any Derivative Works 174 | that You distribute, all copyright, patent, trademark, and 175 | attribution notices from the Source form of the Work, 176 | excluding those notices that do not pertain to any part of 177 | the Derivative Works; and 178 | 179 | (d) If the Work includes a "NOTICE" text file as part of its 180 | distribution, then any Derivative Works that You distribute must 181 | include a readable copy of the attribution notices contained 182 | within such NOTICE file, excluding those notices that do not 183 | pertain to any part of the Derivative Works, in at least one 184 | of the following places: within a NOTICE text file distributed 185 | as part of the Derivative Works; within the Source form or 186 | documentation, if provided along with the Derivative Works; or, 187 | within a display generated by the Derivative Works, if and 188 | wherever such third-party notices normally appear. The contents 189 | of the NOTICE file are for informational purposes only and 190 | do not modify the License. You may add Your own attribution 191 | notices within Derivative Works that You distribute, alongside 192 | or as an addendum to the NOTICE text from the Work, provided 193 | that such additional attribution notices cannot be construed 194 | as modifying the License. 195 | 196 | You may add Your own copyright statement to Your modifications and 197 | may provide additional or different license terms and conditions 198 | for use, reproduction, or distribution of Your modifications, or 199 | for any such Derivative Works as a whole, provided Your use, 200 | reproduction, and distribution of the Work otherwise complies with 201 | the conditions stated in this License. 202 | 203 | 5. Submission of Contributions. Unless You explicitly state otherwise, 204 | any Contribution intentionally submitted for inclusion in the Work 205 | by You to the Licensor shall be under the terms and conditions of 206 | this License, without any additional terms or conditions. 207 | Notwithstanding the above, nothing herein shall supersede or modify 208 | the terms of any separate license agreement you may have executed 209 | with Licensor regarding such Contributions. 210 | 211 | 6. Trademarks. This License does not grant permission to use the trade 212 | names, trademarks, service marks, or product names of the Licensor, 213 | except as required for reasonable and customary use in describing the 214 | origin of the Work and reproducing the content of the NOTICE file. 215 | 216 | 7. Disclaimer of Warranty. Unless required by applicable law or 217 | agreed to in writing, Licensor provides the Work (and each 218 | Contributor provides its Contributions) on an "AS IS" BASIS, 219 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 220 | implied, including, without limitation, any warranties or conditions 221 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 222 | PARTICULAR PURPOSE. You are solely responsible for determining the 223 | appropriateness of using or redistributing the Work and assume any 224 | risks associated with Your exercise of permissions under this License. 225 | 226 | 8. Limitation of Liability. In no event and under no legal theory, 227 | whether in tort (including negligence), contract, or otherwise, 228 | unless required by applicable law (such as deliberate and grossly 229 | negligent acts) or agreed to in writing, shall any Contributor be 230 | liable to You for damages, including any direct, indirect, special, 231 | incidental, or consequential damages of any character arising as a 232 | result of this License or out of the use or inability to use the 233 | Work (including but not limited to damages for loss of goodwill, 234 | work stoppage, computer failure or malfunction, or any and all 235 | other commercial damages or losses), even if such Contributor 236 | has been advised of the possibility of such damages. 237 | 238 | 9. Accepting Warranty or Additional Liability. While redistributing 239 | the Work or Derivative Works thereof, You may choose to offer, 240 | and charge a fee for, acceptance of support, warranty, indemnity, 241 | or other liability obligations and/or rights consistent with this 242 | License. However, in accepting such obligations, You may act only 243 | on Your own behalf and on Your sole responsibility, not on behalf 244 | of any other Contributor, and only if You agree to indemnify, 245 | defend, and hold each Contributor harmless for any liability 246 | incurred by, or claims asserted against, such Contributor by reason 247 | of your accepting any such warranty or additional liability. -------------------------------------------------------------------------------- /distlinux/staging/usr/share/doc/endercalc/changelog.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startrekdude/EnderCalc/a6fbbd8c85ddeb47c555183d9b09752aecbf3f83/distlinux/staging/usr/share/doc/endercalc/changelog.gz -------------------------------------------------------------------------------- /distlinux/staging/usr/share/doc/endercalc/copyright: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: Sam Haskins 3 | Upstream-Contact: cheesedude54321@gmail.com 4 | Source: https://github.com/startrekdude/EnderCalc 5 | License: GPL-3 6 | Copyright: 2020 Sam Haskins 7 | 8 | Files: * 9 | Copyright: 2020 Sam Haskins 10 | License: GPL-3 11 | -------------------------------------------------------------------------------- /distlinux/staging/usr/share/icons/hicolor/16x16/apps/endercalc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startrekdude/EnderCalc/a6fbbd8c85ddeb47c555183d9b09752aecbf3f83/distlinux/staging/usr/share/icons/hicolor/16x16/apps/endercalc.png -------------------------------------------------------------------------------- /distlinux/staging/usr/share/icons/hicolor/24x24/apps/endercalc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startrekdude/EnderCalc/a6fbbd8c85ddeb47c555183d9b09752aecbf3f83/distlinux/staging/usr/share/icons/hicolor/24x24/apps/endercalc.png -------------------------------------------------------------------------------- /distlinux/staging/usr/share/icons/hicolor/256x256/apps/endercalc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startrekdude/EnderCalc/a6fbbd8c85ddeb47c555183d9b09752aecbf3f83/distlinux/staging/usr/share/icons/hicolor/256x256/apps/endercalc.png -------------------------------------------------------------------------------- /distlinux/staging/usr/share/icons/hicolor/32x32/apps/endercalc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startrekdude/EnderCalc/a6fbbd8c85ddeb47c555183d9b09752aecbf3f83/distlinux/staging/usr/share/icons/hicolor/32x32/apps/endercalc.png -------------------------------------------------------------------------------- /distlinux/staging/usr/share/icons/hicolor/48x48/apps/endercalc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startrekdude/EnderCalc/a6fbbd8c85ddeb47c555183d9b09752aecbf3f83/distlinux/staging/usr/share/icons/hicolor/48x48/apps/endercalc.png -------------------------------------------------------------------------------- /distlinux/staging/usr/share/icons/hicolor/64x64/apps/endercalc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startrekdude/EnderCalc/a6fbbd8c85ddeb47c555183d9b09752aecbf3f83/distlinux/staging/usr/share/icons/hicolor/64x64/apps/endercalc.png -------------------------------------------------------------------------------- /distlinux/staging/usr/share/man/man1/endercalc.1.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startrekdude/EnderCalc/a6fbbd8c85ddeb47c555183d9b09752aecbf3f83/distlinux/staging/usr/share/man/man1/endercalc.1.gz -------------------------------------------------------------------------------- /distlinux/staging/usr/share/pixmaps/endercalc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startrekdude/EnderCalc/a6fbbd8c85ddeb47c555183d9b09752aecbf3f83/distlinux/staging/usr/share/pixmaps/endercalc.png -------------------------------------------------------------------------------- /include/calc.h: -------------------------------------------------------------------------------- 1 | #ifndef _INCLUDED_CALC_H 2 | #define _INCLUDED_CALC_H 3 | 4 | // define global variables here to let the command interpreter poke them 5 | extern unsigned int g_debug; 6 | extern unsigned int g_time; 7 | extern unsigned int g_suppress_scientific_notation; 8 | 9 | #endif -------------------------------------------------------------------------------- /include/command.h: -------------------------------------------------------------------------------- 1 | #ifndef _INCLUDED_COMMAND_H 2 | #define _INCLUDED_COMMAND_H 3 | 4 | // Various meta-command that influence parts of the calculator 5 | // Set precision, show extra debug information, etc 6 | 7 | extern char* g_config_path; 8 | 9 | typedef void (cmd_func_t)(char *s); 10 | 11 | typedef struct { 12 | char str[16]; // name of the command w/o slashes 13 | unsigned int len; // length of name 14 | cmd_func_t *op; // pointer to executing function 15 | } cmd_t; 16 | 17 | void command_load_config(); 18 | void exec_meta_command(char *s); 19 | 20 | #endif -------------------------------------------------------------------------------- /include/engine.h: -------------------------------------------------------------------------------- 1 | #ifndef _INCLUDED_ENGINE_H 2 | #define _INCLUDED_ENGINE_H 3 | 4 | #include "libbf.h" 5 | 6 | #define ENGINE_CONST_PI 0 7 | #define ENGINE_CONST_E 1 8 | #define ENGINE_CONST_TAU 2 9 | #define ENGINE_CONST_MAX_FAC 3 10 | #define ENGINE_CONST_ONE 4 11 | #define ENGINE_CONST_THIRD 5 12 | #define ENGINE_CONST_TWO 6 13 | #define ENGINE_CONST_D2R 7 14 | #define ENGINE_CONST_MILLION 8 15 | #define ENGINE_CONST_MILLIONTH 9 16 | #define ENGINE_CONST_NEG_MILLIONTH 10 17 | #define ENGINE_CONST_ZERO 11 18 | #define ENGINE_CONST_R2D 12 19 | #define ENGINE_CONST_MAX_HYP 13 20 | #define ENGINE_CONST_MIN_HYP 14 21 | #define ENGINE_CONST_HALF 15 22 | #define ENGINE_CONST_MAX_POW_BASE 16 23 | 24 | // the global context used for all math operations 25 | extern bf_context_t g_engine_ctx; 26 | 27 | // The precision used for the binary engine (in bits) 28 | extern limb_t g_engine_prec; 29 | 30 | // The precision used for the decimal engine (in decimals) 31 | // this is /only/ used for display, and should be 32 | // slightly lower than the binary engine - 33 | // this is because binary can't actually represent certain 34 | // numbers, so we wanna round before displaying them 35 | extern limb_t g_dec_engine_prec; 36 | 37 | extern bf_t *g_engine_const[]; 38 | 39 | void engine_init(); 40 | void engine_cleanup(); 41 | 42 | bf_t* engine_num_alloc(); 43 | void engine_num_free(bf_t *num); 44 | 45 | void engine_num_print(bf_t *num, unsigned int show_real, unsigned int suppress_scientific_mode); 46 | 47 | bf_t* engine_copy_const(unsigned int i); 48 | 49 | // 0 = radians, 1 = degrees 50 | extern unsigned char g_use_degrees; 51 | 52 | // the functions that actually do things 53 | int calc_neg(bf_t **args, bf_t **result); 54 | int calc_add(bf_t **args, bf_t **result); 55 | int calc_sub(bf_t **args, bf_t **result); 56 | int calc_mul(bf_t **args, bf_t **result); 57 | int calc_div(bf_t **args, bf_t **result); 58 | int calc_mod(bf_t **args, bf_t **result); 59 | int calc_exp(bf_t **args, bf_t **result); 60 | int calc_pow(bf_t **args, bf_t **result); 61 | int calc_fac(bf_t **args, bf_t **result); 62 | int calc_sqrt(bf_t **args, bf_t **result); 63 | int calc_cbrt(bf_t **args, bf_t **result); 64 | int calc_root(bf_t **args, bf_t **result); 65 | int calc_ln(bf_t **args, bf_t **result); 66 | int calc_log(bf_t **args, bf_t **result); 67 | int calc_sin(bf_t **args, bf_t **result); 68 | int calc_cos(bf_t **args, bf_t **result); 69 | int calc_tan(bf_t **args, bf_t **result); 70 | int calc_asin(bf_t **args, bf_t **result); 71 | int calc_acos(bf_t **args, bf_t **result); 72 | int calc_atan(bf_t **args, bf_t **result); 73 | int calc_sinh(bf_t **args, bf_t **result); 74 | int calc_cosh(bf_t **args, bf_t **result); 75 | int calc_tanh(bf_t **args, bf_t **result); 76 | int calc_asinh(bf_t **args, bf_t **result); 77 | int calc_acosh(bf_t **args, bf_t **result); 78 | int calc_atanh(bf_t **args, bf_t **result); 79 | int calc_permu(bf_t **args, bf_t **result); 80 | int calc_combi(bf_t **args, bf_t **result); 81 | int calc_abs(bf_t **args, bf_t **result); 82 | int calc_2fac(bf_t **args, bf_t **result); 83 | 84 | #endif -------------------------------------------------------------------------------- /include/eval.h: -------------------------------------------------------------------------------- 1 | #ifndef _INCLUDED_EVAL_H 2 | #define _INCLUDED_EVAL_H 3 | 4 | #include "libbf.h" 5 | #include "vector.h" 6 | 7 | #define EVAL_SUCCESS 0 8 | #define EVAL_SYNTAX_ERROR 1 9 | #define EVAL_MISSING_OPERATOR 2 10 | #define EVAL_NO_SAVED_ANSWER 3 11 | #define EVAL_ZERO_DIVISION 4 12 | #define EVAL_MATH_ERROR 5 13 | #define EVAL_OVERFLOW 6 14 | #define EVAL_NO_RECALL 7 15 | 16 | extern bf_t *g_last_answer; 17 | 18 | unsigned int eval_expr(vector_t expr, bf_t **result); 19 | void eval_print_error(unsigned int err); 20 | 21 | #endif -------------------------------------------------------------------------------- /include/expr.h: -------------------------------------------------------------------------------- 1 | #ifndef _INCLUDED_EXPR_H 2 | #define _INCLUDED_EXPR_H 3 | 4 | #include "vector.h" 5 | 6 | #define TOKEN_EXPR 0 7 | #define TOKEN_STR 1 8 | #define TOKEN_NUM 2 9 | #define TOKEN_SYM 3 10 | 11 | typedef struct { 12 | char *ptr; // start location of slice 13 | unsigned int len; // number of characters in slice 14 | } str_slice_t; 15 | 16 | void token_tag(void **ptr, unsigned int tag); 17 | unsigned int token_untag(void **ptr); 18 | 19 | void expr_print(vector_t expr); 20 | 21 | void token_delete(void *tk); 22 | void expr_delete(vector_t expr); 23 | 24 | #endif -------------------------------------------------------------------------------- /include/mem.h: -------------------------------------------------------------------------------- 1 | #ifndef _INCLUDED_MEM_H 2 | #define _INCLUDED_MEM_H 3 | 4 | #include "libbf.h" 5 | 6 | // the calculator can store numbers in memory 7 | // these also get written to the ini file 8 | extern bf_t *g_mem[]; 9 | #define CALC_MEMORY_SIZE 9 10 | 11 | void free_mem(); 12 | 13 | unsigned int mem_run_command(char *s); 14 | 15 | // commands executed directly by command.c 16 | void do_clear_mem(char *s); 17 | void do_show_mem(char *s); 18 | 19 | // for loading memory from the ini file 20 | void mem_try_load(const char *section, const char *key, const char *value); 21 | 22 | #endif -------------------------------------------------------------------------------- /include/minGlue.h: -------------------------------------------------------------------------------- 1 | /* Glue functions for the minIni library, based on the C/C++ stdio library 2 | * 3 | * Or better said: this file contains macros that maps the function interface 4 | * used by minIni to the standard C/C++ file I/O functions. 5 | * 6 | * By CompuPhase, 2008-2012 7 | * This "glue file" is in the public domain. It is distributed without 8 | * warranties or conditions of any kind, either express or implied. 9 | */ 10 | 11 | /* map required file I/O types and functions to the standard C library */ 12 | #include 13 | 14 | // no unicode support 15 | #define INI_ANSIONLY 16 | 17 | #define INI_FILETYPE FILE* 18 | #define ini_openread(filename,file) ((*(file) = fopen((filename),"rb")) != NULL) 19 | #define ini_openwrite(filename,file) ((*(file) = fopen((filename),"wb")) != NULL) 20 | #define ini_close(file) (fclose(*(file)) == 0) 21 | #define ini_read(buffer,size,file) (fgets((buffer),(size),*(file)) != NULL) 22 | #define ini_write(buffer,file) (fputs((buffer),*(file)) >= 0) 23 | #define ini_rename(source,dest) (rename((source), (dest)) == 0) 24 | #define ini_remove(filename) (remove(filename) == 0) 25 | 26 | #define INI_FILEPOS fpos_t 27 | #define ini_tell(file,pos) (fgetpos(*(file), (pos)) == 0) 28 | #define ini_seek(file,pos) (fsetpos(*(file), (pos)) == 0) 29 | 30 | // no floating point support -------------------------------------------------------------------------------- /include/minini.h: -------------------------------------------------------------------------------- 1 | /* minIni - Multi-Platform INI file parser, suitable for embedded systems 2 | * 3 | * Copyright (c) CompuPhase, 2008-2012 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 6 | * use this file except in compliance with the License. You may obtain a copy 7 | * of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * License for the specific language governing permissions and limitations 15 | * under the License. 16 | * 17 | * Version: $Id: minIni.h 44 2012-01-04 15:52:56Z thiadmer.riemersma@gmail.com $ 18 | */ 19 | #ifndef MININI_H 20 | #define MININI_H 21 | 22 | #include "minGlue.h" 23 | 24 | #if (defined _UNICODE || defined __UNICODE__ || defined UNICODE) && !defined MININI_ANSI 25 | #include 26 | #define mTCHAR TCHAR 27 | #else 28 | /* force TCHAR to be "char", but only for minIni */ 29 | #define mTCHAR char 30 | #endif 31 | 32 | #if !defined INI_BUFFERSIZE 33 | #define INI_BUFFERSIZE 512 34 | #endif 35 | 36 | #if defined __cplusplus 37 | extern "C" { 38 | #endif 39 | 40 | int ini_getbool(const mTCHAR *Section, const mTCHAR *Key, int DefValue, const mTCHAR *Filename); 41 | long ini_getl(const mTCHAR *Section, const mTCHAR *Key, long DefValue, const mTCHAR *Filename); 42 | int ini_gets(const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *DefValue, mTCHAR *Buffer, int BufferSize, const mTCHAR *Filename); 43 | int ini_getsection(int idx, mTCHAR *Buffer, int BufferSize, const mTCHAR *Filename); 44 | int ini_getkey(const mTCHAR *Section, int idx, mTCHAR *Buffer, int BufferSize, const mTCHAR *Filename); 45 | 46 | #if defined INI_REAL 47 | INI_REAL ini_getf(const mTCHAR *Section, const mTCHAR *Key, INI_REAL DefValue, const mTCHAR *Filename); 48 | #endif 49 | 50 | #if !defined INI_READONLY 51 | int ini_putl(const mTCHAR *Section, const mTCHAR *Key, long Value, const mTCHAR *Filename); 52 | int ini_puts(const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *Value, const mTCHAR *Filename); 53 | #if defined INI_REAL 54 | int ini_putf(const mTCHAR *Section, const mTCHAR *Key, INI_REAL Value, const mTCHAR *Filename); 55 | #endif 56 | #endif /* INI_READONLY */ 57 | 58 | #if !defined INI_NOBROWSE 59 | typedef int (*INI_CALLBACK)(const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *Value, const void *UserData); 60 | int ini_browse(INI_CALLBACK Callback, const void *UserData, const mTCHAR *Filename); 61 | #endif /* INI_NOBROWSE */ 62 | 63 | #if defined __cplusplus 64 | } 65 | #endif 66 | 67 | 68 | #if defined __cplusplus 69 | 70 | #if defined __WXWINDOWS__ 71 | #include "wxMinIni.h" 72 | #else 73 | #include 74 | 75 | /* The C++ class in minIni.h was contributed by Steven Van Ingelgem. */ 76 | class minIni 77 | { 78 | public: 79 | minIni(const std::string& filename) : iniFilename(filename) 80 | { } 81 | 82 | bool getbool(const std::string& Section, const std::string& Key, bool DefValue=false) const 83 | { return ini_getbool(Section.c_str(), Key.c_str(), int(DefValue), iniFilename.c_str()) != 0; } 84 | 85 | long getl(const std::string& Section, const std::string& Key, long DefValue=0) const 86 | { return ini_getl(Section.c_str(), Key.c_str(), DefValue, iniFilename.c_str()); } 87 | 88 | int geti(const std::string& Section, const std::string& Key, int DefValue=0) const 89 | { return static_cast(this->getl(Section, Key, long(DefValue))); } 90 | 91 | std::string gets(const std::string& Section, const std::string& Key, const std::string& DefValue="") const 92 | { 93 | char buffer[INI_BUFFERSIZE]; 94 | ini_gets(Section.c_str(), Key.c_str(), DefValue.c_str(), buffer, INI_BUFFERSIZE, iniFilename.c_str()); 95 | return buffer; 96 | } 97 | 98 | std::string getsection(int idx) const 99 | { 100 | char buffer[INI_BUFFERSIZE]; 101 | ini_getsection(idx, buffer, INI_BUFFERSIZE, iniFilename.c_str()); 102 | return buffer; 103 | } 104 | 105 | std::string getkey(const std::string& Section, int idx) const 106 | { 107 | char buffer[INI_BUFFERSIZE]; 108 | ini_getkey(Section.c_str(), idx, buffer, INI_BUFFERSIZE, iniFilename.c_str()); 109 | return buffer; 110 | } 111 | 112 | #if defined INI_REAL 113 | INI_REAL getf(const std::string& Section, const std::string& Key, INI_REAL DefValue=0) const 114 | { return ini_getf(Section.c_str(), Key.c_str(), DefValue, iniFilename.c_str()); } 115 | #endif 116 | 117 | #if ! defined INI_READONLY 118 | bool put(const std::string& Section, const std::string& Key, long Value) const 119 | { return ini_putl(Section.c_str(), Key.c_str(), Value, iniFilename.c_str()) != 0; } 120 | 121 | bool put(const std::string& Section, const std::string& Key, int Value) const 122 | { return ini_putl(Section.c_str(), Key.c_str(), (long)Value, iniFilename.c_str()) != 0; } 123 | 124 | bool put(const std::string& Section, const std::string& Key, bool Value) const 125 | { return ini_putl(Section.c_str(), Key.c_str(), (long)Value, iniFilename.c_str()) != 0; } 126 | 127 | bool put(const std::string& Section, const std::string& Key, const std::string& Value) const 128 | { return ini_puts(Section.c_str(), Key.c_str(), Value.c_str(), iniFilename.c_str()) != 0; } 129 | 130 | bool put(const std::string& Section, const std::string& Key, const char* Value) const 131 | { return ini_puts(Section.c_str(), Key.c_str(), Value, iniFilename.c_str()) != 0; } 132 | 133 | #if defined INI_REAL 134 | bool put(const std::string& Section, const std::string& Key, INI_REAL Value) const 135 | { return ini_putf(Section.c_str(), Key.c_str(), Value, iniFilename.c_str()) != 0; } 136 | #endif 137 | 138 | bool del(const std::string& Section, const std::string& Key) const 139 | { return ini_puts(Section.c_str(), Key.c_str(), 0, iniFilename.c_str()) != 0; } 140 | 141 | bool del(const std::string& Section) const 142 | { return ini_puts(Section.c_str(), 0, 0, iniFilename.c_str()) != 0; } 143 | #endif 144 | 145 | private: 146 | std::string iniFilename; 147 | }; 148 | 149 | #endif /* __WXWINDOWS__ */ 150 | #endif /* __cplusplus */ 151 | 152 | #endif /* MININI_H */ 153 | -------------------------------------------------------------------------------- /include/parse.h: -------------------------------------------------------------------------------- 1 | #ifndef _INCLUDED_PARSE_H 2 | #define _INCLUDED_PARSE_H 3 | 4 | #include "vector.h" 5 | 6 | #define PARSE_SUCCESS 0 7 | #define PARSE_UNMATCHED_CLOSE_BRACKET 1 8 | #define PARSE_UNMATCHED_OPEN_BRACKET 2 9 | #define PARSE_INVALID_SYMBOL 3 10 | #define PARSE_EMPTY_EXPRESSION 4 11 | 12 | // 0 = off, 1 = on 13 | extern unsigned int g_parse_debug; 14 | 15 | int match_brackets(char *s, vector_t *expr); 16 | int tokenize(vector_t *expr); 17 | void constants(vector_t expr); // cannot fail, inplace 18 | void implicit_multiply(vector_t *expr); // cannot fail, does create new vector 19 | void unary_neg(vector_t expr); // cannot fail, inplace 20 | 21 | int parse_expr(char *s, vector_t *expr); 22 | void parse_print_error(int err); 23 | 24 | #endif -------------------------------------------------------------------------------- /include/readline.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | readline.h 4 | 5 | is part of: 6 | 7 | WinEditLine (formerly MinGWEditLine) 8 | Copyright 2010-2020 Paolo Tosco 9 | All rights reserved. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions 13 | are met: 14 | 15 | * Redistributions of source code must retain the above copyright 16 | notice, this list of conditions and the following disclaimer. 17 | * Redistributions in binary form must reproduce the above copyright 18 | notice, this list of conditions and the following disclaimer in the 19 | documentation and/or other materials provided with the distribution. 20 | * Neither the name of WinEditLine (formerly MinGWEditLine) nor the 21 | name of its contributors may be used to endorse or promote products 22 | derived from this software without specific prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS 25 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 30 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 31 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 32 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 33 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | 36 | */ 37 | 38 | 39 | #ifndef _READLINE_H_ 40 | #define _READLINE_H_ 41 | 42 | #include 43 | 44 | /* 45 | these defines may be changed 46 | */ 47 | #define DEFAULT_HISTORY_SIZE 200 /* default number of history entries */ 48 | 49 | #ifdef __cplusplus 50 | extern "C" { 51 | #endif 52 | 53 | typedef char **rl_completion_func_t(const char *, int, int); 54 | typedef char *rl_compentry_func_t(const char *, int); 55 | typedef void rl_compentryfree_func_t(void *); 56 | /* 57 | this is ignored by WinEditLine 58 | */ 59 | typedef void *histdata_t; 60 | 61 | typedef struct _hist_entry { 62 | char *line; 63 | char *timestamp; 64 | histdata_t data; 65 | } HIST_ENTRY; 66 | 67 | typedef struct _hist_state { 68 | HIST_ENTRY **entries; 69 | int offset; 70 | int length; 71 | int size; 72 | int flags; 73 | } HISTORY_STATE; 74 | 75 | 76 | /* 77 | prototypes of functions which may be 78 | called by the user 79 | */ 80 | void source_editrc(); 81 | char *readline(const char *prompt); 82 | char **rl_completion_matches(const char *text, char *entry_func(const char *, int)); 83 | char *rl_filename_completion_function(const char *text, int state); 84 | void rl_free(void *mem); 85 | int using_history(); 86 | void free_history(); 87 | void free_history_entry(HIST_ENTRY *entry); 88 | void clear_history(); 89 | char *add_history(char *line); 90 | HIST_ENTRY *remove_history(int i); 91 | HIST_ENTRY *replace_history_entry(int i, char *line, histdata_t dummy); 92 | HIST_ENTRY **history_list(); 93 | int where_history(); 94 | int history_length(); 95 | HIST_ENTRY *current_history(); 96 | HIST_ENTRY *history_get(int offset); 97 | int history_set_pos(int i); 98 | HIST_ENTRY *previous_history(); 99 | HIST_ENTRY *next_history(); 100 | int read_history(const char *filename); 101 | int write_history(const char *filename); 102 | int append_history(int nelements, const char *filename); 103 | int history_truncate_file(const char *filename, int nlines); 104 | 105 | /* 106 | extern variables 107 | */ 108 | extern char *rl_line_buffer; 109 | extern char *rl_prompt; 110 | extern int rl_point; 111 | extern int rl_attempted_completion_over; 112 | extern int rl_completion_append_character; 113 | extern const char rl_basic_word_break_characters[]; 114 | extern const char *rl_completer_word_break_characters; 115 | extern const char *rl_readline_name; 116 | extern rl_completion_func_t *rl_attempted_completion_function; 117 | extern rl_compentry_func_t *rl_completion_entry_function; 118 | extern rl_compentryfree_func_t *rl_user_completion_entry_free_function; 119 | 120 | #ifdef __cplusplus 121 | } 122 | #endif 123 | 124 | #endif /* _READLINE_H_ */ 125 | -------------------------------------------------------------------------------- /include/stats.h: -------------------------------------------------------------------------------- 1 | #ifndef _INCLUDED_STATS_H 2 | #define _INCLUDED_STATS_H 3 | 4 | // one export, used to hook in to command.c 5 | void do_stats(char *s); 6 | 7 | #endif -------------------------------------------------------------------------------- /include/symbols.h: -------------------------------------------------------------------------------- 1 | #ifndef _INCLUDED_SYMBOLS_H 2 | #define _INCLUDED_SYMBOLS_H 3 | 4 | // Symbols with special handling 5 | #define SYM_ANS 0 6 | #define SYM_NEG 1 7 | 8 | // Basic operators 9 | #define SYM_ADD 2 10 | #define SYM_SUB 3 11 | #define SYM_MUL 4 12 | #define SYM_DIV 5 13 | #define SYM_MOD 6 14 | #define SYM_EXP 7 15 | #define SYM_POW 8 16 | #define SYM_FAC 9 17 | 18 | // Root operations 19 | #define SYM_SQRT 10 20 | #define SYM_CBRT 11 21 | #define SYM_ROOT 12 22 | 23 | // Logarithms 24 | #define SYM_LN 13 25 | #define SYM_LOG 14 26 | 27 | // Constants 28 | #define SYM_PI 15 29 | #define SYM_E 16 30 | #define SYM_TAU 17 31 | 32 | // Trig operations 33 | #define SYM_SIN 18 34 | #define SYM_COS 19 35 | #define SYM_TAN 20 36 | #define SYM_ASIN 21 37 | #define SYM_ACOS 22 38 | #define SYM_ATAN 23 39 | 40 | // sinh et al 41 | #define SYM_SINH 24 42 | #define SYM_COSH 25 43 | #define SYM_TANH 26 44 | #define SYM_ASINH 27 45 | #define SYM_ACOSH 28 46 | #define SYM_ATANH 29 47 | 48 | // Stats operations 49 | #define SYM_PERMU 30 50 | #define SYM_COMBI 31 51 | 52 | // Misc 53 | #define SYM_ABS 32 54 | 55 | // Recall operations (interact with memory) 56 | #define SYM_RCL1 33 57 | #define SYM_RCL2 34 58 | #define SYM_RCL3 35 59 | #define SYM_RCL4 36 60 | #define SYM_RCL5 37 61 | #define SYM_RCL6 38 62 | #define SYM_RCL7 39 63 | #define SYM_RCL8 40 64 | #define SYM_RCL9 41 65 | 66 | // Symbols added after v1.0 67 | #define SYM_2FAC 42 // double factorial 68 | 69 | #define SYM_MAX SYM_2FAC 70 | #define SYM_RCL_MIN SYM_RCL1 71 | #define SYM_RCL_MAX SYM_RCL9 72 | 73 | typedef struct { 74 | unsigned int sym; // the symbol referred to 75 | char str[7]; // the string that should parse as the symbol 76 | unsigned char len; // length 77 | } sym_str_t; 78 | 79 | extern const sym_str_t g_sym_str[]; 80 | extern const unsigned int g_sym_str_len; 81 | 82 | // translation table for display 83 | extern const char * const g_sym_names[]; 84 | 85 | #define SYMC_NOT_CONSTANT -1 86 | 87 | // constant symbols -> engine constants 88 | extern const char g_sym_const[]; 89 | 90 | #define SYMO_NOT_OPERATOR -1 91 | #define SYMO_UNARY_PREFIX 0 92 | #define SYMO_UNARY_POSTFIX 1 93 | #define SYMO_BINARY 2 94 | 95 | extern const char g_op_args[]; 96 | 97 | #define SYMP_NOT_OPERATOR 0xDEAD 98 | 99 | // lower is higher 100 | extern const unsigned int g_op_precedence[]; 101 | 102 | #define SYMA_NOT_OPERATOR -1 103 | #define SYMA_LEFT 0 104 | #define SYMA_RIGHT 1 105 | 106 | extern const char g_op_associativity[]; 107 | 108 | // this structures describes how to collect the arguments for an operator 109 | typedef struct { 110 | unsigned char len; // number of args 111 | char args[2]; // relative indices to pull args from 112 | char cleanup[2]; // relative indices to cleanup, compensating for shift 113 | char result; // after cleanup, relative index to replace with result 114 | } arg_collect_t; 115 | 116 | // indexed by SYMO values 117 | extern const arg_collect_t g_op_arg_collect[]; 118 | 119 | // OMG the actual math - took days to get this far, ha 120 | typedef int (op_func_t)(bf_t**, bf_t**); 121 | 122 | extern op_func_t * const g_op_funcs[]; 123 | 124 | #endif -------------------------------------------------------------------------------- /include/vector.h: -------------------------------------------------------------------------------- 1 | #ifndef _INCLUDED_VECTOR_H 2 | #define _INCLUDED_VECTOR_H 3 | 4 | typedef struct { 5 | unsigned int cap; // capacity of buffer 6 | unsigned int len; // number of elements actually in list 7 | void* buf[]; // the backing store 8 | } internal_vector_t; 9 | 10 | typedef internal_vector_t **vector_t; // use ** so we can resize it w/o caller intervention 11 | 12 | vector_t vector_new(); 13 | void vector_delete(vector_t a); 14 | 15 | unsigned int vector_get_len(vector_t a); 16 | 17 | void* vector_get(vector_t a, unsigned int i); 18 | void* vector_get_last(vector_t a); 19 | void vector_set(vector_t a, unsigned int i, void* x); 20 | 21 | void vector_add(vector_t a, void* x); 22 | void vector_remove(vector_t a, unsigned int x); 23 | 24 | #endif -------------------------------------------------------------------------------- /lib/libbf/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2020 Fabrice Bellard 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /lib/libbf/Makefile: -------------------------------------------------------------------------------- 1 | DEBUG= 2 | DEBUG=-D NDEBUG 3 | 4 | CC=gcc 5 | CFLAGS=-pie -std=c99 -ffunction-sections -fdata-sections -fno-asynchronous-unwind-tables -O2 $(DEBUG) 6 | 7 | .DEFAULT_GOAL := libbf.a 8 | 9 | ALL_OBJECTS=build/cutils.o build/libbf.o 10 | 11 | ifeq ($(OS),Windows_NT) 12 | DIR_GUARD=@if not exist build mkdir build 13 | PLATFORM_RMDIR=rd /q /s 14 | else 15 | DIR_GUARD=@mkdir -p build 16 | PLATFORM_RMDIR=rm -rf 17 | endif 18 | 19 | build/cutils.o : cutils.c cutils.h 20 | build/libbf.o : libbf.c libbf.h cutils.h 21 | 22 | $(ALL_OBJECTS) : 23 | $(DIR_GUARD) 24 | $(CC) $(CFLAGS) -o $@ -c $< 25 | 26 | libbf.a : $(ALL_OBJECTS) 27 | ar rcu $@ $^ 28 | ranlib $@ 29 | 30 | .PHONY : clean 31 | clean : 32 | $(PLATFORM_RMDIR) build 33 | -------------------------------------------------------------------------------- /lib/libbf/cutils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * C utilities 3 | * 4 | * Copyright (c) 2017 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "cutils.h" 29 | 30 | void pstrcpy(char *buf, int buf_size, const char *str) 31 | { 32 | int c; 33 | char *q = buf; 34 | 35 | if (buf_size <= 0) 36 | return; 37 | 38 | for(;;) { 39 | c = *str++; 40 | if (c == 0 || q >= buf + buf_size - 1) 41 | break; 42 | *q++ = c; 43 | } 44 | *q = '\0'; 45 | } 46 | 47 | /* strcat and truncate. */ 48 | char *pstrcat(char *buf, int buf_size, const char *s) 49 | { 50 | int len; 51 | len = strlen(buf); 52 | if (len < buf_size) 53 | pstrcpy(buf + len, buf_size - len, s); 54 | return buf; 55 | } 56 | 57 | int strstart(const char *str, const char *val, const char **ptr) 58 | { 59 | const char *p, *q; 60 | p = str; 61 | q = val; 62 | while (*q != '\0') { 63 | if (*p != *q) 64 | return 0; 65 | p++; 66 | q++; 67 | } 68 | if (ptr) 69 | *ptr = p; 70 | return 1; 71 | } 72 | 73 | void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func) 74 | { 75 | memset(s, 0, sizeof(*s)); 76 | s->opaque = opaque; 77 | s->realloc_func = realloc_func; 78 | } 79 | 80 | static void *dbuf_default_realloc(void *opaque, void *ptr, size_t size) 81 | { 82 | return realloc(ptr, size); 83 | } 84 | 85 | void dbuf_init(DynBuf *s) 86 | { 87 | dbuf_init2(s, NULL, dbuf_default_realloc); 88 | } 89 | 90 | /* return < 0 if error */ 91 | int dbuf_realloc(DynBuf *s, size_t new_size) 92 | { 93 | size_t size; 94 | uint8_t *new_buf; 95 | if (new_size > s->allocated_size) { 96 | if (s->error) 97 | return -1; 98 | size = s->allocated_size * 3 / 2; 99 | if (size > new_size) 100 | new_size = size; 101 | new_buf = s->realloc_func(s->opaque, s->buf, new_size); 102 | if (!new_buf) { 103 | s->error = TRUE; 104 | return -1; 105 | } 106 | s->buf = new_buf; 107 | s->allocated_size = new_size; 108 | } 109 | return 0; 110 | } 111 | 112 | int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len) 113 | { 114 | size_t end; 115 | end = offset + len; 116 | if (dbuf_realloc(s, end)) 117 | return -1; 118 | memcpy(s->buf + offset, data, len); 119 | if (end > s->size) 120 | s->size = end; 121 | return 0; 122 | } 123 | 124 | int dbuf_put(DynBuf *s, const uint8_t *data, size_t len) 125 | { 126 | if (unlikely((s->size + len) > s->allocated_size)) { 127 | if (dbuf_realloc(s, s->size + len)) 128 | return -1; 129 | } 130 | memcpy(s->buf + s->size, data, len); 131 | s->size += len; 132 | return 0; 133 | } 134 | 135 | int dbuf_putc(DynBuf *s, uint8_t c) 136 | { 137 | return dbuf_put(s, &c, 1); 138 | } 139 | 140 | int dbuf_putstr(DynBuf *s, const char *str) 141 | { 142 | return dbuf_put(s, (const uint8_t *)str, strlen(str)); 143 | } 144 | 145 | int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s, 146 | const char *fmt, ...) 147 | { 148 | va_list ap; 149 | char buf[128]; 150 | int len; 151 | 152 | va_start(ap, fmt); 153 | len = vsnprintf(buf, sizeof(buf), fmt, ap); 154 | va_end(ap); 155 | if (len < sizeof(buf)) { 156 | /* fast case */ 157 | return dbuf_put(s, (uint8_t *)buf, len); 158 | } else { 159 | if (dbuf_realloc(s, s->size + len + 1)) 160 | return -1; 161 | va_start(ap, fmt); 162 | vsnprintf((char *)(s->buf + s->size), s->allocated_size - s->size, 163 | fmt, ap); 164 | va_end(ap); 165 | s->size += len; 166 | } 167 | return 0; 168 | } 169 | 170 | void dbuf_free(DynBuf *s) 171 | { 172 | /* we test s->buf as a fail safe to avoid crashing if dbuf_free() 173 | is called twice */ 174 | if (s->buf) { 175 | s->realloc_func(s->opaque, s->buf, 0); 176 | } 177 | memset(s, 0, sizeof(*s)); 178 | } 179 | -------------------------------------------------------------------------------- /lib/libbf/cutils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * C utilities 3 | * 4 | * Copyright (c) 2017 Fabrice Bellard 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | */ 24 | #ifndef _CUTILS_H 25 | #define _CUTILS_H 26 | 27 | #include 28 | 29 | #define likely(x) __builtin_expect(!!(x), 1) 30 | #define unlikely(x) __builtin_expect(!!(x), 0) 31 | #define force_inline inline __attribute__((always_inline)) 32 | #define no_inline __attribute__((noinline)) 33 | #define __maybe_unused __attribute__((unused)) 34 | 35 | #define xglue(x, y) x ## y 36 | #define glue(x, y) xglue(x, y) 37 | #define stringify(s) tostring(s) 38 | #define tostring(s) #s 39 | 40 | #ifndef offsetof 41 | #define offsetof(type, field) ((size_t) &((type *)0)->field) 42 | #endif 43 | #define countof(x) (sizeof(x) / sizeof(x[0])) 44 | 45 | typedef int BOOL; 46 | 47 | enum { 48 | FALSE = 0, 49 | TRUE = 1, 50 | }; 51 | 52 | void pstrcpy(char *buf, int buf_size, const char *str); 53 | char *pstrcat(char *buf, int buf_size, const char *s); 54 | int strstart(const char *str, const char *val, const char **ptr); 55 | 56 | static inline int max_int(int a, int b) 57 | { 58 | if (a > b) 59 | return a; 60 | else 61 | return b; 62 | } 63 | 64 | static inline int min_int(int a, int b) 65 | { 66 | if (a < b) 67 | return a; 68 | else 69 | return b; 70 | } 71 | 72 | /* WARNING: undefined if a = 0 */ 73 | static inline int clz32(unsigned int a) 74 | { 75 | return __builtin_clz(a); 76 | } 77 | 78 | /* WARNING: undefined if a = 0 */ 79 | static inline int clz64(uint64_t a) 80 | { 81 | return __builtin_clzll(a); 82 | } 83 | 84 | /* WARNING: undefined if a = 0 */ 85 | static inline int ctz32(unsigned int a) 86 | { 87 | return __builtin_ctz(a); 88 | } 89 | 90 | /* WARNING: undefined if a = 0 */ 91 | static inline int ctz64(uint64_t a) 92 | { 93 | return __builtin_ctzll(a); 94 | } 95 | 96 | struct __attribute__((packed)) packed_u32 { 97 | uint32_t v; 98 | }; 99 | 100 | struct __attribute__((packed)) packed_u16 { 101 | uint16_t v; 102 | }; 103 | 104 | static inline uint32_t get_u32(const uint8_t *tab) 105 | { 106 | return ((struct packed_u32 *)tab)->v; 107 | } 108 | 109 | static inline void put_u32(uint8_t *tab, uint32_t val) 110 | { 111 | ((struct packed_u32 *)tab)->v = val; 112 | } 113 | 114 | static inline uint32_t get_u16(const uint8_t *tab) 115 | { 116 | return ((struct packed_u16 *)tab)->v; 117 | } 118 | 119 | static inline void put_u16(uint8_t *tab, uint16_t val) 120 | { 121 | ((struct packed_u16 *)tab)->v = val; 122 | } 123 | 124 | typedef void *DynBufReallocFunc(void *opaque, void *ptr, size_t size); 125 | 126 | typedef struct { 127 | uint8_t *buf; 128 | size_t size; 129 | size_t allocated_size; 130 | BOOL error; /* true if a memory allocation error occurred */ 131 | DynBufReallocFunc *realloc_func; 132 | void *opaque; /* for realloc_func */ 133 | } DynBuf; 134 | 135 | void dbuf_init(DynBuf *s); 136 | void dbuf_init2(DynBuf *s, void *opaque, DynBufReallocFunc *realloc_func); 137 | int dbuf_realloc(DynBuf *s, size_t new_size); 138 | int dbuf_write(DynBuf *s, size_t offset, const uint8_t *data, size_t len); 139 | int dbuf_put(DynBuf *s, const uint8_t *data, size_t len); 140 | int dbuf_putc(DynBuf *s, uint8_t c); 141 | int dbuf_putstr(DynBuf *s, const char *str); 142 | static inline int dbuf_put_u32(DynBuf *s, uint32_t val) 143 | { 144 | return dbuf_put(s, (uint8_t *)&val, 4); 145 | } 146 | static inline int dbuf_put_u16(DynBuf *s, uint16_t val) 147 | { 148 | return dbuf_put(s, (uint8_t *)&val, 2); 149 | } 150 | int __attribute__((format(printf, 2, 3))) dbuf_printf(DynBuf *s, 151 | const char *fmt, ...); 152 | void dbuf_free(DynBuf *s); 153 | static inline BOOL dbuf_error(DynBuf *s) { 154 | return s->error; 155 | } 156 | 157 | #endif 158 | -------------------------------------------------------------------------------- /lib/libedit/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2016, Paolo Tosco 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | 3. Neither the name of MinGWEditLine nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /lib/libedit/Makefile: -------------------------------------------------------------------------------- 1 | DEBUG= 2 | DEBUG=-D NDEBUG 3 | 4 | CC=gcc 5 | CFLAGS=-pie -std=c99 -ffunction-sections -fdata-sections -fno-asynchronous-unwind-tables -O2 $(DEBUG) -I . 6 | 7 | .DEFAULT_GOAL := libedit.a 8 | 9 | ALL_OBJECTS=build/history.o build/fn_complete.o build/editline.o 10 | 11 | DIR_GUARD=@if not exist build mkdir build 12 | 13 | build/history.o : history.c editline/readline.h editline/wineditline.h 14 | build/fn_complete.o : fn_complete.c editline/readline.h editline/wineditline.h 15 | build/editline.o : editline.c el_globals.h editline/readline.h editline/wineditline.h 16 | 17 | $(ALL_OBJECTS) : 18 | $(DIR_GUARD) 19 | $(CC) $(CFLAGS) -o $@ -c $< 20 | 21 | libedit.a : $(ALL_OBJECTS) 22 | ar rcu $@ $^ 23 | ranlib $@ 24 | 25 | .PHONY : clean 26 | clean : 27 | rd /q /s build 28 | -------------------------------------------------------------------------------- /lib/libedit/editline/readline.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | readline.h 4 | 5 | is part of: 6 | 7 | WinEditLine (formerly MinGWEditLine) 8 | Copyright 2010-2020 Paolo Tosco 9 | All rights reserved. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions 13 | are met: 14 | 15 | * Redistributions of source code must retain the above copyright 16 | notice, this list of conditions and the following disclaimer. 17 | * Redistributions in binary form must reproduce the above copyright 18 | notice, this list of conditions and the following disclaimer in the 19 | documentation and/or other materials provided with the distribution. 20 | * Neither the name of WinEditLine (formerly MinGWEditLine) nor the 21 | name of its contributors may be used to endorse or promote products 22 | derived from this software without specific prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS 25 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 30 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 31 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 32 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 33 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | 36 | */ 37 | 38 | 39 | #ifndef _READLINE_H_ 40 | #define _READLINE_H_ 41 | 42 | #include 43 | 44 | /* 45 | these defines may be changed 46 | */ 47 | #define DEFAULT_HISTORY_SIZE 200 /* default number of history entries */ 48 | 49 | #ifdef __cplusplus 50 | extern "C" { 51 | #endif 52 | 53 | typedef char **rl_completion_func_t(const char *, int, int); 54 | typedef char *rl_compentry_func_t(const char *, int); 55 | typedef void rl_compentryfree_func_t(void *); 56 | /* 57 | this is ignored by WinEditLine 58 | */ 59 | typedef void *histdata_t; 60 | 61 | typedef struct _hist_entry { 62 | char *line; 63 | char *timestamp; 64 | histdata_t data; 65 | } HIST_ENTRY; 66 | 67 | typedef struct _hist_state { 68 | HIST_ENTRY **entries; 69 | int offset; 70 | int length; 71 | int size; 72 | int flags; 73 | } HISTORY_STATE; 74 | 75 | 76 | /* 77 | prototypes of functions which may be 78 | called by the user 79 | */ 80 | void source_editrc(); 81 | char *readline(const char *prompt); 82 | char **rl_completion_matches(const char *text, char *entry_func(const char *, int)); 83 | char *rl_filename_completion_function(const char *text, int state); 84 | void rl_free(void *mem); 85 | int using_history(); 86 | void free_history(); 87 | void free_history_entry(HIST_ENTRY *entry); 88 | void clear_history(); 89 | char *add_history(char *line); 90 | HIST_ENTRY *remove_history(int i); 91 | HIST_ENTRY *replace_history_entry(int i, char *line, histdata_t dummy); 92 | HIST_ENTRY **history_list(); 93 | int where_history(); 94 | int history_length(); 95 | HIST_ENTRY *current_history(); 96 | HIST_ENTRY *history_get(int offset); 97 | int history_set_pos(int i); 98 | HIST_ENTRY *previous_history(); 99 | HIST_ENTRY *next_history(); 100 | int read_history(const char *filename); 101 | int write_history(const char *filename); 102 | int append_history(int nelements, const char *filename); 103 | int history_truncate_file(const char *filename, int nlines); 104 | 105 | /* 106 | extern variables 107 | */ 108 | extern char *rl_line_buffer; 109 | extern char *rl_prompt; 110 | extern int rl_point; 111 | extern int rl_attempted_completion_over; 112 | extern int rl_completion_append_character; 113 | extern const char rl_basic_word_break_characters[]; 114 | extern const char *rl_completer_word_break_characters; 115 | extern const char *rl_readline_name; 116 | extern rl_completion_func_t *rl_attempted_completion_function; 117 | extern rl_compentry_func_t *rl_completion_entry_function; 118 | extern rl_compentryfree_func_t *rl_user_completion_entry_free_function; 119 | 120 | #ifdef __cplusplus 121 | } 122 | #endif 123 | 124 | #endif /* _READLINE_H_ */ 125 | -------------------------------------------------------------------------------- /lib/libedit/editline/wineditline.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | wineditline.h 4 | 5 | is part of: 6 | 7 | WinEditLine (formerly MinGWEditLine) 8 | Copyright 2010-2020 Paolo Tosco 9 | All rights reserved. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions 13 | are met: 14 | 15 | * Redistributions of source code must retain the above copyright 16 | notice, this list of conditions and the following disclaimer. 17 | * Redistributions in binary form must reproduce the above copyright 18 | notice, this list of conditions and the following disclaimer in the 19 | documentation and/or other materials provided with the distribution. 20 | * Neither the name of WinEditLine (formerly MinGWEditLine) nor the 21 | name of its contributors may be used to endorse or promote products 22 | derived from this software without specific prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS 25 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 30 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 31 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 32 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 33 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | 36 | */ 37 | 38 | 39 | #ifndef _WINEDITLINE_H_ 40 | #define _WINEDITLINE_H_ 41 | 42 | #include 43 | 44 | /* 45 | these defines may be changed 46 | */ 47 | #define _EL_BUF_LEN 4096 /* line buffer size increment */ 48 | 49 | /* 50 | these defines should not be mangled 51 | */ 52 | #define _EL_CONSOLE_BUF_LEN 8 53 | #define _EL_MIN_HIST_SIZE 1 54 | #define _EL_ENV_BUF_LEN 64 55 | #define _EL_MAX_FILE_BREAK_CHARACTERS 64 56 | #define _EL_BASIC_FILE_BREAK_CHARACTERS _T(" \"\t\n=><|") 57 | #define _EL_BASIC_FILE_QUOTE_CHARACTERS _T(" $;=&") 58 | 59 | /* 60 | these are included because for some reason 61 | they are missing from MinGW gcc 4.5.0 62 | */ 63 | #ifndef ENABLE_EXTENDED_FLAGS 64 | #define ENABLE_EXTENDED_FLAGS 0x0080 65 | #endif 66 | #ifndef ENABLE_INSERT_MODE 67 | #define ENABLE_INSERT_MODE 0x0020 68 | #endif 69 | #ifndef ENABLE_QUICK_EDIT_MODE 70 | #define ENABLE_QUICK_EDIT_MODE 0x0040 71 | #endif 72 | 73 | 74 | #ifdef __cplusplus 75 | extern "C" { 76 | #endif 77 | 78 | /* 79 | prototypes of internal functions 80 | */ 81 | char **_el_alloc_array(int n, int size); 82 | wchar_t *_el_mb2w(char *mb, wchar_t **w); 83 | char *_el_w2mb(wchar_t *w, char **mb); 84 | int _el_grow_buffers(size_t size); 85 | void _el_free_array(void *array); 86 | void _el_clean_exit(); 87 | int _el_insert_char(wchar_t *buf, int n); 88 | int _el_delete_char(UINT32 vk, int n); 89 | void _el_add_char(wchar_t *string, wchar_t c, int n); 90 | int _el_pad(CONSOLE_SCREEN_BUFFER_INFO *sbInfo, wchar_t *_el_temp_print); 91 | int _el_print_string(wchar_t *string); 92 | int _el_move_cursor(UINT32 vk, UINT32 ctrl); 93 | int _el_set_cursor(int offset); 94 | void _el_remove_tail_spaces(char *line); 95 | wchar_t *_el_get_compl_text(int *start, int *end); 96 | int _el_check_root_identity(wchar_t *root, wchar_t *entry_name); 97 | int _el_fn_qsort_string_compare(const void *i1, const void *i2); 98 | void _el_display_history(); 99 | int _el_find_history_file(const char *filename, wchar_t **name); 100 | int _el_write_history_helper(const char *filename, const wchar_t *mode, int nelements); 101 | int _el_display_prev_hist(); 102 | int _el_display_next_hist(); 103 | int _el_display_first_hist(); 104 | int _el_display_last_hist(); 105 | HIST_ENTRY *_el_previous_history(); 106 | HIST_ENTRY *_el_next_history(); 107 | int _el_history_set_pos(int i); 108 | BOOL _el_signal_handler(DWORD fdwCtrlType); 109 | BOOL _el_replace_char(wchar_t *string, wchar_t src, wchar_t dest); 110 | 111 | extern wchar_t *_el_line_buffer; 112 | extern wchar_t *_el_print; 113 | extern wchar_t *_el_temp_print; 114 | extern wchar_t *_el_next_compl; 115 | extern wchar_t *_el_file_name; 116 | extern wchar_t *_el_dir_name; 117 | extern wchar_t *_el_old_arg; 118 | extern wchar_t *_el_wide; 119 | extern wchar_t *_el_text; 120 | extern char *_el_text_mb; 121 | extern wchar_t *_el_prompt; 122 | extern wchar_t **_el_compl_array; 123 | extern wchar_t *_el_basic_word_break_characters; 124 | extern wchar_t *_el_completer_word_break_characters; 125 | extern wchar_t _el_basic_file_break_characters[_EL_MAX_FILE_BREAK_CHARACTERS]; 126 | extern int _el_ctrl_c_pressed; 127 | extern int _el_compl_index; 128 | extern int _el_n_compl; 129 | extern int _el_prompt_len; 130 | extern BOOL _el_prev_in_cm_saved; 131 | extern BOOL _el_prev_out_cm_saved; 132 | extern DWORD _el_prev_in_cm; 133 | extern DWORD _el_prev_out_cm; 134 | extern HANDLE _el_h_in; 135 | extern HANDLE _el_h_out; 136 | extern COORD _el_prev_size; 137 | 138 | #ifdef __cplusplus 139 | } 140 | #endif 141 | 142 | #endif /* _WINEDITLINE_H_ */ 143 | -------------------------------------------------------------------------------- /lib/libedit/el_globals.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | el_globals.h 4 | 5 | is part of: 6 | 7 | WinEditLine (formerly MinGWEditLine) 8 | Copyright 2010-2020 Paolo Tosco 9 | All rights reserved. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions 13 | are met: 14 | 15 | * Redistributions of source code must retain the above copyright 16 | notice, this list of conditions and the following disclaimer. 17 | * Redistributions in binary form must reproduce the above copyright 18 | notice, this list of conditions and the following disclaimer in the 19 | documentation and/or other materials provided with the distribution. 20 | * Neither the name of WinEditLine (formerly MinGWEditLine) nor the 21 | name of its contributors may be used to endorse or promote products 22 | derived from this software without specific prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS 25 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 30 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 31 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 32 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 33 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | 36 | */ 37 | 38 | 39 | #define _UNICODE 40 | #define UNICODE 41 | 42 | const char *rl_readline_name = NULL; 43 | wchar_t *_el_print = NULL; 44 | wchar_t *_el_temp_print = NULL; 45 | size_t _el_temp_print_size = 0; 46 | wchar_t *_el_next_compl = NULL; 47 | wchar_t *_el_file_name = NULL; 48 | wchar_t *_el_dir_name = NULL; 49 | wchar_t *_el_old_arg = NULL; 50 | wchar_t *_el_wide = NULL; 51 | wchar_t *_el_text = NULL; 52 | wchar_t *_el_line_buffer = NULL; 53 | size_t _el_line_buffer_size = 0; 54 | wchar_t *_el_basic_word_break_characters = NULL; 55 | wchar_t *_el_completer_word_break_characters = NULL; 56 | wchar_t _el_basic_file_break_characters[_EL_MAX_FILE_BREAK_CHARACTERS]; 57 | char *rl_line_buffer = NULL; 58 | char *rl_prompt = NULL; 59 | const char rl_basic_word_break_characters[] = " \t\n\\'`@$><=;|&{("; 60 | const char *rl_completer_word_break_characters = NULL; 61 | char *_el_text_mb = NULL; 62 | wchar_t *_el_prompt = NULL; 63 | wchar_t **_el_compl_array = NULL; 64 | int _el_ctrl_c_pressed = FALSE; 65 | int rl_point = 0; 66 | int rl_attempted_completion_over = 0; 67 | int rl_completion_append_character = ' '; 68 | int _el_compl_index = 0; 69 | int _el_n_compl = 0; 70 | int _el_prompt_len = 0; 71 | rl_completion_func_t *rl_attempted_completion_function = NULL; 72 | rl_compentry_func_t *rl_completion_entry_function = NULL; 73 | rl_compentryfree_func_t *rl_user_completion_entry_free_function = NULL; 74 | BOOL _el_prev_in_cm_saved = FALSE; 75 | BOOL _el_prev_out_cm_saved = FALSE; 76 | BOOL _el_prev_sbInfo_saved = FALSE; 77 | DWORD _el_prev_in_cm = 0; 78 | DWORD _el_prev_out_cm = 0; 79 | HANDLE _el_h_in = NULL; 80 | HANDLE _el_h_out = NULL; 81 | COORD _el_prev_size; 82 | -------------------------------------------------------------------------------- /lib/libedit/histedit.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | histedit.h 4 | 5 | is part of: 6 | 7 | WinEditLine (formerly MinGWEditLine) 8 | Copyright 2010-2020 Paolo Tosco 9 | All rights reserved. 10 | 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions 13 | are met: 14 | 15 | * Redistributions of source code must retain the above copyright 16 | notice, this list of conditions and the following disclaimer. 17 | * Redistributions in binary form must reproduce the above copyright 18 | notice, this list of conditions and the following disclaimer in the 19 | documentation and/or other materials provided with the distribution. 20 | * Neither the name of WinEditLine (formerly MinGWEditLine) nor the 21 | name of its contributors may be used to endorse or promote products 22 | derived from this software without specific prior written permission. 23 | 24 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS 25 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 26 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 27 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 28 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 29 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 30 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 31 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 32 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 33 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 | 36 | */ 37 | 38 | 39 | #ifndef _HISTEDIT_H_ 40 | #define _HISTEDIT_H_ 41 | #endif /* _HISTEDIT_H_ */ 42 | -------------------------------------------------------------------------------- /lib/libminini/LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | 7 | EXCEPTION TO THE APACHE 2.0 LICENSE 8 | 9 | As a special exception to the Apache License 2.0 (and referring to the 10 | definitions in Section 1 of this license), you may link, statically or 11 | dynamically, the "Work" to other modules to produce an executable file 12 | containing portions of the "Work", and distribute that executable file 13 | in "Object" form under the terms of your choice, without any of the 14 | additional requirements listed in Section 4 of the Apache License 2.0. 15 | This exception applies only to redistributions in "Object" form (not 16 | "Source" form) and only if no modifications have been made to the "Work". 17 | 18 | 19 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 20 | 21 | 1. Definitions. 22 | 23 | "License" shall mean the terms and conditions for use, reproduction, 24 | and distribution as defined by Sections 1 through 9 of this document. 25 | 26 | "Licensor" shall mean the copyright owner or entity authorized by 27 | the copyright owner that is granting the License. 28 | 29 | "Legal Entity" shall mean the union of the acting entity and all 30 | other entities that control, are controlled by, or are under common 31 | control with that entity. For the purposes of this definition, 32 | "control" means (i) the power, direct or indirect, to cause the 33 | direction or management of such entity, whether by contract or 34 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 35 | outstanding shares, or (iii) beneficial ownership of such entity. 36 | 37 | "You" (or "Your") shall mean an individual or Legal Entity 38 | exercising permissions granted by this License. 39 | 40 | "Source" form shall mean the preferred form for making modifications, 41 | including but not limited to software source code, documentation 42 | source, and configuration files. 43 | 44 | "Object" form shall mean any form resulting from mechanical 45 | transformation or translation of a Source form, including but 46 | not limited to compiled object code, generated documentation, 47 | and conversions to other media types. 48 | 49 | "Work" shall mean the work of authorship, whether in Source or 50 | Object form, made available under the License, as indicated by a 51 | copyright notice that is included in or attached to the work 52 | (an example is provided in the Appendix below). 53 | 54 | "Derivative Works" shall mean any work, whether in Source or Object 55 | form, that is based on (or derived from) the Work and for which the 56 | editorial revisions, annotations, elaborations, or other modifications 57 | represent, as a whole, an original work of authorship. For the purposes 58 | of this License, Derivative Works shall not include works that remain 59 | separable from, or merely link (or bind by name) to the interfaces of, 60 | the Work and Derivative Works thereof. 61 | 62 | "Contribution" shall mean any work of authorship, including 63 | the original version of the Work and any modifications or additions 64 | to that Work or Derivative Works thereof, that is intentionally 65 | submitted to Licensor for inclusion in the Work by the copyright owner 66 | or by an individual or Legal Entity authorized to submit on behalf of 67 | the copyright owner. For the purposes of this definition, "submitted" 68 | means any form of electronic, verbal, or written communication sent 69 | to the Licensor or its representatives, including but not limited to 70 | communication on electronic mailing lists, source code control systems, 71 | and issue tracking systems that are managed by, or on behalf of, the 72 | Licensor for the purpose of discussing and improving the Work, but 73 | excluding communication that is conspicuously marked or otherwise 74 | designated in writing by the copyright owner as "Not a Contribution." 75 | 76 | "Contributor" shall mean Licensor and any individual or Legal Entity 77 | on behalf of whom a Contribution has been received by Licensor and 78 | subsequently incorporated within the Work. 79 | 80 | 2. Grant of Copyright License. Subject to the terms and conditions of 81 | this License, each Contributor hereby grants to You a perpetual, 82 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 83 | copyright license to reproduce, prepare Derivative Works of, 84 | publicly display, publicly perform, sublicense, and distribute the 85 | Work and such Derivative Works in Source or Object form. 86 | 87 | 3. Grant of Patent License. Subject to the terms and conditions of 88 | this License, each Contributor hereby grants to You a perpetual, 89 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 90 | (except as stated in this section) patent license to make, have made, 91 | use, offer to sell, sell, import, and otherwise transfer the Work, 92 | where such license applies only to those patent claims licensable 93 | by such Contributor that are necessarily infringed by their 94 | Contribution(s) alone or by combination of their Contribution(s) 95 | with the Work to which such Contribution(s) was submitted. If You 96 | institute patent litigation against any entity (including a 97 | cross-claim or counterclaim in a lawsuit) alleging that the Work 98 | or a Contribution incorporated within the Work constitutes direct 99 | or contributory patent infringement, then any patent licenses 100 | granted to You under this License for that Work shall terminate 101 | as of the date such litigation is filed. 102 | 103 | 4. Redistribution. You may reproduce and distribute copies of the 104 | Work or Derivative Works thereof in any medium, with or without 105 | modifications, and in Source or Object form, provided that You 106 | meet the following conditions: 107 | 108 | (a) You must give any other recipients of the Work or 109 | Derivative Works a copy of this License; and 110 | 111 | (b) You must cause any modified files to carry prominent notices 112 | stating that You changed the files; and 113 | 114 | (c) You must retain, in the Source form of any Derivative Works 115 | that You distribute, all copyright, patent, trademark, and 116 | attribution notices from the Source form of the Work, 117 | excluding those notices that do not pertain to any part of 118 | the Derivative Works; and 119 | 120 | (d) If the Work includes a "NOTICE" text file as part of its 121 | distribution, then any Derivative Works that You distribute must 122 | include a readable copy of the attribution notices contained 123 | within such NOTICE file, excluding those notices that do not 124 | pertain to any part of the Derivative Works, in at least one 125 | of the following places: within a NOTICE text file distributed 126 | as part of the Derivative Works; within the Source form or 127 | documentation, if provided along with the Derivative Works; or, 128 | within a display generated by the Derivative Works, if and 129 | wherever such third-party notices normally appear. The contents 130 | of the NOTICE file are for informational purposes only and 131 | do not modify the License. You may add Your own attribution 132 | notices within Derivative Works that You distribute, alongside 133 | or as an addendum to the NOTICE text from the Work, provided 134 | that such additional attribution notices cannot be construed 135 | as modifying the License. 136 | 137 | You may add Your own copyright statement to Your modifications and 138 | may provide additional or different license terms and conditions 139 | for use, reproduction, or distribution of Your modifications, or 140 | for any such Derivative Works as a whole, provided Your use, 141 | reproduction, and distribution of the Work otherwise complies with 142 | the conditions stated in this License. 143 | 144 | 5. Submission of Contributions. Unless You explicitly state otherwise, 145 | any Contribution intentionally submitted for inclusion in the Work 146 | by You to the Licensor shall be under the terms and conditions of 147 | this License, without any additional terms or conditions. 148 | Notwithstanding the above, nothing herein shall supersede or modify 149 | the terms of any separate license agreement you may have executed 150 | with Licensor regarding such Contributions. 151 | 152 | 6. Trademarks. This License does not grant permission to use the trade 153 | names, trademarks, service marks, or product names of the Licensor, 154 | except as required for reasonable and customary use in describing the 155 | origin of the Work and reproducing the content of the NOTICE file. 156 | 157 | 7. Disclaimer of Warranty. Unless required by applicable law or 158 | agreed to in writing, Licensor provides the Work (and each 159 | Contributor provides its Contributions) on an "AS IS" BASIS, 160 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 161 | implied, including, without limitation, any warranties or conditions 162 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 163 | PARTICULAR PURPOSE. You are solely responsible for determining the 164 | appropriateness of using or redistributing the Work and assume any 165 | risks associated with Your exercise of permissions under this License. 166 | 167 | 8. Limitation of Liability. In no event and under no legal theory, 168 | whether in tort (including negligence), contract, or otherwise, 169 | unless required by applicable law (such as deliberate and grossly 170 | negligent acts) or agreed to in writing, shall any Contributor be 171 | liable to You for damages, including any direct, indirect, special, 172 | incidental, or consequential damages of any character arising as a 173 | result of this License or out of the use or inability to use the 174 | Work (including but not limited to damages for loss of goodwill, 175 | work stoppage, computer failure or malfunction, or any and all 176 | other commercial damages or losses), even if such Contributor 177 | has been advised of the possibility of such damages. 178 | 179 | 9. Accepting Warranty or Additional Liability. While redistributing 180 | the Work or Derivative Works thereof, You may choose to offer, 181 | and charge a fee for, acceptance of support, warranty, indemnity, 182 | or other liability obligations and/or rights consistent with this 183 | License. However, in accepting such obligations, You may act only 184 | on Your own behalf and on Your sole responsibility, not on behalf 185 | of any other Contributor, and only if You agree to indemnify, 186 | defend, and hold each Contributor harmless for any liability 187 | incurred by, or claims asserted against, such Contributor by reason 188 | of your accepting any such warranty or additional liability. 189 | -------------------------------------------------------------------------------- /lib/libminini/Makefile: -------------------------------------------------------------------------------- 1 | DEBUG= 2 | DEBUG=-D NDEBUG 3 | 4 | CC=gcc 5 | CFLAGS=-pie -std=c99 -ffunction-sections -fdata-sections -fno-asynchronous-unwind-tables -O2 $(DEBUG) 6 | 7 | .DEFAULT_GOAL := libminini.a 8 | 9 | ALL_OBJECTS=build/minIni.o 10 | 11 | ifeq ($(OS),Windows_NT) 12 | DIR_GUARD=@if not exist build mkdir build 13 | PLATFORM_RMDIR=rd /q /s 14 | else 15 | DIR_GUARD=@mkdir -p build 16 | PLATFORM_RMDIR=rm -rf 17 | endif 18 | 19 | build/minIni.o : minIni.c minIni.h minGlue.h 20 | 21 | $(ALL_OBJECTS) : 22 | $(DIR_GUARD) 23 | $(CC) $(CFLAGS) -o $@ -c $< 24 | 25 | libminini.a : $(ALL_OBJECTS) 26 | ar rcu $@ $^ 27 | ranlib $@ 28 | 29 | .PHONY : clean 30 | clean : 31 | $(PLATFORM_RMDIR) build 32 | -------------------------------------------------------------------------------- /lib/libminini/minGlue.h: -------------------------------------------------------------------------------- 1 | /* Glue functions for the minIni library, based on the C/C++ stdio library 2 | * 3 | * Or better said: this file contains macros that maps the function interface 4 | * used by minIni to the standard C/C++ file I/O functions. 5 | * 6 | * By CompuPhase, 2008-2012 7 | * This "glue file" is in the public domain. It is distributed without 8 | * warranties or conditions of any kind, either express or implied. 9 | */ 10 | 11 | /* map required file I/O types and functions to the standard C library */ 12 | #include 13 | 14 | // no unicode support 15 | #define INI_ANSIONLY 16 | 17 | #define INI_FILETYPE FILE* 18 | #define ini_openread(filename,file) ((*(file) = fopen((filename),"rb")) != NULL) 19 | #define ini_openwrite(filename,file) ((*(file) = fopen((filename),"wb")) != NULL) 20 | #define ini_close(file) (fclose(*(file)) == 0) 21 | #define ini_read(buffer,size,file) (fgets((buffer),(size),*(file)) != NULL) 22 | #define ini_write(buffer,file) (fputs((buffer),*(file)) >= 0) 23 | #define ini_rename(source,dest) (rename((source), (dest)) == 0) 24 | #define ini_remove(filename) (remove(filename) == 0) 25 | 26 | #define INI_FILEPOS fpos_t 27 | #define ini_tell(file,pos) (fgetpos(*(file), (pos)) == 0) 28 | #define ini_seek(file,pos) (fsetpos(*(file), (pos)) == 0) 29 | 30 | // no floating point support -------------------------------------------------------------------------------- /lib/libminini/minIni.h: -------------------------------------------------------------------------------- 1 | /* minIni - Multi-Platform INI file parser, suitable for embedded systems 2 | * 3 | * Copyright (c) CompuPhase, 2008-2012 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not 6 | * use this file except in compliance with the License. You may obtain a copy 7 | * of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14 | * License for the specific language governing permissions and limitations 15 | * under the License. 16 | * 17 | * Version: $Id: minIni.h 44 2012-01-04 15:52:56Z thiadmer.riemersma@gmail.com $ 18 | */ 19 | #ifndef MININI_H 20 | #define MININI_H 21 | 22 | #include "minGlue.h" 23 | 24 | #if (defined _UNICODE || defined __UNICODE__ || defined UNICODE) && !defined MININI_ANSI 25 | #include 26 | #define mTCHAR TCHAR 27 | #else 28 | /* force TCHAR to be "char", but only for minIni */ 29 | #define mTCHAR char 30 | #endif 31 | 32 | #if !defined INI_BUFFERSIZE 33 | #define INI_BUFFERSIZE 512 34 | #endif 35 | 36 | #if defined __cplusplus 37 | extern "C" { 38 | #endif 39 | 40 | int ini_getbool(const mTCHAR *Section, const mTCHAR *Key, int DefValue, const mTCHAR *Filename); 41 | long ini_getl(const mTCHAR *Section, const mTCHAR *Key, long DefValue, const mTCHAR *Filename); 42 | int ini_gets(const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *DefValue, mTCHAR *Buffer, int BufferSize, const mTCHAR *Filename); 43 | int ini_getsection(int idx, mTCHAR *Buffer, int BufferSize, const mTCHAR *Filename); 44 | int ini_getkey(const mTCHAR *Section, int idx, mTCHAR *Buffer, int BufferSize, const mTCHAR *Filename); 45 | 46 | #if defined INI_REAL 47 | INI_REAL ini_getf(const mTCHAR *Section, const mTCHAR *Key, INI_REAL DefValue, const mTCHAR *Filename); 48 | #endif 49 | 50 | #if !defined INI_READONLY 51 | int ini_putl(const mTCHAR *Section, const mTCHAR *Key, long Value, const mTCHAR *Filename); 52 | int ini_puts(const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *Value, const mTCHAR *Filename); 53 | #if defined INI_REAL 54 | int ini_putf(const mTCHAR *Section, const mTCHAR *Key, INI_REAL Value, const mTCHAR *Filename); 55 | #endif 56 | #endif /* INI_READONLY */ 57 | 58 | #if !defined INI_NOBROWSE 59 | typedef int (*INI_CALLBACK)(const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *Value, const void *UserData); 60 | int ini_browse(INI_CALLBACK Callback, const void *UserData, const mTCHAR *Filename); 61 | #endif /* INI_NOBROWSE */ 62 | 63 | #if defined __cplusplus 64 | } 65 | #endif 66 | 67 | 68 | #if defined __cplusplus 69 | 70 | #if defined __WXWINDOWS__ 71 | #include "wxMinIni.h" 72 | #else 73 | #include 74 | 75 | /* The C++ class in minIni.h was contributed by Steven Van Ingelgem. */ 76 | class minIni 77 | { 78 | public: 79 | minIni(const std::string& filename) : iniFilename(filename) 80 | { } 81 | 82 | bool getbool(const std::string& Section, const std::string& Key, bool DefValue=false) const 83 | { return ini_getbool(Section.c_str(), Key.c_str(), int(DefValue), iniFilename.c_str()) != 0; } 84 | 85 | long getl(const std::string& Section, const std::string& Key, long DefValue=0) const 86 | { return ini_getl(Section.c_str(), Key.c_str(), DefValue, iniFilename.c_str()); } 87 | 88 | int geti(const std::string& Section, const std::string& Key, int DefValue=0) const 89 | { return static_cast(this->getl(Section, Key, long(DefValue))); } 90 | 91 | std::string gets(const std::string& Section, const std::string& Key, const std::string& DefValue="") const 92 | { 93 | char buffer[INI_BUFFERSIZE]; 94 | ini_gets(Section.c_str(), Key.c_str(), DefValue.c_str(), buffer, INI_BUFFERSIZE, iniFilename.c_str()); 95 | return buffer; 96 | } 97 | 98 | std::string getsection(int idx) const 99 | { 100 | char buffer[INI_BUFFERSIZE]; 101 | ini_getsection(idx, buffer, INI_BUFFERSIZE, iniFilename.c_str()); 102 | return buffer; 103 | } 104 | 105 | std::string getkey(const std::string& Section, int idx) const 106 | { 107 | char buffer[INI_BUFFERSIZE]; 108 | ini_getkey(Section.c_str(), idx, buffer, INI_BUFFERSIZE, iniFilename.c_str()); 109 | return buffer; 110 | } 111 | 112 | #if defined INI_REAL 113 | INI_REAL getf(const std::string& Section, const std::string& Key, INI_REAL DefValue=0) const 114 | { return ini_getf(Section.c_str(), Key.c_str(), DefValue, iniFilename.c_str()); } 115 | #endif 116 | 117 | #if ! defined INI_READONLY 118 | bool put(const std::string& Section, const std::string& Key, long Value) const 119 | { return ini_putl(Section.c_str(), Key.c_str(), Value, iniFilename.c_str()) != 0; } 120 | 121 | bool put(const std::string& Section, const std::string& Key, int Value) const 122 | { return ini_putl(Section.c_str(), Key.c_str(), (long)Value, iniFilename.c_str()) != 0; } 123 | 124 | bool put(const std::string& Section, const std::string& Key, bool Value) const 125 | { return ini_putl(Section.c_str(), Key.c_str(), (long)Value, iniFilename.c_str()) != 0; } 126 | 127 | bool put(const std::string& Section, const std::string& Key, const std::string& Value) const 128 | { return ini_puts(Section.c_str(), Key.c_str(), Value.c_str(), iniFilename.c_str()) != 0; } 129 | 130 | bool put(const std::string& Section, const std::string& Key, const char* Value) const 131 | { return ini_puts(Section.c_str(), Key.c_str(), Value, iniFilename.c_str()) != 0; } 132 | 133 | #if defined INI_REAL 134 | bool put(const std::string& Section, const std::string& Key, INI_REAL Value) const 135 | { return ini_putf(Section.c_str(), Key.c_str(), Value, iniFilename.c_str()) != 0; } 136 | #endif 137 | 138 | bool del(const std::string& Section, const std::string& Key) const 139 | { return ini_puts(Section.c_str(), Key.c_str(), 0, iniFilename.c_str()) != 0; } 140 | 141 | bool del(const std::string& Section) const 142 | { return ini_puts(Section.c_str(), 0, 0, iniFilename.c_str()) != 0; } 143 | #endif 144 | 145 | private: 146 | std::string iniFilename; 147 | }; 148 | 149 | #endif /* __WXWINDOWS__ */ 150 | #endif /* __cplusplus */ 151 | 152 | #endif /* MININI_H */ 153 | -------------------------------------------------------------------------------- /lib/libminini/minIni.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startrekdude/EnderCalc/a6fbbd8c85ddeb47c555183d9b09752aecbf3f83/lib/libminini/minIni.pdf -------------------------------------------------------------------------------- /reference.odt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startrekdude/EnderCalc/a6fbbd8c85ddeb47c555183d9b09752aecbf3f83/reference.odt -------------------------------------------------------------------------------- /reference.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startrekdude/EnderCalc/a6fbbd8c85ddeb47c555183d9b09752aecbf3f83/reference.pdf -------------------------------------------------------------------------------- /rsrc/EnderCalc.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/startrekdude/EnderCalc/a6fbbd8c85ddeb47c555183d9b09752aecbf3f83/rsrc/EnderCalc.ico -------------------------------------------------------------------------------- /rsrc/icon.rc: -------------------------------------------------------------------------------- 1 | 1 ICON "EnderCalc.ico" -------------------------------------------------------------------------------- /rsrc/version.rc: -------------------------------------------------------------------------------- 1 | 1 VERSIONINFO 2 | FILEVERSION 1,3,0,0 3 | PRODUCTVERSION 1,3,0,0 4 | FILEFLAGSMASK 0x0003f 5 | FILEFLAGS 0 6 | FILEOS 0x40004 7 | FILETYPE 1 8 | FILESUBTYPE 0 9 | { 10 | BLOCK "StringFileInfo" 11 | { 12 | BLOCK "04090000" 13 | { 14 | VALUE "CompanyName" , "Sam Haskins" 15 | VALUE "FileDescription" , "A simple scientific calculator" 16 | VALUE "FileVersion" , "1.3" 17 | VALUE "InternalName" , "EnderCalc" 18 | VALUE "LegalCopyright" , "(C) Sam Haskins 2020" 19 | VALUE "OriginalFilename" , "EnderCalc.exe" 20 | VALUE "ProductName" , "EnderCalc" 21 | VALUE "ProductVersion" , "1.3" 22 | } 23 | } 24 | BLOCK "VarFileInfo" 25 | { 26 | VALUE "Translation", 0x0409, 0x0000 27 | } 28 | } -------------------------------------------------------------------------------- /src/calc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "calc.h" 7 | #include "command.h" 8 | #include "engine.h" 9 | #include "eval.h" 10 | #include "expr.h" 11 | #include "mem.h" 12 | #include "parse.h" 13 | 14 | #ifdef _WIN32 15 | #include "readline.h" 16 | #else 17 | #include 18 | #endif 19 | 20 | unsigned int g_debug = 0; 21 | unsigned int g_suppress_scientific_notation = 0; 22 | unsigned int g_time = 0; 23 | 24 | // Run a single command, given as a string (does not free it) 25 | static void run_cmd(char *cmd) { 26 | // meta commands (/prec, /debug) are handled elsewhere 27 | if (cmd[0] == '/') { 28 | exec_meta_command(&cmd[1]); 29 | return; 30 | } 31 | 32 | vector_t expr; 33 | int err = parse_expr(cmd, &expr); 34 | if (err == PARSE_SUCCESS) { 35 | if (g_debug) expr_print(expr); 36 | bf_t *result; 37 | err = eval_expr(expr, &result); 38 | if (err != EVAL_SUCCESS) { 39 | expr_delete(expr); 40 | printf("Evaluation error: "); 41 | eval_print_error(err); 42 | puts(""); 43 | return; 44 | } 45 | vector_delete(expr); // leave the number intact 46 | engine_num_print(result, g_debug, g_suppress_scientific_notation); 47 | 48 | if (g_last_answer != 0) engine_num_free(g_last_answer); 49 | g_last_answer = result; 50 | } else { 51 | printf("Parse error: "); 52 | parse_print_error(err); 53 | puts(""); 54 | } 55 | } 56 | 57 | static char* null_matches(const char *text, int state) { 58 | return 0; 59 | } 60 | 61 | // stub to disable readline's autocomplete - file names make no sense 62 | static char** null_completion(const char *text, int start, int end) { 63 | rl_attempted_completion_over = 1; 64 | return rl_completion_matches(text, null_matches); 65 | } 66 | 67 | static int simple_eval_expr(char *s) { 68 | vector_t expr; 69 | int err = parse_expr(s, &expr); 70 | if (err == PARSE_SUCCESS) { 71 | bf_t *result; 72 | err = eval_expr(expr, &result); 73 | if (err == EVAL_SUCCESS) { 74 | engine_num_print(result, 0, 1); 75 | } else { 76 | printf("Evaluation error: "); 77 | eval_print_error(err); 78 | putchar('\n'); 79 | } 80 | expr_delete(expr); 81 | } else { 82 | printf("Parse error: "); 83 | parse_print_error(err); 84 | putchar('\n'); 85 | } 86 | return err = 0 ? 0 : -1; 87 | } 88 | 89 | int main(int argc, char **argv) { 90 | engine_init(); 91 | 92 | if (argc > 1) { 93 | int rc = simple_eval_expr(argv[1]); 94 | engine_cleanup(); 95 | return rc; 96 | } 97 | 98 | puts("EnderCalc v1.3"); 99 | 100 | rl_attempted_completion_function = null_completion; 101 | 102 | // calculate and store the config file path 103 | g_config_path = (char*) malloc(512); // bigger than both win32's MAX_PATH and limits.h PATH_MAX 104 | #ifdef _WIN32 105 | char *env_home_drive = getenv("HOMEDRIVE"); 106 | strcpy(g_config_path, env_home_drive); 107 | strcat(g_config_path, getenv("HOMEPATH")); 108 | strcat(g_config_path, "\\"); 109 | #else // unix-y system 110 | char *env_home = getenv("HOME"); 111 | strcpy(g_config_path, env_home); 112 | strcat(g_config_path, "/"); 113 | #endif 114 | strcat(g_config_path, ".endercalc"); 115 | command_load_config(); 116 | 117 | while (1) { 118 | char *line = readline("? "); 119 | if (line == NULL) { 120 | break; 121 | } 122 | if (line[0] == '\0') { 123 | free(line); 124 | break; 125 | } 126 | add_history(line); // if it doesn't parse, all the more reason - they can go and fix it 127 | 128 | struct timeb start, stop; 129 | ftime(&start); 130 | 131 | run_cmd(line); 132 | 133 | ftime(&stop); 134 | unsigned int msec = (stop.time - start.time) * 1000 + stop.millitm - start.millitm; 135 | if (g_time && line[0] != '/') printf("Command completed in %d ms.\n", msec); 136 | 137 | free(line); 138 | } 139 | 140 | if (g_last_answer != 0) engine_num_free(g_last_answer); 141 | free_mem(); 142 | free(g_config_path); 143 | engine_cleanup(); 144 | } 145 | -------------------------------------------------------------------------------- /src/command.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #ifdef HELP_USE_WIN32 6 | #define WIN32_LEAN_AND_MEAN 7 | #include 8 | #include 9 | #include 10 | #endif 11 | 12 | #include "calc.h" 13 | #include "command.h" 14 | #include "engine.h" 15 | #include "eval.h" 16 | #include "mem.h" 17 | #include "minini.h" 18 | #include "parse.h" 19 | #include "stats.h" 20 | 21 | char *g_config_path = (char*) 0; // set by calc.c 22 | 23 | static inline const char* on_off(unsigned int x) { 24 | return x ? "On" : "Off"; 25 | } 26 | 27 | static void do_parsedebug(char *s) { 28 | g_parse_debug ^= 1; 29 | 30 | if (g_config_path) 31 | ini_putl("EnderCalc", "parse_debug", g_parse_debug, g_config_path); 32 | 33 | printf("Parse debug: %s\n", on_off(g_parse_debug)); 34 | } 35 | 36 | static void do_degrees(char *s) { 37 | g_use_degrees ^= 1; 38 | 39 | if (g_config_path) 40 | ini_putl("EnderCalc", "use_degrees", g_use_degrees, g_config_path); 41 | 42 | printf("Toggled, trigonometric functions now use %s.\n", g_use_degrees ? "degrees" : "radians"); 43 | } 44 | 45 | static void do_format(char *s) { 46 | g_suppress_scientific_notation ^= 1; 47 | 48 | if (g_config_path) 49 | ini_putl("EnderCalc", "suppress_scientific_notation", g_suppress_scientific_notation, g_config_path); 50 | 51 | printf("Suppress Scientific Notation: %s\n", on_off(g_suppress_scientific_notation)); 52 | } 53 | 54 | // Print the last calculated answer in whichever formatting mode *isn't* active 55 | static void do_format_last(char *s) { 56 | if (g_last_answer == 0) { 57 | puts("No saved answer."); 58 | return; 59 | } 60 | 61 | engine_num_print(g_last_answer, 0, g_suppress_scientific_notation ^ 1); 62 | } 63 | 64 | static void do_debug(char *s) { 65 | g_debug ^= 1; 66 | 67 | if (g_config_path) 68 | ini_putl("EnderCalc", "debug", g_debug, g_config_path); 69 | 70 | printf("Debug: %s\n", on_off(g_debug)); 71 | } 72 | 73 | // Parse as a positive long int, return -1 for failure 74 | // Nothing should be after 75 | // Precision should be at least 1 76 | static long int parse_prec(const char *s) { 77 | char *end = 0; 78 | long int num = strtol(s, &end, 10); 79 | if (*end != '\0' || num < 1) return -1; 80 | return num; 81 | } 82 | 83 | static void print_prec_err(char *s) { 84 | printf("Invalid precision: %s\n", s); 85 | puts("Precision must be a natural number."); 86 | } 87 | 88 | static void do_bprec(char *s) { 89 | long int prec = parse_prec(s); 90 | if (prec == -1) { 91 | print_prec_err(s); 92 | return; 93 | } 94 | 95 | g_engine_prec = prec; 96 | 97 | if (g_config_path) 98 | ini_putl("EnderCalc", "engine_prec", g_engine_prec, g_config_path); 99 | 100 | printf("Binary engine precision: %lu bits\n", g_engine_prec); 101 | } 102 | 103 | static void do_dprec(char *s) { 104 | long int prec = parse_prec(s); 105 | if (prec == -1) { 106 | print_prec_err(s); 107 | return; 108 | } 109 | 110 | g_dec_engine_prec = prec; 111 | 112 | if (g_config_path) 113 | ini_putl("EnderCalc", "dec_engine_prec", g_dec_engine_prec, g_config_path); 114 | 115 | printf("Decimal engine precision: %lu digits\n", g_dec_engine_prec); 116 | } 117 | 118 | static void do_prec(char *s) { 119 | long int prec = parse_prec(s); 120 | if (prec == -1) { 121 | print_prec_err(s); 122 | return; 123 | } 124 | 125 | g_dec_engine_prec = prec; 126 | g_engine_prec = prec * 5; 127 | 128 | if (g_config_path) { 129 | ini_putl("EnderCalc", "engine_prec", g_engine_prec, g_config_path); 130 | ini_putl("EnderCalc", "dec_engine_prec", g_dec_engine_prec, g_config_path); 131 | } 132 | 133 | printf("Decimal engine precision: %lu digits\n", g_dec_engine_prec); 134 | printf("Binary engine precision: %lu bits\n", g_engine_prec); 135 | } 136 | 137 | static void do_about(char *s) { 138 | puts("EnderCalc v1.3 by Sam Haskins"); 139 | puts("(licensed under the GNU General Public License, version 3)"); 140 | puts("============================="); 141 | puts("Open-source libaries:"); 142 | puts("libbf 20200119 by Fabrice Bellard"); 143 | puts("WinEditLine 2.206 by Paolo Tosco"); 144 | puts("minIni 1.2b by Thiadmer Riemersma"); 145 | } 146 | 147 | static void do_time(char *s) { 148 | g_time ^= 1; 149 | 150 | if (g_config_path) 151 | ini_putl("EnderCalc", "time", g_time, g_config_path); 152 | 153 | if (g_time) 154 | puts("Now timing math operations."); 155 | else 156 | puts("No longer timing math operations."); 157 | } 158 | 159 | static void do_show(char *s) { 160 | printf("Trigonometric functions use : %s\n", g_use_degrees ? "Degrees" : "Radians"); 161 | printf("Debug : %s\n", on_off(g_debug)); 162 | printf("Parse debug : %s\n", on_off(g_parse_debug)); 163 | printf("Timing : %s\n", on_off(g_time)); 164 | printf("Suppress Scientific Notation : %s\n", on_off(g_suppress_scientific_notation)); 165 | printf("Binary engine precision : %lu bits\n", g_engine_prec); 166 | printf("Decimal engine precision : %lu digits\n", g_dec_engine_prec); 167 | } 168 | 169 | // When compiled for Windows, we can actually open the help pdf 170 | // Otherwise, just mention it 171 | static void do_help(char *s) { 172 | #ifdef HELP_USE_WIN32 173 | char path[MAX_PATH+20]; // reference.pdf could be longer than EnderCalc.exe - add a little extra space 174 | GetModuleFileName(GetModuleHandle(NULL), path, MAX_PATH); 175 | PathRemoveFileSpecA(path); 176 | PathAppendA(path, "reference.pdf"); 177 | ShellExecuteA(0, "open", path, 0, 0, SW_SHOWDEFAULT); 178 | #else 179 | puts("Please consult reference.pdf, available in the same directory as the executable, for help."); 180 | #endif 181 | } 182 | 183 | static const cmd_t commands[] = { 184 | { "parsedebug", 10, do_parsedebug }, 185 | { "formatlast", 10, do_format_last }, 186 | { "clearmem" , 8 , do_clear_mem }, 187 | { "showmem" , 7 , do_show_mem }, 188 | { "degrees" , 7 , do_degrees }, 189 | { "radians" , 7 , do_degrees }, 190 | { "format" , 6 , do_format }, 191 | { "debug" , 5 , do_debug }, 192 | { "bprec" , 5 , do_bprec }, 193 | { "dprec" , 5 , do_dprec }, 194 | { "about" , 5 , do_about }, 195 | { "stats" , 5 , do_stats }, // stats.c 196 | { "prec" , 4 , do_prec }, 197 | { "time" , 4 , do_time }, 198 | { "show" , 4 , do_show }, 199 | { "help" , 4 , do_help }, 200 | { "last" , 4 , do_format_last }, 201 | { "mem" , 3 , do_show_mem }, 202 | }; 203 | static const unsigned int commands_len = 18; 204 | 205 | // Arg is without the leading slash 206 | // Acts only as a dispatcher 207 | void exec_meta_command(char *s) { 208 | for (unsigned int i = 0; i < commands_len; i++) { 209 | const cmd_t *cmd = &commands[i]; 210 | if (strncmp(cmd->str, s, cmd->len) == 0) { 211 | // reject constructions like /dprecenugasfhasf 212 | char cont = s[cmd->len]; 213 | if (cont == ' ' || strlen(s) == cmd->len) { 214 | cmd->op(&s[cmd->len]); 215 | return; 216 | } 217 | } 218 | } 219 | 220 | if (!mem_run_command(s)) printf("%s: command not found\n", s); 221 | } 222 | 223 | // Config loading, woo - first the callback 224 | static int ini_kv_callback(const char *section, const char *key, const char *value, const void *unused) { 225 | // First, check the section 226 | if (strcmp(section, "EnderCalc") == 0) { 227 | unsigned int bool_value = 1 ? strcmp(value, "1") == 0 : 0; 228 | long int prec_value = parse_prec(value); 229 | 230 | if (strcmp(key, "parse_debug") == 0) 231 | g_parse_debug = bool_value; 232 | if (strcmp(key, "debug") == 0) 233 | g_debug = bool_value; 234 | if (strcmp(key, "use_degrees") == 0) 235 | g_use_degrees = bool_value; 236 | if (strcmp(key, "time") == 0) 237 | g_time = bool_value; 238 | if (strcmp(key, "suppress_scientific_notation") == 0) 239 | g_suppress_scientific_notation = bool_value; 240 | 241 | if (strcmp(key, "engine_prec") == 0 && prec_value != -1) 242 | g_engine_prec = prec_value; 243 | if (strcmp(key, "dec_engine_prec") == 0 && prec_value != -1) 244 | g_dec_engine_prec = prec_value; 245 | } 246 | // the memory 247 | mem_try_load(section, key, value); 248 | 249 | return 1; 250 | } 251 | 252 | void command_load_config() { 253 | ini_browse(ini_kv_callback, 0, g_config_path); 254 | } -------------------------------------------------------------------------------- /src/engine.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "engine.h" 6 | #include "eval.h" 7 | 8 | // see header file 9 | bf_context_t g_engine_ctx = {0}; 10 | limb_t g_engine_prec = 100; 11 | limb_t g_dec_engine_prec = 20; 12 | unsigned char g_use_degrees = 0; 13 | 14 | // Precision for the table of constants 15 | static const limb_t engine_const_prec = 150; 16 | 17 | // The constant table 18 | static const char * const engine_const_str[] = { 19 | "3.1415926535897932384626433832795029", // PI 20 | "2.7182818284590452353602874713526625", // E 21 | "6.2831853071795864769252867665590058", // TAU 22 | "3072000" , // MAX_FAC 23 | "1" , // ONE 24 | "0.3333333333333333333333333333333333", // THIRD 25 | "2" , // TWO 26 | "0.0174532925199432957692369076848861", // D2R 27 | "1000000" , // MILLION 28 | "0.0000001" , // MILLIONTH 29 | "-0.0000001" , // NEG_MILLIONTH 30 | "0" , // ZERO 31 | "57.295779513082320876798154814105170", // R2D 32 | "12000000" , // MAX_HYP 33 | "-12000000" , // MIN_HYP 34 | "0.5" , // HALF 35 | "9e1900000" , // MAX_POW_BASE 36 | }; 37 | static const unsigned int engine_const_len = 17; 38 | 39 | bf_t *g_engine_const[17]; 40 | 41 | static void* engine_bf_realloc(void *opaque, void *ptr, size_t size) { 42 | return realloc(ptr, size); 43 | } 44 | 45 | void engine_init() { 46 | bf_context_init(&g_engine_ctx, engine_bf_realloc, 0); 47 | 48 | // Initialize the constant table 49 | for (unsigned int i = 0; i < engine_const_len; i++) { 50 | bf_t *num = engine_num_alloc(); 51 | bf_atof(num, engine_const_str[i], (const char**) 0, 10, engine_const_prec, 0); 52 | g_engine_const[i] = num; 53 | } 54 | } 55 | 56 | void engine_cleanup() { 57 | bf_context_end(&g_engine_ctx); 58 | 59 | for (unsigned int i = 0; i < engine_const_len; i++) { 60 | engine_num_free(g_engine_const[i]); 61 | } 62 | } 63 | 64 | // make a new number 65 | bf_t* engine_num_alloc() { 66 | bf_t *num = (bf_t*) malloc(sizeof(bf_t)); 67 | bf_init(&g_engine_ctx, num); 68 | return num; 69 | } 70 | 71 | // free a number 72 | void engine_num_free(bf_t *num) { 73 | bf_delete(num); 74 | free(num); 75 | } 76 | 77 | // Print a number - this uses the decimal engine 78 | // display a result - convert to lower-accuracy decimal fp first 79 | void engine_num_print(bf_t *num, unsigned int show_real, unsigned int suppress_scientific_mode) { 80 | char *bin_s = bf_ftoa(0, num, 10, g_engine_prec, BF_FTOA_FORMAT_FRAC); 81 | 82 | // debug option: display the binary result 83 | if (show_real) printf("(Actual Result: %s)\n", bin_s); 84 | 85 | bfdec_t dec; 86 | bfdec_init(&g_engine_ctx, &dec); 87 | bfdec_atof(&dec, bin_s, (const char**) 0, g_dec_engine_prec, BF_RNDN); 88 | free(bin_s); 89 | 90 | char *dec_s = bfdec_ftoa(0, &dec, g_dec_engine_prec, suppress_scientific_mode ? BF_FTOA_FORMAT_FRAC : BF_FTOA_FORMAT_FREE_MIN); 91 | 92 | // Okay, so, for dec_s when suppressing scientfic notation, there may be trailing zeros 93 | // Here we try and get rid of them 94 | if (suppress_scientific_mode) { 95 | char *from_end = &dec_s[strlen(dec_s)-1]; 96 | while (*from_end == '0' && from_end > dec_s) from_end--; 97 | if (*from_end == '.') from_end--; 98 | from_end++; 99 | *from_end = '\0'; 100 | } 101 | 102 | puts(dec_s); 103 | 104 | free(dec_s); 105 | bfdec_delete(&dec); 106 | } 107 | 108 | // Copy a constant 109 | bf_t* engine_copy_const(unsigned int i) { 110 | bf_t *num = engine_num_alloc(); 111 | bf_t *c = g_engine_const[i]; 112 | bf_set(num, c); 113 | bf_round(num, g_engine_prec, BF_RNDN); 114 | return num; 115 | } 116 | 117 | // convert a libbf error into an evaluation error 118 | unsigned int map_err(int err) { 119 | if (err & BF_ST_DIVIDE_ZERO) return EVAL_ZERO_DIVISION; 120 | if (err & BF_ST_INVALID_OP) return EVAL_MATH_ERROR; 121 | return EVAL_SUCCESS; 122 | } -------------------------------------------------------------------------------- /src/engine/engine_basic.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "engine.h" 4 | #include "eval.h" 5 | 6 | unsigned int map_err(int err); 7 | 8 | // r = -a0 9 | int calc_neg(bf_t **args, bf_t **result) { 10 | bf_set(*result, *args); 11 | bf_neg(*result); 12 | return EVAL_SUCCESS; 13 | } 14 | 15 | // r = a0 + a1 16 | int calc_add(bf_t **args, bf_t **result) { 17 | return map_err(bf_add(*result, args[0], args[1], g_engine_prec, BF_RNDN)); 18 | } 19 | 20 | // r = a0 - a1 21 | int calc_sub(bf_t **args, bf_t **result) { 22 | return map_err(bf_sub(*result, args[0], args[1], g_engine_prec, BF_RNDN)); 23 | } 24 | 25 | // r = a0 * a1 26 | int calc_mul(bf_t **args, bf_t **result) { 27 | return map_err(bf_mul(*result, args[0], args[1], g_engine_prec, BF_RNDN)); 28 | } 29 | 30 | // r = a0 / a1 31 | int calc_div(bf_t **args, bf_t **result) { 32 | return map_err(bf_div(*result, args[0], args[1], g_engine_prec, BF_RNDN)); 33 | } 34 | 35 | // r = a0 % a1 36 | int calc_mod(bf_t **args, bf_t **result) { 37 | return map_err(bf_rem(*result, args[0], args[1], g_engine_prec, BF_RNDN, BF_DIVREM_EUCLIDIAN)); 38 | } 39 | 40 | // r = e^a0 41 | int calc_exp(bf_t **args, bf_t **result) { 42 | if (bf_cmp_lt(g_engine_const[ENGINE_CONST_MILLION], *args)) return EVAL_MATH_ERROR; 43 | return map_err(bf_exp(*result, *args, g_engine_prec, BF_RNDN)); 44 | } 45 | 46 | // r = a0^a1 47 | int calc_pow(bf_t **args, bf_t **result) { 48 | if (bf_cmp_lt(g_engine_const[ENGINE_CONST_MILLION], args[1])) return EVAL_MATH_ERROR; 49 | 50 | if (bf_cmp_lt(g_engine_const[ENGINE_CONST_MAX_POW_BASE], args[0])) return EVAL_MATH_ERROR; 51 | 52 | #ifdef __GNUC__ 53 | if (args[0]->expn > 0 && args[1]->expn > 0) { 54 | unsigned __int128 e1 = args[0]->expn; 55 | unsigned __int128 e2 = args[1]->expn; 56 | unsigned __int128 e3 = e1; 57 | unsigned __int128 lim = *((unsigned __int128*) "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"); 58 | while (e2) { 59 | if (e3 > lim / e1) return EVAL_MATH_ERROR; 60 | e3 *= e1; 61 | e2--; 62 | } 63 | } 64 | #else 65 | #warning "Compiling without anti-hang checks for pow" 66 | #endif 67 | 68 | return map_err(bf_pow(*result, args[0], args[1], g_engine_prec, BF_RNDN)); 69 | } 70 | 71 | // r = a0! 72 | int calc_fac(bf_t **args, bf_t **result) { 73 | if ((*args)->sign == 1) { 74 | return EVAL_MATH_ERROR; 75 | } 76 | 77 | bf_set(*result, g_engine_const[ENGINE_CONST_ONE]); 78 | 79 | int err = bf_rint(*args, BF_RNDN); 80 | if (err & BF_ST_INEXACT) return EVAL_MATH_ERROR; 81 | if (bf_cmp_le(*args, g_engine_const[ENGINE_CONST_MAX_FAC])) { 82 | while (!bf_is_zero(*args)) { 83 | bf_mul(*result, *result, *args, g_engine_prec, BF_RNDN); 84 | bf_sub(*args, *args, g_engine_const[ENGINE_CONST_ONE], g_engine_prec, BF_RNDN); 85 | } 86 | return EVAL_SUCCESS; 87 | } else { 88 | return EVAL_MATH_ERROR; 89 | } 90 | } 91 | 92 | // r = a0!! 93 | int calc_2fac(bf_t **args, bf_t **result) { 94 | // negative inputs must be handled specially 95 | unsigned char negate = 0; 96 | if ((*args)->sign == 1) { 97 | negate = 1; 98 | bf_neg(*args); 99 | } 100 | 101 | // should be whole number 102 | bf_set(*result, g_engine_const[ENGINE_CONST_ONE]); 103 | int err = bf_rint(*args, BF_RNDN); 104 | if (err & BF_ST_INEXACT) return EVAL_MATH_ERROR; 105 | 106 | // anti hang check 107 | if (bf_cmp_le(g_engine_const[ENGINE_CONST_MAX_FAC], *args)) 108 | return EVAL_MATH_ERROR; 109 | 110 | // the double factorial is not defined for even negative numbers 111 | if (negate) { 112 | bf_t *rem = engine_num_alloc(); 113 | bf_rem(rem, *args, g_engine_const[ENGINE_CONST_TWO], g_engine_prec, BF_RNDN, BF_DIVREM_EUCLIDIAN); 114 | if (bf_cmp_eq(rem, g_engine_const[ENGINE_CONST_ZERO])) { 115 | engine_num_free(rem); 116 | return EVAL_MATH_ERROR; 117 | } 118 | engine_num_free(rem); 119 | } 120 | 121 | if (negate) 122 | bf_sub(*args, *args, g_engine_const[ENGINE_CONST_TWO], g_engine_prec, BF_RNDN); 123 | 124 | unsigned char iterCount = 0; 125 | while (!bf_cmp_le(*args, g_engine_const[ENGINE_CONST_ZERO])) { 126 | bf_mul(*result, *result, *args, g_engine_prec, BF_RNDN); 127 | bf_sub(*args, *args, g_engine_const[ENGINE_CONST_TWO], g_engine_prec, BF_RNDN); 128 | iterCount ^= 1; 129 | } 130 | 131 | if (negate) 132 | bf_div(*result, g_engine_const[ENGINE_CONST_ONE], *result, g_engine_prec, BF_RNDN); 133 | if (negate && iterCount) 134 | bf_neg(*result); 135 | 136 | return EVAL_SUCCESS; 137 | } 138 | 139 | // r = sqrt(a0) 140 | int calc_sqrt(bf_t **args, bf_t **result) { 141 | return map_err(bf_sqrt(*result, *args, g_engine_prec, BF_RNDN)); 142 | } 143 | 144 | //r = cbrt(a0) 145 | int calc_cbrt(bf_t **args, bf_t **result) { 146 | if ((*args)->sign == 1) { 147 | bf_neg(*args); 148 | int err = map_err(bf_pow(*result, *args, g_engine_const[ENGINE_CONST_THIRD], g_engine_prec, BF_RNDN)); 149 | bf_neg(*result); 150 | return err; 151 | } 152 | return map_err(bf_pow(*result, *args, g_engine_const[ENGINE_CONST_THIRD], g_engine_prec, BF_RNDN)); 153 | } 154 | 155 | //r = a0root(a1) 156 | int calc_root(bf_t **args, bf_t **result) { 157 | // okay, so in the case of a positive odd integer root, we do allow negative a1 values 158 | // the logic for this is a bit complex 159 | unsigned char negate = 0; 160 | if (args[1]->sign == 1 && args[0]->sign == 0) { 161 | bf_t *rem = engine_num_alloc(); 162 | bf_rem(rem, args[0], g_engine_const[ENGINE_CONST_TWO], g_engine_prec, BF_RNDN, BF_DIVREM_EUCLIDIAN); 163 | if (bf_cmp_eq(rem, g_engine_const[ENGINE_CONST_ONE])) { 164 | negate = 1; 165 | bf_neg(args[1]); 166 | } 167 | bf_set(*result, rem); 168 | engine_num_free(rem); 169 | } 170 | 171 | int err = map_err(bf_div(args[0], g_engine_const[ENGINE_CONST_ONE], args[0], g_engine_prec, BF_RNDN)); 172 | if (err != EVAL_SUCCESS) return err; 173 | err = map_err(bf_pow(*result, args[1], args[0], g_engine_prec, BF_RNDN)); 174 | if (negate) bf_neg(*result); 175 | return err; 176 | } 177 | 178 | // r = ln(a0) 179 | int calc_ln(bf_t **args, bf_t **result) { 180 | if (bf_is_zero(*args)) return EVAL_MATH_ERROR; 181 | return map_err(bf_log(*result, *args, g_engine_prec, BF_RNDN)); 182 | } 183 | 184 | // r = a0log(a1) 185 | int calc_log(bf_t **args, bf_t **result) { 186 | if (bf_is_zero(args[0])) return EVAL_MATH_ERROR; 187 | if (bf_is_zero(args[1])) return EVAL_MATH_ERROR; 188 | 189 | int err = map_err(bf_log(args[1], args[1], g_engine_prec, BF_RNDN)); 190 | if (err != EVAL_SUCCESS) return err; 191 | err = map_err(bf_log(args[0], args[0], g_engine_prec, BF_RNDN)); 192 | if (err != EVAL_SUCCESS) return err; 193 | return map_err(bf_div(*result, args[1], args[0], g_engine_prec, BF_RNDN)); 194 | } 195 | 196 | // r = abs(a0) 197 | int calc_abs(bf_t **args, bf_t **result) { 198 | bf_set(*result, *args); 199 | if ((*args)->sign == 1) bf_neg(*result); 200 | return EVAL_SUCCESS; 201 | } -------------------------------------------------------------------------------- /src/engine/engine_hyperbolic.c: -------------------------------------------------------------------------------- 1 | #include "engine.h" 2 | #include "eval.h" 3 | 4 | unsigned int map_err(int err); 5 | 6 | static int internal_calc_sinh_or_cosh(bf_t **args, bf_t **result, unsigned char use_cosh) { 7 | // limits - we don't want the calculator to hang 8 | if (bf_cmp_lt(g_engine_const[ENGINE_CONST_MAX_HYP], *args)) return EVAL_MATH_ERROR; 9 | if (bf_cmp_lt(*args, g_engine_const[ENGINE_CONST_MIN_HYP])) return EVAL_MATH_ERROR; 10 | 11 | bf_t *exp_pos = engine_num_alloc(); 12 | bf_t *exp_neg = engine_num_alloc(); 13 | 14 | int err = map_err(bf_exp(exp_pos, *args, g_engine_prec, BF_RNDN)); 15 | if (err != EVAL_SUCCESS) { 16 | engine_num_free(exp_pos); 17 | engine_num_free(exp_neg); 18 | return err; 19 | } 20 | 21 | bf_neg(*args); 22 | err = map_err(bf_exp(exp_neg, *args, g_engine_prec, BF_RNDN)); 23 | if (err != EVAL_SUCCESS) { 24 | engine_num_free(exp_pos); 25 | engine_num_free(exp_neg); 26 | return err; 27 | } 28 | 29 | if (use_cosh) { 30 | err = map_err(bf_add(*result, exp_pos, exp_neg, g_engine_prec, BF_RNDN)); 31 | } else { 32 | err = map_err(bf_sub(*result, exp_pos, exp_neg, g_engine_prec, BF_RNDN)); 33 | } 34 | engine_num_free(exp_pos); 35 | engine_num_free(exp_neg); 36 | if (err != EVAL_SUCCESS) return err; 37 | 38 | return map_err(bf_div(*result, *result, g_engine_const[ENGINE_CONST_TWO], g_engine_prec, BF_RNDN)); 39 | } 40 | 41 | // r = sinh(a0) 42 | int calc_sinh(bf_t **args, bf_t **result) { 43 | return internal_calc_sinh_or_cosh(args, result, 0); 44 | } 45 | 46 | // r = cosh(a0) 47 | int calc_cosh(bf_t **args, bf_t **result) { 48 | return internal_calc_sinh_or_cosh(args, result, 1); 49 | } 50 | 51 | // r = tanh(a0) 52 | int calc_tanh(bf_t **args, bf_t **result) { 53 | if (bf_cmp_lt(g_engine_const[ENGINE_CONST_MAX_HYP], *args)) return EVAL_MATH_ERROR; 54 | if (bf_cmp_lt(*args, g_engine_const[ENGINE_CONST_MIN_HYP])) return EVAL_MATH_ERROR; 55 | 56 | bf_t *exp_pos = engine_num_alloc(); 57 | bf_t *exp_neg = engine_num_alloc(); 58 | 59 | int err = map_err(bf_exp(exp_pos, *args, g_engine_prec, BF_RNDN)); 60 | if (err != EVAL_SUCCESS) { 61 | engine_num_free(exp_pos); 62 | engine_num_free(exp_neg); 63 | return err; 64 | } 65 | 66 | bf_neg(*args); 67 | err = map_err(bf_exp(exp_neg, *args, g_engine_prec, BF_RNDN)); 68 | if (err != EVAL_SUCCESS) { 69 | engine_num_free(exp_pos); 70 | engine_num_free(exp_neg); 71 | return err; 72 | } 73 | 74 | bf_t *top = engine_num_alloc(); 75 | bf_t *bottom = engine_num_alloc(); 76 | err = map_err(bf_sub(top, exp_pos, exp_neg, g_engine_prec, BF_RNDN)); 77 | if (err != EVAL_SUCCESS) { 78 | engine_num_free(exp_pos); 79 | engine_num_free(exp_neg); 80 | engine_num_free(top); 81 | engine_num_free(bottom); 82 | return err; 83 | } 84 | 85 | err = map_err(bf_add(bottom, exp_pos, exp_neg, g_engine_prec, BF_RNDN)); 86 | engine_num_free(exp_pos); 87 | engine_num_free(exp_neg); 88 | if (err != EVAL_SUCCESS) { 89 | engine_num_free(top); 90 | engine_num_free(bottom); 91 | return err; 92 | } 93 | 94 | err = map_err(bf_div(*result, top, bottom, g_engine_prec, BF_RNDN)); 95 | engine_num_free(top); 96 | engine_num_free(bottom); 97 | return err; 98 | } 99 | 100 | static int internal_calc_asinh_or_acosh(bf_t **args, bf_t **result, unsigned char use_acosh) { 101 | // fast-fail for <1 on acosh 102 | if (use_acosh && bf_cmp_lt(*args, g_engine_const[ENGINE_CONST_ONE])) return EVAL_MATH_ERROR; 103 | if (!use_acosh && bf_cmp_eq(*args, g_engine_const[ENGINE_CONST_ZERO])) { 104 | bf_set(*result, g_engine_const[ENGINE_CONST_ZERO]); 105 | return EVAL_SUCCESS; 106 | } 107 | 108 | bf_t *sqrt = engine_num_alloc(); 109 | bf_set(sqrt, *args); 110 | 111 | int err = map_err(bf_mul(sqrt, sqrt, sqrt, g_engine_prec, BF_RNDN)); 112 | if (err != EVAL_SUCCESS) { 113 | engine_num_free(sqrt); 114 | return err; 115 | } 116 | 117 | if (use_acosh) { 118 | err = map_err(bf_sub(sqrt, sqrt, g_engine_const[ENGINE_CONST_ONE], g_engine_prec, BF_RNDN)); 119 | } else { 120 | err = map_err(bf_add(sqrt, sqrt, g_engine_const[ENGINE_CONST_ONE], g_engine_prec, BF_RNDN)); 121 | } 122 | if (err != EVAL_SUCCESS) { 123 | engine_num_free(sqrt); 124 | return err; 125 | } 126 | 127 | err = map_err(bf_sqrt(*result, sqrt, g_engine_prec, BF_RNDN)); 128 | if (err != EVAL_SUCCESS) { 129 | engine_num_free(sqrt); 130 | return err; 131 | } 132 | 133 | err = map_err(bf_add(*args, *args, *result, g_engine_prec, BF_RNDN)); 134 | engine_num_free(sqrt); 135 | if (err != EVAL_SUCCESS) return err; 136 | 137 | return map_err(bf_log(*result, *args, g_engine_prec, BF_RNDN)); 138 | } 139 | 140 | // r = asinh(a0) 141 | int calc_asinh(bf_t **args, bf_t **result) { 142 | return internal_calc_asinh_or_acosh(args, result, 0); 143 | } 144 | 145 | // r = acosh(a0) 146 | int calc_acosh(bf_t **args, bf_t **result) { 147 | return internal_calc_asinh_or_acosh(args, result, 1); 148 | } 149 | 150 | int calc_atanh(bf_t **args, bf_t **result) { 151 | bf_t *top = engine_num_alloc(); 152 | bf_t *bottom = engine_num_alloc(); 153 | bf_set(top, g_engine_const[ENGINE_CONST_ONE]); 154 | bf_set(bottom, g_engine_const[ENGINE_CONST_ONE]); 155 | 156 | int err = map_err(bf_add(top, top, *args, g_engine_prec, BF_RNDN)); 157 | if (err != EVAL_SUCCESS) { 158 | engine_num_free(top); 159 | engine_num_free(bottom); 160 | return err; 161 | } 162 | 163 | err = map_err(bf_sub(bottom, bottom, *args, g_engine_prec, BF_RNDN)); 164 | if (err != EVAL_SUCCESS) { 165 | engine_num_free(top); 166 | engine_num_free(bottom); 167 | return err; 168 | } 169 | 170 | err = map_err(bf_div(*result, top, bottom, g_engine_prec, BF_RNDN)); 171 | engine_num_free(top); 172 | engine_num_free(bottom); 173 | if (err != EVAL_SUCCESS) return err; 174 | 175 | err = map_err(bf_log(*args, *result, g_engine_prec, BF_RNDN)); 176 | if (err != EVAL_SUCCESS) return err; 177 | 178 | err = map_err(bf_mul(*result, *args, g_engine_const[ENGINE_CONST_HALF], g_engine_prec, BF_RNDN)); 179 | return err; 180 | } 181 | -------------------------------------------------------------------------------- /src/engine/engine_stats.c: -------------------------------------------------------------------------------- 1 | #include "engine.h" 2 | #include "eval.h" 3 | 4 | unsigned int map_err(int err); 5 | 6 | // r = a0 P a1 7 | int calc_permu(bf_t **args, bf_t **result) { 8 | bf_t *scratch = engine_num_alloc(); 9 | bf_t *bottom_fac = engine_num_alloc(); 10 | 11 | int err = map_err(bf_sub(scratch, args[0], args[1], g_engine_prec, BF_RNDN)); 12 | if (err != EVAL_SUCCESS) { 13 | engine_num_free(scratch); 14 | engine_num_free(bottom_fac); 15 | return err; 16 | } 17 | 18 | err = calc_fac(&scratch, &bottom_fac); 19 | if (err != EVAL_SUCCESS) { 20 | engine_num_free(scratch); 21 | engine_num_free(bottom_fac); 22 | return err; 23 | } 24 | 25 | err = calc_fac(args, &scratch); 26 | if (err != EVAL_SUCCESS) { 27 | engine_num_free(scratch); 28 | engine_num_free(bottom_fac); 29 | return err; 30 | } 31 | 32 | err = map_err(bf_div(*result, scratch, bottom_fac, g_engine_prec, BF_RNDN)); 33 | engine_num_free(scratch); 34 | engine_num_free(bottom_fac); 35 | return err; 36 | } 37 | 38 | // r = a0 C a1 39 | int calc_combi(bf_t **args, bf_t **result) { 40 | bf_t *top = engine_num_alloc(); 41 | bf_t *arg0_bkup = engine_num_alloc(); 42 | bf_set(arg0_bkup, *args); 43 | int err = calc_fac(&arg0_bkup, &top); 44 | engine_num_free(arg0_bkup); 45 | if (err != EVAL_SUCCESS) { 46 | engine_num_free(top); 47 | return err; 48 | } 49 | 50 | bf_t *scratch1 = engine_num_alloc(); 51 | bf_t *arg_bkup = engine_num_alloc(); 52 | bf_set(arg_bkup, args[1]); 53 | err = calc_fac(&arg_bkup, &scratch1); 54 | engine_num_free(arg_bkup); 55 | if (err != EVAL_SUCCESS) { 56 | engine_num_free(top); 57 | engine_num_free(scratch1); 58 | return err; 59 | } 60 | 61 | bf_t *scratch2 = engine_num_alloc(); 62 | 63 | err = map_err(bf_sub(scratch2, args[0], args[1], g_engine_prec, BF_RNDN)); 64 | if (err != EVAL_SUCCESS) { 65 | engine_num_free(top); 66 | engine_num_free(scratch1); 67 | engine_num_free(scratch2); 68 | return err; 69 | } 70 | 71 | err = calc_fac(&scratch2, &args[1]); 72 | engine_num_free(scratch2); 73 | if (err != EVAL_SUCCESS) { 74 | engine_num_free(top); 75 | engine_num_free(scratch1); 76 | return err; 77 | } 78 | 79 | err = map_err(bf_mul(scratch1, scratch1, args[1], g_engine_prec, BF_RNDN)); 80 | if (err != EVAL_SUCCESS) { 81 | engine_num_free(top); 82 | engine_num_free(scratch1); 83 | return err; 84 | } 85 | 86 | err = map_err(bf_div(*result, top, scratch1, g_engine_prec, BF_RNDN)); 87 | engine_num_free(top); 88 | engine_num_free(scratch1); 89 | return err; 90 | } -------------------------------------------------------------------------------- /src/engine/engine_trig.c: -------------------------------------------------------------------------------- 1 | #include "engine.h" 2 | #include "eval.h" 3 | 4 | unsigned int map_err(int err); 5 | 6 | static int is_trig_result_zero(bf_t *result) { 7 | return (result->sign == 0 && bf_cmp_lt(result, g_engine_const[ENGINE_CONST_MILLIONTH])) || \ 8 | (result->sign == 1 && bf_cmp_lt(g_engine_const[ENGINE_CONST_NEG_MILLIONTH], result)); 9 | } 10 | 11 | // r = sin(a0) 12 | int calc_sin(bf_t **args, bf_t **result) { 13 | if (g_use_degrees) { 14 | int err = map_err(bf_mul(*args, *args, g_engine_const[ENGINE_CONST_D2R], g_engine_prec, BF_RNDN)); 15 | if (err != EVAL_SUCCESS) return err; 16 | } 17 | 18 | // if it's below a millionth, we round to zero 19 | int err = map_err(bf_sin(*result, *args, g_engine_prec, BF_RNDN)); 20 | if (is_trig_result_zero(*result)) bf_set(*result, g_engine_const[ENGINE_CONST_ZERO]); 21 | return err; 22 | } 23 | 24 | // r = cos(a0) 25 | int calc_cos(bf_t **args, bf_t **result) { 26 | if (g_use_degrees) { 27 | int err = map_err(bf_mul(*args, *args, g_engine_const[ENGINE_CONST_D2R], g_engine_prec, BF_RNDN)); 28 | if (err != EVAL_SUCCESS) return err; 29 | } 30 | 31 | // if it's below a millionth, we round to zero 32 | int err = map_err(bf_cos(*result, *args, g_engine_prec, BF_RNDN)); 33 | if (is_trig_result_zero(*result)) bf_set(*result, g_engine_const[ENGINE_CONST_ZERO]); 34 | return err; 35 | } 36 | 37 | // r = tan(a0) 38 | int calc_tan(bf_t **args, bf_t **result) { 39 | if (g_use_degrees) { 40 | int err = map_err(bf_mul(*args, *args, g_engine_const[ENGINE_CONST_D2R], g_engine_prec, BF_RNDN)); 41 | if (err != EVAL_SUCCESS) return err; 42 | } 43 | int err = map_err(bf_tan(*result, *args, g_engine_prec, BF_RNDN)); 44 | 45 | // tan can actually give an infinite result - this is considered an error 46 | if (bf_cmp_lt(g_engine_const[ENGINE_CONST_MILLION], *result)) return EVAL_MATH_ERROR; 47 | if (is_trig_result_zero(*result)) bf_set(*result, g_engine_const[ENGINE_CONST_ZERO]); 48 | return err; 49 | } 50 | 51 | // r = asin(a0) 52 | int calc_asin(bf_t **args, bf_t **result) { 53 | int err = map_err(bf_asin(*result, *args, g_engine_prec, BF_RNDN)); 54 | if (err != EVAL_SUCCESS || !g_use_degrees) return err; 55 | return map_err(bf_mul(*result, *result, g_engine_const[ENGINE_CONST_R2D], g_engine_prec, BF_RNDN)); 56 | } 57 | 58 | // r = acos(a0) 59 | int calc_acos(bf_t **args, bf_t **result) { 60 | int err = map_err(bf_acos(*result, *args, g_engine_prec, BF_RNDN)); 61 | if (err != EVAL_SUCCESS || !g_use_degrees) return err; 62 | return map_err(bf_mul(*result, *result, g_engine_const[ENGINE_CONST_R2D], g_engine_prec, BF_RNDN)); 63 | } 64 | 65 | // r = atan(a0) 66 | int calc_atan(bf_t **args, bf_t **result) { 67 | int err = map_err(bf_atan(*result, *args, g_engine_prec, BF_RNDN)); 68 | if (err != EVAL_SUCCESS || !g_use_degrees) return err; 69 | return map_err(bf_mul(*result, *result, g_engine_const[ENGINE_CONST_R2D], g_engine_prec, BF_RNDN)); 70 | } -------------------------------------------------------------------------------- /src/eval.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "engine.h" 4 | #include "eval.h" 5 | #include "expr.h" 6 | #include "mem.h" 7 | #include "symbols.h" 8 | 9 | bf_t *g_last_answer = 0; 10 | 11 | // duplicate a bf_t into an expression at position i 12 | static bf_t* duplicate_into(bf_t *num, vector_t expr, unsigned int i) { 13 | bf_t *clone, *tk; 14 | clone = tk = engine_num_alloc(); 15 | bf_set(clone, num); 16 | 17 | token_tag((void**) &tk, TOKEN_NUM); 18 | vector_set(expr, i, tk); 19 | 20 | return clone; 21 | } 22 | 23 | // resolve an argument, optionally placing it back 24 | static unsigned int resolve_arg(vector_t expr, unsigned int i, bf_t **result) { 25 | void *tk = vector_get(expr, i); 26 | unsigned int tag = token_untag(&tk); 27 | if (tag == TOKEN_NUM) { 28 | // numbers are simple = no conversion needed 29 | *result = tk; 30 | return EVAL_SUCCESS; 31 | } else if (tag == TOKEN_EXPR) { 32 | // for expressions, just solve 33 | vector_t sub_expr = (vector_t) tk; 34 | unsigned int err = eval_expr(sub_expr, result); 35 | return err; 36 | } else if (tag == TOKEN_SYM) { 37 | // only answer/memory symbols are allowed in place of a number 38 | unsigned int sym = (unsigned int) (uintptr_t) tk; 39 | if (sym == SYM_ANS) { 40 | if (g_last_answer == 0) return EVAL_NO_SAVED_ANSWER; 41 | *result = duplicate_into(g_last_answer, expr, i); 42 | return EVAL_SUCCESS; 43 | } else if (sym <= SYM_RCL_MAX && sym >= SYM_RCL_MIN) { 44 | bf_t *saved = g_mem[sym - SYM_RCL_MIN]; 45 | if (saved == 0) return EVAL_NO_RECALL; 46 | *result = duplicate_into(saved, expr, i); 47 | return EVAL_SUCCESS; 48 | } else { 49 | return EVAL_SYNTAX_ERROR; 50 | } 51 | } 52 | } 53 | 54 | // The expression evaluator - sometimes errors, sometimes doesn't 55 | unsigned int eval_expr(vector_t expr, bf_t **result) { 56 | unsigned int err; 57 | 58 | // Perform a reduction 59 | while (vector_get_len(expr) > 1) { 60 | // 1: Find the next operator, and its location 61 | unsigned char valid_op = 0; 62 | unsigned int op = 0; 63 | unsigned int op_index = 0; 64 | 65 | unsigned int len = vector_get_len(expr); 66 | for (unsigned int i = 0; i < len; i++) { 67 | void *tk = vector_get(expr, i); 68 | unsigned int tag = token_untag(&tk); 69 | if (tag != TOKEN_SYM) continue; // all operators are symbols 70 | unsigned int sym = (unsigned int) (uintptr_t) tk; 71 | 72 | unsigned int precedence = g_op_precedence[sym]; 73 | if (precedence == SYMP_NOT_OPERATOR) continue; // not all symbols are operators 74 | 75 | // precedence and associativity rules 76 | if (valid_op == 0 || precedence < g_op_precedence[op] || 77 | (g_op_associativity[op] == SYMA_RIGHT && precedence <= g_op_precedence[op])) { 78 | valid_op = 1; 79 | op = sym; 80 | op_index = i; 81 | } 82 | } 83 | if (valid_op == 0) return EVAL_MISSING_OPERATOR; 84 | 85 | // 2: Collect the arguments 86 | bf_t *args[2]; 87 | arg_collect_t desc = g_op_arg_collect[g_op_args[op]]; 88 | unsigned int desc_len = desc.len; 89 | for (unsigned int i = 0; i < desc_len; i++) { 90 | char off = desc.args[i]; 91 | if (off + op_index < 0 || off + op_index >= len) return EVAL_SYNTAX_ERROR; 92 | err = resolve_arg(expr, off + op_index, &args[i]); 93 | if (err != EVAL_SUCCESS) return err; 94 | } 95 | 96 | // 3: do the operation 97 | bf_t *op_result = engine_num_alloc(); 98 | op_func_t *f = g_op_funcs[op]; 99 | err = f(args, &op_result); 100 | if (err != EVAL_SUCCESS) { 101 | engine_num_free(op_result); 102 | return err; 103 | } 104 | if (!bf_is_finite(op_result)) { 105 | engine_num_free(op_result); 106 | return EVAL_OVERFLOW; 107 | } 108 | 109 | // 4: cleanup and slot in the result 110 | for (unsigned int i = 0; i < desc_len; i++) { 111 | void *tk = vector_get(expr, op_index + desc.cleanup[i]); 112 | token_delete(tk); 113 | vector_remove(expr, op_index + desc.cleanup[i]); 114 | } 115 | token_tag((void**) &op_result, TOKEN_NUM); 116 | vector_set(expr, desc.result + op_index, op_result); 117 | } 118 | 119 | if (vector_get_len(expr) == 0) return EVAL_SYNTAX_ERROR; 120 | 121 | // Down to one; let's make it a number 122 | err = resolve_arg(expr, 0, result); 123 | return err; 124 | } 125 | 126 | void eval_print_error(unsigned int err) { 127 | switch(err) { 128 | case EVAL_SUCCESS: 129 | printf("success"); 130 | break; 131 | case EVAL_SYNTAX_ERROR: 132 | printf("syntax error"); 133 | break; 134 | case EVAL_MISSING_OPERATOR: 135 | printf("missing operator"); 136 | break; 137 | case EVAL_NO_SAVED_ANSWER: 138 | printf("no saved answer"); 139 | break; 140 | case EVAL_ZERO_DIVISION: 141 | printf("zero division"); 142 | break; 143 | case EVAL_MATH_ERROR: 144 | printf("math error"); 145 | break; 146 | case EVAL_OVERFLOW: 147 | printf("overflow"); 148 | break; 149 | case EVAL_NO_RECALL: 150 | printf("unable to recall"); 151 | break; 152 | default: 153 | printf("unknown error"); 154 | } 155 | } -------------------------------------------------------------------------------- /src/expr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "engine.h" 6 | #include "expr.h" 7 | #include "libbf.h" 8 | #include "symbols.h" 9 | 10 | // Add a two-bit tag to a pointer, inplace 11 | void token_tag(void **ptr, unsigned int tag) { 12 | assert(tag <= 3); 13 | 14 | uintptr_t val = (uintptr_t) *ptr; 15 | 16 | // We set at most two bits (62 and 63) 17 | for (unsigned int i = 0; i < 2; i++) { 18 | unsigned int bit = (tag & (1 << i)) >> i; 19 | 20 | // Use a 64 bit value as the mask, or it truncates 21 | uintptr_t shift = 1; 22 | shift <<= 62 + i; 23 | 24 | if (bit) { 25 | val |= shift; 26 | } else { 27 | val &= ~shift; 28 | } 29 | } 30 | 31 | *ptr = (void*) val; 32 | } 33 | 34 | // Remove the token from the pointer and return it 35 | unsigned int token_untag(void **ptr) { 36 | uintptr_t val = (uintptr_t) *ptr; 37 | unsigned int tag = (val & 0xc000000000000000) >> 62; 38 | 39 | // somewhat hacky way to sign-extend the value 40 | intptr_t sval = (intptr_t) *ptr; 41 | sval <<= 16; 42 | sval >>= 16; 43 | *ptr = (void*) sval; 44 | return tag; 45 | } 46 | 47 | // Fairly basic - iterate over the expression and print each token 48 | static void internal_expr_print(vector_t expr) { 49 | unsigned int len = vector_get_len(expr); 50 | for (unsigned int i = 0; i < len; i++) { 51 | void *tk = vector_get(expr, i); 52 | unsigned int tag = token_untag(&tk); 53 | 54 | // Print the token 55 | if (tag == TOKEN_EXPR) { 56 | putchar('('); 57 | internal_expr_print(tk); 58 | putchar(')'); 59 | } else if (tag == TOKEN_STR) { 60 | str_slice_t *str = (str_slice_t*) tk; 61 | printf("%.*s", str->len, str->ptr); 62 | } else if (tag == TOKEN_NUM) { 63 | bf_t *num = (bf_t*) tk; 64 | char *s = bf_ftoa(0, num, 10, g_engine_prec, BF_FTOA_FORMAT_FREE_MIN); 65 | printf("%s", s); 66 | free(s); 67 | } else if (tag == TOKEN_SYM) { 68 | printf("%s", g_sym_names[(unsigned int) (uintptr_t) tk]); 69 | } 70 | 71 | // Spaces between tokens 72 | if (i + 1 < len) 73 | putchar(' '); 74 | } 75 | } 76 | 77 | // print - but followed by newline 78 | void expr_print(vector_t expr) { 79 | internal_expr_print(expr); 80 | puts(""); 81 | } 82 | 83 | // I'd comment these but they're pretty self-explanatory 84 | 85 | void token_delete(void *tk) { 86 | unsigned int tag = token_untag(&tk); 87 | if (tag == TOKEN_EXPR) { 88 | expr_delete(tk); 89 | } else if (tag == TOKEN_STR) { 90 | free(tk); 91 | } else if (tag == TOKEN_NUM) { 92 | engine_num_free((bf_t*) tk); 93 | } // symbols don't need to be freed 94 | } 95 | 96 | void expr_delete(vector_t expr) { 97 | unsigned int len = vector_get_len(expr); 98 | for (unsigned int i = 0; i < len; i++) 99 | token_delete(vector_get(expr, i)); 100 | vector_delete(expr); 101 | } -------------------------------------------------------------------------------- /src/mem.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "calc.h" 5 | #include "command.h" 6 | #include "engine.h" 7 | #include "eval.h" 8 | #include "mem.h" 9 | #include "minini.h" 10 | 11 | // slots 1 thru 9 - init with nullptrs 12 | bf_t *g_mem[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 13 | 14 | // free the entire memory 15 | void free_mem() { 16 | for (unsigned int i = 0; i < CALC_MEMORY_SIZE; i++) { 17 | bf_t *num = g_mem[i]; 18 | if (num != 0) engine_num_free(num); 19 | g_mem[i] = 0; 20 | } 21 | } 22 | 23 | // Store memory slot to the ini file 24 | static void sto_slot(unsigned int i) { 25 | if (g_config_path == 0) return; 26 | 27 | // first, the key name in the ini file (4 chars + null) 28 | char key[5]; 29 | sprintf(key, "mem%u", i + 1); 30 | 31 | // now, are we storing to ini or clearing? 32 | bf_t *num = g_mem[i]; 33 | if (num == 0) { 34 | ini_puts("Memory", key, 0, g_config_path); 35 | } else { 36 | char *s = bf_ftoa(0, num, 16, g_engine_prec, BF_FTOA_FORMAT_FREE); 37 | ini_puts("Memory", key, s, g_config_path); 38 | free(s); 39 | } 40 | } 41 | 42 | // Store a number into a memory slot 43 | // (i should be between 0 and 8, inclusive) 44 | static void do_sto(unsigned int i, char *s) { 45 | // mode 1, add the last answer (if no number specified, skipping spaces) 46 | while (*s == ' ') s++; 47 | if (*s == '\0') { 48 | if (g_last_answer == 0) { 49 | puts("No saved answer."); 50 | } else { 51 | // free the slot and copy it over 52 | if (g_mem[i] == 0) g_mem[i] = engine_num_alloc(); 53 | bf_set(g_mem[i], g_last_answer); 54 | engine_num_print(g_mem[i], 0, g_suppress_scientific_notation); 55 | } 56 | sto_slot(i); 57 | return; 58 | } 59 | 60 | // mode 2, try to parse a number 61 | g_mem[i] = engine_num_alloc(); 62 | char *end; 63 | bf_atof(g_mem[i], s, (const char**) &end, 10, g_engine_prec, BF_RNDN); 64 | if (*end != '\0') { 65 | printf("%s: not a number\n", s); 66 | engine_num_free(g_mem[i]); 67 | g_mem[i] = 0; 68 | } else { 69 | engine_num_print(g_mem[i], 0, g_suppress_scientific_notation); 70 | } 71 | sto_slot(i); 72 | } 73 | 74 | // Recall a single number from memory 75 | static void do_rcl(unsigned int i) { 76 | bf_t *num = g_mem[i]; 77 | printf("MEM%u = ", i + 1); 78 | if (num == 0) { 79 | puts("(empty)"); 80 | } else { 81 | engine_num_print(num, 0, g_suppress_scientific_notation); 82 | } 83 | } 84 | 85 | // Clear a single memory slot 86 | static void do_clr(unsigned int i) { 87 | bf_t *num = g_mem[i]; 88 | if (num != 0) engine_num_free(num); 89 | g_mem[i] = 0; 90 | printf("Cleared slot %u.\n", i + 1); 91 | sto_slot(i); 92 | } 93 | 94 | unsigned int mem_run_command(char *s) { 95 | // the store and recall commands - /stoX and /rclX 96 | // also, new /clrX 97 | unsigned int is_sto = strncmp("sto", s, 3) == 0; 98 | unsigned int is_rcl = strncmp("rcl", s, 3) == 0; 99 | unsigned int is_clr = strncmp("clr", s, 3) == 0; 100 | if (is_sto || is_rcl || is_clr) { 101 | char c = s[3]; 102 | if (c >= '1' && c <= '9') { 103 | unsigned int i = c - '1'; 104 | if (is_sto) do_sto(i, &s[4]); 105 | if (is_rcl) do_rcl(i); 106 | if (is_clr) do_clr(i); 107 | } else { 108 | printf("%c: invalid memory slot\n", c); 109 | } 110 | return 1; 111 | } 112 | return 0; 113 | } 114 | 115 | // commands executed directly by command.c 116 | void do_clear_mem(char *s) { 117 | free_mem(); 118 | if (g_config_path) 119 | ini_puts("Memory", 0, 0, g_config_path); 120 | puts("Cleared memory."); 121 | } 122 | 123 | void do_show_mem(char *s) { 124 | for (unsigned int i = 0; i < CALC_MEMORY_SIZE; i++) { 125 | do_rcl(i); 126 | } 127 | } 128 | 129 | // called for ini sections 130 | void mem_try_load(const char *section, const char *key, const char *value) { 131 | if (strcmp(section, "Memory") == 0 && strncmp(key, "mem", 3) == 0) { 132 | char c = key[3]; 133 | if (c >= '1' && c <= '9') { 134 | unsigned int i = c - '1'; 135 | bf_t *num = engine_num_alloc(); 136 | char *end; 137 | bf_atof(num, value, (const char**) &end, 16, g_engine_prec, BF_RNDN); 138 | if (*end == '\0') { 139 | g_mem[i] = num; 140 | } else { 141 | engine_num_free(num); 142 | } 143 | } 144 | } 145 | } -------------------------------------------------------------------------------- /src/parse.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "expr.h" 4 | #include "parse.h" 5 | 6 | unsigned int g_parse_debug = 0; 7 | 8 | // Run the entire parser on the expression 9 | int parse_expr(char *s, vector_t *expr) { 10 | // Match brackets 11 | int err = match_brackets(s, expr); 12 | if (err != PARSE_SUCCESS) { 13 | expr_delete(*expr); 14 | return err; 15 | } 16 | if (g_parse_debug) { 17 | printf("match_brackets: "); 18 | expr_print(*expr); 19 | } 20 | 21 | // Tokenize (this destroys the old expr) 22 | err = tokenize(expr); 23 | if (err != PARSE_SUCCESS) return err; 24 | if (vector_get_len(*expr) == 0) { 25 | expr_delete(*expr); 26 | return PARSE_EMPTY_EXPRESSION; 27 | } 28 | if (g_parse_debug) { 29 | printf("tokenize: "); 30 | expr_print(*expr); 31 | } 32 | 33 | constants(*expr); 34 | if (g_parse_debug) { 35 | printf("constants: "); 36 | expr_print(*expr); 37 | } 38 | 39 | implicit_multiply(expr); 40 | if (g_parse_debug) { 41 | printf("implicit_multiply: "); 42 | expr_print(*expr); 43 | } 44 | 45 | unary_neg(*expr); 46 | if (g_parse_debug) { 47 | printf("unary_neg: "); 48 | expr_print(*expr); 49 | } 50 | 51 | return err; 52 | } 53 | 54 | void parse_print_error(int err) { 55 | switch(err) { 56 | case PARSE_SUCCESS: 57 | printf("success"); 58 | break; 59 | case PARSE_UNMATCHED_CLOSE_BRACKET: 60 | printf("unmatched close bracket"); 61 | break; 62 | case PARSE_UNMATCHED_OPEN_BRACKET: 63 | printf("unmatched open bracket"); 64 | break; 65 | case PARSE_INVALID_SYMBOL: 66 | printf("invalid symbol"); 67 | break; 68 | case PARSE_EMPTY_EXPRESSION: 69 | printf("empty expression"); 70 | break; 71 | default: 72 | printf("unknown error"); 73 | } 74 | } -------------------------------------------------------------------------------- /src/parse_ezpass.c: -------------------------------------------------------------------------------- 1 | #include "engine.h" 2 | #include "expr.h" 3 | #include "parse.h" 4 | #include "symbols.h" 5 | 6 | // Replace every constant symbol with an actual number, go figure 7 | // so like pi is 3.14, e is 2.7 8 | // Operates inplace 9 | void constants(vector_t expr) { 10 | unsigned int len = vector_get_len(expr); 11 | for (unsigned int i = 0; i < len; i++) { 12 | void *tk = vector_get(expr, i); 13 | unsigned int tag = token_untag(&tk); 14 | if (tag == TOKEN_SYM) { 15 | unsigned int sym = (unsigned int) (uintptr_t) tk; 16 | int c = g_sym_const[sym]; 17 | if (c != SYMC_NOT_CONSTANT) { 18 | bf_t *num = engine_copy_const(c); 19 | token_tag((void**) &num, TOKEN_NUM); 20 | vector_set(expr, i, num); 21 | // We don't need to delete the old one-just a symbol, literally a number 22 | } 23 | } else if (tag == TOKEN_EXPR) { 24 | constants((vector_t) tk); // gotta recurse 25 | } 26 | } 27 | } 28 | 29 | // Adds implicit multiplication symbols - whenever a subexpr is preceded by a postfix op, 30 | // a subexpr, or a decimal - never fails 31 | void implicit_multiply(vector_t *expr) { 32 | vector_t result = vector_new(); 33 | unsigned int len = vector_get_len(*expr); 34 | 35 | void *mul_tk = (void*) (uintptr_t) SYM_MUL; 36 | token_tag(&mul_tk, TOKEN_SYM); 37 | 38 | for (unsigned int i = 0; i < len; i++) { 39 | void *tk = vector_get(*expr, i); 40 | unsigned int tag = token_untag(&tk); 41 | 42 | if (tag == TOKEN_EXPR) { 43 | // First thing: recurse 44 | implicit_multiply((vector_t*) &tk); 45 | 46 | // Next: do we need a MUL symbol? 47 | if (i > 0) { 48 | void *prev_tk = vector_get(*expr, i - 1); 49 | unsigned int prev_tag = token_untag(&prev_tk); 50 | if (prev_tag == TOKEN_NUM || prev_tag == TOKEN_EXPR) { 51 | vector_add(result, mul_tk); 52 | } else if (prev_tag == TOKEN_SYM) { 53 | unsigned int sym = (unsigned int) (uintptr_t) prev_tk; 54 | char c = g_op_args[sym]; 55 | if (c == SYMO_UNARY_POSTFIX || c == SYMO_NOT_OPERATOR) { 56 | vector_add(result, mul_tk); 57 | } 58 | } 59 | } 60 | } 61 | 62 | token_tag(&tk, tag); 63 | vector_add(result, tk); 64 | } 65 | vector_delete(*expr); 66 | *expr = result; 67 | } 68 | 69 | // Swaps out SUB for NEG in situations where SUB is never valid (NEG might not be either) 70 | void unary_neg(vector_t expr) { 71 | void *neg_tk = (void*) (uintptr_t) SYM_NEG; 72 | token_tag(&neg_tk, TOKEN_SYM); 73 | 74 | unsigned int len = vector_get_len(expr); 75 | for (unsigned int i = 0; i < len; i++) { 76 | void *tk = vector_get(expr, i); 77 | unsigned int tag = token_untag(&tk); 78 | if (tag == TOKEN_SYM) { 79 | unsigned int sym = (unsigned int) (uintptr_t) tk; 80 | if (sym == SYM_SUB) { 81 | if (i == 0) { 82 | vector_set(expr, 0, neg_tk); 83 | } else { 84 | void *prev_tk = vector_get(expr, i - 1); 85 | unsigned int prev_tag = token_untag(&prev_tk); 86 | if (prev_tag == TOKEN_SYM) { 87 | unsigned int prev_sym = (unsigned int) (uintptr_t) prev_tk; 88 | char c = g_op_args[prev_sym]; 89 | if (c != SYMO_UNARY_POSTFIX && c != SYMO_NOT_OPERATOR) { 90 | vector_set(expr, i, neg_tk); 91 | } 92 | } 93 | } 94 | } 95 | } else if (tag == TOKEN_EXPR) { 96 | unary_neg((vector_t) tk); 97 | } 98 | } 99 | } -------------------------------------------------------------------------------- /src/parse_match_brackets.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "parse.h" 4 | #include "expr.h" 5 | 6 | // Append a str slice of size 1 to the end of top 7 | static void new_str_slice(vector_t top, char *s) { 8 | str_slice_t *str = (str_slice_t*) malloc(sizeof(str_slice_t)); 9 | str->ptr = s; 10 | str->len = 1; 11 | token_tag((void**) &str, TOKEN_STR); 12 | vector_add(top, str); 13 | } 14 | 15 | // Turn a string into an expr composed of slices and sub expressions 16 | // Error if too many opening brackets, or too many closing brackets 17 | int match_brackets(char *s, vector_t *expr) { 18 | *expr = vector_new(); 19 | vector_t stack = vector_new(); 20 | vector_add(stack, *expr); 21 | 22 | while (*s != '\0') { 23 | vector_t top = (vector_t) vector_get_last(stack); 24 | 25 | if (*s == '(') { 26 | vector_t new = vector_new(); 27 | vector_add(stack, new); 28 | token_tag((void**) &new, TOKEN_EXPR); 29 | vector_add(top, new); 30 | } else if (*s == ')') { 31 | if (vector_get_len(stack) == 1) { 32 | vector_delete(stack); 33 | return PARSE_UNMATCHED_CLOSE_BRACKET; 34 | } 35 | vector_remove(stack, vector_get_len(stack) - 1); 36 | } else if (vector_get_len(top) == 0) { 37 | new_str_slice(top, s); 38 | } else { 39 | void *last_tk = vector_get_last(top); 40 | unsigned int tag = token_untag(&last_tk); 41 | if (tag == TOKEN_STR) { 42 | str_slice_t *str = (str_slice_t*) last_tk; 43 | str->len++; 44 | } else { 45 | new_str_slice(top, s); 46 | } 47 | } 48 | s++; 49 | } 50 | 51 | // We should be at the top of the stack now 52 | if (vector_get_len(stack) > 1) { 53 | vector_delete(stack); 54 | return PARSE_UNMATCHED_OPEN_BRACKET; 55 | } 56 | 57 | vector_delete(stack); 58 | return PARSE_SUCCESS; 59 | } -------------------------------------------------------------------------------- /src/parse_tokenize.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "engine.h" 5 | #include "expr.h" 6 | #include "libbf.h" 7 | #include "parse.h" 8 | #include "symbols.h" 9 | 10 | // Read a number at the given position (return characters read) 11 | static int read_num(str_slice_t *str, bf_t **num) { 12 | *num = engine_num_alloc(); 13 | 14 | // conveniently enough, libbf has an out parameter that returns chars read 15 | const char *pnext; 16 | bf_atof(*num, str->ptr, &pnext, 10, g_engine_prec, BF_ATOF_NO_NAN_INF); 17 | 18 | return pnext - str->ptr; 19 | } 20 | 21 | // Read a symbol at the given position - return > SYM_MAX for error 22 | // (otherwise, return characters read) 23 | static int read_sym(str_slice_t *str, uintptr_t *sym) { 24 | // Find the symbol string that (prefix) matches 25 | for (unsigned int i = 0; i < g_sym_str_len; i++) { 26 | const sym_str_t *ss = &g_sym_str[i]; 27 | if (strncmp(ss->str, str->ptr, ss->len) == 0) { 28 | *sym = ss->sym; 29 | return ss->len; 30 | } 31 | } 32 | *sym = SYM_MAX+1; 33 | return 0; 34 | } 35 | 36 | // Tokenize a string into the given vector - possibility of error 37 | static int tokenize_str(str_slice_t *str, vector_t expr) { 38 | while (str->len > 0) { 39 | char c = *str->ptr; 40 | if (c == ' ') { 41 | // Skip whitespace 42 | str->len--; 43 | str->ptr++; 44 | } else if (c >= '0' && c <= '9') { 45 | // Read a number 46 | bf_t *num; 47 | unsigned int i = read_num(str, &num); 48 | str->len -= i; 49 | str->ptr += i; 50 | token_tag((void**) &num, TOKEN_NUM); 51 | vector_add(expr, num); 52 | } else { 53 | // Read a symbol 54 | uintptr_t sym; 55 | unsigned int i = read_sym(str, &sym); 56 | if (sym > SYM_MAX) return PARSE_INVALID_SYMBOL; 57 | str->len -= i; 58 | str->ptr += i; 59 | token_tag((void**) &sym, TOKEN_SYM); 60 | vector_add(expr, (void*)sym); 61 | } 62 | } 63 | return PARSE_SUCCESS; 64 | } 65 | 66 | // Tokenize the expression. Split STR into NUM and SYM 67 | static int internal_tokenize(vector_t expr, vector_t *result) { 68 | *result = vector_new(); 69 | unsigned int len = vector_get_len(expr); 70 | 71 | for (unsigned int i = 0; i < len; i++) { 72 | void *tk = vector_get(expr, i); 73 | unsigned int tag = token_untag(&tk); 74 | 75 | if (tag == TOKEN_EXPR) { 76 | // Recursively run the tokenizer 77 | vector_t sub_result; 78 | int err = internal_tokenize((vector_t) tk, &sub_result); 79 | if (err != PARSE_SUCCESS) { 80 | expr_delete(*result); 81 | return err; 82 | } 83 | token_tag((void**) &sub_result, TOKEN_EXPR); 84 | vector_add(*result, sub_result); 85 | } else if (tag == TOKEN_STR) { 86 | // Try to tokenize the string - a lot of the work happens here 87 | str_slice_t *str = (str_slice_t*) tk; 88 | int err = tokenize_str(str, *result); 89 | if (err != PARSE_SUCCESS) { 90 | expr_delete(*result); 91 | return err; 92 | } 93 | } else { 94 | // Panic! This would be a programmer error, so crashing is ok 95 | assert(0); 96 | } 97 | } 98 | 99 | return PARSE_SUCCESS; 100 | } 101 | 102 | // Wrapper that frees the old expression 103 | int tokenize(vector_t *expr) { 104 | vector_t result; 105 | int err = internal_tokenize(*expr, &result); 106 | expr_delete(*expr); 107 | *expr = result; 108 | return err; 109 | } -------------------------------------------------------------------------------- /src/stats.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "calc.h" 5 | #include "engine.h" 6 | #include "libbf.h" 7 | 8 | #ifdef _WIN32 9 | #include "readline.h" 10 | #else 11 | #include 12 | #endif 13 | 14 | #include "stats.h" 15 | #include "vector.h" 16 | 17 | // the statistics module of the calculator 18 | // calculates sample or population mean, variance, and standard deviation 19 | 20 | #define POPULATION 0 21 | #define SAMPLE 1 22 | 23 | // remove any remaining input from stdin 24 | static void clear_stdin() { 25 | int c; 26 | while ((c = getchar()) != '\n' && c != EOF) { } 27 | } 28 | 29 | static unsigned int sample_or_population() { 30 | while (1) { 31 | printf("\r(P)opulation or (S)ample? "); 32 | char c = getchar() & ~32; // convert to uppercase 33 | clear_stdin(); 34 | if (c == 'P') return POPULATION; 35 | if (c == 'S') return SAMPLE; 36 | } 37 | } 38 | 39 | // Free a dataset 40 | static void free_dataset(vector_t ds) { 41 | unsigned int len = vector_get_len(ds); 42 | for (unsigned int i = 0; i < len; i++) { 43 | bf_t *num = (bf_t*) vector_get(ds, i); 44 | engine_num_free(num); 45 | } 46 | vector_delete(ds); 47 | } 48 | 49 | // Read a dataset from the user; allow multiple of same number using 4.5|50 syntax 50 | static unsigned int read_dataset(vector_t *ds) { 51 | *ds = vector_new(); 52 | char *line, *original_line; 53 | line = original_line = readline("Dataset? "); 54 | 55 | while (*line != '\0') { 56 | while (*line == ' ') line++; // skip spaces 57 | 58 | char c = *line; 59 | unsigned char was_pipe = 0; 60 | if (c == '-' || c == '|') { 61 | if (c == '-') c = line[1]; 62 | if (c == '|' && vector_get_len(*ds) > 0) { 63 | was_pipe = 1; 64 | line++; 65 | c = *line; 66 | } 67 | } 68 | if (c < '0' || c > '9') { 69 | printf("Invalid character: %c\n", c); 70 | free_dataset(*ds); 71 | free(original_line); 72 | return 1; 73 | } 74 | 75 | if (was_pipe) { 76 | bf_t *repeat = (bf_t*) vector_get_last(*ds); 77 | long int count = strtol(line, &line, 10) - 1; 78 | if (count <= 0 || count > 65535) { 79 | printf("Invalid value for repeat: %ld\n", count + 1); 80 | free_dataset(*ds); 81 | free(original_line); 82 | return 1; 83 | } 84 | while (count) { 85 | bf_t *num = engine_num_alloc(); 86 | bf_set(num, repeat); 87 | vector_add(*ds, num); 88 | count--; 89 | } 90 | continue; 91 | } 92 | 93 | // handle repeated datapoints via the 4.3|5 syntax 94 | if (c == '|') { 95 | *line++; 96 | c = *line; 97 | } 98 | 99 | bf_t *num = engine_num_alloc(); 100 | vector_add(*ds, num); 101 | bf_atof(num, line, (const char**) &line, 10, g_engine_prec, BF_RNDN); 102 | } 103 | 104 | free(original_line); 105 | return 0; 106 | } 107 | 108 | // Calculate the mean of a dataset 109 | static bf_t* calc_mean(vector_t ds) { 110 | unsigned int len = vector_get_len(ds); 111 | 112 | bf_t *den = engine_num_alloc(); 113 | bf_set_ui(den, len); 114 | 115 | bf_t *acc = engine_num_alloc(); 116 | for (unsigned int i = 0; i < len; i++) { 117 | bf_t *num = (bf_t*) vector_get(ds, i); 118 | bf_add(acc, acc, num, g_engine_prec, BF_RNDN); 119 | } 120 | 121 | bf_div(acc, acc, den, g_engine_prec, BF_RNDN); 122 | engine_num_free(den); 123 | return acc; 124 | } 125 | 126 | // Calculate the variance (messes up the data set for performance) 127 | static bf_t* calc_variance(vector_t ds, bf_t *mean, unsigned int ds_type) { 128 | unsigned int len = vector_get_len(ds); 129 | 130 | bf_t *den = engine_num_alloc(); 131 | bf_set_ui(den, len); 132 | if (ds_type == SAMPLE) bf_sub(den, den, g_engine_const[ENGINE_CONST_ONE], g_engine_prec, BF_RNDN); 133 | 134 | bf_t *acc = engine_num_alloc(); 135 | for (unsigned int i = 0; i < len; i++) { 136 | bf_t *num = (bf_t*) vector_get(ds, i); 137 | bf_sub(num, num, mean, g_engine_prec, BF_RNDN); 138 | bf_mul(num, num, num , g_engine_prec, BF_RNDN); 139 | bf_add(acc, acc, num , g_engine_prec, BF_RNDN); 140 | } 141 | 142 | bf_div(acc, acc, den, g_engine_prec, BF_RNDN); 143 | engine_num_free(den); 144 | return acc; 145 | } 146 | 147 | void do_stats(char *s) { 148 | unsigned int ds_type = sample_or_population(); 149 | vector_t ds; 150 | unsigned int err = read_dataset(&ds); 151 | if (err == 1) return; 152 | 153 | unsigned int len = vector_get_len(ds); 154 | printf("Dataset has %u point(s).\n", len); 155 | if (len == 0) { 156 | free_dataset(ds); 157 | return; 158 | } 159 | 160 | bf_t *mean = calc_mean(ds); 161 | printf("Mean: "); 162 | engine_num_print(mean, 0, g_suppress_scientific_notation); 163 | 164 | bf_t *variance = calc_variance(ds, mean, ds_type); 165 | printf("Variance: "); 166 | engine_num_print(variance, 0, g_suppress_scientific_notation); 167 | 168 | bf_t *std_dev = engine_num_alloc(); 169 | bf_sqrt(std_dev, variance, g_engine_prec, BF_RNDN); 170 | printf("Standard Deviation: "); 171 | engine_num_print(std_dev, 0, g_suppress_scientific_notation); 172 | 173 | engine_num_free(mean); 174 | engine_num_free(variance); 175 | engine_num_free(std_dev); 176 | free_dataset(ds); 177 | } 178 | -------------------------------------------------------------------------------- /src/symbols.c: -------------------------------------------------------------------------------- 1 | #include "engine.h" 2 | #include "symbols.h" 3 | 4 | // THIS FILE CONTAINS DATA ONLY 5 | // (NO FUNCTIONS) 6 | // arrays are indexed by the symbol #defines - i try to make this clear 7 | 8 | // This *must* be sorted by length 9 | const sym_str_t g_sym_str[] = { 10 | { SYM_PERMU, "arrange", 7}, 11 | { SYM_COMBI, "choose" , 6}, 12 | { SYM_ASINH, "asinh" , 5 }, 13 | { SYM_ACOSH, "acosh" , 5 }, 14 | { SYM_ATANH, "atanh" , 5 }, 15 | { SYM_SINH , "sinh" , 4 }, 16 | { SYM_COSH , "cosh" , 4 }, 17 | { SYM_TANH , "tanh" , 4 }, 18 | { SYM_ASIN , "asin" , 4 }, 19 | { SYM_ACOS , "acos" , 4 }, 20 | { SYM_ATAN , "atan" , 4 }, 21 | { SYM_SQRT , "sqrt" , 4 }, 22 | { SYM_CBRT , "cbrt" , 4 }, 23 | { SYM_ROOT , "root" , 4 }, 24 | { SYM_RCL1 , "rcl1" , 4 }, 25 | { SYM_RCL2 , "rcl2" , 4 }, 26 | { SYM_RCL3 , "rcl3" , 4 }, 27 | { SYM_RCL4 , "rcl4" , 4 }, 28 | { SYM_RCL5 , "rcl5" , 4 }, 29 | { SYM_RCL6 , "rcl6" , 4 }, 30 | { SYM_RCL7 , "rcl7" , 4 }, 31 | { SYM_RCL8 , "rcl8" , 4 }, 32 | { SYM_RCL9 , "rcl9" , 4 }, 33 | { SYM_ANS , "ans" , 3 }, 34 | { SYM_EXP , "exp" , 3 }, 35 | { SYM_LOG , "log" , 3 }, 36 | { SYM_TAU , "tau" , 3 }, 37 | { SYM_SIN , "sin" , 3 }, 38 | { SYM_COS , "cos" , 3 }, 39 | { SYM_TAN , "tan" , 3 }, 40 | { SYM_ABS , "abs" , 3 }, 41 | { SYM_2FAC , "!!" , 2 }, 42 | { SYM_POW , "**" , 2 }, 43 | { SYM_LN , "ln" , 2 }, 44 | { SYM_PI , "pi" , 2 }, 45 | { SYM_ADD , "+" , 1 }, 46 | { SYM_SUB , "-" , 1 }, 47 | { SYM_MUL , "*" , 1 }, 48 | { SYM_DIV , "/" , 1 }, 49 | { SYM_MOD , "%" , 1 }, 50 | { SYM_POW , "^" , 1 }, 51 | { SYM_FAC , "!" , 1 }, 52 | { SYM_E , "e" , 1 }, 53 | { SYM_PERMU, "P" , 1 }, 54 | { SYM_COMBI, "C" , 1 }, 55 | }; 56 | const unsigned int g_sym_str_len = 43; 57 | 58 | const char * const g_sym_names[] = { 59 | "ANS", 60 | "NEG", 61 | "ADD", 62 | "SUB", 63 | "MUL", 64 | "DIV", 65 | "MOD", 66 | "EXP", 67 | "POW", 68 | "FAC", 69 | "SQRT", 70 | "CBRT", 71 | "ROOT", 72 | "LN", 73 | "LOG", 74 | "PI", 75 | "E", 76 | "TAU", 77 | "SIN", 78 | "COS", 79 | "TAN", 80 | "ASIN", 81 | "ACOS", 82 | "ATAN", 83 | "SINH", 84 | "COSH", 85 | "TANH", 86 | "ASINH", 87 | "ACOSH", 88 | "ATANH", 89 | "PERMU", 90 | "COMBI", 91 | "ABS", 92 | "RCL1", 93 | "RCL2", 94 | "RCL3", 95 | "RCL4", 96 | "RCL5", 97 | "RCL6", 98 | "RCL7", 99 | "RCL8", 100 | "RCL9", 101 | "2FAC", 102 | }; 103 | 104 | const char g_sym_const[] = { 105 | SYMC_NOT_CONSTANT, // ANS 106 | SYMC_NOT_CONSTANT, // NEG 107 | SYMC_NOT_CONSTANT, // ADD 108 | SYMC_NOT_CONSTANT, // SUB 109 | SYMC_NOT_CONSTANT, // MUL 110 | SYMC_NOT_CONSTANT, // DIV 111 | SYMC_NOT_CONSTANT, // MOD 112 | SYMC_NOT_CONSTANT, // EXP 113 | SYMC_NOT_CONSTANT, // POW 114 | SYMC_NOT_CONSTANT, // FAC 115 | SYMC_NOT_CONSTANT, // SQRT 116 | SYMC_NOT_CONSTANT, // CBRT 117 | SYMC_NOT_CONSTANT, // ROOT 118 | SYMC_NOT_CONSTANT, // LN 119 | SYMC_NOT_CONSTANT, // LOG 120 | ENGINE_CONST_PI , // PI 121 | ENGINE_CONST_E , // E 122 | ENGINE_CONST_TAU , // TAU 123 | SYMC_NOT_CONSTANT, // SIN 124 | SYMC_NOT_CONSTANT, // COS 125 | SYMC_NOT_CONSTANT, // TAN 126 | SYMC_NOT_CONSTANT, // ASIN 127 | SYMC_NOT_CONSTANT, // ACOS 128 | SYMC_NOT_CONSTANT, // ATAN 129 | SYMC_NOT_CONSTANT, // SINH 130 | SYMC_NOT_CONSTANT, // COSH 131 | SYMC_NOT_CONSTANT, // TANH 132 | SYMC_NOT_CONSTANT, // ASINH 133 | SYMC_NOT_CONSTANT, // ACOSH 134 | SYMC_NOT_CONSTANT, // ATANH 135 | SYMC_NOT_CONSTANT, // PERMU 136 | SYMC_NOT_CONSTANT, // COMBI 137 | SYMC_NOT_CONSTANT, // ABS 138 | SYMC_NOT_CONSTANT, // RCL1 139 | SYMC_NOT_CONSTANT, // RCL2 140 | SYMC_NOT_CONSTANT, // RCL3 141 | SYMC_NOT_CONSTANT, // RCL4 142 | SYMC_NOT_CONSTANT, // RCL5 143 | SYMC_NOT_CONSTANT, // RCL6 144 | SYMC_NOT_CONSTANT, // RCL7 145 | SYMC_NOT_CONSTANT, // RCL8 146 | SYMC_NOT_CONSTANT, // RCL9 147 | SYMC_NOT_CONSTANT, // 2FAC 148 | }; 149 | 150 | const char g_op_args[] = { 151 | SYMO_NOT_OPERATOR , // ANS 152 | SYMO_UNARY_PREFIX , // NEG 153 | SYMO_BINARY , // ADD 154 | SYMO_BINARY , // SUB 155 | SYMO_BINARY , // MUL 156 | SYMO_BINARY , // DIV 157 | SYMO_BINARY , // MOD 158 | SYMO_UNARY_PREFIX , // EXP 159 | SYMO_BINARY , // POW 160 | SYMO_UNARY_POSTFIX, // FAC 161 | SYMO_UNARY_PREFIX , // SQRT 162 | SYMO_UNARY_PREFIX , // CBRT 163 | SYMO_BINARY , // ROOT 164 | SYMO_UNARY_PREFIX , // LN 165 | SYMO_BINARY , // LOG 166 | SYMO_NOT_OPERATOR , // PI 167 | SYMO_NOT_OPERATOR , // E 168 | SYMO_NOT_OPERATOR , // TAU 169 | SYMO_UNARY_PREFIX , // SIN 170 | SYMO_UNARY_PREFIX , // COS 171 | SYMO_UNARY_PREFIX , // TAN 172 | SYMO_UNARY_PREFIX , // ASIN 173 | SYMO_UNARY_PREFIX , // ACOS 174 | SYMO_UNARY_PREFIX , // ATAN 175 | SYMO_UNARY_PREFIX , // SINH 176 | SYMO_UNARY_PREFIX , // COSH 177 | SYMO_UNARY_PREFIX , // TANH 178 | SYMO_UNARY_PREFIX , // ASINH 179 | SYMO_UNARY_PREFIX , // ACOSH 180 | SYMO_UNARY_PREFIX , // ATANH 181 | SYMO_BINARY , // PERMU 182 | SYMO_BINARY , // COMBI 183 | SYMO_UNARY_PREFIX , // ABS 184 | SYMA_NOT_OPERATOR , // RCL1 185 | SYMA_NOT_OPERATOR , // RCL2 186 | SYMA_NOT_OPERATOR , // RCL3 187 | SYMA_NOT_OPERATOR , // RCL4 188 | SYMA_NOT_OPERATOR , // RCL5 189 | SYMA_NOT_OPERATOR , // RCL6 190 | SYMA_NOT_OPERATOR , // RCL7 191 | SYMA_NOT_OPERATOR , // RCL8 192 | SYMA_NOT_OPERATOR , // RCL9 193 | SYMO_UNARY_POSTFIX, // 2FAC 194 | }; 195 | 196 | const unsigned int g_op_precedence[] = { 197 | SYMP_NOT_OPERATOR, // ANS 198 | 0 , // NEG 199 | 5 , // ADD 200 | 5 , // SUB 201 | 4 , // MUL 202 | 4 , // DIV 203 | 4 , // MOD 204 | 0 , // EXP 205 | 3 , // POW 206 | 1 , // FAC 207 | 0 , // SQRT 208 | 0 , // CBRT 209 | 3 , // ROOT 210 | 0 , // LN 211 | 2 , // LOG 212 | SYMP_NOT_OPERATOR, // PI 213 | SYMP_NOT_OPERATOR, // E 214 | SYMP_NOT_OPERATOR, // TAU 215 | 0 , // SIN 216 | 0 , // COS 217 | 0 , // TAN 218 | 0 , // ASIN 219 | 0 , // ACOS 220 | 0 , // ATAN 221 | 0 , // SINH 222 | 0 , // COSH 223 | 0 , // TANH 224 | 0 , // ASINH 225 | 0 , // ACOSH 226 | 0 , // ATANH 227 | 2 , // PERMU 228 | 2 , // COMBI 229 | 0 , // ABS 230 | SYMP_NOT_OPERATOR, // RCL1 231 | SYMP_NOT_OPERATOR, // RCL2 232 | SYMP_NOT_OPERATOR, // RCL3 233 | SYMP_NOT_OPERATOR, // RCL4 234 | SYMP_NOT_OPERATOR, // RCL5 235 | SYMP_NOT_OPERATOR, // RCL6 236 | SYMP_NOT_OPERATOR, // RCL7 237 | SYMP_NOT_OPERATOR, // RCL8 238 | SYMP_NOT_OPERATOR, // RCL9 239 | 1 , // 2FAC 240 | }; 241 | 242 | const char g_op_associativity[] = { 243 | SYMA_NOT_OPERATOR, // ANS 244 | SYMA_RIGHT , // NEG 245 | SYMA_LEFT , // ADD 246 | SYMA_LEFT , // SUB 247 | SYMA_LEFT , // MUL 248 | SYMA_LEFT , // DIV 249 | SYMA_LEFT , // MOD 250 | SYMA_RIGHT , // EXP 251 | SYMA_RIGHT , // POW 252 | SYMA_LEFT , // FAC 253 | SYMA_RIGHT , // SQRT 254 | SYMA_RIGHT , // CBRT 255 | SYMA_LEFT , // ROOT 256 | SYMA_RIGHT , // LN 257 | SYMA_LEFT , // LOG 258 | SYMA_NOT_OPERATOR, // PI 259 | SYMA_NOT_OPERATOR, // E 260 | SYMA_NOT_OPERATOR, // TAU 261 | SYMA_RIGHT , // SIN 262 | SYMA_RIGHT , // COS 263 | SYMA_RIGHT , // TAN 264 | SYMA_RIGHT , // ASIN 265 | SYMA_RIGHT , // ACOS 266 | SYMA_RIGHT , // ATAN 267 | SYMA_RIGHT , // SINH 268 | SYMA_RIGHT , // COSH 269 | SYMA_RIGHT , // TANH 270 | SYMA_RIGHT , // ASINH 271 | SYMA_RIGHT , // ACOSH 272 | SYMA_RIGHT , // ATANH 273 | SYMA_LEFT , // PERMU 274 | SYMA_LEFT , // COMBI 275 | SYMA_RIGHT , // ABS 276 | SYMA_NOT_OPERATOR, // RCL1 277 | SYMA_NOT_OPERATOR, // RCL2 278 | SYMA_NOT_OPERATOR, // RCL3 279 | SYMA_NOT_OPERATOR, // RCL4 280 | SYMA_NOT_OPERATOR, // RCL5 281 | SYMA_NOT_OPERATOR, // RCL6 282 | SYMA_NOT_OPERATOR, // RCL7 283 | SYMA_NOT_OPERATOR, // RCL8 284 | SYMA_NOT_OPERATOR, // RCL9 285 | SYMA_LEFT , // 2FAC 286 | }; 287 | 288 | const arg_collect_t g_op_arg_collect[] = { 289 | {1, {1, 0} , {1, 0} , 0 }, // SYMO_UNARY_PREFIX 290 | {1, {-1, 0}, {-1, 0}, -1}, // SYMO_UNARY_POSTFIX 291 | {2, {-1, 1}, {1, -1}, -1}, // SYMO_BINARY 292 | }; 293 | 294 | // actual math stuff - took a while to get here 295 | op_func_t * const g_op_funcs[] = { 296 | 0 , // ANS 297 | calc_neg , // NEG 298 | calc_add , // ADD 299 | calc_sub , // SUB 300 | calc_mul , // MUL 301 | calc_div , // DIV 302 | calc_mod , // MOD 303 | calc_exp , // EXP 304 | calc_pow , // POW 305 | calc_fac , // FAC 306 | calc_sqrt , // SQRT 307 | calc_cbrt , // CBRT 308 | calc_root , // ROOT 309 | calc_ln , // LN 310 | calc_log , // LOG 311 | 0 , // PI 312 | 0 , // E 313 | 0 , // TAU 314 | calc_sin , // SIN 315 | calc_cos , // COS 316 | calc_tan , // TAN 317 | calc_asin , // ASIN 318 | calc_acos , // ACOS 319 | calc_atan , // ATAN 320 | calc_sinh , // SINH 321 | calc_cosh , // COSH 322 | calc_tanh , // TANH 323 | calc_asinh, // ASINH 324 | calc_acosh, // ACOSH 325 | calc_atanh, // ATANH 326 | calc_permu, // PERMU 327 | calc_combi, // COMBI 328 | calc_abs , // ABS 329 | 0 , // RCL1 330 | 0 , // RCL2 331 | 0 , // RCL3 332 | 0 , // RCL4 333 | 0 , // RCL5 334 | 0 , // RCL6 335 | 0 , // RCL7 336 | 0 , // RCL8 337 | 0 , // RCL9 338 | calc_2fac , // 2FAC 339 | }; -------------------------------------------------------------------------------- /src/vector.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "vector.h" 6 | 7 | /* 8 | * a: vector 9 | * b: backing store 10 | * x: item 11 | * i: index 12 | */ 13 | 14 | // Allocate a vector of the given capacity 15 | static internal_vector_t* vector_alloc(int cap) { 16 | size_t sz = sizeof(internal_vector_t) + sizeof(void*) * cap; 17 | internal_vector_t *b = (internal_vector_t*) malloc(sz); 18 | memset(b, 0, sz); 19 | b->cap = cap; 20 | return b; 21 | } 22 | 23 | // Create a new vector 24 | vector_t vector_new() { 25 | internal_vector_t *b = vector_alloc(16); 26 | // Use a second layer of indirection to let us swap out the backing store 27 | vector_t a = (vector_t) malloc(sizeof(internal_vector_t*)); 28 | *a = b; 29 | return a; 30 | } 31 | 32 | // Deletes a vector (NOTE: does not attempt to free members) 33 | void vector_delete(vector_t a) { 34 | internal_vector_t *b = *a; 35 | free(a); 36 | free(b); 37 | } 38 | 39 | unsigned int vector_get_len(vector_t a) { 40 | return (*a)->len; 41 | } 42 | 43 | // We don't let the user read past len, even if it's within cap 44 | void* vector_get(vector_t a, unsigned int i) { 45 | internal_vector_t *b = *a; 46 | assert(i < b->len); 47 | return b->buf[i]; 48 | } 49 | 50 | void* vector_get_last(vector_t a) { 51 | internal_vector_t *b = *a; 52 | assert(b->len >= 1); 53 | return b->buf[b->len-1]; 54 | } 55 | 56 | void vector_set(vector_t a, unsigned int i, void* x) { 57 | internal_vector_t *b = *a; 58 | assert(i < b->len); 59 | b->buf[i] = x; 60 | } 61 | 62 | static internal_vector_t* vector_resize(internal_vector_t *b, unsigned int cap) { 63 | // Clone the old one into the new one 64 | internal_vector_t* b2 = vector_alloc(cap); 65 | b2->len = b->len; 66 | memcpy(b2->buf, b->buf, sizeof(void*) * b->len); 67 | 68 | // Clean the old one 69 | free(b); 70 | return b2; 71 | } 72 | 73 | // Add an item to the vector, reallocating if neccessary 74 | void vector_add(vector_t a, void* x) { 75 | internal_vector_t *b = *a; 76 | 77 | // If the vector doesn't have room, we must resize it 78 | if (b->len >= b->cap) 79 | *a = b = vector_resize(b, b->cap * 2); 80 | 81 | b->buf[b->len] = x; 82 | b->len++; 83 | } 84 | 85 | // Remove an item from the vector 86 | void vector_remove(vector_t a, unsigned int i) { 87 | internal_vector_t *b = *a; 88 | assert(i < b->len); 89 | 90 | memmove(&b->buf[i], &b->buf[i+1], sizeof(void*) * (b->len - i - 1)); 91 | b->buf[b->len-1] = 0; 92 | b->len--; 93 | 94 | // If the vector is too big, we resize it here - must save memory 95 | if (b->len <= (b->cap / 3)) 96 | *a = vector_resize(b, b->cap / 2); 97 | } --------------------------------------------------------------------------------