Added pdc: the programmers desktop calculator,
imported from https://github.com/daniel-thompson/pdc repository.
This commit is contained in:
@@ -499,6 +499,7 @@ file /bin/od
|
||||
file /bin/pagesize
|
||||
file /bin/passwd
|
||||
mode 04755
|
||||
file /bin/pdc
|
||||
file /bin/picoc
|
||||
file /bin/portio
|
||||
file /bin/pr
|
||||
|
||||
343
src/cmd/pdc/COPYING
Normal file
343
src/cmd/pdc/COPYING
Normal file
@@ -0,0 +1,343 @@
|
||||
Unless otherwise stated inside the file, all files
|
||||
in this package are covered by the following license:
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
29
src/cmd/pdc/Makefile
Normal file
29
src/cmd/pdc/Makefile
Normal file
@@ -0,0 +1,29 @@
|
||||
TOPSRC = $(shell cd ../../..; pwd)
|
||||
include $(TOPSRC)/target.mk
|
||||
#include $(TOPSRC)/cross.mk
|
||||
#CFLAGS = -DCROSS
|
||||
|
||||
OBJS = pdc.o
|
||||
|
||||
LDFLAGS += -g
|
||||
|
||||
CFLAGS += -Werror -Wall -Os
|
||||
CFLAGS += -DGCC_COMPAT -DHAVE_CPP_VARARG_MACRO_GCC
|
||||
|
||||
all: pdc
|
||||
|
||||
pdc: $(OBJS)
|
||||
${CC} ${LDFLAGS} -o pdc.elf $(OBJS) ${LIBS}
|
||||
${OBJDUMP} -S pdc.elf > pdc.dis
|
||||
${SIZE} pdc.elf
|
||||
${ELF2AOUT} pdc.elf $@ && rm pdc.elf
|
||||
|
||||
clean:
|
||||
rm -f *.o *.0 *.elf pdc *.dis tags *~ y.tab.[ch]
|
||||
|
||||
install: all
|
||||
install pdc $(DESTDIR)/bin/
|
||||
|
||||
pdc.o: pdc.y
|
||||
$(YACC) -d $(YFLAGS) pdc.y
|
||||
$(CC) $(DEFS) $(CPPFLAGS) $(CFLAGS) -c -o pdc.o y.tab.c
|
||||
64
src/cmd/pdc/Makefile-unix
Normal file
64
src/cmd/pdc/Makefile-unix
Normal file
@@ -0,0 +1,64 @@
|
||||
#
|
||||
# Makefile
|
||||
#
|
||||
# The programmers desktop calculator. A desktop calculator supporting both
|
||||
# shifts and mixed base inputs.
|
||||
#
|
||||
# Copyright (C) 2001, 2002, 2003, 2004, 2005
|
||||
# Daniel Thompson <see help function for e-mail>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
|
||||
TARGET = pdc
|
||||
|
||||
CC = $(COMPILER_PREFIX)gcc
|
||||
CFLAGS += -O2 -g
|
||||
|
||||
STRIP = $(COMPILER_PREFIX)strip
|
||||
|
||||
|
||||
ifndef WITHOUT_GCC
|
||||
CFLAGS += -Wall
|
||||
endif
|
||||
|
||||
ifdef WITH_CMDEDIT
|
||||
CFLAGS += -DHAVE_CMDEDIT
|
||||
else
|
||||
|
||||
# This assumes a dynamic link to libreadline.dll in .../bin. Defining
|
||||
# WITHOUT_READLINE should have the normal effect. The .../lib part is just in
|
||||
# case people do strange things to their layouts.
|
||||
ifdef WIN32_HOME
|
||||
CFLAGS += -I$(WIN32_HOME)/include -L$(WIN32_HOME)/lib -L$(WIN32_HOME)/bin
|
||||
WITHOUT_NCURSES = 1
|
||||
TARGET := $(TARGET).exe
|
||||
endif
|
||||
|
||||
ifndef WITHOUT_READLINE
|
||||
LDFLAGS += -lreadline
|
||||
CFLAGS += -DHAVE_READLINE
|
||||
endif
|
||||
ifndef WITHOUT_NCURSES
|
||||
LDFLAGS += -lncurses
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
strip : $(TARGET)
|
||||
$(STRIP) $(TARGET)
|
||||
|
||||
$(TARGET) : y.tab.o
|
||||
$(CC) $(CFLAGS) -o $@ y.tab.o $(LDFLAGS)
|
||||
|
||||
y.tab.c : pdc.y
|
||||
$(YACC) pdc.y
|
||||
|
||||
clean :
|
||||
$(RM) $(TARGET) y.tab.c *.o
|
||||
|
||||
74
src/cmd/pdc/README
Normal file
74
src/cmd/pdc/README
Normal file
@@ -0,0 +1,74 @@
|
||||
PDC - the programmers desktop calculator
|
||||
========================================
|
||||
|
||||
PDC is a desktop calculator similar to bc but with features designed
|
||||
for use by programmers. In particular PDC supports most ANSI C
|
||||
operators including bitwise operators and shifts. PDC also makes
|
||||
dealing with mixed bases very easy since it supports contant pefixes
|
||||
(eg 0xff, 0755).
|
||||
|
||||
PDC is licenced under the GNU General Public Licence. The latest
|
||||
version of PDC can be downloaded from http://www.redfelineninja.org.uk.
|
||||
Jason Hood has ported PDC to DOS/Win32 (in five different ways). These
|
||||
ports can be found at http://pdc.adoxa.cjb.net.
|
||||
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* mathematic operators +, -, *, /, %
|
||||
* logic operators &&, ||, !
|
||||
* bitwise operators &, |, ^, ~, <<, >>
|
||||
* uses ANSI C operator precedence
|
||||
* prefix numbers with 0b, 0, 0d and 0x to support binary, octal,
|
||||
decimal and hex regardless of input base
|
||||
* output numbers in any number base of 16 or less
|
||||
* functions to assist with 'bit bashing'
|
||||
* command line expression evaluation
|
||||
|
||||
|
||||
Building PDC
|
||||
------------
|
||||
|
||||
PDC is supplied with a simple makefile. It should build with no
|
||||
modifications on most Unix-like operating systems. However, you may need
|
||||
to change the compilation flags (for example, to remove -Wall) if
|
||||
you are not using gcc.
|
||||
|
||||
PDC is tested most often on Solaris and GNU/Linux. It's written in YACC and C.
|
||||
|
||||
PDC can also be built for Windows. The supplied Makefile has been written with
|
||||
MinGW in mind, but other compilers may also work with some minor changes. To
|
||||
build for Win32 using MinGW, the variable COMPILER_PREFIX must be defined to
|
||||
the toolchain prefix - for example, "i586-mingw32msvc-". If building under
|
||||
Win32, the variable WIN32_HOME should be used to point to where the required
|
||||
include files and libraries may be found.
|
||||
|
||||
By default PDC is built against the GNU readline library. If your system
|
||||
does not have the library installed, set WITHOUT_READLINE on the make
|
||||
command line (make WITHOUT_READLINE=1). You'll know if you don't have the
|
||||
library due to all the errors. :-) A Win32 port of GNU readline can be
|
||||
found at http://mingwrep.sf.net .
|
||||
|
||||
DJGPP users will not have GNU readline but who have CmdEdit installed
|
||||
can use that instead by setting HAVE_CMDEDIT.
|
||||
|
||||
|
||||
Build examples
|
||||
--------------
|
||||
|
||||
GNU/Linux:
|
||||
make
|
||||
|
||||
Solaris (generally Solaris does not have readline installed):
|
||||
make WITHOUT_READLINE=1
|
||||
|
||||
MinGW/Win32 (assumes toolset headers in $HOME/win32/include and
|
||||
readline.dll in $HOME/win32/bin ):
|
||||
make WIN32_HOME=$HOME/win32 COMPILER_PREFIX=i586-mingw32msvc-
|
||||
|
||||
Bugs and Feature Requests
|
||||
--------------------------
|
||||
|
||||
Reproducable bugs and feature requests should be sent to
|
||||
bugs-pdc@redfelineninja.org.uk.
|
||||
918
src/cmd/pdc/pdc.y
Normal file
918
src/cmd/pdc/pdc.y
Normal file
@@ -0,0 +1,918 @@
|
||||
/*
|
||||
* pdc.y
|
||||
*
|
||||
* The programmers desktop calculator. A desktop calculator supporting both
|
||||
* shifts and mixed base inputs.
|
||||
*
|
||||
* Copyright (C) 2001-2005, 2013
|
||||
* Daniel Thompson <see help function for e-mail>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
%{
|
||||
/* Includes ---------------------------------------------------------------- */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#if defined(HAVE_READLINE)
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#endif
|
||||
|
||||
#if defined(__DJGPP__)
|
||||
#include <crt0.h>
|
||||
char** __crt0_glob_function(char *d) { return 0; }
|
||||
#if !defined(HAVE_READLINE)
|
||||
void __crt0_load_environment_file(char *d) { }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
int _CRT_glob = 0;
|
||||
#endif
|
||||
|
||||
/* Types ----------------------------------------------------------- */
|
||||
|
||||
typedef struct symbol {
|
||||
const char *name;
|
||||
const char *description;
|
||||
int type;
|
||||
union {
|
||||
long var;
|
||||
long (*func)(long);
|
||||
} value;
|
||||
struct symbol *next;
|
||||
} symbol_t;
|
||||
|
||||
/* Variables ------------------------------------------------------- */
|
||||
|
||||
symbol_t *symbol_table = NULL;
|
||||
symbol_t initial_symbols[];
|
||||
|
||||
const char *version_string = "1.0";
|
||||
|
||||
int yyargc;
|
||||
char **yyargv;
|
||||
|
||||
/* are we taking input from the command line? */
|
||||
static int input_from_cmdline = 0;
|
||||
|
||||
/* are we recovering from an internal error */
|
||||
static int internal_error = 0;
|
||||
|
||||
#define LONGBITS (sizeof(long) * CHAR_BIT)
|
||||
#define CHARMASK ((1 << CHAR_BIT) - 1)
|
||||
|
||||
/* Function Prototypes --------------------------------------------- */
|
||||
|
||||
int yyerror(char *s);
|
||||
int yylex(void);
|
||||
int yyparse();
|
||||
symbol_t *getsym(const char *name);
|
||||
symbol_t *putsym(const char *name, int type);
|
||||
const char *num2str(unsigned long num, int base, int pad);
|
||||
long print(long x);
|
||||
|
||||
%}
|
||||
|
||||
/* yylval's structure */
|
||||
%union {
|
||||
long integer;
|
||||
symbol_t *symbol;
|
||||
}
|
||||
|
||||
%token <integer> INTEGER
|
||||
%token <symbol> VARIABLE FUNCTION
|
||||
%type <integer> expression
|
||||
|
||||
/* operators have C conventions for precedence */
|
||||
%right '=' INC DEC MUL DIV MOD AND XOR OR LEFT RIGHT
|
||||
%right '?' ':'
|
||||
%left LOGICAL_OR
|
||||
%left LOGICAL_AND
|
||||
%left '|'
|
||||
%left '^'
|
||||
%left '&'
|
||||
%left EQ NE
|
||||
%left '<' LE '>' GE
|
||||
%left LEFT_SHIFT RIGHT_SHIFT
|
||||
%left '+' '-'
|
||||
%left '*' '/' '%'
|
||||
%left '!' '~' NEG
|
||||
|
||||
|
||||
%% /* YACC grammar follows */
|
||||
|
||||
input: /* empty */
|
||||
| input line
|
||||
;
|
||||
|
||||
line : expression '\n' { getsym("ans")->value.var = print($1); }
|
||||
| expression ',' { getsym("ans")->value.var = $1; }
|
||||
| '\n' /* do nothing */
|
||||
| error '\n' { yyerrok; }
|
||||
;
|
||||
|
||||
expression:
|
||||
INTEGER { $$ = $1; }
|
||||
| VARIABLE { $$ = $1->value.var; }
|
||||
| FUNCTION '(' expression ')' { $$ = (*($1->value.func))($3); }
|
||||
| FUNCTION expression { $$ = (*($1->value.func))($2); }
|
||||
| FUNCTION { $$ = (*($1->value.func))(getsym("ans")->value.var); }
|
||||
| VARIABLE '=' expression { $$ = $1->value.var = $3; }
|
||||
| VARIABLE INC expression { $$ = $1->value.var += $3; }
|
||||
| VARIABLE DEC expression { $$ = $1->value.var -= $3; }
|
||||
| VARIABLE MUL expression { $$ = $1->value.var *= $3; }
|
||||
| VARIABLE DIV expression { if (0 != $3) {
|
||||
$$ = $1->value.var /= $3;
|
||||
} else {
|
||||
yyerror("divide by zero error");
|
||||
internal_error = 1;
|
||||
$$ = 0;
|
||||
}
|
||||
}
|
||||
| VARIABLE MOD expression { $$ = $1->value.var %= $3; }
|
||||
| VARIABLE AND expression { $$ = $1->value.var &= $3; }
|
||||
| VARIABLE XOR expression { $$ = $1->value.var ^= $3; }
|
||||
| VARIABLE OR expression { $$ = $1->value.var |= $3; }
|
||||
| VARIABLE LEFT expression { $$ = $1->value.var <<= $3; }
|
||||
| VARIABLE RIGHT expression { $$ = $1->value.var >>= $3; }
|
||||
| expression '?' expression ':' expression
|
||||
{ $$ = $1 ? $3 : $5; }
|
||||
| expression '+' expression { $$ = $1 + $3; }
|
||||
| expression '-' expression { $$ = $1 - $3; }
|
||||
| expression '|' expression { $$ = $1 | $3; }
|
||||
| expression '^' expression { $$ = $1 ^ $3; }
|
||||
| expression '*' expression { $$ = $1 * $3; }
|
||||
| expression '/' expression { if (0 != $3) {
|
||||
$$ = $1 / $3;
|
||||
} else {
|
||||
yyerror("divide by zero error");
|
||||
internal_error = 1;
|
||||
$$ = 0;
|
||||
}
|
||||
}
|
||||
| expression '%' expression { $$ = $1 % $3; }
|
||||
| expression '&' expression { $$ = $1 & $3; }
|
||||
| expression '<' expression { $$ = $1 < $3; }
|
||||
| expression '>' expression { $$ = $1 > $3; }
|
||||
| expression EQ expression { $$ = $1 == $3; }
|
||||
| expression LE expression { $$ = $1 <= $3; }
|
||||
| expression GE expression { $$ = $1 >= $3; }
|
||||
| expression NE expression { $$ = $1 != $3; }
|
||||
| '~' expression { $$ = ~$2; }
|
||||
| '-' expression %prec NEG { $$ = -$2; }
|
||||
| expression LEFT_SHIFT expression
|
||||
{ $$ = $1 << $3; }
|
||||
| expression RIGHT_SHIFT expression
|
||||
{ $$ = $1 >> $3; }
|
||||
| expression LOGICAL_AND expression
|
||||
{ $$ = $1 && $3; }
|
||||
| expression LOGICAL_OR expression
|
||||
{ $$ = $1 || $3; }
|
||||
| '!' expression { $$ = !$2; }
|
||||
| '(' expression ')' { $$ = $2; }
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
/* Functions --------------------------------------------------------------- */
|
||||
|
||||
#if defined(HAVE_READLINE)
|
||||
int yygetc(void)
|
||||
{
|
||||
static char *line, *pos;
|
||||
|
||||
if (!line) {
|
||||
line = pos = readline("> ");
|
||||
if (!line) {
|
||||
return EOF;
|
||||
}
|
||||
|
||||
/* if the line has any text in it, save it in the history */
|
||||
if ('\0' != *line) {
|
||||
add_history(line);
|
||||
}
|
||||
}
|
||||
|
||||
if ('\0' == *pos) {
|
||||
free(line);
|
||||
line = 0;
|
||||
return '\n';
|
||||
}
|
||||
|
||||
return *pos++;
|
||||
}
|
||||
#elif defined(HAVE_CMDEDIT)
|
||||
/* Use the editing and history features provided by CmdEdit. */
|
||||
#include <dpmi.h>
|
||||
#include <go32.h>
|
||||
#include <sys/farptr.h>
|
||||
int yygetc(void)
|
||||
{
|
||||
static char line[256], *pos = line;
|
||||
|
||||
if (pos == line) {
|
||||
fputs("> ", stdout);
|
||||
fflush(stdout);
|
||||
__dpmi_regs regs;
|
||||
regs.h.ah = 0x0a; /* buffered input */
|
||||
regs.x.ds = __tb >> 4;
|
||||
regs.x.dx = __tb & 0x0f;
|
||||
_farpokeb(_dos_ds, __tb, 255);
|
||||
_farpokeb(_dos_ds, __tb+1, 0);
|
||||
__dpmi_int(0x21, ®s);
|
||||
dosmemget(__tb+2, 256, line);
|
||||
putchar('\n');
|
||||
pos = line;
|
||||
if ('\x1a' == *pos) {
|
||||
return EOF;
|
||||
}
|
||||
}
|
||||
|
||||
if ('\r' == *pos) {
|
||||
pos = line;
|
||||
return '\n';
|
||||
}
|
||||
|
||||
return *pos++;
|
||||
}
|
||||
#else
|
||||
int yygetc(void)
|
||||
{
|
||||
static int lastch = '\n';
|
||||
|
||||
/* manage the prompt */
|
||||
if ('\n' == lastch) {
|
||||
printf("> ");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
lastch = getchar();
|
||||
return lastch;
|
||||
}
|
||||
#endif
|
||||
|
||||
int yyungetc;
|
||||
int yygetchar(void)
|
||||
{
|
||||
if ('\0' != yyungetc) {
|
||||
int ch = yyungetc;
|
||||
yyungetc = '\0';
|
||||
return ch;
|
||||
}
|
||||
|
||||
if (input_from_cmdline) {
|
||||
static int arg=1, pos=0;
|
||||
|
||||
if (arg >= yyargc) {
|
||||
return (arg++ == yyargc ? '\n' : EOF);
|
||||
}
|
||||
|
||||
if ('\0' == yyargv[arg][pos]) {
|
||||
arg++;
|
||||
pos = 0;
|
||||
return ' ';
|
||||
}
|
||||
|
||||
return yyargv[arg][pos++];
|
||||
}
|
||||
|
||||
return yygetc();
|
||||
}
|
||||
|
||||
int yyerror(char *s)
|
||||
{
|
||||
printf("%s\n", s);
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int yylex(void)
|
||||
{
|
||||
int c, i;
|
||||
|
||||
/* ignore whitespace */
|
||||
do {
|
||||
c = yygetchar();
|
||||
} while (strchr(" \t", c));
|
||||
|
||||
/* handle end of input */
|
||||
if (EOF == c) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* handle numeric types */
|
||||
if (isdigit(c)) {
|
||||
int base;
|
||||
int nDigits;
|
||||
|
||||
/* determine the base of this number */
|
||||
if (c != '0') {
|
||||
base = getsym("ibase")->value.var;
|
||||
yyungetc = c;
|
||||
} else {
|
||||
c = yygetchar();
|
||||
switch(c) {
|
||||
case 'd':
|
||||
case 'D':
|
||||
base = 10;
|
||||
break;
|
||||
case 'x':
|
||||
case 'X':
|
||||
base = 16;
|
||||
break;
|
||||
case 'b':
|
||||
case 'B':
|
||||
base = 2;
|
||||
break;
|
||||
default:
|
||||
base = 8;
|
||||
yyungetc = c;
|
||||
}
|
||||
}
|
||||
|
||||
yylval.integer = 0;
|
||||
nDigits = 0;
|
||||
c = yygetchar();
|
||||
while (EOF != c && isxdigit(c)) {
|
||||
unsigned digit = (c <= '9') ?
|
||||
(c & 0xf) :
|
||||
(((c - 'A') & 7) + 10);
|
||||
if (digit >= base) {
|
||||
break;
|
||||
}
|
||||
|
||||
nDigits++;
|
||||
yylval.integer *= base;
|
||||
yylval.integer += digit;
|
||||
|
||||
c = yygetchar();
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case 'K':
|
||||
yylval.integer *= 1024;
|
||||
break;
|
||||
case 'M':
|
||||
yylval.integer *= 1024*1024;
|
||||
break;
|
||||
case 'G':
|
||||
yylval.integer *= 1024*1024*1024;
|
||||
break;
|
||||
case 'b':
|
||||
case 'B':
|
||||
case '_':
|
||||
yylval.integer = 1l << yylval.integer;
|
||||
break;
|
||||
default:
|
||||
if (0 == nDigits && 2 == base)
|
||||
yylval.integer = 1;
|
||||
yyungetc = c;
|
||||
}
|
||||
|
||||
return INTEGER;
|
||||
}
|
||||
|
||||
/* handle single quoted strings including multi-character
|
||||
* constants (a common extension to ANSI C)
|
||||
*/
|
||||
if ('\'' == c) {
|
||||
yylval.integer = 0;
|
||||
|
||||
for (c = yygetchar(); EOF != c && '\'' != c; c = yygetchar()) {
|
||||
yylval.integer = (yylval.integer << 8) + (c & 255);
|
||||
}
|
||||
|
||||
return INTEGER;
|
||||
}
|
||||
|
||||
/* handle identifiers */
|
||||
if (isalpha(c)) {
|
||||
symbol_t *sym;
|
||||
static char *buf = NULL; /* this is allocated only once */
|
||||
static int length = 0;
|
||||
|
||||
if (NULL == buf) {
|
||||
length = 40;
|
||||
buf = malloc(length + 1);
|
||||
}
|
||||
|
||||
i = 0;
|
||||
do {
|
||||
/* grow the buffer if it is too small */
|
||||
if (i == length) {
|
||||
length *= 2;
|
||||
buf = realloc(buf, length +1);
|
||||
}
|
||||
|
||||
buf[i++] = c;
|
||||
c = yygetchar();
|
||||
} while ((EOF != c) && isalnum(c));
|
||||
|
||||
yyungetc = c;
|
||||
buf[i] = '\0';
|
||||
|
||||
/* look up (or generate) the symbol */
|
||||
if (NULL == (sym = getsym(buf))) {
|
||||
sym = putsym(buf, VARIABLE);
|
||||
}
|
||||
yylval.symbol = sym;
|
||||
return sym->type;
|
||||
}
|
||||
|
||||
/* check for the shift and logical operators */
|
||||
if (strchr("<>&|=+-*/%^!", c)) {
|
||||
int d = yygetchar();
|
||||
if (c == d) {
|
||||
switch (c) {
|
||||
case '<':
|
||||
case '>':
|
||||
d = yygetchar();
|
||||
if ('=' == d) {
|
||||
return ('<' == c ? LEFT : RIGHT);
|
||||
}
|
||||
yyungetc = d;
|
||||
return ('<' == c ? LEFT_SHIFT : RIGHT_SHIFT);
|
||||
case '&': return LOGICAL_AND;
|
||||
case '|': return LOGICAL_OR;
|
||||
case '=': return EQ;
|
||||
}
|
||||
} else if (d == '=') {
|
||||
switch (c) {
|
||||
case '<': return LE;
|
||||
case '>': return GE;
|
||||
case '!': return NE;
|
||||
case '+': return INC;
|
||||
case '-': return DEC;
|
||||
case '*': return MUL;
|
||||
case '/': return DIV;
|
||||
case '%': return MOD;
|
||||
case '&': return AND;
|
||||
case '^': return XOR;
|
||||
case '|': return OR;
|
||||
}
|
||||
} else {
|
||||
yyungetc = d;
|
||||
}
|
||||
}
|
||||
|
||||
/* this is a single character terminal */
|
||||
return c;
|
||||
}
|
||||
|
||||
long defaultfunc(long i)
|
||||
{
|
||||
fprintf(stderr, "internal error\n");
|
||||
exit(0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
symbol_t *putsym(const char *name, int type)
|
||||
{
|
||||
symbol_t *sym;
|
||||
|
||||
sym = (symbol_t*) malloc(sizeof(*sym));
|
||||
if (NULL == sym) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sym->name = strdup(name);
|
||||
if (NULL == sym->name) {
|
||||
free(sym);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sym->type = type;
|
||||
switch(type) {
|
||||
case VARIABLE:
|
||||
sym->value.var = 0;
|
||||
break;
|
||||
case FUNCTION:
|
||||
sym->value.func = defaultfunc;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Can't think of a good way to set that at present. */
|
||||
sym->description = NULL;
|
||||
sym->next = symbol_table;
|
||||
symbol_table = sym;
|
||||
|
||||
return sym;
|
||||
}
|
||||
|
||||
symbol_t *getsym(const char *name)
|
||||
{
|
||||
symbol_t *p;
|
||||
|
||||
for (p = symbol_table; p != NULL; p = p->next) {
|
||||
if (0 == strcmp(p->name, name)) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *num2str(unsigned long num, int base, int pad) {
|
||||
static const char lookup[] = "0123456789abcdef";
|
||||
static char str[LONGBITS + 1];
|
||||
char *pStr, *padStr;
|
||||
|
||||
/* check for unsupported bases */
|
||||
if (base < 2 || base >= sizeof(lookup)) {
|
||||
printf("(bad obase, assuming base 10)\n\t");
|
||||
base = 10;
|
||||
}
|
||||
|
||||
/* and illegal pad lengths */
|
||||
if (pad < 1 || pad > LONGBITS) {
|
||||
printf("(bad pad, assuming pad 1)\n\t");
|
||||
pad = 1;
|
||||
}
|
||||
|
||||
/* pad str with zeros */
|
||||
memset(str, '0', sizeof(str));
|
||||
|
||||
pStr = &str[sizeof(str)];
|
||||
*--pStr = '\0';
|
||||
padStr = pStr - pad;
|
||||
|
||||
do {
|
||||
*--pStr = lookup[num % base];
|
||||
num /= base;
|
||||
} while (num);
|
||||
|
||||
return (padStr < pStr ? padStr : pStr);
|
||||
}
|
||||
|
||||
long ascii(long x)
|
||||
{
|
||||
long w;
|
||||
int b;
|
||||
|
||||
printf("\t'");
|
||||
if (0 == x) {
|
||||
printf("\\0");
|
||||
} else {
|
||||
/* ignore leading NILs */
|
||||
b = LONGBITS / CHAR_BIT;
|
||||
w = x;
|
||||
while (0 == ((w >> (LONGBITS - CHAR_BIT)) & CHARMASK)) {
|
||||
--b;
|
||||
w <<= CHAR_BIT;
|
||||
}
|
||||
for (; b > 0; w <<= CHAR_BIT, --b) {
|
||||
char c = (w >> (LONGBITS - CHAR_BIT)) & CHARMASK;
|
||||
if (0 == c) {
|
||||
printf("\\0");
|
||||
} else {
|
||||
printf(isprint(c) ? "%c" : "\\x%02x", c);
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("'\n\n");
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
long bitcnt(long x)
|
||||
{
|
||||
long b;
|
||||
for (b=0; x!=0; b++) {
|
||||
x &= x-1; /* clear least significant (set) bit */
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
long bitfield(long x)
|
||||
{
|
||||
symbol_t *N = getsym("N");
|
||||
long result;
|
||||
|
||||
if (0 == N->value.var) {
|
||||
printf("WARNING: N is zero - automatically setting N to ans\n\n");
|
||||
N->value.var = getsym("ans")->value.var;
|
||||
}
|
||||
|
||||
result = N->value.var & ~(-1l << x);
|
||||
N->value.var >>= x;
|
||||
|
||||
/* force logical shift on all machines */
|
||||
N->value.var &= ~(-1l << (LONGBITS - x));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
long decompose(long x)
|
||||
{
|
||||
char *separator = "";
|
||||
long i;
|
||||
|
||||
if (0 != x) {
|
||||
printf("\t");
|
||||
|
||||
for (i = LONGBITS - 1; i >= 0; i--) {
|
||||
if (0 != (x & (1l<<i))) {
|
||||
printf("%s%ld", separator, i);
|
||||
separator = ", ";
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n\n");
|
||||
} else {
|
||||
printf("\tNo set bits\n\n");
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
long lssb(long x)
|
||||
{
|
||||
if (0 == x) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
x ^= x-1; /* isolate the least significant bit */
|
||||
return bitcnt(x-1);
|
||||
}
|
||||
|
||||
long mssb(long x)
|
||||
{
|
||||
long i;
|
||||
|
||||
for (i = LONGBITS - 1; i >= 0; i--) {
|
||||
if (0 != (x & (1l<<i))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
long swap32(long d)
|
||||
{
|
||||
return (d >> 24 & 0x000000ff) |
|
||||
(d >> 8 & 0x0000ff00) |
|
||||
(d << 8 & 0x00ff0000) |
|
||||
(d << 24 & 0xff000000);
|
||||
}
|
||||
|
||||
long labs(long d)
|
||||
{
|
||||
if (d < 0)
|
||||
return -d;
|
||||
return d;
|
||||
}
|
||||
|
||||
long quit(long ret)
|
||||
{
|
||||
exit((int) ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
long print(long x)
|
||||
{
|
||||
long obase = getsym("obase")->value.var;
|
||||
int pad = abs(getsym("pad")->value.var);
|
||||
|
||||
if (internal_error) {
|
||||
internal_error = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!input_from_cmdline) {
|
||||
printf("\t");
|
||||
}
|
||||
|
||||
/* print the prefixes */
|
||||
switch(obase) {
|
||||
case 16:
|
||||
printf("0x");
|
||||
break;
|
||||
case 10:
|
||||
break;
|
||||
case 8:
|
||||
printf("0");
|
||||
break;
|
||||
case 2:
|
||||
printf("0b");
|
||||
break;
|
||||
case 0:
|
||||
case 1:
|
||||
break;
|
||||
default:
|
||||
printf("[base %ld] ", obase);
|
||||
}
|
||||
|
||||
/* now print the actual values */
|
||||
switch(obase) {
|
||||
case 10:
|
||||
/* print base 10 values directly to keep signedness */
|
||||
printf("%0*ld\n", pad, x);
|
||||
break;
|
||||
case 1:
|
||||
/* special case base 1 (print dex, hex and binary) */
|
||||
printf("%0*ld\t[0x%0*lx]\t[0b%s]\n", pad, x, pad, x, num2str(x, 2, LONGBITS));
|
||||
break;
|
||||
case 0:
|
||||
/* special case base 0 (print dec and hex) */
|
||||
printf("%0*ld\t[0x%0*lx]\n", pad, x, pad, x);
|
||||
break;
|
||||
default:
|
||||
printf("%s\n", num2str(x, obase, pad));
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
void print_help(long mode)
|
||||
{
|
||||
printf(
|
||||
"pdc %s - the programmers desktop calculator\n"
|
||||
"\n"
|
||||
"Copyright (C) 2001-2005, 2013 Daniel Thompson <daniel\100redfelineninja\056org\056uk>\n"
|
||||
"This is free software with ABSOLUTELY NO WARRANTY.\n"
|
||||
"For details type `warranty'.\n"
|
||||
"\n",
|
||||
version_string);
|
||||
|
||||
if (1 == mode) {
|
||||
symbol_t *sym;
|
||||
printf(
|
||||
"Contributors:\n"
|
||||
" Daniel Thompson <d\056thompson\100gmx\056net>\n"
|
||||
" Paul Walker <paul\100blacksun\056org\056uk>\n"
|
||||
" Jason Hood <jadoxa\100yahoo\056com\056au>\n"
|
||||
"\n"
|
||||
);
|
||||
printf("Variables:\n");
|
||||
for (sym=initial_symbols; NULL != sym->name; sym++) {
|
||||
if (VARIABLE == sym->type) {
|
||||
printf(" %-9s - %s\n", sym->name, sym->description);
|
||||
}
|
||||
}
|
||||
printf("\nFunctions:\n");
|
||||
for (sym=initial_symbols; NULL != sym->name; sym++) {
|
||||
if (FUNCTION == sym->type) {
|
||||
printf(" %-9s - %s\n", sym->name, sym->description);
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
if (input_from_cmdline) {
|
||||
printf(
|
||||
"Usage:\n"
|
||||
" pdc [<expression>] [, <expression>] ...\n"
|
||||
"\n"
|
||||
" Without arguments pdc enters interactive mode; otherwise it evaluates its\n"
|
||||
" arguments and prints the result. Expressions are separated using the ,\n"
|
||||
" operator (e.g. 'pdc obase=2, 4*12'). Only the last expression evaluated\n"
|
||||
" will be printed automatically. Use the print function to display\n"
|
||||
" intermediate values if required.\n"
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (2 == mode) {
|
||||
printf(
|
||||
"This program is free software; you can redistribute it and/or modify\n"
|
||||
"it under the terms of the GNU General Public License as published by\n"
|
||||
"the Free Software Foundation; either version 2 of the License, or\n"
|
||||
"(at your option) any later version.\n"
|
||||
"\n"
|
||||
"This program is distributed in the hope that it will be useful,\n"
|
||||
"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
|
||||
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
|
||||
"GNU General Public License for more details.\n"
|
||||
"\n"
|
||||
"You should have received a copy of the GNU General Public License along\n"
|
||||
"with this program; if not, write to the Free Software Foundation, Inc.,\n"
|
||||
"51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n"
|
||||
"\n"
|
||||
"Or see https://www.gnu.org/licenses/old-licenses/gpl-2.0.html\n"
|
||||
"\n"
|
||||
);
|
||||
}
|
||||
if (3 == mode) {
|
||||
symbol_t *sym;
|
||||
|
||||
printf("Compiled: "__TIME__" "__DATE__"\n");
|
||||
printf("Built-in symbols: ");
|
||||
for (sym=initial_symbols; NULL != sym->name; sym++) {
|
||||
printf(" %s%s", sym->name, (FUNCTION == sym->type ? "()" : ""));
|
||||
}
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
long help(long ans)
|
||||
{
|
||||
print_help(1);
|
||||
return ans;
|
||||
}
|
||||
|
||||
long version(long ans)
|
||||
{
|
||||
print_help(3);
|
||||
return ans;
|
||||
}
|
||||
|
||||
long warranty(long ans)
|
||||
{
|
||||
print_help(2);
|
||||
return ans;
|
||||
}
|
||||
|
||||
#define BASE_FN(name, base) \
|
||||
long name(long ans) \
|
||||
{ \
|
||||
getsym("obase")->value.var = base; \
|
||||
return ans; \
|
||||
}
|
||||
|
||||
BASE_FN(dechex, 0)
|
||||
BASE_FN(dxb, 1)
|
||||
BASE_FN(bin, 2)
|
||||
BASE_FN(oct, 8)
|
||||
BASE_FN(dec, 10)
|
||||
BASE_FN(hex, 16)
|
||||
|
||||
/* Print routine in the help function isn't too clever, so VARIABLE and
|
||||
* FUNCTION should be grouped together, otherwise the display looks a
|
||||
* bit weird. Not hard to fix, but probably more work than it's worth.
|
||||
*/
|
||||
symbol_t initial_symbols[] = {
|
||||
{ "ans", "the result of the previous calculation", VARIABLE, { 0 }, NULL },
|
||||
{ "ibase", "the default input base (to force decimal use 0d10)", VARIABLE, { 10 }, NULL },
|
||||
{ "obase", "the output base (set to zero or one for combined bases)", VARIABLE, { 0 }, NULL },
|
||||
{ "pad", "the amount of zero padding used when displaying numbers", VARIABLE, { 1 }, NULL },
|
||||
{ "N", "global variable used by the bitfield function", VARIABLE, { 0 }, NULL },
|
||||
{ "abs", "get the absolute value of x", FUNCTION, { (long) labs }, NULL },
|
||||
{ "ascii", "convert x into a character constant", FUNCTION, { (long) ascii }, NULL },
|
||||
{ "bin", "change output base to binary", FUNCTION, { (long) bin }, NULL },
|
||||
{ "bitcnt", "get the population count of x", FUNCTION, { (long) bitcnt }, NULL },
|
||||
{ "bitfield", "extract the bottom x bits of N and shift N", FUNCTION, { (long) bitfield}, NULL },
|
||||
{ "bits", "alias for decompose", FUNCTION, {(long) decompose}, NULL },
|
||||
{ "dec", "set the output base to decimal", FUNCTION, { (long) dec }, NULL },
|
||||
{ "decompose", "decompose x into a list of bits set", FUNCTION, {(long) decompose}, NULL },
|
||||
{ "default", "set the default output base (decimal and hex)", FUNCTION, { (long) dechex }, NULL },
|
||||
{ "dxb", "output in decimal, hex and binary", FUNCTION, { (long) dxb }, NULL },
|
||||
{ "help", "display this help message", FUNCTION, { (long) help }, NULL },
|
||||
{ "hex", "change output base to hex", FUNCTION, { (long) hex }, NULL },
|
||||
{ "lssb", "get the least significant set bit in x", FUNCTION, { (long) lssb }, NULL },
|
||||
{ "mssb", "get the most significant set bit in x", FUNCTION, { (long) mssb }, NULL },
|
||||
{ "oct", "change output base to octal", FUNCTION, { (long) oct }, NULL },
|
||||
{ "print", "print an expression (useful for command line work)", FUNCTION, { (long) print }, NULL },
|
||||
{ "quit", "leave pdc", FUNCTION, { (long) quit }, NULL },
|
||||
{ "swap32", "perform a 32-bit byte swap", FUNCTION, { (long) swap32 }, NULL },
|
||||
{ "version", "display version information", FUNCTION, { (long) version }, NULL },
|
||||
{ "warranty", "display warranty and licencing information", FUNCTION, { (long) warranty}, NULL },
|
||||
{ "K", "Defaults to KiB (1024 bytes)", VARIABLE, { 1024 }, NULL },
|
||||
{ "M", "Defaults to MiB (1048576 bytes)", VARIABLE, { 1024 * 1024 }, NULL },
|
||||
{ "G", "Defaults to GiB (1073741824 bytes)", VARIABLE, { 1073741824 }, NULL },
|
||||
{ NULL, "", 0, { 0 }, NULL }
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
/* setup the initial symbol table */
|
||||
for (i=1; NULL != initial_symbols[i].name; i++) {
|
||||
initial_symbols[i].next = &initial_symbols[i-1];
|
||||
}
|
||||
symbol_table = &initial_symbols[i-1];
|
||||
|
||||
/* run in non-interactive mode if we have command line arguments */
|
||||
if (argc > 1) {
|
||||
input_from_cmdline = 1;
|
||||
yyargc = argc;
|
||||
yyargv = argv;
|
||||
} else {
|
||||
print_help(0);
|
||||
}
|
||||
|
||||
/* run the calculator */
|
||||
yyparse();
|
||||
|
||||
#if defined(HAVE_READLINE) || (!defined(__DJGPP__) && !defined(__MINGW32__))
|
||||
if (!input_from_cmdline) {
|
||||
/* shutdown cleanly after a ^D */
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user