├── .editorconfig
├── .github
├── ISSUE_TEMPLATE
│ └── bug_report.md
└── workflows
│ ├── build-osx.yaml
│ └── c-cpp.yml
├── .gitignore
├── .travis.yml
├── AUTHORS
├── COPYING
├── ChangeLog
├── LICENSE
├── Makefile.am
├── NEWS
├── README
├── README.md
├── bitwise.1
├── bootstrap.sh
├── configure.ac
├── debian
├── changelog
├── compat
├── control
├── copyright
├── rules
├── source
│ └── format
└── watch
├── inc
├── bitwise.h
├── shunting-yard.h
└── stack.h
├── m4
├── ax_lib_readline.m4
├── ax_require_defined.m4
├── ax_with_curses.m4
└── ax_with_curses_extra.m4
├── resources
├── bitwise.gif
├── bitwise.png
├── bitwise.svg
├── cmdline.png
├── conversion.png
└── snip.txt
├── snapcraft.yaml
├── src
├── cmd.c
├── help.c
├── interactive.c
├── main.c
├── misc.c
├── shunting-yard.c
└── stack.c
├── tests
└── test-shunting-yard.c
└── ubuntu_release.sh
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [**]
4 | insert_final_newline = true
5 | charset = utf-8
6 |
7 | [**.{c,h}]
8 | indent_style = tab
9 | indent_size = tab
10 | trim_trailing_whitespace = true
11 |
12 | [**.{yml,yaml}]
13 | indent_style = space
14 | indent_size = 2
15 | trim_trailing_whitespace = true
16 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug
6 | assignees: mellowcandle
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Version:**
27 | - [e.g. v0.32, master]
28 |
29 | **Desktop (please complete the following information):**
30 | - OS: [e.g. Linux Fedora / Ubuntu 18.04]
31 |
32 | **Additional context**
33 | Add any other context about the problem here.
34 |
--------------------------------------------------------------------------------
/.github/workflows/build-osx.yaml:
--------------------------------------------------------------------------------
1 | name: C/C++ CI
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | jobs:
10 | build:
11 | env:
12 | LDFLAGS: "-L/usr/local/opt/readline/lib"
13 | CPPFLAGS: "-I/usr/local/opt/readline/include"
14 |
15 | runs-on: macos-latest
16 |
17 | steps:
18 | - uses: actions/checkout@v2
19 | - name: Install lib-cunit
20 | run: brew install readline cunit autoconf automake
21 | - name: Bootstrap
22 | run: ./bootstrap.sh
23 | - name: configure
24 | run: ./configure
25 | - name: make check
26 | run: make check
27 |
28 |
--------------------------------------------------------------------------------
/.github/workflows/c-cpp.yml:
--------------------------------------------------------------------------------
1 | name: C/C++ CI
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | jobs:
10 | build:
11 |
12 | runs-on: ubuntu-latest
13 |
14 | steps:
15 | - uses: actions/checkout@v2
16 | - name: Install xmllint
17 | run: sudo apt-get install libcunit1-dev
18 | - name: Bootstrap
19 | run: ./bootstrap.sh
20 | - name: configure
21 | run: ./configure --enable-gcov
22 | - name: make check
23 | run: make check
24 |
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 |
4 | # Object files
5 | *.o
6 | *.ko
7 | *.obj
8 | *.elf
9 |
10 | # Linker output
11 | *.ilk
12 | *.map
13 | *.exp
14 |
15 | # Precompiled Headers
16 | *.gch
17 | *.pch
18 |
19 | # Libraries
20 | *.lib
21 | *.a
22 | *.la
23 | *.lo
24 |
25 | # Shared objects (inc. Windows DLLs)
26 | *.dll
27 | *.so
28 | *.so.*
29 | *.dylib
30 |
31 | # Executables
32 | bitwise
33 | *.exe
34 | *.out
35 | *.app
36 | *.i*86
37 | *.x86_64
38 | *.hex
39 |
40 | # Build output
41 | config.log
42 | inc/config.h
43 | inc/stamp-h1
44 | src/.deps/
45 | src/.dirstamp
46 | tests/.deps/
47 |
48 | # Debug files
49 | *.dSYM/
50 | *.su
51 | *.idb
52 | *.pdb
53 |
54 | # Kernel Module Compile Results
55 | *.mod*
56 | *.cmd
57 | .tmp_versions/
58 | modules.order
59 | Module.symvers
60 | Mkfile.old
61 | dkms.conf
62 |
63 | # Autotools stuff
64 | Makefile
65 | *.in
66 | aclocal.m4
67 | autom4te.cache/
68 | build-aux/
69 | config.status
70 | configure
71 | pre-inst-env
72 | install-sh
73 | missing
74 | test-driver
75 | compile
76 | depcomp
77 |
78 | # tracing stuff
79 | log.txt
80 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: c
2 |
3 | compiler: gcc
4 |
5 | os:
6 | - linux
7 | - osx
8 |
9 | arch:
10 | - AMD64
11 | - ppc64le
12 |
13 | before_install:
14 | - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get -qq update ; fi
15 | - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get install libcunit1-dev ; fi
16 | - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install readline; fi
17 | - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install cunit; fi
18 | - if [ "$TRAVIS_OS_NAME" == "osx" ]; then export LDFLAGS="-L/usr/local/opt/readline/lib"; fi
19 | - if [ "$TRAVIS_OS_NAME" == "osx" ]; then export CPPFLAGS="-I/usr/local/opt/readline/include"; fi
20 |
21 | script:
22 | - "./bootstrap.sh"
23 | - if [ "$TRAVIS_OS_NAME" = "linux" ]; then ./configure --enable-gcov; fi
24 | - if [ "$TRAVIS_OS_NAME" = "linux" ]; then make check; fi
25 |
26 | - if [ "$TRAVIS_OS_NAME" = "osx" ]; then ./configure; fi
27 | - if [ "$TRAVIS_OS_NAME" = "osx" ]; then make check; fi
28 |
29 | after_success:
30 | - bash <(curl -s https://codecov.io/bash)
31 |
32 | after_failure:
33 | - if [ -f ./test-suite.log ]; then cat ./test-suite.log; fi
34 |
35 |
--------------------------------------------------------------------------------
/AUTHORS:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mellowcandle/bitwise/0a4e7d93b3e922e2293251fdbfd0e4fb1cc7910b/AUTHORS
--------------------------------------------------------------------------------
/COPYING:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C)
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/ChangeLog:
--------------------------------------------------------------------------------
1 | Bitwise v0.20
2 | ==========================================
3 | * Added calculator mode
4 | * Added support for commandline interface
5 | in interactive mode.
6 |
7 | Bitwise v0.14
8 | ==========================================
9 | * Added NOT (~) command to interactive mode
10 | * Support binary input in command line mode
11 | * Updated documentation
12 |
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C)
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/Makefile.am:
--------------------------------------------------------------------------------
1 | bin_PROGRAMS=bitwise
2 | bitwise_SOURCES= src/main.c src/misc.c \
3 | src/interactive.c src/cmd.c \
4 | src/stack.c src/shunting-yard.c \
5 | src/help.c inc/bitwise.h inc/stack.h \
6 | inc/shunting-yard.h
7 |
8 | dist_man_MANS=bitwise.1
9 |
10 | if COND_GCOV
11 | MAYBE_COVERAGE=--coverage --no-inline
12 | endif
13 |
14 | if COND_TRACE
15 | MAYBE_TRACE=-DTRACE
16 | endif
17 |
18 | if COND_DEBUG
19 | MAYBE_DEBUG=-g -O0
20 | endif
21 |
22 | AM_CFLAGS = $(MAYBE_COVERAGE) $(MAYBE_DEBUG) $(MAYBE_TRACE)
23 |
24 | check_PROGRAMS = tests/test-shunting-yard
25 | tests_test_shunting_yard_SOURCES = src/shunting-yard.c inc/shunting-yard.h \
26 | src/stack.c inc/stack.h inc/bitwise.h \
27 | src/misc.c \
28 | tests/test-shunting-yard.c
29 | tests_test_shunting_yard_LDADD = -lcunit
30 |
31 | TESTS = $(check_PROGRAMS)
32 |
33 | clean-local:
34 | rm -f *.gcno
35 |
--------------------------------------------------------------------------------
/NEWS:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mellowcandle/bitwise/0a4e7d93b3e922e2293251fdbfd0e4fb1cc7910b/NEWS
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | README.md
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Bitwise
2 | ## Terminal based bitwise calculator in curses
3 | [](https://build.snapcraft.io/user/mellowcandle/bitwise)
4 |
6 |
7 |
8 |
9 |
10 | _Bitwise_ is multi base interactive calculator supporting dynamic base conversion and bit manipulation.
11 | It's a handy tool for low level hackers, kernel developers and device drivers developers.
12 |
13 | Some of the features include:
14 | * Interactive ncurses interface
15 | * Command line calculator supporting all bitwise operations.
16 | * Individual bit manipulator.
17 | * Bitwise operations such as NOT, OR, AND, XOR, and shifts.
18 |
19 | ##
20 |
21 | 
22 |
23 | ## Usage
24 | _bitwise_ can be used both interactively and in command line mode.
25 |
26 | ### Command line calculator mode
27 | In command line mode, bitwise will calculate the given expression and will output the result in all bases including binary representation.
28 |
29 | _bitwise_ detects the base by the prefix of the input (_0x/0X_ for hexadecimal, leading _0_ for octal, _b_ for binary, and the rest is decimal).
30 |
31 | **NEW** Bitwise now support parsing IPv4 addresses, it will also output the possible IPv4 address in both Network and reversed byte order.
32 |
33 | ### Examples:
34 |
35 | #### Simple base conversion
36 |
37 | 
38 |
39 |
40 | #### C style syntax Calculator
41 |
42 | 
43 |
44 | ### Interactive mode
45 | _bitwise_ starts in interactive mode if no command line parameters are passed or if the _-i | --interactive_ flag is passed.
46 | In this mode, you can input a number and manipulate it and see the other bases change dynamically.
47 | It also allows changing individual bits in the binary.
48 | You can show the help screen by pressing F1 .
49 |
50 | #### Navigation in interactive mode
51 | To move around use the arrow keys, or use _vi_ key bindings : h j k l .
52 | Leave the program by pressing q .
53 |
54 | ##### Binary specific movement
55 | You can toggle a bit using the space key.
56 | You can jump a byte forward using w and backwards one byte using b .
57 |
58 | #### Bitwise operation in interactive mode
59 |
60 | ##### Setting the bit width:
61 |
62 | Reducing or extending the bit width interactively is also very easy, just use:
63 | ! for 8bit, @ for 16Bit, $ for 32Bit and * for 64Bit.
64 | When changing the bit width, the number is *masked* with the new width, so you might lose precision, use with care.
65 |
66 | ##### NOT:
67 |
68 | Press ~ to perform the NOT operator.
69 |
70 | ##### Reversing Endianness:
71 |
72 | Press r to reverse the endianness.
73 |
74 | ##### Shifts
75 |
76 | Press < and > to perform the left or right shift.
77 |
78 | #### expression calculator in interactive mode
79 |
80 | You can enter expression calculator mode by typing : (Just like in vim).
81 |
82 | To exit the mode, just press ESC .
83 |
84 | In this mode, you can type any expression you like to be evaluated.
85 | The result will be printed in the history window and also printed in the binary and various bases on top.
86 |
87 | ###### operators and functions
88 | * All C operators are supported, additionally, you can use the "$" symbol to refer to the last result.
89 | * Refer to a specific bit by using the function _BIT(x)_.
90 |
91 | ###### commands
92 | * _h(elp)_ - Show the help screen.
93 | * _c(lear)_ - Clear the history window.
94 | * _w(idth)_ [8 | 16 | 32 | 64] - Set the required width mask
95 | * _o(utput)_ [dec(imal) | hex(adecimal) | oct(al) | bin(ary) | all] - Set the default output for results.
96 | * _q(uit)_ - Exit
97 |
98 | ## Integration with other software
99 | ### Vim
100 | * [vim-bitwise](https://github.com/mellowcandle/vim-bitwise "vim bitwise")
101 |
102 | ## Installation
103 |
104 | ### Linux
105 | #### Ubuntu
106 | From 20.04 you can just type
107 | ```
108 | sudo apt-get install bitwise
109 | ```
110 | For earlier versions:
111 | ```
112 | sudo add-apt-repository ppa:ramon-fried/bitwise
113 | sudo apt-get update
114 | sudo apt-get install bitwise
115 | ```
116 | #### Snap
117 | If your distribution supports Snap just type:
118 | `
119 | sudo snap install bitwise
120 | `
121 | #### OpenSuse
122 | `
123 | zypper install bitwise
124 | `
125 |
126 | #### Arch
127 | You can use the AUR repository: https://aur.archlinux.org/packages/bitwise/
128 |
129 | #### Void
130 | _bitwise_ is in the default repository, so just type:
131 | `
132 | sudo xbps-install -S bitwise
133 | `
134 |
135 | #### Fedora Linux
136 |
137 | bitwise is available in the [official repository](https://src.fedoraproject.org/rpms/bitwise)
138 |
139 | ```
140 | sudo dnf install bitwise
141 | ```
142 |
143 | #### Buildroot / Yocto
144 | Bitwise is available both in Buildroot and in Yocto, please refer to the documentation on how to add those to your target image.
145 |
146 | ### macOS
147 |
148 | #### MacPorts
149 | ```
150 | sudo port install bitwise
151 | ```
152 |
153 | #### Homebrew
154 | ```
155 | brew install bitwise
156 | ```
157 |
158 | ### Windows
159 | NCurses doesn't support Windows. You can use the Windows Subsystem for Linux as a workaround.
160 |
161 | ### Nix
162 | ```
163 | nix-env -i bitwise
164 | ```
165 |
166 | ### Building from source
167 |
168 | #### Prerequisites
169 | * libreadline
170 | * libncurses (with forms)
171 | * libcunit (only needed for testing)
172 |
173 | On Ubuntu/Debian system you can just paste:
174 | ```
175 | sudo apt-get install build-essential
176 | sudo apt-get install libncurses5-dev
177 | sudo apt-get install libreadline-dev
178 | sudo apt-get install libcunit1-dev
179 | ```
180 | On Mac systems:
181 | ```
182 | brew install automake
183 | brew install autoconf
184 | brew install readline
185 | export LDFLAGS="-L/usr/local/opt/readline/lib"
186 | export CPPFLAGS="-I/usr/local/opt/readline/include"
187 | ```
188 | - Download [the latest release](https://github.com/mellowcandle/bitwise/releases/latest)
189 |
190 | ```sh
191 | tar xfz RELEASE-FILE.TAR.GZ
192 | cd RELEASE-DIR
193 | ./configure
194 | make
195 | sudo make install
196 | ```
197 |
198 | Running unit tests by typing
199 | ``` make check ```
200 |
201 | ### Contribution
202 | * Install prerequisites
203 | * Fork the repo
204 | * Run ```./bootstrap.sh```
205 | * Follow the building from source section.
206 | * commit and send pull request
207 |
--------------------------------------------------------------------------------
/bitwise.1:
--------------------------------------------------------------------------------
1 | .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.47.10.
2 | .TH BITWISE "1" "July 2023" "bitwise v0.50" "User Commands"
3 | .SH NAME
4 | bitwise \- Terminal based bit manipulator in ncurses
5 | .SH SYNOPSIS
6 | .B bitwise
7 | [\fI\,OPTION\/\fR...] [\fI\,expression\/\fR]
8 | .SH DESCRIPTION
9 | [expression] mathematical expression
10 | .TP
11 | \fB\-i\fR, \fB\-\-interactive\fR
12 | Load interactive mode (default if no input)
13 | .TP
14 | \fB\-w\fR, \fB\-\-width[b\fR|w|l|d]
15 | Set bit width (default: l)
16 | .TP
17 | \fB\-h\fR, \fB\-\-help\fR
18 | Display this help and exit
19 | .TP
20 | \fB\-v\fR, \fB\-\-version\fR
21 | Output version information and exit
22 | .TP
23 | \fB\-s\fR, \fB\-\-si\fR
24 | Output sizes according to SI standard. (default: IEC standard)
25 | .TP
26 | \fB\-\-no\-color\fR
27 | Start without color support
28 | .SH AUTHOR
29 | Written by Ramon Fried
30 | .SH "SEE ALSO"
31 | The full documentation for
32 | .B bitwise
33 | can be found at https://github.com/mellowcandle/bitwise
34 |
--------------------------------------------------------------------------------
/bootstrap.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | autoreconf --verbose --install --force
4 |
--------------------------------------------------------------------------------
/configure.ac:
--------------------------------------------------------------------------------
1 | # -*- Autoconf -*-
2 | # Process this file with autoconf to produce a configure script.
3 |
4 | AC_PREREQ([2.69])
5 | AC_INIT([bitwise], [v0.50], [rfried.dev@gmail.com])
6 | AC_CONFIG_SRCDIR([src/misc.c])
7 | AC_CONFIG_HEADERS([inc/config.h])
8 |
9 | dnl Document where we keep our .m4 file.
10 | AC_CONFIG_MACRO_DIR([m4])
11 | dnl Make sure aclocal actually found it!
12 | m4_pattern_forbid([^AX_])
13 |
14 | AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
15 |
16 | # Checks for programs.
17 | AC_PROG_CC
18 | AC_PROG_CC_STDC
19 | AC_PROG_INSTALL
20 | AC_PROG_CC_C99
21 |
22 | AX_LIB_READLINE
23 | if test "$ac_cv_have_readline" = no; then
24 | AC_MSG_ERROR([requires readline library])
25 | fi
26 |
27 | # Checks for libraries.
28 | AC_CHECK_LIB([form], [form_driver])
29 | AC_CHECK_LIB([ncurses], [newwin])
30 | AC_SEARCH_LIBS([sqrt], [m])
31 |
32 | # Checks for header files.
33 | AC_CHECK_HEADERS([fcntl.h inttypes.h stdint.h stdlib.h string.h curses.h form.h])
34 |
35 | AC_CHECK_DECLS([bswap_32], [], [], [[#include ]])
36 | AM_CONDITIONAL(HAVE_BYTESWAP_H, [test "x$ac_cv_have_decl_bswap_32" = "xyes"])
37 |
38 | # Checks for typedefs, structures, and compiler characteristics.
39 | AC_CHECK_HEADER_STDBOOL
40 | AC_TYPE_UINT64_T
41 |
42 | # Checks for library functions.
43 | AC_FUNC_STRCOLL
44 | AC_CHECK_FUNCS([memchr memmove memset stpcpy strchr strcspn strdup strerror strpbrk strrchr strspn strstr])
45 |
46 | AC_CONFIG_FILES([Makefile])
47 |
48 | AC_ARG_ENABLE([gcov],
49 | [AS_HELP_STRING([--enable-gcov],
50 | [Build with coverage support])],
51 | [],
52 | [enable_gcov=no])
53 | AM_CONDITIONAL([COND_GCOV],[test '!' "$enable_gcov" = no])
54 |
55 | AC_ARG_ENABLE([trace],
56 | [AS_HELP_STRING([--enable-trace],
57 | [Build with trace support])],
58 | [],
59 | [enable_trace=no])
60 | AM_CONDITIONAL([COND_TRACE],[test '!' "$enable_trace" = no])
61 |
62 | AC_ARG_ENABLE([debug],
63 | [AS_HELP_STRING([--enable-debug],
64 | [Build with debug symbols])],
65 | [],
66 | [enable_debug=no])
67 | AM_CONDITIONAL([COND_DEBUG],[test '!' "$enable_debug" = no])
68 |
69 | AC_OUTPUT
70 |
--------------------------------------------------------------------------------
/debian/changelog:
--------------------------------------------------------------------------------
1 | bitwise (0.40-1) unstable; urgency=medium
2 |
3 | * Initial release Closes: Bug#933990
4 |
5 | -- Ramon Fried Sat, 10 Aug 2019 21:00:03 -0400
6 |
--------------------------------------------------------------------------------
/debian/compat:
--------------------------------------------------------------------------------
1 | 12
2 |
--------------------------------------------------------------------------------
/debian/control:
--------------------------------------------------------------------------------
1 | Source: bitwise
2 | Section: science
3 | Priority: optional
4 | Maintainer: Ramon Fried
5 | Build-Depends: debhelper (>= 12~), libncurses-dev, libreadline-dev, libcunit1-dev
6 | Standards-Version: 4.4.0
7 | Homepage: https://github.com/mellowcandle/bitwise
8 |
9 | Package: bitwise
10 | Architecture: any
11 | Depends: ${shlibs:Depends}, ${misc:Depends}
12 | Description: Interactive bitwise operation in ncurses
13 | Bitwise is multi base interactive calculator supporting dynamic base
14 | conversion and bit manipulation. It's a handy tool for low level hackers,
15 | kernel developers and device drivers developers.
16 | .
17 | Some of the features include:
18 | .
19 | Interactive ncurses interface
20 | Command line calculator.
21 | Individual bit manipulator.
22 | Bitwise operations such as NOT, OR, AND, XOR, and shifts.
23 |
--------------------------------------------------------------------------------
/debian/copyright:
--------------------------------------------------------------------------------
1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
2 | Upstream-Name: bitwise
3 | Upstream-Contact: Ramon Fried
4 | Source: https://github.com/mellowcandle/bitwise
5 |
6 | Files: inc/shunting-yard.h src/stack.c src/shunting-yard.c
7 | Copyright: 2011 - 2012, 2014 Brian Marshall
8 | 2019 Ramon Fried
9 | License: BSD-2-clause
10 |
11 | Files: m4/ax_require_defined.m4
12 | Copyright: 2014 Mike Frysinger vapier@gentoo.org
13 | License: GFDL
14 |
15 | Files: m4/ax_lib_readline.m4
16 | Copyright: 2008 Ville Laurikari
17 | License: GFDL
18 |
19 | Files: debian/*
20 | Copyright: 2019 Ramon Fried
21 | License: GPL-3.0+
22 |
23 | Files: *
24 | Copyright: 2019
25 | License: GPL-3.0+
26 |
27 | License: GPL-3.0+
28 | This program is free software: you can redistribute it and/or modify
29 | it under the terms of the GNU General Public License as published by
30 | the Free Software Foundation, either version 3 of the License, or
31 | (at your option) any later version.
32 | .
33 | This package is distributed in the hope that it will be useful,
34 | but WITHOUT ANY WARRANTY; without even the implied warranty of
35 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36 | GNU General Public License for more details.
37 | .
38 | You should have received a copy of the GNU General Public License
39 | along with this program. If not, see .
40 | .
41 | On Debian systems, the complete text of the GNU General
42 | Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
43 |
--------------------------------------------------------------------------------
/debian/rules:
--------------------------------------------------------------------------------
1 | #!/usr/bin/make -f
2 | # See debhelper(7) (uncomment to enable)
3 | # output every command that modifies files on the build system.
4 | #export DH_VERBOSE = 1
5 |
6 | # see FEATURE AREAS in dpkg-buildflags(1)
7 | export DEB_BUILD_MAINT_OPTIONS = hardening=+all
8 | # package maintainers to append CFLAGS
9 | export DEB_CFLAGS_MAINT_APPEND = -Wall -pedantic
10 | # package maintainers to append LDFLAGS
11 | export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed
12 |
13 |
14 | %:
15 | dh $@
16 |
--------------------------------------------------------------------------------
/debian/source/format:
--------------------------------------------------------------------------------
1 | 3.0 (quilt)
2 |
--------------------------------------------------------------------------------
/debian/watch:
--------------------------------------------------------------------------------
1 | version=4
2 |
3 | opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%bitwise-$1.tar.gz%" \
4 | https://github.com/mellowcandle/bitwise/releases \
5 | (?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian uupdate
6 |
--------------------------------------------------------------------------------
/inc/bitwise.h:
--------------------------------------------------------------------------------
1 | /* Copyright 2019
2 | * Ramon Fried
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include "config.h"
15 | /* Readine checks */
16 |
17 | #ifdef HAVE_LIBREADLINE
18 | # if defined(HAVE_READLINE_READLINE_H)
19 | # include
20 | # elif defined(HAVE_READLINE_H)
21 | # include
22 | # else /* !defined(HAVE_READLINE_H) */
23 | extern char *readline();
24 | # endif /* !defined(HAVE_READLINE_H) */
25 | #else /* !defined(HAVE_READLINE_READLINE_H) */
26 | /* no readline */
27 | #endif /* HAVE_LIBREADLINE */
28 |
29 | #ifdef HAVE_READLINE_HISTORY
30 | # if defined(HAVE_READLINE_HISTORY_H)
31 | # include
32 | # elif defined(HAVE_HISTORY_H)
33 | # include
34 | # else /* !defined(HAVE_HISTORY_H) */
35 | extern void add_history();
36 | extern int write_history();
37 | extern int read_history();
38 | # endif /* defined(HAVE_READLINE_HISTORY_H) */
39 | /* no history */
40 | #endif /* HAVE_READLINE_HISTORY */
41 |
42 | #define MAX_HISTORY_LEN 100
43 |
44 | #define FIELDS_WIN 0
45 | #define BINARY_WIN 1
46 | #define COMMAND_WIN 2
47 |
48 | #define BIT(nr) (1ULL << (nr))
49 | #define MASK(s) (~0ULL >> (64 - s))
50 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
51 |
52 | typedef enum output_type {
53 | CMD_OUTPUT_DECIMAL,
54 | CMD_OUTPUT_HEXADECIMAL,
55 | CMD_OUTPUT_OCTAL,
56 | CMD_OUTPUT_BINARY,
57 | CMD_OUTPUT_ALL,
58 | } output_type;
59 |
60 | /* Misc */
61 | int lltostr(uint64_t val, char *buf, int base);
62 | int set_width(char width);
63 | void set_width_by_val(uint64_t val);
64 | void die(const char *fmt, ...);
65 | int parse_input(const char *input, uint64_t *val);
66 | int validate_input(int ch, int base);
67 | int sprintf_type(uint64_t val, char *buf, output_type type);
68 |
69 | void init_terminal(void);
70 | void deinit_terminal(void);
71 |
72 | /* Interactive */
73 | extern FORM *form;
74 |
75 | int sprintf_size(uint64_t val, char *buf, bool si);
76 | int start_interactive(uint64_t start);
77 | void set_active_field(bool none);
78 | void set_fields_width(int width);
79 | void position_binary_curser(int previous_pos, int next_pos);
80 | void paint_screen(void);
81 | void unpaint_screen(void);
82 | void update_binary();
83 | int update_fields(int index);
84 |
85 | /* Command */
86 | void process_cmd(int ch);
87 | void init_readline(void);
88 | void deinit_readline(void);
89 | void readline_redisplay(void);
90 |
91 | /* calc */
92 | int calc(int argc, char *argv[]);
93 |
94 | /* Help */
95 | void show_help(void);
96 |
97 | #ifdef TRACE
98 | #define LOG(...) do { \
99 | fprintf(fd, __VA_ARGS__); \
100 | fflush(fd);\
101 | } while (0)
102 | extern FILE *fd;
103 | #else
104 | #define LOG(...) do { } while (0)
105 | #endif
106 |
107 | /* Colors */
108 | void init_colors(void);
109 |
110 | extern char *color_green;
111 | extern char *color_red;
112 | extern char *color_blue;
113 | extern char *color_magenta;
114 | extern char *color_cyan;
115 | extern char *color_white;
116 | extern char *color_reset;
117 |
118 | extern WINDOW *fields_win;
119 | extern WINDOW *binary_win;
120 | extern WINDOW *cmd_win;
121 | extern int active_win;
122 | extern int last_win;
123 |
124 | extern int bit_pos;
125 | extern int g_has_color;
126 | extern int g_width;
127 | extern int g_output;
128 | extern bool g_input_avail;
129 | extern int g_input;
130 | extern bool g_leave_req;
131 | extern uint64_t g_val;
132 |
133 | /* History */
134 | typedef enum history_type {
135 | TYPE_INPUT_COMMAND = 0,
136 | TYPE_INPUT_EXPRESSION,
137 | TYPE_OUTPUT_RESULT,
138 | TYPE_OUTPUT_ERROR,
139 | } history_type;
140 |
141 | struct history_entry {
142 | history_type type;
143 | char *line;
144 | };
145 |
146 | extern struct history_entry history[];
147 | extern unsigned int history_pos;
148 |
149 | void flush_history(void);
150 | void update_history_win(void);
151 |
152 | static inline void append_to_history(const char *str, history_type type) {
153 | char *new_line;
154 |
155 | new_line = strdup(str);
156 | if (!new_line) {
157 | LOG("No memory to allocate string\n");
158 | return;
159 | }
160 |
161 | history[history_pos % MAX_HISTORY_LEN].line = new_line;
162 | history[history_pos % MAX_HISTORY_LEN].type = type;
163 | history_pos++;
164 |
165 | update_history_win();
166 | }
167 |
168 | static inline WINDOW *get_win(int win)
169 | {
170 | if (win == FIELDS_WIN)
171 | return fields_win;
172 | else if (win == BINARY_WIN)
173 | return binary_win;
174 | else if (win == COMMAND_WIN)
175 | return cmd_win;
176 | else
177 | return NULL;
178 | }
179 |
180 | #endif /* end of include guard: BITWISE_H */
181 |
--------------------------------------------------------------------------------
/inc/shunting-yard.h:
--------------------------------------------------------------------------------
1 | // Copyright 2011 - 2012, 2014 Brian Marshall. All rights reserved.
2 | //
3 | // Use of this source code is governed by the BSD 2-Clause License that can be
4 | // found in the LICENSE file.
5 |
6 | #include
7 |
8 | #ifndef SHUNTING_YARD_H
9 | #define SHUNTING_YARD_H
10 |
11 | typedef enum {
12 | STATUS_OK,
13 | ERROR_SYNTAX,
14 | ERROR_OPEN_PARENTHESIS,
15 | ERROR_CLOSE_PARENTHESIS,
16 | ERROR_UNRECOGNIZED,
17 | ERROR_NO_INPUT,
18 | ERROR_UNDEFINED_FUNCTION,
19 | ERROR_FUNCTION_ARGUMENTS,
20 | ERROR_UNDEFINED_CONSTANT,
21 | ERROR_WRONG_ARGUMENTS,
22 | ERROR_DIVIDE_BY_ZERO,
23 | } Status;
24 |
25 | // Calculates the result of a mathematical expression.
26 | Status shunting_yard(const char *expression, uint64_t *result);
27 |
28 | #endif // SHUNTING_YARD_H
29 |
--------------------------------------------------------------------------------
/inc/stack.h:
--------------------------------------------------------------------------------
1 | // Copyright 2011 - 2014 Brian Marshall. All rights reserved.
2 | //
3 | // Use of this source code is governed by the BSD 2-Clause License that can be
4 | // found in the LICENSE file.
5 |
6 | #ifndef SHUNTING_YARD_STACK_H
7 | #define SHUNTING_YARD_STACK_H
8 |
9 | typedef struct Stack Stack;
10 |
11 | // Inserts an item at the top of the stack.
12 | void stack_push(Stack **stack, const void *value);
13 |
14 | // Removes an item from the top of the stack.
15 | const void *stack_pop(Stack **stack);
16 |
17 | // Returns the item at the top of the stack without removing it.
18 | const void *stack_top(const Stack *stack);
19 |
20 | #endif // SHUNTING_YARD_STACK_H
21 |
--------------------------------------------------------------------------------
/m4/ax_lib_readline.m4:
--------------------------------------------------------------------------------
1 | # ===========================================================================
2 | # https://www.gnu.org/software/autoconf-archive/ax_lib_readline.html
3 | # ===========================================================================
4 | #
5 | # SYNOPSIS
6 | #
7 | # AX_LIB_READLINE
8 | #
9 | # DESCRIPTION
10 | #
11 | # Searches for a readline compatible library. If found, defines
12 | # `HAVE_LIBREADLINE'. If the found library has the `add_history' function,
13 | # sets also `HAVE_READLINE_HISTORY'. Also checks for the locations of the
14 | # necessary include files and sets `HAVE_READLINE_H' or
15 | # `HAVE_READLINE_READLINE_H' and `HAVE_READLINE_HISTORY_H' or
16 | # 'HAVE_HISTORY_H' if the corresponding include files exists.
17 | #
18 | # The libraries that may be readline compatible are `libedit',
19 | # `libeditline' and `libreadline'. Sometimes we need to link a termcap
20 | # library for readline to work, this macro tests these cases too by trying
21 | # to link with `libtermcap', `libcurses' or `libncurses' before giving up.
22 | #
23 | # Here is an example of how to use the information provided by this macro
24 | # to perform the necessary includes or declarations in a C file:
25 | #
26 | # #ifdef HAVE_LIBREADLINE
27 | # # if defined(HAVE_READLINE_READLINE_H)
28 | # # include
29 | # # elif defined(HAVE_READLINE_H)
30 | # # include
31 | # # else /* !defined(HAVE_READLINE_H) */
32 | # extern char *readline ();
33 | # # endif /* !defined(HAVE_READLINE_H) */
34 | # char *cmdline = NULL;
35 | # #else /* !defined(HAVE_READLINE_READLINE_H) */
36 | # /* no readline */
37 | # #endif /* HAVE_LIBREADLINE */
38 | #
39 | # #ifdef HAVE_READLINE_HISTORY
40 | # # if defined(HAVE_READLINE_HISTORY_H)
41 | # # include
42 | # # elif defined(HAVE_HISTORY_H)
43 | # # include
44 | # # else /* !defined(HAVE_HISTORY_H) */
45 | # extern void add_history ();
46 | # extern int write_history ();
47 | # extern int read_history ();
48 | # # endif /* defined(HAVE_READLINE_HISTORY_H) */
49 | # /* no history */
50 | # #endif /* HAVE_READLINE_HISTORY */
51 | #
52 | # LICENSE
53 | #
54 | # Copyright (c) 2008 Ville Laurikari
55 | #
56 | # Copying and distribution of this file, with or without modification, are
57 | # permitted in any medium without royalty provided the copyright notice
58 | # and this notice are preserved. This file is offered as-is, without any
59 | # warranty.
60 |
61 | #serial 8
62 |
63 | AU_ALIAS([VL_LIB_READLINE], [AX_LIB_READLINE])
64 | AC_DEFUN([AX_LIB_READLINE], [
65 | AC_CACHE_CHECK([for a readline compatible library],
66 | ax_cv_lib_readline, [
67 | ORIG_LIBS="$LIBS"
68 | for readline_lib in readline edit editline; do
69 | for termcap_lib in "" termcap curses ncurses; do
70 | if test -z "$termcap_lib"; then
71 | TRY_LIB="-l$readline_lib"
72 | else
73 | TRY_LIB="-l$readline_lib -l$termcap_lib"
74 | fi
75 | LIBS="$ORIG_LIBS $TRY_LIB"
76 | AC_LINK_IFELSE([AC_LANG_CALL([], [readline])], [ax_cv_lib_readline="$TRY_LIB"])
77 | if test -n "$ax_cv_lib_readline"; then
78 | break
79 | fi
80 | done
81 | if test -n "$ax_cv_lib_readline"; then
82 | break
83 | fi
84 | done
85 | if test -z "$ax_cv_lib_readline"; then
86 | ax_cv_lib_readline="no"
87 | fi
88 | LIBS="$ORIG_LIBS"
89 | ])
90 |
91 | if test "$ax_cv_lib_readline" != "no"; then
92 | LIBS="$LIBS $ax_cv_lib_readline"
93 | AC_DEFINE(HAVE_LIBREADLINE, 1,
94 | [Define if you have a readline compatible library])
95 | AC_CHECK_HEADERS(readline.h readline/readline.h)
96 | AC_CACHE_CHECK([whether readline supports history],
97 | ax_cv_lib_readline_history, [
98 | ax_cv_lib_readline_history="no"
99 | AC_LINK_IFELSE([AC_LANG_CALL([], [add_history])], [ax_cv_lib_readline_history="yes"])
100 | ])
101 | if test "$ax_cv_lib_readline_history" = "yes"; then
102 | AC_DEFINE(HAVE_READLINE_HISTORY, 1,
103 | [Define if your readline library has \`add_history'])
104 | AC_CHECK_HEADERS(history.h readline/history.h)
105 | fi
106 | fi
107 | ])dnl
108 |
--------------------------------------------------------------------------------
/m4/ax_require_defined.m4:
--------------------------------------------------------------------------------
1 | # ===========================================================================
2 | # https://www.gnu.org/software/autoconf-archive/ax_require_defined.html
3 | # ===========================================================================
4 | #
5 | # SYNOPSIS
6 | #
7 | # AX_REQUIRE_DEFINED(MACRO)
8 | #
9 | # DESCRIPTION
10 | #
11 | # AX_REQUIRE_DEFINED is a simple helper for making sure other macros have
12 | # been defined and thus are available for use. This avoids random issues
13 | # where a macro isn't expanded. Instead the configure script emits a
14 | # non-fatal:
15 | #
16 | # ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found
17 | #
18 | # It's like AC_REQUIRE except it doesn't expand the required macro.
19 | #
20 | # Here's an example:
21 | #
22 | # AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
23 | #
24 | # LICENSE
25 | #
26 | # Copyright (c) 2014 Mike Frysinger
27 | #
28 | # Copying and distribution of this file, with or without modification, are
29 | # permitted in any medium without royalty provided the copyright notice
30 | # and this notice are preserved. This file is offered as-is, without any
31 | # warranty.
32 |
33 | #serial 2
34 |
35 | AC_DEFUN([AX_REQUIRE_DEFINED], [dnl
36 | m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])])
37 | ])dnl AX_REQUIRE_DEFINED
38 |
--------------------------------------------------------------------------------
/m4/ax_with_curses.m4:
--------------------------------------------------------------------------------
1 | # ===========================================================================
2 | # https://www.gnu.org/software/autoconf-archive/ax_with_curses.html
3 | # ===========================================================================
4 | #
5 | # SYNOPSIS
6 | #
7 | # AX_WITH_CURSES
8 | #
9 | # DESCRIPTION
10 | #
11 | # This macro checks whether a SysV or X/Open-compatible Curses library is
12 | # present, along with the associated header file. The NcursesW
13 | # (wide-character) library is searched for first, followed by Ncurses,
14 | # then the system-default plain Curses. The first library found is the
15 | # one returned. Finding libraries will first be attempted by using
16 | # pkg-config, and should the pkg-config files not be available, will
17 | # fallback to combinations of known flags itself.
18 | #
19 | # The following options are understood: --with-ncursesw, --with-ncurses,
20 | # --without-ncursesw, --without-ncurses. The "--with" options force the
21 | # macro to use that particular library, terminating with an error if not
22 | # found. The "--without" options simply skip the check for that library.
23 | # The effect on the search pattern is:
24 | #
25 | # (no options) - NcursesW, Ncurses, Curses
26 | # --with-ncurses --with-ncursesw - NcursesW only [*]
27 | # --without-ncurses --with-ncursesw - NcursesW only [*]
28 | # --with-ncursesw - NcursesW only [*]
29 | # --with-ncurses --without-ncursesw - Ncurses only [*]
30 | # --with-ncurses - NcursesW, Ncurses [**]
31 | # --without-ncurses --without-ncursesw - Curses only
32 | # --without-ncursesw - Ncurses, Curses
33 | # --without-ncurses - NcursesW, Curses
34 | #
35 | # [*] If the library is not found, abort the configure script.
36 | #
37 | # [**] If the second library (Ncurses) is not found, abort configure.
38 | #
39 | # The following preprocessor symbols may be defined by this macro if the
40 | # appropriate conditions are met:
41 | #
42 | # HAVE_CURSES - if any SysV or X/Open Curses library found
43 | # HAVE_CURSES_ENHANCED - if library supports X/Open Enhanced functions
44 | # HAVE_CURSES_COLOR - if library supports color (enhanced functions)
45 | # HAVE_CURSES_OBSOLETE - if library supports certain obsolete features
46 | # HAVE_NCURSESW - if NcursesW (wide char) library is to be used
47 | # HAVE_NCURSES - if the Ncurses library is to be used
48 | #
49 | # HAVE_CURSES_H - if is present and should be used
50 | # HAVE_NCURSESW_H - if should be used
51 | # HAVE_NCURSES_H - if should be used
52 | # HAVE_NCURSESW_CURSES_H - if should be used
53 | # HAVE_NCURSES_CURSES_H - if should be used
54 | #
55 | # (These preprocessor symbols are discussed later in this document.)
56 | #
57 | # The following output variables are defined by this macro; they are
58 | # precious and may be overridden on the ./configure command line:
59 | #
60 | # CURSES_LIBS - library to add to xxx_LDADD
61 | # CURSES_CFLAGS - include paths to add to xxx_CPPFLAGS
62 | #
63 | # In previous versions of this macro, the flags CURSES_LIB and
64 | # CURSES_CPPFLAGS were defined. These have been renamed, in keeping with
65 | # AX_WITH_CURSES's close bigger brother, PKG_CHECK_MODULES, which should
66 | # eventually supersede the use of AX_WITH_CURSES. Neither the library
67 | # listed in CURSES_LIBS, nor the flags in CURSES_CFLAGS are added to LIBS,
68 | # respectively CPPFLAGS, by default. You need to add both to the
69 | # appropriate xxx_LDADD/xxx_CPPFLAGS line in your Makefile.am. For
70 | # example:
71 | #
72 | # prog_LDADD = @CURSES_LIBS@
73 | # prog_CPPFLAGS = @CURSES_CFLAGS@
74 | #
75 | # If CURSES_LIBS is set on the configure command line (such as by running
76 | # "./configure CURSES_LIBS=-lmycurses"), then the only header searched for
77 | # is . If the user needs to specify an alternative path for a
78 | # library (such as for a non-standard NcurseW), the user should use the
79 | # LDFLAGS variable.
80 | #
81 | # The following shell variables may be defined by this macro:
82 | #
83 | # ax_cv_curses - set to "yes" if any Curses library found
84 | # ax_cv_curses_enhanced - set to "yes" if Enhanced functions present
85 | # ax_cv_curses_color - set to "yes" if color functions present
86 | # ax_cv_curses_obsolete - set to "yes" if obsolete features present
87 | #
88 | # ax_cv_ncursesw - set to "yes" if NcursesW library found
89 | # ax_cv_ncurses - set to "yes" if Ncurses library found
90 | # ax_cv_plaincurses - set to "yes" if plain Curses library found
91 | # ax_cv_curses_which - set to "ncursesw", "ncurses", "plaincurses" or "no"
92 | #
93 | # These variables can be used in your configure.ac to determine the level
94 | # of support you need from the Curses library. For example, if you must
95 | # have either Ncurses or NcursesW, you could include:
96 | #
97 | # AX_WITH_CURSES
98 | # if test "x$ax_cv_ncursesw" != xyes && test "x$ax_cv_ncurses" != xyes; then
99 | # AC_MSG_ERROR([requires either NcursesW or Ncurses library])
100 | # fi
101 | #
102 | # If any Curses library will do (but one must be present and must support
103 | # color), you could use:
104 | #
105 | # AX_WITH_CURSES
106 | # if test "x$ax_cv_curses" != xyes || test "x$ax_cv_curses_color" != xyes; then
107 | # AC_MSG_ERROR([requires an X/Open-compatible Curses library with color])
108 | # fi
109 | #
110 | # Certain preprocessor symbols and shell variables defined by this macro
111 | # can be used to determine various features of the Curses library. In
112 | # particular, HAVE_CURSES and ax_cv_curses are defined if the Curses
113 | # library found conforms to the traditional SysV and/or X/Open Base Curses
114 | # definition. Any working Curses library conforms to this level.
115 | #
116 | # HAVE_CURSES_ENHANCED and ax_cv_curses_enhanced are defined if the
117 | # library supports the X/Open Enhanced Curses definition. In particular,
118 | # the wide-character types attr_t, cchar_t and wint_t, the functions
119 | # wattr_set() and wget_wch() and the macros WA_NORMAL and _XOPEN_CURSES
120 | # are checked. The Ncurses library does NOT conform to this definition,
121 | # although NcursesW does.
122 | #
123 | # HAVE_CURSES_COLOR and ax_cv_curses_color are defined if the library
124 | # supports color functions and macros such as COLOR_PAIR, A_COLOR,
125 | # COLOR_WHITE, COLOR_RED and init_pair(). These are NOT part of the
126 | # X/Open Base Curses definition, but are part of the Enhanced set of
127 | # functions. The Ncurses library DOES support these functions, as does
128 | # NcursesW.
129 | #
130 | # HAVE_CURSES_OBSOLETE and ax_cv_curses_obsolete are defined if the
131 | # library supports certain features present in SysV and BSD Curses but not
132 | # defined in the X/Open definition. In particular, the functions
133 | # getattrs(), getcurx() and getmaxx() are checked.
134 | #
135 | # To use the HAVE_xxx_H preprocessor symbols, insert the following into
136 | # your system.h (or equivalent) header file:
137 | #
138 | # #if defined HAVE_NCURSESW_CURSES_H
139 | # # include
140 | # #elif defined HAVE_NCURSESW_H
141 | # # include
142 | # #elif defined HAVE_NCURSES_CURSES_H
143 | # # include
144 | # #elif defined HAVE_NCURSES_H
145 | # # include
146 | # #elif defined HAVE_CURSES_H
147 | # # include
148 | # #else
149 | # # error "SysV or X/Open-compatible Curses header file required"
150 | # #endif
151 | #
152 | # For previous users of this macro: you should not need to change anything
153 | # in your configure.ac or Makefile.am, as the previous (serial 10)
154 | # semantics are still valid. However, you should update your system.h (or
155 | # equivalent) header file to the fragment shown above. You are encouraged
156 | # also to make use of the extended functionality provided by this version
157 | # of AX_WITH_CURSES, as well as in the additional macros
158 | # AX_WITH_CURSES_PANEL, AX_WITH_CURSES_MENU and AX_WITH_CURSES_FORM.
159 | #
160 | # LICENSE
161 | #
162 | # Copyright (c) 2009 Mark Pulford
163 | # Copyright (c) 2009 Damian Pietras
164 | # Copyright (c) 2012 Reuben Thomas
165 | # Copyright (c) 2011 John Zaitseff
166 | #
167 | # This program is free software: you can redistribute it and/or modify it
168 | # under the terms of the GNU General Public License as published by the
169 | # Free Software Foundation, either version 3 of the License, or (at your
170 | # option) any later version.
171 | #
172 | # This program is distributed in the hope that it will be useful, but
173 | # WITHOUT ANY WARRANTY; without even the implied warranty of
174 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
175 | # Public License for more details.
176 | #
177 | # You should have received a copy of the GNU General Public License along
178 | # with this program. If not, see .
179 | #
180 | # As a special exception, the respective Autoconf Macro's copyright owner
181 | # gives unlimited permission to copy, distribute and modify the configure
182 | # scripts that are the output of Autoconf when processing the Macro. You
183 | # need not follow the terms of the GNU General Public License when using
184 | # or distributing such scripts, even though portions of the text of the
185 | # Macro appear in them. The GNU General Public License (GPL) does govern
186 | # all other use of the material that constitutes the Autoconf Macro.
187 | #
188 | # This special exception to the GPL applies to versions of the Autoconf
189 | # Macro released by the Autoconf Archive. When you make and distribute a
190 | # modified version of the Autoconf Macro, you may extend this special
191 | # exception to the GPL to apply to your modified version as well.
192 |
193 | #serial 18
194 |
195 | # internal function to factorize common code that is used by both ncurses
196 | # and ncursesw
197 | AC_DEFUN([_FIND_CURSES_FLAGS], [
198 | AC_MSG_CHECKING([for $1 via pkg-config])
199 |
200 | AX_REQUIRE_DEFINED([PKG_CHECK_EXISTS])
201 | _PKG_CONFIG([_ax_cv_$1_libs], [libs], [$1])
202 | _PKG_CONFIG([_ax_cv_$1_cppflags], [cflags], [$1])
203 |
204 | AS_IF([test "x$pkg_failed" = "xyes" || test "x$pkg_failed" = "xuntried"],[
205 | AC_MSG_RESULT([no])
206 | # No suitable .pc file found, have to find flags via fallback
207 | AC_CACHE_CHECK([for $1 via fallback], [ax_cv_$1], [
208 | AS_ECHO()
209 | pkg_cv__ax_cv_$1_libs="-l$1"
210 | pkg_cv__ax_cv_$1_cppflags="-D_GNU_SOURCE $CURSES_CFLAGS"
211 | LIBS="$ax_saved_LIBS $pkg_cv__ax_cv_$1_libs"
212 | CPPFLAGS="$ax_saved_CPPFLAGS $pkg_cv__ax_cv_$1_cppflags"
213 |
214 | AC_MSG_CHECKING([for initscr() with $pkg_cv__ax_cv_$1_libs])
215 | AC_LINK_IFELSE([AC_LANG_CALL([], [initscr])],
216 | [
217 | AC_MSG_RESULT([yes])
218 | AC_MSG_CHECKING([for nodelay() with $pkg_cv__ax_cv_$1_libs])
219 | AC_LINK_IFELSE([AC_LANG_CALL([], [nodelay])],[
220 | ax_cv_$1=yes
221 | ],[
222 | AC_MSG_RESULT([no])
223 | m4_if(
224 | [$1],[ncursesw],[pkg_cv__ax_cv_$1_libs="$pkg_cv__ax_cv_$1_libs -ltinfow"],
225 | [$1],[ncurses],[pkg_cv__ax_cv_$1_libs="$pkg_cv__ax_cv_$1_libs -ltinfo"]
226 | )
227 | LIBS="$ax_saved_LIBS $pkg_cv__ax_cv_$1_libs"
228 |
229 | AC_MSG_CHECKING([for nodelay() with $pkg_cv__ax_cv_$1_libs])
230 | AC_LINK_IFELSE([AC_LANG_CALL([], [nodelay])],[
231 | ax_cv_$1=yes
232 | ],[
233 | ax_cv_$1=no
234 | ])
235 | ])
236 | ],[
237 | ax_cv_$1=no
238 | ])
239 | ])
240 | ],[
241 | AC_MSG_RESULT([yes])
242 | # Found .pc file, using its information
243 | LIBS="$ax_saved_LIBS $pkg_cv__ax_cv_$1_libs"
244 | CPPFLAGS="$ax_saved_CPPFLAGS $pkg_cv__ax_cv_$1_cppflags"
245 | ax_cv_$1=yes
246 | ])
247 | ])
248 |
249 | AU_ALIAS([MP_WITH_CURSES], [AX_WITH_CURSES])
250 | AC_DEFUN([AX_WITH_CURSES], [
251 | AC_ARG_VAR([CURSES_LIBS], [linker library for Curses, e.g. -lcurses])
252 | AC_ARG_VAR([CURSES_CFLAGS], [preprocessor flags for Curses, e.g. -I/usr/include/ncursesw])
253 | AC_ARG_WITH([ncurses], [AS_HELP_STRING([--with-ncurses],
254 | [force the use of Ncurses or NcursesW])],
255 | [], [with_ncurses=check])
256 | AC_ARG_WITH([ncursesw], [AS_HELP_STRING([--without-ncursesw],
257 | [do not use NcursesW (wide character support)])],
258 | [], [with_ncursesw=check])
259 |
260 | ax_saved_LIBS=$LIBS
261 | ax_saved_CPPFLAGS=$CPPFLAGS
262 |
263 | AS_IF([test "x$with_ncurses" = xyes || test "x$with_ncursesw" = xyes],
264 | [ax_with_plaincurses=no], [ax_with_plaincurses=check])
265 |
266 | ax_cv_curses_which=no
267 |
268 | # Test for NcursesW
269 | AS_IF([test "x$CURSES_LIBS" = x && test "x$with_ncursesw" != xno], [
270 | _FIND_CURSES_FLAGS([ncursesw])
271 |
272 | AS_IF([test "x$ax_cv_ncursesw" = xno && test "x$with_ncursesw" = xyes], [
273 | AC_MSG_ERROR([--with-ncursesw specified but could not find NcursesW library])
274 | ])
275 |
276 | AS_IF([test "x$ax_cv_ncursesw" = xyes], [
277 | ax_cv_curses=yes
278 | ax_cv_curses_which=ncursesw
279 | CURSES_LIBS="$pkg_cv__ax_cv_ncursesw_libs"
280 | CURSES_CFLAGS="$pkg_cv__ax_cv_ncursesw_cppflags"
281 | AC_DEFINE([HAVE_NCURSESW], [1], [Define to 1 if the NcursesW library is present])
282 | AC_DEFINE([HAVE_CURSES], [1], [Define to 1 if a SysV or X/Open compatible Curses library is present])
283 |
284 | AC_CACHE_CHECK([for working ncursesw/curses.h], [ax_cv_header_ncursesw_curses_h], [
285 | AC_LINK_IFELSE([AC_LANG_PROGRAM([[
286 | @%:@define _XOPEN_SOURCE_EXTENDED 1
287 | @%:@include
288 | ]], [[
289 | chtype a = A_BOLD;
290 | int b = KEY_LEFT;
291 | chtype c = COLOR_PAIR(1) & A_COLOR;
292 | attr_t d = WA_NORMAL;
293 | cchar_t e;
294 | wint_t f;
295 | int g = getattrs(stdscr);
296 | int h = getcurx(stdscr) + getmaxx(stdscr);
297 | initscr();
298 | init_pair(1, COLOR_WHITE, COLOR_RED);
299 | wattr_set(stdscr, d, 0, NULL);
300 | wget_wch(stdscr, &f);
301 | ]])],
302 | [ax_cv_header_ncursesw_curses_h=yes],
303 | [ax_cv_header_ncursesw_curses_h=no])
304 | ])
305 | AS_IF([test "x$ax_cv_header_ncursesw_curses_h" = xyes], [
306 | ax_cv_curses_enhanced=yes
307 | ax_cv_curses_color=yes
308 | ax_cv_curses_obsolete=yes
309 | AC_DEFINE([HAVE_CURSES_ENHANCED], [1], [Define to 1 if library supports X/Open Enhanced functions])
310 | AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)])
311 | AC_DEFINE([HAVE_CURSES_OBSOLETE], [1], [Define to 1 if library supports certain obsolete features])
312 | AC_DEFINE([HAVE_NCURSESW_CURSES_H], [1], [Define to 1 if is present])
313 | ])
314 |
315 | AC_CACHE_CHECK([for working ncursesw.h], [ax_cv_header_ncursesw_h], [
316 | AC_LINK_IFELSE([AC_LANG_PROGRAM([[
317 | @%:@define _XOPEN_SOURCE_EXTENDED 1
318 | @%:@include
319 | ]], [[
320 | chtype a = A_BOLD;
321 | int b = KEY_LEFT;
322 | chtype c = COLOR_PAIR(1) & A_COLOR;
323 | attr_t d = WA_NORMAL;
324 | cchar_t e;
325 | wint_t f;
326 | int g = getattrs(stdscr);
327 | int h = getcurx(stdscr) + getmaxx(stdscr);
328 | initscr();
329 | init_pair(1, COLOR_WHITE, COLOR_RED);
330 | wattr_set(stdscr, d, 0, NULL);
331 | wget_wch(stdscr, &f);
332 | ]])],
333 | [ax_cv_header_ncursesw_h=yes],
334 | [ax_cv_header_ncursesw_h=no])
335 | ])
336 | AS_IF([test "x$ax_cv_header_ncursesw_h" = xyes], [
337 | ax_cv_curses_enhanced=yes
338 | ax_cv_curses_color=yes
339 | ax_cv_curses_obsolete=yes
340 | AC_DEFINE([HAVE_CURSES_ENHANCED], [1], [Define to 1 if library supports X/Open Enhanced functions])
341 | AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)])
342 | AC_DEFINE([HAVE_CURSES_OBSOLETE], [1], [Define to 1 if library supports certain obsolete features])
343 | AC_DEFINE([HAVE_NCURSESW_H], [1], [Define to 1 if is present])
344 | ])
345 |
346 | AC_CACHE_CHECK([for working ncurses.h], [ax_cv_header_ncurses_h_with_ncursesw], [
347 | AC_LINK_IFELSE([AC_LANG_PROGRAM([[
348 | @%:@define _XOPEN_SOURCE_EXTENDED 1
349 | @%:@include
350 | ]], [[
351 | chtype a = A_BOLD;
352 | int b = KEY_LEFT;
353 | chtype c = COLOR_PAIR(1) & A_COLOR;
354 | attr_t d = WA_NORMAL;
355 | cchar_t e;
356 | wint_t f;
357 | int g = getattrs(stdscr);
358 | int h = getcurx(stdscr) + getmaxx(stdscr);
359 | initscr();
360 | init_pair(1, COLOR_WHITE, COLOR_RED);
361 | wattr_set(stdscr, d, 0, NULL);
362 | wget_wch(stdscr, &f);
363 | ]])],
364 | [ax_cv_header_ncurses_h_with_ncursesw=yes],
365 | [ax_cv_header_ncurses_h_with_ncursesw=no])
366 | ])
367 | AS_IF([test "x$ax_cv_header_ncurses_h_with_ncursesw" = xyes], [
368 | ax_cv_curses_enhanced=yes
369 | ax_cv_curses_color=yes
370 | ax_cv_curses_obsolete=yes
371 | AC_DEFINE([HAVE_CURSES_ENHANCED], [1], [Define to 1 if library supports X/Open Enhanced functions])
372 | AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)])
373 | AC_DEFINE([HAVE_CURSES_OBSOLETE], [1], [Define to 1 if library supports certain obsolete features])
374 | AC_DEFINE([HAVE_NCURSES_H], [1], [Define to 1 if is present])
375 | ])
376 |
377 | AS_IF([test "x$ax_cv_header_ncursesw_curses_h" = xno && test "x$ax_cv_header_ncursesw_h" = xno && test "x$ax_cv_header_ncurses_h_with_ncursesw" = xno], [
378 | AC_MSG_WARN([could not find a working ncursesw/curses.h, ncursesw.h or ncurses.h])
379 | ])
380 | ])
381 | ])
382 | unset pkg_cv__ax_cv_ncursesw_libs
383 | unset pkg_cv__ax_cv_ncursesw_cppflags
384 |
385 | # Test for Ncurses
386 | AS_IF([test "x$CURSES_LIBS" = x && test "x$with_ncurses" != xno && test "x$ax_cv_curses_which" = xno], [
387 | _FIND_CURSES_FLAGS([ncurses])
388 |
389 | AS_IF([test "x$ax_cv_ncurses" = xno && test "x$with_ncurses" = xyes], [
390 | AC_MSG_ERROR([--with-ncurses specified but could not find Ncurses library])
391 | ])
392 |
393 | AS_IF([test "x$ax_cv_ncurses" = xyes], [
394 | ax_cv_curses=yes
395 | ax_cv_curses_which=ncurses
396 | CURSES_LIBS="$pkg_cv__ax_cv_ncurses_libs"
397 | CURSES_CFLAGS="$pkg_cv__ax_cv_ncurses_cppflags"
398 | AC_DEFINE([HAVE_NCURSES], [1], [Define to 1 if the Ncurses library is present])
399 | AC_DEFINE([HAVE_CURSES], [1], [Define to 1 if a SysV or X/Open compatible Curses library is present])
400 |
401 | AC_CACHE_CHECK([for working ncurses/curses.h], [ax_cv_header_ncurses_curses_h], [
402 | AC_LINK_IFELSE([AC_LANG_PROGRAM([[
403 | @%:@include
404 | ]], [[
405 | chtype a = A_BOLD;
406 | int b = KEY_LEFT;
407 | chtype c = COLOR_PAIR(1) & A_COLOR;
408 | int g = getattrs(stdscr);
409 | int h = getcurx(stdscr) + getmaxx(stdscr);
410 | initscr();
411 | init_pair(1, COLOR_WHITE, COLOR_RED);
412 | ]])],
413 | [ax_cv_header_ncurses_curses_h=yes],
414 | [ax_cv_header_ncurses_curses_h=no])
415 | ])
416 | AS_IF([test "x$ax_cv_header_ncurses_curses_h" = xyes], [
417 | ax_cv_curses_color=yes
418 | ax_cv_curses_obsolete=yes
419 | AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)])
420 | AC_DEFINE([HAVE_CURSES_OBSOLETE], [1], [Define to 1 if library supports certain obsolete features])
421 | AC_DEFINE([HAVE_NCURSES_CURSES_H], [1], [Define to 1 if is present])
422 | ])
423 |
424 | AC_CACHE_CHECK([for working ncurses.h], [ax_cv_header_ncurses_h], [
425 | AC_LINK_IFELSE([AC_LANG_PROGRAM([[
426 | @%:@include
427 | ]], [[
428 | chtype a = A_BOLD;
429 | int b = KEY_LEFT;
430 | chtype c = COLOR_PAIR(1) & A_COLOR;
431 | int g = getattrs(stdscr);
432 | int h = getcurx(stdscr) + getmaxx(stdscr);
433 | initscr();
434 | init_pair(1, COLOR_WHITE, COLOR_RED);
435 | ]])],
436 | [ax_cv_header_ncurses_h=yes],
437 | [ax_cv_header_ncurses_h=no])
438 | ])
439 | AS_IF([test "x$ax_cv_header_ncurses_h" = xyes], [
440 | ax_cv_curses_color=yes
441 | ax_cv_curses_obsolete=yes
442 | AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)])
443 | AC_DEFINE([HAVE_CURSES_OBSOLETE], [1], [Define to 1 if library supports certain obsolete features])
444 | AC_DEFINE([HAVE_NCURSES_H], [1], [Define to 1 if is present])
445 | ])
446 |
447 | AS_IF([test "x$ax_cv_header_ncurses_curses_h" = xno && test "x$ax_cv_header_ncurses_h" = xno], [
448 | AC_MSG_WARN([could not find a working ncurses/curses.h or ncurses.h])
449 | ])
450 | ])
451 | ])
452 | unset pkg_cv__ax_cv_ncurses_libs
453 | unset pkg_cv__ax_cv_ncurses_cppflags
454 |
455 | # Test for plain Curses (or if CURSES_LIBS was set by user)
456 | AS_IF([test "x$with_plaincurses" != xno && test "x$ax_cv_curses_which" = xno], [
457 | AS_IF([test "x$CURSES_LIBS" != x], [
458 | LIBS="$ax_saved_LIBS $CURSES_LIBS"
459 | ], [
460 | LIBS="$ax_saved_LIBS -lcurses"
461 | ])
462 |
463 | AC_CACHE_CHECK([for Curses library], [ax_cv_plaincurses], [
464 | AC_LINK_IFELSE([AC_LANG_CALL([], [initscr])],
465 | [ax_cv_plaincurses=yes], [ax_cv_plaincurses=no])
466 | ])
467 |
468 | AS_IF([test "x$ax_cv_plaincurses" = xyes], [
469 | ax_cv_curses=yes
470 | ax_cv_curses_which=plaincurses
471 | AS_IF([test "x$CURSES_LIBS" = x], [
472 | CURSES_LIBS="-lcurses"
473 | ])
474 | AC_DEFINE([HAVE_CURSES], [1], [Define to 1 if a SysV or X/Open compatible Curses library is present])
475 |
476 | # Check for base conformance (and header file)
477 |
478 | AC_CACHE_CHECK([for working curses.h], [ax_cv_header_curses_h], [
479 | AC_LINK_IFELSE([AC_LANG_PROGRAM([[
480 | @%:@include
481 | ]], [[
482 | chtype a = A_BOLD;
483 | int b = KEY_LEFT;
484 | initscr();
485 | ]])],
486 | [ax_cv_header_curses_h=yes],
487 | [ax_cv_header_curses_h=no])
488 | ])
489 | AS_IF([test "x$ax_cv_header_curses_h" = xyes], [
490 | AC_DEFINE([HAVE_CURSES_H], [1], [Define to 1 if is present])
491 |
492 | # Check for X/Open Enhanced conformance
493 |
494 | AC_CACHE_CHECK([for X/Open Enhanced Curses conformance], [ax_cv_plaincurses_enhanced], [
495 | AC_LINK_IFELSE([AC_LANG_PROGRAM([[
496 | @%:@define _XOPEN_SOURCE_EXTENDED 1
497 | @%:@include
498 | @%:@ifndef _XOPEN_CURSES
499 | @%:@error "this Curses library is not enhanced"
500 | "this Curses library is not enhanced"
501 | @%:@endif
502 | ]], [[
503 | chtype a = A_BOLD;
504 | int b = KEY_LEFT;
505 | chtype c = COLOR_PAIR(1) & A_COLOR;
506 | attr_t d = WA_NORMAL;
507 | cchar_t e;
508 | wint_t f;
509 | initscr();
510 | init_pair(1, COLOR_WHITE, COLOR_RED);
511 | wattr_set(stdscr, d, 0, NULL);
512 | wget_wch(stdscr, &f);
513 | ]])],
514 | [ax_cv_plaincurses_enhanced=yes],
515 | [ax_cv_plaincurses_enhanced=no])
516 | ])
517 | AS_IF([test "x$ax_cv_plaincurses_enhanced" = xyes], [
518 | ax_cv_curses_enhanced=yes
519 | ax_cv_curses_color=yes
520 | AC_DEFINE([HAVE_CURSES_ENHANCED], [1], [Define to 1 if library supports X/Open Enhanced functions])
521 | AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)])
522 | ])
523 |
524 | # Check for color functions
525 |
526 | AC_CACHE_CHECK([for Curses color functions], [ax_cv_plaincurses_color], [
527 | AC_LINK_IFELSE([AC_LANG_PROGRAM([[
528 | @%:@define _XOPEN_SOURCE_EXTENDED 1
529 | @%:@include
530 | ]], [[
531 | chtype a = A_BOLD;
532 | int b = KEY_LEFT;
533 | chtype c = COLOR_PAIR(1) & A_COLOR;
534 | initscr();
535 | init_pair(1, COLOR_WHITE, COLOR_RED);
536 | ]])],
537 | [ax_cv_plaincurses_color=yes],
538 | [ax_cv_plaincurses_color=no])
539 | ])
540 | AS_IF([test "x$ax_cv_plaincurses_color" = xyes], [
541 | ax_cv_curses_color=yes
542 | AC_DEFINE([HAVE_CURSES_COLOR], [1], [Define to 1 if library supports color (enhanced functions)])
543 | ])
544 |
545 | # Check for obsolete functions
546 |
547 | AC_CACHE_CHECK([for obsolete Curses functions], [ax_cv_plaincurses_obsolete], [
548 | AC_LINK_IFELSE([AC_LANG_PROGRAM([[
549 | @%:@include
550 | ]], [[
551 | chtype a = A_BOLD;
552 | int b = KEY_LEFT;
553 | int g = getattrs(stdscr);
554 | int h = getcurx(stdscr) + getmaxx(stdscr);
555 | initscr();
556 | ]])],
557 | [ax_cv_plaincurses_obsolete=yes],
558 | [ax_cv_plaincurses_obsolete=no])
559 | ])
560 | AS_IF([test "x$ax_cv_plaincurses_obsolete" = xyes], [
561 | ax_cv_curses_obsolete=yes
562 | AC_DEFINE([HAVE_CURSES_OBSOLETE], [1], [Define to 1 if library supports certain obsolete features])
563 | ])
564 | ])
565 |
566 | AS_IF([test "x$ax_cv_header_curses_h" = xno], [
567 | AC_MSG_WARN([could not find a working curses.h])
568 | ])
569 | ])
570 | ])
571 |
572 | AS_IF([test "x$ax_cv_curses" != xyes], [ax_cv_curses=no])
573 | AS_IF([test "x$ax_cv_curses_enhanced" != xyes], [ax_cv_curses_enhanced=no])
574 | AS_IF([test "x$ax_cv_curses_color" != xyes], [ax_cv_curses_color=no])
575 | AS_IF([test "x$ax_cv_curses_obsolete" != xyes], [ax_cv_curses_obsolete=no])
576 |
577 | LIBS=$ax_saved_LIBS
578 | CPPFLAGS=$ax_saved_CPPFLAGS
579 |
580 | unset ax_saved_LIBS
581 | unset ax_saved_CPPFLAGS
582 | ])dnl
583 |
--------------------------------------------------------------------------------
/m4/ax_with_curses_extra.m4:
--------------------------------------------------------------------------------
1 | # ===========================================================================
2 | # https://www.gnu.org/software/autoconf-archive/ax_with_curses_extra.html
3 | # ===========================================================================
4 | #
5 | # SYNOPSIS
6 | #
7 | # AX_WITH_CURSES_PANEL
8 | # AX_WITH_CURSES_MENU
9 | # AX_WITH_CURSES_FORM
10 | #
11 | # DESCRIPTION
12 | #
13 | # These macros try to find additional libraries that often come with
14 | # SysV-compatible Curses. In particular, the Panel, Menu and Form
15 | # libraries are searched, along with their header files. These macros
16 | # depend on AX_WITH_CURSES.
17 | #
18 | # The following preprocessor symbols may be defined by these macros:
19 | #
20 | # By AX_WITH_CURSES_PANEL:
21 | #
22 | # HAVE_PANEL - if the Panel library is present
23 | # HAVE_PANEL_H - if is present and should be used
24 | # HAVE_NCURSES_PANEL_H - if should be used
25 | # HAVE_NCURSESW_PANEL_H - if should be used
26 | #
27 | # By AX_WITH_CURSES_MENU:
28 | #
29 | # HAVE_MENU - if the Menu library is present
30 | # HAVE_MENU_H - if is present and should be used
31 | # HAVE_NCURSES_MENU_H - if should be used
32 | # HAVE_NCURSESW_MENU_H - if should be used
33 | #
34 | # By AX_WITH_CURSES_FORM:
35 | #
36 | # HAVE_FORM - if the Form library is present
37 | # HAVE_FORM_H - if is present and should be used
38 | # HAVE_NCURSES_FORM_H - if should be used
39 | # HAVE_NCURSESW_FORM_H - if should be used
40 | #
41 | # The following output variables may be defined by these macros; these are
42 | # precious and may be overridden on the ./configure command line:
43 | #
44 | # PANEL_LIBS - library to add to xxx_LDADD before CURSES_LIBS
45 | # MENU_LIBS - library to add to xxx_LDADD before CURSES_LIBS
46 | # FORM_LIBS - library to add to xxx_LDADD before CURSES_LIBS
47 | #
48 | # In previous versions of this macro, the flags PANEL_LIB, MENU_LIB and
49 | # FORM_LIB were defined. These have been renamed, in keeping with the
50 | # variable scheme of PKG_CHECK_MODULES, which should eventually supersede
51 | # the use of AX_WITH_CURSES and AX_WITH_CURSES_* macros. These libraries
52 | # are NOT added to LIBS by default. You need to add them to the
53 | # appropriate xxx_LDADD line in your Makefile.am in front of the
54 | # equivalent CURSES_LIBS incantation. For example:
55 | #
56 | # prog_LDADD = @PANEL_LIBS@ @CURSES_LIBS@
57 | #
58 | # If one of the xxx_LIBS variables is set on the configure command line
59 | # (such as by running "./configure PANEL_LIBS=-lmypanel"), then the header
60 | # file searched must NOT contain a subpath. In this case, in other words,
61 | # only would be searched for. The user may use the CPPFLAGS
62 | # precious variable to override the standard #include search path.
63 | #
64 | # The following shell variables may be defined by these macros:
65 | #
66 | # ax_cv_panel - set to "yes" if Panels library is present
67 | # ax_cv_menu - set to "yes" if Menu library is present
68 | # ax_cv_form - set to "yes" if Form library is present
69 | #
70 | # These variables can be used in your configure.ac to determine whether a
71 | # library you require is actually present. For example:
72 | #
73 | # AX_WITH_CURSES
74 | # if test "x$ax_cv_curses" != xyes; then
75 | # AC_MSG_ERROR([requires a SysV or X/Open-compatible Curses library])
76 | # fi
77 | # AX_WITH_CURSES_PANEL
78 | # if test "x$ax_cv_panel" != xyes; then
79 | # AC_MSG_ERROR([requires the Curses Panel library])
80 | # fi
81 | #
82 | # To use the HAVE_xxx_H preprocessor symbols, insert the following into
83 | # your system.h (or equivalent) header file:
84 | #
85 | # For AX_WITH_CURSES_PANEL:
86 | #
87 | # #if defined HAVE_NCURSESW_PANEL_H
88 | # # include
89 | # #elif defined HAVE_NCURSES_PANEL_H
90 | # # include
91 | # #elif defined HAVE_PANEL_H
92 | # # include
93 | # #else
94 | # # error "SysV-compatible Curses Panel header file required"
95 | # #endif
96 | #
97 | # For AX_WITH_CURSES_MENU:
98 | #
99 | # #if defined HAVE_NCURSESW_MENU_H
100 | # # include
101 | # #elif defined HAVE_NCURSES_MENU_H
102 | # # include
103 | # #elif defined HAVE_MENU_H
104 | # # include
105 | # #else
106 | # # error "SysV-compatible Curses Menu header file required"
107 | # #endif
108 | #
109 | # For AX_WITH_CURSES_FORM:
110 | #
111 | # #if defined HAVE_NCURSESW_FORM_H
112 | # # include
113 | # #elif defined HAVE_NCURSES_FORM_H
114 | # # include
115 | # #elif defined HAVE_FORM_H
116 | # # include
117 | # #else
118 | # # error "SysV-compatible Curses Form header file required"
119 | # #endif
120 | #
121 | # LICENSE
122 | #
123 | # Copyright (c) 2011 John Zaitseff
124 | #
125 | # This program is free software: you can redistribute it and/or modify it
126 | # under the terms of the GNU General Public License as published by the
127 | # Free Software Foundation, either version 3 of the License, or (at your
128 | # option) any later version.
129 | #
130 | # This program is distributed in the hope that it will be useful, but
131 | # WITHOUT ANY WARRANTY; without even the implied warranty of
132 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
133 | # Public License for more details.
134 | #
135 | # You should have received a copy of the GNU General Public License along
136 | # with this program. If not, see .
137 | #
138 | # As a special exception, the respective Autoconf Macro's copyright owner
139 | # gives unlimited permission to copy, distribute and modify the configure
140 | # scripts that are the output of Autoconf when processing the Macro. You
141 | # need not follow the terms of the GNU General Public License when using
142 | # or distributing such scripts, even though portions of the text of the
143 | # Macro appear in them. The GNU General Public License (GPL) does govern
144 | # all other use of the material that constitutes the Autoconf Macro.
145 | #
146 | # This special exception to the GPL applies to versions of the Autoconf
147 | # Macro released by the Autoconf Archive. When you make and distribute a
148 | # modified version of the Autoconf Macro, you may extend this special
149 | # exception to the GPL to apply to your modified version as well.
150 |
151 | #serial 5
152 |
153 | AC_DEFUN([_AX_WITH_CURSES_CHECKEXTRA], [
154 | dnl Parameter 1 is the variable name component, using uppercase letters only
155 | dnl Parameter 2 is the printable library name
156 | dnl Parameter 3 is the C code to try compiling and linking
157 | dnl Parameter 4 is the header filename
158 | dnl Parameter 5 is the library command line
159 |
160 | AS_VAR_PUSHDEF([_AX_WITH_CURSES_CHECKEXTRA_have_var], [HAVE_$1])dnl
161 | AS_VAR_PUSHDEF([_AX_WITH_CURSES_CHECKEXTRA_cv_var], [ax_cv_[]m4_tolower($1)])dnl
162 | AS_VAR_PUSHDEF([_AX_WITH_CURSES_CHECKEXTRA_header_var], [ax_cv_header_$4])dnl
163 | AS_VAR_PUSHDEF([_AX_WITH_CURSES_CHECKEXTRA_have_header_var], [HAVE_[]m4_toupper($4)])dnl
164 |
165 | ax_saved_LIBS=$LIBS
166 | ax_saved_CPPFLAGS=$CPPFLAGS
167 |
168 | AC_CACHE_CHECK([for Curses $2 library with $4], [_AX_WITH_CURSES_CHECKEXTRA_header_var], [
169 | LIBS="$ax_saved_LIBS $5 $CURSES_LIBS"
170 | CPPFLAGS="$ax_saved_CPPFLAGS $CURSES_CFLAGS"
171 | AC_LINK_IFELSE([AC_LANG_PROGRAM([[
172 | @%:@include <$4>
173 | ]], [$3])],
174 | [_AX_WITH_CURSES_CHECKEXTRA_header_var=yes],
175 | [_AX_WITH_CURSES_CHECKEXTRA_header_var=no])
176 | ])
177 | AS_IF([test "x$[]_AX_WITH_CURSES_CHECKEXTRA_header_var" = xyes], [
178 | _AX_WITH_CURSES_CHECKEXTRA_cv_var=yes
179 | AS_LITERAL_IF([$5], [$1_LIBS="$5"])
180 | AC_DEFINE([_AX_WITH_CURSES_CHECKEXTRA_have_var], [1], [Define to 1 if the Curses $2 library is present])
181 | AC_DEFINE([_AX_WITH_CURSES_CHECKEXTRA_have_header_var], [1], [Define to 1 if <$4> is present])
182 | ], [
183 | AS_IF([test "x$[]_AX_WITH_CURSES_CHECKEXTRA_cv_var" = xyes], [],
184 | [_AX_WITH_CURSES_CHECKEXTRA_cv_var=no])
185 | ])
186 |
187 | LIBS=$ax_saved_LIBS
188 | CPPFLAGS=$ax_saved_CPPFLAGS
189 | unset ax_saved_LIBS
190 | unset ax_saved_CPPFLAGS
191 |
192 | AS_VAR_POPDEF([_AX_WITH_CURSES_CHECKEXTRA_have_header_var])dnl
193 | AS_VAR_POPDEF([_AX_WITH_CURSES_CHECKEXTRA_header_var])dnl
194 | AS_VAR_POPDEF([_AX_WITH_CURSES_CHECKEXTRA_cv_var])dnl
195 | AS_VAR_POPDEF([_AX_WITH_CURSES_CHECKEXTRA_have_var])dnl
196 | ])dnl
197 |
198 | AC_DEFUN([_AX_WITH_CURSES_EXTRA], [
199 | dnl Parameter 1 is the variable name component, using uppercase letters only
200 | dnl Parameter 2 is the printable library name
201 | dnl Parameter 3 is the C code to try compiling and linking
202 | dnl Parameter 4 is the header filename component
203 | dnl Parameter 5 is the NCursesW library command line
204 | dnl Parameter 6 is the NCurses library command line
205 | dnl Parameter 7 is the plain Curses library command line
206 |
207 | AC_REQUIRE([AX_WITH_CURSES])
208 | AC_ARG_VAR([$1_LIBS], [linker library for Curses $2, e.g. $7])
209 |
210 | AS_IF([test "x$[]$1_LIBS" != x], [
211 | _AX_WITH_CURSES_CHECKEXTRA([$1], [$2], [$3], [$4], [$[]$1_LIBS])
212 | ], [
213 | AS_IF([test "x$ax_cv_curses_which" = xncursesw], [
214 | _AX_WITH_CURSES_CHECKEXTRA([$1], [$2], [$3], [ncursesw/$4], [$5])
215 | ], [test "x$ax_cv_curses_which" = xncurses], [
216 | _AX_WITH_CURSES_CHECKEXTRA([$1], [$2], [$3], [$4], [$6])
217 | AS_IF([test x$[]ax_cv_[]m4_tolower($1) != "xyes"], [
218 | _AX_WITH_CURSES_CHECKEXTRA([$1], [$2], [$3], [ncurses/$4], [$6])
219 | ])
220 | ], [test "x$ax_cv_curses_which" = xplaincurses], [
221 | _AX_WITH_CURSES_CHECKEXTRA([$1], [$2], [$3], [$4], [$7])
222 | ])
223 | ])
224 | ])dnl
225 |
226 | AC_DEFUN([AX_WITH_CURSES_PANEL], [
227 | _AX_WITH_CURSES_EXTRA([PANEL], [Panel], [[
228 | WINDOW *win = newwin(0, 0, 0, 0);
229 | PANEL *pan = new_panel(win);
230 | ]], [panel.h], [-lpanelw], [-lpanel], [-lpanel])
231 | ])dnl
232 |
233 | AC_DEFUN([AX_WITH_CURSES_MENU], [
234 | _AX_WITH_CURSES_EXTRA([MENU], [Menu], [[
235 | ITEM **mi;
236 | MENU *m = new_menu(mi);
237 | ]], [menu.h], [-lmenuw], [-lmenu], [-lmenu])
238 | ])dnl
239 |
240 | AC_DEFUN([AX_WITH_CURSES_FORM], [
241 | _AX_WITH_CURSES_EXTRA([FORM], [Form], [[
242 | FIELD **ff;
243 | FORM *f = new_form(ff);
244 | ]], [form.h], [-lformw], [-lform], [-lform])
245 | ])dnl
246 |
--------------------------------------------------------------------------------
/resources/bitwise.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mellowcandle/bitwise/0a4e7d93b3e922e2293251fdbfd0e4fb1cc7910b/resources/bitwise.gif
--------------------------------------------------------------------------------
/resources/bitwise.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mellowcandle/bitwise/0a4e7d93b3e922e2293251fdbfd0e4fb1cc7910b/resources/bitwise.png
--------------------------------------------------------------------------------
/resources/bitwise.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
71 |
--------------------------------------------------------------------------------
/resources/cmdline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mellowcandle/bitwise/0a4e7d93b3e922e2293251fdbfd0e4fb1cc7910b/resources/cmdline.png
--------------------------------------------------------------------------------
/resources/conversion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mellowcandle/bitwise/0a4e7d93b3e922e2293251fdbfd0e4fb1cc7910b/resources/conversion.png
--------------------------------------------------------------------------------
/resources/snip.txt:
--------------------------------------------------------------------------------
1 | scrot -a 1,50,1000,160
2 |
--------------------------------------------------------------------------------
/snapcraft.yaml:
--------------------------------------------------------------------------------
1 | name: bitwise
2 | version: "v0.41"
3 | summary: Terminal based bitwise calculator in curses
4 | description: |
5 | Interactively manipulate bits.
6 |
7 | confinement: strict
8 |
9 | apps:
10 | bitwise:
11 | command: bitwise
12 |
13 | parts:
14 | bitwise:
15 | plugin: autotools
16 | source: https://github.com/mellowcandle/bitwise/releases/download/v0.40/bitwise-v0.40.tar.gz
17 | build-packages:
18 | - libncurses5-dev
19 | - libreadline-dev
20 |
--------------------------------------------------------------------------------
/src/cmd.c:
--------------------------------------------------------------------------------
1 | /* Copyright 2019
2 | * Ramon Fried
3 | */
4 | #include
5 | #include
6 | #include
7 | #include "bitwise.h"
8 | #include "shunting-yard.h"
9 |
10 | #define MAX_TOKENS 4
11 |
12 | static int cmd_clear(char **argv, int argc);
13 | static int cmd_quit(char **argv, int argc);
14 | static int cmd_help(char **argv, int argc);
15 | static int cmd_set_width(char **argv, int argc);
16 | static int cmd_set_output(char **argv, int argc);
17 |
18 | struct cmd {
19 | const char *name;
20 | int min_args;
21 | int max_args;
22 | int (*func)(char **argv, int argc);
23 | };
24 |
25 | static struct cmd cmds[] = {
26 | {"clear", 0, 0, cmd_clear},
27 | {"c", 0, 0, cmd_clear},
28 | {"help", 0, 0, cmd_help},
29 | {"h", 0, 0, cmd_help},
30 | {"quit", 0, 0, cmd_quit},
31 | {"q", 0, 0, cmd_quit},
32 | {"width ", 1, 1, cmd_set_width},
33 | {"w ", 1, 1, cmd_set_width},
34 | {"output ", 1, 1, cmd_set_output},
35 | {"o ", 1, 1, cmd_set_output},
36 | };
37 |
38 | static int get_cmd(const char *cmd_name)
39 | {
40 | size_t i = 0;
41 |
42 | for (i = 0; i < ARRAY_SIZE(cmds); i++) {
43 | LOG("comparing %s to command %s\n", cmd_name, cmds[i].name);
44 | if (cmds[i].max_args == 0) {
45 | /* These commands do not have arguments, compare exact */
46 | if (!strcmp(cmds[i].name, cmd_name))
47 | return i;
48 | } else {
49 | /*
50 | * Commands with arguments end with a trailing space,
51 | * compare just the beginning of the command including
52 | * the space
53 | */
54 | if (!strncmp(cmds[i].name, cmd_name, strlen(cmds[i].name)))
55 | return i;
56 | }
57 | }
58 |
59 | return -1;
60 | }
61 |
62 | void show_error(Status status)
63 | {
64 | char *message = NULL;
65 |
66 | switch (status) {
67 | case ERROR_SYNTAX:
68 | message = "Syntax error";
69 | break;
70 | case ERROR_OPEN_PARENTHESIS:
71 | message = "Missing parenthesis";
72 | break;
73 | case ERROR_CLOSE_PARENTHESIS:
74 | message = "Extra parenthesis";
75 | break;
76 | case ERROR_UNRECOGNIZED:
77 | message = "Unknown character";
78 | break;
79 | case ERROR_NO_INPUT:
80 | message = "Empty expression";
81 | break;
82 | case ERROR_UNDEFINED_FUNCTION:
83 | message = "Unknown function";
84 | break;
85 | case ERROR_FUNCTION_ARGUMENTS:
86 | message = "Missing function arguments";
87 | break;
88 | case ERROR_UNDEFINED_CONSTANT:
89 | message = "Unknown constant";
90 | break;
91 | case ERROR_WRONG_ARGUMENTS:
92 | message = "Wrong arguments";
93 | break;
94 | case ERROR_DIVIDE_BY_ZERO:
95 | message = "Divide by zero";
96 | break;
97 | default:
98 | message = "Unknown error";
99 | }
100 |
101 | werase(cmd_win);
102 | mvwprintw(cmd_win, 0, 0, "%s", message);
103 | append_to_history(message, TYPE_OUTPUT_ERROR);
104 | wrefresh(cmd_win);
105 | }
106 |
107 | /* Remove trailing and leading white spaces, and NULL if all-white */
108 | static char *trim_whitespace(char *str)
109 | {
110 | char *str_end = &str[strlen(str) - 1];
111 | size_t i;
112 |
113 | /* Remove leding white characters */
114 | while (isspace(str[0]))
115 | str++;
116 |
117 | /* There are only white characters */
118 | if (str[0] == '\0')
119 | return NULL;
120 |
121 | /* There is at least one non-white character, find the last one */
122 | while (isspace(str_end[0]))
123 | str_end--;
124 |
125 | str_end[1] = '\0';
126 |
127 | return str;
128 | }
129 |
130 | static int parse_cmd(char *cmdline)
131 | {
132 | static char *tokens[MAX_TOKENS];
133 | int cmd_entry;
134 | int i = 0;
135 | int rc = 0;
136 | uint64_t result;
137 |
138 | cmdline = trim_whitespace(cmdline);
139 | if (!cmdline)
140 | return 0;
141 |
142 | LOG("got command: %s\n", cmdline);
143 |
144 | /* First let's see if this is a command */
145 | cmd_entry = get_cmd(cmdline);
146 | if (cmd_entry >= 0) {
147 | /* It looks like a command, let's tokenize this */
148 | append_to_history(cmdline, TYPE_INPUT_COMMAND);
149 |
150 | tokens[i] = strtok(cmdline, " ");
151 | LOG("%s\n", tokens[i]);
152 | do {
153 | i++;
154 | tokens[i] = strtok(NULL, " ");
155 | LOG("%s\n", tokens[i]);
156 | } while (tokens[i] != NULL && (i) < MAX_TOKENS);
157 |
158 | LOG("Finished tokenizing %d tokens\n", i);
159 |
160 | if ((i - 1 >= cmds[cmd_entry].min_args) &&
161 | (i - 1 <= cmds[cmd_entry].max_args))
162 | rc = cmds[cmd_entry].func(&tokens[1], i - 1);
163 | else {
164 | werase(cmd_win);
165 | mvwprintw(cmd_win, 0, 0, "%s: Invalid parameter(s)", tokens[0]);
166 | wrefresh(cmd_win);
167 | LOG("Invalid parameters\n");
168 | return -1;
169 | }
170 | if (rc) {
171 | show_error(rc);
172 | return -1;
173 | }
174 |
175 | } else {
176 | append_to_history(cmdline, TYPE_INPUT_EXPRESSION);
177 | Status status = shunting_yard(cmdline, &result);
178 | if (status != OK) {
179 | show_error(status);
180 | return -1;
181 | } else {
182 | char result_string[256];
183 | if (result > MASK(g_width)) {
184 | result &= MASK(g_width);
185 | append_to_history("Overflow!", TYPE_OUTPUT_ERROR);
186 | }
187 | g_val = result;
188 |
189 | if (g_output == CMD_OUTPUT_ALL) {
190 | sprintf_type(result, result_string,
191 | CMD_OUTPUT_DECIMAL);
192 | append_to_history(result_string,
193 | TYPE_OUTPUT_RESULT);
194 | sprintf_type(result, result_string,
195 | CMD_OUTPUT_HEXADECIMAL);
196 | append_to_history(result_string,
197 | TYPE_OUTPUT_RESULT);
198 | sprintf_type(result, result_string,
199 | CMD_OUTPUT_OCTAL);
200 | append_to_history(result_string,
201 | TYPE_OUTPUT_RESULT);
202 | sprintf_type(result, result_string,
203 | CMD_OUTPUT_BINARY);
204 | append_to_history(result_string,
205 | TYPE_OUTPUT_RESULT);
206 | update_binary();
207 | update_fields(-1);
208 | } else {
209 | sprintf_type(result, result_string, g_output);
210 | update_binary();
211 | update_fields(-1);
212 | append_to_history(result_string,
213 | TYPE_OUTPUT_RESULT);
214 | }
215 | }
216 | }
217 |
218 | return 0;
219 | }
220 |
221 | static int readline_input_avail(void)
222 | {
223 | return g_input_avail;
224 | }
225 |
226 | static int readline_getc(FILE *dummy)
227 | {
228 | g_input_avail = false;
229 | return g_input;
230 | }
231 |
232 | static void got_command(char *line)
233 | {
234 | int rc;
235 | /* Handle exit commands immediately */
236 | if (!line) {
237 | /* Handle CTL-D */
238 | g_leave_req = true;
239 | return;
240 | }
241 |
242 | if (*line)
243 | add_history(line);
244 |
245 | rc = parse_cmd(line);
246 | free(line);
247 |
248 | if (!rc) {
249 | keypad(stdscr, FALSE);
250 | werase(cmd_win);
251 | wrefresh(cmd_win);
252 | }
253 |
254 | return;
255 | }
256 |
257 | void readline_redisplay(void)
258 | {
259 | if (active_win != COMMAND_WIN)
260 | return;
261 |
262 | werase(cmd_win);
263 | mvwprintw(cmd_win, 0, 0, "%s%s", rl_display_prompt, rl_line_buffer);
264 | wmove(cmd_win, 0, rl_point + 1);
265 | wrefresh(cmd_win);
266 | }
267 |
268 |
269 | void init_readline(void)
270 | {
271 | rl_catch_signals = 0;
272 | rl_catch_sigwinch = 0;
273 | rl_deprep_term_function = NULL;
274 | rl_prep_term_function = NULL;
275 | rl_change_environment = 0;
276 | rl_getc_function = readline_getc;
277 | rl_input_available_hook = readline_input_avail;
278 | rl_redisplay_function = readline_redisplay;
279 | //rl_bind_key('\t', rl_insert);
280 | rl_callback_handler_install(":", got_command);
281 |
282 | }
283 |
284 | void deinit_readline(void)
285 | {
286 | rl_callback_handler_remove();
287 | }
288 |
289 | void process_cmd(int ch)
290 | {
291 | int new_char;
292 |
293 | LOG("Process cmd %u\n", ch);
294 |
295 | if (ch == 27) {
296 | nodelay(get_win(active_win), true);
297 | new_char = wgetch(get_win(active_win));
298 | nodelay(get_win(active_win), false);
299 |
300 | if (new_char == ERR) {
301 | LOG("IT's a real escape\n");
302 | active_win = last_win;
303 |
304 | // Re-enable mouse events
305 | mousemask(BUTTON1_CLICKED, NULL);
306 |
307 | if (active_win == FIELDS_WIN) {
308 | set_active_field(false);
309 | form_driver(form, REQ_END_LINE);
310 | form_driver(form, REQ_VALIDATION);
311 | curs_set(1);
312 | wrefresh(fields_win);
313 | } else if (active_win == BINARY_WIN) {
314 | curs_set(0);
315 | position_binary_curser(0, bit_pos);
316 | wrefresh(binary_win);
317 | }
318 | keypad(stdscr, FALSE);
319 | werase(cmd_win);
320 | wrefresh(cmd_win);
321 | return;
322 | } else
323 | ungetch(new_char);
324 | }
325 |
326 | /* If TAB || BACKSPACE (to -1) */
327 | if (ch == 127 && !rl_point) {
328 | LOG("Detected exit cmd\n");
329 | active_win = last_win;
330 | if (active_win == FIELDS_WIN) {
331 | set_active_field(false);
332 | form_driver(form, REQ_END_LINE);
333 | form_driver(form, REQ_VALIDATION);
334 | curs_set(1);
335 | wrefresh(fields_win);
336 | } else if (active_win == BINARY_WIN) {
337 | curs_set(0);
338 | position_binary_curser(0, bit_pos);
339 | wrefresh(binary_win);
340 | }
341 | keypad(stdscr, FALSE);
342 | werase(cmd_win);
343 | wrefresh(cmd_win);
344 | return;
345 | }
346 |
347 | g_input = ch;
348 | g_input_avail = true;
349 | rl_callback_read_char();
350 | }
351 |
352 | static int cmd_clear(char **argv, int argc)
353 | {
354 | LOG("%s: argc %d\n", __func__, argc);
355 | flush_history();
356 | update_history_win();
357 | return 0;
358 | }
359 |
360 | static int cmd_quit(char **argv, int argc)
361 | {
362 | LOG("%s: argc %d\n", __func__, argc);
363 | g_leave_req = true;
364 | return 0;
365 | }
366 |
367 | static int cmd_set_width(char **argv, int argc)
368 | {
369 | LOG("%s: argc %d\n", __func__, argc);
370 | if (!strcmp("64", argv[0]))
371 | set_fields_width(64);
372 | else if (!strcmp("32", argv[0]))
373 | set_fields_width(32);
374 | else if (!strcmp("16", argv[0]))
375 | set_fields_width(16);
376 | else if (!strcmp("8", argv[0]))
377 | set_fields_width(8);
378 | else
379 | return ERROR_WRONG_ARGUMENTS;
380 |
381 | unpaint_screen();
382 | paint_screen();
383 |
384 | return 0;
385 | }
386 |
387 | static int cmd_set_output(char **argv, int argc)
388 | {
389 | LOG("%s: argc %d\n", __func__, argc);
390 | if (!strcmp("hexadecimal", argv[0]) || !strcmp("hex", argv[0]))
391 | g_output = CMD_OUTPUT_HEXADECIMAL;
392 | else if (!strcmp("decimal", argv[0]) || !strcmp("dec", argv[0]))
393 | g_output = CMD_OUTPUT_DECIMAL;
394 | else if (!strcmp("octal", argv[0]) || !strcmp("oct", argv[0]))
395 | g_output = CMD_OUTPUT_OCTAL;
396 | else if (!strcmp("binary", argv[0]) || !strcmp("bin", argv[0]))
397 | g_output = CMD_OUTPUT_BINARY;
398 | else if (!strcmp("all", argv[0]))
399 | g_output = CMD_OUTPUT_ALL;
400 | else
401 | return ERROR_WRONG_ARGUMENTS;
402 |
403 | return 0;
404 | }
405 |
406 | static int cmd_help(char **argv, int argc)
407 | {
408 | unpaint_screen();
409 | curs_set(0);
410 | show_help();
411 | curs_set(2);
412 | paint_screen();
413 |
414 | return 0;
415 | }
416 |
--------------------------------------------------------------------------------
/src/help.c:
--------------------------------------------------------------------------------
1 | /* Copyright 2019
2 | * Ramon Fried
3 | */
4 |
5 | #include "bitwise.h"
6 |
7 | static const char *help_header = PACKAGE " " VERSION;
8 | static const char *interactive_mode = "Type numbers in different bases and directly manipulate bits.\n" \
9 | "To move around use the arrow keys, or use vi key bindings ('h|j|k|l').\n" \
10 | "In the binary field, toggle a bit using 'SPACE'.\n" \
11 | "You can jump a byte forward using 'w' and backwards one byte using 'b'.\n\n" \
12 | "Additional key mapping:\n" \
13 | "'F1' Show this help screen.\n" \
14 | "'~' Perform logical NOT.\n" \
15 | "'<' Perform left shift.\n" \
16 | "'>' Perform right shift.\n\n" \
17 | "'!' Set bit width to 8bit.\n" \
18 | "'@' Set bit width to 16bit.\n" \
19 | "'$' Set bit width to 32bit.\n" \
20 | "'*' Set bit width to 64bit.\n" \
21 | "'r' Reverse the endianness\n" \
22 | "':' Switch to command mode.\n" \
23 | "'q' Exit back to shell.\n";
24 |
25 | static const char *command_mode = "Type expressions or commands, result will be appended to history window.\n" \
26 | "Supported operators: (,),+, -, *, /, !, ~, <<_, >>_, BIT(_).\n" \
27 | "Precedence of operators is defined as C language precedence.\n\n" \
28 | "You can referr to the last result with '$' inside an expression.\n" \
29 | "To return to interactive mode type 'ESC'.\n\n" \
30 | "Supported commands:\n" \
31 | "'help' Show this help screen.\n" \
32 | "'clear' Clear the history window.\n" \
33 | "'width []' Set the bit width to [8 | 16 | 32 | 64]\n" \
34 | "'output []' Set the default output for results [decimal | hex | octal | binary | all]\n" \
35 | "'q' Exit back to shell.\n";
36 |
37 | void show_help(void)
38 | {
39 | WINDOW *help_win;
40 | int ch;
41 |
42 | /* Create full screen window */
43 | help_win = newwin(0, 0, 0, 0);
44 |
45 | if (g_has_color)
46 | wattron(help_win, COLOR_PAIR(2));
47 | mvwprintw(help_win, 0, COLS / 2 - strlen(help_header), "%s",
48 | help_header);
49 | if (g_has_color)
50 | wattroff(help_win, COLOR_PAIR(2));
51 |
52 | wmove(help_win, 1, 0);
53 | if (g_has_color)
54 | wattron(help_win, A_UNDERLINE | COLOR_PAIR(3));
55 | wprintw(help_win, "Interactive Mode:\n\n");
56 | if (g_has_color)
57 | wattroff(help_win, A_UNDERLINE | COLOR_PAIR(3));
58 |
59 | wprintw(help_win, "%s\n", interactive_mode);
60 | if (g_has_color)
61 | wattroff(help_win, A_UNDERLINE | COLOR_PAIR(1));
62 |
63 | if (g_has_color)
64 | wattron(help_win, A_UNDERLINE | COLOR_PAIR(3));
65 | wprintw(help_win, "Command Mode:\n\n");
66 | if (g_has_color)
67 | wattroff(help_win, A_UNDERLINE | COLOR_PAIR(3));
68 | wprintw(help_win, "%s", command_mode);
69 |
70 | wrefresh(help_win);
71 | refresh();
72 | ch = wgetch(help_win);
73 |
74 | werase(help_win);
75 | wrefresh(help_win);
76 | delwin(help_win);
77 |
78 | if (ch == 'q' || ch == 'Q')
79 | g_leave_req = true;
80 |
81 | if (ch == KEY_RESIZE) {
82 | rl_resize_terminal();
83 | show_help();
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/interactive.c:
--------------------------------------------------------------------------------
1 | /* Copyright 2019
2 | * Ramon Fried
3 | */
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 | #include "bitwise.h"
17 |
18 | #define MAX_DEC_DIGITS_64 20
19 | #define MAX_HEX_DIGITS_64 16
20 | #define MAX_OCT_DIGITS_64 32
21 |
22 | #define MAX_DEC_DIGITS_32 10
23 | #define MAX_HEX_DIGITS_32 8
24 | #define MAX_OCT_DIGITS_32 16
25 |
26 | #define MAX_DEC_DIGITS_16 5
27 | #define MAX_HEX_DIGITS_16 4
28 | #define MAX_OCT_DIGITS_16 8
29 |
30 | #define MAX_DEC_DIGITS_8 3
31 | #define MAX_HEX_DIGITS_8 2
32 | #define MAX_OCT_DIGITS_8 4
33 |
34 | #define CLEAR_BIT 0
35 | #define SET_BIT 1
36 | #define TOGGLE_BIT 2
37 |
38 | #ifdef TRACE
39 | FILE *fd;
40 | #endif
41 |
42 | int max_dec_digits, max_hex_digits, max_oct_digits;
43 | int min_frame_size;
44 | static char title[] = "Bitwise";
45 | static char *width_str;
46 | WINDOW *fields_win;
47 | WINDOW *binary_win;
48 | WINDOW *cmd_win;
49 | WINDOW *history_win;
50 |
51 | int active_win, last_win;
52 | int g_output = CMD_OUTPUT_HEXADECIMAL;
53 |
54 | static FIELD *field[5];
55 | FORM *form;
56 | uint64_t g_val;
57 | int bit_pos;
58 | static int binary_field_size;
59 |
60 | static int base[3] = {
61 | 10,
62 | 16,
63 | 8,
64 | };
65 |
66 | struct history_entry history[MAX_HISTORY_LEN] = { { 0, NULL } };
67 | unsigned int history_pos = 0;
68 | int max_display_history;
69 |
70 | #define BINARY_WIN_LEN 17
71 | #define BYTE_BINARY_WIN_LEN (BINARY_WIN_LEN + 2)
72 | #define WORD_BINARY_WIN_LEN (BINARY_WIN_LEN * 2) + 3
73 | #define LONG_BINARY_WIN_LEN (BINARY_WIN_LEN * 4) + 5
74 | #define DBL_BINARY_WIN_LEN (BINARY_WIN_LEN * 8) + 9
75 |
76 | void flush_history(void)
77 | {
78 | int i;
79 |
80 | history_pos = 0;
81 |
82 | for (i = 0; i < MAX_HISTORY_LEN; i++)
83 | if (history[i].line) {
84 | free(history[i].line);
85 | history[i].line = NULL;
86 | }
87 | }
88 |
89 | void update_history_win(void)
90 | {
91 | unsigned int max_display = LINES - 17;
92 | int i, j;
93 |
94 | if (history_pos < max_display)
95 | max_display = history_pos;
96 |
97 | werase(history_win);
98 | box(history_win, 0, 0);
99 |
100 | for (i = max_display, j = 1; i > 0; i--, j++) {
101 | if (g_has_color)
102 | switch (history[history_pos -i].type) {
103 | case TYPE_INPUT_COMMAND:
104 | wattron(history_win, COLOR_PAIR(2));
105 | break;
106 | case TYPE_INPUT_EXPRESSION:
107 | wattron(history_win, COLOR_PAIR(1));
108 | break;
109 | case TYPE_OUTPUT_RESULT:
110 | wattron(history_win, COLOR_PAIR(3));
111 | break;
112 | case TYPE_OUTPUT_ERROR:
113 | wattron(history_win, COLOR_PAIR(5));
114 | break;
115 | }
116 |
117 | mvwprintw(history_win, j, 2, "%s", history[history_pos - i].line);
118 | }
119 |
120 | if (g_has_color)
121 | wattroff(history_win, COLOR_PAIR(1));
122 | wrefresh(history_win);
123 | }
124 |
125 | char binary_field[DBL_BINARY_WIN_LEN];
126 | int dec_pos, hex_pos, oct_pos;
127 | bool g_leave_req;
128 | void set_fields_width(int width)
129 | {
130 | int min_field_distance;
131 | g_width = width;
132 | switch (width) {
133 | case 64:
134 | binary_field_size = DBL_BINARY_WIN_LEN;
135 | max_dec_digits = MAX_DEC_DIGITS_64;
136 | max_hex_digits = MAX_HEX_DIGITS_64;
137 | max_oct_digits = MAX_OCT_DIGITS_64;
138 | min_field_distance = 4;
139 | width_str = " 64Bit ";
140 | break;
141 | case 32:
142 | g_val &= 0xFFFFFFFF;
143 | binary_field_size = LONG_BINARY_WIN_LEN;
144 | max_dec_digits = MAX_DEC_DIGITS_32;
145 | max_hex_digits = MAX_HEX_DIGITS_32;
146 | max_oct_digits = MAX_OCT_DIGITS_32;
147 | min_field_distance = 6;
148 | width_str = " 32Bit ";
149 | break;
150 | case 16:
151 | g_val &= 0xFFFF;
152 | binary_field_size = WORD_BINARY_WIN_LEN;
153 | max_dec_digits = MAX_DEC_DIGITS_16;
154 | max_hex_digits = MAX_HEX_DIGITS_16;
155 | max_oct_digits = MAX_OCT_DIGITS_16;
156 | min_field_distance = 8;
157 | width_str = " 16Bit ";
158 | break;
159 | case 8:
160 | g_val &= 0xFF;
161 | binary_field_size = BYTE_BINARY_WIN_LEN;
162 | max_dec_digits = MAX_DEC_DIGITS_8;
163 | max_hex_digits = MAX_HEX_DIGITS_8;
164 | max_oct_digits = MAX_OCT_DIGITS_8;
165 | min_field_distance = 10;
166 | width_str = " 8Bit ";
167 | break;
168 | }
169 |
170 | /* Reserve space for the cursor at the end */
171 | max_dec_digits += 1;
172 | max_hex_digits += 1;
173 | max_oct_digits += 1;
174 |
175 | dec_pos = 0;
176 | hex_pos = dec_pos + max_dec_digits + min_field_distance - 2;
177 | oct_pos = hex_pos + max_hex_digits + min_field_distance + 1;
178 | }
179 |
180 | static void update_bit(int pos, int op)
181 | {
182 | if (op == SET_BIT)
183 | g_val |= BIT(g_width - 1 - pos);
184 | else if (op == CLEAR_BIT)
185 | g_val &= ~(BIT(g_width - 1 - pos));
186 | else
187 | g_val ^= BIT(g_width - 1 - pos);
188 | LOG("g_width: %d\ng_val: %llu\n", g_width, g_val);
189 |
190 |
191 | update_binary();
192 | }
193 |
194 | void update_binary()
195 | {
196 | int i;
197 | int pos = 0;
198 |
199 | for (i = g_width; i > 0; i--) {
200 | if ((i % 8 == 0) && (i != g_width)) {
201 | binary_field[pos] = '|';
202 | binary_field[pos + 1] = ' ';
203 | pos += 2;
204 | }
205 | if (g_val & BIT(i - 1))
206 | binary_field[pos] = '1';
207 | else
208 | binary_field[pos] = '0';
209 | binary_field[pos + 1] = ' ';
210 | pos += 2;
211 | }
212 |
213 | binary_field[pos] = '\0';
214 | mvwprintw(binary_win, 1, 2, "%s", binary_field);
215 |
216 | pos = 6;
217 | if (g_has_color)
218 | wattron(binary_win, COLOR_PAIR(3));
219 | for (i = 0; i < g_width / 8; i++, pos += 18)
220 | mvwprintw(binary_win, 2, pos, "%2d - %2d",
221 | (g_width - 1) - (i * 8),
222 | (g_width - 8) - (i * 8));
223 | if (g_has_color)
224 | wattroff(binary_win, COLOR_PAIR(3));
225 | wrefresh(binary_win);
226 | }
227 |
228 |
229 | void mouse_to_bit(int xPos){
230 | int binaryDigitWinSize = 18;
231 | //Indicates that user is clicking a separating bar
232 | if(xPos % binaryDigitWinSize == 0){
233 | return;
234 | }
235 | int field = floor(xPos / binaryDigitWinSize);
236 | // How many bits from the previous separating line was the click
237 | int bitFromLine = floor((xPos%binaryDigitWinSize)/2) - 1;
238 | // If they are on the first bit
239 | if (bitFromLine < 0) {
240 | bitFromLine = 0;
241 | }
242 | int relativeBit = (8 * (field)) + bitFromLine;
243 | update_bit(relativeBit, TOGGLE_BIT);
244 | update_fields(-1);
245 | }
246 |
247 | WINDOW * process_mouse(MEVENT *event)
248 | {
249 | WINDOW *mouse_window = NULL;
250 | if (wmouse_trafo(binary_win, &event->y, &event->x, FALSE) == TRUE) {
251 | mouse_window = binary_win;
252 | mouse_to_bit(event->x);
253 | } else if (wmouse_trafo(fields_win, &event->y, &event->x, FALSE) == TRUE) {
254 | mouse_window = fields_win;
255 | }
256 |
257 | return mouse_window;
258 | }
259 |
260 |
261 | int update_fields(int index)
262 | {
263 | FIELD *tmp_field = current_field(form);
264 | int *cur_base = field_userptr(tmp_field);
265 | char *buffer;
266 | char number[64];
267 | int *base;
268 | uint64_t tmp_val;
269 | if (index != -1) {
270 | buffer = field_buffer(tmp_field, 0);
271 | assert(buffer);
272 |
273 | tmp_val = strtoull(buffer, NULL, *cur_base);
274 | if (tmp_val == LLONG_MAX) {
275 | /*
276 | * Make sure we don't get a number which is
277 | * too big to represent in 64bit */
278 | beep();
279 | return 1;
280 | }
281 | if (tmp_val > MASK(g_width)) {
282 | FIELD *tmp_field = current_field(form);
283 | unpaint_screen();
284 | set_fields_width(g_width * 2);
285 | paint_screen();
286 | set_current_field(form, tmp_field);
287 | set_active_field(false);
288 | LOG("Overflow: tmp_val = %" PRIu64 "\n", tmp_val);
289 | index = -1;
290 | }
291 | g_val = tmp_val;
292 | }
293 | LOG("Val = %" PRIu64 "\n", g_val);
294 | for (int i = 0; i < 3; i++) {
295 | base = field_userptr(field[i]);
296 | if (g_val)
297 | lltostr(g_val, number, *base);
298 | else
299 | number[0] = '\0';
300 | LOG("updating field %d\n", i);
301 | set_field_buffer(field[i], 0, number);
302 | }
303 | form_driver(form, REQ_VALIDATION);
304 | form_driver(form, REQ_END_FIELD);
305 | wrefresh(fields_win);
306 |
307 | return 0;
308 | }
309 |
310 | void set_active_field(bool none)
311 | {
312 | if (!g_has_color)
313 | return;
314 |
315 | if (!none) {
316 | set_field_fore(current_field(form), COLOR_PAIR(1));
317 | set_field_back(current_field(form),
318 | A_UNDERLINE | COLOR_PAIR(1));
319 | }
320 |
321 | for (int i = 0; i < 3; i++) {
322 | if ((field[i] == current_field(form)) && (!none))
323 | continue;
324 | set_field_fore(field[i], COLOR_PAIR(0));
325 | set_field_back(field[i], COLOR_PAIR(0));
326 | }
327 | }
328 |
329 | void position_binary_curser(int previous_pos, int next_pos)
330 | {
331 |
332 | int pos;
333 |
334 | pos = 2 + (2 * previous_pos) + (2 * (previous_pos / 8));
335 | mvwchgat(binary_win, 1, pos, 1, A_NORMAL, COLOR_PAIR(0), NULL);
336 |
337 | if (next_pos != -1) {
338 | pos = 2 + (2 * next_pos) + (2 * (next_pos / 8));
339 | mvwchgat(binary_win, 1, pos, 1, A_UNDERLINE,
340 | COLOR_PAIR(0), NULL);
341 | mvwprintw(binary_win, 3, 1, "bit %.2u\t\t",
342 | g_width - 1 - next_pos);
343 | }
344 | wrefresh(binary_win);
345 | }
346 |
347 | void process_binary(int ch)
348 | {
349 | int tmp;
350 |
351 | switch (ch) {
352 | case 'w':
353 | case 'W':
354 | LOG("word right\n");
355 | tmp = (bit_pos + 8) & ~(8 - 1);
356 | if (tmp >= g_width - 1) {
357 | beep();
358 | break;
359 | }
360 | position_binary_curser(bit_pos, tmp);
361 | bit_pos = tmp;
362 | break;
363 |
364 | case 'b':
365 | case 'B':
366 | LOG("word left\n");
367 | tmp = (bit_pos - 8) & ~(8 - 1);
368 | if (tmp < 0) {
369 | beep();
370 | break;
371 | }
372 | position_binary_curser(bit_pos, tmp);
373 | bit_pos = tmp;
374 | break;
375 | case KEY_RIGHT:
376 | case 'l':
377 | LOG("Key right\n");
378 | if (bit_pos == g_width - 1) {
379 | beep();
380 | break;
381 | }
382 | position_binary_curser(bit_pos, bit_pos + 1);
383 | bit_pos++;
384 | break;
385 | case KEY_LEFT:
386 | case 'h':
387 | LOG("Key left\n");
388 | if (bit_pos == 0) {
389 | beep();
390 | break;
391 | }
392 | position_binary_curser(bit_pos, bit_pos - 1);
393 | bit_pos--;
394 | break;
395 | case KEY_UP:
396 | case 'k':
397 | case '\t':
398 | LOG("Key up\n");
399 | active_win = FIELDS_WIN;
400 | set_active_field(false);
401 | position_binary_curser(bit_pos, -1);
402 | form_driver(form, REQ_END_LINE);
403 | form_driver(form, REQ_VALIDATION);
404 | curs_set(1);
405 | wrefresh(fields_win);
406 | break;
407 | case KEY_BACKSPACE:
408 | case 127:
409 | LOG("Backspace\n");
410 | if (bit_pos != 0) {
411 | bit_pos--;
412 | update_bit(bit_pos, CLEAR_BIT);
413 | update_fields(-1);
414 | } else
415 | beep();
416 | break;
417 | default:
418 | if (ch == '1') {
419 | update_bit(bit_pos, SET_BIT);
420 | position_binary_curser(bit_pos,
421 | (bit_pos + 1) == (g_width) ?
422 | (bit_pos) : (bit_pos + 1));
423 | update_fields(-1);
424 | if (bit_pos != g_width - 1)
425 | bit_pos++;
426 | break;
427 | } else if (ch == '0') {
428 | update_bit(bit_pos, CLEAR_BIT);
429 | position_binary_curser(bit_pos,
430 | (bit_pos + 1) == (g_width) ?
431 | (bit_pos) : (bit_pos + 1));
432 | update_fields(-1);
433 | if (bit_pos != g_width - 1)
434 | bit_pos++;
435 | break;
436 | } else if (ch == ' ') {
437 | update_bit(bit_pos, TOGGLE_BIT);
438 | position_binary_curser(bit_pos, bit_pos);
439 | update_fields(-1);
440 | }
441 | break;
442 | }
443 | }
444 |
445 | void process_fields(int ch)
446 | {
447 | FIELD *tmp_field;
448 | int *cur_base;
449 |
450 | switch (ch) {
451 | case KEY_RIGHT:
452 | case 'l':
453 | LOG("Key right\n");
454 | /* Go to next field */
455 | form_driver(form, REQ_NEXT_FIELD);
456 | /* Go to the end of the present buffer */
457 | /* Leaves nicely at the last character */
458 | form_driver(form, REQ_END_FIELD);
459 | set_active_field(false);
460 | wrefresh(fields_win);
461 | break;
462 | case KEY_LEFT:
463 | case 'h':
464 | LOG("Key left\n");
465 | /* Go to previous field */
466 | form_driver(form, REQ_PREV_FIELD);
467 | form_driver(form, REQ_END_FIELD);
468 | set_active_field(false);
469 | wrefresh(fields_win);
470 | break;
471 | case KEY_DOWN:
472 | case 'j':
473 | case '\t':
474 | LOG("Key down\n");
475 | active_win = BINARY_WIN;
476 | curs_set(0);
477 | set_active_field(true);
478 | form_driver(form, REQ_VALIDATION);
479 | position_binary_curser(0, bit_pos);
480 | wrefresh(fields_win);
481 | break;
482 | case KEY_BACKSPACE:
483 | case KEY_DC:
484 | case 127:
485 | case 8:
486 | LOG("Backspace\n");
487 | form_driver(form, REQ_DEL_CHAR);
488 | form_driver(form, REQ_DEL_PREV);
489 | form_driver(form, REQ_VALIDATION);
490 | update_fields(field_index(current_field(form)));
491 | set_active_field(false);
492 | update_binary();
493 | wrefresh(fields_win);
494 | break;
495 | default:
496 | LOG("default char: %d\n", ch);
497 |
498 | tmp_field = current_field(form);
499 | cur_base = field_userptr(tmp_field);
500 |
501 | if (validate_input(ch, *cur_base))
502 | break;
503 | form_driver(form, ch);
504 | form_driver(form, REQ_VALIDATION);
505 | if (update_fields(field_index(tmp_field))) {
506 | form_driver(form, REQ_DEL_CHAR);
507 | form_driver(form, REQ_PREV_CHAR);
508 | form_driver(form, REQ_VALIDATION);
509 | }
510 | update_binary();
511 | wrefresh(fields_win);
512 | break;
513 | }
514 | }
515 |
516 | void paint_screen(void)
517 | {
518 | int rows, cols;
519 | int rc;
520 |
521 | /* Initialize the fields */
522 | field[0] = new_field(1, max_dec_digits, 1,
523 | dec_pos, 0, 0);
524 |
525 | field[1] = new_field(1, max_hex_digits, 1,
526 | hex_pos, 0, 0);
527 | field[2] = new_field(1, max_oct_digits, 1,
528 | oct_pos, 0, 0);
529 | field[3] = NULL;
530 |
531 | for (int i = 0; i < 3; i++) {
532 | set_field_back(field[i], A_UNDERLINE);
533 | field_opts_off(field[i], O_AUTOSKIP);
534 | set_field_userptr(field[i], &base[i]);
535 | }
536 |
537 | if (g_has_color) {
538 | init_pair(1, COLOR_BLUE, COLOR_BLACK);
539 | init_pair(2, COLOR_GREEN, COLOR_BLACK);
540 | init_pair(3, COLOR_CYAN, COLOR_BLACK);
541 | init_pair(4, COLOR_MAGENTA, COLOR_BLACK);
542 | init_pair(5, COLOR_RED, COLOR_BLACK);
543 | }
544 |
545 | form = new_form(field);
546 | if (!form)
547 | die("new form failed\n");
548 |
549 | scale_form(form, &rows, &cols);
550 |
551 | fields_win = newwin(rows + 3, cols + 6, 2, 0);
552 | keypad(fields_win, TRUE);
553 |
554 | binary_win = newwin(5, binary_field_size, 8, 0);
555 | keypad(binary_win, TRUE);
556 | box(binary_win, 0, 0);
557 |
558 | history_win = newwin(LINES - 15, COLS, 13, 0);
559 | box(history_win, 0, 0);
560 |
561 | rc = set_form_win(form, fields_win);
562 | if (rc != E_OK)
563 | die("set_form_win failed\n");
564 |
565 | rc = set_form_sub(form, derwin(fields_win, rows, cols, 2, 2));
566 | if (rc != E_OK)
567 | die("set_form_sub failed\n");
568 |
569 | set_current_field(form, field[0]);
570 | set_active_field(false);
571 |
572 | mvprintw(0, (COLS - strlen(title)) / 2, "%s", title);
573 | box(fields_win, 0, 0);
574 | mvwprintw(fields_win, 0, (cols + 6 - strlen(width_str)) / 2, "%s",
575 | width_str);
576 | if (g_has_color)
577 | wattron(fields_win, COLOR_PAIR(2));
578 | mvwprintw(fields_win, 1, dec_pos + 2, "Decimal:");
579 | mvwprintw(fields_win, 1, hex_pos + 2, "Hexdecimal:");
580 | mvwprintw(fields_win, 1, oct_pos + 2, "Octal:");
581 | if (g_has_color)
582 | wattroff(binary_win, COLOR_PAIR(2));
583 |
584 | cmd_win = newwin(1, COLS, LINES - 1, 0);
585 |
586 | wrefresh(fields_win);
587 | update_binary();
588 | update_history_win();
589 |
590 | wrefresh(cmd_win);
591 | refresh();
592 |
593 | rc = post_form(form);
594 | if (rc != E_OK)
595 | die("post_form failed: %d\n", rc);
596 |
597 | update_fields(-1);
598 | }
599 |
600 | void unpaint_screen(void)
601 | {
602 | int i;
603 |
604 | unpost_form(form);
605 | free_form(form);
606 | for (i = 0; i < 3; i++)
607 | free_field(field[i]);
608 | delwin(fields_win);
609 | delwin(binary_win);
610 | delwin(history_win);
611 | delwin(cmd_win);
612 | clear();
613 | refresh();
614 | }
615 |
616 | int start_interactive(uint64_t start)
617 | {
618 | int ch;
619 | uint64_t tmp_val;
620 | MEVENT event;
621 |
622 | g_val = start;
623 |
624 | init_terminal();
625 | init_readline();
626 | mousemask(BUTTON1_CLICKED, NULL);
627 |
628 | refresh();
629 |
630 | set_fields_width(g_width);
631 |
632 | paint_screen();
633 | last_win = active_win = FIELDS_WIN;
634 |
635 | while (true) {
636 | if (g_leave_req)
637 | break;
638 |
639 | ch = wgetch(get_win(active_win));
640 | LOG("%d window ch= %d\n", active_win, ch);
641 |
642 | if (active_win == COMMAND_WIN) {
643 | process_cmd(ch);
644 | continue;
645 | }
646 |
647 | switch (ch) {
648 | case KEY_MOUSE:
649 | if(getmouse(&event) == OK){
650 | process_mouse(&event);
651 | }
652 | break;
653 |
654 | case KEY_F(1):
655 | unpaint_screen();
656 | show_help();
657 | paint_screen();
658 | break;
659 | case 'q':
660 | case 'Q':
661 | g_leave_req = true;
662 | continue;
663 | case KEY_RESIZE:
664 | LOG("Terminal resize\n");
665 | unpaint_screen();
666 | paint_screen();
667 | rl_resize_terminal();
668 | break;
669 | case '!':
670 | unpaint_screen();
671 | set_fields_width(8);
672 | if (bit_pos > 7)
673 | bit_pos = 7;
674 | paint_screen();
675 | break;
676 | case '@':
677 | unpaint_screen();
678 | set_fields_width(16);
679 | if (bit_pos > 15)
680 | bit_pos = 15;
681 | paint_screen();
682 | break;
683 | case '$':
684 | unpaint_screen();
685 | set_fields_width(32);
686 | if (bit_pos > 31)
687 | bit_pos = 31;
688 | paint_screen();
689 | break;
690 | case '*':
691 | unpaint_screen();
692 | set_fields_width(64);
693 | paint_screen();
694 | break;
695 | case '~':
696 | unpaint_screen();
697 | g_val = ~g_val & MASK(g_width);
698 | paint_screen();
699 | break;
700 | case 'r':
701 | unpaint_screen();
702 | switch (g_width) {
703 | case 16:
704 | g_val = __builtin_bswap16(g_val);
705 | break;
706 | case 32:
707 | g_val = __builtin_bswap32(g_val);
708 | break;
709 | case 64:
710 | g_val = __builtin_bswap64(g_val);
711 | break;
712 | }
713 | paint_screen();
714 | break;
715 | case '>':
716 | unpaint_screen();
717 | g_val = g_val >> 1;
718 | paint_screen();
719 | break;
720 | case '<':
721 | tmp_val = (g_val << 1);
722 |
723 | if (tmp_val < MASK(g_width)) {
724 | unpaint_screen();
725 | g_val = tmp_val;
726 | paint_screen();
727 | }
728 | break;
729 | case ':':
730 | last_win = active_win;
731 | active_win = COMMAND_WIN;
732 | if (last_win == FIELDS_WIN) {
733 | set_active_field(true);
734 | form_driver(form, REQ_VALIDATION);
735 | wrefresh(fields_win);
736 | } else if (last_win == BINARY_WIN)
737 | position_binary_curser(bit_pos, -1);
738 |
739 | // Stop handling of mouse events
740 | mousemask(0, NULL);
741 |
742 | curs_set(1);
743 | keypad(stdscr, FALSE);
744 | intrflush(NULL, FALSE);
745 | readline_redisplay();
746 | break;
747 | default:
748 | if (active_win == BINARY_WIN)
749 | process_binary(ch);
750 | else if (active_win == FIELDS_WIN)
751 | process_fields(ch);
752 | }
753 |
754 | if (active_win == BINARY_WIN) {
755 | LOG("Bit pos = %u\n", bit_pos);
756 | position_binary_curser(0, bit_pos);
757 | }
758 |
759 | }
760 |
761 | unpaint_screen();
762 | /* OK. this is really weird, it seems that by calling
763 | * deinit_readline() before exiting is breaking bash
764 | * afterwards and must be fixed by typing reset in the
765 | * terminal.
766 | * I couldn't figure this one out, let's just leave it like
767 | * this, hopefully it won't affect other env */
768 |
769 | /* deinit_readline(); */
770 |
771 | flush_history();
772 | deinit_terminal();
773 |
774 | return 0;
775 | }
776 |
--------------------------------------------------------------------------------
/src/main.c:
--------------------------------------------------------------------------------
1 | /* Copyright 2019
2 | * Ramon Fried
3 | */
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | #ifdef HAVE_DECL_BSWAP_32
15 | #include
16 | #else
17 | #define bswap_32(x) \
18 | ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
19 | (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
20 |
21 | #endif
22 |
23 | #include "bitwise.h"
24 | #include "shunting-yard.h"
25 |
26 |
27 | int print_conversions(uint64_t val, bool si)
28 | {
29 | char buf_size[16];
30 | char binary[512];
31 | int pos = 0;
32 | int i, j;
33 | struct in_addr ip_addr;
34 |
35 | buf_size[0] = '\0';
36 | sprintf_size(val, buf_size, si);
37 |
38 | printf("%sUnsigned decimal: %s%" PRIu64 "\n", color_green, color_blue, val);
39 |
40 | switch (g_width) {
41 | case 64:
42 | printf("%sSigned decimal: %s%" PRId64 "\n", color_green,
43 | color_blue, (int64_t)val);
44 | break;
45 | case 32:
46 | printf("%sSigned decimal: %s%" PRId32 "\n", color_green,
47 | color_blue, (int32_t)val);
48 | break;
49 | case 16:
50 | printf("%sSigned decimal: %s%" PRId16 "\n", color_green,
51 | color_blue, (int16_t)val);
52 | break;
53 | case 8:
54 | printf("%sSigned decimal: %s%" PRId8 "\n", color_green,
55 | color_blue, (int8_t)val);
56 | break;
57 | default:
58 | break;
59 | }
60 |
61 | printf("%sHexadecimal: %s0x%" PRIx64 "\n", color_green, color_blue, val);
62 | printf("%sOctal: %s0%" PRIo64 "\n", color_green, color_blue, val);
63 | if (buf_size[0])
64 | printf("%sHuman: %s%s\n", color_green, color_blue, buf_size);
65 |
66 | if (g_width < 64)
67 | printf("%sRadix64: %s%s\n", color_green, color_blue, l64a(val));
68 |
69 | if (val > UINT_MAX) {
70 | printf("%sIPv4: %s%s\n", color_green, color_blue, "Value too big to be a valid IPv4 address");
71 | } else {
72 | ip_addr.s_addr = val;
73 | printf("%sIPv4 (Network byte order - Big): %s %s\n", color_green, color_blue, inet_ntoa(ip_addr));
74 | ip_addr.s_addr = bswap_32(val);
75 | printf("%sIPv4 (Reversed byte order - Little): %s %s\n", color_green, color_blue, inet_ntoa(ip_addr));
76 | }
77 |
78 | printf("%sASCII: %s", color_green, color_blue);
79 | for (i = sizeof(uint64_t) - 1; i >= 0; i--) {
80 | char c = ((char *)&val)[i];
81 | if (isgraph(c))
82 | printf("%s%c", color_blue, c);
83 | else
84 | printf("%s.", color_white);
85 | }
86 |
87 | printf("\n%sBinary:\n%s", color_green, color_reset);
88 | for (i = g_width; i > 0; i--) {
89 | if ((i % 8 == 0) && (i != g_width)) {
90 | pos += sprintf(&binary[pos], "%s", color_white);
91 | binary[pos] = '|';
92 | binary[pos + 1] = ' ';
93 | pos += 2;
94 | }
95 | if (val & BIT(i - 1)) {
96 | pos += sprintf(&binary[pos], "%s", color_blue);
97 | binary[pos] = '1';
98 | }
99 | else {
100 | pos += sprintf(&binary[pos], "%s", color_magenta);
101 | binary[pos] = '0';
102 | }
103 | binary[pos + 1] = ' ';
104 | pos += 2;
105 | }
106 |
107 | binary[pos-1] = '\0';
108 | printf("%s\n ", binary);
109 | fputs(color_cyan, stdout);
110 | for (i = 0; i < g_width / 8; i++) {
111 | printf("%2d - %2d", g_width - 1 - (i * 8), (g_width - 8) - (i * 8));
112 | if (i != (g_width / 8) - 1)
113 | for (j = 0; j < 11; j++)
114 | putchar(' ');
115 | }
116 | printf("\n");
117 | puts(color_reset);
118 | return 0;
119 | }
120 |
121 | static void print_version(void)
122 | {
123 | printf(PACKAGE " " VERSION "\n");
124 | }
125 |
126 | static void print_help(FILE *out)
127 | {
128 | fprintf(out, "Usage: bitwise [OPTION...] [expression]\n\n");
129 | fprintf(out,
130 | "[expression] mathematical expression\n\n");
131 | fprintf(out,
132 | " -i, --interactive\t Load interactive mode (default if no input)\n");
133 | fprintf(out, " -w, --width[b|w|l|d]\t Set bit width (default: l)\n");
134 | fprintf(out, " -h, --help\t\t Display this help and exit\n");
135 | fprintf(out, " -v, --version\t\t Output version information and exit\n");
136 | fprintf(out, " -s, --si\t\t Print size according to SI standard. (default: IEC standard)\n");
137 | fprintf(out, " --no-color\t Start without color support\n\n");
138 | }
139 |
140 | int main(int argc, char *argv[])
141 | {
142 | int c;
143 | char width;
144 | int interactive = 0;
145 | uint64_t val = 0;
146 | int rc;
147 | bool si = false;
148 |
149 | #ifdef TRACE
150 | fd = fopen("log.txt", "w");
151 | #endif
152 |
153 | setlocale(LC_ALL, "");
154 |
155 | while (1) {
156 | static struct option long_options[] = {
157 | {"no-color", no_argument, &g_has_color, 0},
158 | {"version", no_argument, 0, 'v'},
159 | {"help", no_argument, 0, 'h'},
160 | {"interactive", no_argument, 0, 'i'},
161 | {"si", no_argument, 0, 's'},
162 | {"width", required_argument, 0, 'w'},
163 | {0, 0, 0, 0}
164 | };
165 |
166 | int option_index = 0;
167 |
168 | c = getopt_long(argc, argv, "vhisw:", long_options, &option_index);
169 | if (c == -1)
170 | break;
171 | switch (c) {
172 | case 0:
173 | break;
174 | case 'v':
175 | print_version();
176 | exit(EXIT_SUCCESS);
177 | case 'h':
178 | print_help(stdout);
179 | exit(EXIT_SUCCESS);
180 | case 'i':
181 | interactive = 1;
182 | break;
183 | case 's':
184 | si = true;
185 | break;
186 | case 'w':
187 | width = *optarg;
188 | if (!set_width(width))
189 | break;
190 | fprintf(stderr, "Unsupported width size: accepted values are: [b|w|l|d]\n");
191 | // fall through
192 | case '?':
193 | default:
194 | print_help(stderr);
195 | exit(EXIT_FAILURE);
196 | }
197 | }
198 |
199 | init_colors();
200 |
201 | if (optind < argc) { // non-interactive mode
202 | uint32_t expr_len = argc - optind; // account for ' ' between args
203 | for (int i = optind; i < argc; i++)
204 | expr_len += strlen(argv[i]);
205 |
206 | char *expression = malloc(sizeof(char) * expr_len);
207 | if (expression == NULL) {
208 | fprintf(stderr, "Error parsing arguments");
209 | exit(EXIT_FAILURE);
210 | }
211 |
212 | uint32_t expr_pos = 0;
213 | for (int i = optind; i < argc; i++) {
214 | strncpy(&expression[expr_pos], argv[i], expr_len - expr_pos);
215 | expr_pos += strlen(argv[i]);
216 | expression[expr_pos++] = ' ';
217 | }
218 | expression[expr_pos - 1] = '\0';
219 |
220 | rc = shunting_yard(expression, &val);
221 | if (rc) {
222 | fprintf(stderr, "Couldn't parse expression: %s\n", expression);
223 | print_help(stderr);
224 | exit(EXIT_FAILURE);
225 | }
226 | free(expression);
227 | if (!g_width)
228 | set_width_by_val(val);
229 | if (val > MASK(g_width))
230 | fprintf(stderr, "%sExpression overflowed!\n", color_red);
231 | val &= MASK(g_width);
232 | if (!interactive)
233 | return print_conversions(val, si);
234 | }
235 |
236 | if (!g_width)
237 | g_width = 32;
238 | start_interactive(val);
239 |
240 | #ifdef TRACE
241 | fclose(fd);
242 | #endif
243 | return 0;
244 | }
245 |
--------------------------------------------------------------------------------
/src/misc.c:
--------------------------------------------------------------------------------
1 | /* Copyright 2019
2 | * Ramon Fried
3 | */
4 |
5 | #include
6 | #include
7 | #include "bitwise.h"
8 |
9 | /* IEC Standard */
10 | #define KiB (1ULL << 10)
11 | #define MiB (1ULL << 20)
12 | #define GiB (1ULL << 30)
13 | #define TiB (1ULL << 40)
14 | #define PiB (1ULL << 50)
15 |
16 | /* SI Standard */
17 | #define kB (1000ULL)
18 | #define MB (1000 * kB)
19 | #define GB (1000 * MB)
20 | #define TB (1000 * GB)
21 | #define PB (1000 * TB)
22 |
23 | int g_has_color = 1;
24 | int g_width = 0;
25 | bool g_input_avail;
26 | int g_input;
27 |
28 | #define RED "\x1B[31m"
29 | #define GREEN "\x1B[32m"
30 | #define YEL "\x1B[33m"
31 | #define BLUE "\x1B[34m"
32 | #define MAGENTA "\x1B[35m"
33 | #define CYAN "\x1B[36m"
34 | #define WHITE "\x1B[37m"
35 | #define RESET "\x1B[0m"
36 | #define NOTHING ""
37 |
38 | char *color_green = NOTHING;
39 | char *color_red = NOTHING;
40 | char *color_blue = NOTHING;
41 | char *color_magenta = NOTHING;
42 | char *color_cyan = NOTHING;
43 | char *color_white = NOTHING;
44 | char *color_reset = NOTHING;
45 |
46 | void init_colors(void)
47 | {
48 | if (g_has_color) {
49 | color_green = GREEN;
50 | color_red = RED;
51 | color_blue = BLUE;
52 | color_magenta = MAGENTA;
53 | color_cyan = CYAN;
54 | color_white = WHITE;
55 | color_reset = RESET;
56 | } else {
57 | color_green = NOTHING;
58 | color_red = NOTHING;
59 | color_blue = NOTHING;
60 | color_magenta = NOTHING;
61 | color_cyan = NOTHING;
62 | color_white = NOTHING;
63 | color_reset = NOTHING;
64 | }
65 | }
66 |
67 | void init_terminal(void)
68 | {
69 | initscr();
70 | if (has_colors() == FALSE)
71 | g_has_color = 0;
72 | else {
73 | start_color();
74 | init_colors();
75 | }
76 | cbreak();
77 | noecho();
78 | nonl();
79 | intrflush(NULL, FALSE);
80 | keypad(stdscr, TRUE);
81 | curs_set(2);
82 | }
83 |
84 | void deinit_terminal(void)
85 | {
86 | endwin();
87 | }
88 |
89 | void die(const char *fmt, ...)
90 | {
91 | va_list args;
92 | va_start(args, fmt);
93 |
94 | deinit_terminal();
95 | /* See interactive.c for reasoning */
96 | /* deinit_readline(); */
97 | vfprintf(stderr, fmt, args);
98 | va_end(args);
99 | exit(EXIT_FAILURE);
100 | }
101 |
102 | int validate_input(int ch, int base)
103 | {
104 | switch (base) {
105 | case 2:
106 | if (ch == '0' || ch == '1')
107 | return 0;
108 | break;
109 | case 8:
110 | if (ch >= '0' && ch <= '7')
111 | return 0;
112 | break;
113 | case 16:
114 | if ((ch >= '0' && ch <= '9') ||
115 | (ch >= 'A' && ch <= 'F') ||
116 | (ch >= 'a' && ch <= 'f'))
117 | return 0;
118 | break;
119 | case 10:
120 | if (isdigit(ch))
121 | return 0;
122 | break;
123 | default:
124 | break;
125 | }
126 |
127 | return 1;
128 | }
129 |
130 | int binary_scanf(const char *buf, uint64_t *val)
131 | {
132 | uint64_t value = 0;
133 |
134 | /* Skip the leading 0 */
135 | if (buf[0] == '0') {
136 | buf++;
137 | }
138 |
139 | /* Skip the leading b */
140 | buf++;
141 |
142 | while (*buf) {
143 | switch (*buf) {
144 |
145 | case '0':
146 | value <<= 1;
147 | break;
148 | case '1':
149 | value <<= 1;
150 | value++;
151 | break;
152 | default:
153 | return 0;
154 | }
155 | buf++;
156 | }
157 |
158 | *val = value;
159 |
160 | return 1;
161 | }
162 |
163 | int base_scanf(const char *buf, int base, uint64_t *value)
164 | {
165 | int ret = 0;
166 |
167 | switch (base) {
168 | case 10:
169 | ret = sscanf(buf, "%" PRIu64, value);
170 | break;
171 | case 16:
172 | ret = sscanf(buf, "%" PRIX64, value);
173 | break;
174 | case 8:
175 | ret = sscanf(buf, "%" PRIo64, value);
176 | break;
177 | case 2:
178 | ret = binary_scanf(buf, value);
179 | break;
180 | default:
181 | fprintf(stderr, "Unknown base\n");
182 | break;
183 | }
184 |
185 | if (ret == EOF || !ret) {
186 | LOG("Couldn't parse number: %s\n", buf);
187 | return 1;
188 | }
189 |
190 | return 0;
191 | }
192 |
193 | int ip_scanf(const char *input, uint64_t *val)
194 | {
195 | union {
196 | uint8_t ip[4];
197 | uint32_t ip32;
198 | } ip;
199 | if (sscanf(input, "%hhu.%hhu.%hhu.%hhu",
200 | &ip.ip[0], &ip.ip[1], &ip.ip[2], &ip.ip[3]) != 4) {
201 | fprintf(stderr, "Failed parsing IPv4 address\n");
202 | return 1;
203 | }
204 |
205 | *val = ip.ip32;
206 | return 0;
207 | }
208 |
209 | int parse_input(const char *input, uint64_t *val)
210 | {
211 | int base;
212 |
213 | if (strchr(input, '.'))
214 | return ip_scanf(input, val);
215 | if (tolower(input[0]) == 'b')
216 | base = 2;
217 | else if (input[0] == '0')
218 | if (tolower(input[1]) == 'b')
219 | base = 2;
220 | else if (input[1] == 'x' || input[1] == 'X')
221 | base = 16;
222 | else
223 | base = 8;
224 | else
225 | base = 10;
226 |
227 | return base_scanf(input, base, val);
228 | }
229 |
230 | int lltostr(uint64_t val, char *buf, int base)
231 | {
232 | int rc;
233 |
234 | switch (base) {
235 | case 10:
236 | rc = sprintf(buf, "%" PRIu64, val);
237 | break;
238 | case 16:
239 | rc = sprintf(buf, "%" PRIx64, val);
240 | break;
241 | case 8:
242 | rc = sprintf(buf, "%" PRIo64, val);
243 | break;
244 | case 2:
245 | default:
246 | sprintf(buf, "Not implemeted");
247 | return -1;
248 | }
249 |
250 | if (rc < 0)
251 | LOG("sprintf failed with error: %d\n", rc);
252 |
253 | return rc;
254 | }
255 |
256 | int sprintf_type(uint64_t val, char *buf, output_type type)
257 | {
258 | int i;
259 | int pos = 0;
260 |
261 | switch (type) {
262 | case CMD_OUTPUT_DECIMAL:
263 | sprintf(buf, "Decimal: %" PRIu64, val);
264 | break;
265 | case CMD_OUTPUT_HEXADECIMAL:
266 | sprintf(buf, "Hexadecimal: 0x%" PRIx64, val);
267 | break;
268 | case CMD_OUTPUT_OCTAL:
269 | sprintf(buf, "Octal: 0%" PRIo64, val);
270 | break;
271 | case CMD_OUTPUT_BINARY:
272 | pos = sprintf(buf, "Binary: ");
273 | for (i = g_width; i > 0; i--) {
274 | if ((i % 8 == 0) && (i != g_width)) {
275 | buf[pos] = '|';
276 | buf[pos + 1] = ' ';
277 | pos += 2;
278 | }
279 | if (val & BIT(i - 1)) {
280 | buf[pos] = '1';
281 | }
282 | else {
283 | buf[pos] = '0';
284 | }
285 | buf[pos + 1] = ' ';
286 | pos += 2;
287 | }
288 | buf[pos-1] = '\0';
289 | break;
290 |
291 | default:
292 | break;
293 | }
294 |
295 | return 0;
296 | }
297 |
298 | int sprintf_size(uint64_t val, char *buf, bool si)
299 | {
300 | int ret;
301 | double f_val = val;
302 |
303 | if (si) {
304 | if (val >= PB)
305 | ret = sprintf(buf, "%.2lf PB", f_val / PB);
306 | else if (val >= TB)
307 | ret = sprintf(buf, "%.2lf TB", f_val / TB);
308 | else if (val >= GB)
309 | ret = sprintf(buf, "%.2lf GB", f_val / GB);
310 | else if (val >= MB)
311 | ret = sprintf(buf, "%.2lf MB", f_val / MB);
312 | else if (val >= kB)
313 | ret = sprintf(buf, "%.2lf Kb", f_val / kB);
314 | else
315 | ret = sprintf(buf, "%" PRIu64, val);
316 | } else {
317 | if (val >= PiB)
318 | ret = sprintf(buf, "%.2lf PiB", f_val / PiB);
319 | else if (val >= TiB)
320 | ret = sprintf(buf, "%.2lf TiB", f_val / TiB);
321 | else if (val >= GiB)
322 | ret = sprintf(buf, "%.2lf GiB", f_val / GiB);
323 | else if (val >= MiB)
324 | ret = sprintf(buf, "%.2lf MiB", f_val / MiB);
325 | else if (val >= KiB)
326 | ret = sprintf(buf, "%.2lf KiB", f_val / KiB);
327 | else
328 | ret = sprintf(buf, "%" PRIu64, val);
329 | }
330 |
331 | return ret;
332 | }
333 |
334 | void set_width_by_val(uint64_t val)
335 | {
336 | if (val & 0xFFFFFFFF00000000)
337 | g_width = 64;
338 | else if (val & 0xFFFF0000)
339 | g_width = 32;
340 | else if (val & 0xFF00)
341 | g_width = 16;
342 | else if (val & 0xFF)
343 | g_width = 8;
344 | else
345 | g_width = 32;
346 | }
347 |
348 | int set_width(char width)
349 | {
350 | if (tolower(width) == 'b')
351 | g_width = 8;
352 | else if (tolower(width) == 'w')
353 | g_width = 16;
354 | else if (tolower(width) == 'l')
355 | g_width = 32;
356 | else if (tolower(width) == 'd')
357 | g_width = 64;
358 | else
359 | return 1;
360 |
361 | return 0;
362 | }
363 |
--------------------------------------------------------------------------------
/src/shunting-yard.c:
--------------------------------------------------------------------------------
1 | // Copyright 2011 - 2014 Brian Marshall. All rights reserved.
2 | //
3 | // Use of this source code is governed by the BSD 2-Clause License that can be
4 | // found in the LICENSE file.
5 |
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include "bitwise.h"
13 | #include "shunting-yard.h"
14 | #include "stack.h"
15 |
16 | typedef enum {
17 | TOKEN_NONE,
18 | TOKEN_UNKNOWN,
19 | TOKEN_OPEN_PARENTHESIS,
20 | TOKEN_CLOSE_PARENTHESIS,
21 | TOKEN_OPERATOR,
22 | TOKEN_NUMBER,
23 | TOKEN_IDENTIFIER
24 | } TokenType;
25 |
26 | typedef struct {
27 | TokenType type;
28 | char *value;
29 | } Token;
30 |
31 | typedef enum {
32 | OPERATOR_OTHER,
33 | OPERATOR_UNARY,
34 | OPERATOR_BINARY
35 | } OperatorArity;
36 |
37 | typedef enum {
38 | OPERATOR_NONE,
39 | OPERATOR_LEFT,
40 | OPERATOR_RIGHT
41 | } OperatorAssociativity;
42 |
43 | typedef struct {
44 | char *symbol;
45 | int op_len;
46 | int precedence;
47 | OperatorArity arity;
48 | OperatorAssociativity associativity;
49 | } Operator;
50 |
51 | static const Token NO_TOKEN = {TOKEN_NONE, NULL};
52 |
53 | static const Operator OPERATORS[] = {
54 | {"!", 1, 1, OPERATOR_UNARY, OPERATOR_RIGHT},
55 | {"~", 1, 1, OPERATOR_UNARY, OPERATOR_RIGHT},
56 | {"*", 1, 2, OPERATOR_BINARY, OPERATOR_LEFT},
57 | {"/", 1, 2, OPERATOR_BINARY, OPERATOR_LEFT},
58 | {"%", 1, 2, OPERATOR_BINARY, OPERATOR_LEFT},
59 | {"+", 1, 3, OPERATOR_BINARY, OPERATOR_LEFT},
60 | {"-", 1, 3, OPERATOR_BINARY, OPERATOR_LEFT},
61 | {">>", 2, 4, OPERATOR_BINARY, OPERATOR_LEFT},
62 | {"<<", 2, 4, OPERATOR_BINARY, OPERATOR_LEFT},
63 | {"&", 1, 5, OPERATOR_BINARY, OPERATOR_LEFT},
64 | {"^", 1, 5, OPERATOR_BINARY, OPERATOR_LEFT},
65 | {"|", 1, 6, OPERATOR_BINARY, OPERATOR_LEFT},
66 | {"(", 1, 7, OPERATOR_OTHER, OPERATOR_NONE}
67 | };
68 |
69 | // Returns an array of tokens extracted from the expression. The array is
70 | // terminated by a token with type `TOKEN_NONE`.
71 | static Token *tokenize(const char *expression);
72 |
73 | // Parses a tokenized expression.
74 | static Status parse(const Token *tokens, Stack **operands, Stack **operators,
75 | Stack **functions);
76 |
77 | // Pushes an operator to the stack after applying operators with a higher
78 | // precedence.
79 | static Status push_operator(const Operator *operator, Stack **operands,
80 | Stack **operators);
81 |
82 | // Pushes the multiplication operator to the stack.
83 | static Status push_multiplication(Stack **operands, Stack **operators);
84 |
85 | // Allocates memory for a double and pushes it to the stack.
86 | static void push_num(uint64_t x, Stack **operands);
87 |
88 | // Pops a double from the stack, frees its memory and returns its value.
89 | static uint64_t pop_num(Stack **operands);
90 |
91 | // Converts a string into a number and pushes it to the stack.
92 | static Status push_number(const char *value, Stack **operands);
93 |
94 | // Converts a constant identifier into its value and pushes it to the stack.
95 | static Status push_constant(const char *value, Stack **operands);
96 |
97 | // Applies an operator to the top one or two operands, depending on if the
98 | // operator is unary or binary.
99 | static Status apply_operator(const Operator *operator, Stack **operands);
100 |
101 | // Applies a unary operator to the top operand.
102 | static Status apply_unary_operator(const Operator *operator, Stack **operands);
103 |
104 | // Applies a function to the top operand.
105 | static Status apply_function(const char *function, Stack **operands);
106 |
107 | // Returns the arity of an operator, using the previous token for context.
108 | static OperatorArity get_arity(char *symbol, const Token *previous);
109 |
110 | // Returns a matching operator.
111 | static const Operator *get_operator(char *symbol, OperatorArity arity);
112 |
113 | Status shunting_yard(const char *expression, uint64_t *result)
114 | {
115 | Token *tokens = tokenize(expression);
116 | Stack *operands = NULL, *operators = NULL, *functions = NULL;
117 | Status status = parse(tokens, &operands, &operators, &functions);
118 | if (operands)
119 | *result = pop_num(&operands);
120 | else if (status == STATUS_OK)
121 | status = ERROR_NO_INPUT;
122 |
123 | for (Token *token = tokens; token->type != TOKEN_NONE; token++)
124 | free(token->value);
125 | free(tokens);
126 | while (operands)
127 | pop_num(&operands);
128 | while (operators)
129 | stack_pop(&operators);
130 | while (functions)
131 | stack_pop(&functions);
132 | return status;
133 | }
134 |
135 | #define MAX_TOKEN_SIZE 64
136 |
137 | Token *tokenize(const char *expression)
138 | {
139 | int length = 0;
140 | Token *tokens = malloc(sizeof * tokens);
141 | const char *c = expression;
142 | while (*c) {
143 | char cur_token[MAX_TOKEN_SIZE];
144 | Token token = {TOKEN_UNKNOWN, NULL};
145 |
146 | if (*c == '(')
147 | token.type = TOKEN_OPEN_PARENTHESIS;
148 | else if (*c == ')')
149 | token.type = TOKEN_CLOSE_PARENTHESIS;
150 | else if (!strncmp("<<", c, 2) || !strncmp(">>", c, 2)) {
151 | token.type = TOKEN_OPERATOR;
152 | token.value = strndup(c, 2);
153 | } else if (strchr("~!^*/%+-|&", *c)) {
154 | token.type = TOKEN_OPERATOR;
155 | token.value = strndup(c, 1);
156 | } else if (!strncmp("bit", c, 3) || !strncmp("BIT", c, 3)) {
157 | token.value = strndup(c, 3);
158 | token.type = TOKEN_IDENTIFIER;
159 | } else if (sscanf(c, "%[xX0-9a-fA-F.]", cur_token)) {
160 | token.type = TOKEN_NUMBER;
161 | token.value = strdup(cur_token);
162 | } else if (sscanf(c, "%[A-Za-z$]", cur_token)) {
163 | token.type = TOKEN_IDENTIFIER;
164 | token.value = strdup(cur_token);
165 | }
166 |
167 | if (!isspace(*c)) {
168 | tokens = realloc(tokens, sizeof * tokens *
169 | (++length + 1));
170 | tokens[length - 1] = token;
171 | }
172 | c += token.value ? strlen(token.value) : 1;
173 | }
174 | tokens[length] = NO_TOKEN;
175 |
176 | return tokens;
177 | }
178 |
179 | Status parse(const Token *tokens, Stack **operands, Stack **operators,
180 | Stack **functions)
181 | {
182 | Status status = STATUS_OK;
183 |
184 | for (const Token *token = tokens, *previous = &NO_TOKEN, *next = token + 1;
185 | token->type != TOKEN_NONE; previous = token, token = next++) {
186 | switch (token->type) {
187 | case TOKEN_OPEN_PARENTHESIS:
188 | // Implicit multiplication: "(2)(2)".
189 | if (previous->type == TOKEN_CLOSE_PARENTHESIS)
190 | status = push_multiplication(operands, operators);
191 |
192 | stack_push(operators, get_operator("(", OPERATOR_OTHER));
193 | break;
194 |
195 | case TOKEN_CLOSE_PARENTHESIS: {
196 | // Apply operators until the previous open parenthesis is found.
197 | bool found_parenthesis = false;
198 | while (*operators && status == STATUS_OK && !found_parenthesis) {
199 | const Operator *operator = stack_pop(operators);
200 | if (!strncmp(operator->symbol, "(", 1))
201 | found_parenthesis = true;
202 | else
203 | status = apply_operator(operator, operands);
204 | }
205 | if (!found_parenthesis)
206 | status = ERROR_CLOSE_PARENTHESIS;
207 | else if (*functions)
208 | status = apply_function(stack_pop(functions), operands);
209 | break;
210 | }
211 |
212 | case TOKEN_OPERATOR:
213 | status = push_operator(
214 | get_operator(token->value,
215 | get_arity(token->value, previous)),
216 | operands, operators);
217 | break;
218 |
219 | case TOKEN_NUMBER:
220 | if (previous->type == TOKEN_CLOSE_PARENTHESIS ||
221 | previous->type == TOKEN_NUMBER ||
222 | previous->type == TOKEN_IDENTIFIER)
223 | status = ERROR_SYNTAX;
224 | else {
225 | status = push_number(token->value, operands);
226 |
227 | // Implicit multiplication: "2(2)" or "2a".
228 | if (next->type == TOKEN_OPEN_PARENTHESIS ||
229 | next->type == TOKEN_IDENTIFIER)
230 | status = push_multiplication(operands, operators);
231 | }
232 | break;
233 |
234 | case TOKEN_IDENTIFIER:
235 | // The identifier could be either a constant or function.
236 | status = push_constant(token->value, operands);
237 | if ((status == ERROR_UNDEFINED_CONSTANT) &&
238 | (next->type == TOKEN_OPEN_PARENTHESIS)) {
239 | stack_push(functions, token->value);
240 | status = STATUS_OK;
241 | } else if (next->type == TOKEN_OPEN_PARENTHESIS ||
242 | next->type == TOKEN_IDENTIFIER) {
243 | // Implicit multiplication: "a(2)" or "a b".
244 | status = push_multiplication(operands, operators);
245 | }
246 | break;
247 |
248 | default:
249 | status = ERROR_UNRECOGNIZED;
250 | }
251 | if (status != STATUS_OK)
252 | return status;
253 | }
254 |
255 | // Apply all remaining operators.
256 | while (*operators && status == STATUS_OK) {
257 | const Operator *operator = stack_pop(operators);
258 | if (!strncmp(operator->symbol, "(", 1))
259 | status = ERROR_OPEN_PARENTHESIS;
260 | else
261 | status = apply_operator(operator, operands);
262 | }
263 | return status;
264 | }
265 |
266 | Status push_operator(const Operator *operator, Stack **operands,
267 | Stack **operators)
268 | {
269 | if (!operator)
270 | return ERROR_SYNTAX;
271 |
272 | Status status = STATUS_OK;
273 | while (*operators && status == STATUS_OK) {
274 | const Operator *stack_operator = stack_top(*operators);
275 | if (operator->arity == OPERATOR_UNARY ||
276 | operator->precedence < stack_operator->precedence ||
277 | (operator->associativity == OPERATOR_RIGHT &&
278 | operator->precedence == stack_operator->precedence))
279 | break;
280 |
281 | status = apply_operator(stack_pop(operators), operands);
282 | }
283 | stack_push(operators, operator);
284 | return status;
285 | }
286 |
287 | Status push_multiplication(Stack **operands, Stack **operators)
288 | {
289 | return push_operator(get_operator("*", OPERATOR_BINARY), operands,
290 | operators);
291 | }
292 |
293 | void push_num(uint64_t x, Stack **operands)
294 | {
295 | uint64_t *pointer = malloc(sizeof * pointer);
296 | *pointer = x;
297 | stack_push(operands, pointer);
298 | }
299 |
300 | uint64_t pop_num(Stack **operands)
301 | {
302 | const uint64_t *pointer = stack_pop(operands);
303 | uint64_t x = *pointer;
304 | free((void *)pointer);
305 | return x;
306 | }
307 |
308 | Status push_number(const char *value, Stack **operands)
309 | {
310 | uint64_t x;
311 |
312 | if (parse_input(value, &x))
313 | return ERROR_SYNTAX;
314 |
315 | push_num(x, operands);
316 | return STATUS_OK;
317 | }
318 |
319 | Status push_constant(const char *value, Stack **operands)
320 | {
321 | uint64_t x;
322 |
323 | if (strncmp(value, "$", 1) == 0)
324 | x = g_val;
325 | else
326 | return ERROR_UNDEFINED_CONSTANT;
327 |
328 | push_num(x, operands);
329 | return STATUS_OK;
330 | }
331 |
332 | Status apply_operator(const Operator *operator, Stack **operands)
333 | {
334 | if (!operator || !*operands)
335 | return ERROR_SYNTAX;
336 | if (operator->arity == OPERATOR_UNARY)
337 | return apply_unary_operator(operator, operands);
338 |
339 | uint64_t y = pop_num(operands);
340 | if (!*operands)
341 | return ERROR_SYNTAX;
342 | uint64_t x = pop_num(operands);
343 | Status status = STATUS_OK;
344 | switch (*operator->symbol) {
345 | case '*':
346 | x = x * y;
347 | break;
348 | case '/':
349 | if (y == 0)
350 | return ERROR_DIVIDE_BY_ZERO;
351 | x = x / y;
352 | break;
353 | case '%':
354 | x = x % y;
355 | break;
356 | case '+':
357 | x = x + y;
358 | break;
359 | case '-':
360 | x = x - y;
361 | break;
362 | case '>':
363 | x = x >> y;
364 | break;
365 | case '<':
366 | x = x << y;
367 | break;
368 | case '|':
369 | x = x | y;
370 | break;
371 | case '&':
372 | x = x & y;
373 | break;
374 | case '^':
375 | x = x ^ y;
376 | break;
377 | default:
378 | return ERROR_UNRECOGNIZED;
379 | }
380 | push_num(x, operands);
381 | return status;
382 | }
383 |
384 | Status apply_unary_operator(const Operator *operator, Stack **operands)
385 | {
386 | uint64_t x = pop_num(operands);
387 | switch (*operator->symbol) {
388 | case '+':
389 | break;
390 | case '-':
391 | x = -x;
392 | break;
393 | case '~':
394 | x = ~x;
395 | break;
396 | case '!':
397 | x = !x;
398 | break;
399 | default:
400 | return ERROR_UNRECOGNIZED;
401 | }
402 | push_num(x, operands);
403 | return STATUS_OK;
404 | }
405 |
406 | Status apply_function(const char *function, Stack **operands)
407 | {
408 | if (!*operands)
409 | return ERROR_FUNCTION_ARGUMENTS;
410 |
411 | uint64_t x = pop_num(operands);
412 |
413 | if (strcasecmp(function, "bit") == 0)
414 | x = BIT(x);
415 | else
416 | return ERROR_UNDEFINED_FUNCTION;
417 |
418 | push_num(x, operands);
419 | return STATUS_OK;
420 | }
421 |
422 | OperatorArity get_arity(char *symbol, const Token *previous)
423 | {
424 | if (*symbol == '!' || previous->type == TOKEN_NONE ||
425 | previous->type == TOKEN_OPEN_PARENTHESIS ||
426 | (previous->type == TOKEN_OPERATOR && *previous->value != '!'))
427 | return OPERATOR_UNARY;
428 | return OPERATOR_BINARY;
429 | }
430 |
431 | const Operator *get_operator(char *symbol, OperatorArity arity)
432 | {
433 | for (size_t i = 0; i < sizeof OPERATORS / sizeof OPERATORS[0]; i++) {
434 | if (!strncmp(OPERATORS[i].symbol, symbol, OPERATORS[i].op_len) &&
435 | OPERATORS[i].arity == arity)
436 | return &OPERATORS[i];
437 | }
438 |
439 | LOG("couldn't find %s operator\n", symbol);
440 | return NULL;
441 | }
442 |
--------------------------------------------------------------------------------
/src/stack.c:
--------------------------------------------------------------------------------
1 | // Copyright 2011 - 2014 Brian Marshall. All rights reserved.
2 | //
3 | // Use of this source code is governed by the BSD 2-Clause License that can be
4 | // found in the LICENSE file.
5 |
6 | #include "stack.h"
7 |
8 | #include
9 |
10 | struct Stack {
11 | const void *value;
12 | Stack *next;
13 | };
14 |
15 | void stack_push(Stack **stack, const void *value)
16 | {
17 | Stack *item = malloc(sizeof * item);
18 | item->value = value;
19 | item->next = *stack;
20 | *stack = item;
21 | }
22 |
23 | const void *stack_pop(Stack **stack)
24 | {
25 | Stack *item = *stack;
26 | const void *value = item->value;
27 | *stack = item->next;
28 | free(item);
29 | return value;
30 | }
31 |
32 | const void *stack_top(const Stack *stack)
33 | {
34 | return stack->value;
35 | }
36 |
--------------------------------------------------------------------------------
/tests/test-shunting-yard.c:
--------------------------------------------------------------------------------
1 | // Copyright 2012 - 2014 Brian Marshall. All rights reserved.
2 | //
3 | // Use of this source code is governed by the BSD 2-Clause License that can be
4 | // found in the LICENSE file.
5 | //
6 | // Based on CUnit example code: .
7 |
8 | #include "../inc/shunting-yard.h"
9 |
10 | #include
11 | #include
12 |
13 | #define ASSERT_RESULT(expression, expected) \
14 | ASSERT_STATUS(expression, STATUS_OK); \
15 | CU_ASSERT_EQUAL(result, expected)
16 |
17 | #define ASSERT_STATUS(expression, expected) \
18 | CU_ASSERT(shunting_yard(expression, &result) == expected)
19 |
20 | static uint64_t result = 0;
21 | uint64_t g_val = 0x512;
22 |
23 | static void test_addition()
24 | {
25 | ASSERT_RESULT("2+2", 4);
26 | ASSERT_RESULT("0x2+0x2", 0x4);
27 | ASSERT_RESULT("0x2 + 0x2", 0x4);
28 | ASSERT_RESULT("0x2 + b101", 7);
29 | ASSERT_RESULT("0x2 + 0b101", 7);
30 | ASSERT_RESULT("0b101 + 0x2", 7);
31 | ASSERT_RESULT("2 + 2", 4);
32 | ASSERT_RESULT("3 + (5 + 1 + (2 + 2))", 13);
33 | ASSERT_RESULT("1+2+4+8+16 + 11", 42);
34 |
35 | }
36 |
37 | static void test_shifts()
38 | {
39 | ASSERT_RESULT("1<<0", 1);
40 | ASSERT_RESULT("1 << 2", 4);
41 | ASSERT_RESULT("2 >> 1", 1);
42 | ASSERT_RESULT("0x2 >> 1", 1);
43 | }
44 |
45 | static void test_subtraction()
46 | {
47 | ASSERT_RESULT("8-4", 4);
48 | ASSERT_RESULT("15-10", 5);
49 | ASSERT_RESULT("27 - (10 - 11)", 28);
50 | }
51 |
52 | static void test_multiplication()
53 | {
54 | ASSERT_RESULT("13 * 2", 26);
55 | ASSERT_RESULT("2(3)", 6);
56 | ASSERT_RESULT("(2)(3)", 6);
57 | ASSERT_RESULT("0x2(0x3)", 6);
58 | }
59 |
60 | static void test_division()
61 | {
62 | ASSERT_RESULT("2987898/34743", 86);
63 | }
64 |
65 | static void test_modulus()
66 | {
67 | ASSERT_RESULT("10 % 6", 4);
68 | ASSERT_RESULT("2+3 % 3", 2);
69 | ASSERT_RESULT("6*5%21", 9);
70 | ASSERT_RESULT("10%11", 10);
71 | ASSERT_RESULT("5 %5", 0);
72 | }
73 |
74 |
75 | static void test_functions()
76 | {
77 | ASSERT_RESULT("BIT(3)", 8);
78 |
79 | }
80 |
81 | static void test_constants()
82 | {
83 | ASSERT_RESULT("$+0x30", 0x542);
84 | }
85 |
86 | static void test_precedence()
87 | {
88 | ASSERT_RESULT("6/3*5", 10);
89 | ASSERT_RESULT("6+3*2", 12);
90 | ASSERT_RESULT("2+6/2*5+10/3-2/6", 20);
91 | }
92 |
93 | static void test_errors()
94 | {
95 | ASSERT_STATUS("2+*2", ERROR_SYNTAX);
96 | ASSERT_STATUS("2**2", ERROR_SYNTAX);
97 | ASSERT_STATUS("*1", ERROR_SYNTAX);
98 | ASSERT_STATUS("2*.", ERROR_SYNTAX);
99 | ASSERT_STATUS("2*2 3", ERROR_SYNTAX);
100 | ASSERT_STATUS("(2+2", ERROR_OPEN_PARENTHESIS);
101 | ASSERT_STATUS("(2+2)+(2+2", ERROR_OPEN_PARENTHESIS);
102 | ASSERT_STATUS("(2+2))", ERROR_CLOSE_PARENTHESIS);
103 | ASSERT_STATUS("", ERROR_NO_INPUT);
104 | ASSERT_STATUS(" ", ERROR_NO_INPUT);
105 | ASSERT_STATUS("foo(2)", ERROR_UNDEFINED_FUNCTION);
106 | // ASSERT_STATUS("bit(foo)", ERROR_FUNCTION_ARGUMENTS);
107 | // ASSERT_STATUS("foo", ERROR_UNDEFINED_CONSTANT);
108 |
109 | }
110 |
111 | int main()
112 | {
113 | if (CU_initialize_registry() != CUE_SUCCESS)
114 | return CU_get_error();
115 |
116 | unsigned int tests_failed = 0;
117 | CU_pSuite suite = CU_add_suite("Shunting Yard", NULL, NULL);
118 | if (!suite)
119 | goto exit;
120 |
121 | if (!CU_add_test(suite, "addition", test_addition) ||
122 | !CU_add_test(suite, "shifts", test_shifts) ||
123 | !CU_add_test(suite, "subtraction", test_subtraction) ||
124 | !CU_add_test(suite, "multiplication", test_multiplication) ||
125 | !CU_add_test(suite, "division", test_division) ||
126 | !CU_add_test(suite, "modulus", test_modulus) ||
127 | !CU_add_test(suite, "functions", test_functions) ||
128 | !CU_add_test(suite, "constants", test_constants) ||
129 | !CU_add_test(suite, "operator precedence", test_precedence) ||
130 | !CU_add_test(suite, "error handling", test_errors))
131 | goto exit;
132 |
133 | CU_basic_set_mode(CU_BRM_NORMAL);
134 | CU_basic_run_tests();
135 | tests_failed = CU_get_number_of_tests_failed();
136 | exit:
137 | CU_cleanup_registry();
138 | return tests_failed ? EXIT_FAILURE : CU_get_error();
139 | }
140 |
--------------------------------------------------------------------------------
/ubuntu_release.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e
4 |
5 | releases="xenial disco cosmic bionic trusty" # List of releases to generate
6 |
7 | if [ ! -f "bitwise-v$1.tar.gz" ]; then
8 | wget https://github.com/mellowcandle/bitwise/releases/download/v$1/bitwise-v$1.tar.gz
9 | fi
10 |
11 | for release in $releases; do
12 | echo "Creating release for $release"
13 | mkdir -p $release
14 | cd $release
15 | rm -rf bitwise-v$1
16 | tar xf ../bitwise-v$1.tar.gz
17 | cd bitwise-v$1
18 | cp -r ../../debian .
19 | dch -D $release -v $1-1ubuntu+$release v$1
20 | dpkg-buildpackage -S
21 | cd ..
22 | dput ppa bitwise_$1-1ubuntu+${release}_source.changes
23 | cd ../
24 | done
25 |
26 |
27 |
--------------------------------------------------------------------------------