mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Remove calc(1).
This program was mostly replaced with the standard expr(1) tool and the code quality was not up to the standards. Finally, it was not very useful.
This commit is contained in:
parent
5e295b8d94
commit
91a1df02b1
4 changed files with 0 additions and 400 deletions
|
@ -144,7 +144,6 @@ Sortix comes with a number of home-made programs. Here is an overview:
|
|||
* `basename` - strip directory from filenames
|
||||
* `benchctxswitch` - useless benchmark
|
||||
* `benchsyscall` - slightly less useless benchmark
|
||||
* `calc` - reverse polish calculator
|
||||
* `carray` - convert a binary file to a C array
|
||||
* `cat` - display file on terminal
|
||||
* `chmod` - change file mode bits
|
||||
|
|
1
utils/.gitignore
vendored
1
utils/.gitignore
vendored
|
@ -1,6 +1,5 @@
|
|||
*.o
|
||||
basename
|
||||
calc
|
||||
cat
|
||||
chmod
|
||||
chroot
|
||||
|
|
|
@ -11,7 +11,6 @@ CXXFLAGS:=$(CXXFLAGS) -Wall -Wextra -fno-exceptions -fno-rtti
|
|||
|
||||
BINARIES:=\
|
||||
basename \
|
||||
calc \
|
||||
cat \
|
||||
chmod \
|
||||
chroot \
|
||||
|
|
397
utils/calc.cpp
397
utils/calc.cpp
|
@ -1,397 +0,0 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Steve Dougherty 2011.
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2011.
|
||||
|
||||
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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
calc.cpp
|
||||
A simple reverse polish calculator.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
//Stack, pending standard library implementation. All in one file due to linking
|
||||
// annoyances with the makefile.
|
||||
template <typename T>
|
||||
class Stack {
|
||||
public:
|
||||
|
||||
//Is its own iterator.
|
||||
/* MODIFIES: this.
|
||||
* EFFECTS: Self-iterator: sets to first element and returns it.
|
||||
*/
|
||||
const T *begin() {
|
||||
currentIter = head;
|
||||
return next();
|
||||
}
|
||||
|
||||
/* MODIFIES: this.
|
||||
* EFFECTS: Self-iterator: returns element from the list and advances.
|
||||
* If all elements have been iterated, returns NULL. Does not
|
||||
* have invalidation - be careful!
|
||||
*/
|
||||
const T *next() {
|
||||
if (!currentIter) return NULL;
|
||||
|
||||
const T *element = currentIter->o;
|
||||
currentIter = currentIter->next;
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/* EFFECTS: Returns true if stack is empty, false otherwise.
|
||||
*/
|
||||
bool isEmpty() const {
|
||||
return !head;
|
||||
}
|
||||
|
||||
/* MODIFIES: this.
|
||||
* EFFECTS: Pushes o onto the top of the stack.
|
||||
*/
|
||||
void push(T *o) {
|
||||
head = new node(head, o);
|
||||
}
|
||||
|
||||
/* MODIFIES this
|
||||
* EFFECTS Pops and returns the top element. Returns NULL if empty.
|
||||
*/
|
||||
T *pop() {
|
||||
if (isEmpty()) return NULL;
|
||||
|
||||
node *oldHead = head;
|
||||
T *element = oldHead->o;
|
||||
head = oldHead->next;
|
||||
delete oldHead;
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
Stack() : head(NULL) , currentIter(NULL) {}
|
||||
|
||||
Stack(const Stack &s) : head(NULL) , currentIter(NULL) {
|
||||
s.begin();
|
||||
copyAll(s.head);
|
||||
}
|
||||
|
||||
Stack &operator=(const Stack &s) {
|
||||
if (this == &s) return;
|
||||
removeAll();
|
||||
copyAll(s.head);
|
||||
}
|
||||
|
||||
~Stack() {
|
||||
removeAll();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
struct node {
|
||||
node(node *next, T *o) : next(next), o(o) {}
|
||||
node *next;
|
||||
T *o;
|
||||
};
|
||||
|
||||
node *head;
|
||||
node *currentIter;
|
||||
|
||||
/* MODIFIES: this.
|
||||
* EFFECT: called by copy constructor and operator= to copy elements
|
||||
* following from the given node into the local instance.
|
||||
*/
|
||||
void copyAll(const node *n) {
|
||||
if (n) {
|
||||
copyAll(n->next);
|
||||
push(new T(*(n->o)));
|
||||
}
|
||||
}
|
||||
|
||||
void removeAll() {
|
||||
while (!isEmpty()) delete pop();
|
||||
}
|
||||
};
|
||||
|
||||
/* MODIFIES: stack.
|
||||
* EFFECTS: Pushes value onto the stack.
|
||||
*/
|
||||
void push(long *value, Stack<long> &stack) {
|
||||
stack.push(value);
|
||||
}
|
||||
|
||||
/* MODIFIES: stack.
|
||||
* EFFECTS: Pushes value onto the stack.
|
||||
*/
|
||||
void push(long value, Stack<long> &stack) {
|
||||
stack.push(new long(value));
|
||||
}
|
||||
|
||||
/* MODIFIES: operand, stack, standard output.
|
||||
* EFFECTS: Attempts to set operand to the top value on the stack. If there
|
||||
* are no operands on the stack, prints an error message and aborts
|
||||
* the process with exit code 1.
|
||||
*/
|
||||
void pop(long *&operand, Stack<long> &stack) {
|
||||
if (stack.isEmpty()) {
|
||||
printf("%s: not enough operands\n", program_invocation_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
operand = stack.pop();
|
||||
}
|
||||
|
||||
/* MODIFIES: operand1, operand2, stack, standard output.
|
||||
* EFFECTS: Attempts to remove two operands from the top of the stack, setting
|
||||
* operand1 to the first one removed and operand2 to the second. If
|
||||
* there are fewer than two enough operands on the stack, prints
|
||||
* an error message and aborts the process with exit code 1.
|
||||
*/
|
||||
void popTwo(long *&operand1, long *&operand2, Stack<long> &stack) {
|
||||
pop(operand1, stack);
|
||||
pop(operand2, stack);
|
||||
}
|
||||
|
||||
/* MODIFIES: stack, standard output.
|
||||
* EFFECTS: Attempts to replace the top two operands on the stack with the
|
||||
* result returned by func(first, second).
|
||||
*/
|
||||
//Lambda functions would be wonderful for calling this function.
|
||||
//http://www2.research.att.com/~bs/C++0xFAQ.html#lambda
|
||||
void apply(long(*func)(long, long), Stack<long> &stack) {
|
||||
long *operand1, *operand2;
|
||||
popTwo(operand1, operand2, stack);
|
||||
push(func(*operand1, *operand2), stack);
|
||||
delete operand1;
|
||||
delete operand2;
|
||||
}
|
||||
|
||||
/* EFFECTS: Returns first + second.
|
||||
*/
|
||||
long add(long first, long second) { return first + second; }
|
||||
|
||||
/* EFFECTS: Returns subtracting "the first number from the second" (pg. 5)
|
||||
*/
|
||||
long subtract(long first, long second) { return second - first; }
|
||||
|
||||
/* EFFECTS: Returns first * second.
|
||||
*/
|
||||
long multiply(long first, long second) { return first * second; }
|
||||
|
||||
/* MODIFIES: stack, standard output.
|
||||
* EFFECTS: Attempts to replace the top two operands on the stack with the
|
||||
* result of dividing the second one by the first.
|
||||
* If the first number is zero, prints an division by zero error and
|
||||
* exits the process with exit code 1.
|
||||
*/
|
||||
void divide(Stack<long> &stack) {
|
||||
/* Can't use apply for this because it requires a check for the
|
||||
* denominator being zero. It could have an error-checking function
|
||||
* pointer, but that would muddy things as no other operators have such
|
||||
* conditions.
|
||||
*/
|
||||
long *first, *second;
|
||||
|
||||
popTwo(first, second, stack);
|
||||
if (*first == 0) {
|
||||
printf("%s: division by zero\n", program_invocation_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
push(*second / *first, stack);
|
||||
delete first;
|
||||
delete second;
|
||||
}
|
||||
|
||||
/* MODIFIES: stack, standard output.
|
||||
* EFFECTS: Attempts to negate the top element on the stack.
|
||||
*/
|
||||
void negate(Stack<long> &stack) {
|
||||
long *operand;
|
||||
|
||||
pop(operand, stack);
|
||||
push(-(*operand), stack);
|
||||
delete operand;
|
||||
}
|
||||
|
||||
/* MODIFIES: stack, standard output.
|
||||
* EFFECTS: Attempts to push a copy of the top element on top of the already
|
||||
* existing one.
|
||||
*/
|
||||
void duplicate(Stack<long> &stack) {
|
||||
long *operand;
|
||||
|
||||
pop(operand, stack);
|
||||
//Dereferencing creates new instance.
|
||||
push(*operand, stack);
|
||||
push(operand, stack);
|
||||
}
|
||||
|
||||
/* MODIFIES: stack, standard output.
|
||||
* EFFECTS: Attempts to reverse the first two elements on the stack.
|
||||
*/
|
||||
void reverse(Stack<long> &stack) {
|
||||
long *first, *second;
|
||||
|
||||
popTwo(first, second, stack);
|
||||
//Push the former first before the former second.
|
||||
push(first, stack);
|
||||
push(second, stack);
|
||||
}
|
||||
|
||||
/* MODIFIES: standard output.
|
||||
* EFFECTS: Prints the first element on the stack to standard output, followed
|
||||
* by a newline.
|
||||
*/
|
||||
void print(Stack<long> &stack) {
|
||||
long *operand;
|
||||
|
||||
pop(operand, stack);
|
||||
printf("%li\n", *operand);
|
||||
push(operand, stack);
|
||||
}
|
||||
|
||||
/* MODIFIES: stack.
|
||||
* EFFECTS: Empties the stack.
|
||||
*/
|
||||
void clear(Stack<long> &stack) {
|
||||
while (!stack.isEmpty()) delete stack.pop();
|
||||
}
|
||||
|
||||
/* MODIFIES: standard output.
|
||||
* EFFECTS: Prints all the elements on the stack, from top to bottom, each
|
||||
* separated by a single space. No trailing space. Ends with newline.
|
||||
*/
|
||||
void printAll(Stack<long> &stack) {
|
||||
if (!stack.isEmpty()) {
|
||||
const long *element = stack.begin();
|
||||
do {
|
||||
printf("%li", *element);
|
||||
} while ((element = stack.next()) && printf(" "));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* MODIFIES: standard output.
|
||||
* EFFECTS: Prints usage information and returns 0.
|
||||
*/
|
||||
int printHelp(const char* argv0) {
|
||||
printf("Usage: %s [--help] COMMAND ...\n", argv0);
|
||||
printf("%s is a Reverse Polish Notation integer calculator.\n", argv0);
|
||||
printf("\n");
|
||||
printf(" --help Display this help and exit\n");
|
||||
printf("\n");
|
||||
printf("%s supports the following commands:\n", argv0);
|
||||
printf("Any integers supplied are pushed onto the stack and can be given in decimal\n");
|
||||
printf("(default), octal with a leading 0, or hexadecimal with a leading 0x. Numbers\n");
|
||||
printf("can be prefixed with + or - to specify positive or negative, respectively.\n");
|
||||
printf("The operators +, -, *, and / pop the top two elements and push the result of\n");
|
||||
printf("<second> <operator> <first> to the stack. The top element is printed on exit\n");
|
||||
printf("unless a print command is given or an error occurs. Also,\n");
|
||||
printf(" a: prints all elements from first to last.\n");
|
||||
printf(" c: clears the stack.\n");
|
||||
printf(" d: duplicates the top element.\n");
|
||||
printf(" n: negates the top element.\n");
|
||||
printf(" p: prints the top element.\n");
|
||||
printf(" r: reverses the order of the top two elements.\n");
|
||||
printf("\n");
|
||||
printf("Examples:\n");
|
||||
printf(" %s 2 2 +\n", argv0);
|
||||
printf(" %s 0xCAFE42 0777 *\n", argv0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
//If no arguments, --help.
|
||||
if (argc == 1 ||
|
||||
(argc > 1 && !strcmp(argv[1], "--help")))
|
||||
return printHelp(argv[0]);
|
||||
|
||||
Stack<long> stack;
|
||||
bool printedAnything = false;
|
||||
|
||||
//Skip program name in arguments list.
|
||||
for (int i = 1; i < argc; i++) {
|
||||
char *endPtr;
|
||||
//Allow input in decimal, octal, or hex.
|
||||
long numberInput = strtol(argv[i], &endPtr, 0);
|
||||
|
||||
//Make sure the string is a number and not empty.
|
||||
if (*argv[i] && !(*endPtr)) {
|
||||
push(numberInput, stack);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Input was not a valid number, attempt to parse as operator.
|
||||
* Anything other than one character is not a valid operator.
|
||||
*/
|
||||
if (strlen(argv[i]) == 1) {
|
||||
switch (argv[i][0]) {
|
||||
case '+':
|
||||
//Add
|
||||
apply(add, stack);
|
||||
continue;
|
||||
case '-':
|
||||
//Subtract
|
||||
apply(subtract, stack);
|
||||
continue;
|
||||
case '*':
|
||||
//Multiply
|
||||
apply(multiply, stack);
|
||||
continue;
|
||||
case '/':
|
||||
//Divide
|
||||
divide(stack);
|
||||
continue;
|
||||
case 'n':
|
||||
//Negate
|
||||
negate(stack);
|
||||
continue;
|
||||
case 'd':
|
||||
//Duplicate
|
||||
duplicate(stack);
|
||||
continue;
|
||||
case 'r':
|
||||
//Reverse
|
||||
reverse(stack);
|
||||
continue;
|
||||
case 'p':
|
||||
//Print
|
||||
print(stack);
|
||||
printedAnything = true;
|
||||
continue;
|
||||
case 'c':
|
||||
//Clear
|
||||
clear(stack);
|
||||
continue;
|
||||
case 'a':
|
||||
//Print-all
|
||||
printAll(stack);
|
||||
printedAnything = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s: unsupported command: %s\n", program_invocation_name, argv[i]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ( !printedAnything && !stack.isEmpty() ) {
|
||||
print(stack);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue