/* Copyright (C) 2011-2016 Patrick H. E. Foubet - S.E.R.I.A.N.E.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or any
later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see
*******************************************************************/
#include "conf.h"
/* stackV.c */
#include
#include
#include
#include
#include
#include "nife.h"
#include "mth.h"
#include "err.h"
#include "debug.h"
#include "lib.h"
#include "stackV.h"
#include "stackF.h"
#include "stackN.h"
#include "stackC.h"
#include "stackL.h"
/* types of var */
#define VT_I 0 /* Initial = INTERGER NULL */
#define VT_B 1 /* BOOLEAN */
#define VT_C 2 /* CHARACTER STRING */
#define VT_N 3 /* NUMBER */
#define VT_L 4 /* LIB FUNCTION */
#define VT_F 5 /* USER FUNCTION */
#define VT_XF 15 /* USER FUNCTION NOT IDENTIFIED during restore */
#define VT_V 9 /* VARIABLE (for "install_v ... in" only) */
#define VT_NO -1 /* cf ci-dessous */
static void * stackV = VIDE;
/* modeExeVar guide le traitement des variables
* si affectation : un des VT_x sinon -1
* *************************************/
static int modeExeVar=VT_NO;
struct Var {
char *l; /* libelle */
void *n; /* next */
union {
bool b;
void *a; /* adresse num/char/code */
};
short t; /* type */
};
static void cpVar(void * S, void *D)
{
struct Var *vS, *vD;
if (S==D) return;
vS = (struct Var *)S;
vD = (struct Var *)D;
vD->t = vS->t;
vD->a = vS->a;
/* duplication if number !! */
if (vD->t == VT_N)
vD->a = duplicateNum(vS->a, 0);
}
void initVarSL(char *L)
{
void * M;
struct Var * N;
if ((M = malloc(sizeof(struct Var))) == NULL) stopErr("initVarSL","malloc");
N = (struct Var*)M;
N->l = L;
N->n = stackV;
N->t = VT_I;
stackV = M;
}
void initVar(char *Lib)
{
void *L;
if ((L = malloc(strlen(Lib)+1)) == NULL) stopErr("initVar","malloc");
strcpy((char*)L,Lib);
initVarSL((char*)L);
}
static void setCodeVar(struct Var * Elt, short t, void* A)
{
switch (Elt->t) { /* TODO VT_F */
case VT_C :
free(Elt->a);
break;
case VT_N :
if (nbOnStack(Elt->a) == 0) free(Elt->a);
else numVarOff(Elt->a);
break;
default : /* VT_I, VT_B, VT_L, VT_F */
break;
}
Elt->t = t;
Elt->a = A;
}
static void rmVar(void **Ref, struct Var * Elt)
{
if (Elt->t==VT_N) setCodeVar(Elt, VT_I, VIDE);
*Ref = Elt->n;
free((void*)Elt->l);
free((void*)Elt);
}
void rmLastVar(void)
{
if (stackV != VIDE) rmVar(&stackV, (struct Var *)stackV);
else messErr(23);
}
void IF_show_stackV(void)
{
void * Next;
struct Var * N;
Next = stackV;
while (Next != VIDE) {
N = (struct Var*) Next;
printf(" %-25s : Type ",N->l);
switch(N->t) {
case VT_I :
printf("initial (NULL)");
break;
case VT_B :
printf("Boolean ");
if (N->b) printf("TRUE"); else printf("FALSE");
break;
case VT_C :
printf("String \"%s\"", (char*)N->a);
break;
case VT_N :
printf("Number ");
printNumber(N->a);
break;
case VT_L :
printf("Lib. Fct. %s", libByAddr(N->a));
break;
case VT_F :
printf("User Fct. %s", fctByAddr(N->a));
break;
default :
printf("Undefined (%d) !??", N->t);
}
printf("\n");
Next = N->n;
}
printf("\n");
}
void IFD_show_stackV(void)
{
_IFD_BEGIN_
IF_show_stackV();
_IFD_END_
}
static void newVar(char * S)
{
char Lib[LDFLT+1];
strncpy(Lib,S,LDFLT);
Lib[LDFLT]='\0';
initVar(Lib);
dropTrSuite();
}
void IF_debVar(void)
{
putTrSuite(newVar);
}
void IF_debVarCS(void)
{
char *v;
v = getString();
if (v != NULL) {
initVar(v);
free((void*)v);
}
}
void * varByName(char * L)
{
void * Next;
struct Var * N;
Next = stackV;
while (Next != VIDE) {
N = (struct Var*) Next;
if (strcmp(N->l,L)==0) return(Next);
Next = N->n;
}
return VIDE;
}
char * varByAddr(void * A) /* non optimise mais C'EST FAIT EXPRES !! */
{
void * Next;
struct Var * N;
Next = stackV;
while (Next != VIDE) {
N = (struct Var*) Next;
if (Next==A) return(N->l);
Next = N->n;
}
return NULL;
}
char * varByAddrA(void * A)
{
void * Next;
struct Var * N;
Next = stackV;
while (Next != VIDE) {
N = (struct Var*) Next;
if (N->a==A) return(N->l);
Next = N->n;
}
return NULL;
}
long iVarByAddr(void * A)
{
void * Next;
struct Var * N;
long i=0;
Next = stackV;
while (Next != VIDE) {
i++;
if (Next==A) return(i);
N = (struct Var*) Next;
Next = N->n;
}
return 0L;
}
long iVarByAddrA(void * A)
{
void * Next;
struct Var * N;
long i=0;
Next = stackV;
while (Next != VIDE) {
i++;
N = (struct Var*) Next;
if (N->a==A) return(i);
Next = N->n;
}
return 0L;
}
void * varAddrByInd(long i)
{
void * Next;
struct Var * N;
long j=0;
Next = stackV;
while (Next != VIDE) {
j++;
if (i==j) return(Next);
N = (struct Var*) Next;
Next = N->n;
}
return NULL;
}
void * varAddrAByInd(long i)
{
void * Next;
struct Var * N;
long j=0;
Next = stackV;
while (Next != VIDE) {
j++;
N = (struct Var*) Next;
if (i==j) return(N->a);
Next = N->n;
}
return NULL;
}
int isVarChar(void * A)
{
struct Var * N;
N = (struct Var*) A;
if (N->t == VT_C) return 1;
return 0;
}
static void exec_Var(void * A)
{
void * C;
struct Var * N;
void (*f) (void);
N = (struct Var*) A;
/* printf("executeVar %s %d !!\n",N->l, N->t);*/
switch(N->t) {
case VT_B :
putBool(N->b);
break;
case VT_C :
putString((char*)N->a);
break;
case VT_N :
if (nbOnStack(N->a) > 0) {
C = duplicateNum(N->a,1);
N->a = C;
}
putVar(N->a);
break;
case VT_L :
f = (PFV)(N->a);
f();
break;
case VT_F :
execFctV(N->a);
break;
default : /* VT_I */
break;
}
}
static void delVar(char * L)
{
void ** PNext;
struct Var * N;
dropTrSuite();
PNext = &stackV;
while (*PNext != VIDE) {
N = (struct Var*) *PNext;
if (strcmp(N->l,L)==0) {
rmVar(PNext, N);
return;
}
PNext = &N->n;
}
messErr(24);
}
void IF_delVar(void)
{
putTrSuite(delVar);
}
void putInVar(void * A, short t)
{
struct Var * N;
N = (struct Var*) A;
switch(t) {
case VT_B :
setCodeVar(N, t, VIDE);
N->b = getBool();
break;
case VT_C :
setCodeVar(N, t, getString());
break;
case VT_N :
setCodeVar(N, t, getVar());
break;
case VT_L :
case VT_F :
setCodeVar(N, t, FCT_INST);
break;
default :
setCodeVar(N, VT_I, VIDE);
break;
}
}
/* PLUS UTILISEE ***********************
static void updateVar(char * L, short t)
{
void * Next;
struct Var * N;
Next = stackV;
while (Next != VIDE) {
N = (struct Var*) Next;
if (strcmp(N->l,L)==0) {
putInVar(Next, t);
return;
}
Next = N->n;
}
messErr(24);
}
*****************/
void IF_setVarN(void)
{
modeExeVar=VT_N;
}
void IF_setVarC(void)
{
modeExeVar=VT_C;
}
void IF_setVarB(void)
{
modeExeVar=VT_B;
}
void IF_setVarI(void)
{
modeExeVar=VT_I;
}
void IF_setVarLF(void)
{
switch (FCT_TYP) {
case 0 :
modeExeVar=VT_I;
break;
case 1 :
modeExeVar=VT_L;
break;
case 2 :
modeExeVar=VT_F;
break;
case 3 :
modeExeVar=VT_V;
break;
}
}
void executeVar(void * A)
{
if (fctEnCours) makeFct(T_VAR, A);
else {
if (modeExeVar == VT_NO) exec_Var(A);
else {
if (modeExeVar == VT_V) cpVar(FCT_INST,A);
else putInVar(A, modeExeVar);
modeExeVar=VT_NO;
}
}
}
int IF_execVar(char * L)
{
void * Next;
struct Var * N;
Next = stackV;
while (Next != VIDE) {
N = (struct Var*) Next;
if (strcmp(N->l,L)==0) {
executeVar(Next);
return 1;
}
Next = N->n;
}
return 0;
}
void dump_eltV(int fd, void *A)
{
struct Var * N;
uint32_t a;
int nc;
N = (struct Var*)A;
nc = write(fd, (void*)&(N->t), sizeof(N->t));
dump_eltC(fd, N->l);
switch(N->t) {
case VT_I :
break;
case VT_B :
nc = write(fd, (void*)&(N->b), sizeof(N->b));
break;
case VT_C :
dump_eltC(fd, (char*)N->a);
break;
case VT_N :
dump_eltN(fd, N->a, 0);
break;
case VT_L :
a = iLibByAddr(N->a);
nc = write(fd, (void*)&a, sizeof(a));
break;
case VT_F :
a = iFctByAddr(N->a);
nc = write(fd, (void*)&a, sizeof(a));
break;
default :
printf("Var type %d !?\n", N->t);
break;
}
}
void dump_stackV(int fd)
{
void * Next, *A;
struct Var * N;
uint32_t n=0;
long l, i, j;
int nc;
Next = stackV;
while (Next != VIDE) {
N = (struct Var*) Next;
n++;
Next = N->n;
}
nc = write(fd, (void*)&n, sizeof(n));
for (i=n; i>0; i--) {
Next = stackV;
j=0;
while (Next != VIDE) {
N = (struct Var*) Next;
j++;
if (i==j) break;
Next = N->n;
}
dump_eltV(fd, Next);
}
dump_rest_pr(0,n,"variables");
}
void restore_links_stackV(void)
{
void * Next;
struct Var * N;
long i, j=0;
Next = stackV;
while (Next != VIDE) {
N = (struct Var*) Next;
if (N->t == VT_XF) {
i = (long)(N->a);
N->a = fctByInd(i);
N->t = VT_F;
j++;
}
Next = N->n;
}
rest_links_pr(j, "user function", "variables");
}
static int NbARIL;
void restore_eltV(int fd)
{
struct Var * N;
short t;
char *L;
void *A;
bool b;
uint32_t i;
long Vi;
int nc;
if (read(fd, (void*)&t, sizeof(t)) != sizeof(t)) return;
L = restore_eltC(fd);
initVarSL(L);
/* printf("Var %s %d\n", L, t); */
N = (struct Var *)stackV;
switch(t) {
case VT_I :
A = VIDE;
break;
case VT_B :
A = VIDE;
nc = read(fd, (void*)&b, sizeof(b));
break;
case VT_C :
A = (void*) restore_eltC(fd);
break;
case VT_N :
A = restore_eltN(fd);
break;
case VT_L :
nc = read(fd, (void*)&i, sizeof(i));
A = libByInd(i);
NbARIL++;
break;
case VT_F :
nc = read(fd, (void*)&i, sizeof(i));
/* A = fctByInd(i); not possible ! */
Vi = (long)i;
A = (void*)Vi;
t = VT_XF;
break;
default :
printf("Var type %d !?\n", N->t);
break;
}
setCodeVar(N, t, A);
if (t == VT_B) N->b = b;
}
void restore_stackV(int fd)
{
uint32_t n=0, i;
if (read(fd, (void*)&n, sizeof(n)) != sizeof(n)) return;
NbARIL=0;
while (stackV != VIDE) rmVar(&stackV, (struct Var *)stackV);
for (i=0; i