├── 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 | 
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 | 
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 | }
--------------------------------------------------------------------------------