Console loop

////// Default, Console loop, Shunt ///////////

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <dlfcn.h>
#include <stdarg.h>
#include <setjmp.h>
#include <unistd.h>
#include "/home/so/maps.h"
#define CONSOLE_VERSION " Console 1.0.13"
#define putstr(a) fputs(a,stdout)
int fputstrs(FILE* fd, const char *str, ...);
#define putstrs(...) fputstrs (stdout, __VA_ARGS__)

// Using long jump to clear error duing execution
static jmp_buf env;
int runtime_error=1;

// ### compile constants, this does not call malloc
#define MAXSYM 200
#define MAXARGS 1024
#define MAXDEPTH 6
#define MAXTOKS 256
#define MAXCHRS 32
#define MAXSRC 4096
#define MAXLINE  64
#define MAXMODULE 10

// syntax flag format specific to Default
// Used variously to hold information about a token
// including the syntax tags,a compiled in defnition of Default
typedef struct {
char * src;
int form;
int len;
int prec;
} Tag;
//////// ### Universals //////
typedef int EntryType(int *, void**);
// Reentrant, searches all known locations for command
int ExecCommand(int * argc, void * args[]);
// Default variable forms
typedef union { unsigned long l; char * s; void * vp;
char txt[8]; Tag *tag; EntryType * entry;
} Val;
/////////### Symbol Table Defs///////////
typedef struct {
char  *name;
int len;
int type;
Val val;
} Sym;
typedef  Sym* PSym;
Sym * GetSym(char * name);
Sym * PutSym(char * name);

// specialty stacks with fill and empty
typedef struct {
Val * list;
int empty;
int fill;
} Stack;
typedef Stack* PStack;

// ### Tags ///////////////////////////////////////////
// Syntax reporting utilities
int syntax_tags_error(char * error, char * src,int lineno);

// Token types, used everywhere, first four are position dependent
enum { undef_tag, string_tag, int_tag, var_tag,
block_tag,op_tag,macro_tag,entry_tag,
builtin_tag,while_tag,assign_tag,null,fname_tag,comment,end_tag,tag_type};
#define T(a,b,...) {a,b,sizeof(a)-1, __VA_ARGS__}
Tag syntax_tags[] = {
  T("undef_tag",undef_tag,0), T("string",string_tag,5),
  T("integer",int_tag,6),T("variable",var_tag,5,),
  T("{",block_tag,8),T("}",block_tag,0),
T("+",op_tag,4),T("-",op_tag,4),
T("/",op_tag,3),T("*",op_tag,3),
T("macro_tag",macro_tag),
T("(",op_tag,0),T(")",op_tag,0), // These are op_tags for Shunt
T("//",fname_tag,3), T("./",fname_tag,3),T("..",fname_tag,3), // selector op
T("=",assign_tag,0), T("while",while_tag,10),T(";",end_tag,0)
};
#define NKEYS sizeof(syntax_tags)/sizeof(Tag)
void init_tags() {
PSym s;
int i;
for(i=0;i< NKEYS;i++){
syntax_tags[i].len=strlen(syntax_tags[i].src);
s = PutSym(syntax_tags[i].src);
s->val.tag= &syntax_tags[i];
s->type=tag_type;
s->len=syntax_tags[i].len;
}
}  // Bit of spaghetti for double ops
int len_tok(char *name ) {
int  len;
if(ispunct(*name) ) {
len=1;
if(!strchr("(){};",*name) && (ispunct( *(name+1) )) )
len=2; // double op
} else len = strlen(name);
return(len);
}
// Fill in a tag descriptor from some token
int  make_tag(char * code,Tag * tag) {
if(isdigit(*code)) {
*tag =syntax_tags[int_tag];
tag->src=code;
tag->len=0;
while(isdigit(code[tag->len])) tag->len++;
return(SUCCESS);
}
PSym s = GetSym(code);
if (s) {
if(s->type == tag_type)  {
*tag = *s->val.tag;
return(SUCCESS);
}
if(isalpha(*code)) {
tag->src=code;
tag->len=strlen(code);
tag->prec= syntax_tags[var_tag].prec;
} else
return(syntax_tags_error("Bad name,code", code,__LINE__));
if(s->type == macro_tag)
tag->form= macro_tag;
else
tag->form= var_tag;
return(SUCCESS);
}
if(isalpha(*code)) {
*tag = syntax_tags[string_tag];
tag->src=code;
tag->len=strlen(code);
return(SUCCESS);
}
return(syntax_tags_error("No tag",code, __LINE__));
}

// Symbol space
Sym symbols[MAXSYM];
int symbols_index=0;

///////////### Assembler /////////////////
// args have this assembly structure for Default
////  Fixed sizes everywhere and the purists will pester me
// A typedef on args list
typedef struct {
char * TokStrs[4];
long Accum;  // for expression execution
Val Toks[MAXTOKS]; // Tokenizers output from source
Val Data[MAXARGS]; // Syntax engine output

} Base;
typedef Base * PBase;
// Tokenizer and format stuff with punctuation
#define D_FilePuncts    "-_./"
#define D_OpPuncts    ";{}()*/=+-^&."
#define D_NamePuncts   "_."
#define D_QuotePuncts    "'\"`"

Base D_Base = {
{ D_OpPuncts, D_NamePuncts,
D_FilePuncts,D_QuotePuncts}};
char Strings[MAXSRC];  // Siurce,where tokens get null terminated
int ArgcBase=0; // Current argc
int TokeBase=0; // the original tokens we identified from source
int TokeEnd=0; // End of token list
int StartCommand=0; // Tracks the start of Bus command point
int DepthBase=0; // Recursion depth
int syntax_flag=0;  // A control variabe fr syntax engines, ill defined
////////////////////////////////////////////////////////
// Default assembler - One pass over the console tokens  will execute code
// Process the tags list and generate cmd format sequences

int  DefaultTags( int * argc,void *args[]);
// Calling Shunt here eats the parenth pair
int  make_expr(int *argc,void *args[])  {
int base = *argc;
args [base]=  "Shunt";
args[base + 1] = (void *) (long)  TokeBase;// source of expression
ExecCommand(argc,args); // Called in standard format
int size = (long)  *argc -  base;
args [base]= "expr_cmd";  // executable form
args[base + size-1] =  ";"; // terminate
return(1);
}
int make_macro(int *argc,void *args[]){
DepthBase++;
DefaultTags(argc,args);  // defne the executable loop
DepthBase--;
// some over kill on macro exit
args[*argc] =  "exit_cmd";
*argc +=1;
args[*argc] =  ";";
*argc +=1;
return(1);
}
int make_while(int *argc,void *args[]){
int base = *argc;
args[*argc] = "while_cmd";  // force the while
*argc += 1;
make_expr(argc,args);
make_macro(argc,args);
args[*argc] =  ";";
*argc +=1;
return(base);
}
int make_assign(int *argc,void *args[]) {
int base = *argc;
args[*argc]="assign_cmd";
*argc +=1;
TokeBase++; // skip the equals op
*argc += 1;
make_expr(argc,args);
return(base);
}
// Get a tag desscriptor and decide what to do
void source_type(char * src, Tag * tag) {
char ch;
make_tag(src,tag);
// Raw Text, variable or undefined pass thru
if( (tag->form == string_tag) && D_Base.Toks[TokeBase+1].l) {
ch= D_Base.Toks[TokeBase+1].s[0]; // peek
if(ch == '(')   tag->form = macro_tag;
else if(ch == '=')  tag->form = assign_tag;
}
}
#define  RUNX  if(!DepthBase) {\
*argc=base;\
ExecCommand(argc,args); \
}
// Assemble and execution start
int  DefaultTags( int * argc,void *args[]) {
Tag T;
char * src;
PSym s;
int base;
while(1) {
// look at original tokens and discern something aboutthem
if(TokeBase == TokeEnd) return(SUCCESS);
src = D_Base.Toks[TokeBase].s;
if(src == 0) syntax_tags_error("Not closed",0,__LINE__);
source_type(src,&T);
TokeBase++; // We never look at a token twice
base = *argc;
switch(T.form) {
case macro_tag:
s=GetSym(T.src);
if(!s) {  // define
putstrs("New Macro ",T.src,"\n",0);
s = PutSym(T.src);
s->val.l = *argc; // binding this spot, here
s->type=macro_tag; // In the command spot, this will be called.
make_macro(argc,args);
}
else{
args[*argc] = T.src;
RUNX else (*argc) += 1;
}
break;
case while_tag:
make_while(argc,args);;
RUNX;
break;
case assign_tag: // Equals sign
make_assign(argc,args);
args[base+1]= T.src; // destination name
RUNX;
break;
case end_tag: // Handles inux pass thru
args[*argc]=";";  // Making sure
*argc +=1;
base=StartCommand;
RUNX;
break;
case block_tag: // blocking characters, the bracket likely
if(T.src[0] == '}') DepthBase--;
if(T.src[0] == '{') DepthBase++;
if(!DepthBase) StartCommand=base;
break;
case op_tag: // mainly the parenth is ignored if not in expression
break;
default:
args[*argc] = T.src;
(*argc) += 1;
break;
}

}
}

////### Execution methods //////////////
// Entry points exposed to the Bus
//////////////////////////////////////
//0un time assignment
long ValToken(Val);  // Reesolves symbol
int binop(Val op,PStack stk);
Val pull(PStack s);
int exit_cmd(int * argc, void * args[]){
argc+=1;
return(EXIT);
}
int expr_cmd(int *argc,void * args[]) {
Val op;
Stack Stk;
*argc +=1;
Stk.empty=0;  // expression pulls from the bottom
Stk.list = (Val*) (args + *argc);
op.s= "="; // init the accumulator
binop(op,&Stk);
return(SUCCESS);
}
int binop(Val op,PStack stk) {
Val r;
r = pull(stk);
if(r.s[0] == ';')  return(SUCCESS);
if(ispunct(r.s[0]))
binop(r,stk);
r.l = ValToken(r);
if(op.s[0]== '=') D_Base.Accum = r.l;
else if(op.s[0] == '*' ) D_Base.Accum *= r.l;
else if(op.s[0] == '/') D_Base.Accum /= r.l;
else if(op.s[0] == '+') D_Base.Accum += r.l;
else if(op.s[0] == '-') D_Base.Accum -= r.l;
else syntax_tags_error("Operator unknown\n",op.s,__LINE__);
return(SUCCESS);
}

// While loop
int while_cmd(int * argc,void * args[]) {
int base =*argc+1;
do{
*argc=base;
ExecCommand(argc,args); // get the condition
if(!D_Base.Accum) break;
ExecCommand(argc,args);  // Then the definition
} while(1);
return(SUCCESS);
}
int assign_cmd(int * argc,void * args[]) {
*argc +=1;
PSym n=PutSym(args[*argc]);
*argc +=1;
ExecCommand(argc,args);
n->val.l= D_Base.Accum;
return(SUCCESS);
}
// Default reprocesses the tokenized output,
// sifting an executle up the args list.
int Default(int * argc, void * args[]) {
if(!TokeBase) { // First time through
*argc = 0; // code layout begins here
TokeBase++;
StartCommand = *argc;
}
if(!args[TokeBase]) return(CONTINUE); //Nothing to do
*argc= StartCommand;  // Continue where Default left off
args=(void **) D_Base.Data;  // swap segment,argc remains consistent
DefaultTags(argc,args);  // Assemble and execute
return(CONTINUE);
}

int Shunt(int * argc, void * args[]);
// Default built ins
int InitDefault(int * argc, void * args[]){return(SUCCESS);};
///////////### Shunt //////////

/* Shunt and stacks*/
#define OPS "^ * / + -"

int prec(char*  op) {
Tag T;
int k =make_tag(op,&T);
//printf("P %d %s\n",p,op);
if(k) return(T.prec);
else return(0 ); // alpha likely;
}

Val push(PStack s,Val x) {
s->list[s->fill++] =x;
return(s->list[s->fill-1]);
}
Val lift(PStack s,Val x) {
int i=s->fill;
for(i=s->fill;i > 0;  i--) s->list[i]=s->list[i-1];
s->list[i]=x;
return(s->list[s->fill++]);
}
Val pop(PStack s) {
return(s->list[--s->fill]);
}
Val pull(PStack s) {
return(s->list[s->empty++]);
}
Val top(PStack s) {
Val x;
x.l=0;
if(s->fill == 0) return(x);
return(s->list[s->fill-1]);
}
char topchar(PStack s) {
char * ptr=  top(s).s;
return(ptr[0]);
};

// Make the reverse polish notation onto args
// input is a parenth pair (...)

int shunt_cmd(PStack input,PStack output) {
Val datum;
Val opers[40];
int count=0;
Stack Oper;
Oper.fill=0;
Oper.list = opers;
do {
datum = pull(input);
TokeBase++;
if(datum.s[0] == ';') break;
if(datum.s[0] == ')') count--;
if(datum.s[0] == '(') count++;
if(Oper.fill)
while((prec(datum.s) < prec(top(&Oper).s) ) )
lift(output,pop(&Oper));
push(&Oper,datum);
} while(count);
while(Oper.fill) {
datum= pop(&Oper);
if((datum.s[0] != '(') && (datum.s[0] != ')'))
lift(output,datum);
}
return(SUCCESS);
}
// Shunt Input_loc
int Shunt(int * argc, void * args[]) {
Stack Output;
Stack Input;
int from;
Input.empty=0;
Output.fill=0;
*argc += 1; // Just past command
Output.list =(Val* ) (D_Base.Data + *argc);
from = Output.list[0].l; // start location of input tokens
Input.list = (Val *)(D_Base.Toks + from);
if(from != TokeBase)  // Kind of a default trick test
syntax_tags_error("Expression fouled",0,__LINE__);
shunt_cmd(&Input,&Output); // Read input write output
*argc += (Output.fill+1); // Expr size args[size]
return(SUCCESS);
}
///////### Modules,  files and console loop //////////////////////
typedef struct {
void * handle;  //open libs
EntryType * entry;
char  name[20]; } Module;


Module modules[MAXMODULE];
int modules_index=0;

void FreeModule(int i) {
dlclose(modules[i].handle);
}
void FreeModules() {
int i;
for(i=0;i < modules_index;i++)
FreeModule(i);
}
#define FNAME 30
char * make_fname(char * name,char * args[]) {
memset(name,0,FNAME);
int i;
char * ptr = name;
// Should be a // or ./
if(!strstr(".//",args[0]))
syntax_tags_error("Bad file name", args[0],__LINE__);
strcpy(ptr,args[0]);
strcat(ptr,args[1]);
i=strlen(ptr);
while(isalpha(ptr[i-1])) i--;
return(ptr+i);
}
 int LoadModule(int *argc, void *args[]) {
        void *handle;
        char *error;
        char name[FNAME];
        int base = *argc;
        int status;
        char * name_pos =  make_fname(name,(char **)( args + 1));   
        handle = dlopen (name, RTLD_LAZY | RTLD_LOCAL);
        putstrs("Loading ",name,0);
        if (!handle) {
            fputs (dlerror(), stdout);
            return(SUCCESS);
        }
        modules[modules_index].entry = dlsym(handle,name_pos);
        if ((error = dlerror()) != NULL)  {
            fputs(error, stdout);
            return(SUCCESS);
        }
        putstr(" Loaded\n");
        modules[modules_index].handle =handle;
        strcpy(modules[modules_index].name,name_pos);
        base++;
        args[base] = "Init";
        args[base+1]=ExecCommand; // the return entry for executing on the command bus
        putstrs("New Module %",modules[modules_index].name,0);
        status = (modules[modules_index].entry)(&base,args); // Run module Init
putstrs("New Module ", ( (status== SUCCESS) ? "Up" : "Fail") ,0);
PSym s = PutSym(modules[modules_index].name);
modules_index++;
s->type=entry_tag;
return(SUCCESS);
    }
int UnloadModule(int *argc, void *args[]) {
char * name = args[1];
int i;
while(i < modules_index && strcmp(modules[i].name,name)) i++;
modules_index--;
while(i < modules_index)  {
modules[i]=modules[1+1];
i++;
}
return(SUCCESS);
}
int ConsoleLoop(FILE *);
int ExecFile(int * argc, void * args[]) {
char name[FNAME];
    make_fname(name,(char **) (args+1));
FILE* fin;
if(syntax_flag == CONTINUE) syntax_tags_error("Not allowed in script",name,__LINE__);
fin = fopen(name,"rb");
if(!fin) {
printf("\n no file %s\n",name);
return(SUCCESS);
}
memset(&Strings,0,sizeof(Strings));
//fread(p,1,MAXSRC-1,fin);
ConsoleLoop(fin);
return(SUCCESS);
}

char * arg_text(char * str, Val val) {
int len,i;
if(!val.vp) sprintf(str," NULL  ");
else if(val.l < MAXINT) sprintf(str,"%8ld",val.l);
else {
len = len_tok(val.s);
for(i=0;i < len;i++){
*str=val.s[i];
str++;
}
*str=0;
}
return(str);
}

int ListArgs(int *argc, void * args[]) {
int i=1;
char  text[MAXCHRS*4];
Val * val = D_Base.Toks;
putstr("Toks \n");
for(i= 0;i < 32; i++) {
arg_text(text,val[i]);
printf("%s ",text);
if(!((i+1)  % 16) ) printf("\n");
}
val = D_Base.Data;
putstr("\nArgs \n");
for(i= 0;i < 32; i++) {
arg_text(text,val[i]);
printf("%s ",text);
if(!((i+1) % 16) ) printf("\n");
}
putstr("\n");
*argc +=1;
return(SUCCESS);
}

int ListNames(int *argc, void * args[]) {
int i;
putstr("-- Names --\n");
for(i=0;i < symbols_index;i++)
printf("%s %ld \n",symbols[i].name,symbols[i].val.l);
*argc +=1;
return(SUCCESS);
}
int GetKey(int *argc, void * args[])  {
PSym s= GetSym(args[*argc +1]);
if(s)
args[*argc +2]= s->val.vp;
else
args[*argc +2]=0;
return(SUCCESS);

}


// using # for comments and semi colons
// fill in the bottom of args with token pointers

#define flush_line(a,b) {*a=0; do a++; while(*a && (*a != b));}
char * argtoks(char * src ) {
//PBase p = &D_Base;
Val * p= D_Base.Toks;
char * op=0;
char * end=0;
char  ch=0;
while(*src) {
while(*src && isspace(*src ) ) src++; // skip valid arg separator
if(!(*src)) {
if(ch) *end=0;
break;
} else if(*src == '#') 
flush_line(src,'\n') // comment
else if(strchr(D_QuotePuncts, *src))
flush_line(src,*src) // quote
else if((op = strchr(D_OpPuncts, *src))) { // operator, single or double
PSym sym = GetSym(src);
if(!sym) syntax_tags_error("Bad op",op,__LINE__);
if(sym->type != tag_type)  syntax_tags_error("Bad tag",op,__LINE__);
if(ch) *end=0;  // termine any previous string
ch = 0;
p[TokeEnd].s=sym->name; // version from table
TokeEnd++;
src +=sym->len;
if(sym->val.tag->form == fname_tag)  { // file name , collect expression
p[TokeEnd].s= src;  // collecting fname token
TokeEnd++;
while( *src &&
( isalnum(*src) || strchr(D_FilePuncts,*src) )) src++;
end=src;
ch = *(end-1);
}
} else{ // must be name
p[TokeEnd].s= src;
if(ch) *end=0;
while( *src && ( isalnum(*src)
|| strchr(D_NamePuncts,*src)) ) 
src++; // while valid arg charn
end=src;
ch= *(end-1);
TokeEnd++;
}
}
return(src);
}
int Tokenize(int * argc, void*args[]) {
char * str= args[*argc+1];
TokeBase=0;TokeEnd=0;
argtoks(str);  // fill args with tkens, in place
*argc =TokeBase; // Args got wiped
return(SUCCESS);
}

// Here is where we would first
// check for any macro expanion on the bus
int ExecCommand(int * argc, void * args[]) {
int mode=NOTFOUND;
int i=0;
int base;
Val v;
EntryType *entry;
v = (Val) args[*argc];
if(!strcmp(v.s,"qt")) exit(1);
if(v.s[0]==';') {
*argc +=1;
mode=SUCCESS;}
if(mode==NOTFOUND) {
PSym s= GetSym(args[*argc]);
if(s) {
if(s->type==builtin_tag) {
entry = s->val.entry;
mode = entry(argc,args);
} else if(s->type==entry_tag) {
entry = s->val.entry;
*argc +=1;
mode = entry(argc,args);
} else if( s->type == macro_tag) {   // If this is an expansion, just recurse
base=*argc;
*argc = s->val.l;
do
mode = ExecCommand(argc,args);
while(mode != EXIT);
*argc=base+1;
}
}
}
if(mode == NOTFOUND){
while(i <  modules_index) {
mode=modules[i].entry(argc,args);
i++;
if(mode != NOTFOUND) break;;
}
if(mode == NOTFOUND) putstr("Unknown\n");

}
#ifdef SYSTEM
if(mode == NOTFOUND)
mode = ((system(argv[*argc]) < 0)  ? NOTFOUND : SUCCESS);
#endif
if(mode == NOTFOUND)
while(v.s && (v.s[0] != ';')){
*argc +=1;
v = D_Base.Data[*argc];
}
StartCommand=*argc; // Next undefined start point
return(mode);
}
// Test string
char *last = "Default MyLoad() {LoadModule ./tester; LoadModule ./xchars;}";
char * get_line(FILE * fin,char * str) {
// Chk fo max src here
if((str-Strings) > (MAXSRC - MAXLINE))
syntax_tags_error("Too much source",str-20,__LINE__);
else
do {  // Try until we have input
memset(str,0,MAXLINE);
if(fin == stdin)
printf("::");
str = fgets(str,MAXLINE,fin);
} while(str && (*str == '\n')); // Empty return key
return(str);
}

int ConsoleLoop(FILE * fin){
char * str=Strings;
int mode=NOTFOUND;
//First handle any interrupts
while(mode != EXIT) {
runtime_error=sigsetjmp(env,1);                                               
if(runtime_error) {
printf("\nRestart %d \n",runtime_error);
syntax_flag=0;
}
// Doing some adjustments for syntax engine
if(syntax_flag != CONTINUE) {
str=Strings;  // Source  not saved unless syntax mode
TokeBase=0;TokeEnd=0;
memset(D_Base.Toks,0,sizeof(D_Base.Toks));

} else{ // Leave the Default tokens, save args list
TokeBase=1;TokeEnd=1;
memset(D_Base.Toks+1,0,sizeof(D_Base.Toks)-sizeof(Val));
}
str= get_line(fin,str);
if(!str || !(*str)) return(EXIT);
str = argtoks(str);
ArgcBase = 0;  // Always restart at zero for first token

// Execute multiple commands until done
// Syntax engines issue a continue and exit here
do{
mode = ExecCommand(&ArgcBase,(void **) D_Base.Toks);
syntax_flag = mode; // static copy for syntax egines
} while( (mode == SUCCESS ) && D_Base.Toks[ArgcBase].l );

}
printf("%s %d\n","Exit",mode);
return(mode);
}

const char test[100]= " while(a+4)  {  }" ;
// main for test only
static int NList;
int Init(int *argc, void * args[]);
int main(int argc, char * argv[]) {
int control;
putstr(CONSOLE_VERSION);
if(argc > 1) control = atoi(argv[1]);
Init(&argc,(void *)argv);
printf("warn %s cc %x Entries %d Ntags %ld\n",
argv[1],control,NList,NKEYS);
ListNames(&argc,(void *)argv);
putstrs("Puncts Op", D_OpPuncts,"\nName", D_NamePuncts,
"\nPairs",D_QuotePuncts,"\n",0);
ConsoleLoop(stdin);
}

// Syntax_tags errors and aborts

int syntax_tags_error(char * error, char * src, int line ) {
printf("Syntax ");
if(error)
printf("Line: %d %s\n",line,error);
if(src)
printf("%10s\n",src);
abort();
return(0);
}
//////////////// Symbol methods /////////////
Sym * GetNSym(char * name,int len) {
int i;
if(len > MAXCHRS) syntax_tags_error("Name too long",name,__LINE__);
for(i=0;i < symbols_index;i++){  // first entry reserved
if((len == symbols[i].len) &&
(!strncmp(symbols[i].name,name,symbols[i].len)))
return(&symbols[i]);
}
return(0);
}

Sym * GetSym(char * name) {
int len=len_tok(name);
return(GetNSym(name,len));
}

Sym * PutSym(char * name) {
Sym * p;
if(symbols_index==MAXSYM) syntax_tags_error("No symbols",name, __LINE__);
if(strlen(name) > MAXCHRS) syntax_tags_error("Name too long",name,__LINE__);
p= &symbols[symbols_index];
symbols_index++;
p->name=name;
p->len=strlen(name);
return(p);
}

long ValToken(Val tok) {
PSym s;
if(tok.l < MAXINT) return(tok.l);
else if(isdigit(tok.s[0])) return(atoi(tok.s));
else if (isalpha(tok.s[0])) {
s = GetSym(tok.s);
if(!s) {
s = PutSym(tok.s);
s->val.l=0;
}
return(s->val.l);
} else return(syntax_tags_error("PunctToke",tok.s,__LINE__));
}

#include <signal.h>
void signal_handler (int signo) {
runtime_error=signo;
siglongjmp(env, signo);
//longjmp(env, signo);
}
int init_exceptions(void) {
struct sigaction sa;
putstr("Exceptions\n");
sa.sa_handler = signal_handler;
sigemptyset(&(sa.sa_mask));

sa.sa_flags = SA_ONSTACK | SA_RESTART | SA_SIGINFO;
sigaddset(&(sa.sa_mask), SIGABRT);
sigaction(SIGABRT, &sa, NULL);
sigaddset(&(sa.sa_mask), SIGFPE);
sigaction(SIGFPE, &sa, NULL);
sigaddset(&(sa.sa_mask), SIGINT);
sigaction(SIGINT, &sa, NULL);
sigaddset(&(sa.sa_mask), SIGSEGV);
sigaction(SIGSEGV,&sa, NULL);
return(SUCCESS);
}

#define m(a) {#a,a}
struct {
char * str;
EntryType * entry;
} List[] = {
m(ListArgs),m(LoadModule),m(UnloadModule),
m(ExecFile),m(Tokenize),m(Shunt),m(ListNames),
m(Init), m(Default),m(InitDefault),
m(GetKey),
//// default execution layer
m(while_cmd),m(expr_cmd),
m(exit_cmd),m(assign_cmd)
};
void init_commands() {
int i=0;
PSym s;
NList = sizeof( List)/(sizeof(long)*2);
while(i < NList) {
s = PutSym(List[i].str);
s->val.entry=  List[i].entry;
s->type=builtin_tag;
i++;
}
}
int Init(int *argc, void * args[]) {
init_tags();
init_commands();
init_exceptions();
*argc +=2;
return(SUCCESS);
}
 int fputstrs(FILE* fd, const char *str, ...) {
const char * p;
int i=0;
va_list argp;
va_start(argp, str);
p=str;
do  {
fputs(p,fd);
p = va_arg(argp,  char *);
} while(p && *p && (*p != ';'));
va_end(argp);
return(i);
}

No comments: