Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d32522c75 |
No files matched your search
@@ -1,8 +1,9 @@
|
||||
|
||||
#define ARG_DEBUG "d"
|
||||
#define ARG_TRACE "t"
|
||||
#define ARG_DISASM "u"
|
||||
#define ARG_COMPRESS "c"
|
||||
#define ARG_DEBUG "d" /* avec lw */
|
||||
#define ARG_TRACE "t" /* avec lw */
|
||||
#define ARG_DISASM "u" /* avec lwa */
|
||||
#define ARG_COMPRESS "c" /* avec lwa */
|
||||
#define ARG_SOURCE "s" /* avec lwc */
|
||||
|
||||
void GetArgs(env * e, int argc, char * argv[], Dynamic * arg)
|
||||
{
|
||||
@@ -21,6 +22,8 @@ void GetArgs(env * e, int argc, char * argv[], Dynamic * arg)
|
||||
dynStoreSz(e, arg, 1, ++nbOpt, ARG_DISASM, 1, cFM, cVM);
|
||||
else if(strcmp(argv[a], "-" ARG_COMPRESS) == 0)
|
||||
dynStoreSz(e, arg, 1, ++nbOpt, ARG_COMPRESS, 1, cFM, cVM);
|
||||
else if(strcmp(argv[a], "-" ARG_SOURCE) == 0)
|
||||
dynStoreSz(e, arg, 1, ++nbOpt, ARG_SOURCE, 1, cFM, cVM);
|
||||
//
|
||||
else if(strncmp(argv[a], "-WBIN:", 6) == 0 && strlen(argv[a]) > 6)
|
||||
dynStoreSz(e, arg, 3, DYN_NONE, &argv[a][6], DYN_LGNONE, cFM, DYN_NONE); // memo (.o .so)
|
||||
|
||||
+4
-2
@@ -671,7 +671,9 @@ int assembler(env * e, char * fichier, int * cptLig, int compress)
|
||||
PCODE(tmp.mPtr[p]);
|
||||
break;
|
||||
case IN_INCL:
|
||||
// INCL (lg=0 possible si rien)
|
||||
// INCL (lg=0 possible si rien) - ne pas mettre dans le pcode car ne sert plus
|
||||
i++;
|
||||
break;
|
||||
dynField(e, &ligne, &tmp, i++, 0, ' ', 0, 1);
|
||||
if(tmp.mLg < 0 || tmp.mLg > 255) { ret = -4; break; } // erreur longueur nom variable
|
||||
num = tmp.mLg;
|
||||
@@ -945,7 +947,7 @@ int disassembler(env * e, char * fichier)
|
||||
case IN_PVHD:
|
||||
case IN_PVID:
|
||||
case IN_PNAM:
|
||||
case IN_INCL:
|
||||
//case IN_INCL:
|
||||
// CPAN / CPHN / PARM / PVAR / PVAH / PVAI / DELE / NLET / PNAM / INCL / PHDE / PIDE
|
||||
si++;
|
||||
lg = pcode.ptr[si++];
|
||||
|
||||
@@ -66,7 +66,8 @@ char * strerr[] = {
|
||||
"EX_INT_EXP Fractional exponentiation is not calculated",
|
||||
"EX_VARPARAM_KO Null parameter pointer",
|
||||
"EX_PARAM_NOTFOUND Named parameter not found", // 45
|
||||
"EX_NUMOVF Numeric overflow"
|
||||
"EX_NUMOVF Numeric overflow",
|
||||
"EX_INPUT_TTY Cannot read from terminal or stdin"
|
||||
};
|
||||
|
||||
enum {
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "langage.h"
|
||||
#include "dynamic.h"
|
||||
#include "lex.h"
|
||||
#include "instr.h"
|
||||
|
||||
env e;
|
||||
|
||||
@@ -181,17 +182,103 @@ enum {
|
||||
|
||||
static void formatage_asm(Dynamic * s, Dynamic * f)
|
||||
{
|
||||
// TODO
|
||||
Dynamic trav, lig; /* variables de travail */
|
||||
dynInit(&e, &trav, 0);
|
||||
dynInit(&e, &lig, 0);
|
||||
long sdlw = 0;
|
||||
if(dynIndexSz(&e, s, "\r\n", 2, 1) > -1)
|
||||
{
|
||||
/* saut de ligne windows : supprimer \r et les remettre a la fin */
|
||||
sdlw = 1;
|
||||
/* supprimer les \r de la chaine ! */
|
||||
dynErase(&e, s, "\r");
|
||||
}
|
||||
//
|
||||
long numlig = 0, niveau = 0, flag_trt;
|
||||
dynRemove(&e, s, NULL, 0, DYN_TRUE);
|
||||
while(dynRemove(&e, s, &lig, 10, DYN_FALSE) > -1)
|
||||
{
|
||||
// traiter chaque ligne
|
||||
numlig++;
|
||||
if(lig.mLg == 0)
|
||||
continue; // ligne vide
|
||||
//
|
||||
// mettre dans trav la ligne sans le debut (blanc/tab)
|
||||
int i, pos = -1;
|
||||
for(i = 0; i < lig.mLg; i++)
|
||||
{
|
||||
if(lig.mPtr[i] == 32 || lig.mPtr[i] == 9)
|
||||
continue;
|
||||
pos = i;
|
||||
break;
|
||||
}
|
||||
if(pos == -1)
|
||||
continue; /* ligne avec que des blancs/tabs : idem vide */
|
||||
/* */
|
||||
dynSubstr(&e, &lig, &trav, pos, lig.mLg - pos, DYN_NONE, DYN_NONE, DYN_NONE, DYN_NONE);
|
||||
/* recherche instr dans la liste */
|
||||
int instr = -1, trouve = 0;
|
||||
if(lig.mPtr[pos] == ';')
|
||||
trouve = 1;
|
||||
for(i = 0; i < 256 && !trouve; i++)
|
||||
{
|
||||
if(strncmp(libInstr + i * 4, trav.mPtr, 4) == 0)
|
||||
{
|
||||
// instruction <instr> trouvee
|
||||
trouve = 1;
|
||||
instr = i;
|
||||
}
|
||||
}
|
||||
if(!trouve)
|
||||
flag_trt = 0; // aligner sur le bloc courant, idem instruction ou commentaire
|
||||
else if(instr == IN_PROG || instr == IN_LIBR || instr == IN_BACK || instr == IN_SUBR || instr == IN_PHDS || instr == IN_PIDS)
|
||||
flag_trt = 1;
|
||||
else if(instr == IN_ENDP || instr == IN_ENDS || instr == IN_ENDL)
|
||||
flag_trt = 2;
|
||||
else if(instr == IN_EXCE)
|
||||
flag_trt = 3;
|
||||
else
|
||||
flag_trt = 0;
|
||||
//
|
||||
if(flag_trt == 1)
|
||||
{
|
||||
// niveau +1 apres
|
||||
dynFmt(&e, &trav, &lig, 'R', ' ', lig.mLg + (niveau++) * TAB_COUNT);
|
||||
}
|
||||
else if(flag_trt == 2)
|
||||
{
|
||||
// niveau -1 avant
|
||||
if(niveau > 0)
|
||||
niveau--;
|
||||
dynFmt(&e, &trav, &lig, 'R', ' ', lig.mLg + niveau * TAB_COUNT);
|
||||
}
|
||||
else if(flag_trt == 3)
|
||||
{
|
||||
// niveau -1 local sans changement
|
||||
if(niveau > 0)
|
||||
dynFmt(&e, &trav, &lig, 'R', ' ', lig.mLg + (niveau-1) * TAB_COUNT);
|
||||
else
|
||||
dynFmt(&e, &trav, &lig,'R', ' ', lig.mLg + niveau * TAB_COUNT);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 0 : niveau courant
|
||||
dynFmt(&e, &trav, &lig, 'R', ' ', lig.mLg + niveau * TAB_COUNT);
|
||||
}
|
||||
// changer la ligne courante avec sa version formatee
|
||||
dynStoreSz(&e, f, numlig, DYN_NONE, lig.mPtr, lig.mLg, 10, DYN_NONE);
|
||||
}
|
||||
//
|
||||
if(sdlw)
|
||||
dynChange(&e, f, "\n", "\r\n", 0); /* remettre les sauts de ligne windows (0 = tous) */
|
||||
//
|
||||
dynFree(&e, &trav);
|
||||
dynFree(&e, &lig);
|
||||
}
|
||||
|
||||
static void formatage(Dynamic * s, Dynamic * f, int type)
|
||||
static void formatage(Dynamic * s, Dynamic * f)
|
||||
{
|
||||
// s : source ; f : source apres formatage, type : 1 w, 2 pcode
|
||||
if(type == 2)
|
||||
{
|
||||
formatage_asm(s, f);
|
||||
return;
|
||||
}
|
||||
// s : source ; f : source apres formatage
|
||||
//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 */
|
||||
@@ -411,7 +498,7 @@ int main(int argc, char * argv[])
|
||||
if(strcmp(argv[1], "-w") == 0)
|
||||
type = 1;
|
||||
else if(strcmp(argv[1], "-wa") == 0)
|
||||
type = 2; // formatage du pcode (fichier .wa) TODO
|
||||
type = 2; // formatage du pcode (fichier .wa)
|
||||
else
|
||||
{
|
||||
printf("Usage: lwf [-w|-wa] <source>\n");
|
||||
@@ -429,7 +516,11 @@ int main(int argc, char * argv[])
|
||||
}
|
||||
else
|
||||
{
|
||||
formatage(&source, &formate, type);
|
||||
if(type == 2)
|
||||
formatage_asm(&source, &formate);
|
||||
else
|
||||
formatage(&source, &formate);
|
||||
/* */
|
||||
printf("%s\n", formate.mPtr);
|
||||
if(dynWrite(&e, &formate, argv[argfic]) != OK)
|
||||
{
|
||||
|
||||
@@ -341,6 +341,21 @@ long tok2number(env * e, ent64s * numb, Dynamic * valex, Dynamic * tmp, Dynamic
|
||||
}
|
||||
}
|
||||
|
||||
long tok2negnumber(env * e, ent64s * numb, Dynamic * valex, Dynamic * tmp, Dynamic * encours)
|
||||
{
|
||||
dynField(e, valex, tmp, 1, norig(n), cFM, cVM, 1);
|
||||
hex2str(e, tmp, encours);
|
||||
*numb = - dynToNumber(e, encours); // negatif ici
|
||||
if(encours->mInternal != DYN_OK)
|
||||
return TERM_ERR; /* TODO erreur de conversion numerique */
|
||||
else
|
||||
{
|
||||
/* reconvertir en chaine dans <encours>, au bon format */
|
||||
dynLet(e, encours, Int64ToSz(e, *numb, TRUE, 0), DYN_LGNONE);
|
||||
return TERM_NUM;
|
||||
}
|
||||
}
|
||||
|
||||
long tok2string(env * e, Dynamic * valex, Dynamic * tmp, Dynamic * encours)
|
||||
{
|
||||
dynField(e, valex, tmp, 1, norig(n), cFM, cVM, 1);
|
||||
@@ -521,6 +536,16 @@ long terme(env * e, ent16 t, Dynamic * valex, Dynamic * tmp, Dynamic * encours)
|
||||
tok = nreg(n);
|
||||
return ret; /* encours contient le number */
|
||||
}
|
||||
/* ne marche pas sur des expressions du type : let x = x - 1 */
|
||||
//if(t == r.minus && (nreg(n+1) == r.numberint || nreg(n+1) == r.numberdec))
|
||||
//{
|
||||
// n++;
|
||||
// ent64s numb;
|
||||
// ret = tok2negnumber(e, &numb, valex, tmp, encours); /* token "n" */
|
||||
// n++;
|
||||
// tok = nreg(n);
|
||||
// return ret; /* encours contient le number */
|
||||
//}
|
||||
if(t == r.stringq || t == r.stringdq)
|
||||
{
|
||||
ret = tok2string(e, valex, tmp, encours); /* token "n" */
|
||||
@@ -1245,6 +1270,8 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
printf("Erreur ligne %dc%s : code trouve apres la fin du programme\n", numlig, tmp->mPtr);
|
||||
return DYN_ERR; /* TODO numeroter les erreurs */
|
||||
}
|
||||
if(trav.mLg > 0)
|
||||
dynConcat(e, resultat, &trav); /* edition ligne de source dans le code assembleur wa (mis en commentaire) */
|
||||
/* -------------------------------------------------------------------------------------- */
|
||||
if(numNiv == 0)
|
||||
{
|
||||
@@ -1652,7 +1679,7 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
/* -------------------------------------------------------------------------------------- */
|
||||
if(tok == r.foreach)
|
||||
{
|
||||
// TODO foreach num in 1,10,1 debut/fin/incr
|
||||
// foreach num in 1,10,1 debut/fin/incr / foreach var in dynamic / foreach var in hashtable
|
||||
n++;
|
||||
dynSetLen(e, &trav, 0);
|
||||
dynSetLen(e, &envers, 0);
|
||||
@@ -2970,6 +2997,60 @@ long parse(env * e, Dynamic * valex, Dynamic * resultat, Dynamic * tmp, Dynamic
|
||||
return DYN_ERR;
|
||||
}
|
||||
|
||||
void source_include_tree(env * e, Dynamic * meta, Dynamic * resultat, Dynamic * tmp)
|
||||
{
|
||||
/*
|
||||
(global) (local) (filename)
|
||||
; 1 >1 fichier: 1
|
||||
; 20 | >19 include: 2
|
||||
; 30 | | >10 include2: 3
|
||||
; 40 | | <11 2
|
||||
; 42 | <20 1
|
||||
; 44 | >21 include3: 2
|
||||
; 50 | <23 1
|
||||
; 60
|
||||
*/
|
||||
dynConcatSz(e, resultat, "; ----------------------------------------------\n", DYN_LGNONE);
|
||||
long precLevel = 0;
|
||||
long cpt, nb = dynDcount(e, meta, cVM, META_GLOBAL_LN, cFM);
|
||||
for(cpt = 1; cpt <= nb; cpt++)
|
||||
{
|
||||
long numGlobal = dynFieldAsNumber(e, meta, META_GLOBAL_LN, cpt, cFM, cVM);
|
||||
long numLocal = dynFieldAsNumber(e, meta, META_LOCAL_LN, cpt, cFM, cVM);
|
||||
long level = dynFieldAsNumber(e, meta, META_LEVEL, cpt, cFM, cVM);
|
||||
/* */
|
||||
dynFmtNumber(e, numGlobal, tmp, 'R', ' ', 8);
|
||||
dynConcatSz(e, resultat, "; ", 2);
|
||||
dynConcat(e, resultat, tmp);
|
||||
dynConcatSz(e, resultat, " ", 2);
|
||||
/* */
|
||||
dynField(e, meta, tmp, META_FILENAME, cpt, cFM, cVM, 1);
|
||||
/* */
|
||||
for(long i = 1; i < level; i++)
|
||||
dynConcatSz(e, resultat, "| ", 7);
|
||||
if(precLevel < level)
|
||||
{
|
||||
dynConcatSz(e, resultat, ">", 1);
|
||||
dynConcatSz(e, resultat, Int64ToSz(e, numLocal, FALSE, 0), DYN_LGNONE);
|
||||
dynConcatSz(e, resultat, " ", 1);
|
||||
dynConcat(e, resultat, tmp);
|
||||
dynConcatSz(e, resultat, ":\n", 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
dynConcatSz(e, resultat, "<", 1);
|
||||
dynConcatSz(e, resultat, Int64ToSz(e, numLocal, FALSE, 0), DYN_LGNONE);
|
||||
dynConcatSz(e, resultat, "\n", 1);
|
||||
}
|
||||
/* */
|
||||
precLevel = level;
|
||||
}
|
||||
/* FmtNumber(e, numlig, tmp, 'R', ' ', 8); // nb total de lignes, tous fichiers include confondus
|
||||
dynConcatSz(e, resultat, "; ", 2);
|
||||
dynConcat(e, resultat, tmp); */
|
||||
dynConcatSz(e, resultat, "; ----------------------------------------------\n", DYN_LGNONE);
|
||||
}
|
||||
|
||||
/* ***************************************************************************************************** */
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
@@ -3012,6 +3093,7 @@ int main(int argc, char * argv[])
|
||||
dynExtractField(&e, &arg, 4, &wsrc);
|
||||
dynExtractField(&e, &arg, 5, &wlib);
|
||||
dynExtractSubField(&e, &arg, 2, 1, &file); // file = fichier.w a compiler
|
||||
int arg_source = dynLocateSz(&e, &arg, ARG_SOURCE, cVM, 1, cFM); /* TRUE si option pour ajouter le source w dans le code assembleur genere */
|
||||
/* */
|
||||
for(;;)
|
||||
{
|
||||
@@ -3058,6 +3140,8 @@ int main(int argc, char * argv[])
|
||||
if(wsrc.mPtr[wsrc.mLg - 1] != e.path_sep[0])
|
||||
dynConcatSz(&e, &wsrc, e.path_sep, 1); // ajoute le / si absent a la fin
|
||||
dynStore(&e, &srcdbg, META_WSRC, DYN_NONE, &wsrc, cFM, DYN_NONE);
|
||||
if(arg_source)
|
||||
source_include_tree(&e, &srcdbg, &resultat, &tmp);
|
||||
//
|
||||
if(lire_regles_lex(&e, ®les, "wlex") != DYN_OK)
|
||||
{
|
||||
@@ -3078,6 +3162,21 @@ int main(int argc, char * argv[])
|
||||
{
|
||||
lex(&e, ®les, &ligne, &valex);
|
||||
/* */
|
||||
dynSetLen(&e, &trav, 0);
|
||||
if(arg_source)
|
||||
{
|
||||
long localnumlig;
|
||||
GetFile(&e, numlig + 1, &srcdbg, 1, &tmp, &localnumlig);
|
||||
/* ; <file>:<numlig_local> | <source> */
|
||||
dynConcatSz(&e, &trav, "; ", 2);
|
||||
dynConcat(&e, &trav, &tmp);
|
||||
dynConcatSz(&e, &trav, ":", 1);
|
||||
dynConcatSz(&e, &trav, Int64ToSz(&e, localnumlig, FALSE, 8), DYN_LGNONE);
|
||||
dynConcatSz(&e, &trav, " | ", 3);
|
||||
dynConcat(&e, &trav, &ligne);
|
||||
dynConcatSz(&e, &trav, "\n", 1);
|
||||
}
|
||||
/* */
|
||||
ret = parse(&e, &valex, &resultat, &tmp, &encours, &file);
|
||||
/* */
|
||||
if(ret == 0)
|
||||
|
||||
@@ -84,6 +84,17 @@ WAPIDECL char * raz_nom(env * e)
|
||||
return e->nom;
|
||||
}
|
||||
|
||||
WAPIDECL int nom_is(env * e, const char * s)
|
||||
{
|
||||
long lg = strlen(s);
|
||||
if(lg < 1 || lg > 24)
|
||||
return FALSE;
|
||||
ent64 f[3];
|
||||
f[0] = 0; f[1] = 0; f[2] = 0;
|
||||
strncpy((char *)f, s, lg);
|
||||
return (e->nom64[0] == f[0] && e->nom64[1] == f[1] && e->nom64[2] == f[2]);
|
||||
}
|
||||
|
||||
WAPIDECL int modFnIs(env * e, const char * fn, int lg)
|
||||
{
|
||||
// modifier l'endroit ou e->fn est mis a jour : verif fn64[0 1 2] est bien remis a zero avant la maj
|
||||
|
||||
@@ -29,6 +29,7 @@ WAPIDECL void init_env(env * e);
|
||||
|
||||
WAPIDECL char * copy_nom(env * e, const char * s);
|
||||
WAPIDECL char * raz_nom(env * e);
|
||||
WAPIDECL int nom_is(env * e, const char * s);
|
||||
WAPIDECL int modFnIs(env * e, const char * fn, int lg);
|
||||
|
||||
/* ************************************************************************** */
|
||||
|
||||
+84
@@ -234,6 +234,19 @@ WAPIDECL void hashtable_do(env * e, int action, var * varht, char * nom, var **
|
||||
}
|
||||
}
|
||||
|
||||
WAPIDECL void hashtable_deleteentry(env * e, var * varht, var * content)
|
||||
{
|
||||
/* cf. hashtable_do / DELETE */
|
||||
/* liberer la variable "pentry->content" ; si PARAM, libere la var pointee */
|
||||
var_free(e, content, TRUE);
|
||||
entry * pentry = (entry *)((pointeur)content - 3 * sizeof(ent64));
|
||||
pentry->nom1 = 0;
|
||||
pentry->nom2 = 0;
|
||||
pentry->nom3 = 0;
|
||||
pentry->content.type = 0;
|
||||
((entry *)varht->ptr)->content.ptr = NULL; /* securite si dans select/next */
|
||||
}
|
||||
|
||||
WAPIDECL var * hashtable_writeinfirstfreeentry(env * e, var * varht, char * nom, var * v)
|
||||
{
|
||||
if(varht == NULL || v == NULL || nom == NULL)
|
||||
@@ -515,4 +528,75 @@ WAPIDECL void hashtable_printdebug(env * e, var * varht, int detail)
|
||||
printf("taille totale=%lld, occupee=%lld (taux %lld%%), nb item=%lld\n", tot, occ, occ * 100 / tot, nb);
|
||||
}
|
||||
|
||||
WAPIDECL void hashtable_analyze(env * e, var * varht)
|
||||
{
|
||||
entry * pentry; /* pointe sur une entree */
|
||||
entry * pchain; /* pointe sur la premiere du groupe, servant au chainage */
|
||||
entry * pchain_first; /* premier bloc */
|
||||
ent64 groupe; /* groupe en cours */
|
||||
/* affiche le contenu d'une hashtable */
|
||||
if(varht == NULL)
|
||||
return;
|
||||
if(varht->type == VAR_PARAM)
|
||||
varht = (var *)varht->ptr; /* travailler avec la var pointee ! */
|
||||
if(varht == NULL)
|
||||
return;
|
||||
if(varht->type != VAR_HASHTABLE && varht->type != VAR_OBJECT)
|
||||
return;
|
||||
if(e->demon)
|
||||
{
|
||||
dynPrintfInt64(e, "hashtable analyze modulo=" PRINTF_MARK " separateur=", varht->modulo, 0);
|
||||
dynPrintfInt64(e, PRINTF_MARK "\n", varht->separateur, 0);
|
||||
}
|
||||
else
|
||||
printf("hashtable analyze modulo=%lld separateur=%lld\n", varht->modulo, varht->separateur);
|
||||
/* */
|
||||
ent64 nb_entry, occ_entry, nb_item_group, nb_group_1entry = 0, nb_empty_group = 0, nb_item = 0;
|
||||
ent64 occ_entry_min = varht->separateur/sizeof(entry), occ_entry_max = 0;
|
||||
ent64 nb_entry_min = (ent64)(-1), nb_entry_max = 0;
|
||||
ent64 nb_item_group_min = (ent64)(-1), nb_item_group_max = 0;
|
||||
/* */
|
||||
pchain = (entry *)varht->ptr;
|
||||
for(groupe = 0; groupe < varht->modulo; groupe++)
|
||||
{
|
||||
nb_entry = 0;
|
||||
nb_item_group = 0;
|
||||
pchain_first = pchain;
|
||||
do
|
||||
{
|
||||
nb_entry++;
|
||||
occ_entry = 0;
|
||||
pentry = pchain + 1; /* la premiere est toujours "occupee", utilisee en interne par la hashtable : ne pas mettre dans les stats */
|
||||
while((ent64)pentry - (ent64)pchain < varht->separateur)
|
||||
{
|
||||
if((pentry->nom1 | pentry->nom2 | pentry->nom3 | pentry->content.type) == 0)
|
||||
; /* entree libre */
|
||||
else
|
||||
{
|
||||
occ_entry++; /* entree occupee */
|
||||
nb_item_group++;
|
||||
nb_item++;
|
||||
}
|
||||
pentry++;
|
||||
}
|
||||
/* */
|
||||
if(occ_entry < occ_entry_min) occ_entry_min = occ_entry;
|
||||
if(occ_entry > occ_entry_max) occ_entry_max = occ_entry;
|
||||
/* chainage */
|
||||
} while ((pchain = (entry *)pchain->chainage_avant) != 0);
|
||||
pchain = (entry *)((ent64)pchain_first + varht->separateur);
|
||||
/* */
|
||||
if(nb_entry < nb_entry_min) nb_entry_min = nb_entry;
|
||||
if(nb_entry > nb_entry_max) nb_entry_max = nb_entry;
|
||||
if(nb_item_group < nb_item_group_min) nb_item_group_min = nb_item_group;
|
||||
if(nb_item_group > nb_item_group_max) nb_item_group_max = nb_item_group;
|
||||
if(nb_item_group == 0) nb_empty_group++;
|
||||
if(nb_entry == 1) nb_group_1entry++;
|
||||
}
|
||||
printf(" => nb bloc/group: min=%lld, max=%lld, 1bloc=%lld/%lld\n", nb_entry_min, nb_entry_max, nb_group_1entry, varht->modulo);
|
||||
printf(" => occ bloc: min=%lld, max=%lld (/%lld)\n", occ_entry_min, occ_entry_max, varht->separateur/sizeof(entry) - 1);
|
||||
printf(" => nb item/group: min=%lld, max=%lld, empty=%lld/%lld\n", nb_item_group_min, nb_item_group_max, nb_empty_group, varht->modulo);
|
||||
printf(" => nb item total=%lld\n", nb_item);
|
||||
}
|
||||
|
||||
/* ********************************************** */
|
||||
@@ -33,10 +33,12 @@ WAPIDECL void hashtable_clear(env *e, var * varht);
|
||||
WAPIDECL long hashtable_count(env *e, var * varht);
|
||||
WAPIDECL var * hashtable_lastitemwritten(var * varht);
|
||||
WAPIDECL var * hashtable_writeinfirstfreeentry(env * e, var * varht, char * nom, var * v);
|
||||
WAPIDECL void hashtable_deleteentry(env * e, var * varht, var * content);
|
||||
|
||||
WAPIDECL void hashtable_serialize(env * e, var * varht, var * out);
|
||||
|
||||
WAPIDECL void hashtable_printdebug(env * e, var * varht, int detail);
|
||||
WAPIDECL void hashtable_analyze(env * e, var * varht);
|
||||
|
||||
/* ********************************************** */
|
||||
#endif
|
||||
@@ -87,8 +87,8 @@ void dyn_printdebug(env * e, var * v, int detail)
|
||||
#include "lzw.h"
|
||||
|
||||
/* seules variables globales : celle indiquant un signal de terminaison du programme et celles pour basculer en mode debug on/off ! */
|
||||
octet ctx_env_kill = 0; /* mis a 255 si signal de terminaison */
|
||||
octet ctx_env_debug = 0; /* mis a 1 pour basculer le mode debug, uniquement dans instr_003 ! */
|
||||
volatile octet ctx_env_kill = 0; /* mis a 255 si signal de terminaison */
|
||||
volatile octet ctx_env_debug = 0; /* mis a 1 pour basculer le mode debug, uniquement dans instr_003 ! */
|
||||
|
||||
ent64 lap = 0; /* calcul temps du programme (hors init, alloc et free), en ms */
|
||||
|
||||
@@ -2140,16 +2140,6 @@ void ntostring(env * e)
|
||||
}
|
||||
}
|
||||
|
||||
void numstack_printdebug(env * e)
|
||||
{
|
||||
printf("num_stack read=%lld lgmax=%lld\n", e->num_stack.read, e->num_stack.lgmax);
|
||||
for(e->num_stack.write = e->num_stack.read; e->num_stack.write > 0; )
|
||||
{
|
||||
e->num_stack.write -= sizeof(number);
|
||||
printf(" %03lld > %lld\n", e->num_stack.write, *(number *)(e->num_stack.ptr + e->num_stack.write));
|
||||
}
|
||||
}
|
||||
|
||||
void numstrstack_printdebug(env * e)
|
||||
{
|
||||
numstr * pns;
|
||||
@@ -2277,7 +2267,8 @@ void instr_trace(env * e)
|
||||
numstrstack_printdebug(e);
|
||||
callstack_printdebug(e);
|
||||
hashtable_printdebug(e, &e->g, 1);
|
||||
/* TODO : env_printdebug */
|
||||
hashtable_analyze(e, &e->g);
|
||||
/* */
|
||||
printf("tmp_free %d tmp_cpt %d\n", e->tmp_free, e->tmp_cpt);
|
||||
printf("sizeof(env) : %ld\n", (long)sizeof(env));
|
||||
break;
|
||||
@@ -2392,18 +2383,12 @@ void instr_007(env * e)
|
||||
/* => mecanisme realise dans la fonction "decode" */
|
||||
}
|
||||
/* */
|
||||
//void NewProcess(env * e, var * prog); // TODO a enlever ensuite !!!!
|
||||
void instr_008(env * e)
|
||||
{
|
||||
/* PART */
|
||||
if(e->si > e->fin) { e->exception = EX_END; return; }
|
||||
e->part = lire8(e->si++);
|
||||
/* definit la region/partie du code en cours */
|
||||
/* TEST a enlever !!! TODO
|
||||
dynLet(e, &e->int_dynamic, "calc", 4);
|
||||
printf("part: %d\n", e->part);
|
||||
if(e->part == 255)
|
||||
NewProcess(e, &e->int_dynamic);*/
|
||||
}
|
||||
/* */
|
||||
void instr_009(env * e)
|
||||
@@ -2490,19 +2475,34 @@ void instr_010(env * e)
|
||||
}
|
||||
var_free(e, v, FALSE);
|
||||
/* si objet, memoriser dans _local le pointeur "this" et "parent" */
|
||||
if(e->ad_var_obj)
|
||||
if(e->ad_var_obj && e->ad_var_class)
|
||||
{
|
||||
var_init(e, &e->int_param, VAR_PARAM, 0, 0, (pointeur)e->ad_var_obj);
|
||||
v = &e->int_param;
|
||||
hashtable_do(e, HASH_WRITE, e->local, copy_nom(e, "this"), &v);
|
||||
hashtable_do(e, HASH_WRITE, e->local, copy_nom(e, GOV_THIS), &v);
|
||||
//
|
||||
var_init(e, &e->int_param, VAR_PARAM, 0, 0, (pointeur)e->ad_var_class);
|
||||
v = &e->int_param;
|
||||
hashtable_do(e, HASH_WRITE, e->local, copy_nom(e, "parent"), &v);
|
||||
//
|
||||
e->ad_var_obj = NULL;
|
||||
e->ad_var_class = NULL;
|
||||
e->ad_var = NULL;
|
||||
if(dynNext(e, e->ad_var_class, &e->tmp_dynamic, cFM) != -1)
|
||||
{
|
||||
hashtable_do(e, HASH_READ, &e->g, e->tmp_dynamic.mPtr, &e->ad_var);
|
||||
if(!e->ad_var || e->ad_var->type != VAR_OBJECT)
|
||||
e->ad_var = NULL;
|
||||
}
|
||||
if(!e->ad_var)
|
||||
{
|
||||
/* pas de classe parent (methode dans Base) : parent est une var NULL */
|
||||
e->v.type = VAR_NULL;
|
||||
v = &e->v;
|
||||
}
|
||||
else
|
||||
{
|
||||
var_init(e, &e->int_param, VAR_PARAM, 0, 0, (pointeur)e->ad_var);
|
||||
v = &e->int_param;
|
||||
}
|
||||
hashtable_do(e, HASH_WRITE, e->local, copy_nom(e, GOV_PARENT), &v);
|
||||
}
|
||||
e->ad_var_obj = NULL;
|
||||
e->ad_var_class = NULL;
|
||||
/* memoriser dans la hash locale : e->si e->si_except e->debut e->fin e->except_ex e->part */
|
||||
//var_init(e, v, VAR_DYNAMIC, 0, 0, NULL);
|
||||
v = &e->int_dynamic;
|
||||
@@ -2906,6 +2906,7 @@ void instr_028(env * e)
|
||||
{
|
||||
strncpy(e->nom, (char *)e->si, lg);
|
||||
e->si += lg;
|
||||
int parent = nom_is(e, GOV_PARENT);
|
||||
/* */
|
||||
if(e->mode_typeof && e->typeof_ == VAR_UNDECLARED) return; /* derniere var inconnue : mode typeof, continuer en attendant le PSHT */
|
||||
/* */
|
||||
@@ -2922,6 +2923,7 @@ void instr_028(env * e)
|
||||
}
|
||||
if(e->ad_var->type == VAR_PARAM)
|
||||
{
|
||||
e->ad_var_dele = e->ad_var; /* memoriser l'adresse de la var PARAM origine, en cas de DELE */
|
||||
if((e->ad_var = (var *)e->ad_var->ptr) == NULL) /* travailler avec la var pointee ! */
|
||||
{
|
||||
e->exception = EX_VARPARAM_KO;
|
||||
@@ -2932,7 +2934,10 @@ void instr_028(env * e)
|
||||
}
|
||||
return;
|
||||
}
|
||||
e->ad_var->etat = e->ad_var_dele->etat;
|
||||
}
|
||||
else
|
||||
e->ad_var_dele = NULL;
|
||||
/* */
|
||||
if(e->mode_typeof)
|
||||
{
|
||||
@@ -2949,6 +2954,27 @@ void instr_028(env * e)
|
||||
e->ad_var_hash = NULL;
|
||||
if(e->ad_var->type == VAR_HASHTABLE || e->ad_var->type == VAR_OBJECT)
|
||||
e->ad_var_hash = e->ad_var;
|
||||
e->ad_var_obj = NULL; // hash pour les membres (= objet) : this
|
||||
e->ad_var_class = NULL; // dynamic contenant _class de l'objet 'this'
|
||||
if(e->ad_var->type == VAR_OBJECT && !e->mode_typeof)
|
||||
{
|
||||
var * this = NULL;
|
||||
if(parent && e->local)
|
||||
{
|
||||
hashtable_do(e, HASH_READ, e->local, copy_nom(e, GOV_THIS), &this);
|
||||
if(this && this->type == VAR_PARAM)
|
||||
this = (var *)this->ptr;
|
||||
}
|
||||
/* lire _class mais pas en mode "typeof" */
|
||||
hashtable_do(e, HASH_READ, e->ad_var_hash, copy_nom(e, GUV_CLASS), &e->ad_var_class);
|
||||
if(e->ad_var_class)
|
||||
{
|
||||
if(parent && this)
|
||||
e->ad_var_obj = this; /* garder le point de depart initial */
|
||||
else
|
||||
e->ad_var_obj = e->ad_var_hash; /* le point de depart est bien un objet/classe */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* */
|
||||
@@ -3040,6 +3066,15 @@ void instr_029(env * e)
|
||||
else
|
||||
e->mode_typeof = FALSE; /* annuler le mode "typeof" si exception autre que var inconnue */
|
||||
}
|
||||
else if(e->ad_var_hash && e->ad_var_hash->type == VAR_OBJECT)
|
||||
{
|
||||
/* idem PVAR : si objet et pas en mode typeof, lire _class */
|
||||
e->ad_var_obj = NULL; // hash pour les membres (= objet) : this
|
||||
e->ad_var_class = NULL; // dynamic contenant _class de l'objet 'this'
|
||||
hashtable_do(e, HASH_READ, e->ad_var_hash, copy_nom(e, GUV_CLASS), &e->ad_var_class);
|
||||
if(e->ad_var_class)
|
||||
e->ad_var_obj = e->ad_var_hash; /* le point de depart est bien un objet/classe */
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -3409,30 +3444,20 @@ void instr_040(env * e)
|
||||
e->exception = EX_NOADVAR;
|
||||
return;
|
||||
}
|
||||
/* suppression variable "simple" (que PVAR : locale ou globale) => mis en VARNULL, idem declare */
|
||||
if(e->ad_var->type == VAR_PARAM)
|
||||
/* suppression variable "simple" (que PVAR : locale ou globale) => mis en VARNULL, idem declare
|
||||
la detection de VAR_PARAM (sur ad_var) a ete faite avant dans PVAR */
|
||||
if(e->ad_var->etat != NULL && e->ad_var_dele != NULL)
|
||||
{
|
||||
/* cas particulier si param sur hash : suppression reelle a faire (et PAS PVHD/PVID dans ce cas ici) */
|
||||
if(e->ad_var->ptr == NULL)
|
||||
{
|
||||
e->exception = EX_VARPARAM_KO;
|
||||
return;
|
||||
}
|
||||
if(e->ad_var->etat != NULL)
|
||||
{
|
||||
/* appartient a une hash : supprimer de la hash et RAZ pointeur (VAR_PARAM plus utilisable) */
|
||||
var_free(e, e->ad_var, TRUE);
|
||||
((var *)(e->ad_var->ptr))->type = 0;
|
||||
ent64 * ent = (ent64 *)(e->ad_var->ptr - 3 * sizeof(ent64));
|
||||
*ent++ = 0; *ent++ = 0; *ent = 0;
|
||||
e->ad_var->ptr = NULL;
|
||||
return;
|
||||
}
|
||||
/* n'appartient pas a une hash, variable "simple" : forcer la var a VAR_NULL */
|
||||
/* appartient a une hash : supprimer de la hash et RAZ pointeur (mais pas le nom ici...) */
|
||||
hashtable_deleteentry(e, (var *)e->ad_var->etat, e->ad_var); /* etat = hash, ad_var = var dans la hash */
|
||||
/* maj pour remplacer VAR_PARAM, inutilisable, par VAR_NULL */
|
||||
e->ad_var = e->ad_var_dele; /* VAR_PARAM */
|
||||
}
|
||||
/* n'appartient pas a une hash, variable "simple" : forcer la var a VAR_NULL */
|
||||
var * v = &e->v;
|
||||
v->type = VAR_NULL;
|
||||
var_let(e, e->ad_var, v, TRUE, FALSE);
|
||||
var_let(e, e->ad_var, v, FALSE, FALSE);
|
||||
}
|
||||
/* */
|
||||
void instr_041(env * e)
|
||||
@@ -3604,17 +3629,17 @@ void instr_043(env * e)
|
||||
/* */
|
||||
void instr_044(env * e)
|
||||
{
|
||||
/* INCL lg nom - onsolete, ne sert plus, a garder pour info dans le compile */
|
||||
if(e->si > e->fin) { e->exception = EX_END; return; }
|
||||
int lg = lire8(e->si++);
|
||||
if(e->si + lg - 1 > e->fin) { e->exception = EX_END; return; }
|
||||
//
|
||||
if(lg < 0 || lg > 24)
|
||||
e->exception = EX_LGNOM;
|
||||
else if(lg > 0)
|
||||
e->si += lg;
|
||||
return;
|
||||
}
|
||||
/* INCL lg nom - obsolete, ne sert plus, a garder pour info dans le compile */
|
||||
//if(e->si > e->fin) { e->exception = EX_END; return; }
|
||||
//int lg = lire8(e->si++);
|
||||
//if(e->si + lg - 1 > e->fin) { e->exception = EX_END; return; }
|
||||
////
|
||||
//if(lg < 0 || lg > 24)
|
||||
// e->exception = EX_LGNOM;
|
||||
//else if(lg > 0)
|
||||
// e->si += lg;
|
||||
//return;
|
||||
}//
|
||||
/* */
|
||||
void instr_045(env * e)
|
||||
{
|
||||
@@ -4090,6 +4115,15 @@ void instr_060(env * e)
|
||||
else
|
||||
e->mode_typeof = FALSE; /* annuler le mode "typeof" si exception autre que var inconnue */
|
||||
}
|
||||
else if(e->ad_var_hash && e->ad_var_hash->type == VAR_OBJECT)
|
||||
{
|
||||
/* idem PVAR : si objet et pas en mode typeof, lire _class */
|
||||
e->ad_var_obj = NULL; // hash pour les membres (= objet) : this
|
||||
e->ad_var_class = NULL; // dynamic contenant _class de l'objet 'this'
|
||||
hashtable_do(e, HASH_READ, e->ad_var_hash, copy_nom(e, GUV_CLASS), &e->ad_var_class);
|
||||
if(e->ad_var_class)
|
||||
e->ad_var_obj = e->ad_var_hash; /* le point de depart est bien un objet/classe */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4147,6 +4181,19 @@ void instr_063(env * e)
|
||||
e->ad_var->ptr[e->ad_var->mLg++] = c;
|
||||
e->ad_var->ptr[e->ad_var->mLg] = 0;
|
||||
}
|
||||
/* detection erreur dans le cas ou le process est lance par un autre process W => le partage de terminal n'est pas possible sous unix dans ce cas (process cree independant) */
|
||||
if(c == EOF)
|
||||
{
|
||||
int err = errno;
|
||||
int std_erreur = ferror(stdin);
|
||||
clearerr(stdin); /* sinon l'erreur reste lors des getchar() suivants */
|
||||
if(std_erreur && err == EIO) /* si pas EIO sans doute signal (ctrl-c...) */
|
||||
{
|
||||
/* erreur, terminal non disponible, pas une fin de saisie/flux */
|
||||
e->exception = EX_INPUT_TTY;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* */
|
||||
void instr_064(env * e)
|
||||
@@ -4629,7 +4676,7 @@ void instr_077(env * e)
|
||||
/* PHDO */
|
||||
/* PHDO <nom> : a partir de <e->ad_var_hash> recherche <nom> (classe + meres) et ad finale de la sub dans <e->ad_var> */
|
||||
if(e->si > e->fin) { e->exception = EX_END; return; }
|
||||
int pos = 2, lg = lire8(e->si++);
|
||||
int lg = lire8(e->si++);
|
||||
if(e->si + lg - 1 > e->fin) { e->exception = EX_END; return; }
|
||||
//
|
||||
if(lg < 1 || lg > 24)
|
||||
@@ -4637,15 +4684,6 @@ void instr_077(env * e)
|
||||
e->exception = EX_LGNOM;
|
||||
return;
|
||||
}
|
||||
var * class = NULL;
|
||||
e->ad_var_obj = NULL; // hash pour les membres (= objet) : this
|
||||
e->ad_var_class = NULL; // hash pour la classe de l'objet : parent (TODO)
|
||||
if(e->ad_var_hash != NULL)
|
||||
if(e->ad_var_hash->type == VAR_OBJECT)
|
||||
{
|
||||
e->ad_var_obj = e->ad_var_hash;
|
||||
hashtable_do(e, HASH_READ, e->ad_var_hash, copy_nom(e, GUV_CLASS), &class);
|
||||
}
|
||||
e->nom64[0] = 0;
|
||||
e->nom64[1] = 0;
|
||||
e->nom64[2] = 0;
|
||||
@@ -4656,7 +4694,7 @@ void instr_077(env * e)
|
||||
e->exception = EX_NOADVAR;
|
||||
return;
|
||||
}
|
||||
if(!class)
|
||||
if( !e->ad_var_obj || !e->ad_var_class)
|
||||
{
|
||||
// hash simple : chercher la sub
|
||||
hashtable_do(e, HASH_READ, e->ad_var_hash, e->nom, &e->ad_var);
|
||||
@@ -4664,46 +4702,29 @@ void instr_077(env * e)
|
||||
e->exception = EX_NAVAR;
|
||||
return;
|
||||
}
|
||||
// classe : chercher dans l'objet courant, puis les classes (doit fonctionner en mode type "classe static")
|
||||
hashtable_do(e, HASH_READ, e->ad_var_hash, e->nom, &e->ad_var);
|
||||
for(; !e->ad_var; pos++)
|
||||
// objet/classe : chercher dans l'objet courant, puis les classes (doit fonctionner en mode type "classe static")
|
||||
/* e->ad_var_class contient _class de l'obj */
|
||||
dynBegin(e, e->ad_var_class);
|
||||
memset(e->tmp_dynamic.mPtr, 0, 25); /* sinon HASH_READ ko */
|
||||
while(dynNext(e, e->ad_var_class, &e->tmp_dynamic, cFM) != -1)
|
||||
{
|
||||
memset(e->int_dynamic.mPtr, 0, 25);
|
||||
dynField(e, class, &e->int_dynamic, pos, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
if(e->int_dynamic.mLg <= 0)
|
||||
break; // plus de classe dans lesquelles regarder
|
||||
//
|
||||
hashtable_do(e, HASH_READ, &e->g, e->int_dynamic.mPtr, &e->ad_var_hash);
|
||||
if(!e->ad_var_hash)
|
||||
break; // classe non trouvee
|
||||
//
|
||||
hashtable_do(e, HASH_READ, e->ad_var_hash, e->nom, &e->ad_var);
|
||||
}
|
||||
if(e->ad_var)
|
||||
{
|
||||
if(e->ad_var->type != VAR_SUBROUTINE)
|
||||
e->exception = EX_NAVAR;
|
||||
if(e->tmp_dynamic.mPtr[0] == '0')
|
||||
e->ad_var_hash = e->ad_var_obj; /* l'oid 0xxxx n'est pas connu comme tel dans e->g */
|
||||
else
|
||||
{
|
||||
// maj pour parent
|
||||
if(*class->mPtr == '0')
|
||||
pos = 3; // this pointe sur un objet : mettre la classe mere de la classe de l'objet
|
||||
else
|
||||
pos = 2; // this pointe sur une classe : prendre sa mere directe
|
||||
memset(e->int_dynamic.mPtr, 0, 25);
|
||||
dynField(e, class, &e->int_dynamic, pos, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
if(e->int_dynamic.mLg <= 0)
|
||||
e->exception = EX_NAVAR;
|
||||
else
|
||||
{
|
||||
hashtable_do(e, HASH_READ, &e->g, e->int_dynamic.mPtr, &e->ad_var_class);
|
||||
if(!e->ad_var_class)
|
||||
e->exception = EX_NAVAR;
|
||||
}
|
||||
}
|
||||
hashtable_do(e, HASH_READ, &e->g, e->tmp_dynamic.mPtr, &e->ad_var_hash);
|
||||
if(!e->ad_var_hash || e->ad_var_hash->type != VAR_OBJECT)
|
||||
break; /* objet/classe non trouve ou pas objet : inutile de continuer */
|
||||
memset(e->tmp_dynamic.mPtr, 0, 25); /* sinon HASH_READ ko */
|
||||
/* */
|
||||
hashtable_do(e, HASH_READ, e->ad_var_hash, e->nom, &e->ad_var);
|
||||
if(!e->ad_var)
|
||||
continue; /* sub non trouve : chercher dans la classe mere suivante */
|
||||
if(e->ad_var->type != VAR_SUBROUTINE)
|
||||
break; /* pas une sub : exception, inutile de continuer */
|
||||
/* trouve, ad_var pointe sur la sub voulue */
|
||||
return;
|
||||
}
|
||||
else
|
||||
e->exception = EX_NAVAR;
|
||||
e->exception = EX_NAVAR;
|
||||
}
|
||||
/* */
|
||||
void instr_078(env * e)
|
||||
@@ -4711,7 +4732,7 @@ void instr_078(env * e)
|
||||
/* PIDO */
|
||||
/* PIDO <nom> : a partir de <e->ad_var_hash> recherche <nom> (avec indirection) (classe + meres) et ad finale de la sub dans <e->ad_var> */
|
||||
if(e->si > e->fin) { e->exception = EX_END; return; }
|
||||
int pos = 2, lg = lire8(e->si++);
|
||||
int lg = lire8(e->si++);
|
||||
if(e->si + lg - 1 > e->fin) { e->exception = EX_END; return; }
|
||||
//
|
||||
if(lg < 1 || lg > 24)
|
||||
@@ -4719,15 +4740,6 @@ void instr_078(env * e)
|
||||
e->exception = EX_LGNOM;
|
||||
return;
|
||||
}
|
||||
var * class = NULL;
|
||||
e->ad_var_obj = NULL; // hash pour les membres (= objet) : this
|
||||
e->ad_var_class = NULL; // hash pour la classe de l'objet : parent (TODO)
|
||||
if(e->ad_var_hash != NULL)
|
||||
if(e->ad_var_hash->type == VAR_OBJECT)
|
||||
{
|
||||
e->ad_var_obj = e->ad_var_hash;
|
||||
hashtable_do(e, HASH_READ, e->ad_var_hash, copy_nom(e, GUV_CLASS), &class);
|
||||
}
|
||||
e->nom64[0] = 0;
|
||||
e->nom64[1] = 0;
|
||||
e->nom64[2] = 0;
|
||||
@@ -4763,7 +4775,7 @@ void instr_078(env * e)
|
||||
e->nom64[2] = 0;
|
||||
strncpy(e->nom, v->mPtr, v->lg);
|
||||
//
|
||||
if(!class)
|
||||
if( !e->ad_var_obj || !e->ad_var_class)
|
||||
{
|
||||
// hash simple : chercher la sub
|
||||
hashtable_do(e, HASH_READ, e->ad_var_hash, e->nom, &e->ad_var);
|
||||
@@ -4771,46 +4783,29 @@ void instr_078(env * e)
|
||||
e->exception = EX_NAVAR;
|
||||
return;
|
||||
}
|
||||
// classe : chercher dans l'objet courant, puis les classes (doit fonctionner en mode type "classe static")
|
||||
hashtable_do(e, HASH_READ, e->ad_var_hash, e->nom, &e->ad_var);
|
||||
for(; !e->ad_var; pos++)
|
||||
// objet/classe : chercher dans l'objet courant, puis les classes (doit fonctionner en mode type "classe static")
|
||||
/* e->ad_var_class contient _class de l'obj */
|
||||
dynBegin(e, e->ad_var_class);
|
||||
memset(e->tmp_dynamic.mPtr, 0, 25); /* sinon HASH_READ ko */
|
||||
while(dynNext(e, e->ad_var_class, &e->tmp_dynamic, cFM) != -1)
|
||||
{
|
||||
memset(e->int_dynamic.mPtr, 0, 25);
|
||||
dynField(e, class, &e->int_dynamic, pos, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
if(e->int_dynamic.mLg <= 0)
|
||||
break; // plus de classe dans lesquelles regarder
|
||||
//
|
||||
hashtable_do(e, HASH_READ, &e->g, e->int_dynamic.mPtr, &e->ad_var_hash);
|
||||
if(!e->ad_var_hash)
|
||||
break; // classe non trouvee
|
||||
//
|
||||
hashtable_do(e, HASH_READ, e->ad_var_hash, e->nom, &e->ad_var);
|
||||
}
|
||||
if(e->ad_var)
|
||||
{
|
||||
if(e->ad_var->type != VAR_SUBROUTINE)
|
||||
e->exception = EX_NAVAR;
|
||||
if(e->tmp_dynamic.mPtr[0] == '0')
|
||||
e->ad_var_hash = e->ad_var_obj; /* l'oid 0xxxx n'est pas connu comme tel dans e->g */
|
||||
else
|
||||
{
|
||||
// maj pour parent
|
||||
if(*class->mPtr == '0')
|
||||
pos = 3; // this pointe sur un objet : mettre la classe mere de la classe de l'objet
|
||||
else
|
||||
pos = 2; // this pointe sur une classe : prendre sa mere directe
|
||||
memset(e->int_dynamic.mPtr, 0, 25);
|
||||
dynField(e, class, &e->int_dynamic, pos, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
if(e->int_dynamic.mLg <= 0)
|
||||
e->exception = EX_NAVAR;
|
||||
else
|
||||
{
|
||||
hashtable_do(e, HASH_READ, &e->g, e->int_dynamic.mPtr, &e->ad_var_class);
|
||||
if(!e->ad_var_class)
|
||||
e->exception = EX_NAVAR;
|
||||
}
|
||||
}
|
||||
hashtable_do(e, HASH_READ, &e->g, e->tmp_dynamic.mPtr, &e->ad_var_hash);
|
||||
if(!e->ad_var_hash || e->ad_var_hash->type != VAR_OBJECT)
|
||||
break; /* objet/classe non trouve ou pas objet : inutile de continuer */
|
||||
memset(e->tmp_dynamic.mPtr, 0, 25); /* sinon HASH_READ ko */
|
||||
/* */
|
||||
hashtable_do(e, HASH_READ, e->ad_var_hash, e->nom, &e->ad_var);
|
||||
if(!e->ad_var)
|
||||
continue; /* sub non trouve : chercher dans la classe mere suivante */
|
||||
if(e->ad_var->type != VAR_SUBROUTINE)
|
||||
break; /* pas une sub : exception, inutile de continuer */
|
||||
/* trouve, ad_var pointe sur la sub voulue */
|
||||
return;
|
||||
}
|
||||
else
|
||||
e->exception = EX_NAVAR;
|
||||
e->exception = EX_NAVAR;
|
||||
}
|
||||
/* */
|
||||
void instr_079(env * e)
|
||||
@@ -6406,12 +6401,6 @@ void instr_253(env * e)
|
||||
else
|
||||
{
|
||||
/* dans le demon ici */
|
||||
// A ESSAYER
|
||||
chdir("/"); // permet de ne pas bloquer un filesystem avec ce process
|
||||
setsid(); // nouvelle session
|
||||
//for(int i = 0;i < FOPEN_MAX; i++)
|
||||
// close(i); // ferme les fichiers ouverts par le pere
|
||||
// autre possibilite : rediriger avec dup2 le fichiers 0 1 2 vers /dev/null
|
||||
e->trace = 0;
|
||||
e->demon = 1;
|
||||
}
|
||||
@@ -6699,7 +6688,7 @@ void (*instr[256])(env * e) = {instr_000,instr_001,instr_002,instr_003,instr_004
|
||||
; 085 55 DCOF 1 dcount(var)
|
||||
; 086 56 FIEL 1 fonction "field" : chercher dans la chaine pile1, avec le caractere pile2 (1er car), le champ no pile3, depile + met le resultat
|
||||
; 087 57 INDX 1 index(var, search, occ)
|
||||
; 088 58 SRCH 1 search(var) search string in field
|
||||
; 088 58 SRCH 1 search(var, string) search string in field
|
||||
; 089 59 CHNG 1 change(var, cherche, remplace)
|
||||
; 090 5A FMTA 1 format "alignment" (left right center)
|
||||
; 091 5B INSE 1 insert(var, chaine, field)
|
||||
@@ -6714,7 +6703,7 @@ void (*instr[256])(env * e) = {instr_000,instr_001,instr_002,instr_003,instr_004
|
||||
; 100 64 DCOS 1 dcount(var, numchamp)
|
||||
; 101 65 FMTT 1 format "trim"
|
||||
; 102 66 FMTS 1 format "surround"
|
||||
; 103 67 SCHS 1 search(var, numField) search string in subfield of the field given
|
||||
; 103 67 SCHS 1 search(var, string, numField) search string in subfield of the numField given
|
||||
; 104 68 INSS 1 insert(var, chaine, field, subfield)
|
||||
; 105 69 REMS 1 remove(var, field, subfield)
|
||||
; 106 6A DEXH lg nom 2+lg ad_var_hash.nom<pile1, pile2> = pile3 (suite PHDE)
|
||||
@@ -6736,8 +6725,8 @@ void (*instr[256])(env * e) = {instr_000,instr_001,instr_002,instr_003,instr_004
|
||||
; 122 7A HCOU 1 idem PVAH/PVAI mais renvoi le nombre d'element de la hash/objet en cours (dans ad_var = e->int_number)
|
||||
; 123 7B PVHD lg nom 2+lg enchainement PVAH/PVAI, en dernier supprime dans la hash <ad_var_hash> la var <nom> (idem DELE mais avec suppression)
|
||||
; 124 7C PVID lg nom 2+lg enchainement PVAH/PVAI, en dernier supprime dans la hash <ad_var_hash> la var <nom> (avec indirection) (idem DELE mais avec suppression)
|
||||
; 125 7D SSRC 1 sortedsearch(var) search sorted string in field
|
||||
; 126 7E SSCS 1 search(var, numField) search sorted string in subfield of the field given
|
||||
; 125 7D SSRC 1 sortedsearch(var, string, sens) search sorted string in field
|
||||
; 126 7E SSCS 1 sortedsearch(var, string, numField, sens) search sorted string in subfield of the numField given
|
||||
; 127 7F CPHH 1 idem CPHA mais avec flag positionne indiquant l'empilage d'une var appartenant a une hash
|
||||
; 128 80 CPHN lg nom 2+lg empile dans la call stack la var ad_var en nommant le parametre <nom> (idem CPAN) et avec flag positionne indiquant l'empilage d'une var appartenant a une hash
|
||||
;
|
||||
@@ -6802,6 +6791,7 @@ void trt_sig(int sig)
|
||||
ctx_env_debug = 1;
|
||||
return;
|
||||
case SIGTERM:
|
||||
case SIGHUP:
|
||||
case SIGINT:
|
||||
/* forcer l'arret du process */
|
||||
ctx_env_kill = IN_ENDP; /* 255 sinon ko */
|
||||
@@ -6816,7 +6806,7 @@ void init_sig()
|
||||
sa.sa_flags = 0; /* Pas de SA_RESTART */
|
||||
sigemptyset(&sa.sa_mask);
|
||||
|
||||
signal(SIGHUP, trt_sig); /* 1 */
|
||||
sigaction(SIGHUP, &sa, NULL); /* 1 */
|
||||
sigaction(SIGINT, &sa, NULL); /* 2 */
|
||||
signal(SIGQUIT, trt_sig); /* 3 */
|
||||
signal(SIGILL, trt_sig); /* 4 */
|
||||
@@ -6834,12 +6824,12 @@ void init_sig()
|
||||
signal(SIGUSR1, trt_sig); /* 16 signal utilisateur 1 */
|
||||
signal(SIGUSR2, trt_sig); /* 17 signal utilisateur 2 */
|
||||
signal(SIGCHLD, SIG_IGN); /* 18 ATTENTION : permet de ne pas devoir lire l'etat des fils avec wait() !! */
|
||||
signal(SIGCLD, trt_sig); /* 18 */
|
||||
/* signal(SIGCLD, trt_sig); */ /* 18 signal duplique */
|
||||
signal(SIGPWR, trt_sig); /* 19 */
|
||||
signal(SIGVTALRM, trt_sig); /* 20 */
|
||||
signal(SIGPROF, trt_sig); /* 21 */
|
||||
signal(SIGIO, trt_sig); /* 22 */
|
||||
signal(SIGPOLL, trt_sig); /* 22 */
|
||||
/* signal(SIGPOLL, trt_sig); */ /* 22 signal duplique */
|
||||
signal(SIGWINCH, trt_sig);/* 23 */
|
||||
/* signal(SIGSTOP, trt_sig); */ /* 24 : ne se detourne pas */
|
||||
signal(SIGTSTP, trt_sig); /* 25 */
|
||||
@@ -6943,100 +6933,6 @@ void free_sig()
|
||||
|
||||
#endif
|
||||
|
||||
// EN COURS - mettre dans processMod => non ! car depuis dlsym, risques avec les libs appeles entre fork et execve !
|
||||
void NewProcess(env * e, var * prog)
|
||||
{
|
||||
// <prog> de type DYNAMIC : programme w et ses parametres en VM
|
||||
if(prog->type != VAR_DYNAMIC)
|
||||
{
|
||||
e->exception = EX_NAVAR;
|
||||
return;
|
||||
}
|
||||
var * v;
|
||||
hashtable_do(e, HASH_READ, &e->g, copy_nom(e, GUV_WARGV), &v);
|
||||
if(v == NULL) ; /* TODO exception ?! */
|
||||
/* */
|
||||
dynIns(e, prog, 1, 1, v, cFM, cVM); /* tester si prog contient un prog w valide ! et ses parametres en MV ! */
|
||||
dynField(e, v, &e->tmp_dynamic, 1, 1, cFM, cVM, 1);
|
||||
// Prendre en compte si process en cours est PROG ou BACK (e->demon) + bool en param pour choisir PROG=>BACK (par defaut PROG=>PROG et BACK=>BACK ; BACK=>PROG non autorise)
|
||||
// ATTENTION : depend du programme lance : si BACK, pas besoin forcement de refaire fork/CreateProcess
|
||||
#ifndef WINLIB
|
||||
long pid;
|
||||
if((pid = fork()) > 0)
|
||||
{
|
||||
return; // le pere ne fait rien de plus, apres le lancement du fils
|
||||
}
|
||||
else if(pid < 0)
|
||||
{
|
||||
e->exception = EX_CHILD_FORK;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* eventuellement a tester :
|
||||
if (pid == 0) {
|
||||
setpgid(0, 0);
|
||||
pause(); // attend que le père donne le terminal
|
||||
execvp(...);
|
||||
}
|
||||
|
||||
else {
|
||||
setpgid(pid, pid);
|
||||
tcsetpgrp(STDIN_FILENO, pid);
|
||||
kill(pid, SIGCONT); // libère le fils
|
||||
exit(0);
|
||||
}
|
||||
*/
|
||||
/* dans le fils ici A essayer */
|
||||
//chdir("/"); // permet de ne pas bloquer un filesystem avec ce process mais attention au path qaudn execvp !
|
||||
//setsid(); /* bloque le meme terminal/console */
|
||||
//
|
||||
// si socket retournee par accept, reste ouverte dans le fils : juste envoyer le descripteur
|
||||
// Appel de shm_lib : newProcessShmWriter()
|
||||
// TODO
|
||||
//
|
||||
printf("avant execvp: %s (%s)\n", e->tmp_dynamic.mPtr, prog->mPtr); // mais param ko dans execvp !
|
||||
execvp(e->tmp_dynamic.mPtr, dynToTabPtr(e, prog, cVM)); // autre programme, mais garder les autres params de argv, avant le nom du prog wp
|
||||
// TODO gestion console idem windows !!
|
||||
/* si on arrive ici : execvp n'a pas fonctionne : erreur dans le fils : sortie immediate */
|
||||
printf("erreur execvp: %d\n", errno);
|
||||
exit(-1);
|
||||
}
|
||||
#else
|
||||
STARTUPINFO si = { sizeof(si) };
|
||||
PROCESS_INFORMATION pi;
|
||||
// Lancer une nouvelle instance
|
||||
dynReplace(e, prog, cVM, ' ');
|
||||
printf("exec win:%s\n", prog->mPtr); // ok
|
||||
//if (CreateProcess(NULL, v->mPtr, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi))
|
||||
if (CreateProcess(NULL, prog->mPtr, NULL, NULL, FALSE, e->demon ? CREATE_NO_WINDOW : CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) // CREATE_NEW_CONSOLE ou 0 pour garder la console courante, CREATE_NO_WINDOW phantom (ou DETACHED_PROCESS ?!)
|
||||
{
|
||||
// si socket retournee par accept, faire un DuplicateHandle et envoyer le descripteur de la socket
|
||||
//HANDLE clientSocket = NULL;
|
||||
//HANDLE dupSocket; // a caster en SOCKET ensuite
|
||||
//if( ! DuplicateHandle(GetCurrentProcess(), clientSocket, pi.hProcess, &dupSocket, 0, FALSE, DUPLICATE_SAME_ACCESS)) // le handle dupliqué n’a pas besoin d’être héritable
|
||||
//{
|
||||
// erreur
|
||||
//}
|
||||
// aussi : WSADuplicateSocket puis WSASocket
|
||||
// Appel de shm_lib : newProcessShmWriter()
|
||||
// TODO
|
||||
// Lancer l'execution du process
|
||||
//ResumeThread(pi.hThread);
|
||||
// Fermer les handles inutiles
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
//printf("Lancement en tache de fond du process, pid %d\n", pi.dwProcessId);
|
||||
}
|
||||
else
|
||||
{
|
||||
e->exception = EX_CHILD_EXEC;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* si fork : avant exec :
|
||||
fcntl(sock, F_SETFD, 0); // enlève FD_CLOEXEC, par defaut mettre 1 aux sockets ouverts
|
||||
*/
|
||||
/*
|
||||
int unix_sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
|
||||
@@ -7187,7 +7083,6 @@ int CreateContext(env ** ctx, int useSignal, int argc, char *argv[])
|
||||
var_init(e, &e->int_dynamic, VAR_DYNAMIC, 0, 0, NULL);
|
||||
var_init(e, &e->tmp_dynamic, VAR_DYNAMIC, 0, 0, NULL);
|
||||
var_init(e, &e->int_number, VAR_NUMBER, 0, 0, NULL);
|
||||
var_init(e, &e->num_stack, VAR_BUFFER, 0, 0, NULL);
|
||||
var_init(e, &e->numstr_stack, VAR_BUFFER, 0, 0, NULL);
|
||||
var_init(e, &e->call_stack, VAR_BUFFER, 0, 0, NULL);
|
||||
var_init(e, &e->int_hash, VAR_HASHTABLE, 7, 8, NULL);
|
||||
@@ -7204,7 +7099,7 @@ int CreateContext(env ** ctx, int useSignal, int argc, char *argv[])
|
||||
/* verif alloc mem ok */
|
||||
if(e->g.type == VAR_NULL || e->int_dynamic.type == VAR_NULL || e->int_number.type == VAR_NULL ||
|
||||
e->numstr_stack.type == VAR_NULL || e->int_hash.type == VAR_NULL || e->tmp_dynamic.type == VAR_NULL ||
|
||||
e->num_stack.type == VAR_NULL || e->call_stack.type == VAR_NULL || e->debugbrkpoint.type == VAR_NULL ||
|
||||
e->call_stack.type == VAR_NULL || e->debugbrkpoint.type == VAR_NULL ||
|
||||
e->debugreglelex.type == VAR_NULL || e->debugcmd.type == VAR_NULL || e->debugvalex.type == VAR_NULL ||
|
||||
e->printf.type == VAR_NULL)
|
||||
return (e->except_ex = EX_MEM);
|
||||
@@ -7335,7 +7230,6 @@ void FreeContext(env * ctx)
|
||||
var_free(ctx, &ctx->int_dynamic, TRUE);
|
||||
var_free(ctx, &ctx->tmp_dynamic, TRUE);
|
||||
var_free(ctx, &ctx->int_number, TRUE);
|
||||
var_free(ctx, &ctx->num_stack, TRUE);
|
||||
var_free(ctx, &ctx->call_stack, TRUE);
|
||||
var_free(ctx, &ctx->numstr_stack, TRUE);
|
||||
/* ne pas suivre le ptr si <v> ou <int_param> sont des param, donc ptr vers une autre variable, car la pointee a ete desallouee par ailleurs (provoque un bug sous Windows) */
|
||||
@@ -7591,6 +7485,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
ent64 cr;
|
||||
env * ctx_env = NULL;
|
||||
octet demon = 0;
|
||||
/* avis de licence */
|
||||
printf("W language Copyright 2024-2026 lanisys.fr\n");
|
||||
printf("This program comes with ABSOLUTELY NO WARRANTY;\nThis is free software, and you are welcome to redistribute it\nunder certain conditions (GPL-3.0-or-later)\n\n");
|
||||
@@ -7626,21 +7521,25 @@ int main(int argc, char *argv[])
|
||||
A l'init, choix du nom de la CALL externe, 1 seul param, hashtable (!?). Definir le pseudo PROG...
|
||||
*/
|
||||
cr = ctx_env->except_ex;
|
||||
demon = ctx_env->demon;
|
||||
}
|
||||
/* */
|
||||
FreeContext(ctx_env);
|
||||
/* */
|
||||
if((cr >> 8) != 0)
|
||||
cr = EX_EXCEPTNUM;
|
||||
printf("\nexit:%llu ", cr);
|
||||
if(cr > 0 && cr <= EXNB)
|
||||
printf("%s ",strerr[cr - 1]);
|
||||
if(lap < 1500)
|
||||
printf("(%llu µs)\n", lap);
|
||||
else if(lap < 1500000)
|
||||
printf("(%llu ms)\n", lap/1000);
|
||||
else
|
||||
printf("(%llu s)\n", lap/1000000);
|
||||
if(!demon)
|
||||
{
|
||||
printf("\nexit:%llu ", cr);
|
||||
if(cr > 0 && cr <= EXNB)
|
||||
printf("%s ",strerr[cr - 1]);
|
||||
if(lap < 1500)
|
||||
printf("(%llu µs)\n", lap);
|
||||
else if(lap < 1500000)
|
||||
printf("(%llu ms)\n", lap/1000);
|
||||
else
|
||||
printf("(%llu s)\n", lap/1000000);
|
||||
}
|
||||
exit(cr);
|
||||
}
|
||||
|
||||
@@ -7679,8 +7578,8 @@ int main(int argc, char *argv[])
|
||||
formule : _srcdbg< (e->bin_indice - 1) * META_NB + 1 > donne le premier attribut pour le source concerne
|
||||
|
||||
_class => pour une variable de type objet/classe, variable dynamic ecrite dans la hash de l'objet/classe contenant l'enchainement d'heritage des classes et info si objet instancie
|
||||
objet : oid FM classe FM classe heritee FM ... FM Base
|
||||
classe: classe FM classe heritee FM ... FM Base
|
||||
objet : oid FM classe FM classe heritee FM ... FM 'Base' (avec oid = '0xxxxxx')
|
||||
classe: classe FM classe heritee FM ... FM 'Base'
|
||||
|
||||
_tmpxxx => de _tmp1 a _tmp254 : variables temporaires de type dynamic, creees une fois, servant dans les expressions
|
||||
|
||||
|
||||
@@ -256,12 +256,12 @@ enum {
|
||||
EX_VARPARAM_KO = 44, /* la variable passee en parametre n'est plus presente en memoire */
|
||||
EX_PARAM_NOTFOUND = 45, /* la variable passee en parametre est affectee a un nom de parametre inconnu de la sub */
|
||||
EX_NUMOVF = 46, /* depassement de capacite lors d'un calcul */
|
||||
EXNB = 46 /* MEMO !!!! */
|
||||
EX_INPUT_TTY = 47, /* terminal indisponible, lecture entree standard impossible */
|
||||
EXNB = 47 /* MEMO !!!! */
|
||||
};
|
||||
|
||||
typedef struct env {
|
||||
/* environnement global */
|
||||
var num_stack; /* buffers qui contiennent les 2 piles : nombre et appel */
|
||||
var call_stack; /* mettre les adresses des params dans la call_stack => au debut de la fn, tout est depile ! */
|
||||
var numstr_stack; /* pile contenant number et string */
|
||||
var g; /* hashtable qui contient toutes les variables "globales" (begin/end) + objets + vars systemes + modules */
|
||||
@@ -281,8 +281,9 @@ typedef struct env {
|
||||
var * ad_var; /* permet de recuperer l'adresse d'une var entre 2 instructions */
|
||||
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 */
|
||||
var * ad_var_class; /* donne l'adresse de la var dynamic _class de l'objet ad_var_obj */
|
||||
var * ad_var_sav; /* pour memoriser ad_var sur une affectation simple let a.b = c.d, instruction SADV / VLET / PHDV / PIDV / CPHH / CPHN */
|
||||
var * ad_var_dele; /* memorise ad_var pour DELE */
|
||||
/* */
|
||||
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 ! */
|
||||
@@ -395,6 +396,9 @@ enum {
|
||||
#define GUV_BIN "_bin"
|
||||
#define GUV_WDIR "_wdir"
|
||||
|
||||
#define GOV_THIS "this"
|
||||
#define GOV_PARENT "parent"
|
||||
|
||||
#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,@cr,@lf,@tab,@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,37,38,39,40,41,42,50,51,52,53,54,55,56"
|
||||
|
||||
#include "global.h"
|
||||
|
||||
@@ -393,3 +393,12 @@ WAPIDECL void GetFile(env * e, long lineNumber, Dynamic * meta, int indice, Dyna
|
||||
*ficLine = lineNumber - dynFieldAsNumber(e, meta, indice + META_GLOBAL_LN, pos, cFM, cVM) + dynFieldAsNumber(e, meta, indice + META_LOCAL_LN, pos, cFM, cVM);
|
||||
dynField(e, meta, fileFound, indice + META_FILENAME, pos, cFM, cVM, 1);
|
||||
}
|
||||
|
||||
WAPIDECL void GetTempDirectory(env * e, Dynamic * dir)
|
||||
{
|
||||
#ifdef WINLIB
|
||||
dynLet(e, dir, "C:\\Temp\\", DYN_LGNONE);
|
||||
#else
|
||||
dynLet(e, dir, "/tmp/", 5);
|
||||
#endif
|
||||
}
|
||||
@@ -40,5 +40,7 @@ WAPIDECL long GetSource(env * e, Dynamic * directory, const char * filename, Dyn
|
||||
|
||||
WAPIDECL void GetFile(env * e, long lineNumber, Dynamic * meta, int indice, Dynamic * fileFound, long * ficLine);
|
||||
|
||||
WAPIDECL void GetTempDirectory(env * e, Dynamic * dir);
|
||||
|
||||
/* ********************************************** */
|
||||
#endif
|
||||
+4
-4
@@ -209,9 +209,9 @@ long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
|
||||
exc = setError(p_etat, EXMOD_SECURESOCK_SERVER_PORT_INVALID); /* en dessous de 1024, necessite des autorisations speciales, non gere ici */
|
||||
else
|
||||
{
|
||||
if(NewSocket(e, &p_etat->ctxSecureSock.ctxSock) == WSOCKET_OK)
|
||||
if(NewSocket(e, &p_etat->ctxSecureSock.ctxSock, FALSE) == WSOCKET_OK) /* uniquement socket TCP */
|
||||
{
|
||||
if(SocketSetServer(e, &p_etat->ctxSecureSock.ctxSock, p_etat->ctxSecureSock.ctxSock.sock, (int)(port / NUM_FACTEUR)) == WSOCKET_OK)
|
||||
if(SocketSetServer(e, &p_etat->ctxSecureSock.ctxSock, p_etat->ctxSecureSock.ctxSock.sock, (int)(port / NUM_FACTEUR), NULL) == WSOCKET_OK)
|
||||
{
|
||||
if(SetPemCertificate(e, &p_etat->ctxSecureSock, paramCertificate, paramPrivateKey) == WSECURESOCKET_OK)
|
||||
{
|
||||
@@ -252,9 +252,9 @@ long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
if(NewSocket(e, &p_etat->ctxSecureSock.ctxSock) == WSOCKET_OK)
|
||||
if(NewSocket(e, &p_etat->ctxSecureSock.ctxSock, FALSE) == WSOCKET_OK) /* uniquement socket TCP */
|
||||
{
|
||||
if(SocketConnectToServer(e, &p_etat->ctxSecureSock.ctxSock, p_etat->ctxSecureSock.ctxSock.sock, (int)(port / NUM_FACTEUR), paramHost) == WSOCKET_OK)
|
||||
if(SocketConnectToServer(e, &p_etat->ctxSecureSock.ctxSock, p_etat->ctxSecureSock.ctxSock.sock, (int)(port / NUM_FACTEUR), NULL, paramHost) == WSOCKET_OK)
|
||||
{
|
||||
if(SecureSocketClient(e, &p_etat->ctxSecureSock, p_etat->ctxSecureSock.ctxSock.sock, paramHost, timeout * 1000 / NUM_FACTEUR) == WSECURESOCKET_OK)
|
||||
{
|
||||
|
||||
@@ -68,6 +68,3 @@ 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);
|
||||
@@ -261,108 +261,7 @@ WAPIDECL long writeShm(env * e, modContextShm * ctx)
|
||||
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;
|
||||
}
|
||||
|
||||
/* utilite ? */
|
||||
#ifndef WINLIB
|
||||
WAPIDECL int OpenLock(env * e, const char * name)
|
||||
{
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#ifndef WINLIB
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/un.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
@@ -42,6 +43,7 @@
|
||||
#define INVALID_SOCKET -1
|
||||
#else
|
||||
#include "winsock2.h" // link avec ws2_32.lib
|
||||
#include <afunix.h>
|
||||
#include <windows.h>
|
||||
typedef SOCKET Socket;
|
||||
typedef Socket * wPoll;
|
||||
@@ -61,6 +63,7 @@ enum {
|
||||
|
||||
typedef struct {
|
||||
Dynamic listSocket; // contient le tableau de pollfd/Socket encapsule dans un dynamic
|
||||
Dynamic localSocket; // chemin de la socket unix locale, vide si socket TCP
|
||||
int nbSocket; // nombre d'elements dans le tableau de pollfd
|
||||
int posAddSocket; // endroit ou l'ajout a ete fait dans listSocket
|
||||
wPoll poll; // pointeur vers le tableau de pollfd/Socket
|
||||
@@ -77,10 +80,10 @@ typedef struct {
|
||||
WAPIDECL void initSock(env * e, modContextSocket * ctx);
|
||||
WAPIDECL void freeSock(env * e, modContextSocket * ctx);
|
||||
WAPIDECL void SetBlocking(Socket sock, int blocking);
|
||||
WAPIDECL Socket NewSocket(env * e, modContextSocket * ctx);
|
||||
WAPIDECL long SocketSetServer(env * e, modContextSocket * ctx, Socket sock, int port);
|
||||
WAPIDECL Socket NewSocket(env * e, modContextSocket * ctx, int local);
|
||||
WAPIDECL long SocketSetServer(env * e, modContextSocket * ctx, Socket sock, int port, var * localPath);
|
||||
WAPIDECL long AcceptClientSocket(env * e, modContextSocket * ctx);
|
||||
WAPIDECL long SocketConnectToServer(env * e, modContextSocket * ctx, Socket sock, int port, var * server);
|
||||
WAPIDECL long SocketConnectToServer(env * e, modContextSocket * ctx, Socket sock, int port, var * localPath, var * server);
|
||||
WAPIDECL long AddSocket(env * e, modContextSocket * ctx, Socket sock);
|
||||
WAPIDECL void DelSocket(env * e, modContextSocket * ctx, Socket sock);
|
||||
WAPIDECL long WaitSocketForRead(env * e, modContextSocket * ctx, int timeoutMs);
|
||||
@@ -93,3 +96,5 @@ WAPIDECL int SocketWouldBlock();
|
||||
WAPIDECL long ReadSocket(env * e, modContextSocket * ctx, Socket sock, var * data, long timeoutMs);
|
||||
WAPIDECL long WriteSocket(env * e, modContextSocket * ctx, Socket sock, var * data);
|
||||
|
||||
WAPIDECL long SendSocket(env * e, modContextSocket * ctx, Socket sock, Socket socketToSend, number pid);
|
||||
WAPIDECL long ReceiveSocket(env * e, modContextSocket * ctx, Socket sock, Socket * socketReceived);
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "langage.h"
|
||||
#include "dynamic.h"
|
||||
#include "var.h"
|
||||
#include "rep.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
@@ -195,6 +196,7 @@ long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
|
||||
{
|
||||
/* get param in the right order */
|
||||
var * paramPortNumber = getParam(e, "portNumber", 10);
|
||||
/* TODO socket unix locale (pas en mode secure) */
|
||||
if(paramPortNumber == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(paramPortNumber->type != VAR_NUMBER && paramPortNumber->type != VAR_DYNAMIC)
|
||||
@@ -209,9 +211,9 @@ long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
|
||||
exc = setError(p_etat, EXMOD_SOCK_SERVER_PORT_INVALID); /* en dessous de 1024, necessite des autorisations speciales, non gere ici */
|
||||
else
|
||||
{
|
||||
if(NewSocket(e, &p_etat->ctxSock) == WSOCKET_OK)
|
||||
if(NewSocket(e, &p_etat->ctxSock, FALSE) == WSOCKET_OK)
|
||||
{
|
||||
if(SocketSetServer(e, &p_etat->ctxSock, p_etat->ctxSock.sock, (int)(port / NUM_FACTEUR)) != WSOCKET_OK)
|
||||
if(SocketSetServer(e, &p_etat->ctxSock, p_etat->ctxSock.sock, (int)(port / NUM_FACTEUR), NULL) != WSOCKET_OK)
|
||||
exc = setError(p_etat, EXMOD_SOCK_SETSERVER);
|
||||
}
|
||||
else
|
||||
@@ -226,6 +228,7 @@ long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
|
||||
var * paramHost = getParam(e, "host", 4);
|
||||
var * paramPortNumber = getParam(e, "portNumber", 10);
|
||||
var * paramSocket = getParam(e, "socket", 6);
|
||||
/* socket unix locale (pas en mode secure) */
|
||||
if(paramHost == NULL || paramPortNumber == NULL || paramSocket == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(paramHost->type != VAR_DYNAMIC || (paramPortNumber->type != VAR_NUMBER && paramPortNumber->type != VAR_DYNAMIC))
|
||||
@@ -238,9 +241,9 @@ long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
|
||||
exc = setError(p_etat, EXMOD_SOCK_SERVER_PORT_NUM);
|
||||
else
|
||||
{
|
||||
if(NewSocket(e, &p_etat->ctxSock) == WSOCKET_OK)
|
||||
if(NewSocket(e, &p_etat->ctxSock, FALSE) == WSOCKET_OK)
|
||||
{
|
||||
if(SocketConnectToServer(e, &p_etat->ctxSock, p_etat->ctxSock.sock, (int)(port / NUM_FACTEUR), paramHost) == WSOCKET_OK)
|
||||
if(SocketConnectToServer(e, &p_etat->ctxSock, p_etat->ctxSock.sock, (int)(port / NUM_FACTEUR), NULL, paramHost) == WSOCKET_OK)
|
||||
{
|
||||
if(paramSocket->type != VAR_NUMBER)
|
||||
var_let(e, paramSocket, &e->int_number, FALSE, FALSE);
|
||||
@@ -442,6 +445,115 @@ long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(modFnIs(e, "export", 6))
|
||||
{
|
||||
/* get param in the right order */
|
||||
var * paramSocket = getParam(e, "socket", 6);
|
||||
var * paramPid = getParam(e, "pid", 3);
|
||||
/* envoi d'une socket a un autre process via son pid, par socket unix locale (non secu) */
|
||||
if(paramSocket == NULL || paramPid == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if((paramSocket->type != VAR_NUMBER && paramSocket->type != VAR_DYNAMIC) || (paramPid->type != VAR_NUMBER && paramPid->type != VAR_DYNAMIC))
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
number socket, pid;
|
||||
if( ! var_conv_num(e, paramSocket, &socket) || ! var_conv_num(e, paramPid, &pid))
|
||||
exc = setError(p_etat, EXMOD_SOCK_SERVER_PORT_NUM); // TODO
|
||||
else
|
||||
{
|
||||
if(NewSocket(e, &p_etat->ctxSock, TRUE) == WSOCKET_OK)
|
||||
{
|
||||
GetTempDirectory(e, &e->tmp_dynamic);
|
||||
dynConcatSz(e, &e->tmp_dynamic, "wsocket_", 8);
|
||||
dynConcatNumber(e, &e->tmp_dynamic, pid);
|
||||
if(SocketConnectToServer(e, &p_etat->ctxSock, p_etat->ctxSock.sock, 0, &e->tmp_dynamic, NULL) == WSOCKET_OK)
|
||||
{
|
||||
if(SendSocket(e, &p_etat->ctxSock, p_etat->ctxSock.sock, socket, pid) == OK)
|
||||
{
|
||||
if(ReadSocket(e, &p_etat->ctxSock, p_etat->ctxSock.sock, &e->tmp_dynamic, 1000) == WSOCKET_OK) /* delai 1 sec. */
|
||||
{
|
||||
/* verifier si les donnes lues sont egales a "OK" */
|
||||
/* socket bien recue par l'autre process : fermer celle ici */
|
||||
FreeSocket(e, &p_etat->ctxSock, socket);
|
||||
}
|
||||
else
|
||||
exc = setError(p_etat, EXMOD_SOCK_READ); // TODO
|
||||
}
|
||||
else
|
||||
exc = setError(p_etat, EXMOD_SOCK_READ); // TODO
|
||||
FreeSocket(e, &p_etat->ctxSock, p_etat->ctxSock.sock);
|
||||
}
|
||||
else
|
||||
exc = setError(p_etat, EXMOD_SOCK_CONNECT); // TODO
|
||||
}
|
||||
else
|
||||
exc = setError(p_etat, EXMOD_SOCK_NEW); // TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ----------------------------------------------------------------------------------------------- */
|
||||
else if(modFnIs(e, "import", 6))
|
||||
{
|
||||
/* get param in the right order */
|
||||
var * paramSocket = getParam(e, "socket", 6);
|
||||
/* recuperation d'une socket depuis un autre process, par socket unix locale (non secu) */
|
||||
if(paramSocket == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
if(paramSocket->type != VAR_NUMBER)
|
||||
var_let(e, paramSocket, &e->int_number, FALSE, FALSE);
|
||||
paramSocket->num = NUM_MOINSUN;
|
||||
/* */
|
||||
if(NewSocket(e, &p_etat->ctxSock, TRUE) == WSOCKET_OK)
|
||||
{
|
||||
GetTempDirectory(e, &e->tmp_dynamic);
|
||||
dynConcatSz(e, &e->tmp_dynamic, "wsocket_", 8);
|
||||
dynConcatNumber(e, &e->tmp_dynamic, getpid());
|
||||
if(SocketSetServer(e, &p_etat->ctxSock, p_etat->ctxSock.sock, 0, &e->tmp_dynamic) == WSOCKET_OK)
|
||||
{
|
||||
// couper ici et faire 2 fn : une qui init la socket unix locale, et une qui ecoute et lit une socket
|
||||
// attend une activite sur la socket serveur et si oui cree une nouvelle socket, timeout 1 seconde en ms
|
||||
long cr = WaitOneSocketForRead(e, &p_etat->ctxSock, p_etat->ctxSock.servSock, 1000);
|
||||
if(cr < 0)
|
||||
exc = setError(p_etat, EXMOD_SOCK_WAIT);
|
||||
else if(cr == 0)
|
||||
; /* => timeout, RAS */
|
||||
else
|
||||
{
|
||||
/* nouvelle connexion entrante */
|
||||
if(AcceptClientSocket(e, &p_etat->ctxSock) == WSOCKET_OK)
|
||||
{
|
||||
Socket socket;
|
||||
if(ReceiveSocket(e, &p_etat->ctxSock, p_etat->ctxSock.sock, &socket) == OK)
|
||||
{
|
||||
dynLet(e, &e->tmp_dynamic, "OK", 2);
|
||||
if(WriteSocket(e, &p_etat->ctxSock, p_etat->ctxSock.sock, &e->tmp_dynamic) == WSOCKET_OK)
|
||||
{
|
||||
/* socket bien recue de l'autre process */
|
||||
paramSocket->num = socket;
|
||||
}
|
||||
else
|
||||
exc = setError(p_etat, EXMOD_SOCK_WRITE); // TODO
|
||||
}
|
||||
else
|
||||
exc = setError(p_etat, EXMOD_SOCK_READ); // TODO
|
||||
FreeSocket(e, &p_etat->ctxSock, p_etat->ctxSock.sock);
|
||||
}
|
||||
else
|
||||
exc = setError(p_etat, EXMOD_SOCK_ACCEPT);
|
||||
}
|
||||
FreeSocket(e, &p_etat->ctxSock, p_etat->ctxSock.servSock); // idem 'stopserver', a separer
|
||||
}
|
||||
else
|
||||
exc = setError(p_etat, EXMOD_SOCK_CONNECT); // TODO
|
||||
}
|
||||
else
|
||||
exc = setError(p_etat, EXMOD_SOCK_NEW); // TODO
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else
|
||||
{
|
||||
|
||||
+267
-69
@@ -43,15 +43,38 @@
|
||||
/* ---------------------------------------------------- */
|
||||
|
||||
/* ****** PRIVATE ************************ */
|
||||
static void DeleteLocalSocketFile(env * e, modContextSocket * ctx)
|
||||
{
|
||||
if(ctx->localSocket.mLg > 0)
|
||||
#ifndef WINLIB
|
||||
unlink(ctx->localSocket.mPtr);
|
||||
#else
|
||||
DeleteFileA(ctx->localSocket.mPtr);
|
||||
#endif
|
||||
dynSetLen(e, &ctx->localSocket, 0);
|
||||
}
|
||||
|
||||
static int SetCloexec(Socket fd)
|
||||
{
|
||||
#ifndef WINLIB
|
||||
int ret = fcntl(fd, F_GETFD);
|
||||
if(ret != -1)
|
||||
ret = fcntl(fd, F_SETFD, ret | FD_CLOEXEC);
|
||||
return (ret == -1); /* TRUE si erreur */
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ****** PUBLIC ************************ */
|
||||
WAPIDECL void initSock(env * e, modContextSocket * ctx)
|
||||
{
|
||||
dynInit(e, &ctx->listSocket, DYN_LGMIN);
|
||||
dynSetLen(e, &ctx->listSocket, 0); // raz liste sockets
|
||||
dynInit(e, &ctx->localSocket, DYN_LGMIN);
|
||||
ctx->servSock = INVALID_SOCKET;
|
||||
ctx->sock = INVALID_SOCKET;
|
||||
ctx->packet = 16000;
|
||||
ctx->packet = 16000; /* parametrable par une fonction ? */
|
||||
ctx->nbSocket = 0;
|
||||
//
|
||||
#ifdef WINLIB
|
||||
@@ -63,6 +86,8 @@ WAPIDECL void initSock(env * e, modContextSocket * ctx)
|
||||
WAPIDECL void freeSock(env * e, modContextSocket * ctx)
|
||||
{
|
||||
/* fermer les sockets ouvertes */
|
||||
DeleteLocalSocketFile(e, ctx);
|
||||
/* */
|
||||
ctx->poll = (wPoll)ctx->listSocket.ptr;
|
||||
for(int cpt = 0; cpt < ctx->nbSocket; cpt++)
|
||||
{
|
||||
@@ -75,6 +100,7 @@ WAPIDECL void freeSock(env * e, modContextSocket * ctx)
|
||||
#endif
|
||||
}
|
||||
dynFree(e, &ctx->listSocket);
|
||||
dynFree(e, &ctx->localSocket);
|
||||
#ifdef WINLIB
|
||||
WSACleanup();
|
||||
#endif
|
||||
@@ -91,8 +117,9 @@ WAPIDECL void SetBlocking(Socket sock, int blocking)
|
||||
#endif
|
||||
}
|
||||
|
||||
WAPIDECL Socket NewSocket(env * e, modContextSocket * ctx)
|
||||
WAPIDECL Socket NewSocket(env * e, modContextSocket * ctx, int local)
|
||||
{
|
||||
/* local = 1: socket unix, sinon socket TCP */
|
||||
#ifdef WINLIB
|
||||
BOOL bOptVal = TRUE;
|
||||
int bOptLen = sizeof(BOOL);
|
||||
@@ -105,14 +132,31 @@ WAPIDECL Socket NewSocket(env * e, modContextSocket * ctx)
|
||||
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
|
||||
if(local)
|
||||
{
|
||||
ctx->err = GetSocketError();
|
||||
return WSOCKET_ERROR;
|
||||
/* socket "Unix" (local a une machine) */
|
||||
#ifndef WINLIB
|
||||
if((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
|
||||
#else
|
||||
if((sock = WSASocket(AF_UNIX, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_NO_HANDLE_INHERIT)) == INVALID_SOCKET)
|
||||
#endif
|
||||
{
|
||||
ctx->err = GetSocketError();
|
||||
return WSOCKET_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* socket TCP */
|
||||
#ifndef WINLIB
|
||||
if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
|
||||
#else
|
||||
if((sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_NO_HANDLE_INHERIT)) == INVALID_SOCKET)
|
||||
#endif
|
||||
{
|
||||
ctx->err = GetSocketError();
|
||||
return WSOCKET_ERROR;
|
||||
}
|
||||
}
|
||||
/* */
|
||||
//#ifndef WINLIB
|
||||
@@ -120,37 +164,45 @@ WAPIDECL Socket NewSocket(env * e, modContextSocket * ctx)
|
||||
//#else
|
||||
//ioctlsocket(sock, FIONBIO, &block_mode);
|
||||
//#endif
|
||||
SetCloexec(sock); /* sous Windows, le flag WSA_FLAG_NO_HANDLE_INHERIT fait la meme chose lors du CreateProcess */
|
||||
/* */
|
||||
SetBlocking(sock, WSOCKET_NONBLOCKING);
|
||||
/* */
|
||||
/* 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
|
||||
if(!local) /* options inutiles en mode socket unix locale */
|
||||
{
|
||||
ctx->err = GetSocketError();
|
||||
/* 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
|
||||
close(sock);
|
||||
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
|
||||
closesocket(sock);
|
||||
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
|
||||
return WSOCKET_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)))
|
||||
{
|
||||
ctx->err = GetSocketError();
|
||||
#ifndef WINLIB
|
||||
close(sock);
|
||||
#else
|
||||
closesocket(sock);
|
||||
#endif
|
||||
return WSOCKET_ERROR;
|
||||
{
|
||||
ctx->err = GetSocketError();
|
||||
#ifndef WINLIB
|
||||
close(sock);
|
||||
#else
|
||||
closesocket(sock);
|
||||
#endif
|
||||
return WSOCKET_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)))
|
||||
{
|
||||
ctx->err = GetSocketError();
|
||||
#ifndef WINLIB
|
||||
close(sock);
|
||||
#else
|
||||
closesocket(sock);
|
||||
#endif
|
||||
return WSOCKET_ERROR;
|
||||
}
|
||||
}
|
||||
/* autres options ?
|
||||
int flag = 1;
|
||||
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag)); // demande à TCP d'envoyer les données sans attendre leur regroupement, afin de privilégier la faible latence plutôt que l'efficacité du trafic réseau.
|
||||
//
|
||||
int buf = 64000; // de 4 ko a 256 Ko, mais impact tres limite => prevoir plutot un heartbeat applicatif
|
||||
if(setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (void*)&buf, sizeof(buf))) ; // erreur
|
||||
if(setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (void*)&buf, sizeof(buf))) ;
|
||||
@@ -183,18 +235,47 @@ WAPIDECL Socket NewSocket(env * e, modContextSocket * ctx)
|
||||
return WSOCKET_OK;
|
||||
}
|
||||
|
||||
WAPIDECL long SocketSetServer(env * e, modContextSocket * ctx, Socket sock, int port)
|
||||
WAPIDECL long SocketSetServer(env * e, modContextSocket * ctx, Socket sock, int port, var * localPath)
|
||||
{
|
||||
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);
|
||||
struct sockaddr * sa;
|
||||
int sofsa;
|
||||
/* */
|
||||
dynSetLen(e, &ctx->localSocket, 0);
|
||||
if(localPath)
|
||||
{
|
||||
struct sockaddr_un addr;
|
||||
addr.sun_family = AF_UNIX;
|
||||
dynSetAs(e, &ctx->localSocket, localPath);
|
||||
/* localPath doit contenir le chemin complet d'un "fichier" unique pour la socket locale (exemple: /tmp/wsock_1234.sock et C:\\Temp\\wsock_1234.sock) */
|
||||
if(ctx->localSocket.mLg >= sizeof(addr.sun_path))
|
||||
{
|
||||
dynSetLen(e, &ctx->localSocket, 0);
|
||||
return WSOCKET_ERROR;
|
||||
}
|
||||
strcpy(addr.sun_path, ctx->localSocket.mPtr);
|
||||
/* Supprimer l'ancien fichier de socket s'il existe, sinon le prochain bind echouera */
|
||||
#ifndef WINLIB
|
||||
unlink(addr.sun_path);
|
||||
#else
|
||||
DeleteFileA(addr.sun_path);
|
||||
#endif
|
||||
sa = (struct sockaddr *)&addr;
|
||||
sofsa = sizeof(addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
sa = (struct sockaddr *)&addr;
|
||||
sofsa = sizeof(addr);
|
||||
}
|
||||
#ifndef WINLIB
|
||||
if(bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
|
||||
if(bind(sock, sa, sofsa) < 0)
|
||||
#else
|
||||
if(bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
|
||||
if(bind(sock, sa, sofsa) == SOCKET_ERROR)
|
||||
#endif
|
||||
{
|
||||
ctx->err = GetSocketError();
|
||||
@@ -203,6 +284,7 @@ WAPIDECL long SocketSetServer(env * e, modContextSocket * ctx, Socket sock, int
|
||||
#else
|
||||
closesocket(sock);
|
||||
#endif
|
||||
DeleteLocalSocketFile(e, ctx);
|
||||
return WSOCKET_ERROR;
|
||||
}
|
||||
#ifndef WINLIB
|
||||
@@ -217,6 +299,7 @@ WAPIDECL long SocketSetServer(env * e, modContextSocket * ctx, Socket sock, int
|
||||
#else
|
||||
closesocket(sock);
|
||||
#endif
|
||||
DeleteLocalSocketFile(e, ctx);
|
||||
return WSOCKET_ERROR;
|
||||
}
|
||||
if(AddSocket(e, ctx, sock) == WSOCKET_OK)
|
||||
@@ -225,7 +308,15 @@ WAPIDECL long SocketSetServer(env * e, modContextSocket * ctx, Socket sock, int
|
||||
return WSOCKET_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifndef WINLIB
|
||||
close(sock);
|
||||
#else
|
||||
closesocket(sock);
|
||||
#endif
|
||||
DeleteLocalSocketFile(e, ctx);
|
||||
return WSOCKET_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
WAPIDECL long AcceptClientSocket(env * e, modContextSocket * ctx)
|
||||
@@ -259,39 +350,59 @@ WAPIDECL long AcceptClientSocket(env * e, modContextSocket * ctx)
|
||||
}
|
||||
}
|
||||
|
||||
WAPIDECL long SocketConnectToServer(env * e, modContextSocket * ctx, Socket sock, int port, var * server)
|
||||
WAPIDECL long SocketConnectToServer(env * e, modContextSocket * ctx, Socket sock, int port, var * localPath, 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.sin_addr) != 1)
|
||||
#endif
|
||||
struct sockaddr * sa;
|
||||
int sofsa;
|
||||
/* utilise soit 'localPath' soit 'server' 'port' */
|
||||
if(localPath)
|
||||
{
|
||||
// no ip v4 format, search for name
|
||||
if((serv = gethostbyname(server->mPtr)) == NULL)
|
||||
struct sockaddr_un addr;
|
||||
addr.sun_family = AF_UNIX;
|
||||
dynSetAs(e, &ctx->localSocket, localPath);
|
||||
/* localPath doit contenir le chemin complet d'un "fichier" unique pour la socket locale (exemple: /tmp/wsock_1234.sock et C:\\Temp\\wsock_1234.sock) */
|
||||
if(ctx->localSocket.mLg >= sizeof(addr.sun_path))
|
||||
{
|
||||
ctx->err = GetSocketError();
|
||||
#ifndef WINLIB
|
||||
close(sock);
|
||||
#else
|
||||
closesocket(sock);
|
||||
#endif
|
||||
dynSetLen(e, &ctx->localSocket, 0);
|
||||
return WSOCKET_ERROR;
|
||||
}
|
||||
//addr.sin_addr.s_addr = ((struct in_addr *)(serv->h_addr))->s_addr;
|
||||
//addr.sin_addr.s_addr = (*(long *)(serv->h_addr));
|
||||
memcpy(&addr.sin_addr, serv->h_addr_list[0], serv->h_length);
|
||||
strcpy(addr.sun_path, ctx->localSocket.mPtr); /* la gestion du fichier socket local est laisse a la gestion du socket serveur en ecoute */
|
||||
sa = (struct sockaddr *)&addr;
|
||||
sofsa = sizeof(addr);
|
||||
}
|
||||
/* laisser en bloquant (tout le temps) et gerer la pseudo erreur
|
||||
"EINPROGRESS/EWOULDBLOCK" => attendre ici que socket ok en ecriture
|
||||
*/
|
||||
int ret = connect(sock, (struct sockaddr *)&addr, sizeof(addr));
|
||||
else
|
||||
{
|
||||
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.sin_addr) != 1)
|
||||
#endif
|
||||
{
|
||||
// no ip v4 format, search for name
|
||||
if((serv = gethostbyname(server->mPtr)) == NULL)
|
||||
{
|
||||
ctx->err = GetSocketError();
|
||||
#ifndef WINLIB
|
||||
close(sock);
|
||||
#else
|
||||
closesocket(sock);
|
||||
#endif
|
||||
return WSOCKET_ERROR;
|
||||
}
|
||||
//addr.sin_addr.s_addr = ((struct in_addr *)(serv->h_addr))->s_addr;
|
||||
//addr.sin_addr.s_addr = (*(long *)(serv->h_addr));
|
||||
memcpy(&addr.sin_addr, serv->h_addr_list[0], serv->h_length);
|
||||
}
|
||||
sa = (struct sockaddr *)&addr;
|
||||
sofsa = sizeof(addr);
|
||||
}
|
||||
/* laisser en non bloquant */
|
||||
int ret = connect(sock, sa, sofsa);
|
||||
#ifdef WINLIB
|
||||
if (ret == SOCKET_ERROR)
|
||||
{
|
||||
@@ -346,6 +457,91 @@ WAPIDECL long SocketConnectToServer(env * e, modContextSocket * ctx, Socket sock
|
||||
return WSOCKET_OK;
|
||||
}
|
||||
|
||||
WAPIDECL long SendSocket(env * e, modContextSocket * ctx, Socket sock, Socket socketToSend, number pid)
|
||||
{
|
||||
/* send socket using AF_UNIX local socket */
|
||||
#ifndef WINLIB
|
||||
struct msghdr msg = {0};
|
||||
char buffer[CMSG_SPACE(sizeof(int))];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
struct iovec io = {
|
||||
.iov_base = (void *)"X", /* peu importe... */
|
||||
.iov_len = 1
|
||||
};
|
||||
msg.msg_iov = &io;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = buffer;
|
||||
msg.msg_controllen = sizeof(buffer);
|
||||
struct cmsghdr * cmsg = CMSG_FIRSTHDR(&msg);
|
||||
if(cmsg == NULL)
|
||||
return -1;
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
|
||||
memcpy(CMSG_DATA(cmsg), &socketToSend, sizeof(socketToSend));
|
||||
if(sendmsg(sock, &msg, 0) < 0)
|
||||
return -1;
|
||||
else
|
||||
return OK;
|
||||
/* */
|
||||
#else
|
||||
WSAPROTOCOL_INFO info = {0};
|
||||
if(WSADuplicateSocket(socketToSend, pid, &info) == SOCKET_ERROR)
|
||||
return -1;
|
||||
var * v = &e->tmp_dynamic; // verifier que v assez grand pour info
|
||||
if(dynCtrl(e, v, sizeof(info), FALSE))
|
||||
return -1;
|
||||
memcpy(v->ptr, &info, sizeof(info));
|
||||
v->mLg = sizeof(info);
|
||||
if(WriteSocket(e, ctx, sock, v) != WSOCKET_OK)
|
||||
return -1;
|
||||
else
|
||||
return OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
WAPIDECL long ReceiveSocket(env * e, modContextSocket * ctx, Socket sock, Socket * socketReceived)
|
||||
{
|
||||
/* receive socket from AF_UNIX local socket */
|
||||
#ifndef WINLIB
|
||||
struct msghdr msg = {0};
|
||||
char buffer[CMSG_SPACE(sizeof(int))];
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
struct iovec io = {
|
||||
.iov_base = (void *)"X", /* peu importe... */
|
||||
.iov_len = sizeof(1)
|
||||
};
|
||||
msg.msg_iov = &io;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = buffer;
|
||||
msg.msg_controllen = sizeof(buffer);
|
||||
if(recvmsg(sock, &msg, 0) <= 0)
|
||||
return -1;
|
||||
if(msg.msg_flags & MSG_CTRUNC)
|
||||
return -1;
|
||||
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
|
||||
if(cmsg == NULL || cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS || cmsg->cmsg_len < CMSG_LEN(sizeof(int)))
|
||||
return -1; /* pas de socket valide recue */
|
||||
memcpy(socketReceived, CMSG_DATA(cmsg), sizeof(*socketReceived));
|
||||
return OK;
|
||||
/* */
|
||||
#else
|
||||
var * v = &e->tmp_dynamic;
|
||||
dynSetLen(e, v, 0);
|
||||
if(ReadSocket(e, ctx, sock, v, 1000) != WSOCKET_OK) // 1 sec.
|
||||
return -1;
|
||||
WSAPROTOCOL_INFO info = {0};
|
||||
if(v->mLg != sizeof(info))
|
||||
return -1;
|
||||
memcpy(&info, v->ptr, sizeof(info));
|
||||
*socketReceived = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, &info, 0, 0);
|
||||
if(*socketReceived == INVALID_SOCKET)
|
||||
return -1;
|
||||
else
|
||||
return OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
WAPIDECL long AddSocket(env * e, modContextSocket * ctx, Socket sock)
|
||||
{
|
||||
#ifndef WINLIB
|
||||
@@ -499,7 +695,7 @@ WAPIDECL long WaitOneSocketForWrite(env * e, modContextSocket * ctx, Socket sock
|
||||
|
||||
WAPIDECL void FreeSocket(env * e, modContextSocket * ctx, Socket sock)
|
||||
{
|
||||
|
||||
/* supprimer le fichier d'un socket unix (local) - uniquement au moment de la liberation du socket serveur en ecoute */
|
||||
#ifndef WINLIB
|
||||
shutdown(sock, SHUT_RDWR); // inutile a cause de SO_LINGER = 1 !?
|
||||
close(sock);
|
||||
@@ -507,6 +703,8 @@ WAPIDECL void FreeSocket(env * e, modContextSocket * ctx, Socket sock)
|
||||
shutdown(sock, SD_BOTH); // inutile a cause de SO_LINGER = 1 !?
|
||||
closesocket(sock);
|
||||
#endif
|
||||
if(sock == ctx->servSock)
|
||||
DeleteLocalSocketFile(e, ctx);
|
||||
DelSocket(e, ctx, sock);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <WinSock2.h>
|
||||
#else
|
||||
#include "poll.h"
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
// force exporting
|
||||
@@ -110,6 +111,19 @@ int ssh_read_timeout(env * e, modContextSsh * ctx, Dynamic * data, number timeou
|
||||
return ssh_channel_read(ctx->channel, data->mPtr + data->mLg, ctx->packet, 0); /* 0 signifie lire stdout, 1 pour stderr */
|
||||
}
|
||||
|
||||
static int setSessionCloexec(ssh_session session)
|
||||
{
|
||||
#ifndef WINLIB
|
||||
int fd = (int)ssh_get_fd(session);
|
||||
int ret = fcntl(fd, F_GETFD);
|
||||
if(ret != -1)
|
||||
ret = fcntl(fd, F_SETFD, ret | FD_CLOEXEC);
|
||||
return (ret == -1); /* TRUE si erreur */
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* ****** PUBLIC ************************ */
|
||||
WAPIDECL void initSsh(env * e, modContextSsh * ctx)
|
||||
{
|
||||
@@ -140,6 +154,7 @@ WAPIDECL long setSession(env * e, modContextSsh * ctx, Dynamic * host, Dynamic
|
||||
ctx->session = NULL;
|
||||
return (ctx->err = WSSH_SESSION_CONNECT);
|
||||
}
|
||||
setSessionCloexec(ctx->session); /* permet fork + execv securises, une fois connecte */
|
||||
/* */
|
||||
if(ssh_userauth_password(ctx->session, NULL, pwd->mPtr) != SSH_AUTH_SUCCESS)
|
||||
{
|
||||
|
||||
+68
-2
@@ -28,6 +28,7 @@
|
||||
#include "langage.h"
|
||||
#include "dynamic.h"
|
||||
#include "var.h"
|
||||
#include "hashtable.h"
|
||||
|
||||
#ifdef WINLIB
|
||||
#include "windows.h"
|
||||
@@ -54,7 +55,8 @@ enum {
|
||||
EXMOD_SYSTEM_SETENV = 3,
|
||||
EXMOD_SYSTEM_UNSETENV = 4,
|
||||
EXMOD_SYSTEM_UNAME = 5,
|
||||
EXMOD_NB = 5
|
||||
EXMOD_CMDLINE_ARG = 6,
|
||||
EXMOD_NB = 6
|
||||
};
|
||||
/* libelles des codes d'erreur, qui doivent aller de 1 a EXMOD_NB */
|
||||
char * descModErr[] = {
|
||||
@@ -63,7 +65,8 @@ char * descModErr[] = {
|
||||
"Unknown environment variable",
|
||||
"set environment variable error",
|
||||
"delete environment variable error",
|
||||
"Cannot get host name" // 5
|
||||
"Cannot get host name", // 5
|
||||
"Cannot read command line arguments"
|
||||
};
|
||||
/* ============================================================================================= */
|
||||
|
||||
@@ -445,6 +448,69 @@ long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
|
||||
exc = EX_MODPARAM;
|
||||
}
|
||||
}
|
||||
else if(modFnIs(e, "newProcess", 10))
|
||||
{
|
||||
/* get param in the right order */
|
||||
var * paramArgs = getParam(e, "args", 4);
|
||||
var * paramPid = getParam(e, "newPid", 6);
|
||||
if(paramArgs == NULL || paramPid == NULL)
|
||||
exc = EX_MODPARAM;
|
||||
else if(paramArgs->type != VAR_DYNAMIC) /* progs w + arguments en FM */
|
||||
exc = EX_MODPARAM;
|
||||
else
|
||||
{
|
||||
if(paramPid->type != VAR_NUMBER)
|
||||
var_let(e, paramPid, &e->int_number, FALSE, FALSE);
|
||||
paramPid->num = 0; /* erreur par defaut */
|
||||
/* lire GUV_ENV et GUV_WARGV{1} pour reconstituer la ligne de commande windows/unix */
|
||||
var * va = &e->int_dynamic;
|
||||
hashtable_do(e, HASH_READ, &e->g, copy_nom(e, GUV_WARGV), &va); // garder {1,1} = executeur W
|
||||
var * ve = &e->tmp_dynamic;
|
||||
hashtable_do(e, HASH_READ, &e->g, copy_nom(e, GUV_ENV), &ve); // wbin wsrc wlib {1,1-3}
|
||||
if(va && ve)
|
||||
{
|
||||
dynStore(e, va, 2, DYN_NONE, ve, cVM, DYN_NONE);
|
||||
dynField(e, va, ve, 1, DYN_NONE, cVM, DYN_NONE, 4); /* ve = execw wbin wsrc wlib en VM */
|
||||
dynReplace(e, ve, cVM, cFM);
|
||||
dynConcatSz(e, ve, sFM, 1);
|
||||
dynConcat(e, ve, paramArgs); /* ve = execw wbin wsrc wlib progw argw1 etc. en FM */
|
||||
dynInsSz(e, ve, 2, 1, "-WBIN", 5, cFM, ':');
|
||||
dynInsSz(e, ve, 3, 1, "-WSRC", 5, cFM, ':');
|
||||
dynInsSz(e, ve, 4, 1, "-WLIB", 5, cFM, ':');
|
||||
/* ve (tmp_dynamic) contient la ligne de commande complete */
|
||||
#ifdef WINLIB
|
||||
dynReplace(e, ve, cFM, ' '); /* recree une ligne de commande */
|
||||
STARTUPINFO si = {0};
|
||||
PROCESS_INFORMATION pi = {0};
|
||||
si.cb = sizeof(si);
|
||||
if(CreateProcess(NULL, ve->mPtr, NULL, NULL, FALSE, e->demon ? CREATE_NO_WINDOW : CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) // ou DETACHED_PROCESS comme avec BACK !?
|
||||
{
|
||||
paramPid->num = pi.dwProcessId * NUM_FACTEUR; /* ok, code retour = pid du process cree */
|
||||
CloseHandle(pi.hThread);
|
||||
CloseHandle(pi.hProcess);
|
||||
}
|
||||
#else
|
||||
long pid = fork();
|
||||
if(pid > 0)
|
||||
{
|
||||
/* dans le pere, retourner le pid du process cree */
|
||||
paramPid->num = pid * NUM_FACTEUR;
|
||||
}
|
||||
else if(pid == 0)
|
||||
{
|
||||
/* dans le fils : execvp et sortie */
|
||||
dynField(e, ve, va, 1, DYN_NONE, cFM, DYN_NONE, 1);
|
||||
char ** argv = dynToTabPtr(e, ve, cFM);
|
||||
execvp(va->mPtr, argv); /* attention : si programme interactif en front lance (cas exec 'calc') avec acces entree standard => generera une exception car ce n'est pas possible sous Unix (ok windows) */
|
||||
/* ici, erreur de execvp */
|
||||
_exit(127); /* mieux que exit(0) !? */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
exc = setError(p_etat, EXMOD_CMDLINE_ARG);
|
||||
}
|
||||
}
|
||||
/* ============================================================================================= */
|
||||
else
|
||||
{
|
||||
|
||||
@@ -287,7 +287,7 @@ WAPIDECL void var_let(env * e, var * let, var * v, int suivre_let, int suivre_v)
|
||||
}
|
||||
}
|
||||
// liberation variable affectee
|
||||
var_free(e, let, TRUE);
|
||||
var_free(e, let, FALSE); /* let pointe sur la vraie var si VAR_PARAM et suivre */
|
||||
// init et copie
|
||||
switch(v->type)
|
||||
{
|
||||
@@ -315,7 +315,10 @@ WAPIDECL void var_let(env * e, var * let, var * v, int suivre_let, int suivre_v)
|
||||
//
|
||||
case VAR_PARAM:
|
||||
if(!suivre_v) // ??
|
||||
{
|
||||
var_init(e, let, VAR_PARAM, 0, 0, v->ptr);
|
||||
let->etat = v->etat;
|
||||
}
|
||||
break;
|
||||
|
||||
case VAR_BUFFER:
|
||||
|
||||
Reference in new issue
Block a user