cfunction - Describes how to add new functions in C
See Description
This page is designed to describe how to add new functions in C. Functions in C can be used in a callback or as a standalone function. C functions are called with the following signature:
int function(snparser *p, int nbargs, int *sp, snvalue *s, bool fctcb);
Within structure snparser, the structure callback contains the following variables:
typedef enum {
sncb_start=0, /* Initialisation */
sncb_running, /* We have allocated memory and we need to release if */
sncb_finish, /* We do not need to release memory */
sncb_release, /* We need to release memory */
} sncallback_state;
typedef struct _callback {
snvalue *v_nb, *v_nb1; /* Variable for nb and nb1 */
snvalue *v_var, *v_loop; /* Variable for loop and var */
struct _callback *next, *prev; /* Double linked list */
bool used; /* In used */
int nb; /* loop counter from 0 */
int nb1; /* loop counter from 1 */
snvalue *var; /* Pointer to the current variable */
void *parm; /* Parameter for the callback to hold data */
apr_pool_t *p; /* old pool */
sncallback_state state; /* State of loop */
int (*f) (); /* Function of call */
} callback;
If the function is used in a callback, the variable fctcb will be set to true. In that case, one can use the structure callback.
A function must return a status code. Status codes can be: - snok, - snerror, - sneof, - snnauth, - sndeclined, - snerrparse, /* Parse error / - snerrexec, / Execution error / - sndivundef, / Division by undefined / - sndivzero, / Division by zero / - sndivnull, / Division by null / - snmodundef, / Modulo by undefined / - snmodzero, / Modulo by zero / - snmodnull, / Modulo by null / - snerrsql, / SQL Error */
If the function is a callback, then the returned value on the stack must be true or false: true to continue the callback, false to stop it.
If a function is a callback, then it's possible the function is break in a middle. If you set the following variable:
if (p ->cb) p -> cb -> state = sncb_running;
then, if a break is called, your function will be called:
if (fctcb && p -> cb -> state == sncb_release) {
cb = (sndb_sql_cb *) p -> cb -> parm;
sqlret = cb -> sqlret;
sndbi_free(sqlret) ;
p -> cb -> state = sncb_finish;
return snok;
}
Arguments for the function are put on the stack "s" point by the stack pointer "sp". To get the first argument one can use:
v = &s[*sp-1];
To remove all arguments on the stack, one can use:
(*sp)-=(nbargs-1);
To return an argument, one can use:
v = &s[*sp-1]; snexec_initvar(p,v); // Init variable v -> typeval = SNIVAL; v -> ival = mbstowcs(NULL,str,0);
The name of the function is in the structure snparser; so p → fctname returns the function name.
Note: In the following examples, the _ between the { should be removed to make it work.
int
snstr_length(snparser *p, int nbargs, int *sp, snvalue *s, bool fctcb) {
int i, n;
snvalue *v, *w;
char *str;
int retcode;
SNDEBUG("snfonctions_length(p=%x, nbargs=%d, sp=%d, s=%x)\n", (unsigned int)p, nbargs, *sp, s);
if (nbargs != 1)
return SNERROR(p, snerrexec, "Invalid number of arguments\n");
if (fctcb)
return SNERROR(p, snerrexec, "This function cannot be used in a callback\n");
v = &s[*sp-1];
if (v -> typeval == SNRVAL)
v = v -> rval;
retcode = snfonctions_get_sval(p, v, &str);
if (retcode != snok)
return SNERROR(p, snerrexec, "Parameter cannot be a string.\n");
(*sp)-=(nbargs-1);
v = &s[*sp-1];
snexec_initvar(p, v);
v -> typeval = SNIVAL;
v -> ival = mbstowcs(NULL,str,0);
return snok;
}
Written by Pierre Laplante and Caroline Laplante, <laplante@sednove.com>
Cras sit amet nibh libero, in gravida nulla. Nulla vel metus scelerisque ante sollicitudin commodo. Cras purus odio, vestibulum in vulputate at, tempus viverra turpis.
1.0 2014-09-09 21:24:14 laplante@sednove.com