mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-29 18:19:30 +00:00
This commit closes bug 7605, and half-closes 7638. The AEL code has been redistributed/repartitioned to allow code re-use both inside and outside of Asterisk. This commit introduces the utils/conf2ael program, and an external config-file reader, for both normal config files, and for extensions.conf (context, exten, prio); It provides an API for programs outside of asterisk to use to play with the dialplan and config files.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@79595 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -25,6 +25,8 @@
|
||||
#ifndef _ASTERISK_AEL_STRUCTS_H
|
||||
#define _ASTERISK_AEL_STRUCTS_H
|
||||
|
||||
#include "pval.h"
|
||||
|
||||
#if !defined(SOLARIS) && !defined(__CYGWIN__)
|
||||
/* #include <err.h> */
|
||||
#else
|
||||
@@ -46,118 +48,15 @@
|
||||
# endif
|
||||
|
||||
|
||||
typedef enum {
|
||||
PV_WORD, /* an ident, string, name, label, etc. A user-supplied string. */ /* 0 */
|
||||
PV_MACRO, /* 1 */
|
||||
PV_CONTEXT, /* 2 */
|
||||
PV_MACRO_CALL, /* 3 */
|
||||
PV_APPLICATION_CALL, /* 4 */
|
||||
PV_CASE, /* 5 */
|
||||
PV_PATTERN, /* 6 */
|
||||
PV_DEFAULT, /* 7 */
|
||||
PV_CATCH, /* 8 */
|
||||
PV_SWITCHES, /* 9 */
|
||||
PV_ESWITCHES, /* 10 */
|
||||
PV_INCLUDES, /* 11 */
|
||||
PV_STATEMENTBLOCK, /* 12 */
|
||||
PV_VARDEC, /* you know, var=val; */ /* 13 */
|
||||
PV_GOTO, /* 14 */
|
||||
PV_LABEL, /* 15 */
|
||||
PV_FOR, /* 16 */
|
||||
PV_WHILE, /* 17 */
|
||||
PV_BREAK, /* 18 */
|
||||
PV_RETURN, /* 19 */
|
||||
PV_CONTINUE, /* 20 */
|
||||
PV_IF, /* 21 */
|
||||
PV_IFTIME, /* 22 */
|
||||
PV_RANDOM, /* 23 */
|
||||
PV_SWITCH, /* 24 */
|
||||
PV_EXTENSION, /* 25 */
|
||||
PV_IGNOREPAT, /* 26 */
|
||||
PV_GLOBALS, /* 27 */
|
||||
PV_LOCALVARDEC, /* you know, local var=val; */ /* 28 */
|
||||
|
||||
} pvaltype;
|
||||
|
||||
/* why this horrible mess? It's always been a tradeoff-- tons of structs,
|
||||
each storing it's specific lists of goodies, or a 'simple' single struct,
|
||||
with lots of fields, that catches all uses at once. Either you have a long
|
||||
list of struct names and subnames, or you have a long list of field names,
|
||||
and where/how they are used. I'm going with a single struct, using unions
|
||||
to reduce storage. Some simple generalizations, and a long list of types,
|
||||
and a book about what is used with what types.... Sorry!
|
||||
*/
|
||||
|
||||
struct pval
|
||||
{
|
||||
pvaltype type;
|
||||
int startline;
|
||||
int endline;
|
||||
int startcol;
|
||||
int endcol;
|
||||
char *filename;
|
||||
|
||||
union
|
||||
{
|
||||
char *str; /* wow, used almost everywhere! */
|
||||
struct pval *list; /* used in SWITCHES, ESWITCHES, INCLUDES, STATEMENTBLOCK, GOTO */
|
||||
struct pval *statements;/* used in EXTENSION */
|
||||
char *for_init; /* used in FOR */
|
||||
} u1;
|
||||
struct pval *u1_last; /* to build in-order lists -- looks like we only need one */
|
||||
|
||||
union
|
||||
{
|
||||
struct pval *arglist; /* used in macro_call, application_call, MACRO def, also attached to PWORD, the 4 timevals for includes */
|
||||
struct pval *statements; /* used in case, default, catch, while's statement, CONTEXT elements, GLOBALS */
|
||||
char *val; /* used in VARDEC */
|
||||
char *for_test; /* used in FOR */
|
||||
int label_in_case; /* a boolean for LABELs */
|
||||
struct pval *goto_target; /* used in GOTO */
|
||||
} u2;
|
||||
|
||||
union
|
||||
{
|
||||
char *for_inc; /* used in FOR */
|
||||
struct pval *else_statements; /* used in IF */
|
||||
struct pval *macro_statements; /* used in MACRO */
|
||||
int abstract; /* used for context */
|
||||
char *hints; /* used in EXTENSION */
|
||||
int goto_target_in_case; /* used in GOTO */
|
||||
struct ael_extension *compiled_label;
|
||||
} u3;
|
||||
|
||||
union
|
||||
{
|
||||
struct pval *for_statements; /* used in PV_FOR */
|
||||
int regexten; /* used in EXTENSION */
|
||||
} u4;
|
||||
|
||||
struct pval *next; /* the pval at the end of this ptr will ALWAYS be of the same type as this one!
|
||||
EXCEPT for objects of the different types, that are in the same list, like contexts & macros, etc */
|
||||
|
||||
struct pval *dad; /* the 'container' of this struct instance */
|
||||
struct pval *prev; /* the opposite of the 'next' pointer */
|
||||
} ;
|
||||
|
||||
|
||||
typedef struct pval pval;
|
||||
|
||||
#if 0
|
||||
pval *npval(pvaltype type, int first_line, int last_line, int first_column, int last_column);
|
||||
void linku1(pval *head, pval *tail);
|
||||
void print_pval_list(FILE *f, pval *item, int depth);
|
||||
void print_pval(FILE *f, pval *item, int depth);
|
||||
void ael2_semantic_check(pval *item, int *errs, int *warns, int *notes);
|
||||
struct pval *find_label_in_current_context(char *exten, char *label);
|
||||
struct pval *find_label_in_current_extension(char *label);
|
||||
int count_labels_in_current_context(char *label);
|
||||
struct pval *find_label_in_current_db(char *context, char *exten, char *label);
|
||||
void ael2_print(char *fname, pval *tree);
|
||||
#endif
|
||||
void ael2_semantic_check(pval *item, int *errs, int *warns, int *notes);
|
||||
pval *npval(pvaltype type, int first_line, int last_line, int first_column, int last_column);
|
||||
pval *linku1(pval *head, pval *tail);
|
||||
void ael2_print(char *fname, pval *tree);
|
||||
struct pval *ael2_parse(char *fname, int *errs); /* in ael.flex */
|
||||
void destroy_pval(pval *item);
|
||||
|
||||
|
||||
extern char *prev_word; /* in ael.flex */
|
||||
|
||||
#ifndef YY_TYPEDEF_YY_SCANNER_T
|
||||
|
@@ -19,7 +19,6 @@
|
||||
#ifndef _ASTERISK_EXPR_H
|
||||
#define _ASTERISK_EXPR_H
|
||||
#ifndef STANDALONE
|
||||
#include "asterisk/channel.h"
|
||||
#endif
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
extern "C" {
|
||||
|
@@ -904,6 +904,52 @@ int ast_func_read(struct ast_channel *chan, const char *function, char *workspac
|
||||
*/
|
||||
int ast_func_write(struct ast_channel *chan, const char *function, const char *value);
|
||||
|
||||
/*!
|
||||
* When looking up extensions, we can have different requests
|
||||
* identified by the 'action' argument, as follows.
|
||||
* Note that the coding is such that the low 4 bits are the
|
||||
* third argument to extension_match_core.
|
||||
*/
|
||||
|
||||
enum ext_match_t {
|
||||
E_MATCHMORE = 0x00, /* extension can match but only with more 'digits' */
|
||||
E_CANMATCH = 0x01, /* extension can match with or without more 'digits' */
|
||||
E_MATCH = 0x02, /* extension is an exact match */
|
||||
E_MATCH_MASK = 0x03, /* mask for the argument to extension_match_core() */
|
||||
E_SPAWN = 0x12, /* want to spawn an extension. Requires exact match */
|
||||
E_FINDLABEL = 0x22 /* returns the priority for a given label. Requires exact match */
|
||||
};
|
||||
|
||||
#define STATUS_NO_CONTEXT 1
|
||||
#define STATUS_NO_EXTENSION 2
|
||||
#define STATUS_NO_PRIORITY 3
|
||||
#define STATUS_NO_LABEL 4
|
||||
#define STATUS_SUCCESS 5
|
||||
#define AST_PBX_MAX_STACK 128
|
||||
|
||||
/* request and result for pbx_find_extension */
|
||||
struct pbx_find_info {
|
||||
#if 0
|
||||
const char *context;
|
||||
const char *exten;
|
||||
int priority;
|
||||
#endif
|
||||
|
||||
char *incstack[AST_PBX_MAX_STACK]; /* filled during the search */
|
||||
int stacklen; /* modified during the search */
|
||||
int status; /* set on return */
|
||||
struct ast_switch *swo; /* set on return */
|
||||
const char *data; /* set on return */
|
||||
const char *foundcontext; /* set on return */
|
||||
};
|
||||
|
||||
struct ast_exten *pbx_find_extension(struct ast_channel *chan,
|
||||
struct ast_context *bypass, struct pbx_find_info *q,
|
||||
const char *context, const char *exten, int priority,
|
||||
const char *label, const char *callerid, enum ext_match_t action);
|
||||
|
||||
|
||||
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user