mirror of
https://github.com/louisrubet/rpn
synced 2024-12-26 09:58:55 +01:00
Change date, time, ticks, remove nop, add welcome
This commit is contained in:
parent
bafc48ab85
commit
c0b9ef0cda
12 changed files with 63 additions and 101 deletions
21
CHANGELOG.md
21
CHANGELOG.md
|
@ -5,6 +5,27 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [2.4.1] - 2022-03-02
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- A welcome message has been added in interactive mode.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- The function `date` return format is now a string `"YYY-MM-DD"` (local ISO 8601).
|
||||||
|
- The function `time` return format is now a string `"HH:MM:SS"` (local ISO 8601).
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- The useless function `nop` has been removed.
|
||||||
|
- GENERATION.md file has been removed, the generation instructions are in README.md.
|
||||||
|
- The useless file TODO.md has been removed.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- The function `ticks` now returns correctly the current date in µs
|
||||||
|
|
||||||
## [2.4.0] - 2022-02-28
|
## [2.4.0] - 2022-02-28
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
# Generation
|
|
||||||
|
|
||||||
rpn is proposed for **GNU/Linux**.
|
|
||||||
|
|
||||||
It can be generated following the steps below.
|
|
||||||
|
|
||||||
rpn is dynamically linked against GNU MP and GNU MPFR and integrates [linenoise-ng](https://github.com/louisrubet/linenoise-ng.git) and [mpreal](http://www.holoborodko.com/pavel/mpfr/) code as git submodules.
|
|
||||||
|
|
||||||
## Generate and install under Ubuntu 20.04 LTS
|
|
||||||
|
|
||||||
```shell
|
|
||||||
sudo apt install git cmake g++ libmpfr6 libmpfr-dev
|
|
||||||
git clone https://github.com/louisrubet/rpn/
|
|
||||||
mkdir -p rpn/build && cd rpn/build
|
|
||||||
cmake ..
|
|
||||||
make -j
|
|
||||||
sudo make install
|
|
||||||
```
|
|
||||||
|
|
||||||
## Generate and install under Fedora 35
|
|
||||||
|
|
||||||
```shell
|
|
||||||
sudo dnf install git cmake g++ mpfrf mpfr-devel
|
|
||||||
git clone https://github.com/louisrubet/rpn/
|
|
||||||
mkdir -p rpn/build && cd rpn/build
|
|
||||||
cmake ..
|
|
||||||
make -j
|
|
||||||
sudo make install
|
|
||||||
```
|
|
10
MANUAL.md
10
MANUAL.md
|
@ -17,14 +17,13 @@ A help command is provided by rpn:
|
||||||
```rpn
|
```rpn
|
||||||
rpn> help
|
rpn> help
|
||||||
|
|
||||||
rpn v2.4.0, (c) 2022 <louis@rubet.fr>
|
rpn v2.4.1, (c) 2022 <louis@rubet.fr>
|
||||||
Reverse Polish Notation CLI calculator
|
Reverse Polish Notation CLI calculator
|
||||||
|
|
||||||
Syntax: rpn [command]
|
Syntax: rpn [command]
|
||||||
with optional command = list of commands
|
with optional command = list of commands
|
||||||
|
|
||||||
GENERAL
|
GENERAL
|
||||||
nop no operation
|
|
||||||
help this help message
|
help this help message
|
||||||
(...)
|
(...)
|
||||||
```
|
```
|
||||||
|
@ -123,7 +122,6 @@ rpn> 7b1252 dec
|
||||||
|
|
||||||
| keyword | description |
|
| keyword | description |
|
||||||
|-------------------|-----------------------------------------|
|
|-------------------|-----------------------------------------|
|
||||||
| `nop` | no operation |
|
|
||||||
| `help` `h` `?` | this help message |
|
| `help` `h` `?` | this help message |
|
||||||
| `quit` `q` `exit` | quit software |
|
| `quit` `q` `exit` | quit software |
|
||||||
| `version` | show rpn version |
|
| `version` | show rpn version |
|
||||||
|
@ -316,9 +314,9 @@ rpn> 7b1252 dec
|
||||||
| `acosh` | inverse hyperbolic cosine |
|
| `acosh` | inverse hyperbolic cosine |
|
||||||
| `tanh` | hyperbolic tangent |
|
| `tanh` | hyperbolic tangent |
|
||||||
| `atanh` | inverse hyperbolic tangent |
|
| `atanh` | inverse hyperbolic tangent |
|
||||||
| `time` | time in format HH.MMSSssssss |
|
| `time` | local time in ISO 8601 format HH:MM:SS |
|
||||||
| `date` | date in format (M)M.DDYYYY |
|
| `date` | local date in ISO 8601 format YYYY-MM-DD |
|
||||||
| `ticks` | system tick in µs |
|
| `ticks` | local date and time in µs |
|
||||||
|
|
||||||
### default
|
### default
|
||||||
|
|
||||||
|
|
|
@ -76,8 +76,7 @@ rpn> 12 fibo
|
||||||
|
|
||||||
```rpn
|
```rpn
|
||||||
rpn>
|
rpn>
|
||||||
Display all 146 possibilities? (y or n)
|
Display all 145 possibilities? (y or n)
|
||||||
nop pow conj < pick step eval exp10
|
|
||||||
help sqrt arg <= depth ift -> log2
|
help sqrt arg <= depth ift -> log2
|
||||||
h sq c->r != roll ifte pi alog2
|
h sq c->r != roll ifte pi alog2
|
||||||
? abs r->c == rolld do sin exp2
|
? abs r->c == rolld do sin exp2
|
||||||
|
@ -96,6 +95,7 @@ inv min bin rot end sto* exp
|
||||||
chs max base dup start sto/ expm
|
chs max base dup start sto/ expm
|
||||||
neg re > dup2 for sneg log10
|
neg re > dup2 for sneg log10
|
||||||
^ im >= dupn next sinv alog10
|
^ im >= dupn next sinv alog10
|
||||||
|
pow conj < pick step eval exp10
|
||||||
```
|
```
|
||||||
|
|
||||||
## Download
|
## Download
|
||||||
|
|
7
TODO.md
7
TODO.md
|
@ -1,7 +0,0 @@
|
||||||
TODO
|
|
||||||
|
|
||||||
missing tests / problems
|
|
||||||
- les arguments d'une fonction en erreur doivent ils être consommés ?
|
|
||||||
ex embettant : sto+
|
|
||||||
- supprimer les vector et map static (il y en a 3 dans program)
|
|
||||||
- cpplint to install and run automatically
|
|
|
@ -85,6 +85,8 @@ int main(int argc, char* argv[]) {
|
||||||
|
|
||||||
// run with interactive prompt
|
// run with interactive prompt
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
|
program::Welcome();
|
||||||
|
|
||||||
// init history
|
// init history
|
||||||
EnterInteractive();
|
EnterInteractive();
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,7 @@ struct Number : Object {
|
||||||
Number() : Object(kNumber), base(10) {}
|
Number() : Object(kNumber), base(10) {}
|
||||||
explicit Number(const mpreal& value__, int base__ = 10) : Object(kNumber), base(base__), value(value__) {}
|
explicit Number(const mpreal& value__, int base__ = 10) : Object(kNumber), base(base__), value(value__) {}
|
||||||
explicit Number(int value__, int base__ = 10) : Object(kNumber), base(base__), value(value__) {}
|
explicit Number(int value__, int base__ = 10) : Object(kNumber), base(base__), value(value__) {}
|
||||||
|
explicit Number(uint64_t value__, int base__ = 10) : Object(kNumber), base(base__), value(value__) {}
|
||||||
|
|
||||||
int base;
|
int base;
|
||||||
mpreal value;
|
mpreal value;
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
vector<program::keyword_t> program::keywords_{
|
vector<program::keyword_t> program::keywords_{
|
||||||
// GENERAL
|
// GENERAL
|
||||||
{kUndef, "", nullptr, "\nGENERAL"},
|
{kUndef, "", nullptr, "\nGENERAL"},
|
||||||
{kKeyword, "nop", &program::RpnNop, "no operation"},
|
|
||||||
{kKeyword, "help", &program::RpnHelp, "this help message"},
|
{kKeyword, "help", &program::RpnHelp, "this help message"},
|
||||||
{kKeyword, "h", &program::RpnHelp, ""},
|
{kKeyword, "h", &program::RpnHelp, ""},
|
||||||
{kKeyword, "?", &program::RpnHelp, ""},
|
{kKeyword, "?", &program::RpnHelp, ""},
|
||||||
|
@ -199,9 +198,9 @@ vector<program::keyword_t> program::keywords_{
|
||||||
|
|
||||||
// TIME AND DATE
|
// TIME AND DATE
|
||||||
{kUndef, "", nullptr, "\nTIME AND DATE"},
|
{kUndef, "", nullptr, "\nTIME AND DATE"},
|
||||||
{kKeyword, "time", &program::RpnTime, "time in local format"},
|
{kKeyword, "time", &program::RpnTime, "local time in ISO 8601 format"},
|
||||||
{kKeyword, "date", &program::RpnDate, "date in local format"},
|
{kKeyword, "date", &program::RpnDate, "local date in ISO 8601 format"},
|
||||||
{kKeyword, "ticks", &program::RpnTicks, "system tick in µs"},
|
{kKeyword, "ticks", &program::RpnTicks, "local date and time in µs"}
|
||||||
};
|
};
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ class program : public deque<Object*>, public Lexer {
|
||||||
void ShowStack(bool show_separator = true);
|
void ShowStack(bool show_separator = true);
|
||||||
|
|
||||||
static void ApplyDefault();
|
static void ApplyDefault();
|
||||||
|
static void Welcome();
|
||||||
|
|
||||||
static vector<string>& GetAutocompletionWords();
|
static vector<string>& GetAutocompletionWords();
|
||||||
|
|
||||||
|
@ -105,7 +106,6 @@ class program : public deque<Object*>, public Lexer {
|
||||||
void RpnP2r();
|
void RpnP2r();
|
||||||
|
|
||||||
// general
|
// general
|
||||||
void RpnNop();
|
|
||||||
void RpnQuit();
|
void RpnQuit();
|
||||||
void RpnHelp();
|
void RpnHelp();
|
||||||
void RpnStd();
|
void RpnStd();
|
||||||
|
|
|
@ -25,11 +25,7 @@ static const char _syntax[] = ATTR_BOLD "Syntax" ATTR_OFF ": rpn [command]\nwith
|
||||||
|
|
||||||
static const char _uname[] = ATTR_BOLD "rpn " RPN_VERSION ", (c) 2022 <louis@rubet.fr>" ATTR_OFF;
|
static const char _uname[] = ATTR_BOLD "rpn " RPN_VERSION ", (c) 2022 <louis@rubet.fr>" ATTR_OFF;
|
||||||
|
|
||||||
/// @brief nop keyword implementation
|
static const char _welcome[] = ATTR_BOLD "rpn " RPN_VERSION ATTR_OFF "\nType h or help for more information.";
|
||||||
///
|
|
||||||
void program::RpnNop() {
|
|
||||||
// nop
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @brief quit keyword implementation
|
/// @brief quit keyword implementation
|
||||||
///
|
///
|
||||||
|
@ -88,6 +84,10 @@ void program::RpnHelp() {
|
||||||
cout << endl;
|
cout << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief welcome string
|
||||||
|
///
|
||||||
|
void program::Welcome() { cout << _welcome << endl; }
|
||||||
|
|
||||||
/// @brief whether a printed precision is in the precision min/max
|
/// @brief whether a printed precision is in the precision min/max
|
||||||
///
|
///
|
||||||
/// @param precision the precision in digits
|
/// @param precision the precision in digits
|
||||||
|
|
|
@ -1,29 +1,24 @@
|
||||||
// Copyright (c) 2014-2022 Louis Rubet
|
// Copyright (c) 2014-2022 Louis Rubet
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
using namespace std::chrono;
|
||||||
|
|
||||||
#include "program.h"
|
#include "program.h"
|
||||||
|
|
||||||
/// @brief time keyword implementation
|
/// @brief time keyword implementation
|
||||||
///
|
///
|
||||||
void program::RpnTime() {
|
void program::RpnTime() {
|
||||||
struct timespec ts;
|
std::time_t rawtime = system_clock::to_time_t(system_clock::now());
|
||||||
struct tm* tm;
|
struct tm tm;
|
||||||
double date;
|
|
||||||
|
|
||||||
// get local date
|
if (localtime_r(&rawtime, &tm) != nullptr) {
|
||||||
clock_gettime(CLOCK_REALTIME, &ts);
|
char buffer[80];
|
||||||
time_t time = (time_t)ts.tv_sec;
|
size_t sz = strftime(buffer, sizeof(buffer), "%T", &tm);
|
||||||
tm = localtime(&time);
|
if (sz > 0)
|
||||||
if (tm != nullptr) {
|
stack_.push(new String(buffer));
|
||||||
// date format = HH.MMSSssssss
|
else
|
||||||
date = (static_cast<double>(tm->tm_hour) * 10000000000.0 + static_cast<double>(tm->tm_min) * 100000000.0 +
|
ERROR_CONTEXT(kInternalError);
|
||||||
static_cast<double>(tm->tm_sec) * 1000000.0 + static_cast<double>(ts.tv_nsec / 1000));
|
|
||||||
|
|
||||||
// push it
|
|
||||||
// division after push for real precision
|
|
||||||
stack_.push(new Number(date));
|
|
||||||
stack_.value<Number>(0) /= 10000000000.0;
|
|
||||||
} else {
|
} else {
|
||||||
ERROR_CONTEXT(kInternalError);
|
ERROR_CONTEXT(kInternalError);
|
||||||
}
|
}
|
||||||
|
@ -32,21 +27,16 @@ void program::RpnTime() {
|
||||||
/// @brief date keyword implementation
|
/// @brief date keyword implementation
|
||||||
///
|
///
|
||||||
void program::RpnDate() {
|
void program::RpnDate() {
|
||||||
struct timespec ts;
|
std::time_t rawtime = system_clock::to_time_t(system_clock::now());
|
||||||
struct tm* tm;
|
struct tm tm;
|
||||||
double date;
|
|
||||||
|
|
||||||
// get local date
|
if (localtime_r(&rawtime, &tm) != nullptr) {
|
||||||
clock_gettime(CLOCK_REALTIME, &ts);
|
char buffer[80];
|
||||||
time_t time = (time_t)ts.tv_sec;
|
size_t sz = strftime(buffer, sizeof(buffer), "%F", &tm);
|
||||||
tm = localtime(&time);
|
if (sz > 0)
|
||||||
if (tm != nullptr) {
|
stack_.push(new String(buffer));
|
||||||
// date format = (M)M.DDYYYY
|
else
|
||||||
date = static_cast<double>(tm->tm_mon + 1) * 1000000.0 + static_cast<double>(tm->tm_mday) * 10000.0 +
|
ERROR_CONTEXT(kInternalError);
|
||||||
static_cast<double>(tm->tm_year + 1900);
|
|
||||||
// division after push for real precision
|
|
||||||
stack_.push(new Number(date));
|
|
||||||
stack_.value<Number>(0) /= 1000000.0;
|
|
||||||
} else {
|
} else {
|
||||||
ERROR_CONTEXT(kInternalError);
|
ERROR_CONTEXT(kInternalError);
|
||||||
}
|
}
|
||||||
|
@ -55,19 +45,6 @@ void program::RpnDate() {
|
||||||
/// @brief ticks keyword implementation
|
/// @brief ticks keyword implementation
|
||||||
///
|
///
|
||||||
void program::RpnTicks() {
|
void program::RpnTicks() {
|
||||||
struct timespec ts;
|
uint64_t time_span = (uint64_t)duration_cast<microseconds>(high_resolution_clock::now().time_since_epoch()).count();
|
||||||
struct tm* tm;
|
stack_.push(new Number(time_span));
|
||||||
double date;
|
|
||||||
|
|
||||||
// get local date
|
|
||||||
clock_gettime(CLOCK_REALTIME, &ts);
|
|
||||||
time_t time = (time_t)ts.tv_sec;
|
|
||||||
tm = localtime(&time);
|
|
||||||
if (tm != nullptr) {
|
|
||||||
// date in µs
|
|
||||||
date = 1000000.0 * static_cast<double>(ts.tv_sec) + static_cast<double>(ts.tv_nsec / 1000);
|
|
||||||
stack_.push(new Number(date));
|
|
||||||
} else {
|
|
||||||
ERROR_CONTEXT(kInternalError);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
-> error should be 0
|
-> error should be 0
|
||||||
|
|
||||||
-> stack should be "number"
|
-> stack should be "string"
|
||||||
|
|
||||||
`del`
|
`del`
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
-> error should be 0
|
-> error should be 0
|
||||||
|
|
||||||
-> stack should be "number"
|
-> stack should be "string"
|
||||||
|
|
||||||
`del`
|
`del`
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue