13 Commits
Author SHA1 Message Date
nicolas 3c86d54a10 Merge pull request 'Ajout section installation' (#5) from nicolas-patch-installation into master
Reviewed-on: #5
2026-01-02 15:30:59 +01:00
nicolas ac2ade566a Changement nom sources files
Changement du nom du source file dans /etc/apt/sources.list.d de docker.sources en wlanguage.sources

Signed-off-by: Deville <nicolas@lanisys.fr>
2026-01-02 12:06:40 +01:00
nicolas 81b7307d18 Suppression espace
Suppression d'un espace pour faire plus jolie

Signed-off-by: Deville <nicolas@lanisys.fr>
2026-01-02 12:00:53 +01:00
nicolas e120af6ec3 Ajout section installation
Ajout de la section installation pour décrire l'ajout du dépôt officiel.

Signed-off-by: Deville <nicolas@lanisys.fr>
2026-01-02 11:57:26 +01:00
fred 264291b36b Merge pull request 'Update Wiki W' (#3) from nicolas-patch-1 into master
Reviewed-on: #3
2025-12-24 17:29:43 +01:00
nicolas 73ab1c2aa6 Update Wiki W
Suite changement hébergement web, le lien du wiki a changé. Mise à jour du lien.

Signed-off-by: Deville <nicolas@lanisys.fr>
2025-12-24 13:30:32 +01:00
fred 676dd07036 Merge pull request 'alpha' (#1) from alpha into master
Reviewed-on: #1
2025-05-01 19:43:25 +02:00
fred c80524017d feat: licence 2025 2025-05-01 19:38:57 +02:00
fred 23761bad27 feat: license 2025 2025-05-01 19:37:38 +02:00
fred 74159114d3 test 2025-05-01 19:35:46 +02:00
fred 902311f40d test 2025-05-01 19:32:54 +02:00
fred d49c1ed476 feat: add @exceptline + appel sub object 2025-05-01 12:24:10 +02:00
fred 1f7b840256 WIP 2025-04-27 17:28:40 +02:00
17 changed files with 2526 additions and 972 deletions

No files matched your search

+17 -1
View File
@@ -24,6 +24,22 @@ 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
```
# Execution
var pour la shared lib, puis exécution :
@@ -46,4 +62,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
View File
@@ -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);
}
+1 -1
View File
@@ -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"
+12 -6
View File
@@ -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
+5
View File
@@ -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)
+1 -1
View File
@@ -199,7 +199,7 @@ static void formatage(Dynamic * s, Dynamic * f, int type)
//
dynInit(&e, &regles, 0);
//
if(lire_regles_lex(&e, &regles, "lex/wlex") != DYN_OK)
if(lire_regles_lex(&e, &regles, "/etc/wlanguage/wlex") != DYN_OK) // au lieu de lex/wlex
{
dynLet(&e, f, s->mPtr, s->mLg);
dynFree(&e, &regles);
+529 -289
View File
File diff suppressed because it is too large. Load diff
+11
View File
@@ -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
+2
View 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
View File
@@ -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);
}
+15 -4
View File
@@ -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
View File
@@ -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;
}
+1025 -344
View File
File diff suppressed because it is too large. Load diff
+8 -7
View File
@@ -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
View File
@@ -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);
+617 -27
View File
@@ -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
}
}
}
}
}
}
/* ----------------------------------------------------------------------------------------------- */
+4 -5
View File
@@ -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;