Figured out termios
This commit is contained in:
@@ -4,6 +4,8 @@ Equi is a general-purpose 16-bit stack-based platform (and a programming languag
|
|||||||
|
|
||||||
The name Equi comes from the fact each source code instruction is **equi**valent to a machine instruction. No, it isn't mapped to one machine instruction. It **is the** machine instruction. All the instructions and data in Equi are represented with printable ASCII characters only. This allows to bootstrap Equi code directly from the keyboard (any standard keyboard/keypad that allows serial input) using a tiny interpreter stored, for instance, in the hardware ROM.
|
The name Equi comes from the fact each source code instruction is **equi**valent to a machine instruction. No, it isn't mapped to one machine instruction. It **is the** machine instruction. All the instructions and data in Equi are represented with printable ASCII characters only. This allows to bootstrap Equi code directly from the keyboard (any standard keyboard/keypad that allows serial input) using a tiny interpreter stored, for instance, in the hardware ROM.
|
||||||
|
|
||||||
|
This document describes a more-or-less formal specification. For a tutorial on how to use it, please read the [Programming in Equi](programming-in-equi.md) book.
|
||||||
|
|
||||||
## Specification
|
## Specification
|
||||||
|
|
||||||
Main features of an Equi machine:
|
Main features of an Equi machine:
|
||||||
@@ -84,16 +86,16 @@ Op |Stack state |Meaning
|
|||||||
`:`|`( -- )` |Compilation mode start: set CM flag and set CBP to PC+1 value
|
`:`|`( -- )` |Compilation mode start: set CM flag and set CBP to PC+1 value
|
||||||
`;`|`( -- )` |Compilation mode end: replace this instruction in-memory with `R` instruction, pop all characters from the literal stack, append the lookup table with their CRC16 hash and CBP value, unset the CM flag and increment CLTP value
|
`;`|`( -- )` |Compilation mode end: replace this instruction in-memory with `R` instruction, pop all characters from the literal stack, append the lookup table with their CRC16 hash and CBP value, unset the CM flag and increment CLTP value
|
||||||
`'`|`( -- )` |Call the compiled word: pop all characters from the literal stack, compute their CRC16 hash, look it up in CLT for a CBP value, set PC to CBP if found, error out if not, then push PC to return stack and set PC to the CBP value
|
`'`|`( -- )` |Call the compiled word: pop all characters from the literal stack, compute their CRC16 hash, look it up in CLT for a CBP value, set PC to CBP if found, error out if not, then push PC to return stack and set PC to the CBP value
|
||||||
`R`|`( -- )` |**R**eturn: pop and assign the PC value from the return stack
|
`R`|R: `( a -- )` |**R**eturn: pop and assign the PC value from the return stack
|
||||||
`]`|`( a -- )` |Pop the value from main stack and push onto return stack
|
`]`|M: `( a -- )` R: `( -- a )` |Pop the value from main stack and push onto return stack
|
||||||
`[`|`( -- a )` |Pop the value from return stack and push onto main stack
|
`[`|M: `( -- a )` R: `( a -- )` |Pop the value from return stack and push onto main stack
|
||||||
`L`|`( addr -- a` ) |**L**oad a 16-bit value from `addr`
|
`L`|`( addr -- a` ) |**L**oad a 16-bit value from `addr`
|
||||||
`S`|`( a addr -- )` |**S**tore a 16-bit value into `addr`
|
`S`|`( a addr -- )` |**S**tore a 16-bit value into `addr`
|
||||||
`W`|`( a addr -- )` |**W**rite a 8-bit value into `addr` (note that both value and address still must be 16-bit, the higher byte of the value is discarded)
|
`W`|`( a addr -- )` |**W**rite a 8-bit value into `addr` (note that both value and address still must be 16-bit, the higher byte of the value is discarded)
|
||||||
`!`|`( a -- )` |Drop the top value from the stack
|
`!`|`( a -- )` |Drop the top value from the stack
|
||||||
`$`|`( a -- a a )` |Duplicate the top value on the stack
|
`$`|`( a -- a a )` |Duplicate the top value on the stack
|
||||||
`%`|`( a b -- b a )` |Swap two top values on the stack
|
`%`|`( a b -- b a )` |Swap top two values on the stack
|
||||||
`@`|`( a b c -- b c a )` |Rotate three top values on the stack
|
`@`|`( a b c -- b c a )` |Rotate top three values on the stack
|
||||||
`\`|`( a b -- a b a )` |Copy over the second value on the stack
|
`\`|`( a b -- a b a )` |Copy over the second value on the stack
|
||||||
`J`|`( rel -- )` |**J**ump: increase or decrease PC according to the relative value (treated as signed, from -32768 to 32767)
|
`J`|`( rel -- )` |**J**ump: increase or decrease PC according to the relative value (treated as signed, from -32768 to 32767)
|
||||||
`I`|`( cond rel -- ) ` |Pop relative value and condition. **I**f the condition value is not zero, `J` to the relative value
|
`I`|`( cond rel -- ) ` |Pop relative value and condition. **I**f the condition value is not zero, `J` to the relative value
|
||||||
|
|||||||
@@ -13,12 +13,19 @@
|
|||||||
|
|
||||||
#ifdef __TINYC__
|
#ifdef __TINYC__
|
||||||
#include <tcclib.h>
|
#include <tcclib.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
#define stderr 2
|
#define stderr 2
|
||||||
#define SEEK_SET 0
|
#define SEEK_SET 0
|
||||||
#else
|
#else
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -723,9 +730,11 @@ int main(int argc, char* argv[]) {
|
|||||||
int host_islittle = 1;
|
int host_islittle = 1;
|
||||||
host_islittle = (*((char *)&host_islittle) == 1) ? 1 : 0;
|
host_islittle = (*((char *)&host_islittle) == 1) ? 1 : 0;
|
||||||
/* _attempt_ to disable buffering for char input/output */
|
/* _attempt_ to disable buffering for char input/output */
|
||||||
#if !defined __CC65__ && !defined __TINYC__
|
#if !defined __CC65__
|
||||||
setvbuf(stdin, NULL, _IONBF, 0);
|
struct termios tty_opts_raw, tty_opts_backup;
|
||||||
setvbuf(stdout, NULL, _IONBF, 0);
|
tcgetattr(STDIN_FILENO, &tty_opts_backup);
|
||||||
|
cfmakeraw(&tty_opts_raw);
|
||||||
|
tcsetattr(STDIN_FILENO, TCSANOW, &tty_opts_raw);
|
||||||
#endif
|
#endif
|
||||||
/* initialize the PRNG */
|
/* initialize the PRNG */
|
||||||
srand((unsigned)time(NULL));
|
srand((unsigned)time(NULL));
|
||||||
@@ -736,8 +745,10 @@ int main(int argc, char* argv[]) {
|
|||||||
ram.cmd_size = CMD_BUF_SIZE;
|
ram.cmd_size = CMD_BUF_SIZE;
|
||||||
ram.II = ram.MM = 0; /* reset all flags */
|
ram.II = ram.MM = 0; /* reset all flags */
|
||||||
/* process command line params */
|
/* process command line params */
|
||||||
if(argc > 1 && argv[1][0] == 'm') /* enter minification mode, don't run the programs */
|
if(argc > 1 && argv[1][0] == 'm') { /* enter minification mode, don't run the programs */
|
||||||
ram.MM = 1;
|
ram.MM = 1;
|
||||||
|
smode = 1; /* also behave as if in the silent mode */
|
||||||
|
}
|
||||||
else if(argc > 1 && argv[1][0] == 's') /* enter silent mode, don't print the banners and prompts */
|
else if(argc > 1 && argv[1][0] == 's') /* enter silent mode, don't print the banners and prompts */
|
||||||
smode = 1;
|
smode = 1;
|
||||||
/* Start input buffering from the start of command buffer (-1 because we use prefix increment) */
|
/* Start input buffering from the start of command buffer (-1 because we use prefix increment) */
|
||||||
@@ -750,26 +761,25 @@ int main(int argc, char* argv[]) {
|
|||||||
#else /* VT100-compatible terminal init */
|
#else /* VT100-compatible terminal init */
|
||||||
printf("\033c");
|
printf("\033c");
|
||||||
#endif
|
#endif
|
||||||
printf("Welcome to Equi v" EQUI_VER " by Luxferre, 2022\nSystem RAM: %d bytes\nEqui ready\n\n> ", (int) sizeof(ram));
|
printf("Welcome to Equi v" EQUI_VER " by Luxferre, 2022\r\nSystem RAM: %d bytes\r\nEqui ready\r\n\r\n> ", (int) sizeof(ram));
|
||||||
}
|
}
|
||||||
|
|
||||||
while(1) { /* Now, we're in the command mode loop */
|
while(1) { /* Now, we're in the command mode loop */
|
||||||
instr = cgetc(); /* Fetch the next instruction from the keyboard/stdin */
|
instr = cgetc(); /* Fetch the next instruction from the keyboard/stdin */
|
||||||
if(instr == 0xFFU || instr == 0U) /* exit on zero byte */
|
if(instr == 0xFFU || instr == 0U || instr == 3U || instr == 4U) /* exit on zero byte or ctrl+C or ctrl+D */
|
||||||
break;
|
break;
|
||||||
else if(instr == BS || instr == CR || instr == LF || instr == ' ' || instr == '\t') { /* ignore the backspace or whitespaces */
|
else if(instr == BS || instr == CR || instr == LF || instr == ' ' || instr == '\t') { /* ignore the backspace or whitespaces */
|
||||||
#ifdef __CC65__
|
if(!smode)
|
||||||
cputc(instr); /* echo it */
|
cputc(instr); /* echo it if not in silent mode */
|
||||||
#endif
|
if(instr == CR)
|
||||||
|
cputc(LF);
|
||||||
} else if(instr == INS_IISTART) { /* process II start */
|
} else if(instr == INS_IISTART) { /* process II start */
|
||||||
#ifdef __CC65__
|
if(!smode)
|
||||||
cputc(instr); /* echo it */
|
cputc(instr); /* echo it if not in silent mode */
|
||||||
#endif
|
|
||||||
ram.II = 1;
|
ram.II = 1;
|
||||||
} else if(instr == INS_IIEND) { /* process II end */
|
} else if(instr == INS_IIEND) { /* process II end */
|
||||||
#ifdef __CC65__
|
if(!smode)
|
||||||
cputc(instr); /* echo it */
|
cputc(instr); /* echo it if not in silent mode */
|
||||||
#endif
|
|
||||||
ram.II = 0;
|
ram.II = 0;
|
||||||
} else if(!ram.II && instr == INS_QUIT) {
|
} else if(!ram.II && instr == INS_QUIT) {
|
||||||
if(ram.MM) { /* output command buffer contents to stdout and exit */
|
if(ram.MM) { /* output command buffer contents to stdout and exit */
|
||||||
@@ -798,10 +808,13 @@ int main(int argc, char* argv[]) {
|
|||||||
} else { /* append the instruction/character to the command buffer if and only if it doesn't match the above criteria and we're not in II mode */
|
} else { /* append the instruction/character to the command buffer if and only if it doesn't match the above criteria and we're not in II mode */
|
||||||
if(!ram.II)
|
if(!ram.II)
|
||||||
ram.cmdbuf[++ram.ibp] = instr;
|
ram.cmdbuf[++ram.ibp] = instr;
|
||||||
#ifdef __CC65__
|
if(!smode)
|
||||||
cputc(instr); /* echo it */
|
cputc(instr); /* echo it if not in silent mode */
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
} /* command mode loop end */
|
} /* command mode loop end */
|
||||||
|
#if !defined __CC65__ && !defined __TINYC__
|
||||||
|
/* restore the terminal settings */
|
||||||
|
tcsetattr(STDIN_FILENO, TCSANOW, &tty_opts_backup);
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user