initialize

This commit is contained in:
Pratyush Desai 2021-11-03 08:59:33 +05:30
commit baffac466d
Signed by: pratyush
GPG Key ID: DBA5BB7505946FAD
50 changed files with 6100 additions and 0 deletions

8
.gitignore vendored Executable file
View File

@ -0,0 +1,8 @@
*~
\#*\#
*.o
calc.*
botforth
db
log
l

4
LICENSE Normal file
View File

@ -0,0 +1,4 @@
dieser kram ist nicht gpl oder sonstwas, sondern gehoert Florian Amrhein,
http://florian-amrhein.de
alles weitere bedarf ner absprache.

25
Makefile Normal file
View File

@ -0,0 +1,25 @@
CC = gcc
CFLAGS = -g -D_GNU_SOURCE -std=gnu11 -O0 -Og -Wall -Wextra -Werror
LIBS = -lz -lm -lcdb -ldb
OBJECTS = vector.o node.o sql.o intcommands.o file.o db_cdb.o db_bdb.o com.o botforth.o
HEADERS = def.h botforth.h com.h node.h vector.h
all: botforth db
makeintcommand:
./makeintcommand.sh > getintcommand.c
botforth: $(OBJECTS)
$(CC) $(CFLAGS) -o botforth $(OBJECTS) $(LIBS)
$(OBJECTS): $(HEADERS)
db: vector.o node.o file.o db_cdb.o db_bdb.o db.o
$(CC) $(CFLAGS) -o db vector.o node.o file.o db_cdb.o db_bdb.o db.o $(LIBS)
static: $(OBJECTS)
$(CC) $(CFLAGS) -static -o botforth $(OBJECTS) $(LIBS)
clean:
rm -f *.o

115
README Normal file
View File

@ -0,0 +1,115 @@
doku? gibts nicht.
organisation des infoblocks:
1. accesslevel
2. name
3. clearcache
4. cachename
hier der text, den ich zum entwurf verwendet habe. eher veraltet:
Programmfestspeicher
====================
Vorerst einfach auf Festplatte in einem Verzeichnis.
Datenfestspeicher
=================
Noch garnicht, später vielleicht auch Festplatte, oder mysql, oder wie auch
immer.
Datenarbeitsspeicher
====================
Doppelt verkettete Liste, jedes Element kann zusätzlich einen Namen haben.
Zugriff entweder durch push/pop bzw. shift/unshift, über eine Nummer wie bei
einem Array oder über seinen Namen wie bei einem Hash.
Es ist aber auch möglich, direkt über einen Pointer zuzugreifen. Pointer
lassen sich jedoch nicht vom Benutzer direkt erstellen, sondern nur von
entsprechend priviligierten Programmen.
Im ersten Entwurf würde man Elemente, auf die per Nummer oder Namen
zugegriffen wird, durch naive Suche finden. Später kann man ja noch einen
Index oder ähnliches drauf setzen.
Diese Speicherstruktur nenne ich "vector".
Datentypen:
Nach Außen hin sollen nur wenige verschiedene Datentypen sichtbar sein:
- Wert (integer, string, was auch immer)
- Vector
Wert wird intern in mehrere subtypen unterteilt, die jedoch automatisch
bei Bedarf konvertiert werden:
- int
- float
- string, bzw. pointer auf string
- pointer auf Elemente eines Vektors
Aus technischer Sicht gibt es nach Außen hin eigentlich auch nicht die
Unterscheidung zwischen Wert und vector. Auch hier kann und wird bei Bedarf
eine automatische Konvertierung vorgenommen. Im Normalfall wird jedoch der
Anwender dies nicht tun, und in der Dokumentation wird auch immer ein klarer
Unterschied zwischen normalen Werten und Vektoren gemacht.
Ein Sonderfall ist der Pointer auf Elemente eines Vektors: Weder kann von
einem Wert in diesen Typ konvertiert werden, noch anders herum (bzw. doch,
aber dann käme nur ein String "pointer" oder 0 bei heraus).
Die einzelnen Elemente eines Vektors werden in einem union gespeichert. Der
Union enthält die verschiedenen möglichen Ausprägungen der Werte, also int,
float, und pointer. Zudem gibt es ein Feld, in dem gespeichert wird, welche
Ausprägung gerade "aktiv" ist.
Ein zusätzlicher Typ, den man später noch hinzufügen könnte wäre "array".
Dieser Typ würde sich zum Speichern größerer Datenmengen eignen, da er
gegenüber einem Vektor keinen Overhead pro Element hätte.
Programmarbeitsspeicher
=======================
Der Programmspeicher ist nichts anderes als normaler Datenspeicher. Dies
macht es möglich, Compilererweiterungen selbst in botforth zu schreiben.
minibotforth
============
Folgende Befehle müssen implementiert werden:
- swap
- +
...
minibotforth sollte so extrem simpel sein, daß man es später vielleicht
sogar ganz weg lassen kann, um direkt nach Maschinensprache zu kompilieren.
Compiler von botforth nach minibotforth
========================================
1. Schritt: lexikalische analyse, also erkennen der einzelnen
schluesselworte usw.
Hier wird zwar erkannt, was ein Befehl ist, aber noch nicht, ob der Befehl
intern oder extern vorliegt. Jeder Befehl wird als Node vom Typ
BF_TYPE_C_TEXT gespeichert, wobei der Befehlsname in Klartext als String
abgelegt wird.
2. Schritt: Compiler. Hier wird botforth nach minibotforth gewandelt. Auch
hier werden jedoch Befehlsnamen als BF_TYPE_C_TEXT abgelegt.
3. Ausführung: Erst während der Programmausführung, also wenn wir uns schon
längst nicht mehr im Compilermodus befinden, werden Befehle vom Typ
BF_TYPE_C_TEXT, sobald sie ausgeführt werden sollen, in BF_TYPE_C_INT bzw.
BF_TYPE_C_EXT gewandelt.
Dies dient dazu, den Compiler vom User erweiterbar zu halten. Er kann so
leicht Befehle einfügen, ohne mit Pointern etc. rumspielen zu müssen. Somit
wird auch kein Sicherheitsloch erzeugt. Aus der Sicht eines Anwenders, der
den Compiler durch das Programmieren von Compilezeitverhaltens von Befehlen
erweitern will, sind Befehle quasi wie Strings zu handhaben.

947
botforth.c Normal file
View File

@ -0,0 +1,947 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <string.h>
#include "botforth.h"
// CDB-Krempel
extern void cdb_startup();
// Berkeley-DB-Krempel
extern void bdb_init();
int infoblock_get_accesslevel(struct vector *word)
{
struct vector *infoblock;
assert(word);
infoblock = word->head->content;
return *(int *) infoblock->head->content;
}
void infoblock_set_accesslevel(struct vector *word, int al)
{
struct vector *infoblock;
assert(word);
infoblock = word->head->content;
*(int *) infoblock->head->content = al;
}
char *infoblock_get_name(struct vector *word)
{
struct vector *infoblock;
assert(word);
infoblock = word->head->content;
return infoblock->head->next->content;
}
void infoblock_set_name(struct vector *word, char *name)
{
struct vector *infoblock;
assert(word);
infoblock = word->head->content;
// problem hier
//(char*)infoblock->head->next->content=name;
infoblock->head->next->content = name;
}
/*
* welchen typ hat ein string in wirklichkeit? int? float? string?
*/
int get_stringtype(char *s)
{
int z = 0; // zustand
unsigned i;
char c; // aktuelles zeichen
int ret = -1;
for (i = 0; i <= strlen(s); i++) {
c = s[i];
switch (z) {
case 0:
if (c == '\0') // schon zuende, pech gehat
ret = BF_TYPE_STRING;
if (c == '-' || c == '+')
z = 1; // ein vorzeichen
if (c >= '0' && c <= '9')
z = 2; // eine zahl beginnt
if (z == 0) // nichts gefunden? schade.
ret = BF_TYPE_STRING;
break;
case 1: // Vorzeichen
if (c >= '0' && c <= '9')
z = 2; // eine zahl beginnt
if (z == 1 && ret == -1) // nichts gefunden? schade.
ret = BF_TYPE_STRING;
break;
case 2: // Zahl nach Vorzeichen
z = 0;
if (c >= '0' && c <= '9')
z = 2; // die zahl geht weiter, gut.
if (c == '\0') // zuende? gut, int erkannt.
ret = BF_TYPE_INT;
if (c == '.')
z = 17; // koennte floating-point sein.
if (c == 'e' || c == 'E')
z = 19; // exponent von floating-point zahl
if (z == 0 && ret == -1) // nichts gefunden? schade.
ret = BF_TYPE_STRING;
break;
case 17: // floating-point, direkt nach dem .
if (c >= '0' && c <= '9')
z = 18; // ist wohl doch noch ne ziffer, prima.
if (c == 'e' || c == 'E')
z = 19; // exponent erkannt
if (c == '\0') // schon vorbei? das reicht nicht.
ret = BF_TYPE_STRING;
if (z == 17 && ret == -1) // nichts gefunden? schade.
ret = BF_TYPE_STRING;
break;
case 18: // ziffern nach dem .
z = 0;
if (c >= '0' && c <= '9')
z = 18; // ist wohl doch noch ne ziffer, prima.
if (c == 'e' || c == 'E')
z = 19; // exponent erkannt
if (c == '\0')
ret = BF_TYPE_FLOAT; // prima, float erkannt
if (z == 0 && ret == -1) // nichts gefunden? schade.
ret = BF_TYPE_STRING;
break;
case 19: // floating-point: e
z = 0; // wenns sonst nichts ist, ists ein string
if (c == '+' || c == '-')
z = 20; // ein vorzeichen
if (c >= '0' && c <= '9')
z = 21; // schoen, eine ziffer
if (z == 0) // nichts gefunden? schade.
ret = BF_TYPE_STRING;
break;
case 20: // floating-point: vorzeichen nach e
z = 0; // wie immer, wenns sonst nix ist, ists ein string
if (c >= '0' && c <= '9')
z = 21; // schoen, eine ziffer
if (z == 0 && ret == -1) // nichts gefunden? schade.
ret = BF_TYPE_STRING;
break;
case 21: // floating-point: ziffern nach e
z = 0; // wenns sonst nichts ist, ists ein befehl
if (c >= '0' && c <= '9')
z = 21; // gut, noch immer eine ziffer
if (c == '\0')
ret = BF_TYPE_FLOAT;
if (z == 0 && ret == -1) // nichts gefunden? schade.
ret = BF_TYPE_STRING;
break;
}
if (ret > -1) {
return ret;
}
}
return BF_TYPE_STRING;
}
/*
* Lexikalische Analyse eines botforth-programms
*
* progstring: Das Programm als String
*
* return: vector, der die einzelnen Symbole des Programms enthält
*/
struct vector *botforth_parse(char *progstring)
{
struct vector *program = vector_create();
struct vector *infoblock = vector_create();
int lineend(char c) {
if (c == '\r' || c == '\n' || c == '\0')
return 1;
return 0;
}
int whitespace(char c) {
if (c == ' ' || c == '\t' || lineend(c))
return 1;
return 0;
}
void addsymbol(char *progstring, int *first, int last, int type) {
struct node *symb = 0;
char *item;
int itemlen;
int *i;
float *f;
printf("neues Symbol\n");
itemlen = last - (*first) + 1;
//assert(itemlen>0);
item = malloc(itemlen + 1);
assert(item != 0);
strncpy(item, progstring + (*first) - 1, itemlen);
item[itemlen] = 0;
//printf("Symbol erkannt: %s (%i)\n",item,type);
switch (type) {
case BF_TYPE_STRING:
case BF_TYPE_C_TEXT:
symb = node_create(item, type);
break;
case BF_TYPE_INT:
i = malloc(sizeof(int));
*i = atoi(item);
symb = node_create(i, type);
free(item);
break;
case BF_TYPE_FLOAT:
f = malloc(sizeof(float));
*f = atof(item);
symb = node_create(f, type);
free(item);
break;
}
vector_push(program, symb);
*first = last + 1;
}
int z = 0; // Zustand
char c; // Aktuelles Zeichen
unsigned i;
int first;
char item[255];
char *temps;
int *tempi;
struct node *tempn;
int temp;
// create infoblock
tempi = malloc(sizeof(int));
*tempi = 99;
tempn = node_create(tempi, BF_TYPE_INT);
vector_put(infoblock, "accesslevel", tempn);
temps = malloc(7);
sprintf(temps, "noname");
tempn = node_create(temps, BF_TYPE_STRING);
vector_put(infoblock, "name", tempn);
tempi = malloc(sizeof(int));
*tempi = 0;
tempn = node_create(tempi, BF_TYPE_INT);
vector_put(infoblock, "clearcache", tempn);
// add program infoblock to the programm
vector_put_vector(program, "infoblock", infoblock);
printf("start parser\n");
strcpy(item, "");
first = 1;
for (i = 0; i <= strlen(progstring); i++) {
c = progstring[i];
switch (z) {
case 0:
z = 2; // wenns sonst nix ist, ists ein Befehl
if ((c >= '0') && (c <= '9')) // Vermutlich Zahl, oder Befehl
z = 1;
if (((c >= 'a') && (c <= 'z')) || // Befehl
(c == '.'))
z = 2;
if ((c == '+') || (c == '-')) // Vorzeichen einer Zahl oder Befehl
z = 4;
if (c == '"') // Zeichenkette
z = 5;
if (c == '{') // Befehlszeiger
z = 6;
if (whitespace(c)) // Leerzeichen ist nix
z = 0;
if (c == '/') // Kommentar-Beginn oder Befehl
z = 8;
if (c == '$') // Variable lesen
z = 12;
if (c == '!') // Variable schreiben
z = 14;
break;
case 1: // Zahl
// davon ausgehen, dass es ein befehl wird
z = 2;
if ((c >= '0') && (c <= '9'))
z = 1; // bleibt eine zahl
if (c == '.')
z = 17; // koennte floating-point sein.
if (c == 'e' || c == 'E')
z = 19; // exponent von floating-point zahl
if (whitespace(c)) {
addsymbol(progstring, &first, i,
BF_TYPE_INT);
z = 0; // zahl fertig erkannt
}
break;
case 2: // Befehl
if (whitespace(c)) {
addsymbol(progstring, &first, i,
BF_TYPE_C_TEXT);
z = 0;
}
break;
case 3: // Zeichenkette
if (c == '"') {
addsymbol(progstring, &first, i,
BF_TYPE_STRING);
z = 0;
}
break;
case 4: // Vorzeichen
// wenns sonst nichts ist, ists ein Befehl
z = 2;
if ((c >= 'a') && (c <= 'z')) // Befehl
z = 2;
if ((c >= '0') && (c <= '9')) // Zahl (mit Vorzeichen) oder Befehl
z = 1;
if (whitespace(c)) { // Befehl erkannt
z = 0;
addsymbol(progstring, &first, i,
BF_TYPE_C_TEXT);
}
break;
case 5: // führendes " einer Zeichenkette
// Zeichenkette vielleicht sofort schon wieder zuende?
if (c == '"') {
addsymbol(progstring, &first, i,
BF_TYPE_STRING);
z = 0;
} else
z = 3;
break;
case 6: // Führendes { eines Befehlszeigers
z = 7;
break;
case 7: // Befehlszeiger
if (c == '}') {
addsymbol(progstring, &first, i,
BF_TYPE_C_TEXT);
z = 0;
}
break;
case 8: // Kommentar-Beginn
if (c == '*') {
z = 9; // Ja, wirklich ein Kommentar-Beginn, also weitermachen
first++;
} else if (c == '/') { // ein Zeilenkommentar
z = 11;
first++;
} else if (whitespace(c)) {
addsymbol(progstring, &first, i,
BF_TYPE_C_TEXT);
z = 0;
} else
z = 2;
break;
case 9: // Im Kommentar
first++;
if (c == '*')
z = 10; // Vielleicht hört der Kommentar ja nun auf...
break;
case 10: // Kommentar-Ende
first++;
if (c == '/')
z = 0;
else
z = 9;
break;
case 11: // Zeilenkommentar
first++;
if (lineend(c)) {
z = 0;
}
break;
case 12: // Variable lesen, $-Zeichen
z = 13;
first++;
break;
case 13: // Variable lesen, Variablenname
if (whitespace(c)) {
temp = 1;
addsymbol(progstring, &first, i,
BF_TYPE_STRING);
addsymbol("$", &temp, 1, BF_TYPE_C_TEXT);
z = 0;
}
break;
case 14: // Variable schreiben, !-Zeichen
if (c == '=') {
// koennte sich um != statt um ne variable handeln...
z = 16;
} else if (whitespace(c) || c == '=') {
addsymbol(progstring, &first, i,
BF_TYPE_C_TEXT);
z = 0;
} else {
z = 15;
first++;
}
break;
case 15: // Variable schreiben, Variablenname
if (whitespace(c)) {
temp = 1;
addsymbol(progstring, &first, i,
BF_TYPE_STRING);
addsymbol("!", &temp, 1, BF_TYPE_C_TEXT);
z = 0;
}
break;
case 16: // womoeglich != statt einem Variablen-schreiben
if (whitespace(c)) {
addsymbol(progstring, &first, i,
BF_TYPE_C_TEXT);
z = 0;
} else {
z = 15; // wohl doch nur ein Variablen-lesen, wo aber ein = im Variablenname ist...
}
break;
case 17: // floating-point, direkt nach dem .
z = 2; // wenns sonst nichts ist, ists ein befehl
if (c >= '0' && c <= '9')
z = 18; // ist wohl doch noch ne ziffer, prima.
if (c == 'e' || c == 'E')
z = 19; // exponent erkannt
if (whitespace(c)) { // leerzeichen direkt nach .? kann nur befehl sein
addsymbol(progstring, &first, i, BF_TYPE_C_TEXT); // befehl
z = 0;
}
break;
case 18: // ziffern nach dem .
z = 2; // wenns sonst nichts ist, ists ein befehl
if (c >= '0' && c <= '9')
z = 18; // ist wohl doch noch ne ziffer, prima.
if (c == 'e' || c == 'E')
z = 19; // exponent erkannt
if (whitespace(c)) {
addsymbol(progstring, &first, i, BF_TYPE_FLOAT); // prima, float erkannt
z = 0;
}
break;
case 19: // floating-point: e
z = 2; // wenns sonst nichts ist, ists ein befehl
if (c == '+' || c == '-')
z = 20; // ein vorzeichen
if (c >= '0' && c <= '9')
z = 21; // schoen, eine ziffer
if (whitespace(c)) { // leerzeichen direkt nach e? kann nur befehl sein
addsymbol(progstring, &first, i, BF_TYPE_C_TEXT); // befehl
z = 0;
}
break;
case 20: // floating-point: vorzeichen nach e
z = 2; // wie immer, wenns sonst nix ist, ists ein befehl
if (c >= '0' && c <= '9')
z = 21; // schoen, eine ziffer
if (whitespace(c)) { // leerzeichen direkt nach vorzeichen? kann nur befehl sein
addsymbol(progstring, &first, i, BF_TYPE_C_TEXT); // befehl
z = 0;
}
break;
case 21: // floating-point: ziffern nach e
z = 2; // wenns sonst nichts ist, ists ein befehl
if (c >= '0' && c <= '9')
z = 21; // gut, noch immer eine ziffer
if (whitespace(c)) {
addsymbol(progstring, &first, i, BF_TYPE_FLOAT); // prima, float erkannt
z = 0;
}
break;
}
if ((z == 0) || (z == 5) || (z == 6))
first++;
}
return program;
}
struct vector *word_load(char *name, char *ns)
{
char *word;
char *buffer, *buffer2;
char *tmpns;
struct vector *program;
struct node *lex;
int newaccesslevel;
int *tempint;
struct vector *v, *infoblock;
struct node *n = NULL, *n2 = NULL;
// todo: ueberpruefen, ob lexicon leer ist
assert(lexicon);
assert(name);
buffer = NULL;
v = NULL;
lex = lexicon->tail;
do {
if (buffer)
free(buffer);
if (ns == NULL) {
// search all namespaces
buffer =
malloc(10 + strlen(lex->content) +
strlen(name));
sprintf(buffer, "command/%s/%s",
(char *) lex->content, name);
tmpns = lex->content;
} else {
// only use given namespace
buffer = malloc(10 + strlen(ns) + strlen(name));
sprintf(buffer, "command/%s/%s", ns, name);
tmpns = ns;
}
printf("lade wort: %s\n", buffer);
// set new accesslevel depending on the name of the namespace
newaccesslevel = 3;
if (strcmp(tmpns, "lib") == 0)
newaccesslevel = 2;
if (strcmp(tmpns, "service") == 0)
newaccesslevel = 2;
if (strcmp(tmpns, "bot") == 0)
newaccesslevel = 1;
// is the word in the cache?
n = vector_pick(words, buffer);
if (n) {
if (n->type != BF_TYPE_INT) {
if (n->type == BF_TYPE_VECTOR) {
v = n->content;
printf
("wort %s im cache gefunden\n",
buffer);
} else {
printf
("falscher typ auf dem word-cache\n");
exit(1);
}
} else {
printf("Nur Dummy im Cache gefunden\n");
}
} else {
printf("wort muss von platte geholt werden\n");
v = load_file(buffer);
if (v == NULL) {
// Falls das Programm nicht gefunden wurde: Einen Dummy in den Cache legen
tempint = malloc(sizeof(int));
*tempint = 0;
n2 = node_create(tempint, BF_TYPE_INT);
vector_put(words, buffer, n2);
}
}
lex = lex->prev;
} while (v == NULL && lex != NULL && ns == NULL);
if (v) { // sollte immer erfuellt sein
// ist schon ein fertig kompiliertes programm enthalten?
n = vector_pick(v, "program");
if (n) {
if (n->type == BF_TYPE_VECTOR) {
printf
("vorkompiliertes programm gefunden\n");
program = n->content;
} else {
printf("cache-word ist kein vector\n");
exit(1);
}
} else {
word = vector_pick_string(v, "inhalt");
assert(word != NULL);
program = botforth_parse(word);
// infoblock ergaenzen
infoblock =
(struct vector *) program->head->content;
buffer2 = malloc(strlen(buffer) + 1);
sprintf(buffer2, "%s", buffer);
n2 = node_create(buffer2, BF_TYPE_STRING);
vector_put(infoblock, "cachename", n2);
buffer2 = malloc(strlen(name) + 1);
sprintf(buffer2, "%s", name);
free(infoblock->head->next->content);
infoblock->head->next->content = buffer2;
// update accesslevel in the infoblock
infoblock_set_accesslevel(program, newaccesslevel);
// update program name
buffer2 = malloc(strlen(name) + 1);
sprintf(buffer2, "%s", name);
infoblock_set_name(program, buffer2);
if (program->head == NULL) {
printf("leeres programm: %s\n", word);
}
// todo: speicherleck?
if (program) {
program = botforth_compile(program);
if (program->head) {
// todo: und was wenn nicht? speicherleck?
printf
("Wort im cache speichern\n");
printf("name: %s\n", buffer);
buffer2 = malloc(8);
sprintf(buffer2, "program");
vector_put_vector(v, buffer2,
program);
vector_replace_vector(words,
buffer, v);
}
}
}
return program;
} else {
if (buffer)
free(buffer);
}
return NULL;
}
void botforth_replaceword(struct vector *program)
{
char *cachename, *newcachename;
char *shortname;
struct node *n, *newn;
struct node *oldcache;
struct vector *oldcachecontent;
struct node *newcache;
struct vector *newcachecontent;
struct vector *newprogram;
// Programmname ermitteln
cachename =
(char *) ((struct vector *) program->head->content)->
head->next->next->next->content;
shortname =
(char *) ((struct vector *) program->head->content)->
head->next->content;
printf("name des zu ersetzenden programs %s bzw. %s\n", cachename,
shortname);
// den kompletten Cache-Eintrag zu dem Programm laden
oldcache = vector_get(words, cachename);
oldcachecontent = (struct vector *) oldcache->content;
// altes programm entfernen, aber noch im speicher belassen, wird noch
// durch *program referenziert
vector_get(oldcachecontent, "program");
// rest des alten cacheeintrags komplett loeschen
node_destroy(oldcache);
newprogram = word_load(shortname, NULL);
if (newprogram) {
// wort existiert noch auf platte
newcachename =
(char *) ((struct vector *) program->head->
content)->head->next->next->next->content;
// word_load hat das neue wort auch in den cache geworfen
newcache = vector_pick(words, newcachename);
assert(newcache != NULL);
newcachecontent = (struct vector *) newcache->content;
// Das neue Programm aus den Cacheeintrag rausnehmen, bleibt durch
// *newprogram verzeigert
vector_get(newcachecontent, "program");
// Das alte Programm erstmal in den neuen Cacheeintrag schieben
n = node_create(program, BF_TYPE_VECTOR);
// todo: irgendwas stimmt hier nicht, abstuerze an dieser stelle
vector_replace(newcachecontent, "program", n);
} else {
// programm existiert nicht mehr auf platte. nun wenigstens
// einen platzhalter anlegen
// todo: das sollte man auch mal wirklich richtig machen...
newprogram = vector_create();
printf("programm existiert nicht mehr!\n");
exit(0);
}
// den _inhalt_ des alten programms manuell loeschen
n = program->head;
while (n) {
newn = n->next;
node_destroy(n);
n = newn;
}
// Zeiger anpassen
program->head = newprogram->head;
program->tail = newprogram->tail;
program->size = newprogram->size;
}
void botforth_call(struct vector *program)
{
assert(program != NULL);
// int die tiefenbegrenzung noch nicht erreicht?
//if(rstack->size<50) {
vector_push_node(rstack, pc);
vector_push_vector(rstack, cword);
vector_push_int(rstack, accesslevel);
// soll das programm aus dem cache entfernt werden?
if (*(int *) ((struct vector *) program->head->content)->
head->next->next->content == 1) {
printf("aufruf eines zu loeschenden programms\n");
botforth_replaceword(program);
}
// set the accesslevel
//printf("acceslevel: %i\n",infoblock_get_accesslevel(program));
accesslevel = infoblock_get_accesslevel(program);
// set the program counter to the new word
pc = program->head->next;
cword = program;
//}
}
void botforth_return()
{
int oldaccesslevel;
// todo: speicherleck vielleicht irgendwie?
oldaccesslevel = vector_pop_int(rstack);
(void) oldaccesslevel; // Warnung unterdrücken
cword = vector_pop_vector(rstack);
pc = vector_pop_node(rstack);
if (cword)
accesslevel = infoblock_get_accesslevel(cword);
//printf("ruecksprung\n");
}
void botforth_interpreter(struct vector *program, int withinfoblock)
{
char *command;
void *temppointer;
char *temp;
char *temp2;
int (*fpointer) (); // function pointer
struct vector *newprogram; // temp var for loading new words;
struct node *tempnode;
struct node *c; // pointer to the actual command
cword = program;
pc = program->head;
if (pc == NULL)
return;
if (withinfoblock)
pc = pc->next;
if (pc == NULL)
return;
do {
printf(".");
// increase the program counter and load the new word
c = pc;
assert(c != NULL);
pc = pc->next;
assert(c->content != NULL);
// printf("'%s'(%i) ",node_toString(node_copy(c)),c->type);
switch (c->type) {
case BF_TYPE_C_TEXT: // Befehl in Textform
command = c->content;
//printf("textbefehl: %s\n",command);
if (strlen(command) > 1 && command[0] == '_'
&& command[1] != '_') {
temp2 = infoblock_get_name(cword);
printf("hauptfunktionsname: %s\n", temp2);
temp =
malloc(strlen(temp2) +
strlen(command) + 1);
sprintf(temp, "%s%s", temp2, command);
// free(command); // temp2 muss nicht geloescht werden
command = temp; // problem, wo wird command freigegeben?
// unterfunktionsaufruf
}
temppointer = getintcommand(command);
if (temppointer) {
free(c->content);
c->type = BF_TYPE_C_INT;
c->content = temppointer;
pc = c;
} else {
printf("neues wort laden: %s\n", command);
// load and execute a word
newprogram = word_load(command, NULL);
printf("programm geladen: %s\n", command);
if (newprogram) {
// call the word
botforth_call(newprogram);
// change the program
printf("setze externer befehl\n");
free(c->content);
c->content = newprogram;
c->type = BF_TYPE_C_EXT;
}
}
break;
case BF_TYPE_C_INT: // Interner Befehl
fpointer = c->content;
fpointer();
break;
case BF_TYPE_C_EXT: // Externer Befehl
//printf("externer befehl\n");
if (rstack->size < 8000) {
botforth_call((struct vector *)
c->content);
} else {
printf("RSTACK UEBERGELAUFEN!\n");
}
break;
case BF_TYPE_STRING: // String
temp = malloc(strlen(c->content) + 1);
sprintf(temp, "%s", (char *) c->content);
tempnode = node_create(temp, c->type);
vector_push(dstack, tempnode);
break;
case BF_TYPE_INT: // Integer
case BF_TYPE_FLOAT: // Float
case BF_TYPE_POINTER: // Pointer
tempnode = node_copy(c);
vector_push(dstack, tempnode);
break;
default: // Unbekannt (todo!)
printf("unbekanntes symbol im programm: %i\n",
c->type);
exit(0);
break;
}
// end of the word? have a look at the return stack...
while ((pc == NULL && rstack->tail != NULL) ||
(accesslevel > 1 && runlimit > 0
&& (int) time(NULL) > runlimit)) {
botforth_return();
}
} while (pc != NULL);
printf("Interpreter ende\n");
}
struct vector *botforth_compile(struct vector *word)
{
struct node *n, *newn, *cn, *newcn;
char *buffer;
// char *text;
struct vector *compword;
// struct vector *ncstack;
struct vector *nword = vector_create();
printf("starte compiler\n");
assert(cstack != NULL);
if (word == NULL)
return NULL;
n = word->head;
while (n != NULL) {
newn = n->next;
if (n->type == BF_TYPE_C_TEXT) {
if (getintcommand(n->content)) {
// internal command
// todo: hier direkt die adresse reinsetzen
vector_push(nword, n);
} else {
// external command
// save the environment to estack
//vector_push_vector(estack,lexicon);
vector_push_vector(estack, rstack);
vector_push_node(estack, pc);
vector_push_vector(estack, cword);
// create a new environment
//lexicon=vector_create();
buffer = malloc(9);
sprintf(buffer, "compiler");
vector_push_string(lexicon, buffer);
rstack = vector_create();
// try to load the compiler-word
compword =
word_load(n->content, "compiler");
// restore the old environment
cword = vector_pop_vector(estack);
pc = vector_pop_node(estack);
vector_destroy(rstack);
rstack = vector_pop_vector(estack);
assert(rstack != NULL);
/*
vector_destroy(lexicon);
lexicon=vector_pop_vector(estack);
*/
node_destroy(vector_pop(lexicon));
assert(lexicon != NULL);
if (compword) {
assert(compword->head != NULL); // todo: das sollte weg, leere programme sind ok
printf("kompiliere %s\n",
(char *) n->content);
// save the environment to estack
assert(cstack != NULL);
vector_push_vector(estack, cstack);
vector_push_vector(estack, rstack);
vector_push_node(estack, pc);
vector_push_vector(estack, cword);
// create a new environment
cstack = vector_create();
rstack = vector_create();
// start the interpreter
printf("start interpreter\n");
botforth_interpreter(compword, 1);
printf
("den neuen teil nochmal kompilieren\n");
cstack = botforth_compile(cstack);
// copy the cstack to the new word
printf("umkopieren\n");
cn = cstack->head;
while (cn) {
assert(cn != NULL);
newcn = cn->next;
vector_push(nword, cn);
//newn=cn;
//vector_insert(word,n,cn);
cn = newcn;
}
// restore the old environment
cword = vector_pop_vector(estack);
pc = vector_pop_node(estack);
vector_destroy(rstack);
rstack = vector_pop_vector(estack);
assert(rstack != NULL);
cstack->head = cstack->tail = NULL;
vector_destroy(cstack);
cstack = vector_pop_vector(estack);
assert(cstack != NULL);
node_destroy(n);
} else {
vector_push(nword, n);
}
}
} else {
vector_push(nword, n);
}
n = newn;
}
free(word);
return nword;
}
int main(int argc, char **argv)
{
//struct vector *rstack=vector_create();
struct vector *program;
char *temp;
int i;
words = vector_create();
cstack = vector_create();
rstack = vector_create();
dstack = vector_create();
estack = vector_create();
lstack = vector_create();
// help stacks
zstack = vector_create();
var = vector_create();
lexicon = vector_create();
interpretcounter = 0;
// zufall initialisieren
srand(time(NULL));
cdb_startup();
bdb_init();
// push parameters to dstack
for (i = 1; i < argc; i++) {
temp = malloc(strlen(argv[i]) + 1);
sprintf(temp, "%s", argv[i]);
vector_push_string(dstack, temp);
}
// set lexicon
//temp=malloc(5); sprintf(temp,"dope");
//vector_push_string(lexicon,temp);
temp = malloc(strlen("lib") + 1);
sprintf(temp, "lib");
vector_push_string(lexicon, temp);
temp = malloc(strlen("service") + 1);
sprintf(temp, "service");
vector_push_string(lexicon, temp);
temp = malloc(strlen("bot") + 1);
sprintf(temp, "bot");
vector_push_string(lexicon, temp);
program = word_load("main", "bot");
debug(program);
botforth_interpreter(program, 1);
printf("Datenstapel: ");
debug(dstack);
return 0;
}

59
botforth.h Normal file
View File

@ -0,0 +1,59 @@
#ifndef BOTFORTH_H
#define BOTFORTH_H
#include <stdint.h>
#include "def.h"
#include "vector.h"
#include "node.h"
// einige globale Variablen
struct node *pc; // Program Counter - Zeiger auf den nächsten Befehl
struct vector *cword; // pointer to the actual running word
int accesslevel;
int interpretcounter;
int runlimit;
// stacks
struct vector *rstack; // Return Stack, hält Rücksprungadressen
struct vector *dstack; // Data Stack
struct vector *cstack; // Compiler Stack
struct vector *estack; // Environment Stack for the Compiler
struct vector *lexicon; // In which directories will words be searched
struct vector *var; // Variable stack, for storing variables
struct vector *lstack; // loop-stack
// help stacks
struct vector *zstack;
// speicher fuer fertig kompilierte Worte
struct vector *words;
// irc-kram
int ircsocket;
// botforth functions
struct vector *botforth_compile(struct vector *word);
struct vector *botforth_parse(char *progstring);
int get_stringtype(char *s);
void botforth_interpreter(struct vector *program, int withinfoblock);
void botforth_call(struct vector *program);
void botforth_return();
// getintcommand
void *getintcommand(char *command);
char *getintcommandname(void *p);
// file
struct vector *load_file(char *name);
struct vector *load_rand_file();
struct vector *load_rand_single_cmd();
struct vector *load_rand_cmd();
int iterate(int (*action) (int n, struct vector * content));
extern struct vector *word_load(char *name, char *ns);
extern void infoblock_set_accesslevel(struct vector *word, int al);
extern void infoblock_set_name(struct vector *word, char *name);
extern char *infoblock_get_name(struct vector *word);
#endif

274
com.c Normal file
View File

@ -0,0 +1,274 @@
// com.c - v0.3.1
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#define LINELENGTH 900
#define PORT 6667
int set_socket_timeout(int connectSocket, int milliseconds)
{
struct timeval tv;
tv.tv_sec = milliseconds / 1000;
tv.tv_usec = (milliseconds % 1000) * 1000;
return setsockopt(connectSocket, SOL_SOCKET, SO_RCVTIMEO,
(char *) &tv, sizeof tv);
}
// *************************************************************
// stellt verbindung zum ircd her
// int port = ircd-port
// char *ipnum = ipnummer des ircd in xxx.xxx.xxx.xxx -notation
// return -1 = fehler beim socket-erstellen
// return -2 = fehler beim connecten
// return num>0 = socketfd
//
int connect_irc(int port, char *ipnum)
{
int create_socket = 0;
struct sockaddr_in address;
if ((create_socket = socket(AF_INET, SOCK_STREAM, 0)) > 0)
printf("The Socket was created\n");
else {
fprintf(stderr, "Unable to create socket\n");
return -1;
}
address.sin_family = AF_INET;
assert(port >= 1 && port <= 65535);
address.sin_port = htons(port);
inet_pton(AF_INET, ipnum, &address.sin_addr);
if (connect
(create_socket, (struct sockaddr *) &address,
sizeof(address)) == 0)
printf("The connection was accepted by %s...\n",
inet_ntoa(address.sin_addr));
else {
fprintf(stderr,
"The connection wasn't accepted by %s...\n",
inet_ntoa(address.sin_addr));
return -2;
}
set_socket_timeout(create_socket, 10);
return create_socket;
}
// *************************************************************
// stellt verbindung zum IPv6 ircd her
// int port = ircd-port
// char *ipnum = ipnummer des ircd in
// xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx -notation
// return -1 = fehler beim socket-erstellen
// return -2 = fehler beim connecten
// return num>0 = socketfd
//
int connect_irc6(int port, char *ipnum)
{
return -1; // FIXME
int create_socket = 0;
struct sockaddr_in6 address;
if ((create_socket = socket(AF_INET6, SOCK_STREAM, 0)) > 0)
printf("The Socket was created %s\n", ipnum);
else {
fprintf(stderr, "Unable to create socket\n");
return -1;
}
address.sin6_family = AF_INET6;
assert(port >= 1 && port <= 65535);
address.sin6_port = htons(port);
inet_pton(AF_INET6, ipnum, &address.sin6_addr);
if (connect
(create_socket, (struct sockaddr *) &address,
sizeof(address)) == 0)
printf("The connection was accepted by %s...\n", ipnum);
else {
fprintf(stderr,
"the connection wasn't accepted by %s...\n",
ipnum);
return -2;
}
set_socket_timeout(create_socket, 10);
return create_socket;
}
// **************************************************************
// schliesst den socket / beendet die Verbindung
//
int disconnect_irc(int socketnum)
{
return (close(socketnum));
}
// ***************************************************************
// sendet einen string an den ircd,
// zu lange strings werden nach stelle LINELENGTH-2 abgeschnitten
// und nen CR-LF (also \r\n) angefügt
// int socketnum = socket-handler
// char *msg = zu sendender string (1-LINELENGTH byte)
// return -2 = string leer
// return -1 = fehler in send()
// return num>0 = übertragene bytes
//
int netsend(int socketnum, char *msg)
{
int len = 0, sended = 0;
len = strlen(msg);
assert(len > 0 && len <= LINELENGTH);
//assert(socketnum > 0);
if (len <= 1) {
fprintf(stderr,
"string zu kurz. mindestlänge 2byte (CR-LF)!\n");
return -2;
}
else if (len > LINELENGTH) {
fprintf(stderr,
"string zu lang. maximallänge %dbyte (inkl. CR-LF)! \n",
LINELENGTH);
msg[LINELENGTH + 1] = '\0';
msg[LINELENGTH] = '\n';
msg[LINELENGTH - 1] = '\r';
len = strlen(msg);
}
else
// BAUSTELLE if ( BOTFORTH_CRLF == TRUE )
sended = send(socketnum, msg, len, 0);
if (sended == -1) {
fprintf(stderr, "Failed to send to server\n>%s<\n", msg);
return -1;
}
fprintf(stderr, "sended to server: >%s<\n", msg);
return (sended);
}
// ************************************************
// empfängt eine zeile vom ircd und gibt einen zeiger auf den string zurück.
// jede zeile des ircd SOLLTE mit einem \r\n abgeschlossen sein.
// die zeilenlänge ist in LINELENGTH definiert. im RFC ist diese mit maximal
// 512byte (inklusive \r\n) angegeben. standard it aber 255byte
// sollte die zeilenlänge LINELENGTH überschreiten wird socket geschlossen.
// int socketnum = socketfd zum ircd
// return '\0' = zeile zu lang oder CR-LF-fehler leerer string wird zurückgegeben und disconnect
// return *char = zeiger auf den empfangenen string
//
char *netrecv(int socketnum)
{
static char buffer[LINELENGTH];
char *a;
int i = 0;
// assert(socketnum > 0);
a = malloc(sizeof(char));
buffer[0] = '\0';
while ((recv(socketnum, a, 1, 0) > 0) && (*a != '\n')) {
if (i >= LINELENGTH - 1) {
fprintf(stderr, "\nERROR: zu lange zeile vom server empfangen\ndisconnect!\n\
i=%d,a=%s,b=%s", i, a, buffer);
exit(1);
disconnect_irc(socketnum);
buffer[0] = '\0';
}
if (*a != '\r') {
buffer[i] = *a;
i++;
}
}
if (i >= 1 && (*a == '\n')) {
//recv(socketnum,a,1,0);
//i++;
if (i > LINELENGTH) {
fprintf(stderr, "\nERROR: zu lange zeile vom server empfangen\ndisconnect!\n\
eingestelle maximallänge einer zeile ist zZ %d\n",
LINELENGTH);
exit(1);
disconnect_irc(socketnum);
buffer[0] = '\0';
}
if (*a == '\n') {
fprintf(stderr, "\nZeilenende gefunden\n");
buffer[i + 2] = '\0';
buffer[i + 1] = '\n';
buffer[i] = '\r';
} else {
fprintf(stderr,
"\nERROR: mit den zeilenenden stimmt was nicht\n");
disconnect_irc(socketnum);
buffer[0] = '\0';
return (buffer);
}
}
// todo: was ist mit a? speicherleck?
free(a);
return (buffer);
}
int resolve_ircd(char *host, int port)
{
struct hostent *he;
// struct in6_addr addr6;
struct in_addr addr;
// char ipv6[INET6_ADDRSTRLEN];
printf("Resolving host: %s\n", host);
/*
// Resolve IPv6
he = gethostbyname2(host, AF_INET6);
//he=NULL;
if (he == NULL)
printf("Host %s got no IPv6 address\n", host);
else {
inet_ntop(AF_INET6, (void *) he->h_addr_list[0], ipv6,
INET6_ADDRSTRLEN);
printf
("Host %s got IPv6 address %s\nConnecting (IPv6)...\n",
host, ipv6);
return (connect_irc6(port, ipv6));
}
*/
// Resolve IPv4
he = gethostbyname(host);
if (he == NULL)
printf("Host %s got no IPv4 address.\n", host);
else {
memcpy(&addr, he->h_addr_list[0], sizeof(struct in_addr));
printf("Host %s got IPv4 address %s\nConnecting (IPv4)...",
host, inet_ntoa(addr));
return (connect_irc(port, inet_ntoa(addr)));
}
return 0;
}

54
com.h Normal file
View File

@ -0,0 +1,54 @@
// *************************************************************
// stellt verbindung zum (IPv6) ircd her
// int port = ircd-port
// char *ipnum = ipnummer des ircd in xxx.xxx.xxx.xxx -notation
// return -1 = fehler beim socket-erstellen
// return -2 = fehler beim connecten
// return num>0 = socketfd
//
extern int connect_irc(int port, char *ipnum);
extern int connect_irc6(int port, char *ipnum);
// *************************************************************
// resolved die IPv4 / IPv6 des ircd
//
extern int resolve_ircd(char *host, int port);
// *************************************************************
// schliesst die verbindung zum ircd
// int socketnum = socketfd
//
extern int disconnect_irc(int socketnum);
// ***************************************************************
// sendet einen string an den ircd,
// zu lange strings werden nach stelle LINELENGTH-2 abgeschnitten
// und nen CR-LF (also \r\n) angefügt
// int socketnum = socket-handler
// char *msg = zu sendender string (1-LINELENGTH byte)
// return -2 = string leer
// return -1 = fehler in send()
// return num>0 = übertragene bytes
//
extern int netsend(int socketnum, char *msg);
// ************************************************
// empfängt eine zeile vom ircd und gibt einen zeiger auf den string zurück.
// jede zeile des ircd SOLLTE mit einem \r\n abgeschlossen sein.
// die zeilenlänge ist in LINELENGTH definiert. im RFC ist diese mit maximal
// 512byte (inklusive \r\n) angegeben. standard it aber 255byte
// sollte die zeilenlänge LINELENGTH überschreiten wird socket geschlossen.
// int socketnum = socketfd zum ircd
// return '\0' = zeile zu lang oder CR-LF-fehler leerer string wird zurückgegeben und disconnect
// return *char = zeiger auf den empfangenen string
//
extern char *netrecv(int socketnum);

View File

@ -0,0 +1 @@
"cstack_get_address" 'command

View File

@ -0,0 +1 @@
"cstack_put_address" 'command

View File

@ -0,0 +1 @@
"cstack_push_command" cstack_push_command

1
command/compiler/'const Normal file
View File

@ -0,0 +1 @@
"cstack_push" cstack_push_command

4
command/compiler/* Normal file
View File

@ -0,0 +1,4 @@
"mul" 'command

1
command/compiler/+ Normal file
View File

@ -0,0 +1 @@
"add" 'command

18
command/compiler/+loop Normal file
View File

@ -0,0 +1,18 @@
// Laufvariable Inkrementieren und mit Grenze vergleichen
"r>" 'command
"+" 'command
"dup" 'command
">r" 'command
"i'" 'command
">" 'command
"not" 'command
// Sprung zurück zu do, falls die Laufvariable noch kleiner ist
'const
"__bz" 'command
// Die Laufvariable ist wohl schon zu groß: Also aufräumen
"r>" 'command
"r>" 'command
"drop" 'command
"drop" 'command

1
command/compiler/- Normal file
View File

@ -0,0 +1 @@
"sub" 'command

2
command/compiler/< Normal file
View File

@ -0,0 +1,2 @@
"swap" 'command
"greaterthan" 'command

1
command/compiler/> Normal file
View File

@ -0,0 +1 @@
"greaterthan" 'command

1
command/compiler/>r Normal file
View File

@ -0,0 +1 @@
"rstack_push" 'command

4
command/compiler/do Normal file
View File

@ -0,0 +1,4 @@
"swap" 'command
">r" 'command
">r" 'command
"nop" 'command '?address

4
command/compiler/else Normal file
View File

@ -0,0 +1,4 @@
44 'const '?address
"__b" 'command
swap
"nop" 'command '?address '@address

3
command/compiler/i Normal file
View File

@ -0,0 +1,3 @@
"r>" 'command
"dup" 'command
">r" 'command

6
command/compiler/i' Normal file
View File

@ -0,0 +1,6 @@
"r>" 'command
"r>" 'command
"dup" 'command
">r" 'command
"swap" 'command
">r" 'command

4
command/compiler/if Normal file
View File

@ -0,0 +1,4 @@
"not" 'command
42 'const
'?address
"__bz" 'command

2
command/compiler/loop Normal file
View File

@ -0,0 +1,2 @@
1 'const
"+loop" 'command

1
command/compiler/pi Normal file
View File

@ -0,0 +1 @@
"3.14" 'const

2
command/compiler/r> Normal file
View File

@ -0,0 +1,2 @@
"rstack_pop" 'command

3
command/compiler/sub Normal file
View File

@ -0,0 +1,3 @@
-1 cstack_push
"*" cstack_push_command
"+" cstack_push_command

1
command/compiler/then Normal file
View File

@ -0,0 +1 @@
"nop" 'command '?address '@address

6
command/system/init Normal file
View File

@ -0,0 +1,6 @@
"select * from irc_calc where eintrag like 'test%'" sql_query >r
r> sql_fetch swap >r "inhalt" vector_pick
r> sql_fetch swap >r "inhalt" vector_pick

1
command/system/zahlen Normal file
View File

@ -0,0 +1 @@
30 40 50

361
db.c Normal file
View File

@ -0,0 +1,361 @@
// Kredite: Michael Tokarev (tinycdb), Daniel Julius Bernstein (CDB)
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <fcntl.h>
#include <errno.h>
#include <getopt.h>
#include <unistd.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <inttypes.h>
#include <sys/types.h>
#include "cdb.h"
#include "vector.h"
#include "botforth.h"
#define blen 2048
static unsigned char buf[blen];
extern void cdb_startup();
extern struct vector *cdb_load_random(bool cmd);
extern void bdb_init();
extern void bdb_store(char *name, struct vector *v);
void puthelp()
{
printf("Argumente:\n"
" --help Diese Hilfe\n"
" --dump [Eintrag] Datenbankeintrag mit Spaltennamen anzeigen\n"
" --dumpall Alle Datenbankeinträge (mit Spalten) zeigen\n"
" --dumprandom Zufälligen Datenbankeintrag liefern\n"
" --content [Eintrag] Das Feld „Inhalt“ ausgeben\n"
" --allcont Das Feld „Inhalt“ aller Einträge ausgeben\n"
" --anlcont ^ mit „\\n“ statt „\\0“ als Trenner\n"
" --genindex_cdb Indexdatei für CDB-Datenbank anlegen\n"
" --genindex_cdb_cmd Indexdatei für CDB-Datenbank anlegen, nur Kommandos\n"
" --genindex_cdb_nocmd Indexdatei für CDB-Datenbank anlegen, Kommandos rausgefiltert\n");
}
static void
fget(FILE * f, unsigned char *b, unsigned len, unsigned *posp,
unsigned limit)
{
if (posp && limit - *posp < len)
exit(1);
if (fread(b, 1, len, f) != len) {
if (ferror(f))
exit(1);
fprintf(stderr, "unable to read: short file\n");
exit(2);
}
if (posp)
*posp += len;
}
static bool fskip_iscmd(FILE * fi, unsigned len, unsigned *posp,
unsigned limit, bool * fine)
{
if (fine)
*fine = false;
while (len > blen) {
fget(fi, buf, blen, posp, limit);
len -= blen;
}
if (len) {
fget(fi, buf, len, posp, limit);
if (len != blen) {
buf[len] = 0;
char *cmdname = strstr((char *) buf, "command");
if (!cmdname)
return false;
cmdname = strstr((char *) buf, "command/dope/");
if (!cmdname)
return true;
unsigned char cmdfirstchr =
cmdname[strlen("command/dope/")];
if (!isalnum(cmdfirstchr))
return true;;
if (strchr(cmdname, '_'))
return true;
if (fine)
*fine = true;
}
}
return false;
}
static void genindex_cdb()
{
unsigned eod, klen, vlen;
unsigned pos = 0;
FILE *f, *fo;
if (!(f = fopen("calc.cdb", "r")))
exit(1);
else if (!(fo = fopen("calc.cdb.index", "w")))
exit(1);
fget(f, buf, blen, &pos, blen);
eod = cdb_unpack(buf);
while (pos < eod) {
cdb_pack(pos, buf);
fwrite(buf, 4, 1, fo);
fget(f, buf, 8, &pos, eod);
klen = cdb_unpack(buf);
vlen = cdb_unpack(buf + 4);
fskip_iscmd(f, klen, &pos, eod, 0);
fskip_iscmd(f, vlen, &pos, eod, 0);
}
if (fflush(fo) < 0 || pos != eod)
exit(1);
}
static void genindex_cdb_nocmd()
{
unsigned eod, klen, vlen;
unsigned pos = 0;
FILE *f, *fo;
if (!(f = fopen("calc.cdb", "r")))
exit(1);
else if (!(fo = fopen("calc.cdb.index.nocmd", "w")))
exit(1);
fget(f, buf, blen, &pos, blen);
eod = cdb_unpack(buf);
while (pos < eod) {
int savepos = pos;
fget(f, buf, 8, &pos, eod);
klen = cdb_unpack(buf);
vlen = cdb_unpack(buf + 4);
bool iscmd = fskip_iscmd(f, klen, &pos, eod, 0);
fskip_iscmd(f, vlen, &pos, eod, 0);
if (iscmd)
continue;
cdb_pack(savepos, buf);
fwrite(buf, 4, 1, fo);
}
if (fflush(fo) < 0 || pos != eod)
exit(1);
}
static void genindex_cdb_cmd()
{
unsigned eod, klen, vlen;
unsigned pos = 0;
FILE *f, *fo;
if (!(f = fopen("calc.cdb", "r")))
exit(1);
else if (!(fo = fopen("calc.cdb.index.cmd", "w")))
exit(1);
fget(f, buf, blen, &pos, blen);
eod = cdb_unpack(buf);
while (pos < eod) {
int savepos = pos;
fget(f, buf, 8, &pos, eod);
klen = cdb_unpack(buf);
vlen = cdb_unpack(buf + 4);
bool fine;
fskip_iscmd(f, klen, &pos, eod, &fine);
fskip_iscmd(f, vlen, &pos, eod, 0);
if (!fine)
continue;
cdb_pack(savepos, buf);
fwrite(buf, 4, 1, fo);
}
if (fflush(fo) < 0 || pos != eod)
exit(1);
}
static void build_node(char *name, struct vector *v, char *content)
{
char *memp = malloc(strlen(content) + 1);
assert(memp);
strcpy(memp, content);
struct node *node = node_create(memp, BF_TYPE_STRING);
assert(name && *name);
vector_put(v, name, node);
}
static int dump(int n, struct vector *v)
{
printf("#%7d: ", n);
debug(v);
putchar('\n');
return 0;
}
static int dump_content(int n, struct vector *v)
{
(void) n;
if (!v)
return 0;
char *inhalt = vector_pick_string(v, "inhalt");
if (!inhalt)
return 0;
printf("%s", inhalt);
putchar(0);
return 0;
}
static int dump_content_newline(int n, struct vector *v)
{
(void) n;
if (!v)
return 0;
char *inhalt = vector_pick_string(v, "inhalt");
if (!inhalt)
return 0;
printf("%s", inhalt);
putchar('\n');
return 0;
}
int main(int argc, char **argv)
{
if (argc < 2) {
puthelp();
return 1;
}
cdb_startup();
bdb_init();
char *eintrag = 0;
for (;;) {
int option_index = 0;
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"dump", required_argument, 0, 'd'},
{"dumpall", no_argument, 0, 'D'},
{"dumprandom", no_argument, 0, 'r'},
{"content", required_argument, 0, 'c'},
{"allcont", no_argument, 0, 'C'},
{"anlcont", no_argument, 0, 'N'},
{"write", required_argument, 0, 'w'},
{"genindex_cdb", no_argument, 0, 'g'},
{"genindex_cdb_cmd", no_argument, 0, 'K'},
{"genindex_cdb_nocmd", no_argument, 0, 'G'},
{0, 0, 0, 0}
};
int c = getopt_long(argc, argv, "d:c:hdrCNw:gGK",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 'h':
puthelp();
return 1;
case 'd':
{
struct vector *v = load_file(optarg);
debug(v);
break;
}
case 'D':
{
iterate(dump);
break;
}
case 'r':
{
struct vector *v = cdb_load_random(false);
if (!v)
break;
char *eintrag =
vector_pick_string(v, "eintrag");
char *inhalt =
vector_pick_string(v, "inhalt");
if (!eintrag || !inhalt)
break;
printf("%s → „%s“\n", eintrag,
inhalt);
break;
}
case 'c':
{
struct vector *v = load_file(optarg);
if (!v)
break;
char *inhalt =
vector_pick_string(v, "inhalt");
if (!inhalt)
break;
printf("%s", inhalt);
break;
}
case 'C':
{
iterate(dump_content);
break;
}
case 'N':
{
iterate(dump_content_newline);
break;
}
case 'w':
eintrag = optarg;
break;
case 'g':
genindex_cdb();
break;
case 'G':
genindex_cdb_nocmd();
break;
case 'K':
genindex_cdb_cmd();
break;
case '?':
break;
}
}
if (eintrag) {
if (optind >= argc) {
fprintf(stderr, "Inhalt fehlt.\n");
return 1;
}
char *inhalt = argv[optind];
struct vector *v = vector_create();
build_node("eintrag", v, eintrag);
build_node("auth", v, "0");
build_node("inhalt", v, inhalt);
build_node("name", v, "db");
build_node("bot", v, "db");
build_node("network", v, "db");
build_node("channel", v, "");
build_node("zeit", v, "");
build_node("type", v, "0");
build_node("lastcall", v, "0");
bdb_store(eintrag, v);
vector_destroy(v);
}
return 0;
}

240
db_bdb.c Normal file
View File

@ -0,0 +1,240 @@
#include <sys/types.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <db.h>
#include "node.h"
#include "vector.h"
static DB *dbp;
void bdb_init()
{
int ret = db_create(&dbp, 0, 0);;
if (ret) {
fprintf(stderr, "db_create: %s\n", db_strerror(ret));
exit(EXIT_FAILURE);
}
ret = dbp->open(dbp, 0, "calc.bdb", 0, DB_BTREE, DB_CREATE, 0664);
if (ret) {
dbp->err(dbp, ret, "calc.bdb");
exit(EXIT_FAILURE);
}
}
static void bdb_put(char *key, char *val)
{
assert(key);
assert(val);
DBT field = { 0 };
field.data = key;
field.size = strlen(key) + 1;
DBT data = { 0 };
data.data = val;
data.size = strlen(val) + 1;
int ret = dbp->put(dbp, 0, &field, &data, 0);
if (ret) {
dbp->err(dbp, ret, "[BDB] DB->put");
assert(!ret);
}
int cret = dbp->close(dbp, 0);
assert(!cret);
bdb_init();
}
static void bdb_del(char *key)
{
assert(key);
DBT field = { 0 };
field.data = key;
field.size = strlen(key) + 1;
int ret = dbp->del(dbp, 0, &field, 0);
if (ret) {
if (ret == DB_NOTFOUND)
return;
dbp->err(dbp, ret, "[BDB] DB->del");
assert(!ret);
}
int cret = dbp->close(dbp, 0);
assert(!cret);
bdb_init();
}
char *bdballoc(char *key)
{
DBT field = { 0 };
field.data = key;
field.size = strlen(key) + 1;
DBT data = { 0 };
int ret = dbp->get(dbp, 0, &field, &data, 0);
if (ret) {
if (ret == DB_NOTFOUND)
return 0;
dbp->err(dbp, ret, "✝ DB->get");
assert(0);
}
char *s = strdup(data.data);
return s;
}
static void store_node(char *name, struct vector *v, char *sub)
{
char *inhalt = vector_pick_string(v, sub);
if (!inhalt)
return;
char key[strlen(name) + sizeof("/") + strlen(sub)];
char *p = key, *n = name;
while (*n)
*p++ = tolower(*n++);
*p++ = '/';
n = sub;
while (*n)
*p++ = tolower(*n++);
*p = 0;
bdb_put(key, inhalt);
}
static void remove_node(char *name, char *sub)
{
char key[strlen(name) + sizeof("/") + strlen(sub)];
char *p = key, *n = name;
while (*n)
*p++ = tolower(*n++);
*p++ = '/';
n = sub;
while (*n)
*p++ = tolower(*n++);
*p = 0;
bdb_del(key);
}
static void build_node(char *name, struct vector *v, char *sub)
{
if (!sub) {
struct node *node = node_create(name, BF_TYPE_STRING);
vector_put(v, "eintrag", node);
return;
}
char key[strlen(name) + strlen("/") + strlen(sub) + 1];
char *p = key, *n = name;
while (*n)
*p++ = tolower(*n++);
*p = 0;
strcat(key, "/");
strcat(key, sub);
char *val = bdballoc(key);
if (val) {
struct node *node;
if (!strcmp(sub, "auth") ||
(!strcmp(sub, "type") && !*val)) {
char *nil = malloc(sizeof("0"));
assert(nil);
strcpy(nil, "0");
node = node_create(nil, BF_TYPE_STRING);
} else
node = node_create(val, BF_TYPE_STRING);
vector_put(v, sub, node);
}
}
int bdb_exists(char *name)
{
char key[strlen(name) + strlen("/") + strlen("bot") + 1];
char *p = key, *n = name;
while (*n)
*p++ = tolower(*n++);
*p = 0;
strcat(key, "/");
strcat(key, "bot");
DBT field = { 0 };
field.data = key;
field.size = strlen(key) + 1;
DBT data = { 0 };
int ret = dbp->get(dbp, 0, &field, &data, 0);
if (ret) {
if (ret == DB_NOTFOUND)
return 0;
dbp->err(dbp, ret, "✝ DB->get");
assert(0);
}
return 1;
}
struct vector *bdb_load(char *name)
{
int exists = bdb_exists(name);
if (!exists)
return 0;
struct vector *vb = vector_create();
build_node(name, vb, "auth");
build_node(name, vb, "name");
build_node(name, vb, 0); // „eintrag“
build_node(name, vb, "inhalt");
build_node(name, vb, "zeit");
build_node(name, vb, "bot");
build_node(name, vb, "protected");
build_node(name, vb, "channel");
build_node(name, vb, "network");
build_node(name, vb, "count");
build_node(name, vb, "type");
build_node(name, vb, "tag");
build_node(name, vb, "lastcall");
return vb;
}
void bdb_store(char *name, struct vector *v)
{
store_node(name, v, "auth");
store_node(name, v, "name");
store_node(name, v, "inhalt");
store_node(name, v, "zeit");
store_node(name, v, "protected");
store_node(name, v, "channel");
store_node(name, v, "network");
store_node(name, v, "count");
store_node(name, v, "type");
store_node(name, v, "tag");
store_node(name, v, "lastcall");
store_node(name, v, "eintrag");
store_node(name, v, "bot");
}
void bdb_delete(char *name)
{
remove_node(name, "eintrag");
remove_node(name, "inhalt");
remove_node(name, "name");
remove_node(name, "zeit");
remove_node(name, "protected");
remove_node(name, "channel");
remove_node(name, "network");
remove_node(name, "count");
remove_node(name, "type");
remove_node(name, "tag");
remove_node(name, "lastcall");
remove_node(name, "bot");
remove_node(name, "auth");
}

269
db_cdb.c Normal file
View File

@ -0,0 +1,269 @@
#include <cdb.h>
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "def.h"
#include "node.h"
#include "vector.h"
struct cdb cdb;
unsigned pos;
void cdb_startup()
{
int fd = open("calc.cdb", O_RDONLY);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
cdb_init(&cdb, fd);
}
char *cdballoc(char *key)
{
char *val = 0;
if (cdb_find(&cdb, key, strlen(key)) > 0) {
unsigned vpos = cdb_datapos(&cdb);
unsigned vlen = cdb_datalen(&cdb);
val = malloc(vlen + 1);
if (!val)
return 0;
cdb_read(&cdb, val, vlen, vpos);
val[vlen] = 0;
}
return val;
}
int cdb_exists(char *name)
{
if (!name)
return 0;
char key[strlen(name) + strlen("/") + strlen("bot") + 1];
char *p = key, *n = name;
while (*n)
*p++ = tolower(*n++);
*p = 0;
strcat(key, "/");
strcat(key, "bot");
int cdbret = cdb_find(&cdb, key, strlen(key));
assert(cdbret != -1);
return cdbret;
}
static char *name;
static char *sub;
static char *val;
static void split_key(char *key)
{
name = sub = 0;
if (!key || !*key)
return;
char tmp[strlen(key) + 1];
char *slash = strrchr(key, '/');
if (!slash || !*slash)
return;
char *p = tmp;
while (key != slash)
*p++ = *key++;
*p = 0;
name = strdup(tmp);
sub = strdup(slash + 1);
}
static bool build_next()
{
if (cdb_seqnext(&pos, &cdb) <= 0)
return false;
unsigned keylen = cdb_keylen(&cdb);
char *key = malloc(keylen + 1);
cdb_read(&cdb, key, keylen, cdb_keypos(&cdb));
key[keylen] = 0;
unsigned datalen = cdb_datalen(&cdb);
val = malloc(datalen + 1);
cdb_read(&cdb, val, datalen, cdb_datapos(&cdb));
val[datalen] = 0;
split_key(key);
free(key);
return true;
}
void cdb_loadall_init()
{
cdb_seqinit(&pos, &cdb);
if (name) {
free(name);
name = 0;
}
if (sub) {
free(sub);
sub = 0;
}
if (val) {
free(val);
val = 0;
}
build_next();
}
struct vector *cdb_loadall_next()
{
if (!name)
cdb_loadall_init();
struct vector *v = vector_create();
struct node *node = node_create(name, BF_TYPE_STRING);
char cur_name[strlen(name) + 1];
strcpy(cur_name, name);
vector_put(v, "eintrag", node);
while (!strcmp(cur_name, name)) {
if (!sub)
continue;
node = node_create(val, BF_TYPE_STRING);
vector_put(v, sub, node);
if (!build_next())
return 0;
}
return v;
}
static void build_node(char *name, struct vector *v, char *sub)
{
if (!sub) {
struct node *node = node_create(name, BF_TYPE_STRING);
vector_put(v, "eintrag", node);
return;
}
char key[strlen(name) + strlen("/") + strlen(sub) + 1];
char *p = key, *n = name;
while (*n)
*p++ = tolower(*n++);
*p = 0;
strcat(key, "/");
strcat(key, sub);
char *val = cdballoc(key);
struct node *node = node_create(val, BF_TYPE_STRING);
vector_put(v, sub, node);
}
struct vector *cdb_load(char *name)
{
int cdbret = cdb_exists(name);
if (!cdbret)
return 0;
struct vector *vc = vector_create();
build_node(name, vc, "auth");
build_node(name, vc, "name");
build_node(name, vc, 0); // „eintrag“
build_node(name, vc, "inhalt");
build_node(name, vc, "zeit");
build_node(name, vc, "bot");
build_node(name, vc, "protected");
build_node(name, vc, "channel");
build_node(name, vc, "network");
build_node(name, vc, "count");
build_node(name, vc, "type");
build_node(name, vc, "tag");
build_node(name, vc, "lastcall");
return vc;
}
void uint32_unpack(const char s[4], uint32_t * u)
{
uint32_t result;
result = (unsigned char) s[3];
result <<= 8;
result += (unsigned char) s[2];
result <<= 8;
result += (unsigned char) s[1];
result <<= 8;
result += (unsigned char) s[0];
*u = result;
}
struct vector *cdb_load_random(bool cmd)
{
int guard;
for (guard = 0; guard < 23; guard++) {
char *fname = cmd ? "calc.cdb.index.cmd" :
"calc.cdb.index.nocmd";
int fd = open(fname, O_RDONLY);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
off_t size = lseek(fd, 0, SEEK_END);
assert(size > 0 && size % 4 == 0);
int rndmax = min(RAND_MAX, size / 4);
int rnd = rand() % rndmax;
off_t off = rnd;
off *= 4;
lseek(fd, off, SEEK_SET);
char buf_pos[4];
read(fd, buf_pos, 4);
uint32_t pos;
uint32_unpack(buf_pos, &pos);
close(fd);
fd = open("calc.cdb", O_RDONLY);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
off_t loc = lseek(fd, pos, SEEK_SET);
assert(loc == pos);
char buf_keylen[4];
read(fd, buf_keylen, 4);
char buf_datalen[4];
read(fd, buf_datalen, 4);
uint32_t keylen;
uint32_unpack(buf_keylen, &keylen);
uint32_t datalen;
uint32_unpack(buf_datalen, &datalen);
if (!datalen) {
continue;
}
char key[keylen + 1];
read(fd, key, keylen);
key[keylen] = 0;
close(fd);
split_key(key);
struct vector *vc = cdb_load(name);
if (vc)
return vc;
}
return 0;
}

37
def.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef DEF_H
#define DEF_H
#include <cdb.h>
#include <time.h>
#include <assert.h>
#include <stdbool.h>
#define BF_TYPE_NODE 0
#define BF_TYPE_C_TEXT 1
#define BF_TYPE_C_INT 2
#define BF_TYPE_C_EXT 3
#define BF_TYPE_INT 4
#define BF_TYPE_FLOAT 5
#define BF_TYPE_POINTER 6
#define BF_TYPE_STRING 7
#define BF_TYPE_VECTOR 8
#define BF_TYPE_DB 9
// Generische Struktur für alle unterstützten Datenbanken
struct db {
char *query;
char *field;
};
// Makros
#define min(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a < _b ? _a : _b; })
#define max(a,b) \
({ __typeof__ (a) _a = (a); \
__typeof__ (b) _b = (b); \
_a > _b ? _a : _b; })
#endif

103
entwurf.txt Normal file
View File

@ -0,0 +1,103 @@
Programmfestspeicher
====================
Vorerst einfach auf Festplatte in einem Verzeichnis.
Datenfestspeicher
=================
Noch garnicht, später vielleicht auch Festplatte, oder mysql, oder wie auch
immer.
Datenarbeitsspeicher
====================
Doppelt verkettete Liste, jedes Element kann zusätzlich einen Namen haben.
Zugriff entweder durch push/pop bzw. shift/unshift, über eine Nummer wie bei
einem Array oder über seinen Namen wie bei einem Hash.
Es ist aber auch möglich, direkt über einen Pointer zuzugreifen. Pointer
lassen sich jedoch nicht vom Benutzer direkt erstellen, sondern nur von
entsprechend priviligierten Programmen.
Im ersten Entwurf würde man Elemente, auf die per Nummer oder Namen
zugegriffen wird, durch naive Suche finden. Später kann man ja noch einen
Index oder ähnliches drauf setzen.
Diese Speicherstruktur nenne ich "vector".
Datentypen:
Nach Außen hin sollen nur wenige verschiedene Datentypen sichtbar sein:
- Wert (integer, string, was auch immer)
- Vector
Wert wird intern in mehrere subtypen unterteilt, die jedoch automatisch
bei Bedarf konvertiert werden:
- int
- float
- string, bzw. pointer auf string
- pointer auf Elemente eines Vektors
Aus technischer Sicht gibt es nach Außen hin eigentlich auch nicht die
Unterscheidung zwischen Wert und vector. Auch hier kann und wird bei Bedarf
eine automatische Konvertierung vorgenommen. Im Normalfall wird jedoch der
Anwender dies nicht tun, und in der Dokumentation wird auch immer ein klarer
Unterschied zwischen normalen Werten und Vektoren gemacht.
Ein Sonderfall ist der Pointer auf Elemente eines Vektors: Weder kann von
einem Wert in diesen Typ konvertiert werden, noch anders herum (bzw. doch,
aber dann käme nur ein String "pointer" oder 0 bei heraus).
Die einzelnen Elemente eines Vektors werden in einem union gespeichert. Der
Union enthält die verschiedenen möglichen Ausprägungen der Werte, also int,
float, und pointer. Zudem gibt es ein Feld, in dem gespeichert wird, welche
Ausprägung gerade "aktiv" ist.
Ein zusätzlicher Typ, den man später noch hinzufügen könnte wäre "array".
Dieser Typ würde sich zum Speichern größerer Datenmengen eignen, da er
gegenüber einem Vektor keinen Overhead pro Element hätte.
Programmarbeitsspeicher
=======================
Der Programmspeicher ist nichts anderes als normaler Datenspeicher. Dies
macht es möglich, Compilererweiterungen selbst in botforth zu schreiben.
minibotforth
============
Folgende Befehle müssen implementiert werden:
- swap
- +
...
minibotforth sollte so extrem simpel sein, daß man es später vielleicht
sogar ganz weg lassen kann, um direkt nach Maschinensprache zu kompilieren.
Compiler von botforth nach minibotforth
========================================
1. Schritt: lexikalische analyse, also erkennen der einzelnen
schluesselworte usw.
Hier wird zwar erkannt, was ein Befehl ist, aber noch nicht, ob der Befehl
intern oder extern vorliegt. Jeder Befehl wird als Node vom Typ
BF_TYPE_C_TEXT gespeichert, wobei der Befehlsname in Klartext als String
abgelegt wird.
2. Schritt: Compiler. Hier wird botforth nach minibotforth gewandelt. Auch
hier werden jedoch Befehlsnamen als BF_TYPE_C_TEXT abgelegt.
3. Ausführung: Erst während der Programmausführung, also wenn wir uns schon
längst nicht mehr im Compilermodus befinden, werden Befehle vom Typ
BF_TYPE_C_TEXT, sobald sie ausgeführt werden sollen, in BF_TYPE_C_INT bzw.
BF_TYPE_C_EXT gewandelt.
Dies dient dazu, den Compiler vom User erweiterbar zu halten. Er kann so
leicht Befehle einfügen, ohne mit Pointern etc. rumspielen zu müssen. Somit
wird auch kein Sicherheitsloch erzeugt. Aus der Sicht eines Anwenders, der
den Compiler durch das Programmieren von Compilezeitverhaltens von Befehlen
erweitern will, sind Befehle quasi wie Strings zu handhaben.

4
feuerzeug Executable file
View File

@ -0,0 +1,4 @@
#!/bin/bash
ulimit -d 50000 -v 50000
while [ 1 ]; do (./botforth $1 ) ; sleep 20; done

5
feuerzeug-proxychains Executable file
View File

@ -0,0 +1,5 @@
#!/bin/sh
ulimit -d 50000
ulimit -v 50000
while [ 1 ]; do (proxychains ./botforth $1 ) ; sleep 20; done

5
feuerzeug-tsocks Executable file
View File

@ -0,0 +1,5 @@
#!/bin/sh
ulimit -d 50000
ulimit -v 50000
while [ 1 ]; do (tsocks ./botforth $1 ) ; sleep 20; done

112
file.c Normal file
View File

@ -0,0 +1,112 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "node.h"
#include "vector.h"
extern struct vector *cdb_load(char *name);
extern void cdb_loadall_init();
extern struct vector *cdb_loadall_next();
extern struct vector *cdb_load_random(bool cmd);
// Zum Debuggen
bool vector_str_equal(struct vector *v0, struct vector *v1)
{
if (!v0 && !v1)
return true;
if ((!v0 && v1) || (v0 && !v1))
return false;
struct node *elem0 = v0->head, *elem1 = v1->head;
if ((elem0 && !elem1) || (!elem0 && elem1))
return false;
while (elem0 && elem1) {
char *c0 = elem0->content;
char *c1 = elem1->content;
if (strcmp(c0, c1)) {
printf("\n⋄%s\n„%s“\n⚡%s\n„%s“\n",
elem0->name, c0, elem1->name, c1);
return false;
}
elem0 = elem0->next;
elem1 = elem1->next;
}
if ((elem0 && !elem1) || (!elem0 && elem1))
return false;
return true;
}
extern struct vector *bdb_load(char *name);
extern void bdb_store(char *name, struct vector *v);
struct vector *load_file(char *name)
{
struct vector *v_bdb = bdb_load(name);
struct vector *v_cdb = cdb_load(name);
if (!v_bdb && !v_cdb)
return 0;
if (v_bdb)
return v_bdb;
if (!v_cdb)
return 0;
bdb_store(name, v_cdb);
return v_cdb;
}
void iterate(int (*action) (int64_t n, struct vector * content))
{
int64_t count = 0;
struct vector *v_cdb = 0;
for (cdb_loadall_init(); (v_cdb = cdb_loadall_next()); count++) {
action(count, v_cdb);
}
// TODO: Berkeley-DB auch.
}
struct vector *load_rand_single_cmd()
{
struct vector *v = cdb_load_random(true);
char *eintrag = vector_pick_string(v, "eintrag");
assert(eintrag);
return v;
// TODO: Berkeley-DB auch.
}
struct vector *load_rand_cmd()
{
struct vector *v = cdb_load_random(true);
char *eintrag = vector_pick_string(v, "eintrag");
assert(eintrag);
assert(strlen(eintrag) > 13);
char *shortened = malloc(strlen(eintrag) - 13);
assert(shortened);
strcpy(shortened, eintrag + 13);
vector_replace_string(v, "eintrag", shortened);
free(eintrag);
return v;
// TODO: Berkeley-DB auch.
}
struct vector *load_rand_file()
{
struct vector *v = cdb_load_random(false);
char *eintrag = vector_pick_string(v, "eintrag");
assert(eintrag);
return v;
// TODO: Berkeley-DB auch.
}

673
getintcommand.c Normal file
View File

@ -0,0 +1,673 @@
void *getintcommand(char *command) {
void *p=NULL;
if(strcmp(command,"zstack_push")==0) {
p=bf_c_zstack_push;
}
if(strcmp(command,"zstack_pop")==0) {
p=bf_c_zstack_pop;
}
if(strcmp(command,"halt")==0) {
p=bf_c_halt;
}
if(strcmp(command,"file_append")==0) {
p=bf_c_file_append;
}
if(strcmp(command,"lstack_push")==0) {
p=bf_c_lstack_push;
}
if(strcmp(command,"lstack_pop")==0) {
p=bf_c_lstack_pop;
}
if(strcmp(command,"setname")==0) {
p=bf_c_setname;
}
if(strcmp(command,"stop")==0) {
p=bf_c_stop;
}
if(strcmp(command,"var_put")==0) {
p=bf_c_var_put;
}
if(strcmp(command,"var_pick")==0) {
p=bf_c_var_pick;
}
if(strcmp(command,"date")==0) {
p=bf_c_date;
}
if(strcmp(command,"is_vector")==0) {
p=bf_c_is_vector;
}
if(strcmp(command,"vector_get")==0) {
p=bf_c_vector_get;
}
if(strcmp(command,"explain")==0) {
p=bf_c_explain;
}
if(strcmp(command,"frexp")==0) {
p=bf_c_frexp;
}
if(strcmp(command,"ldexp")==0) {
p=bf_c_ldexp;
}
if(strcmp(command,"name")==0) {
p=bf_c_name;
}
if(strcmp(command,"vector_replace")==0) {
p=bf_c_vector_replace;
}
if(strcmp(command,"div")==0) {
p=bf_c_div;
}
if(strcmp(command,"set_runlimit")==0) {
p=bf_c_set_runlimit;
}
if(strcmp(command,"lexicon_swap")==0) {
p=bf_c_lexicon_swap;
}
if(strcmp(command,"lexicon_get")==0) {
p=bf_c_lexicon_get;
}
if(strcmp(command,"interpret")==0) {
p=bf_c_interpret;
}
if(strcmp(command,"pick")==0) {
p=bf_c_pick;
}
if(strcmp(command,"mod")==0) {
p=bf_c_mod;
}
if(strcmp(command,"ceil")==0) {
p=bf_c_ceil;
}
if(strcmp(command,"round")==0) {
p=bf_c_round;
}
if(strcmp(command,"floor")==0) {
p=bf_c_floor;
}
if(strcmp(command,"vector_put")==0) {
p=bf_c_vector_put;
}
if(strcmp(command,"var_swap")==0) {
p=bf_c_var_swap;
}
if(strcmp(command,"vector_shift")==0) {
p=bf_c_vector_shift;
}
if(strcmp(command,"vector_unshift")==0) {
p=bf_c_vector_unshift;
}
if(strcmp(command,"timestamp")==0) {
p=bf_c_timestamp;
}
if(strcmp(command,"sql_escape")==0) {
p=bf_c_sql_escape;
}
if(strcmp(command,"rand")==0) {
p=bf_c_rand;
}
if(strcmp(command,"vector_count")==0) {
p=bf_c_vector_count;
}
if(strcmp(command,"dstack_unshift")==0) {
p=bf_c_dstack_unshift;
}
if(strcmp(command,"dstack_shift")==0) {
p=bf_c_dstack_shift;
}
if(strcmp(command,"fdiv")==0) {
p=bf_c_fdiv;
}
if(strcmp(command,"al")==0) {
p=bf_c_al;
}
if(strcmp(command,"sql_freeres")==0) {
p=bf_c_sql_freeres;
}
if(strcmp(command,"die")==0) {
p=bf_c_die;
}
if(strcmp(command,"clearcache")==0) {
p=bf_c_clearcache;
}
if(strcmp(command,"ord")==0) {
p=bf_c_ord;
}
if(strcmp(command,"chr")==0) {
p=bf_c_chr;
}
if(strcmp(command,"depth")==0) {
p=bf_c_depth;
}
if(strcmp(command,"exec")==0) {
p=bf_c_exec;
}
if(strcmp(command,"exec_ns")==0) {
p=bf_c_exec_ns;
}
if(strcmp(command,"var_replace")==0) {
p=bf_c_var_replace;
}
if(strcmp(command,"var_get")==0) {
p=bf_c_var_get;
}
if(strcmp(command,"print")==0) {
p=bf_c_print;
}
if(strcmp(command,"strlen")==0) {
p=bf_c_strlen;
}
if(strcmp(command,"strpos")==0) {
p=bf_c_strpos;
}
if(strcmp(command,"strsplit")==0) {
p=bf_c_strsplit;
}
if(strcmp(command,"__sleep")==0) {
p=bf_c___sleep;
}
if(strcmp(command,"concat")==0) {
p=bf_c_concat;
}
if(strcmp(command,"irc_connect")==0) {
p=bf_c_irc_connect;
}
if(strcmp(command,"irc_put_raw")==0) {
p=bf_c_irc_put_raw;
}
if(strcmp(command,"irc_get")==0) {
p=bf_c_irc_get;
}
if(strcmp(command,"sql_query")==0) {
p=bf_c_sql_query;
}
if(strcmp(command,"sql_fetch")==0) {
p=bf_c_sql_fetch;
}
if(strcmp(command,"sql_numrows")==0) {
p=bf_c_sql_numrows;
}
if(strcmp(command,"vector")==0) {
p=bf_c_vector;
}
if(strcmp(command,"vector_pick")==0) {
p=bf_c_vector_pick;
}
if(strcmp(command,"vector_pop")==0) {
p=bf_c_vector_pop;
}
if(strcmp(command,"vector_push")==0) {
p=bf_c_vector_push;
}
if(strcmp(command,"greaterthan")==0) {
p=bf_c_greaterthan;
}
if(strcmp(command,"dup")==0) {
p=bf_c_dup;
}
if(strcmp(command,"drop")==0) {
p=bf_c_drop;
}
if(strcmp(command,"not")==0) {
p=bf_c_not;
}
if(strcmp(command,"nop")==0) {
p=bf_c_nop;
}
if(strcmp(command,"__b")==0) {
p=bf_c___b;
}
if(strcmp(command,"__bz")==0) {
p=bf_c___bz;
}
if(strcmp(command,"cstack_put_address")==0) {
p=bf_c_cstack_put_address;
}
if(strcmp(command,"cstack_get_address")==0) {
p=bf_c_cstack_get_address;
}
if(strcmp(command,"add")==0) {
p=bf_c_add;
}
if(strcmp(command,"mul")==0) {
p=bf_c_mul;
}
if(strcmp(command,"equal")==0) {
p=bf_c_equal;
}
if(strcmp(command,"swap")==0) {
p=bf_c_swap;
}
if(strcmp(command,"rstack_push")==0) {
p=bf_c_rstack_push;
}
if(strcmp(command,"rstack_pop")==0) {
p=bf_c_rstack_pop;
}
if(strcmp(command,"cstack_push")==0) {
p=bf_c_cstack_push;
}
if(strcmp(command,"cstack_push_command")==0) {
p=bf_c_cstack_push_command;
}
return p;
}
char *getintcommandname(void *p) {
char *name=NULL;
if(bf_c_zstack_push==p) {
name=malloc(strlen("zstack_push")+1);
strcpy(name,"zstack_push");
name[strlen("zstack_push")]=0;
}
if(bf_c_zstack_pop==p) {
name=malloc(strlen("zstack_pop")+1);
strcpy(name,"zstack_pop");
name[strlen("zstack_pop")]=0;
}
if(bf_c_halt==p) {
name=malloc(strlen("halt")+1);
strcpy(name,"halt");
name[strlen("halt")]=0;
}
if(bf_c_file_append==p) {
name=malloc(strlen("file_append")+1);
strcpy(name,"file_append");
name[strlen("file_append")]=0;
}
if(bf_c_lstack_push==p) {
name=malloc(strlen("lstack_push")+1);
strcpy(name,"lstack_push");
name[strlen("lstack_push")]=0;
}
if(bf_c_lstack_pop==p) {
name=malloc(strlen("lstack_pop")+1);
strcpy(name,"lstack_pop");
name[strlen("lstack_pop")]=0;
}
if(bf_c_setname==p) {
name=malloc(strlen("setname")+1);
strcpy(name,"setname");
name[strlen("setname")]=0;
}
if(bf_c_stop==p) {
name=malloc(strlen("stop")+1);
strcpy(name,"stop");
name[strlen("stop")]=0;
}
if(bf_c_var_put==p) {
name=malloc(strlen("var_put")+1);
strcpy(name,"var_put");
name[strlen("var_put")]=0;
}
if(bf_c_var_pick==p) {
name=malloc(strlen("var_pick")+1);
strcpy(name,"var_pick");
name[strlen("var_pick")]=0;
}
if(bf_c_date==p) {
name=malloc(strlen("date")+1);
strcpy(name,"date");
name[strlen("date")]=0;
}
if(bf_c_is_vector==p) {
name=malloc(strlen("is_vector")+1);
strcpy(name,"is_vector");
name[strlen("is_vector")]=0;
}
if(bf_c_vector_get==p) {
name=malloc(strlen("vector_get")+1);
strcpy(name,"vector_get");
name[strlen("vector_get")]=0;
}
if(bf_c_explain==p) {
name=malloc(strlen("explain")+1);
strcpy(name,"explain");
name[strlen("explain")]=0;
}
if(bf_c_frexp==p) {
name=malloc(strlen("frexp")+1);
strcpy(name,"frexp");
name[strlen("frexp")]=0;
}
if(bf_c_ldexp==p) {
name=malloc(strlen("ldexp")+1);
strcpy(name,"ldexp");
name[strlen("ldexp")]=0;
}
if(bf_c_name==p) {
name=malloc(strlen("name")+1);
strcpy(name,"name");
name[strlen("name")]=0;
}
if(bf_c_vector_replace==p) {
name=malloc(strlen("vector_replace")+1);
strcpy(name,"vector_replace");
name[strlen("vector_replace")]=0;
}
if(bf_c_div==p) {
name=malloc(strlen("div")+1);
strcpy(name,"div");
name[strlen("div")]=0;
}
if(bf_c_set_runlimit==p) {
name=malloc(strlen("set_runlimit")+1);
strcpy(name,"set_runlimit");
name[strlen("set_runlimit")]=0;
}
if(bf_c_lexicon_swap==p) {
name=malloc(strlen("lexicon_swap")+1);
strcpy(name,"lexicon_swap");
name[strlen("lexicon_swap")]=0;
}
if(bf_c_lexicon_get==p) {
name=malloc(strlen("lexicon_get")+1);
strcpy(name,"lexicon_get");
name[strlen("lexicon_get")]=0;
}
if(bf_c_interpret==p) {
name=malloc(strlen("interpret")+1);
strcpy(name,"interpret");
name[strlen("interpret")]=0;
}
if(bf_c_pick==p) {
name=malloc(strlen("pick")+1);
strcpy(name,"pick");
name[strlen("pick")]=0;
}
if(bf_c_mod==p) {
name=malloc(strlen("mod")+1);
strcpy(name,"mod");
name[strlen("mod")]=0;
}
if(bf_c_ceil==p) {
name=malloc(strlen("ceil")+1);
strcpy(name,"ceil");
name[strlen("ceil")]=0;
}
if(bf_c_round==p) {
name=malloc(strlen("round")+1);
strcpy(name,"round");
name[strlen("round")]=0;
}
if(bf_c_floor==p) {
name=malloc(strlen("floor")+1);
strcpy(name,"floor");
name[strlen("floor")]=0;
}
if(bf_c_vector_put==p) {
name=malloc(strlen("vector_put")+1);
strcpy(name,"vector_put");
name[strlen("vector_put")]=0;
}
if(bf_c_var_swap==p) {
name=malloc(strlen("var_swap")+1);
strcpy(name,"var_swap");
name[strlen("var_swap")]=0;
}
if(bf_c_vector_shift==p) {
name=malloc(strlen("vector_shift")+1);
strcpy(name,"vector_shift");
name[strlen("vector_shift")]=0;
}
if(bf_c_vector_unshift==p) {
name=malloc(strlen("vector_unshift")+1);
strcpy(name,"vector_unshift");
name[strlen("vector_unshift")]=0;
}
if(bf_c_timestamp==p) {
name=malloc(strlen("timestamp")+1);
strcpy(name,"timestamp");
name[strlen("timestamp")]=0;
}
if(bf_c_sql_escape==p) {
name=malloc(strlen("sql_escape")+1);
strcpy(name,"sql_escape");
name[strlen("sql_escape")]=0;
}
if(bf_c_rand==p) {
name=malloc(strlen("rand")+1);
strcpy(name,"rand");
name[strlen("rand")]=0;
}
if(bf_c_vector_count==p) {
name=malloc(strlen("vector_count")+1);
strcpy(name,"vector_count");
name[strlen("vector_count")]=0;
}
if(bf_c_dstack_unshift==p) {
name=malloc(strlen("dstack_unshift")+1);
strcpy(name,"dstack_unshift");
name[strlen("dstack_unshift")]=0;
}
if(bf_c_dstack_shift==p) {
name=malloc(strlen("dstack_shift")+1);
strcpy(name,"dstack_shift");
name[strlen("dstack_shift")]=0;
}
if(bf_c_fdiv==p) {
name=malloc(strlen("fdiv")+1);
strcpy(name,"fdiv");
name[strlen("fdiv")]=0;
}
if(bf_c_al==p) {
name=malloc(strlen("al")+1);
strcpy(name,"al");
name[strlen("al")]=0;
}
if(bf_c_sql_freeres==p) {
name=malloc(strlen("sql_freeres")+1);
strcpy(name,"sql_freeres");
name[strlen("sql_freeres")]=0;
}
if(bf_c_die==p) {
name=malloc(strlen("die")+1);
strcpy(name,"die");
name[strlen("die")]=0;
}
if(bf_c_clearcache==p) {
name=malloc(strlen("clearcache")+1);
strcpy(name,"clearcache");
name[strlen("clearcache")]=0;
}
if(bf_c_ord==p) {
name=malloc(strlen("ord")+1);
strcpy(name,"ord");
name[strlen("ord")]=0;
}
if(bf_c_chr==p) {
name=malloc(strlen("chr")+1);
strcpy(name,"chr");
name[strlen("chr")]=0;
}
if(bf_c_depth==p) {
name=malloc(strlen("depth")+1);
strcpy(name,"depth");
name[strlen("depth")]=0;
}
if(bf_c_exec==p) {
name=malloc(strlen("exec")+1);
strcpy(name,"exec");
name[strlen("exec")]=0;
}
if(bf_c_exec_ns==p) {
name=malloc(strlen("exec_ns")+1);
strcpy(name,"exec_ns");
name[strlen("exec_ns")]=0;
}
if(bf_c_var_replace==p) {
name=malloc(strlen("var_replace")+1);
strcpy(name,"var_replace");
name[strlen("var_replace")]=0;
}
if(bf_c_var_get==p) {
name=malloc(strlen("var_get")+1);
strcpy(name,"var_get");
name[strlen("var_get")]=0;
}
if(bf_c_print==p) {
name=malloc(strlen("print")+1);
strcpy(name,"print");
name[strlen("print")]=0;
}
if(bf_c_strlen==p) {
name=malloc(strlen("strlen")+1);
strcpy(name,"strlen");
name[strlen("strlen")]=0;
}
if(bf_c_strpos==p) {
name=malloc(strlen("strpos")+1);
strcpy(name,"strpos");
name[strlen("strpos")]=0;
}
if(bf_c_strsplit==p) {
name=malloc(strlen("strsplit")+1);
strcpy(name,"strsplit");
name[strlen("strsplit")]=0;
}
if(bf_c___sleep==p) {
name=malloc(strlen("__sleep")+1);
strcpy(name,"__sleep");
name[strlen("__sleep")]=0;
}
if(bf_c_concat==p) {
name=malloc(strlen("concat")+1);
strcpy(name,"concat");
name[strlen("concat")]=0;
}
if(bf_c_irc_connect==p) {
name=malloc(strlen("irc_connect")+1);
strcpy(name,"irc_connect");
name[strlen("irc_connect")]=0;
}
if(bf_c_irc_put_raw==p) {
name=malloc(strlen("irc_put_raw")+1);
strcpy(name,"irc_put_raw");
name[strlen("irc_put_raw")]=0;
}
if(bf_c_irc_get==p) {
name=malloc(strlen("irc_get")+1);
strcpy(name,"irc_get");
name[strlen("irc_get")]=0;
}
if(bf_c_sql_query==p) {
name=malloc(strlen("sql_query")+1);
strcpy(name,"sql_query");
name[strlen("sql_query")]=0;
}
if(bf_c_sql_fetch==p) {
name=malloc(strlen("sql_fetch")+1);
strcpy(name,"sql_fetch");
name[strlen("sql_fetch")]=0;
}
if(bf_c_sql_numrows==p) {
name=malloc(strlen("sql_numrows")+1);
strcpy(name,"sql_numrows");
name[strlen("sql_numrows")]=0;
}
if(bf_c_vector==p) {
name=malloc(strlen("vector")+1);
strcpy(name,"vector");
name[strlen("vector")]=0;
}
if(bf_c_vector_pick==p) {
name=malloc(strlen("vector_pick")+1);
strcpy(name,"vector_pick");
name[strlen("vector_pick")]=0;
}
if(bf_c_vector_pop==p) {
name=malloc(strlen("vector_pop")+1);
strcpy(name,"vector_pop");
name[strlen("vector_pop")]=0;
}
if(bf_c_vector_push==p) {
name=malloc(strlen("vector_push")+1);
strcpy(name,"vector_push");
name[strlen("vector_push")]=0;
}
if(bf_c_greaterthan==p) {
name=malloc(strlen("greaterthan")+1);
strcpy(name,"greaterthan");
name[strlen("greaterthan")]=0;
}
if(bf_c_dup==p) {
name=malloc(strlen("dup")+1);
strcpy(name,"dup");
name[strlen("dup")]=0;
}
if(bf_c_drop==p) {
name=malloc(strlen("drop")+1);
strcpy(name,"drop");
name[strlen("drop")]=0;
}
if(bf_c_not==p) {
name=malloc(strlen("not")+1);
strcpy(name,"not");
name[strlen("not")]=0;
}
if(bf_c_nop==p) {
name=malloc(strlen("nop")+1);
strcpy(name,"nop");
name[strlen("nop")]=0;
}
if(bf_c___b==p) {
name=malloc(strlen("__b")+1);
strcpy(name,"__b");
name[strlen("__b")]=0;
}
if(bf_c___bz==p) {
name=malloc(strlen("__bz")+1);
strcpy(name,"__bz");
name[strlen("__bz")]=0;
}
if(bf_c_cstack_put_address==p) {
name=malloc(strlen("cstack_put_address")+1);
strcpy(name,"cstack_put_address");
name[strlen("cstack_put_address")]=0;
}
if(bf_c_cstack_get_address==p) {
name=malloc(strlen("cstack_get_address")+1);
strcpy(name,"cstack_get_address");
name[strlen("cstack_get_address")]=0;
}
if(bf_c_add==p) {
name=malloc(strlen("add")+1);
strcpy(name,"add");
name[strlen("add")]=0;
}
if(bf_c_mul==p) {
name=malloc(strlen("mul")+1);
strcpy(name,"mul");
name[strlen("mul")]=0;
}
if(bf_c_equal==p) {
name=malloc(strlen("equal")+1);
strcpy(name,"equal");
name[strlen("equal")]=0;
}
if(bf_c_swap==p) {
name=malloc(strlen("swap")+1);
strcpy(name,"swap");
name[strlen("swap")]=0;
}
if(bf_c_rstack_push==p) {
name=malloc(strlen("rstack_push")+1);
strcpy(name,"rstack_push");
name[strlen("rstack_push")]=0;
}
if(bf_c_rstack_pop==p) {
name=malloc(strlen("rstack_pop")+1);
strcpy(name,"rstack_pop");
name[strlen("rstack_pop")]=0;
}
if(bf_c_cstack_push==p) {
name=malloc(strlen("cstack_push")+1);
strcpy(name,"cstack_push");
name[strlen("cstack_push")]=0;
}
if(bf_c_cstack_push_command==p) {
name=malloc(strlen("cstack_push_command")+1);
strcpy(name,"cstack_push_command");
name[strlen("cstack_push_command")]=0;
}
if(name!=NULL) return name;
return NULL;
}

1309
intcommands.c Normal file

File diff suppressed because it is too large Load Diff

28
makeintcommand.sh Executable file
View File

@ -0,0 +1,28 @@
#!/bin/sh
export COMMANDS="zstack_push zstack_pop halt file_append lstack_push lstack_pop \
setname stop var_put var_pick date is_vector vector_get explain \
frexp ldexp name vector_replace div set_runlimit lexicon_swap lexicon_get interpret pick mod ceil round floor vector_put var_swap vector_shift vector_unshift timestamp sql_escape rand vector_count dstack_unshift dstack_shift fdiv al sql_freeres die clearcache ord chr depth exec exec_ns var_replace var_get print strlen strpos strsplit __sleep concat irc_connect irc_put_raw irc_get sql_query sql_fetch sql_numrows vector vector_pick vector_pop vector_push greaterthan dup drop not nop __b __bz cstack_put_address cstack_get_address add mul equal swap rstack_push rstack_pop cstack_push cstack_push_command"
echo 'void *getintcommand(char *command) {'
echo ' void *p=NULL;'
for a in ${COMMANDS}; do
echo ' if(strcmp(command,"'$a'")==0) {'
echo ' p=bf_c_'$a';'
echo ' }'
done
echo ' return p;'
echo '}'
echo 'char *getintcommandname(void *p) {'
echo ' char *name=NULL;'
for a in ${COMMANDS}; do
echo ' if(bf_c_'$a'==p) {'
echo ' name=malloc(strlen("'$a'")+1);'
echo ' strcpy(name,"'$a'");'
echo ' name[strlen("'$a'")]=0;'
echo ' }'
done
echo ' if(name!=NULL) return name;'
echo ' return NULL;';
echo '}'

284
node.c Normal file
View File

@ -0,0 +1,284 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "botforth.h"
#define STRINGLENGTH 255
#define DEBUG printf("\n---DEBUG---\n");
struct node *node_create(void *content, int type)
{
struct node *n = malloc(sizeof(struct node));
//char *name;
assert(type < 20);
n->content = content;
n->type = type;
/*
name=malloc(5);
sprintf(name,"none");
*/
n->name = NULL;
return n;
}
struct node *node_copy(struct node *n)
{
struct node *c;
void *content;
assert(n != NULL);
assert(n->type < 20);
switch (n->type) {
case BF_TYPE_INT:
content = malloc(sizeof(int));
memcpy(content, n->content, sizeof(int));
break;
case BF_TYPE_FLOAT:
content = malloc(sizeof(float));
memcpy(content, n->content, sizeof(float));
break;
case BF_TYPE_STRING:
assert(n->content != NULL);
content = malloc(strlen(n->content) + 1);
memcpy(content, n->content, strlen(n->content) + 1);
break;
case BF_TYPE_POINTER:
content = n->content;
break;
case BF_TYPE_VECTOR:
content =
(void *) vector_copy((struct vector *) n->content);
break;
default:
printf
("Der Datentyp %i kann bislang nicht kopiert werden.\n",
n->type);
exit(1);
break;
}
c = node_create(content, n->type);
if (n->name) {
c->name = malloc(strlen(n->name) + 1);
sprintf(c->name, "%s", n->name);
}
return c;
}
int node_destroy(struct node *n)
{
if (n == NULL)
return 0;
// todo: alle typen abfragen
switch (n->type) {
case BF_TYPE_C_TEXT:
case BF_TYPE_STRING:
case BF_TYPE_INT:
case BF_TYPE_FLOAT:
free(n->content);
break;
//case BF_TYPE_C_EXT: // leider nein, weil sonst der cache sich rekursiv dematerialisiert
case BF_TYPE_VECTOR:
if(n != n->content)
vector_destroy((struct vector *) n->content);
break;
case BF_TYPE_NODE:
if(n != n->content)
node_destroy((struct node *) n->content);
break;
case BF_TYPE_DB:
{
struct db *tmp = n->content;
assert(tmp);
if (tmp->query)
free(tmp->query);
if (tmp->field)
free(tmp->field);
break;
}
case BF_TYPE_POINTER:
// nichts loeschen, der node hier gehoert ja wem anders
break;
}
if (n->name)
free(n->name);
free(n);
return 1;
}
int node_toInt(struct node *n)
{
int temp;
if (n == NULL)
return 0;
switch (n->type) {
case BF_TYPE_INT:
temp = *(int *) n->content;
node_destroy(n);
return temp;
break;
case BF_TYPE_FLOAT:
temp = (int) *(float *) n->content;
node_destroy(n);
return temp;
break;
case BF_TYPE_STRING:
temp = atoi(n->content);
node_destroy(n);
return temp;
break;
default:
node_destroy(n);
}
return 0;
}
float node_toFloat(struct node *n)
{
float temp;
if (n == NULL)
return 0.0;
switch (n->type) {
case BF_TYPE_FLOAT:
temp = *(float *) n->content;
node_destroy(n);
return temp;
break;
case BF_TYPE_INT:
temp = (float) *(int *) n->content;
node_destroy(n);
return temp;
break;
case BF_TYPE_STRING:
temp = atof(n->content);
node_destroy(n);
return temp;
break;
default:
node_destroy(n);
}
return 0.0;
}
char *node_toString(struct node *n)
{
char *temp, *r;
//printf("%i\n",n->type);
if (n == NULL) {
temp = malloc(1);
temp[0] = '\0';
return temp;
}
switch (n->type) {
case BF_TYPE_STRING:
case BF_TYPE_C_TEXT:
r = n->content;
if (n->name)
free(n->name);
free(n);
break;
case BF_TYPE_INT:
r = malloc(sizeof(char) * 100); // todo: moeglicher bufferoverflow
sprintf(r, "%i", node_toInt(n));
break;
case BF_TYPE_FLOAT:
r = malloc(sizeof(char) * 100); // todo: moeglicher bufferoverflow
sprintf(r, "%g", node_toFloat(n));
break;
case BF_TYPE_VECTOR:
r = malloc(7);
sprintf(r, "Vector");
node_destroy(n);
break;
case BF_TYPE_NODE:
r = malloc(5);
sprintf(r, "Node");
node_destroy(n);
break;
case BF_TYPE_DB:
r = malloc(strlen("db") + 1);
strcpy(r, "db");
node_destroy(n);
break;
default:
r = malloc(1);
r[0] = '\0';
node_destroy(n);
break;
}
return r;
}
struct vector *node_toVector(struct node *n)
{
struct vector *content;
if (n == NULL)
return NULL;
switch (n->type) {
case BF_TYPE_C_EXT:
case BF_TYPE_VECTOR:
content = n->content;
if (n->name)
free(n->name);
free(n);
return content;
break;
default:
node_destroy(n);
return NULL;
}
return NULL;
}
struct node *node_toPointer(struct node *n)
{
struct node *content;
if (n == NULL)
return NULL;
if (n->type == BF_TYPE_POINTER) {
content = n->content;
if (n->name)
free(n->name);
free(n);
return content;
}
node_destroy(n);
return NULL;
}
struct db *node_todb(struct node *n)
{
struct db *content = 0;
if (!n)
return content;
if (n->type == BF_TYPE_DB) {
content = (struct db *) n->content;
if (n->name)
free(n->name);
free(n);
return content;
}
node_destroy(n);
return content;
}
struct node *node_toNode(struct node *n)
{
struct node *content;
if (n == NULL)
return NULL;
if (n->type == BF_TYPE_NODE) {
if (n->name)
free(n->name);
content = n->content;
free(n);
return content;
} else {
node_destroy(n);
}
return NULL;
}

25
node.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef NODE_H
#define NODE_H
#include "def.h"
struct node {
void *content;
int type;
char *name;
struct node *next;
struct node *prev;
};
extern struct node *node_create(void *content, int type);
extern struct node *node_copy(struct node *n);
extern int node_destroy(struct node *n);
extern int node_toInt(struct node *n);
extern char *node_toString(struct node *n);
extern struct vector *node_toVector(struct node *n);
extern float node_toFloat(struct node *n);
extern struct node *node_toPointer(struct node *n);
extern struct node *node_toNode(struct node *n);
extern struct db *node_todb(struct node *n);
#endif

220
sql.c Normal file
View File

@ -0,0 +1,220 @@
#include "node.h"
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "vector.h"
#include "botforth.h"
// CDB-Krempel
extern int cdb_exists(char *name);
// BDB-Krempel
extern int bdb_exists(char *name);
extern void bdb_store(char *name, struct vector *v);
extern void bdb_delete(char *name);
static char ripple[16384];
static char *build_node(char *name, struct vector *v, char **sqlp)
{
char *p = *sqlp;
if (!*p || *p == ')')
return 0;
if (*p == ',')
p++;
char *end = p;
if (*p == '\'') {
end = ++p;
while (*end && *end != '\'')
end++;
if (!*end)
*sqlp = end;
else
*sqlp = end + 1;
*end = 0;
} else {
while (*end && *end != ',' && *end != ')')
end++;
if (!*end)
*sqlp = end;
else
*sqlp = end + 1;
*end = 0;
}
char *memp = malloc(strlen(p) + 1);
assert(memp);
strcpy(memp, p);
struct node *node = node_create(memp, BF_TYPE_STRING);
assert(name && *name);
vector_put(v, name, node);
return p;
}
static void insert_sql(char *s)
{
if (*s++ != '(')
return;
struct vector *v = vector_create();
char *eintrag = build_node("eintrag", v, &s);
build_node("inhalt", v, &s);
build_node("name", v, &s);
build_node("bot", v, &s);
build_node("network", v, &s);
build_node("channel", v, &s);
build_node("zeit", v, &s);
build_node("type", v, &s);
if (eintrag && *eintrag)
bdb_store(eintrag, v);
vector_destroy(v);
}
static void replace_sql(char *s)
{
if (*s++ != '(')
return;
struct vector *v = vector_create();
char *eintrag = build_node("eintrag", v, &s);
build_node("inhalt", v, &s);
build_node("name", v, &s);
build_node("bot", v, &s);
build_node("channel", v, &s);
build_node("network", v, &s);
build_node("zeit", v, &s);
if (eintrag && *eintrag)
bdb_store(eintrag, v);
vector_destroy(v);
}
char *rip_query(char *orig_query)
{
assert(orig_query);
assert(strlen(orig_query) + 1 < 16383);
char *buf = ripple;
strcpy(buf, orig_query);
char *p;
const char *sq = "select * from calc where eintrag";
const char *rq =
"select *,rand() as r from calc where (NOT (eintrag LIKE 'command/dope";
const char *Rq = "select *,rand() as r from calc where type=0";
const char *rrq =
"select substring(eintrag,14) as eintrag, tag, if";
const char *rrrq = "select * from calc where ((eintrag > 'command";
const char *iq =
"insert into calc (eintrag,inhalt,name,bot,network,channel,zeit,type) ";
const char *rc =
"replace into calc (eintrag,inhalt,name,bot,channel,network,zeit) ";
const char *aa =
"select count(*) as anzahl from archiv where eintrag='";
const char *uc = "update calc set count=count+1, lastcall='";
const char *dc = "delete from calc where ";
if (!strncmp(buf, sq, strlen(sq))) {
p = buf + strlen(sq);
while (*p == ' ')
p++;
if (*p == '=')
p++;
while (*p == ' ')
p++;
if (*p == '\'')
p++;
if (p[strlen(p) - 1] == '\'')
p[strlen(p) - 1] = 0;
while (*p && p[strlen(p) - 1] == '/')
p[strlen(p) - 1] = 0;
return p;
} else if (!strncmp(buf, rq, strlen(rq))) {
strcpy(ripple, "randsinglecmd()");
return ripple;
} else if (!strncmp(buf, Rq, strlen(Rq))) {
strcpy(ripple, "randcalc()");
return ripple;
} else if (!strncmp(buf, rrq, strlen(rrq))) {
strcpy(ripple, "randcmds()");
return ripple;
} else if (!strncmp(buf, rrrq, strlen(rrrq))) {
strcpy(ripple, "randcmd()");
return ripple;
} else if (!strncmp(buf, dc, strlen(dc))) {
p = buf + strlen(dc);
if (strncmp(p, "eintrag='", strlen("eintrag=")))
return 0;
p += strlen("eintrag='");
if (p[strlen(p) - 1] == '\'')
p[strlen(p) - 1] = 0;
bdb_delete(p);
return 0;
} else if (!strncmp(buf, iq, strlen(iq))) {
p = buf + strlen(iq);
if (strncmp(p, "values ", strlen("values ")))
return 0;
p += strlen("values ");
insert_sql(p);
return 0;
} else if (!strncmp(buf, rc, strlen(rc))) {
p = buf + strlen(rc);
if (strncmp(p, "values ", strlen("values ")))
return 0;
p += strlen("values ");
replace_sql(p);
return 0;
} else if (!strncmp(buf, aa, strlen(aa))) {
strcpy(ripple, "archivanzahl()");
return ripple;
} else if (!strncmp(buf, uc, strlen(uc))) {
p = buf + strlen(uc);
char *lastcall = malloc(strlen(p) + 1);
assert(lastcall);
strcpy(lastcall, p);
while (isdigit(*p))
p++;
const char *we = "' where eintrag='";
if (strncmp(p, we, strlen(we)))
return 0;
p += strlen(we);
if (p[strlen(p) - 1] == '\'')
p[strlen(p) - 1] = 0;
while (*p && p[strlen(p) - 1] == '/')
p[strlen(p) - 1] = 0;
char *memp = malloc(strlen(p) + 1);
assert(memp);
strcpy(memp, p);
struct vector *v = load_file(memp);
if (!v)
return 0;
char *count = vector_pick_string(v, "count");
assert(count);
int icount = atoi(count);
icount++;
free(count);
count = malloc(100);
assert(count);
sprintf(count, "%i", icount);
vector_replace_string(v, "count", count);
vector_replace_string(v, "lastcall", lastcall);
bdb_store(p, v);
vector_destroy(v);
return 0;
} else {
printf("Unsupported SQL-Query: „%s“\n", buf);
// exit(23);
return 0;
}
}

104
test.c Normal file
View File

@ -0,0 +1,104 @@
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include "datenstapel.c"
#include "com.c"
enum bool { FALSE, TRUE };
int main(int argc, char **argv)
{
char option, c, *puffer;
FILE *fd;
int i = 0, zeile = 0;
enum bool _FILE = FALSE;
enum bool _OPEN = FALSE;
if (argc < 2) {
fprintf(stderr, "\n%s -h ist dein freund\n", argv[0]);
exit(1);
}
while ((option = getopt(argc, argv, "-fh")) != EOF) {
i++;
switch (option) {
case 'f':
_FILE = TRUE;
break;
case 'h':
printf("\nSo gehts:\n"
"%s <parameter>\n\n"
"Argumente: -h diese Hilfe aufrufen\n"
" -f <file> inhalt der datei auswerten\n",
argv[0]);
exit(0);
break;
case '?':
fprintf(stderr,
"\nfalscher schalter, %s -h ist dein freund",
argv[0]);
exit(1);
break;
case 1:
if (_FILE == TRUE) {
printf
("versuche file. argc=%d i=%d argv=\n%s\n",
argc, i, argv[i]);
if ((fd = fopen(argv[i], "r")) != NULL) {
_OPEN = TRUE;
} else {
fprintf(stderr,
"konnte datei nicht öffnen\n");
exit(1);
}
i++;
} else
printf("Normaler String:\n%s\n", argv[i]);
break;
}
}
printf("\ngebe datei aus:\n");
puffer = malloc(513 * sizeof(char));
i = 0;
while ((c = getc(fd)) != EOF) {
puffer[i] = c;
i++;
if (c == '\n') {
puffer[i] = '\0';
printf("%d: <%s>", ++zeile, puffer);
i = 0;
continue;
}
if (i <= LINELENGTH)
continue;
puffer[i] = '\0';
puffer[i - 1] = '\n';
puffer[i - 2] = '\r';
i = 0;
break;
}
/*
while ( (fscanf(fd,"%s\n", puffer)) != EOF ) {
i++;
printf("%d: <%s>",i,puffer);
}
*/
free(puffer);
if (_OPEN == TRUE)
fclose(fd);
return 0;
}

73
testcom.c Normal file
View File

@ -0,0 +1,73 @@
//ver 0.2
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include "com.c"
// #include "resolv.c"
#define PORT 6667
void help()
{
printf("Usage: ./irc <irc server>\n");
exit(1);
}
int main(int argc, char *argv[])
{
int _socket = 0;
char eingabe[1000];
int l = 0;
pid_t _pid;
if (argc != 2)
help();
printf("\ncreate socket...\n");
_socket = resolve_ircd(argv[1]);
printf("socketfd: %d\n", _socket);
netsend(_socket, "USER arzt arzt.arzt.be arzt arzt\r\n");
netsend(_socket, "NICK ArztTest\r\n");
printf("aktiviere netrecv()\n");
switch (_pid = fork()) {
case -1:
fprintf(stderr, "fehler in fork()\n");
exit(-1);
break;
case 0:
printf("kindprozess aktiv, aktiviere netrecv()\n");
while (1) {
printf("%s", netrecv(_socket));
}
exit(0);
break;
default:
printf("elternprozess aktiv. kind hat pid %d\n", _pid);
break;
}
printf("EINGABE (max. 1000b) - LEERE ZEILE FÜR QUIT.\n\n ");
while (1) {
// fflush(stdin);
gets(eingabe);
// printf("%s",eingabe);
if ((l = strlen(eingabe)) == 0)
break;
// printf("L=%d\n",l);
eingabe[l] = '\r';
eingabe[l + 1] = '\n';
eingabe[l + 2] = '\0';
netsend(_socket, eingabe);
}
printf("exit\n");
kill(_pid, SIGINT);
disconnect_irc(_socket);
return 0;
}

633
vector.c Normal file
View File

@ -0,0 +1,633 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "node.h"
#include "vector.h"
#include "botforth.h"
#define STRINGLENGTH 255
#define DEBUG printf("\n---DEBUG---\n");
/* ********************************************* */
/* delete löscht ein element vom stapel */
/* return 1 wenn stack leer, 0 wenn IO */
/* übergabewert: ein element des stapels */
/* ********************************************* */
int vector_delete(struct vector *v, struct node *n)
{
// todo: rueckgabewerte einbauen
if (n == NULL || v->tail == NULL)
return 0;
v->size--;
assert(v->size >= 0);
if (n->prev != NULL)
n->prev->next = n->next;
else
v->head = n->next;
if (n->next != NULL)
n->next->prev = n->prev;
else
v->tail = n->prev;
return 2342;
}
/* ********************************************* */
/* clear gibt stapelspeicher komplett frei */
/* return 0 wenn I.O. */
/* übergabe: ein element des stapels */
/* umbauen, dass man den zu löschenden Vektor angibt, und nicht ein element */
/* ********************************************* */
int vector_destroy(struct vector *stapel)
{
struct node *elem, *newelem;
elem = stapel->head;
while (elem) {
//printf("\ngebe %0xd frei",elem);
newelem = elem->next;
node_destroy(elem);
elem = newelem;
}
//printf("\ngebe %0xd frei ... stack freigegeben\n",elem);
free(stapel);
return 0;
}
/* ********************************************* */
/* debug gibt listenelemente aus, deren adresse, */
/* inhalt des strings und wohin die * zeigen */
/* return 0 wenn I.O. und ausgabe */
/* uebergabe: ein element des stapels */
/* ********************************************* */
int debug(struct vector *v)
{
struct node *elem;
if (!v) {
printf("\n· Vector [leer]\n");
return 0;
}
printf("\n· Vector:\n");
if (!v->head)
printf(" [leer]\n");
elem = v->head;
while (elem) {
assert(elem->type < 20);
printf(" ");
switch (elem->type) {
case BF_TYPE_INT:
printf("int: %11s → %i\n", elem->name,
node_toInt(node_copy(elem)));
break;
case BF_TYPE_FLOAT:
printf("float: %11s → %g\n", elem->name,
node_toFloat(node_copy(elem)));
break;
case BF_TYPE_STRING:
case BF_TYPE_C_TEXT:
printf("str: %11s → „%s“\n", elem->name,
(char *) elem->content);
break;
default:
printf("%6d: „%s“ → ??? [%09lx]\n",
elem->type, elem->name,
(unsigned long) elem->content);
break;
}
assert(elem != elem->next);
assert(elem != elem->prev);
elem = elem->next;
}
return 0;
}
/***************************************
* top HOLT oberstes element vom stapel
*
* v: Vektor, von dem gelesen werden soll
*
* return: pointer auf das oberste Element
****************************************/
struct node *vector_top(struct vector *v)
{
if (v->tail != NULL) {
return v->tail;
}
return NULL;
}
/***************************************
* bottom HOLT unterstes element vom stapel
*
* v: Vektor, von dem gelesen werden soll
*
* return: pointer auf das unterste Element
****************************************/
struct node *vector_bottom(struct vector *v)
{
if (v->head != NULL) {
return v->head;
}
return NULL;
}
/* ************************************************ */
/* push legt ein neues element mit inhalt buffer */
/* auf den stapel */
/* return 0 wenn I.O. */
/* übergabe: element der liste und *buffer (string) */
/* ************************************************ */
int vector_push(struct vector *v, struct node *n)
{
assert(v != NULL);
assert(n != NULL);
assert(n->type < 20);
n->prev = v->tail;
n->next = NULL;
if (v->tail != NULL)
v->tail->next = n;
if (v->head == NULL)
v->head = n;
v->tail = n;
v->size++;
return 1;
}
// todo: vector_put_string verwenden
int vector_push_string(struct vector *v, char *content)
{
struct node *n = node_create(content, BF_TYPE_STRING);
char *name = malloc(1);
name[0] = '\0';
n->name = name;
return vector_push(v, n);
}
int vector_push_int(struct vector *v, int content)
{
int *temp;
struct node *n;
char *name = malloc(1);
name[0] = '\0';
temp = malloc(sizeof(int));
*temp = content;
n = node_create(temp, BF_TYPE_INT);
n->name = name;
return vector_push(v, n);
}
int vector_push_float(struct vector *v, float content)
{
float *temp;
struct node *n;
char *name = malloc(1);
name[0] = '\0';
temp = malloc(sizeof(float));
*temp = content;
n = node_create(temp, BF_TYPE_FLOAT);
n->name = name;
return vector_push(v, n);
}
// todo: vector_put_vector verwenden
int vector_push_vector(struct vector *v, struct vector *content)
{
struct node *n = node_create(content, BF_TYPE_VECTOR);
char *name = malloc(1);
name[0] = '\0';
n->name = name;
return vector_push(v, n);
}
int vector_push_node(struct vector *v, struct node *content)
{
struct node *n = node_create(content, BF_TYPE_NODE);
char *name = malloc(1);
name[0] = '\0';
n->name = name;
return vector_push(v, n);
}
int vector_push_pointer(struct vector *v, struct node *content)
{
struct node *n = node_create(content, BF_TYPE_POINTER);
char *name = malloc(1);
name[0] = '\0';
n->name = name;
return vector_push(v, n);
}
int vector_push_db(struct vector *v, struct db *content)
{
struct node *n = node_create(content, BF_TYPE_DB);
char *name = malloc(1);
name[0] = '\0';
n->name = name;
return vector_push(v, n);
}
/* ************************************************
* unshift legt ein neues element mit inhalt buffer
* unter den stapel
* return 1 wenn I.O.
* übergabe: element der liste und *buffer (string)
* ************************************************ */
int vector_unshift(struct vector *v, struct node *n)
{
assert(v != NULL);
assert(n != NULL);
assert(n->type < 20);
n->next = v->head;
n->prev = NULL;
if (v->head != NULL)
v->head->prev = n;
if (v->tail == NULL)
v->tail = n;
v->head = n;
v->size++;
return 1;
}
/* ************************************************* */
/* pop HOLT operstes element vom stapel und schreibt */
/* dess inhalt in *buffer, dann wird das oberste */
/* element entfernt */
/* return: zeiger auf buffer (string/charray) */
/* ************************************************* */
struct node *vector_pop(struct vector *v)
{
struct node *n;
n = vector_top(v);
if (n) {
vector_delete(v, n);
return n;
}
return NULL;
}
char *vector_pop_string(struct vector *v)
{
char *temp;
struct node *n = vector_pop(v);
temp = node_toString(n);
return temp;
}
int vector_pop_int(struct vector *v)
{
int temp;
struct node *n = vector_pop(v);
temp = node_toInt(n);
return temp;
}
float vector_pop_float(struct vector *v)
{
float temp;
struct node *n = vector_pop(v);
temp = node_toFloat(n);
return temp;
}
struct vector *vector_pop_vector(struct vector *v)
{
struct vector *temp;
struct node *n = vector_pop(v);
temp = node_toVector(n);
return temp;
}
struct node *vector_pop_node(struct vector *v)
{
struct node *temp;
struct node *n = vector_pop(v);
temp = node_toNode(n);
return temp;
}
struct node *vector_pop_pointer(struct vector *v)
{
struct node *temp;
struct node *n = vector_pop(v);
temp = (struct node *) node_toPointer(n);
return temp;
}
struct db *vector_pop_db(struct vector *v)
{
struct node *n = vector_pop(v);
struct db *tmp = node_todb(n);
return tmp;
}
/* *************************************************
* shift HOLT das unterste element vom stapel und
* *************************************************/
struct node *vector_shift(struct vector *v)
{
struct node *n;
n = vector_bottom(v);
if (n) {
vector_delete(v, n);
return n;
}
return NULL;
}
/*********************************
* Lädt einen Node aus einem Vektor anhand seines Namens, ohne ihn
* zu löschen
*********************************/
struct node *vector_pick(struct vector *v, char *name)
{
struct node *pos;
assert(v != NULL);
pos = v->tail;
while (pos != NULL && strcmp(pos->name, name) != 0) {
pos = pos->prev;
if (pos != NULL)
assert(pos->name != NULL);
}
if (pos != NULL) {
assert(pos->type < 20);
return pos;
}
return NULL;
}
char *vector_pick_string(struct vector *v, char *name)
{
char *temp;
struct node *n = vector_pick(v, name);
if (n)
return node_toString(node_copy(n));
temp = malloc(1);
*temp = 0;
return temp;
}
int vector_pick_int(struct vector *v, char *name)
{
int temp;
struct node *n = vector_pick(v, name);
temp = node_toInt(n);
return temp;
}
struct vector *vector_pick_vector(struct vector *v, char *name)
{
struct vector *temp;
struct node *n = vector_pick(v, name);
temp = node_toVector(n);
return temp;
}
struct node *vector_pick_node(struct vector *v, char *name)
{
struct node *temp;
struct node *n = vector_pick(v, name);
temp = node_toNode(n);
return temp;
}
/*************************************
* Lädt einen Node aus einem Vektor anhand seines Namens und löscht iht
*************************************/
struct node *vector_get(struct vector *v, char *name)
{
struct node *pos;
pos = v->tail;
while (pos != NULL && strcmp(pos->name, name) != 0) {
pos = pos->prev;
if (pos != NULL)
assert(pos->name != NULL);
}
if (pos != NULL) {
v->size--;
assert(v->size >= 0);
// node zwar nicht loeschen, aber aus dem vector "entlinken"
if (v->tail == pos)
v->tail = pos->prev;
if (v->head == pos)
v->head = pos->next;
if (pos->prev)
pos->prev->next = pos->next;
if (pos->next)
pos->next->prev = pos->prev;
return pos;
}
return NULL;
}
char *vector_get_string(struct vector *v, char *name)
{
struct node *n = vector_get(v, name);
return node_toString(n);
}
int vector_get_int(struct vector *v, char *name)
{
struct node *n = vector_get(v, name);
return node_toInt(n);
}
/*************************************
* Hängt genauso wie push einen Node hinten an den Vektor an, wobei hier
* der Node noch einen Namen bekommt
*/
int vector_put(struct vector *v, char *name, struct node *n)
{
char *newname;
assert(name != NULL);
assert(n != NULL);
assert(v != NULL);
assert(n->type < 10);
if (v == NULL || n == NULL)
return 0;
newname = malloc(strlen(name) + 1);
sprintf(newname, "%s", name);
if (n->name)
free(n->name);
n->name = newname;
return vector_push(v, n);
}
int vector_put_vector(struct vector *v, char *name, struct vector *content)
{
struct node *n = node_create(content, BF_TYPE_VECTOR);
assert(name != NULL);
return vector_put(v, name, n);
}
int vector_put_string(struct vector *v, char *name, char *content)
{
struct node *n = node_create(content, BF_TYPE_STRING);
return vector_put(v, name, n);
}
/*************************************
* Ersetzt einen Knoten eines Vektors durch einen neuen Knoten, wobei
* der Knoten durch seinen Namen gegeben wird
*************************************/
int vector_replace(struct vector *v, char *name, struct node *n)
{
struct node *temp;
char *newname;
if (v == NULL || n == NULL)
return 0;
assert(n != NULL);
temp = vector_pick(v, name);
if (temp) {
// Ein zu ersetzender Knoten gefunden, nun Referenzen umhängen
if (v->head == temp)
v->head = n;
if (v->tail == temp)
v->tail = n;
if (temp->next)
temp->next->prev = n;
if (temp->prev)
temp->prev->next = n;
n->next = temp->next;
n->prev = temp->prev;
newname = malloc(strlen(name) + 1);
sprintf(newname, "%s", name);
n->name = newname;
//free(temp->name);
//free(temp);
node_destroy(temp);
// todo: warum absturz, wenn node_destroy statt free bei !clearcache?
// momentan ist das hier jedenfalls ein speicherleck
} else {
// Kein Knoten gefunden, den neuen Knoten also einfach putten
printf("put\n");
vector_put(v, name, n);
}
return 1;
}
int vector_replace_string(struct vector *v, char *name, char *content)
{
struct node *n = node_create(content, BF_TYPE_STRING);
return vector_replace(v, name, n);
}
int vector_replace_int(struct vector *v, char *name, int content)
{
int *temp;
struct node *n;
temp = malloc(sizeof(int));
*temp = content;
n = node_create(temp, BF_TYPE_INT);
return vector_replace(v, name, n);
}
int vector_replace_vector(struct vector *v, char *name,
struct vector *content)
{
struct node *n = node_create(content, BF_TYPE_VECTOR);
assert(n != NULL);
return vector_replace(v, name, n);
}
int vector_replace_node(struct vector *v, char *name, struct node *content)
{
struct node *n = node_create(content, BF_TYPE_NODE);
return vector_replace(v, name, n);
}
/*******************
* fügt einen Node nach einem gegebenen Node ein
******************/
int vector_insert(struct vector *v, struct node *n, struct node *new)
{
new->next = n->next;
if (v->tail == n)
v->tail = new;
new->prev = n;
if (new->next)
new->next->prev = new;
n->next = new;
v->size++;
assert(v->size >= 0);
return 0;
}
/* ***************************************** */
/* empty prüft ob elemente im stapel liegen */
/* return 1: stapel ist LEER */
/* return 0; stapel ist NICHT leer */
/* uebergabe: ein element vom stapel */
/* ***************************************** */
int vector_empty(struct vector *v)
{
if (v->head == NULL)
return 1;
return 0;
}
int vector_size(struct vector *v)
{
return v->size;
}
struct vector *vector_create()
{
struct vector *v = malloc(sizeof(struct vector));
v->head = NULL;
v->tail = NULL;
v->size = 0;
return v;
}
struct vector *vector_copy(struct vector *v)
{
struct vector *newv;
struct node *newn, *pos;
assert(v);
newv = vector_create();
pos = v->head;
if (pos == NULL) {
newv->head = NULL;
newv->tail = NULL;
}
// todo: was ist mit den namen der elemente?
while (pos != NULL) {
assert(pos->type < 20);
newn = node_copy(pos);
vector_push(newv, newn);
pos = pos->next;
}
return newv;
}
/*
int main() {
struct vector *v=vector_create();
char *buffer;
struct node *n;
int i;
vector_push_string(v,"null");
vector_push_string(v,"eins");
vector_push_int(v,2);
vector_push_string(v,"3");
vector_push_string(v,"vier");
vector_replace_string(v,"erstes","ERSTES");
vector_replace_string(v,"zweites","ZWEITES");
vector_replace_string(v,"erstes","NEUES ERSTES");
debug(v);
for(i=0;i<8;i++) {
buffer=vector_pop_string(v);
printf("%s\n",buffer);
}
}
*/

60
vector.h Normal file
View File

@ -0,0 +1,60 @@
#ifndef VECTOR_H
#define VECTOR_H
#include "def.h"
struct vector {
struct node *head;
struct node *tail;
int size;
};
extern int vector_destroy(struct vector *stapel);
extern int vector_delete(struct vector *v, struct node *n);
extern int vector_clear(struct node *stapel);
extern struct vector *vector_copy(struct vector *v);
extern struct node *vector_top(struct vector *v);
extern int vector_push(struct vector *v, struct node *n);
extern int vector_push_string(struct vector *v, char *content);
extern int vector_push_int(struct vector *v, int content);
extern int vector_push_vector(struct vector *v, struct vector *content);
extern int vector_push_node(struct vector *v, struct node *content);
extern int vector_push_pointer(struct vector *v, struct node *content);
extern struct node *vector_pop(struct vector *v);
extern char *vector_pop_string(struct vector *v);
extern int vector_pop_int(struct vector *v);
extern struct vector *vector_pop_vector(struct vector *v);
extern struct node *vector_pop_node(struct vector *v);
extern struct node *vector_pop_pointer(struct vector *v);
extern struct node *vector_pick(struct vector *v, char *name);
extern char *vector_pick_string(struct vector *v, char *name);
extern int vector_pick_int(struct vector *v, char *name);
extern struct vector *vector_pick_vector(struct vector *v, char *name);
extern struct node *vector_pick_node(struct vector *v, char *name);
extern struct node *vector_get(struct vector *v, char *name);
extern char *vector_get_string(struct vector *v, char *name);
extern int vector_get_int(struct vector *v, char *name);
extern int vector_put(struct vector *v, char *name, struct node *n);
extern int vector_put_vector(struct vector *v, char *name,
struct vector *content);
extern int vector_replace(struct vector *v, char *name, struct node *n);
extern int vector_replace_string(struct vector *v, char *name,
char *content);
extern int vector_replace_int(struct vector *v, char *name, int content);
extern int vector_replace_vector(struct vector *v, char *name,
struct vector *content);
extern int vector_replace_node(struct vector *v, char *name,
struct node *content);
extern int vector_empty(struct vector *v);
extern struct vector *vector_create();
extern int vector_size(struct vector *v);
extern struct node *vector_shift(struct vector *v);
extern int vector_unshift(struct vector *v, struct node *n);
extern int vector_push_float(struct vector *v, float content);
extern float vector_pop_float(struct vector *v);
extern int vector_push_db(struct vector *v, struct db *content);
extern struct db *vector_pop_db(struct vector *v);
extern int debug(struct vector *v);
#endif