Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
14b314484c | ||
|
|
f45b6a9181 | ||
|
|
3c86d54a10 | ||
|
|
ac2ade566a | ||
|
|
81b7307d18 | ||
|
|
e120af6ec3 | ||
|
|
264291b36b | ||
|
|
73ab1c2aa6 | ||
|
|
676dd07036 | ||
|
|
c80524017d | ||
|
|
23761bad27 | ||
|
|
74159114d3 | ||
|
|
902311f40d | ||
|
|
d49c1ed476 | ||
|
|
1f7b840256 |
No files matched your search
@@ -24,6 +24,23 @@ W
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
```
|
||||
# Installation
|
||||
Installation depuis les dépôts officiels pour base Debian/Ubuntu:
|
||||
```
|
||||
sudo apt update
|
||||
sudo apt install ca-certificates curl
|
||||
sudo curl -fsSL http://apt.lanisys.fr/public.key -o /etc/apt/keyrings/wlanguage.gpg
|
||||
sudo tee /etc/apt/sources.list.d/wlanguage.sources <<EOF
|
||||
Types: deb
|
||||
URIs: http://apt.lanisys.fr
|
||||
Suites: $(. /etc/os-release && echo "$VERSION_CODENAME")
|
||||
Components: main
|
||||
Signed-By: /etc/apt/keyrings/wlanguage.gpg
|
||||
EOF
|
||||
sudo apt update
|
||||
sudo apt install wlanguage
|
||||
sudo exec bash -l
|
||||
```
|
||||
|
||||
# Execution
|
||||
var pour la shared lib, puis exécution :
|
||||
@@ -46,4 +63,4 @@ cat /proc/*/maps et faire des grep pour voir les .so et module chargés par open
|
||||
exec/genw $1.w && exec/lwa $1.wa ; exec/lw $1
|
||||
```
|
||||
# Site Web
|
||||
https://www.lanisys.fr/wiki/doku.php?id=w
|
||||
https://w.lanisys.fr/
|
||||
+215
-285
@@ -34,35 +34,47 @@ char libComp[9 * 3] = {"EQ " "NE " "LT " "GT " "LE " "GE " "AND" "OR " "NOT"};
|
||||
env e;
|
||||
|
||||
/* nota : pour les calculs de saut, BEXC et SUBR donnent l'offset par rapport au DEBUT de l'instruction
|
||||
JUMP, JMPT, JMPF : offset depuis le debut de sub en cours (instruction juste apres SUBR) */
|
||||
JUMP, JMPT, JMPF : offset depuis le debut de sub en cours (instruction juste apres SUBR)
|
||||
|
||||
/* gestion des niveaux d'imbrication des structures : prog/sub/loop/foreach/if
|
||||
prog/back/libr : niveau 1 forcement => iNiv = 1
|
||||
sub/loop/foreach : niveau + 1 => iNiv++ (SUBR :L :F)
|
||||
ends/endloop/endfor : niveau - 1 => iNiv-- et del des attributs (ENDS :l :f)
|
||||
endp/endl : niveau 1 : ne plus rien faire ; si iNiv <> 1, erreur
|
||||
if/else/elseif/endif : a l'interieur d'un niveau, il peut y avoir plusieurs if imbriques : a gerer a part
|
||||
format du Dynamic :
|
||||
niv<1,iNiv> = adresse SUBR ou mettre l'adresse de ENDS quand survient (0 si PROG/BACK/LIBR pour niveau 1)
|
||||
niv<2,iNiv> = adresse BEXC ou mettre l'adresse de EXCE quand survient
|
||||
niv<3,iNiv> = adresse debut PROG/BACK/LIBR/SUB en cours (reporter celui de niv-1 si niveau++ <> sub)
|
||||
niv<4,iNiv> = adresse :L :F pour continue/continueon dans loop/foreach du meme niveau JUMP :L :F JMPT :L :F
|
||||
|
||||
brk<iNiv, n> = adresses des <n> JUMP :l :f JMPT :l :f (break/breakon) ou mettre l'adresse de :l :f (fin de loop/foreach du meme niveau)
|
||||
|
||||
ifn<iNiv> = nb if imbriques, maj quand :I et :e et quand iNiv++ (mettre 0)
|
||||
ife<iNiv, m> = adresse dernier JMPF :E ou mettre l'adresse du prochain :E ou :e a venir ; if: m++ ; endif: m-- pour le niveau
|
||||
ifq<iNiv, m> = adresses des JUMP :e (fin branche if) ou mettre l'adresse de :e (fin if), separes par SVM, pour le if encours du niveau en cours
|
||||
(<m> = nb if imbriques)
|
||||
|
||||
gestion des noms de variable (dans genw.c) :
|
||||
prog/back/libr : niveau 1 forcement (vars globales) iVar = 1
|
||||
sub : niveau + 1 => iVar++ (vars locales)
|
||||
ends : niveau - 1 => iVar-- et del attribut
|
||||
decvar<iVar> = liste des variables en VM declarees dans le niveau iVar
|
||||
*/
|
||||
int iNiv;
|
||||
Dynamic niv, brk, ifn, ife, ifq;
|
||||
int subNiv;
|
||||
Dynamic adrLabel;
|
||||
/*
|
||||
adrLabel<1> = label, adrLabel<2> = offset (adresse) du label
|
||||
adrLabel<3, subNiv> = ad debut sub en cours (debut PROG/SUBR)
|
||||
adrLabel<4> = liste labels dans des JUMP a completer
|
||||
adrLabel<5> = liste de la position du JUMP ou ecrire l'offset (adresse) du label
|
||||
*/
|
||||
|
||||
/* -------------------- */
|
||||
ent64 lap = 0; /* calcul temps du programme (hors init, alloc et free), en ms */
|
||||
|
||||
static int clock_gettime_monotonic(struct timespec * tv)
|
||||
{
|
||||
#ifdef UNIX
|
||||
return clock_gettime(CLOCK_MONOTONIC, tv);
|
||||
#else
|
||||
/* cf stackoverflow */
|
||||
static LARGE_INTEGER ticksPerSec;
|
||||
LARGE_INTEGER ticks;
|
||||
if (!ticksPerSec.QuadPart)
|
||||
{
|
||||
QueryPerformanceFrequency(&ticksPerSec);
|
||||
if(!ticksPerSec.QuadPart)
|
||||
return -1;
|
||||
}
|
||||
QueryPerformanceCounter(&ticks);
|
||||
tv->tv_sec = (long)(ticks.QuadPart / ticksPerSec.QuadPart);
|
||||
tv->tv_nsec = (long)(((ticks.QuadPart % ticksPerSec.QuadPart) * 1000000000) / ticksPerSec.QuadPart);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
/* -------------------- */
|
||||
|
||||
void decodeString(env * e, Dynamic * this)
|
||||
{
|
||||
@@ -84,16 +96,13 @@ int assembler(env * e, char * fichier, int * cptLig)
|
||||
return -1;
|
||||
// traiter chaque ligne
|
||||
Dynamic ligne, tmp, pcode, varsys, trav;
|
||||
int ret = OK, i, sav, offset, instr;
|
||||
int premiere_instr = 1, derniere_instr = 0, nbif;
|
||||
int ret = OK, i, sav, offset, instr, debutSub;
|
||||
int premiere_instr = 1, derniere_instr = 0;
|
||||
long pos; // pour locate
|
||||
ent64s num;
|
||||
//
|
||||
iNiv = 0;
|
||||
dynInit(e, &niv, DYN_LGMIN);
|
||||
dynInit(e, &brk, DYN_LGMIN);
|
||||
dynInit(e, &ifn, DYN_LGMIN);
|
||||
dynInit(e, &ife, DYN_LGMIN);
|
||||
dynInit(e, &ifq, DYN_LGMIN);
|
||||
subNiv = 0;
|
||||
dynInit(e, &adrLabel, DYN_LGMIN);
|
||||
dynInit(e, &ligne, DYN_LGMIN);
|
||||
dynInit(e, &tmp, DYN_LGMIN);
|
||||
dynInit(e, &trav, DYN_LGMIN);
|
||||
@@ -116,123 +125,48 @@ int assembler(env * e, char * fichier, int * cptLig)
|
||||
continue;
|
||||
//
|
||||
dynField(e, &ligne, &tmp, 1, 0, ' ', 0, 1);
|
||||
// gestion labels sauts boucles LOOP, si premiere instruction passee
|
||||
// gestion labels sauts boucles loop/foreach/if, si premiere instruction passee
|
||||
if(!premiere_instr)
|
||||
{
|
||||
if(strncmp(tmp.mPtr, ":L", 2) == 0 || strncmp(tmp.mPtr, ":F", 2) == 0)
|
||||
/* nouvelle methode de gestion des labels adrLabel<1> = nom, adrLabel<2> = adresse */
|
||||
if(strncmp(tmp.mPtr, ":L", 2) == 0 || strncmp(tmp.mPtr, ":l", 2) == 0 ||
|
||||
strncmp(tmp.mPtr, ":F", 2) == 0 || strncmp(tmp.mPtr, ":f", 2) == 0 ||
|
||||
strncmp(tmp.mPtr, ":I", 2) == 0 || strncmp(tmp.mPtr, ":i", 2) == 0 )
|
||||
{
|
||||
/* nouveau niveau LOOP ou FOREACH */
|
||||
dynLet(e, &tmp, Int32ToSz(pcode.mLg, DYN_FALSE, 0), DYN_LGNONE); // position en cours
|
||||
iNiv++;
|
||||
dynStore(e, &niv, 4, iNiv, &tmp, cFM, cVM); // adresse debut loop/foreach
|
||||
dynField(e, &niv, &trav, 3, iNiv - 1, cFM, cVM, 1);
|
||||
dynStore(e, &niv, 3, iNiv, &trav, cFM, cVM); // report adresse debut prog/sub
|
||||
dynStoreSz(e, &niv, 1, iNiv, "", 0, cFM, cVM); // init
|
||||
dynStoreSz(e, &niv, 2, iNiv, "", 0, cFM, cVM); // init
|
||||
dynStoreSz(e, &ifn, iNiv, DYN_NONE, "0", 1, cFM, cVM); // init nb if dans niveau (0)
|
||||
dynStoreSz(e, &ife, iNiv, DYN_NONE, "", 0, cFM, cVM); // init
|
||||
dynStoreSz(e, &ifq, iNiv, DYN_NONE, "", 0, cFM, cVM); // init
|
||||
dynStoreSz(e, &brk, iNiv, DYN_NONE, "", 0, cFM, cVM); // init brk a vide
|
||||
continue;
|
||||
}
|
||||
if(strncmp(tmp.mPtr, ":I", 2) == 0)
|
||||
{
|
||||
/* nouveau IF (imbrique) pour le niveau en cours */
|
||||
dynField(e, &ifn, &trav, iNiv, DYN_NONE, cFM, cVM, 1);
|
||||
nbif = dynToNum(e, &trav, DYN_FALSE, 6) + 1;
|
||||
dynStoreSz(e, &ifn, iNiv, DYN_NONE, Int32ToSz(nbif, DYN_FALSE, 0), DYN_LGNONE, cFM, cVM); // maj nbif dans le niveau en cours
|
||||
dynStoreSz(e, &ife, iNiv, nbif, "", 0, cFM, cVM);
|
||||
dynStoreSz(e, &ifq, iNiv, nbif, "", 0, cFM, cVM);
|
||||
continue;
|
||||
}
|
||||
/* */
|
||||
int fin_loop;
|
||||
if((fin_loop = strncmp(tmp.mPtr, ":l", 2)) == 0 || strncmp(tmp.mPtr, ":f", 2) == 0)
|
||||
{
|
||||
/* fin LOOP/FOREACH */
|
||||
if(iNiv < 2)
|
||||
dynIns(e, &adrLabel, 1, 1, &tmp, cFM, cVM);
|
||||
dynInsSz(e, &adrLabel, 2, 1, Int32ToSz(pcode.mLg, DYN_FALSE, 0), DYN_LGNONE, cFM, cVM);
|
||||
//
|
||||
if(strncmp(tmp.mPtr, ":L", 2) == 0 || strncmp(tmp.mPtr, ":F", 2) == 0 ||
|
||||
strncmp(tmp.mPtr, ":I", 2) == 0 || strncmp(tmp.mPtr, ":i", 2) == 0 )
|
||||
{
|
||||
ret = -8; /* erreur descente de niveau incorrecte */
|
||||
break;
|
||||
}
|
||||
/* maj chaque break */
|
||||
int nb_break = 0;
|
||||
dynField(e, &brk, &trav, iNiv, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
dynRemove(e, &trav, NULL, cVM, DYN_TRUE);
|
||||
while(dynRemove(e, &trav, &tmp, cVM, DYN_FALSE) > -1)
|
||||
{
|
||||
/* */
|
||||
nb_break++;
|
||||
sav = pcode.mLg;
|
||||
pcode.mLg = dynToNum(e, &tmp, DYN_FALSE, 8);
|
||||
dynField(e, &niv, &tmp, 3, iNiv, cFM, cVM, 1);
|
||||
offset = sav - dynToNum(e, &tmp, DYN_FALSE, 8); // debut du prog/sub en cours
|
||||
PCODEP((offset >> 16) & 255)
|
||||
PCODEP((offset >> 8 ) & 255)
|
||||
PCODEP(offset & 255)
|
||||
pcode.mLg = sav;
|
||||
}
|
||||
if(nb_break == 0 && fin_loop == 0)
|
||||
{
|
||||
ret = -8; /* loop sans break : erreur (boucle infinie) */
|
||||
break;
|
||||
}
|
||||
/* */
|
||||
iNiv--;
|
||||
continue;
|
||||
}
|
||||
if(strncmp(tmp.mPtr, ":E", 2) == 0 || strncmp(tmp.mPtr, ":e", 2) == 0)
|
||||
{
|
||||
/* ELSE ELSEIF ENDIF */
|
||||
/* maj adresse saut du dernier JMPF/JMPT (derniere condition if) si present (cas endif qui suit un else) */
|
||||
dynField(e, &ifn, &trav, iNiv, DYN_NONE, cFM, cVM, 1);
|
||||
nbif = dynToNum(e, &trav, DYN_FALSE, 6);
|
||||
dynField(e, &ife, &trav, iNiv, nbif, cFM, cVM, 1);
|
||||
if(trav.mLg != 0)
|
||||
{
|
||||
sav = pcode.mLg;
|
||||
pcode.mLg = dynToNum(e, &trav, DYN_FALSE, 8);
|
||||
dynField(e, &niv, &trav, 3, iNiv, cFM, cVM, 1);
|
||||
offset = sav - dynToNum(e, &trav, DYN_FALSE, 8); // debut du prog/sub en cours
|
||||
PCODEP((offset >> 16) & 255)
|
||||
PCODEP((offset >> 8 ) & 255)
|
||||
PCODEP(offset & 255)
|
||||
pcode.mLg = sav;
|
||||
dynStoreSz(e, &ife, iNiv, nbif, "", 0, cFM, cVM); // raz cas else puis endif : pas de saut a maj au endif :e
|
||||
}
|
||||
}
|
||||
if(strncmp(tmp.mPtr, ":e", 2) == 0)
|
||||
{
|
||||
/* ENDIF */
|
||||
/* maj adresses de tous les saut vers :e */
|
||||
dynField(e, &ifn, &trav, iNiv, DYN_NONE, cFM, cVM, 1);
|
||||
nbif = dynToNum(e, &trav, DYN_FALSE, 6);
|
||||
/* */
|
||||
dynField(e, &ifq, &trav, iNiv, nbif, cFM, DYN_NONE, 1);
|
||||
dynRemove(e, &trav, NULL, cSVM, DYN_TRUE);
|
||||
while(dynRemove(e, &trav, &tmp, cSVM, DYN_FALSE) > -1)
|
||||
{
|
||||
if(tmp.mLg != 0)
|
||||
// chercher les endroits ou il faut ecrire cette adresse (saut deja fait avant)
|
||||
int nbLabel = dynDcount(e, &adrLabel, cVM, 4, cFM);
|
||||
for(int iLabel = nbLabel; iLabel >=1; iLabel--)
|
||||
{
|
||||
sav = pcode.mLg;
|
||||
pcode.mLg = dynToNum(e, &tmp, DYN_FALSE, 8);
|
||||
dynField(e, &niv, &tmp, 3, iNiv, cFM, cVM, 1);
|
||||
offset = sav - dynToNum(e, &tmp, DYN_FALSE, 8); // debut du prog/sub en cours
|
||||
PCODEP((offset >> 16) & 255)
|
||||
PCODEP((offset >> 8 ) & 255)
|
||||
PCODEP(offset & 255)
|
||||
pcode.mLg = sav;
|
||||
dynField(e, &adrLabel, &trav, 4, iLabel, cFM, cVM, 1);
|
||||
if(strcmp(trav.mPtr, tmp.mPtr) == 0)
|
||||
{
|
||||
dynField(e, &adrLabel, &trav, 3, subNiv, cFM, cVM, 1); // adresse debut sub en cours
|
||||
debutSub = dynToNum(e, &trav, DYN_FALSE, 8);
|
||||
if(subNiv > 1)
|
||||
debutSub = debutSub + 2 + pcode.ptr[debutSub + 1];
|
||||
offset = pcode.mLg + 1 - debutSub;
|
||||
// maj offset
|
||||
sav = pcode.mLg;
|
||||
dynField(e, &adrLabel, &trav, 5, iLabel, cFM, cVM, 1);
|
||||
pcode.mLg = dynToNum(e, &trav, DYN_FALSE, 0);
|
||||
PCODEP((offset >> 16) & 255)
|
||||
PCODEP((offset >> 8 ) & 255)
|
||||
PCODEP(offset & 255)
|
||||
pcode.mLg = sav;
|
||||
dynDel(e, &adrLabel, 4, iLabel, cFM, cVM, 1);
|
||||
dynDel(e, &adrLabel, 5, iLabel, cFM, cVM, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* */
|
||||
dynStoreSz(e, &ife, iNiv, nbif, "", 0, cFM, cVM); // raz
|
||||
dynStoreSz(e, &ifq, iNiv, nbif, "", 0, cFM, cVM); // raz
|
||||
nbif--;
|
||||
dynStoreSz(e, &ifn, iNiv, DYN_NONE, Int32ToSz(nbif, DYN_FALSE, 0), DYN_LGNONE, cFM, cVM); // maj nbif dans le niveau en cours
|
||||
continue;
|
||||
}
|
||||
else if(strncmp(tmp.mPtr, ":E", 2) == 0)
|
||||
continue;
|
||||
/* fin */
|
||||
}
|
||||
// recherche instr dans la liste
|
||||
int trouve = 0;
|
||||
@@ -283,61 +217,33 @@ int assembler(env * e, char * fichier, int * cptLig)
|
||||
case IN_JUMP:
|
||||
case IN_JMPF:
|
||||
case IN_JMPT:
|
||||
// JUMP / JMPF / JMPT (:L :F :l :f :E :e )
|
||||
// JUMP / JMPF / JMPT :xxx
|
||||
dynField(e, &ligne, &tmp, i++, 0, ' ', 0, 1);
|
||||
if(strcmp((char *)tmp.ptr, ":L") == 0 || strcmp((char *)tmp.ptr, ":F") == 0)
|
||||
/* nouvelle methode */
|
||||
pos = dynLocateSz(e, &adrLabel, tmp.mPtr, cVM, 1, cFM);
|
||||
if(pos > 0)
|
||||
{
|
||||
/* continue dans loop/foreach */
|
||||
PCODE(instr)
|
||||
dynField(e, &niv, &trav, 4, iNiv, cFM, cVM, 1);
|
||||
dynField(e, &niv, &tmp, 3, iNiv, cFM, cVM, 1);
|
||||
offset = dynToNum(e, &trav, DYN_FALSE, 8) - dynToNum(e, &tmp, DYN_FALSE, 8); // ad debut loop/foreach - debut du prog/sub en cours
|
||||
dynField(e, &adrLabel, &trav, 2, pos, cFM, cVM, 1); // adresse debut loop
|
||||
offset = dynToNum(e, &trav, DYN_FALSE, 8);
|
||||
dynField(e, &adrLabel, &trav, 3, subNiv, cFM, cVM, 1); // adresse debut sub en cours
|
||||
debutSub = dynToNum(e, &trav, DYN_FALSE, 8);
|
||||
if(subNiv > 1)
|
||||
debutSub = debutSub + 2 + pcode.ptr[debutSub + 1];
|
||||
offset = offset + 1 - debutSub; // ad debut loop - debut du prog/sub en cours
|
||||
PCODEP((offset >> 16) & 255)
|
||||
PCODEP((offset >> 8 ) & 255)
|
||||
PCODEP(offset & 255)
|
||||
}
|
||||
else if(strcmp((char *)tmp.ptr, ":l") == 0 || strcmp((char *)tmp.ptr, ":f") == 0)
|
||||
{
|
||||
/* break dans loop/foreach */
|
||||
PCODE(instr)
|
||||
dynInsSz(e, &brk, iNiv, 1, Int32ToSz(pcode.mLg, DYN_FALSE, 0), DYN_LGNONE, cFM, cVM); /* pcode.mLg a verifier */
|
||||
PCODE(0)
|
||||
PCODE(0)
|
||||
PCODE(0)
|
||||
}
|
||||
else if(strcmp((char *)tmp.ptr, ":E") == 0)
|
||||
{
|
||||
/* saut au prochain else/endif */
|
||||
PCODE(instr)
|
||||
dynField(e, &ifn, &trav, iNiv, DYN_NONE, cFM, cVM, 1);
|
||||
nbif = dynToNum(e, &trav, DYN_FALSE, 6);
|
||||
dynStoreSz(e, &ife, iNiv, nbif, Int32ToSz(pcode.mLg, DYN_FALSE, 0), DYN_LGNONE, cFM, cVM); /* pcode.mLg a verifier */
|
||||
PCODE(0)
|
||||
PCODE(0)
|
||||
PCODE(0)
|
||||
}
|
||||
else if(strcmp((char *)tmp.ptr, ":e") == 0)
|
||||
{
|
||||
/* saut prochain endif */
|
||||
PCODE(instr)
|
||||
dynField(e, &ifn, &trav, iNiv, DYN_NONE, cFM, cVM, 1);
|
||||
nbif = dynToNum(e, &trav, DYN_FALSE, 6);
|
||||
dynField(e, &ifq, &trav, iNiv, nbif, cFM, cVM, 1);
|
||||
dynInsSz(e, &trav, 1, DYN_NONE, Int32ToSz(pcode.mLg, DYN_FALSE, 0), DYN_LGNONE, cSVM, DYN_NONE); /* pcode.mLg a verifier */
|
||||
dynStore(e, &ifq, iNiv, nbif, &trav, cFM, cVM);
|
||||
PCODE(0)
|
||||
PCODE(0)
|
||||
PCODE(0)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* cas d'usage ici ? */
|
||||
num = dynToNum(e, &tmp, 1, 8) & 0xFFFFFF;
|
||||
if(tmp.mInternal == DYN_ERR) ret = -3; // erreur conversion
|
||||
PCODE(instr)
|
||||
PCODE((num >> 16) & 255)
|
||||
PCODE((num >> 8) & 255)
|
||||
PCODE(num & 255)
|
||||
// memoriser l'endroit ou on veut mettre l'offset du jump a faire adrLabel<4> et <5>
|
||||
dynIns(e, &adrLabel, 4, 1, &tmp, cFM, cVM);
|
||||
dynInsSz(e, &adrLabel, 5, 1, Int32ToSz(pcode.mLg, DYN_FALSE, 0), DYN_LGNONE, cFM, cVM);
|
||||
PCODE(0)
|
||||
PCODE(0)
|
||||
PCODE(0)
|
||||
}
|
||||
break;
|
||||
case IN_DECL:
|
||||
@@ -363,11 +269,44 @@ int assembler(env * e, char * fichier, int * cptLig)
|
||||
PCODE((num >> 8) & 255)
|
||||
PCODE(num & 255)
|
||||
break;
|
||||
case IN_PHDS:
|
||||
case IN_PIDS:
|
||||
case IN_SUBR:
|
||||
// SUBR
|
||||
sav = pcode.mLg;
|
||||
dynField(e, &ligne, &tmp, i++, 0, ' ', 0, 1);
|
||||
if(tmp.mLg < 1 || tmp.mLg > 255) { ret = -4; break; } // erreur longueur nom variable
|
||||
num = tmp.mLg;
|
||||
if(num == 1 && tmp.mPtr[0] == '_') // assembler SUBR _ pour avoir lg = 0
|
||||
num = 0;
|
||||
PCODE(instr)
|
||||
PCODE(num)
|
||||
for(int p = 0; p < num; p++)
|
||||
PCODE(tmp.mPtr[p])
|
||||
PCODE(0)
|
||||
PCODE(0)
|
||||
PCODE(0)
|
||||
/* nouvelle methode */
|
||||
dynStoreSz(e, &adrLabel, 3, ++subNiv, Int32ToSz(sav, DYN_FALSE, 0), DYN_LGNONE, cFM, cVM);
|
||||
break;
|
||||
case IN_ENDS:
|
||||
// ENDS
|
||||
if(subNiv < 2) { ret = -8; break; } // erreur descente de niveau incorrecte
|
||||
dynField(e, &adrLabel, &trav, 3, subNiv--, cFM, cVM, 1);
|
||||
debutSub = dynToNum(e, &trav, DYN_FALSE, 8);
|
||||
sav = pcode.mLg;
|
||||
pcode.mLg = debutSub + 2 + pcode.ptr[debutSub + 1];
|
||||
offset = sav + 1 - debutSub;
|
||||
PCODEP((offset >> 16) & 255)
|
||||
PCODEP((offset >> 8 ) & 255)
|
||||
PCODEP(offset & 255)
|
||||
pcode.mLg = sav;
|
||||
PCODE(instr)
|
||||
break;
|
||||
case IN_BEXC:
|
||||
// BEXC
|
||||
// memoriser la position pour renseigner l'offset plus tard
|
||||
// memoriser la position pour renseigner l'offset plus tard => idem adrLabel<3> : BEXC juste apres PROG et SUBR !
|
||||
PCODE(instr)
|
||||
dynStoreSz(e, &niv, 2, iNiv, Int32ToSz(pcode.mLg, DYN_FALSE, 0), DYN_LGNONE, cFM, cVM);
|
||||
PCODE(0)
|
||||
PCODE(0)
|
||||
PCODE(0)
|
||||
@@ -377,10 +316,20 @@ int assembler(env * e, char * fichier, int * cptLig)
|
||||
// debut du bloc except : ecrire l'adresse dans l'instruction BEXC
|
||||
PCODE(instr)
|
||||
sav = pcode.mLg;
|
||||
//pcode.mLg = bexc[niveau];
|
||||
dynField(e, &niv, &trav, 2, iNiv, cFM, cVM, 1);
|
||||
pcode.mLg = dynToNum(e, &trav, DYN_FALSE, 8);
|
||||
offset = sav - pcode.mLg + 1;
|
||||
/* nouvelle methode */
|
||||
dynField(e, &adrLabel, &trav, 3, subNiv, cFM, cVM, 1); // adresse debut sub en cours
|
||||
debutSub = dynToNum(e, &trav, DYN_FALSE, 8);
|
||||
if(subNiv > 1)
|
||||
{
|
||||
debutSub = debutSub + 2 + pcode.ptr[debutSub + 1] + 3;
|
||||
offset = pcode.mLg - debutSub;
|
||||
pcode.mLg = debutSub + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = pcode.mLg - debutSub;
|
||||
pcode.mLg = debutSub + 1;
|
||||
}
|
||||
PCODEP((offset >> 16) & 255)
|
||||
PCODEP((offset >> 8 ) & 255)
|
||||
PCODEP(offset & 255)
|
||||
@@ -459,6 +408,8 @@ int assembler(env * e, char * fichier, int * cptLig)
|
||||
case IN_PIDE:
|
||||
case IN_PHDH:
|
||||
case IN_PIDH:
|
||||
case IN_PHDO:
|
||||
case IN_PIDO:
|
||||
case IN_DELE:
|
||||
case IN_NLET:
|
||||
// CPSH / PARM / PVAR / PVAH / PVAI / DELE / NLET / PHDE / PIDE
|
||||
@@ -473,40 +424,6 @@ int assembler(env * e, char * fichier, int * cptLig)
|
||||
for(int p = 0; p < num; p++)
|
||||
PCODE(tmp.mPtr[p])
|
||||
break;
|
||||
case IN_SUBR:
|
||||
// SUBR
|
||||
// offset : memoriser la position a mettre a jour
|
||||
//dynField(e, &ligne, &tmp, i++, 0, ' ', 0, 1);
|
||||
//subr[niveau] = pcode.mLg; /* TODO */
|
||||
//num = dynToNum(e, &tmp, 0, 3) & 255;
|
||||
//if(tmp.mInternal == DYN_ERR) { ret = -3; break; } // erreur conversion
|
||||
sav = pcode.mLg;
|
||||
dynField(e, &ligne, &tmp, i++, 0, ' ', 0, 1);
|
||||
if(tmp.mLg < 1 || tmp.mLg > 255) { ret = -4; break; } // erreur longueur nom variable
|
||||
num = tmp.mLg;
|
||||
if(num == 1 && tmp.mPtr[0] == '_') // assembler SUBR _ pour avoir lg = 0
|
||||
num = 0;
|
||||
PCODE(instr)
|
||||
PCODE(num)
|
||||
for(int p = 0; p < num; p++)
|
||||
PCODE(tmp.mPtr[p])
|
||||
PCODE(0)
|
||||
PCODE(0)
|
||||
PCODE(0)
|
||||
/* empiler un niveau */
|
||||
dynLet(e, &tmp, Int32ToSz(sav, DYN_FALSE, 0), DYN_LGNONE); // position debut SUBR
|
||||
dynLet(e, &trav, Int32ToSz(pcode.mLg - 3, DYN_FALSE, 0), DYN_LGNONE); // lg subr a mettre
|
||||
iNiv++;
|
||||
dynStoreSz(e, &niv, 4, iNiv, "", 0, cFM, cVM);
|
||||
dynStore(e, &niv, 1, iNiv, &trav, cFM, cVM); // adresse lg SUBR = en cours - 3
|
||||
dynStore(e, &niv, 3, iNiv, &tmp, cFM, cVM); // adresse debut SUBR = en cours
|
||||
dynStoreSz(e, &niv, 2, iNiv, "", 0, cFM, cVM); // init
|
||||
dynStoreSz(e, &ifn, iNiv, DYN_NONE, "0", 1, cFM, cVM); // init nb if dans niveau (0)
|
||||
dynStoreSz(e, &ife, iNiv, DYN_NONE, "", 0, cFM, cVM); // init
|
||||
dynStoreSz(e, &ifq, iNiv, DYN_NONE, "", 0, cFM, cVM); // init
|
||||
dynStoreSz(e, &brk, iNiv, DYN_NONE, "", 0, cFM, cVM); // init brk a vide
|
||||
//
|
||||
break;
|
||||
case IN_COMP:
|
||||
// COMP
|
||||
PCODE(instr)
|
||||
@@ -610,6 +527,10 @@ int assembler(env * e, char * fichier, int * cptLig)
|
||||
// TOST
|
||||
case IN_DEXV:
|
||||
// DEXV
|
||||
case IN_DESV:
|
||||
// DESV
|
||||
case IN_DEZV:
|
||||
// DEZV
|
||||
PCODE(instr)
|
||||
break;
|
||||
case IN_MODL:
|
||||
@@ -663,7 +584,7 @@ int assembler(env * e, char * fichier, int * cptLig)
|
||||
case IN_PSHA:
|
||||
// PSHA d1 : transco chaine / numero
|
||||
dynField(e, &ligne, &tmp, i++, 0, ' ', 0, 1);
|
||||
int pos = dynLocateSz(e, &varsys, tmp.mPtr, ',', 1, ';');
|
||||
pos = dynLocateSz(e, &varsys, tmp.mPtr, ',', 1, ';');
|
||||
if(pos < 1) { ret = -10; break; }
|
||||
dynField(e, &varsys, &tmp, 2, pos, ';', ',', 1);
|
||||
num = dynToNum(e, &tmp, 0, 3) & 255;
|
||||
@@ -686,6 +607,14 @@ int assembler(env * e, char * fichier, int * cptLig)
|
||||
// DEXH
|
||||
case IN_DEXI:
|
||||
// DEXI
|
||||
case IN_DESH:
|
||||
// DESH
|
||||
case IN_DESI:
|
||||
// DESI
|
||||
case IN_DEZH:
|
||||
// DEZH
|
||||
case IN_DEZI:
|
||||
// DEZI
|
||||
case IN_DSTO:
|
||||
// DSTO
|
||||
case IN_VLET:
|
||||
@@ -714,6 +643,8 @@ int assembler(env * e, char * fichier, int * cptLig)
|
||||
dynField(e, &ligne, &tmp, i++, 0, ' ', 0, 1);
|
||||
if(tmp.mLg < 1 || tmp.mLg > 255) { ret = -4; break; } // erreur longueur nom var
|
||||
num = tmp.mLg;
|
||||
if(num == 1 && tmp.mPtr[0] == '_') // assembler CLAS lg1 nom1 _ pour avoir lg2 = 0
|
||||
num = 0;
|
||||
PCODE(num)
|
||||
for(int p = 0; p < num; p++)
|
||||
PCODE(tmp.mPtr[p])
|
||||
@@ -770,33 +701,17 @@ int assembler(env * e, char * fichier, int * cptLig)
|
||||
case IN_LIBR:
|
||||
// debut de programme executable directement (normal et demon) et debut library, non executable directement
|
||||
PCODE(instr)
|
||||
iNiv = 1;
|
||||
dynLet(e, &niv, "0" sFM sFM "0" sFM, DYN_LGNONE); // le programme principal commence toujours a 0, meme LIBR...
|
||||
dynLet(e, &ifn, "0", DYN_LGNONE);
|
||||
/* nouvelle methode */
|
||||
dynStoreSz(e, &adrLabel, 3, ++subNiv, Int32ToSz(pcode.mLg, DYN_FALSE, 0), DYN_LGNONE, cFM, cVM);
|
||||
break;
|
||||
case IN_TEST:
|
||||
// TEST
|
||||
PCODE(instr)
|
||||
break;
|
||||
case IN_ENDS:
|
||||
// ENDS
|
||||
if(iNiv < 2) { ret = -8; break; } // erreur descente de niveau incorrecte
|
||||
PCODE(instr)
|
||||
// maj offset dans la declaration
|
||||
sav = pcode.mLg;
|
||||
dynField(e, &niv, &tmp, 3, iNiv, cFM, cVM, 1); /* ad debut */
|
||||
dynField(e, &niv, &trav, 1, iNiv--, cFM, cVM, 1); /* ad ou mettre la longueur */
|
||||
pcode.mLg = dynToNum(e, &trav, DYN_FALSE, 8);
|
||||
offset = sav - dynToNum(e, &tmp, DYN_FALSE, 8);
|
||||
PCODEP((offset >> 16) & 255)
|
||||
PCODEP((offset >> 8 ) & 255)
|
||||
PCODEP(offset & 255)
|
||||
pcode.mLg = sav;
|
||||
break;
|
||||
case IN_ENDL:
|
||||
case IN_ENDP:
|
||||
// ENDL / ENDP : fin de libraire / prog directement executable
|
||||
if(iNiv != 1) { ret = -8; break; } // erreur descente de niveau incorrecte
|
||||
// ENDL / ENDP : fin de librairie / prog directement executable
|
||||
if(subNiv != 1) { ret = -8; break; } // erreur descente de niveau incorrecte
|
||||
PCODE(instr)
|
||||
derniere_instr = 1;
|
||||
break;
|
||||
@@ -824,28 +739,28 @@ int assembler(env * e, char * fichier, int * cptLig)
|
||||
if(!ret)
|
||||
{
|
||||
// si pas d'erreur : copier dans le repertoire WBIN en renommant "xxx.wa" en "xxx.wp"
|
||||
char * wbin = getenv("WBIN");
|
||||
if(wbin == NULL)
|
||||
wbin = getenv("LD_LIBRARY_PATH");
|
||||
if(wbin == NULL)
|
||||
{
|
||||
ret = -11;
|
||||
}
|
||||
else
|
||||
{
|
||||
dynLet(e, &tmp, wbin, DYN_LGNONE);
|
||||
dynConcatSz(e, &tmp, e->path_sep, DYN_LGNONE);
|
||||
dynConcatSz(e, &tmp, fichier, DYN_LGNONE);
|
||||
tmp.mPtr[tmp.mLg - 1] = 'p';
|
||||
dynWrite(e, &pcode, tmp.mPtr);
|
||||
}
|
||||
//char * wbin = getenv("WBIN");
|
||||
//if(wbin == NULL)
|
||||
// wbin = getenv("LD_LIBRARY_PATH");
|
||||
//if(wbin == NULL)
|
||||
//{
|
||||
// ret = -11;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// dynLet(e, &tmp, wbin, DYN_LGNONE);
|
||||
// dynConcatSz(e, &tmp, e->path_sep, DYN_LGNONE);
|
||||
// dynConcatSz(e, &tmp, fichier, DYN_LGNONE);
|
||||
// tmp.mPtr[tmp.mLg - 1] = 'p';
|
||||
// dynWrite(e, &pcode, tmp.mPtr);
|
||||
//}
|
||||
// ecrire au meme endroit que le .w et .wa
|
||||
dynLet(e, &tmp, fichier, DYN_LGNONE);
|
||||
tmp.mPtr[tmp.mLg - 1] = 'p';
|
||||
dynWrite(e, &pcode, tmp.mPtr);
|
||||
}
|
||||
//
|
||||
dynFree(e, &niv);
|
||||
dynFree(e, &brk);
|
||||
dynFree(e, &ifn);
|
||||
dynFree(e, &ife);
|
||||
dynFree(e, &ifq);
|
||||
dynFree(e, &adrLabel);
|
||||
dynFree(e, &pcode);
|
||||
dynFree(e, &tmp);
|
||||
dynFree(e, &trav);
|
||||
@@ -886,7 +801,6 @@ int disassembler(env * e, char * fichier)
|
||||
ent64s ent;
|
||||
char * l;
|
||||
//
|
||||
//debut[niveau] = 0;
|
||||
dynLet(e, &niv, Int32ToSz(0, DYN_FALSE, 0), DYN_LGNONE); // niv<niveau> = adresse debut PROG/SUBR en cours
|
||||
//
|
||||
while(si < pcode.mLg)
|
||||
@@ -905,13 +819,14 @@ int disassembler(env * e, char * fichier)
|
||||
dumpHex(&pcode, si_instr, si);
|
||||
break;
|
||||
case IN_JUMP:
|
||||
case IN_JMPF:
|
||||
case IN_JMPT:
|
||||
// JUMP
|
||||
si++;
|
||||
num = pcode.ptr[si++];
|
||||
num = num << 8 | pcode.ptr[si++];
|
||||
num = num << 8 | pcode.ptr[si++];
|
||||
dynField(e, &niv, &tmp, niveau, DYN_NONE, cFM, cVM, 1);
|
||||
//printf("%d\n", num + debut[niveau]);
|
||||
printf("%lld\n", num + dynToNum(e, &tmp, DYN_FALSE, 6));
|
||||
dumpHex(&pcode, si_instr, si);
|
||||
break;
|
||||
@@ -1018,6 +933,8 @@ int disassembler(env * e, char * fichier)
|
||||
case IN_PIDE:
|
||||
case IN_PHDH:
|
||||
case IN_PIDH:
|
||||
case IN_PHDO:
|
||||
case IN_PIDO:
|
||||
case IN_DELE:
|
||||
case IN_NLET:
|
||||
case IN_PNAM:
|
||||
@@ -1030,6 +947,8 @@ int disassembler(env * e, char * fichier)
|
||||
printf("\n");
|
||||
dumpHex(&pcode, si_instr, si);
|
||||
break;
|
||||
case IN_PHDS:
|
||||
case IN_PIDS:
|
||||
case IN_SUBR:
|
||||
// SUBR
|
||||
si++;
|
||||
@@ -1041,7 +960,6 @@ int disassembler(env * e, char * fichier)
|
||||
num = num * 256 + pcode.ptr[si++];
|
||||
printf(" %d\n", num + si - 5 - lg);
|
||||
dumpHex(&pcode, si_instr, si);
|
||||
//debut[++niveau] = si;
|
||||
dynStoreSz(e, &niv, ++niveau, DYN_NONE, Int32ToSz(si, DYN_FALSE, 0), DYN_LGNONE, cFM, cVM);
|
||||
break;
|
||||
case IN_COMP:
|
||||
@@ -1057,24 +975,6 @@ int disassembler(env * e, char * fichier)
|
||||
}
|
||||
dumpHex(&pcode, si_instr, si);
|
||||
break;
|
||||
case IN_JMPF:
|
||||
// JMPF
|
||||
si++;
|
||||
num = pcode.ptr[si++];
|
||||
num = num << 8 | pcode.ptr[si++];
|
||||
num = num << 8 | pcode.ptr[si++];
|
||||
printf("%d\n", num + si - 4);
|
||||
dumpHex(&pcode, si_instr, si);
|
||||
break;
|
||||
case IN_JMPT:
|
||||
// JMPT
|
||||
si++;
|
||||
num = pcode.ptr[si++];
|
||||
num = num << 8 | pcode.ptr[si++];
|
||||
num = num << 8 | pcode.ptr[si++];
|
||||
printf("%d\n", num + si - 4);
|
||||
dumpHex(&pcode, si_instr, si);
|
||||
break;
|
||||
case IN_ADDN:
|
||||
// ADDN
|
||||
case IN_SBCN:
|
||||
@@ -1153,6 +1053,10 @@ int disassembler(env * e, char * fichier)
|
||||
// TOST
|
||||
case IN_DEXV:
|
||||
// DEXV
|
||||
case IN_DESV:
|
||||
// DESV
|
||||
case IN_DEZV:
|
||||
// DEZV
|
||||
si++;
|
||||
printf("\n");
|
||||
dumpHex(&pcode, si_instr, si);
|
||||
@@ -1247,6 +1151,14 @@ int disassembler(env * e, char * fichier)
|
||||
// DEXH
|
||||
case IN_DEXI:
|
||||
// DEXI
|
||||
case IN_DESH:
|
||||
// DESH
|
||||
case IN_DESI:
|
||||
// DESI
|
||||
case IN_DEZH:
|
||||
// DEZH
|
||||
case IN_DEZI:
|
||||
// DEZI
|
||||
case IN_DSTO:
|
||||
// DSTO
|
||||
case IN_VLET:
|
||||
@@ -1346,6 +1258,11 @@ int main(int argc, char * argv[])
|
||||
exit(-1);
|
||||
}
|
||||
/* */
|
||||
struct timespec ts;
|
||||
lap = 0;
|
||||
if(clock_gettime_monotonic(&ts) != -1)
|
||||
lap = ts.tv_sec * 1000000 + (ts.tv_nsec / 1000);
|
||||
/* */
|
||||
init_env(&e);
|
||||
/* */
|
||||
if(strcmp(argv[1], "-d") == 0)
|
||||
@@ -1372,7 +1289,20 @@ int main(int argc, char * argv[])
|
||||
{
|
||||
printf("Erreur %d a la ligne %d\n", cr, numLig);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Result : OK, lines=%d\n", numLig);
|
||||
}
|
||||
}
|
||||
/* */
|
||||
if(clock_gettime_monotonic(&ts) != -1)
|
||||
lap = ts.tv_sec * 1000000 + (ts.tv_nsec / 1000) - lap;
|
||||
printf("exit:%u ", cr);
|
||||
if(lap < 1500)
|
||||
printf("(%llu µs)\n", lap);
|
||||
else if(lap < 1500000)
|
||||
printf("(%llu ms)\n", lap/1000);
|
||||
else
|
||||
printf("(%llu s)\n", lap/1000000);
|
||||
exit(cr);
|
||||
}
|
||||
@@ -51,7 +51,7 @@ echo 14. Generation du generateur de fichier lex
|
||||
gcc w_src/genlex.c -o exec/genlex -s -Wall -m64 -DUNIX -L./exec -l:libw.so
|
||||
|
||||
echo 15. Generation de l\'analyseur de source w
|
||||
gcc w_src/genw.c -s -o exec/genw -Wall -m64 -DUNIX -L./exec -l:libw.so
|
||||
gcc w_src/genw.c -s -o exec/genw -Wall -m64 -DUNIX -Wno-stringop-truncation -L./exec -l:libw.so
|
||||
|
||||
echo "compress => gcc compress.c -s -o compress -Wall -m64 -DUNIX -L./exec -l:libw.so"
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024 lanisys.fr
|
||||
\/ \/ Copyright 2024,2025 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
@@ -36,7 +36,7 @@ long rg(env * e, Dynamic * regles, char * nom, Dynamic * tmp)
|
||||
/*
|
||||
blanc,1,commande,2,aide,3,nombre,4,ajouter,5,supprimer,6,ident,7,reste,8
|
||||
*/
|
||||
struct {
|
||||
static struct {
|
||||
ent16 blanc,commande,aide,nombre,ajouter,supprimer,ident,reste;
|
||||
} r;
|
||||
|
||||
@@ -137,16 +137,21 @@ void debug(env * e)
|
||||
dynInit(e, &dyn, 0);
|
||||
ent16 tok, tok2; /* token lu par la macro ci-dessous "ntok" */
|
||||
long n; /* indice en cours dans les token (parametre de la macro "ntok") base 1 */
|
||||
#define ntok(x) dynExtractSubFieldAsNumber(e, &e->debugvalex, 2, x, &e->debugcmd)
|
||||
//#define ntok(x) dynExtractSubFieldAsNumber(e, &e->debugvalex, 2, x, &e->debugcmd) // attention aux separateurs !
|
||||
#define ntok(x) dynFieldAsNumber(e, &e->debugvalex, 2, x, cFM, cVM)
|
||||
//
|
||||
// afficher source et ligne en cours
|
||||
e->nom64[0] = 0;e->nom64[1] = 0;e->nom64[2] = 0;
|
||||
e->nom64[0] = 0;
|
||||
e->nom64[1] = 0;
|
||||
e->nom64[2] = 0;
|
||||
strncpy(e->nom, "_env", 4);
|
||||
hashtable_do(e, HASH_READ, &e->g, e->nom, &v);
|
||||
if(v != NULL)
|
||||
{
|
||||
dynField(e, v, &dyn, 2, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
e->nom64[0] = 0;e->nom64[1] = 0;e->nom64[2] = 0;
|
||||
e->nom64[0] = 0;
|
||||
e->nom64[1] = 0;
|
||||
e->nom64[2] = 0;
|
||||
strncpy(e->nom, "_file", 5);
|
||||
hashtable_do(e, HASH_READ, &e->g, e->nom, &v);
|
||||
if(v != NULL)
|
||||
@@ -188,7 +193,7 @@ void debug(env * e)
|
||||
//
|
||||
// analyse lex de la commande
|
||||
lex(e, &e->debugreglelex, &e->debugcmd, &e->debugvalex);
|
||||
//printf("cmd %s valex %s\n", e->debugcmd.mPtr, e->debugvalex.mPtr);
|
||||
//printf("cmd %s lgcmd %lld valex %s lgvalex %lld tok1direct %ld\n", e->debugcmd.mPtr, e->debugcmd.mLg, e->debugvalex.mPtr, e->debugvalex.mLg, dynExtractSubFieldAsNumber(e, &e->debugvalex, 2, 1, &e->debugcmd));
|
||||
//
|
||||
if(e->debugvalex.mLg == 0)
|
||||
continue; // empty line
|
||||
@@ -381,6 +386,7 @@ void debug(env * e)
|
||||
break;
|
||||
case VAR_OBJECT:
|
||||
printf("Var %c\n",e->var_car[v->type]); // O
|
||||
hashtable_printdebug(e, v, 1);
|
||||
break;
|
||||
case VAR_SUBROUTINE:
|
||||
printf("Var %c\n",e->var_car[v->type]); // S
|
||||
|
||||
@@ -1873,6 +1873,11 @@ long dynSetSubstr(env * e, Dynamic * this, Dynamic * valeur, long debut, long le
|
||||
debutEx = this->mInternal;
|
||||
//
|
||||
// dans l'intervalle [debutEx, lgEx] (base 0), remplacer la sous-chaine [debut, len] (base 0) par <valeur>
|
||||
// si debut = -1, prendre les "len" derniers cars
|
||||
if(debut == -1)
|
||||
{
|
||||
debut = lgEx - len;
|
||||
}
|
||||
if(debut < 0 || debut > lgEx || len < 0)
|
||||
return DYN_OK; // hors chaine, ne rien faire
|
||||
if(debut == lgEx || len == 0)
|
||||
|
||||
@@ -199,7 +199,7 @@ static void formatage(Dynamic * s, Dynamic * f, int type)
|
||||
//
|
||||
dynInit(&e, ®les, 0);
|
||||
//
|
||||
if(lire_regles_lex(&e, ®les, "lex/wlex") != DYN_OK)
|
||||
if(lire_regles_lex(&e, ®les, "/etc/wlanguage/wlex") != DYN_OK) // au lieu de lex/wlex
|
||||
{
|
||||
dynLet(&e, f, s->mPtr, s->mLg);
|
||||
dynFree(&e, ®les);
|
||||
|
||||
@@ -56,6 +56,17 @@ void init_env(env * e)
|
||||
e->sep_subfield = '\xFD'; // cVM
|
||||
}
|
||||
|
||||
char * copy_nom(env * e, const char * s)
|
||||
{
|
||||
e->nom64[0] = 0;
|
||||
e->nom64[1] = 0;
|
||||
e->nom64[2] = 0;
|
||||
int lg = strlen(s);
|
||||
if(lg > 0 && lg <= 24)
|
||||
strncpy(e->nom, s, lg);
|
||||
return e->nom;
|
||||
}
|
||||
|
||||
/* CONTENU DE env->g
|
||||
_arg : contient en FM les arguments de la ligne de commande a partir du nom du pcode wp ; @ARG
|
||||
_file : contient le fichier source en cours, arborescence en FM celui en cours toujours en <1> ; @FILE
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
void init_env(env * e);
|
||||
|
||||
char * copy_nom(env * e, const char * s);
|
||||
|
||||
/* CONTENU DE env->g
|
||||
_arg : contient en FM les arguments de la ligne de commande a partir du nom du pcode wp ; @ARG
|
||||
_file : contient le fichier source en cours, arborescence en FM celui en cours toujours en <1> ; @FILE
|
||||
|
||||
+7
-1
@@ -100,7 +100,7 @@ void hashtable_do(env * e, int action, var * varht, char * nom, var ** v)
|
||||
}
|
||||
if(action == HASH_WRITE) /* write */
|
||||
{
|
||||
/* ecraser la var presente (et liberer), sauf si meme var */
|
||||
/* ecraser la var presente (et liberer), sauf si meme var : NON car si type different => KO !! et d'ailleurs, est-ce utile ici puisque même pointeur ?? */
|
||||
if(*v != (var *)&pentry->content)
|
||||
{
|
||||
/* liberer pentry->content ; si PARAM, libere la var pointee + copie de la var */
|
||||
@@ -267,6 +267,7 @@ void hashtable_printdebug(env * e, var * varht, int detail)
|
||||
entry * pchain_first; /* premier bloc */
|
||||
ent64 groupe; /* groupe en cours */
|
||||
ent64 occ, tot; /* taille occupee, totale */
|
||||
char * ptrClass = NULL;
|
||||
/* affiche le contenu d'une hashtable */
|
||||
if(varht == NULL)
|
||||
return;
|
||||
@@ -311,6 +312,9 @@ void hashtable_printdebug(env * e, var * varht, int detail)
|
||||
else
|
||||
printf("%c", e->var_car[pentry->content.type % 10]);
|
||||
/* */
|
||||
if(varht->type == VAR_OBJECT && strncmp((char *)&pentry->nom1, "_class", 6) == 0 && ! ptrClass)
|
||||
ptrClass = pentry->content.mPtr;
|
||||
/* */
|
||||
occ += sizeof(entry);
|
||||
}
|
||||
pentry++;
|
||||
@@ -320,6 +324,8 @@ void hashtable_printdebug(env * e, var * varht, int detail)
|
||||
} while ((pchain = (entry *)pchain->chainage_avant) != 0);
|
||||
pchain = (entry *)((ent64)pchain_first + varht->separateur);
|
||||
}
|
||||
if(ptrClass)
|
||||
printf("_class : %s\n", ptrClass);
|
||||
printf("taille totale=%lld, occupee=%lld (taux %lld%%)\n", tot, occ, occ * 100 / tot);
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,8 @@ char libInstr[256 * 4] ={"VERS" "JUMP" "DECL" "SRCL" "BEXC" "EXCE" "CATC" "THRW"
|
||||
"SELE" "RNXT" "CPHA" "PHDE" "PIDE" "PHDH" "PIDH" "PHDO" "PIDO" "PHDS"
|
||||
"PIDS" "TYPE" "ROUN" "LENG" "COUN" "DCOF" "FIEL" "INDX" "SRCH" "CHNG"
|
||||
"FMTA" "INSE" "REMV" "TONU" "TOST" "CCAT" "SSTR" "SSEP" "FLDF" "FLDS" /* 0-99 */
|
||||
"DCOS" "FMTT" "FMTS" "SCHS" "INSS" "REMS" "DEXH" "DEXI" "PREC" "xxxx"
|
||||
"DCOS" "FMTT" "FMTS" "SCHS" "INSS" "REMS" "DEXH" "DEXI" "PREC" "DESV"
|
||||
"DESH" "DESI" "DEZV" "DEZH" "DEZI" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" /* 110-119 */
|
||||
"xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx"
|
||||
"xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx"
|
||||
"xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx"
|
||||
@@ -54,7 +55,6 @@ char libInstr[256 * 4] ={"VERS" "JUMP" "DECL" "SRCL" "BEXC" "EXCE" "CATC" "THRW"
|
||||
"xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx"
|
||||
"xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx"
|
||||
"xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx"
|
||||
"xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" /* 100-199 */
|
||||
"xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx"
|
||||
"xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx"
|
||||
"xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx"
|
||||
@@ -291,8 +291,19 @@ char libInstr[256 * 4] ={"VERS" "JUMP" "DECL" "SRCL" "BEXC" "EXCE" "CATC" "THRW"
|
||||
#define IN_DEXI 107
|
||||
#define IS_PREC "\x6C"
|
||||
#define IN_PREC 108
|
||||
#define IS_0109 "\x6D"
|
||||
#define IN_0109 109
|
||||
#define IS_DESV "\x6D"
|
||||
#define IN_DESV 109
|
||||
|
||||
#define IS_DESH "\x6E"
|
||||
#define IN_DESH 110
|
||||
#define IS_DESI "\x6F"
|
||||
#define IN_DESI 111
|
||||
#define IS_DEZV "\x70"
|
||||
#define IN_DEZV 112
|
||||
#define IS_DEZH "\x71"
|
||||
#define IN_DEZH 113
|
||||
#define IS_DEZI "\x72"
|
||||
#define IN_DEZI 114
|
||||
|
||||
#define IS_LIBR "\xFB"
|
||||
#define IN_LIBR 251
|
||||
|
||||
+1
-1
@@ -636,6 +636,6 @@ int jsonTreeFetch(env * e, modContextJson * ctx, var * param1, var * param2, var
|
||||
// KeyList, CurrentKey, Name, Value, DecodeCle, DecodeValue; // Dynamic
|
||||
// KeyField, KeyItem, KeyCount, ItemCount, Id, Parent, IdKey, ParentKey, ValuePresent, Begin; // Number
|
||||
treefetch tree;
|
||||
hashtable_do(e, HASH_READ, param1, "KeyList", &tree.KeyList);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "KeyList"), &tree.KeyList);
|
||||
return OK;
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024 lanisys.fr
|
||||
\/ \/ Copyright 2024-2025 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
@@ -262,6 +262,7 @@ typedef struct {
|
||||
/* */
|
||||
ent64 exception; /* exception courante (di) ; 0 ok, si # 0, levee d'une exception et saut au code qui le traite, 0 a chaque debut de fonction */
|
||||
ent64 except_ex; /* dans bloc except, code erreur ayant genere l'exception ; a mettre a 0 a chaque debut de methode sauf si appel depuis le bloc except ! */
|
||||
ent64 ligexcept; /* no ligne source au moment de l'exception */
|
||||
/* */
|
||||
ent64 pid;
|
||||
octet instr; /* instruction en cours */
|
||||
@@ -276,10 +277,11 @@ typedef struct {
|
||||
var debugvalex;
|
||||
/* */
|
||||
octet bin_comp; /* indique si les binaires lus sont compresses (1) et si oui, avec une cle (2), 0 RAS */
|
||||
octet demon; /* 1 si prog lance en demon, 0 sinon (lu par @DEMON) */
|
||||
octet demon; /* 1 si prog lance en demon, 0 sinon (lu par @demon) */
|
||||
octet trace; /* 1 pour affichier la trace de chaque instruction executee (option -t) */
|
||||
octet global; /* utilise dans var_search pour remonter si la var trouvee est dans la hash globale ou non */
|
||||
int interpreter; /* 1 si en mode interprete, 0 en mode compile */
|
||||
ent64 ppid; /* 0 dans le process pere, sinon pid du process pere, dans le fils */
|
||||
/* */
|
||||
octet mode_typeof; /* 0 cas courant, 1 (TRUE) si en mode typeof (?var1.var2!var3. etc.) */
|
||||
octet typeof_; /* valeur du type de la var en cours, -1 si aucune */
|
||||
@@ -297,10 +299,9 @@ typedef struct {
|
||||
ent64 mem_size; /* taille des bloc memoire alloues */
|
||||
/* */
|
||||
ent64 oid_cpt; /* compteur pour les object ID (OID) */
|
||||
union {
|
||||
ent64 oid1,oid2,oid3; /* conversion en ascii, mis en binaire (16 chiffres max car 2x8 octets), oid3 ne sert pas (0) */
|
||||
char oidc[24]; /* seuls les 15 premiers cars servent, les 8 derniers sont des fillers pour aller a 24 cars */
|
||||
};
|
||||
/* */
|
||||
char oidc[24]; /* conversion en ascii, mis en binaire (16 chiffres max car 2x8 octets), oid3 ne sert pas (0)
|
||||
seuls les 15 premiers cars servent, les 8 derniers sont des fillers pour aller a 24 cars */
|
||||
/* */
|
||||
union { /* var interne pour copie d'une cle d'acces a un element d'une hashtable */
|
||||
ent64 nom64[3];
|
||||
@@ -328,7 +329,7 @@ typedef struct {
|
||||
#define CMP_OR 8
|
||||
#define CMP_NOT 9
|
||||
|
||||
#define VARSYS "@varnull,@varnumber,@varsubroutine,@varparam,@vardynamic,@varhashtable,@varobject,@varbuffer,@false,@true,@forcount,@kill,@fork,@except,@part,@line,@os,@vers,@verw,@demon,@endian,@file,@arg,@pi,@fm,@vm,@svm,@tm,@currfm,@currvm,@number,@dynamic,@empty,@trim,@left,@right,@center,@surround;1,2,3,4,5,6,7,8,10,11,12,13,14,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,40,41,42,50,51,52,53,54"
|
||||
#define VARSYS "@varnull,@varnumber,@varsubroutine,@varparam,@vardynamic,@varhashtable,@varobject,@varbuffer,@false,@true,@forcount,@kill,@fork,@exceptline,@except,@part,@line,@os,@vers,@verw,@demon,@endian,@file,@arg,@pi,@fm,@vm,@svm,@tm,@currfm,@currvm,@number,@dynamic,@empty,@trim,@left,@right,@center,@surround;1,2,3,4,5,6,7,8,10,11,12,13,14,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,40,41,42,50,51,52,53,54"
|
||||
|
||||
#include "global.h"
|
||||
|
||||
|
||||
+56
@@ -29,6 +29,7 @@
|
||||
#include <dirent.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/wait.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
@@ -54,6 +55,7 @@ typedef struct {
|
||||
#define EXMOD_SYSTEM_UNSETENV 4
|
||||
#define EXMOD_SYSTEM_GETHOST 5
|
||||
#define EXMOD_SYSTEM_UNAME 6
|
||||
#define EXMOD_SYSTEM_FORK 7
|
||||
|
||||
static int setError(modEtat * p, int err)
|
||||
{
|
||||
@@ -336,6 +338,60 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "fork", 4) == 0)
|
||||
{
|
||||
p_etat->error = 0;
|
||||
#ifndef UNIX
|
||||
// faire differemment sous windows : pas de fork dispo ? CreateProcess()
|
||||
#else
|
||||
pid_t fils = fork();
|
||||
if(fils == -1)
|
||||
{
|
||||
exc = EXMOD_SYSTEM_FORK;
|
||||
setError(p_etat, errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(fils == 0)
|
||||
e->ppid = 0; // process fils
|
||||
else
|
||||
e->ppid = fils; // process pere
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "wait", 4) == 0)
|
||||
{
|
||||
#ifndef UNIX
|
||||
// faire differemment sous windows : pas de wait dispo ? WaitForSingleObject()
|
||||
#else
|
||||
if(param1->type != VAR_NUMBER)
|
||||
exc = EX_MODPARAM;
|
||||
param1->num = waitpid(-1, NULL, WNOHANG) * NUM_FACTEUR; // renvoi le pid d'un fils qui s'est fini, 0 si pas de fils termine
|
||||
#endif
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "kill", 4) == 0)
|
||||
{
|
||||
#ifndef UNIX
|
||||
// faire differemment sous windows : pas de kill dispo ?
|
||||
#else
|
||||
kill(0, SIGTERM); // envoi un signal de fin a tous les fils
|
||||
#endif
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "sleep", 5) == 0)
|
||||
{
|
||||
#ifndef UNIX
|
||||
// faire differemment sous windows : pas de sleep dispo ?
|
||||
#else
|
||||
if(param1->type != VAR_NUMBER)
|
||||
exc = EX_MODPARAM;
|
||||
// duree attente envoyee en secondes, avec les decimales
|
||||
usleep(param1->num * (1000000 / NUM_FACTEUR)); // en microsec.
|
||||
#endif
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else
|
||||
{
|
||||
setError(p_etat, 0);
|
||||
|
||||
@@ -28,16 +28,31 @@
|
||||
#include "langage.h"
|
||||
#include "dynamic.h"
|
||||
|
||||
#include "hashtable.h"
|
||||
|
||||
typedef struct {
|
||||
int error; // dernier code erreur specifique au module
|
||||
//*** a completer selon le besoin du module
|
||||
number start, lap;
|
||||
//*** pour duree ; n'est pas un membre d'un objet => global a tous les appels (et n'est pas reentrant - ok en multi process uniquement...)
|
||||
struct timespec sts;
|
||||
//*** pour horodate
|
||||
time_t dhm, decalageHoraire;
|
||||
struct tm stm;
|
||||
var v;
|
||||
var * pv;
|
||||
Dynamic horodate, valNum;
|
||||
} modEtat;
|
||||
|
||||
#define HORODATE_ISO8601 "A-M-JTh:m:SF"
|
||||
|
||||
/* mettre ici les codes d'erreurs specifiques au module */
|
||||
/* codes a passer a la fonction setError */
|
||||
#define EXMOD_GETCLOCK 1
|
||||
#define EXMOD_PARAMNUM 2
|
||||
#define EXMOD_GETCLOCK 1
|
||||
#define EXMOD_PARAMNUM 2
|
||||
#define EXMOD_FORMAT_KO 3
|
||||
#define EXMOD_JETLAG_KO 4
|
||||
#define EXMOD_DURATION_GETCLOCK 5
|
||||
|
||||
static int setError(modEtat * p, int err)
|
||||
{
|
||||
@@ -46,12 +61,248 @@ static int setError(modEtat * p, int err)
|
||||
return EX_MODERR;
|
||||
}
|
||||
|
||||
/* fonction locale aux calculs de duree */
|
||||
static int clock_gettime_monotonic(struct timespec * tv)
|
||||
{
|
||||
#ifdef UNIX
|
||||
return clock_gettime(CLOCK_MONOTONIC, tv);
|
||||
#else
|
||||
/* cf stackoverflow */
|
||||
static LARGE_INTEGER ticksPerSec;
|
||||
LARGE_INTEGER ticks;
|
||||
if (!ticksPerSec.QuadPart)
|
||||
{
|
||||
QueryPerformanceFrequency(&ticksPerSec);
|
||||
if(!ticksPerSec.QuadPart)
|
||||
return -1;
|
||||
}
|
||||
QueryPerformanceCounter(&ticks);
|
||||
tv->tv_sec = (long)(ticks.QuadPart / ticksPerSec.QuadPart);
|
||||
tv->tv_nsec = (long)(((ticks.QuadPart % ticksPerSec.QuadPart) * 1000000000) / ticksPerSec.QuadPart);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* fonction locale aux alarmes */
|
||||
static void AddOneDay(env * e, modEtat * p_etat)
|
||||
{
|
||||
// horodate au format AAAA-MM-DDThh:mm:ss+99:99
|
||||
// ajout de 1 jour au format "externe"
|
||||
// nb jours de chaque mois, d'abord annee normale puis bisextile
|
||||
static long nbj[24] = {31,28,31,30,31,30,31,31,30,31,30,31,
|
||||
31,29,31,30,31,30,31,31,30,31,30,31};
|
||||
long annee, mois, jour, bisextile = 0;
|
||||
dynField(e, &p_etat->horodate, &p_etat->valNum, 1, 1, 'T', '-', 1);
|
||||
annee = dynToNum(e, &p_etat->valNum, FALSE, 4);
|
||||
dynField(e, &p_etat->horodate, &p_etat->valNum, 1, 2, 'T', '-', 1);
|
||||
mois = dynToNum(e, &p_etat->valNum, FALSE, 2);
|
||||
dynField(e, &p_etat->horodate, &p_etat->valNum, 1, 3, 'T', '-', 1);
|
||||
jour = dynToNum(e, &p_etat->valNum, FALSE, 2);
|
||||
if(annee % 4 == 0 && (annee % 100 != 0 || annee % 400 == 0))
|
||||
bisextile = 12;
|
||||
jour += 1;
|
||||
if(jour > nbj[mois + bisextile - 1])
|
||||
{
|
||||
jour = 1;
|
||||
mois += 1;
|
||||
if(mois > 12)
|
||||
{
|
||||
mois = 1;
|
||||
annee += 1;
|
||||
}
|
||||
}
|
||||
sprintf(p_etat->horodate.mPtr, "%04ld", annee);
|
||||
sprintf(p_etat->horodate.mPtr + 5, "%02ld", mois);
|
||||
sprintf(p_etat->horodate.mPtr + 8, "%02ld", jour);
|
||||
*(p_etat->horodate.mPtr + 4) = '-';
|
||||
*(p_etat->horodate.mPtr + 7) = '-';
|
||||
*(p_etat->horodate.mPtr + 10) = 'T';
|
||||
}
|
||||
|
||||
/* fonctions locales aux horodates */
|
||||
#define HORODATE_DECALAGEHORAIREINCONNU 999999
|
||||
#define LIRE1(d,i,e) {if((e=e&&(*d))){i=(*d++);}if(!e)break;}
|
||||
#define LIRE2(d,i,e) {if((e=e&&(*d))){e=e&&((*d)>='0'&&(*d)<='9');i=(*d++)-'0';if((e=e&&(*d))){e=e&&((*d)>='0'&&(*d)<='9');i=i*10+(*d++)-'0';}}if(!e)break;}
|
||||
#define LIRE4(d,i,e) {if((e=e&&(*d))){e=e&&((*d)>='0'&&(*d)<='9');i=(*d++)-'0';if((e=e&&(*d))){e=e&&((*d)>='0'&&(*d)<='9');i=i*10+(*d++)-'0';if((e=e&&(*d))){e=e&&((*d)>='0'&&(*d)<='9');i=i*10+(*d++)-'0';if((e=e&&(*d))){e=e&&((*d)>='0'&&(*d)<='9');i=i*10+(*d++)-'0';}}}}if(!e)break;}
|
||||
|
||||
static int MajTm(modEtat * p_etat, const char * format, const char * date)
|
||||
{
|
||||
memset(&p_etat->stm, 0, sizeof(p_etat->stm));
|
||||
p_etat->stm.tm_mday = 1; // le jour du mois ne demarre pas a 0 (ce que fait le numero de mois : 0 a 11)
|
||||
p_etat->stm.tm_isdst = -1;
|
||||
p_etat->decalageHoraire = HORODATE_DECALAGEHORAIREINCONNU;
|
||||
//
|
||||
int encore = TRUE;
|
||||
int i, signe;
|
||||
char * f = (char *)format, * d = (char *)date, c;
|
||||
while((c = *f++) && encore)
|
||||
{
|
||||
switch(c)
|
||||
{
|
||||
case 'A':
|
||||
LIRE4(d,i,encore);
|
||||
p_etat->stm.tm_year = i - 1900;
|
||||
break;
|
||||
case 'a':
|
||||
LIRE2(d,i,encore);
|
||||
p_etat->stm.tm_year = i + 100; // pas d'annee avant 2000... mettre une annee pivot ? type si < 50, 20xx sinon 19xx ?
|
||||
break;
|
||||
case 'M':
|
||||
LIRE2(d,i,encore);
|
||||
p_etat->stm.tm_mon = i - 1;
|
||||
break;
|
||||
case 'J':
|
||||
LIRE2(d,i,encore);
|
||||
p_etat->stm.tm_mday = i;
|
||||
break;
|
||||
case 'h':
|
||||
LIRE2(d,i,encore);
|
||||
p_etat->stm.tm_hour = i;
|
||||
break;
|
||||
case 'm':
|
||||
LIRE2(d,i,encore);
|
||||
p_etat->stm.tm_min = i;
|
||||
break;
|
||||
case 's':
|
||||
LIRE2(d,i,encore);
|
||||
p_etat->stm.tm_sec = i;
|
||||
break;
|
||||
case 'S':
|
||||
LIRE2(d,i,encore);
|
||||
p_etat->stm.tm_sec = i;
|
||||
LIRE1(d,i,encore);
|
||||
if(i != ',') {d--;break;}
|
||||
LIRE1(d,i,encore);
|
||||
if(i < '0' || i > '9') {d--;break;}
|
||||
LIRE1(d,i,encore);
|
||||
if(i < '0' || i > '9') {d--;break;}
|
||||
LIRE1(d,i,encore);
|
||||
if(i < '0' || i > '9') {d--;break;}
|
||||
LIRE1(d,i,encore);
|
||||
if(i < '0' || i > '9') {d--;break;}
|
||||
LIRE1(d,i,encore);
|
||||
if(i < '0' || i > '9') {d--;break;}
|
||||
LIRE1(d,i,encore);
|
||||
if(i < '0' || i > '9') {d--;break;}
|
||||
LIRE1(d,i,encore);
|
||||
if(i < '0' || i > '9') {d--;break;}
|
||||
// 7 decimales maxi...
|
||||
break;
|
||||
case 'F':
|
||||
LIRE1(d,i,encore);
|
||||
if(i == 'Z') {p_etat->decalageHoraire=0;break;}
|
||||
else if(i != '+' && i != '-') {encore=FALSE;break;}
|
||||
if(i == '-') signe = -1 ; else signe = 1;
|
||||
LIRE2(d,i,encore);
|
||||
p_etat->decalageHoraire = signe * i * 3600;
|
||||
LIRE1(d,i,encore);
|
||||
if(i != ':') {d--;break;}
|
||||
LIRE2(d,i,encore);
|
||||
p_etat->decalageHoraire += signe * i * 60;
|
||||
break;
|
||||
default:
|
||||
LIRE1(d,i,encore);
|
||||
if(c != i) {encore=FALSE;break;}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return encore; // true = ok, false = erreur
|
||||
}
|
||||
|
||||
static time_t MkTimeTU(modEtat * p_etat)
|
||||
{
|
||||
// utilisation de l'agorithme http://howardhinnant.github.io/date_algorithms.html
|
||||
// car pas de fonction directe dans time.h : mktime suppose que struct tm est locale
|
||||
int y, m, d;
|
||||
y = p_etat->stm.tm_year + 1900;
|
||||
m = p_etat->stm.tm_mon + 1;
|
||||
d = p_etat->stm.tm_mday;
|
||||
//
|
||||
if(m <= 2) y--;
|
||||
if(y < 0) y -= 399;
|
||||
int era = y / 400;
|
||||
unsigned int yoe = (y - era * 400); // [0, 399]
|
||||
unsigned int doy = (153 * (m > 2 ? m - 3 : m + 9) + 2) / 5 + d - 1; // [0, 365]
|
||||
unsigned int doe = yoe * 365 + yoe / 4 - yoe / 100 + doy; // [0, 146096]
|
||||
time_t t = (time_t)(era * 146097 + doe - 719468);
|
||||
t = t * 86400 + p_etat->stm.tm_hour * 3600 + p_etat->stm.tm_min * 60 + p_etat->stm.tm_sec;
|
||||
return t;
|
||||
}
|
||||
|
||||
static void FormatTm(env * e, modEtat * p_etat, const char * format, time_t dhm, time_t decalageHoraire)
|
||||
{
|
||||
dynSetLen(e, &p_etat->horodate, 0);
|
||||
char * p = (char *)format, c[2] = {0};
|
||||
dhm += decalageHoraire;
|
||||
p_etat->stm.tm_isdst = -1;
|
||||
p_etat->stm = *gmtime(&dhm);
|
||||
//
|
||||
while((c[0] = *p++))
|
||||
{
|
||||
switch(c[0])
|
||||
{
|
||||
case 'A':
|
||||
case 'Y':
|
||||
dynLet(e, &p_etat->valNum, Int64ToSz(e, p_etat->stm.tm_year + 1900, FALSE, 4), DYN_LGNONE);
|
||||
dynConcat(e, &p_etat->horodate, &p_etat->valNum);
|
||||
break;
|
||||
case 'a':
|
||||
case 'y':
|
||||
dynLet(e, &p_etat->valNum, Int64ToSz(e, p_etat->stm.tm_year % 100, FALSE, 2), DYN_LGNONE);
|
||||
dynConcat(e, &p_etat->horodate, &p_etat->valNum);
|
||||
break;
|
||||
case 'M':
|
||||
dynLet(e, &p_etat->valNum, Int64ToSz(e, p_etat->stm.tm_mon + 1, FALSE, 2), DYN_LGNONE);
|
||||
dynConcat(e, &p_etat->horodate, &p_etat->valNum);
|
||||
break;
|
||||
case 'J':
|
||||
case 'D':
|
||||
dynLet(e, &p_etat->valNum, Int64ToSz(e, p_etat->stm.tm_mday, FALSE, 2), DYN_LGNONE);
|
||||
dynConcat(e, &p_etat->horodate, &p_etat->valNum);
|
||||
break;
|
||||
case 'h':
|
||||
dynLet(e, &p_etat->valNum, Int64ToSz(e, p_etat->stm.tm_hour, FALSE, 2), DYN_LGNONE);
|
||||
dynConcat(e, &p_etat->horodate, &p_etat->valNum);
|
||||
break;
|
||||
case 'm':
|
||||
dynLet(e, &p_etat->valNum, Int64ToSz(e, p_etat->stm.tm_min, FALSE, 2), DYN_LGNONE);
|
||||
dynConcat(e, &p_etat->horodate, &p_etat->valNum);
|
||||
break;
|
||||
case 's':
|
||||
case 'S':
|
||||
dynLet(e, &p_etat->valNum, Int64ToSz(e, p_etat->stm.tm_sec, FALSE, 2), DYN_LGNONE);
|
||||
dynConcat(e, &p_etat->horodate, &p_etat->valNum);
|
||||
break;
|
||||
case 'F':
|
||||
if(decalageHoraire == 0)
|
||||
dynConcatSz(e, &p_etat->horodate, "Z", 1);
|
||||
else
|
||||
{
|
||||
dynConcatSz(e, &p_etat->horodate, decalageHoraire > 0 ? "+" : "-", 1);
|
||||
//
|
||||
dynLet(e, &p_etat->valNum, Int64ToSz(e, (abs(decalageHoraire) / 3600) % 100, FALSE, 2), DYN_LGNONE);
|
||||
dynConcat(e, &p_etat->horodate, &p_etat->valNum);
|
||||
//
|
||||
dynConcatSz(e, &p_etat->horodate, ":", 1);
|
||||
//
|
||||
dynLet(e, &p_etat->valNum, Int64ToSz(e, (abs(decalageHoraire) % 3600) / 60, FALSE, 2), DYN_LGNONE);
|
||||
dynConcat(e, &p_etat->horodate, &p_etat->valNum);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
dynConcatSz(e, &p_etat->horodate, c, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* fonctions locales au module FIN */
|
||||
|
||||
#ifndef UNIX
|
||||
/* Sous Windows, export de la fonction de base au sein d'une DLL : 1 module = 1 DLL */
|
||||
__declspec(dllexport) long execModule(env * , var * , var * , var * , void ** );
|
||||
long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
|
||||
#else
|
||||
extern long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
extern long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
|
||||
#endif
|
||||
{
|
||||
/* TODO : gestion des 3 parametres (au lieu d'un seul) */
|
||||
@@ -59,12 +310,19 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
long exc = OK;
|
||||
// init/end/vers/error sont obligatoires pour tout module
|
||||
// - - - - - - - - - - - - - - - - - - - -
|
||||
if(param == NULL || etat == NULL)
|
||||
return EX_MODPARAM;
|
||||
if(etat == NULL)
|
||||
return EX_MODETAT;
|
||||
else
|
||||
p_etat = (modEtat *)(*etat); /* evite de la faire a chaque fonction */
|
||||
if(param->type == VAR_PARAM)
|
||||
param = (var *)param->ptr; /* evite de le faire a chaque fonction */
|
||||
p_etat = (modEtat *)(*etat); /* evite de le faire a chaque fonction */
|
||||
if(param1 != NULL)
|
||||
if(param1->type == VAR_PARAM)
|
||||
param1 = (var *)param1->ptr; /* evite de le faire a chaque fonction */
|
||||
if(param2 != NULL)
|
||||
if(param2->type == VAR_PARAM)
|
||||
param2 = (var *)param2->ptr; /* evite de le faire a chaque fonction */
|
||||
if(param3 != NULL)
|
||||
if(param3->type == VAR_PARAM)
|
||||
param3 = (var *)param3->ptr; /* evite de le faire a chaque fonction */
|
||||
//
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
/* les 4 fonctions suivantes doivent toujours exister dans chaque module */
|
||||
@@ -81,6 +339,8 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
//*** code specifique ici
|
||||
p_etat->start = 0;
|
||||
p_etat->lap = 0;
|
||||
dynInit(e, &p_etat->horodate, DYN_LGMIN);
|
||||
dynInit(e, &p_etat->valNum, DYN_LGMIN);
|
||||
}
|
||||
}
|
||||
else if(strncmp(e->fn, "end", 3) == 0)
|
||||
@@ -89,14 +349,18 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
if(p_etat != NULL)
|
||||
memfree(e, p_etat);
|
||||
//*** code specifique ici
|
||||
dynFree(e, &p_etat->horodate);
|
||||
dynFree(e, &p_etat->valNum);
|
||||
}
|
||||
else if(strncmp(e->fn, "vers", 4) == 0)
|
||||
{
|
||||
// renvoie la version du module/plugins
|
||||
if(param->type == VAR_DYNAMIC)
|
||||
dynLet(e, param, "1", 1); //*** version en alpha
|
||||
else if(param->type == VAR_NUMBER)
|
||||
param->num = NUM_UN; //*** version en numerique
|
||||
if(param1 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type == VAR_DYNAMIC)
|
||||
dynLet(e, param1, "1", 1); //*** version en alpha
|
||||
else if(param1->type == VAR_NUMBER)
|
||||
param1->num = NUM_UN; //*** version en numerique
|
||||
else
|
||||
exc = EX_MODPARAM; // variable en parametre du mauvais type
|
||||
}
|
||||
@@ -105,10 +369,12 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
// renvoie la derniere erreur specifique au module
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param1 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
if(param->type == VAR_NUMBER)
|
||||
param->num = (ent64)(NUM_FACTEUR * p_etat->error);
|
||||
if(param1->type == VAR_NUMBER)
|
||||
param1->num = (ent64)(NUM_FACTEUR * p_etat->error);
|
||||
else
|
||||
exc = EX_MODPARAM; // variable en parametre du mauvais type
|
||||
}
|
||||
@@ -116,29 +382,353 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
/* ============================================================================================= */
|
||||
else if(strncmp(e->fn, "startChrono", 11) == 0)
|
||||
{
|
||||
struct timespec ts;
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param1 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_NUMBER)
|
||||
exc = EX_MODPARAM; // variables en parametre du mauvais type
|
||||
//
|
||||
if (clock_gettime_monotonic(&p_etat->sts) == -1)
|
||||
exc = setError(p_etat, EXMOD_GETCLOCK);
|
||||
else if(param->type != VAR_NUMBER)
|
||||
exc = setError(p_etat, EXMOD_PARAMNUM);
|
||||
else
|
||||
{
|
||||
p_etat->start = ts.tv_sec * NUM_FACTEUR + (ts.tv_nsec / 10000);
|
||||
param->num = p_etat->start;
|
||||
p_etat->start = p_etat->sts.tv_sec * NUM_FACTEUR + (p_etat->sts.tv_nsec / 10000);
|
||||
param1->num = p_etat->start;
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "lapChrono", 9) == 0)
|
||||
{
|
||||
struct timespec ts;
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param1 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_NUMBER)
|
||||
exc = EX_MODPARAM; // variables en parametre du mauvais type
|
||||
//
|
||||
if (clock_gettime_monotonic(&p_etat->sts) == -1)
|
||||
exc = setError(p_etat, EXMOD_GETCLOCK);
|
||||
else if(param->type != VAR_NUMBER)
|
||||
exc = setError(p_etat, EXMOD_PARAMNUM);
|
||||
else
|
||||
{
|
||||
p_etat->lap = ts.tv_sec * NUM_FACTEUR + (ts.tv_nsec / 10000);
|
||||
param->num = p_etat->lap - p_etat->start;
|
||||
p_etat->lap = p_etat->sts.tv_sec * NUM_FACTEUR + (p_etat->sts.tv_nsec / 10000);
|
||||
param1->num = p_etat->lap - p_etat->start;
|
||||
p_etat->start = p_etat->lap; // permet de refaire un appel de lapChrono
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "setUTC", 6) == 0)
|
||||
{
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param1 == NULL || param2 == NULL || param3 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_HASHTABLE || param2->type != VAR_DYNAMIC || param3->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM; // variables en parametre du mauvais type
|
||||
else
|
||||
{
|
||||
// param2 = format ; param3 = date
|
||||
if( ! MajTm(p_etat, param2->mPtr, param3->mPtr))
|
||||
exc = EXMOD_FORMAT_KO;
|
||||
else
|
||||
{
|
||||
p_etat->dhm = MkTimeTU(p_etat);
|
||||
p_etat->decalageHoraire = 0;
|
||||
// maj param1 avec les 2 champs dhm et decalage (number)
|
||||
p_etat->v.type = VAR_NUMBER;
|
||||
p_etat->v.num = p_etat->dhm * NUM_FACTEUR;
|
||||
p_etat->pv = &p_etat->v;
|
||||
hashtable_do(e, HASH_WRITE, param1, copy_nom(e, "timestamp"), &p_etat->pv);
|
||||
p_etat->v.num = p_etat->decalageHoraire * NUM_FACTEUR;
|
||||
hashtable_do(e, HASH_WRITE, param1, copy_nom(e, "jetlag"), &p_etat->pv);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "setLocal", 8) == 0)
|
||||
{
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param1 == NULL || param2 == NULL || param3 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_HASHTABLE || param2->type != VAR_DYNAMIC || param3->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM; // variables en parametre du mauvais type
|
||||
else
|
||||
{
|
||||
// param2 = format ; param3 = date
|
||||
if(!MajTm(p_etat, param2->mPtr, param3->mPtr))
|
||||
exc = EXMOD_FORMAT_KO;
|
||||
else
|
||||
{
|
||||
p_etat->dhm = MkTimeTU(p_etat);
|
||||
// calcul decalage horaire local
|
||||
struct tm stm, stmtu;
|
||||
stm.tm_isdst = -1;
|
||||
stm = *localtime(&p_etat->dhm);
|
||||
stmtu = *gmtime(&p_etat->dhm);
|
||||
p_etat->decalageHoraire = (stm.tm_isdst == 1 ? 3600 : 0); // gestion heure d'ete
|
||||
p_etat->decalageHoraire += mktime(&stm) - mktime(&stmtu); // modifie stm.tm_isdst !
|
||||
p_etat->dhm -= p_etat->decalageHoraire;
|
||||
// maj param1 avec les 2 champs dhm et decalage (number)
|
||||
p_etat->v.type = VAR_NUMBER;
|
||||
p_etat->v.num = p_etat->dhm * NUM_FACTEUR;
|
||||
p_etat->pv = &p_etat->v;
|
||||
hashtable_do(e, HASH_WRITE, param1, copy_nom(e, "timestamp"), &p_etat->pv);
|
||||
p_etat->v.num = p_etat->decalageHoraire * NUM_FACTEUR;
|
||||
hashtable_do(e, HASH_WRITE, param1, copy_nom(e, "jetlag"), &p_etat->pv);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "setNowLocal", 11) == 0)
|
||||
{
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param1 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_HASHTABLE)
|
||||
exc = EX_MODPARAM; // variables en parametre du mauvais type
|
||||
else
|
||||
{
|
||||
p_etat->dhm = time(NULL);
|
||||
// calcul decalage horaire local
|
||||
struct tm stm, stmtu;
|
||||
stm.tm_isdst = -1;
|
||||
stm = *localtime(&p_etat->dhm);
|
||||
stmtu = *gmtime(&p_etat->dhm);
|
||||
p_etat->decalageHoraire = (stm.tm_isdst == 1 ? 3600 : 0); // gestion heure d'ete
|
||||
p_etat->decalageHoraire += mktime(&stm) - mktime(&stmtu); // modifie stm.tm_isdst !
|
||||
// maj param1 avec les 2 champs dhm et decalage (number)
|
||||
p_etat->v.type = VAR_NUMBER;
|
||||
p_etat->v.num = p_etat->dhm * NUM_FACTEUR;
|
||||
p_etat->pv = &p_etat->v;
|
||||
hashtable_do(e, HASH_WRITE, param1, copy_nom(e, "timestamp"), &p_etat->pv);
|
||||
p_etat->v.num = p_etat->decalageHoraire * NUM_FACTEUR;
|
||||
hashtable_do(e, HASH_WRITE, param1, copy_nom(e, "jetlag"), &p_etat->pv);
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "setNowUTC", 9) == 0)
|
||||
{
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param1 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_HASHTABLE)
|
||||
exc = EX_MODPARAM; // variables en parametre du mauvais type
|
||||
else
|
||||
{
|
||||
p_etat->dhm = time(NULL);
|
||||
p_etat->decalageHoraire = 0;
|
||||
// maj param1avec les 2 champs dhm et decalage (number)
|
||||
p_etat->v.type = VAR_NUMBER;
|
||||
p_etat->v.num = p_etat->dhm * NUM_FACTEUR;
|
||||
p_etat->pv = &p_etat->v;
|
||||
hashtable_do(e, HASH_WRITE, param1, copy_nom(e, "timestamp"), &p_etat->pv);
|
||||
p_etat->v.num = p_etat->decalageHoraire * NUM_FACTEUR;
|
||||
hashtable_do(e, HASH_WRITE, param1, copy_nom(e, "jetlag"), &p_etat->pv);
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "set", 3) == 0)
|
||||
{
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param1 == NULL || param2 == NULL || param3 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_HASHTABLE || param2->type != VAR_DYNAMIC || param3->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM; // variables en parametre du mauvais type
|
||||
else
|
||||
{
|
||||
// param2 = format ; param3 = date
|
||||
if( ! MajTm(p_etat, param2->mPtr, param3->mPtr))
|
||||
exc = EXMOD_FORMAT_KO;
|
||||
else
|
||||
{
|
||||
p_etat->dhm = MkTimeTU(p_etat);
|
||||
if(p_etat->decalageHoraire == HORODATE_DECALAGEHORAIREINCONNU)
|
||||
exc = EXMOD_JETLAG_KO;
|
||||
else
|
||||
{
|
||||
p_etat->dhm -= p_etat->decalageHoraire;
|
||||
// maj param1 avec les 2 champs dhm et decalage (number)
|
||||
p_etat->v.type = VAR_NUMBER;
|
||||
p_etat->v.num = p_etat->dhm * NUM_FACTEUR;
|
||||
p_etat->pv = &p_etat->v;
|
||||
hashtable_do(e, HASH_WRITE, param1, copy_nom(e, "timestamp"), &p_etat->pv);
|
||||
p_etat->v.num = p_etat->decalageHoraire * NUM_FACTEUR;
|
||||
hashtable_do(e, HASH_WRITE, param1, copy_nom(e, "jetlag"), &p_etat->pv);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "getUTC", 6) == 0)
|
||||
{
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param1 == NULL || param2 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_HASHTABLE || param2->type != VAR_DYNAMIC || param3->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM; // variables en parametre du mauvais type
|
||||
else
|
||||
{
|
||||
p_etat->decalageHoraire = 0;
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "timestamp"), &p_etat->pv);
|
||||
p_etat->dhm = (p_etat->pv)->num / NUM_FACTEUR;
|
||||
//
|
||||
FormatTm(e, p_etat, param2->mPtr, p_etat->dhm, p_etat->decalageHoraire);
|
||||
// resultat
|
||||
dynLet(e, param3, p_etat->horodate.mPtr, DYN_LGNONE);
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "getLocal", 8) == 0)
|
||||
{
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param1 == NULL || param2 == NULL || param3 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_HASHTABLE || param2->type != VAR_DYNAMIC || param3->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM; // variables en parametre du mauvais type
|
||||
else
|
||||
{
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "timestamp"), &p_etat->pv);
|
||||
p_etat->dhm = (p_etat->pv)->num / NUM_FACTEUR;
|
||||
// calcul decalage horaire local
|
||||
struct tm stm, stmtu;
|
||||
stm.tm_isdst = -1;
|
||||
stm = *localtime(&p_etat->dhm);
|
||||
stmtu = *gmtime(&p_etat->dhm);
|
||||
p_etat->decalageHoraire = (stm.tm_isdst == 1 ? 3600 : 0); // gestion heure d'ete
|
||||
p_etat->decalageHoraire += mktime(&stm) - mktime(&stmtu); // modifie stm.tm_isdst !
|
||||
//
|
||||
FormatTm(e, p_etat, param2->mPtr, p_etat->dhm, p_etat->decalageHoraire);
|
||||
// resultat
|
||||
dynLet(e, param3, p_etat->horodate.mPtr, DYN_LGNONE);
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "get", 3) == 0)
|
||||
{
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param1 == NULL || param2 == NULL || param3 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_HASHTABLE || param2->type != VAR_DYNAMIC || param3->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM; // variables en parametre du mauvais type
|
||||
else
|
||||
{
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "jetlag"), &p_etat->pv);
|
||||
p_etat->decalageHoraire = (p_etat->pv)->num / NUM_FACTEUR;
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "timestamp"), &p_etat->pv);
|
||||
p_etat->dhm = (p_etat->pv)->num / NUM_FACTEUR;
|
||||
//
|
||||
if(p_etat->decalageHoraire == HORODATE_DECALAGEHORAIREINCONNU)
|
||||
p_etat->decalageHoraire = 0; // securite : se remettre en UTC
|
||||
FormatTm(e, p_etat, param2->mPtr, p_etat->dhm, p_etat->decalageHoraire);
|
||||
// resultat
|
||||
dynLet(e, param3, p_etat->horodate.mPtr, DYN_LGNONE);
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "alarmUTCHM", 16) == 0)
|
||||
{
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param1 == NULL || param2 == NULL || param3 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_NUMBER || param2->type != VAR_DYNAMIC || param3->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM; // variables en parametre du mauvais type
|
||||
else
|
||||
{
|
||||
// TODO a tester
|
||||
ent64s hhmm = param1->num / NUM_FACTEUR;
|
||||
// param2 = alarme_tfin (sortie) ; param3 = m_Tmp ~ delai (sortie)
|
||||
long now,alarme_tfin;
|
||||
now = time(NULL);
|
||||
p_etat->decalageHoraire = 0;
|
||||
p_etat->dhm = now;
|
||||
FormatTm(e, p_etat, HORODATE_ISO8601, p_etat->dhm, p_etat->decalageHoraire);
|
||||
sprintf(p_etat->horodate.mPtr + 11, "%02lld", hhmm / 100);
|
||||
p_etat->horodate.mPtr[13] = ':';
|
||||
sprintf(p_etat->horodate.mPtr + 14, "%02lld", hhmm % 100);
|
||||
p_etat->horodate.mPtr[16] = ':';
|
||||
p_etat->horodate.mPtr[17] = '0';
|
||||
p_etat->horodate.mPtr[18] = '0';
|
||||
//
|
||||
if( ! MajTm(p_etat, HORODATE_ISO8601, p_etat->horodate.mPtr))
|
||||
exc = EXMOD_FORMAT_KO;
|
||||
else
|
||||
{
|
||||
alarme_tfin = p_etat->dhm;
|
||||
if(alarme_tfin < now)
|
||||
alarme_tfin += 86400;
|
||||
dynLet(e, param2, Int64ToSz(e, alarme_tfin, FALSE, 19), DYN_LGNONE);
|
||||
dynLet(e, param3, "86400", 5); // delai
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "alarmLocalHM", 18) == 0)
|
||||
{
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param1 == NULL || param2 == NULL || param3 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_NUMBER || param2->type != VAR_DYNAMIC || param3->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM; // variables en parametre du mauvais type
|
||||
else
|
||||
{
|
||||
// TODO prendre la version debuggee + a tester
|
||||
ent64s hhmm = param1->num / NUM_FACTEUR;
|
||||
// param2 = alarme_tfin (sortie) ; param3 = m_Tmp ~ delai (sortie)
|
||||
long alarme_tfin, now;
|
||||
now = time(NULL);
|
||||
p_etat->dhm = now;
|
||||
// calcul decalage horaire local
|
||||
struct tm stm, stmtu;
|
||||
stm.tm_isdst = -1;
|
||||
stm = *localtime(&p_etat->dhm);
|
||||
stmtu = *gmtime(&p_etat->dhm);
|
||||
p_etat->decalageHoraire = (stm.tm_isdst == 1 ? 3600 : 0); // gestion heure d'ete
|
||||
p_etat->decalageHoraire += mktime(&stm) - mktime(&stmtu); // modifie stm.tm_isdst !
|
||||
//
|
||||
FormatTm(e, p_etat, param2->mPtr, p_etat->dhm, p_etat->decalageHoraire);
|
||||
sprintf(p_etat->horodate.mPtr + 11, "%02lld", hhmm / 100);
|
||||
p_etat->horodate.mPtr[13] = ':';
|
||||
sprintf(p_etat->horodate.mPtr + 14, "%02lld", hhmm % 100);
|
||||
p_etat->horodate.mPtr[16] = ':';
|
||||
p_etat->horodate.mPtr[17] = '0';
|
||||
p_etat->horodate.mPtr[18] = '0';
|
||||
//
|
||||
if( ! MajTm(p_etat, HORODATE_ISO8601, p_etat->horodate.mPtr))
|
||||
exc = EXMOD_FORMAT_KO;
|
||||
else
|
||||
{
|
||||
alarme_tfin = p_etat->dhm;
|
||||
if(alarme_tfin < now)
|
||||
{
|
||||
// ajouter un jour sur le format "externe" ISO8601, idem quand echue pour calcul suivant
|
||||
AddOneDay(e, p_etat);
|
||||
// TODO : convertir les 2 lignes a suivre
|
||||
if( ! MajTm(p_etat, HORODATE_ISO8601, p_etat->horodate.mPtr))
|
||||
exc = EXMOD_FORMAT_KO;
|
||||
else
|
||||
{
|
||||
p_etat->dhm = MkTimeTU(p_etat);
|
||||
if(p_etat->decalageHoraire == HORODATE_DECALAGEHORAIREINCONNU)
|
||||
exc = EXMOD_JETLAG_KO;
|
||||
else
|
||||
{
|
||||
p_etat->dhm -= p_etat->decalageHoraire;
|
||||
alarme_tfin = p_etat->dhm;
|
||||
dynLet(e, param2, Int64ToSz(e, alarme_tfin, FALSE, 19), DYN_LGNONE);
|
||||
dynLet(e, param3, p_etat->horodate.mPtr, 5); // delai
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
|
||||
@@ -129,6 +129,7 @@ void var_free(env * e, var * v, int suivre_par)
|
||||
case VAR_BUFFER:
|
||||
memfree(e, v->ptr);
|
||||
break;
|
||||
case VAR_OBJECT:
|
||||
case VAR_HASHTABLE:
|
||||
/* boucler et liberer chaque variable, attention aux cycles ! */
|
||||
hashtable_select(e, v);
|
||||
@@ -139,10 +140,7 @@ void var_free(env * e, var * v, int suivre_par)
|
||||
hashtable_free_ovf(e, v);
|
||||
/* liberer bloc primaire */
|
||||
memfree(e, v->ptr);
|
||||
break;
|
||||
case VAR_OBJECT:
|
||||
/* ne pas liberer un object/classe : sera fait par "free" ou a la fin du process car global (env->g) */
|
||||
break;
|
||||
break;
|
||||
}
|
||||
v->type = VAR_NULL;
|
||||
}
|
||||
@@ -175,6 +173,7 @@ void var_let(env * e, var * let, var * v, int suivre_let, int suivre_v)
|
||||
let->lg = v->lg;
|
||||
break;
|
||||
//
|
||||
case VAR_OBJECT:
|
||||
case VAR_HASHTABLE:
|
||||
var_init(e, let, v->type, v->modulo, v->separateur / sizeof(entry), NULL);
|
||||
// boucler et copier les elements, attention aux cycles !
|
||||
@@ -188,7 +187,7 @@ void var_let(env * e, var * let, var * v, int suivre_let, int suivre_v)
|
||||
if(!suivre_v)
|
||||
var_init(e, let, VAR_PARAM, 0, 0, v->ptr);
|
||||
break;
|
||||
case VAR_OBJECT:
|
||||
|
||||
case VAR_BUFFER:
|
||||
// RAF pour l'instant
|
||||
break;
|
||||
|
||||
Reference in new issue
Block a user