Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:49:09 2009

## Asterisk developer's documentation

# pbx_ael.c File Reference

Compile symbolic Asterisk Extension Logic into Asterisk extensions. More...

`#include <sys/types.h>`
`#include <stdlib.h>`
`#include <stdio.h>`
`#include <string.h>`
`#include <ctype.h>`
`#include <errno.h>`
`#include "asterisk.h"`
`#include "asterisk/pbx.h"`
`#include "asterisk/config.h"`
`#include "asterisk/module.h"`
`#include "asterisk/logger.h"`
`#include "asterisk/cli.h"`
`#include "asterisk/callerid.h"`

Include dependency graph for pbx_ael.c:

Go to the source code of this file.

## Data Structures

struct | fillin
struct | stringlink

## Defines

#define | DEBUG_CONTEXTS (1 << 3)
#define | DEBUG_MACROS (1 << 2)
#define | DEBUG_READ (1 << 0)
#define | DEBUG_TOKENS (1 << 1)
#define | FILLIN_BREAK 1
#define | FILLIN_CONTINUE 2
#define | FREE free

## Functions

static int | __build_step (const char *what, const char *name, const char *filename, int lineno, struct ast_context *con, char *exten, int *pos, char *data, struct fillin **fillout, char **label)
static char * | __grab_token (char *src, const char *filename, int lineno, int link)
static int | ael_debug_contexts (int fd, int argc, char *argv[])
static int | ael_debug_macros (int fd, int argc, char *argv[])
static int | ael_debug_read (int fd, int argc, char *argv[])
static int | ael_debug_tokens (int fd, int argc, char *argv[])
static int | ael_no_debug (int fd, int argc, char *argv[])
static int | ael_reload (int fd, int argc, char *argv[])
static void | arg_free (struct stringlink *cur)
static struct stringlink * | arg_parse (char *args, const char *filename, int lineno)
static char * | argument_end (char *str)
static int | ast_ael_compile (struct ast_context **local_contexts, const char *filename)
static int | build_step (const char *what, const char *name, const char *filename, int lineno, struct ast_context *con, char *exten, int *pos, char *data, struct fillin **fillout, char **label)
char * | description (void)
| Provides a description of the module.
static void | fillin_free (struct fillin *fillin)
static void | fillin_process (struct ast_context *con, struct fillin *fillin, const char *filename, int lineno, const char *breakexten, int breakprio, const char *contexten, int contprio)
static void | gen_match_to_pattern (const char *pattern, char *result)
static const char * | get_case (char *s, char **restout, int *pattern)
static char * | grab_else (char *args, const char *filename, int lineno)
static char * | grab_token (char *src, const char *filename, int lineno)
static void | handle_context (struct ast_context **local_contexts, struct stringlink *vars, const char *filename, int lineno)
static void | handle_globals (struct stringlink *vars)
static void | handle_macro (struct ast_context **local_contexts, struct stringlink *vars, const char *filename, int lineno)
static int | handle_root_token (struct ast_context **local_contexts, char *token, int level, const char *filename, int lineno)
char * | key (void)
| Returns the ASTERISK_GPL_KEY.
int | load_module (void)
| Initialize the module.
static int | match_assignment (char *variable, char **value)
static int | matches_extension (char *exten, char **extout)
static int | matches_keyword (const char *data, const char *keyword)
static int | matches_label (char *data, char **rest)
static struct stringlink * | param_parse (char *parms, const char *macro, const char *filename, int lineno)
static int | parse_catch (char *data, char **catch, char **rest)
static void | parse_keyword (char *s, char **o)
static int | pbx_load_module (void)
int | reload (void)
| Reload stuff.
static struct stringlink * | split_params (char *token, const char *filename, int lineno)
static struct stringlink * | split_token (char *token, const char *filename, int lineno)
int | unload_module (void)
| Cleanup all module structures, sockets, etc.
int | usecount (void)
| Provides a usecount.

## Variables

static struct ast_cli_entry | ael_cli []
static int | aeldebug = 0
static char * | config = "extensions.ael"
static char * | dtext = "Asterisk Extension Language Compiler"
static char * | registrar = "pbx_ael"

## Detailed Description

Compile symbolic Asterisk Extension Logic into Asterisk extensions.

Definition in file pbx_ael.c.

## Define Documentation

#define DEBUG_CONTEXTS (1 << 3)

Definition at line 70 of file pbx_ael.c.

Referenced by ael_debug_contexts(), and handle_context().

#define DEBUG_MACROS (1 << 2)

Definition at line 69 of file pbx_ael.c.

Referenced by ael_debug_macros(), and handle_macro().

#define DEBUG_READ (1 << 0)

Definition at line 67 of file pbx_ael.c.

#define DEBUG_TOKENS (1 << 1)

Definition at line 68 of file pbx_ael.c.

Referenced by __build_step(), __grab_token(), ael_debug_tokens(), arg_parse(), get_case(), grab_else(), and handle_root_token().

#define FILLIN_BREAK 1

Definition at line 48 of file pbx_ael.c.

Referenced by __build_step(), and fillin_process().

#define FILLIN_CONTINUE 2

Definition at line 49 of file pbx_ael.c.

Referenced by __build_step(), and fillin_process().

#define FREE free

Definition at line 64 of file pbx_ael.c.

## Function Documentation

static int __build_step | ( | const char * | what,
|  | const char * | name,
|  | const char * | filename,
|  | int | lineno,
|  | struct ast_context * | con,
|  | char * | exten,
|  | int * | pos,
|  | char * | data,
|  | struct fillin ** | fillout,
|  | char ** | label |
| ) |  |  | `[static]`

Definition at line 501 of file pbx_ael.c.

References app, arg_free(), arg_parse(), argument_end(), ast_add_extension2(), ast_log(), ast_process_quotes_and_slashes(), ast_strlen_zero(), ast_verbose(), build_step(), stringlink::data, DEBUG_TOKENS, fillin::exten, FILLIN_BREAK, FILLIN_CONTINUE, fillin_free(), fillin_process(), FREE, gen_match_to_pattern(), get_case(), grab_else(), ifend, LOG_NOTICE, LOG_WARNING, malloc, match_assignment(), matches_keyword(), matches_label(), fillin::next, stringlink::next, fillin::priority, strdup, and fillin::type.

Referenced by build_step().

    00502 {
    00503    char *app;
    00504    char *args;
    00505    char *c;
    00506    char *margs=NULL;
    00507    char *oargs;
    00508    char *rest;
    00509    const char *curcase, *newcase;
    00510    struct stringlink *swargs, *cur;
    00511    int cpos;
    00512    int mlen;
    00513    int pattern = 0;
    00514    struct fillin *fillin;
    00515
    00516    data = ast_skip_blanks(data);
    00517    if (matches_label(data, &c)) {
    00518       *label = data;
    00519       data = c;
    00520       data = ast_skip_blanks(data);
    00521    }
    00522    if (ast_strlen_zero(data))
    00523       return 0;
    00524    if (matches_keyword(data, "switch")) {
    00525       fillin = NULL;
    00526       /* Switch */
    00527       args = data + strlen("switch");
    00528       while ((*args < 33) && (*args != '(')) args++;
    00529       if ((*args == '(') && (c = argument_end(args))) {
    00530          args++;
    00531          *c = '\0';
    00532          c++;
    00533          if (aeldebug & DEBUG_TOKENS)
    00534             ast_verbose("--SWITCH on : %s\n", args);
    00535          mlen = strlen(exten) + 128 + strlen(args) + strlen(name);
    00536          margs = alloca(mlen);
    00537          app = "Goto";
    00538          sprintf(margs, "sw-%d-%s|1", *pos, args);
    00539          ast_process_quotes_and_slashes(margs, ',', '|');
    00540          oargs = args;
    00541          args = margs;
    00542          if (ast_add_extension2(con, 0, exten, *pos, *label, NULL, app, strdup(args), FREE, registrar))
    00543             ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
    00544          else {
    00545             *label = NULL;
    00546             (*pos)++;
    00547          }
    00548          app = "NoOp";
    00549          sprintf(margs, "Finish switch-%d", *pos - 1);
    00550          if (ast_add_extension2(con, 0, exten, *pos, *label, NULL, app, strdup(args), FREE, registrar))
    00551             ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
    00552          else {
    00553             *label = NULL;
    00554             (*pos)++;
    00555          }
    00556          c = ast_skip_blanks(c);
    00557          if (aeldebug & DEBUG_TOKENS)
    00558             ast_verbose("ARG Parsing '%s'\n", c);
    00559          swargs = arg_parse(c, filename, lineno);
    00560          cur = swargs;
    00561          curcase = NULL;
    00562          while(cur) {
    00563             if ((newcase = get_case(cur->data, &rest, &pattern))) {
    00564                if (aeldebug & DEBUG_TOKENS)
    00565                   ast_verbose("--NEWCASE: '%s'!\n", newcase);
    00566                if (curcase) {
    00567                   char zbuf[256];
    00568
    00569                   /* Handle fall through */
    00570                   char tmp[strlen(newcase) + strlen(name) + 40];
    00571                   gen_match_to_pattern(newcase,zbuf);
    00572                   sprintf(tmp, "sw-%d-%s|%d", *pos - 2, zbuf, 1);
    00573                   ast_add_extension2(con, 0, margs, cpos, NULL, NULL, "Goto", strdup(tmp), FREE, registrar);
    00574                }
    00575                curcase = newcase;
    00576                cpos = 1;
    00577                if (pattern)
    00578                   snprintf(margs, mlen, "_sw-%d-%s", *pos - 2, curcase);
    00579                else
    00580                   snprintf(margs, mlen, "sw-%d-%s", *pos - 2, curcase);
    00581                if (!strcasecmp(rest, "break")) {
    00582                   char tmp[strlen(exten) + 10];
    00583                   sprintf(tmp, "%s|%d", exten, *pos - 1);
    00584                   ast_add_extension2(con, 0, exten, cpos, *label, NULL, "Goto", strdup(tmp), FREE, registrar);
    00585                   curcase = NULL;
    00586                   *label = NULL;
    00587                } else
    00588                   build_step("switch", margs, filename, lineno, con, margs, &cpos, rest, &fillin, label);
    00589             } else if (curcase) {
    00590                if (aeldebug & DEBUG_TOKENS)
    00591                   ast_verbose("Building statement from '%s'\n", rest);
    00592                if (!strcasecmp(rest, "break")) {
    00593                   char tmp[strlen(exten) + 10];
    00594                   sprintf(tmp, "%s|%d", exten, *pos - 1);
    00595                   ast_add_extension2(con, 0, margs, cpos, *label, NULL, "Goto", strdup(tmp), FREE, registrar);
    00596                   curcase = NULL;
    00597                   *label = NULL;
    00598                } else
    00599                   build_step("switch", margs, filename, lineno, con, margs, &cpos, rest, &fillin, label);
    00600             } else
    00601                ast_log(LOG_WARNING, "Unreachable code in switch at about line %d of %s\n", lineno, filename);
    00602             if (aeldebug & DEBUG_TOKENS)
    00603                ast_verbose("--SWARG: %s\n", cur->data);
    00604             cur = cur->next;
    00605          }
    00606          /* Can't do anything with these */
    00607          fillin_process(con, fillin, filename, lineno, NULL, 0, NULL, 0);
    00608          fillin_free(fillin);
    00609          arg_free(swargs);
    00610       } else
    00611          ast_log(LOG_WARNING, "Syntax error in switch declaration in %s around line %d!\n", filename, lineno);
    00612
    00613    } else if (matches_keyword(data, "if")) {
    00614       /* If... */
    00615       args = data + strlen("if");
    00616       while ((*args < 33) && (*args != '(')) args++;
    00617       if ((*args == '(') && (c = argument_end(args))) {
    00618          int ifblock;
    00619          int ifstart;
    00620          int elsestart;
    00621          int ifend;
    00622          int ifskip;
    00623          char *elses;
    00624          char *iflabel;
    00625          args++;
    00626          *c = '\0';
    00627          c++;
    00628          c = ast_skip_blanks(c);
    00629          if (aeldebug & DEBUG_TOKENS)
    00630             ast_verbose("--IF on : '%s' : '%s'\n", args, c);
    00631          mlen = strlen(exten) + 128 + strlen(args) + strlen(name);
    00632          margs = alloca(mlen);
    00633          /* Remember where the ifblock starts, and skip over */
    00634          ifblock = (*pos)++;
    00635          iflabel = *label;
    00636          *label = NULL;
    00637          /* Remember where the start of the ifblock is */
    00638          ifstart = *pos;
    00639          snprintf(margs, mlen, "if-%s-%d", name, ifblock);
    00640          /* Now process the block of the if */
    00641          if (aeldebug & DEBUG_TOKENS)
    00642             ast_verbose("Searching for elses in '%s'\n", c);
    00643          elses = grab_else(c, filename, lineno);
    00644          build_step("if", margs, filename, lineno, con, exten, pos, c, fillout, label);
    00645          if (elses) {
    00646             /* Reserve a goto to exit the if */
    00647             ifskip = *pos;
    00648             (*pos)++;
    00649             elsestart = *pos;
    00650             build_step("else", margs, filename, lineno, con, exten, pos, elses, fillout, label);
    00651          } else {
    00652             elsestart = *pos;
    00653             ifskip = 0;
    00654          }
    00655          ifend = *pos;
    00656          (*pos)++;
    00657          app = "NoOp";
    00658          snprintf(margs, mlen, "Finish if-%s-%d", name, ifblock);
    00659          if (ast_add_extension2(con, 0, exten, ifend, *label, NULL, app, strdup(margs), FREE, registrar))
    00660             ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
    00661          *label = NULL;
    00662          app = "GotoIf";
    00663          snprintf(margs, mlen, "$[ %s ]?%d:%d", args, ifstart, elsestart);
    00664          if (ast_add_extension2(con, 0, exten, ifblock, iflabel, NULL, app, strdup(margs), FREE, registrar))
    00665             ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
    00666          if (ifskip) {
    00667             /* Skip as appropriate around else clause */
    00668             snprintf(margs, mlen, "%d", ifend);
    00669             if (ast_add_extension2(con, 0, exten, ifskip, NULL, NULL, "Goto", strdup(margs), FREE, registrar))
    00670                ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
    00671          }
    00672       } else
    00673          ast_log(LOG_WARNING, "Syntax error in if declaration in %s around line %d!\n", filename, lineno);
    00674    } else if (matches_keyword(data, "while")) {
    00675       /* While... */
    00676       fillin = NULL;
    00677       args = data + strlen("while");
    00678       while ((*args < 33) && (*args != '(')) args++;
    00679       if ((*args == '(') && (c = argument_end(args))) {
    00680          int whileblock;
    00681          int whilestart;
    00682          int whileend;
    00683          char *whilelabel;
    00684          args++;
    00685          *c = '\0';
    00686          c++;
    00687          c = ast_skip_blanks(c);
    00688          if (aeldebug & DEBUG_TOKENS)
    00689             ast_verbose("--WHILE on : '%s' : '%s'\n", args, c);
    00690          mlen = strlen(exten) + 128 + strlen(args) + strlen(name);
    00691          margs = alloca(mlen);
    00692          /* Remember where to put the conditional, and keep its position */
    00693          whilestart = (*pos);
    00694          whilelabel = *label;
    00695          *label = NULL;
    00696          (*pos)++;
    00697          /* Remember where the whileblock starts */
    00698          whileblock = (*pos);
    00699          snprintf(margs, mlen, "while-%s-%d", name, whilestart);
    00700          build_step("while", margs, filename, lineno, con, exten, pos, c, &fillin, label);
    00701          /* Close the loop */
    00702          app = "Goto";
    00703          snprintf(margs, mlen, "%d", whilestart);
    00704          if (ast_add_extension2(con, 0, exten, (*pos)++, *label, NULL, app, strdup(margs), FREE, registrar))
    00705             ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
    00706          *label = NULL;
    00707          whileend = (*pos);
    00708          /* Place trailer */
    00709          app = "NoOp";
    00710          snprintf(margs, mlen, "Finish while-%s-%d", name, whilestart);
    00711          if (ast_add_extension2(con, 0, exten, (*pos)++, *label, NULL, app, strdup(margs), FREE, registrar))
    00712             ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
    00713          *label = NULL;
    00714          app = "GotoIf";
    00715          snprintf(margs, mlen, "$[ %s ]?%d:%d", args, whileblock, whileend);
    00716          if (ast_add_extension2(con, 0, exten, whilestart, whilelabel, NULL, app, strdup(margs), FREE, registrar))
    00717             ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
    00718          fillin_process(con, fillin, filename, lineno, exten, whileend, exten, whilestart);
    00719          fillin_free(fillin);
    00720       } else
    00721          ast_log(LOG_WARNING, "Syntax error in while declaration in %s around line %d!\n", filename, lineno);
    00722    } else if (matches_keyword(data, "jump")) {
    00723       char *p;
    00724       /* Jump... */
    00725       fillin = NULL;
    00726       args = data + strlen("jump");
    00727       args = ast_skip_blanks(args);
    00728       if (aeldebug & DEBUG_TOKENS)
    00729          ast_verbose("--JUMP to : '%s'\n", args);
    00730       p = strchr(args, ',');
    00731       if (p) {
    00732          *p = '\0';
    00733          p++;
    00734       } else
    00735          p = "1";
    00736       c = strchr(args, '@');
    00737       if (c) {
    00738          *c = '\0';
    00739          c++;
    00740       }
    00741       mlen = strlen(exten) + 128 + strlen(args) + strlen(name) + (c ? strlen(c) : 0);
    00742       margs = alloca(mlen);
    00743       if (c)
    00744          snprintf(margs, mlen, "%s|%s|%s", c,args, p);
    00745       else
    00746          snprintf(margs, mlen, "%s|%s", args, p);
    00747       app = "Goto";
    00748       if (ast_add_extension2(con, 0, exten, (*pos)++, *label, NULL, app, strdup(margs), FREE, registrar))
    00749          ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
    00750       *label = NULL;
    00751    } else if (matches_keyword(data, "goto")) {
    00752       /* Jump... */
    00753       fillin = NULL;
    00754       args = data + strlen("goto");
    00755       args = ast_skip_blanks(args);
    00756       if (aeldebug & DEBUG_TOKENS)
    00757          ast_verbose("--GOTO to : '%s'\n", args);
    00758       app = "Goto";
    00759       if (args[0] == '(' && args[strlen(args) - 1] == ')') {
    00760          args[0] = '\0';
    00761          args++;
    00762          args[strlen(args) - 1] = '\0';
    00763       }
    00764       if (ast_add_extension2(con, 0, exten, (*pos)++, *label, NULL, app, strdup(args), FREE, registrar))
    00765          ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
    00766       *label = NULL;
    00767    } else if (matches_keyword(data, "for")) {
    00768       /* While... */
    00769       fillin = NULL;
    00770       args = data + strlen("for");
    00771       while ((*args < 33) && (*args != '(')) args++;
    00772       if ((*args == '(') && (c = argument_end(args))) {
    00773          int forblock;
    00774          int forprep;
    00775          int forstart;
    00776          int forend;
    00777          struct stringlink *fields;
    00778          char *tmp;
    00779          char *forlabel = NULL;
    00780          args++;
    00781          *c = '\0';
    00782          c++;
    00783          c = ast_skip_blanks(c);
    00784          /* Parse arguments first */
    00785          tmp = alloca(strlen(args) + 10);
    00786          if (tmp) {
    00787             snprintf(tmp, strlen(args) + 10, "{%s;}", args);
    00788             fields = arg_parse(tmp, filename, lineno);
    00789          } else
    00790             fields = NULL;
    00791          if (fields && fields->next && fields->next->next) {
    00792             if (aeldebug & DEBUG_TOKENS)
    00793                ast_verbose("--FOR ('%s' ; '%s' ; '%s') : '%s'\n", fields->data, fields->next->data, fields->next->next->data, c);
    00794             mlen = strlen(exten) + 128 + strlen(args) + strlen(name);
    00795             margs = alloca(mlen);
    00796             forprep = *pos;
    00797             snprintf(margs, mlen, "for-%s-%d", name, forprep);
    00798             fillin = NULL;
    00799             build_step("while", margs, filename, lineno, con, exten, pos, fields->data, &fillin, label);
    00800             /* Remember where to put the conditional, and keep its position */
    00801             forstart = (*pos);
    00802             forlabel = *label;
    00803             (*pos)++;
    00804             *label = NULL;
    00805             /* Remember where the whileblock starts */
    00806             forblock = (*pos);
    00807             build_step("for", margs, filename, lineno, con, exten, pos, c, &fillin, label);
    00808             build_step("for", margs, filename, lineno, con, exten, pos, fields->next->next->data, &fillin, label);
    00809             /* Close the loop */
    00810             app = "Goto";
    00811             snprintf(margs, mlen, "%d", forstart);
    00812             if (ast_add_extension2(con, 0, exten, (*pos)++, *label, NULL, app, strdup(margs), FREE, registrar))
    00813                ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
    00814             *label = NULL;
    00815             forend = (*pos);
    00816             /* Place trailer */
    00817             app = "NoOp";
    00818             snprintf(margs, mlen, "Finish for-%s-%d", name, forprep);
    00819             if (ast_add_extension2(con, 0, exten, (*pos)++, *label, NULL, app, strdup(margs), FREE, registrar))
    00820                ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
    00821             *label = NULL;
    00822             app = "GotoIf";
    00823             snprintf(margs, mlen, "$[ %s ]?%d:%d", fields->next->data, forblock, forend);
    00824             if (ast_add_extension2(con, 0, exten, forstart, forlabel, NULL, app, strdup(margs), FREE, registrar))
    00825                ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", forstart, what, name);
    00826             fillin_process(con, fillin, filename, lineno, exten, forend, exten, forstart);
    00827             fillin_free(fillin);
    00828          } else
    00829             ast_log(LOG_NOTICE, "Improper for declaration in %s around line %d!\n", filename, lineno);
    00830          arg_free(fields);
    00831       } else
    00832          ast_log(LOG_WARNING, "Syntax error in for declaration in %s around line %d!\n", filename, lineno);
    00833
    00834    } else if (!strcasecmp(data, "break") || !strcasecmp(data, "continue")) {
    00835       struct fillin *fi;
    00836       fi = malloc(sizeof(struct fillin));
    00837       if (fi) {
    00838          memset(fi, 0, sizeof(struct fillin));
    00839          if (!strcasecmp(data, "break"))
    00840             fi->type = FILLIN_BREAK;
    00841          else
    00842             fi->type = FILLIN_CONTINUE;
    00843          ast_copy_string(fi->exten, exten, sizeof(fi->exten));
    00844          fi->priority = (*pos)++;
    00845          fi->next = *fillout;
    00846          *fillout = fi;
    00847       }
    00848    } else if (match_assignment(data, &rest)) {
    00849       if (aeldebug & DEBUG_TOKENS)
    00850          ast_verbose("ASSIGN  '%s' = '%s'\n", data, rest);
    00851       mlen = strlen(rest) + strlen(data) + 20;
    00852       margs = alloca(mlen);
    00853       snprintf(margs, mlen, "%s=$[ %s ]", data, rest);
    00854       app = "Set";
    00855       if (ast_add_extension2(con, 0, exten, *pos, *label, NULL, app, strdup(margs), FREE, registrar))
    00856          ast_log(LOG_WARNING, "Unable to add assignment at priority '%d' of %s '%s'\n", *pos, what, name);
    00857       else {
    00858          *label = NULL;
    00859          (*pos)++;
    00860       }
    00861    } else {
    00862       app = data;
    00863       args = app;
    00864       while (*args && (*args > 32) && (*args != '(')) args++;
    00865          if (*args != '(') {
    00866          while(*args && (*args != '(')) { *args = '\0'; args++; };
    00867       }
    00868       if (*args == '(') {
    00869          *args = '\0';
    00870          args++;
    00871          /* Got arguments, trim trailing ')' */
    00872          c = args + strlen(args) - 1;
    00873          while((c >= args) && (*c < 33) && (*c != ')')) { *c = '\0'; c--; };
    00874          if ((c >= args) && (*c == ')')) *c = '\0';
    00875       } else
    00876          args = "";
    00877       ast_process_quotes_and_slashes(args, ',', '|');
    00878       if (app[0] == '&') {
    00879          app++;
    00880          margs = alloca(strlen(args) + strlen(app) + 10);
    00881          sprintf(margs, "%s|%s", app, args);
    00882          args = margs;
    00883          app = "Macro";
    00884       }
    00885       if (aeldebug & DEBUG_TOKENS)
    00886          ast_verbose("-- APP: '%s', ARGS: '%s'\n", app, args);
    00887       if (ast_add_extension2(con, 0, exten, *pos, *label, NULL, app, strdup(args), FREE, registrar))
    00888          ast_log(LOG_WARNING, "Unable to add step at priority '%d' of %s '%s'\n", *pos, what, name);
    00889       else {
    00890          (*pos)++;
    00891          *label = NULL;
    00892       }
    00893    }
    00894    return 0;
    00895 }

static char* __grab_token | ( | char * | src,
|  | const char * | filename,
|  | int | lineno,
|  | int | link |
| ) |  |  | `[static]`

Definition at line 78 of file pbx_ael.c.

References ast_log(), ast_verbose(), DEBUG_TOKENS, LOG_WARNING, malloc, and strdup.

Referenced by arg_parse(), and grab_token().

    00079 {
    00080    char *c;
    00081    char *b;
    00082    char *a;
    00083    int level = 0;
    00084    char *ret;
    00085 #if 0
    00086    if (aeldebug || DEBUG_TOKENS)
    00087       ast_verbose("Searching for token in '%s'!\n", src);
    00088 #endif
    00089    c = src;
    00090    while(*c) {
    00091       if ((*c == '\\')) {
    00092          c++;
    00093          if (!*c)
    00094             c--;
    00095       } else {
    00096          if ((*c == '{') || (*c == '(')) {
    00097             level++;
    00098          } else if ((*c == '}') || (*c == ')')) {
    00099             if (level)
    00100                level--;
    00101             else
    00102                ast_log(LOG_WARNING, "Syntax error at line %d of '%s', too many closing braces!\n", lineno, filename);
    00103          } else if ((*c == ';') && !level) {
    00104             /* Got a token! */
    00105             *c = '\0';
    00106             b = c;
    00107             b--;
    00108             c++;
    00109             while((b > src) && (*b < 33)) {
    00110                *b = '\0';
    00111                b--;
    00112             }
    00113             a = ast_skip_blanks(src);
    00114             if (link) {
    00115                ret = malloc(strlen(a) + sizeof(struct stringlink) + 1);
    00116                if (ret)
    00117                   strcpy(ret + sizeof(struct stringlink), a);
    00118             } else
    00119                ret = strdup(a);
    00120             /* Save remainder */
    00121             memmove(src, c, strlen(c) + 1);
    00122             return ret;
    00123          }
    00124       }
    00125       c++;
    00126    }
    00127    return NULL;
    00128 }

static int ael_debug_contexts | ( | int | fd,
|  | int | argc,
|  | char * | argv[] |
| ) |  |  | `[static]`

Definition at line 1247 of file pbx_ael.c.

References DEBUG_CONTEXTS.

    01248 {
    01249    aeldebug |= DEBUG_CONTEXTS;
    01250    return 0;
    01251 }

static int ael_debug_macros | ( | int | fd,
|  | int | argc,
|  | char * | argv[] |
| ) |  |  | `[static]`

Definition at line 1241 of file pbx_ael.c.

References DEBUG_MACROS.

    01242 {
    01243    aeldebug |= DEBUG_MACROS;
    01244    return 0;
    01245 }

static int ael_debug_read | ( | int | fd,
|  | int | argc,
|  | char * | argv[] |
| ) |  |  | `[static]`

Definition at line 1229 of file pbx_ael.c.

References DEBUG_READ.

    01230 {
    01231    aeldebug |= DEBUG_READ;
    01232    return 0;
    01233 }

static int ael_debug_tokens | ( | int | fd,
|  | int | argc,
|  | char * | argv[] |
| ) |  |  | `[static]`

Definition at line 1235 of file pbx_ael.c.

References DEBUG_TOKENS.

    01236 {
    01237    aeldebug |= DEBUG_TOKENS;
    01238    return 0;
    01239 }

static int ael_no_debug | ( | int | fd,
|  | int | argc,
|  | char * | argv[] |
| ) |  |  | `[static]`

Definition at line 1253 of file pbx_ael.c.

    01254 {
    01255    aeldebug = 0;
    01256    return 0;
    01257 }

static int ael_reload | ( | int | fd,
|  | int | argc,
|  | char * | argv[] |
| ) |  |  | `[static]`

Definition at line 1259 of file pbx_ael.c.

References ast_context_destroy(), and pbx_load_module().

    01260 {
    01261    ast_context_destroy(NULL, registrar);
    01262    return (pbx_load_module());
    01263 }

static void arg_free | ( | struct stringlink * | cur | ) | `[static]`

Definition at line 241 of file pbx_ael.c.

References free, last, and stringlink::next.

Referenced by __build_step(), build_step(), handle_context(), handle_macro(), and handle_root_token().

    00242 {
    00243    struct stringlink *last;
    00244    while(cur) {
    00245       last = cur;
    00246       cur = cur->next;
    00247       free(last);
    00248    }
    00249 }

static struct stringlink* arg_parse | ( | char * | args,
|  | const char * | filename,
|  | int | lineno |
| ) |  |  | `[static, read]`

Definition at line 135 of file pbx_ael.c.

References __grab_token(), ast_verbose(), DEBUG_TOKENS, malloc, and stringlink::next.

Referenced by __build_step(), build_step(), handle_context(), and split_token().

    00136 {
    00137    struct stringlink *cur, *prev=NULL, *root=NULL;
    00138    if (args) {
    00139       if (aeldebug & DEBUG_TOKENS)
    00140          ast_verbose("Parsing args '%s'!\n", args);
    00141       if (args[0] == '{') {
    00142          /* Strip mandatory '}' from end */
    00143          args[strlen(args) - 1] = '\0';
    00144          while ((cur = (struct stringlink *)__grab_token(args + 1, filename, lineno, 1))) {
    00145             cur->next = NULL;
    00146             if (prev)
    00147                prev->next = cur;
    00148             else
    00149                root = cur;
    00150             prev = cur;
    00151          }
    00152       } else if (*args) {
    00153          root = malloc(sizeof(struct stringlink) + strlen(args) + 1);
    00154          if (root) {
    00155             strcpy(root->data, args);
    00156             root->next = NULL;
    00157          }
    00158       }
    00159    }
    00160    return root;
    00161 }

static char* argument_end | ( | char * | str | ) | `[static]`

Definition at line 456 of file pbx_ael.c.

Referenced by __build_step().

    00457 {
    00458    int level=0;
    00459    while(*++str) {
    00460       switch(*str) {
    00461       case '(':
    00462          level++;
    00463          break;
    00464       case ')':
    00465          if(level)
    00466             level--;
    00467          else
    00468             return str;
    00469          break;
    00470       default:
    00471          break;
    00472       }
    00473    }
    00474    return NULL;
    00475 }

static int ast_ael_compile | ( | struct ast_context ** | local_contexts,
|  | const char * | filename |
| ) |  |  | `[static]`

Definition at line 1153 of file pbx_ael.c.

References ast_config_AST_CONFIG_DIR, ast_log(), ast_verbose(), DEBUG_READ, free, grab_token(), handle_root_token(), LOG_WARNING, malloc, and realloc.

Referenced by pbx_load_module().

    01154 {
    01155    char *rfilename;
    01156    char *buf, *tbuf;
    01157    int bufsiz;
    01158    FILE *f;
    01159    char *c;
    01160    char *token;
    01161    int lineno=0;
    01162
    01163    if (filename[0] == '/')
    01164       rfilename = (char *)filename;
    01165    else {
    01166       rfilename = alloca(strlen(filename) + strlen(ast_config_AST_CONFIG_DIR) + 2);
    01167       sprintf(rfilename, "%s/%s", ast_config_AST_CONFIG_DIR, filename);
    01168    }
    01169
    01170    f = fopen(rfilename, "r");
    01171    if (!f) {
    01172       ast_log(LOG_WARNING, "Unable to open '%s': %s\n", rfilename, strerror(errno));
    01173       return -1;
    01174    }
    01175    buf = malloc(4096);
    01176    if (!buf) {
    01177       ast_log(LOG_WARNING, "Out of memory!\n");
    01178       fclose(f);
    01179       return -1;
    01180    }
    01181    buf[0] = 0;
    01182    bufsiz = 4096;
    01183    while(!feof(f)) {
    01184       if (bufsiz - strlen(buf) < 2048) {
    01185          bufsiz += 4096;
    01186          tbuf = realloc(buf, bufsiz);
    01187          if (tbuf) {
    01188             buf = tbuf;
    01189          } else {
    01190             free(buf);
    01191             ast_log(LOG_WARNING, "Out of memory!\n");
    01192             fclose(f);
    01193          }
    01194       }
    01195       if (fgets(buf + strlen(buf), bufsiz - strlen(buf), f)) {
    01196          lineno++;
    01197          while(*buf && buf[strlen(buf) - 1] < 33)
    01198             buf[strlen(buf) - 1] = '\0';
    01199          c = strstr(buf, "//");
    01200          if (c)
    01201             *c = '\0';
    01202          if (*buf) {
    01203             if (aeldebug & DEBUG_READ)
    01204                ast_verbose("Newly composed line '%s'\n", buf);
    01205             while((token = grab_token(buf, filename, lineno))) {
    01206                handle_root_token(local_contexts, token, 0, filename, lineno);
    01207                free(token);
    01208             }
    01209          }
    01210       }
    01211    };
    01212    free(buf);
    01213    fclose(f);
    01214    return 0;
    01215 }

static int build_step | ( | const char * | what,
|  | const char * | name,
|  | const char * | filename,
|  | int | lineno,
|  | struct ast_context * | con,
|  | char * | exten,
|  | int * | pos,
|  | char * | data,
|  | struct fillin ** | fillout,
|  | char ** | label |
| ) |  |  | `[static]`

Definition at line 897 of file pbx_ael.c.

References __build_step(), arg_free(), arg_parse(), stringlink::data, fillin_free(), fillin_process(), and stringlink::next.

Referenced by __build_step(), handle_context(), and handle_macro().

    00898 {
    00899    struct stringlink *args, *cur;
    00900    int res=0;
    00901    struct fillin *fillin=NULL;
    00902    int dropfill = 0;
    00903    char *labelin = NULL;
    00904    if (!fillout) {
    00905       fillout = &fillin;
    00906       dropfill = 1;
    00907    }
    00908    if (!label) {
    00909       label = &labelin;
    00910    };
    00911    args = arg_parse(data, filename, lineno);
    00912    cur = args;
    00913    while(cur) {
    00914       res |= __build_step(what, name, filename, lineno, con, exten, pos, cur->data, fillout, label);
    00915       cur = cur->next;
    00916    }
    00917    arg_free(args);
    00918    if (dropfill) {
    00919       fillin_process(con, fillin, filename, lineno, NULL, 0, NULL, 0);
    00920       fillin_free(fillin);
    00921    }
    00922    return res;
    00923 }

char* description | ( | void |  | ) |

Provides a description of the module.

Returns:
  a short description of your module

Definition at line 1302 of file pbx_ael.c.

    01303 {
    01304    return dtext;
    01305 }

static void fillin_free | ( | struct fillin * | fillin | ) | `[static]`

Definition at line 356 of file pbx_ael.c.

References free, and fillin::next.

Referenced by __build_step(), and build_step().

    00357 {
    00358    struct fillin *cur, *next;
    00359    cur =  fillin;
    00360    while(cur) {
    00361       next = cur->next;
    00362       free(cur);
    00363       cur = next;
    00364    }
    00365 }

static void fillin_process | ( | struct ast_context * | con,
|  | struct fillin * | fillin,
|  | const char * | filename,
|  | int | lineno,
|  | const char * | breakexten,
|  | int | breakprio,
|  | const char * | contexten,
|  | int | contprio |
| ) |  |  | `[static]`

Definition at line 367 of file pbx_ael.c.

References app, ast_add_extension2(), ast_log(), AST_MAX_EXTENSION, fillin::exten, FILLIN_BREAK, FILLIN_CONTINUE, FREE, LOG_NOTICE, LOG_WARNING, fillin::next, fillin::priority, strdup, and fillin::type.

Referenced by __build_step(), and build_step().

    00368 {
    00369    struct fillin *cur;
    00370    char *app;
    00371    char mdata[AST_MAX_EXTENSION + 20];
    00372    cur = fillin;
    00373    while(cur) {
    00374       if (cur->type == FILLIN_BREAK) {
    00375          if (breakexten && breakprio) {
    00376             app = "Goto";
    00377             snprintf(mdata, sizeof(mdata), "%s|%d", breakexten, breakprio);
    00378          } else {
    00379             app = "NoOp";
    00380             snprintf(mdata, sizeof(mdata), "Invalid break");
    00381             ast_log(LOG_NOTICE, "Ignoring inappropriate break around line %d of %s\n", lineno, filename);
    00382          }
    00383          if (ast_add_extension2(con, 0, cur->exten, cur->priority, NULL, NULL, app, strdup(mdata), FREE, registrar))
    00384             ast_log(LOG_WARNING, "Unable to add step at priority '%d' of break '%s'\n", cur->priority, cur->exten);
    00385       } else if (cur->type == FILLIN_CONTINUE) {
    00386          if (contexten && contprio) {
    00387             app = "Goto";
    00388             snprintf(mdata, sizeof(mdata), "%s|%d", contexten, contprio);
    00389          } else {
    00390             app = "NoOp";
    00391             snprintf(mdata, sizeof(mdata), "Invalid continue");
    00392             ast_log(LOG_NOTICE, "Ignoring inappropriate continue around line %d of %s\n", lineno, filename);
    00393          }
    00394          if (ast_add_extension2(con, 0, cur->exten, cur->priority, NULL, NULL, app, strdup(mdata), FREE, registrar))
    00395             ast_log(LOG_WARNING, "Unable to add step at priority '%d' of continue '%s'\n", cur->priority, cur->exten);
    00396       } else {
    00397          ast_log(LOG_WARNING, "Whoa, unknown fillin type '%d'\n", cur->type);
    00398       }
    00399       cur = cur->next;
    00400    }
    00401 }

static void gen_match_to_pattern | ( | const char * | pattern,
|  | char * | result |
| ) |  |  | `[static]`

Definition at line 477 of file pbx_ael.c.

References t.

Referenced by __build_step().

    00478 {
    00479        /* the result will be a string that will be matched by pattern */
    00480        char *p=(char *)pattern, *t=result;
    00481        while (*p) {
    00482                if (*p == 'x' || *p == 'n' || *p == 'z' || *p == 'X' || *p == 'N' || *p == 'Z')
    00483                        *t++ = '9';
    00484                else if (*p == '[') {
    00485                        char *z = p+1;
    00486                        while (*z != ']')
    00487                                z++;
    00488                        if (*(z+1)== ']')
    00489                                z++;
    00490                        *t++=*(p+1); /* use the first char in the set */
    00491                        p = z;
    00492                } else {
    00493                        *t++ = *p;
    00494                }
    00495                p++;
    00496        }
    00497        *t++ = 0; /* cap it off */
    00498 }

static const char* get_case | ( | char * | s,
|  | char ** | restout,
|  | int * | pattern |
| ) |  |  | `[static]`

Definition at line 318 of file pbx_ael.c.

References ast_verbose(), and DEBUG_TOKENS.

Referenced by __build_step().

    00319 {
    00320    char *newcase=NULL;
    00321    char *rest=NULL;
    00322    if (!strncasecmp(s, "case", 4) && s[4] && ((s[4] < 33) || (s[4] == ':'))) {
    00323       newcase = s + 4;
    00324       newcase = ast_skip_blanks(newcase);
    00325       rest = newcase;
    00326       *pattern = 0;
    00327    } else if (!strncasecmp(s, "pattern", 7) && s[7] && ((s[7] < 33) || (s[7] == ':'))) {
    00328       newcase = s + 8;
    00329       newcase = ast_skip_blanks(newcase);
    00330       rest = newcase;
    00331       *pattern = 1;
    00332    } else if (!strncasecmp(s, "default", 7) && ((s[7] < 33) || (s[7] == ':'))) {
    00333       newcase = ".";
    00334       rest = s + 7;
    00335       rest = ast_skip_blanks(rest);
    00336       *pattern = 1;
    00337    }
    00338
    00339    if (rest) {
    00340       while (*rest && (*rest > 32) && (*rest != ':')) rest++;
    00341       if (*rest) {
    00342          *rest = 0;
    00343          rest++;
    00344          while (*rest && ((*rest == ':') || (*rest < 33))) rest++;
    00345          *restout = rest;
    00346       } else {
    00347          *restout = "";
    00348       }
    00349    } else
    00350       *restout = s;
    00351    if (aeldebug & DEBUG_TOKENS)
    00352       ast_verbose("GETCASE: newcase is '%s', rest = '%s'\n", newcase, *restout);
    00353    return newcase;
    00354 }

static char* grab_else | ( | char * | args,
|  | const char * | filename,
|  | int | lineno |
| ) |  |  | `[static]`

Definition at line 163 of file pbx_ael.c.

References ast_verbose(), and DEBUG_TOKENS.

Referenced by __build_step().

    00164 {
    00165    char *ret = NULL;
    00166    int level=0;
    00167    char *c;
    00168    if (args) {
    00169       if (args[0] == '{') {
    00170          c = args;
    00171          while(*c) {
    00172             if (*c == '{')
    00173                level++;
    00174             else if (*c == '}') {
    00175                level--;
    00176                if (!level) {
    00177                   c++;
    00178                   while(*c && (*c < 33)) { *c = '\0'; c++; };
    00179                   if (!strncasecmp(c, "else", 4) &&
    00180                      ((c[4] == '{') || (c[4] < 33))) {
    00181                         /* Ladies and gentlemen, we have an else clause */
    00182                      *c = '\0';
    00183                      c += 4;
    00184                      c = ast_skip_blanks(c);
    00185                      ret = c;
    00186                      if (aeldebug & DEBUG_TOKENS)
    00187                         ast_verbose("Returning else clause '%s'\n", c);
    00188                   }
    00189                   break;
    00190                }
    00191             }
    00192             c++;
    00193          }
    00194       }
    00195    }
    00196    return ret;
    00197 }

static char* grab_token | ( | char * | src,
|  | const char * | filename,
|  | int | lineno |
| ) |  |  | `[static]`

Definition at line 130 of file pbx_ael.c.

References __grab_token().

Referenced by ast_ael_compile().

    00131 {
    00132    return __grab_token(src, filename, lineno, 0);
    00133 }

static void handle_context | ( | struct ast_context ** | local_contexts,
|  | struct stringlink * | vars,
|  | const char * | filename,
|  | int | lineno |
| ) |  |  | `[static]`

Definition at line 1045 of file pbx_ael.c.

References arg_free(), arg_parse(), ast_context_add_ignorepat2(), ast_context_add_include2(), ast_context_add_switch2(), ast_context_create(), ast_log(), ast_verbose(), build_step(), stringlink::data, DEBUG_CONTEXTS, LOG_NOTICE, LOG_WARNING, matches_extension(), matches_keyword(), name, stringlink::next, parse_keyword(), and split_token().

Referenced by handle_root_token().

    01046 {
    01047    struct stringlink *argv;
    01048    struct stringlink *cur2;
    01049    struct stringlink *argv2;
    01050    struct stringlink *cur;
    01051    struct ast_context *con;
    01052    char *rest;
    01053    char *c;
    01054    char name[256];
    01055    int pos;
    01056
    01057    if (aeldebug & DEBUG_CONTEXTS)
    01058       ast_verbose("Root context def is '%s'\n", vars->data);
    01059    argv = split_token(vars->data, filename, lineno);
    01060    if (aeldebug & DEBUG_CONTEXTS)
    01061       ast_verbose("Found context '%s'\n", vars->data);
    01062    snprintf(name, sizeof(name), "%s", vars->data);
    01063    con = ast_context_create(local_contexts, name, registrar);
    01064    if (con) {
    01065       cur = argv;
    01066       while(cur) {
    01067          if (matches_keyword(cur->data, "includes")) {
    01068             if (aeldebug & DEBUG_CONTEXTS)
    01069                ast_verbose("--INCLUDES: '%s'\n", cur->data);
    01070             parse_keyword(cur->data, &rest);
    01071             if (rest) {
    01072                argv2 = arg_parse(rest, filename, lineno);
    01073                cur2 = argv2;
    01074                while(cur2) {
    01075                   ast_context_add_include2(con, cur2->data, registrar);
    01076                   cur2 = cur2->next;
    01077                }
    01078                arg_free(argv2);
    01079             }
    01080          } else if (matches_keyword(cur->data, "ignorepat")) {
    01081             if (aeldebug & DEBUG_CONTEXTS)
    01082                ast_verbose("--IGNOREPAT: '%s'\n", cur->data);
    01083             parse_keyword(cur->data, &rest);
    01084             if (rest) {
    01085                argv2 = arg_parse(rest, filename, lineno);
    01086                cur2 = argv2;
    01087                while(cur2) {
    01088                   ast_context_add_ignorepat2(con, cur2->data, registrar);
    01089                   cur2 = cur2->next;
    01090                }
    01091                arg_free(argv2);
    01092             }
    01093          } else if (matches_keyword(cur->data, "switches") || matches_keyword(cur->data, "eswitches")) {
    01094             if (aeldebug & DEBUG_CONTEXTS)
    01095                ast_verbose("--[E]SWITCH: '%s'\n", cur->data);
    01096             parse_keyword(cur->data, &rest);
    01097             if (rest) {
    01098                argv2 = arg_parse(rest, filename, lineno);
    01099                cur2 = argv2;
    01100                while(cur2) {
    01101                   c = strchr(cur2->data, '/');
    01102                   if (c) {
    01103                      *c = '\0';
    01104                      c++;
    01105                   } else
    01106                      c = "";
    01107                   ast_context_add_switch2(con, cur2->data, c, (cur->data[0] == 'e'), registrar);
    01108                   cur2 = cur2->next;
    01109                }
    01110                arg_free(argv2);
    01111             }
    01112          } else if (matches_extension(cur->data, &rest)) {
    01113             if (aeldebug & DEBUG_CONTEXTS)
    01114                ast_verbose("Extension: '%s' => '%s'\n", cur->data, rest);
    01115             pos = 1;
    01116             build_step("extension", cur->data, filename, lineno, con, cur->data, &pos, rest, NULL, NULL);
    01117          }
    01118          cur = cur->next;
    01119       }
    01120    } else
    01121          ast_log(LOG_WARNING, "Unable to create context '%s'\n", name);
    01122    arg_free(argv);
    01123    if (vars->next)
    01124       ast_log(LOG_NOTICE, "Ignoring excess tokens in macro definition around line %d of %s!\n", lineno, filename);
    01125 }

static void handle_globals | ( | struct stringlink * | vars | ) | `[static]`

Definition at line 251 of file pbx_ael.c.

References stringlink::data, stringlink::next, and pbx_builtin_setvar().

Referenced by handle_root_token().

    00252 {
    00253    while(vars) {
    00254       pbx_builtin_setvar(NULL, vars->data);
    00255       vars = vars->next;
    00256    }
    00257 }

static void handle_macro | ( | struct ast_context ** | local_contexts,
|  | struct stringlink * | vars,
|  | const char * | filename,
|  | int | lineno |
| ) |  |  | `[static]`

Definition at line 947 of file pbx_ael.c.

References arg_free(), ast_add_extension2(), ast_context_create(), ast_log(), ast_verbose(), build_step(), stringlink::data, DEBUG_MACROS, FREE, LOG_NOTICE, LOG_WARNING, matches_keyword(), name, stringlink::next, parse_catch(), split_params(), split_token(), and strdup.

Referenced by handle_root_token().

    00948 {
    00949    struct stringlink *argv;
    00950    struct stringlink *paramv;
    00951    struct stringlink *cur;
    00952    struct ast_context *con;
    00953    struct fillin *fillin;
    00954    char *catch, *rest;
    00955    char name[256];
    00956    int pos;
    00957    int cpos;
    00958
    00959    if (aeldebug & DEBUG_MACROS)
    00960       ast_verbose("Root macro def is '%s'\n", vars->data);
    00961    argv = split_token(vars->data, filename, lineno);
    00962    paramv = split_params(vars->data, filename, lineno);
    00963    if (aeldebug & DEBUG_MACROS)
    00964       ast_verbose("Found macro '%s'\n", vars->data);
    00965    snprintf(name, sizeof(name), "macro-%s", vars->data);
    00966    con = ast_context_create(local_contexts, name, registrar);
    00967    if (con) {
    00968       pos = 1;
    00969       cur = paramv;
    00970       while(cur) {
    00971          if (aeldebug & DEBUG_MACROS)
    00972             ast_verbose("  PARAM => '%s'\n", cur->data);
    00973          snprintf(name, sizeof(name), "%s=${ARG%d}", cur->data, pos);
    00974          if (ast_add_extension2(con, 0, "s", pos, NULL, NULL, "Set", strdup(name), FREE, registrar))
    00975             ast_log(LOG_WARNING, "Unable to add step at priority '%d' of macro '%s'\n", pos, vars->data);
    00976          else
    00977             pos++;
    00978          cur = cur->next;
    00979       }
    00980       cur = argv;
    00981       while(cur) {
    00982          if (aeldebug & DEBUG_MACROS)
    00983             ast_verbose("  STEP => '%s'\n", cur->data);
    00984          if (matches_keyword(cur->data, "catch")) {
    00985             if (aeldebug & DEBUG_MACROS)
    00986                ast_verbose("--CATCH: '%s'\n", cur->data);
    00987             if (parse_catch(cur->data, &catch, &rest)) {
    00988                cpos = 1;
    00989                build_step("catch", catch, filename, lineno, con, catch, &cpos, rest, NULL, NULL);
    00990             } else
    00991                ast_log(LOG_NOTICE, "Parse error for catch at about line %d of %s\n", lineno, filename);
    00992          } else {
    00993             fillin = NULL;
    00994             build_step("macro", vars->data, filename, lineno, con, "s", &pos, cur->data, NULL, NULL);
    00995          }
    00996          cur = cur->next;
    00997       }
    00998    } else
    00999       ast_log(LOG_WARNING, "Unable to create context '%s'\n", name);
    01000    arg_free(paramv);
    01001    arg_free(argv);
    01002    if (vars->next)
    01003       ast_log(LOG_NOTICE, "Ignoring excess tokens in macro definition around line %d of %s!\n", lineno, filename);
    01004 }

static int handle_root_token | ( | struct ast_context ** | local_contexts,
|  | char * | token,
|  | int | level,
|  | const char * | filename,
|  | int | lineno |
| ) |  |  | `[static]`

Definition at line 1127 of file pbx_ael.c.

References arg_free(), ast_log(), ast_verbose(), stringlink::data, DEBUG_TOKENS, handle_context(), handle_globals(), handle_macro(), LOG_NOTICE, stringlink::next, and split_token().

Referenced by ast_ael_compile().

    01128 {
    01129    struct stringlink *argv, *cur;
    01130    argv = split_token(token, filename, lineno);
    01131    if (aeldebug & DEBUG_TOKENS) {
    01132       ast_verbose("Found root token '%s' at level %d (%s:%d)!\n", token, level, filename, lineno);
    01133       cur = argv;
    01134       while(cur) {
    01135          ast_verbose("   ARG => '%s'\n", cur->data);
    01136          cur = cur->next;
    01137       }
    01138    }
    01139    if (!strcasecmp(token, "globals")) {
    01140       handle_globals(argv);
    01141    } else if (!strcasecmp(token, "macro")) {
    01142       handle_macro(local_contexts, argv, filename, lineno);
    01143    } else if (!strcasecmp(token, "context")) {
    01144       handle_context(local_contexts, argv, filename, lineno);
    01145    } else {
    01146       ast_log(LOG_NOTICE, "Unknown root token '%s'\n", token);
    01147    }
    01148    arg_free(argv);
    01149    return 0;
    01150 }

char* key | ( | void |  | ) |

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

     char *key(void) {
             return ASTERISK_GPL_KEY;
     }

Returns:
  ASTERISK_GPL_KEY

Definition at line 1307 of file pbx_ael.c.

References ASTERISK_GPL_KEY.

    01308 {
    01309    return ASTERISK_GPL_KEY;
    01310 }

int load_module | ( | void |  | ) |

Initialize the module.

This function is called at module load time. Put all code in here that needs to set up your module's hardware, software, registrations, etc.

Returns:
  This function should return 0 on success and non-zero on failure. If the module is not loaded successfully, Asterisk will call its unload_module() function.

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
  int Always 0.

TE STUFF END

Definition at line 1285 of file pbx_ael.c.

References ast_cli_register_multiple(), and pbx_load_module().

    01286 {
    01287    ast_cli_register_multiple(ael_cli, sizeof(ael_cli)/ sizeof(ael_cli[0]));
    01288    return (pbx_load_module());
    01289 }

static int match_assignment | ( | char * | variable,
|  | char ** | value |
| ) |  |  | `[static]`

Definition at line 403 of file pbx_ael.c.

Referenced by __build_step().

    00404 {
    00405    char *c;
    00406    char *ws;
    00407    int inpar = 0;
    00408    c = variable;
    00409
    00410    while (*c) {
    00411       if(*c == ')' && (inpar > 0)) {
    00412          inpar--;
    00413       } else if(*c == '(' && (inpar >= 0)) {
    00414          inpar++;
    00415       } else if(*c == '=' && (inpar == 0)) {
    00416          break;
    00417       }
    00418       c++;
    00419    }
    00420    ws = c;
    00421    c = ast_skip_blanks(c);
    00422    if (*c == '=') {
    00423       *ws = '\0';
    00424       *c = '\0';
    00425       c++;
    00426       c = ast_skip_blanks(c);
    00427       *value = c;
    00428       return 1;
    00429    }
    00430    return 0;
    00431 }

static int matches_extension | ( | char * | exten,
|  | char ** | extout |
| ) |  |  | `[static]`

Definition at line 1006 of file pbx_ael.c.

Referenced by handle_context().

    01007 {
    01008    char *c;
    01009    *extout = NULL;
    01010    c = exten;
    01011    while(*c && (*c > 32)) c++;
    01012    if (*c) {
    01013       *c = '\0';
    01014       c++;
    01015       c = ast_skip_blanks(c);
    01016       if (*c) {
    01017          if (*c == '=') {
    01018             *c = '\0';
    01019             c++;
    01020             if (*c == '>')
    01021                c++;
    01022             c = ast_skip_blanks(c);
    01023             *extout = c;
    01024             return 1;
    01025          }
    01026       }
    01027    }
    01028    return 0;
    01029 }

static int matches_keyword | ( | const char * | data,
|  | const char * | keyword |
| ) |  |  | `[static]`

Definition at line 286 of file pbx_ael.c.

Referenced by __build_step(), handle_context(), and handle_macro().

    00287 {
    00288    char c;
    00289    if (!strncasecmp(data, keyword, strlen(keyword))) {
    00290       c = data[strlen(keyword)];
    00291       if ((c < 33) || (c == '(') || (c == '{'))
    00292          return 1;
    00293    }
    00294    return 0;
    00295 }

static int matches_label | ( | char * | data,
|  | char ** | rest |
| ) |  |  | `[static]`

Definition at line 433 of file pbx_ael.c.

References last.

Referenced by __build_step().

    00434 {
    00435    char last = 0;
    00436    char *start = data;
    00437    while (*data > 32) {
    00438       last = *data;
    00439       data++;
    00440    }
    00441    if (last != ':') {
    00442       data = ast_skip_blanks(data);
    00443       last = *data;
    00444       data++;
    00445    }
    00446    if (last == ':') {
    00447       *rest = data;
    00448       /* Go back and trim up the label */
    00449       while(*start && ((*start > 32) && (*start != ':'))) start++;
    00450       *start = '\0';
    00451       return 1;
    00452    }
    00453    return 0;
    00454 }

static struct stringlink* param_parse | ( | char * | parms,
|  | const char * | macro,
|  | const char * | filename,
|  | int | lineno |
| ) |  |  | `[static, read]`

Definition at line 199 of file pbx_ael.c.

References ast_log(), LOG_NOTICE, malloc, and s.

Referenced by split_params().

    00200 {
    00201    char *s, *e;
    00202    struct stringlink *root = NULL, *prev=NULL, *cur;
    00203    if (!parms || !*parms)
    00204       return NULL;
    00205    if (*parms != '(') {
    00206       ast_log(LOG_NOTICE, "Syntax error in parameter list for macro '%s' at about line %d of %s: Expecting '(' but got '%c'\n", macro, lineno, filename, *parms);
    00207       return NULL;
    00208    }
    00209    s = parms + 1;
    00210    while(*s) {
    00211       s = ast_skip_blanks(s);
    00212       e = s;
    00213       while(*e &&  (*e != ')') && (*e != ',')) {
    00214          if (*e < 33)
    00215             *e = '\0';
    00216          e++;
    00217       }
    00218       if (*e) {
    00219          /* Strip token */
    00220          *e = '\0';
    00221          e++;
    00222          /* Skip over whitespace */
    00223          e = ast_skip_blanks(e);
    00224          /* Link */
    00225          cur = malloc(strlen(s) + sizeof(struct stringlink) + 1);
    00226          if (cur) {
    00227             cur->next = NULL;
    00228             strcpy(cur->data, s);
    00229             if (prev)
    00230                prev->next = cur;
    00231             else
    00232                root = cur;
    00233             prev = cur;
    00234          }
    00235          s = e;
    00236       }
    00237    }
    00238    return root;
    00239 }

static int parse_catch | ( | char * | data,
|  | char ** | catch,
|  | char ** | rest |
| ) |  |  | `[static]`

Definition at line 925 of file pbx_ael.c.

Referenced by handle_macro().

    00926 {
    00927    /* Skip the word 'catch' */
    00928    data += 5;
    00929    data = ast_skip_blanks(data);
    00930    /* Here's the extension */
    00931    *catch = data;
    00932    if (!*data)
    00933       return 0;
    00934    while (*data && (*data > 32)) data++;
    00935    if (!*data)
    00936       return 0;
    00937    /* Trim any trailing spaces */
    00938    *data = '\0';
    00939    data++;
    00940    data = ast_skip_blanks(data);
    00941    if (!*data)
    00942       return 0;
    00943    *rest = data;
    00944    return 1;
    00945 }

static void parse_keyword | ( | char * | s,
|  | char ** | o |
| ) |  |  | `[static]`

Definition at line 1031 of file pbx_ael.c.

Referenced by handle_context().

    01032 {
    01033    char *c;
    01034    c = s;
    01035    while((*c) && (*c > 32)) c++;
    01036    if (*c) {
    01037       *c = '\0';
    01038       c++;
    01039       c = ast_skip_blanks(c);
    01040       *o = c;
    01041    } else
    01042       *o = NULL;
    01043 }

static int pbx_load_module | ( | void |  | ) | `[static]`

Definition at line 1217 of file pbx_ael.c.

References ast_ael_compile(), ast_context_verify_includes(), ast_merge_contexts_and_delete(), ast_walk_contexts(), and local_contexts.

Referenced by ael_reload(), handle_reload_extensions(), load_module(), and reload().

    01218 {
    01219    struct ast_context *local_contexts=NULL, *con;
    01220    ast_ael_compile(&local_contexts, config);
    01221    ast_merge_contexts_and_delete(&local_contexts, registrar);
    01222    for (con = ast_walk_contexts(NULL); con; con = ast_walk_contexts(con))
    01223       ast_context_verify_includes(con);
    01224
    01225    return 0;
    01226 }

int reload | ( | void |  | ) |

Reload stuff.

This function is where any reload routines take place. Re-read config files, change signalling, whatever is appropriate on a reload.

Returns:
  The return value is not used.

Definition at line 1291 of file pbx_ael.c.

References ast_context_destroy(), and pbx_load_module().

    01292 {
    01293    ast_context_destroy(NULL, registrar);
    01294    return pbx_load_module();
    01295 }

static struct stringlink* split_params | ( | char * | token,
|  | const char * | filename,
|  | int | lineno |
| ) |  |  | `[static, read]`

Definition at line 297 of file pbx_ael.c.

References param_parse().

Referenced by handle_macro().

    00298 {
    00299    char *params;
    00300    struct stringlink *paramv;
    00301    params = token;
    00302    while(*params && (*params > 32) && (*params != '(')) params++;
    00303    if (*params) {
    00304       if (*params != '(') {
    00305          *params = '\0';
    00306          params++;
    00307          params = ast_skip_blanks(params);
    00308       }
    00309       if (!*params)
    00310          params = NULL;
    00311    } else params = NULL;
    00312    paramv = param_parse(params, token, filename, lineno);
    00313    if (params)
    00314       *params = '\0';
    00315    return paramv;
    00316 }

static struct stringlink* split_token | ( | char * | token,
|  | const char * | filename,
|  | int | lineno |
| ) |  |  | `[static, read]`

Definition at line 259 of file pbx_ael.c.

References arg_parse().

Referenced by handle_context(), handle_macro(), and handle_root_token().

    00260 {
    00261    char *args, *p;
    00262    struct stringlink *argv;
    00263    args = token;
    00264    while (*args && (*args > 32) && (*args != '{') && (*args != '(')) args++;
    00265    if (*args) {
    00266       p = args;
    00267       args = ast_skip_blanks(args);
    00268       if (*args != '(') {
    00269          *p = '\0';
    00270       } else {
    00271          while (*args && (*args != ')')) args++;
    00272          if (*args == ')') {
    00273             args++;
    00274             args = ast_skip_blanks(args);
    00275          }
    00276       }
    00277       if (!*args)
    00278          args = NULL;
    00279    } else args = NULL;
    00280    argv = arg_parse(args, filename, lineno);
    00281    if (args)
    00282       *args = '\0';
    00283    return argv;
    00284 }

int unload_module | ( | void |  | ) |

Cleanup all module structures, sockets, etc.

This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).

Returns:
  Zero on success, or non-zero on error.

Definition at line 1277 of file pbx_ael.c.

References ast_cli_unregister_multiple(), and ast_context_destroy().

    01278 {
    01279    ast_context_destroy(NULL, registrar);
    01280    ast_cli_unregister_multiple(ael_cli, sizeof(ael_cli)/ sizeof(ael_cli[0]));
    01281    return 0;
    01282 }

int usecount | ( | void |  | ) |

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
  The module's usecount.

Definition at line 1297 of file pbx_ael.c.

    01298 {
    01299    return 0;
    01300 }

## Variable Documentation

struct ast_cli_entry ael_cli[]`[static]`

Definition at line 1265 of file pbx_ael.c.

int aeldebug = 0`[static]`

Definition at line 72 of file pbx_ael.c.

char* config = "extensions.ael"`[static]`

Definition at line 75 of file pbx_ael.c.

char* dtext = "Asterisk Extension Language Compiler"`[static]`

Definition at line 74 of file pbx_ael.c.

char* registrar = "pbx_ael"`[static]`

Definition at line 76 of file pbx_ael.c.