Sat Nov 1 06:31:10 2008

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 stringlinkarg_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 stringlinkparam_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 stringlinksplit_params (char *token, const char *filename, int lineno)
static struct stringlinksplit_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_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(), stringlink::next, and strdup.

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]

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(), local_contexts, 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 ( stru