Author SHA1 Message Date
fred ba010944e2 WIP fn mod, shmMod 2025-09-28 17:36:18 +02:00
fred 2b076ebd18 WIP pdfMod + revoir le test des fonctions 2025-09-27 21:20:21 +02:00
fred 7cdd94920e WIP modPdf 2025-09-14 19:46:07 +02:00
12 changed files with 849 additions and 208 deletions

No files matched your search

+193
View File
@@ -0,0 +1,193 @@
/* **********************************************
__ __ __
\ \/ \/ / W language
\ /\ /
\/ \/ Copyright 2024,2025 lanisys.fr
This file is part of W language.
W language is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version (GPL-3.0-or-later).
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
********************************************** */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "langage.h"
#include "var.h"
#include "buffer.h"
#include "dynamic.h"
void buffer_read(env * e, var * varbuf, var * v)
{
ent16 lg, lgfin; /* taille max d'un element dans un buffer : 64 Ko */
ent64 p;
if(varbuf == NULL || v == NULL)
return;
if(varbuf->type != VAR_BUFFER)
return;
/* uniquement lecture dans VAR_DYNAMIC : raz var sinon */
if(v->type == VAR_PARAM)
v = (var *)v->ptr; /* travailler avec la var pointee ! */
if(v->type != VAR_DYNAMIC)
{
var_free(e, v, TRUE);
var_init(e, v, VAR_DYNAMIC, 0, 0, NULL);
if(v->type == VAR_NULL)
{
/* erreur alloc memoire */
e->exception = EX_MEM;
return;
}
}
dynLet(e, v, NULL, DYN_LGNONE);
if(varbuf->read == varbuf->write)
return; /* buffer vide : var dynamic vide aussi */
/* */
p = varbuf->read;
lg = *(octet *)(varbuf->ptr + p++) * 256;
if(p >= varbuf->lgmax) p = 0;
lg += *(octet *)(varbuf->ptr + p++);
if(p >= varbuf->lgmax) p = 0;
if(lg > 0)
{
if(dynCtrl(e, v, lg, TRUE) != DYN_OK) /* avec RAZ */
return;
/* */
if(lg <= (lgfin = varbuf->lgmax - p))
{
/* copier un seul bloc */
memcopie(v->ptr, varbuf->ptr + p, lg);
//memcpy(v->ptr, varbuf->ptr + p, lg);
v->lg = lg;
*(v->ptr + lg) = 0; /* \0 de fin de chaine */
if(p + lg >= varbuf->lgmax)
varbuf->read = 0; /* cela ne peut pas etre plus loin, car sinon il y aurait eu 2 blocs a lire */
else
varbuf->read = p + lg;
}
else
{
/* 2 blocs */
memcopie(v->ptr, varbuf->ptr + p, lgfin);
//memcpy(v->ptr, varbuf->ptr + p, lgfin);
memcopie(v->ptr + lgfin, varbuf->ptr, lg - lgfin);
//memcpy(v->ptr + lgfin, varbuf->ptr, lg - lgfin);
varbuf->read = lg - lgfin;
}
}
else
varbuf->read = p;
}
void buffer_write(env * e, var * varbuf, var * v)
{
ent64 p, lgfin;
if(varbuf == NULL || v == NULL)
return;
if(v->type == VAR_PARAM)
v = (var *)v->ptr; /* travailler avec la var pointee ! */
if(varbuf->type != VAR_BUFFER || v->type != VAR_DYNAMIC)
return;
/* uniquement ecriture d'une VAR_DYNAMIC */
if(v->lg > (v->lgmax / 16)) // pour pouvoir ecrire au moins 16 items dans le buffer
{
e->exception = EX_BUFOVF; /* trop grand a ecrire */
return;
}
ent64 vbread = varbuf->read;
if(varbuf->write < vbread)
{
/* ecriture en une fois, + 3 car lg sur 16 bits en plus et laisser au moins 1 octet libre => read=write veut dire vide ! */
if(vbread - varbuf->write < v->lg + 3)
{
e->exception = EX_BUFOVF; /* pas assez de place */
return;
}
/* */
p = varbuf->write;
*(varbuf->ptr + p) = (v->lg & 65535) >> 8;
p++;
*(varbuf->ptr + p) = v->lg & 255;
p++;
memcopie(varbuf->ptr + p, v->ptr, v->lg);
//memcpy(varbuf->ptr + p, v->ptr, v->lg);
varbuf->write = p + v->lg;
}
else
{
/* ecriture en une ou 2 fois */
if(varbuf->lgmax + vbread - varbuf->write < v->lg + 3) /* lgbuffer - (write - read) */
{
e->exception = EX_BUFOVF; /* pas assez de place */
return;
}
/* */
p = varbuf->write;
*(varbuf->ptr + p) = (v->lg & 65535) >> 8;
p++;
if(p >= varbuf->lgmax) p = 0;
*(varbuf->ptr + p) = v->lg & 255;
p++;
if(p >= varbuf->lgmax) p = 0;
if(v->lg == 0)
{
varbuf->write = p;
return;
}
if(v->lg <= (lgfin = varbuf->lgmax - p))
{
/* copier en une fois */
memcopie(varbuf->ptr + p, v->ptr, v->lg);
//memcpy(varbuf->ptr + p, v->ptr, v->lg);
if(p + v->lg >= varbuf->lgmax)
varbuf->write = 0; /* pas plus cas sinon il y aurait eu copie en 2 fois */
else
varbuf->write = p + v->lg;
}
else
{
/* en 2 fois */
memcopie(varbuf->ptr + p, v->ptr, lgfin);
//memcpy(varbuf->ptr + p, v->ptr, lgfin);
memcopie(varbuf->ptr, v->ptr + lgfin, v->lg - lgfin);
//memcpy(varbuf->ptr, v->ptr + lgfin, v->lg - lgfin);
varbuf->write = v->lg - lgfin;
}
}
}
void buffer_clear(env * e, var * varbuf)
{
if(varbuf == NULL)
return;
if(varbuf->type != VAR_BUFFER)
return;
varbuf->read = 0;
varbuf->write = 0;
memset(varbuf->ptr, 0, varbuf->lgmax);
}
void buffer_printdebug(env * e, var * varbuf, ent32 lg)
{
if(varbuf == NULL)
return;
if(varbuf->type != VAR_BUFFER)
return;
printf("buffer lgmax=%lld read=%lld write=%lld\n", varbuf->lgmax, varbuf->read, varbuf->write);
if(lg == 0)
lg = varbuf->lgmax;
/* affichage brut en hexa */
hex2((char *)varbuf->ptr, lg, 32);
}
+33
View File
@@ -0,0 +1,33 @@
/* **********************************************
__ __ __
\ \/ \/ / W language
\ /\ /
\/ \/ Copyright 2024,2025 lanisys.fr
This file is part of W language.
W language is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version (GPL-3.0-or-later).
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
********************************************** */
#ifndef BUFFER_H
#define BUFFER_H
void buffer_read(env * e, var * varbuf, var * v);
void buffer_write(env * e, var * varbuf, var * v);
void buffer_clear(env * e, var * varbuf);
void buffer_printdebug(env * e, var * varbuf, ent32 lg);
/* ********************************************** */
#endif
+11
View File
@@ -66,6 +66,17 @@ char * copy_nom(env * e, const char * s)
return e->nom;
}
int modFnIs(env * e, const char * fn, int lg)
{
// modifier l'endroit ou e->fn est mis a jour : verif fn64[0 1 2] est bien remis a zero avant la maj
ent64 f[3];
f[0] = 0; f[1] = 0; f[2] = 0;
if(lg < 1 || lg > 23)
return FALSE;
strncpy((char *)f, fn, lg);
return (e->fn64[0] == f[0] && e->fn64[1] == f[1] && e->fn64[2] == f[2]);
}
/* ************************************************************************** */
/* fonctions wrapper au cas ou on aurait besoin de ne plus utiliser certaines */
/* fonctions standards (malloc, etc.) */
+1
View File
@@ -27,6 +27,7 @@
void init_env(env * e);
char * copy_nom(env * e, const char * s);
int modFnIs(env * e, const char * fn, int lg);
/* ************************************************************************** */
/* fonctions wrapper au cas ou on aurait besoin de ne plus utiliser certaines */
+11 -199
View File
@@ -53,21 +53,6 @@
- lzwMod.c : compression lzw
- jsonMod.c : prise en charge format json (avec et sans "")
- timeMod.c : gestion du temps, chrono
fichiers du langage w :
.w : fichier texte en langage w => execution en mode "interpreté" par 'lwi' ou 'runw' (mode "script")
.wp : pseudo code binaire du langage w => execution par 'lw' (binaire compatible multi-plateformes)
.wa : assembleur texte du langage w
.w ===> s'interprete avec 'lwi' ou 'runw'
.wp ===> s'execute avec 'lw'
outils du langage w :
.w ------> .c ------> .o / executable
TODO gcc
.w ------> .wa ------> .wp ------> .wa (lwa : assembleur/desassembleur)
lwc lwa lwa -d
*/
@@ -115,7 +100,7 @@ void dyn_printdebug(env * e, var * v, int detail)
#include "lex.c"
#include "reseau.c"
//#include "reseau.c"
/* 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 */
@@ -150,6 +135,7 @@ int clock_gettime_monotonic(struct timespec * tv)
#include "hashtable.h"
#include "var.h"
#include "rep.h"
#include "buffer.h"
#include "debug.c"
@@ -1816,173 +1802,6 @@ void numstrstack_printdebug(env * e)
}
}
/* ******************************** */
/* BUFFER */
/* ******************************** */
void buffer_read(env * e, var * varbuf, var * v)
{
ent16 lg, lgfin; /* taille max d'un element dans un buffer : 64 Ko */
ent64 p;
if(varbuf == NULL || v == NULL)
return;
if(varbuf->type != VAR_BUFFER)
return;
/* uniquement lecture dans VAR_DYNAMIC : raz var sinon */
if(v->type == VAR_PARAM)
v = (var *)v->ptr; /* travailler avec la var pointee ! */
if(v->type != VAR_DYNAMIC)
{
var_free(e, v, TRUE);
var_init(e, v, VAR_DYNAMIC, 0, 0, NULL);
if(v->type == VAR_NULL)
{
/* erreur alloc memoire */
e->exception = EX_MEM;
return;
}
}
dynLet(e, v, NULL, DYN_LGNONE);
if(varbuf->read == varbuf->write)
return; /* buffer vide : var dynamic vide aussi */
/* */
p = varbuf->read;
lg = *(octet *)(varbuf->ptr + p++) * 256;
if(p >= varbuf->lgmax) p = 0;
lg += *(octet *)(varbuf->ptr + p++);
if(p >= varbuf->lgmax) p = 0;
if(lg > 0)
{
if(dynCtrl(e, v, lg, TRUE) != DYN_OK) /* avec RAZ */
return;
/* */
if(lg <= (lgfin = varbuf->lgmax - p))
{
/* copier un seul bloc */
memcopie(v->ptr, varbuf->ptr + p, lg);
//memcpy(v->ptr, varbuf->ptr + p, lg);
v->lg = lg;
*(v->ptr + lg) = 0; /* \0 de fin de chaine */
if(p + lg >= varbuf->lgmax)
varbuf->read = 0; /* cela ne peut pas etre plus loin, car sinon il y aurait eu 2 blocs a lire */
else
varbuf->read = p + lg;
}
else
{
/* 2 blocs */
memcopie(v->ptr, varbuf->ptr + p, lgfin);
//memcpy(v->ptr, varbuf->ptr + p, lgfin);
memcopie(v->ptr + lgfin, varbuf->ptr, lg - lgfin);
//memcpy(v->ptr + lgfin, varbuf->ptr, lg - lgfin);
varbuf->read = lg - lgfin;
}
}
else
varbuf->read = p;
}
void buffer_write(env * e, var * varbuf, var * v)
{
ent64 p, lgfin;
if(varbuf == NULL || v == NULL)
return;
if(v->type == VAR_PARAM)
v = (var *)v->ptr; /* travailler avec la var pointee ! */
if(varbuf->type != VAR_BUFFER || v->type != VAR_DYNAMIC)
return;
/* uniquement ecriture d'une VAR_DYNAMIC */
if(v->lg > (v->lgmax / 16)) // pour pouvoir ecrire au moins 16 items dans le buffer
{
e->exception = EX_BUFOVF; /* trop grand a ecrire */
return;
}
ent64 vbread = varbuf->read;
if(varbuf->write < vbread)
{
/* ecriture en une fois, + 3 car lg sur 16 bits en plus et laisser au moins 1 octet libre => read=write veut dire vide ! */
if(vbread - varbuf->write < v->lg + 3)
{
e->exception = EX_BUFOVF; /* pas assez de place */
return;
}
/* */
p = varbuf->write;
*(varbuf->ptr + p) = (v->lg & 65535) >> 8;
p++;
*(varbuf->ptr + p) = v->lg & 255;
p++;
memcopie(varbuf->ptr + p, v->ptr, v->lg);
//memcpy(varbuf->ptr + p, v->ptr, v->lg);
varbuf->write = p + v->lg;
}
else
{
/* ecriture en une ou 2 fois */
if(varbuf->lgmax + vbread - varbuf->write < v->lg + 3) /* lgbuffer - (write - read) */
{
e->exception = EX_BUFOVF; /* pas assez de place */
return;
}
/* */
p = varbuf->write;
*(varbuf->ptr + p) = (v->lg & 65535) >> 8;
p++;
if(p >= varbuf->lgmax) p = 0;
*(varbuf->ptr + p) = v->lg & 255;
p++;
if(p >= varbuf->lgmax) p = 0;
if(v->lg == 0)
{
varbuf->write = p;
return;
}
if(v->lg <= (lgfin = varbuf->lgmax - p))
{
/* copier en une fois */
memcopie(varbuf->ptr + p, v->ptr, v->lg);
//memcpy(varbuf->ptr + p, v->ptr, v->lg);
if(p + v->lg >= varbuf->lgmax)
varbuf->write = 0; /* pas plus cas sinon il y aurait eu copie en 2 fois */
else
varbuf->write = p + v->lg;
}
else
{
/* en 2 fois */
memcopie(varbuf->ptr + p, v->ptr, lgfin);
//memcpy(varbuf->ptr + p, v->ptr, lgfin);
memcopie(varbuf->ptr, v->ptr + lgfin, v->lg - lgfin);
//memcpy(varbuf->ptr, v->ptr + lgfin, v->lg - lgfin);
varbuf->write = v->lg - lgfin;
}
}
}
void buffer_clear(env * e, var * varbuf)
{
if(varbuf == NULL)
return;
if(varbuf->type != VAR_BUFFER)
return;
varbuf->read = 0;
varbuf->write = 0;
memset(varbuf->ptr, 0, varbuf->lgmax);
}
void buffer_printdebug(env * e, var * varbuf, ent32 lg)
{
if(varbuf == NULL)
return;
if(varbuf->type != VAR_BUFFER)
return;
printf("buffer lgmax=%lld read=%lld write=%lld\n", varbuf->lgmax, varbuf->read, varbuf->write);
if(lg == 0)
lg = varbuf->lgmax;
/* affichage brut en hexa */
hex2((char *)varbuf->ptr, lg, 32);
}
/* --- fonctions pour les objets, equiv. hash --- */
void get_new_oid(env * e)
{
@@ -2519,7 +2338,7 @@ void instr_024(env * e)
for(pos_fn = 0; pos_fn < lg; pos_fn++)
if(e->si[pos_fn] == '@')
break;
if(pos_fn < 1 || pos_fn >= lg - 1)
if(pos_fn < 1 || pos_fn >= lg - 1 || pos_fn > 21 || lg - pos_fn - 1 > 23)
{
e->exception = EX_MODNAME;
e->si += lg;
@@ -2639,18 +2458,9 @@ void instr_024(env * e)
//
// declaration de la fonction dans le module externe :
// extern long execModule(env * env, var * param, void * etat);
// (prevoir d'ajouter un appel comme etant un element du langage ??)
//
// exemples de modules "systemes"
// - file.create/open/close/read/write : create(nom, bool raz) => true : raz fichier si existant, false except si existe ; open(nom) except si n'existe pas
// - db.open/close/read/write/delete/request/prepare/trans
// - socket.create_serveur/accept_client/connect_serveur/close/read/write/secu => secu(certificat)
// db avec Postgresql : libpq.o libfe.h
// socket secu : openssl.h socket.h
// - threads.run/wait/kill ??
// + prevoir d'ajouter un appel comme etant un element du langage
//
// syntaxe : call file@create(var) => module <file>, fonction <create> avec parametre <var> (dans ad_var)
// ou alors file@create fm1, fm2, fm3, resultat => idem l'autre var contiendra fm1 FM fm2 FM fm3 et au retour var dans resultat
// syntaxe : call file&create(var) => module <file>, fonction <create> avec parametre <var> (dans ad_var)
//
// les variable de la call stack sont deja toutes des pointeurs (VAR_PARAM)
var param1, param2, param3;
@@ -5617,6 +5427,8 @@ void instr_255(env * e)
}
// liberer les modules e->g en __nom (dlclose)
e->fn64[0] = 0;
e->fn64[1] = 0;
e->fn64[2] = 0;
strncpy(e->fn, "end", 3);
e->int_dynamic.mPtr[0] = 0;
//
@@ -6493,9 +6305,9 @@ int main(int argc, char *argv[])
}
/* */
setlocale(LC_ALL, "");
/* */
/*
initReseau();
/* */
*/
if((cr = CreateContext(&ctx_env, TRUE, argc, argv)) == OK)
{
ctx_env->except_ex = EX_CMDLINE_ARG; // incorrect arg in command line : no program to run
@@ -6563,9 +6375,9 @@ int main(int argc, char *argv[])
}
/* */
FreeContext(ctx_env);
/* */
/*
finReseau();
/* */
*/
if((cr >> 8) != 0)
cr = EX_EXCEPTNUM;
printf("exit:%llu ", cr);
+5 -5
View File
@@ -74,7 +74,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
//
/* ----------------------------------------------------------------------------------------------- */
/* les 4 fonctions suivantes doivent toujours exister dans chaque module */
if(strncmp(e->fn, "init", 4) == 0)
if(modFnIs(e, "init", 4))
{
// alloc ptr sur zone memoire pour memoriser l'etat du module
*etat = memalloc(e, sizeof(modEtat));
@@ -88,7 +88,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
//
}
}
else if(strncmp(e->fn, "end", 3) == 0)
else if(modFnIs(e, "end", 3))
{
//*** code specifique ici
//
@@ -96,7 +96,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
if(p_etat != NULL)
memfree(e, p_etat);
}
else if(strncmp(e->fn, "vers", 4) == 0)
else if(modFnIs(e, "vers", 4))
{
if(param1 == NULL)
exc = EX_MODPARAM;
@@ -111,7 +111,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
exc = EX_MODPARAM; // variable en parametre du mauvais type
}
}
else if(strncmp(e->fn, "error", 5) == 0)
else if(modFnIs(e, "error", 5))
{
// renvoie la derniere erreur specifique au module
if(p_etat == NULL)
@@ -127,7 +127,7 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
}
}
/* ============================================================================================= */
else if(strncmp(e->fn, "xxx", 3) == 0)
else if(modFnIs(e, "xxx", 3))
{
//*** coder les autres fonctions ici de la meme maniere, au a mettre au debut !
exc = setError(p_etat, EXMOD_xxx);
+216
View File
@@ -0,0 +1,216 @@
/* **********************************************
__ __ __
\ \/ \/ / W language
\ /\ /
\/ \/ Copyright 2024,2025 lanisys.fr
This file is part of W language.
W language is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version (GPL-3.0-or-later).
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
********************************************** */
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include "langage.h"
#include "dynamic.h"
#include "var.h"
#include "hashtable.h"
#include "pdf.h"
typedef struct {
int error; // dernier code erreur specifique au module
//*** a completer selon le besoin du module
modContextPdf cp;
} modEtat;
/* mettre ici les codes d'erreurs specifiques au module */
/* codes a passer a la fonction setError */
#define EXMOD_xxx 1
static int setError(modEtat * p, int err)
{
if(p != NULL)
p->error = err;
return err == OK ? OK : EX_MODERR;
}
#ifndef UNIX
/* Sous Windows, export de la fonction de base au sein d'une DLL : 1 module = 1 DLL */
__declspec(dllexport) long execModule(env * , var * , var * , var * , void ** );
long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
#else
extern long execModule(env * e, var * param1, var * param2, var * param3, void ** etat)
#endif
{
modEtat * p_etat;
long exc = OK;
// init/end/vers/error sont obligatoires pour tout module
// - - - - - - - - - - - - - - - - - - - -
if(etat == NULL)
return EX_MODPARAM;
else
p_etat = (modEtat *)(*etat); /* evite de la faire a chaque fonction */
//
if(param1 != NULL)
if(param1->type == VAR_PARAM)
param1 = (var *)param1->ptr; /* evite de le faire a chaque fonction */
if(param2 != NULL)
if(param2->type == VAR_PARAM)
param2 = (var *)param2->ptr; /* evite de le faire a chaque fonction */
if(param3 != NULL)
if(param3->type == VAR_PARAM)
param3 = (var *)param3->ptr; /* evite de le faire a chaque fonction */
//
/* ----------------------------------------------------------------------------------------------- */
/* les 4 fonctions suivantes doivent toujours exister dans chaque module */
if(modFnIs(e, "init", 4))
{
// alloc ptr sur zone memoire pour memoriser l'etat du module
*etat = memalloc(e, sizeof(modEtat));
if(*etat == NULL)
exc = EX_MODETAT;
else
{
p_etat = (modEtat *)(*etat);
p_etat->error = 0;
//*** code specifique ici
initPdf(e, &p_etat->cp);
}
}
else if(modFnIs(e, "end", 3))
{
if(p_etat != NULL)
{
//*** code specifique ici
freePdf(e, &p_etat->cp);
// fin liberation specifique module avant arret process
memfree(e, p_etat);
}
}
else if(modFnIs(e, "vers", 4))
{
if(p_etat == NULL)
exc = EX_MODETAT;
else if(param1 == NULL)
exc = EX_MODPARAM;
else
{
// renvoie la version du module/plugins
if(param1->type == VAR_DYNAMIC)
dynLet(e, param1, "1", 1); //*** version en alpha
else if(param1->type == VAR_NUMBER)
param1->num = NUM_UN; //*** version en numerique
else
exc = EX_MODPARAM; // variable en parametre du mauvais type
}
}
else if(modFnIs(e, "error", 5))
{
// renvoie la derniere erreur specifique au module
if(p_etat == NULL)
exc = EX_MODETAT;
else if(param1 == NULL)
exc = EX_MODPARAM;
else
{
if(param1->type == VAR_NUMBER)
param1->num = (ent64)(NUM_FACTEUR * p_etat->error);
else
exc = EX_MODPARAM; // bad type of parameter
}
}
/* ============================================================================================= */
else if(modFnIs(e, "beginDoc", 8))
{
// nouveau document pdf
if(p_etat == NULL)
exc = EX_MODETAT;
else if(param1->type != VAR_HASHTABLE)
exc = EX_MODPARAM;
else
{
// lire les infos necessaires a la creation d'un nouveau doc. pdf :
// titre, nb pages, format, fontes utilisees
var * titre, * fontes;
hashtable_do(e, HASH_READ, param1, copy_nom(e, "Titre"), &titre);
hashtable_do(e, HASH_READ, param1, copy_nom(e, "Fontes"), &fontes);
if(titre && fontes)
{
if(titre->type == VAR_DYNAMIC && fontes->type == VAR_DYNAMIC)
exc = setError(p_etat, ! newPdf(e, &p_etat->cp, titre, 1, PDFFMT_A4P, fontes));
else
exc = EX_MODPARAM;
}
else
exc = EX_MODPARAM;
}
}
/* ============================================================================================= */
else if(modFnIs(e, "endDoc", 6))
{
// finalise le document pdf, et renvoi le contenu dans param1
if(p_etat == NULL)
exc = EX_MODETAT;
else if(param1 == NULL)
exc = EX_MODPARAM;
else
{
int cr = endPdf(e, &p_etat->cp);
if(cr)
{
var_let(e, param1, getPdf(e, &p_etat->cp), FALSE, FALSE);
}
exc = setError(p_etat, ! cr);
}
}
/* ============================================================================================= */
else if(modFnIs(e, "addPage", 7))
{
if(p_etat == NULL)
exc = EX_MODETAT;
else
// ajouter la page en cours au doucment pdf
exc = setError(p_etat, ! setPdfPage(e, &p_etat->cp, 1)); // 1 = avec compression ; parametrer ?
}
/* ============================================================================================= */
else if(modFnIs(e, "addText", 7))
{
if(p_etat == NULL)
exc = EX_MODETAT;
else if(param1 == NULL)
exc = EX_MODPARAM;
else if(param2 == NULL)
exc = EX_MODPARAM;
else if(param1->type != VAR_HASHTABLE || param2->type != VAR_DYNAMIC)
exc = EX_MODPARAM;
else
{
// ajouter le texte
exc = setError(p_etat, ! setPdfText(e, &p_etat->cp, 100, 900, 300, 300, 1, 10, 0, param2));
}
}
/* ----------------------------------------------------------------------------------------------- */
else
{
setError(p_etat, 0); // evite un warning de compil
exc = EX_MODFUNC; // fonction non prise en charge
}
//
return exc;
}
+7 -2
View File
@@ -211,7 +211,6 @@ static int fmtc(env * e, Dynamic * res, long coul)
long r = (coul >> 16) & 255; // red
long g = (coul >> 8) & 255; // green
long b = coul & 255; // blue
printf("r %ld, g %ld b %ld\n", r, g, b);
cr = cr && !dynConcatSz(e, res, r == 255 ? "1" : "0", 1);
cr = cr && (r != 255 ? !dynConcatSz(e, res, &table100[((int)(r * 100 / 255)) * 4], 3) : TRUE);
cr = cr && !dynConcatSz(e, res, g == 255 ? " 1" : " 0", 2);
@@ -238,6 +237,7 @@ void initPdf(env * e, modContextPdf * ctxPdf)
dynInit(e, &ctxPdf->mTmp2, 1024);
dynInit(e, &ctxPdf->mPage, 4096);
dynInit(e, &ctxPdf->mPdf, 8192);
ctxPdf->mPdf.type = VAR_DYNAMIC;
dynInit(e, &ctxPdf->mXref, 1024);
dynInit(e, &ctxPdf->mImg, 2048);
/* nom des fontes standards */
@@ -302,7 +302,7 @@ int newPdf(env * e, modContextPdf * ctxPdf, Dynamic * titre, long nb_page, long
dynSetLen(e, &ctxPdf->mXref, 0);
/* */
cr = cr && pdfEchap(e, &ctxPdf->mTmp1, titre); // dans les chaines "echapper" ( ) \ avec \( \) \\ (seuls cas)
cr = cr && dynConcat(e, &ctxPdf->mXref, &ctxPdf->mTmp1); // xref<1> = titre
dynConcat(e, &ctxPdf->mXref, &ctxPdf->mTmp1); // xref<1> = titre
/* */
nb_font = dynDcount(e, fonts, cFM, DYN_NONE, DYN_NONE);
nb_img = dynDcount(e, &ctxPdf->mImg, cFM, DYN_NONE, DYN_NONE);
@@ -435,6 +435,11 @@ int endPdf(env * e, modContextPdf * ctxPdf)
return TRUE;
}
Dynamic * getPdf(env * e, modContextPdf * ctxPdf)
{
return &ctxPdf->mPdf;
}
int setPdfPage(env * e, modContextPdf * ctxPdf, int compression)
{
int cr = TRUE;
+61
View File
@@ -0,0 +1,61 @@
/* **********************************************
__ __ __
\ \/ \/ / W language
\ /\ /
\/ \/ Copyright 2024,2025 lanisys.fr
This file is part of W language.
W language is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version (GPL-3.0-or-later).
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
********************************************** */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifndef WINLIB
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#else
#include <windows.h>
#endif
#include "langage.h"
#ifdef WINLIB
typedef int key_t;
#endif
typedef struct {
// proprietaire
key_t cle;
char nom[24]; // 23 cars + \0
long taille;
var * buffer;
#ifndef WINLIB
int handle;
#else
HANDLE handle;
#endif
// destinataire
char desti[24]; // 23 cars + \0
// message lu/ecrit
var * message;
} modContextShm;
void initShm(env * e, modContextShm * ctx);
void freeShm(env * e, modContextShm * ctx);
void readShm(env * e, modContextShm * ctx);
void writeShm(env * e, modContextShm * ctx);
+134
View File
@@ -0,0 +1,134 @@
/* **********************************************
__ __ __
\ \/ \/ / W language
\ /\ /
\/ \/ Copyright 2024 lanisys.fr
This file is part of W language.
W language is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version (GPL-3.0-or-later).
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
********************************************** */
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include "langage.h"
#include "dynamic.h"
#include "shm.h"
typedef struct {
int error; // dernier code erreur specifique au module
//*** a completer selon le besoin du module
modContextShm cs;
} modEtat;
/* mettre ici les codes d'erreurs specifiques au module */
/* codes a passer a la fonction setError */
#define EXMOD_xxx 1
static int setError(modEtat * p, int err)
{
if(p != NULL)
p->error = err;
return err == OK ? OK : EX_MODERR;
}
#ifndef UNIX
/* Sous Windows, export de la fonction de base au sein d'une DLL : 1 module = 1 DLL */
__declspec(dllexport) long execModule(env * , var * , var * , var * , void ** );
long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
#else
extern long execModule(env * e, var * param, var * param2, var * param3, void ** etat)
#endif
{
/* TODO : gestion des 3 parametres (au lieu d'un seul) */
modEtat * p_etat;
long exc = OK;
// init/end/vers/error sont obligatoires pour tout module
// - - - - - - - - - - - - - - - - - - - -
if(param == NULL || etat == NULL)
return EX_MODPARAM;
else
p_etat = (modEtat *)(*etat); /* evite de la faire a chaque fonction */
if(param->type == VAR_PARAM)
param = (var *)param->ptr; /* evite de le faire a chaque fonction */
//
/* ----------------------------------------------------------------------------------------------- */
/* les 4 fonctions suivantes doivent toujours exister dans chaque module */
if(modFnIs(e, "init", 4))
{
// alloc ptr sur zone memoire pour memoriser l'etat du module
*etat = memalloc(e, sizeof(modEtat));
if(*etat == NULL)
exc = EX_MODETAT;
else
{
p_etat = (modEtat *)(*etat);
p_etat->error = 0;
//*** code specifique ici
initShm(e, &p_etat->cs);
}
}
else if(modFnIs(e, "end", 3))
{
// liberation specifique au module avant arret process
if(p_etat != NULL)
{
freeShm(e, &p_etat->cs);
//*** FIN du code specifique ici
memfree(e, p_etat);
}
}
else if(modFnIs(e, "vers", 4))
{
// renvoie la version du module/plugins
if(param->type == VAR_DYNAMIC)
dynLet(e, param, "1", 1); //*** version en alpha
else if(param->type == VAR_NUMBER)
param->num = NUM_UN; //*** version en numerique
else
exc = EX_MODPARAM; // variable en parametre du mauvais type
}
else if(modFnIs(e, "error", 5))
{
// renvoie la derniere erreur specifique au module
if(p_etat == NULL)
exc = EX_MODETAT;
else
{
if(param->type == VAR_NUMBER)
param->num = (ent64)(NUM_FACTEUR * p_etat->error);
else
exc = EX_MODPARAM; // variable en parametre du mauvais type
}
}
/* ============================================================================================= */
else if(modFnIs(e, "xxx", 3))
{
//*** coder les autres fonctions ici de la meme maniere, au a mettre au debut !
exc = setError(p_etat, EXMOD_xxx);
}
/* ----------------------------------------------------------------------------------------------- */
else
{
exc = EX_MODFUNC; // fonction non prise en charge
}
//
return exc;
}
/* **************************************************************************************************** */
+175
View File
@@ -0,0 +1,175 @@
/* **********************************************
__ __ __
\ \/ \/ / W language
\ /\ /
\/ \/ Copyright 2024,2025 lanisys.fr
This file is part of W language.
W language is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version (GPL-3.0-or-later).
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
********************************************** */
#include "shm.h"
#include "buffer.h"
#define SHM_MIN_SIZE 1000
/* PRIVATE */
static key_t Hash32(const char * cle, int lg)
{
// lg multiple de 4 et > 0
// cle est une zone memoire de lg cars
ent64 k, h = 0;
if(lg > 0 && (lg % 4 == 0))
{
h = *(int *)cle;
for(int i = 0; i < lg; )
{
k = (ent64)cle[i++];
k |= ((ent64)cle[i++]) << 8;
k |= ((ent64)cle[i++]) << 16;
k |= ((ent64)cle[i++]) << 24;
k *= 0xcc9e2d51;
k = (k << 15) | (k >> 17); // 32 - 15
k *= 0x1b873593;
h ^= k;
h = (h << 13) | (h >> 19); // 32 - 13
h = h * 5 + 0xe6546b64;
}
}
h ^= lg;
h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
h *= 0xc2b2ae35;
h ^= h >> 16;
return (key_t)h;
}
/* --------------------------------------------------------------------------------------- */
void initShm(env * e, modContextShm * ctx)
{
#ifndef WINLIB
ctx->buffer = NULL;
ctx->handle = -1;
// creer la sharedmemory du process, pour lecture
if(ctx->taille < SHM_MIN_SIZE)
return; // erreur buffer trop petit
// calculer la cle a partir du nom du prog (ctx->nom)
ctx->cle = Hash32(ctx->nom, 24); // chaine de 23 cars + \0
// creer le buffer
ctx->handle = shmget(ctx->cle, ctx->taille, IPC_CREAT | IPC_EXCL | 0x666); // < 0 si ko
if(ctx->handle < 0)
return; // erreur creation sharedmemory
// lire le pointeur
ctx->buffer = (var *)shmat(ctx->handle, NULL, 0);
if( ! ctx->buffer)
{
shmctl(ctx->handle, IPC_RMID, NULL);
ctx->handle = -1;
return; // erreur recup pointeur
}
#else
ctx->buffer = NULL;
ctx->handle = NULL;
// creer la sharedmemory du process, pour lecture
if(ctx->taille < SHM_MIN_SIZE)
return; // erreur buffer trop petit
// la cle est directement le nom
// creer le buffer
ctx->handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, ctx->taille, ctx->nom); // NULL si ko, attention au \0 de fin de ctx->nom
if( ! ctx->handle)
return; // erreur creation sharedmemory
ctx->buffer = (var *)MapViewOfFile(ctx->handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if( ! ctx->buffer)
{
CloseHandle(ctx->handle);
ctx->handle = NULL;
return; // erreur recup pointeur
}
#endif
ctx->buffer->type = VAR_BUFFER;
ctx->buffer->lgmax = ctx->taille - sizeof(var);
ctx->buffer->read = 0;
ctx->buffer->write = 0;
ctx->buffer->ptr = (pointeur)ctx->buffer + sizeof(var); // le contenu est a la suite de l'entete de la variable
}
void freeShm(env * e, modContextShm * ctx)
{
#ifndef WINLIB
if(ctx->buffer)
shmdt(ctx->buffer);
if(ctx->handle >= 0)
shmctl(ctx->handle, IPC_RMID, NULL);
#else
if(ctx->buffer)
UnmapViewOfFile(ctx->buffer);
if(ctx->handle >= 0)
CloseHandle(ctx->handle); // verif que bien detruit
#endif
}
void readShm(env * e, modContextShm * ctx)
{
buffer_read(e, ctx->buffer, ctx->message);
// e->exception != OK si exception en lecture (que EX_MEM) ! vide si rien a lire (Dynamic)
}
void writeShm(env * e, modContextShm * ctx)
{
#ifndef WINLIB
// calculer la cle a partir du nom du prog (ctx->nom)
key_t cle = Hash32(ctx->desti, 24); // chaine de 23 cars + \0
// acceder au buffer
int handle = shmget(cle, 0, 0);
if(handle < 0)
return; // erreur access
// lire le pointeur
var * buffer = (var *)shmat(handle, NULL, 0);
if( ! buffer)
return; // seul le ptr se libere
// EcrireBuffer
buffer_write(e, buffer, ctx->message);
// e->exception != OK si exception en ecriture (que EX_BUFOVF) !
// ne liberer que le ptr sous unix
shmdt(buffer);
#else
// la cle est directement le destinataire
HANDLE handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, ctx->desti); // attention au \0 de fin
if( ! handle)
return; // erreur access
// lire le pointeur
var * buffer = (var *)MapViewOfFile(handle, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if( ! buffer)
{
CloseHandle(handle);
return; // erreur recup pointeur
}
// EcrireBuffer
buffer_write(e, buffer, ctx->message);
// e->exception != OK si exception en ecriture (que EX_BUFOVF) !
// liberations
UnmapViewOfFile(buffer);
CloseHandle(handle);
#endif
}
/*
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg); DispatchMessage(&msg);
}
*/
+2 -2
View File
@@ -151,9 +151,9 @@ extern long execModule(env * e, var * param1, var * param2, var * param3, void *
p_etat->error = 0;
// execute(command, returning, capturing)
// pour les vars en sortie, forcer le chgt de type si besoin ?
if(param1->type != VAR_DYNAMIC)
if(!param1 || param1->type != VAR_DYNAMIC)
exc = EX_MODPARAM;
else if(param2->type != VAR_NUMBER)
else if(!param2 || param2->type != VAR_NUMBER)
exc = EX_MODPARAM;
else
{