Compare commits
15
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f55fc23f3 | ||
|
|
fa533a0a2d | ||
|
|
5ddbd73146 | ||
|
|
80847f4993 | ||
|
|
1fe89c0b6a | ||
|
|
ddbbb29038 | ||
|
|
eca0605104 | ||
|
|
72f749172f | ||
|
|
5c58e7ba97 | ||
|
|
c036ec478c | ||
|
|
a23c183f7d | ||
|
|
dc02ac4243 | ||
|
|
280b10ca99 | ||
|
|
db24144e31 | ||
|
|
efd1b9a91d |
No files matched your search
@@ -5,10 +5,13 @@
|
||||
|
||||
void GetArgs(env * e, int argc, char * argv[], Dynamic * arg)
|
||||
{
|
||||
int nbOpt = 0, cpt = 0;
|
||||
int nbOpt = 0, cpt = 0, clc = 0;
|
||||
dynSetLen(e, arg, 0);
|
||||
dynStoreSz(e, arg, 6, ++clc, argv[0], DYN_LGNONE, cFM, cVM);
|
||||
for(int a = 1; a < argc; a++)
|
||||
{
|
||||
dynStoreSz(e, arg, 6, ++clc, argv[a], DYN_LGNONE, cFM, cVM);
|
||||
//
|
||||
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)
|
||||
@@ -47,5 +50,6 @@ void GetArgs(env * e, int argc, char * argv[], Dynamic * arg)
|
||||
arg<3> = WBIN (.o .so) => invoke, LD_LIBRARY_PATH
|
||||
arg<4> = WSRC (.w) => lwc
|
||||
arg<5> = WLIB (.wp .wa) => call, lwa lwc
|
||||
arg<6> = les argv ligne de commande AVANT le prog wp
|
||||
*/
|
||||
}
|
||||
+45
-14
@@ -47,7 +47,8 @@ env e;
|
||||
int subNiv;
|
||||
Dynamic adrLabel;
|
||||
/*
|
||||
adrLabel<1> = label, adrLabel<2> = offset (adresse) du label
|
||||
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
|
||||
@@ -82,8 +83,10 @@ void decodeString(env * e, Dynamic * this)
|
||||
{
|
||||
/* TODO ! voir avec le compilateur s'il ne fait pas deja le travail */
|
||||
/* genw remplace " par #22 et ' ' par #20 : on fait l'inverse ici */
|
||||
dynChange(e, this, "#22", "\"", DYN_ALL);
|
||||
dynChange(e, this, "#20", " ", DYN_ALL);
|
||||
/* + pbm #0A qui saute une ligen et ok ici ... */
|
||||
//dynChange(e, this, "#22", "\"", DYN_ALL);
|
||||
//dynChange(e, this, "#20", " ", DYN_ALL);
|
||||
dynCleanHexaMark(e, this);
|
||||
}
|
||||
|
||||
Dynamic pcode;
|
||||
@@ -244,7 +247,7 @@ int assembler(env * e, char * fichier, int * cptLig)
|
||||
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];
|
||||
debutSub = debutSub + 2 + 3 + 1 + pcode.ptr[debutSub + 1]; // se mettre APRES l'instruction SUBR/PHDS/PIDS (5 + lg et le 1 pour annuler le +1 qui est apres...)
|
||||
offset = offset + 1 - debutSub; // ad debut loop - debut du prog/sub en cours
|
||||
PCODE((offset >> 16) & 255); // 23/11/2025 - verif PCODE ok a la place de PCODEP
|
||||
PCODE((offset >> 8 ) & 255); // 23/11/2025 - verif PCODE ok a la place de PCODEP
|
||||
@@ -292,7 +295,7 @@ 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 variable
|
||||
num = tmp.mLg;
|
||||
if(num == 1 && tmp.mPtr[0] == '_') // assembler SUBR _ pour avoir lg = 0
|
||||
if(num == 1 && tmp.mPtr[0] == '_') // assembler SUBR _ pour avoir lg = 0 (?? A GARDER ?? FDE 08/03/2026)
|
||||
num = 0;
|
||||
PCODE(instr);
|
||||
PCODE(num);
|
||||
@@ -421,8 +424,13 @@ int assembler(env * e, char * fichier, int * cptLig)
|
||||
case IN_PIDH:
|
||||
case IN_PHDO:
|
||||
case IN_PIDO:
|
||||
case IN_DELE:
|
||||
case IN_PHDN:
|
||||
case IN_PIDN:
|
||||
case IN_PHDV:
|
||||
case IN_PIDV:
|
||||
case IN_NLET:
|
||||
case IN_PVHD:
|
||||
case IN_PVID:
|
||||
// CPSH / PARM / PVAR / PVAH / PVAI / DELE / NLET / PHDE / PIDE
|
||||
//dynField(e, &ligne, &tmp, i++, 0, ' ', 0, 1);
|
||||
//num = dynToNum(e, &tmp, 0, 3) & 255;
|
||||
@@ -457,6 +465,8 @@ int assembler(env * e, char * fichier, int * cptLig)
|
||||
PCODE(CMP_OR);
|
||||
else if(strcmp(tmp.mPtr, "NOT") == 0)
|
||||
PCODE(CMP_NOT);
|
||||
else if(strcmp(tmp.mPtr, "FOR") == 0)
|
||||
PCODE(CMP_FOR);
|
||||
else
|
||||
ret = -9; // code comparaison inconnu
|
||||
break;
|
||||
@@ -522,6 +532,10 @@ int assembler(env * e, char * fichier, int * cptLig)
|
||||
// SRCH
|
||||
case IN_SCHS:
|
||||
// SCHS
|
||||
case IN_SSRC:
|
||||
// SSRC
|
||||
case IN_SSCS:
|
||||
// SSCS
|
||||
case IN_CHNG:
|
||||
// CHNG
|
||||
case IN_INSE:
|
||||
@@ -542,6 +556,10 @@ int assembler(env * e, char * fichier, int * cptLig)
|
||||
// DESV
|
||||
case IN_DEZV:
|
||||
// DEZV
|
||||
case IN_SADV:
|
||||
case IN_VLET:
|
||||
case IN_HCOU:
|
||||
case IN_DELE:
|
||||
PCODE(instr);
|
||||
break;
|
||||
case IN_MODL:
|
||||
@@ -604,7 +622,7 @@ int assembler(env * e, char * fichier, int * cptLig)
|
||||
PCODE(num);
|
||||
break;
|
||||
case IN_DSET:
|
||||
// DSET - TODO decoder la chaine, cas des \xx en hexa (recalcul lg : fn qui met a jour directement tmp et maj lg)
|
||||
// DSET - TODO decoder la chaine, cas des #xx en hexa (recalcul lg : fn qui met a jour directement tmp et maj lg)
|
||||
dynField(e, &ligne, &tmp, 2, 0, '"', 0, 1);
|
||||
decodeString(e, &tmp);
|
||||
if(tmp.mLg < 0 || tmp.mLg > 255) { ret = -4; break; } // erreur longueur nom
|
||||
@@ -628,14 +646,14 @@ int assembler(env * e, char * fichier, int * cptLig)
|
||||
// DEZI
|
||||
case IN_DSTO:
|
||||
// DSTO
|
||||
case IN_VLET:
|
||||
// VLET
|
||||
case IN_LETV:
|
||||
// LETV
|
||||
case IN_DCAT:
|
||||
// DCAT
|
||||
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 DEXF/DEXV/VLET/DCAT _ pour avoir lg = 0
|
||||
if(num == 1 && tmp.mPtr[0] == '_') // assembler DEXF/DEXV/LETV/DCAT _ pour avoir lg = 0
|
||||
num = 0;
|
||||
PCODE(instr);
|
||||
PCODE(num);
|
||||
@@ -936,8 +954,13 @@ int disassembler(env * e, char * fichier)
|
||||
case IN_PIDH:
|
||||
case IN_PHDO:
|
||||
case IN_PIDO:
|
||||
case IN_DELE:
|
||||
case IN_PHDN:
|
||||
case IN_PIDN:
|
||||
case IN_PHDV:
|
||||
case IN_PIDV:
|
||||
case IN_NLET:
|
||||
case IN_PVHD:
|
||||
case IN_PVID:
|
||||
case IN_PNAM:
|
||||
case IN_INCL:
|
||||
// CPSH / PARM / PVAR / PVAH / PVAI / DELE / NLET / PNAM / INCL / PHDE / PIDE
|
||||
@@ -967,7 +990,7 @@ int disassembler(env * e, char * fichier)
|
||||
// COMP
|
||||
si++;
|
||||
num = pcode.ptr[si++];
|
||||
if(num < CMP_EQ || num > CMP_NOT)
|
||||
if(num < CMP_EQ || num > CMP_FOR)
|
||||
printf("%d\n", num);
|
||||
else
|
||||
{
|
||||
@@ -1038,6 +1061,10 @@ int disassembler(env * e, char * fichier)
|
||||
// SRCH
|
||||
case IN_SCHS:
|
||||
// SCHS
|
||||
case IN_SSRC:
|
||||
// SSRC
|
||||
case IN_SSCS:
|
||||
// SSCS
|
||||
case IN_CHNG:
|
||||
// CHNG
|
||||
case IN_INSE:
|
||||
@@ -1058,6 +1085,10 @@ int disassembler(env * e, char * fichier)
|
||||
// DESV
|
||||
case IN_DEZV:
|
||||
// DEZV
|
||||
case IN_SADV:
|
||||
case IN_VLET:
|
||||
case IN_HCOU:
|
||||
case IN_DELE:
|
||||
si++;
|
||||
printf("\n");
|
||||
dumpHex(&pcode, si_instr, si);
|
||||
@@ -1162,8 +1193,8 @@ int disassembler(env * e, char * fichier)
|
||||
// DEZI
|
||||
case IN_DSTO:
|
||||
// DSTO
|
||||
case IN_VLET:
|
||||
// VLET
|
||||
case IN_LETV:
|
||||
// LETV
|
||||
case IN_DCAT:
|
||||
// DCAT
|
||||
si++;
|
||||
|
||||
@@ -45,6 +45,22 @@
|
||||
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.
|
||||
*/
|
||||
/*
|
||||
lgmax = taille buffer
|
||||
max lg message = lgmax - 4 => un message = lg (2 octets) + msg
|
||||
|
||||
cas 0 read = write : buffer vide : lg msg max = lgmax - 4 (et maxi 65535)
|
||||
|
||||
cas 1 : read <= write (inclus cas 0)
|
||||
+-------------^*********************^------------------+ lgmax
|
||||
read write
|
||||
occ = write - read ; free = lgmax - (write - read) - 4
|
||||
|
||||
cas 2 : read > write
|
||||
+********^---------------------------------------^*****+ lgmax
|
||||
write read
|
||||
occ = write + (lgmax - read) ; free = read - write - 4
|
||||
*/
|
||||
|
||||
//#define BUFPTR(x) (pointeur)(x->ptr == NULL ? (pointeur)(x + sizeof(var)) : x->ptr)
|
||||
pointeur BUFPTR(var * x)
|
||||
|
||||
@@ -8,8 +8,9 @@ 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 -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
|
||||
gcc -c w_src/lex.c -s -Wall -DUNIX -m64 -fPIC -o exec/lex.o
|
||||
gcc -shared -s exec/dynamic.o exec/var.o exec/hashtable.o exec/global.o exec/rep.o exec/buffer.o exec/lex.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 exec/lex.o
|
||||
|
||||
echo 1. Compilation de templateMod.c
|
||||
gcc -shared -s -o exec/template.o w_src/templateMod.c -m64 -DUNIX -Wall -fPIC -L./exec -l:libw.so
|
||||
@@ -18,12 +19,17 @@ echo 2. Compilation de fileMod.c
|
||||
gcc -shared -s -o exec/file.o w_src/fileMod.c -m64 -DUNIX -Wall -fPIC -L./exec -l:libw.so
|
||||
|
||||
echo 3. Compilation de sockMod.c
|
||||
gcc -shared -s -o exec/sock.o w_src/sockMod.c -m64 -DUNIX -Wall -fPIC -L./exec -l:libw.so
|
||||
gcc -shared -s -o exec/sock_lib.so w_src/sock_lib.c -m64 -DUNIX -Wall -fPIC -L./exec -l:libw.so
|
||||
gcc -shared -s -o exec/sock.o w_src/sockMod.c -m64 -DUNIX -Wall -fPIC -L./exec -l:libw.so -l:sock_lib.so
|
||||
|
||||
#echo 4. Compilation de dbMod.c et dbpgsql.c
|
||||
#gcc -shared -s -o exec/db.o w_src/dbMod.c -m64 -DUNIX -Wall -ldl -fPIC -L./exec -l:libw.so
|
||||
#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 4. Compilation de encodMod.c
|
||||
gcc -shared -s -o exec/encod_lib.so w_src/encod_lib.c -m64 -DUNIX -Wall -fPIC -L./exec -l:libw.so -Wno-char-subscripts
|
||||
#gcc -shared -s -o exec/encod.o w_src/encodMod.c -m64 -DUNIX -Wall -fPIC -L./exec -l:libw.so -l:encod_lib.so
|
||||
|
||||
echo 5. Compilation de lzwMod.c
|
||||
gcc -shared -s -o exec/lzw_lib.so 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.so
|
||||
|
||||
+31
-20
@@ -7,59 +7,70 @@ cd "C:\Users\Poupougne42\source\repos\win_w_src"
|
||||
|
||||
echo ------------------------------------------------------------------------------------------
|
||||
echo 0. Compilation pour dynamic lib DLL
|
||||
cl /LD /DWINLIB /DWAPIEXPORT /Feexec\libw.dll w_src\dynamic.c w_src\var.c w_src\hashtable.c w_src\buffer.c w_src\global.c w_src\rep.c
|
||||
cl /LD /DWINLIB /DWAPIEXPORT /Gy /MD /Feexec\libw.dll w_src\dynamic.c w_src\var.c w_src\hashtable.c w_src\buffer.c w_src\global.c w_src\rep.c w_src\lex.c /DEBUG:NONE
|
||||
|
||||
echo 1a. Compilation de templateMod.c
|
||||
cl /LD /DWINLIB /DWAPIIMPORT /Feexec\template.dll w_src\templateMod.c exec\libw.lib
|
||||
cl /LD /DWINLIB /DWAPIIMPORT /Gy /MD /Feexec\template.dll w_src\templateMod.c exec\libw.lib /DEBUG:NONE
|
||||
|
||||
echo 1b. Compilation de fileMod.c
|
||||
cl /LD /DWINLIB /DWAPIIMPORT /Feexec\file.dll w_src\fileMod.c exec\libw.lib
|
||||
cl /LD /DWINLIB /DWAPIIMPORT /Gy /MD /Feexec\file.dll w_src\fileMod.c exec\libw.lib /DEBUG:NONE
|
||||
|
||||
echo 1c. Compilation de timeMod.c
|
||||
cl /LD /DWINLIB /DWAPIIMPORT /Feexec\time.dll w_src\timeMod.c exec\libw.lib
|
||||
cl /LD /DWINLIB /DWAPIIMPORT /Gy /MD /Feexec\time.dll w_src\timeMod.c exec\libw.lib /DEBUG:NONE
|
||||
|
||||
echo 1d. Compilation de hashMod.c
|
||||
cl /LD /DWINLIB /DWAPIIMPORT /Feexec\hash.dll w_src\hashMod.c exec\libw.lib
|
||||
cl /LD /DWINLIB /DWAPIIMPORT /Gy /MD /Feexec\hash.dll w_src\hashMod.c exec\libw.lib /DEBUG:NONE
|
||||
|
||||
echo 1e. Compilation de systemMod.c (ws2_32.lib pour socket)
|
||||
cl /LD /DWINLIB /DWAPIIMPORT /Feexec\system.dll w_src\systemMod.c exec\libw.lib ws2_32.lib
|
||||
cl /LD /DWINLIB /DWAPIIMPORT /Gy /MD /Feexec\system.dll w_src\systemMod.c exec\libw.lib ws2_32.lib advapi32.lib /DEBUG:NONE
|
||||
|
||||
echo 1f. Compilation de randomMod.c
|
||||
cl /LD /DWINLIB /DWAPIIMPORT /Feexec\random.dll w_src\randomMod.c exec\libw.lib
|
||||
cl /LD /DWINLIB /DWAPIIMPORT /Gy /MD /Feexec\random.dll w_src\randomMod.c exec\libw.lib /DEBUG:NONE
|
||||
|
||||
|
||||
echo ------------------------------------------------------------------------------------------
|
||||
echo 2a. Compilation de jsonMod.c
|
||||
cl /LD /DWINLIB /DWAPIEXPORT /Feexec\json_lib.dll w_src\json_lib.c exec\libw.lib
|
||||
cl /LD /DWINLIB /DWAPIIMPORT /Feexec\json.dll w_src\jsonMod.c exec\libw.lib exec\json_lib.lib
|
||||
cl /LD /DWINLIB /DWAPIEXPORT /Gy /MD /Feexec\json_lib.dll w_src\json_lib.c exec\libw.lib /DEBUG:NONE
|
||||
cl /LD /DWINLIB /DWAPIIMPORT /Gy /MD /Feexec\json.dll w_src\jsonMod.c exec\libw.lib exec\json_lib.lib /DEBUG:NONE
|
||||
|
||||
echo 2b. Compilation de shmMod.c
|
||||
cl /LD /DWINLIB /DWAPIEXPORT /Feexec\shm_lib.dll w_src\shm_lib.c exec\libw.lib
|
||||
cl /LD /DWINLIB /DWAPIIMPORT /Feexec\shm.dll w_src\shmMod.c exec\libw.lib exec\shm_lib.lib
|
||||
cl /LD /DWINLIB /DWAPIEXPORT /Gy /MD /Feexec\shm_lib.dll w_src\shm_lib.c exec\libw.lib advapi32.lib /DEBUG:NONE
|
||||
cl /LD /DWINLIB /DWAPIIMPORT /Gy /MD /Feexec\shm.dll w_src\shmMod.c exec\libw.lib exec\shm_lib.lib /DEBUG:NONE
|
||||
|
||||
echo 2c. Compilation de lzwMod.c
|
||||
cl /LD /DWINLIB /DWAPIEXPORT /Feexec\lzw_lib.dll w_src\lzw_lib.c exec\libw.lib
|
||||
cl /LD /DWINLIB /DWAPIIMPORT /Feexec\lzw.dll w_src\lzwMod.c exec\libw.lib exec\lzw_lib.lib
|
||||
cl /LD /DWINLIB /DWAPIEXPORT /Gy /MD /Feexec\lzw_lib.dll w_src\lzw_lib.c exec\libw.lib /DEBUG:NONE
|
||||
cl /LD /DWINLIB /DWAPIIMPORT /Gy /MD /Feexec\lzw.dll w_src\lzwMod.c exec\libw.lib exec\lzw_lib.lib /DEBUG:NONE
|
||||
|
||||
echo 2d. Compilation de pdfMod.c
|
||||
cl /LD /DWINLIB /DWAPIEXPORT /Feexec\pdf_lib.dll w_src\pdf_lib.c exec\libw.lib exec\lzw_lib.lib
|
||||
cl /LD /DWINLIB /DWAPIIMPORT /Feexec\pdf.dll w_src\pdfMod.c exec\libw.lib exec\pdf_lib.lib
|
||||
cl /LD /DWINLIB /DWAPIEXPORT /Gy /MD /Feexec\pdf_lib.dll w_src\pdf_lib.c exec\libw.lib exec\lzw_lib.lib /DEBUG:NONE
|
||||
cl /LD /DWINLIB /DWAPIIMPORT /Gy /MD /Feexec\pdf.dll w_src\pdfMod.c exec\libw.lib exec\pdf_lib.lib /DEBUG:NONE
|
||||
|
||||
echo 2e. Compilation de sockMod.c
|
||||
cl /LD /DWINLIB /DWAPIEXPORT /Gy /MD /Feexec\sock_lib.dll w_src\sock_lib.c exec\libw.lib ws2_32.lib /DEBUG:NONE
|
||||
cl /LD /DWINLIB /DWAPIIMPORT /Gy /MD /Feexec\sock.dll w_src\sockMod.c exec\libw.lib exec\sock_lib.lib ws2_32.lib /DEBUG:NONE
|
||||
|
||||
echo 2f. Compilation de encodMod.c
|
||||
cl /LD /DWINLIB /DWAPIEXPORT /Gy /MD /Feexec\encod_lib.dll w_src\encod_lib.c exec\libw.lib /DEBUG:NONE
|
||||
rem cl /LD /DWINLIB /DWAPIIMPORT /Gy /MD /Feexec\json.dll w_src\jsonMod.c exec\libw.lib exec\json_lib.lib /DEBUG:NONE
|
||||
|
||||
echo ------------------------------------------------------------------------------------------
|
||||
echo 3a. Generation lw.exe
|
||||
cl w_src\langage.c /DWINLIB /DWAPIIMPORT /Feexec\lw.exe exec\libw.lib exec\shm_lib.lib /link
|
||||
cl w_src\langage.c /DWINLIB /DWAPIIMPORT /Gy /MD /Feexec\lw.exe exec\libw.lib exec\shm_lib.lib advapi32.lib /link /DEBUG:NONE /OPT:REF /OPT:ICF
|
||||
|
||||
echo 3b. Generation lwa.exe
|
||||
cl w_src\assembler.c /DWINLIB /DWAPIIMPORT /Feexec\lwa.exe exec\libw.lib /link
|
||||
cl w_src\assembler.c /DWINLIB /DWAPIIMPORT /Gy /MD /Feexec\lwa.exe exec\libw.lib /link /DEBUG:NONE /OPT:REF /OPT:ICF
|
||||
|
||||
echo 3c. Generation lwc.exe
|
||||
cl w_src\genw.c /DWINLIB /DWAPIIMPORT /Feexec\lwc.exe exec\libw.lib /link
|
||||
cl w_src\genw.c /DWINLIB /DWAPIIMPORT /Gy /MD /Feexec\lwc.exe exec\libw.lib /link /DEBUG:NONE /OPT:REF /OPT:ICF
|
||||
|
||||
echo 3d. Generation lwf.exe
|
||||
cl w_src\format.c /DWINLIB /DWAPIIMPORT /Feexec\lwf.exe exec\libw.lib /link
|
||||
cl w_src\format.c /DWINLIB /DWAPIIMPORT /Gy /MD /Feexec\lwf.exe exec\libw.lib /link /DEBUG:NONE /OPT:REF /OPT:ICF
|
||||
|
||||
echo 3d. Generation wlex.exe
|
||||
cl w_src\genlex.c /DWINLIB /DWAPIIMPORT /Feexec\wlex.exe exec\libw.lib /link
|
||||
cl w_src\genlex.c /DWINLIB /DWAPIIMPORT /Gy /MD /Feexec\wlex.exe exec\libw.lib /link /DEBUG:NONE /OPT:REF /OPT:ICF
|
||||
|
||||
rem echo 3e. Generation test.exe
|
||||
rem cl w_src\test.c /DWINLIB /DWAPIIMPORT /Gy /MD /Feexec\test.exe exec\libw.lib exec\encod_lib.lib /link /DEBUG:NONE /OPT:REF /OPT:ICF
|
||||
|
||||
echo ------------------------------------------------------------------------------------------
|
||||
echo 4. Purge
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024,2025 lanisys.fr
|
||||
\/ \/ Copyright 2024-2026 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
@@ -57,7 +57,11 @@ char * strerr[] = {
|
||||
"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"
|
||||
"EX_REMOVE_KO remove field error",
|
||||
"EX_CHILD_FORK cannot fork process",
|
||||
"EX_CHILD_EXEC cannot run new process",
|
||||
"EX_ZERO_FOR_INCR foreach increment is zero", // 40
|
||||
"EX_SORTEDSEARCH_KO sort type incorrect"
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -78,10 +82,10 @@ long rg(env * e, Dynamic * regles, char * nom, Dynamic * tmp)
|
||||
return pos;
|
||||
}
|
||||
/*
|
||||
blanc,1,commande,2,aide,3,nombre,4,ajouter,5,supprimer,6,ident,7,reste,8
|
||||
blanc,1,commande,2,aide,3,nombre,4,ajouter,5,supprimer,6,ident,7,identnext,8,reste,9
|
||||
*/
|
||||
static struct {
|
||||
ent16 blanc,commande,aide,nombre,ajouter,supprimer,ident,reste;
|
||||
ent16 blanc,commande,aide,nombre,ajouter,supprimer,ident,identnext,reste;
|
||||
} r;
|
||||
|
||||
void init_reg(env * e, Dynamic * regles, Dynamic * tmp)
|
||||
@@ -93,6 +97,7 @@ void init_reg(env * e, Dynamic * regles, Dynamic * tmp)
|
||||
r.ajouter = rg(e, regles, "ajouter", tmp);
|
||||
r.supprimer = rg(e, regles, "supprimer", tmp);
|
||||
r.ident = rg(e, regles, "ident", tmp);
|
||||
r.identnext = rg(e, regles, "identnext", tmp);
|
||||
r.reste = rg(e, regles, "reste", tmp);
|
||||
}
|
||||
|
||||
@@ -365,6 +370,7 @@ void debug(env * e)
|
||||
dynPrintfInt64(e, "W" PRINTF_MARK, VERSION, 0);
|
||||
if( ! srcFound)
|
||||
dynPrintfInt64(e, ":" PRINTF_MARK, e->ligsrc, 0);
|
||||
dynPrintfInt64(e, "!" PRINTF_MARK, e->except_ex, 0);
|
||||
dynPrintfSz(e, "> ", NULL);
|
||||
writeShm(e, (modContextShm *)e->debugCtxShm);
|
||||
//
|
||||
@@ -388,9 +394,9 @@ void debug(env * e)
|
||||
{
|
||||
// prompt
|
||||
if(srcFound)
|
||||
printf("W%d> ", VERSION);
|
||||
printf("W%d!%lld> ", VERSION, e->except_ex);
|
||||
else
|
||||
printf("W%d:%lld> ", VERSION, e->ligsrc);
|
||||
printf("W%d:%lld!%lld> ", VERSION, e->ligsrc, e->except_ex);
|
||||
dynSetLen(e, &e->debugcmd, 0);
|
||||
int c;
|
||||
char cmd[2];
|
||||
@@ -432,9 +438,9 @@ void debug(env * e)
|
||||
"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"
|
||||
"v V :ident.hash... voir le contenu de la variable <ident>.<hash>...\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"
|
||||
"vg VG :ident.hash... voir le contenu de la var <ident>.<hash>... 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"
|
||||
@@ -476,36 +482,59 @@ void debug(env * e)
|
||||
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)
|
||||
var * v = &e->g, * vnext;
|
||||
while(tok)
|
||||
{
|
||||
if(e->demon)
|
||||
dynPrintfSz(e, "Incorrect var name\n", NULL);
|
||||
else
|
||||
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)
|
||||
if(tok == r.blanc)
|
||||
{
|
||||
print_var(e, v, &tmp, prettyPrint);
|
||||
tok = ntok(++n);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
if(tok != r.identnext && tok != r.ident)
|
||||
{
|
||||
if(e->demon)
|
||||
dynPrintfSz(e, "Unknown global var\n", NULL);
|
||||
dynPrintfSz(e, "Missing var name\n", NULL);
|
||||
else
|
||||
printf("Unknown global var\n");
|
||||
printf("Missing var name\n");
|
||||
v = NULL;
|
||||
break;
|
||||
}
|
||||
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)
|
||||
{
|
||||
if(e->demon)
|
||||
dynPrintfSz(e, "Incorrect var name : %s\n", e->debugcmd.mPtr);
|
||||
else
|
||||
printf("Incorrect var name : %s\n", e->debugcmd.mPtr);
|
||||
v = NULL;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
vnext = NULL;
|
||||
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];
|
||||
hashtable_do(e, HASH_READ, v, e->nom, &vnext);
|
||||
v = vnext;
|
||||
if( ! v)
|
||||
{
|
||||
if(e->demon)
|
||||
dynPrintfSz(e, "Not a member of hashtable : %s\n", e->nom);
|
||||
else
|
||||
printf("Not a member of hashtable : %s\n", e->nom);
|
||||
v = NULL;
|
||||
break;
|
||||
}
|
||||
// continue
|
||||
tok = ntok(++n);
|
||||
}
|
||||
}
|
||||
if(v != NULL)
|
||||
print_var(e, v, &tmp, prettyPrint);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -691,42 +720,76 @@ void debug(env * e)
|
||||
}
|
||||
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)
|
||||
var * v = NULL, * vnext = NULL;
|
||||
while(tok)
|
||||
{
|
||||
if(e->demon)
|
||||
dynPrintfSz(e, "Incorrect var name\n", NULL);
|
||||
else
|
||||
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];
|
||||
// chercher la var
|
||||
var * v = NULL;
|
||||
if(e->local)
|
||||
if(tok == r.blanc)
|
||||
{
|
||||
hashtable_do(e, HASH_READ, e->local, e->nom, &v);
|
||||
tok = ntok(++n);
|
||||
continue;
|
||||
}
|
||||
if(v == NULL)
|
||||
{
|
||||
/* si pas trouve (ou pas de locale), cherche dans la hash "globale" */
|
||||
hashtable_do(e, HASH_READ, &e->g, e->nom, &v);
|
||||
}
|
||||
if(v != NULL)
|
||||
print_var(e, v, &tmp, prettyPrint);
|
||||
else
|
||||
if(tok != r.identnext && tok != r.ident)
|
||||
{
|
||||
if(e->demon)
|
||||
dynPrintfSz(e, "Unknown var\n", NULL);
|
||||
dynPrintfSz(e, "Missing var name\n", NULL);
|
||||
else
|
||||
printf("Unknown var\n");
|
||||
printf("Missing var name\n");
|
||||
v = NULL;
|
||||
break;
|
||||
}
|
||||
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)
|
||||
{
|
||||
if(e->demon)
|
||||
dynPrintfSz(e, "Incorrect var name : %s\n", e->debugcmd.mPtr);
|
||||
else
|
||||
printf("Incorrect var name : %s\n", e->debugcmd.mPtr);
|
||||
v = NULL;
|
||||
break;
|
||||
}
|
||||
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];
|
||||
// chercher la var
|
||||
vnext = NULL;
|
||||
if( ! v)
|
||||
{
|
||||
if(e->local)
|
||||
{
|
||||
hashtable_do(e, HASH_READ, e->local, e->nom, &vnext);
|
||||
}
|
||||
if(vnext == NULL)
|
||||
{
|
||||
/* si pas trouve (ou pas de locale), cherche dans la hash "globale" */
|
||||
hashtable_do(e, HASH_READ, &e->g, e->nom, &vnext);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hashtable_do(e, HASH_READ, v, e->nom, &vnext);
|
||||
}
|
||||
if(! vnext )
|
||||
{
|
||||
if(e->demon)
|
||||
dynPrintfSz(e, "Unknown var and/or not member of hashtable : %s\n", e->nom);
|
||||
else
|
||||
printf("Unknown var and/or not member of hashtable : %s\n", e->nom);
|
||||
v = NULL;
|
||||
break;
|
||||
}
|
||||
v = vnext;
|
||||
// continue
|
||||
tok = ntok(++n);
|
||||
}
|
||||
}
|
||||
if(v != NULL)
|
||||
{
|
||||
print_var(e, v, &tmp, prettyPrint);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
@@ -761,7 +824,8 @@ void debug(env * e)
|
||||
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
|
||||
ident: (1,1,#3A) (1,1,a-zA-Z_) (0,23,a-zA-Z0-9) ; :_abcABC123
|
||||
identnext:(1,1,#2E) (1,1,a-zA-Z) (0,23,a-zA-Z0-9) ; .abcABC123
|
||||
reste: (1,1,#00-#FF)
|
||||
|
||||
Commandes :
|
||||
@@ -771,7 +835,7 @@ void debug(env * e)
|
||||
q Q continuer et arreter le mode debug 0
|
||||
n N continuer en mode debug pas a pas 1
|
||||
c C continuer en mode debug 2 arret aux points d'arret uniquement
|
||||
v V :ident voir le contenu de la variable <ident>
|
||||
v V :ident.hash voir le contenu de la variable <ident>.<hash>...
|
||||
b B liste des breakpoints
|
||||
b B +/- <nombre> ajouter ou supprimer un breakpoint ; si pas de nombre, à l'emplacement en cours, sinon numero de ligne source <nombre>
|
||||
a A + afficher les infos assembleur (idem trace)
|
||||
@@ -785,13 +849,14 @@ blanc,1,commande,2,aide,3,nombre,4,ajouter,5,supprimer,6,ident,7,reste,8
|
||||
1,9,30-39
|
||||
1,1,2B
|
||||
1,1,2D
|
||||
1,1,3A;5F:1,1,61-7A:41-5A;0,23,61-7A:41-5A:30-39
|
||||
1,1,3A;5F:1,1,61-7A:41-5A:5F;0,23,61-7A:41-5A:30-39
|
||||
1,1,2E;5F:1,1,61-7A:41-5A;0,23,61-7A:41-5A:30-39
|
||||
1,1,00-FF
|
||||
|
||||
|
||||
blanc,1,commande,2,aide,3,nombre,4,ajouter,5,supprimer,6,ident,7,reste,8
|
||||
blanc,1,commande,2,aide,3,nombre,4,ajouter,5,supprimer,6,ident,7,identnext,8,reste,9
|
||||
|
||||
ent16 blanc,commande,aide,nombre,ajouter,supprimer,ident,reste;
|
||||
ent16 blanc,commande,aide,nombre,ajouter,supprimer,ident,identnext,reste;
|
||||
|
||||
r.blanc = rg(e, regles, "blanc", tmp);
|
||||
r.commande = rg(e, regles, "commande", tmp);
|
||||
@@ -800,6 +865,7 @@ r.nombre = rg(e, regles, "nombre", tmp);
|
||||
r.ajouter = rg(e, regles, "ajouter", tmp);
|
||||
r.supprimer = rg(e, regles, "supprimer", tmp);
|
||||
r.ident = rg(e, regles, "ident", tmp);
|
||||
r.identnext = rg(e, regles, "identnext", tmp);
|
||||
r.reste = rg(e, regles, "reste", tmp);
|
||||
|
||||
*/
|
||||
|
||||
@@ -5,5 +5,7 @@ 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
|
||||
ident: (1,1,#3A) (1,1,a-zA-Z_) (0,23,a-zA-Z0-9) ; :_abcABC123
|
||||
identnext:(1,1,#2E) (1,1,a-zA-Z) (0,23,a-zA-Z0-9) ; .abcABC123
|
||||
reste: (1,1,#00-#FF)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
; Usage: lw debug <pid2debug>
|
||||
;
|
||||
begin wdebug
|
||||
declare idProc, msg, pid, cmd, ret, capt, again, delay, debugging
|
||||
declare idProc, msg, pid, cmd, ret, capt, again, delay, debugging, signal
|
||||
declare OK, ERROR
|
||||
let debugging = @false
|
||||
let OK = 0
|
||||
@@ -43,9 +43,8 @@ begin wdebug
|
||||
echonl msg
|
||||
let capt = ''
|
||||
let ret = 0
|
||||
let cmd = 'kill -10 ':pid
|
||||
invoke system&execute(cmd, ret, capt)
|
||||
breakon ret # OK
|
||||
let signal = 10
|
||||
invoke system&sendSignal(pid, signal)
|
||||
; now waiting for shm to init from signaled process
|
||||
let delay = 1
|
||||
invoke system&sleep(delay)
|
||||
|
||||
@@ -1310,6 +1310,8 @@ WAPIDECL long dynInsSz(env * e, Dynamic * this, long numChamp, long numSousChamp
|
||||
}
|
||||
/* chercher le sousChamp */
|
||||
nSep = 1;
|
||||
if(numSousChamp == 0 && (this->mPtr[iPos + 1] == separateurChamp || iPos + 1 == this->mLg))
|
||||
nSep = 0; // si champ vide et sous-champ no 1, ne pas ajouter de marque de sous-champ a la fin
|
||||
for(iScan = iPos + 1; numSousChamp > 0 && iScan < this->mLg; iScan++)
|
||||
if(this->mPtr[iScan] == separateurSousChamp)
|
||||
{
|
||||
@@ -1318,9 +1320,9 @@ WAPIDECL long dynInsSz(env * e, Dynamic * this, long numChamp, long numSousChamp
|
||||
}
|
||||
else if(this->mPtr[iScan] == separateurChamp)
|
||||
{
|
||||
iPos = iScan - 1;
|
||||
nSep = 0;
|
||||
break;
|
||||
iPos = iScan - 1;
|
||||
nSep = 0;
|
||||
break;
|
||||
}
|
||||
else if(iScan == this->mLg - 1)
|
||||
{
|
||||
@@ -3170,4 +3172,95 @@ WAPIDECL long dynTrimUtf8(env * e, Dynamic * this, Dynamic * resultat, char * ca
|
||||
return DYN_OK;
|
||||
}
|
||||
|
||||
WAPIDECL long dynCleanString(env * e, Dynamic * this, octet debutGarde, octet finGarde, long convHexa)
|
||||
{
|
||||
/* nettoie la chaine <this> des octets dont le code ascii n'est PAS dans [debutGarde, finGarde]
|
||||
convHexa : FALSE pour supprimer et ne pas convertir en hexa #xx, TRUE garder le car et mis en hexa #xx
|
||||
*/
|
||||
if(this == NULL || debutGarde > finGarde)
|
||||
return DYN_ERR;
|
||||
if(this->mLg == 0)
|
||||
return DYN_OK;
|
||||
/* */
|
||||
if(convHexa)
|
||||
{
|
||||
long scan = 0, lgc = 1, lgr = 3;
|
||||
do
|
||||
{
|
||||
if(this->mPtr[scan] >= debutGarde && this->mPtr[scan] <= finGarde)
|
||||
scan++;
|
||||
else
|
||||
{
|
||||
// repris de dynChange, quand remplace est plus grand que cherchee : insertion de 2 cars
|
||||
// car remplace par # et insertion du code ascii (remplace 1 octet (lgc) par 3 octets (lgr))
|
||||
// scan = pos_p ( => p - this->mPtr )
|
||||
if(dynCtrl(e, this, this->mLg + lgr - lgc, DYN_TRUE))
|
||||
return DYN_ERR; // erreur memoire
|
||||
char * p = this->mPtr + scan;
|
||||
//
|
||||
// deplacement depuis la fin
|
||||
long n = this->mLg - scan - lgc + 1; // +1 pour copier le \0 de fin...
|
||||
memcopie(p + lgr, p + lgc, n);
|
||||
//
|
||||
char * hex = dynConvertCharToCharHexa((octet)(*p));
|
||||
*p++ = '#';
|
||||
*p++ = hex[0];
|
||||
*p++ = hex[1];
|
||||
//
|
||||
this->mLg += (lgr - lgc);
|
||||
scan += lgr;
|
||||
}
|
||||
} while (scan < this->mLg);
|
||||
/* this->mLg et 0 de fin deja a jour */
|
||||
this->mPtr[this->mLg] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* equivalent a dynErase sur octets hors de la plage de codes ASCII, PAS de gestion UTF8 ici, uniquement octets */
|
||||
long i, pos = 0;
|
||||
for(i = 0; i < this->mLg; i++)
|
||||
{
|
||||
if(this->mPtr[i] >= debutGarde && this->mPtr[i] <= finGarde)
|
||||
{
|
||||
if(pos != i) /* pour ne pas recopier les premiers caracteres quand pas de suppression */
|
||||
this->mPtr[pos++] = this->mPtr[i];
|
||||
else
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
this->mLg = pos;
|
||||
this->mPtr[this->mLg] = 0;
|
||||
}
|
||||
return DYN_OK;
|
||||
}
|
||||
|
||||
WAPIDECL void dynCleanHexaMark(env * e, Dynamic * this)
|
||||
{
|
||||
if(this == NULL)
|
||||
return;
|
||||
/* */
|
||||
/* equivalent a dynErase sur #xx, suppression "xx" et remplacement # par l'octet "xx" */
|
||||
long i, pos = 0;
|
||||
for(i = 0; i < this->mLg; i++)
|
||||
{
|
||||
if(this->mPtr[i] != '#' || i >= this->mLg - 2) // car si pas la place pour le code ascii, ne pas traiter # comme debut du code (securite)
|
||||
{
|
||||
if(pos != i) /* pour ne pas recopier les premiers caracteres quand pas de suppression */
|
||||
this->mPtr[pos++] = this->mPtr[i];
|
||||
else
|
||||
pos++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// remplace #xx (hexa) par l'octet correspondant
|
||||
if(dynConvertCharHexaToChar(this->mPtr[i + 1], this->mPtr[i + 2], &this->mPtr[pos]) == DYN_ERR)
|
||||
this->mPtr[pos] = '?'; // securite
|
||||
pos++;
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
this->mLg = pos;
|
||||
this->mPtr[this->mLg] = 0;
|
||||
}
|
||||
|
||||
/* ********************************************** */
|
||||
@@ -149,6 +149,8 @@ WAPIDECL long dynFmtUtf8(env * e, Dynamic * this, Dynamic * resultat, char cadra
|
||||
WAPIDECL long dynFmtNumber(env * e, ent64s valeur, Dynamic * resultat, char cadrage, char filler, long lg);
|
||||
WAPIDECL long dynTrim(env * e, Dynamic * this, Dynamic * resultat, char car, long option);
|
||||
WAPIDECL long dynTrimUtf8(env * e, Dynamic * this, Dynamic * resultat, char * car, long option);
|
||||
WAPIDECL long dynCleanString(env * e, Dynamic * this, octet debut, octet fin, long convHexa);
|
||||
WAPIDECL void dynCleanHexaMark(env * e, Dynamic * this);
|
||||
|
||||
/* ********************************************** */
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
/* **********************************************
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024-2026 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 "langage.h"
|
||||
#include "dynamic.h"
|
||||
|
||||
typedef struct {
|
||||
int dum;
|
||||
} modContextEncod;
|
||||
|
||||
WAPIDECL long str2hex(env * e, Dynamic * this, Dynamic * resultat);
|
||||
WAPIDECL long str2base64(env * e, Dynamic * this, Dynamic * resultat);
|
||||
WAPIDECL long hex2str(env * e, Dynamic * this, Dynamic * resultat);
|
||||
WAPIDECL long base642str(env * e, Dynamic * this, Dynamic * resultat);
|
||||
+233
@@ -0,0 +1,233 @@
|
||||
/* **********************************************
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024-2026 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 "encod.h"
|
||||
|
||||
// force exporting
|
||||
#ifdef WINLIB
|
||||
#undef WAPIDECL
|
||||
#define WAPIDECL __declspec(dllexport)
|
||||
#else
|
||||
#undef WAPIDECL
|
||||
#define WAPIDECL
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------- */
|
||||
|
||||
/* ****** PRIVATE ************************ */
|
||||
|
||||
static char hexa[256] = { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,
|
||||
-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 128 cars a la fin de cette ligne */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 };
|
||||
|
||||
static char carhex[16] = {"0123456789abcdef"};
|
||||
// TODO static char carHEX[16] = {"0123456789ABCDEF"};
|
||||
|
||||
static char base64[256] = { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, /* '+' = 62 ; '/' = 63 ; '-' (62) se trouve au milieu entre les deux */
|
||||
52,53,54,55,56,57,58,59,60,61,-1,-1,-1,99,-1,-1, /* '=' mis a 99 */
|
||||
-1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,
|
||||
15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, /* dernier -1 ici = '_' (63) */
|
||||
-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
|
||||
41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1, /* 128 cars a la fin de cette ligne */
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
||||
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 }; // "=" mis a 99
|
||||
|
||||
static char carBase64[65] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}; /* et caractere "=" en complement */
|
||||
// TODO static char carBase64url[65] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_="}; /* et caractere "=" en complement */
|
||||
|
||||
/* TODO compatible UTF8 !! */
|
||||
|
||||
/* ****** PUBLIC ************************ */
|
||||
WAPIDECL long str2hex(env * e, Dynamic * this, Dynamic * resultat)
|
||||
{
|
||||
if(this->mLg == 0)
|
||||
{
|
||||
dynSetLen(e, resultat, 0);
|
||||
return DYN_OK;
|
||||
}
|
||||
if(dynCtrl(e, resultat, this->mLg * 2, DYN_FALSE)) /* chaine hexa : taille double de celle origine */
|
||||
return DYN_ERR;
|
||||
long from = this->mLg - 1;
|
||||
long to = from * 2 + 1;
|
||||
/* cette methode fonctionne aussi si this et resultat pointent sur la meme variable... mettre TRUE dans dynCtrl alors ! */
|
||||
for( ;from >= 0; )
|
||||
{
|
||||
resultat->mPtr[to--] = carhex[this->mPtr[from] % 16];
|
||||
resultat->mPtr[to--] = carhex[this->mPtr[from--] / 16];
|
||||
}
|
||||
dynSetLen(e, resultat, this->mLg * 2);
|
||||
return DYN_OK;
|
||||
}
|
||||
|
||||
WAPIDECL long str2base64(env * e, Dynamic * this, Dynamic * resultat)
|
||||
{
|
||||
/* conversion en base64 /base64url */
|
||||
/* 3 cars en clair en donne 4 en base 64 ; si le dernier bloc contient 2 cars, la sortie est de 3 cars */
|
||||
/* + car "=" ; si le dernier bloc contient 1 car, la sortie est de 2 cars + deux cars "=" */
|
||||
/* quand le dernier bloc contient 1 ou 2 cars, les bits manquants pour avoir des octets complets sont mis a 0 */
|
||||
/* +-------------+-----------+-------------+ */
|
||||
/* | 6 | 2 | 4 | 4 | 2 | 6 | */
|
||||
/* +---------+---------+---------+---------+ */
|
||||
/* */
|
||||
if(this->mLg == 0)
|
||||
{
|
||||
dynSetLen(e, resultat, 0);
|
||||
return DYN_OK;
|
||||
}
|
||||
long lg64 = this->mLg / 3;
|
||||
if(this->mLg % 3 != 0)
|
||||
lg64++;
|
||||
lg64 *= 4; // longueur finale du base64
|
||||
if(dynCtrl(e, resultat, lg64, DYN_FALSE))
|
||||
return DYN_ERR;
|
||||
/* */
|
||||
long from, to;
|
||||
for(from = 0, to = 0; from < this->mLg; from += 3)
|
||||
{
|
||||
if(from + 1 >= this->mLg)
|
||||
{
|
||||
/* bloc de 1 octet => 2 cars en sortie + 2 cars de complement */
|
||||
resultat->mPtr[to++] = carBase64[this->mPtr[from] >> 2];
|
||||
resultat->mPtr[to++] = carBase64[((this->mPtr[from] & 3) << 4)];
|
||||
resultat->mPtr[to++] = carBase64[64];
|
||||
resultat->mPtr[to++] = carBase64[64];
|
||||
/* */
|
||||
} else if(from + 2 >= this->mLg)
|
||||
{
|
||||
/* bloc de 2 octets => 3 cars en sortie + 1 car en complement */
|
||||
resultat->mPtr[to++] = carBase64[this->mPtr[from] >> 2];
|
||||
resultat->mPtr[to++] = carBase64[((this->mPtr[from] & 3) << 4) | (this->mPtr[from + 1] >> 4)];
|
||||
resultat->mPtr[to++] = carBase64[((this->mPtr[from + 1] & 15) << 2)];
|
||||
resultat->mPtr[to++] = carBase64[64];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* bloc de 3 octets => 4 cars en sortie */
|
||||
resultat->mPtr[to++] = carBase64[this->mPtr[from] >> 2];
|
||||
resultat->mPtr[to++] = carBase64[((this->mPtr[from] & 3) << 4) | (this->mPtr[from + 1] >> 4)];
|
||||
resultat->mPtr[to++] = carBase64[((this->mPtr[from + 1] & 15) << 2) | (this->mPtr[from + 2] >> 6)];
|
||||
resultat->mPtr[to++] = carBase64[this->mPtr[from + 2] & 63];
|
||||
}
|
||||
}
|
||||
/* */
|
||||
dynSetLen(e, resultat, lg64);
|
||||
return DYN_OK;
|
||||
}
|
||||
|
||||
WAPIDECL long hex2str(env * e, Dynamic * this, Dynamic * resultat)
|
||||
{
|
||||
if(this->mLg == 0)
|
||||
{
|
||||
dynSetLen(e, resultat, 0);
|
||||
return DYN_OK;
|
||||
}
|
||||
if(this->mLg % 2 != 0)
|
||||
return DYN_ERR; /* erreur format hexa incorrect */
|
||||
if(dynCtrl(e, resultat, this->mLg / 2, DYN_FALSE))
|
||||
return DYN_ERR;
|
||||
/* */
|
||||
char c1, c2;
|
||||
long from, to;
|
||||
for(from = 0, to = 0; from < this->mLg; from += 2)
|
||||
{
|
||||
if((c1 = hexa[this->mPtr[from]]) == -1 || (c2 = hexa[this->mPtr[from + 1]]) == -1)
|
||||
return DYN_ERR; /* erreur format hexa incorrect */
|
||||
resultat->mPtr[to++] = (c1 << 4) | c2;
|
||||
}
|
||||
dynSetLen(e, resultat, this->mLg / 2);
|
||||
return DYN_OK;
|
||||
}
|
||||
|
||||
WAPIDECL long base642str(env * e, Dynamic * this, Dynamic * resultat)
|
||||
{
|
||||
|
||||
/* conversion en clair de la chaine en base64 */
|
||||
/* +-------------+-----------+-------------+ */
|
||||
/* | 6 | 2 | 4 | 4 | 2 | 6 | */
|
||||
/* +---------+---------+---------+---------+ */
|
||||
if(this->mLg == 0)
|
||||
{
|
||||
dynSetLen(e, resultat, 0);
|
||||
return DYN_OK;
|
||||
}
|
||||
if(this->mLg % 4 != 0)
|
||||
return DYN_ERR; /* erreur format base64 incorrect */
|
||||
long lgClair = (this->mLg / 4) * 3;
|
||||
if(dynCtrl(e, resultat, lgClair, DYN_FALSE))
|
||||
return DYN_ERR;
|
||||
/* */
|
||||
long from, to;
|
||||
for(from = 0, to = 0; from < this->mLg; from += 4, to += 3)
|
||||
{
|
||||
char c1 = base64[this->mPtr[from]];
|
||||
char c2 = base64[this->mPtr[from + 1]];
|
||||
char c3 = base64[this->mPtr[from + 2]];
|
||||
char c4 = base64[this->mPtr[from + 3]];
|
||||
if(c1 == -1 || c2 == -1 || c3 == -1 || c4 == -1 || c1 == 99 || c2 == 99 || (c3 == 99 && c4 != 99))
|
||||
return DYN_ERR; /* erreur format base64 incorrect */
|
||||
if(c4 == 99 && from + 4 < this->mLg)
|
||||
return DYN_ERR; /* '=' autorise en fin de chaine uniquement */
|
||||
//
|
||||
resultat->mPtr[to] = 0;
|
||||
resultat->mPtr[to + 1] = 0;
|
||||
resultat->mPtr[to + 2] = 0;
|
||||
resultat->mPtr[to] = c1 << 2;
|
||||
resultat->mPtr[to] |= c2 >> 4;
|
||||
if(c3 != 99)
|
||||
{
|
||||
resultat->mPtr[to + 1] = (c2 & 15) << 4;
|
||||
resultat->mPtr[to + 1] |= c3 >> 2;
|
||||
if(c4 != 99)
|
||||
{
|
||||
resultat->mPtr[to + 2] = (c3 & 3) << 6;
|
||||
resultat->mPtr[to + 2] |= c4;
|
||||
}
|
||||
else
|
||||
lgClair--;
|
||||
}
|
||||
else
|
||||
lgClair--;
|
||||
}
|
||||
dynSetLen(e, resultat, lgClair);
|
||||
return DYN_OK;
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024 lanisys.fr
|
||||
\/ \/ Copyright 2024-2026 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
#include "langage.h"
|
||||
#include "dynamic.h"
|
||||
#include "lex.c"
|
||||
#include "lex.h"
|
||||
|
||||
env e;
|
||||
|
||||
@@ -49,7 +49,7 @@ blank,1,comment,2,begin,3,background,4,library,5,end,6,except,7,throw,8,catch,9,
|
||||
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
|
||||
new,41,class,42,this,43,parent,44,hold,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
|
||||
@@ -61,7 +61,7 @@ struct {
|
||||
ent16 sub,endsub,if_,then,else_,elseif,endif,do_,call,invoke;
|
||||
ent16 return_,returnon,loop,endloop,foreach,in,like,endfor,break_,breakon;
|
||||
ent16 continue_,continueon,nop,part,echonl,echo,input,declare,let,delet;
|
||||
ent16 new,class,this,parent,free,precision,setsep,int_,frac,abs;
|
||||
ent16 new,class,this,parent,hold,precision,setsep,int_,frac,abs;
|
||||
ent16 neg,round,type,len,count,dcount,field,index,search,change;
|
||||
ent16 format,insert,remove,tonum,tostring,equal,diff,gt,lt,gte;
|
||||
ent16 lte,and,or,not,beginpar,endpar,beginh,endh,begins,ends;
|
||||
@@ -119,7 +119,7 @@ void init_reg(env * e, Dynamic * regles, Dynamic * tmp)
|
||||
r.class = rg(e, regles, "class", tmp);
|
||||
r.this = rg(e, regles, "this", tmp);
|
||||
r.parent = rg(e, regles, "parent", tmp);
|
||||
r.free = rg(e, regles, "free", tmp);
|
||||
r.hold = rg(e, regles, "hold", tmp);
|
||||
r.precision = rg(e, regles, "precision", tmp);
|
||||
r.setsep = rg(e, regles, "setsep", tmp);
|
||||
r.int_ = rg(e, regles, "int", tmp);
|
||||
@@ -186,9 +186,19 @@ enum {
|
||||
COMMENT_EOL = 8
|
||||
};
|
||||
|
||||
static void formatage_asm(Dynamic * s, Dynamic * f)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
static void formatage(Dynamic * s, Dynamic * f, int type)
|
||||
{
|
||||
// s : source ; f : source apres formatage, type : 1 w, 2 pcode
|
||||
if(type == 2)
|
||||
{
|
||||
formatage_asm(s, f);
|
||||
return;
|
||||
}
|
||||
//Dynamic token; /* contient les tokens suite au decodage lex d'une ligne */
|
||||
ent16 tok; //,tok2,tok3; /* token lu par la macro ci-dessous "nreg" */
|
||||
long n; /* indice en cours dans les token (parametre de la macro "nreg") base 1 */
|
||||
@@ -319,7 +329,7 @@ static void formatage(Dynamic * s, Dynamic * f, int type)
|
||||
//if(tok2 != r.comment)
|
||||
// pos_comment = -1;
|
||||
}
|
||||
// si pos_comment > -1 traiter le commentaire en fin de ligne, position multiple de 10 (par exemple), >= position actuelle
|
||||
// si pos_comment > -1 traiter le commentaire en fin de ligne, position multiple de 8, >= position actuelle
|
||||
// + formatage debut de ligne
|
||||
if(pos_comment == -1)
|
||||
{
|
||||
@@ -331,7 +341,8 @@ static void formatage(Dynamic * s, Dynamic * f, int type)
|
||||
}
|
||||
else
|
||||
{
|
||||
dynSubstr(&e, &trav, &lig, pos - 1, pos_comment - pos, 1, DYN_NONE, 10, DYN_NONE);
|
||||
dynSubstr(&e, &trav, &tmp, pos - 1, pos_comment - pos, 1, DYN_NONE, 10, DYN_NONE);
|
||||
dynTrim(&e, &tmp, &lig, ' ', 2);
|
||||
#ifdef WINLIB
|
||||
dynSubstr(&e, &trav, &tmp, pos_comment - 1, ((intptr_t)(trav.mPtr)) - pos_comment, 1, DYN_NONE, 10, DYN_NONE);
|
||||
#else
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
begin gened
|
||||
;
|
||||
class Gened = {Base}
|
||||
;
|
||||
let Gened.trace = @false
|
||||
;
|
||||
let Gened.name = ''
|
||||
let Gened.query = ''
|
||||
;
|
||||
let Gened.breakInfo = ''
|
||||
let Gened.breakCount = 0
|
||||
;
|
||||
let Gened.recordCount = 0
|
||||
let Gened.init = @true
|
||||
let Gened.first = @true
|
||||
let Gened.last = @false
|
||||
let Gened.currentRecord = ''
|
||||
let Gened.precRecord = ''
|
||||
;
|
||||
; breakInfo, champs en multi-valeurs :
|
||||
let Gened.BREAKFIELDNUM = 1 ; {1} = num champ dans l'enregistrement
|
||||
let Gened.BREAKFIELDVAL = 2 ; {2} = valeur champ enreg en cours
|
||||
let Gened.BREAKFIELDVALPREC = 3 ; {2} = valeur champ enreg en cours
|
||||
let Gened.BREAKDIFF = 4 ; {4} = flag si difference pour ce niveau
|
||||
let Gened.BREAKCOUNTER = 5 ; {5} = compteur d'enregs pour ce niveau de rupture
|
||||
;
|
||||
sub Gened.ParamSection()
|
||||
; maj de name/query/breakInfo{1}
|
||||
if this.trace then
|
||||
echonl "ED => in ParamSection"
|
||||
endif
|
||||
except
|
||||
endsub
|
||||
;
|
||||
sub Gened.SetQuery()
|
||||
; creer la requete de recuperation des enregistrements (utilise query)
|
||||
if this.trace then
|
||||
echonl "ED => in SetQuery"
|
||||
endif
|
||||
except
|
||||
endsub
|
||||
;
|
||||
sub Gened.GetNextRecord()
|
||||
; recupere l'enregistrement suivant, et l'ecrit dans this.currentRecord et this.last = @false, sinon this.last = @true et this.currentRecord = ''
|
||||
if this.trace then
|
||||
echonl "ED => in GetNextRecord"
|
||||
endif
|
||||
except
|
||||
endsub
|
||||
;
|
||||
sub Gened.EndOfQuery()
|
||||
; terminer la requete de recup. des enregistrements
|
||||
if this.trace then
|
||||
echonl "ED => in EndOfQuery"
|
||||
endif
|
||||
except
|
||||
endsub
|
||||
;
|
||||
sub Gened.InitSection()
|
||||
if this.trace then
|
||||
echonl "ED => in InitSection"
|
||||
endif
|
||||
except
|
||||
endsub
|
||||
;
|
||||
sub Gened.DoSection()
|
||||
if this.trace then
|
||||
echonl "ED => in DoSection, record #23":this.recordCount:' => ':this.currentRecord
|
||||
endif
|
||||
except
|
||||
endsub
|
||||
;
|
||||
sub Gened.EndSection()
|
||||
if this.trace then
|
||||
echonl "ED => in EndSection"
|
||||
endif
|
||||
except
|
||||
endsub
|
||||
;
|
||||
sub Gened.LevelBreakHeader(level)
|
||||
if this.trace then
|
||||
echonl "ED => in LevelBreakHeader:":level:' ':field(this.breakInfo{this.BREAKFIELDVAL, level}, "#FC", level)
|
||||
endif
|
||||
except
|
||||
endsub
|
||||
;
|
||||
sub Gened.LevelBreakFooter(level)
|
||||
if this.trace then
|
||||
echonl "ED => in LevelBreakFooter:":level:' ':field(this.breakInfo{this.BREAKFIELDVALPREC, level}, "#FC", level):' last(':this.last:')'
|
||||
endif
|
||||
except
|
||||
endsub
|
||||
;
|
||||
sub Gened.Execute()
|
||||
declare un, moinsUn, breakVal, breakNum ; compteur des niveaux de rupture
|
||||
let un = 1
|
||||
let moinsUn = neg(1)
|
||||
declare SVM
|
||||
let SVM = "#FC"
|
||||
let breakVal = ''
|
||||
let breakNum = 0
|
||||
;
|
||||
do this.ParamSection()
|
||||
;
|
||||
do this.SetQuery()
|
||||
;
|
||||
do this.GetNextRecord()
|
||||
;
|
||||
let this.recordCount = 0
|
||||
let this.breakCount = dcount(this.breakInfo, this.BREAKFIELDNUM)
|
||||
;
|
||||
do this.InitSection()
|
||||
;
|
||||
if not(this.last) then
|
||||
loop
|
||||
breakon this.last
|
||||
if not(this.init) then
|
||||
do this.GetNextRecord()
|
||||
else
|
||||
let this.init = @false
|
||||
endif
|
||||
;
|
||||
foreach breakNum in un, this.breakCount
|
||||
let breakVal = this.currentRecord{ this.breakInfo{this.BREAKFIELDNUM, breakNum} }
|
||||
if breakNum > un then
|
||||
let breakVal = this.breakInfo{this.BREAKFIELDVAL, breakNum - 1}:SVM:breakVal
|
||||
endif
|
||||
let this.breakInfo{this.BREAKFIELDVAL, breakNum} = breakVal
|
||||
let this.breakInfo{this.BREAKDIFF, breakNum} = (this.breakInfo{this.BREAKFIELDVALPREC, breakNum} # breakVal)
|
||||
endfor
|
||||
;
|
||||
if this.breakCount > 0 and (this.first or this.last or this.breakInfo{4, this.breakCount}) then
|
||||
if not(this.first) then
|
||||
foreach breakNum in this.breakCount, un, moinsUn
|
||||
if this.last or this.breakInfo{this.BREAKDIFF, breakNum} then
|
||||
do this.LevelBreakFooter(breakNum)
|
||||
endif
|
||||
endfor
|
||||
endif
|
||||
if not(this.last) then
|
||||
foreach breakNum in un, this.breakCount
|
||||
if this.first or this.breakInfo{this.BREAKDIFF, breakNum} then
|
||||
let this.breakInfo{this.BREAKCOUNTER, breakNum} = 0
|
||||
do this.LevelBreakHeader(breakNum)
|
||||
endif
|
||||
endfor
|
||||
endif
|
||||
let this.first = @false
|
||||
endif
|
||||
;
|
||||
if not(this.last) then
|
||||
foreach breakNum in un, this.breakCount
|
||||
let this.breakInfo{this.BREAKCOUNTER, breakNum} = this.breakInfo{this.BREAKCOUNTER, breakNum} + 1
|
||||
endfor
|
||||
let this.recordCount = this.recordCount + 1
|
||||
;
|
||||
do this.DoSection()
|
||||
;
|
||||
let this.precRecord = this.currentRecord
|
||||
let this.breakInfo{this.BREAKFIELDVALPREC} = this.breakInfo{this.BREAKFIELDVAL}
|
||||
endif
|
||||
endloop
|
||||
endif
|
||||
;
|
||||
do this.EndSection()
|
||||
;
|
||||
do this.EndOfQuery()
|
||||
;
|
||||
except
|
||||
; TODO
|
||||
echonl "Exception in Execute"
|
||||
endsub
|
||||
;
|
||||
class EdTest = {Gened}
|
||||
;
|
||||
sub EdTest.SetQuery()
|
||||
declare path
|
||||
let path = 'data.txt'
|
||||
let this.data = ''
|
||||
let this.line = 0
|
||||
;
|
||||
invoke file&get(path, this.data)
|
||||
let this.data = change(this.data, '#0A', @fm)
|
||||
;
|
||||
let this.breakInfo = "3":@vm:5
|
||||
;
|
||||
do parent.SetQuery
|
||||
except
|
||||
endsub
|
||||
;
|
||||
sub EdTest.InitSection()
|
||||
;echonl 'nb break: ':this.breakCount
|
||||
do parent.InitSection
|
||||
except
|
||||
endsub
|
||||
;
|
||||
sub EdTest.GetNextRecord()
|
||||
let this.line = this.line + 1
|
||||
let this.currentRecord = this.data{this.line}
|
||||
if this.currentRecord = '' then
|
||||
let this.last = @true
|
||||
else
|
||||
let this.currentRecord = change(this.currentRecord, ';', @fm)
|
||||
endif
|
||||
;echonl "EdTest GetNextRecord: ":this.last:' / line ':this.line:' => ':this.currentRecord
|
||||
except
|
||||
endsub
|
||||
;
|
||||
declare ed
|
||||
let ed = new EdTest
|
||||
let ed.trace = @true
|
||||
do ed.Execute()
|
||||
;
|
||||
except
|
||||
;
|
||||
echonl "Exception in main: ":@except
|
||||
end
|
||||
@@ -2,7 +2,7 @@
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024 lanisys.fr
|
||||
\/ \/ Copyright 2024-2026 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
@@ -27,213 +27,10 @@
|
||||
|
||||
#include "langage.h"
|
||||
#include "dynamic.h"
|
||||
#include "lex.c"
|
||||
#include "lex.h"
|
||||
|
||||
env e;
|
||||
|
||||
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);
|
||||
if(pos > 0)
|
||||
{
|
||||
dynField(e, regles, tmp, 1, pos + 1, 10, ',', 1);
|
||||
pos = dynToNum(e, tmp, DYN_FALSE, 5); // pas de signe et num regle sur 16 bits : 5 chiffres
|
||||
if(tmp->mInternal != DYN_OK)
|
||||
pos = 0;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
struct {
|
||||
long blanc, nomregle, debut, fin, occ, infini, commentaire, intervalle, hexa, car, reste;
|
||||
} r;
|
||||
|
||||
void init_reg(env * e, Dynamic * regles, Dynamic * tmp)
|
||||
{
|
||||
r.blanc = rg(e, regles, "blanc", tmp); // 1
|
||||
r.nomregle = rg(e, regles, "nomregle", tmp); // 2
|
||||
r.debut = rg(e, regles, "debut", tmp); // 3
|
||||
r.fin = rg(e, regles, "fin", tmp); // 4
|
||||
r.occ = rg(e, regles, "occ", tmp); // 5
|
||||
r.infini = rg(e, regles, "infini", tmp); // 6
|
||||
r.commentaire = rg(e, regles, "commentaire", tmp); // 7
|
||||
r.intervalle = rg(e, regles, "intervalle", tmp); // 8
|
||||
r.hexa = rg(e, regles, "hexa", tmp); // 9
|
||||
r.car = rg(e, regles, "car", tmp); // 10
|
||||
r.reste = rg(e, regles, "reste", tmp); // 11
|
||||
}
|
||||
|
||||
long parse(Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic * trav, Dynamic * encours)
|
||||
{
|
||||
#define nreg(x) ((x)*2 > trav->mLg ? 0 : *(ent16 *)(trav->mPtr + (x)*2 - 2))
|
||||
/* */
|
||||
static int numlig = 0;
|
||||
numlig++;
|
||||
/* */
|
||||
if(valex->mLg == 0)
|
||||
return OK; /* ligne vide */
|
||||
/* */
|
||||
int nbres = dynDcount(&e, resultat, 10, DYN_NONE, DYN_NONE);
|
||||
int nbval = dynDcount(&e, valex, cVM, 2, cFM);
|
||||
ent16 regle;
|
||||
dynSetLen(&e, trav, 0);
|
||||
dynSetLen(&e, encours, 0);
|
||||
for(int ival = nbval; ival > 0; ival--)
|
||||
{
|
||||
/* suppression des regles 1 et 7 (blanc et commentaire) */
|
||||
dynField(&e, valex, tmp, 2, ival, cFM, cVM, 1);
|
||||
regle = dynToNum(&e, tmp, DYN_FALSE, 0);
|
||||
if(regle == r.blanc || regle == r.commentaire)
|
||||
{
|
||||
dynDel(&e, valex, 1, ival, cFM, cVM, 1);
|
||||
dynDel(&e, valex, 2, ival, cFM, cVM, 1);
|
||||
dynDel(&e, valex, 3, ival, cFM, cVM, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(dynCtrl(&e, trav, trav->mLg + 2, TRUE) != DYN_OK)
|
||||
return DYN_ERR;
|
||||
if(trav->mLg > 0)
|
||||
memcopie(trav->mPtr + 2, trav->mPtr, trav->mLg);
|
||||
*(ent16 *)(trav->mPtr) = regle;
|
||||
dynSetLen(&e, trav, trav->mLg + 2);
|
||||
}
|
||||
}
|
||||
//dynDel(&e, valex, 2, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
if(trav->mLg == 0)
|
||||
return OK; /* blancs et/ou commentaire seuls */
|
||||
/* */
|
||||
//for(int i=1;i<=trav->mLg/2;i++) printf("%d,",nreg(i)); printf("\n");
|
||||
/* debut d'analyse des tokens : nomregle */
|
||||
if(nreg(1) != r.nomregle)
|
||||
{
|
||||
dynField(&e, valex, tmp, 3, 1, cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : nom regle attendu\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR;
|
||||
}
|
||||
/* liste de et/ou */
|
||||
for(ent16 n = 2;;)
|
||||
{
|
||||
if((regle = nreg(n)) == 0)
|
||||
break;
|
||||
/* */
|
||||
if(regle == r.debut || regle == r.car) ; else
|
||||
{
|
||||
dynField(&e, valex, tmp, 3, n, cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : car ou debut et/ou attendu\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR;
|
||||
}
|
||||
/* et */
|
||||
if(n == 2)
|
||||
dynStoreSz(&e, valex, 4, DYN_NONE, "", 0, cFM, DYN_NONE);
|
||||
else
|
||||
dynConcatSz(&e, valex, ";", 1);
|
||||
/* */
|
||||
if(regle == r.car)
|
||||
{
|
||||
/* 1 caractere = (1,1,car) (raccourci d'ecriture) */
|
||||
dynConcatSz(&e, valex, "1,1,", 4);
|
||||
dynField(&e, valex, tmp, 1, n, cFM, cVM, 1);
|
||||
dynConcat(&e, valex, tmp);
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
if(nreg(n+1) == r.occ && (nreg(n+2) == r.occ || nreg(n+2) == r.infini)) ; else
|
||||
{
|
||||
dynField(&e, valex, tmp, 3, n, cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : occurence min/max attendue %d\n", numlig, tmp->mPtr, n);
|
||||
return DYN_ERR;
|
||||
}
|
||||
n++;
|
||||
dynField(&e, valex, tmp, 1, n, cFM, cVM, 1);
|
||||
dynIconv(&e, tmp, encours, "X");
|
||||
dynConcat(&e, valex, encours); // occmin
|
||||
n++;
|
||||
if(nreg(n) == r.infini)
|
||||
dynConcatSz(&e, valex, "-1,", 3);
|
||||
else
|
||||
{
|
||||
dynField(&e, valex, tmp, 1, n, cFM, cVM, 1);
|
||||
dynIconv(&e, tmp, encours, "X");
|
||||
dynConcat(&e, valex, encours); // occmax
|
||||
}
|
||||
ent16 n1,n2,n3; char unefois[2] = {0};
|
||||
n1 = nreg(n+1);
|
||||
n2 = nreg(n+2);
|
||||
n3 = nreg(n+3);
|
||||
while(n1 == r.car || n1 == r.hexa || ((n1 == r.car || n1 == r.hexa) && n2 == r.intervalle && (n3 == r.car || n3 == r.hexa)))
|
||||
{
|
||||
dynConcatSz(&e, valex, unefois, DYN_LGNONE);
|
||||
if((n1 == r.car || n1 == r.hexa) && n2 == r.intervalle && (n3 == r.car || n3 == r.hexa))
|
||||
{
|
||||
n++;
|
||||
dynField(&e, valex, tmp, 1, n, cFM, cVM, 1);
|
||||
if(n1 == 10)
|
||||
dynConcat(&e, valex, tmp);
|
||||
else
|
||||
{
|
||||
dynIconv(&e, tmp, encours, "X");
|
||||
dynConcatSz(&e, valex, encours->mPtr + 1, DYN_LGNONE); // copier apres le #
|
||||
}
|
||||
dynConcatSz(&e, valex, "-", 1);
|
||||
n += 2;
|
||||
dynField(&e, valex, tmp, 1, n, cFM, cVM, 1);
|
||||
if(n3 == r.car)
|
||||
dynConcat(&e, valex, tmp);
|
||||
else
|
||||
{
|
||||
dynIconv(&e, tmp, encours, "X");
|
||||
dynConcatSz(&e, valex, encours->mPtr + 1, DYN_LGNONE); // copier apres le #
|
||||
}
|
||||
}
|
||||
else if(n1 == r.car)
|
||||
{
|
||||
n++;
|
||||
dynField(&e, valex, tmp, 1, n, cFM, cVM, 1);
|
||||
dynConcat(&e, valex, tmp);
|
||||
}
|
||||
else if(n1 == r.hexa)
|
||||
{
|
||||
n++;
|
||||
dynField(&e, valex, tmp, 1, n, cFM, cVM, 1);
|
||||
dynIconv(&e, tmp, encours, "X");
|
||||
dynConcatSz(&e, valex, encours->mPtr + 1, DYN_LGNONE); // copier apres le #
|
||||
}
|
||||
n1 = nreg(n+1);
|
||||
n2 = nreg(n+2);
|
||||
n3 = nreg(n+3);
|
||||
unefois[0] = ':';
|
||||
}
|
||||
if(unefois[0] == 0)
|
||||
{
|
||||
dynField(&e, valex, tmp, 3, n, cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : caractere/intervalle attendu\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR;
|
||||
}
|
||||
if(n1 == r.fin) ; else
|
||||
{
|
||||
dynField(&e, valex, tmp, 3, n, cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : fin et/ou attendue\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR;
|
||||
}
|
||||
n += 2;
|
||||
}
|
||||
/* lecture nom regle en hexa */
|
||||
dynField(&e, valex, tmp, 1, 1, cFM, cVM, 1);
|
||||
dynIconv(&e, tmp, trav, "X");
|
||||
trav->mPtr[trav->mLg - 1] = ','; /* exemple : begin,1,comment,2,... permet de faire un locate */
|
||||
dynConcatSz(&e, trav, Int64ToSz(&e, nbres == 0 ? 1 : nbres, DYN_FALSE, 0), DYN_LGNONE);
|
||||
dynStore(&e, resultat, 1, nbres == 0 ? 1 : nbres*2-1, trav, 10, ',');
|
||||
/* */
|
||||
dynField(&e, valex, tmp, 4, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
nbres = (nbres == 0 ? 2 : nbres + 1);
|
||||
dynStoreSz(&e, resultat, nbres, DYN_NONE, tmp->mPtr, tmp->mLg, 10, DYN_NONE);
|
||||
/* */
|
||||
#undef nreg
|
||||
return OK;
|
||||
}
|
||||
|
||||
long gen_c(Dynamic * resultat, Dynamic * elem1, Dynamic * elem2, Dynamic * elem3)
|
||||
{
|
||||
dynSetLen(&e, elem2, 0); // token
|
||||
@@ -350,13 +147,12 @@ int main(int argc, char * argv[])
|
||||
}
|
||||
else
|
||||
{
|
||||
if(lire_regles_lex(&e, ®les, NULL) != DYN_OK)
|
||||
if(lire_regles_lex(&e, ®les, "lexlex") != DYN_OK)
|
||||
ret = -3;
|
||||
}
|
||||
if(ret == 0)
|
||||
{
|
||||
init_reg(&e, ®les, &elem1);
|
||||
//printf("commentaire : %ld nomregle : %ld\n", r.commentaire, r.nomregle);
|
||||
init_reg_lex(&e, ®les, &elem1); // elem1 = var tmp
|
||||
//
|
||||
dynErase(&e, &fichier, "\r");
|
||||
dynRemove(&e, &fichier, NULL, 0, DYN_TRUE);
|
||||
@@ -364,7 +160,7 @@ int main(int argc, char * argv[])
|
||||
{
|
||||
lex(&e, ®les, &ligne, &valex);
|
||||
/* */
|
||||
ret = parse(&valex, &resultat, &elem1, &elem2, &elem3);
|
||||
ret = parse_lex(&e, &valex, &resultat, &elem1, &elem2, &elem3);
|
||||
/* */
|
||||
//dynConvert(&e, &valex, sFM sVM, "\n|");
|
||||
//printf("valex %s\n", valex.mPtr);//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024,2025 lanisys.fr
|
||||
\/ \/ Copyright 2024-2026 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
#include "langage.h"
|
||||
#include "dynamic.h"
|
||||
#include "lex.c"
|
||||
#include "lex.h"
|
||||
#include "instr.h"
|
||||
#include "rep.h"
|
||||
#include "arg.c"
|
||||
@@ -89,12 +89,22 @@ long numNiv; /* numero de niveau en cours */
|
||||
long idNiv; /* numero unique de chaque instruction qui cree un niveau */
|
||||
Dynamic label; /* label formatte selon le contexte (:i<niv>.<id>.<ind>, etc.) */
|
||||
|
||||
long nbNivIdent; /* numero attribut en cours, 1 global, >1 local (dernier attribut de nivIdent) */
|
||||
Dynamic nivIdent; /* contient les variables globales (<1>) et locales <last> pour controle */
|
||||
|
||||
Dynamic trav; /* variable de travail */
|
||||
Dynamic envers; /* variable de travail pour empiler les params a l'envers */
|
||||
Dynamic dercode;/* pour la gestion des variables de hash a gauche du signe " = " (methode variable() ) */
|
||||
long setfld; /* pour gestion let x{1} et let x{1,1} : 1 ou 2 si field ou value */
|
||||
long setsubstr; /* pour gestion let x[1,2] et x{3,4}[1,2] : 1 si substr avec 2 params */
|
||||
|
||||
Dynamic forend,forinc; /* variables pour le code asm des boucles foreach numeriques */
|
||||
|
||||
Dynamic varparam; /* contient les variables passees en parametre a une sub : interdire ceratins formes d'appel pour eviter plus tard des erreurs de pointeur */
|
||||
int doVarParam; /* booleen pour activer dans variable() la memo des variables dans varparam */
|
||||
|
||||
int typeof_; /* gestion du cas "typeof var" dans terme() */
|
||||
|
||||
/* -------------------- */
|
||||
ent64 lap = 0; /* calcul temps du programme (hors init, alloc et free), en ms */
|
||||
|
||||
@@ -132,11 +142,15 @@ long init(env * e)
|
||||
dynInit(e, &dercode, 0);
|
||||
dynInit(e, &wdir, 0);
|
||||
dynInit(e, &srcdbg, 0);
|
||||
dynInit(e, &forend, 0);
|
||||
dynInit(e, &forinc, 0);
|
||||
dynInit(e, &varparam, 0);
|
||||
iPrio = 0;
|
||||
iImbriPrio = 1;
|
||||
numNiv = 0;
|
||||
idNiv = 0;
|
||||
numlig = 0;
|
||||
doVarParam = 0;
|
||||
return OK; /* TODO controles */
|
||||
}
|
||||
|
||||
@@ -151,6 +165,9 @@ void fin(env * e)
|
||||
dynFree(e, &dercode);
|
||||
dynFree(e, &wdir);
|
||||
dynFree(e, &srcdbg);
|
||||
dynFree(e, &forend);
|
||||
dynFree(e, &forinc);
|
||||
dynFree(e, &varparam);
|
||||
}
|
||||
|
||||
long rg(env * e, Dynamic * regles, char * nom, Dynamic * tmp)
|
||||
@@ -172,24 +189,24 @@ blank,1,comment,2,begin,3,background,4,library,5,end,6,except,7,throw,8,catch,9,
|
||||
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
|
||||
new,41,class,42,this,43,parent,44,hold,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,sortedsearch,60
|
||||
change,61,format,62,insert,63,remove,64,tonum,65,tostring,66,equal,67,diff,68,gt,69,lt,70
|
||||
gte,71,lte,72,and,73,or,74,not,75,beginpar,76,endpar,77,beginh,78,endh,79,begins,80
|
||||
ends,81,indirect,82,typeof,83,stringdq,84,stringq,85,ident,86,varsys,87,numberdec,88,numberint,89,minus,90
|
||||
plus,91,multiply,92,divide,93,divident,94,modulo,95,concat,96,listesep,97,identsep,98,modsep,99,other,100
|
||||
*/
|
||||
struct {
|
||||
ent16 blank,comment,begin,background,library,end,except,throw,catch,include;
|
||||
ent16 sub,endsub,if_,then,else_,elseif,endif,do_,call,invoke;
|
||||
ent16 return_,returnon,loop,endloop,foreach,in,like,endfor,break_,breakon;
|
||||
ent16 continue_,continueon,nop,part,echonl,echo,input,declare,let,delet;
|
||||
ent16 new,class,this,parent,free,precision,setsep,int_,frac,abs;
|
||||
ent16 neg,round,type,len,count,dcount,field,index,search,change;
|
||||
ent16 format,insert,remove,tonum,tostring,equal,diff,gt,lt,gte;
|
||||
ent16 lte,and,or,not,beginpar,endpar,beginh,endh,begins,ends;
|
||||
ent16 indirect,typeof_,stringdq,stringq,ident,varsys,numberdec,numberint,minus,plus;
|
||||
ent16 multiply,divide,divident,modulo,concat,listesep,identsep,modsep,other;
|
||||
ent16 new,class,this,parent,hold,precision,setsep,int_,frac,abs;
|
||||
ent16 neg,round,type,len,count,dcount,field,index,search,sortedsearch;
|
||||
ent16 change,format,insert,remove,tonum,tostring,equal,diff,gt,lt;
|
||||
ent16 gte,lte,and,or,not,beginpar,endpar,beginh,endh,begins;
|
||||
ent16 ends,indirect,typeof_,stringdq,stringq,ident,varsys,numberdec,numberint,minus;
|
||||
ent16 plus,multiply,divide,divident,modulo,concat,listesep,identsep,modsep,other;
|
||||
} r;
|
||||
/* les 2 fonctions fictives ci dessous doivent avoir un numero < 512 et > au max de "r" ci-dessus */
|
||||
/* servent a gerer la notation x{1,2}[3,4] */
|
||||
@@ -251,7 +268,7 @@ void init_reg(env * e, Dynamic * regles, Dynamic * tmp)
|
||||
r.class = rg(e, regles, "class", tmp);
|
||||
r.this = rg(e, regles, "this", tmp);
|
||||
r.parent = rg(e, regles, "parent", tmp);
|
||||
r.free = rg(e, regles, "free", tmp);
|
||||
r.hold = rg(e, regles, "hold", tmp);
|
||||
r.precision = rg(e, regles, "precision", tmp);
|
||||
r.setsep = rg(e, regles, "setsep", tmp);
|
||||
r.int_ = rg(e, regles, "int", tmp);
|
||||
@@ -267,8 +284,9 @@ void init_reg(env * e, Dynamic * regles, Dynamic * tmp)
|
||||
r.field = rg(e, regles, "field", tmp);
|
||||
r.index = rg(e, regles, "index", tmp);
|
||||
r.search = rg(e, regles, "search", tmp);
|
||||
r.change = rg(e, regles, "change", tmp);
|
||||
r.sortedsearch = rg(e, regles, "sortedsearch", tmp);
|
||||
/* */
|
||||
r.change = rg(e, regles, "change", tmp);
|
||||
r.format = rg(e, regles, "format", tmp);
|
||||
r.insert = rg(e, regles, "insert", tmp);
|
||||
r.remove = rg(e, regles, "remove", tmp);
|
||||
@@ -278,8 +296,8 @@ void init_reg(env * e, Dynamic * regles, Dynamic * tmp)
|
||||
r.diff = rg(e, regles, "diff", tmp);
|
||||
r.gt = rg(e, regles, "gt", tmp);
|
||||
r.lt = rg(e, regles, "lt", tmp);
|
||||
r.gte = rg(e, regles, "gte", tmp);
|
||||
/* */
|
||||
r.gte = rg(e, regles, "gte", tmp);
|
||||
r.lte = rg(e, regles, "lte", tmp);
|
||||
r.and = rg(e, regles, "and", tmp);
|
||||
r.or = rg(e, regles, "or", tmp);
|
||||
@@ -289,8 +307,8 @@ void init_reg(env * e, Dynamic * regles, Dynamic * tmp)
|
||||
r.beginh = rg(e, regles, "beginh", tmp);
|
||||
r.endh = rg(e, regles, "endh", tmp);
|
||||
r.begins = rg(e, regles, "begins", tmp);
|
||||
r.ends = rg(e, regles, "ends", tmp);
|
||||
/* */
|
||||
r.ends = rg(e, regles, "ends", tmp);
|
||||
r.indirect = rg(e, regles, "indirect", tmp);
|
||||
r.typeof_ = rg(e, regles, "typeof", tmp);
|
||||
r.stringdq = rg(e, regles, "stringdq", tmp);
|
||||
@@ -300,8 +318,8 @@ void init_reg(env * e, Dynamic * regles, Dynamic * tmp)
|
||||
r.numberdec = rg(e, regles, "numberdec", tmp);
|
||||
r.numberint = rg(e, regles, "numberint", tmp);
|
||||
r.minus = rg(e, regles, "minus", tmp);
|
||||
r.plus = rg(e, regles, "plus", tmp);
|
||||
/* */
|
||||
r.plus = rg(e, regles, "plus", tmp);
|
||||
r.multiply = rg(e, regles, "multiply", tmp);
|
||||
r.divide = rg(e, regles, "divide", tmp);
|
||||
r.divident = rg(e, regles, "divident", tmp);
|
||||
@@ -362,21 +380,55 @@ long tok2string(env * e, Dynamic * valex, Dynamic * tmp, Dynamic * encours)
|
||||
return TERM_STR;
|
||||
}
|
||||
|
||||
long IdentInconnu(env * e, Dynamic * ident)
|
||||
{
|
||||
if(dynCompare(e, ident, CMP_EQ, "Base", 4))
|
||||
return FALSE; // objet cree par defaut par w
|
||||
/* d'abord chercher dans le dernier niveau = niveau local, et ensuite niveau 1 = niveau global */
|
||||
if(nbNivIdent > 1)
|
||||
if(dynLocateSz(e, &nivIdent, ident->mPtr, cVM, nbNivIdent, cFM) > 0)
|
||||
return FALSE;
|
||||
//
|
||||
if(nbNivIdent > 0)
|
||||
if(dynLocateSz(e, &nivIdent, ident->mPtr, cVM, 1, cFM) > 0)
|
||||
return FALSE;
|
||||
// ident inconnu
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
||||
long variable(env * e, Dynamic * resultat, Dynamic * valex, Dynamic * tmp, Dynamic * encours, long * aGauche)
|
||||
{
|
||||
/* controle si Var : Ident[.Ident][!Ident] etc. */
|
||||
/* si ok, <n> et <tok> sont sur le token suivant */
|
||||
/* si *aGauche = 1 : permet de faire PHDE PIDE, sinon que PVAH PVAI (a droite du =) => mis a jour avec 2 si le dernier est bien PHDE/PIDE */
|
||||
ent16 tok_prec = tok;
|
||||
/* renvoi VAR_OK ou VAR_ERR */
|
||||
tok = nreg(n);
|
||||
if(tok != r.ident && tok != r.this && tok != r.parent)
|
||||
return VAR_ERR;
|
||||
//
|
||||
if(typeof_)
|
||||
dynConcatSz(e, resultat, "TYPO\n", 5); // aGauche vaut toujours 0 en mode typeof
|
||||
//
|
||||
dynField(e, valex, tmp, 1, norig(n), cFM, cVM, 1);
|
||||
dynIconv(e, tmp, encours, "X");
|
||||
dynConcatSz(e, resultat, "PVAR ", 5);
|
||||
dynConcat(e, resultat, encours);
|
||||
dynConcatSz(e, resultat, "\n", 1);
|
||||
if(*aGauche) dynLet(e, &dercode, "", 0); // si expr a droite, garder le <dercode> trouve a gauche
|
||||
// verif presence ident
|
||||
if(tok == r.ident && tok_prec != r.sub && IdentInconnu(e, encours))
|
||||
{
|
||||
//printf("ident:%s niv:%ld liste:%s\n", encours->mPtr, nbNivIdent, nivIdent.mPtr);
|
||||
return VAR_ERR; // creer une erreur specifique
|
||||
}
|
||||
if(doVarParam)
|
||||
{
|
||||
dynConcatSz(e, &varparam, sFM, 1);
|
||||
dynConcat(e, &varparam, encours);
|
||||
}
|
||||
/* */
|
||||
n++;
|
||||
for(;;)
|
||||
@@ -384,18 +436,37 @@ long variable(env * e, Dynamic * resultat, Dynamic * valex, Dynamic * tmp, Dynam
|
||||
tok = nreg(n);
|
||||
tok2 = nreg(n+1);
|
||||
tok3 = nreg(n+2);
|
||||
if((tok == r.identsep || tok == r.indirect) && tok2 == r.ident) ; else break;
|
||||
if((tok == r.identsep || tok == r.indirect) && (tok2 == r.ident || tok2 == r.count)) ; else break;
|
||||
/* */
|
||||
n++;
|
||||
dynField(e, valex, tmp, 1, norig(n), cFM, cVM, 1);
|
||||
dynIconv(e, tmp, encours, "X");
|
||||
if(tok3 == r.identsep || tok3 == r.indirect || ! *aGauche) // si a droite du " = " : toujours PVAH/PVAI !
|
||||
{
|
||||
if(tok == r.identsep)
|
||||
dynConcatSz(e, resultat, "PVAH ", 5);
|
||||
if(tok2 == r.count)
|
||||
{
|
||||
if(typeof_)
|
||||
return VAR_ERR; // pas de hash.count en mode typeof : non autorise
|
||||
dynConcatSz(e, resultat, "HCOU", 4);
|
||||
}
|
||||
else
|
||||
dynConcatSz(e, resultat, "PVAI ", 5);
|
||||
dynConcat(e, resultat, encours);
|
||||
{
|
||||
if(tok == r.identsep)
|
||||
dynConcatSz(e, resultat, "PVAH ", 5);
|
||||
else
|
||||
{
|
||||
dynConcatSz(e, resultat, "PVAI ", 5);
|
||||
if(doVarParam)
|
||||
doVarParam = 2; // indique au moins une indirection dans les vars
|
||||
}
|
||||
dynConcat(e, resultat, encours);
|
||||
/* */
|
||||
if(doVarParam)
|
||||
{
|
||||
dynConcatSz(e, &varparam, sVM, 1);
|
||||
dynConcat(e, &varparam, encours);
|
||||
}
|
||||
}
|
||||
dynConcatSz(e, resultat, "\n", 1);
|
||||
}
|
||||
else
|
||||
@@ -412,9 +483,32 @@ long variable(env * e, Dynamic * resultat, Dynamic * valex, Dynamic * tmp, Dynam
|
||||
/* */
|
||||
n++;
|
||||
}
|
||||
if(typeof_)
|
||||
dynConcatSz(e, resultat, "PSHT\n", 5);
|
||||
return VAR_OK;
|
||||
}
|
||||
|
||||
long var_ident(env * e, Dynamic * instr, Dynamic * tmp, long offset)
|
||||
{
|
||||
// renvoi TRUE si instr ne contient que des PVAR/PVAH/PVAI, en partant de la fin (nb ligne de instr - offset)
|
||||
// arret quand plus de ligne ou SRCL lu
|
||||
long cr = FALSE, cpt, nb = dynDcount(e, instr, 10, DYN_NONE, DYN_NONE) - offset;
|
||||
// lire instr de nb a 1, sauf si SRCL est lu (arret alors)
|
||||
for(cpt = nb; cpt > 0; cpt--)
|
||||
{
|
||||
dynField(e, instr, tmp, cpt, DYN_NONE, 10, DYN_NONE, 1);
|
||||
if(strncmp(tmp->mPtr, "SRCL", 4) == 0)
|
||||
return cr;
|
||||
if(strncmp(tmp->mPtr, "PVAR", 4) == 0 ||
|
||||
strncmp(tmp->mPtr, "PVAH", 4) == 0 ||
|
||||
strncmp(tmp->mPtr, "PVAI", 4) == 0)
|
||||
cr = TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
return cr;
|
||||
}
|
||||
|
||||
long terme(env * e, ent16 t, Dynamic * valex, Dynamic * tmp, Dynamic * encours)
|
||||
{
|
||||
long ret = TERM_ERR, aGauche = 0;
|
||||
@@ -458,7 +552,7 @@ long terme(env * e, ent16 t, Dynamic * valex, Dynamic * tmp, Dynamic * encours)
|
||||
}
|
||||
if((t == r.abs || t == r.int_ || t == r.frac || t == r.neg ||
|
||||
t == r.type || t == r.round || t == r.tonum || t == r.tostring ||
|
||||
t == r.len || t == r.count || t == r.not || t == r.typeof_ ||
|
||||
t == r.len || t == r.count || t == r.not || t == r.sortedsearch ||
|
||||
t == r.dcount || t == r.field || t == r.index || t == r.search ||
|
||||
t == r.change || t == r.format || t == r.insert || t == r.remove ) && nreg(n+1) == r.beginpar)
|
||||
{
|
||||
@@ -488,13 +582,22 @@ long terme(env * e, ent16 t, Dynamic * valex, Dynamic * tmp, Dynamic * encours)
|
||||
tok = nreg(n);
|
||||
return TERM_ENDS;
|
||||
}
|
||||
typeof_ = FALSE;
|
||||
if(t == r.typeof_)
|
||||
{
|
||||
typeof_ = TRUE;
|
||||
n++;
|
||||
tok = nreg(n);
|
||||
}
|
||||
dynSetLen(e, &trav, 0);
|
||||
if(variable(e, &trav, valex, tmp, encours, &aGauche) == VAR_OK)
|
||||
{
|
||||
typeof_ = FALSE;
|
||||
/* var ; n et tok sont deja a jour (positionne sur le prochain token) */
|
||||
return TERM_VAR;
|
||||
}
|
||||
/* sinon erreur */
|
||||
typeof_ = FALSE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -597,9 +700,6 @@ long stack_fn(env * e, Dynamic * resultat, long fn, long nbParam)
|
||||
if(fn == r.count)
|
||||
return nbParam != 2 ? -1 : dynConcatSz(e, resultat, "COUN\n", DYN_LGNONE);
|
||||
|
||||
if(fn == r.typeof_)
|
||||
return nbParam != 1 ? -1 : dynConcatSz(e, resultat, "TEST\n", DYN_LGNONE); /* TODO dans langage.c !! */
|
||||
|
||||
if(fn == r.dcount)
|
||||
{
|
||||
if(nbParam == 1)
|
||||
@@ -628,6 +728,14 @@ long stack_fn(env * e, Dynamic * resultat, long fn, long nbParam)
|
||||
else
|
||||
return dynConcatSz(e, resultat, (nbParam == 2 ? "SRCH\n" : "SCHS\n"), DYN_LGNONE);
|
||||
}
|
||||
|
||||
if(fn == r.sortedsearch)
|
||||
{
|
||||
if(nbParam != 3 && nbParam != 4)
|
||||
return -1;
|
||||
else
|
||||
return dynConcatSz(e, resultat, (nbParam == 3 ? "SSRC\n" : "SSCS\n"), DYN_LGNONE);
|
||||
}
|
||||
|
||||
if(fn == r.change)
|
||||
return nbParam != 3 ? -1 : dynConcatSz(e, resultat, "CHNG\n", DYN_LGNONE);
|
||||
@@ -844,9 +952,12 @@ long expr(env * e, Dynamic * resultat, Dynamic * valex, Dynamic * tmp, Dynamic *
|
||||
else if(termType == TERM_STR)
|
||||
{
|
||||
/* empiler le terme en assembleur <string> */
|
||||
dynConcatSz(e, resultat, "PVAT\nDSET \"", DYN_LGNONE); /* TODO pbm " dans la chaine : quid ?? */
|
||||
dynChange(e, encours, (char *)"\"", "#22", DYN_ALL);
|
||||
dynChange(e, encours, (char *)" ", "#20", DYN_ALL); // car dans assembler.c, "trim(3)" de chaque ligne...
|
||||
dynConcatSz(e, resultat, "PVAT\nDSET \"", DYN_LGNONE);
|
||||
//dynChange(e, encours, (char *)"\"", "#22", DYN_ALL);
|
||||
//dynChange(e, encours, (char *)" ", "#20", DYN_ALL);
|
||||
/* mettre en hexa les cars "speciaux", dont <espace> 32/#20 car assembleur.c fait un trim,
|
||||
" 34/#22 car instr DSET utilise les guillements - ne pas convertir # 35/#23 car sert a coder un car en hexa, mettre #35 pour utiliser le # !! */
|
||||
dynCleanString(e, encours, (octet)35, (octet)126, TRUE); // TRUE convertit les octets hors intervalle en hexa #xx
|
||||
dynConcat(e, resultat, encours);
|
||||
dynConcatSz(e, resultat, "\"\nPSHV\n", DYN_LGNONE);
|
||||
/* chercher ENDPAR */
|
||||
@@ -1124,6 +1235,7 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
printf("Erreur ligne %dc%s : premiere instruction du programme incorrecte\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR; /* TODO numeroter les erreurs */
|
||||
}
|
||||
nbNivIdent = 1;
|
||||
n++;
|
||||
tok2 = nreg(n);
|
||||
n++;
|
||||
@@ -1191,6 +1303,8 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
dynIconv(e, tmp, encours, "X"); /* la longueur d'un ident (24 max) est controlee dans lex */
|
||||
dynConcat(e, resultat, encours);
|
||||
dynConcatSz(e, resultat, "\n", 1);
|
||||
// ajout aux vars a controler
|
||||
dynIns(e, &nivIdent, nbNivIdent, 1, encours, cFM, cVM);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1259,6 +1373,8 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
dynConcatSz(e, resultat, Int64ToSz(e, numlig, FALSE, 0), DYN_LGNONE);
|
||||
dynConcatSz(e, resultat, "\nENDS\n", DYN_LGNONE); /* idem PROG et BACK */
|
||||
FinNiveau(e);
|
||||
// suppression des variables a controler
|
||||
if(nbNivIdent > 1) dynDel(e, &nivIdent, nbNivIdent--, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
return OK;
|
||||
}
|
||||
/* -------------------------------------------------------------------------------------- */
|
||||
@@ -1316,6 +1432,8 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
printf("Erreur ligne %dc%s : nom fichier include incorrect\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR; /* TODO numeroter les erreurs */
|
||||
}
|
||||
/* ne garder que les cars entre 33 et 126, car INCL n'est que informatif ici */
|
||||
dynCleanString(e, encours, (octet)33, (octet)126, FALSE); // FALSE pour supprimer et ne pas convertir en hexa #xx
|
||||
// include deja mis dans <source>, mis ici pour info dans le compile
|
||||
dynConcatSz(e, resultat, "SRCL ", DYN_LGNONE);
|
||||
dynConcatSz(e, resultat, Int64ToSz(e, numlig, FALSE, 0), DYN_LGNONE);
|
||||
@@ -1354,6 +1472,7 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
ent64s numb;
|
||||
if(tok2number(e, &numb, valex, tmp, encours) != TERM_NUM)
|
||||
{
|
||||
/* TODO : tester une variable + modif langage.c/assembler */
|
||||
dynField(e, valex, tmp, 3, norig(n), cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : numero exception throw incorrect\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR; /* TODO numeroter les erreurs */
|
||||
@@ -1439,6 +1558,7 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
ent64s numb;
|
||||
if(tok2number(e, &numb, valex, tmp, encours) != TERM_NUM)
|
||||
{
|
||||
/* TODO : tester une variable + modif langage.c/assembler */
|
||||
dynField(e, valex, tmp, 3, norig(n), cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : numero part incorrect\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR; /* TODO numeroter les erreurs */
|
||||
@@ -1530,35 +1650,117 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
printf("Erreur ligne %dc%s : foreach variable 2 incorrecte\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR; /* TODO numeroter les erreurs */
|
||||
}
|
||||
dynSetLen(e, &forend, 0);
|
||||
dynSetLen(e, &forinc, 0);
|
||||
if(tok == r.listesep)
|
||||
{
|
||||
/* forme numerique : foreach x in debut,fin,increment */
|
||||
n++;
|
||||
if(variable(e, &forend, valex, tmp, encours, &aGauche) != VAR_OK)
|
||||
{
|
||||
dynField(e, valex, tmp, 3, norig(n), cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : foreach variable 3 incorrecte\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR; /* TODO numeroter les erreurs */
|
||||
}
|
||||
if(tok == r.listesep)
|
||||
{
|
||||
n++;
|
||||
if(variable(e, &forinc, valex, tmp, encours, &aGauche) != VAR_OK)
|
||||
{
|
||||
dynField(e, valex, tmp, 3, norig(n), cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : foreach variable 4 incorrecte\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR; /* TODO numeroter les erreurs */
|
||||
}
|
||||
}
|
||||
// par defaut, l'increment est 1 (forinc vide)
|
||||
}
|
||||
if(tok != 0)
|
||||
{
|
||||
dynField(e, valex, tmp, 3, norig(n), cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : foreach fin incorrecte\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR; /* TODO numeroter les erreurs */
|
||||
}
|
||||
// trav = 1ere var, envers = 2eme var (in)
|
||||
// trav = 1ere var, envers = 2eme var (in), forend = 3eme var, forinc = 4eme var
|
||||
//
|
||||
dynConcatSz(e, resultat, "SRCL ", DYN_LGNONE);
|
||||
dynConcatSz(e, resultat, Int64ToSz(e, numlig, FALSE, 0), DYN_LGNONE);
|
||||
dynConcatSz(e, resultat, "\n", DYN_LGNONE);
|
||||
/* */
|
||||
dynConcat(e, resultat, &envers);
|
||||
dynConcatSz(e, resultat, "SELE\n", DYN_LGNONE);
|
||||
if(forend.mLg == 0)
|
||||
{
|
||||
dynConcat(e, resultat, &envers);
|
||||
dynConcatSz(e, resultat, "SELE\n", DYN_LGNONE);
|
||||
/* */
|
||||
AjoutNiveau(e, "F");
|
||||
dynConcat(e, resultat, &label);
|
||||
dynConcatSz(e, resultat, "\n", DYN_LGNONE);
|
||||
/* */
|
||||
//dynConcatSz(e, resultat, "PSH0\n", DYN_LGNONE); /* a remplacer */
|
||||
dynConcat(e, resultat, &trav);
|
||||
dynConcatSz(e, resultat, "CPHA\n", DYN_LGNONE);
|
||||
dynConcat(e, resultat, &envers);
|
||||
dynConcatSz(e, resultat, "RNXT\n", DYN_LGNONE);
|
||||
/* */
|
||||
label.mPtr[1] = 'F';
|
||||
dynConcatSz(e, resultat, "JMPF ", DYN_LGNONE);
|
||||
dynConcat(e, resultat, &label);
|
||||
dynConcatSz(e, resultat, "\n", DYN_LGNONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// trav = envers - forinc (si forinc positif, sinon + forinc)
|
||||
dynConcat(e, resultat, &envers);
|
||||
dynConcatSz(e, resultat, "PSHV\n", DYN_LGNONE);
|
||||
if(forinc.mLg == 0)
|
||||
dynConcatSz(e, resultat, "PSH1\n", DYN_LGNONE);
|
||||
else
|
||||
{
|
||||
dynConcat(e, resultat, &forinc);
|
||||
dynConcatSz(e, resultat, "PSHV\n", DYN_LGNONE);
|
||||
}
|
||||
dynConcatSz(e, resultat, "SBCN\n", DYN_LGNONE);
|
||||
dynConcat(e, resultat, &trav);
|
||||
dynConcatSz(e, resultat, "POPV\n", DYN_LGNONE);
|
||||
/* */
|
||||
AjoutNiveau(e, "F");
|
||||
dynConcat(e, resultat, &label);
|
||||
dynConcatSz(e, resultat, "\n", DYN_LGNONE);
|
||||
/* */
|
||||
// trav = trav + forinc
|
||||
dynConcat(e, resultat, &trav);
|
||||
dynConcatSz(e, resultat, "PSHV\n", DYN_LGNONE);
|
||||
if(forinc.mLg == 0)
|
||||
dynConcatSz(e, resultat, "PSH1\n", DYN_LGNONE);
|
||||
else
|
||||
{
|
||||
dynConcat(e, resultat, &forinc);
|
||||
dynConcatSz(e, resultat, "PSHV\n", DYN_LGNONE);
|
||||
}
|
||||
dynConcatSz(e, resultat, "ADDN\n", DYN_LGNONE);
|
||||
dynConcat(e, resultat, &trav);
|
||||
dynConcatSz(e, resultat, "POPV\n", DYN_LGNONE);
|
||||
/* */
|
||||
// compare trav <= forend (si forinc positif, sinon trav >= forend)
|
||||
dynConcat(e, resultat, &trav);
|
||||
dynConcatSz(e, resultat, "PSHV\n", DYN_LGNONE);
|
||||
dynConcat(e, resultat, &forend);
|
||||
dynConcatSz(e, resultat, "PSHV\n", DYN_LGNONE);
|
||||
if(forinc.mLg == 0)
|
||||
dynConcatSz(e, resultat, "PSH1\n", DYN_LGNONE);
|
||||
else
|
||||
{
|
||||
dynConcat(e, resultat, &forinc);
|
||||
dynConcatSz(e, resultat, "PSHV\n", DYN_LGNONE);
|
||||
}
|
||||
dynConcatSz(e, resultat, "COMP FOR\n", DYN_LGNONE); // instruction qui compare selon la valeur de forinc (pile) : positif <=, negatif >=, 0 exception => COMP FOR
|
||||
//dynConcatSz(e, resultat, "PSH0\n", DYN_LGNONE); /* a remplacer */
|
||||
/* */
|
||||
label.mPtr[1] = 'F';
|
||||
dynConcatSz(e, resultat, "JMPF ", DYN_LGNONE);
|
||||
dynConcat(e, resultat, &label);
|
||||
dynConcatSz(e, resultat, "\n", DYN_LGNONE);
|
||||
}
|
||||
/* */
|
||||
AjoutNiveau(e, "F");
|
||||
dynConcat(e, resultat, &label);
|
||||
dynConcatSz(e, resultat, "\n", DYN_LGNONE);
|
||||
/* */
|
||||
//dynConcatSz(e, resultat, "PSH0\n", DYN_LGNONE); /* a remplacer */
|
||||
dynConcat(e, resultat, &trav);
|
||||
dynConcatSz(e, resultat, "CPHA\n", DYN_LGNONE);
|
||||
dynConcat(e, resultat, &envers);
|
||||
dynConcatSz(e, resultat, "RNXT\n", DYN_LGNONE);
|
||||
/* */
|
||||
label.mPtr[1] = 'F';
|
||||
dynConcatSz(e, resultat, "JMPF ", DYN_LGNONE);
|
||||
dynConcat(e, resultat, &label);
|
||||
dynConcatSz(e, resultat, "\n", DYN_LGNONE);
|
||||
return OK;
|
||||
}
|
||||
/* -------------------------------------------------------------------------------------- */
|
||||
@@ -1717,6 +1919,8 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
dynConcatSz(e, resultat, "\nDECL ", DYN_LGNONE);
|
||||
dynConcat(e, resultat, encours);
|
||||
dynConcatSz(e, resultat, "\n", DYN_LGNONE);
|
||||
// ajout aux vars connues
|
||||
if(nbNivIdent > 0) dynIns(e, &nivIdent, nbNivIdent, 1, encours, cFM, cVM);
|
||||
n++;
|
||||
for(;;)
|
||||
{
|
||||
@@ -1730,6 +1934,8 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
dynConcatSz(e, resultat, "DECL ", DYN_LGNONE);
|
||||
dynConcat(e, resultat, encours);
|
||||
dynConcatSz(e, resultat, "\n", DYN_LGNONE);
|
||||
// ajout aux vars connues
|
||||
if(nbNivIdent > 0) dynIns(e, &nivIdent, nbNivIdent, 1, encours, cFM, cVM);
|
||||
n++;
|
||||
}
|
||||
if(tok != 0)
|
||||
@@ -1773,7 +1979,7 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
dynConcatSz(e, resultat, "\n", DYN_LGNONE);
|
||||
n++;
|
||||
aGauche = 1;
|
||||
if(variable(e, &envers, valex, tmp, encours, &aGauche) == VAR_ERR)
|
||||
if(variable(e, &envers, valex, tmp, encours, &aGauche) == VAR_ERR) // attention, ici variable() se sert de <tok> pour ne pas controler la sub declaree !
|
||||
{
|
||||
dynField(e, valex, tmp, 3, norig(n), cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : identifiant sub incorrect\n", numlig, tmp->mPtr);
|
||||
@@ -1785,6 +1991,8 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
strncpy(envers.mPtr, "SUBR", 4);
|
||||
dynConcat(e, resultat, &envers);
|
||||
dynConcatSz(e, resultat, "BEXC\n", DYN_LGNONE);
|
||||
// ajout aux vars a controler
|
||||
if(nbNivIdent > 0) dynIns(e, &nivIdent, nbNivIdent, 1, encours, cFM, cVM);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1794,6 +2002,7 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
dynConcat(e, resultat, &dercode);
|
||||
dynConcatSz(e, resultat, "BEXC\n", DYN_LGNONE);
|
||||
}
|
||||
nbNivIdent++;
|
||||
if(tok != 0)
|
||||
{
|
||||
// parametres
|
||||
@@ -1835,6 +2044,8 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
dynConcatSz(e, resultat, "PARM ", DYN_LGNONE);
|
||||
dynConcat(e, resultat, encours);
|
||||
dynConcatSz(e, resultat, "\n", DYN_LGNONE);
|
||||
// ajout aux vars a controler
|
||||
dynIns(e, &nivIdent, nbNivIdent, 1, encours, cFM, cVM);
|
||||
n++;
|
||||
for(;;)
|
||||
{
|
||||
@@ -1847,6 +2058,8 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
dynConcatSz(e, resultat, "PARM ", DYN_LGNONE);
|
||||
dynConcat(e, resultat, encours);
|
||||
dynConcatSz(e, resultat, "\n", DYN_LGNONE);
|
||||
// ajout aux vars a controler
|
||||
dynIns(e, &nivIdent, nbNivIdent, 1, encours, cFM, cVM);
|
||||
n++;
|
||||
}
|
||||
}
|
||||
@@ -1863,6 +2076,7 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
/* -------------------------------------------------------------------------------------- */
|
||||
if(tok == r.do_ || tok == r.call || tok == r.invoke)
|
||||
{
|
||||
//ent16 toksub = tok; // si besoin pour differencier do/call/invoke
|
||||
dynSetLen(e, &envers, 0);
|
||||
/* 3 formes : do var ; do ident@ident ; do library@ident
|
||||
invoke ident&ident call ident */
|
||||
@@ -1871,7 +2085,7 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
dynConcatSz(e, resultat, "\nCRAZ\n", DYN_LGNONE);
|
||||
if(tok == r.call || tok == r.invoke)
|
||||
{
|
||||
/* appel de module ou de library **FINIR** */
|
||||
/* appel de module ou de library */
|
||||
if(tok == r.call)
|
||||
{
|
||||
tok2 = nreg(n+1);
|
||||
@@ -1973,6 +2187,8 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
tok = nreg(n);
|
||||
if(tok != r.endpar)
|
||||
{
|
||||
dynSetLen(e, &varparam, 0);
|
||||
doVarParam = 1;
|
||||
/* au moins 1 var en parametre */
|
||||
for(;;)
|
||||
{
|
||||
@@ -1980,6 +2196,7 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
aGauche = 0;
|
||||
if(variable(e, &trav, valex, tmp, encours, &aGauche) == VAR_ERR)
|
||||
{
|
||||
doVarParam = 0;
|
||||
dynField(e, valex, tmp, 3, norig(n), cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : parametre do/call/invoke incorrect\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR; /* TODO numeroter les erreurs */
|
||||
@@ -1990,12 +2207,52 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
break;
|
||||
if(tok != r.listesep)
|
||||
{
|
||||
doVarParam = 0;
|
||||
dynField(e, valex, tmp, 3, norig(n), cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : parametre do/call/invoke incorrect\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR; /* TODO numeroter les erreurs */
|
||||
}
|
||||
n++;
|
||||
}
|
||||
/* TODO => controler certaines formes de variables passees en parametre (varparam) :
|
||||
(a, a) (a, a.b) (a.b, a.b.c) (a!c) : sont interdites
|
||||
*/
|
||||
if(doVarParam == 2)
|
||||
{
|
||||
doVarParam = 0;
|
||||
dynField(e, valex, tmp, 3, norig(n), cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : parametre do/call/invoke avec indirection non autorisee\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR; /* TODO numeroter les erreurs */
|
||||
}
|
||||
doVarParam = 0;
|
||||
long i, j, nbi, nbj, nb = dynDcount(e, &varparam, cFM, DYN_NONE, DYN_NONE);
|
||||
for(i = 2; i < nb; i++)
|
||||
for(j = i + 1; j <= nb; j++)
|
||||
{
|
||||
// comparer i et j
|
||||
dynField(e, &varparam, tmp, i, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
dynField(e, &varparam, encours, j, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
if(dynCompare(e, tmp, CMP_EQ, encours->mPtr, encours->mLg))
|
||||
{
|
||||
dynField(e, valex, tmp, 3, norig(n), cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : parametres do/call/invoke identiques non autorises\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR; /* TODO numeroter les erreurs */
|
||||
}
|
||||
nbi = dynDcount(e, tmp, cVM, DYN_NONE, DYN_NONE);
|
||||
nbj = dynDcount(e, encours, cVM, DYN_NONE, DYN_NONE);
|
||||
if(nbi == nbj)
|
||||
continue;
|
||||
if(nbi > nbj)
|
||||
nbi = nbj; // nbi est le min de var enchainees : comparer sur le min, si egal : non autorise
|
||||
dynField(e, &varparam, tmp, i, 1, cFM, cVM, nbi);
|
||||
dynField(e, &varparam, encours, j, 1, cFM, cVM, nbi);
|
||||
if(dynCompare(e, tmp, CMP_EQ, encours->mPtr, encours->mLg))
|
||||
{
|
||||
dynField(e, valex, tmp, 3, norig(n), cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : parametres do/call/invoke imbriques, de meme base, non autorises\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR; /* TODO numeroter les erreurs */
|
||||
}
|
||||
}
|
||||
}
|
||||
if(nreg(n+1) != 0)
|
||||
{
|
||||
@@ -2017,8 +2274,11 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
dynConcatSz(e, resultat, "\n", DYN_LGNONE);
|
||||
n++;
|
||||
aGauche = 1;
|
||||
dynSetLen(e, &varparam, 0);
|
||||
doVarParam = 1; // pour ctrl new : "classe.membre = new classe" non autorise
|
||||
if(variable(e, &envers, valex, tmp, encours, &aGauche) == VAR_ERR)
|
||||
{
|
||||
doVarParam = 0;
|
||||
dynField(e, valex, tmp, 3, norig(n), cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : variable let incorrecte\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR; /* TODO numeroter les erreurs */
|
||||
@@ -2026,6 +2286,7 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
setfld = 0; // 1 pour x{1} et 2 pour x{1,1}
|
||||
if(tok == r.beginh)
|
||||
{
|
||||
doVarParam = 0;
|
||||
if(expr(e, resultat, valex, tmp, encours, 0, r.let) != 0) // var{ is followed by 1 or 2 expr, comma separated
|
||||
{
|
||||
/* erreur dans l'expression */
|
||||
@@ -2037,6 +2298,7 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
setsubstr = 0; // 1 pour x[1,1]
|
||||
if(tok == r.begins)
|
||||
{
|
||||
doVarParam = 0;
|
||||
if(expr(e, resultat, valex, tmp, encours, 0, r.change) != 0) // var[ is followed by 2 expr, comma separated
|
||||
{
|
||||
/* erreur dans l'expression */
|
||||
@@ -2047,6 +2309,7 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
}
|
||||
if(tok != r.equal)
|
||||
{
|
||||
doVarParam = 0;
|
||||
dynField(e, valex, tmp, 3, norig(n), cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : let incorrect\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR; /* TODO numeroter les erreurs */
|
||||
@@ -2055,6 +2318,7 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
tok = nreg(n);
|
||||
if(tok == r.beginh)
|
||||
{
|
||||
doVarParam = 0;
|
||||
if(setfld != 0 || setsubstr != 0)
|
||||
{
|
||||
dynField(e, valex, tmp, 3, norig(n), cFM, cVM, 1);
|
||||
@@ -2164,6 +2428,7 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
{
|
||||
if(setfld != 0 || setsubstr != 0)
|
||||
{
|
||||
doVarParam = 0;
|
||||
dynField(e, valex, tmp, 3, norig(n), cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : creation objet incorrecte\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR; /* TODO numeroter les erreurs */
|
||||
@@ -2175,6 +2440,7 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
/* TODO : indirection sur le nom de la classe : var a la place de ident dans ce cas la */
|
||||
if(tok == r.ident && tok2 == 0) ; else
|
||||
{
|
||||
doVarParam = 0;
|
||||
dynField(e, valex, tmp, 3, norig(n), cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : new incorrect\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR; /* TODO numeroter les erreurs */
|
||||
@@ -2183,10 +2449,34 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
dynIconv(e, &envers, tmp, "X");
|
||||
if(tmp->mLg < 1 || tmp->mLg > 24)
|
||||
{
|
||||
doVarParam = 0;
|
||||
dynField(e, valex, tmp, 3, norig(n), cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : new, classe incorrecte\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR; /* TODO numeroter les erreurs */
|
||||
}
|
||||
doVarParam = 0;
|
||||
/* si "tmp" (la classe) est le premier element de varparam : non autorise */
|
||||
dynField(e, &varparam, &envers, 2, 1, cFM, cVM, 1);
|
||||
if(dynCompare(e, &envers, CMP_EQ, tmp->mPtr, tmp->mLg))
|
||||
{
|
||||
dynField(e, valex, tmp, 3, norig(n), cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : new, classe non autorise quand mise a jour membre pour elle meme\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR; /* TODO numeroter les erreurs */
|
||||
}
|
||||
// pbm test suivant si new appele dans library et classe declaree dans le prog principal (ou inversement)... donc plus de controle
|
||||
if(IdentInconnu(e, tmp))
|
||||
{
|
||||
//dynField(e, valex, tmp, 3, norig(n), cFM, cVM, 1);
|
||||
//printf("Erreur ligne %dc%s : new, classe inconnue\n", numlig, tmp->mPtr);
|
||||
//return DYN_ERR;
|
||||
// TODO : mettre un warning ?
|
||||
}
|
||||
if(aGauche == 2)
|
||||
{
|
||||
// dercode avec une var a creer : PHDN/PIDN
|
||||
dercode.mPtr[3] = 'N';
|
||||
dynConcat(e, resultat, &dercode);
|
||||
}
|
||||
dynConcatSz(e, resultat, "NLET ", DYN_LGNONE);
|
||||
dynConcat(e, resultat, tmp);
|
||||
dynConcatSz(e, resultat, "\n", DYN_LGNONE);
|
||||
@@ -2194,6 +2484,7 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
else
|
||||
{
|
||||
/* expression "simple" */
|
||||
doVarParam = 0;
|
||||
if(expr(e, resultat, valex, tmp, encours, 0, 0) != 0)
|
||||
{
|
||||
/* erreur dans l'expression */
|
||||
@@ -2210,17 +2501,39 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
}
|
||||
if(setsubstr == 0)
|
||||
{
|
||||
dynConcat(e, resultat, &envers);
|
||||
//dynConcat(e, resultat, &envers);
|
||||
if(setfld == 0)
|
||||
{
|
||||
// var
|
||||
if(aGauche != 2)
|
||||
dynConcatSz(e, resultat, "POPV\n", 5); // une seule var a gauche
|
||||
// var - si juste enchainement de var a droite (a.b!c) => nouvelles instructions VLET/PHDV/PIDV
|
||||
// verifier dans &envers et fin de &resultat (depuis le dernier SRCL en partant de la fin) si que des PVAR/PVAH/PVAI
|
||||
// offset 2 pour ne pas lire PSHV de resultat, et 1/2 pour sauter la derniere ligne (car se termine avec \n)
|
||||
if(var_ident(e, resultat, tmp, 2) && var_ident(e, &envers, tmp, 1))
|
||||
{
|
||||
// que des enchainement de PVAR/PVAI/PVAH => affectation "simple" de var (var_let au final)
|
||||
// remplacer dans la derniere ligne de resultat PHSV par SADV
|
||||
dynStoreSz(e, resultat, dynDcount(e, resultat, 10, DYN_NONE, DYN_NONE) - 1,DYN_NONE, "SADV", 4, 10, DYN_NONE); // -1 car resultat se termine par \n
|
||||
dynConcat(e, resultat, &envers);
|
||||
if(aGauche != 2)
|
||||
dynConcatSz(e, resultat, "VLET\n", 5); // une seule var a gauche
|
||||
else
|
||||
{
|
||||
dercode.mPtr[3] = 'V';
|
||||
dynConcat(e, resultat, &dercode); // PHDV PIDV
|
||||
}
|
||||
}
|
||||
else
|
||||
dynConcat(e, resultat, &dercode); // PHDE PIDE
|
||||
{
|
||||
// var
|
||||
dynConcat(e, resultat, &envers);
|
||||
if(aGauche != 2)
|
||||
dynConcatSz(e, resultat, "POPV\n", 5); // une seule var a gauche
|
||||
else
|
||||
dynConcat(e, resultat, &dercode); // PHDE PIDE
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dynConcat(e, resultat, &envers);
|
||||
// setfld = 1 ou 2 : var{}
|
||||
if(aGauche != 2)
|
||||
dynConcatSz(e, resultat, "DEXV\n", 5); // une seule var a gauche
|
||||
@@ -2289,6 +2602,13 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
n += 2;
|
||||
dynField(e, valex, &dercode, 1, norig(n), cFM, cVM, 1);
|
||||
dynIconv(e, &dercode, &envers, "X"); /* envers est le nom de la classe mere */
|
||||
// verif classe mere connue
|
||||
if(IdentInconnu(e, &envers))
|
||||
{
|
||||
dynField(e, valex, tmp, 3, norig(n), cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : classe mere inconnue\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR;
|
||||
}
|
||||
n += 2;
|
||||
}
|
||||
else
|
||||
@@ -2306,12 +2626,15 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
dynConcatSz(e, resultat, " ", DYN_LGNONE);
|
||||
dynConcat(e, resultat, &envers);
|
||||
dynConcatSz(e, resultat, "\n", DYN_LGNONE);
|
||||
// ajout nouvelle classe aux vars a controler
|
||||
if(nbNivIdent > 0) dynIns(e, &nivIdent, 1, 1, tmp, cFM, cVM); // niveau global toujours pour les classes
|
||||
return OK;
|
||||
}
|
||||
/* -------------------------------------------------------------------------------------- */
|
||||
if(tok == r.free)
|
||||
if(tok == r.hold)
|
||||
{
|
||||
// TODO
|
||||
// plugin mode - TODO
|
||||
return OK;
|
||||
}
|
||||
/* -------------------------------------------------------------------------------------- */
|
||||
if(tok == r.echo || tok == r.echonl)
|
||||
@@ -2323,37 +2646,33 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
if(tok == r.echo) strcpy(instr, "WRIT\n"); else strcpy(instr, "WRLN\n");
|
||||
/* */
|
||||
n++;
|
||||
tok = nreg(n);
|
||||
tok2 = nreg(n+1);
|
||||
/* temporaire pour tests, A FINIR */
|
||||
if(tok == r.ident && tok2 == 0) // enlever tok2 == 0 FINIR
|
||||
{
|
||||
aGauche = 0;
|
||||
if(variable(e, resultat, valex, tmp, encours, &aGauche) == VAR_ERR)
|
||||
{
|
||||
dynField(e, valex, tmp, 3, norig(n), cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : variable echo incorrecte\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR; /* TODO numeroter les erreurs */
|
||||
}
|
||||
dynConcatSz(e, resultat, instr, 5);
|
||||
}
|
||||
else if((tok == r.stringdq || tok == r.stringq) && tok2 == 0)
|
||||
{
|
||||
dynConcatSz(e, resultat, "PVAT\nDSET \"", DYN_LGNONE); /* TODO pbm " dans la chaine : quid ?? */
|
||||
tok2string(e, valex, tmp, encours);
|
||||
dynChange(e, encours, "\"", "#22", DYN_ALL);
|
||||
dynChange(e, encours, " ", "#20", DYN_ALL);
|
||||
dynConcat(e, resultat, encours);
|
||||
dynConcatSz(e, resultat, "\"\n", DYN_LGNONE);
|
||||
dynConcatSz(e, resultat, instr, 5);
|
||||
}
|
||||
else
|
||||
/* expression "simple" */
|
||||
doVarParam = 0;
|
||||
if(expr(e, resultat, valex, tmp, encours, 0, 0) != 0)
|
||||
{
|
||||
/* erreur dans l'expression */
|
||||
dynField(e, valex, tmp, 3, norig(n), cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : fin echo/echonl incorrect\n", numlig, tmp->mPtr);
|
||||
printf("Erreur ligne %dc%s : expression let incorrecte\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR;
|
||||
}
|
||||
if(tok != 0)
|
||||
{
|
||||
/* erreur en fin d'expression */
|
||||
dynField(e, valex, tmp, 3, norig(n), cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : fin d'expression let incorrecte\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR;
|
||||
}
|
||||
dynConcatSz(e, resultat, instr, 5);
|
||||
return OK;
|
||||
/* */
|
||||
//aGauche = 0;
|
||||
//if(variable(e, resultat, valex, tmp, encours, &aGauche) == VAR_ERR)
|
||||
//{
|
||||
// dynField(e, valex, tmp, 3, norig(n), cFM, cVM, 1);
|
||||
// printf("Erreur ligne %dc%s : variable echo incorrecte\n", numlig, tmp->mPtr);
|
||||
// return DYN_ERR; /* TODO numeroter les erreurs */
|
||||
//}
|
||||
//dynConcatSz(e, resultat, instr, 5);
|
||||
}
|
||||
/* -------------------------------------------------------------------------------------- */
|
||||
if(tok == r.delet)
|
||||
@@ -2375,7 +2694,26 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
printf("Erreur ligne %dc%s : fin delet incorrect\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR; /* TODO numeroter les erreurs */
|
||||
}
|
||||
dynConcatSz(e, resultat, "DELE\n", 5);
|
||||
// var_ident(e, resultat, tmp, 1)) pas necessaire, car que des enchainements de PVAR/PVAH/PVAI a droite
|
||||
// remplacer dans la derniere ligne de resultat PVAH/PVAI par PVHD/PVID ; si PVAR, ajouter en fin DELE
|
||||
long lig = dynDcount(e, resultat, 10, DYN_NONE, DYN_NONE) - 1; // -1 car resultat se termine par \n
|
||||
dynField(e, resultat, tmp, lig, DYN_NONE, 10, DYN_NONE, 1);
|
||||
if(strncmp(tmp->mPtr, "PVAH", 4) == 0)
|
||||
{
|
||||
tmp->mPtr[2] = 'H';
|
||||
tmp->mPtr[3] = 'D';
|
||||
dynStore(e, resultat, lig, DYN_NONE, tmp, 10, DYN_NONE);
|
||||
}
|
||||
else if(strncmp(tmp->mPtr, "PVAI", 4) == 0)
|
||||
{
|
||||
tmp->mPtr[2] = 'I';
|
||||
tmp->mPtr[3] = 'D';
|
||||
dynStore(e, resultat, lig, DYN_NONE, tmp, 10, DYN_NONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
dynConcatSz(e, resultat, "DELE\n", 5);
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
/* -------------------------------------------------------------------------------------- */
|
||||
@@ -2594,6 +2932,7 @@ int main(int argc, char * argv[])
|
||||
dynInit(&e, &wsrc, 0);
|
||||
dynInit(&e, &wlib, 0);
|
||||
dynInit(&e, &encours, 0);
|
||||
dynInit(&e, &nivIdent, 0);
|
||||
/* */
|
||||
GetArgs(&e, argc, argv, &arg);
|
||||
dynExtractField(&e, &arg, 4, &wsrc);
|
||||
@@ -2656,6 +2995,7 @@ int main(int argc, char * argv[])
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
/* resultat contient l'assembleur wa du source en entree */
|
||||
long currentLevel = 1, level = 0;
|
||||
nbNivIdent = 0;
|
||||
dynRemove(&e, &source, NULL, 0, DYN_TRUE);
|
||||
while(dynRemove(&e, &source, &ligne, 10, DYN_FALSE) > -1 && ret == 0)
|
||||
{
|
||||
@@ -2712,6 +3052,7 @@ int main(int argc, char * argv[])
|
||||
dynFree(&e, &wsrc);
|
||||
dynFree(&e, &wlib);
|
||||
dynFree(&e, &encours);
|
||||
dynFree(&e, &nivIdent);
|
||||
/* */
|
||||
if(clock_gettime_monotonic(&ts) != -1)
|
||||
lap = ts.tv_sec * 1000000 + (ts.tv_nsec / 1000) - lap;
|
||||
|
||||
@@ -52,10 +52,10 @@ static int setError(modEtat * p, int err)
|
||||
{
|
||||
if(p != NULL)
|
||||
p->error = err;
|
||||
return EX_MODERR;
|
||||
return err == OK ? OK : EX_MODERR;
|
||||
}
|
||||
|
||||
static void encodageMD2(char * entree, ent64 longueur, char * sortie)
|
||||
static void encodageMD2(env * e, var * entree, var * sortie)
|
||||
{
|
||||
unsigned char checksum[16] = {0};
|
||||
unsigned char padding[16] = {0};
|
||||
@@ -74,8 +74,9 @@ static void encodageMD2(char * entree, ent64 longueur, char * sortie)
|
||||
235, 117, 75, 10, 49, 68, 80, 180, 143, 237, 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 };
|
||||
static char carhex[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
|
||||
/* */
|
||||
unsigned char * p = (unsigned char *)entree;
|
||||
unsigned char * p = (unsigned char *)(entree->ptr);
|
||||
unsigned char L = 0, T;
|
||||
long longueur = entree->mLg;
|
||||
while(longueur >= 16)
|
||||
{
|
||||
for(i = 0; i < 16; i++)
|
||||
@@ -131,13 +132,13 @@ static void encodageMD2(char * entree, ent64 longueur, char * sortie)
|
||||
/* fin du calcul md2 : en hexa dans sortie (tableau de 32 cars mini) et binaire dans binaire */
|
||||
for(i = 0, j = 0; i < 16; i++)
|
||||
{
|
||||
sortie[j++] = carhex[buffer[i] / 16];
|
||||
sortie[j++] = carhex[buffer[i] % 16];
|
||||
sortie->ptr[j++] = carhex[buffer[i] / 16];
|
||||
sortie->ptr[j++] = carhex[buffer[i] % 16];
|
||||
}
|
||||
sortie[j] = 0;
|
||||
dynSetLen(e, sortie, j); // len = 32 ici
|
||||
}
|
||||
|
||||
static void majMD4(unsigned int * md4, unsigned int * buffer)
|
||||
static void majMD4(unsigned int * md4, pointeur buffer)
|
||||
{
|
||||
unsigned int A, B, C, D, tmp;
|
||||
unsigned int buf[16];
|
||||
@@ -150,7 +151,7 @@ static void majMD4(unsigned int * md4, unsigned int * buffer)
|
||||
#define h(W,X,Y,Z,i,r) W = rot((W + (X^Y^Z) + buf[i] + 0x6ED9EBA1),r)
|
||||
|
||||
/* coder le buffer en little endian */
|
||||
octet = (unsigned char *)buffer;
|
||||
octet = buffer;
|
||||
for(i=0; i<16; i++, octet+=4)
|
||||
buf[i] = (*octet) | ((*(octet+1))<<8) | ((*(octet+2))<<16) | ((*(octet+3))<<24);
|
||||
/* */
|
||||
@@ -217,7 +218,7 @@ static void majMD4(unsigned int * md4, unsigned int * buffer)
|
||||
md4[3] += D;
|
||||
}
|
||||
|
||||
void encodageMD4(char * entree, ent64 longueur, char * sortie)
|
||||
static void encodageMD4(env * e, var * entree, var * sortie)
|
||||
{
|
||||
unsigned char lg[8];
|
||||
unsigned char buffer[64];
|
||||
@@ -229,12 +230,14 @@ void encodageMD4(char * entree, ent64 longueur, char * sortie)
|
||||
md4[1] = (unsigned int)0xefcdab89;
|
||||
md4[2] = (unsigned int)0x98badcfe;
|
||||
md4[3] = (unsigned int)0x10325476;
|
||||
long longueur = entree->mLg;
|
||||
*(ent64 *)lg = (ent64)longueur * 8;
|
||||
/* */
|
||||
pointeur p = entree->ptr;
|
||||
while(longueur >= 64)
|
||||
{
|
||||
majMD4(md4, (unsigned int *)entree);
|
||||
entree += 64;
|
||||
majMD4(md4, p);
|
||||
p += 64;
|
||||
longueur -= 64;
|
||||
}
|
||||
/* traitement du dernier bloc */
|
||||
@@ -242,7 +245,7 @@ void encodageMD4(char * entree, ent64 longueur, char * sortie)
|
||||
/* si pas assez de place, faire un nouveau bloc */
|
||||
memset(buffer, 0, 64);
|
||||
if(longueur > 0)
|
||||
memcpy(buffer, entree, longueur);
|
||||
memcpy(buffer, p, longueur);
|
||||
buffer[longueur] = 128; /* 0x80 */
|
||||
if(longueur <= 55)
|
||||
{
|
||||
@@ -256,12 +259,12 @@ void encodageMD4(char * entree, ent64 longueur, char * sortie)
|
||||
*(unsigned char *)(buffer+61) = (*(ent64 *)lg >> 40) & 255;
|
||||
*(unsigned char *)(buffer+62) = (*(ent64 *)lg >> 48) & 255;
|
||||
*(unsigned char *)(buffer+63) = (*(ent64 *)lg >> 56) & 255;
|
||||
majMD4(md4, (unsigned int *)buffer);
|
||||
majMD4(md4, buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 2 derniers blocs */
|
||||
majMD4(md4, (unsigned int *)buffer);
|
||||
majMD4(md4, buffer);
|
||||
/* */
|
||||
memset(buffer, 0, 64);
|
||||
// encoder la longueur en little endian
|
||||
@@ -273,7 +276,7 @@ void encodageMD4(char * entree, ent64 longueur, char * sortie)
|
||||
*(unsigned char *)(buffer+61) = (*(ent64 *)lg >> 40) & 255;
|
||||
*(unsigned char *)(buffer+62) = (*(ent64 *)lg >> 48) & 255;
|
||||
*(unsigned char *)(buffer+63) = (*(ent64 *)lg >> 56) & 255;
|
||||
majMD4(md4, (unsigned int *)buffer);
|
||||
majMD4(md4, buffer);
|
||||
}
|
||||
//
|
||||
/* calcul md4 en hexa dans sortie (tableau de 32 cars mini) et binaire dans binaire */
|
||||
@@ -281,26 +284,257 @@ void encodageMD4(char * entree, ent64 longueur, char * sortie)
|
||||
{
|
||||
buffer[0] = md4[i] & 255;
|
||||
md4[i] >>= 8;
|
||||
sortie[j] = carhex[buffer[0]/16];
|
||||
sortie[j+1] = carhex[buffer[0]%16];
|
||||
sortie->ptr[j] = carhex[buffer[0]/16];
|
||||
sortie->ptr[j+1] = carhex[buffer[0]%16];
|
||||
/* */
|
||||
buffer[0] = md4[i] & 255;
|
||||
md4[i] >>= 8;
|
||||
sortie[j+2] = carhex[buffer[0]/16];
|
||||
sortie[j+3] = carhex[buffer[0]%16];
|
||||
sortie->ptr[j+2] = carhex[buffer[0]/16];
|
||||
sortie->ptr[j+3] = carhex[buffer[0]%16];
|
||||
/* */
|
||||
buffer[0] = md4[i] & 255;
|
||||
md4[i] >>= 8;
|
||||
sortie[j+4] = carhex[buffer[0]/16];
|
||||
sortie[j+5] = carhex[buffer[0]%16];
|
||||
sortie->ptr[j+4] = carhex[buffer[0]/16];
|
||||
sortie->ptr[j+5] = carhex[buffer[0]%16];
|
||||
/* */
|
||||
buffer[0] = md4[i] & 255;
|
||||
sortie[j+6] = carhex[buffer[0]/16];
|
||||
sortie[j+7] = carhex[buffer[0]%16];
|
||||
sortie->ptr[j+6] = carhex[buffer[0]/16];
|
||||
sortie->ptr[j+7] = carhex[buffer[0]%16];
|
||||
}
|
||||
sortie[32] = 0;
|
||||
dynSetLen(e, sortie, 32);
|
||||
}
|
||||
|
||||
/* MD5 stuff, as of RFC 1321 */
|
||||
|
||||
#define S11 7
|
||||
#define S12 12
|
||||
#define S13 17
|
||||
#define S14 22
|
||||
#define S21 5
|
||||
#define S22 9
|
||||
#define S23 14
|
||||
#define S24 20
|
||||
#define S31 4
|
||||
#define S32 11
|
||||
#define S33 16
|
||||
#define S34 23
|
||||
#define S41 6
|
||||
#define S42 10
|
||||
#define S43 15
|
||||
#define S44 21
|
||||
|
||||
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
|
||||
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define I(x, y, z) ((y) ^ ((x) | (~z)))
|
||||
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
|
||||
|
||||
#define FF(a, b, c, d, x, s, ac) { (a) += F ((b), (c), (d)) + (x) + (ent32)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
|
||||
#define GG(a, b, c, d, x, s, ac) { (a) += G ((b), (c), (d)) + (x) + (ent32)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
|
||||
#define HH(a, b, c, d, x, s, ac) { (a) += H ((b), (c), (d)) + (x) + (ent32)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
|
||||
#define II(a, b, c, d, x, s, ac) { (a) += I ((b), (c), (d)) + (x) + (ent32)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
|
||||
|
||||
static void encodageMD5(env * e, var * entree, var * sortie)
|
||||
{
|
||||
ent32 a, b, c, d, s0, s1, s2, s3, i, x[16];
|
||||
unsigned char buffer[64];
|
||||
/* */
|
||||
s0 = 0x67452301;
|
||||
s1 = 0xefcdab89;
|
||||
s2 = 0x98badcfe;
|
||||
s3 = 0x10325476;
|
||||
/* */
|
||||
long len64 = entree->mLg % 64;
|
||||
long nb64 = entree->mLg / 64;
|
||||
long der1 = 0, der2 = 0, der3 = 0;
|
||||
if(len64 < 56)
|
||||
{
|
||||
// dernier bloc : len64(entree) 1(128) 55-len64(0) 8(mLg)
|
||||
der1 = ++nb64;
|
||||
}
|
||||
else
|
||||
{
|
||||
// avant dernier bloc : len64(entree) 1(128) 63-len64(0)
|
||||
// dernier bloc : 0(56) 8(mLg)
|
||||
der2 = ++nb64;
|
||||
der3 = ++nb64;
|
||||
}
|
||||
ent64 nb = (ent64)(entree->mLg * 8); /* en bits */
|
||||
pointeur p = entree->ptr;
|
||||
/* pour chaque bloc de 64 octets (512 bits) */
|
||||
for(long cpt = 1; cpt <= nb64; cpt++)
|
||||
{
|
||||
if(cpt == der1)
|
||||
{
|
||||
// dernier bloc cas modulo < 56
|
||||
memset(buffer, 0, 64);
|
||||
if(len64 > 0)
|
||||
memcpy(buffer, p, len64);
|
||||
buffer[len64] = 128;
|
||||
buffer[56] = (nb) & 0xff;
|
||||
buffer[57] = (nb >> 8) & 0xff;
|
||||
buffer[58] = (nb >> 16) & 0xff;
|
||||
buffer[59] = (nb >> 24) & 0xff;
|
||||
buffer[60] = (nb >> 32) & 0xff;
|
||||
buffer[61] = (nb >> 40) & 0xff;
|
||||
buffer[62] = (nb >> 48) & 0xff;
|
||||
buffer[63] = (nb >> 56) & 0xff;
|
||||
p = buffer;
|
||||
}
|
||||
else if(cpt == der2)
|
||||
{
|
||||
// avant dernier bloc cas modulo >= 56
|
||||
memset(buffer, 0, 64);
|
||||
memcpy(buffer, p, len64);
|
||||
buffer[len64] = 128;
|
||||
p = buffer;
|
||||
}
|
||||
else if (cpt == der3)
|
||||
{
|
||||
// dernier bloc cas modulo >= 56
|
||||
memset(buffer, 0, 64);
|
||||
buffer[56] = (nb) & 0xff;
|
||||
buffer[57] = (nb >> 8) & 0xff;
|
||||
buffer[58] = (nb >> 16) & 0xff;
|
||||
buffer[59] = (nb >> 24) & 0xff;
|
||||
buffer[60] = (nb >> 32) & 0xff;
|
||||
buffer[61] = (nb >> 40) & 0xff;
|
||||
buffer[62] = (nb >> 48) & 0xff;
|
||||
buffer[63] = (nb >> 56) & 0xff;
|
||||
p = buffer;
|
||||
}
|
||||
/* deplier la boucle ? */
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
x[i] = ((ent32)(*p++));
|
||||
x[i] |= (((ent32)(*p++)) << 8);
|
||||
x[i] |= (((ent32)(*p++)) << 16);
|
||||
x[i] |= (((ent32)(*p++)) << 24);
|
||||
}
|
||||
//hex(p, 64);
|
||||
/* */
|
||||
a = s0;
|
||||
b = s1;
|
||||
c = s2;
|
||||
d = s3;
|
||||
/* Round 1 */
|
||||
FF(a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
|
||||
FF(d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
|
||||
FF(c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
|
||||
FF(b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
|
||||
FF(a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
|
||||
FF(d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
|
||||
FF(c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
|
||||
FF(b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
|
||||
FF(a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
|
||||
FF(d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
|
||||
FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
|
||||
FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
|
||||
FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
|
||||
FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
|
||||
FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
|
||||
FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
|
||||
/* Round 2 */
|
||||
GG(a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
|
||||
GG(d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
|
||||
GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
|
||||
GG(b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
|
||||
GG(a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
|
||||
GG(d, a, b, c, x[10], S22, 0x02441453); /* 22 */
|
||||
GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
|
||||
GG(b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
|
||||
GG(a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
|
||||
GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
|
||||
GG(c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
|
||||
GG(b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
|
||||
GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
|
||||
GG(d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
|
||||
GG(c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
|
||||
GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
|
||||
/* Round 3 */
|
||||
HH(a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
|
||||
HH(d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
|
||||
HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
|
||||
HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
|
||||
HH(a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
|
||||
HH(d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
|
||||
HH(c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
|
||||
HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
|
||||
HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
|
||||
HH(d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
|
||||
HH(c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
|
||||
HH(b, c, d, a, x[ 6], S34, 0x04881d05); /* 44 */
|
||||
HH(a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
|
||||
HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
|
||||
HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
|
||||
HH(b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
|
||||
/* Round 4 */
|
||||
II(a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
|
||||
II(d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
|
||||
II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
|
||||
II(b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
|
||||
II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
|
||||
II(d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
|
||||
II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
|
||||
II(b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
|
||||
II(a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
|
||||
II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
|
||||
II(c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
|
||||
II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
|
||||
II(a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
|
||||
II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
|
||||
II(c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
|
||||
II(b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
|
||||
/* */
|
||||
s0 += a;
|
||||
s1 += b;
|
||||
s2 += c;
|
||||
s3 += d;
|
||||
}
|
||||
p = sortie->ptr; /* 16 octets en hexa */
|
||||
char hexa[16] = "0123456789abcdef";
|
||||
/* */
|
||||
*p++ = hexa[(s0 >> 4) & 0xf];
|
||||
*p++ = hexa[(s0) & 0xf];
|
||||
*p++ = hexa[(s0 >> 12) & 0xf];
|
||||
*p++ = hexa[(s0 >> 8) & 0xf];
|
||||
*p++ = hexa[(s0 >> 20) & 0xf];
|
||||
*p++ = hexa[(s0 >> 16) & 0xf];
|
||||
*p++ = hexa[(s0 >> 28) & 0xf];
|
||||
*p++ = hexa[(s0 >> 24) & 0xf];
|
||||
/* */
|
||||
*p++ = hexa[(s1 >> 4) & 0xf];
|
||||
*p++ = hexa[(s1) & 0xf];
|
||||
*p++ = hexa[(s1 >> 12) & 0xf];
|
||||
*p++ = hexa[(s1 >> 8) & 0xf];
|
||||
*p++ = hexa[(s1 >> 20) & 0xf];
|
||||
*p++ = hexa[(s1 >> 16) & 0xf];
|
||||
*p++ = hexa[(s1 >> 28) & 0xf];
|
||||
*p++ = hexa[(s1 >> 24) & 0xf];
|
||||
/* */
|
||||
*p++ = hexa[(s2 >> 4) & 0xf];
|
||||
*p++ = hexa[(s2) & 0xf];
|
||||
*p++ = hexa[(s2 >> 12) & 0xf];
|
||||
*p++ = hexa[(s2 >> 8) & 0xf];
|
||||
*p++ = hexa[(s2 >> 20) & 0xf];
|
||||
*p++ = hexa[(s2 >> 16) & 0xf];
|
||||
*p++ = hexa[(s2 >> 28) & 0xf];
|
||||
*p++ = hexa[(s2 >> 24) & 0xf];
|
||||
/* */
|
||||
*p++ = hexa[(s3 >> 4) & 0xf];
|
||||
*p++ = hexa[(s3) & 0xf];
|
||||
*p++ = hexa[(s3 >> 12) & 0xf];
|
||||
*p++ = hexa[(s3 >> 8) & 0xf];
|
||||
*p++ = hexa[(s3 >> 20) & 0xf];
|
||||
*p++ = hexa[(s3 >> 16) & 0xf];
|
||||
*p++ = hexa[(s3 >> 28) & 0xf];
|
||||
*p++ = hexa[(s3 >> 24) & 0xf];
|
||||
/* */
|
||||
dynSetLen(e, sortie, 32);
|
||||
}
|
||||
|
||||
/* *********************************************************************************** */
|
||||
#ifdef WINLIB
|
||||
/* 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 ** );
|
||||
@@ -356,8 +590,10 @@ long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
|
||||
}
|
||||
else if(modFnIs(e, "vers", 4))
|
||||
{
|
||||
if(param1 == NULL)
|
||||
exc = EX_MODETAT;
|
||||
// renvoie la version du module/plugins
|
||||
if(param1->type == VAR_DYNAMIC)
|
||||
else if(param1->type == VAR_DYNAMIC)
|
||||
dynLet(e, param1, "1", 1); // version 1 ici
|
||||
else if(param1->type == VAR_NUMBER)
|
||||
param1->num = NUM_UN;
|
||||
@@ -371,7 +607,9 @@ long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
|
||||
exc = EX_MODETAT;
|
||||
else
|
||||
{
|
||||
if(param1->type == VAR_NUMBER)
|
||||
if(param1 == 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
|
||||
@@ -380,29 +618,46 @@ long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
|
||||
/* ============================================================================================= */
|
||||
else if(modFnIs(e, "MD2", 3))
|
||||
{
|
||||
p_etat->error = 0;
|
||||
// pour les vars en sortie, forcer le chgt de type si besoin ?
|
||||
if(param1->type != VAR_DYNAMIC)
|
||||
if(param1 == NULL || param2 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param2->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
encodageMD2(param1->mPtr, param1->lg, param2->mPtr);
|
||||
encodageMD2(e, param1, param2);
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(modFnIs(e, "MD4", 3))
|
||||
{
|
||||
p_etat->error = 0;
|
||||
// pour les vars en sortie, forcer le chgt de type si besoin ?
|
||||
if(param1->type != VAR_DYNAMIC)
|
||||
if(param1 == NULL || param2 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param2->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
encodageMD4(param1->mPtr, param1->lg, param2->mPtr);
|
||||
encodageMD4(e, param1, param2);
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(modFnIs(e, "MD5", 3))
|
||||
{
|
||||
// pour les vars en sortie, forcer le chgt de type si besoin ?
|
||||
if(param1 == NULL || param2 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param2->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
encodageMD5(e, param1, param2);
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
|
||||
+6
-1
@@ -27,6 +27,7 @@
|
||||
#include "langage.h"
|
||||
#include "var.h"
|
||||
#include "hashtable.h"
|
||||
#include "dynamic.h"
|
||||
|
||||
// force exporting
|
||||
#ifdef WINLIB
|
||||
@@ -371,7 +372,11 @@ WAPIDECL void hashtable_printdebug(env * e, var * varht, int detail)
|
||||
pchain = (entry *)((ent64)pchain_first + varht->separateur);
|
||||
}
|
||||
if(ptrClass)
|
||||
printf("%s : %s\n", GUV_CLASS, ptrClass);
|
||||
{
|
||||
dynLet(e, &e->tmp_dynamic, ptrClass, DYN_LGNONE);
|
||||
dynReplace(e, &e->tmp_dynamic, cFM, ':');
|
||||
printf("%s %s\n", GUV_CLASS, e->tmp_dynamic.mPtr);
|
||||
}
|
||||
printf("taille totale=%lld, occupee=%lld (taux %lld%%), nb item=%lld\n", tot, occ, occ * 100 / tot, nb);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ void instr_unassemble(env * e, pointeur debutBin, ent64 nolig)
|
||||
/* special 2 bytes w opcode */
|
||||
case IN_COMP:
|
||||
d1 = lire8(p);
|
||||
if(d1 < CMP_EQ || d1 > CMP_NOT)
|
||||
if(d1 < CMP_EQ || d1 > CMP_FOR)
|
||||
printf("??? (%d)", d1);
|
||||
else
|
||||
{
|
||||
@@ -73,6 +73,12 @@ void instr_unassemble(env * e, pointeur debutBin, ent64 nolig)
|
||||
case IN_PIDH:
|
||||
case IN_PHDO:
|
||||
case IN_PIDO:
|
||||
case IN_PHDN:
|
||||
case IN_PIDN:
|
||||
case IN_PHDV:
|
||||
case IN_PIDV:
|
||||
case IN_PVHD:
|
||||
case IN_PVID:
|
||||
case IN_DEXH:
|
||||
case IN_DEXI:
|
||||
case IN_DESH:
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
/* ************************************ */
|
||||
/* AJOUT D'UNE INSTRUCTION
|
||||
- instr.h : ci-dessous, 2 constantes + ajout a libInstr
|
||||
- instr.c : ajout constante, si besoin, dans instr_unassemble
|
||||
- langage.c : ajout dans le tableau de function instr + dans le commentaire en dessous,
|
||||
ajouter la function instr_xxx
|
||||
- assembler.c : ajout switch de la function assembler,
|
||||
@@ -38,7 +39,7 @@
|
||||
char libInstr[256 * 4] ={"VERS" "JUMP" "DECL" "SRCL" "BEXC" "EXCE" "CATC" "THRW" "PART" "RETN"
|
||||
"CALL" "PARM" "SUBR" "COMP" "JMPF" "JMPT" "ADDN" "SBCN" "MULN" "DIVN"
|
||||
"INTE" "FRAC" "NEGN" "ABSN" "MODL" "PSHC" "PSHV" "POPV" "PVAR" "PVAH"
|
||||
"WRIT" "WRLN" "DSET" "DEXV" "DCMP" "DSTO" "VLET" "DCAT" "DTON" "NTOD"
|
||||
"WRIT" "WRLN" "DSET" "DEXV" "DCMP" "DSTO" "LETV" "DCAT" "DTON" "NTOD"
|
||||
"DELE" "HLET" "CLAS" "NLET" "INCL" "PNAM" "PSH0" "PSH1" "PSH2" "PSH3"
|
||||
"PSH4" "PSH5" "PSH6" "PSH7" "PSH8" "PSH9" "PSHA" "PROG" "BACK" "CLIB"
|
||||
"PVAI" "DIVE" "MODN" "INPT" "PVAT" "TYPO" "PSHT" "CRAZ" "CPSH" "RETT"
|
||||
@@ -46,8 +47,8 @@ char libInstr[256 * 4] ={"VERS" "JUMP" "DECL" "SRCL" "BEXC" "EXCE" "CATC" "THRW"
|
||||
"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" "DESV"
|
||||
"DESH" "DESI" "DEZV" "DEZH" "DEZI" "SDBG" "xxxx" "xxxx" "xxxx" "xxxx" /* 110-119 */
|
||||
"xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx" "xxxx"
|
||||
"DESH" "DESI" "DEZV" "DEZH" "DEZI" "SDBG" "PHDN" "PIDN" "SADV" "VLET" /* 110-119 */
|
||||
"PHDV" "PIDV" "HCOU" "PVHD" "PVID" "SSRC" "SSCS" "xxxx" "xxxx" "xxxx" /* 126 */
|
||||
"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,7 +63,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"};
|
||||
char libComp[10 * 3] = {"EQ " "NE " "LT " "GT " "LE " "GE " "AND" "OR " "NOT" "FOR"};
|
||||
|
||||
#define IS_VERS "\x00"
|
||||
#define IN_VERS 0
|
||||
@@ -139,8 +140,8 @@ char libComp[9 * 3] = {"EQ " "NE " "LT " "GT " "LE " "GE " "AND" "OR " "NOT"};
|
||||
#define IN_DCMP 34
|
||||
#define IS_DSTO "\x23"
|
||||
#define IN_DSTO 35
|
||||
#define IS_VLET "\x24"
|
||||
#define IN_VLET 36
|
||||
#define IS_LETV "\x24"
|
||||
#define IN_LETV 36
|
||||
#define IS_DCAT "\x25"
|
||||
#define IN_DCAT 37
|
||||
#define IS_DTON "\x26"
|
||||
@@ -307,6 +308,28 @@ char libComp[9 * 3] = {"EQ " "NE " "LT " "GT " "LE " "GE " "AND" "OR " "NOT"};
|
||||
#define IN_DEZI 114
|
||||
#define IS_SDBG "\x73"
|
||||
#define IN_SDBG 115
|
||||
#define IS_PHDN "\x74"
|
||||
#define IN_PHDN 116
|
||||
#define IS_PIDN "\x75"
|
||||
#define IN_PIDN 117
|
||||
#define IS_SADV "\x76"
|
||||
#define IN_SADV 118
|
||||
#define IS_VLET "\x77"
|
||||
#define IN_VLET 119
|
||||
#define IS_PHDV "\x78"
|
||||
#define IN_PHDV 120
|
||||
#define IS_PIDV "\x79"
|
||||
#define IN_PIDV 121
|
||||
#define IS_HCOU "\x7A"
|
||||
#define IN_HCOU 122
|
||||
#define IS_PVHD "\x7B"
|
||||
#define IN_PVHD 123
|
||||
#define IS_PVID "\x7C"
|
||||
#define IN_PVID 124
|
||||
#define IS_SSRC "\x7D"
|
||||
#define IN_SSRC 125
|
||||
#define IS_SSCS "\x7E"
|
||||
#define IN_SSCS 126
|
||||
|
||||
#define IS_LIBR "\xFB"
|
||||
#define IN_LIBR 251
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024,2025 lanisys.fr
|
||||
\/ \/ Copyright 2024-2026 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
@@ -87,9 +87,9 @@ enum {
|
||||
VAR_OBJECT = 7, /* idem hashtable mais en objet : seule diff. element "_class" cree dans la table (interne) */
|
||||
VAR_BUFFER = 8, /* usage interne : pile calcul + pile appel sub (autre ? buffer circulaire ptr read/write) */
|
||||
VAR_NB = 8,
|
||||
VAR_EMPTY = 0, /* retour @empty */
|
||||
VAR_EMPTY = 0, /* retour @empty fonction type(expr) */
|
||||
|
||||
VAR_UNDECLARED = -1,
|
||||
VAR_UNDECLARED = 0, /* cas de retour si pas de var dans "typeof var1.var2.var3" */
|
||||
|
||||
WCP_WIN1252 = 1252,
|
||||
WCP_8859_1 = 28591,
|
||||
@@ -250,7 +250,11 @@ enum {
|
||||
EX_FORMAT_KO = 35, /* erreur de parametre (type format ou longueur incorrects) */
|
||||
EX_INSERT_KO = 36, /* erreur de parametre ou memoire dans insert() */
|
||||
EX_REMOVE_KO = 37, /* erreur de parametre ou memoire dans remove() */
|
||||
EXNB = 37 /* MEMO !!!! */
|
||||
EX_CHILD_FORK = 38, /* erreur de fork sur nouveau process */
|
||||
EX_CHILD_EXEC = 39, /* erreur execution nouveau process */
|
||||
EX_ZERO_FOR_INCR = 40, /* erreur increment a zero dans une boucle foreach numerique */
|
||||
EX_SORTEDSEARCH_KO = 41, /* erreur de parametre (type de tri incorrect) */
|
||||
EXNB = 41 /* MEMO !!!! */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@@ -266,7 +270,7 @@ typedef struct {
|
||||
octet tmp_cpt; /* nb de var tmp Dynamic, ne pas sauvegarder car dans la hash globale */
|
||||
octet tmp_free; /* numero de var tmp Dynamic dispo ; si > tmp_cpt, a creer dans la hash globale */
|
||||
//
|
||||
//var tblptr; /* contient les pointeurs sur les vars de type SUB/PARAM/OBJET, pour les rendre VAR_NULL si le ptr est libere */
|
||||
var varptrtbl; /* 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 */
|
||||
@@ -278,6 +282,7 @@ typedef struct {
|
||||
var * ad_var_hash; /* dans les enchainements PVAR/PVAH-PVAI, donne l'adresse de la hash possédant la "derniere" variable */
|
||||
var * ad_var_obj; /* dans une affectation let ou do sub, donne l'objet concerne si objet, pour lire les membres (hors sub) -> pour creer this */
|
||||
var * ad_var_class; /* donne l'objet de la classe mere de l'objet courant, objet Base si objet de classe Base */
|
||||
var * ad_var_sav; /* pour memoriser ad_var sur une affectation simple let a.b = c.d, instruction SADV / VLET / PHDV / PIDV */
|
||||
/* */
|
||||
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 ! */
|
||||
@@ -310,6 +315,9 @@ typedef struct {
|
||||
char sep_field, sep_subfield; /* pour dynamic */
|
||||
/* */
|
||||
int endianess; /* pour detection automatique de l'endianess de la plateforme d'execution */
|
||||
int use_signal; /* 1 si w gere et traite les signaux, 0 sinon (mode plugin : signaux geres par programme maitre) */
|
||||
/* */
|
||||
int level; /* niveau d'imvrication des appels do/call ; prog principal = level 1 */
|
||||
/* */
|
||||
int bin_indice; /* position dans _bin du binaire en cours d'exec ( _bin<2, bin_indice> ) */
|
||||
/* */
|
||||
@@ -351,7 +359,22 @@ enum {
|
||||
CMP_GE = 6,
|
||||
CMP_AND = 7,
|
||||
CMP_OR = 8,
|
||||
CMP_NOT = 9
|
||||
CMP_NOT = 9,
|
||||
CMP_FOR = 10
|
||||
};
|
||||
|
||||
enum {
|
||||
FORMAT_TRIM = 1,
|
||||
FORMAT_LEFT = 2,
|
||||
FORMAT_RIGHT = 3,
|
||||
FORMAT_CENTER = 4,
|
||||
FORMAT_SURROUND = 5
|
||||
};
|
||||
|
||||
enum {
|
||||
SORTEDSEARCH_NONE = 0,
|
||||
SORTEDSEARCH_ASC = 1, // = DYN_SORT_ASC
|
||||
SORTEDSEARCH_DESC = 2 // = DYN_SORT_DESC
|
||||
};
|
||||
|
||||
#define GUV_CLASS "_class"
|
||||
@@ -359,6 +382,7 @@ enum {
|
||||
#define GUV_LOCAL "_local"
|
||||
#define GUV_ENV "_env"
|
||||
#define GUV_ARG "_arg"
|
||||
#define GUV_WARGV "_wargv"
|
||||
#define GUV_ARGBACK "_argback"
|
||||
#define GUV_SRCDBG "_srcdbg"
|
||||
#define GUV_PROG "_prog"
|
||||
@@ -366,7 +390,7 @@ enum {
|
||||
#define GUV_BIN "_bin"
|
||||
#define GUV_WDIR "_wdir"
|
||||
|
||||
#define VARSYS "@varnull,@varnumber,@varsubroutine,@varparam,@vardynamic,@varhashtable,@varobject,@varbuffer,@false,@true,@forcount,@kill,@fork,@prog,@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,15,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"
|
||||
#define VARSYS "@varnull,@varnumber,@varsubroutine,@varparam,@vardynamic,@varhashtable,@varobject,@varbuffer,@false,@true,@level,@kill,@oid,@prog,@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,@asc,@desc;1,2,3,4,5,6,7,8,10,11,12,13,14,15,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,55,56"
|
||||
|
||||
#include "global.h"
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024 lanisys.fr
|
||||
\/ \/ Copyright 2024-2026 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
@@ -47,69 +47,253 @@ reste: (1,1,#00-#FF) ;11; 1,1,00-FF
|
||||
[] est remplace par () car cela revient au meme !
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "langage.h"
|
||||
#include "dynamic.h"
|
||||
#include "lex.h"
|
||||
|
||||
// force exporting
|
||||
#ifdef WINLIB
|
||||
#undef WAPIDECL
|
||||
#define WAPIDECL __declspec(dllexport)
|
||||
#else
|
||||
#undef WAPIDECL
|
||||
#define WAPIDECL
|
||||
#endif
|
||||
|
||||
static struct {
|
||||
long blanc, nomregle, debut, fin, occ, infini, commentaire, intervalle, hexa, car, reste;
|
||||
} rlex;
|
||||
|
||||
static long rg_lex(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);
|
||||
if(pos > 0)
|
||||
{
|
||||
dynField(e, regles, tmp, 1, pos + 1, 10, ',', 1);
|
||||
pos = dynToNum(e, tmp, DYN_FALSE, 5); // pas de signe et num regle sur 16 bits : 5 chiffres
|
||||
if(tmp->mInternal != DYN_OK)
|
||||
pos = 0;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
WAPIDECL void init_reg_lex(env * e, Dynamic * regles, Dynamic * tmp)
|
||||
{
|
||||
rlex.blanc = rg_lex(e, regles, "blanc", tmp); // 1
|
||||
rlex.nomregle = rg_lex(e, regles, "nomregle", tmp); // 2
|
||||
rlex.debut = rg_lex(e, regles, "debut", tmp); // 3
|
||||
rlex.fin = rg_lex(e, regles, "fin", tmp); // 4
|
||||
rlex.occ = rg_lex(e, regles, "occ", tmp); // 5
|
||||
rlex.infini = rg_lex(e, regles, "infini", tmp); // 6
|
||||
rlex.commentaire = rg_lex(e, regles, "commentaire", tmp); // 7
|
||||
rlex.intervalle = rg_lex(e, regles, "intervalle", tmp); // 8
|
||||
rlex.hexa = rg_lex(e, regles, "hexa", tmp); // 9
|
||||
rlex.car = rg_lex(e, regles, "car", tmp); // 10
|
||||
rlex.reste = rg_lex(e, regles, "reste", tmp); // 11
|
||||
}
|
||||
|
||||
WAPIDECL long parse_lex(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic * trav, Dynamic * encours)
|
||||
{
|
||||
#define nreg(x) ((x)*2 > trav->mLg ? 0 : *(ent16 *)(trav->mPtr + (x)*2 - 2))
|
||||
/* */
|
||||
static int numlig = 0;
|
||||
numlig++;
|
||||
/* */
|
||||
if(valex->mLg == 0)
|
||||
return OK; /* ligne vide */
|
||||
/* */
|
||||
int nbres = dynDcount(e, resultat, 10, DYN_NONE, DYN_NONE);
|
||||
int nbval = dynDcount(e, valex, cVM, 2, cFM);
|
||||
ent16 regle;
|
||||
dynSetLen(e, trav, 0);
|
||||
dynSetLen(e, encours, 0);
|
||||
for(int ival = nbval; ival > 0; ival--)
|
||||
{
|
||||
/* suppression des regles 1 et 7 (blanc et commentaire) */
|
||||
dynField(e, valex, tmp, 2, ival, cFM, cVM, 1);
|
||||
regle = dynToNum(e, tmp, DYN_FALSE, 0);
|
||||
if(regle == rlex.blanc || regle == rlex.commentaire)
|
||||
{
|
||||
dynDel(e, valex, 1, ival, cFM, cVM, 1);
|
||||
dynDel(e, valex, 2, ival, cFM, cVM, 1);
|
||||
dynDel(e, valex, 3, ival, cFM, cVM, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(dynCtrl(e, trav, trav->mLg + 2, TRUE) != DYN_OK)
|
||||
return DYN_ERR;
|
||||
if(trav->mLg > 0)
|
||||
memcopie(trav->mPtr + 2, trav->mPtr, trav->mLg);
|
||||
*(ent16 *)(trav->mPtr) = regle;
|
||||
dynSetLen(e, trav, trav->mLg + 2);
|
||||
}
|
||||
}
|
||||
//dynDel(e, valex, 2, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
if(trav->mLg == 0)
|
||||
return OK; /* blancs et/ou commentaire seuls */
|
||||
/* */
|
||||
//for(int i=1;i<=trav->mLg/2;i++) printf("%d,",nreg(i)); printf("\n");
|
||||
/* debut d'analyse des tokens : nomregle */
|
||||
if(nreg(1) != rlex.nomregle)
|
||||
{
|
||||
dynField(e, valex, tmp, 3, 1, cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : nom regle attendu\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR;
|
||||
}
|
||||
/* liste de et/ou */
|
||||
for(ent16 n = 2;;)
|
||||
{
|
||||
if((regle = nreg(n)) == 0)
|
||||
break;
|
||||
/* */
|
||||
if(regle == rlex.debut || regle == rlex.car) ; else
|
||||
{
|
||||
dynField(e, valex, tmp, 3, n, cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : car ou debut et/ou attendu\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR;
|
||||
}
|
||||
/* et */
|
||||
if(n == 2)
|
||||
dynStoreSz(e, valex, 4, DYN_NONE, "", 0, cFM, DYN_NONE);
|
||||
else
|
||||
dynConcatSz(e, valex, ";", 1);
|
||||
/* */
|
||||
if(regle == rlex.car)
|
||||
{
|
||||
/* 1 caractere = (1,1,car) (raccourci d'ecriture) */
|
||||
dynConcatSz(e, valex, "1,1,", 4);
|
||||
dynField(e, valex, tmp, 1, n, cFM, cVM, 1);
|
||||
dynConcat(e, valex, tmp);
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
if(nreg(n+1) == rlex.occ && (nreg(n+2) == rlex.occ || nreg(n+2) == rlex.infini)) ; else
|
||||
{
|
||||
dynField(e, valex, tmp, 3, n, cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : occurence min/max attendue %d\n", numlig, tmp->mPtr, n);
|
||||
return DYN_ERR;
|
||||
}
|
||||
n++;
|
||||
dynField(e, valex, tmp, 1, n, cFM, cVM, 1);
|
||||
dynIconv(e, tmp, encours, "X");
|
||||
dynConcat(e, valex, encours); // occmin
|
||||
n++;
|
||||
if(nreg(n) == rlex.infini)
|
||||
dynConcatSz(e, valex, "-1,", 3);
|
||||
else
|
||||
{
|
||||
dynField(e, valex, tmp, 1, n, cFM, cVM, 1);
|
||||
dynIconv(e, tmp, encours, "X");
|
||||
dynConcat(e, valex, encours); // occmax
|
||||
}
|
||||
ent16 n1,n2,n3; char unefois[2] = {0};
|
||||
n1 = nreg(n+1);
|
||||
n2 = nreg(n+2);
|
||||
n3 = nreg(n+3);
|
||||
while(n1 == rlex.car || n1 == rlex.hexa || ((n1 == rlex.car || n1 == rlex.hexa) && n2 == rlex.intervalle && (n3 == rlex.car || n3 == rlex.hexa)))
|
||||
{
|
||||
dynConcatSz(e, valex, unefois, DYN_LGNONE);
|
||||
if((n1 == rlex.car || n1 == rlex.hexa) && n2 == rlex.intervalle && (n3 == rlex.car || n3 == rlex.hexa))
|
||||
{
|
||||
n++;
|
||||
dynField(e, valex, tmp, 1, n, cFM, cVM, 1);
|
||||
if(n1 == 10)
|
||||
dynConcat(e, valex, tmp);
|
||||
else
|
||||
{
|
||||
dynIconv(e, tmp, encours, "X");
|
||||
dynConcatSz(e, valex, encours->mPtr + 1, DYN_LGNONE); // copier apres le #
|
||||
}
|
||||
dynConcatSz(e, valex, "-", 1);
|
||||
n += 2;
|
||||
dynField(e, valex, tmp, 1, n, cFM, cVM, 1);
|
||||
if(n3 == rlex.car)
|
||||
dynConcat(e, valex, tmp);
|
||||
else
|
||||
{
|
||||
dynIconv(e, tmp, encours, "X");
|
||||
dynConcatSz(e, valex, encours->mPtr + 1, DYN_LGNONE); // copier apres le #
|
||||
}
|
||||
}
|
||||
else if(n1 == rlex.car)
|
||||
{
|
||||
n++;
|
||||
dynField(e, valex, tmp, 1, n, cFM, cVM, 1);
|
||||
dynConcat(e, valex, tmp);
|
||||
}
|
||||
else if(n1 == rlex.hexa)
|
||||
{
|
||||
n++;
|
||||
dynField(e, valex, tmp, 1, n, cFM, cVM, 1);
|
||||
dynIconv(e, tmp, encours, "X");
|
||||
dynConcatSz(e, valex, encours->mPtr + 1, DYN_LGNONE); // copier apres le #
|
||||
}
|
||||
n1 = nreg(n+1);
|
||||
n2 = nreg(n+2);
|
||||
n3 = nreg(n+3);
|
||||
unefois[0] = ':';
|
||||
}
|
||||
if(unefois[0] == 0)
|
||||
{
|
||||
dynField(e, valex, tmp, 3, n, cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : caractere/intervalle attendu\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR;
|
||||
}
|
||||
if(n1 == rlex.fin) ; else
|
||||
{
|
||||
dynField(e, valex, tmp, 3, n, cFM, cVM, 1);
|
||||
printf("Erreur ligne %dc%s : fin et/ou attendue\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR;
|
||||
}
|
||||
n += 2;
|
||||
}
|
||||
/* lecture nom regle en hexa */
|
||||
dynField(e, valex, tmp, 1, 1, cFM, cVM, 1);
|
||||
dynIconv(e, tmp, trav, "X");
|
||||
trav->mPtr[trav->mLg - 1] = ','; /* exemple : begin,1,comment,2,... permet de faire un locate */
|
||||
dynConcatSz(e, trav, Int64ToSz(e, nbres == 0 ? 1 : nbres, DYN_FALSE, 0), DYN_LGNONE);
|
||||
dynStore(e, resultat, 1, nbres == 0 ? 1 : nbres*2-1, trav, 10, ',');
|
||||
/* */
|
||||
dynField(e, valex, tmp, 4, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
nbres = (nbres == 0 ? 2 : nbres + 1);
|
||||
dynStoreSz(e, resultat, nbres, DYN_NONE, tmp->mPtr, tmp->mLg, 10, DYN_NONE);
|
||||
/* */
|
||||
#undef nreg
|
||||
return OK;
|
||||
}
|
||||
|
||||
#include "lex_files.h"
|
||||
|
||||
long regles_lex(env * e, Dynamic * r)
|
||||
WAPIDECL long lire_regles_lex(env * e, Dynamic * regles, char * fichier_lex)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
dynConcatSz(e, r, "1,1,29\n", DYN_LGNONE);
|
||||
dynConcatSz(e, r, "1,9,30-39;1,1,2C\n", DYN_LGNONE);
|
||||
dynConcatSz(e, r, "1,1,2A;1,1,2C\n", DYN_LGNONE);
|
||||
dynConcatSz(e, r, "1,1,3B;0,-1,09-7E\n", DYN_LGNONE);
|
||||
dynConcatSz(e, r, "1,1,2D\n", DYN_LGNONE);
|
||||
dynConcatSz(e, r, "1,1,23;2,2,30-39:41-46\n", DYN_LGNONE);
|
||||
dynConcatSz(e, r, "1,1,21-7E\n", DYN_LGNONE);
|
||||
dynConcatSz(e, r, "1,1,00-FF", DYN_LGNONE);
|
||||
return DYN_OK;
|
||||
}
|
||||
//
|
||||
long lire_regles_lex(env * e, Dynamic * regles, char * fichier_lex)
|
||||
{
|
||||
long cr;
|
||||
long cr = DYN_ERR;
|
||||
if(fichier_lex != NULL)
|
||||
{
|
||||
/* 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);
|
||||
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);
|
||||
cr = dynLet(e, regles, file_wlex, DYN_LGNONE);
|
||||
}
|
||||
else if(strncmp(fichier_lex, "lexlex", 6) == 0)
|
||||
{
|
||||
cr = dynLet(e, regles, file_lexlex, 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" (?!)
|
||||
//
|
||||
if(cr == DYN_OK)
|
||||
{
|
||||
dynErase(e, regles, "\r"); /* nettoyage au cas ou fichier Windows */
|
||||
//dynDel(e, regles, 1, DYN_NONE, 10, DYN_NONE, 1); /* la premiere ligne contient le <numero,nom> des regles, separe par "," */
|
||||
}
|
||||
//dynErase(e, regles, "\r"); /* nettoyage au cas ou fichier Windows */
|
||||
return cr;
|
||||
}
|
||||
//
|
||||
long concorde_h(env * e, Dynamic * chaine, Dynamic * regle, Dynamic * elem, Dynamic * detail)
|
||||
|
||||
static long concorde_h(env * e, Dynamic * chaine, Dynamic * regle, Dynamic * elem, Dynamic * detail)
|
||||
{
|
||||
long conc = 1, lgconc = 0, fin = FALSE, ichaine = 0, nch, t1, t2, trouve;
|
||||
long occmin, occmax, occtrouve, occsuiv;
|
||||
@@ -208,8 +392,8 @@ long concorde_h(env * e, Dynamic * chaine, Dynamic * regle, Dynamic * elem, Dyna
|
||||
conc = lgconc;
|
||||
return conc;
|
||||
}
|
||||
//
|
||||
void lex(env * e, Dynamic * regles, Dynamic * saisie, Dynamic * valex)
|
||||
|
||||
WAPIDECL void lex(env * e, Dynamic * regles, Dynamic * saisie, Dynamic * valex)
|
||||
{
|
||||
/* vars Dynamic :
|
||||
regles (en entree) : liste des regles ; etregle : regle ET en cours
|
||||
@@ -361,6 +545,57 @@ void lex(env * e, Dynamic * regles, Dynamic * saisie, Dynamic * valex)
|
||||
dynFree(e, &motencours);
|
||||
dynFree(e, &trouvemot);
|
||||
}
|
||||
|
||||
WAPIDECL long compile_lex(env * e, Dynamic * fichier_lex, Dynamic * compile)
|
||||
{
|
||||
// "compile" les regles lex fournies dans <fichier_lex> et renvoi le resultat dans <compile>
|
||||
// <1> = nom et numeros des regles, <2> a <n> = regles lex
|
||||
long cr = DYN_OK, ret = 0;
|
||||
Dynamic regles, tmp, ligne, tmp1, tmp2, tmp3;
|
||||
//
|
||||
dynInit(e, ®les, 0);
|
||||
dynInit(e, &tmp, 0);
|
||||
dynInit(e, &ligne, 0);
|
||||
dynInit(e, &tmp1, 0);
|
||||
dynInit(e, &tmp2, 0);
|
||||
dynInit(e, &tmp3, 0);
|
||||
//
|
||||
dynSetLen(e, compile, 0);
|
||||
//
|
||||
cr = lire_regles_lex(e, ®les, "lexlex"); // <regles> = regles lex compiles
|
||||
if(cr == DYN_OK)
|
||||
{
|
||||
init_reg_lex(e, ®les, &tmp);
|
||||
dynErase(e, fichier_lex, "\r");
|
||||
dynRemove(e, fichier_lex, NULL, 0, DYN_TRUE);
|
||||
while(dynRemove(e, fichier_lex, &ligne, 10, DYN_FALSE) > -1 && ret == 0)
|
||||
{
|
||||
lex(e, ®les, &ligne, &tmp); // tmp au format "valex" : chaine/noregle/position
|
||||
ret = parse_lex(e, &tmp, compile, &tmp1, &tmp2, &tmp3);
|
||||
}
|
||||
if(ret != 0)
|
||||
cr = DYN_ERR;
|
||||
}
|
||||
//
|
||||
dynFree(e, ®les);
|
||||
dynFree(e, &tmp);
|
||||
dynFree(e, &ligne);
|
||||
dynFree(e, &tmp1);
|
||||
dynFree(e, &tmp2);
|
||||
dynFree(e, &tmp3);
|
||||
//
|
||||
return cr;
|
||||
}
|
||||
|
||||
/*
|
||||
pour utiliser lex :
|
||||
- compiler les regles 1 fois : compile_lex(e, regles, compile)
|
||||
- analyser du contenu : lex(e, compile, contenu, valex)
|
||||
le resultat est dans valex : <1> chaine hexa en VM, <2> no regle en VM, <3> position origine contenu en VM
|
||||
le nom de la regle <no regle> se trouve comme cela : dynField(e, compile, nom, 1, noregle*2-1, 10, ',', 1)
|
||||
la conversion en clair de la chaine hexa trouvee : dynIconv(e, hexa, clair, "X");
|
||||
*/
|
||||
|
||||
/* source OK :
|
||||
* LEX.REGLE = regles Lex, valeurs ET separees par "," ; liste de cars en OU pour chaque partie ET
|
||||
LEX.REGLE = ""
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/* **********************************************
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024-2026 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 LEX_H
|
||||
#define LEX_H
|
||||
|
||||
#include "apidecl.h"
|
||||
|
||||
/* utilise par genlex */
|
||||
WAPIDECL void init_reg_lex(env * e, Dynamic * regles, Dynamic * tmp);
|
||||
WAPIDECL long parse_lex(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic * trav, Dynamic * encours);
|
||||
|
||||
/* */
|
||||
WAPIDECL long lire_regles_lex(env * e, Dynamic * regles, char * fichier_lex);
|
||||
WAPIDECL void lex(env * e, Dynamic * regles, Dynamic * saisie, Dynamic * valex);
|
||||
|
||||
WAPIDECL long compile_lex(env * e, Dynamic * fichier_lex, Dynamic * compile);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,168 @@
|
||||
/* **********************************************
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024-2026 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 "lex.h"
|
||||
|
||||
typedef struct {
|
||||
int error; // dernier code erreur specifique au module
|
||||
//*** a completer selon le besoin du module
|
||||
} modEtat;
|
||||
|
||||
/* mettre ici les codes d'erreurs specifiques au module */
|
||||
/* codes a passer a la fonction setError */
|
||||
#define EXMOD_COMPILE -1
|
||||
|
||||
static int setError(modEtat * p, int err)
|
||||
{
|
||||
if(p != NULL)
|
||||
p->error = err;
|
||||
return err == OK ? OK : EX_MODERR;
|
||||
}
|
||||
|
||||
#ifdef WINLIB
|
||||
/* 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 ** );
|
||||
#endif
|
||||
|
||||
long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
|
||||
{
|
||||
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
|
||||
//
|
||||
}
|
||||
}
|
||||
else if(modFnIs(e, "end", 3))
|
||||
{
|
||||
//*** code specifique ici
|
||||
//
|
||||
// liberation specifique au module avant arret process
|
||||
if(p_etat != NULL)
|
||||
memfree(e, p_etat);
|
||||
}
|
||||
else if(modFnIs(e, "vers", 4))
|
||||
{
|
||||
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, "compile", 7))
|
||||
{
|
||||
// pour les vars en sortie, forcer le chgt de type si besoin ?
|
||||
if(param1 == NULL || param2 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param2->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
exc = setError(p_etat, compile_lex(e, param1, param2));
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(modFnIs(e, "analyze", 7))
|
||||
{
|
||||
// pour les vars en sortie, forcer le chgt de type si besoin ?
|
||||
if(param1 == NULL || param2 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_DYNAMIC) // rules
|
||||
exc = EX_MODPARAM;
|
||||
else if(param2->type != VAR_DYNAMIC) // input
|
||||
exc = EX_MODPARAM;
|
||||
else if(param3->type != VAR_DYNAMIC) // result
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
lex(e, param1, param2, param3);
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else
|
||||
{
|
||||
setError(p_etat, 0); // evite un warning de compil
|
||||
exc = EX_MODFUNC; // fonction non prise en charge
|
||||
}
|
||||
//
|
||||
return exc;
|
||||
}
|
||||
+42
-4
@@ -1,6 +1,44 @@
|
||||
|
||||
//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";
|
||||
// !! ne pas mettre de caracteres \r dans les constantes ci-dessous !!
|
||||
|
||||
//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";
|
||||
// fichiers lex
|
||||
static char file_lexlex[] = "blanc,1,nomregle,2,debut,3,fin,4,occ,5,infini,6,commentaire,7,intervalle,8,hexa,9,car,10,reste,11\n"
|
||||
"1,-1,20:09\n"
|
||||
"1,1,61-7A;0,-1,30-39:61-7A;1,1,3A\n"
|
||||
"1,1,28\n"
|
||||
"1,1,29\n"
|
||||
"1,9,30-39;1,1,2C\n"
|
||||
"1,1,2A;1,1,2C\n"
|
||||
"1,1,3B;0,-1,09-7E\n"
|
||||
"1,1,2D\n"
|
||||
"1,1,23;2,2,30-39:41-46\n"
|
||||
"1,1,21-7E\n"
|
||||
"1,1,00-FF";
|
||||
|
||||
// debugger w
|
||||
static char file_debuglex[] = "blanc,1,commande,2,aide,3,nombre,4,ajouter,5,supprimer,6,ident,7,identnext,8,reste,9\n"
|
||||
"1,-1,20:09:0A:0D\n"
|
||||
"1,2,61-7A:41-5A\n"
|
||||
"1,1,3F\n"
|
||||
"1,9,30-39\n"
|
||||
"1,1,2B\n"
|
||||
"1,1,2D\n"
|
||||
"1,1,3A;1,1,61-7A:41-5A:5F;0,23,61-7A:41-5A:30-39\n"
|
||||
"1,1,2E;1,1,61-7A:41-5A;0,23,61-7A:41-5A:30-39\n"
|
||||
"1,1,00-FF";
|
||||
|
||||
// langage W
|
||||
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,hold,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,sortedsearch,60,"
|
||||
"change,61,format,62,insert,63,remove,64,tonum,65,tostring,66,equal,67,diff,68,gt,69,lt,70,gte,71,lte,72,and,73,or,74,not,75,beginpar,76,endpar,77,beginh,78,endh,79,begins,80,ends,81,indirect,82,typeof,83,stringdq,84,stringq,85,ident,86,varsys,87,numberdec,88,numberint,89,minus,90,"
|
||||
"plus,91,multiply,92,divide,93,divident,94,modulo,95,concat,96,listesep,97,identsep,98,modsep,99,other,100"
|
||||
"\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\n"
|
||||
"1,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\n"
|
||||
"1,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\n"
|
||||
"1,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\n"
|
||||
"1,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\n"
|
||||
"1,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,68;1,1,6F;1,1,6C;1,1,64\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\n"
|
||||
"1,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,73;1,1,6F;1,1,72;1,1,74;1,1,65;1,1,64;1,1,73;1,1,65;1,1,61;1,1,72;1,1,63;1,1,68\n"
|
||||
"1,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\n"
|
||||
"1,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,74;1,1,79;1,1,70;1,1,65;1,1,6F;1,1,66\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\n"
|
||||
"1,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";
|
||||
@@ -44,6 +44,7 @@ typedef struct {
|
||||
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)
|
||||
int inverse; // "inverse" le decodage des bits LZW (cas des fichiers GIF)
|
||||
} modContextLzw;
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "langage.h"
|
||||
#include "dynamic.h"
|
||||
#include "var.h"
|
||||
|
||||
#include "lzw.h"
|
||||
|
||||
@@ -52,19 +53,23 @@ static int setError(modEtat * p, int err)
|
||||
__declspec(dllexport) long execModule(env * , var * , var * , var * , void ** );
|
||||
#endif
|
||||
|
||||
long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
|
||||
{
|
||||
/* 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(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 */
|
||||
/* */
|
||||
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 */
|
||||
//
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
/* les 4 fonctions suivantes doivent toujours exister dans chaque module */
|
||||
@@ -80,9 +85,6 @@ long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
p_etat->error = 0;
|
||||
//*** code specifique ici
|
||||
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(modFnIs(e, "end", 3))
|
||||
@@ -91,32 +93,38 @@ long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
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);
|
||||
}
|
||||
}
|
||||
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(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param1 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
exc = EX_MODPARAM; // variable en parametre du mauvais type
|
||||
{
|
||||
// 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(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
|
||||
}
|
||||
@@ -125,40 +133,40 @@ long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
else if(modFnIs(e, "set", 3))
|
||||
{
|
||||
/* compression du clair de param, en une fois */
|
||||
/* sinon utiliser : setinit, setnext, setend */
|
||||
/*exc = setError(p_etat, EXMOD_xxx);*/
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param1 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
if(param->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
exc = setError(p_etat, setLzw(e, param, &p_etat->cl, 0)); /* 0 : en une fois */
|
||||
}
|
||||
exc = setError(p_etat, setLzw(e, param1, &p_etat->cl, 0)); /* 0 : en une fois */
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(modFnIs(e, "get", 3))
|
||||
{
|
||||
/* decompression du code de param, en une fois */
|
||||
/* sinon utiliser getinit, getnext, getend */
|
||||
/*exc = setError(p_etat, EXMOD_xxx);*/
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param1 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
if(param->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
exc = setError(p_etat, getLzw(e, param, &p_etat->cl, 0)); /* 0 : en une fois */
|
||||
p_etat->cl.inverse = FALSE;
|
||||
if(param2 != NULL)
|
||||
{
|
||||
if(param2->type == VAR_DYNAMIC || param2->type == VAR_NUMBER)
|
||||
{
|
||||
number inv;
|
||||
if(var_conv_num(e, param2, &inv))
|
||||
p_etat->cl.inverse = (inv != 0 ? TRUE : FALSE);
|
||||
}
|
||||
}
|
||||
exc = setError(p_etat, getLzw(e, param1, &p_etat->cl, 0)); /* 0 : en une fois */
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else if(strncmp(e->fn, "xxx", 3) == 0)
|
||||
{
|
||||
//*** coder les autres fonctions ici de la meme maniere, au a mettre au debut !
|
||||
exc = setError(p_etat, EXMOD_xxx);
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else
|
||||
{
|
||||
|
||||
@@ -232,7 +232,7 @@ WAPIDECL long setLzw(env * e, var * clair, modContextLzw * cl, int type)
|
||||
WAPIDECL 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};
|
||||
long masque[13] = {0, 1, 3, 7, 15, 31, 63, 127, 0, 511, 1023, 2047, 4095}; // les 8 premiers servent au mode normal, les 4 derniers au mode "inverse"
|
||||
/* decodage lzw, type = 1 : premier appel, 2 : appel suivant, 3 : dernier appel, type = 0 : un seul appel pour tout */
|
||||
if(type == 1 || type == 0)
|
||||
{
|
||||
@@ -256,16 +256,33 @@ WAPIDECL long getLzw(env * e, var * comp, modContextLzw * cl, int type)
|
||||
/* 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;
|
||||
if(cl->inverse) // test, sinon param "inverse"
|
||||
{
|
||||
// cas LZW du giff (different de LZW natif/PDF !)
|
||||
if(cl->code.mInternal == 0)
|
||||
cl->reste |= c;
|
||||
else
|
||||
cl->reste |= (c << cl->code.mInternal);
|
||||
cl->code.mInternal += 8;
|
||||
if(cl->code.mInternal < cl->bits)
|
||||
continue;
|
||||
v = (cl->reste & masque[cl->bits]);
|
||||
cl->reste >>= cl->bits;
|
||||
cl->code.mInternal -= cl->bits;
|
||||
}
|
||||
else
|
||||
v = cl->reste >> cl->code.mInternal;
|
||||
cl->reste &= masque[cl->code.mInternal];
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -140,6 +140,8 @@ long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
|
||||
// nouveau document pdf
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param1 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(param1->type != VAR_HASHTABLE)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
|
||||
@@ -56,6 +56,7 @@ typedef struct {
|
||||
#else
|
||||
HANDLE handle;
|
||||
char semDesti[25]; // 23 cars + '#' + \0 (different desti sinon ko sous windows)
|
||||
HANDLE newProcess; // writer: handle process creee en SUSPEND, reader : handle passe en arg et convertit en num
|
||||
#endif
|
||||
// destinataire
|
||||
char desti[24]; // 23 cars + \0
|
||||
@@ -67,3 +68,6 @@ WAPIDECL void initShm(env * e, modContextShm * ctx);
|
||||
WAPIDECL void freeShm(env * e, modContextShm * ctx);
|
||||
WAPIDECL long readShm(env * e, modContextShm * ctx);
|
||||
WAPIDECL long writeShm(env * e, modContextShm * ctx);
|
||||
|
||||
WAPIDECL long newProcessShmWriter(env * e, modContextShm * ctx);
|
||||
WAPIDECL long newProcessShmReader(env * e, modContextShm * ctx);
|
||||
@@ -2,7 +2,7 @@
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024,2025 lanisys.fr
|
||||
\/ \/ Copyright 2024-2026 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
|
||||
@@ -23,9 +23,11 @@
|
||||
#include "shm.h"
|
||||
|
||||
#include "buffer.h"
|
||||
#include "dynamic.h"
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef WINLIB
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/sem.h>
|
||||
@@ -185,7 +187,6 @@ WAPIDECL long readShm(env * e, modContextShm * ctx)
|
||||
|
||||
WAPIDECL 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
|
||||
@@ -259,3 +260,232 @@ WAPIDECL long writeShm(env * e, modContextShm * ctx)
|
||||
#endif
|
||||
return e->exception;
|
||||
}
|
||||
|
||||
WAPIDECL long newProcessShmWriter(env * e, modContextShm * ctx)
|
||||
{
|
||||
int sizeLg = 20;
|
||||
#ifndef WINLIB
|
||||
key_t cle = Hash32(ctx->desti, 24); // chaine de 23 cars + \0
|
||||
// acceder au message (type Dynamic, a controler ?)
|
||||
int handle = shmget(cle, ctx->message->lg + sizeLg, IPC_CREAT | IPC_EXCL | 0666); // < 0 si ko
|
||||
if(handle < 0)
|
||||
return EXMOD_BUFFER_WRITE; // erreur access TODO revoir les erreurs
|
||||
// lire le pointeur
|
||||
pointeur data = (pointeur)shmat(handle, NULL, 0);
|
||||
if(data == (pointeur)(-1))
|
||||
{
|
||||
shmctl(handle, IPC_RMID, NULL);
|
||||
return EXMOD_BUFFER_WRITE;
|
||||
}
|
||||
// Ecrire les donnees
|
||||
memset(data, 0, sizeLg);
|
||||
strcpy((char *)data, Int64ToSz(e, ctx->message->lg, FALSE, sizeLg - 1));
|
||||
memcpy(data + sizeLg, ctx->message->ptr, ctx->message->lg);
|
||||
// ne liberer que le ptr sous unix
|
||||
shmdt(data);
|
||||
#else
|
||||
// la cle est directement le destinataire
|
||||
HANDLE handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, ctx->message->lg + sizeLg, ctx->desti); // attention au \0 de fin
|
||||
if( ! handle)
|
||||
return EXMOD_BUFFER_WRITE; // erreur access
|
||||
// lire le pointeur
|
||||
pointeur data = (pointeur)MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
|
||||
if( ! data)
|
||||
{
|
||||
CloseHandle(handle);
|
||||
return EXMOD_BUFFER_WRITE; // erreur recup pointeur
|
||||
}
|
||||
// Ecrire les donnees
|
||||
memset(data, 0, sizeLg);
|
||||
strcpy((char *)data, Int64ToSz(e, ctx->message->lg, FALSE, sizeLg - 1));
|
||||
memcpy(data + sizeLg, ctx->message->ptr, ctx->message->lg);
|
||||
// dupliquer le HANDLE sur le mapping
|
||||
HANDLE dup = NULL;
|
||||
if( ! DuplicateHandle(GetCurrentProcess(), handle, ctx->newProcess, &dup, 0, FALSE, DUPLICATE_SAME_ACCESS))// FALSE : le handle dupliqué n’a pas besoin d’être héritable
|
||||
e->exception = EXMOD_BUFFER_WRITE;
|
||||
// liberations
|
||||
UnmapViewOfFile(data);
|
||||
CloseHandle(handle);
|
||||
#endif
|
||||
return e->exception;
|
||||
}
|
||||
|
||||
WAPIDECL long newProcessShmReader(env * e, modContextShm * ctx)
|
||||
{
|
||||
int sizeLg = 20;
|
||||
#ifndef WINLIB
|
||||
key_t cle = Hash32(ctx->desti, 24); // chaine de 23 cars + \0
|
||||
// acceder au message (type Dynamic, a controler ?)
|
||||
int handle = shmget(cle, 0, 0); // < 0 si ko
|
||||
if(handle < 0)
|
||||
return EXMOD_BUFFER_WRITE; // erreur access TODO revoir les erreurs
|
||||
// lire le pointeur
|
||||
pointeur data = (pointeur)shmat(handle, NULL, 0);
|
||||
if(data == (pointeur)(-1))
|
||||
{
|
||||
shmctl(handle, IPC_RMID, NULL);
|
||||
return EXMOD_BUFFER_WRITE;
|
||||
}
|
||||
// Lire les donnees
|
||||
long err, lg = dynSzToNum(e, (char *)data, FALSE, sizeLg - 1, &err);
|
||||
if( ! dynCtrl(e, ctx->message, lg, FALSE))
|
||||
dynSetLen(e, ctx->message, 0);
|
||||
else
|
||||
{
|
||||
dynSetLen(e, ctx->message, lg);
|
||||
memcpy(data + sizeLg, ctx->message->ptr, ctx->message->lg);
|
||||
}
|
||||
// ne liberer que le ptr sous unix
|
||||
shmdt(data);
|
||||
shmctl(handle, IPC_RMID, NULL);
|
||||
#else
|
||||
// lire le pointeur, a partir du handle lu de la ligne de commande
|
||||
HANDLE handle = ctx->newProcess;
|
||||
pointeur data = (pointeur)MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
|
||||
if( ! data)
|
||||
{
|
||||
CloseHandle(handle);
|
||||
return EXMOD_BUFFER_WRITE; // erreur recup pointeur
|
||||
}
|
||||
// Lire les donnees
|
||||
long err, lg = dynSzToNum(e, (char *)data, FALSE, sizeLg - 1, &err);
|
||||
if( ! dynCtrl(e, ctx->message, lg, FALSE))
|
||||
dynSetLen(e, ctx->message, 0);
|
||||
else
|
||||
{
|
||||
dynSetLen(e, ctx->message, lg);
|
||||
memcpy(data + sizeLg, ctx->message->ptr, ctx->message->lg);
|
||||
}
|
||||
// liberations
|
||||
UnmapViewOfFile(data);
|
||||
CloseHandle(handle);
|
||||
#endif
|
||||
return e->exception;
|
||||
}
|
||||
|
||||
#ifndef WINLIB
|
||||
WAPIDECL int OpenLock(env * e, const char * name)
|
||||
{
|
||||
key_t cle = Hash32(name, 24); // chaine de 23 cars max + \0 de fin
|
||||
int semId = semget(cle, NBSEM, IPC_CREAT | IPC_EXCL | 0666);
|
||||
if(semId < 0)
|
||||
{
|
||||
if(errno != EEXIST)
|
||||
return -1; // erreur
|
||||
// deja cree, ok
|
||||
semId = semget(cle, NBSEM, 0);
|
||||
if(semId < 0)
|
||||
{
|
||||
return -1; // erreur
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// init semaphore
|
||||
unsigned short table[NBSEM];
|
||||
table[0] = 1;
|
||||
if(semctl(semId, 0, SETALL, table) < 0)
|
||||
{
|
||||
semctl(semId, IPC_RMID, 0);
|
||||
return -1; // erreur
|
||||
}
|
||||
}
|
||||
return semId; // >=0 : ok
|
||||
}
|
||||
#else
|
||||
WAPIDECL HANDLE OpenLock(env * e, const char * name)
|
||||
{
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
SECURITY_DESCRIPTOR sd;
|
||||
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
|
||||
SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE); // NULL => acces total pour tous
|
||||
sa.nLength = sizeof(sa);
|
||||
sa.lpSecurityDescriptor = &sd;
|
||||
sa.bInheritHandle = FALSE;
|
||||
|
||||
char fullName[40] = {0};
|
||||
if(strlen(name) > 23)
|
||||
return NULL; // nom trop long
|
||||
//
|
||||
strcpy(fullName, "Global\\");
|
||||
strcat(fullName, name);
|
||||
HANDLE hSem = CreateSemaphore(&sa, 1, 1, fullName); // 1 = valeur initiale du semaphore ; 1 = valeur max du semaphore ; nom du semaphore (unique)
|
||||
if( ! hSem)
|
||||
return NULL; // erreur (si existe, ne passe pas ici, hSem est renseigne avec le sem existant) // GetLastError() == ERROR_ALREADY_EXISTS n'est pas une erreur, dans ce cas hSem n'est pas NULL
|
||||
else
|
||||
return hSem;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef WINLIB
|
||||
WAPIDECL void CloseLock(env * e, int semId)
|
||||
{
|
||||
if(semId >= 0)
|
||||
semctl(semId, IPC_RMID, 0);
|
||||
}
|
||||
#else
|
||||
WAPIDECL void CloseLock(env * e, HANDLE hSem)
|
||||
{
|
||||
CloseHandle(hSem);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef WINLIB
|
||||
WAPIDECL int SetLock(env * e, int semId, int milliSec)
|
||||
{
|
||||
// prendre le verrou (semaphore) pour ecrire, avec attente
|
||||
struct sembuf bufw;
|
||||
struct timespec ts;
|
||||
ts.tv_sec = milliSec / 1000;
|
||||
ts.tv_nsec = (milliSec % 1000) * 1000000; // xxx ms
|
||||
bufw.sem_num = 0;
|
||||
bufw.sem_op = -1; // prendre
|
||||
bufw.sem_flg = SEM_UNDO | IPC_NOWAIT;
|
||||
if(semop(semId, &bufw, 1) < 0)
|
||||
{
|
||||
if(errno != EAGAIN)
|
||||
return -1; // erreur : semaphore ko
|
||||
// semaphore pris : attendre et reessayer une fois
|
||||
nanosleep(&ts, NULL);
|
||||
if(semop(semId, &bufw, 1) < 0)
|
||||
{
|
||||
if(errno != EAGAIN)
|
||||
return -1; // erreur : semaphore ko
|
||||
return 0; // sortie en timeout cette fois
|
||||
}
|
||||
}
|
||||
return 1; // ok
|
||||
}
|
||||
#else
|
||||
WAPIDECL int SetLock(env * e, HANDLE hSem, int milliSec)
|
||||
{
|
||||
int cr = WaitForSingleObject(hSem, milliSec);
|
||||
if( cr != WAIT_OBJECT_0) // retour WAIT_OBJECT_0 si ok, WAIT_TIMEOUT ou autre si pas dispo ou erreur
|
||||
{
|
||||
// semaphore pris : attendre ?
|
||||
if(cr != WAIT_TIMEOUT)
|
||||
return -1; // erreur
|
||||
// sortie en time out, semaphore pris, attendre ?
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef WINLIB
|
||||
WAPIDECL void UnsetLock(env * e, int semId)
|
||||
{
|
||||
// liberer le verrou
|
||||
struct sembuf bufw;
|
||||
bufw.sem_num = 0;
|
||||
bufw.sem_op = 1; // liberer
|
||||
bufw.sem_flg = SEM_UNDO | IPC_NOWAIT;
|
||||
semop(semId, &bufw, 1);
|
||||
}
|
||||
#else
|
||||
WAPIDECL void UnsetLock(env * e, HANDLE hSem)
|
||||
{
|
||||
// liberer le semaphore
|
||||
ReleaseSemaphore(hSem, 1, NULL);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,78 @@
|
||||
/* **********************************************
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024-2026 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>
|
||||
|
||||
#include "langage.h"
|
||||
|
||||
#ifndef WINLIB
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <poll.h>
|
||||
#include <unistd.h>
|
||||
typedef int Socket;
|
||||
typedef struct pollfd * wPoll;
|
||||
#else
|
||||
#include "winsock2.h" // link avec ws2_32.lib
|
||||
#include <windows.h>
|
||||
typedef SOCKET Socket;
|
||||
typedef LPWSAPOLLFD wPoll;
|
||||
#endif
|
||||
|
||||
/* codes a passer a la fonction setError */
|
||||
enum {
|
||||
EXMOD_SOCKET_ERROR = -1,
|
||||
EXMOD_SOCKET_OK = 0,
|
||||
EXMOD_SOCKET_INIT = 1,
|
||||
SOCKET_LISTEN_MAX = 10
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
var * listSocket; // contient le tableau de pollfd/WSAPOLLFD encapsule dans un dynamic
|
||||
int nbSocket; // nombre d'elements dans le tableau de pollfd
|
||||
wPoll poll; // pointeur vers le tableau de pollfd/WSAPOLLFD
|
||||
#ifdef UNIX
|
||||
sigset_t mOldBlockSig,mBlockSig; /* gestion des signaux sur socket serveur en ecoute (utile ?) */
|
||||
#endif
|
||||
} modContextSocket;
|
||||
|
||||
WAPIDECL void initSock(env * e, modContextSocket * ctx);
|
||||
WAPIDECL void freeSock(env * e, modContextSocket * ctx);
|
||||
WAPIDECL Socket NewSocket();
|
||||
WAPIDECL int SocketSetServer(env * e, modContextSocket * ctx, Socket sock, int port);
|
||||
WAPIDECL Socket AcceptClientSocket(env * e, modContextSocket * ctx, Socket sock);
|
||||
WAPIDECL int SocketConnectToServer(env * e, modContextSocket * ctx, Socket sock, int port, var * server);
|
||||
WAPIDECL int AddSocket(env * e, modContextSocket * ctx, Socket sock);
|
||||
WAPIDECL void DelSocket(env * e, modContextSocket * ctx, Socket sock);
|
||||
WAPIDECL int WaitSocketForRead(env * e, modContextSocket * ctx, int timeoutMs);
|
||||
WAPIDECL int WaitOneSocketForRead(env * e, modContextSocket * ctx, Socket sock, int timeoutMs);
|
||||
WAPIDECL void FreeSocket(env * e, modContextSocket * ctx, Socket sock);
|
||||
WAPIDECL int GetSocketError();
|
||||
WAPIDECL long ReadSocket(env * e, modContextSocket * ctx, Socket sock, var * data);
|
||||
WAPIDECL long WriteSocket(env * e, modContextSocket * ctx, Socket sock, var * data);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024,2025 lanisys.fr
|
||||
\/ \/ Copyright 2024-2026 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
@@ -35,26 +35,27 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <netdb.h>
|
||||
#else
|
||||
#include "winsock2.h"
|
||||
#include "windows.h"
|
||||
#endif
|
||||
|
||||
#include "langage.h"
|
||||
#include "dynamic.h"
|
||||
|
||||
#include "sock.h"
|
||||
|
||||
typedef struct {
|
||||
int error; /* dernier code erreur specifique au module */
|
||||
//***
|
||||
long mSocket; /* socket en cours */
|
||||
int mServeur; /* 0 socket serveur mere en ecoute, 1 socket serveur fille connectee a un client, 2 socket client */
|
||||
modContextSocket cs;
|
||||
|
||||
// TODO a enlever quand sock_lib.c ok
|
||||
int mSocket,mServeur;
|
||||
#ifdef UNIX
|
||||
sigset_t mOldBlockSig,mBlockSig; /* gestion des signaux sur socket serveur en ecoute */
|
||||
#endif
|
||||
// TODO : gerer plusieurs sockets (serveur ? client ?)
|
||||
} modEtat;
|
||||
|
||||
/* mettre ici les codes d'erreurs specifiques au module */
|
||||
/* codes a passer a la fonction setError */
|
||||
#define EXMOD_xxx 1
|
||||
} modEtat;
|
||||
|
||||
static int setError(modEtat * p, int err)
|
||||
{
|
||||
@@ -68,7 +69,7 @@ static int setError(modEtat * p, int err)
|
||||
__declspec(dllexport) long execModule(env * , var * , var * , var * , void ** );
|
||||
#endif
|
||||
|
||||
long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
|
||||
{
|
||||
/* TODO : gestion des 3 parametres (au lieu d'un seul) */
|
||||
modEtat * p_etat;
|
||||
@@ -76,12 +77,20 @@ long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
// init/end/vers/error sont obligatoires pour tout module
|
||||
// fonction createServer, arret
|
||||
// - - - - - - - - - - - - - - - - - - - -
|
||||
if(param == NULL || etat == NULL)
|
||||
if(etat == NULL)
|
||||
return EX_MODPARAM;
|
||||
else
|
||||
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 */
|
||||
//
|
||||
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 */
|
||||
@@ -96,8 +105,7 @@ long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
p_etat = (modEtat *)(*etat);
|
||||
p_etat->error = 0;
|
||||
//***
|
||||
p_etat->mSocket = 0;
|
||||
p_etat->mServeur = 0;
|
||||
initSock(e, &p_etat->cs);
|
||||
}
|
||||
}
|
||||
else if(modFnIs(e, "end", 3))
|
||||
@@ -106,9 +114,7 @@ long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
p_etat = (modEtat *)(*etat);
|
||||
if(p_etat != NULL)
|
||||
{
|
||||
//***
|
||||
if(p_etat->mSocket > 0)
|
||||
close(p_etat->mSocket);
|
||||
freeSock(e, &p_etat->cs);
|
||||
//***
|
||||
memfree(e, p_etat);
|
||||
}
|
||||
@@ -116,10 +122,10 @@ long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
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->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
|
||||
}
|
||||
@@ -130,8 +136,8 @@ long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
exc = EX_MODETAT;
|
||||
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
|
||||
}
|
||||
@@ -146,8 +152,8 @@ long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
return exc;
|
||||
}
|
||||
// param<1> = numero de port ; TODO : mettre une VAR_NUMBER ??
|
||||
long port = dynToNum(e, param, 0, 5);
|
||||
if(param->mInternal == DYN_ERR)
|
||||
long port = dynToNum(e, param1, 0, 5);
|
||||
if(param1->mInternal == DYN_ERR)
|
||||
{
|
||||
exc = setError(p_etat, 1);
|
||||
return exc;
|
||||
@@ -199,7 +205,7 @@ long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
p_etat->mSocket = 0;
|
||||
return exc;
|
||||
}
|
||||
// linger n'impacte QUE le close de la socket
|
||||
// linger n'impacte QUE le close de la socket, a voir si vraiment utile avec shutdown...
|
||||
l_s.l_onoff = 1;
|
||||
l_s.l_linger = 0; // les 2 valeurs provoquent un close avec retour immediat, sans traiter les donnees eventuelles en attente d'envoi et envoi RST au client s'il est connecte en TCP
|
||||
if(setsockopt(p_etat->mSocket, SOL_SOCKET, SO_LINGER, (void*)&l_s, sizeof (l_s)))
|
||||
@@ -249,21 +255,21 @@ long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
/* connexion a un serveur */
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(dynDcount(e, param, cFM, DYN_NONE, DYN_NONE) < 2)
|
||||
else if(dynDcount(e, param1, cFM, DYN_NONE, DYN_NONE) < 2)
|
||||
exc = EX_MODPARAM; /* erreur */
|
||||
else
|
||||
{
|
||||
// param<1> = host (nom ou ip)
|
||||
// param<2> = port
|
||||
// decouper en 2 chaines Comm
|
||||
tParam = dynToTabPtr(e, param, cFM);
|
||||
tParam = dynToTabPtr(e, param1, cFM);
|
||||
if(tParam == NULL)
|
||||
exc = EX_MODPARAM; /* erreur */
|
||||
}
|
||||
if(exc != OK)
|
||||
return exc;
|
||||
long port = atoi(tParam[1]);
|
||||
if(param->mInternal == DYN_ERR)
|
||||
if(param1->mInternal == DYN_ERR)
|
||||
{
|
||||
exc = setError(p_etat, 1);
|
||||
return exc;
|
||||
@@ -316,7 +322,7 @@ long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
p_etat->mSocket = 0;
|
||||
return exc;
|
||||
}
|
||||
// linger n'impacte QUE le close de la socket
|
||||
// linger n'impacte QUE le close de la socket, a voir si vraiment utile avec shutdown...
|
||||
l_s.l_onoff = 1;
|
||||
l_s.l_linger = 0; // les 2 valeurs provoquent un close avec retour immediat, sans traiter les donnees eventuelles en attente d'envoi et envoi RST au client s'il est connecte en TCP
|
||||
if(setsockopt(p_etat->mSocket, SOL_SOCKET, SO_LINGER, (void*)&l_s, sizeof (l_s)))
|
||||
@@ -351,7 +357,7 @@ long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
/* arret connexion cliente ou serveur */
|
||||
if(p_etat != NULL)
|
||||
{
|
||||
shutdown(p_etat->mSocket, 2);
|
||||
shutdown(p_etat->mSocket, 2); // 2 = RDWR sous Unix, shutdown permet de se passer de SO_LINGER !?
|
||||
close(p_etat->mSocket);
|
||||
p_etat->mSocket = 0;
|
||||
}
|
||||
@@ -361,9 +367,9 @@ long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
{
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param == NULL)
|
||||
else if(param1 == NULL)
|
||||
exc = EX_MODPARAM; /* erreur */
|
||||
else if(param->type != VAR_NUMBER)
|
||||
else if(param1->type != VAR_NUMBER)
|
||||
exc = EX_MODPARAM; /* erreur */
|
||||
if(exc == OK)
|
||||
{
|
||||
@@ -371,8 +377,8 @@ long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
struct timeval delai;
|
||||
long cr;
|
||||
// attend une activite sur la socket, timeOut en 1/10 de sec.
|
||||
delai.tv_sec = param->num / NUM_FACTEUR; // x sec
|
||||
delai.tv_usec = (param->num % NUM_FACTEUR) * 10; // y µsec
|
||||
delai.tv_sec = param1->num / NUM_FACTEUR; // x sec
|
||||
delai.tv_usec = (param1->num % NUM_FACTEUR) * 10; // y µsec
|
||||
FD_ZERO(&masque);
|
||||
FD_SET(p_etat->mSocket, &masque);
|
||||
//
|
||||
@@ -396,9 +402,9 @@ long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
cr = FD_ISSET(p_etat->mSocket, &masque);
|
||||
}
|
||||
if(cr > 0)
|
||||
param->num = NUM_UN; /* ok pour lire */
|
||||
param1->num = NUM_UN; /* ok pour lire */
|
||||
else
|
||||
param->num = NUM_ZERO; /* pas de donnees */
|
||||
param1->num = NUM_ZERO; /* pas de donnees */
|
||||
// si cr > 0 : ok pour continuer et lire la socket
|
||||
}
|
||||
}
|
||||
@@ -409,9 +415,9 @@ long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
/* lecture sur la connexion */
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param == NULL)
|
||||
else if(param1 == NULL)
|
||||
exc = EX_MODPARAM; /* erreur */
|
||||
else if(param->type != VAR_DYNAMIC)
|
||||
else if(param1->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM; /* erreur */
|
||||
if(exc == OK)
|
||||
{
|
||||
@@ -420,17 +426,17 @@ long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
#ifdef UNIX
|
||||
ioctl(p_etat->mSocket, FIONBIO, &arg); /* socket non bloquant (sys/ioctl.h) necessaire quand la longueur n'est pas connue (sinon lire sur la longueur et laisser(?) la socket bloquante) */
|
||||
#endif
|
||||
dynSetLen(e, param, 0);
|
||||
dynSetLen(e, param1, 0);
|
||||
do
|
||||
{
|
||||
if(!dynCtrl(e, param, param->mLg + pas, 1)) /* avec recopie */
|
||||
if(!dynCtrl(e, param1, param1->mLg + pas, 1)) /* avec recopie */
|
||||
{
|
||||
exc = setError(p_etat, 1);
|
||||
break;
|
||||
}
|
||||
would_block = 0;
|
||||
while((nblu = read(p_etat->mSocket, param->mPtr + param->mLg, pas)) < 0 && errno == EWOULDBLOCK /* WouldBlock = 11 */
|
||||
&& (param->mLg == 0 || flagInProgress) && (++would_block) < 100)
|
||||
while((nblu = read(p_etat->mSocket, param1->mPtr + param1->mLg, pas)) < 0 && errno == EWOULDBLOCK /* WouldBlock = 11 */
|
||||
&& (param1->mLg == 0 || flagInProgress) && (++would_block) < 100)
|
||||
#ifdef UNIX
|
||||
usleep(10000); /* attente de 10 ms entre chaque appel, maxi 100 fois (a garder ?) */
|
||||
#else
|
||||
@@ -439,7 +445,7 @@ long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
if(errno == EINPROGRESS) /* 115 */
|
||||
flagInProgress = 1; /* indique un envoi en plusieurs parties : ne plus sortir quand getLen # 0 car lecture pas finie ! */
|
||||
if(nblu > 0)
|
||||
dynSetLen(e, param, param->mLg + nblu);
|
||||
dynSetLen(e, param1, param1->mLg + nblu);
|
||||
/* */
|
||||
} while (nblu > 0);
|
||||
}
|
||||
@@ -451,17 +457,17 @@ long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
/* ecriture sur la connexion */
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param == NULL)
|
||||
else if(param1 == NULL)
|
||||
exc = EX_MODPARAM; /* erreur */
|
||||
else if(param->type != VAR_DYNAMIC)
|
||||
else if(param1->type != VAR_DYNAMIC)
|
||||
exc = EX_MODPARAM; /* erreur */
|
||||
if(exc == OK)
|
||||
{
|
||||
lg = param->mLg;
|
||||
lg = param1->mLg;
|
||||
while(lg > 0)
|
||||
{
|
||||
would_block = 0;
|
||||
while((nb = write(p_etat->mSocket, param->mPtr + pos, lg)) < 0 && errno == EWOULDBLOCK
|
||||
while((nb = write(p_etat->mSocket, param1->mPtr + pos, lg)) < 0 && errno == EWOULDBLOCK
|
||||
&& (++would_block) < 100)
|
||||
#ifdef UNIX
|
||||
usleep(10000); /* attente 10 ms entre chaque appel, maxi 100 fois (a garder ?) */
|
||||
@@ -485,9 +491,9 @@ long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
/* ecriture sur la connexion */
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param == NULL)
|
||||
else if(param1 == NULL)
|
||||
exc = EX_MODPARAM; /* erreur */
|
||||
else if(param->type != VAR_NUMBER)
|
||||
else if(param1->type != VAR_NUMBER)
|
||||
exc = EX_MODPARAM; /* erreur */
|
||||
if(exc == OK)
|
||||
{
|
||||
@@ -495,9 +501,9 @@ long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
|
||||
unsigned int size_addr_cnx = sizeof(addr_cnx);
|
||||
int sock;
|
||||
if((sock = accept(p_etat->mSocket, (struct sockaddr *)&addr_cnx, &size_addr_cnx)) >= 0)
|
||||
param->num = sock * NUM_FACTEUR; /* nouvelle requete entrante : renvoie num socket */
|
||||
param1->num = sock * NUM_FACTEUR; /* nouvelle requete entrante : renvoie num socket */
|
||||
else
|
||||
param->num = NUM_ZERO; /* pas de nouvelle connexion entrante finalement */
|
||||
param1->num = NUM_ZERO; /* pas de nouvelle connexion entrante finalement */
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
|
||||
+360
@@ -0,0 +1,360 @@
|
||||
/* **********************************************
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024-2026 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 "sock.h"
|
||||
|
||||
#include "dynamic.h"
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef WINLIB
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
// force exporting
|
||||
#ifdef WINLIB
|
||||
#undef WAPIDECL
|
||||
#define WAPIDECL __declspec(dllexport)
|
||||
#else
|
||||
#undef WAPIDECL
|
||||
#define WAPIDECL
|
||||
#endif
|
||||
|
||||
/* ---------------------------------------------------- */
|
||||
|
||||
/* ****** PRIVATE ************************ */
|
||||
|
||||
/* ****** PUBLIC ************************ */
|
||||
WAPIDECL void initSock(env * e, modContextSocket * ctx)
|
||||
{
|
||||
dynSetLen(e, ctx->listSocket, 0); // raz liste sockets
|
||||
//
|
||||
#ifdef WINLIB
|
||||
WSADATA wsa;
|
||||
WSAStartup(MAKEWORD(2,2), &wsa);
|
||||
#endif
|
||||
}
|
||||
|
||||
WAPIDECL void freeSock(env * e, modContextSocket * ctx)
|
||||
{
|
||||
// TODO fermer les sockets ouvertes
|
||||
#ifdef WINLIB
|
||||
WSACleanup();
|
||||
#endif
|
||||
}
|
||||
|
||||
WAPIDECL Socket NewSocket()
|
||||
{
|
||||
#ifdef WINLIB
|
||||
BOOL bOptVal = TRUE;
|
||||
int bOptLen = sizeof(BOOL);
|
||||
int iOptVal = 0;
|
||||
int iOptLen = sizeof(int);
|
||||
u_long block_mode = 1; // 1 = non-bloquant, 0 = bloquant
|
||||
#else
|
||||
int sockopt = 1;
|
||||
#endif
|
||||
struct linger l_s; /* Structure pour setsockopt */
|
||||
Socket sock;
|
||||
/* */
|
||||
#ifndef WINLIB
|
||||
if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
|
||||
#else
|
||||
if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
|
||||
#endif
|
||||
return EXMOD_SOCKET_ERROR;
|
||||
/* */
|
||||
#ifndef WINLIB
|
||||
ioctl(sock, FIONBIO, &sockopt); /* socket non bloquant (sys/ioctl.h) */
|
||||
// autre maniere
|
||||
//int flags = fcntl(fd, F_GETFL, 0);
|
||||
//if (flags == -1) return -1;
|
||||
//if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) return -1;
|
||||
#else
|
||||
ioctlsocket(sock, FIONBIO, &block_mode);
|
||||
#endif
|
||||
/* */
|
||||
/* voir ici https://learn.microsoft.com/fr-fr/windows/win32/api/winsock/nf-winsock-setsockopt pour les parametres a passer selon l'option */
|
||||
#ifndef WINLIB
|
||||
if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt))) /* pour eliminer une erreur : permet de rouvrir des socket suite a fermeture avec des clients encore connectes */
|
||||
#else
|
||||
if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&bOptVal, bOptLen)) /* pour eliminer une erreur : permet de rouvrir des socket suite a fermeture avec des clients encore connectes */
|
||||
#endif
|
||||
{
|
||||
#ifndef WINLIB
|
||||
close(sock);
|
||||
#else
|
||||
closesocket(sock);
|
||||
#endif
|
||||
return EXMOD_SOCKET_ERROR;
|
||||
}
|
||||
/* linger n'impacte QUE le close de la socket */
|
||||
l_s.l_onoff = 1;
|
||||
l_s.l_linger = 0; // les 2 valeurs provoquent un close avec retour immediat, sans traiter les donnees eventuelles en attente d'envoi et envoi RST au client s'il est connecte en TCP
|
||||
if(setsockopt(sock, SOL_SOCKET, SO_LINGER, (void*)&l_s, sizeof (l_s)))
|
||||
{
|
||||
#ifndef WINLIB
|
||||
close(sock);
|
||||
#else
|
||||
closesocket(sock);
|
||||
#endif
|
||||
return EXMOD_SOCKET_ERROR;
|
||||
}
|
||||
/* autres options ? */
|
||||
return sock;
|
||||
}
|
||||
|
||||
WAPIDECL int SocketSetServer(env * e, modContextSocket * ctx, Socket sock, int port)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
//
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_addr.s_addr = INADDR_ANY;
|
||||
addr.sin_port = htons(port);
|
||||
#ifndef WINLIB
|
||||
if(bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
|
||||
#else
|
||||
if(bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == EXMOD_SOCKET_ERROR)
|
||||
#endif
|
||||
{
|
||||
#ifndef WINLIB
|
||||
close(sock);
|
||||
#else
|
||||
closesocket(sock);
|
||||
#endif
|
||||
return EXMOD_SOCKET_ERROR;
|
||||
}
|
||||
#ifndef WINLIB
|
||||
if(listen(sock, SOCKET_LISTEN_MAX) < 0)
|
||||
#else
|
||||
if(listen(sock, SOCKET_LISTEN_MAX) == EXMOD_SOCKET_ERROR)
|
||||
#endif
|
||||
{
|
||||
#ifndef WINLIB
|
||||
close(sock);
|
||||
#else
|
||||
closesocket(sock);
|
||||
#endif
|
||||
return EXMOD_SOCKET_ERROR;
|
||||
}
|
||||
return EXMOD_SOCKET_OK;
|
||||
}
|
||||
|
||||
WAPIDECL Socket AcceptClientSocket(env * e, modContextSocket * ctx, Socket sock)
|
||||
{
|
||||
struct sockaddr_in addr_cnx;
|
||||
unsigned int size_addr_cnx = sizeof(addr_cnx);
|
||||
Socket clientSock;
|
||||
#ifndef WINLIB
|
||||
if((clientSock = accept(sock, (struct sockaddr *)&addr_cnx, &size_addr_cnx)) >= 0)
|
||||
#else
|
||||
if((clientSock = accept(sock, (struct sockaddr *)&addr_cnx, &size_addr_cnx)) != INVALID_SOCKET)
|
||||
#endif
|
||||
return clientSock;
|
||||
else
|
||||
return EXMOD_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
WAPIDECL int SocketConnectToServer(env * e, modContextSocket * ctx, Socket sock, int port, var * server)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
struct hostent * serv;
|
||||
//
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
#ifndef WINLIB
|
||||
if(inet_aton(server->mPtr, &(addr.sin_addr)) == 0)
|
||||
#else
|
||||
if(InetPton(AF_INET, server->mPtr, &addr) == 1)
|
||||
#endif
|
||||
{
|
||||
// no ip v4 format, search for name
|
||||
if((serv = gethostbyname(server->mPtr)) == NULL)
|
||||
{
|
||||
#ifndef WINLIB
|
||||
close(sock);
|
||||
#else
|
||||
closesocket(sock);
|
||||
#endif
|
||||
return EXMOD_SOCKET_ERROR;
|
||||
}
|
||||
addr.sin_addr.s_addr = ((struct in_addr *)(serv->h_addr))->s_addr;
|
||||
}
|
||||
#ifndef WINLIB
|
||||
if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
|
||||
#else
|
||||
if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == EXMOD_SOCKET_ERROR)
|
||||
#endif
|
||||
{
|
||||
#ifndef WINLIB
|
||||
close(sock);
|
||||
#else
|
||||
closesocket(sock);
|
||||
#endif
|
||||
return EXMOD_SOCKET_ERROR; /* erreur (TODO plusieurs essais avant erreur ?) */
|
||||
}
|
||||
if(AddSocket(e, ctx, sock))
|
||||
return EXMOD_SOCKET_OK;
|
||||
else
|
||||
return EXMOD_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
WAPIDECL int AddSocket(env * e, modContextSocket * ctx, Socket sock)
|
||||
{
|
||||
// controle pas deja existant
|
||||
ctx->poll = (wPoll)ctx->listSocket->ptr;
|
||||
for(int cpt = 0; cpt < ctx->nbSocket; cpt++)
|
||||
if(ctx->poll[cpt].fd == sock)
|
||||
return TRUE; // deja present : RAF
|
||||
// ajouter
|
||||
if(! dynCtrl(e, ctx->listSocket, (ctx->nbSocket + 1) * sizeof(*ctx->poll), TRUE))
|
||||
return FALSE; // pbm memoire
|
||||
ctx->poll = (wPoll)ctx->listSocket->ptr;
|
||||
ctx->poll[ctx->nbSocket].fd = sock;
|
||||
ctx->poll[ctx->nbSocket++].events = POLLIN; // post incrementation car tableau base 0
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
WAPIDECL void DelSocket(env * e, modContextSocket * ctx, Socket sock)
|
||||
{
|
||||
ctx->poll = (wPoll)ctx->listSocket->ptr;
|
||||
for(int cpt = 0; cpt < ctx->nbSocket; cpt++)
|
||||
if(ctx->poll[cpt].fd == sock)
|
||||
if(cpt < --ctx->nbSocket) // autre solution : mettre le fd en negatif : sera ignore par poll
|
||||
ctx->poll[cpt] = ctx->poll[ctx->nbSocket]; // remplacer par le dernier (bouche le trou tout de suite)
|
||||
}
|
||||
|
||||
WAPIDECL int WaitSocketForRead(env * e, modContextSocket * ctx, int timeoutMs)
|
||||
{
|
||||
ctx->poll = (wPoll)ctx->listSocket->ptr;
|
||||
#ifdef WINLIB
|
||||
return WSAPoll(ctx->poll, ctx->nbSocket, timeoutMs);
|
||||
#else
|
||||
return poll(ctx->poll, ctx->nbSocket, timeoutMs);
|
||||
#endif
|
||||
// socket pret a la lecture si (ctx->poll[cpt].revents & POLLIN) != 0 et poll retourne > 0, 0 = timeout (RAS), < 0 erreur (errno ou WSAGetLastError())
|
||||
}
|
||||
|
||||
WAPIDECL int WaitOneSocketForRead(env * e, modContextSocket * ctx, Socket sock, int timeoutMs)
|
||||
{
|
||||
ctx->poll = (wPoll)ctx->listSocket->ptr;
|
||||
for(int cpt = 0; cpt < ctx->nbSocket; cpt++)
|
||||
if(ctx->poll[cpt].fd == sock)
|
||||
#ifdef WINLIB
|
||||
return WSAPoll(&ctx->poll[cpt], 1, timeoutMs);
|
||||
#else
|
||||
return poll(&ctx->poll[cpt], 1, timeoutMs);
|
||||
#endif
|
||||
// socket pret a la lecture si (ctx->poll[cpt].revents & POLLIN) != 0 et poll retourne > 0, 0 = timeout (RAS), < 0 erreur (errno ou WSAGetLastError())
|
||||
return EXMOD_SOCKET_ERROR;
|
||||
}
|
||||
|
||||
WAPIDECL void FreeSocket(env * e, modContextSocket * ctx, Socket sock)
|
||||
{
|
||||
shutdown(sock, 2);
|
||||
#ifndef WINLIB
|
||||
close(sock);
|
||||
#else
|
||||
closesocket(sock);
|
||||
#endif
|
||||
DelSocket(e, ctx, sock);
|
||||
}
|
||||
|
||||
WAPIDECL int GetSocketError()
|
||||
{
|
||||
#ifdef WINLIB
|
||||
return WSAGetLastError();
|
||||
#else
|
||||
return errno;
|
||||
#endif
|
||||
}
|
||||
|
||||
// TODO *********************************************************
|
||||
// https://broux.developpez.com/articles/c/sockets
|
||||
// https://learn.microsoft.com/fr-fr/windows/win32/winsock/using-winsock
|
||||
// lecture / ecriture : utiliser send/recv => read/write fait idem avec attribute = 0
|
||||
WAPIDECL long ReadSocket(env * e, modContextSocket * ctx, Socket sock, var * data)
|
||||
{
|
||||
int packetLg = 10000; // parametre ?
|
||||
int timeoutMs = 100; // parametre ?
|
||||
int nbTot = 0;
|
||||
// code ici avec une socket non bloquante (sinon a revoir) ; ajouter dans la boucle le poll sur la socket quand besoin de reessayer
|
||||
for(;;)
|
||||
{
|
||||
/* TODO : mettre une limite en nb octets lus ? */
|
||||
int cr = WaitOneSocketForRead(e, ctx, sock, timeoutMs);
|
||||
if(cr < 0)
|
||||
{
|
||||
if(errno == EINTR)
|
||||
continue; // reprendre si signal
|
||||
return -1; /* erreur */
|
||||
}
|
||||
if(cr == 0)
|
||||
return nbTot; /* timeout : renvoi des donnees eventuellement deja lues */
|
||||
/* */
|
||||
if( ! dynCtrl(e, data, data->mLg + packetLg, TRUE))
|
||||
{
|
||||
return -2; // erreur memoire
|
||||
}
|
||||
int nbRead = read(sock, data->mPtr + data->mLg, packetLg);
|
||||
if(nbRead < 0)
|
||||
{
|
||||
if(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
continue; // reprendre si signal
|
||||
return -1; /* erreur */
|
||||
}
|
||||
if(nbRead == 0)
|
||||
return -1; /* fin de lecture car fin du client */
|
||||
/* nbRead positif ici */
|
||||
data->mLg += nbRead;
|
||||
nbTot += nbRead;
|
||||
}
|
||||
}
|
||||
|
||||
WAPIDECL long WriteSocket(env * e, modContextSocket * ctx, Socket sock, var * data)
|
||||
{
|
||||
//int timeoutMs = 100; // parametre ?
|
||||
long len = data->mLg, nbTot = 0;
|
||||
if(len == 0)
|
||||
return 0;
|
||||
/* */
|
||||
for(;;)
|
||||
{
|
||||
int nbWrite = write(sock, data->mPtr + nbTot, len);
|
||||
if(nbWrite == 0)
|
||||
return -1; /* fin du client */
|
||||
if(nbWrite < 0)
|
||||
{
|
||||
if(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
{
|
||||
// TODO : avant continuer, faire un poll sur la socket en ecriture idem read
|
||||
continue; // reprendre si signal
|
||||
}
|
||||
return -1; /* erreur */
|
||||
}
|
||||
len -= nbWrite;
|
||||
nbTot += nbWrite;
|
||||
if(len <= 0)
|
||||
return nbTot; /* OK */
|
||||
}
|
||||
}
|
||||
+61
-10
@@ -2,7 +2,7 @@
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024,2025 lanisys.fr
|
||||
\/ \/ Copyright 2024-2026 lanisys.fr
|
||||
|
||||
This file is part of W language.
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef UNIX
|
||||
#ifdef WINLIB
|
||||
#include "windows.h"
|
||||
#else
|
||||
#include <dirent.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/utsname.h>
|
||||
@@ -35,12 +37,11 @@
|
||||
#include <netinet/in.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include "windows.h" // TODO ici
|
||||
#endif
|
||||
|
||||
#include "langage.h"
|
||||
#include "dynamic.h"
|
||||
#include "var.h"
|
||||
|
||||
typedef struct {
|
||||
int error; // dernier code erreur specifique au module
|
||||
@@ -346,6 +347,7 @@ long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(modFnIs(e, "getHostname", 11))
|
||||
{
|
||||
// TODO dans sockMod !!
|
||||
p_etat->error = 0;
|
||||
// uname() donne les infos
|
||||
if(param1->type != VAR_DYNAMIC)
|
||||
@@ -429,6 +431,7 @@ long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(modFnIs(e, "fork", 4))
|
||||
{
|
||||
// TODO a supprimer, cf. processMod
|
||||
p_etat->error = 0;
|
||||
#ifndef UNIX
|
||||
// faire differemment sous windows : pas de fork dispo ? CreateProcess()
|
||||
@@ -451,6 +454,7 @@ long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(modFnIs(e, "wait", 4))
|
||||
{
|
||||
// TODO a supprimer, cf. processMod
|
||||
#ifndef UNIX
|
||||
// faire differemment sous windows : pas de wait dispo ? WaitForSingleObject()
|
||||
#else
|
||||
@@ -460,13 +464,60 @@ long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
|
||||
#endif
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(modFnIs(e, "kill", 4))
|
||||
else if(modFnIs(e, "sendSignal", 10))
|
||||
{
|
||||
#ifndef UNIX
|
||||
// faire differemment sous windows : pas de kill dispo ?
|
||||
#else
|
||||
kill(0, SIGTERM); // envoi un signal de fin a tous les fils
|
||||
#endif
|
||||
if(p_etat == NULL)
|
||||
exc = EX_MODETAT;
|
||||
else if(param1 == NULL || param2 == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
number pid, numSignal;
|
||||
if( var_conv_num(e,param1, &pid) && var_conv_num(e, param2, &numSignal) )
|
||||
{
|
||||
pid /= NUM_FACTEUR;
|
||||
numSignal /= NUM_FACTEUR;
|
||||
#ifdef WINLIB
|
||||
// faire differemment sous windows : pas de kill dispo, passer par des evenements (GenerateConsoleCtrlEvent ne fonctionne pas si autre session/cmd/BACK...)
|
||||
#define SIGINT 2
|
||||
#define SIGUSR1 10
|
||||
#define SIGTERM 15
|
||||
// autoriser tous les process a inter agir...
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
SECURITY_DESCRIPTOR sd;
|
||||
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
|
||||
SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE); // NULL => acces total pour tous
|
||||
sa.nLength = sizeof(sa);
|
||||
sa.lpSecurityDescriptor = &sd;
|
||||
sa.bInheritHandle = FALSE;
|
||||
//
|
||||
HANDLE hEvent = NULL;
|
||||
char eventName[40] = {0};
|
||||
if(numSignal == SIGTERM || numSignal == SIGINT)
|
||||
{
|
||||
sprintf(eventName, "Global\\wterm%lld", pid);
|
||||
hEvent= CreateEvent(&sa, FALSE, FALSE, eventName);
|
||||
}
|
||||
else if(numSignal == SIGUSR1)
|
||||
{
|
||||
sprintf(eventName, "Global\\wdebug%lld", pid);
|
||||
hEvent = CreateEvent(&sa, FALSE, FALSE, eventName);
|
||||
}
|
||||
if(hEvent != NULL) // GetLastError() == ERROR_ALREADY_EXISTS n'est pas une erreur : l'event existe deja (et hEvent n'est pas NULL)
|
||||
{
|
||||
// envoyer le signal
|
||||
SetEvent(hEvent);
|
||||
CloseHandle(hEvent);
|
||||
}
|
||||
//
|
||||
#else
|
||||
if(numSignal == SIGTERM || numSignal == SIGINT || numSignal == SIGUSR1)
|
||||
kill(pid, numSignal);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
exc = EX_MODPARAM;
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(modFnIs(e, "sleep", 5))
|
||||
|
||||
+1
-2
@@ -41,7 +41,7 @@ static int setError(modEtat * p, int err)
|
||||
{
|
||||
if(p != NULL)
|
||||
p->error = err;
|
||||
return EX_MODERR;
|
||||
return err == OK ? OK : EX_MODERR;
|
||||
}
|
||||
|
||||
#ifdef WINLIB
|
||||
@@ -51,7 +51,6 @@ __declspec(dllexport) long execModule(env * , var * , var * , var * , void ** );
|
||||
|
||||
long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
|
||||
{
|
||||
/* 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
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/* **********************************************
|
||||
__ __ __
|
||||
\ \/ \/ / W language
|
||||
\ /\ /
|
||||
\/ \/ Copyright 2024-2026 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"
|
||||
|
||||
/* programme de test unitaire de lib/fonctions */
|
||||
/* gcc w_src/test.c -s -o exec/test -Wall -m64 -DUNIX -L./exec -l:libw.so -l:encod_lib.so */
|
||||
|
||||
#include "encod.h"
|
||||
|
||||
env e;
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
init_env(&e);
|
||||
//
|
||||
Dynamic v, w;
|
||||
dynInit(&e, &v, DYN_LGMIN);
|
||||
dynInit(&e, &w, DYN_LGMIN);
|
||||
//
|
||||
dynLet(&e, &v, "test des encodages12", DYN_LGNONE);
|
||||
printf("test base64: %s\n", v.mPtr);
|
||||
//str2hex(&e, &v, &w);
|
||||
str2base64(&e, &v, &w);
|
||||
printf("%s\n", w.mPtr);
|
||||
dynLet(&e, &v, "dGVzdCBkZXMgZW5jb2RhZ2VzMTI=", DYN_LGNONE);
|
||||
base642str(&e, &v, &w);
|
||||
printf("decodage: %s\n", w.mPtr);
|
||||
dynLet(&e, &v, "303132333435363738394142434445", DYN_LGNONE);
|
||||
hex2str(&e, &v, &w);
|
||||
printf("hexa2str: %s\n", w.mPtr);
|
||||
//
|
||||
dynFree(&e, &v);
|
||||
dynFree(&e, &w);
|
||||
//
|
||||
return 0;
|
||||
}
|
||||
@@ -111,13 +111,92 @@ WAPIDECL void var_init(env * e, var * v, octet type, ent64 mod_lg, ent64 sep_lgm
|
||||
}
|
||||
}
|
||||
|
||||
WAPIDECL void var_ctrl_param(env * e, var * v)
|
||||
WAPIDECL int varptrtbl_ctrl(env * e, var * v)
|
||||
{
|
||||
/* controle que la var "v", si de type PARAM, pointe sur une var toujours existante... */
|
||||
/* indique si la var "v" appartient a une var de type pointeur (TRUE) */
|
||||
if(v == NULL)
|
||||
return FALSE;
|
||||
if(v->type == VAR_PARAM)
|
||||
return FALSE;
|
||||
/*
|
||||
format de varptrtbl : toutes les entrees sont de 8 octets
|
||||
v[1] = nb, v[2] = ad var param, v[3] = ptr de la var param, v[4] = ad var param2, etc.
|
||||
*/
|
||||
pointeur * beg = (pointeur *)e->varptrtbl.ptr;
|
||||
ent64 nb = *((ent64 *)beg); // ok si sizeof(pointeur) = sizeof(ent64)
|
||||
pointeur * curr = beg + 2;
|
||||
while(nb--)
|
||||
if((pointeur *)(*curr) == (pointeur *)v->ptr)
|
||||
return TRUE; // deja existant
|
||||
else
|
||||
curr += 2;
|
||||
// pas trouve
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WAPIDECL void varptrtbl_maj(env * e, var * v)
|
||||
{
|
||||
// ajoute a e->varptrtbl la var si de type "pointeur" : VAR_PARAM, objet...
|
||||
if(v == NULL)
|
||||
return;
|
||||
if(v->type != VAR_PARAM)
|
||||
return;
|
||||
/* TODO lire e->par_ptr de type dynamic ??? */
|
||||
/* dans le cas : hash, puis var de hash, puis clear hash : quid de la var de hash : ras car c'est une copie ! */
|
||||
/*
|
||||
format de varptrtbl : toutes les entrees sont de 8 octets
|
||||
v[1] = nb, v[2] = ad var param, v[3] = ptr de la var param, v[4] = ad var param2, etc.
|
||||
*/
|
||||
pointeur * beg = (pointeur *)e->varptrtbl.ptr;
|
||||
ent64 nb = *((ent64 *)beg); // ok si sizeof(pointeur) = sizeof(ent64)
|
||||
pointeur * curr = ++beg;
|
||||
ent64 addnb = nb + 1;
|
||||
while(nb--)
|
||||
if((pointeur *)(*curr) == (pointeur *)v)
|
||||
{
|
||||
curr++;
|
||||
*curr = (pointeur)v->ptr;
|
||||
return; // deja existant : maj ptr vraie var
|
||||
}
|
||||
else
|
||||
curr += 2;
|
||||
// pas trouve : ajout a la fin
|
||||
if(dynCtrl(e, &e->varptrtbl, sizeof(pointeur) * addnb * 2 + 1, TRUE))
|
||||
{
|
||||
beg = (pointeur *)e->varptrtbl.ptr; // au cas ou realloc memoire
|
||||
*((ent64 *)beg) = addnb;
|
||||
curr = beg + addnb * 2;
|
||||
*curr-- = (pointeur)v->ptr;
|
||||
*curr = (pointeur)v;
|
||||
}
|
||||
}
|
||||
|
||||
WAPIDECL void varptrtbl_del(env * e, var * v)
|
||||
{
|
||||
// supprime de e->varptrtbl la var param v
|
||||
if(v == NULL)
|
||||
return;
|
||||
/*
|
||||
format de varptrtbl : toutes les entrees sont de 8 octets
|
||||
v[1] = nb, v[2] = ad ptr, v[3] = ptr sur la var param, v[4] = ad ptr 2, etc.
|
||||
*/
|
||||
pointeur * beg = (pointeur *)e->varptrtbl.ptr;
|
||||
ent64 nb = *((ent64 *)beg); // ok si sizeof(pointeur) = sizeof(ent64)
|
||||
pointeur * curr = ++beg;
|
||||
ent64 savnb = nb;
|
||||
while(nb--)
|
||||
if((pointeur *)(*curr) == (pointeur *)v)
|
||||
{
|
||||
// trouve : mettre le dernier a la place de celui en cours, sauf si c'est le dernier
|
||||
*((ent64 *)beg) = savnb - 1;
|
||||
if(nb > 0) // pas de swap a faire si c'est le dernier qui est supprime
|
||||
{
|
||||
beg += savnb * 2 - 1; // le dernier
|
||||
*curr++ = *beg++;
|
||||
*curr = *beg;
|
||||
}
|
||||
}
|
||||
else
|
||||
curr += 2;
|
||||
// pas trouve : RAS
|
||||
}
|
||||
|
||||
WAPIDECL int var_conv_num(env * e, var * v, number * num)
|
||||
@@ -200,7 +279,6 @@ WAPIDECL void var_let(env * e, var * let, var * v, int suivre_let, int suivre_v)
|
||||
case VAR_DYNAMIC:
|
||||
var_init(e, let, v->type, 0, v->lg + 1, NULL); // +1 pour le \0 de fin
|
||||
memcopie(let->ptr, v->ptr, v->lg + 1); // permet de copier le \0 de fin
|
||||
//memcpy(let->ptr, v->ptr, v->lg + 1);
|
||||
let->lg = v->lg;
|
||||
break;
|
||||
//
|
||||
@@ -210,8 +288,7 @@ WAPIDECL void var_let(env * e, var * let, var * v, int suivre_let, int suivre_v)
|
||||
// boucler et copier les elements, attention aux cycles !
|
||||
hashtable_select(e, v);
|
||||
while(hashtable_next(e, v, e->nom, &pvar))
|
||||
// TODO copie recursive + copie de la var "pvar"
|
||||
hashtable_do(e, HASH_WRITE, let, e->nom, &pvar);
|
||||
hashtable_do(e, HASH_WRITE, let, e->nom, &pvar); // WRITE appelle var_let : recursif de fait
|
||||
break;
|
||||
//
|
||||
case VAR_PARAM:
|
||||
|
||||
@@ -26,10 +26,13 @@
|
||||
#include "apidecl.h"
|
||||
|
||||
WAPIDECL void var_init(env * e, var * v, octet type, ent64 mod_lg, ent64 sep_lgm, pointeur pf);
|
||||
WAPIDECL void var_ctrl_param(env * e, var * v);
|
||||
WAPIDECL int var_conv_num(env * e, var * v, number * num);
|
||||
WAPIDECL void var_free(env * e, var * v, int suivre_par);
|
||||
WAPIDECL void var_let(env * e, var * let, var * v, int suivre_let, int suivre_v);
|
||||
|
||||
WAPIDECL int varptrtbl_ctrl(env * e, var * v);
|
||||
WAPIDECL void varptrtbl_maj(env * e, var * v);
|
||||
WAPIDECL void varptrtbl_del(env * e, var * v);
|
||||
|
||||
/* ********************************************** */
|
||||
#endif
|
||||
@@ -57,7 +57,7 @@ new: new
|
||||
class: class
|
||||
this: this
|
||||
parent: parent
|
||||
free: free
|
||||
hold: hold
|
||||
precision: precision
|
||||
setsep: setsep
|
||||
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
/*************************************************************************************
|
||||
* w.php
|
||||
* -----
|
||||
* Author: FDE
|
||||
* Contributors:
|
||||
* Copyright: (c) 2023
|
||||
* Release Version: 1.0
|
||||
* Date Started: 05/10/2024
|
||||
*
|
||||
* W language file for GeSHi.
|
||||
*
|
||||
* a mettre ici : /lamp0/web/vhosts/www.lanisys.fr/htdocs/wiki/vendor/geshi/geshi/src/geshi
|
||||
*
|
||||
*************************************************************************************
|
||||
*
|
||||
* This file is part of GeSHi.
|
||||
*
|
||||
* GeSHi 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 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GeSHi 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 GeSHi; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
$language_data = array (
|
||||
'LANG_NAME' => 'W',
|
||||
'COMMENT_SINGLE' => array(1 => ';'),
|
||||
'COMMENT_MULTI' => array(),
|
||||
'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE,
|
||||
'QUOTEMARKS' => array('"', '\''),
|
||||
'ESCAPE_CHAR' => '',
|
||||
'KEYWORDS' => array(
|
||||
1 => array(
|
||||
'begin', 'background', 'library', 'except', 'end', 'sub',
|
||||
'endsub', 'include', 'loop', 'endloop', 'return', 'returnon',
|
||||
'break', 'breakon', 'continue', 'continueon', 'throw', 'catch',
|
||||
'foreach', 'in', 'like', 'if', 'then', 'elseif', 'else',
|
||||
'endif', 'endfor','echo', 'echonl', 'input', 'nop', 'part', 'declare',
|
||||
'let', 'do', 'call', 'invoke', 'delet', 'class', 'free',
|
||||
'new', 'this', 'parent', 'precision', 'setsep'
|
||||
),
|
||||
2 => array(
|
||||
'or', 'and', 'not', 'int', 'frac', 'abs', 'neg', 'type', 'typeof',
|
||||
'tonum', 'tostring', 'count', 'len', 'format', 'dcount',
|
||||
'round', 'field', 'index', 'search', 'change', 'insert', 'remove'
|
||||
)
|
||||
),
|
||||
'SYMBOLS' => array(
|
||||
'(', ')', '{', '}', '[', ']'
|
||||
),
|
||||
'CASE_SENSITIVE' => array(
|
||||
GESHI_COMMENTS => false,
|
||||
1 => true,
|
||||
2 => true,
|
||||
),
|
||||
'STYLES' => array(
|
||||
'KEYWORDS' => array(
|
||||
1 => 'color: #b1b100; font-weight: bold;',
|
||||
2 => 'color: #b1b100;'
|
||||
),
|
||||
'COMMENTS' => array(
|
||||
1 => 'color: #666666; font-style: italic;',
|
||||
),
|
||||
'ESCAPE_CHAR' => array(
|
||||
0 => 'color: #000099; font-weight: bold;'
|
||||
),
|
||||
'BRACKETS' => array(
|
||||
0 => 'color: #000066;'
|
||||
),
|
||||
'STRINGS' => array(
|
||||
0 => 'color: #009900;'
|
||||
),
|
||||
'NUMBERS' => array(
|
||||
0 => 'color: #CC0000;'
|
||||
),
|
||||
'METHODS' => array(
|
||||
1 => 'color: #006600;'
|
||||
),
|
||||
'SYMBOLS' => array(
|
||||
0 => 'color: #000066;'
|
||||
),
|
||||
'REGEXPS' => array(
|
||||
),
|
||||
'SCRIPT' => array(
|
||||
0 => '',
|
||||
1 => '',
|
||||
)
|
||||
),
|
||||
'URLS' => array(
|
||||
1 => '',
|
||||
2 => ''
|
||||
),
|
||||
'OOLANG' => false,
|
||||
'OBJECT_SPLITTERS' => array(
|
||||
1 => '\\'
|
||||
),
|
||||
'REGEXPS' => array(
|
||||
),
|
||||
'STRICT_MODE_APPLIES' => GESHI_NEVER,
|
||||
'SCRIPT_DELIMITERS' => array(),
|
||||
'HIGHLIGHT_STRICT_BLOCK' => array(
|
||||
0 => false,
|
||||
1 => false
|
||||
)
|
||||
);
|
||||
@@ -1,4 +1,4 @@
|
||||
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
|
||||
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,hold,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
|
||||
@@ -43,7 +43,7 @@ blank,1,comment,2,begin,3,background,4,library,5,end,6,except,7,throw,8,catch,9,
|
||||
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,68;1,1,6F;1,1,6C;1,1,64
|
||||
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
|
||||
@@ -97,4 +97,4 @@ blank,1,comment,2,begin,3,background,4,library,5,end,6,except,7,throw,8,catch,9,
|
||||
1,1,2C
|
||||
1,1,2E
|
||||
1,1,26
|
||||
1,1,00-FF
|
||||
1,1,00-FF
|
||||
Reference in new issue
Block a user