Added 10 more gists.

This commit is contained in:
Miguel Astor
2023-06-20 22:03:49 -04:00
parent 1400a87eab
commit 22ff5bfa25
19 changed files with 1642 additions and 0 deletions

1
ts.c/README.md Normal file
View File

@@ -0,0 +1 @@
A naive interpreter for the Toadskin esoteric language: [https://esolangs.org/wiki/Toadskin](https://esolangs.org/wiki/Toadskin)

236
ts.c/ts.c Normal file
View File

@@ -0,0 +1,236 @@
/***************************************************************************
* This is free and unencumbered software released into the public domain. *
* *
* Anyone is free to copy, modify, publish, use, compile, sell, or *
* distribute this software, either in source code form or as a compiled *
* binary, for any purpose, commercial or non-commercial, and by any *
* means. *
* *
* In jurisdictions that recognize copyright laws, the author or authors *
* of this software dedicate any and all copyright interest in the *
* software to the public domain. We make this dedication for the benefit *
* of the public at large and to the detriment of our heirs and *
* successors. We intend this dedication to be an overt act of *
* relinquishment in perpetuity of all present and future rights to this *
* software under copyright law. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR *
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
* OTHER DEALINGS IN THE SOFTWARE. *
* *
* For more information, please refer to <http://unlicense.org/> *
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STACK_SIZE 40
#define DICT_SIZE 128
#define MAX_PROC 513
#define JMP_SIZE 1024
// Procedure dictionary.
typedef struct DICTIONARY_ENTRY {
char code[MAX_PROC];
} entry_t;
entry_t dictionary[DICT_SIZE];
// Argument stack.
unsigned char stack[STACK_SIZE];
unsigned char * sp = stack;
// Jump stack
long jump[JMP_SIZE];
long * jp = jump;
// Argument register.
unsigned char arg = 0;
// Program counter and instruction register.
char ir;
// Execute simple instructions.
void execute(char c) {
unsigned char aux;
int i;
switch (c) {
case '+':
// ADD
arg++;
break;
case '-':
// SUB
arg--;
break;
case '<':
// PUSH
*sp++ = arg;
arg = 0;
sp = (sp >= &stack[STACK_SIZE]) ? (sp = stack) : sp;
break;
case '>':
// POP
arg = *--sp;
sp = (sp < stack) ? (sp = &stack[STACK_SIZE - 1]) : sp;
break;
case '.':
// PRINT
fputc((int)arg, stdout);
fflush(stdout);
break;
case ',':
// READ
arg = (unsigned char)fgetc(stdin);
break;
case '%':
// SWAP
aux = *sp;
*sp = *(sp - 1);
*(sp - 1) = aux;
break;
default:
// Check if the character is a procedure name, otherwise ignore it.
if ((unsigned char)c < 128 && strlen(dictionary[c].code) > 0) {
for (i = 0; dictionary[c].code[i]; i++)
execute(dictionary[c].code[i]);
break;
}
break;
}
}
int main(int argc, char ** argv) {
unsigned char aux;
char key, inst;
int i, lc;
// Check if there is an input file.
if (argc == 1) {
fprintf(stderr, "%s: fatal error: no input files\n", argv[0]);
fprintf(stderr, "Usage: %s FILE\n", argv[0]);
return EXIT_FAILURE;
}
// Clean initial memory.
memset(stack, 0, STACK_SIZE * sizeof(char));
memset(jump, 0, JMP_SIZE * sizeof(long));
memset(dictionary, 0, DICT_SIZE * sizeof(entry_t));
FILE * prog = fopen(argv[1], "r");
if (prog != NULL) {
ir = (char)fgetc(prog);
while (!feof(prog)) {
switch (ir) {
case '+': // ADD
case '-': // SUB
case '>': // POP
case '<': // PUSH
case '.': // PRINT
case ',': // READ
case '%': // SWAP
// Execute these instructions directly.
execute(ir);
break;
case ':': // Define procedure.
// Read procedure name and check if it's valid.
key = (char)fgetc(prog);
if ((unsigned char)key > 128) {
fprintf(stderr, "%s: runtime error: invalid procedure name 0x%X\n", argv[0], (int)key);
return EXIT_FAILURE;
}
// Read procedure code.
i = 0;
for (inst = (char)fgetc(prog); inst != ';'; inst = (char)fgetc(prog)) {
// Check if code is not too long.
if (i >= MAX_PROC) {
fprintf(stderr, "%s: runtime error: procedure %c too long\n", argv[0], key);
return EXIT_FAILURE;
}
// Check for premature EOF.
if (feof(prog)) {
fprintf(stderr, "%s: runtime error: premature EOF while reading procedure %c\n", argv[0], key);
return EXIT_FAILURE;
}
// Save instruction.
dictionary[key].code[i++] = inst;
}
break;
case '[': // Loop start.
// Check value of the Argument register.
if (arg) {
// If not zero then add this loop's address to the jump stack.
*jp = ftell(prog) - 1;
jp++;
// Check for loop stack overflow.
if (jp >= &jump[JMP_SIZE]) {
fprintf(stderr, "%s: runtime error: too many nested loops\n", argv[0]);
return EXIT_FAILURE;
}
} else {
// Nested loop counter.
lc = 1;
// If not zero then read the instruction stream until the matching ] is found.
inst = (char)fgetc(prog);
while (!feof(prog)) {
if (inst == '[')
lc++;
else if (inst == ']')
lc--;
if (lc == 0)
break;
inst = (char)fgetc(prog);
}
// Check for premature EOF.
if (feof(prog)) {
fprintf(stderr, "%s: runtime error: premature EOF\n", argv[0]);
return EXIT_FAILURE;
}
}
break;
case ']': // Loop end.
// Check for loop stack underflow.
if (jp <= jump) {
fprintf(stderr, "%s: runtime error: mismatched ]\n", argv[0]);
return EXIT_FAILURE;
}
// Pop the loop address from the stack and jump.
fseek(prog, *--jp, SEEK_SET);
break;
default:
// Check if the character is a procedure name, otherwise ignore it.
if ((unsigned char)ir < 128 && strlen(dictionary[ir].code) > 0) {
for (i = 0; dictionary[ir].code[i]; i++)
execute(dictionary[ir].code[i]);
break;
}
break;
}
// Fetch next instruction.
ir = (char)fgetc(prog);
}
fclose(prog);
} else {
// Bad stuff happened!
perror("bad input");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}