Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3384b0df85 | ||
|
|
fcb62ff71c | ||
|
|
0871ed56fc | ||
|
|
a6f8d2aefa | ||
|
|
ba010944e2 | ||
|
|
2b076ebd18 | ||
|
|
7cdd94920e | ||
|
|
764752c3c5 | ||
|
|
84548796b2 | ||
|
|
eb4a60f1e5 | ||
|
|
523a925d0c | ||
|
|
5967052eef | ||
|
|
592298a3df | ||
|
|
a0cf21e3aa | ||
|
|
c051bfa423 | ||
|
|
150697206a | ||
|
|
dde78f169b | ||
|
|
bc4be93744 | ||
|
|
dd6f3ebbcf | ||
|
|
3ae1e8c019 | ||
|
|
31acb7939d | ||
|
|
676dd07036 | ||
|
|
c80524017d | ||
|
|
23761bad27 | ||
|
|
74159114d3 | ||
|
|
902311f40d | ||
|
|
d49c1ed476 | ||
|
|
1f7b840256 |
No files matched your search
@@ -30,6 +30,9 @@ var pour la shared lib, puis exécution :
|
||||
```
|
||||
export LD_LIBRARY_PATH=/home/fde/dev/langage/w/exec
|
||||
|
||||
(sur le serveur de dev. pour que ce soit compatible avec la version installee)
|
||||
sudo ln -s /home/fde/dev/langage/w/lex /etc/wlanguage
|
||||
|
||||
exec/lw -t -WBIN:./exec -WSRC:. test
|
||||
```
|
||||
|
||||
@@ -40,10 +43,43 @@ ldd
|
||||
objdump/readelf (moins bien)
|
||||
cat /proc/*/maps et faire des grep pour voir les .so et module chargés par opendl
|
||||
```
|
||||
# Compilation
|
||||
# Compilation et execution
|
||||
```
|
||||
# exec/lwc $1.w $1.wa < $1.w ; exec/lwa $1.wa ; exec/lw $1
|
||||
exec/genw $1.w && exec/lwa $1.wa ; exec/lw $1
|
||||
exec/genw $1.w && exec/lwa $1.wa && rm $1.wa && exec/lw $1
|
||||
```
|
||||
# Site Web
|
||||
https://www.lanisys.fr/wiki/doku.php?id=w
|
||||
|
||||
## LANGAGE W
|
||||
|
||||
### Présentation
|
||||
|
||||
Le but du langage W est d’être simple, efficace, robuste.
|
||||
Il est fourni avec un compilateur qui génère un code binaire de type
|
||||
*p-code*, compatible toute plateforme.
|
||||
Un exécuteur de p-code W sera disponible sur Linux et d’autres OS.
|
||||
Un interpréteur W permet également d’exécuter un programme W en mode
|
||||
*script*.
|
||||
Un module FastCGI permettra de plus d’utiliser le langage W en mode
|
||||
interprété ou compilé pour les sites Internet.
|
||||
Enfin, les programmes W pourront être appelés depuis d’autres
|
||||
programmes, un peu comme un langage de plugins.
|
||||
Deux utilitaires permettent de formatter le code source et de générer de
|
||||
la documentation à partir de *tags* dans le code, au format
|
||||
[DokuWiki](https://www.dokuwiki.org/dokuwiki).
|
||||
|
||||
Description du fonctionnement des [programmes](/w/prog) d’exécution et
|
||||
compilation.
|
||||
|
||||
Pour démarrer, premier programme d’exemple :
|
||||
|
||||
``` w
|
||||
; Le celebre Hello world en W
|
||||
begin hello
|
||||
echonl "Hello world !"
|
||||
except
|
||||
end
|
||||
```
|
||||
|
||||
Voici la description complète du [langage W](/w/instr).
|
||||
@@ -0,0 +1,51 @@
|
||||
|
||||
#define ARG_DEBUG "d"
|
||||
#define ARG_TRACE "t"
|
||||
#define ARG_DISASM "d"
|
||||
|
||||
void GetArgs(env * e, int argc, char * argv[], Dynamic * arg)
|
||||
{
|
||||
int nbOpt = 0, cpt = 0;
|
||||
dynSetLen(e, arg, 0);
|
||||
for(int a = 1; a < argc; a++)
|
||||
{
|
||||
if(strcmp(argv[a], "-" ARG_DEBUG) == 0)
|
||||
dynStoreSz(e, arg, 1, ++nbOpt, ARG_DEBUG, 1, cFM, cVM);
|
||||
else if(strcmp(argv[a], "-" ARG_TRACE) == 0)
|
||||
dynStoreSz(e, arg, 1, ++nbOpt, ARG_TRACE, 1, cFM, cVM);
|
||||
else if(strncmp(argv[a], "-WBIN:", 6) == 0 && strlen(argv[a]) > 6)
|
||||
dynStoreSz(e, arg, 3, DYN_NONE, &argv[a][6], DYN_LGNONE, cFM, DYN_NONE); // memo (.o .so)
|
||||
else if(strncmp(argv[a], "-WLIB:", 6) == 0 && strlen(argv[a]) > 6)
|
||||
dynStoreSz(e, arg, 5, DYN_NONE, &argv[a][6], DYN_LGNONE, cFM, DYN_NONE); // memo (.wp .wa)
|
||||
else if(strncmp(argv[a], "-WSRC:", 6) == 0 && strlen(argv[a]) > 6)
|
||||
dynStoreSz(e, arg, 4, DYN_NONE, &argv[a][6], DYN_LGNONE, cFM, DYN_NONE); // memo (.w)
|
||||
else if(strncmp(argv[a], "-", 1) == 0)
|
||||
; // argument inconnu, ignorer
|
||||
else
|
||||
{
|
||||
// premier argument ne commencant pas par "-" : nom du prog wp
|
||||
for( ; a < argc; a++)
|
||||
dynStoreSz(e, arg, 2, ++cpt, argv[a], DYN_LGNONE, cFM, cVM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(dynExtractPos(e, arg, 3, DYN_NONE, cFM, DYN_NONE) <= 0)
|
||||
{
|
||||
dynStoreSz(e, arg, 3, DYN_NONE, getenv("WBIN"), DYN_LGNONE, cFM, DYN_NONE); // si absent en ligne de cmd, lire de la var d'env
|
||||
if(dynExtractPos(e, arg, 3, DYN_NONE, cFM, DYN_NONE) <= 0)
|
||||
dynStoreSz(e, arg, 3, DYN_NONE, getenv("LD_LIBRARY_PATH"), DYN_LGNONE, cFM, DYN_NONE); // dernier recours...
|
||||
}
|
||||
//
|
||||
if(dynExtractPos(e, arg, 5, DYN_NONE, cFM, DYN_NONE) <= 0)
|
||||
dynStoreSz(e, arg, 5, DYN_NONE, getenv("WLIB"), DYN_LGNONE, cFM, DYN_NONE); // si absent en ligne de cmd, lire de la var d'env
|
||||
//
|
||||
if(dynExtractPos(e, arg, 4, DYN_NONE, cFM, DYN_NONE) <= 0)
|
||||
dynStoreSz(e, arg, 4, DYN_NONE, getenv("WSRC"), DYN_LGNONE, cFM, DYN_NONE); // si absent en ligne de cmd, lire de la var d'env
|
||||
/*
|
||||
arg<1> = options en MV
|
||||
arg<2> = prog et parametres en MV
|
||||
arg<3> = WBIN (.o .so) => invoke, LD_LIBRARY_PATH
|
||||
arg<4> = WSRC (.w) => lwc
|
||||
arg<5> = WLIB (.wp .wa) => call, lwa lwc
|
||||
*/
|
||||
}
|
||||
+279
-330
@@ -20,6 +20,9 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
********************************************** */
|
||||
#ifdef WINLIB
|
||||
#include "windows.h"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@@ -28,41 +31,52 @@
|
||||
#include "langage.h"
|
||||
#include "dynamic.h"
|
||||
#include "instr.h"
|
||||
|
||||
char libComp[9 * 3] = {"EQ " "NE " "LT " "GT " "LE " "GE " "AND" "OR " "NOT"};
|
||||
#include "arg.c"
|
||||
|
||||
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 +98,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 +127,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 +219,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 +271,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 +318,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)
|
||||
@@ -423,23 +374,22 @@ int assembler(env * e, char * fichier, int * cptLig)
|
||||
case IN_CALL:
|
||||
// CLIB / CALL
|
||||
PCODE(instr)
|
||||
do
|
||||
//dynField(e, &ligne, &tmp, i++, 0, ' ', 0, 1);
|
||||
//num = dynToNum(e, &tmp, 0, 3) & 255;
|
||||
//if(tmp.mInternal == DYN_ERR) { ret = -3; break; } // erreur conversion
|
||||
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] == '_')
|
||||
{
|
||||
PCODE(0)
|
||||
}
|
||||
else
|
||||
{
|
||||
//dynField(e, &ligne, &tmp, i++, 0, ' ', 0, 1);
|
||||
//num = dynToNum(e, &tmp, 0, 3) & 255;
|
||||
//if(tmp.mInternal == DYN_ERR) { ret = -3; break; } // erreur conversion
|
||||
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] == '_')
|
||||
{
|
||||
PCODE(0)
|
||||
break;
|
||||
}
|
||||
PCODE(num)
|
||||
for(int p = 0; p < num; p++)
|
||||
PCODE(tmp.mPtr[p])
|
||||
} while(TRUE);
|
||||
}
|
||||
break;
|
||||
case IN_PVAT:
|
||||
case IN_TYPO:
|
||||
@@ -459,6 +409,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 +425,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 +528,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 +585,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 +608,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 +644,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 +702,27 @@ 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_SDBG:
|
||||
dynField(e, &ligne, &tmp, i++, 0, ' ', 0, 1);
|
||||
num = tmp.mLg;
|
||||
PCODE(instr)
|
||||
PCODE((num >> 16) & 255)
|
||||
PCODE((num >> 8) & 255)
|
||||
PCODE(num & 255)
|
||||
for(int p = 0; p < num; p++)
|
||||
PCODE(tmp.mPtr[p])
|
||||
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;
|
||||
@@ -823,29 +749,13 @@ 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);
|
||||
}
|
||||
// si pas d'erreur, ecrire au meme endroit que le .wa (=> dans WLIB)
|
||||
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 +796,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 +814,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;
|
||||
@@ -989,15 +899,10 @@ int disassembler(env * e, char * fichier)
|
||||
case IN_CALL:
|
||||
// CLIB / CALL
|
||||
si++;
|
||||
do
|
||||
{
|
||||
lg = pcode.ptr[si++];
|
||||
if(lg == 0)
|
||||
break;
|
||||
lg = pcode.ptr[si++];
|
||||
if(lg > 0)
|
||||
for(int p = 0; p < lg; p++)
|
||||
printf("%c", pcode.mPtr[si++]);
|
||||
printf(" ");
|
||||
} while(TRUE);
|
||||
printf("\n");
|
||||
dumpHex(&pcode, si_instr, si);
|
||||
break;
|
||||
@@ -1018,6 +923,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 +937,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 +950,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 +965,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 +1043,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 +1141,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:
|
||||
@@ -1297,6 +1199,16 @@ int disassembler(env * e, char * fichier)
|
||||
printf("\n");
|
||||
dumpHex(&pcode, si_instr, si);
|
||||
break;
|
||||
case IN_SDBG:
|
||||
si++;
|
||||
lg = pcode.ptr[si++];
|
||||
lg = lg * 256 + pcode.ptr[si++];
|
||||
lg = lg * 256 + pcode.ptr[si++];
|
||||
for(int p = 0; p < lg; p++)
|
||||
printf("%c", pcode.mPtr[si++]);
|
||||
printf("\n");
|
||||
dumpHex(&pcode, si_instr, si);
|
||||
break;
|
||||
case IN_TEST:
|
||||
// TEST
|
||||
si++;
|
||||
@@ -1328,13 +1240,14 @@ int disassembler(env * e, char * fichier)
|
||||
dynFree(e, &tmp);
|
||||
dynFree(e, &varsys);
|
||||
dynFree(e, &niv);
|
||||
return 0;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* ***************************************************************************************************** */
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
int cr = 0;
|
||||
int cr = OK;
|
||||
Dynamic arg, wlib, fichier;
|
||||
/* */
|
||||
/* avis de licence */
|
||||
printf("W language Copyright 2024,2025 lanisys.fr\n");
|
||||
@@ -1342,37 +1255,73 @@ int main(int argc, char * argv[])
|
||||
/* argument : fichier a assembler/desassembler (si -d) */
|
||||
if(argc < 2)
|
||||
{
|
||||
printf("Usage: lwa [-d] <fichier>\n");
|
||||
printf("Usage: lwa [-d] [-WLIB:<chemin>] <fichier.wa|fichier.wp>\n");
|
||||
exit(-1);
|
||||
}
|
||||
/* */
|
||||
init_env(&e);
|
||||
struct timespec ts;
|
||||
lap = 0;
|
||||
if(clock_gettime_monotonic(&ts) != -1)
|
||||
lap = ts.tv_sec * 1000000 + (ts.tv_nsec / 1000);
|
||||
/* */
|
||||
if(strcmp(argv[1], "-d") == 0)
|
||||
init_env(&e);
|
||||
dynInit(&e, &arg, 0);
|
||||
dynInit(&e, &wlib, 0);
|
||||
dynInit(&e, &fichier, 0);
|
||||
/* */
|
||||
GetArgs(&e, argc, argv, &arg);
|
||||
dynExtractField(&e, &arg, 5, &wlib);
|
||||
dynExtractSubField(&e, &arg, 2, 1, &fichier); // fichier = .wa a assembler / .wp a desassembler
|
||||
/* */
|
||||
if(fichier.mLg < 4)
|
||||
{
|
||||
if(argc >= 3)
|
||||
{
|
||||
#ifndef UNIX
|
||||
cr = disassembler(&e, argv[2]);
|
||||
#else
|
||||
cr = disassembler(&e, argv[2]);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
printf("Usage: lwa -d <fichier>\n");
|
||||
printf("Nom de fichier incorrect\n");
|
||||
cr = -14;
|
||||
}
|
||||
else if(wlib.mLg == 0)
|
||||
{
|
||||
printf("Variable d'environnement WLIB non definie\n");
|
||||
cr = -15;
|
||||
}
|
||||
else
|
||||
{
|
||||
int numLig = 0;
|
||||
#ifndef UNIX
|
||||
if((cr = assembler(&e, argv[1], &numLig)) != OK)
|
||||
#else
|
||||
if((cr = assembler(&e, argv[1], &numLig)) != OK)
|
||||
#endif
|
||||
if(wlib.mPtr[wlib.mLg - 1] != e.path_sep[0])
|
||||
dynConcatSz(&e, &wlib, e.path_sep, 1);
|
||||
dynConcat(&e, &wlib, &fichier);
|
||||
if(dynLocateSz(&e, &arg, ARG_DISASM, cVM, 1, cFM) > 0)
|
||||
{
|
||||
printf("Erreur %d a la ligne %d\n", cr, numLig);
|
||||
#ifndef UNIX
|
||||
cr = disassembler(&e, wlib.mPtr);
|
||||
#else
|
||||
cr = disassembler(&e, wlib.mPtr);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
int numLig = 0;
|
||||
#ifndef UNIX
|
||||
if((cr = assembler(&e, wlib.mPtr, &numLig)) != OK)
|
||||
#else
|
||||
if((cr = assembler(&e, wlib.mPtr, &numLig)) != OK)
|
||||
#endif
|
||||
{
|
||||
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:%d ", 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);
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
/* **********************************************
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024,2025 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
W language is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version (GPL-3.0-or-later).
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
********************************************** */
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "langage.h"
|
||||
#include "var.h"
|
||||
#include "buffer.h"
|
||||
#include "dynamic.h"
|
||||
|
||||
/*
|
||||
Dans le contexte des IPC, memoire partagee, contenant un buffer (donc partagé), le champ "ptr" pointe forcement a la suite de l'entete,
|
||||
car un malloc ne fonctionne pas en inter process.
|
||||
Contrairement à la création avec "var_init", destiné a ne pas etre partage, ptr est créé par un malloc
|
||||
La macro BUFPTR permet de gerer ces 2 cas : si le buffer est en memoire partagee, le champ ptr = NULL et il suffit alors d'aller juste apres l'entete
|
||||
pour trouver les donnees. Si le buffer est cree avec var_init, il faut utiliser la valeur de ptr directement.
|
||||
*/
|
||||
#define BUFPTR(x) (pointeur)(x->ptr == NULL ? (pointeur)(x + sizeof(var)) : x->ptr)
|
||||
|
||||
void buffer_read(env * e, var * varbuf, var * v)
|
||||
{
|
||||
ent16 lg, lgfin; /* taille max d'un element dans un buffer : 64 Ko */
|
||||
ent64 p;
|
||||
if(varbuf == NULL || v == NULL)
|
||||
return;
|
||||
if(varbuf->type != VAR_BUFFER)
|
||||
return;
|
||||
/* uniquement lecture dans VAR_DYNAMIC : raz var sinon */
|
||||
if(v->type == VAR_PARAM)
|
||||
v = (var *)v->ptr; /* travailler avec la var pointee ! */
|
||||
if(v->type != VAR_DYNAMIC)
|
||||
{
|
||||
var_free(e, v, TRUE);
|
||||
var_init(e, v, VAR_DYNAMIC, 0, 0, NULL);
|
||||
if(v->type == VAR_NULL)
|
||||
{
|
||||
/* erreur alloc memoire */
|
||||
e->exception = EX_MEM;
|
||||
return;
|
||||
}
|
||||
}
|
||||
dynLet(e, v, NULL, DYN_LGNONE);
|
||||
if(varbuf->read == varbuf->write)
|
||||
return; /* buffer vide : var dynamic vide aussi */
|
||||
/* */
|
||||
p = varbuf->read;
|
||||
lg = *(octet *)(BUFPTR(varbuf) + p++) * 256;
|
||||
if(p >= varbuf->lgmax) p = 0;
|
||||
lg += *(octet *)(BUFPTR(varbuf) + p++);
|
||||
if(p >= varbuf->lgmax) p = 0;
|
||||
if(lg > 0)
|
||||
{
|
||||
if(dynCtrl(e, v, lg, TRUE) != DYN_OK) /* avec RAZ */
|
||||
return;
|
||||
/* */
|
||||
if(lg <= (lgfin = varbuf->lgmax - p))
|
||||
{
|
||||
/* copier un seul bloc */
|
||||
memcopie(v->ptr, BUFPTR(varbuf) + p, lg);
|
||||
//memcpy(v->ptr, varbuf->ptr + p, lg);
|
||||
v->lg = lg;
|
||||
*(v->ptr + lg) = 0; /* \0 de fin de chaine */
|
||||
if(p + lg >= varbuf->lgmax)
|
||||
varbuf->read = 0; /* cela ne peut pas etre plus loin, car sinon il y aurait eu 2 blocs a lire */
|
||||
else
|
||||
varbuf->read = p + lg;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 2 blocs */
|
||||
memcopie(v->ptr, BUFPTR(varbuf) + p, lgfin);
|
||||
//memcpy(v->ptr, varbuf->ptr + p, lgfin);
|
||||
memcopie(v->ptr + lgfin, BUFPTR(varbuf), lg - lgfin);
|
||||
//memcpy(v->ptr + lgfin, varbuf->ptr, lg - lgfin);
|
||||
varbuf->read = lg - lgfin;
|
||||
}
|
||||
}
|
||||
else
|
||||
varbuf->read = p;
|
||||
}
|
||||
|
||||
void buffer_write(env * e, var * varbuf, var * v)
|
||||
{
|
||||
ent64 p, lgfin;
|
||||
if(varbuf == NULL || v == NULL)
|
||||
return;
|
||||
if(v->type == VAR_PARAM)
|
||||
v = (var *)v->ptr; /* travailler avec la var pointee ! */
|
||||
if(varbuf->type != VAR_BUFFER || v->type != VAR_DYNAMIC)
|
||||
return;
|
||||
/* uniquement ecriture d'une VAR_DYNAMIC */
|
||||
if(v->lg > (varbuf->lgmax / 2)) // pour pouvoir ecrire au moins 2 items dans le buffer
|
||||
{
|
||||
e->exception = EX_BUFOVF; /* trop grand a ecrire */
|
||||
return;
|
||||
}
|
||||
ent64 vbread = varbuf->read;
|
||||
if(varbuf->write < vbread)
|
||||
{
|
||||
/* ecriture en une fois, + 3 car lg sur 16 bits en plus et laisser au moins 1 octet libre => read=write veut dire vide ! */
|
||||
if(vbread - varbuf->write < v->lg + 3)
|
||||
{
|
||||
e->exception = EX_BUFOVF; /* pas assez de place */
|
||||
return;
|
||||
}
|
||||
/* */
|
||||
p = varbuf->write;
|
||||
*(BUFPTR(varbuf) + p) = (v->lg & 65535) >> 8;
|
||||
p++;
|
||||
*(BUFPTR(varbuf) + p) = v->lg & 255;
|
||||
p++;
|
||||
memcopie(BUFPTR(varbuf) + p, v->ptr, v->lg);
|
||||
//memcpy(varbuf->ptr + p, v->ptr, v->lg);
|
||||
varbuf->write = p + v->lg;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ecriture en une ou 2 fois */
|
||||
if(varbuf->lgmax + vbread - varbuf->write < v->lg + 3) /* lgbuffer - (write - read) */
|
||||
{
|
||||
e->exception = EX_BUFOVF; /* pas assez de place */
|
||||
return;
|
||||
}
|
||||
p = varbuf->write;
|
||||
*(BUFPTR(varbuf) + p) = (v->lg & 65535) >> 8;
|
||||
p++;
|
||||
if(p >= varbuf->lgmax) p = 0;
|
||||
*(BUFPTR(varbuf) + p) = v->lg & 255;
|
||||
p++;
|
||||
if(p >= varbuf->lgmax) p = 0;
|
||||
if(v->lg == 0)
|
||||
{
|
||||
varbuf->write = p;
|
||||
return;
|
||||
}
|
||||
if(v->lg <= (lgfin = varbuf->lgmax - p))
|
||||
{
|
||||
/* copier en une fois */
|
||||
memcopie(BUFPTR(varbuf) + p, v->ptr, v->lg);
|
||||
//memcpy(varbuf->ptr + p, v->ptr, v->lg);
|
||||
if(p + v->lg >= varbuf->lgmax)
|
||||
varbuf->write = 0; /* pas plus cas sinon il y aurait eu copie en 2 fois */
|
||||
else
|
||||
varbuf->write = p + v->lg;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* en 2 fois */
|
||||
memcopie(BUFPTR(varbuf) + p, v->ptr, lgfin);
|
||||
//memcpy(varbuf->ptr + p, v->ptr, lgfin);
|
||||
memcopie(BUFPTR(varbuf), v->ptr + lgfin, v->lg - lgfin);
|
||||
//memcpy(varbuf->ptr, v->ptr + lgfin, v->lg - lgfin);
|
||||
varbuf->write = v->lg - lgfin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void buffer_clear(env * e, var * varbuf)
|
||||
{
|
||||
if(varbuf == NULL)
|
||||
return;
|
||||
if(varbuf->type != VAR_BUFFER)
|
||||
return;
|
||||
varbuf->read = 0;
|
||||
varbuf->write = 0;
|
||||
memset(BUFPTR(varbuf), 0, varbuf->lgmax);
|
||||
}
|
||||
|
||||
void buffer_printdebug(env * e, var * varbuf, ent32 lg)
|
||||
{
|
||||
if(varbuf == NULL)
|
||||
return;
|
||||
if(varbuf->type != VAR_BUFFER)
|
||||
return;
|
||||
printf("buffer lgmax=%lld read=%lld write=%lld\n", varbuf->lgmax, varbuf->read, varbuf->write);
|
||||
if(lg == 0)
|
||||
lg = varbuf->lgmax;
|
||||
/* affichage brut en hexa */
|
||||
hex2((char *)BUFPTR(varbuf), lg, 32);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/* **********************************************
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024,2025 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
W language is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version (GPL-3.0-or-later).
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
********************************************** */
|
||||
#ifndef BUFFER_H
|
||||
#define BUFFER_H
|
||||
|
||||
void buffer_read(env * e, var * varbuf, var * v);
|
||||
void buffer_write(env * e, var * varbuf, var * v);
|
||||
void buffer_clear(env * e, var * varbuf);
|
||||
|
||||
void buffer_printdebug(env * e, var * varbuf, ent32 lg);
|
||||
|
||||
/* ********************************************** */
|
||||
#endif
|
||||
@@ -1,10 +1,12 @@
|
||||
echo 0. Compilation pour shared lib
|
||||
gcc -c w_src/dynamic.c -s -Wall -DUNIX -m64 -fPIC -o exec/dynamic.o
|
||||
gcc -c w_src/dynamic.c -s -Wall -DUNIX -m64 -fPIC -o exec/dynamic.o -Wno-unused-value
|
||||
gcc -c w_src/var.c -s -Wall -DUNIX -m64 -fPIC -o exec/var.o
|
||||
gcc -c w_src/hashtable.c -s -Wall -DUNIX -m64 -fPIC -o exec/hashtable.o
|
||||
gcc -c w_src/buffer.c -s -Wall -DUNIX -m64 -fPIC -o exec/buffer.o
|
||||
gcc -c w_src/global.c -s -Wall -DUNIX -m64 -fPIC -o exec/global.o
|
||||
gcc -shared -s exec/dynamic.o exec/var.o exec/hashtable.o exec/global.o -o exec/libw.so
|
||||
rm -f exec/dynamic.o exec/var.o exec/hashtable.o exec/global.o
|
||||
gcc -c w_src/rep.c -s -Wall -DUNIX -m64 -fPIC -o exec/rep.o
|
||||
gcc -shared -s exec/dynamic.o exec/var.o exec/hashtable.o exec/global.o exec/rep.o exec/buffer.o -o exec/libw.so
|
||||
rm -f exec/dynamic.o exec/var.o exec/hashtable.o exec/global.o exec/rep.o exec/buffer.o
|
||||
|
||||
echo 1. Compilation de modeleMod.c
|
||||
gcc -shared -s -o exec/modele.o w_src/modeleMod.c -m64 -DUNIX -Wall -fPIC -L./exec -l:libw.so
|
||||
@@ -20,12 +22,21 @@ gcc -shared -s -o exec/db.o w_src/dbMod.c -m64 -DUNIX -Wall -ldl -fPIC -L./exec
|
||||
#gcc -shared -s -o exec/pgsql.o w_src/dbpgsql.c -m64 -DUNIX -Wall -I/usr/include/postgresql -fPIC -L./exec -l:libw.so
|
||||
|
||||
echo 5. Compilation de lzwMod.c
|
||||
gcc -shared -s -o exec/lzw.o w_src/lzwMod.c -m64 -DUNIX -Wall -fPIC -L./exec -l:libw.so
|
||||
gcc -shared -s -o exec/lzw_lib.o w_src/lzw_lib.c -m64 -DUNIX -Wall -fPIC -L./exec -l:libw.so
|
||||
gcc -shared -s -o exec/lzw.o w_src/lzwMod.c -m64 -DUNIX -Wall -fPIC -L./exec -l:libw.so -l:lzw_lib.o
|
||||
|
||||
echo 5. Compilation de pdfMod.c
|
||||
gcc -shared -s -o exec/pdf_lib.o w_src/pdf_lib.c -m64 -DUNIX -Wall -fPIC -L./exec -l:libw.so
|
||||
gcc -shared -s -o exec/pdf.o w_src/pdfMod.c -m64 -DUNIX -Wall -fPIC -L./exec -l:libw.so -l:pdf_lib.o -l:lzw_lib.o
|
||||
|
||||
echo 6. Compilation de jsonMod.c
|
||||
gcc -shared -s -o exec/json_lib.o w_src/json_lib.c -m64 -DUNIX -Wall -fPIC -L./exec -l:libw.so
|
||||
gcc -shared -s -o exec/json.o w_src/jsonMod.c -m64 -DUNIX -Wall -fPIC -L./exec -l:libw.so -l:json_lib.o
|
||||
|
||||
echo 6. Compilation de shmMod.c
|
||||
gcc -shared -s -o exec/shm_lib.o w_src/shm_lib.c -m64 -DUNIX -Wall -fPIC -L./exec -l:libw.so
|
||||
gcc -shared -s -o exec/shm.o w_src/shmMod.c -m64 -DUNIX -Wall -fPIC -L./exec -l:libw.so -l:shm_lib.o
|
||||
|
||||
echo 7. Compilation de timeMod.c
|
||||
gcc -shared -s -o exec/time.o w_src/timeMod.c -m64 -DUNIX -Wall -fPIC -L./exec -l:libw.so
|
||||
|
||||
@@ -48,11 +59,12 @@ echo 13. Generation du formatteur de code
|
||||
gcc w_src/format.c -s -o exec/lwf -Wall -m64 -DUNIX -L./exec -l:libw.so
|
||||
|
||||
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
|
||||
gcc w_src/genlex.c -o exec/wlex -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
|
||||
echo 15. Generation de l\'analyseur de source w \(compilateur w\)
|
||||
gcc w_src/genw.c -s -o exec/lwc -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"
|
||||
echo "test_utf => gcc test_utf.c -s -o utf -Wall -m64 -DUNIX -L./exec -l:libw.so"
|
||||
echo "test_pdf => gcc test_pdf.c -s -o pdf -Wall -m64 -DUNIX -L./exec -l:libw.so -l:pdf_lib.o -l:lzw_lib.o"
|
||||
|
||||
echo "rep => gcc rep.c -s -o rep -Wall -m64 -DUNIX -L./exec -l:libw.so"
|
||||
echo "package => dpkg-deb --build wlanguage"
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
@echo off
|
||||
|
||||
cd "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build"
|
||||
call vcvars64.bat
|
||||
|
||||
cd "C:\Users\Poupougne42\source\repos\win_w_src"
|
||||
|
||||
echo 0. Compilation pour static lib
|
||||
cl /c /Foexec\dynamic.obj w_src\dynamic.c
|
||||
cl /c /Foexec\var.obj w_src\var.c
|
||||
cl /c /Foexec\hashtable.obj w_src\hashtable.c
|
||||
cl /c /Foexec\buffer.obj w_src\buffer.c
|
||||
cl /c /Foexec\global.obj w_src\global.c
|
||||
cl /c /Foexec\rep.obj w_src\rep.c
|
||||
|
||||
|
||||
lib /OUT:exec\libw.lib exec\dynamic.obj exec\var.obj exec\hashtable.obj exec\global.obj exec\rep.obj exec\buffer.obj
|
||||
|
||||
echo ------------------------------------------------------------------------
|
||||
echo 1a. Compilation de modeleMod.c
|
||||
cl w_src\modeleMod.c exec\libw.lib /Foexec\modeleMod.obj /DWINLIB /link /DLL /OUT:exec\modele.dll
|
||||
|
||||
echo ------------------------------------------------------------------------
|
||||
echo 1b. Compilation de fileMod.c
|
||||
cl w_src\fileMod.c exec\libw.lib /Foexec\fileMod.obj /DWINLIB /link /DLL /OUT:exec\file.dll
|
||||
|
||||
echo ------------------------------------------------------------------------
|
||||
echo 1c. Compilation de jsonMod.c
|
||||
cl /c /Foexec\json_lib.obj w_src\json_lib.c
|
||||
lib /OUT:exec\json_lib.lib exec\json_lib.obj
|
||||
cl w_src\jsonMod.c exec\libw.lib exec\json_lib.lib /Foexec\jsonMod.obj /DWINLIB /link /DLL /OUT:exec\json.dll
|
||||
|
||||
echo ------------------------------------------------------------------------
|
||||
echo 1d. Compilation de timeMod.c
|
||||
cl w_src\timeMod.c exec\libw.lib /Foexec\timeMod.obj /DWINLIB /link /DLL /OUT:exec\time.dll
|
||||
|
||||
echo ------------------------------------------------------------------------
|
||||
echo 1e. Compilation de hashMod.c
|
||||
cl w_src\hashMod.c exec\libw.lib /Foexec\hashMod.obj /DWINLIB /link /DLL /OUT:exec\hash.dll
|
||||
|
||||
echo ------------------------------------------------------------------------
|
||||
echo 1f. Compilation de systemMod.c
|
||||
cl w_src\systemMod.c exec\libw.lib ws2_32.lib /Foexec\systemMod.obj /DWINLIB /link /DLL /OUT:exec\system.dll
|
||||
|
||||
echo ------------------------------------------------------------------------
|
||||
echo 1g. Compilation de randomMod.c
|
||||
cl w_src\randomMod.c exec\libw.lib /Foexec\randomMod.obj /DWINLIB /link /DLL /OUT:exec\random.dll
|
||||
|
||||
echo ------------------------------------------------------------------------
|
||||
echo 1h. Compilation de lzwMod.c
|
||||
cl /c /Foexec\lzw_lib.obj w_src\lzw_lib.c
|
||||
lib /OUT:exec\lzw_lib.lib exec\lzw_lib.obj
|
||||
cl w_src\lzwMod.c exec\libw.lib exec\lzw_lib.lib /Foexec\lzwMod.obj /DWINLIB /link /DLL /OUT:exec\lzw.dll
|
||||
|
||||
echo ------------------------------------------------------------------------
|
||||
echo 1h. Compilation de pdfMod.c
|
||||
cl /c /Foexec\pdf_lib.obj w_src\pdf_lib.c
|
||||
lib /OUT:exec\pdf_lib.lib exec\pdf_lib.obj
|
||||
cl w_src\pdfMod.c exec\libw.lib exec\pdf_lib.lib exec\lzw_lib.lib /Foexec\pdfMod.obj /DWINLIB /link /DLL /OUT:exec\pdf.dll
|
||||
|
||||
echo ------------------------------------------------------------------------
|
||||
echo 1i. Compilation de shmMod.c
|
||||
cl /c /Foexec\shm_lib.obj w_src\shm_lib.c /DWINLIB
|
||||
lib /OUT:exec\shm_lib.lib exec\shm_lib.obj
|
||||
cl w_src\shmMod.c exec\libw.lib exec\shm_lib.lib /Foexec\shmMod.obj /DWINLIB /link /DLL /OUT:exec\shm.dll
|
||||
|
||||
echo ------------------------------------------------------------------------
|
||||
echo 2. Compilation langage lw (ws2_32.lib pour socket)
|
||||
cl w_src\langage.c exec\libw.lib ws2_32.lib /Foexec\langage.obj /DWINLIB /link /OUT:exec\lw.exe
|
||||
|
||||
echo ------------------------------------------------------------------------
|
||||
echo 3. Compilation assembleur lwa
|
||||
cl w_src\assembler.c exec\libw.lib /Foexec\assembler.obj /DWINLIB /link /OUT:exec\lwa.exe
|
||||
|
||||
echo ------------------------------------------------------------------------
|
||||
echo 4. Compilation du compilateur W (generateur d'assembleur)
|
||||
cl w_src\genw.c exec\libw.lib /Foexec\genw.obj /DWINLIB /link /OUT:exec\lwc.exe
|
||||
|
||||
echo ------------------------------------------------------------------------
|
||||
echo 5. Compilation formatteur de code w
|
||||
cl w_src\format.c exec\libw.lib /Foexec\format.obj /DWINLIB /link /OUT:exec\lwf.exe
|
||||
|
||||
echo ------------------------------------------------------------------------
|
||||
echo 6. Generation du generateur de fichier lex
|
||||
cl w_src\genlex.c exec\libw.lib /Foexec\genlex.obj /DWINLIB /link /OUT:exec\wlex.exe
|
||||
|
||||
rem purge des .obj
|
||||
del exec\*.obj
|
||||
del exec\*.lib
|
||||
del exec\*.exp
|
||||
dir exec
|
||||
@@ -2,7 +2,7 @@
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024 lanisys.fr
|
||||
\/ \/ Copyright 2024,2025 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
@@ -86,7 +86,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
//
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
/* les 4 fonctions suivantes doivent toujours exister dans chaque module */
|
||||
if(strncmp(e->fn, "init", 4) == 0)
|
||||
if(modFnIs(e, "init", 4))
|
||||
{
|
||||
// alloc ptr sur zone memoire pour memoriser l'etat du module
|
||||
*etat = memalloc(e, sizeof(modEtat));
|
||||
@@ -102,14 +102,14 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
p_etat->fnDb = NULL;
|
||||
}
|
||||
}
|
||||
else if(strncmp(e->fn, "end", 3) == 0)
|
||||
else if(modFnIs(e, "end", 3))
|
||||
{
|
||||
// liberation specifique au module avant arret process
|
||||
if(p_etat != NULL)
|
||||
memfree(e, p_etat);
|
||||
//*** code specifique ici
|
||||
}
|
||||
else if(strncmp(e->fn, "vers", 4) == 0)
|
||||
else if(modFnIs(e, "vers", 4))
|
||||
{
|
||||
// renvoie la version du module/plugins
|
||||
if(param->type == VAR_DYNAMIC)
|
||||
@@ -119,7 +119,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
else
|
||||
exc = EX_MODPARAM; // variable en parametre du mauvais type
|
||||
}
|
||||
else if(strncmp(e->fn, "error", 5) == 0)
|
||||
else if(modFnIs(e, "error", 5))
|
||||
{
|
||||
// renvoie la derniere erreur specifique au module
|
||||
if(p_etat == NULL)
|
||||
@@ -133,7 +133,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(strncmp(e->fn, "conn", 4) == 0)
|
||||
else if(modFnIs(e, "conn", 4))
|
||||
{
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
@@ -182,7 +182,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(strncmp(e->fn, "disc", 4) == 0)
|
||||
else if(modFnIs(e, "disc", 4))
|
||||
{
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
@@ -208,7 +208,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(strncmp(e->fn, "info", 4) == 0)
|
||||
else if(modFnIs(e, "info", 4))
|
||||
{
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
|
||||
+9
-9
@@ -221,7 +221,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
}
|
||||
}
|
||||
// -----------------------------------------------------------
|
||||
if(strncmp(e->fn, "read", 4) == 0)
|
||||
if(modFnIs(e, "read", 4))
|
||||
{
|
||||
// param<1> = no fichier ; param<2> = cle
|
||||
dynRemove(e, param, &p_etat->mTmp, cFM, DYN_TRUE);
|
||||
@@ -319,11 +319,11 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
return EX_DB_ELSE; // pas d'erreur : mettre le code pour "non trouve" ELSE
|
||||
}
|
||||
}
|
||||
else if(strncmp(e->fn, "write", 4) == 0)
|
||||
else if(modFnIs(e, "write", 5))
|
||||
{
|
||||
//
|
||||
}
|
||||
else if(strncmp(e->fn, "open", 4) == 0)
|
||||
else if(modFnIs(e, "open", 4))
|
||||
{
|
||||
// param<1> = nom table ; si ok renvoie en retour param<1> = id fichier (indice du tableau)
|
||||
int lgSav = p_etat->mBase.mLg;
|
||||
@@ -376,7 +376,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
}
|
||||
dynSetLen(e, &p_etat->mBase, lgSav);
|
||||
}
|
||||
else if(strncmp(e->fn, "create", 5) == 0)
|
||||
else if(modFnIs(e, "create", 5))
|
||||
{
|
||||
// cree la table : param<1> nom ; modulo param<2> ; separateur param<3>
|
||||
fileHeader info;
|
||||
@@ -421,7 +421,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(strncmp(e->fn, "close", 5) == 0)
|
||||
else if(modFnIs(e, "close", 5))
|
||||
{
|
||||
// param<1> = no fichier
|
||||
int pos = dynToNum(e, param, 0, 6);
|
||||
@@ -437,7 +437,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
// sinon, fichier deja ferme : RAS
|
||||
}
|
||||
}
|
||||
else if(strncmp(e->fn, "setup", 5) == 0)
|
||||
else if(modFnIs(e, "setup", 5))
|
||||
{
|
||||
// sortir si mId deja present (!=0) : une base est deja ouverte
|
||||
// param<1> = repertoire de base => sa cle d'acces = mKey
|
||||
@@ -488,7 +488,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(strncmp(e->fn, "init", 4) == 0)
|
||||
else if(modFnIs(e, "init", 4))
|
||||
{
|
||||
// si init deja fait, ras
|
||||
if(p_etat == NULL)
|
||||
@@ -502,7 +502,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
dynInit(e, &p_etat->mEntry, DYN_LGMIN);
|
||||
}
|
||||
}
|
||||
else if(strncmp(e->fn, "end", 3) == 0)
|
||||
else if(modFnIs(e, "end", 3))
|
||||
{
|
||||
struct shmid_ds attrs = {0};
|
||||
// liberation specifique au module avant arret process
|
||||
@@ -534,7 +534,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
memfree(e, p_etat);
|
||||
*etat = NULL;
|
||||
}
|
||||
else if(strncmp(e->fn, "vers", 4) == 0)
|
||||
else if(modFnIs(e, "vers", 4))
|
||||
{
|
||||
// renvoie la version du module/plugins
|
||||
dynLet(e, param, "100", 3); // version 1.00 ici
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024 lanisys.fr
|
||||
\/ \/ Copyright 2024,2025 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
@@ -20,7 +20,47 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
********************************************** */
|
||||
long rg(env * e, Dynamic * regles, char * nom, Dynamic * tmp)
|
||||
char * strerr[] = {
|
||||
"EX_DIV0 Divide by zero", // 1
|
||||
"EX_MEM memalloc error",
|
||||
"EX_BUFOVF buffer overflow",
|
||||
"EX_IO input/output error (file...)",
|
||||
"EX_END instruction out of program memory", // 5
|
||||
"EX_LGNOM variable' length incorrect (1-24)",
|
||||
"EX_TYPVAR variable type unexpected",
|
||||
"EX_NULLOCAL null local table et not in global",
|
||||
"EX_NOVAR variable name unknown",
|
||||
"EX_MODOPEN module opening error (dlopen)", // 10
|
||||
"EX_MODDSYM module exec error (dlsym)",
|
||||
"EX_NOSTACK ends instruction and no _stack variable found",
|
||||
"EX_NAVAR variable type not expected",
|
||||
"EX_NOADVAR no ad_var pointer found for instruction",
|
||||
"EX_NAVERS pcode version of programm not supported", // 15
|
||||
"EX_MODNAME module name incorrect (1-21&1-23)",
|
||||
"EX_DYNERR string error",
|
||||
"EX_MODFUNC module function unknown",
|
||||
"EX_MODPARAM module parameter incorrect",
|
||||
"EX_MODETAT internal module state error", // 20
|
||||
"EX_MODERR module specific error",
|
||||
"EX_NOTNUM cannot convert from string to number",
|
||||
"EX_NOCLASS class name not found",
|
||||
"EX_CMDLINE_ARG command line argument not supported",
|
||||
"EX_PCODE bad pcode binary", // 25
|
||||
"EX_NOENVVAR environment variables not found",
|
||||
"EX_EXCEPTNUM except number too big (0-255)",
|
||||
"EX_BINVAR_KO _bin global variable not found",
|
||||
"EX_ENVVAR_KO _env global variable not found",
|
||||
"EX_BINADDRVAR_KO _binnaddr global variable not found", // 30
|
||||
"EX_CREATEHASH cannot create hashtable (memory error)",
|
||||
"EX_FIELD_KO extract from string error",
|
||||
"EX_SUBSTR_KO substring from string error",
|
||||
"EX_SEP_INCORRECT setsep characters incorrect",
|
||||
"EX_FORMAT_KO format string incorrect", // 35
|
||||
"EX_INSERT_KO insert field error",
|
||||
"EX_REMOVE_KO remove field error"
|
||||
};
|
||||
|
||||
long rg(env * e, Dynamic * regles, char * nom, Dynamic * tmp)
|
||||
{
|
||||
// renvoie le numero de la regle a partir de son nom, 0 si non trouvee ou erreur conversion en numerique
|
||||
long pos = dynLocateSz(e, regles, nom, ',', 1, 10);
|
||||
@@ -36,7 +76,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;
|
||||
|
||||
@@ -52,62 +92,46 @@ void init_reg(env * e, Dynamic * regles, Dynamic * tmp)
|
||||
r.reste = rg(e, regles, "reste", tmp);
|
||||
}
|
||||
|
||||
#include <dirent.h>
|
||||
|
||||
long searchAndRead(env * e, const char * cheminBase, const char * fichier, Dynamic * fichierLu)
|
||||
void print_var(env * e, var * v, Dynamic * tmp)
|
||||
{
|
||||
#ifdef UNIX
|
||||
// recherche d'un fichier dans un repertoire puis, si pas trouve, dans tous les sous-repertoire
|
||||
DIR * rep = NULL;
|
||||
if((rep = opendir(cheminBase)) == NULL)
|
||||
return DYN_ERR;
|
||||
//
|
||||
Dynamic sousRep;
|
||||
dynInit(e, &sousRep, 0);
|
||||
long lgCheminBase = strlen(cheminBase) - 1;
|
||||
struct dirent * fic = NULL;
|
||||
// 1ere passe sur les fichiers
|
||||
while ((fic = readdir(rep)) != NULL)
|
||||
if(v->type == VAR_PARAM)
|
||||
v = (var *)v->ptr; /* travailler avec la var pointee */
|
||||
switch(v->type)
|
||||
{
|
||||
|
||||
if(fic->d_type == DT_REG && strcmp(fic->d_name, fichier) == 0)
|
||||
{
|
||||
closedir(rep);
|
||||
// fichier trouve : lecture
|
||||
dynLet(e, &sousRep, (char *)cheminBase, DYN_LGNONE);
|
||||
if(lgCheminBase >= 0 && sousRep.mPtr[lgCheminBase] != '/')
|
||||
dynConcatSz(e, &sousRep, "/", 1);
|
||||
dynConcatSz(e, &sousRep, fic->d_name, DYN_LGNONE);
|
||||
long cr = dynRead(e, fichierLu, sousRep.mPtr);
|
||||
dynFree(e, &sousRep);
|
||||
return cr;
|
||||
}
|
||||
}
|
||||
// si pas trouve, 2eme passe recursive sur les fichiers des repertoires
|
||||
rewinddir(rep);
|
||||
while ((fic = readdir(rep)) != NULL)
|
||||
{
|
||||
if(fic->d_type == DT_DIR && strcmp(fic->d_name, ".") != 0 && strcmp(fic->d_name, "..") != 0)
|
||||
{
|
||||
dynLet(e, &sousRep, (char *)cheminBase, DYN_LGNONE);
|
||||
if(lgCheminBase >= 0 && sousRep.mPtr[lgCheminBase] != '/')
|
||||
dynConcatSz(e, &sousRep, "/", 1); // a rendre compatible avec Windows
|
||||
dynConcatSz(e, &sousRep, fic->d_name, DYN_LGNONE);
|
||||
//
|
||||
if(searchAndRead(e, sousRep.mPtr, fichier, fichierLu) == DYN_OK)
|
||||
{
|
||||
closedir(rep);
|
||||
dynFree(e, &sousRep);
|
||||
return DYN_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(rep);
|
||||
dynFree(e, &sousRep);
|
||||
#endif
|
||||
return DYN_ERR;
|
||||
// "0XNSPDHOB"
|
||||
case VAR_NULL:
|
||||
printf("Var %c\n",e->var_car[v->type]); // X
|
||||
break;
|
||||
case VAR_NUMBER:
|
||||
long lg;
|
||||
NumberToSz(e, v->num, tmp->mPtr, &lg);
|
||||
printf("Var %c : %s\n",e->var_car[v->type], tmp->mPtr); // N
|
||||
break;
|
||||
case VAR_DYNAMIC:
|
||||
if(strncmp(e->nom, "_stack", 6) == 0)
|
||||
printf("Var %c(%lld) : %s (ret: %p)\n",e->var_car[v->type], v->mLg, v->mPtr, *(pointeur *)(v->mPtr)); // D
|
||||
else
|
||||
printf("Var %c(%lld) : %s\n",e->var_car[v->type], v->mLg, v->mPtr); // D
|
||||
break;
|
||||
case VAR_BUFFER:
|
||||
printf("Var %c\n",e->var_car[v->type]); // B
|
||||
break;
|
||||
case VAR_HASHTABLE:
|
||||
printf("Var %c\n",e->var_car[v->type]); // H
|
||||
hashtable_printdebug(e, v, 1);
|
||||
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 : %p (-> %p)\n",e->var_car[v->type], v, v->ptr); // S
|
||||
break;
|
||||
case VAR_PARAM:
|
||||
printf("Var %c\n",e->var_car[v->type]); // P : mais ne peut pas arriver ici
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* gestion du mode "debug" dans tous les type d'execution : p-code, compile, script... */
|
||||
void debug(env * e)
|
||||
{
|
||||
@@ -137,34 +161,49 @@ 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;
|
||||
strncpy(e->nom, "_env", 4);
|
||||
long srcFound = FALSE;
|
||||
e->nom64[0] = 0;
|
||||
e->nom64[1] = 0;
|
||||
e->nom64[2] = 0;
|
||||
strncpy(e->nom, "_srcdbg", 7);
|
||||
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;
|
||||
strncpy(e->nom, "_file", 5);
|
||||
// v = liste des noms/fichiers source vs numero de ligne
|
||||
GetFile(e, e->ligsrc, v, e->bin_indice, &tmp);
|
||||
e->nom64[0] = 0;
|
||||
e->nom64[1] = 0;
|
||||
e->nom64[2] = 0;
|
||||
strncpy(e->nom, "_wdir", 5);
|
||||
hashtable_do(e, HASH_READ, &e->g, e->nom, &v);
|
||||
if(v != NULL)
|
||||
if(tmp.mLg > 0 && v != NULL)
|
||||
{
|
||||
dynField(e, v, &tmp, 1, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
if(searchAndRead(e, dyn.mPtr, tmp.mPtr, &e->debugcmd) == DYN_OK)
|
||||
{
|
||||
printf("%s:%lld ", tmp.mPtr, e->ligsrc);
|
||||
dynField(e, &e->debugcmd, &tmp, e->ligsrc, DYN_NONE, 10, DYN_NONE, 1);
|
||||
printf("%s\n", tmp.mPtr);
|
||||
}
|
||||
//
|
||||
long nb,dup;
|
||||
dynSetLen(e, &dyn, 0);
|
||||
ScanDirectory(e, NULL, v, tmp.mPtr, &dyn, &nb, &dup);
|
||||
if(nb >= 1)
|
||||
if(dynRead(e, &e->tmp_dynamic, dyn.mPtr) == OK)
|
||||
{
|
||||
dynField(e, &e->tmp_dynamic, &e->int_dynamic, nb, DYN_NONE, cFM, DYN_NONE, 1); // on prend le permier fichier trouve
|
||||
dynField(e, &e->int_dynamic, &dyn, e->ligsrc, DYN_NONE, 10, DYN_NONE, 1);
|
||||
printf("%s:%lld: %s\n", tmp.mPtr, e->ligsrc, dyn.mPtr);
|
||||
srcFound = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
for(;;)
|
||||
{
|
||||
// prompt
|
||||
printf("W%d:%lld> ", VERSION, e->ligsrc);
|
||||
if(srcFound)
|
||||
printf("W%d> ", VERSION);
|
||||
else
|
||||
printf("W%d:%lld> ", VERSION, e->ligsrc);
|
||||
e->debugcmd.mLg = 0;
|
||||
int c;
|
||||
char cmd[2];
|
||||
@@ -188,7 +227,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
|
||||
@@ -206,16 +245,19 @@ void debug(env * e)
|
||||
if(tok == r.aide)
|
||||
{
|
||||
printf("Debug command list :\n"
|
||||
"? affiche les commandes de debug\n"
|
||||
"s S infos en cours sur le programme\n"
|
||||
"q Q continuer et arreter le mode debug 0\n"
|
||||
"n N continuer en mode debug pas a pas 1\n"
|
||||
"c C continuer en mode debug 2 arret aux points d'arret uniquement\n"
|
||||
"v V :ident voir le contenu de la variable <ident>\n"
|
||||
"b B liste des breakpoints\n"
|
||||
"b B +/- <nombre> ajouter ou supprimer un breakpoint ; si pas de nombre, à l'emplacement en cours, sinon numero de ligne source <nombre>\n"
|
||||
"a A + afficher les infos assembleur (idem trace)\n"
|
||||
"a A - supprimer les infos assembleur\n");
|
||||
"? affiche les commandes de debug\n"
|
||||
"s S infos en cours sur le programme\n"
|
||||
"q Q continuer et arreter le mode debug 0\n"
|
||||
"n N continuer en mode debug pas a pas 1\n"
|
||||
"c C continuer en mode debug 2 arret aux points d'arret uniquement\n"
|
||||
"v V :ident voir le contenu de la variable <ident>\n"
|
||||
"vg VG voir le contenu de la hash globale 'g'\n"
|
||||
"vg VG :ident voir le contenu de la var <ident> a l'interieur de la hash globale 'g'\n"
|
||||
"vl VL voir le contenu de la hash locale courante\n"
|
||||
"b B liste des breakpoints\n"
|
||||
"b B +/- num ajouter ou supprimer un breakpoint ; si pas de nombre, à l'emplacement en cours, sinon numero de ligne source <num>\n"
|
||||
"a A + afficher les infos assembleur (idem trace)\n"
|
||||
"a A - supprimer les infos assembleur\n");
|
||||
continue;
|
||||
}
|
||||
if(tok != r.commande)
|
||||
@@ -226,10 +268,58 @@ void debug(env * e)
|
||||
/* trt cmd ; e->debugcmd sert de variable tmp ici */
|
||||
dynField(e, &e->debugvalex, &tmp, 1, n, cFM, cVM, 1);
|
||||
dynIconv(e, &tmp, &e->debugcmd, "X");
|
||||
if(dynCompare(e, &e->debugcmd, CMP_EQ, "vg", 2) || dynCompare(e, &e->debugcmd, CMP_EQ, "VG", 2))
|
||||
{
|
||||
/* voir le contenu d'une variable */
|
||||
for(n++;;n++)
|
||||
{
|
||||
tok = ntok(n);
|
||||
if(tok == r.blanc)
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if(tok != r.ident)
|
||||
hashtable_printdebug(e, &e->g, 1);
|
||||
else
|
||||
{
|
||||
dynField(e, &e->debugvalex, &tmp, 1, n, cFM, cVM, 1);
|
||||
dynIconv(e, &tmp, &e->debugcmd, "X");
|
||||
if(e->debugcmd.mLg < 2 || e->debugcmd.mLg > 24)
|
||||
printf("Incorrect var name\n");
|
||||
else
|
||||
{
|
||||
e->nom64[0] = 0;
|
||||
e->nom64[1] = 0;
|
||||
e->nom64[2] = 0;
|
||||
for(int i = 0; i < e->debugcmd.mLg - 1; i++)
|
||||
e->nom[i] = e->debugcmd.mPtr[i + 1];
|
||||
var * v;
|
||||
hashtable_do(e, HASH_READ, &e->g, e->nom, &v);
|
||||
if(v != NULL)
|
||||
{
|
||||
print_var(e, v, &tmp);
|
||||
if(strncmp(e->nom, "_binaddr", 8) == 0)
|
||||
hex3(v->mPtr, v->mLg);
|
||||
}
|
||||
else
|
||||
printf("Unknown global var\n");
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if(dynCompare(e, &e->debugcmd, CMP_EQ, "vl", 2) || dynCompare(e, &e->debugcmd, CMP_EQ, "VL", 2))
|
||||
{
|
||||
if(e->local)
|
||||
hashtable_printdebug(e, e->local, 1);
|
||||
else
|
||||
printf("No local hashtable.\n");
|
||||
continue;
|
||||
}
|
||||
if(dynCompare(e, &e->debugcmd, CMP_EQ, "s", 1) || dynCompare(e, &e->debugcmd, CMP_EQ, "S", 1))
|
||||
{
|
||||
printf("Statut du programme en cours, pid %lld, pcode version %d, endianess %d :\n", e->pid, e->version, e->endianess);
|
||||
e->nom64[0] = 0;e->nom64[1] = 0;e->nom64[2] = 0;
|
||||
printf("Statut du programme en cours, pid %lld, pcode version %d, w-exec version %d (%s) :\n", e->pid, e->version, VERSION, (e->endianess == W_BIG_ENDIAN ? "big-endian" : "little-endian"));
|
||||
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)
|
||||
@@ -239,10 +329,15 @@ void debug(env * e)
|
||||
}
|
||||
else
|
||||
dynSetLen(e, &dyn, 0);
|
||||
if(e->except_ex > 0 && e->except_ex <= EXNB)
|
||||
dynLet(e, &e->debugcmd, strerr[e->except_ex - 1], DYN_LGNONE);
|
||||
else
|
||||
dynLet(e, &e->debugcmd, e->except_ex == 0 ? "" : "Unknown", DYN_LGNONE);
|
||||
printf("Source en cours => %s:%lld\n", dyn.mPtr, e->ligsrc);
|
||||
printf("PCode en cours => %p - %p (%d)\n", e->debut, e->fin, (int)(e->fin - e->debut + 1));
|
||||
printf("Part => %d\n", e->part);
|
||||
printf("Precision => %lld\n", e->precision);
|
||||
printf("Exception => %lld\n", e->except_ex);
|
||||
printf("Precision => %lld\n", e->precision / NUM_FACTEUR);
|
||||
printf("Exception => %lld %s\n", e->except_ex, e->debugcmd.mPtr);
|
||||
printf("Occupation memoire => %lld Ko, %lld blocs\n", e->mem_size/1024, e->mem_numb);
|
||||
continue;
|
||||
}
|
||||
@@ -266,6 +361,31 @@ void debug(env * e)
|
||||
dynFree(e, &tmp);
|
||||
dynFree(e, &dyn);
|
||||
return;
|
||||
}
|
||||
if(dynCompare(e, &e->debugcmd, CMP_EQ, "a", 1) || dynCompare(e, &e->debugcmd, CMP_EQ, "A", 1))
|
||||
{
|
||||
/* gestion des breakpoints */
|
||||
for(n++;;n++)
|
||||
{
|
||||
tok = ntok(n);
|
||||
if(tok == r.blanc)
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
}
|
||||
if(tok == r.ajouter)
|
||||
{
|
||||
e->trace = 1;
|
||||
printf("Trace ON\n");
|
||||
}
|
||||
else if(tok == r.supprimer)
|
||||
{
|
||||
e->trace = 0;
|
||||
printf("Trace OFF\n");
|
||||
}
|
||||
else
|
||||
printf("Syntax error in command\n");
|
||||
continue;
|
||||
}
|
||||
if(dynCompare(e, &e->debugcmd, CMP_EQ, "b", 1) || dynCompare(e, &e->debugcmd, CMP_EQ, "B", 1))
|
||||
{
|
||||
@@ -370,7 +490,10 @@ void debug(env * e)
|
||||
printf("Var %c : %s\n",e->var_car[v->type], tmp.mPtr); // N
|
||||
break;
|
||||
case VAR_DYNAMIC:
|
||||
printf("Var %c : %s\n",e->var_car[v->type], v->mPtr); // D
|
||||
if(strncmp(e->nom, "_stack", 6) == 0)
|
||||
printf("Var %c(%lld) : %s (ret: %p)\n",e->var_car[v->type], v->mLg, v->mPtr, *(pointeur *)(v->mPtr)); // D
|
||||
else
|
||||
printf("Var %c(%lld) : %s\n",e->var_car[v->type], v->mLg, v->mPtr); // D
|
||||
break;
|
||||
case VAR_BUFFER:
|
||||
printf("Var %c\n",e->var_car[v->type]); // B
|
||||
@@ -381,9 +504,10 @@ 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
|
||||
printf("Var %c : %p (-> %p)\n",e->var_car[v->type], v, v->ptr); // S
|
||||
break;
|
||||
case VAR_PARAM:
|
||||
printf("Var %c\n",e->var_car[v->type]); // P : mais ne peut pas arriver ici
|
||||
@@ -397,7 +521,7 @@ void debug(env * e)
|
||||
continue;
|
||||
}
|
||||
/* */
|
||||
printf("Unkown command\n");
|
||||
printf("Unknown command\n");
|
||||
}
|
||||
dynFree(e, &tmp);
|
||||
dynFree(e, &dyn);
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
; liste des commandes et mots cles en mode debug
|
||||
blanc: (1,*,#20#09#0A#0D)
|
||||
commande: (1,2,a-zA-Z)
|
||||
aide: (1,1,?)
|
||||
nombre: (1,9,0-9)
|
||||
ajouter: (1,1,#2B) ; +
|
||||
supprimer:(1,1,#2D) ; -
|
||||
ident: (1,1,#3A) (1,1,a-zA-Z_) (0,23,a-zA-Z0-9) ; :abcABC123
|
||||
reste: (1,1,#00-#FF)
|
||||
@@ -0,0 +1,9 @@
|
||||
blanc,1,commande,2,aide,3,nombre,4,ajouter,5,supprimer,6,ident,7,reste,8
|
||||
1,-1,20:09:0A:0D
|
||||
1,2,61-7A:41-5A
|
||||
1,1,3F
|
||||
1,9,30-39
|
||||
1,1,2B
|
||||
1,1,2D
|
||||
1,1,3A;1,1,5F:61-7A:41-5A;0,23,61-7A:41-5A:30-39
|
||||
1,1,00-FF
|
||||
@@ -32,7 +32,7 @@
|
||||
#define sSVM "\xFC"
|
||||
#define sTM "\xFB"
|
||||
|
||||
#define DYN_OK 0
|
||||
#define DYN_OK 0 // attention, DYN_OK doit etre egal a 0 sinon des tests seront KO...
|
||||
#define DYN_ERR -1
|
||||
|
||||
#define DYN_FALSE 0
|
||||
@@ -50,15 +50,19 @@
|
||||
{
|
||||
long mLg, mLgmax, mInternal;
|
||||
char * mPtr;
|
||||
short codePage;
|
||||
} Dynamic;*/
|
||||
typedef var Dynamic;
|
||||
|
||||
#define DYN_LGMIN 256
|
||||
|
||||
/*
|
||||
pour la gestion de l'UTF8, revoir les methodes suivantes :
|
||||
getLen, count, substr, erase, convert, cut
|
||||
pour la gestion de l'UTF8, revoir les methodes suivantes (https://en.wikipedia.org/wiki/UTF-8) :
|
||||
getLen, count, substr [x,y], erase, convert, cut
|
||||
(+ version de getLen sur une chaine sz ; getLen doit remplacer l'utilisation de mLg dans certains cas / creer un getCharLen)
|
||||
travailler en lg physique dans dynamic.c (c'est le cas) et si utf-8, faire un "pre-traitement" pour retrouver la lg physique
|
||||
à partir de la lg "logique" quand besoin ; si pas possible, evo dans chaque methode de dynamic.c ou plutot faire une 2eme methode pour l'UTF8 !!
|
||||
si erreur de codage/lecture utf8, la norme est de le remplacer par le point de code \uFFFD (EF BF BD) et de continuer (à convertir en 3F ? par exemple en mono byte)
|
||||
*/
|
||||
|
||||
/* ********************************************** */
|
||||
@@ -69,10 +73,13 @@ long dynInit(env * e, Dynamic * this, long lgmax);
|
||||
long dynCopy(env * e, Dynamic * this, Dynamic * aCopier);
|
||||
void dynFree(env * e, Dynamic * this);
|
||||
void dynSetLen(env * e, Dynamic * this, long lg);
|
||||
long dynLgU8(env * e, Dynamic * this);
|
||||
//long dynCarU8(env * e, Dynamic * this, long * pos);
|
||||
//long dynLgU8(env * e, Dynamic * this);
|
||||
long dynLengthUtf8(const char * p, long lg, int separator);
|
||||
long dynNextUtf8(char ** p, long lg, long * pos, char * carU8, int separator);
|
||||
long dynCtrl(env * e, Dynamic * this, long lg, long copier);
|
||||
void Win1252ToUTF8(env * e, Dynamic * valeur, Dynamic * resultat);
|
||||
void UTF8ToWin1252(env * e, Dynamic * valeur, Dynamic * resultat);
|
||||
long Win1252ToUTF8(env * e, Dynamic * valeur, Dynamic * resultat);
|
||||
long UTF8ToWin1252(env * e, Dynamic * valeur, Dynamic * resultat);
|
||||
void NumberToBin(env * e, ent64s valeur, pointeur resultat, int nbOctet, int signe, int endianess);
|
||||
void BinToNumber(env * e, pointeur valeur, ent64s * resultat, int nbOctet, int signe, int endianess);
|
||||
long dynSetAsNumber(env * e, Dynamic * this, ent64s valeur);
|
||||
@@ -110,22 +117,31 @@ long dynNext(env * e, Dynamic * this, Dynamic * resultat, char separateur);
|
||||
long dynRemove(env * e, Dynamic * this, Dynamic * resultat, char separateur, long raz);
|
||||
long dynExtractPos(env * e, Dynamic * this, long numChamp, long numSousChamp, char separateurChamp, char separateurSousChamp);
|
||||
long dynCount(env * e, Dynamic * this, char caractere, long numChamp, long numSousChamp, char separateurChamp, char separateurSousChamp);
|
||||
long dynCountUtf8(env * e, Dynamic * this, char * caractere4, long numChamp, long numSousChamp, char separateurChamp, char separateurSousChamp);
|
||||
long dynSetSubstr(env * e, Dynamic * this, Dynamic * valeur, long debut, long len, long numChamp, long numSousChamp, char separateurChamp, char separateurSousChamp);
|
||||
long dynSetSubstrUtf8(env * e, Dynamic * this, Dynamic * valeur, long debut, long len, long numChamp, long numSousChamp, char separateurChamp, char separateurSousChamp);
|
||||
long dynSubstr(env * e, Dynamic * this, Dynamic * resultat, long debut, long len, long numChamp, long numSousChamp, char separateurChamp, char separateurSousChamp);
|
||||
long dynSubstrUtf8(env * e, Dynamic * this, Dynamic * resultat, long debut, long len, long numChamp, long numSousChamp, char separateurChamp, char separateurSousChamp);
|
||||
char ** dynToTabPtr(env * e, Dynamic * this, char separateur);
|
||||
long dynConvert(env * e, Dynamic * this, char * from, char * to);
|
||||
void dynReplace(env * e, Dynamic * this, char from, char to);
|
||||
long dynConvertUtf8(env * e, Dynamic * this, char * from, char * to);
|
||||
void dynErase(env * e, Dynamic * this, char * car);
|
||||
void dynEraseUtf8(env * e, Dynamic * this, char * car);
|
||||
long dynIndexSz(env * e, Dynamic * this, char * chaine, long lgChaine, long occ);
|
||||
long dynIndex(env * e, Dynamic * this, Dynamic * valeur, long occ);
|
||||
long dynIndexSzUtf8(env * e, Dynamic * this, char * chaine, long lgChaine, long occ);
|
||||
long dynChange(env * e, Dynamic * this, char * chaine, char * remplace, long nb);
|
||||
long dynChangeUtf8(env * e, Dynamic * this, char * chaine, char * remplace, long nb);
|
||||
long dynOconv(env * e, Dynamic * this, Dynamic * resultat, char * format);
|
||||
long dynIconv(env * e, Dynamic * this, Dynamic * resultat, char * format);
|
||||
long dynConvertHexaToLong(Dynamic * valeur);
|
||||
long dynConvertCharHexaToChar(char c1, char c2, char * c);
|
||||
long dynFmt(env * e, Dynamic * this, Dynamic * resultat, char cadrage, char filler, long lg);
|
||||
long dynFmtUtf8(env * e, Dynamic * this, Dynamic * resultat, char cadrage, char * filler, long lg);
|
||||
long dynFmtNumber(env * e, ent64s valeur, Dynamic * resultat, char cadrage, char filler, long lg);
|
||||
long dynTrim(env * e, Dynamic * this, Dynamic * resultat, char car, long option);
|
||||
long dynTrimUtf8(env * e, Dynamic * this, Dynamic * resultat, char * car, long option);
|
||||
|
||||
/* ********************************************** */
|
||||
#endif
|
||||
@@ -2,7 +2,7 @@
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024 lanisys.fr
|
||||
\/ \/ Copyright 2024,2025 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024 lanisys.fr
|
||||
\/ \/ Copyright 2024,2025 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
@@ -54,9 +54,9 @@ static int setError(modEtat * p, int err)
|
||||
#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) */
|
||||
@@ -74,17 +74,24 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
// set : ecrit depuis param le dynamic dans le fichier (param = nom FM contenu)
|
||||
// size : donne la taille sur disque du fichier
|
||||
// dir : donne la liste des fichiers et repertoires d'un repertoire
|
||||
if(param == NULL || etat == NULL)
|
||||
if(etat == NULL)
|
||||
return EX_MODPARAM;
|
||||
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 */
|
||||
//printf("In fileMod (dlfcn) : fonction %s(%s)\n", e->fn, param->mPtr);
|
||||
//
|
||||
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 */
|
||||
if(strncmp(e->fn, "init", 4) == 0)
|
||||
if(modFnIs(e, "init", 4))
|
||||
{
|
||||
// alloc ptr sur zone memoire pour memoriser l'etat du module
|
||||
*etat = memalloc(e, sizeof(modEtat));
|
||||
@@ -97,40 +104,42 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
//*** code specifique ici
|
||||
}
|
||||
}
|
||||
else if(strncmp(e->fn, "end", 3) == 0)
|
||||
else if(modFnIs(e, "end", 3))
|
||||
{
|
||||
//*** code specifique ici
|
||||
// liberation specifique au module avant arret process
|
||||
if(p_etat != NULL)
|
||||
{
|
||||
//printf("mod end %d\n", p_etat->test);
|
||||
memfree(e, p_etat);
|
||||
}
|
||||
}
|
||||
else if(strncmp(e->fn, "vers", 4) == 0)
|
||||
else if(modFnIs(e, "vers", 4))
|
||||
{
|
||||
// renvoie la version du module/plugins
|
||||
if(param->type == VAR_DYNAMIC)
|
||||
dynLet(e, param, "1", 1); // version 1 ici
|
||||
else if(param->type == VAR_NUMBER)
|
||||
param->num = NUM_UN;
|
||||
if(param1->type == VAR_DYNAMIC)
|
||||
dynLet(e, param1, "1", 1); // version 1 ici
|
||||
else if(param1->type == VAR_NUMBER)
|
||||
param1->num = NUM_UN;
|
||||
else
|
||||
exc = EX_MODPARAM; // variable en parametre du mauvais type
|
||||
}
|
||||
else if(strncmp(e->fn, "error", 5) == 0)
|
||||
else if(modFnIs(e, "error", 5))
|
||||
{
|
||||
// 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
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(strncmp(e->fn, "create", 6) == 0)
|
||||
else if(modFnIs(e, "create", 6))
|
||||
{
|
||||
// todo...
|
||||
// test
|
||||
@@ -140,59 +149,61 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
printf("mod create %d\n", p_etat->error);
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "get", 3) == 0)
|
||||
else if(modFnIs(e, "get", 3))
|
||||
{
|
||||
/* utilisation de dynRead qui fait le travail */
|
||||
if(param->type == VAR_DYNAMIC)
|
||||
/* utilisation de dynRead qui fait le travail, param1 : nom, param2 : contenu lu */
|
||||
if(param1 == NULL || param2 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_DYNAMIC || param2->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
if(dynRead(e, param, param->mPtr) != DYN_OK)
|
||||
if(dynRead(e, param2, param1->mPtr) != DYN_OK)
|
||||
exc = setError(p_etat, 1);
|
||||
}
|
||||
else
|
||||
exc = EX_MODPARAM; /* TODO code */
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "set", 3) == 0)
|
||||
else if(modFnIs(e, "set", 3))
|
||||
{
|
||||
/* copie du code de dynWrite, avec modif car c'est la meme var dyn qui contient nom + contenu */
|
||||
FILE * fic;
|
||||
ent64s lg;
|
||||
/* */
|
||||
dynRemove(e, param, 0, 0, TRUE);
|
||||
if(dynRemove(e, param, &e->int_dynamic, cFM, FALSE) < 0)
|
||||
exc = setError(p_etat, 1); /* erreur generique : lire la vraie erreur ailleurs */
|
||||
/* copie du code de dynWrite, avec modif param1 : nom, param2 : contenu a ecrire */
|
||||
if(param1 == NULL || param2 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_DYNAMIC || param2->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
lg = e->int_dynamic.mInternal + 1;
|
||||
#ifndef UNIX
|
||||
if((fic = fopen(e->int_dynamic.mPtr, "wb")) == NULL) /* mode binaire sous Windows, sinon conversions faites en auto ! */
|
||||
#else
|
||||
if((fic = fopen(e->int_dynamic.mPtr, "w")) == NULL)
|
||||
#endif
|
||||
exc = setError(p_etat, 1); /* erreur generique : lire la vraie erreur ailleurs */
|
||||
else
|
||||
{
|
||||
if(fwrite(param->mPtr + lg, param->mLg - lg, 1, fic) != 1) /* retourne le nb de blocs ecrits, pas lenb d'octets !! */
|
||||
FILE * fic;
|
||||
#ifndef UNIX
|
||||
if((fic = fopen(param1->mPtr, "wb")) == NULL) /* mode binaire sous Windows, sinon conversions faites en auto ! */
|
||||
#else
|
||||
if((fic = fopen(param1->mPtr, "w")) == NULL)
|
||||
#endif
|
||||
exc = setError(p_etat, 1); /* erreur generique : lire la vraie erreur ailleurs */
|
||||
fclose(fic);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(fwrite(param2->mPtr, param2->mLg, 1, fic) != 1) /* retourne le nb de blocs ecrits, pas lenb d'octets !! */
|
||||
exc = setError(p_etat, 1); /* erreur generique : lire la vraie erreur ailleurs */
|
||||
fclose(fic);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "size", 4) == 0)
|
||||
else if(modFnIs(e, "size", 4))
|
||||
{
|
||||
/* copie du code de dynRead, plus court */
|
||||
FILE * fic;
|
||||
ent64s lg;
|
||||
/* */
|
||||
if(param->type != VAR_DYNAMIC)
|
||||
if(param1 == NULL || param2 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
if(param1->type != VAR_DYNAMIC || param2->type != VAR_NUMBER)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
#ifndef UNIX
|
||||
if((fic = fopen(param->mPtr, "wb")) == NULL) /* mode binaire sous Windows, sinon conversions faites en auto ! */
|
||||
if((fic = fopen(param1->mPtr, "rb")) == NULL) /* mode binaire sous Windows, sinon conversions faites en auto ! */
|
||||
#else
|
||||
if((fic = fopen(param->mPtr, "w")) == NULL)
|
||||
if((fic = fopen(param1->mPtr, "r")) == NULL)
|
||||
#endif
|
||||
exc = setError(p_etat, 1); /* erreur generique : lire la vraie erreur ailleurs */
|
||||
else
|
||||
@@ -202,36 +213,37 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
else
|
||||
{
|
||||
lg = ftell(fic); /* longueur du fichier */
|
||||
NumberToSz(e, lg, param->mPtr, (long *)¶m->mLg); // TODO a verifier
|
||||
param2->num = lg * NUM_FACTEUR;
|
||||
}
|
||||
fclose(fic);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "dir", 3) == 0)
|
||||
else if(modFnIs(e, "dir", 3))
|
||||
{
|
||||
/* copie du code de dynRead, plus court */
|
||||
/* */
|
||||
if(param->type != VAR_DYNAMIC)
|
||||
if(param1 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
if(param1->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
#ifdef UNIX
|
||||
DIR * rep = NULL;
|
||||
if((rep = opendir(param->mPtr)) == NULL)
|
||||
if((rep = opendir(param1->mPtr)) == NULL)
|
||||
exc = setError(p_etat, 1); /* todo vraie erreur */
|
||||
else
|
||||
{
|
||||
dynSetLen(e, param, 0); // idem raz
|
||||
dynSetLen(e, param1, 0); // idem raz
|
||||
struct dirent * fic = NULL;
|
||||
while ((fic = readdir(rep)) != NULL)
|
||||
{
|
||||
if((fic->d_type == DT_DIR || fic->d_type == DT_REG) && strcmp(fic->d_name,".") != 0 && strcmp(fic->d_name,"..") != 0)
|
||||
{
|
||||
if(param->mLg > 0)
|
||||
dynConcatSz(e, param, sFM, 1);
|
||||
dynConcatSz(e, param, fic->d_name, DYN_LGNONE);
|
||||
if(param1->mLg > 0)
|
||||
dynConcatSz(e, param1, sFM, 1);
|
||||
dynConcatSz(e, param1, fic->d_name, DYN_LGNONE);
|
||||
}
|
||||
}
|
||||
/* */
|
||||
@@ -240,17 +252,17 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
#else
|
||||
HANDLE hFind;
|
||||
WIN32_FIND_DATA FindFileData;
|
||||
dynConcatSz(e, param, "\\*", DYN_LGNONE); /* sinon ko... */
|
||||
if((hFind = FindFirstFile(param->mPtr, &FindFileData)) != INVALID_HANDLE_VALUE)
|
||||
dynConcatSz(e, param1, "\\*", DYN_LGNONE); /* sinon ko... */
|
||||
if((hFind = FindFirstFile(param1->mPtr, &FindFileData)) != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
dynSetLen(e, param, 0); // idem raz
|
||||
dynSetLen(e, param1, 0); // idem raz
|
||||
for(int cr = -1;cr != 0;)
|
||||
{
|
||||
if(strcmp(FindFileData.cFileName,".") != 0 && strcmp(FindFileData.cFileName,"..") != 0)
|
||||
{
|
||||
if(param->mLg > 0)
|
||||
dynConcatSz(e, param, sFM, 1);
|
||||
dynConcatSz(e, param, FindFileData.cFileName, DYN_LGNONE);
|
||||
if(param1->mLg > 0)
|
||||
dynConcatSz(e, param1, sFM, 1);
|
||||
dynConcatSz(e, param1, FindFileData.cFileName, DYN_LGNONE);
|
||||
}
|
||||
cr = FindNextFile(hFind, &FindFileData);
|
||||
}
|
||||
|
||||
@@ -199,7 +199,8 @@ 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
|
||||
if(lire_regles_lex(&e, ®les, "wlex") != DYN_OK)
|
||||
{
|
||||
dynLet(&e, f, s->mPtr, s->mLg);
|
||||
dynFree(&e, ®les);
|
||||
@@ -316,11 +317,21 @@ static void formatage(Dynamic * s, Dynamic * f, int type)
|
||||
// si pos_comment > -1 traiter le commentaire en fin de ligne, position multiple de 10 (par exemple), >= position actuelle
|
||||
// + formatage debut de ligne
|
||||
if(pos_comment == -1)
|
||||
dynSubstr(&e, &trav, &lig, pos - 1, (long)trav.mPtr - pos, 1, DYN_NONE, 10, DYN_NONE);
|
||||
{
|
||||
#ifdef WINLIB
|
||||
dynSubstr(&e, &trav, &lig, pos - 1, ((intptr_t)(trav.mPtr)) - pos, 1, DYN_NONE, 10, DYN_NONE);
|
||||
#else
|
||||
dynSubstr(&e, &trav, &lig, pos - 1, (long)(trav.mPtr - pos), 1, DYN_NONE, 10, DYN_NONE);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
dynSubstr(&e, &trav, &lig, pos - 1, pos_comment - pos, 1, DYN_NONE, 10, DYN_NONE);
|
||||
dynSubstr(&e, &trav, &tmp, pos_comment - 1, (long)trav.mPtr - pos_comment, 1, DYN_NONE, 10, DYN_NONE);
|
||||
#ifdef WINLIB
|
||||
dynSubstr(&e, &trav, &tmp, pos_comment - 1, ((intptr_t)(trav.mPtr)) - pos_comment, 1, DYN_NONE, 10, DYN_NONE);
|
||||
#else
|
||||
dynSubstr(&e, &trav, &tmp, pos_comment - 1, (long)(trav.mPtr - pos_comment), 1, DYN_NONE, 10, DYN_NONE);
|
||||
#endif
|
||||
}
|
||||
//
|
||||
if(flag_trt == 1)
|
||||
@@ -382,7 +393,7 @@ int main(int argc, char * argv[])
|
||||
type = 1; // par defaut formatage du source w
|
||||
else if(argc != 3)
|
||||
{
|
||||
printf("Usage: wlf [-w|-wa] <source>\n");
|
||||
printf("Usage: lwf [-w|-wa] <source>\n");
|
||||
exit(-1);
|
||||
}
|
||||
else
|
||||
@@ -394,7 +405,7 @@ int main(int argc, char * argv[])
|
||||
type = 2; // formatage du pcode (fichier .wa) TODO
|
||||
else
|
||||
{
|
||||
printf("Usage: wlf [-w|-wa] <source>\n");
|
||||
printf("Usage: lwf [-w|-wa] <source>\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,6 +313,13 @@ long gen_c(Dynamic * resultat, Dynamic * elem1, Dynamic * elem2, Dynamic * elem3
|
||||
return OK;
|
||||
}
|
||||
|
||||
long gen_h(Dynamic * resultat, Dynamic * elem1, Dynamic * elem2, Dynamic * elem3)
|
||||
{
|
||||
dynErase(&e, resultat, "\r"); /* nettoyage au cas ou fichier Windows */
|
||||
dynChange(&e, resultat, "\n", "\\n", DYN_ALL);
|
||||
return OK;
|
||||
}
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
Dynamic fichier, valex, ligne, resultat, elem1, elem2, elem3, regles;
|
||||
@@ -321,7 +328,7 @@ int main(int argc, char * argv[])
|
||||
/* argument : fichier lex a convertir en format "interne" */
|
||||
if(argc != 2)
|
||||
{
|
||||
printf("Usage: genlex <fichier>\n");
|
||||
printf("Usage: wlex <fichier>\n");
|
||||
exit(-3);
|
||||
}
|
||||
/* */
|
||||
@@ -363,12 +370,17 @@ int main(int argc, char * argv[])
|
||||
//printf("valex %s\n", valex.mPtr);//
|
||||
}
|
||||
printf("Resultat (ret=%d):\n%s\n", ret, resultat.mPtr);
|
||||
dynFree(&e, ®les);
|
||||
//
|
||||
if(ret == 0)
|
||||
{
|
||||
dynLet(&e, &fichier, resultat.mPtr, resultat.mLg); // sauvegarde
|
||||
// generer le code C a copier/coller dans genw.c
|
||||
ret = gen_c(&resultat, &elem1, &elem2, &elem3);
|
||||
printf("\nCode C genere : \n%s\n", resultat.mPtr);
|
||||
//
|
||||
// generer le code C a copier/coller dans lex_files.h
|
||||
ret = gen_h(&fichier, &elem1, &elem2, &elem3);
|
||||
printf("\nCode H genere : \n%s\n", fichier.mPtr);
|
||||
}
|
||||
}
|
||||
dynFree(&e, &valex);
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
|
||||
#include "langage.h"
|
||||
|
||||
#ifndef WINLIB
|
||||
/* met a jour le minimum de <env> pour pouvoir utiliser <dynamic.h> sans erreur... */
|
||||
void init_env(env * e)
|
||||
{
|
||||
@@ -56,29 +55,27 @@ void init_env(env * e)
|
||||
e->sep_subfield = '\xFD'; // cVM
|
||||
}
|
||||
|
||||
/* 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
|
||||
_bin : contient les noms des progs pcode en cours, arborescence d'appel des library en VM att 1 + "position" (1-n) binaddr en VM att 2, prog principal puis chaque appel de libr,
|
||||
si plusieurs appel de la meme libr, le nom est repete ! le nom memorise est sans chemin ni extension (WBIN + .wp ajoute en auto); @BIN
|
||||
exemple : prog VM libA VM libA VM libB FM 1 VM 2 VM 2 VM 3
|
||||
_binaddr : contient les adresses debut et fin et compteur des sub/libr (pour eviter SIGSEGV lors dechargement library)
|
||||
_env : contient les variables d'environnement "WBIN" FM "WSRC" ; @ENV
|
||||
_prog : contient le nom du programme (apres begin dans le source), pas le nom du fichier
|
||||
__xxx : var subroutine point d'entree pour le module xxx (dlsym)
|
||||
a b c : variables globales
|
||||
classe1 : classes, hashtables contenant =>
|
||||
_class, ce qui permet de differencier une hashtable simple d'une classe
|
||||
t u v : membres de la classe
|
||||
objet1 : objet, instanciation d'une classe contenant =>
|
||||
_class (oid FM _class de la classe), pour se differencier d'une hashtable normale
|
||||
_oid : dernier n° d'objet traite (new,...) var @OID
|
||||
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;
|
||||
}
|
||||
|
||||
_local : cree lors d'un do, contient la hashtable des vars de la sub (peut elle meme contenir une var _local pour
|
||||
la sub appelee depuis la sub, etc.). Contenu de _local =>
|
||||
_stack : var memorisant ce qu'il faut pour revenir a l'appelant
|
||||
x y z : variables locales
|
||||
*/
|
||||
int modFnIs(env * e, const char * fn, int lg)
|
||||
{
|
||||
// modifier l'endroit ou e->fn est mis a jour : verif fn64[0 1 2] est bien remis a zero avant la maj
|
||||
ent64 f[3];
|
||||
f[0] = 0; f[1] = 0; f[2] = 0;
|
||||
if(lg < 1 || lg > 23)
|
||||
return FALSE;
|
||||
strncpy((char *)f, fn, lg);
|
||||
return (e->fn64[0] == f[0] && e->fn64[1] == f[1] && e->fn64[2] == f[2]);
|
||||
}
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* fonctions wrapper au cas ou on aurait besoin de ne plus utiliser certaines */
|
||||
@@ -98,7 +95,11 @@ void * memalloc(env * e, ent64 taille)
|
||||
}
|
||||
*(ent64 *)ptr = taille;
|
||||
//printf("P%p+\n", ptr);
|
||||
#ifdef UNIX
|
||||
return(ptr + sizeof(ent64));
|
||||
#else
|
||||
return((pointeur)ptr + sizeof(ent64));
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -112,7 +113,11 @@ void memfree(env * e, void * ptr)
|
||||
{
|
||||
if(ptr != NULL)
|
||||
{
|
||||
ptr -= sizeof(ent64);
|
||||
#ifdef UNIX
|
||||
ptr -= sizeof(ent64);
|
||||
#else
|
||||
(pointeur)ptr -= sizeof(ent64);
|
||||
#endif
|
||||
if(e != NULL)
|
||||
{
|
||||
e->mem_numb--;
|
||||
@@ -205,14 +210,12 @@ void hex2(char * ch, int lg, int nbpl)
|
||||
printf(" (%6d) %s\n", i, a);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// Windows...
|
||||
void init_env(env * e) {}
|
||||
void hex(pointeur ch, int lg) {}
|
||||
void hex2(char * ch, int lg, int nbpl) {}
|
||||
void memcopie(void * dst, void * src, long nb) {}
|
||||
void memfree(env * e, void * ptr) {}
|
||||
void * memalloc(env * e, ent64 taille) {}
|
||||
|
||||
#endif
|
||||
void hex3(const char * p, long lg)
|
||||
{
|
||||
static char hex[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
|
||||
// affiche en hexa la chaine sur une ligne
|
||||
printf("=> ");
|
||||
for(long i = 0; i < lg; i++)
|
||||
printf("%c%c ", hex[((unsigned char)p[i]) >> 4], hex[((unsigned char)p[i]) & 15]);
|
||||
printf("\n");
|
||||
}
|
||||
@@ -26,29 +26,8 @@
|
||||
|
||||
void init_env(env * e);
|
||||
|
||||
/* 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
|
||||
_bin : contient les noms des progs pcode en cours, arborescence d'appel des library en VM att 1 + "position" (1-n) binaddr en VM att 2, prog principal puis chaque appel de libr,
|
||||
si plusieurs appel de la meme libr, le nom est repete ! le nom memorise est sans chemin ni extension (WBIN + .wp ajoute en auto); @BIN
|
||||
exemple : prog VM libA VM libA VM libB FM 1 VM 2 VM 2 VM 3
|
||||
_binaddr : contient les adresses debut et fin et compteur des sub/libr (pour eviter SIGSEGV lors dechargement library)
|
||||
_env : contient les variables d'environnement "WBIN" FM "WSRC" ; @ENV
|
||||
_prog : contient le nom du programme (apres begin dans le source), pas le nom du fichier
|
||||
__xxx : var subroutine point d'entree pour le module xxx (dlsym)
|
||||
a b c : variables globales
|
||||
classe1 : classes, hashtables contenant =>
|
||||
_class, ce qui permet de differencier une hashtable simple d'une classe
|
||||
t u v : membres de la classe
|
||||
objet1 : objet, instanciation d'une classe contenant =>
|
||||
_class (oid FM _class de la classe), pour se differencier d'une hashtable normale
|
||||
_oid : dernier n° d'objet traite (new,...) var @OID
|
||||
|
||||
_local : cree lors d'un do, contient la hashtable des vars de la sub (peut elle meme contenir une var _local pour
|
||||
la sub appelee depuis la sub, etc.). Contenu de _local =>
|
||||
_stack : var memorisant ce qu'il faut pour revenir a l'appelant
|
||||
x y z : variables locales
|
||||
*/
|
||||
char * copy_nom(env * e, const char * s);
|
||||
int modFnIs(env * e, const char * fn, int lg);
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* fonctions wrapper au cas ou on aurait besoin de ne plus utiliser certaines */
|
||||
@@ -60,6 +39,7 @@ void memcopie(void * dst, void * src, long nb);
|
||||
|
||||
void hex(pointeur ch, int lg);
|
||||
void hex2(char * ch, int lg, int nbpl);
|
||||
void hex3(const char * p, long lg);
|
||||
|
||||
/* ************************************ */
|
||||
#endif
|
||||
@@ -333,7 +333,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
//
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
/* les 4 fonctions suivantes doivent toujours exister dans chaque module */
|
||||
if(strncmp(e->fn, "init", 4) == 0)
|
||||
if(modFnIs(e, "init", 4))
|
||||
{
|
||||
// alloc ptr sur zone memoire pour memoriser l'etat du module
|
||||
*etat = memalloc(e, sizeof(modEtat));
|
||||
@@ -346,7 +346,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
//*** code specifique ici
|
||||
}
|
||||
}
|
||||
else if(strncmp(e->fn, "end", 3) == 0)
|
||||
else if(modFnIs(e, "end", 3))
|
||||
{
|
||||
// liberation specifique au module avant arret process
|
||||
if(p_etat != NULL)
|
||||
@@ -355,7 +355,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
memfree(e, p_etat);
|
||||
}
|
||||
}
|
||||
else if(strncmp(e->fn, "vers", 4) == 0)
|
||||
else if(modFnIs(e, "vers", 4))
|
||||
{
|
||||
// renvoie la version du module/plugins
|
||||
if(param1->type == VAR_DYNAMIC)
|
||||
@@ -365,7 +365,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
else
|
||||
exc = EX_MODPARAM; // variable en parametre du mauvais type
|
||||
}
|
||||
else if(strncmp(e->fn, "error", 5) == 0)
|
||||
else if(modFnIs(e, "error", 5))
|
||||
{
|
||||
// renvoie la derniere erreur specifique au module
|
||||
if(p_etat == NULL)
|
||||
@@ -379,7 +379,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(strncmp(e->fn, "MD2", 3) == 0)
|
||||
else if(modFnIs(e, "MD2", 3))
|
||||
{
|
||||
p_etat->error = 0;
|
||||
// pour les vars en sortie, forcer le chgt de type si besoin ?
|
||||
@@ -393,7 +393,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "MD4", 3) == 0)
|
||||
else if(modFnIs(e, "MD4", 3))
|
||||
{
|
||||
p_etat->error = 0;
|
||||
// pour les vars en sortie, forcer le chgt de type si besoin ?
|
||||
|
||||
+52
-16
@@ -33,19 +33,42 @@
|
||||
static entry * calc_entry(char * val, var * varht)
|
||||
{
|
||||
/* fonctionne avec des noms de 24 octets max (val) */
|
||||
/* algo de D. B e r n s t e i n */
|
||||
ent64 hash = 5381;
|
||||
/* optimiser en travaillant sur 3 qword ou 6 dword mais
|
||||
pbm les petites chaines donneront des modules idem */
|
||||
/* ent64 * p = (ent64 *)val;
|
||||
hash += *p++;
|
||||
hash = hash + (hash << 5) + *p++;
|
||||
hash = hash + (hash << 5) + *p;*/
|
||||
for(int iCle = 0; iCle < 24; iCle++)
|
||||
if(val[iCle])
|
||||
hash = hash + (hash<<5) + val[iCle]; /* hash*33 */
|
||||
else
|
||||
break; // stop au premier \0
|
||||
ent64 hash;
|
||||
/* algo de D. B e r n s t e i n / M u r m u r h a s h 6 4 */
|
||||
/* autre algo */
|
||||
if(0) {
|
||||
ent64 * p = (ent64 *)val;
|
||||
ent64 k = *p++;
|
||||
ent64 m = 0xc6a4a7935bd1e995ull;
|
||||
hash = 5381 ^ (24 * m);
|
||||
//
|
||||
k *= m;
|
||||
k ^= k >> 47;
|
||||
k *= m;
|
||||
hash ^= k;
|
||||
hash *= m;
|
||||
k = *p++; /* */
|
||||
k *= m;
|
||||
k ^= k >> 47;
|
||||
k *= m;
|
||||
hash ^= k;
|
||||
hash *= m;
|
||||
k = *p; /* */
|
||||
k *= m;
|
||||
k ^= k >> 47;
|
||||
k *= m;
|
||||
hash ^= k;
|
||||
hash *= m;
|
||||
}
|
||||
/* */
|
||||
if(1) {
|
||||
hash = 5381;
|
||||
for(int iCle = 0; iCle < 24; iCle++)
|
||||
if(val[iCle])
|
||||
hash = hash + (hash<<5) + val[iCle]; /* hash*33 */
|
||||
else
|
||||
break; // stop au premier \0
|
||||
}
|
||||
return((entry *)(varht->ptr + (varht->separateur * (hash % varht->modulo))));
|
||||
}
|
||||
|
||||
@@ -100,7 +123,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 */
|
||||
@@ -153,6 +176,11 @@ void hashtable_do(env * e, int action, var * varht, char * nom, var ** v)
|
||||
}
|
||||
}
|
||||
|
||||
var * hashtable_lastitemwritten(var * varht)
|
||||
{
|
||||
return ((entry *)varht->ptr)->pvar;
|
||||
}
|
||||
|
||||
void hashtable_select(env * e, var * varht)
|
||||
{
|
||||
/* les 4 variables necessaires seront mises dans le groupe 0, premiere entree (celle servant au chainage) */
|
||||
@@ -266,7 +294,8 @@ void hashtable_printdebug(env * e, var * varht, int detail)
|
||||
entry * pchain; /* pointe sur la premiere du groupe, servant au chainage */
|
||||
entry * pchain_first; /* premier bloc */
|
||||
ent64 groupe; /* groupe en cours */
|
||||
ent64 occ, tot; /* taille occupee, totale */
|
||||
ent64 occ, tot, nb; /* taille occupee, totale, nb items */
|
||||
char * ptrClass = NULL;
|
||||
/* affiche le contenu d'une hashtable */
|
||||
if(varht == NULL)
|
||||
return;
|
||||
@@ -278,6 +307,7 @@ void hashtable_printdebug(env * e, var * varht, int detail)
|
||||
/* */
|
||||
occ = 0;
|
||||
tot = 0;
|
||||
nb = 0;
|
||||
pchain = (entry *)varht->ptr;
|
||||
for(groupe = 0; groupe < varht->modulo; groupe++)
|
||||
{
|
||||
@@ -311,7 +341,11 @@ 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);
|
||||
nb++;
|
||||
}
|
||||
pentry++;
|
||||
}
|
||||
@@ -320,7 +354,9 @@ void hashtable_printdebug(env * e, var * varht, int detail)
|
||||
} while ((pchain = (entry *)pchain->chainage_avant) != 0);
|
||||
pchain = (entry *)((ent64)pchain_first + varht->separateur);
|
||||
}
|
||||
printf("taille totale=%lld, occupee=%lld (taux %lld%%)\n", tot, occ, occ * 100 / tot);
|
||||
if(ptrClass)
|
||||
printf("_class : %s\n", ptrClass);
|
||||
printf("taille totale=%lld, occupee=%lld (taux %lld%%), nb item=%lld\n", tot, occ, occ * 100 / tot, nb);
|
||||
}
|
||||
|
||||
/* ********************************************** */
|
||||
@@ -29,6 +29,7 @@ int hashtable_next(env * e, var * varht, char * nom, var ** v);
|
||||
void hashtable_free_ovf(env *e, var * varht);
|
||||
void hashtable_clear(env *e, var * varht);
|
||||
long hashtable_count(env *e, var * varht);
|
||||
var * hashtable_lastitemwritten(var * varht);
|
||||
|
||||
void hashtable_printdebug(env * e, var * varht, int detail);
|
||||
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
|
||||
void instr_unassemble(env * e, pointeur debutBin, ent64 nolig)
|
||||
{
|
||||
char * l = libInstr + e->instr * 4;
|
||||
//
|
||||
if(e->fin - debutBin > 9999)
|
||||
printf("[%d:%08lld-%08lld-%08lld ex %08lld]", e->bin_indice, (ent64)(e->debut - debutBin), (ent64)(e->si - 1 - debutBin), (ent64)(e->fin - debutBin), (ent64)(e->si_except - debutBin));
|
||||
else
|
||||
printf("[%d:%04lld-%04lld-%04lld ex %04lld]", e->bin_indice, (ent64)(e->debut - debutBin), (ent64)(e->si - 1 - debutBin), (ent64)(e->fin - debutBin), (ent64)(e->si_except - debutBin));
|
||||
//
|
||||
printf(" line %06lld ex-ex %04lld > %c%c%c%c ", nolig, e->except_ex, *l, *(l+1), *(l+2), *(l+3));
|
||||
//
|
||||
ent64s d8;
|
||||
int d3;
|
||||
octet d1;
|
||||
pointeur p = e->si;
|
||||
//
|
||||
switch(e->instr)
|
||||
{
|
||||
/* 2 bytes w opcode (instr d1) */
|
||||
case IN_VERS:
|
||||
case IN_PART:
|
||||
case IN_PREC:
|
||||
d1 = lire8(p);
|
||||
printf("%d", d1);
|
||||
break;
|
||||
|
||||
/* special 2 bytes w opcode */
|
||||
case IN_COMP:
|
||||
d1 = lire8(p);
|
||||
if(d1 < CMP_EQ || d1 > CMP_NOT)
|
||||
printf("??? (%d)", d1);
|
||||
else
|
||||
{
|
||||
l = libComp + d1 * 3 - 3;
|
||||
printf("%c%c%c", *l, *(l+1), *(l+2));
|
||||
}
|
||||
break;
|
||||
case IN_PSHA:
|
||||
dynLet(e, &e->tmp_dynamic, VARSYS, DYN_LGNONE);
|
||||
d1 = lire8(p);
|
||||
d3 = dynLocateSz(e, &e->tmp_dynamic, Int32ToSz(d1, FALSE, 0), ',', 2, ';');
|
||||
if(d3 > 0)
|
||||
{
|
||||
d3 = dynExtractPos(e, &e->tmp_dynamic, 1, d3, ';', ',');
|
||||
if(d3 > 0)
|
||||
printf("%.*s", d3, &e->tmp_dynamic.mPtr[e->tmp_dynamic.mInternal]);
|
||||
}
|
||||
if(d3 <= 0)
|
||||
printf("?? (%d)\n", d1);
|
||||
break;
|
||||
|
||||
/* 2+lg bytes w opcode (instr lg valeur) */
|
||||
case IN_DECL:
|
||||
case IN_CALL:
|
||||
case IN_PARM:
|
||||
case IN_MODL:
|
||||
case IN_PVAR:
|
||||
case IN_PVAH:
|
||||
case IN_DSET:
|
||||
case IN_DSTO:
|
||||
case IN_VLET:
|
||||
case IN_DCAT:
|
||||
case IN_NLET:
|
||||
case IN_INCL:
|
||||
case IN_PNAM:
|
||||
case IN_CLIB:
|
||||
case IN_PVAI:
|
||||
case IN_CPSH:
|
||||
case IN_PHDE:
|
||||
case IN_PIDE:
|
||||
case IN_PHDH:
|
||||
case IN_PIDH:
|
||||
case IN_PHDO:
|
||||
case IN_PIDO:
|
||||
case IN_DEXH:
|
||||
case IN_DEXI:
|
||||
case IN_DESH:
|
||||
case IN_DESI:
|
||||
case IN_DEZH:
|
||||
case IN_DEZI:
|
||||
d1 = *p++;
|
||||
if(d1 > 0)
|
||||
for( ;d1;d1--)
|
||||
printf("%c", *p++);
|
||||
else
|
||||
printf("_"); // marque une longueur à 0
|
||||
break;
|
||||
|
||||
/* 3+lg bytes w opcode (instr lg valeur) */
|
||||
case IN_DCMP:
|
||||
d1 = lire8(p++);
|
||||
if(d1 < CMP_EQ || d1 > CMP_NOT)
|
||||
printf("??? (%d) ", d1);
|
||||
else
|
||||
{
|
||||
l = libComp + d1 * 3 - 3;
|
||||
printf("%c%c%c ", *l, *(l+1), *(l+2));
|
||||
}
|
||||
d1 = *p++;
|
||||
if(d1 > 0)
|
||||
for( ;d1;d1--)
|
||||
printf("%c", *p++);
|
||||
else
|
||||
printf("_"); // marque une longueur à 0
|
||||
break;
|
||||
|
||||
/* 5+lg bytes w opcode (instr lg valeur) */
|
||||
case IN_SUBR:
|
||||
d1 = *p++;
|
||||
if(d1 > 0)
|
||||
for( ;d1;d1--)
|
||||
printf("%c", *p++);
|
||||
else
|
||||
printf("_"); // marque une longueur à 0
|
||||
d3 = lire24(p) + (e->si - 1 - debutBin);
|
||||
printf(" %d", d3);
|
||||
break;
|
||||
case IN_PHDS:
|
||||
case IN_PIDS:
|
||||
d1 = *p++;
|
||||
if(d1 > 0)
|
||||
for( ;d1;d1--)
|
||||
printf("%c", *p++);
|
||||
else
|
||||
printf("_"); // marque une longueur à 0
|
||||
d3 = lire24(p);
|
||||
printf(" %d", d3);
|
||||
break;
|
||||
|
||||
/* 4 bytes w opcode (instr d3) */
|
||||
case IN_JUMP:
|
||||
case IN_JMPF:
|
||||
case IN_JMPT:
|
||||
d3 = lire24(e->si) + (e->debut - debutBin);
|
||||
printf("%d", d3);
|
||||
break;
|
||||
case IN_BEXC:
|
||||
d3 = lire24(e->si) + (e->si - 1 - debutBin);
|
||||
printf("%d", d3);
|
||||
break;
|
||||
case IN_SRCL:
|
||||
case IN_THRW:
|
||||
d3 = lire24(e->si);
|
||||
printf("%d", d3);
|
||||
break;
|
||||
|
||||
/* 9 bytes w opcode */
|
||||
case IN_PSHC:
|
||||
d8 = lire64(p);
|
||||
printf("%lld\n", d8);
|
||||
break;
|
||||
|
||||
/* 3+lg1+lg2 bytes w opcode */
|
||||
case IN_CLAS:
|
||||
d1 = *p++;
|
||||
if(d1 > 0)
|
||||
for( ;d1;d1--)
|
||||
printf("%c", *p++);
|
||||
else
|
||||
printf("_"); // marque une longueur à 0
|
||||
printf(":");
|
||||
d1 = *p++;
|
||||
if(d1 > 0)
|
||||
for( ;d1;d1--)
|
||||
printf("%c", *p++);
|
||||
else
|
||||
printf("_"); // marque une longueur à 0
|
||||
break;
|
||||
|
||||
/* 4+d3 bytes w opcode */
|
||||
case IN_SDBG:
|
||||
d3 = *p++;
|
||||
if(d3 > 0)
|
||||
for( ;d3;d3--)
|
||||
printf("%c", *p++);
|
||||
else
|
||||
printf("_"); // marque une longueur à 0
|
||||
break;
|
||||
|
||||
/* one byte w opcode (and unknown opcode...) */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
@@ -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" "SDBG" "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"
|
||||
@@ -62,6 +62,7 @@ char libInstr[256 * 4] ={"VERS" "JUMP" "DECL" "SRCL" "BEXC" "EXCE" "CATC" "THRW"
|
||||
"xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" /* 200-249 */
|
||||
"xxxx" "LIBR" "ENDL" "TEST" "ENDS" "ENDP"};
|
||||
|
||||
char libComp[9 * 3] = {"EQ " "NE " "LT " "GT " "LE " "GE " "AND" "OR " "NOT"};
|
||||
|
||||
#define IS_VERS "\x00"
|
||||
#define IN_VERS 0
|
||||
@@ -291,8 +292,21 @@ 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_SDBG "\x73"
|
||||
#define IN_SDBG 115
|
||||
|
||||
#define IS_LIBR "\xFB"
|
||||
#define IN_LIBR 251
|
||||
|
||||
@@ -54,13 +54,6 @@ int jsonInit(env * e, modContextJson * ctx);
|
||||
int jsonEnd(env * e, modContextJson * ctx);
|
||||
int jsonDecode(env * e, modContextJson * ctx, var * param1, var * param2, var * param3);
|
||||
int jsonPrint(env * e, modContextJson * ctx, var * param1, var * param2, var * param3);
|
||||
|
||||
typedef struct {
|
||||
var * KeyList, * CurrentKey, * Name, * Value, * DecodeCle, * DecodeValue; // Dynamic
|
||||
var * KeyField, * KeyItem, * KeyCount, * ItemCount, * Id, * Parent, * IdKey, * ParentKey, * ValuePresent, * Begin; // Number
|
||||
// output: Name Value IdKey IdParent ValuePresent
|
||||
} treefetch; // contenu de la var hashtable passee en param
|
||||
|
||||
int jsonTreeFetch(env * e, modContextJson * ctx, var * param1, var * param2, var * param3);
|
||||
|
||||
/*
|
||||
|
||||
@@ -73,7 +73,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
//
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
/* les 4 fonctions suivantes doivent toujours exister dans chaque module */
|
||||
if(strncmp(e->fn, "init", 4) == 0)
|
||||
if(modFnIs(e, "init", 4))
|
||||
{
|
||||
// alloc ptr sur zone memoire pour memoriser l'etat du module
|
||||
*etat = memalloc(e, sizeof(modEtat));
|
||||
@@ -87,7 +87,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
exc = setError(p_etat, jsonInit(e, &p_etat->jsonCtx));
|
||||
}
|
||||
}
|
||||
else if(strncmp(e->fn, "end", 3) == 0)
|
||||
else if(modFnIs(e, "end", 3))
|
||||
{
|
||||
//*** code specifique ici
|
||||
exc = setError(p_etat, jsonEnd(e, &p_etat->jsonCtx));
|
||||
@@ -95,7 +95,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
if(p_etat != NULL)
|
||||
memfree(e, p_etat);
|
||||
}
|
||||
else if(strncmp(e->fn, "vers", 4) == 0)
|
||||
else if(modFnIs(e, "vers", 4))
|
||||
{
|
||||
if(param1 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
@@ -110,7 +110,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
exc = EX_MODPARAM; // variable en parametre du mauvais type
|
||||
}
|
||||
}
|
||||
else if(strncmp(e->fn, "error", 5) == 0)
|
||||
else if(modFnIs(e, "error", 5))
|
||||
{
|
||||
// renvoie la derniere erreur specifique au module
|
||||
if(p_etat == NULL)
|
||||
@@ -126,7 +126,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(strncmp(e->fn, "decode", 6) == 0)
|
||||
else if(modFnIs(e, "decode", 6))
|
||||
{
|
||||
if(param1 == NULL || param2 == NULL || param3 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
@@ -141,7 +141,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(strncmp(e->fn, "print", 5) == 0)
|
||||
else if(modFnIs(e, "print", 5))
|
||||
{
|
||||
if(param1 == NULL || param2 == NULL || param3 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
@@ -154,14 +154,14 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
exc = setError(p_etat, jsonPrint(e, &p_etat->jsonCtx, param1, param2, param3));
|
||||
}
|
||||
}
|
||||
else if(strncmp(e->fn, "treeFetch", 9) == 0)
|
||||
else if(modFnIs(e, "treeFetch", 9))
|
||||
{
|
||||
if(param1 == NULL)
|
||||
if(param1 == NULL || param2 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
/* param1 must be a hash table (input) */
|
||||
if(param1->type != VAR_HASHTABLE)
|
||||
if(param1->type != VAR_HASHTABLE || param2->type != VAR_NUMBER)
|
||||
exc = EX_MODPARAM; // bad type of parameter 1
|
||||
else
|
||||
exc = setError(p_etat, jsonTreeFetch(e, &p_etat->jsonCtx, param1, param2, param3));
|
||||
|
||||
+125
-43
@@ -484,52 +484,83 @@ static int MakePrintable(env * e, modContextJson * ctx, var * DecodeBrut, var *
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* NOT USED
|
||||
static void InitTreeFetch()
|
||||
{
|
||||
GetNextTreeFetch(NULL, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
*/
|
||||
typedef struct {
|
||||
var * KeyList, * CurrentKey, * Name, * Value, * DecodeCle, * DecodeValue; // Dynamic
|
||||
var * KeyField, * KeyItem, * KeyCount, * ItemCount, * Id, * Parent, * IdKey, * ParentKey, * ValuePresent; // Number
|
||||
// output: Name Value IdKey ParentKey ValuePresent
|
||||
} treefetch; // contenu de la var hashtable passee en param
|
||||
|
||||
/*
|
||||
static int GetNextTreeFetch(env * e, modContextJson * ctx, long * parentKey, long * idKey, Dynamic * name, Dynamic * value, int * valuePresent)
|
||||
static int GetNextTreeFetch(env * e, treefetch * tree)
|
||||
{
|
||||
static Dynamic KeyList, CurrentKey; // hash entree
|
||||
static long KeyField, KeyItem, KeyCount, ItemCount, id, parent; // hash entree
|
||||
char ArrayMark = '#';
|
||||
//
|
||||
if(parentKey == NULL && idKey == NULL && name == NULL && value == NULL && valuePresent == NULL)
|
||||
{
|
||||
// InitTreeFetch
|
||||
KeyList.DeleteAllContent();
|
||||
KeyField = 1; // current field in mDecodeCle
|
||||
KeyItem = 1; // current part of path of current field
|
||||
mDecodeCle.SetSubFieldDelimiter(cSVM);
|
||||
KeyCount = mDecodeCle.CountField();
|
||||
ItemCount = mDecodeCle.CountSubField(KeyField);
|
||||
id = 1;
|
||||
parent = 0;
|
||||
return true;
|
||||
}
|
||||
if(parentKey == nullptr || idKey == nullptr || name == nullptr || value == nullptr || valuePresent == nullptr)
|
||||
return false; // security
|
||||
//
|
||||
if(KeyField == 0)
|
||||
return false; // false = fini
|
||||
//
|
||||
if(tree->KeyField->num == 0)
|
||||
return FALSE; // false = fini
|
||||
// check here if empty json
|
||||
if(KeyCount == 0 && ItemCount == 0)
|
||||
if(tree->KeyCount->num == 0 && tree->ItemCount->num == 0)
|
||||
{
|
||||
// single value json
|
||||
name->SetAs("#");
|
||||
mDecodeValeur.ExtractField(1, *value, 1);
|
||||
*parentKey = parent;
|
||||
*idKey = id;
|
||||
*valuePresent = true;
|
||||
KeyField = 0;
|
||||
return true;
|
||||
dynLet(e, tree->Name, "#", 1);
|
||||
dynField(e, tree->DecodeValue, tree->Value, 1, DYN_NONE, cVM, cSVM, 1);
|
||||
tree->ParentKey->num = tree->Parent->num;
|
||||
tree->IdKey->num = tree->Id->num;
|
||||
tree->ValuePresent->num = NUM_UN;
|
||||
tree->KeyField->num = 0;
|
||||
return TRUE;
|
||||
}
|
||||
//
|
||||
for(long pos;;)
|
||||
{
|
||||
if(tree->KeyItem->num == tree->ItemCount->num)
|
||||
{
|
||||
// value found
|
||||
tree->ParentKey->num = tree->Parent->num;
|
||||
tree->IdKey->num = tree->Id->num;
|
||||
dynField(e, tree->DecodeCle, tree->Name, tree->KeyField->num, tree->KeyItem->num, cVM, cSVM, 1);
|
||||
dynReplace(e, tree->Name, cTM, ArrayMark);
|
||||
dynField(e, tree->DecodeValue, tree->Value, tree->KeyField->num, DYN_NONE, cVM, DYN_NONE, 1);
|
||||
tree->ValuePresent->num = TRUE; // means send a value
|
||||
// prepare next call
|
||||
if(tree->KeyField->num >= tree->KeyCount->num)
|
||||
tree->KeyField->num = 0;
|
||||
else
|
||||
{
|
||||
tree->Id->num++;
|
||||
tree->Parent->num = 0;
|
||||
tree->KeyField->num++;
|
||||
tree->KeyItem->num = 1;
|
||||
tree->ItemCount->num = dynDcount(e, tree->DecodeCle, cSVM, tree->KeyField->num, cVM);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
dynField(e, tree->DecodeCle, tree->CurrentKey, tree->KeyField->num, 1, cVM, cSVM, tree->KeyItem->num);
|
||||
pos = dynLocateSz(e, tree->KeyList, tree->CurrentKey->mPtr, cVM, 1, cFM);
|
||||
if(pos < 1)
|
||||
{
|
||||
// new path
|
||||
dynIns(e, tree->KeyList, 1, 1, tree->CurrentKey, cFM, cVM);
|
||||
dynInsNumber(e, tree->KeyList, 2, 1, tree->Id->num, cFM, cVM);
|
||||
// part of path found
|
||||
tree->ParentKey->num = tree->Parent->num;
|
||||
tree->IdKey->num = tree->Id->num;
|
||||
dynField(e, tree->DecodeCle, tree->Name, tree->KeyField->num, tree->KeyItem->num, cVM, cSVM, 1);
|
||||
dynReplace(e, tree->Name, cTM, ArrayMark);
|
||||
tree->ValuePresent->num = NUM_ZERO; // means no value here (part of path)
|
||||
// prepare next call
|
||||
tree->Parent->num = tree->Id->num++;
|
||||
tree->KeyItem->num++;
|
||||
//
|
||||
return TRUE;
|
||||
}
|
||||
// loop to next part of path
|
||||
dynExtractSubField(e, tree->KeyList, 2, pos, tree->Parent);
|
||||
tree->KeyItem->num++;
|
||||
}
|
||||
//
|
||||
return TRUE; //ok, but should never reach this point...
|
||||
}
|
||||
|
||||
/*
|
||||
for(long pos;;)
|
||||
{
|
||||
if(KeyItem == ItemCount)
|
||||
@@ -577,9 +608,7 @@ static int GetNextTreeFetch(env * e, modContextJson * ctx, long * parentKey, lon
|
||||
KeyList.ExtractSubField(2, pos, parent);
|
||||
KeyItem++;
|
||||
}
|
||||
//
|
||||
return true; //ok, but should never reach this point...
|
||||
}*/
|
||||
*/
|
||||
|
||||
/* =================== PUBLIC ========================== */
|
||||
int jsonInit(env * e, modContextJson * ctx)
|
||||
@@ -634,8 +663,61 @@ int jsonPrint(env * e, modContextJson * ctx, var * param1, var * param2, var * p
|
||||
int jsonTreeFetch(env * e, modContextJson * ctx, var * param1, var * param2, var * param3)
|
||||
{
|
||||
// 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);
|
||||
// KeyField, KeyItem, KeyCount, ItemCount, Id, Parent, IdKey, ParentKey, ValuePresent; // Number
|
||||
treefetch tree; // contexte specifique a chaque appel
|
||||
//
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "DecodeCle"), &tree.DecodeCle);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "DecodeValue"), &tree.DecodeValue);
|
||||
if(tree.DecodeCle == NULL || tree.DecodeValue == NULL)
|
||||
{
|
||||
param2->num = NUM_UN;
|
||||
return OK; // TODO erreur
|
||||
}
|
||||
//
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "KeyList"), &tree.KeyList);
|
||||
if(tree.KeyList == NULL)
|
||||
{
|
||||
// init vars
|
||||
var * v = &e->int_dynamic;
|
||||
dynSetLen(e, &e->int_dynamic, 0);
|
||||
hashtable_do(e, HASH_WRITE, param1, copy_nom(e, "KeyList"), &v);
|
||||
hashtable_do(e, HASH_WRITE, param1, copy_nom(e, "CurrentKey"), &v);
|
||||
hashtable_do(e, HASH_WRITE, param1, copy_nom(e, "Name"), &v);
|
||||
hashtable_do(e, HASH_WRITE, param1, copy_nom(e, "Value"), &v);
|
||||
v = &e->int_number;
|
||||
v->num = 1;
|
||||
hashtable_do(e, HASH_WRITE, param1, copy_nom(e, "KeyField"), &v);
|
||||
hashtable_do(e, HASH_WRITE, param1, copy_nom(e, "KeyItem"), &v);
|
||||
hashtable_do(e, HASH_WRITE, param1, copy_nom(e, "Id"), &v);
|
||||
v->num = 0;
|
||||
hashtable_do(e, HASH_WRITE, param1, copy_nom(e, "Parent"), &v);
|
||||
v->num = dynDcount(e, tree.DecodeCle, cVM, DYN_NONE, DYN_NONE);
|
||||
hashtable_do(e, HASH_WRITE, param1, copy_nom(e, "KeyCount"), &v);
|
||||
v->num = dynDcount(e, tree.DecodeCle, cSVM, 1, cVM);
|
||||
hashtable_do(e, HASH_WRITE, param1, copy_nom(e, "ItemCount"), &v);
|
||||
hashtable_do(e, HASH_WRITE, param1, copy_nom(e, "IdKey"), &v);
|
||||
hashtable_do(e, HASH_WRITE, param1, copy_nom(e, "ParentKey"), &v);
|
||||
hashtable_do(e, HASH_WRITE, param1, copy_nom(e, "ValuePresent"), &v);
|
||||
}
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "KeyList"), &tree.KeyList);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "CurrentKey"), &tree.CurrentKey);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "Name"), &tree.Name);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "Value"), &tree.Value);
|
||||
//
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "KeyField"), &tree.KeyField);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "KeyItem"), &tree.KeyItem);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "KeyCount"), &tree.KeyCount);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "ItemCount"), &tree.ItemCount);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "Id"), &tree.Id);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "Parent"), &tree.Parent);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "IdKey"), &tree.IdKey);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "ParentKey"), &tree.ParentKey);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "ValuePresent"), &tree.ValuePresent);
|
||||
/* */
|
||||
//hashtable_printdebug(e, param1, 1);
|
||||
if(GetNextTreeFetch(e, &tree)) // TRUE = pas fini
|
||||
param2->num = NUM_ZERO; // var <fin>
|
||||
else
|
||||
param2->num = NUM_UN;
|
||||
return OK;
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024 lanisys.fr
|
||||
\/ \/ Copyright 2024,2025 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
@@ -44,7 +44,11 @@ typedef int ent32s;
|
||||
typedef long long ent64s;
|
||||
typedef unsigned short ent16;
|
||||
|
||||
#ifndef UNIX
|
||||
typedef ent64s ent128s; // sous windows, pas de __int128 : TODO a changer pour des calculs corrects
|
||||
#else
|
||||
typedef __int128 ent128s; // temporaire pour les calculs intermediaires (multiplication)
|
||||
#endif
|
||||
|
||||
#define NUM_MIN -999999999999999999ll
|
||||
#define NUM_MAX 999999999999999999ll
|
||||
@@ -87,13 +91,16 @@ typedef ent64s number; /* 8 octets signes, virgule fixe */
|
||||
#define CP_8859_15 28605
|
||||
#define CP_UTF8 65001
|
||||
|
||||
#define CP_DEFAULT CP_WIN1252 // UTF8 ??
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
ent64 type; /* type defini ci-dessus */
|
||||
//union {
|
||||
ent16 type; /* type defini ci-dessus (au lieu de ent64) */
|
||||
//pointeur local; /* pour memo _stack */
|
||||
ent16 typv[4]; /* permet de gerer des options par type : code page pour dynamic, unite/devise pour number, fuseau si number/date etc. */
|
||||
ent16 codePage; /* pour dynamic */
|
||||
ent16 typv[2]; /* permet de gerer des options par type : unite/devise pour number, fuseau si number/date etc. */
|
||||
/* typv[0] = type; typv[1] = code page/unite/fuseau typv[2] typv[3] usage futur (langue, pays) */
|
||||
};
|
||||
//};
|
||||
union {
|
||||
number num; /* si type = 1 VAR_NUMBER */
|
||||
pointeur ptr; /* si type = 2 a 8 : pointeur vers les donnees variables / variable si "PARAM" / si->debut si SUBROUTINE / ptr si module */
|
||||
@@ -156,8 +163,7 @@ typedef struct {
|
||||
v->ptr v->ptr v->misc
|
||||
*/
|
||||
|
||||
#define BUF_LGBLOC 8192 /* multiple de 32 sinon pile d'elements 8 et 16 octets KO */
|
||||
#define BUF_LGWRITE_MAX 4000 /* doit etre au maxi BUF_LGBLOC - 3 */
|
||||
#define BUF_LGMINBLOC 16384 /* multiple de 32 sinon pile d'elements 8 et 16 octets KO, lgmax message = lg buffer / 32 (512 octets ici) */
|
||||
|
||||
typedef struct {
|
||||
/* buffer servant de stack pour number et string */
|
||||
@@ -224,7 +230,7 @@ typedef struct {
|
||||
#define EX_NOCLASS 23 /* la classe n'a pas ete trouvee dans la hash globale */
|
||||
#define EX_CMDLINE_ARG 24 /* erreur dans les parametres de la ligne de commande */
|
||||
#define EX_PCODE 25 /* pcode "binaire" incorrect : ne commence pas par PROG, library ne commence pas par LIBR, etc.*/
|
||||
#define EX_NOENVVAR 26 /* WBIN et/ou WSRC non defini en var d'envvironnement ou non passe en parametre de la ligne de commande */
|
||||
#define EX_NOENVVAR 26 /* WBIN et/ou WSRC non defini en var d'environnement ou non passe en parametre de la ligne de commande */
|
||||
#define EX_EXCEPTNUM 27 /* code except ne tient pas sur 8 bits : ko pour retour shell */
|
||||
#define EX_BINVAR_KO 28 /* variable _bin de g non trouvee */
|
||||
#define EX_ENVVAR_KO 29 /* variable _env de g non trouvee */
|
||||
@@ -236,6 +242,7 @@ typedef struct {
|
||||
#define EX_FORMAT_KO 35 /* erreur de parametre (type format ou longueur incorrects) */
|
||||
#define EX_INSERT_KO 36 /* erreur de parametre ou memoire dans insert() */
|
||||
#define EX_REMOVE_KO 37 /* erreur de parametre ou memoire dans remove() */
|
||||
#define EXNB 37 /* MEMO !!!! */
|
||||
|
||||
typedef struct {
|
||||
/* environnement global */
|
||||
@@ -252,6 +259,7 @@ typedef struct {
|
||||
//
|
||||
//var tblptr; /* contient les pointeurs sur les vars de type SUB/PARAM/OBJET, pour les rendre VAR_NULL si le ptr est libere */
|
||||
//
|
||||
var tmp_dynamic; /* comme son nom l'indique... doit etre utilise localement et sur une portee tres courte ; pas d'utilisation inter instruction */
|
||||
var int_number; /* variable number interne servant aux conversions */
|
||||
var int_dynamic; /* variable dynamic interne servant aux conversions */
|
||||
var int_hash; /* variable interne servant a la creation de classe/objet */
|
||||
@@ -262,6 +270,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 +285,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 */
|
||||
@@ -287,20 +297,22 @@ typedef struct {
|
||||
char sep_field, sep_subfield; /* pour dynamic */
|
||||
/* */
|
||||
int endianess; /* pour detection automatique de l'endianess de la plateforme d'execution */
|
||||
/* */
|
||||
int bin_indice; /* position dans _bin du binaire en cours d'exec ( _bin<2, bin_indice> ) */
|
||||
/* */
|
||||
pointeur debut,fin; /* position en memoire de la fonction, fin est toujours l'instruction END ou ENDS */
|
||||
pointeur si; /* position dans le source, inclus entre debut et fin inclus */
|
||||
pointeur si_except; /* position dans le source du code traitant les exceptions (apres instruction EXC) */
|
||||
pointeur debutProg, finProg; // debut:fin du prog principal (= toute la zone memoire du prog)
|
||||
/* */
|
||||
pointeur binaddr; /* permet de lire les adresses binaires en mode Trace */
|
||||
/* */
|
||||
ent64 mem_numb; /* nombre de blocs memoire alloues */
|
||||
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 +340,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,@exceptstr,@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,18,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"
|
||||
|
||||
|
||||
@@ -47,11 +47,12 @@ reste: (1,1,#00-#FF) ;11; 1,1,00-FF
|
||||
[] est remplace par () car cela revient au meme !
|
||||
|
||||
*/
|
||||
#include "lex_files.h"
|
||||
|
||||
long regles_lex(env * e, Dynamic * r)
|
||||
{
|
||||
dynLet(e, r, "", 0);
|
||||
dynConcatSz(e, r, "blanc,1,nomregle,2,debut,3,fin,4,occ,5,infini,6,commentaire,7,intervalle,8,hexa,9,car,10,reste,11\n", DYN_LGNONE);
|
||||
//printf("%s", r->mPtr);
|
||||
dynConcatSz(e, r, "1,-1,20:09\n", DYN_LGNONE);
|
||||
dynConcatSz(e, r, "1,1,61-7A;0,-1,30-39:61-7A;1,1,3A\n", DYN_LGNONE);
|
||||
dynConcatSz(e, r, "1,1,28\n", DYN_LGNONE);
|
||||
@@ -70,9 +71,35 @@ long lire_regles_lex(env * e, Dynamic * regles, char * fichier_lex)
|
||||
{
|
||||
long cr;
|
||||
if(fichier_lex != NULL)
|
||||
cr = dynRead(e, regles, fichier_lex); // lire les regles depuis le fichier sur disque
|
||||
{
|
||||
/* selon fichier_lex, lire directement depuis le source */
|
||||
if(strncmp(fichier_lex, "debuglex", 8) == 0)
|
||||
{
|
||||
if(*file_debuglex == 0)
|
||||
#ifdef WINLIB
|
||||
cr = dynRead(e, regles, "C:\\Users\\Poupougne42\\source\\repos\\win_w_src\\lex\\debuglex"); // lire les regles depuis le fichier sur disque
|
||||
#else
|
||||
cr = dynRead(e, regles, "/etc/wlanguage/debuglex"); // lire les regles depuis le fichier sur disque
|
||||
#endif
|
||||
else
|
||||
cr = dynLet(e, regles, file_debuglex, DYN_LGNONE);
|
||||
}
|
||||
else if(strncmp(fichier_lex, "wlex", 4) == 0)
|
||||
{
|
||||
if(*file_wlex == 0)
|
||||
#ifdef WINLIB
|
||||
cr = dynRead(e, regles, "C:\\Users\\Poupougne42\\source\\repos\\win_w_src\\lex\\wlex"); // lire les regles depuis le fichier sur disque
|
||||
#else
|
||||
cr = dynRead(e, regles, "/etc/wlanguage/wlex"); // lire les regles depuis le fichier sur disque
|
||||
#endif
|
||||
else
|
||||
cr = dynLet(e, regles, file_wlex, DYN_LGNONE);
|
||||
}
|
||||
else
|
||||
cr = dynRead(e, regles, fichier_lex); // lire les regles depuis le fichier sur disque
|
||||
}
|
||||
else
|
||||
cr = regles_lex(e, regles); // par defaut, charger les regles lex des fichiers "lex"
|
||||
cr = regles_lex(e, regles); // par defaut, charger les regles lex des fichiers "lex" (?!)
|
||||
//
|
||||
if(cr == DYN_OK)
|
||||
{
|
||||
@@ -334,7 +361,7 @@ void lex(env * e, Dynamic * regles, Dynamic * saisie, Dynamic * valex)
|
||||
dynFree(e, &motencours);
|
||||
dynFree(e, &trouvemot);
|
||||
}
|
||||
/* source Universe (OK) :
|
||||
/* source OK :
|
||||
* LEX.REGLE = regles Lex, valeurs ET separees par "," ; liste de cars en OU pour chaque partie ET
|
||||
LEX.REGLE = ""
|
||||
* 1 entete
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
; fichier de description du lex des fichiers lex
|
||||
|
||||
blanc: (1,*,#20#09) ;1; 1,-1,20:09
|
||||
nomregle: (1,1,a-z) (0,*,0-9a-z) (1,1,#3A) ;2; 1,1,61-7A;0,-1,30-39:61-7A;1,1,3A
|
||||
debut: (1,1,#28) ;3; 1,1,28
|
||||
fin: (1,1,#29) ;4; 1,1,29
|
||||
occ: (1,9,0-9) (1,1,#2C) ;5; 1,9,30-39;1,1,2C
|
||||
infini: (1,1,#2A) (1,1,#2C) ;6; 1,1,2A;1,1,2C
|
||||
commentaire: (1,1,#3B) (0,*,#20-#7E) ;7; 1,1,3B;0,-1,20-7E
|
||||
intervalle: (1,1,#2D) ;8; 1,1,2D
|
||||
hexa: (1,1,#23) (2,2,0-9A-F) ;9; 1,1,23;2,2,30-39:41-46
|
||||
car: (1,1,#21-#7E) ;10; 1,1,21-7E
|
||||
reste: (1,1,#00-#FF) ;11; 1,1,00-FF
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
//static char file_debuglex[] = "";
|
||||
static char file_debuglex[] = "blanc,1,commande,2,aide,3,nombre,4,ajouter,5,supprimer,6,ident,7,reste,8\n1,-1,20:09:0A:0D\n1,2,61-7A:41-5A\n1,1,3F\n1,9,30-39\n1,1,2B\n1,1,2D\n1,1,3A;1,1,61-7A:41-5A:5F;0,23,61-7A:41-5A:30-39\n1,1,00-FF";
|
||||
|
||||
//static char file_wlex[] = "";
|
||||
static char file_wlex[] = "blank,1,comment,2,begin,3,background,4,library,5,end,6,except,7,throw,8,catch,9,include,10,sub,11,endsub,12,if,13,then,14,else,15,elseif,16,endif,17,do,18,call,19,invoke,20,return,21,returnon,22,loop,23,endloop,24,foreach,25,in,26,like,27,endfor,28,break,29,breakon,30,continue,31,continueon,32,nop,33,part,34,echonl,35,echo,36,input,37,declare,38,let,39,delet,40,new,41,class,42,this,43,parent,44,free,45,precision,46,setsep,47,int,48,frac,49,abs,50,neg,51,round,52,type,53,len,54,count,55,dcount,56,field,57,index,58,search,59,change,60,format,61,insert,62,remove,63,tonum,64,tostring,65,equal,66,diff,67,gt,68,lt,69,gte,70,lte,71,and,72,or,73,not,74,beginpar,75,endpar,76,beginh,77,endh,78,begins,79,ends,80,indirect,81,typeof,82,stringdq,83,stringq,84,ident,85,varsys,86,numberdec,87,numberint,88,minus,89,plus,90,multiply,91,divide,92,divident,93,modulo,94,concat,95,listesep,96,identsep,97,modsep,98,other,99\n1,-1,20:09\n1,1,3B;0,-1,00-FF\n1,1,62;1,1,65;1,1,67;1,1,69;1,1,6E\n1,1,62;1,1,61;1,1,63;1,1,6B;1,1,67;1,1,72;1,1,6F;1,1,75;1,1,6E;1,1,64\n1,1,6C;1,1,69;1,1,62;1,1,72;1,1,61;1,1,72;1,1,79\n1,1,65;1,1,6E;1,1,64\n1,1,65;1,1,78;1,1,63;1,1,65;1,1,70;1,1,74\n1,1,74;1,1,68;1,1,72;1,1,6F;1,1,77\n1,1,63;1,1,61;1,1,74;1,1,63;1,1,68\n1,1,69;1,1,6E;1,1,63;1,1,6C;1,1,75;1,1,64;1,1,65\n1,1,73;1,1,75;1,1,62\n1,1,65;1,1,6E;1,1,64;1,1,73;1,1,75;1,1,62\n1,1,69;1,1,66\n1,1,74;1,1,68;1,1,65;1,1,6E\n1,1,65;1,1,6C;1,1,73;1,1,65\n1,1,65;1,1,6C;1,1,73;1,1,65;1,1,69;1,1,66\n1,1,65;1,1,6E;1,1,64;1,1,69;1,1,66\n1,1,64;1,1,6F\n1,1,63;1,1,61;1,1,6C;1,1,6C\n1,1,69;1,1,6E;1,1,76;1,1,6F;1,1,6B;1,1,65\n1,1,72;1,1,65;1,1,74;1,1,75;1,1,72;1,1,6E\n1,1,72;1,1,65;1,1,74;1,1,75;1,1,72;1,1,6E;1,1,6F;1,1,6E\n1,1,6C;1,1,6F;1,1,6F;1,1,70\n1,1,65;1,1,6E;1,1,64;1,1,6C;1,1,6F;1,1,6F;1,1,70\n1,1,66;1,1,6F;1,1,72;1,1,65;1,1,61;1,1,63;1,1,68\n1,1,69;1,1,6E\n1,1,6C;1,1,69;1,1,6B;1,1,65\n1,1,65;1,1,6E;1,1,64;1,1,66;1,1,6F;1,1,72\n1,1,62;1,1,72;1,1,65;1,1,61;1,1,6B\n1,1,62;1,1,72;1,1,65;1,1,61;1,1,6B;1,1,6F;1,1,6E\n1,1,63;1,1,6F;1,1,6E;1,1,74;1,1,69;1,1,6E;1,1,75;1,1,65\n1,1,63;1,1,6F;1,1,6E;1,1,74;1,1,69;1,1,6E;1,1,75;1,1,65;1,1,6F;1,1,6E\n1,1,6E;1,1,6F;1,1,70\n1,1,70;1,1,61;1,1,72;1,1,74\n1,1,65;1,1,63;1,1,68;1,1,6F;1,1,6E;1,1,6C\n1,1,65;1,1,63;1,1,68;1,1,6F\n1,1,69;1,1,6E;1,1,70;1,1,75;1,1,74\n1,1,64;1,1,65;1,1,63;1,1,6C;1,1,61;1,1,72;1,1,65\n1,1,6C;1,1,65;1,1,74\n1,1,64;1,1,65;1,1,6C;1,1,65;1,1,74\n1,1,6E;1,1,65;1,1,77\n1,1,63;1,1,6C;1,1,61;1,1,73;1,1,73\n1,1,74;1,1,68;1,1,69;1,1,73\n1,1,70;1,1,61;1,1,72;1,1,65;1,1,6E;1,1,74\n1,1,66;1,1,72;1,1,65;1,1,65\n1,1,70;1,1,72;1,1,65;1,1,63;1,1,69;1,1,73;1,1,69;1,1,6F;1,1,6E\n1,1,73;1,1,65;1,1,74;1,1,73;1,1,65;1,1,70\n1,1,69;1,1,6E;1,1,74\n1,1,66;1,1,72;1,1,61;1,1,63\n1,1,61;1,1,62;1,1,73\n1,1,6E;1,1,65;1,1,67\n1,1,72;1,1,6F;1,1,75;1,1,6E;1,1,64\n1,1,74;1,1,79;1,1,70;1,1,65\n1,1,6C;1,1,65;1,1,6E\n1,1,63;1,1,6F;1,1,75;1,1,6E;1,1,74\n1,1,64;1,1,63;1,1,6F;1,1,75;1,1,6E;1,1,74\n1,1,66;1,1,69;1,1,65;1,1,6C;1,1,64\n1,1,69;1,1,6E;1,1,64;1,1,65;1,1,78\n1,1,73;1,1,65;1,1,61;1,1,72;1,1,63;1,1,68\n1,1,63;1,1,68;1,1,61;1,1,6E;1,1,67;1,1,65\n1,1,66;1,1,6F;1,1,72;1,1,6D;1,1,61;1,1,74\n1,1,69;1,1,6E;1,1,73;1,1,65;1,1,72;1,1,74\n1,1,72;1,1,65;1,1,6D;1,1,6F;1,1,76;1,1,65\n1,1,74;1,1,6F;1,1,6E;1,1,75;1,1,6D\n1,1,74;1,1,6F;1,1,73;1,1,74;1,1,72;1,1,69;1,1,6E;1,1,67\n1,1,3D\n1,1,23\n1,1,3E\n1,1,3C\n1,1,3E;1,1,3D\n1,1,3C;1,1,3D\n1,1,61;1,1,6E;1,1,64\n1,1,6F;1,1,72\n1,1,6E;1,1,6F;1,1,74\n1,1,28\n1,1,29\n1,1,7B\n1,1,7D\n1,1,5B\n1,1,5D\n1,1,21\n1,1,3F\n1,1,22;0,765,20-21:23-EF;1,1,22\n1,1,27;0,765,20-26:28-EF;1,1,27\n1,1,61-7A:41-5A;0,23,61-7A:41-5A:30-39\n1,1,40;1,-1,61-7A\n1,13,30-39;1,1,2E;0,5,30-39\n1,13,30-39\n1,1,2D\n1,1,2B\n1,1,2A\n1,1,2F\n1,1,5C\n1,1,25\n1,1,3A\n1,1,2C\n1,1,2E\n1,1,26\n1,1,00-FF";
|
||||
@@ -0,0 +1,30 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "langage.h"
|
||||
#include "dynamic.h"
|
||||
|
||||
/*
|
||||
tester avec alloc (size 20) !! TODO
|
||||
*/
|
||||
|
||||
#define MAX_ENTRY 3838 // 4096 - 258
|
||||
#define SIZE_ENTRY (124 + sizeof(int)) // TODO : voir la meilleure taille 91 sur fichier binaire de 130 Ko... !!! tester avec 20...
|
||||
|
||||
typedef struct {
|
||||
octet Dict[MAX_ENTRY * SIZE_ENTRY]; // dictionnaire en cours
|
||||
int posDict; // prochaine entree a ecrire dans le dictionnaire
|
||||
pointeur Alloc[MAX_ENTRY]; // pointeurs des blocs alloues en dehors des entry (car trop grand)
|
||||
int allocEntry; // nb blocs alloue en dehors des entry (car trop grand)
|
||||
var code; // de type dynamic, contient le code/decode en cours
|
||||
var w; // de type dynamic, contient la chaine en cours d'analyse
|
||||
long prec; // dernier code trouve dans le dict
|
||||
long bits; // nb de bits en cours (codage/decodage)
|
||||
long reste; // bits restant a traiter lors du decodage (nb bits dans pe->code.mInternal)
|
||||
} modContextLzw;
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
void initLzw(env * e, modContextLzw * cl);
|
||||
void freeLzw(env * e, modContextLzw * cl);
|
||||
long setLzw(env * e, var * clair, modContextLzw * cl, int type);
|
||||
long getLzw(env * e, var * comp, modContextLzw * cl, int type);
|
||||
@@ -2,7 +2,7 @@
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024 lanisys.fr
|
||||
\/ \/ Copyright 2024,2025 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
@@ -28,16 +28,20 @@
|
||||
#include "langage.h"
|
||||
#include "dynamic.h"
|
||||
|
||||
#include "lzw.h"
|
||||
|
||||
typedef struct {
|
||||
int error; // dernier code erreur specifique au module
|
||||
//*** a completer selon le besoin du module
|
||||
var dict; // de type dynamic, dictionnaire en cours
|
||||
modContextLzw cl;
|
||||
|
||||
/*var dict; // de type dynamic, dictionnaire en cours
|
||||
var code; // de type dynamic, contient le code/decode en cours
|
||||
var w; // de type dynamic, contient la chaine en cours d'analyse
|
||||
long prec; // dernier code trouve dans le dict
|
||||
long posDict;// position en cours du code dans dict + 256 (dernier)
|
||||
long bits; // nb de bits en cours (codage/decodage)
|
||||
long reste; // bits restant a traiter lors du decodage (nb bits dans pe->code.mInternal)
|
||||
long reste; // bits restant a traiter lors du decodage (nb bits dans pe->code.mInternal) */
|
||||
} modEtat;
|
||||
|
||||
/* mettre ici les codes d'erreurs specifiques au module */
|
||||
@@ -51,8 +55,9 @@ static int setError(modEtat * p, int err)
|
||||
return err == OK ? OK : EX_MODERR;
|
||||
}
|
||||
|
||||
long set(env * e, var * clair, modEtat * pe, int type);
|
||||
long get(env * e, var * code, modEtat * pe, int type);
|
||||
//long set(env * e, var * clair, modEtat * pe, int type);
|
||||
//long get(env * e, var * code, modEtat * pe, int type);
|
||||
//long setV2(env * e, var * clair, modEtat * pe, int type);
|
||||
|
||||
#ifndef UNIX
|
||||
/* Sous Windows, export de la fonction de base au sein d'une DLL : 1 module = 1 DLL */
|
||||
@@ -76,7 +81,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
//
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
/* les 4 fonctions suivantes doivent toujours exister dans chaque module */
|
||||
if(strncmp(e->fn, "init", 4) == 0)
|
||||
if(modFnIs(e, "init", 4))
|
||||
{
|
||||
// alloc ptr sur zone memoire pour memoriser l'etat du module
|
||||
*etat = memalloc(e, sizeof(modEtat));
|
||||
@@ -87,24 +92,26 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
p_etat = (modEtat *)(*etat);
|
||||
p_etat->error = 0;
|
||||
//*** code specifique ici
|
||||
dynInit(e, &p_etat->dict, 4096);
|
||||
dynInit(e, &p_etat->code, 4096);
|
||||
dynInit(e, &p_etat->w, 256);
|
||||
initLzw(e, &p_etat->cl);
|
||||
//dynInit(e, &p_etat->dict, 4096);
|
||||
//dynInit(e, &p_etat->code, 4096);
|
||||
//dynInit(e, &p_etat->w, 256);
|
||||
}
|
||||
}
|
||||
else if(strncmp(e->fn, "end", 3) == 0)
|
||||
else if(modFnIs(e, "end", 3))
|
||||
{
|
||||
// liberation specifique au module avant arret process
|
||||
if(p_etat != NULL)
|
||||
{
|
||||
freeLzw(e, &p_etat->cl);
|
||||
//dynFree(e, &p_etat->dict);
|
||||
//dynFree(e, &p_etat->code);
|
||||
//dynFree(e, &p_etat->w);
|
||||
//*** FIN du code specifique ici
|
||||
memfree(e, p_etat);
|
||||
//*** code specifique ici
|
||||
dynFree(e, &p_etat->dict);
|
||||
dynFree(e, &p_etat->code);
|
||||
dynFree(e, &p_etat->w);
|
||||
}
|
||||
}
|
||||
else if(strncmp(e->fn, "vers", 4) == 0)
|
||||
else if(modFnIs(e, "vers", 4))
|
||||
{
|
||||
// renvoie la version du module/plugins
|
||||
if(param->type == VAR_DYNAMIC)
|
||||
@@ -114,7 +121,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
else
|
||||
exc = EX_MODPARAM; // variable en parametre du mauvais type
|
||||
}
|
||||
else if(strncmp(e->fn, "error", 5) == 0)
|
||||
else if(modFnIs(e, "error", 5))
|
||||
{
|
||||
// renvoie la derniere erreur specifique au module
|
||||
if(p_etat == NULL)
|
||||
@@ -128,7 +135,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(strncmp(e->fn, "set", 3) == 0)
|
||||
else if(modFnIs(e, "set", 3))
|
||||
{
|
||||
/* compression du clair de param, en une fois */
|
||||
/* sinon utiliser : setinit, setnext, setend */
|
||||
@@ -140,11 +147,11 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
if(param->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
exc = setError(p_etat, set(e, param, p_etat, 0)); /* 0 : en une fois */
|
||||
exc = setError(p_etat, setLzw(e, param, &p_etat->cl, 0)); /* 0 : en une fois */
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(strncmp(e->fn, "get", 3) == 0)
|
||||
else if(modFnIs(e, "get", 3))
|
||||
{
|
||||
/* decompression du code de param, en une fois */
|
||||
/* sinon utiliser getinit, getnext, getend */
|
||||
@@ -156,7 +163,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
if(param->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
exc = setError(p_etat, get(e, param, p_etat, 0)); /* 0 : en une fois */
|
||||
exc = setError(p_etat, getLzw(e, param, &p_etat->cl, 0)); /* 0 : en une fois */
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
@@ -174,243 +181,3 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
return exc;
|
||||
}
|
||||
/* **************************************************************************************************** */
|
||||
|
||||
void ecrireCode(env * e, modEtat * pe, long num)
|
||||
{
|
||||
long b = pe->bits; /* nb bits a ecrire */
|
||||
/* ecrire dans pe->code le numero num selon pe->bits (9 10 11 12) */
|
||||
/* il y a entre 1 et 3 octets a ecrire dans pe->code */
|
||||
if(pe->code.mInternal > 0)
|
||||
{
|
||||
/* finir de remplir le dernier octet de pe->code : de 1 a 7 bits */
|
||||
b -= pe->code.mInternal;
|
||||
pe->code.ptr[pe->code.mLg - 1] |= (num >> b); /* il reste b bits a ecrire maintenant */
|
||||
}
|
||||
dynCtrl(e, &pe->code, pe->code.mLg + (b > 8 ? 2 : 1), 1); /* tester code retour ? */
|
||||
if(b > 7)
|
||||
{
|
||||
/* ecrire un octet complet */
|
||||
b -= 8;
|
||||
pe->code.ptr[pe->code.mLg++] = (b ? (num >> b) : num) & 255;
|
||||
}
|
||||
if(b > 0)
|
||||
{
|
||||
/* ajouter les derniers bits */
|
||||
b = 8 - b;
|
||||
pe->code.ptr[pe->code.mLg++] = (num << b) & 255;
|
||||
}
|
||||
pe->code.mInternal = b; /* nb bits libres restant */
|
||||
}
|
||||
|
||||
long set(env * e, var * clair, modEtat * pe, int type)
|
||||
{
|
||||
long pos;
|
||||
/* codage lzw, type = 1 : premier appel, 2 : appel suivant, 3 : dernier appel, type = 0 : un seul appel pour tout */
|
||||
if(type == 1 || type == 0)
|
||||
{
|
||||
/* initialisations */
|
||||
dynSetLen(e, &pe->dict, 0);
|
||||
dynSetLen(e, &pe->code, 0);
|
||||
pe->code.mInternal = 0; /* nb de bits libres dans le dernier octet utilise de pe->code */
|
||||
dynLet(e, &pe->w, sFM, 1); /* pour simplifier le concat plus loin */
|
||||
pe->prec = -1;
|
||||
pe->posDict = 258;
|
||||
pe->bits = 9;
|
||||
}
|
||||
long lg_clair = clair->mLg;
|
||||
unsigned char c;
|
||||
char h[3] = {0}; /* c, en faux-hexa de a=0 jusqu'a p=15 (codes ascii 97 a 112) */
|
||||
unsigned char * pclair = clair->ptr; /* ptr en unsigned */
|
||||
while(lg_clair--)
|
||||
{
|
||||
c = *pclair++;
|
||||
h[0] = (c / 16) + 97;
|
||||
h[1] = (c % 16) + 97;
|
||||
dynConcatSz(e, &pe->w, h, 2);
|
||||
/* */
|
||||
if(pe->w.mLg == 3)
|
||||
{
|
||||
/* code simple : trouve */
|
||||
pe->prec = (long)c;
|
||||
}
|
||||
else if((pos = dynLocateSz(e, &pe->dict, pe->w.mPtr + 1, cFM, DYN_NONE, DYN_NONE)) > 0) /* ne pas chercher le FM en debut de w */
|
||||
{
|
||||
/* code compose trouve */
|
||||
pe->prec = pos + 256;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* pas trouve */
|
||||
/* 1. ecriture de pe->prec dans pe->code */
|
||||
ecrireCode(e, pe, pe->prec);
|
||||
/* 2. ajout de w au dict */
|
||||
dynConcat(e, &pe->dict, &pe->w);
|
||||
/* 3. gestion changement bits */
|
||||
if(pe->posDict == 511 || pe->posDict == 1023 || pe->posDict == 2047)
|
||||
pe->bits++; /* passage a 10,11,12 bits */
|
||||
if(pe->posDict == 4095)
|
||||
{
|
||||
/* 3.1 ecrire 256 (raz bits) */
|
||||
ecrireCode(e, pe, 256);
|
||||
/* 3.2 raz dict */
|
||||
dynSetLen(e, &pe->dict, 0);
|
||||
pe->posDict = 258;
|
||||
pe->bits = 9;
|
||||
}
|
||||
else
|
||||
pe->posDict++;
|
||||
/* 4. w = c */
|
||||
dynLet(e, &pe->w, sFM, 1);
|
||||
dynConcatSz(e, &pe->w, h, 2);
|
||||
pe->prec = (long)c;
|
||||
}
|
||||
}
|
||||
if(type == 3 || type == 0)
|
||||
{
|
||||
/* ecrire pe->prec (dernier code en cours) */
|
||||
if(pe->prec > -1)
|
||||
ecrireCode(e, pe, pe->prec);
|
||||
/* ecrire 257 */
|
||||
ecrireCode(e, pe, 257);
|
||||
/* copie du resultat dans le parametre en sortie */
|
||||
dynLet(e, clair, pe->code.mPtr, pe->code.mLg);
|
||||
}
|
||||
/* */
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
long get(env * e, var * comp, modEtat * pe, int type)
|
||||
{
|
||||
long v; /* code en cours de decodage */
|
||||
unsigned char * p;
|
||||
long masque[8] = {0, 1, 3, 7, 15, 31, 63, 127};
|
||||
/* decodage lzw, type = 1 : premier appel, 2 : appel suivant, 3 : dernier appel, type = 0 : un seul appel pour tout */
|
||||
if(type == 1 || type == 0)
|
||||
{
|
||||
/* initialisations */
|
||||
dynSetLen(e, &pe->dict, 0);
|
||||
dynSetLen(e, &pe->code, 0);
|
||||
pe->code.mInternal = 0; /* nb bits restant en entree, a traiter (contenu dans pe->reste) */
|
||||
pe->reste = 0;
|
||||
dynSetLen(e, &pe->w, 0);
|
||||
pe->prec = -1;
|
||||
pe->posDict = 258;
|
||||
pe->bits = 9;
|
||||
}
|
||||
long lg_comp = comp->mLg, lg;
|
||||
char h[3] = {0};
|
||||
unsigned char c;
|
||||
unsigned char * pcomp = comp->ptr; /* ptr en unsigned */
|
||||
while(lg_comp--)
|
||||
{
|
||||
/* lire les bits pour trouver le prochain code */
|
||||
c = *pcomp++;
|
||||
/* */
|
||||
pe->reste = (pe->reste << 8) | c;
|
||||
pe->code.mInternal += 8;
|
||||
if(pe->code.mInternal < pe->bits)
|
||||
continue;
|
||||
pe->code.mInternal -= pe->bits; /* maxi 7 bits restants */
|
||||
if(pe->code.mInternal == 0)
|
||||
v = pe->reste;
|
||||
else
|
||||
v = pe->reste >> pe->code.mInternal;
|
||||
pe->reste &= masque[pe->code.mInternal];
|
||||
/* */
|
||||
if(v == 256)
|
||||
{
|
||||
/* raz dict */
|
||||
dynSetLen(e, &pe->dict, 0);
|
||||
pe->posDict = 258;
|
||||
pe->bits = 9;
|
||||
pe->prec = -1;
|
||||
continue;
|
||||
}
|
||||
if(v == 257)
|
||||
break;
|
||||
/* v est-il dans le dictionnaire ? */
|
||||
if(v < pe->posDict)
|
||||
{
|
||||
/* *** oui *** */
|
||||
/* ecrire dans le clair (pe->code) le dict[v] */
|
||||
if(v < 256)
|
||||
{
|
||||
dynCtrl(e, &pe->code, pe->code.mLg + 1, 1);
|
||||
pe->code.ptr[pe->code.mLg++] = (unsigned char)v;
|
||||
h[0] = (v / 16) + 97;
|
||||
h[1] = (v % 16) + 97;
|
||||
}
|
||||
else
|
||||
{
|
||||
dynField(e, &pe->dict, &pe->w, v - 256, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
/* w contient le clair en faux-hexa : a=0 jusqu'a p=15 (codes ascii 97 a 112) */
|
||||
dynCtrl(e, &pe->code, pe->code.mLg + pe->w.mLg / 2, 1);
|
||||
for(p = pe->w.ptr, lg = pe->w.mLg; lg > 0; p += 2, lg -= 2)
|
||||
pe->code.ptr[pe->code.mLg++] = ((*p) << 4) + (*(p + 1)) - 1649; /* optimisation de : (*p - 97) * 16 + (*(p + 1)) - 97; */
|
||||
/* garder en memoire le premier caractere du dict (h) */
|
||||
h[0] = pe->w.mPtr[0];
|
||||
h[1] = pe->w.mPtr[1];
|
||||
dynSetLen(e, &pe->w, 2);
|
||||
}
|
||||
if(pe->prec != -1)
|
||||
{
|
||||
/* recup dict<pe->prec> dans w */
|
||||
if(pe->prec < 256)
|
||||
{
|
||||
pe->w.ptr[0] = (pe->prec / 16) + 97;
|
||||
pe->w.ptr[1] = (pe->prec % 16) + 97;
|
||||
dynSetLen(e, &pe->w, 2);
|
||||
}
|
||||
else
|
||||
dynField(e, &pe->dict, &pe->w, pe->prec - 256, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
/* ajout premier car du dict<v> (h) */
|
||||
dynConcatSz(e, &pe->w, h, 2);
|
||||
/* ecrire le nouveau dict */
|
||||
dynConcatSz(e, &pe->dict, sFM, 1);
|
||||
dynConcat(e, &pe->dict, &pe->w);
|
||||
pe->posDict++;
|
||||
if(pe->posDict == 511 || pe->posDict == 1023 || pe->posDict == 2047)
|
||||
pe->bits++; /* bug passage a 10,11,12 bits */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* *** non *** */
|
||||
/* recup dict<pe->prec> dans w (ici, pe->prec ne peut pas etre a -1) */
|
||||
if(pe->prec < 256)
|
||||
{
|
||||
pe->w.ptr[0] = (pe->prec / 16) + 97;
|
||||
pe->w.ptr[1] = (pe->prec % 16) + 97;
|
||||
dynSetLen(e, &pe->w, 2);
|
||||
}
|
||||
else
|
||||
dynField(e, &pe->dict, &pe->w, pe->prec - 256, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
/* ajout premier car du dict<pe->prec> (w) a sa fin elle meme (w) */
|
||||
h[0] = pe->w.mPtr[0];
|
||||
h[1] = pe->w.mPtr[1];
|
||||
dynConcatSz(e, &pe->w, h, 2);
|
||||
/* ecrire w dans le clair, w contient le clair en faux-hexa : a=0 jusqu'a p=15 (codes ascii 97 a 112) */
|
||||
dynCtrl(e, &pe->code, pe->code.mLg + pe->w.mLg / 2, 1);
|
||||
for(p = pe->w.ptr, lg = pe->w.mLg; lg > 0; p += 2, lg -= 2)
|
||||
pe->code.ptr[pe->code.mLg++] = ((*p) << 4) + (*(p + 1)) - 1649; /* optimisation de : (*p - 97) * 16 + (*(p + 1)) - 97; */
|
||||
/* ecrire le nouveau dict */
|
||||
dynConcatSz(e, &pe->dict, sFM, 1);
|
||||
dynConcat(e, &pe->dict, &pe->w);
|
||||
pe->posDict++;
|
||||
if(pe->posDict == 511 || pe->posDict == 1023 || pe->posDict == 2047)
|
||||
pe->bits++; /* bug : passage a 10,11,12 bits */
|
||||
}
|
||||
pe->prec = v;
|
||||
}
|
||||
/* */
|
||||
if(type == 3 || type == 0)
|
||||
{
|
||||
/* traiter les bits restant (y-en-a-t-il ?) => a priori, tout a deja ete traite avant... */
|
||||
/* copie du resultat dans le parametre en sortie */
|
||||
dynLet(e, comp, pe->code.mPtr, pe->code.mLg);
|
||||
}
|
||||
/* */
|
||||
return OK;
|
||||
}
|
||||
@@ -0,0 +1,342 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "lzw.h"
|
||||
|
||||
void initLzw(env * e, modContextLzw * cl)
|
||||
{
|
||||
cl->allocEntry = 0;
|
||||
dynInit(e, &cl->code, 4096);
|
||||
dynInit(e, &cl->w, 256);
|
||||
}
|
||||
|
||||
void freeLzw(env * e, modContextLzw * cl)
|
||||
{
|
||||
dynFree(e, &cl->code);
|
||||
dynFree(e, &cl->w);
|
||||
}
|
||||
|
||||
static void InitDict(env * e, modContextLzw * cl)
|
||||
{
|
||||
cl->posDict = 0; // prochaine entree
|
||||
// pour chaque entree, liberer tout bloc alloue (quand lg < 0 de l'entree)
|
||||
for(int alloc = 0; alloc < cl->allocEntry ; alloc++)
|
||||
memfree(e, cl->Alloc[alloc]);
|
||||
cl->allocEntry = 0;
|
||||
}
|
||||
|
||||
static int SearchDictEntry(env * e, modContextLzw * cl, pointeur valeur, int lg)
|
||||
{
|
||||
// Dict => 0-255 : idem ; 256 : EOF ; 257 : RAZ nb bits ; 258-4095 : entrees
|
||||
if(lg <= 1)
|
||||
return *valeur;
|
||||
pointeur pDict = cl->Dict;
|
||||
for(int entry = 0; entry < cl->posDict; entry++, pDict += SIZE_ENTRY)
|
||||
if(lg == *(int *)(pDict))
|
||||
{
|
||||
if(memcmp(valeur, pDict + sizeof(int), lg) == 0)
|
||||
return entry + 258;
|
||||
}
|
||||
else if(-lg == *(int *)(pDict))
|
||||
{
|
||||
// bloc alloue en dehors de l'entry (trop grand)
|
||||
if(memcmp(valeur, *(pointeur *)(pDict + sizeof(int)), lg) == 0)
|
||||
return entry + 258;
|
||||
}
|
||||
return -1; // non trouve
|
||||
}
|
||||
|
||||
static pointeur GetDictEntry(env * e, modContextLzw * cl, int entry, int * lg)
|
||||
{
|
||||
entry -= 258;
|
||||
if(entry < 0 || entry >= cl->posDict)
|
||||
return NULL;
|
||||
pointeur pDict = cl->Dict + entry * SIZE_ENTRY;
|
||||
if((*lg = *(int *)(pDict)) > 0)
|
||||
return pDict + sizeof(int);
|
||||
else
|
||||
{
|
||||
*lg = abs(*lg);
|
||||
return *(pointeur *)(pDict + sizeof(int));
|
||||
}
|
||||
}
|
||||
|
||||
static int AddDictEntry(env * e, modContextLzw * cl, pointeur valeur, int lg)
|
||||
{
|
||||
if(cl->posDict < MAX_ENTRY && lg > 0)
|
||||
{
|
||||
if(lg <= SIZE_ENTRY - sizeof(int))
|
||||
{
|
||||
pointeur pDict = cl->Dict + cl->posDict * SIZE_ENTRY;
|
||||
*(int *)pDict = lg;
|
||||
memcpy(pDict + sizeof(int), valeur, lg);
|
||||
cl->posDict++;
|
||||
return 1; // TRUE : ok
|
||||
}
|
||||
else
|
||||
{
|
||||
// mettre la longueur en negatif et allouer un bloc de la bonne taille
|
||||
pointeur alloc = memalloc(e, lg);
|
||||
if(alloc)
|
||||
{
|
||||
cl->Alloc[cl->allocEntry++] = alloc;
|
||||
//
|
||||
pointeur pDict = cl->Dict + cl->posDict * SIZE_ENTRY;
|
||||
*(int *)pDict = -lg;
|
||||
*(pointeur *)(pDict + sizeof(int)) = alloc;
|
||||
memcpy(alloc, valeur, lg);
|
||||
cl->posDict++;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ecrireCode(env * e, modContextLzw * cl, long num)
|
||||
{
|
||||
long b = cl->bits; /* nb bits a ecrire */
|
||||
/* ecrire dans cl->code le numero num selon cl->bits (9 10 11 12) */
|
||||
/* il y a entre 1 et 3 octets a ecrire dans cl->code */
|
||||
if(cl->code.mInternal > 0)
|
||||
{
|
||||
/* finir de remplir le dernier octet de cl->code : de 1 a 7 bits */
|
||||
b -= cl->code.mInternal;
|
||||
cl->code.ptr[cl->code.mLg - 1] |= (num >> b); /* il reste b bits a ecrire maintenant */
|
||||
}
|
||||
dynCtrl(e, &cl->code, cl->code.mLg + (b > 8 ? 2 : 1), 1); /* tester code retour ? */
|
||||
if(b > 7)
|
||||
{
|
||||
/* ecrire un octet complet */
|
||||
b -= 8;
|
||||
cl->code.ptr[cl->code.mLg++] = (b ? (num >> b) : num) & 255;
|
||||
}
|
||||
if(b > 0)
|
||||
{
|
||||
/* ajouter les derniers bits */
|
||||
b = 8 - b;
|
||||
cl->code.ptr[cl->code.mLg++] = (num << b) & 255;
|
||||
}
|
||||
cl->code.mInternal = b; /* nb bits libres restant */
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
long setLzw(env * e, var * clair, modContextLzw * cl, int type)
|
||||
{
|
||||
/* codage lzw, type = 1 : premier appel, 2 : appel suivant, 3 : dernier appel, type = 0 : un seul appel pour tout */
|
||||
if(type == 1 || type == 0)
|
||||
{
|
||||
/* initialisations */
|
||||
InitDict(e, cl);
|
||||
dynSetLen(e, &cl->code, 0);
|
||||
cl->code.mInternal = 0; /* nb de bits libres dans le dernier octet utilise de pe.le->code */
|
||||
dynSetLen(e, &cl->w, 0);
|
||||
cl->prec = -1;
|
||||
cl->bits = 9;
|
||||
}
|
||||
long pos, lg_clair = clair->mLg;
|
||||
unsigned char c[2], * pclair = clair->ptr; /* ptr en unsigned */
|
||||
c[1] = 0;
|
||||
while(lg_clair--)
|
||||
{
|
||||
c[0] = *pclair++;
|
||||
dynConcatSz(e, &cl->w, (char *)c, 1);
|
||||
/* */
|
||||
if(cl->w.mLg == 1)
|
||||
{
|
||||
/* code simple : trouve */
|
||||
cl->prec = c[0];
|
||||
}
|
||||
else if((pos = SearchDictEntry(e, cl, (pointeur)cl->w.mPtr, cl->w.mLg)) > -1)
|
||||
{
|
||||
/* code compose trouve */
|
||||
cl->prec = pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* pas trouve */
|
||||
/* 1. ecriture de cl->prec dans cl->code */
|
||||
ecrireCode(e, cl, cl->prec);
|
||||
/* 2. ajout de w au dict */
|
||||
AddDictEntry(e, cl, (pointeur)cl->w.mPtr, cl->w.mLg);
|
||||
/* 3. gestion changement bits */
|
||||
if(cl->posDict == 512 - 258 || cl->posDict == 1024 - 258 || cl->posDict == 2048 - 258)
|
||||
cl->bits++; /* passage a 10,11,12 bits */
|
||||
if(cl->posDict == 4096 - 258)
|
||||
{
|
||||
/* 3.1 ecrire 256 (raz bits) */
|
||||
ecrireCode(e, cl, 256);
|
||||
/* 3.2 raz dict */
|
||||
InitDict(e, cl);
|
||||
cl->bits = 9;
|
||||
}
|
||||
/* 4. w = c */
|
||||
*cl->w.ptr = c[0];
|
||||
dynSetLen(e, &cl->w, 1);
|
||||
cl->prec = c[0];
|
||||
}
|
||||
}
|
||||
if(type == 3 || type == 0)
|
||||
{
|
||||
/* ecrire cl->prec (dernier code en cours) */
|
||||
if(cl->prec > -1)
|
||||
ecrireCode(e, cl, cl->prec);
|
||||
/* ecrire 257 */
|
||||
ecrireCode(e, cl, 257);
|
||||
/* copie du resultat dans le parametre en sortie */
|
||||
dynLet(e, clair, cl->code.mPtr, cl->code.mLg);
|
||||
InitDict(e, cl);
|
||||
}
|
||||
/* */
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
long getLzw(env * e, var * comp, modContextLzw * cl, int type)
|
||||
{
|
||||
long v; /* code en cours de decodage */
|
||||
long masque[8] = {0, 1, 3, 7, 15, 31, 63, 127};
|
||||
/* decodage lzw, type = 1 : premier appel, 2 : appel suivant, 3 : dernier appel, type = 0 : un seul appel pour tout */
|
||||
if(type == 1 || type == 0)
|
||||
{
|
||||
/* initialisations */
|
||||
InitDict(e, cl);
|
||||
dynSetLen(e, &cl->code, 0);
|
||||
cl->code.mInternal = 0; /* nb bits restant en entree, a traiter (contenu dans cl->reste) */
|
||||
cl->reste = 0;
|
||||
dynSetLen(e, &cl->w, 0);
|
||||
cl->prec = -1;
|
||||
cl->bits = 9;
|
||||
}
|
||||
long lg_comp = comp->mLg;
|
||||
int lg;
|
||||
unsigned char c, h[2];
|
||||
unsigned char * pcomp = comp->ptr; /* ptr en unsigned */
|
||||
pointeur pEntry;
|
||||
h[1] = 0;
|
||||
while(lg_comp--)
|
||||
{
|
||||
/* lire les bits pour trouver le prochain code */
|
||||
c = *pcomp++;
|
||||
/* */
|
||||
cl->reste = (cl->reste << 8) | c;
|
||||
cl->code.mInternal += 8;
|
||||
if(cl->code.mInternal < cl->bits)
|
||||
continue;
|
||||
cl->code.mInternal -= cl->bits; /* maxi 7 bits restants */
|
||||
if(cl->code.mInternal == 0)
|
||||
v = cl->reste;
|
||||
else
|
||||
v = cl->reste >> cl->code.mInternal;
|
||||
cl->reste &= masque[cl->code.mInternal];
|
||||
/* */
|
||||
if(v == 256)
|
||||
{
|
||||
/* raz dict */
|
||||
InitDict(e, cl);
|
||||
cl->bits = 9;
|
||||
cl->prec = -1;
|
||||
continue;
|
||||
}
|
||||
if(v == 257)
|
||||
break;
|
||||
/* v est-il dans le dictionnaire ? */
|
||||
if(v - 258 < cl->posDict)
|
||||
{
|
||||
/* *** oui *** */
|
||||
/* ecrire dans le clair (cl->code) le dict[v] */
|
||||
if(v < 256)
|
||||
{
|
||||
h[0] = v;
|
||||
dynConcatSz(e, &cl->code, (char *)h, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
pEntry = GetDictEntry(e, cl, v, &lg);
|
||||
//dynField(e, &pe->dict, &pe->w, v - 256, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
/* w contient le clair en faux-hexa : a=0 jusqu'a p=15 (codes ascii 97 a 112) */
|
||||
//dynCtrl(e, &pe->code, pe->code.mLg + pe->w.mLg / 2, 1);
|
||||
//for(p = pe->w.ptr, lg = pe->w.mLg; lg > 0; p += 2, lg -= 2)
|
||||
// pe->code.ptr[pe->code.mLg++] = ((*p) << 4) + (*(p + 1)) - 1649; /* optimisation de : (*p - 97) * 16 + (*(p + 1)) - 97; */
|
||||
dynConcatSz(e, &cl->code, (char *)pEntry, lg);
|
||||
/* garder en memoire le premier caractere du dict (h) */
|
||||
h[0] = *pEntry;
|
||||
*cl->w.mPtr = *pEntry; // utilite ? a mettre en commentaire
|
||||
dynSetLen(e, &cl->w, 1); // utilite ? a mettre en commentaire
|
||||
}
|
||||
if(cl->prec != -1)
|
||||
{
|
||||
/* recup dict<cl->prec> dans w */
|
||||
if(cl->prec < 256)
|
||||
{
|
||||
*cl->w.mPtr = cl->prec;
|
||||
dynSetLen(e, &cl->w, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
//dynField(e, &pe->dict, &pe->w, pe->prec - 256, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
pEntry = GetDictEntry(e, cl, cl->prec, &lg);
|
||||
dynLet(e, &cl->w, (char *)pEntry, lg);
|
||||
}
|
||||
/* ajout premier car du dict<v> (h) */
|
||||
dynConcatSz(e, &cl->w, (char *)h, 1);
|
||||
/* ecrire le nouveau dict */
|
||||
AddDictEntry(e, cl, (pointeur)cl->w.mPtr, cl->w.mLg);
|
||||
//dynConcatSz(e, &pe->dict, sFM, 1);
|
||||
//dynConcat(e, &pe->dict, &pe->w);
|
||||
//cl->posDict++;
|
||||
if(cl->posDict == 511 - 258 || cl->posDict == 1023 - 258 || cl->posDict == 2047 - 258)
|
||||
cl->bits++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* *** non *** */
|
||||
/* recup dict<cl->prec> dans w (ici, cl->prec ne peut pas etre a -1) */
|
||||
if(cl->prec < 256)
|
||||
{
|
||||
*cl->w.mPtr = cl->prec;
|
||||
dynSetLen(e, &cl->w, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
//dynField(e, &pe->dict, &pe->w, pe->prec - 256, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
pEntry = GetDictEntry(e, cl, cl->prec, &lg);
|
||||
dynLet(e, &cl->w, (char *)pEntry, lg);
|
||||
}
|
||||
/* ajout premier car du dict<cl->prec> (w) a sa fin elle meme (w) */
|
||||
h[0] = *cl->w.mPtr;
|
||||
//h[1] = pe->w.mPtr[1];
|
||||
dynConcatSz(e, &cl->w,(char *) h, 1);
|
||||
/* ecrire w dans le clair, w contient le clair en faux-hexa : a=0 jusqu'a p=15 (codes ascii 97 a 112) */
|
||||
//dynCtrl(e, &pe->code, pe->code.mLg + pe->w.mLg / 2, 1);
|
||||
//for(p = pe->w.ptr, lg = pe->w.mLg; lg > 0; p += 2, lg -= 2)
|
||||
// pe->code.ptr[pe->code.mLg++] = ((*p) << 4) + (*(p + 1)) - 1649; /* optimisation de : (*p - 97) * 16 + (*(p + 1)) - 97; */
|
||||
dynConcatSz(e, &cl->code, cl->w.mPtr, cl->w.mLg);
|
||||
/* ecrire le nouveau dict */
|
||||
AddDictEntry(e, cl, (pointeur)cl->w.mPtr, cl->w.mLg);
|
||||
//dynConcatSz(e, &pe->dict, sFM, 1);
|
||||
//dynConcat(e, &pe->dict, &pe->w);
|
||||
//cl->posDict++;
|
||||
if(cl->posDict == 511 - 258 || cl->posDict == 1023 - 258 || cl->posDict == 2047 - 258)
|
||||
cl->bits++;
|
||||
}
|
||||
cl->prec = v;
|
||||
}
|
||||
/* */
|
||||
if(type == 3 || type == 0)
|
||||
{
|
||||
/* traiter les bits restant (y-en-a-t-il ?) => a priori, tout a deja ete traite avant... */
|
||||
/* copie du resultat dans le parametre en sortie */
|
||||
dynLet(e, comp, cl->code.mPtr, cl->code.mLg);
|
||||
InitDict(e, cl);
|
||||
}
|
||||
/* */
|
||||
return OK;
|
||||
}
|
||||
+5
-5
@@ -74,7 +74,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
//
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
/* les 4 fonctions suivantes doivent toujours exister dans chaque module */
|
||||
if(strncmp(e->fn, "init", 4) == 0)
|
||||
if(modFnIs(e, "init", 4))
|
||||
{
|
||||
// alloc ptr sur zone memoire pour memoriser l'etat du module
|
||||
*etat = memalloc(e, sizeof(modEtat));
|
||||
@@ -88,7 +88,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
//
|
||||
}
|
||||
}
|
||||
else if(strncmp(e->fn, "end", 3) == 0)
|
||||
else if(modFnIs(e, "end", 3))
|
||||
{
|
||||
//*** code specifique ici
|
||||
//
|
||||
@@ -96,7 +96,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
if(p_etat != NULL)
|
||||
memfree(e, p_etat);
|
||||
}
|
||||
else if(strncmp(e->fn, "vers", 4) == 0)
|
||||
else if(modFnIs(e, "vers", 4))
|
||||
{
|
||||
if(param1 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
@@ -111,7 +111,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
exc = EX_MODPARAM; // variable en parametre du mauvais type
|
||||
}
|
||||
}
|
||||
else if(strncmp(e->fn, "error", 5) == 0)
|
||||
else if(modFnIs(e, "error", 5))
|
||||
{
|
||||
// renvoie la derniere erreur specifique au module
|
||||
if(p_etat == NULL)
|
||||
@@ -127,7 +127,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(strncmp(e->fn, "xxx", 3) == 0)
|
||||
else if(modFnIs(e, "xxx", 3))
|
||||
{
|
||||
//*** coder les autres fonctions ici de la meme maniere, au a mettre au debut !
|
||||
exc = setError(p_etat, EXMOD_xxx);
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
|
||||
#include "lzw.h"
|
||||
|
||||
/* ******* constantes ********** */
|
||||
#define PDFFMT_A4P 1 /* A4 portrait */
|
||||
#define PDFFMT_A4L 2 /* A4 paysage ("landscape") */
|
||||
#define PDFFMT_A3P 3 /* A3 portrait */
|
||||
#define PDFFMT_A3L 4 /* A3 paysage */
|
||||
|
||||
#define PDFFONT_COURIER 1
|
||||
#define PDFFONT_COURIER_BOLD 2
|
||||
#define PDFFONT_COURIER_BOLDOBLIQUE 3
|
||||
#define PDFFONT_COURIER_OBLIQUE 4
|
||||
#define PDFFONT_HELVETICA 5
|
||||
#define PDFFONT_HELVETICA_BOLD 6
|
||||
#define PDFFONT_HELVETICA_BOLDOBLIQUE 7
|
||||
#define PDFFONT_HELVETICA_OBLIQUE 8
|
||||
#define PDFFONT_TIMES_ROMAN 9
|
||||
#define PDFFONT_TIMES_BOLD 10
|
||||
#define PDFFONT_TIMES_ITALIC 11
|
||||
#define PDFFONT_TIMES_BOLDITALIC 12
|
||||
#define PDFFONT_SYMBOL 13
|
||||
#define PDFFONT_ZAPFDINGBATS 14
|
||||
#define PDFFONT_NB 14
|
||||
|
||||
/* ***** MACRO ****/
|
||||
#define RGB(r,g,b) (((((r&255)<<8)+(g&255))<<8)+(b&255))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Dynamic mPdf; /* PDF en cours de constitution */
|
||||
Dynamic mPage; /* page en cours */
|
||||
Dynamic mXref; /* liste des xref du PDF en cours (<1> contient le titre et les dimensions des images) */
|
||||
Dynamic mImg; /* images en FM, en hexa, BMP 24/32 bpp uniquement (codage RGB) */
|
||||
long mNbPage; /* nb de pages total du PDF */
|
||||
long mFormat; /* A4 ou A3 et Paysage ou portrait */
|
||||
long mLarg, mHaut; /* largeur/hauteur de la page en (mm x 10), selon le format */
|
||||
long mNbObj; /* pour xref */
|
||||
long mNumPage; /* numero page en cours */
|
||||
|
||||
long mLmarg; /* marge gauche en mm x 10 */
|
||||
long mRmarg; /* marge droite en mm x 10 */
|
||||
long mHmarg; /* marge haute en mm x 10 */
|
||||
long mBmarg; /* marge basse en mm x 10 */
|
||||
long mDimFont; /* taille fonte */
|
||||
long mDimFontCadre;
|
||||
long mDimLig;
|
||||
Dynamic mFont; /* nom des 14 fontes standards */
|
||||
|
||||
modContextLzw mCtxLzw; /* gestion compression page lzw */
|
||||
|
||||
Dynamic mTmp1, mTmp2; /* temporaire pour le traitement */
|
||||
} modContextPdf;
|
||||
|
||||
void initPdf(env * e, modContextPdf * ctxPdf);
|
||||
void freePdf(env * e, modContextPdf * ctxPdf);
|
||||
int newPdf(env * e, modContextPdf * ctxPdf, Dynamic * titre, long nb_page, long format, Dynamic * fonts);
|
||||
int endPdf(env * e, modContextPdf * ctxPdf);
|
||||
Dynamic * getPdf(env * e, modContextPdf * ctxPdf);
|
||||
int setPdfPage(env * e, modContextPdf * ctxPdf, int compression);
|
||||
int setPdfText(env * e, modContextPdf * ctxPdf, long x, long y, long w, long h, long font, long taille, long couleur, Dynamic * txt);
|
||||
int setPdfGraph(env * e, modContextPdf * ctxPdf, char type, long x, long y, long w, long h, long coul_trait, long coul_rempl, long epaisseur, long pointille);
|
||||
int setPdfImage(env * e, modContextPdf * ctxPdf, long x, long y, long img);
|
||||
@@ -0,0 +1,267 @@
|
||||
/* **********************************************
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024,2025 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
W language is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version (GPL-3.0-or-later).
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
********************************************** */
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "langage.h"
|
||||
#include "dynamic.h"
|
||||
#include "var.h"
|
||||
#include "hashtable.h"
|
||||
|
||||
#include "pdf.h"
|
||||
|
||||
typedef struct {
|
||||
int error; // dernier code erreur specifique au module
|
||||
//*** a completer selon le besoin du module
|
||||
modContextPdf cp;
|
||||
|
||||
} modEtat;
|
||||
|
||||
/* mettre ici les codes d'erreurs specifiques au module */
|
||||
/* codes a passer a la fonction setError */
|
||||
#define EXMOD_xxx 1
|
||||
|
||||
static int setError(modEtat * p, int err)
|
||||
{
|
||||
if(p != NULL)
|
||||
p->error = err;
|
||||
return err == OK ? OK : EX_MODERR;
|
||||
}
|
||||
|
||||
#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 * param1, var * param2, var * param3, void ** etat)
|
||||
#else
|
||||
extern long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
|
||||
#endif
|
||||
{
|
||||
modEtat * p_etat;
|
||||
long exc = OK;
|
||||
// init/end/vers/error sont obligatoires pour tout module
|
||||
// - - - - - - - - - - - - - - - - - - - -
|
||||
if(etat == NULL)
|
||||
return EX_MODPARAM;
|
||||
else
|
||||
p_etat = (modEtat *)(*etat); /* evite de la 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 */
|
||||
if(modFnIs(e, "init", 4))
|
||||
{
|
||||
// alloc ptr sur zone memoire pour memoriser l'etat du module
|
||||
*etat = memalloc(e, sizeof(modEtat));
|
||||
if(*etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else
|
||||
{
|
||||
p_etat = (modEtat *)(*etat);
|
||||
p_etat->error = 0;
|
||||
//*** code specifique ici
|
||||
initPdf(e, &p_etat->cp);
|
||||
}
|
||||
}
|
||||
else if(modFnIs(e, "end", 3))
|
||||
{
|
||||
if(p_etat != NULL)
|
||||
{
|
||||
//*** code specifique ici
|
||||
freePdf(e, &p_etat->cp);
|
||||
// fin liberation specifique module avant arret process
|
||||
memfree(e, p_etat);
|
||||
}
|
||||
}
|
||||
else if(modFnIs(e, "vers", 4))
|
||||
{
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param1 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
// renvoie la version du module/plugins
|
||||
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
|
||||
}
|
||||
}
|
||||
else if(modFnIs(e, "error", 5))
|
||||
{
|
||||
// renvoie la derniere erreur specifique au module
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param1 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
if(param1->type == VAR_NUMBER)
|
||||
param1->num = (ent64)(NUM_FACTEUR * p_etat->error);
|
||||
else
|
||||
exc = EX_MODPARAM; // bad type of parameter
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(modFnIs(e, "beginDoc", 8))
|
||||
{
|
||||
// nouveau document pdf
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param1->type != VAR_HASHTABLE)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
// lire les infos necessaires a la creation d'un nouveau doc. pdf :
|
||||
// titre, nb pages, format, fontes utilisees
|
||||
var * titre, * fontes, * nbPage, * format;
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "Titre"), &titre);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "Fontes"), &fontes);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "Pages"), &nbPage);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "Format"), &format);
|
||||
if(titre && fontes && nbPage && format)
|
||||
{
|
||||
if(titre->type == VAR_DYNAMIC && fontes->type == VAR_DYNAMIC && nbPage->type == VAR_NUMBER && format->type == VAR_NUMBER)
|
||||
exc = setError(p_etat, ! newPdf(e, &p_etat->cp, titre, nbPage->num / NUM_FACTEUR, format->num / NUM_FACTEUR, fontes));
|
||||
else
|
||||
exc = EX_MODPARAM;
|
||||
}
|
||||
else
|
||||
exc = EX_MODPARAM;
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(modFnIs(e, "endDoc", 6))
|
||||
{
|
||||
// finalise le document pdf, et renvoi le contenu dans param1
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param1 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
int cr = endPdf(e, &p_etat->cp);
|
||||
if(cr)
|
||||
{
|
||||
var_let(e, param1, getPdf(e, &p_etat->cp), FALSE, FALSE);
|
||||
}
|
||||
exc = setError(p_etat, ! cr);
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(modFnIs(e, "addPage", 7))
|
||||
{
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else
|
||||
// ajouter la page en cours au doucment pdf
|
||||
exc = setError(p_etat, ! setPdfPage(e, &p_etat->cp, 1)); // 1 = avec compression ; parametrer ?
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(modFnIs(e, "addText", 7))
|
||||
{
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param1 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param2 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_HASHTABLE || param2->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
// ajouter le texte
|
||||
var * x, * y, * w, * h; // cadre englobant
|
||||
var * fonte, * taille, * couleur;
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "X"), &x);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "Y"), &y);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "W"), &w);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "H"), &h);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "Fonte"), &fonte);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "Taille"), &taille);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "Couleur"), &couleur);
|
||||
if(x && y && w && h && fonte && taille && couleur)
|
||||
{
|
||||
// TODO tester le type des variables !?
|
||||
exc = setError(p_etat, ! setPdfText(e, &p_etat->cp, x->num / NUM_FACTEUR, y->num / NUM_FACTEUR, w->num / NUM_FACTEUR, h->num / NUM_FACTEUR,
|
||||
fonte->num / NUM_FACTEUR, taille->num / NUM_FACTEUR, couleur->num / NUM_FACTEUR, param2)); // param2 = texte
|
||||
}
|
||||
else
|
||||
exc = EX_MODPARAM;
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(modFnIs(e, "addGraph", 8))
|
||||
{
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param1 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_HASHTABLE)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
// ajouter l'element graphique
|
||||
var * x, * y, * w, * h; // cadre englobant
|
||||
var * couleurTrait, * couleurRemplissage, * epaisseur, * pointille, * type;
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "X"), &x); // TODO tester le type des variables !?
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "Y"), &y);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "W"), &w);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "H"), &h);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "CouleurTrait"), &couleurTrait);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "CouleurRemplissage"), &couleurRemplissage);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "EpaisseurTrait"), &epaisseur);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "Pointille"), &pointille);
|
||||
hashtable_do(e, HASH_READ, param1, copy_nom(e, "Type"), &type);
|
||||
if(x && y && w && h && couleurTrait && couleurRemplissage && epaisseur && pointille && type)
|
||||
{
|
||||
// TODO tester le type des variables !?
|
||||
exc = setError(p_etat, ! setPdfGraph(e, &p_etat->cp, *type->mPtr, x->num / NUM_FACTEUR, y->num / NUM_FACTEUR, w->num / NUM_FACTEUR, h->num / NUM_FACTEUR,
|
||||
couleurTrait->num / NUM_FACTEUR, couleurRemplissage->num / NUM_FACTEUR, epaisseur->num / NUM_FACTEUR, pointille->num / NUM_FACTEUR));
|
||||
}
|
||||
else
|
||||
exc = EX_MODPARAM;
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else
|
||||
{
|
||||
setError(p_etat, 0); // evite un warning de compil
|
||||
exc = EX_MODFUNC; // fonction non prise en charge
|
||||
}
|
||||
//
|
||||
return exc;
|
||||
}
|
||||
@@ -0,0 +1,688 @@
|
||||
|
||||
#include "pdf.h"
|
||||
|
||||
//
|
||||
// creation fichier PDF
|
||||
//
|
||||
// structure fichier PDF :
|
||||
// header - body - xref table - trailer
|
||||
//
|
||||
// header :
|
||||
// %PDF-1.2 : version du fichier
|
||||
//
|
||||
// xref table :
|
||||
// xref
|
||||
// "no objet debut" "nb objet" --> no objet debut = 0 le plus souvent
|
||||
// "offset R%10" "00000" n EOL (20 octets pile, autant que de nb objet ; utilise)
|
||||
// "objet libre suiv R%10" "generation num R%5" f EOL (20 octets pile, autant que de nb objet ; libre)
|
||||
// si pas d'objets libres, le zero est toujours libre (debut de la liste chainee : 0000000000 65535 f)
|
||||
//
|
||||
// trailer :
|
||||
// trailer << "liste cle/valeur" >>
|
||||
// startxref
|
||||
// "offset xref-table"
|
||||
// %%EOF
|
||||
// cle/valeur obligatoires :
|
||||
// /Size "nb xref" : nb d'objet dans la xref table --> = "nb objet" de xref
|
||||
// /Root "N" 0 R : reference a l'objet de depart du fichier, numero "N" (sauf 0)
|
||||
// facultatif /Info "N" 0 R --> liste des infos possibles dans l'objet "N" :
|
||||
// N 0 R << /Producer (Nom du logiciel)
|
||||
// /Title (Titre)
|
||||
// /Author (Nom prenom)
|
||||
// /Creator ()
|
||||
// /Subject ()
|
||||
// /Keywords ()
|
||||
// /CreationDate (D:20120906140053) --> format des dates au passage ici
|
||||
// >>
|
||||
//
|
||||
// body :
|
||||
// contient la liste des objets, structure :
|
||||
// catalog - page tree - liste des pages
|
||||
//
|
||||
// commentaires :
|
||||
// % "bla bla bla .." jusqu'à la fin de la ligne
|
||||
// dans un "stream" uniquement
|
||||
//
|
||||
// catalog :
|
||||
// 1 0 obj << /Type /Catalog /Pages 2 0 R >> endobj
|
||||
// Type et Pages sont obligatoires
|
||||
//
|
||||
// page tree :
|
||||
// 2 0 obj << /Type /Pages /Count 3 /Kids [ 3 0 R 4 0 R 5 0 R ] >> end obj
|
||||
// Type, Count et Kids sont obligatoires
|
||||
//
|
||||
// page :
|
||||
// 3 0 obj << /Type /Page /Parent 2 0 R /MediaBox [ x1 y1 x2 y2 ]
|
||||
// /Resources << "ressources de la page : police, etc." >>
|
||||
// /Contents 6 0 R --> contenu de la page dans l'objet 6
|
||||
// >> end obj
|
||||
// Type et Parent sont obligatoires ; Resources et Contents sont heritables
|
||||
//
|
||||
// ressources :
|
||||
// /Font << /F1 7 0 R >>
|
||||
//
|
||||
// contenu : objet 6
|
||||
// 6 0 obj << /Length 123 >>
|
||||
// stream
|
||||
// ... "contenu : BT, etc. de longueur 123 octets" ...
|
||||
// endstream
|
||||
// endobj
|
||||
//
|
||||
// fonte no 1 :
|
||||
// 7 0 obj << /Type /Font /Subtype /Type1 (ou "/TrueType" mais necessite plus d'infos)
|
||||
// /Name F1 /BaseFont Helvetica (ou "Courier" "Times-Roman" "Helvetica-Bold" "Courier-Bold" "Times-Bold")
|
||||
// >> endobj
|
||||
//
|
||||
// Coordonnees :
|
||||
//
|
||||
// y ^
|
||||
// |
|
||||
// |
|
||||
// 0 +------> user space en 1/72 de pouce (=25.4mm)
|
||||
// 0 x
|
||||
// ex. A4 = 210x297 = 595x841 (mm a multiplier par 2.835) ; 1 cm = 28 user space ; 1 userspace = 0.35 mm)
|
||||
// nb avec decimale possible : ex : 594.25, etc.
|
||||
//
|
||||
// zones de texte (dans un "stream") :
|
||||
// BT --> debut texte
|
||||
// /F13 12 Tf --> choix fonte 13 (cf. /Resources) en taille 12
|
||||
// 288 720 Td --> positionnement x y
|
||||
// (ABC) Tj --> texte a editer
|
||||
// ET --> fin texte
|
||||
//
|
||||
// rectangle ("stream") :
|
||||
// "x y w h" re S
|
||||
// ligne :
|
||||
// x1 y1 m x2 y2 l S
|
||||
//
|
||||
// Path clipping :
|
||||
// utiliser l'opérateur "W n" pour définir une région de clipping (à mettre pour les zones texte)
|
||||
//
|
||||
// EXEMPLE (enlever les // de chaque debut de ligne...) -----------------------------------------------------------------------------
|
||||
//
|
||||
// %PDF-1.2
|
||||
// 1 0 obj << /Type /Catalog /Pages 2 0 R >> endobj
|
||||
// 2 0 obj << /Type /Pages /Count 1 /Kids [ 3 0 R ] >> end obj
|
||||
// 3 0 obj << /Type /Page /Parent 2 0 R /MediaBox [ 0 0 595 841 ] /Resources << /Font << /F1 4 0 R >> >> /Contents 5 0 R >> end obj
|
||||
// 4 0 obj << /Type /Font /Subtype /Type1 /Name /F1 /BaseFont /Courier >> endobj
|
||||
// 5 0 obj << /Length 95 >>
|
||||
// stream
|
||||
// % Page 1
|
||||
// 188 720 15 15 re W n
|
||||
// BT
|
||||
// /F1 10 Tf 188 720 Td (ABC) Tj
|
||||
// ET
|
||||
// 0 w
|
||||
// 188 730 80 40 re S
|
||||
// endstream
|
||||
// endobj
|
||||
// xref
|
||||
// 0 6
|
||||
// 0000000000 65535 f
|
||||
// 0000000010 00000 n
|
||||
// 0000000060 00000 n
|
||||
// 0000000121 00000 n
|
||||
// 0000000252 00000 n
|
||||
// 0000000331 00000 n
|
||||
// trailer
|
||||
// << /Size 6 /Root 1 0 R >>
|
||||
// startxref
|
||||
// 481
|
||||
// %%EOF
|
||||
//
|
||||
|
||||
#include "stdio.h"
|
||||
|
||||
#define PDF_CONV1 72000
|
||||
#define PDF_CONV2 2540
|
||||
/* valeur en dixieme de mm * CONV11 / CONV2 = valeur en unites pdf x 100 (72 dpi = 72 points par pouce ; 1 pouce = 25.4) */
|
||||
|
||||
/* PRIVATE *****************************************************/
|
||||
static int pdfEchap(env * e, Dynamic * resultat, Dynamic * chaine)
|
||||
{
|
||||
char * p, * q, c;
|
||||
long lg = chaine->mLg, nb = 0;
|
||||
/* d'abord compter les caracteres a "echapper" */
|
||||
p = chaine->mPtr;
|
||||
while((c=*p++))
|
||||
if(c == '(' || c == ')' || c == '\\')
|
||||
nb++;
|
||||
/* ensuite, preparer la chaine resultat (lg + nb) */
|
||||
if(dynCtrl(e, resultat, lg + nb, FALSE))
|
||||
return FALSE; // erreur memoire
|
||||
/* enfin, recopier les caracteres et prefixer ( ) \ par \ */
|
||||
p = chaine->mPtr;
|
||||
q = resultat->mPtr;
|
||||
while((c=*p++))
|
||||
{
|
||||
if(c == '(' || c == ')' || c == '\\')
|
||||
*q++ = '\\';
|
||||
*q++ = c;
|
||||
}
|
||||
dynSetLen(e, resultat, lg + nb);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static int setXref(env * e, modContextPdf * ctxPdf)
|
||||
{
|
||||
/* calcule la taille actuelle du PDF (pour calcul offset) avec saut de ligne meme sur la derniere ligne */
|
||||
return ! dynConcatSz(e, &ctxPdf->mXref, sFM, 1) && ! dynConcatSz(e, &ctxPdf->mXref, Int64ToSz(e, (ent64s)ctxPdf->mPdf.mLg, FALSE, 10), DYN_LGNONE); // verif leftpad ok (idem "%010ld") !! TODO !!
|
||||
}
|
||||
|
||||
static char table100[400] = ".00\0.01\0.02\0.03\0.04\0.05\0.06\0.07\0.08\0.09\0"
|
||||
".10\0.11\0.12\0.13\0.14\0.15\0.16\0.17\0.18\0.19\0"
|
||||
".20\0.21\0.22\0.23\0.24\0.25\0.26\0.27\0.28\0.29\0"
|
||||
".30\0.31\0.32\0.33\0.34\0.35\0.36\0.37\0.38\0.39\0"
|
||||
".40\0.41\0.42\0.43\0.44\0.45\0.46\0.47\0.48\0.49\0"
|
||||
".50\0.51\0.52\0.53\0.54\0.55\0.56\0.57\0.58\0.59\0"
|
||||
".60\0.61\0.62\0.63\0.64\0.65\0.66\0.67\0.68\0.69\0"
|
||||
".70\0.71\0.72\0.73\0.74\0.75\0.76\0.77\0.78\0.79\0"
|
||||
".80\0.81\0.82\0.83\0.84\0.85\0.86\0.87\0.88\0.89\0"
|
||||
".90\0.91\0.92\0.93\0.94\0.95\0.96\0.97\0.98\0.99\0";
|
||||
|
||||
static int fmt2(env * e, Dynamic * res, ent64s a, ent64s b)
|
||||
{
|
||||
int cr = TRUE;
|
||||
ent64s r = a * PDF_CONV1 / PDF_CONV2;
|
||||
cr = cr && !dynConcatSz(e, res, Int64ToSz(e, r / 100, TRUE, 0), DYN_LGNONE) && !dynConcatSz(e, res, &table100[(abs(r) % 100) * 4], 3) && !dynConcatSz(e, res, " ", 1);
|
||||
r = b * PDF_CONV1 / PDF_CONV2;
|
||||
cr = cr && !dynConcatSz(e, res, Int64ToSz(e, r / 100, TRUE, 0), DYN_LGNONE) && !dynConcatSz(e, res, &table100[(abs(r) % 100) * 4], 3);
|
||||
return cr;
|
||||
}
|
||||
|
||||
static int fmt4(env * e, Dynamic * res, ent64s a, ent64s b, ent64s c, ent64s d)
|
||||
{
|
||||
int cr = TRUE;
|
||||
ent64s r = a * PDF_CONV1 / PDF_CONV2;
|
||||
cr = cr && !dynConcatSz(e, res, Int64ToSz(e, r / 100, TRUE, DYN_NONE), DYN_LGNONE) && !dynConcatSz(e, res, &table100[(abs(r) % 100) * 4], 3) && !dynConcatSz(e, res, " ", 1);
|
||||
r = b * PDF_CONV1 / PDF_CONV2;
|
||||
cr = cr && !dynConcatSz(e, res, Int64ToSz(e, r / 100, TRUE, DYN_NONE), DYN_LGNONE) && !dynConcatSz(e, res, &table100[(abs(r) % 100) * 4], 3) && !dynConcatSz(e, res, " ", 1);
|
||||
r = c * PDF_CONV1 / PDF_CONV2;
|
||||
cr = cr && !dynConcatSz(e, res, Int64ToSz(e, r / 100, TRUE, DYN_NONE), DYN_LGNONE) && !dynConcatSz(e, res, &table100[(abs(r) % 100) * 4], 3) && !dynConcatSz(e, res, " ", 1);
|
||||
r = d * PDF_CONV1 / PDF_CONV2;
|
||||
cr = cr && !dynConcatSz(e, res, Int64ToSz(e, r / 100, TRUE, DYN_NONE), DYN_LGNONE) && !dynConcatSz(e, res, &table100[(abs(r) % 100) * 4], 3);
|
||||
return cr;
|
||||
}
|
||||
|
||||
static int fmtc(env * e, Dynamic * res, long coul)
|
||||
{
|
||||
int cr = TRUE;
|
||||
/* utilise la var t pour renvoyer la couleur convertie en 9 9 9, avec 9 allant de 0 a 1 sur 2 decimales */
|
||||
long r = (coul >> 16) & 255; // red
|
||||
long g = (coul >> 8) & 255; // green
|
||||
long b = coul & 255; // blue
|
||||
cr = cr && !dynConcatSz(e, res, r == 255 ? "1" : "0", 1);
|
||||
cr = cr && (r != 255 ? !dynConcatSz(e, res, &table100[((int)(r * 100 / 255)) * 4], 3) : TRUE);
|
||||
cr = cr && !dynConcatSz(e, res, g == 255 ? " 1" : " 0", 2);
|
||||
cr = cr && (g != 255 ? !dynConcatSz(e, res, &table100[((int)(g * 100 / 255)) * 4], 3) : TRUE);
|
||||
cr = cr && !dynConcatSz(e, res, b == 255 ? " 1" : " 0", 2);
|
||||
cr = cr && (b != 255 ? !dynConcatSz(e, res, &table100[((int)(b * 100 / 255)) * 4], 3) : TRUE);
|
||||
/* */
|
||||
return cr;
|
||||
}
|
||||
|
||||
/* PUBLIC ************************************************************************/
|
||||
void initPdf(env * e, modContextPdf * ctxPdf)
|
||||
{
|
||||
ctxPdf->mLmarg = 100; /* dixieme de mm ( = 1 cm ici) */
|
||||
ctxPdf->mRmarg = 100;
|
||||
ctxPdf->mHmarg = 100;
|
||||
ctxPdf->mBmarg = 100;
|
||||
ctxPdf->mDimFont = 9;
|
||||
ctxPdf->mDimFontCadre = 9;
|
||||
ctxPdf->mDimLig = 9;
|
||||
/* */
|
||||
dynInit(e, &ctxPdf->mFont, 256);
|
||||
dynInit(e, &ctxPdf->mTmp1, 1024);
|
||||
dynInit(e, &ctxPdf->mTmp2, 1024);
|
||||
dynInit(e, &ctxPdf->mPage, 4096);
|
||||
dynInit(e, &ctxPdf->mPdf, 8192);
|
||||
ctxPdf->mPdf.type = VAR_DYNAMIC;
|
||||
dynInit(e, &ctxPdf->mXref, 1024);
|
||||
dynInit(e, &ctxPdf->mImg, 2048);
|
||||
/* nom des fontes standards */
|
||||
dynLet(e, &ctxPdf->mFont, "Courier,Courier-Bold,Courier-BoldOblique,Courier-Oblique,Helvetica,Helvetica-Bold,Helvetica-BoldOblique,Helvetica-Oblique,"
|
||||
"Times-Roman,Times-Bold,Times-Italic,Times-BoldItalic,Symbol,ZapfDingbats", DYN_LGNONE);
|
||||
dynConvert(e, &ctxPdf->mFont, ",", sFM);
|
||||
//
|
||||
initLzw(e, &ctxPdf->mCtxLzw);
|
||||
}
|
||||
|
||||
void freePdf(env * e, modContextPdf * ctxPdf)
|
||||
{
|
||||
freeLzw(e, &ctxPdf->mCtxLzw);
|
||||
/* */
|
||||
dynFree(e, &ctxPdf->mFont);
|
||||
dynFree(e, &ctxPdf->mTmp1);
|
||||
dynFree(e, &ctxPdf->mTmp2);
|
||||
dynFree(e, &ctxPdf->mPage);
|
||||
dynFree(e, &ctxPdf->mPdf);
|
||||
dynFree(e, &ctxPdf->mXref);
|
||||
dynFree(e, &ctxPdf->mImg);
|
||||
}
|
||||
|
||||
int newPdf(env * e, modContextPdf * ctxPdf, Dynamic * titre, long nb_page, long format, Dynamic * fonts)
|
||||
{
|
||||
long i, j, cpt, nbp;
|
||||
long nb_img, nb_obj_entete, nb_font, nb_obj_fixe = 3;
|
||||
int cr = TRUE;
|
||||
/* controles */
|
||||
if(nb_page < 1)
|
||||
return FALSE;
|
||||
/* */
|
||||
switch(format)
|
||||
{
|
||||
/* largeur et hauteur en unités mm x 10 ici */
|
||||
case PDFFMT_A4P:
|
||||
ctxPdf->mLarg = 2100;
|
||||
ctxPdf->mHaut = 2970;
|
||||
ctxPdf->mFormat = format;
|
||||
break;
|
||||
case PDFFMT_A4L:
|
||||
ctxPdf->mLarg = 2970;
|
||||
ctxPdf->mHaut = 2100;
|
||||
ctxPdf->mFormat = format;
|
||||
break;
|
||||
case PDFFMT_A3P:
|
||||
ctxPdf->mLarg = 2970;
|
||||
ctxPdf->mHaut = 4200;
|
||||
ctxPdf->mFormat = format;
|
||||
break;
|
||||
case PDFFMT_A3L:
|
||||
ctxPdf->mLarg = 4200;
|
||||
ctxPdf->mHaut = 2970;
|
||||
ctxPdf->mFormat = format;
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
ctxPdf->mNbPage = nb_page;
|
||||
/* raz vars dynamiques */
|
||||
dynSetLen(e, &ctxPdf->mPdf, 0);
|
||||
dynSetLen(e, &ctxPdf->mPage, 0);
|
||||
dynSetLen(e, &ctxPdf->mXref, 0);
|
||||
/* */
|
||||
cr = cr && pdfEchap(e, &ctxPdf->mTmp1, titre); // dans les chaines "echapper" ( ) \ avec \( \) \\ (seuls cas)
|
||||
dynConcat(e, &ctxPdf->mXref, &ctxPdf->mTmp1); // xref<1> = titre
|
||||
/* */
|
||||
nb_font = dynDcount(e, fonts, cFM, DYN_NONE, DYN_NONE);
|
||||
nb_img = dynDcount(e, &ctxPdf->mImg, cFM, DYN_NONE, DYN_NONE);
|
||||
nb_obj_entete = nb_obj_fixe + nb_font + nb_img;
|
||||
ctxPdf->mNbObj = nb_obj_entete + ctxPdf->mNbPage;
|
||||
ctxPdf->mNumPage = 0;
|
||||
//
|
||||
dynLet(e, &ctxPdf->mPdf, "%PDF-1.2\r\n", DYN_LGNONE);
|
||||
// objet racine root
|
||||
setXref(e, ctxPdf);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, "1 0 obj << /Type /Catalog /Pages 3 0 R >> endobj\r\n", DYN_LGNONE);
|
||||
setXref(e, ctxPdf);
|
||||
// infos sur le pdf
|
||||
dynConcatSz(e, &ctxPdf->mPdf, "2 0 obj << /Producer (WPDF) /Author (WPDF) /Title (", DYN_LGNONE);
|
||||
dynConcat(e, &ctxPdf->mPdf, &ctxPdf->mTmp1); /* titre "echape" */
|
||||
dynConcatSz(e, &ctxPdf->mPdf, ") /CreationDate (", DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, "20000101140000", DYN_LGNONE); // TODO date courante YMDhms dynOconv(e, ...)
|
||||
dynConcatSz(e, &ctxPdf->mPdf, ") >> endobj\r\n", DYN_LGNONE);
|
||||
setXref(e, ctxPdf);
|
||||
// liste des pages
|
||||
cpt = nb_obj_entete;
|
||||
dynConcatSz(e, &ctxPdf->mPdf,"3 0 obj << /Type /Pages /Count ", DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, Int64ToSz(e, ctxPdf->mNbPage, FALSE, 0), DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf," /Kids [ ", DYN_LGNONE);
|
||||
for(i = 1; i <= ctxPdf->mNbPage; i++)
|
||||
{
|
||||
dynConcatSz(e, &ctxPdf->mPdf, Int64ToSz(e, ++cpt, FALSE, 0), DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, " 0 R ", DYN_LGNONE);
|
||||
}
|
||||
dynConcatSz(e, &ctxPdf->mPdf,"] >> endobj\r\n", DYN_LGNONE);
|
||||
/* liste des fontes, prendre celles utilisees */
|
||||
cpt = nb_obj_fixe;
|
||||
for(i = 1, nbp = 0; i <= PDFFONT_NB; i++)
|
||||
{
|
||||
dynField(e, &ctxPdf->mFont, &ctxPdf->mTmp1, i, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
if(dynLocateSz(e, fonts, ctxPdf->mTmp1.mPtr, cFM, DYN_NONE, DYN_NONE) > 0)
|
||||
{
|
||||
setXref(e, ctxPdf);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, Int64ToSz(e, ++cpt, FALSE, DYN_NONE), DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, " 0 obj << /Type /Font /Subtype /Type1 /Name /F", DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, Int64ToSz(e, ++nbp, FALSE, DYN_NONE), DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, " /BaseFont /", DYN_LGNONE);
|
||||
dynConcat(e, &ctxPdf->mPdf, &ctxPdf->mTmp1);
|
||||
dynConcatSz(e, &ctxPdf->mPdf," /Encoding << /Type /Encoding /BaseEncoding /WinAnsiEncoding >> >> endobj\r\n", DYN_LGNONE);
|
||||
}
|
||||
}
|
||||
/* liste des images */
|
||||
for(i = 1; i <= nb_img; i++)
|
||||
{
|
||||
setXref(e, ctxPdf);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, Int64ToSz(e, ++cpt, FALSE, 0), DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, " 0 obj << /Type /XObject /Subtype /Image /Width ", DYN_LGNONE);
|
||||
/* ajout des coordonnes de l'image au format "w 0 0 h" de xref<1,2> a xref<1,1+nb_img> */
|
||||
dynField(e, &ctxPdf->mImg, &ctxPdf->mTmp1, i, 1, cFM, cVM, 1); // vm1 = larg (w) VM2 = haut (h) VM3 = bitmap 32bpp hexa RGB
|
||||
dynConcat(e, &ctxPdf->mPdf, &ctxPdf->mTmp1);
|
||||
dynConcatSz(e, &ctxPdf->mXref, sVM, DYN_LGNONE);
|
||||
dynConcat(e, &ctxPdf->mXref, &ctxPdf->mTmp1);
|
||||
dynConcatSz(e, &ctxPdf->mPdf," /Height ", DYN_LGNONE);
|
||||
dynField(e, &ctxPdf->mImg, &ctxPdf->mTmp1, i, 2, cFM, cVM, 1); // vm1 = larg (w) VM2 = haut (h) VM3 = bitmap 32bpp hexa RGB
|
||||
dynConcat(e, &ctxPdf->mPdf, &ctxPdf->mTmp1);
|
||||
dynConcatSz(e, &ctxPdf->mXref, " 0 0 ", DYN_LGNONE);
|
||||
dynConcat(e, &ctxPdf->mXref, &ctxPdf->mTmp1);
|
||||
dynConcatSz(e, &ctxPdf->mPdf," /BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter /ASCIIHexDecode /Length ", DYN_LGNONE); // TODO remplacer /ASCIIHexDecode par /LZW...
|
||||
dynField(e, &ctxPdf->mImg, &ctxPdf->mTmp1, i, 3, cFM, cVM, 1); // vm1 = larg (w) VM2 = haut (h) VM3 = bitmap 32bpp hexa RGBRGBRGBRGB
|
||||
dynConcatSz(e, &ctxPdf->mPdf, Int64ToSz(e, ctxPdf->mTmp1.mLg, FALSE, 0), DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, " >>\r\nstream\r\n", DYN_LGNONE);
|
||||
dynConcat(e, &ctxPdf->mPdf, &ctxPdf->mTmp1);
|
||||
dynConcatSz(e, &ctxPdf->mPdf,"\r\nendstream\r\nendobj\r\n", DYN_LGNONE);
|
||||
}
|
||||
/* definition de chaque page */
|
||||
cpt = nb_obj_entete;
|
||||
for(i = 1; i <= ctxPdf->mNbPage; i++)
|
||||
{
|
||||
setXref(e, ctxPdf);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, Int64ToSz(e, ++cpt, FALSE, DYN_NONE), DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, " 0 obj << /Type /Page /Parent 3 0 R /MediaBox [ 0 0 ", DYN_LGNONE);
|
||||
fmt2(e, &ctxPdf->mPdf, ctxPdf->mLarg, ctxPdf->mHaut);
|
||||
dynConcatSz(e, &ctxPdf->mPdf," ] /Resources << /Font << ", DYN_LGNONE);
|
||||
for(j = 1; j <= nbp; j++)
|
||||
{
|
||||
dynConcatSz(e, &ctxPdf->mPdf, "/F", DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, Int64ToSz(e, j, FALSE, 0), DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, " ", DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, Int64ToSz(e, j + nb_obj_fixe, FALSE, 0), DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, " 0 R ", DYN_LGNONE);
|
||||
}
|
||||
dynConcatSz(e, &ctxPdf->mPdf, ">> ", DYN_LGNONE);
|
||||
for(j = 1; j <= nb_img; j++)
|
||||
{
|
||||
if(j == 1)
|
||||
dynConcatSz(e, &ctxPdf->mPdf, "/XObject << ", DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, "/Img", DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, Int64ToSz(e, j, FALSE, 0), DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, " ", DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, Int64ToSz(e, j + nb_obj_fixe + nbp, FALSE, 0), DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, " 0 R", DYN_LGNONE);
|
||||
if(j == nb_img)
|
||||
dynConcatSz(e, &ctxPdf->mPdf, ">> ", DYN_LGNONE);
|
||||
}
|
||||
dynConcatSz(e, &ctxPdf->mPdf, ">> /Contents ", DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, Int64ToSz(e, i + nb_obj_entete + ctxPdf->mNbPage, FALSE, 0), DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, " 0 R >> endobj\r\n", DYN_LGNONE);
|
||||
}
|
||||
return cr;
|
||||
}
|
||||
|
||||
int endPdf(env * e, modContextPdf * ctxPdf)
|
||||
{
|
||||
long i, nb; /* nb xref */
|
||||
setXref(e, ctxPdf);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, "xref\r\n0 ", DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, Int64ToSz(e, ctxPdf->mNbObj + 1, FALSE, DYN_NONE), DYN_LGNONE);
|
||||
nb = dynDcount(e, &ctxPdf->mXref, cFM, DYN_NONE, DYN_NONE);
|
||||
for(i = 1; i < nb; i++)
|
||||
if(i == 1)
|
||||
/* le premier attribut ne fait pas partie de "xref" (titre) */
|
||||
dynConcatSz(e, &ctxPdf->mPdf, "\r\n0000000000 65535 f\r\n", DYN_LGNONE);
|
||||
else
|
||||
{
|
||||
dynField(e, &ctxPdf->mXref, &ctxPdf->mTmp1, i, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
dynConcat(e, &ctxPdf->mPdf, &ctxPdf->mTmp1);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, " 00000 n\r\n", DYN_LGNONE);
|
||||
}
|
||||
dynField(e, &ctxPdf->mXref, &ctxPdf->mTmp1, nb, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, "trailer\r\n<< /Size ", DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, Int64ToSz(e, ctxPdf->mNbObj + 1, FALSE, 0), DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, " /Root 1 0 R /Info 2 0 R >>\r\nstartxref\r\n", DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, Int64ToSz(e, dynToNum(e, &ctxPdf->mTmp1, FALSE, 10), FALSE, DYN_NONE), DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, "\r\n%%EOF", DYN_LGNONE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Dynamic * getPdf(env * e, modContextPdf * ctxPdf)
|
||||
{
|
||||
return &ctxPdf->mPdf;
|
||||
}
|
||||
|
||||
int setPdfPage(env * e, modContextPdf * ctxPdf, int compression)
|
||||
{
|
||||
int cr = TRUE;
|
||||
/* compression = 0 : pas de compression LZW */
|
||||
/* 1 : compression LZW en binaire */
|
||||
setXref(e, ctxPdf);
|
||||
ctxPdf->mNbObj++;
|
||||
ctxPdf->mNumPage++;
|
||||
/* ajout du code "PDF" directement */
|
||||
dynConcatSz(e, &ctxPdf->mPdf, Int64ToSz(e, ctxPdf->mNbObj, FALSE, DYN_NONE), DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, " 0 obj << /Length ", DYN_LGNONE);
|
||||
if( ! compression)
|
||||
{
|
||||
/* pas de compression ni codage ici */
|
||||
dynConcatSz(e, &ctxPdf->mPdf, Int64ToSz(e, ctxPdf->mPage.mLg, FALSE, DYN_NONE), DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, " >>\r\nstream\r\n", DYN_LGNONE);
|
||||
dynConcat(e, &ctxPdf->mPdf, &ctxPdf->mPage);
|
||||
}
|
||||
else
|
||||
{
|
||||
// compression LZW du stream de la page
|
||||
//ctxPdf->mCtxLzw.compress_do(0, (unsigned char *)ctxPdf->mPage.mPtr, ctxPdf->mPage.mLg); // verif
|
||||
setLzw(e, &ctxPdf->mPage, &ctxPdf->mCtxLzw, 0);
|
||||
//ctxPdf->mPage = ctxPdf->mLzw.getCode(); // verif
|
||||
/* */
|
||||
dynConcatSz(e, &ctxPdf->mPdf, Int64ToSz(e, ctxPdf->mPage.mLg, FALSE, DYN_NONE), DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPdf, " /Filter /LZWDecode >>\r\nstream\r\n", DYN_LGNONE);
|
||||
dynConcat(e, &ctxPdf->mPdf, &ctxPdf->mPage);
|
||||
}
|
||||
dynConcatSz(e, &ctxPdf->mPdf, "endstream\r\nendobj\r\n", DYN_LGNONE);
|
||||
/* raz page */
|
||||
dynSetLen(e, &ctxPdf->mPage, 0);
|
||||
return cr;
|
||||
}
|
||||
|
||||
int setPdfText(env * e, modContextPdf * ctxPdf, long x, long y, long w, long h, long font, long taille, long couleur, Dynamic * txt)
|
||||
{
|
||||
int cr = TRUE;
|
||||
/* x,y,w,h en mm, font de 1 a PDF_FONT_NB, couleur avec RGB(r,g,b) */
|
||||
cr = cr && pdfEchap(e, &ctxPdf->mTmp1, txt);
|
||||
fmtc(e, &ctxPdf->mPage, couleur);
|
||||
dynConcatSz(e, &ctxPdf->mPage, " rg q ", DYN_LGNONE);
|
||||
fmt4(e, &ctxPdf->mPage, x, y, w, h);
|
||||
dynConcatSz(e, &ctxPdf->mPage, " re W n BT /F", DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPage, Int64ToSz(e, font, FALSE, DYN_NONE), DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPage, " ", DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPage, Int64ToSz(e, taille, FALSE, DYN_NONE), DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPage, " Tf ", DYN_LGNONE);
|
||||
fmt2(e, &ctxPdf->mPage, x, y);
|
||||
dynConcatSz(e, &ctxPdf->mPage, " Td 2 Ts (", DYN_LGNONE);
|
||||
dynConcat(e, &ctxPdf->mPage, &ctxPdf->mTmp1);
|
||||
dynConcatSz(e, &ctxPdf->mPage, ") Tj ET Q 0 0 0 rg\r\n", DYN_LGNONE);
|
||||
return cr;
|
||||
}
|
||||
|
||||
int setPdfGraph(env * e, modContextPdf * ctxPdf, char type, long x, long y, long w, long h, long coul_trait, long coul_rempl, long epaisseur, long pointille)
|
||||
{
|
||||
int cr = TRUE;
|
||||
/* x,y,w,h en mm, font de 1 a PDF_FONT_NB, coul_trait/coul_rempl avec RGB(r,g,b), epaisseur et pointille de 0 a 9 */
|
||||
/* si couleur = -1, ne pas tenir compte */
|
||||
/* type: L ligne C cadre R remplissage D cadre+remplissage */
|
||||
dynConcatSz(e, &ctxPdf->mPage, "q ", DYN_LGNONE);
|
||||
if(coul_trait != -1)
|
||||
{
|
||||
fmtc(e, &ctxPdf->mPage, coul_trait);
|
||||
dynConcatSz(e, &ctxPdf->mPage, " RG ", DYN_LGNONE);
|
||||
}
|
||||
if(coul_rempl != -1 && type != 'L') /* pas de remplissage si trace de ligne... */
|
||||
{
|
||||
fmtc(e, &ctxPdf->mPage, coul_rempl);
|
||||
dynConcatSz(e, &ctxPdf->mPage, " rg ", DYN_LGNONE);
|
||||
}
|
||||
if(pointille > 0)
|
||||
{
|
||||
dynConcatSz(e, &ctxPdf->mPage, "[", DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPage, Int64ToSz(e, pointille % 10, FALSE, DYN_NONE), DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPage, "] 0 d ", DYN_LGNONE);
|
||||
}
|
||||
else
|
||||
dynConcatSz(e, &ctxPdf->mPage, "[] 0 d ", DYN_LGNONE);
|
||||
//
|
||||
if(epaisseur > 0)
|
||||
{
|
||||
dynConcatSz(e, &ctxPdf->mPage, Int64ToSz(e, epaisseur % 10, FALSE, DYN_NONE), DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPage, " w ", DYN_LGNONE);
|
||||
}
|
||||
//
|
||||
if(type == 'L')
|
||||
{
|
||||
fmt2(e, &ctxPdf->mPage, x, y);
|
||||
dynConcatSz(e, &ctxPdf->mPage, " m ", DYN_LGNONE);
|
||||
fmt2(e, &ctxPdf->mPage, x + w, y + h);
|
||||
dynConcatSz(e, &ctxPdf->mPage, " l S Q\r\n", DYN_LGNONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt4(e, &ctxPdf->mPage, x, y, w, h);
|
||||
dynConcatSz(e, &ctxPdf->mPage, " re ", DYN_LGNONE);
|
||||
if(type == 'R')
|
||||
dynConcatSz(e, &ctxPdf->mPage, "f Q\r\n", DYN_LGNONE); /* remplissage */
|
||||
else
|
||||
if(type == 'D')
|
||||
dynConcatSz(e, &ctxPdf->mPage, "B Q\r\n", DYN_LGNONE); /* cadre+remplissage */
|
||||
else
|
||||
dynConcatSz(e, &ctxPdf->mPage, "S Q\r\n", DYN_LGNONE); /* par defaut : cadre seul */
|
||||
}
|
||||
return cr;
|
||||
}
|
||||
|
||||
int setPdfImage(env * e, modContextPdf * ctxPdf, long x, long y, long img)
|
||||
{
|
||||
int cr = TRUE;
|
||||
/* x,y en mm, image numero <img> */
|
||||
dynConcatSz(e, &ctxPdf->mPage, "q ", DYN_LGNONE);
|
||||
dynField(e, &ctxPdf->mImg, &ctxPdf->mTmp1, img, 1, cFM, cVM, 1); // vm1 = larg (w) VM2 = haut (h) VM3 = bitmap 32bpp hexa RGB
|
||||
dynConcat(e, &ctxPdf->mPage, &ctxPdf->mTmp1);
|
||||
dynConcatSz(e, &ctxPdf->mPage, " 0 0 ", DYN_LGNONE);
|
||||
dynField(e, &ctxPdf->mImg, &ctxPdf->mTmp1, img, 2, cFM, cVM, 1); // vm1 = larg (w) VM2 = haut (h) VM3 = bitmap 32bpp hexa RGB
|
||||
dynConcat(e, &ctxPdf->mPage, &ctxPdf->mTmp1);
|
||||
dynConcatSz(e, &ctxPdf->mPage, " ", DYN_LGNONE);
|
||||
fmt2(e, &ctxPdf->mPage, x, y);
|
||||
dynConcatSz(e, &ctxPdf->mPage, " cm /Img", DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPage, Int64ToSz(e, img, FALSE, DYN_NONE), DYN_LGNONE);
|
||||
dynConcatSz(e, &ctxPdf->mPage, " Do Q\r\n", DYN_LGNONE);
|
||||
return cr;
|
||||
}
|
||||
|
||||
/* debug TODO ---------------------------------------- */
|
||||
//int pdfChargeImageRGB(env * e, Dynamic * pixel)
|
||||
//{
|
||||
// /* TODO png, jpeg,... en amont*/
|
||||
// return TRUE;
|
||||
//}
|
||||
//
|
||||
//int pdfChargeImageBmp(env * e, char * fichier)
|
||||
//{
|
||||
// long bpp, larg, haut, offset, par_ligne;
|
||||
// char * p; /* pour simplifier le code... */
|
||||
// long i, j, pos;
|
||||
// /* lecture fichier */
|
||||
// if(!ctxPdf->mTmp1.read(fichier))
|
||||
// return FALSE;
|
||||
// // controle du bitmap avant memorisation
|
||||
// p = ctxPdf->mTmp1.getPtr();
|
||||
// if(p[0] != 'B' && p[1] != 'M')
|
||||
// return FALSE; /* pas un fichier .bmp */
|
||||
// //
|
||||
// bpp = p[28];
|
||||
// if(bpp != 24 && bpp != 32)
|
||||
// return FALSE; /* uniquement les fichiers bmp encodes en 24bpp ou 32bpp */
|
||||
// bpp = bpp >> 3;
|
||||
// /* */
|
||||
// offset = (p[11]<<8) + p[10];
|
||||
// larg = (p[19]<<8) + p[18];
|
||||
// haut = (p[23]<<8) + p[22];
|
||||
// par_ligne = larg * bpp; /* nb octets par ligne */
|
||||
// if((par_ligne&3) != 0)
|
||||
// par_ligne += (4 - (par_ligne&3));
|
||||
// /* la bitmap en hexa fera une taille de larg*haut*3*2 */
|
||||
// if(!ctxPdf->mImg.ctrl(ctxPdf->mImg.getLen() + larg * haut * 6 + 13, TRUE)) /* 13: inclut largeur/hauteur et séparateurs FM VM */
|
||||
// return FALSE;
|
||||
// //
|
||||
// if(ctxPdf->mImg.getLen() != 0)
|
||||
// {
|
||||
// ctxPdf->mImg.concat(sFM);
|
||||
// }
|
||||
// ctxPdf->mImg.concat(larg, "%ld" sVM);
|
||||
// ctxPdf->mImg.concat(haut, "%ld" sVM);
|
||||
// // boucle sur chaque pixel
|
||||
// for(i = haut-1; i >= 0; i--)
|
||||
// for(j = 0; j < larg; j++)
|
||||
// {
|
||||
// pos = offset + j*bpp + i*par_ligne;
|
||||
// ctxPdf->mImg.concat( (((p[pos+2]<<8)+p[pos+1])<<8)+p[pos], "%6X");
|
||||
// }
|
||||
// return TRUE;
|
||||
//}
|
||||
//
|
||||
//int pdfList(env * e, char * titre, Dynamic & lignes, long format, long compression)
|
||||
//{
|
||||
// long nbPage, nbLig, nbLigPage, nbColPage;
|
||||
// long iPage, iLig, iPos;
|
||||
// long tmp;
|
||||
// // enchaine automatiquement les fonctions pour creer un pdf de type "listing" (log ou programme)
|
||||
// // police Courrier taille 9 en A4 =>
|
||||
// // paysage : 60 lignes 145 colonnes
|
||||
// // portrait : 87 lignes 99 colonnes
|
||||
// if(format == PDF_A4P)
|
||||
// {
|
||||
// // portrait
|
||||
// nbLigPage = 87;
|
||||
// nbColPage = 99;
|
||||
// }
|
||||
// else if(format == PDF_A4L)
|
||||
// {
|
||||
// // paysage (Landscape)
|
||||
// nbLigPage = 60;
|
||||
// nbColPage = 145;
|
||||
// }
|
||||
// else
|
||||
// return FALSE; // format non pris en charge
|
||||
// //
|
||||
// lignes.erase("\r");
|
||||
// nbLig = lignes.dcount(10); // \n
|
||||
// if(nbLig == 0)
|
||||
// nbPage = 1;
|
||||
// else
|
||||
// nbPage = (nbLig - 1) / nbLigPage + 1;
|
||||
// //
|
||||
// if(!ctxPdf->nouveau(titre, nbPage, format))
|
||||
// return FALSE; // erreur
|
||||
// //
|
||||
// iPos = 1;
|
||||
// for(iPage = 1; iPage <= nbPage; iPage++)
|
||||
// {
|
||||
// //if(logo_societe(mLarg * 10 / mRatio - 20, mHaut * 10 / mRatio - 20))
|
||||
// // ctxPdf->mPage.concat(mTmp1);
|
||||
// ctxPdf->mPage.concat("BT /F1 9 Tf ");
|
||||
// ctxPdf->mPage.concat(ctxPdf->mRatio * mLmarg / 100, "%ld.");
|
||||
// ctxPdf->mPage.concat(ctxPdf->mRatio * mLmarg % 100, "%ld ");
|
||||
// tmp = mHaut * 10 - (ctxPdf->mRatio * mHmarg);
|
||||
// ctxPdf->mPage.concat(tmp / 100, "%ld.");
|
||||
// ctxPdf->mPage.concat(tmp % 100, "%ld");
|
||||
// ctxPdf->mPage.concat(" Td 9 TL\r\n");
|
||||
// //
|
||||
// for(iLig = 1; iLig <= nbLigPage && iPos <= nbLig; iLig++)
|
||||
// {
|
||||
// lignes.field(10, iPos++, mTmp1); // 10 = \n
|
||||
// mTmp1.substr(0, nbColPage, mTmp2); // tronque au nb de colonnes max
|
||||
// ctxPdf->echap_txt(mTmp1, mTmp2.getPtr());
|
||||
// ctxPdf->mPage.concat("(");
|
||||
// ctxPdf->mPage.concat(mTmp1);
|
||||
// ctxPdf->mPage.concat(") '\r\n");
|
||||
// }
|
||||
// //
|
||||
// ctxPdf->mPage.concat("ET\r\n");
|
||||
// //
|
||||
// if(!ctxPdf->page(compression))
|
||||
// return FALSE; // erreur
|
||||
// }
|
||||
// //
|
||||
// return ctxPdf->termine();
|
||||
//}
|
||||
|
||||
/* ******************************************************** */
|
||||
+6
-6
@@ -114,7 +114,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
//
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
/* les 4 fonctions suivantes doivent toujours exister dans chaque module */
|
||||
if(strncmp(e->fn, "init", 4) == 0)
|
||||
if(modFnIs(e, "init", 4))
|
||||
{
|
||||
// alloc ptr sur zone memoire pour memoriser l'etat du module
|
||||
*etat = memalloc(e, sizeof(modEtat));
|
||||
@@ -129,7 +129,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
//
|
||||
}
|
||||
}
|
||||
else if(strncmp(e->fn, "end", 3) == 0)
|
||||
else if(modFnIs(e, "end", 3))
|
||||
{
|
||||
//*** code specifique ici
|
||||
//
|
||||
@@ -137,7 +137,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
if(p_etat != NULL)
|
||||
memfree(e, p_etat);
|
||||
}
|
||||
else if(strncmp(e->fn, "vers", 4) == 0)
|
||||
else if(modFnIs(e, "vers", 4))
|
||||
{
|
||||
if(param1 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
@@ -152,7 +152,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
exc = EX_MODPARAM; // variable en parametre du mauvais type
|
||||
}
|
||||
}
|
||||
else if(strncmp(e->fn, "error", 5) == 0)
|
||||
else if(modFnIs(e, "error", 5))
|
||||
{
|
||||
// renvoie la derniere erreur specifique au module
|
||||
if(p_etat == NULL)
|
||||
@@ -168,7 +168,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(strncmp(e->fn, "setSeed", 7) == 0)
|
||||
else if(modFnIs(e, "setSeed", 7))
|
||||
{
|
||||
if(param1 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
@@ -180,7 +180,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(strncmp(e->fn, "get", 3) == 0)
|
||||
else if(modFnIs(e, "get", 3))
|
||||
{
|
||||
if(param1 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
|
||||
@@ -0,0 +1,353 @@
|
||||
/* **********************************************
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
W language is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version (GPL-3.0-or-later).
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
********************************************** */
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// TODO version windows
|
||||
#ifdef UNIX
|
||||
#include <dirent.h>
|
||||
#include <sys/types.h>
|
||||
#else
|
||||
#include "windows.h" // pour les fonctions FindFile...
|
||||
#endif
|
||||
|
||||
#include "langage.h"
|
||||
#include "dynamic.h"
|
||||
#include "rep.h"
|
||||
|
||||
long ScanDirectory(env * e, const char * path, Dynamic * directory, const char * fileToSearch, Dynamic * fileFound, long * fileFoundCount, long * duplicateCount)
|
||||
{
|
||||
if(!e || !directory || !fileFound || !fileFoundCount || !duplicateCount)
|
||||
return 0; // error
|
||||
//
|
||||
// non-recursive method : scan <path> and save each directory in <directory>'s fields. Then scan each directory and save subdirectories, in <directory>'s fields, at the end.
|
||||
// And so on for each newly saved subdirectories. Finally, <directory>'s fields will contain all directories and subdirectories within <path>
|
||||
// if <path> is null, <directory> already contains the list of directory to scan, else directory is setup with the directory tree.
|
||||
// if <fileToSearch> is not null : <fileFound> is filled (within fields) with the full path name of each file name found.
|
||||
// <fileFoundCount> contains the number of times the file was found (i.e. <fileFound> field's number)
|
||||
// if <fileToSearch> is equal to "*" : means to check for duplicate files within the whole directory tree (<duplicateCount> gives the number of it),
|
||||
// and so <fileFound> will contains all filenames (without path)
|
||||
//
|
||||
if(path)
|
||||
dynSetAsSz(e, directory, (char *)path);
|
||||
long nb = dynDcount(e, directory, cFM, DYN_NONE, DYN_NONE), done = 0;
|
||||
//
|
||||
#ifdef UNIX
|
||||
DIR * dir = NULL;
|
||||
struct dirent * entry = NULL;
|
||||
#else
|
||||
HANDLE hFind;
|
||||
WIN32_FIND_DATA FindFileData;
|
||||
#endif
|
||||
//
|
||||
Dynamic workPath;
|
||||
dynInit(e, &workPath, DYN_LGMIN);
|
||||
//
|
||||
*duplicateCount = 0;
|
||||
*fileFoundCount = 0;
|
||||
if(fileToSearch)
|
||||
dynSetLen(e, fileFound, 0);
|
||||
//
|
||||
while(nb > done)
|
||||
{
|
||||
long newNb = nb;
|
||||
for(long ind = done + 1; ind <= nb; ind++)
|
||||
{
|
||||
//dynExtractField(e, directory, ind, &workPath);
|
||||
dynField(e, directory, &workPath, ind, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
// read each entry in directory and save subdirectory name (full path)
|
||||
// TODO !? => check that workPath hasn't yet been scanned (e.g. directory link with circular reference)
|
||||
#ifdef UNIX
|
||||
if((dir = opendir(workPath.mPtr)) == NULL)
|
||||
{
|
||||
// continue to next item (no access right for example for this directory, etc.)
|
||||
//dynFree(e, &workPath);
|
||||
//return 0;
|
||||
continue;
|
||||
}
|
||||
while ((entry = readdir(dir)) != NULL)
|
||||
{
|
||||
if(path)
|
||||
{
|
||||
if(entry->d_type == DT_DIR && strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0)
|
||||
{
|
||||
newNb++;
|
||||
dynStore(e, directory, newNb, DYN_NONE, &workPath, cFM, DYN_NONE);
|
||||
if(workPath.mLg > 0 && workPath.mPtr[workPath.mLg - 1] != '/')
|
||||
dynConcatSz(e, directory, "/", 1);
|
||||
dynConcatSz(e, directory, entry->d_name, DYN_LGNONE);
|
||||
}
|
||||
}
|
||||
// check "regular" files (DT_REG si linux specific)
|
||||
if(fileToSearch)
|
||||
{
|
||||
if(entry->d_type == DT_REG && *fileToSearch == '*')
|
||||
{
|
||||
long pos = dynLocateSz(e, fileFound, entry->d_name, cFM, DYN_NONE, DYN_NONE);
|
||||
if(pos > 0)
|
||||
(*duplicateCount)++; // duplicate found
|
||||
else
|
||||
{
|
||||
(*fileFoundCount)++;
|
||||
dynStoreSz(e, fileFound, *fileFoundCount, DYN_NONE, entry->d_name, DYN_LGNONE, cFM, DYN_NONE); // duplicate checking doesn't take care of the file's path
|
||||
}
|
||||
}
|
||||
else if(entry->d_type == DT_REG && strcmp(entry->d_name, fileToSearch) == 0)
|
||||
{
|
||||
// file found
|
||||
(*fileFoundCount)++; // found, save file's directory
|
||||
dynStore(e, fileFound, *fileFoundCount, DYN_NONE, &workPath, cFM, DYN_NONE);
|
||||
if(workPath.mLg > 0 && workPath.mPtr[workPath.mLg - 1] != '/')
|
||||
dynConcatSz(e, fileFound, "/", 1);
|
||||
dynConcatSz(e, fileFound, entry->d_name, DYN_LGNONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
// end readdir
|
||||
#else
|
||||
dynConcatSz(e, &workPath, "\\*", DYN_LGNONE); /* sinon ko... */
|
||||
if((hFind = FindFirstFile(workPath.mPtr, &FindFileData)) == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
// continue to next item (no access right for example for this directory, etc.)
|
||||
//dynFree(e, &workPath);
|
||||
//return 0;
|
||||
continue;
|
||||
}
|
||||
dynSetLen(e, &workPath, workPath.mLg - 2); // enlever \* mis a la fin...
|
||||
for(int cr = -1;cr != 0;)
|
||||
{
|
||||
if(path)
|
||||
{
|
||||
if((FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && strcmp(FindFileData.cFileName,".") != 0 && strcmp(FindFileData.cFileName,"..") != 0)
|
||||
{
|
||||
newNb++;
|
||||
dynStore(e, directory, newNb, DYN_NONE, &workPath, cFM, DYN_NONE);
|
||||
if(workPath.mLg > 0 && workPath.mPtr[workPath.mLg - 1] != '\\')
|
||||
dynConcatSz(e, directory, "\\", 1);
|
||||
dynConcatSz(e, directory, FindFileData.cFileName, DYN_LGNONE);
|
||||
}
|
||||
}
|
||||
// check "regular" files (DT_REG si linux specific)
|
||||
if(fileToSearch)
|
||||
{
|
||||
if( !(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
|
||||
!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) &&
|
||||
!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) &&
|
||||
!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
|
||||
if( *fileToSearch == '*')
|
||||
{
|
||||
long pos = dynLocateSz(e, fileFound, FindFileData.cFileName, cFM, DYN_NONE, DYN_NONE);
|
||||
if(pos > 0)
|
||||
(*duplicateCount)++; // duplicate found
|
||||
else
|
||||
{
|
||||
(*fileFoundCount)++;
|
||||
dynStoreSz(e, fileFound, *fileFoundCount, DYN_NONE, FindFileData.cFileName, DYN_LGNONE, cFM, DYN_NONE); // duplicate checking doesn't take care of the file's path
|
||||
}
|
||||
}
|
||||
else if(strcmp(FindFileData.cFileName, fileToSearch) == 0)
|
||||
{
|
||||
// file found
|
||||
(*fileFoundCount)++; // found, save file's directory
|
||||
dynStore(e, fileFound, *fileFoundCount, DYN_NONE, &workPath, cFM, DYN_NONE);
|
||||
if(workPath.mLg > 0 && workPath.mPtr[workPath.mLg - 1] != '\\')
|
||||
dynConcatSz(e, fileFound, "\\", 1);
|
||||
dynConcatSz(e, fileFound, FindFileData.cFileName, DYN_LGNONE);
|
||||
}
|
||||
}
|
||||
//
|
||||
cr = FindNextFile(hFind, &FindFileData);
|
||||
}
|
||||
FindClose(hFind);
|
||||
#endif
|
||||
}
|
||||
done = nb;
|
||||
nb = newNb;
|
||||
}
|
||||
dynFree(e, &workPath);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int GetInclude(env * e, Dynamic * line, Dynamic * includeFilename)
|
||||
{
|
||||
// check that the <line> is a include w statement. If not, return zero, else
|
||||
// return in <includeFilename> the name of the include file
|
||||
// separators are 9 and 32 (tab and space) and ";"" for the optional end of line comment
|
||||
char * p = line->mPtr, * q;
|
||||
while(*p && (*p == 9 || *p == 32)) p++;
|
||||
if(*p++ != 'i') return 0;
|
||||
if(*p++ != 'n') return 0;
|
||||
if(*p++ != 'c') return 0;
|
||||
if(*p++ != 'l') return 0;
|
||||
if(*p++ != 'u') return 0;
|
||||
if(*p++ != 'd') return 0;
|
||||
if(*p++ != 'e') return 0;
|
||||
if(*p != 9 && *p != 32) return 0;
|
||||
p++;
|
||||
while(*p && (*p == 9 || *p == 32)) p++;
|
||||
q = p; // *p is the first char of include filename (except if *p is null)
|
||||
while(*q && (*q != 9 && *q != 32 && *q != ';')) q++;
|
||||
// *q is the last char of include filename
|
||||
if( (! *p) || *p == ';') return 0;
|
||||
if(*q == ';') q--;
|
||||
// find it : copy do includeFilename
|
||||
long lg = q - p + 1;
|
||||
dynLet(e, includeFilename, p, lg);
|
||||
dynSetLen(e, includeFilename, lg); // to be sure that \0 ends the filename
|
||||
dynErase(e, includeFilename, "'\"");
|
||||
return 1;
|
||||
}
|
||||
|
||||
long GetSource(env * e, const char * wsrc, const char * filename, Dynamic * source, Dynamic * meta)
|
||||
{
|
||||
int cr = 0;
|
||||
char cLF = 10;
|
||||
dynSetLen(e, source, 0);
|
||||
dynSetLen(e, meta, 0);
|
||||
//
|
||||
Dynamic directory, fileFound, line, include, tmp;
|
||||
dynInit(e, &directory, DYN_LGMIN);
|
||||
dynInit(e, &fileFound, DYN_LGMIN);
|
||||
dynInit(e, &line, DYN_LGMIN);
|
||||
dynInit(e, &include, DYN_LGMIN);
|
||||
dynInit(e, &tmp, DYN_LGMIN);
|
||||
//
|
||||
long fileCount, dup;
|
||||
for(;;)
|
||||
{
|
||||
if(dynRead(e, source, (char *)filename) != DYN_OK)
|
||||
break;
|
||||
if( ! ScanDirectory(e, wsrc, &directory, NULL, &fileFound, &fileCount, &dup))
|
||||
break;
|
||||
//
|
||||
long level = 1, current = 1;
|
||||
dynStoreSz(e, meta, 1, DYN_NONE, "00000001", 8, cFM, DYN_NONE);
|
||||
dynStoreSz(e, meta, 2, DYN_NONE, (char *)filename, DYN_LGNONE, cFM, DYN_NONE);
|
||||
dynStoreSz(e, meta, 3, DYN_NONE, (char *)filename, DYN_LGNONE, cFM, DYN_NONE);
|
||||
// foreach source line
|
||||
long numberOfLines = dynDcount(e, source, cLF, DYN_NONE, DYN_NONE);
|
||||
long numLine = 1;
|
||||
for( ;numLine <= numberOfLines; )
|
||||
{
|
||||
dynField(e, source, &line, numLine, DYN_NONE, cLF, DYN_NONE, 1);
|
||||
numLine++;
|
||||
if(GetInclude(e, &line, &include))
|
||||
{
|
||||
//printf("include: %s\n", include.mPtr);
|
||||
if(ScanDirectory(e, NULL, &directory, include.mPtr, &fileFound, &fileCount, &dup))
|
||||
{
|
||||
//printf("nb found %ld: %s\n", fileCount, fileFound.mPtr);
|
||||
if(fileCount == 1)
|
||||
{
|
||||
// memo include file tree to avoid cyclic includes and get meta data
|
||||
// 2 memos : one for call tree, and one for the map of files/number of lines
|
||||
// call tree =>
|
||||
// meta<3> = file tree, multi-valued filenames
|
||||
// meta data =>
|
||||
// meta<1> = beginning number of line
|
||||
// meta<2> = filename
|
||||
//
|
||||
// if filename already presents in file tree, error (ignore include)
|
||||
if(dynLocateSz(e, meta, fileFound.mPtr, cVM, 3, cFM) > 0)
|
||||
continue;
|
||||
// insert include file after include's line
|
||||
dynRead(e, &include, fileFound.mPtr);
|
||||
if(include.mLg == 0)
|
||||
continue; // don't insert empty file
|
||||
// suppress last character if LF : prevent blank line in result
|
||||
if(include.mPtr[include.mLg - 1] == cLF)
|
||||
dynSetLen(e, &include, include.mLg - 1);
|
||||
//
|
||||
// TODO : insert ENDINCLUDE pseudo code at the end of inserted include ? or only when generating pcode ! see with assembler.c
|
||||
dynIns(e, source, numLine, DYN_NONE, &include, cLF, DYN_NONE);
|
||||
long nbInclude = dynDcount(e, &include, cLF, DYN_NONE, DYN_NONE);
|
||||
numberOfLines = dynDcount(e, source, cLF, DYN_NONE, DYN_NONE);
|
||||
//printf("inc ok %s nbinclude %ld nbline %ld current %ld\n", fileFound.mPtr, nbInclude, numberOfLines, numLine);
|
||||
// put in <include> the line number formatted 00000000 and split current block in three
|
||||
dynFmtNumber(e, numLine, &include, 'R', '0', 8);
|
||||
long pos = abs(dynSortLocateSz(e, meta, include.mPtr, cVM, DYN_SORT_ASC, 1, cFM));
|
||||
dynIns(e, meta, 1, pos, &include, cFM, cVM);
|
||||
dynIns(e, meta, 2, pos, &fileFound, cFM, cVM);
|
||||
//
|
||||
//dynExtractSubField(e, meta, 2, pos - 1, &include); // ko si separateurs changent...
|
||||
dynField(e, meta, &include, 2, pos - 1, cFM, cVM, 1);
|
||||
dynIns(e, meta, 2, pos + 1, &include, cFM, cVM);
|
||||
dynFmtNumber(e, numLine + nbInclude, &include, 'R', '0', 8);
|
||||
dynIns(e, meta, 1, pos + 1, &include, cFM, cVM);
|
||||
//
|
||||
// adjust starting line of next blocks
|
||||
long nbMeta = dynDcount(e, meta, cVM, 2, cFM);
|
||||
for(long cpt = pos + 2; cpt <= nbMeta; cpt++)
|
||||
{
|
||||
//long num = dynExtractSubFieldAsNumber(e, meta, 1, cpt, &include) + nbInclude;
|
||||
long num = dynFieldAsNumber(e, meta, 1, cpt, cFM, cVM) + nbInclude;
|
||||
dynFmtNumber(e, num, &include, 'R', '0', 8);
|
||||
dynStore(e, meta, 1, cpt, &include, cFM, cVM);
|
||||
}
|
||||
//
|
||||
dynStore(e, meta, 3, ++level, &fileFound, cFM, cVM);
|
||||
current++;
|
||||
}
|
||||
// if fileCount > 1, error (ignore include)
|
||||
}
|
||||
// if error while searching for the include file, error (ignore include)
|
||||
}
|
||||
// delete last file in call tree when changing of file
|
||||
// dynSetAsNumber(e, &tmp, numLine);
|
||||
//dynFmt(e, &tmp, &include, 'R', '0', 8); // TODO dynFmtNumber
|
||||
dynFmtNumber(e, numLine, &include, 'R', '0', 8);
|
||||
long pos = dynSortLocateSz(e, meta, include.mPtr, cVM, DYN_SORT_ASC, 1, cFM);
|
||||
if(pos != current && level > 0)
|
||||
{
|
||||
current = pos;
|
||||
dynDel(e, meta, 3, level--, cFM, cVM, 1);
|
||||
}
|
||||
}
|
||||
dynDel(e, meta, 3, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
cr = 1;
|
||||
break;
|
||||
}
|
||||
//
|
||||
dynFree(e, &directory);
|
||||
dynFree(e, &fileFound);
|
||||
dynFree(e, &line);
|
||||
dynFree(e, &include);
|
||||
dynFree(e, &tmp);
|
||||
return cr;
|
||||
}
|
||||
|
||||
void GetFile(env * e, long lineNumber, Dynamic * meta, int indice, Dynamic * fileFound)
|
||||
{
|
||||
indice *= 2;
|
||||
dynFmtNumber(e, lineNumber, fileFound, 'R', '0', 8);
|
||||
long pos = dynSortLocateSz(e, meta, fileFound->mPtr, cVM, DYN_SORT_ASC, indice - 1, cFM);
|
||||
if(pos < 0)
|
||||
{
|
||||
pos = abs(pos) - 1;
|
||||
if(pos < 1) pos = 1; // securite
|
||||
}
|
||||
dynSetLen(e, fileFound, 0);
|
||||
dynField(e, meta, fileFound, indice, pos, cFM, cVM, 1);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/* **********************************************
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024,2025 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
W language is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version (GPL-3.0-or-later).
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
********************************************** */
|
||||
#ifndef REP_H
|
||||
#define REP_H
|
||||
|
||||
long ScanDirectory(env * e, const char * path, Dynamic * directory, const char * fileToSearch, Dynamic * fileFound, long * fileFoundCount, long * duplicateCount);
|
||||
long GetSource(env * e, const char * wsrc, const char * filename, Dynamic * source, Dynamic * meta);
|
||||
|
||||
void GetFile(env * e, long lineNumber, Dynamic * meta, int indice, Dynamic * fileFound);
|
||||
|
||||
/* ********************************************** */
|
||||
#endif
|
||||
@@ -0,0 +1,67 @@
|
||||
/* **********************************************
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024,2025 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
W language is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version (GPL-3.0-or-later).
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
********************************************** */
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef WINLIB
|
||||
#include <sys/types.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#else
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "langage.h"
|
||||
|
||||
#ifdef WINLIB
|
||||
typedef int key_t;
|
||||
#endif
|
||||
|
||||
/* codes a passer a la fonction setError */
|
||||
#define EXMOD_BUFFER_INIT 1
|
||||
#define EXMOD_BUFFER_WRITE 2
|
||||
|
||||
typedef struct {
|
||||
// proprietaire
|
||||
key_t cle;
|
||||
char nom[24]; // 23 cars + \0
|
||||
long taille;
|
||||
var * buffer;
|
||||
#ifndef WINLIB
|
||||
int handle;
|
||||
int semId;
|
||||
#else
|
||||
HANDLE handle;
|
||||
char semDesti[25]; // 23 cars + '#' + \0 (different desti sinon ko sous windows)
|
||||
#endif
|
||||
// destinataire
|
||||
char desti[24]; // 23 cars + \0
|
||||
// message lu/ecrit
|
||||
var * message;
|
||||
} modContextShm;
|
||||
|
||||
void initShm(env * e, modContextShm * ctx);
|
||||
void freeShm(env * e, modContextShm * ctx);
|
||||
long readShm(env * e, modContextShm * ctx);
|
||||
long writeShm(env * e, modContextShm * ctx);
|
||||
@@ -0,0 +1,175 @@
|
||||
/* **********************************************
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024,2025 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
W language is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version (GPL-3.0-or-later).
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
********************************************** */
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "langage.h"
|
||||
#include "dynamic.h"
|
||||
#include "hashtable.h"
|
||||
|
||||
#include "shm.h"
|
||||
|
||||
typedef struct {
|
||||
int error; // dernier code erreur specifique au module
|
||||
//*** a completer selon le besoin du module
|
||||
modContextShm cs;
|
||||
|
||||
} modEtat;
|
||||
|
||||
static int setError(modEtat * p, int err)
|
||||
{
|
||||
if(p != NULL)
|
||||
p->error = err;
|
||||
return err == OK ? OK : EX_MODERR;
|
||||
}
|
||||
|
||||
#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 * param1, var * param2, var * param3, void ** etat)
|
||||
#else
|
||||
extern long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
|
||||
#endif
|
||||
{
|
||||
/* TODO : gestion des 3 parametres (au lieu d'un seul) */
|
||||
modEtat * p_etat;
|
||||
long exc = OK;
|
||||
// init/end/vers/error sont obligatoires pour tout module
|
||||
// - - - - - - - - - - - - - - - - - - - -
|
||||
if(etat == NULL)
|
||||
return EX_MODPARAM;
|
||||
else
|
||||
p_etat = (modEtat *)(*etat); /* evite de la 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 */
|
||||
if(modFnIs(e, "init", 4))
|
||||
{
|
||||
// alloc ptr sur zone memoire pour memoriser l'etat du module
|
||||
*etat = memalloc(e, sizeof(modEtat));
|
||||
if(*etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else
|
||||
{
|
||||
p_etat = (modEtat *)(*etat);
|
||||
p_etat->error = 0;
|
||||
//*** code specifique ici
|
||||
var * prog;
|
||||
hashtable_do(e, HASH_READ, &e->g, copy_nom(e, "_prog"), &prog);
|
||||
// maj ctx avec _prog et taille
|
||||
*((ent64 *)(p_etat->cs.nom)) = 0;
|
||||
*(((ent64 *)(p_etat->cs.nom)) + 1) = 0;
|
||||
*(((ent64 *)(p_etat->cs.nom)) + 2) = 0;
|
||||
if(prog && prog->type == VAR_DYNAMIC && prog->mLg < 24)
|
||||
strncpy(p_etat->cs.nom, prog->mPtr, prog->mLg);
|
||||
p_etat->cs.taille = 4000;
|
||||
//
|
||||
initShm(e, &p_etat->cs);
|
||||
}
|
||||
}
|
||||
else if(modFnIs(e, "end", 3))
|
||||
{
|
||||
// liberation specifique au module avant arret process
|
||||
if(p_etat != NULL)
|
||||
{
|
||||
freeShm(e, &p_etat->cs);
|
||||
//*** FIN du code specifique ici
|
||||
memfree(e, p_etat);
|
||||
}
|
||||
}
|
||||
else if(modFnIs(e, "vers", 4))
|
||||
{
|
||||
// renvoie la version du module/plugins
|
||||
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
|
||||
}
|
||||
else if(modFnIs(e, "error", 5))
|
||||
{
|
||||
// renvoie la derniere erreur specifique au module
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else
|
||||
{
|
||||
if(param1->type == VAR_NUMBER)
|
||||
param1->num = (ent64)(NUM_FACTEUR * p_etat->error);
|
||||
else
|
||||
exc = EX_MODPARAM; // variable en parametre du mauvais type
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(modFnIs(e, "get", 3))
|
||||
{
|
||||
if(!param1)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
p_etat->cs.message = param1;
|
||||
exc = setError(p_etat, readShm(e, &p_etat->cs));
|
||||
// param1 vide si rien a lire
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(modFnIs(e, "set", 3))
|
||||
{
|
||||
if(!param1 || !param2)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_DYNAMIC || param2->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
*((ent64 *)(p_etat->cs.desti)) = 0;
|
||||
*(((ent64 *)(p_etat->cs.desti)) + 1) = 0;
|
||||
*(((ent64 *)(p_etat->cs.desti)) + 2) = 0;
|
||||
if(param1->mLg < 24)
|
||||
strncpy(p_etat->cs.desti, param1->mPtr, param1->mLg);
|
||||
p_etat->cs.message = param2;
|
||||
exc = setError(p_etat, writeShm(e, &p_etat->cs));
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else
|
||||
{
|
||||
exc = setError(p_etat, EX_MODFUNC); // fonction non prise en charge
|
||||
}
|
||||
//
|
||||
return exc;
|
||||
}
|
||||
/* **************************************************************************************************** */
|
||||
@@ -0,0 +1,248 @@
|
||||
/* **********************************************
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024,2025 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
W language is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version (GPL-3.0-or-later).
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
********************************************** */
|
||||
#include "shm.h"
|
||||
|
||||
#include "buffer.h"
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef WINLIB
|
||||
#include <sys/types.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/sem.h>
|
||||
#endif
|
||||
|
||||
#define NBSEM 1
|
||||
|
||||
/* PRIVATE */
|
||||
static key_t Hash32(const char * cle, int lg)
|
||||
{
|
||||
// lg multiple de 4 et > 0
|
||||
// cle est une zone memoire de lg cars
|
||||
ent64 k, h = 0;
|
||||
if(lg > 0 && (lg % 4 == 0))
|
||||
{
|
||||
h = *(int *)cle;
|
||||
for(int i = 0; i < lg; )
|
||||
{
|
||||
k = (ent64)cle[i++];
|
||||
k |= ((ent64)cle[i++]) << 8;
|
||||
k |= ((ent64)cle[i++]) << 16;
|
||||
k |= ((ent64)cle[i++]) << 24;
|
||||
k *= 0xcc9e2d51;
|
||||
k = (k << 15) | (k >> 17); // 32 - 15
|
||||
k *= 0x1b873593;
|
||||
h ^= k;
|
||||
h = (h << 13) | (h >> 19); // 32 - 13
|
||||
h = h * 5 + 0xe6546b64;
|
||||
}
|
||||
}
|
||||
h ^= lg;
|
||||
h ^= h >> 16;
|
||||
h *= 0x85ebca6b;
|
||||
h ^= h >> 13;
|
||||
h *= 0xc2b2ae35;
|
||||
h ^= h >> 16;
|
||||
return (key_t)h;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------- */
|
||||
|
||||
void initShm(env * e, modContextShm * ctx)
|
||||
{
|
||||
#ifndef WINLIB
|
||||
ctx->buffer = NULL;
|
||||
ctx->handle = -1;
|
||||
ctx->semId = -1;
|
||||
// creer la sharedmemory du process, pour lecture
|
||||
// ne pas controler la taille, sera fait par 'shmget'
|
||||
// calculer la cle a partir du nom du prog (ctx->nom)
|
||||
ctx->cle = Hash32(ctx->nom, 24); // chaine de 23 cars max + \0 de fin
|
||||
// creer le buffer
|
||||
ctx->handle = shmget(ctx->cle, ctx->taille, IPC_CREAT | IPC_EXCL | 0666); // < 0 si ko
|
||||
if(ctx->handle < 0)
|
||||
return; // erreur creation sharedmemory
|
||||
// lire le pointeur
|
||||
ctx->buffer = (var *)shmat(ctx->handle, NULL, 0);
|
||||
if(ctx->buffer == (var *)(-1))
|
||||
{
|
||||
shmctl(ctx->handle, IPC_RMID, NULL);
|
||||
ctx->buffer = NULL;
|
||||
ctx->handle = -1;
|
||||
return; // erreur recup pointeur
|
||||
}
|
||||
// creer le semaphore pour les writers
|
||||
ctx->semId = semget(ctx->cle, NBSEM, IPC_CREAT | IPC_EXCL | 0666); // < 0 si ko
|
||||
if(ctx->semId < 0)
|
||||
{
|
||||
freeShm(e, ctx); // erreur
|
||||
return;
|
||||
}
|
||||
// init semaphore
|
||||
unsigned short table[NBSEM];
|
||||
table[0] = 1;
|
||||
if(semctl(ctx->semId, 0, SETALL, table) < 0)
|
||||
{
|
||||
freeShm(e, ctx); // erreur
|
||||
return;
|
||||
}
|
||||
#else
|
||||
ctx->buffer = NULL;
|
||||
ctx->handle = NULL;
|
||||
strncpy(ctx->semDesti, ctx->desti, 24);
|
||||
ctx->semDesti[24] = 0;
|
||||
ctx->semDesti[strlen(ctx->desti)] = '#';
|
||||
// creer la sharedmemory du process, pour lecture
|
||||
// ne pas controler la taille, sera fait par 'CreateFileMapping'
|
||||
// la cle est directement le nom
|
||||
// creer le buffer
|
||||
ctx->handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, ctx->taille, ctx->nom); // NULL si ko, attention au \0 de fin de ctx->nom
|
||||
if( ! ctx->handle)
|
||||
return; // erreur creation sharedmemory
|
||||
ctx->buffer = (var *)MapViewOfFile(ctx->handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
|
||||
if( ! ctx->buffer)
|
||||
{
|
||||
CloseHandle(ctx->handle);
|
||||
ctx->buffer = NULL;
|
||||
ctx->handle = NULL;
|
||||
return; // erreur recup pointeur
|
||||
}
|
||||
#endif
|
||||
ctx->buffer->type = VAR_BUFFER;
|
||||
ctx->buffer->lgmax = ctx->taille - sizeof(var);
|
||||
ctx->buffer->read = 0;
|
||||
ctx->buffer->write = 0;
|
||||
ctx->buffer->ptr = NULL; // NULL signifie que le contenu est a la suite de l'entete de la variable (utilise uniquement ici avec les IPC)
|
||||
}
|
||||
|
||||
void freeShm(env * e, modContextShm * ctx)
|
||||
{
|
||||
#ifndef WINLIB
|
||||
if(ctx->buffer)
|
||||
shmdt(ctx->buffer);
|
||||
if(ctx->handle >= 0)
|
||||
shmctl(ctx->handle, IPC_RMID, NULL);
|
||||
if(ctx->semId >= 0)
|
||||
semctl(ctx->semId, IPC_RMID, 0);
|
||||
ctx->buffer = NULL;
|
||||
ctx->handle = -1;
|
||||
ctx->semId = -1;
|
||||
#else
|
||||
if(ctx->buffer)
|
||||
UnmapViewOfFile(ctx->buffer);
|
||||
if(ctx->handle >= 0)
|
||||
CloseHandle(ctx->handle); // verif que bien detruit
|
||||
ctx->buffer = NULL;
|
||||
ctx->handle = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
long readShm(env * e, modContextShm * ctx)
|
||||
{
|
||||
#ifndef WINLIB
|
||||
if( ! ctx->buffer || ctx->handle < 0)
|
||||
return EXMOD_BUFFER_INIT;
|
||||
#else
|
||||
if( ! ctx->buffer || ! ctx->handle)
|
||||
return EXMOD_BUFFER_INIT;
|
||||
#endif
|
||||
buffer_read(e, ctx->buffer, ctx->message);
|
||||
// e->exception != OK si exception en lecture (que EX_MEM) ! vide si rien a lire (Dynamic)
|
||||
return e->exception;
|
||||
}
|
||||
|
||||
long writeShm(env * e, modContextShm * ctx)
|
||||
{
|
||||
// TODO gestion verrou !
|
||||
#ifndef WINLIB
|
||||
// calculer la cle a partir du nom du prog (ctx->nom)
|
||||
key_t cle = Hash32(ctx->desti, 24); // chaine de 23 cars + \0
|
||||
// acceder au buffer
|
||||
int handle = shmget(cle, 0, 0);
|
||||
if(handle < 0)
|
||||
return EXMOD_BUFFER_WRITE; // erreur access
|
||||
// lire le pointeur
|
||||
var * buffer = (var *)shmat(handle, NULL, 0);
|
||||
if(buffer == (var *)(-1))
|
||||
return EXMOD_BUFFER_WRITE; // seul le ptr se libere
|
||||
// prendre le verrou (semaphore) pour ecrire, avec attente
|
||||
int semId = semget(cle, NBSEM, 0);
|
||||
if(semId < 0)
|
||||
{
|
||||
shmdt(buffer);
|
||||
return EXMOD_BUFFER_WRITE;
|
||||
}
|
||||
struct sembuf bufw;
|
||||
bufw.sem_num = 0;
|
||||
bufw.sem_op = -1; // prendre
|
||||
bufw.sem_flg = SEM_UNDO; // | IPC_NOWAIT ?
|
||||
if(semop(semId, &bufw, 1) < 0)
|
||||
{
|
||||
shmdt(buffer);
|
||||
return EXMOD_BUFFER_WRITE;
|
||||
}
|
||||
// EcrireBuffer
|
||||
buffer_write(e, buffer, ctx->message);
|
||||
// e->exception != OK si exception en ecriture (que EX_BUFOVF) !
|
||||
// liberer le verrou
|
||||
bufw.sem_op = 1; // liberer
|
||||
semop(semId, &bufw, 1);
|
||||
// ne liberer que le ptr sous unix
|
||||
shmdt(buffer);
|
||||
#else
|
||||
// la cle est directement le destinataire
|
||||
HANDLE handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, ctx->desti); // attention au \0 de fin
|
||||
if( ! handle)
|
||||
return EXMOD_BUFFER_WRITE; // erreur access
|
||||
// lire le pointeur
|
||||
var * buffer = (var *)MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
|
||||
if( ! buffer)
|
||||
{
|
||||
CloseHandle(handle);
|
||||
return EXMOD_BUFFER_WRITE; // erreur recup pointeur
|
||||
}
|
||||
// prendre le verrou (semaphore) pour ecrire, avec attente
|
||||
HANDLE hSem = CreateSemaphore(NULL, 1, 1, ctx->semDesti); // NULL si erreur
|
||||
if( ! hSem)
|
||||
{
|
||||
UnmapViewOfFile(buffer);
|
||||
CloseHandle(handle);
|
||||
return EXMOD_BUFFER_WRITE; // erreur recup pointeur
|
||||
}
|
||||
if(WaitForSingleObject(hSem, 0) != WAIT_OBJECT_0) // retour WAIT_OBJECT_0 si ok, WAIT_TIMEOUT ou autre si pas dispo ou erreur ; 0 = timeout en secondes
|
||||
{
|
||||
ReleaseSemaphore(hSem, 1, NULL);
|
||||
UnmapViewOfFile(buffer);
|
||||
CloseHandle(handle);
|
||||
return EXMOD_BUFFER_WRITE; // erreur recup pointeur
|
||||
}
|
||||
// EcrireBuffer
|
||||
buffer_write(e, buffer, ctx->message);
|
||||
// e->exception != OK si exception en ecriture (que EX_BUFOVF) !
|
||||
// liberer le verrou
|
||||
ReleaseSemaphore(hSem, 1, NULL);
|
||||
// liberations
|
||||
UnmapViewOfFile(buffer);
|
||||
CloseHandle(handle);
|
||||
#endif
|
||||
return e->exception;
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024 lanisys.fr
|
||||
\/ \/ Copyright 2024,2025 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
@@ -86,7 +86,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
//
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
/* les 4 fonctions suivantes doivent toujours exister dans chaque module */
|
||||
if(strncmp(e->fn, "init", 4) == 0)
|
||||
if(modFnIs(e, "init", 4))
|
||||
{
|
||||
// alloc ptr sur zone memoire pour memoriser l'etat du module
|
||||
*etat = memalloc(e, sizeof(modEtat));
|
||||
@@ -101,7 +101,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
p_etat->mServeur = 0;
|
||||
}
|
||||
}
|
||||
else if(strncmp(e->fn, "end", 3) == 0)
|
||||
else if(modFnIs(e, "end", 3))
|
||||
{
|
||||
// liberation specifique au module avant arret process
|
||||
p_etat = (modEtat *)(*etat);
|
||||
@@ -114,7 +114,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
memfree(e, p_etat);
|
||||
}
|
||||
}
|
||||
else if(strncmp(e->fn, "vers", 4) == 0)
|
||||
else if(modFnIs(e, "vers", 4))
|
||||
{
|
||||
// renvoie la version du module/plugins
|
||||
if(param->type == VAR_DYNAMIC)
|
||||
@@ -124,7 +124,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
else
|
||||
exc = EX_MODPARAM; // variable en parametre du mauvais type
|
||||
}
|
||||
else if(strncmp(e->fn, "error", 5) == 0)
|
||||
else if(modFnIs(e, "error", 5))
|
||||
{
|
||||
// renvoie la derniere erreur specifique au module
|
||||
if(p_etat == NULL)
|
||||
@@ -138,7 +138,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(strncmp(e->fn, "server", 6) == 0)
|
||||
else if(modFnIs(e, "server", 6))
|
||||
{
|
||||
/* cree un point d'entree serveur */
|
||||
if(p_etat == NULL)
|
||||
@@ -244,7 +244,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "connect", 7) == 0)
|
||||
else if(modFnIs(e, "connect", 7))
|
||||
{
|
||||
char ** tParam;
|
||||
/* connexion a un serveur */
|
||||
@@ -347,7 +347,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "arret", 5) == 0)
|
||||
else if(modFnIs(e, "arret", 5))
|
||||
{
|
||||
/* arret connexion cliente ou serveur */
|
||||
if(p_etat != NULL)
|
||||
@@ -358,7 +358,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "attente", 7) == 0)
|
||||
else if(modFnIs(e, "attente", 7))
|
||||
{
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
@@ -404,7 +404,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "get", 3) == 0)
|
||||
else if(modFnIs(e, "get", 3))
|
||||
{
|
||||
long nblu = 0, arg = 1, flagInProgress = 0, pas = 16000, would_block;
|
||||
/* lecture sur la connexion */
|
||||
@@ -446,7 +446,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "set", 3) == 0)
|
||||
else if(modFnIs(e, "set", 3))
|
||||
{
|
||||
long nb , pos = 0, lg, would_block;
|
||||
/* ecriture sur la connexion */
|
||||
@@ -481,7 +481,7 @@ extern long execModule(env * e, var * param, var * param2, var * param3, void **
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "accept", 6) == 0)
|
||||
else if(modFnIs(e, "accept", 6))
|
||||
{
|
||||
/* ecriture sur la connexion */
|
||||
if(p_etat == NULL)
|
||||
|
||||
+158
-13
@@ -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)
|
||||
{
|
||||
@@ -98,7 +100,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
//
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
/* les 4 fonctions suivantes doivent toujours exister dans chaque module */
|
||||
if(strncmp(e->fn, "init", 4) == 0)
|
||||
if(modFnIs(e, "init", 4))
|
||||
{
|
||||
// alloc ptr sur zone memoire pour memoriser l'etat du module
|
||||
*etat = memalloc(e, sizeof(modEtat));
|
||||
@@ -111,7 +113,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
//*** code specifique ici
|
||||
}
|
||||
}
|
||||
else if(strncmp(e->fn, "end", 3) == 0)
|
||||
else if(modFnIs(e, "end", 3))
|
||||
{
|
||||
// liberation specifique au module avant arret process
|
||||
if(p_etat != NULL)
|
||||
@@ -120,7 +122,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
memfree(e, p_etat);
|
||||
}
|
||||
}
|
||||
else if(strncmp(e->fn, "vers", 4) == 0)
|
||||
else if(modFnIs(e, "vers", 4))
|
||||
{
|
||||
// renvoie la version du module/plugins
|
||||
if(param1->type == VAR_DYNAMIC)
|
||||
@@ -130,7 +132,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
else
|
||||
exc = EX_MODPARAM; // variable en parametre du mauvais type
|
||||
}
|
||||
else if(strncmp(e->fn, "error", 5) == 0)
|
||||
else if(modFnIs(e, "error", 5))
|
||||
{
|
||||
// renvoie la derniere erreur specifique au module
|
||||
if(p_etat == NULL)
|
||||
@@ -144,14 +146,14 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(strncmp(e->fn, "execute", 7) == 0)
|
||||
else if(modFnIs(e, "execute", 7))
|
||||
{
|
||||
p_etat->error = 0;
|
||||
// execute(command, returning, capturing)
|
||||
// pour les vars en sortie, forcer le chgt de type si besoin ?
|
||||
if(param1->type != VAR_DYNAMIC)
|
||||
if(!param1 || param1->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param2->type != VAR_NUMBER)
|
||||
else if(!param2 || param2->type != VAR_NUMBER)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
@@ -164,12 +166,19 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
if(flagCapturing && exc == OK)
|
||||
{
|
||||
dynSetLen(e, param3, 0);
|
||||
#ifdef WINLIB
|
||||
if (!GetTempPathA(param3->mLgmax, param3->mPtr))
|
||||
exc = EXMOD_SYSTEM_FICTMP;
|
||||
else if(!GetTempFileNameA(param3->mPtr, "tmp", 0, e->int_dynamic.mPtr))
|
||||
exc = EXMOD_SYSTEM_FICTMP;
|
||||
#else
|
||||
int fd; // pour avoir un nom de fichier temporaire
|
||||
dynLet(e, &e->int_dynamic, "/tmp/cap_XXXXXX", 15);
|
||||
if((fd = mkstemp(e->int_dynamic.mPtr)) == -1)
|
||||
exc = EXMOD_SYSTEM_FICTMP;
|
||||
else
|
||||
close(fd);
|
||||
#endif
|
||||
}
|
||||
if(exc == OK)
|
||||
{
|
||||
@@ -178,6 +187,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
dynIns(e, &e->int_dynamic, 1, DYN_NONE, param3, '>', DYN_NONE);
|
||||
cr = system(param1->mPtr);
|
||||
dynRead(e, param3, e->int_dynamic.mPtr);
|
||||
// TODO : purge fichier temp ?
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -188,7 +198,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "getEnv", 6) == 0)
|
||||
else if(modFnIs(e, "getEnv", 6))
|
||||
{
|
||||
p_etat->error = 0;
|
||||
/* utilisation de dynRead qui fait le travail */
|
||||
@@ -213,7 +223,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "createEnv", 9) == 0)
|
||||
else if(modFnIs(e, "createEnv", 9))
|
||||
{
|
||||
p_etat->error = 0;
|
||||
// setEnv(nom, valeur, overwritting)
|
||||
@@ -224,16 +234,31 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
#ifdef WINLIB
|
||||
// verifier si existe avec getenv, si oui erreur
|
||||
char * varenv = getenv(param1->mPtr);
|
||||
if(varenv)
|
||||
{
|
||||
exc = EXMOD_SYSTEM_SETENV;
|
||||
setError(p_etat, exc);
|
||||
}
|
||||
else if (!SetEnvironmentVariableA(param1->mPtr, param2->mPtr))
|
||||
{
|
||||
exc = EXMOD_SYSTEM_SETENV;
|
||||
setError(p_etat, exc);
|
||||
}
|
||||
#else
|
||||
int cr = setenv(param1->mPtr, param2->mPtr, 0); // 1 = overwrite, 0 = ne pas ecraser si existe
|
||||
if(cr != 0)
|
||||
{
|
||||
exc = EXMOD_SYSTEM_SETENV;
|
||||
setError(p_etat, cr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "updateEnv", 9) == 0)
|
||||
else if(modFnIs(e, "updateEnv", 9))
|
||||
{
|
||||
p_etat->error = 0;
|
||||
// setEnv(nom, valeur, overwritting)
|
||||
@@ -244,16 +269,24 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
#ifdef WINLIB
|
||||
if (!SetEnvironmentVariableA(param1->mPtr, param2->mPtr))
|
||||
{
|
||||
exc = EXMOD_SYSTEM_SETENV;
|
||||
setError(p_etat, exc);
|
||||
}
|
||||
#else
|
||||
int cr = setenv(param1->mPtr, param2->mPtr, 1); // 1 = overwrite, 0 = ne pas ecraser si existe
|
||||
if(cr != 0)
|
||||
{
|
||||
exc = EXMOD_SYSTEM_SETENV;
|
||||
setError(p_etat, cr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "deleteEnv", 9) == 0)
|
||||
else if(modFnIs(e, "deleteEnv", 9))
|
||||
{
|
||||
p_etat->error = 0;
|
||||
// setEnv(nom, valeur, overwritting)
|
||||
@@ -262,16 +295,24 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
#ifdef WINLIB
|
||||
if (!SetEnvironmentVariableA(param1->mPtr, NULL))
|
||||
{
|
||||
exc = EXMOD_SYSTEM_SETENV;
|
||||
setError(p_etat, exc);
|
||||
}
|
||||
#else
|
||||
int cr = unsetenv(param1->mPtr); // suppression
|
||||
if(cr != 0)
|
||||
{
|
||||
exc = EXMOD_SYSTEM_UNSETENV;
|
||||
setError(p_etat, cr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "getOS", 5) == 0)
|
||||
else if(modFnIs(e, "getOS", 5))
|
||||
{
|
||||
p_etat->error = 0;
|
||||
// uname() donne les infos
|
||||
@@ -279,6 +320,9 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
#ifdef WINLIB
|
||||
dynLet(e, param1, "Windows", DYN_LGNONE);
|
||||
#else
|
||||
struct utsname name;
|
||||
int lg;
|
||||
if(uname(&name) == 0)
|
||||
@@ -293,10 +337,11 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
exc = EXMOD_SYSTEM_UNAME;
|
||||
setError(p_etat, errno);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(strncmp(e->fn, "getHostname", 5) == 0)
|
||||
else if(modFnIs(e, "getHostname", 11))
|
||||
{
|
||||
p_etat->error = 0;
|
||||
// uname() donne les infos
|
||||
@@ -306,6 +351,48 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
#ifdef WINLIB
|
||||
DWORD size = param1->mLgmax;
|
||||
if (!GetComputerNameA(param1->mPtr, &size))
|
||||
{
|
||||
exc = EXMOD_SYSTEM_GETHOST;
|
||||
setError(p_etat, errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
WSADATA wsaData;
|
||||
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
|
||||
{
|
||||
exc = EXMOD_SYSTEM_GETHOST;
|
||||
setError(p_etat, errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gethostname(param2->mPtr, param2->mLgmax) == SOCKET_ERROR)
|
||||
{
|
||||
WSACleanup();
|
||||
exc = EXMOD_SYSTEM_GETHOST;
|
||||
setError(p_etat, errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct hostent * host_entry;
|
||||
host_entry = gethostbyname(param2->mPtr);
|
||||
if (host_entry == NULL)
|
||||
{
|
||||
WSACleanup();
|
||||
exc = EXMOD_SYSTEM_GETHOST;
|
||||
setError(p_etat, errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
dynLet(e, param2, inet_ntoa(*(struct in_addr*)host_entry->h_addr_list[0]), DYN_LGNONE);
|
||||
WSACleanup();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
struct utsname name;
|
||||
int lg;
|
||||
if(uname(&name) == 0)
|
||||
@@ -333,9 +420,67 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
|
||||
setError(p_etat, errno);
|
||||
exc = EXMOD_SYSTEM_UNAME;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(modFnIs(e, "fork", 4))
|
||||
{
|
||||
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(modFnIs(e, "wait", 4))
|
||||
{
|
||||
#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(modFnIs(e, "kill", 4))
|
||||
{
|
||||
#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(modFnIs(e, "sleep", 5))
|
||||
{
|
||||
#ifdef WINLIB
|
||||
if(param1->type != VAR_NUMBER)
|
||||
exc = EX_MODPARAM;
|
||||
// duree attente envoyee en secondes
|
||||
Sleep(param1->num * 1000 / NUM_FACTEUR); // en millisec.
|
||||
#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);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024 lanisys.fr
|
||||
\/ \/ Copyright 2024,2025 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
********************************************** */
|
||||
#ifdef WINLIB
|
||||
#include "windows.h"
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
@@ -28,16 +31,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 +64,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,16 +313,23 @@ 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 */
|
||||
if(strncmp(e->fn, "init", 4) == 0)
|
||||
if(modFnIs(e, "init", 4))
|
||||
{
|
||||
// alloc ptr sur zone memoire pour memoriser l'etat du module
|
||||
*etat = memalloc(e, sizeof(modEtat));
|
||||
@@ -81,64 +342,396 @@ 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)
|
||||
else if(modFnIs(e, "end", 3))
|
||||
{
|
||||
// liberation specifique au module avant arret process
|
||||
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)
|
||||
else if(modFnIs(e, "vers", 4))
|
||||
{
|
||||
// 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
|
||||
}
|
||||
else if(strncmp(e->fn, "error", 5) == 0)
|
||||
else if(modFnIs(e, "error", 5))
|
||||
{
|
||||
// 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
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(strncmp(e->fn, "startChrono", 11) == 0)
|
||||
else if(modFnIs(e, "startChrono", 11))
|
||||
{
|
||||
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)
|
||||
else if(modFnIs(e, "lapChrono", 9))
|
||||
{
|
||||
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(modFnIs(e, "setUTC", 6))
|
||||
{
|
||||
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(modFnIs(e, "setLocal", 8))
|
||||
{
|
||||
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(modFnIs(e, "setNowLocal", 11))
|
||||
{
|
||||
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(modFnIs(e, "setNowUTC", 9))
|
||||
{
|
||||
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(modFnIs(e, "set", 3))
|
||||
{
|
||||
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(modFnIs(e, "getUTC", 6))
|
||||
{
|
||||
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(modFnIs(e, "getLocal", 8))
|
||||
{
|
||||
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(modFnIs(e, "get", 3))
|
||||
{
|
||||
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(modFnIs(e, "alarmUTCHM", 10))
|
||||
{
|
||||
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(modFnIs(e, "alarmLocalHM", 12))
|
||||
{
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
|
||||
@@ -55,15 +55,19 @@ void var_init(env * e, var * v, octet type, ent64 mod_lg, ent64 sep_lgm, pointeu
|
||||
v->lg = 0;
|
||||
v->lgmax = sep_lgm;
|
||||
v->ptr[0] = 0;
|
||||
v->codePage = CP_DEFAULT;
|
||||
}
|
||||
break;
|
||||
case VAR_BUFFER:
|
||||
if(sep_lgm < BUF_LGBLOC)
|
||||
sep_lgm = BUF_LGBLOC;
|
||||
if(sep_lgm < BUF_LGMINBLOC)
|
||||
sep_lgm = BUF_LGMINBLOC;
|
||||
else if((sep_lgm % 32) != 0)
|
||||
sep_lgm = ((sep_lgm / 32) + 1) * 32; // taille multiple de 32, sinon pile d'elements de 8 et 16 ko !!
|
||||
if((v->ptr = memalloc(e, sep_lgm)) == NULL)
|
||||
v->type = VAR_NULL; /* exception levee dans memalloc */
|
||||
else
|
||||
{
|
||||
memset(v->ptr, 0, sep_lgm);
|
||||
v->lgmax = sep_lgm;
|
||||
v->read = 0;
|
||||
v->write = 0;
|
||||
@@ -129,6 +133,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 +144,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 +177,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 +191,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;
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
|
||||
; regles lex des token w
|
||||
; \r est supprime des lignes et \n sert de separateur de lignes : non present
|
||||
|
||||
blank: (1,*,#20#09)
|
||||
comment: (1,1,#3B) (0,*,#00-#FF)
|
||||
|
||||
begin: begin
|
||||
background: background
|
||||
library: library
|
||||
end: end
|
||||
except: except
|
||||
throw: throw
|
||||
catch: catch
|
||||
|
||||
include: include
|
||||
|
||||
sub: sub
|
||||
endsub: endsub
|
||||
|
||||
if: if
|
||||
then: then
|
||||
else: else
|
||||
elseif: elseif
|
||||
endif: endif
|
||||
|
||||
do: do
|
||||
call: call
|
||||
invoke: invoke
|
||||
return: return
|
||||
returnon: returnon
|
||||
|
||||
loop: loop
|
||||
endloop: endloop
|
||||
|
||||
foreach: foreach
|
||||
in: in
|
||||
like: like
|
||||
endfor: endfor
|
||||
|
||||
break: break
|
||||
breakon: breakon
|
||||
continue: continue
|
||||
continueon: continueon
|
||||
|
||||
nop: nop
|
||||
part: part
|
||||
echonl: echonl
|
||||
echo: echo
|
||||
input: input
|
||||
|
||||
declare: declare
|
||||
let: let
|
||||
delet: delet ; unlet ??
|
||||
|
||||
new: new
|
||||
class: class
|
||||
this: this
|
||||
parent: parent
|
||||
free: free
|
||||
precision: precision
|
||||
setsep: setsep
|
||||
|
||||
int: int
|
||||
frac: frac
|
||||
abs: abs
|
||||
neg: neg
|
||||
round: round
|
||||
|
||||
type: type
|
||||
len: len
|
||||
count: count
|
||||
dcount: dcount
|
||||
field: field
|
||||
index: index
|
||||
search: search
|
||||
change: change
|
||||
format: format
|
||||
insert: insert
|
||||
remove: remove ; delete (dynamic)
|
||||
|
||||
tonum: tonum
|
||||
tostring: tostring
|
||||
|
||||
equal: =
|
||||
diff: (1,1,#23) ; #
|
||||
gt: >
|
||||
lt: <
|
||||
gte: >=
|
||||
lte: <=
|
||||
and: and
|
||||
or: or
|
||||
not: not
|
||||
|
||||
beginpar: (1,1,#28) ; (
|
||||
endpar: (1,1,#29) ; )
|
||||
beginh: (1,1,#7B) ; {
|
||||
endh: (1,1,#7D) ; }
|
||||
begins: (1,1,#5B) ; [
|
||||
ends: (1,1,#5D) ; ]
|
||||
|
||||
indirect: !
|
||||
|
||||
typeof: ? ; typeof ??
|
||||
|
||||
stringdq: (1,1,#22) (0,765,#20-#21#23-#EF) (1,1,#22) ; contenu chaine : car car car #FF (en majuscule), a verifier lors du parse (hexa -> binaire + controle)
|
||||
stringq: (1,1,#27) (0,765,#20-#26#28-#EF) (1,1,#27) ; idem
|
||||
|
||||
ident: (1,1,a-zA-Z) (0,23,a-zA-Z0-9)
|
||||
varsys: @ (1,*,a-z)
|
||||
numberdec: (1,13,0-9) . (0,5,0-9)
|
||||
numberint: (1,13,0-9)
|
||||
|
||||
minus: (1,1,#2D) ; -
|
||||
plus: (1,1,#2B) ; +
|
||||
multiply: (1,1,#2A) ; *
|
||||
divide: (1,1,#2F) ; /
|
||||
divident: (1,1,#5C) ; \
|
||||
modulo: (1,1,#25) ; %
|
||||
concat: (1,1,#3A) ; :
|
||||
|
||||
listesep: (1,1,#2C) ; ,
|
||||
identsep: (1,1,#2E) ; .
|
||||
modsep: &
|
||||
|
||||
other: (1,1,#00-#FF)
|
||||
|
||||
; fin des regles w.lex
|
||||
@@ -0,0 +1,100 @@
|
||||
blank,1,comment,2,begin,3,background,4,library,5,end,6,except,7,throw,8,catch,9,include,10,sub,11,endsub,12,if,13,then,14,else,15,elseif,16,endif,17,do,18,call,19,invoke,20,return,21,returnon,22,loop,23,endloop,24,foreach,25,in,26,like,27,endfor,28,break,29,breakon,30,continue,31,continueon,32,nop,33,part,34,echonl,35,echo,36,input,37,declare,38,let,39,delet,40,new,41,class,42,this,43,parent,44,free,45,precision,46,setsep,47,int,48,frac,49,abs,50,neg,51,round,52,type,53,len,54,count,55,dcount,56,field,57,index,58,search,59,change,60,format,61,insert,62,remove,63,tonum,64,tostring,65,equal,66,diff,67,gt,68,lt,69,gte,70,lte,71,and,72,or,73,not,74,beginpar,75,endpar,76,beginh,77,endh,78,begins,79,ends,80,indirect,81,typeof,82,stringdq,83,stringq,84,ident,85,varsys,86,numberdec,87,numberint,88,minus,89,plus,90,multiply,91,divide,92,divident,93,modulo,94,concat,95,listesep,96,identsep,97,modsep,98,other,99
|
||||
1,-1,20:09
|
||||
1,1,3B;0,-1,00-FF
|
||||
1,1,62;1,1,65;1,1,67;1,1,69;1,1,6E
|
||||
1,1,62;1,1,61;1,1,63;1,1,6B;1,1,67;1,1,72;1,1,6F;1,1,75;1,1,6E;1,1,64
|
||||
1,1,6C;1,1,69;1,1,62;1,1,72;1,1,61;1,1,72;1,1,79
|
||||
1,1,65;1,1,6E;1,1,64
|
||||
1,1,65;1,1,78;1,1,63;1,1,65;1,1,70;1,1,74
|
||||
1,1,74;1,1,68;1,1,72;1,1,6F;1,1,77
|
||||
1,1,63;1,1,61;1,1,74;1,1,63;1,1,68
|
||||
1,1,69;1,1,6E;1,1,63;1,1,6C;1,1,75;1,1,64;1,1,65
|
||||
1,1,73;1,1,75;1,1,62
|
||||
1,1,65;1,1,6E;1,1,64;1,1,73;1,1,75;1,1,62
|
||||
1,1,69;1,1,66
|
||||
1,1,74;1,1,68;1,1,65;1,1,6E
|
||||
1,1,65;1,1,6C;1,1,73;1,1,65
|
||||
1,1,65;1,1,6C;1,1,73;1,1,65;1,1,69;1,1,66
|
||||
1,1,65;1,1,6E;1,1,64;1,1,69;1,1,66
|
||||
1,1,64;1,1,6F
|
||||
1,1,63;1,1,61;1,1,6C;1,1,6C
|
||||
1,1,69;1,1,6E;1,1,76;1,1,6F;1,1,6B;1,1,65
|
||||
1,1,72;1,1,65;1,1,74;1,1,75;1,1,72;1,1,6E
|
||||
1,1,72;1,1,65;1,1,74;1,1,75;1,1,72;1,1,6E;1,1,6F;1,1,6E
|
||||
1,1,6C;1,1,6F;1,1,6F;1,1,70
|
||||
1,1,65;1,1,6E;1,1,64;1,1,6C;1,1,6F;1,1,6F;1,1,70
|
||||
1,1,66;1,1,6F;1,1,72;1,1,65;1,1,61;1,1,63;1,1,68
|
||||
1,1,69;1,1,6E
|
||||
1,1,6C;1,1,69;1,1,6B;1,1,65
|
||||
1,1,65;1,1,6E;1,1,64;1,1,66;1,1,6F;1,1,72
|
||||
1,1,62;1,1,72;1,1,65;1,1,61;1,1,6B
|
||||
1,1,62;1,1,72;1,1,65;1,1,61;1,1,6B;1,1,6F;1,1,6E
|
||||
1,1,63;1,1,6F;1,1,6E;1,1,74;1,1,69;1,1,6E;1,1,75;1,1,65
|
||||
1,1,63;1,1,6F;1,1,6E;1,1,74;1,1,69;1,1,6E;1,1,75;1,1,65;1,1,6F;1,1,6E
|
||||
1,1,6E;1,1,6F;1,1,70
|
||||
1,1,70;1,1,61;1,1,72;1,1,74
|
||||
1,1,65;1,1,63;1,1,68;1,1,6F;1,1,6E;1,1,6C
|
||||
1,1,65;1,1,63;1,1,68;1,1,6F
|
||||
1,1,69;1,1,6E;1,1,70;1,1,75;1,1,74
|
||||
1,1,64;1,1,65;1,1,63;1,1,6C;1,1,61;1,1,72;1,1,65
|
||||
1,1,6C;1,1,65;1,1,74
|
||||
1,1,64;1,1,65;1,1,6C;1,1,65;1,1,74
|
||||
1,1,6E;1,1,65;1,1,77
|
||||
1,1,63;1,1,6C;1,1,61;1,1,73;1,1,73
|
||||
1,1,74;1,1,68;1,1,69;1,1,73
|
||||
1,1,70;1,1,61;1,1,72;1,1,65;1,1,6E;1,1,74
|
||||
1,1,66;1,1,72;1,1,65;1,1,65
|
||||
1,1,70;1,1,72;1,1,65;1,1,63;1,1,69;1,1,73;1,1,69;1,1,6F;1,1,6E
|
||||
1,1,73;1,1,65;1,1,74;1,1,73;1,1,65;1,1,70
|
||||
1,1,69;1,1,6E;1,1,74
|
||||
1,1,66;1,1,72;1,1,61;1,1,63
|
||||
1,1,61;1,1,62;1,1,73
|
||||
1,1,6E;1,1,65;1,1,67
|
||||
1,1,72;1,1,6F;1,1,75;1,1,6E;1,1,64
|
||||
1,1,74;1,1,79;1,1,70;1,1,65
|
||||
1,1,6C;1,1,65;1,1,6E
|
||||
1,1,63;1,1,6F;1,1,75;1,1,6E;1,1,74
|
||||
1,1,64;1,1,63;1,1,6F;1,1,75;1,1,6E;1,1,74
|
||||
1,1,66;1,1,69;1,1,65;1,1,6C;1,1,64
|
||||
1,1,69;1,1,6E;1,1,64;1,1,65;1,1,78
|
||||
1,1,73;1,1,65;1,1,61;1,1,72;1,1,63;1,1,68
|
||||
1,1,63;1,1,68;1,1,61;1,1,6E;1,1,67;1,1,65
|
||||
1,1,66;1,1,6F;1,1,72;1,1,6D;1,1,61;1,1,74
|
||||
1,1,69;1,1,6E;1,1,73;1,1,65;1,1,72;1,1,74
|
||||
1,1,72;1,1,65;1,1,6D;1,1,6F;1,1,76;1,1,65
|
||||
1,1,74;1,1,6F;1,1,6E;1,1,75;1,1,6D
|
||||
1,1,74;1,1,6F;1,1,73;1,1,74;1,1,72;1,1,69;1,1,6E;1,1,67
|
||||
1,1,3D
|
||||
1,1,23
|
||||
1,1,3E
|
||||
1,1,3C
|
||||
1,1,3E;1,1,3D
|
||||
1,1,3C;1,1,3D
|
||||
1,1,61;1,1,6E;1,1,64
|
||||
1,1,6F;1,1,72
|
||||
1,1,6E;1,1,6F;1,1,74
|
||||
1,1,28
|
||||
1,1,29
|
||||
1,1,7B
|
||||
1,1,7D
|
||||
1,1,5B
|
||||
1,1,5D
|
||||
1,1,21
|
||||
1,1,3F
|
||||
1,1,22;0,765,20-21:23-EF;1,1,22
|
||||
1,1,27;0,765,20-26:28-EF;1,1,27
|
||||
1,1,61-7A:41-5A;0,23,61-7A:41-5A:30-39
|
||||
1,1,40;1,-1,61-7A
|
||||
1,13,30-39;1,1,2E;0,5,30-39
|
||||
1,13,30-39
|
||||
1,1,2D
|
||||
1,1,2B
|
||||
1,1,2A
|
||||
1,1,2F
|
||||
1,1,5C
|
||||
1,1,25
|
||||
1,1,3A
|
||||
1,1,2C
|
||||
1,1,2E
|
||||
1,1,26
|
||||
1,1,00-FF
|
||||
Reference in new issue
Block a user