initialize
This commit is contained in:
commit
baffac466d
8
.gitignore
vendored
Executable file
8
.gitignore
vendored
Executable file
@ -0,0 +1,8 @@
|
||||
*~
|
||||
\#*\#
|
||||
*.o
|
||||
calc.*
|
||||
botforth
|
||||
db
|
||||
log
|
||||
l
|
4
LICENSE
Normal file
4
LICENSE
Normal 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
25
Makefile
Normal 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
115
README
Normal 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
947
botforth.c
Normal 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
59
botforth.h
Normal 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
274
com.c
Normal 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
54
com.h
Normal 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);
|
1
command/compiler/'?address
Normal file
1
command/compiler/'?address
Normal file
@ -0,0 +1 @@
|
||||
"cstack_get_address" 'command
|
1
command/compiler/'@address
Normal file
1
command/compiler/'@address
Normal file
@ -0,0 +1 @@
|
||||
"cstack_put_address" 'command
|
1
command/compiler/'command
Normal file
1
command/compiler/'command
Normal file
@ -0,0 +1 @@
|
||||
"cstack_push_command" cstack_push_command
|
1
command/compiler/'const
Normal file
1
command/compiler/'const
Normal file
@ -0,0 +1 @@
|
||||
"cstack_push" cstack_push_command
|
4
command/compiler/*
Normal file
4
command/compiler/*
Normal file
@ -0,0 +1,4 @@
|
||||
"mul" 'command
|
||||
|
||||
|
||||
|
1
command/compiler/+
Normal file
1
command/compiler/+
Normal file
@ -0,0 +1 @@
|
||||
"add" 'command
|
18
command/compiler/+loop
Normal file
18
command/compiler/+loop
Normal 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
1
command/compiler/-
Normal file
@ -0,0 +1 @@
|
||||
"sub" 'command
|
2
command/compiler/<
Normal file
2
command/compiler/<
Normal file
@ -0,0 +1,2 @@
|
||||
"swap" 'command
|
||||
"greaterthan" 'command
|
1
command/compiler/>
Normal file
1
command/compiler/>
Normal file
@ -0,0 +1 @@
|
||||
"greaterthan" 'command
|
1
command/compiler/>r
Normal file
1
command/compiler/>r
Normal file
@ -0,0 +1 @@
|
||||
"rstack_push" 'command
|
4
command/compiler/do
Normal file
4
command/compiler/do
Normal file
@ -0,0 +1,4 @@
|
||||
"swap" 'command
|
||||
">r" 'command
|
||||
">r" 'command
|
||||
"nop" 'command '?address
|
4
command/compiler/else
Normal file
4
command/compiler/else
Normal file
@ -0,0 +1,4 @@
|
||||
44 'const '?address
|
||||
"__b" 'command
|
||||
swap
|
||||
"nop" 'command '?address '@address
|
3
command/compiler/i
Normal file
3
command/compiler/i
Normal file
@ -0,0 +1,3 @@
|
||||
"r>" 'command
|
||||
"dup" 'command
|
||||
">r" 'command
|
6
command/compiler/i'
Normal file
6
command/compiler/i'
Normal file
@ -0,0 +1,6 @@
|
||||
"r>" 'command
|
||||
"r>" 'command
|
||||
"dup" 'command
|
||||
">r" 'command
|
||||
"swap" 'command
|
||||
">r" 'command
|
4
command/compiler/if
Normal file
4
command/compiler/if
Normal file
@ -0,0 +1,4 @@
|
||||
"not" 'command
|
||||
42 'const
|
||||
'?address
|
||||
"__bz" 'command
|
2
command/compiler/loop
Normal file
2
command/compiler/loop
Normal file
@ -0,0 +1,2 @@
|
||||
1 'const
|
||||
"+loop" 'command
|
1
command/compiler/pi
Normal file
1
command/compiler/pi
Normal file
@ -0,0 +1 @@
|
||||
"3.14" 'const
|
2
command/compiler/r>
Normal file
2
command/compiler/r>
Normal file
@ -0,0 +1,2 @@
|
||||
"rstack_pop" 'command
|
||||
|
3
command/compiler/sub
Normal file
3
command/compiler/sub
Normal file
@ -0,0 +1,3 @@
|
||||
-1 cstack_push
|
||||
"*" cstack_push_command
|
||||
"+" cstack_push_command
|
1
command/compiler/then
Normal file
1
command/compiler/then
Normal file
@ -0,0 +1 @@
|
||||
"nop" 'command '?address '@address
|
6
command/system/init
Normal file
6
command/system/init
Normal 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
1
command/system/zahlen
Normal file
@ -0,0 +1 @@
|
||||
30 40 50
|
361
db.c
Normal file
361
db.c
Normal 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
240
db_bdb.c
Normal 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
269
db_cdb.c
Normal 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
37
def.h
Normal 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
103
entwurf.txt
Normal 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
4
feuerzeug
Executable 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
5
feuerzeug-proxychains
Executable 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
5
feuerzeug-tsocks
Executable 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
112
file.c
Normal 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
673
getintcommand.c
Normal 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
1309
intcommands.c
Normal file
File diff suppressed because it is too large
Load Diff
28
makeintcommand.sh
Executable file
28
makeintcommand.sh
Executable 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
284
node.c
Normal 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
25
node.h
Normal 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
220
sql.c
Normal 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
104
test.c
Normal 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
73
testcom.c
Normal 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
633
vector.c
Normal 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
60
vector.h
Normal 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
|
Loading…
Reference in New Issue
Block a user