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>
1.0 2014-09-09 21:24:14 laplante@sednove.com
Edit© 2024 extenso Inc. All rights reserved.