diff --git a/doc/user-guide b/doc/user-guide index a25c7d07..10d9ec7f 100644 --- a/doc/user-guide +++ b/doc/user-guide @@ -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 diff --git a/utils/.gitignore b/utils/.gitignore index 3d402b80..793f952b 100644 --- a/utils/.gitignore +++ b/utils/.gitignore @@ -1,6 +1,5 @@ *.o basename -calc cat chmod chroot diff --git a/utils/Makefile b/utils/Makefile index 9913cce6..0b85d9cd 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -11,7 +11,6 @@ CXXFLAGS:=$(CXXFLAGS) -Wall -Wextra -fno-exceptions -fno-rtti BINARIES:=\ basename \ -calc \ cat \ chmod \ chroot \ diff --git a/utils/calc.cpp b/utils/calc.cpp deleted file mode 100644 index 8313ef4c..00000000 --- a/utils/calc.cpp +++ /dev/null @@ -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 . - - calc.cpp - A simple reverse polish calculator. - -*******************************************************************************/ - -#include -#include -#include -#include - -//Stack, pending standard library implementation. All in one file due to linking -// annoyances with the makefile. -template -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 &stack) { - stack.push(value); -} - -/* MODIFIES: stack. - * EFFECTS: Pushes value onto the stack. - */ -void push(long value, Stack &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 &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 &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 &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 &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 &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 &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 &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 &stack) { - long *operand; - - pop(operand, stack); - printf("%li\n", *operand); - push(operand, stack); -} - -/* MODIFIES: stack. - * EFFECTS: Empties the stack. - */ -void clear(Stack &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 &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(" 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 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; -}