check_expr.c File Reference

#include "asterisk.h"
#include "asterisk/ast_expr.h"
#include "asterisk/inline_api.h"
#include "asterisk/lock.h"

Include dependency graph for check_expr.c:

Go to the source code of this file.

Data Structures

struct  varz

Defines

#define AST_API_MODULE   1
#define AST_API_MODULE   1

Enumerations

enum  ast_lock_type { AST_MUTEX, AST_RDLOCK, AST_WRLOCK }

Functions

int ast_add_profile (const char *x, uint64_t scale)
 support for event profiling
int ast_atomic_fetchadd_int_slow (volatile int *p, int v)
struct ast_custom_functionast_custom_function_find (const char *name)
void ast_log (int level, const char *file, int line, const char *function, const char *fmt,...)
 Used for sending a log message This is the standard logger function. Probably the only way you will invoke it would be something like this: ast_log(AST_LOG_WHATEVER, "Problem with the %s Captain. We should get some more. Will %d be enough?\n", "flux capacitor", 10); where WHATEVER is one of ERROR, DEBUG, EVENT, NOTICE, or WARNING depending on which log you wish to output to. These are implemented as macros, that will provide the function with the needed arguments.
void ast_register_file_version (const char *file, const char *version)
 Register the version of a source code file with the core.
void ast_unregister_file_version (const char *file)
 Unregister a source code file from the core.
int check_eval (char *buffer, char *error_report)
unsigned int check_expr (char *buffer, char *error_report)
char * find_var (const char *varname)
int main (int argc, char **argv)
void parse_file (const char *fname)
void set_var (const char *varname, const char *varval)

Variables

static int global_expr_count = 0
static int global_expr_max_size = 0
static int global_expr_tot_size = 0
static int global_lineno = 1
static int global_OK_count = 0
struct varzglobal_varlist
static int global_warn_count = 0


Define Documentation

#define AST_API_MODULE   1

Definition at line 31 of file check_expr.c.

#define AST_API_MODULE   1

Definition at line 31 of file check_expr.c.


Enumeration Type Documentation

Enumerator:
AST_MUTEX 
AST_RDLOCK 
AST_WRLOCK 

Definition at line 35 of file check_expr.c.

00035                    {
00036            AST_MUTEX,
00037            AST_RDLOCK,
00038            AST_WRLOCK,
00039 };


Function Documentation

int ast_add_profile ( const char *  x,
uint64_t  scale 
)

support for event profiling

allocates a counter with a given name and scale.

(note, this must be documented a lot more) ast_add_profile allocates a generic 'counter' with a given name, which can be shown with the command 'core show profile <name>'

The counter accumulates positive or negative values supplied by

See also:
ast_add_profile(), dividing them by the 'scale' value passed in the create call, and also counts the number of 'events'. Values can also be taked by the TSC counter on ia32 architectures, in which case you can mark the start of an event calling ast_mark(id, 1) and then the end of the event with ast_mark(id, 0). For non-i386 architectures, these two calls return 0.
support for event profiling

Returns:
Returns the identifier of the counter.

Definition at line 167 of file check_expr.c.

00167 { return 0;} 

int ast_atomic_fetchadd_int_slow ( volatile int *  p,
int  v 
)

Definition at line 169 of file check_expr.c.

00170 {
00171         int ret;
00172         ret = *p;
00173         *p += v;
00174         return ret;
00175 }

struct ast_custom_function* ast_custom_function_find ( const char *  name  )  [read]

Definition at line 4019 of file pbx.c.

04020 {
04021    struct ast_custom_function *acf;
04022 
04023    AST_RWLIST_RDLOCK(&acf_root);
04024    acf = ast_custom_function_find_nolock(name);
04025    AST_RWLIST_UNLOCK(&acf_root);
04026 
04027    return acf;
04028 }

void ast_log ( int  level,
const char *  file,
int  line,
const char *  function,
const char *  fmt,
  ... 
)

Used for sending a log message This is the standard logger function. Probably the only way you will invoke it would be something like this: ast_log(AST_LOG_WHATEVER, "Problem with the %s Captain. We should get some more. Will %d be enough?\n", "flux capacitor", 10); where WHATEVER is one of ERROR, DEBUG, EVENT, NOTICE, or WARNING depending on which log you wish to output to. These are implemented as macros, that will provide the function with the needed arguments.

Parameters:
level Type of log event
file Will be provided by the AST_LOG_* macro
line Will be provided by the AST_LOG_* macro
function Will be provided by the AST_LOG_* macro
fmt This is what is important. The format is the same as your favorite breed of printf. You know how that works, right? :-)

Definition at line 1707 of file logger.c.

01708 {
01709    ast_callid callid;
01710    va_list ap;
01711 
01712    callid = ast_read_threadstorage_callid();
01713 
01714    va_start(ap, fmt);
01715    if (level == __LOG_VERBOSE) {
01716       __ast_verbose_ap(file, line, function, 0, callid, fmt, ap);
01717    } else {
01718       ast_log_full(level, file, line, function, callid, fmt, ap);
01719    }
01720    va_end(ap);
01721 }

void ast_register_file_version ( const char *  file,
const char *  version 
)

Register the version of a source code file with the core.

Parameters:
file the source file name
version the version string (typically a SVN revision keyword string)
Returns:
nothing
This function should not be called directly, but instead the ASTERISK_FILE_VERSION macro should be used to register a file with the core.

Definition at line 486 of file asterisk.c.

00487 {
00488    struct file_version *new;
00489    char *work;
00490    size_t version_length;
00491 
00492    work = ast_strdupa(version);
00493    work = ast_strip(ast_strip_quoted(work, "$", "$"));
00494    version_length = strlen(work) + 1;
00495 
00496    if (!(new = ast_calloc(1, sizeof(*new) + version_length)))
00497       return;
00498 
00499    new->file = file;
00500    new->version = (char *) new + sizeof(*new);
00501    memcpy(new->version, work, version_length);
00502    AST_RWLIST_WRLOCK(&file_versions);
00503    AST_RWLIST_INSERT_HEAD(&file_versions, new, list);
00504    AST_RWLIST_UNLOCK(&file_versions);
00505 }

void ast_unregister_file_version ( const char *  file  ) 

Unregister a source code file from the core.

Parameters:
file the source file name
Returns:
nothing
This function should not be called directly, but instead the ASTERISK_FILE_VERSION macro should be used to automatically unregister the file when the module is unloaded.

Definition at line 507 of file asterisk.c.

00508 {
00509    struct file_version *find;
00510 
00511    AST_RWLIST_WRLOCK(&file_versions);
00512    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&file_versions, find, list) {
00513       if (!strcasecmp(find->file, file)) {
00514          AST_RWLIST_REMOVE_CURRENT(list);
00515          break;
00516       }
00517    }
00518    AST_RWLIST_TRAVERSE_SAFE_END;
00519    AST_RWLIST_UNLOCK(&file_versions);
00520 
00521    if (find)
00522       ast_free(find);
00523 }

int check_eval ( char *  buffer,
char *  error_report 
)

Definition at line 283 of file check_expr.c.

References ast_expr(), find_var(), NULL, and result.

Referenced by parse_file().

00284 {
00285    char *cp, *ep;
00286    char s[4096];
00287    char evalbuf[80000];
00288    int result;
00289 
00290    error_report[0] = 0;
00291    ep = evalbuf;
00292 
00293    for (cp=buffer;*cp;cp++) {
00294       if (*cp == '$' && *(cp+1) == '{') {
00295          int brack_lev = 1;
00296          char *xp= cp+2;
00297          
00298          while (*xp) {
00299             if (*xp == '{')
00300                brack_lev++;
00301             else if (*xp == '}')
00302                brack_lev--;
00303             
00304             if (brack_lev == 0)
00305                break;
00306             xp++;
00307          }
00308          if (*xp == '}') {
00309             char varname[200];
00310             char *val;
00311             
00312             strncpy(varname,cp+2, xp-cp-2);
00313             varname[xp-cp-2] = 0;
00314             cp = xp;
00315             val = find_var(varname);
00316             if (val) {
00317                char *z = val;
00318                while (*z)
00319                   *ep++ = *z++;
00320             }
00321             else {
00322                *ep++ = '5';  /* why not */
00323                *ep++ = '5';
00324                *ep++ = '5';
00325             }
00326          }
00327          else {
00328             printf("Unterminated variable reference at line %d\n", global_lineno);
00329             *ep++ = *cp;
00330          }
00331       }
00332       else if (*cp == '\\') {
00333          /* braindead simple elim of backslash */
00334          cp++;
00335          *ep++ = *cp;
00336       }
00337       else
00338          *ep++ = *cp;
00339    }
00340    *ep++ = 0;
00341 
00342    /* now, run the test */
00343    result = ast_expr(evalbuf, s, sizeof(s),NULL);
00344    if (result) {
00345       sprintf(error_report,"line %d, evaluation of $[ %s ] result: %s\n", global_lineno, evalbuf, s);
00346       return 1;
00347    } else {
00348       sprintf(error_report,"line %d, evaluation of $[ %s ] result: ****SYNTAX ERROR****\n", global_lineno, evalbuf);
00349       return 1;
00350    }
00351 }

unsigned int check_expr ( char *  buffer,
char *  error_report 
)

Definition at line 206 of file check_expr.c.

Referenced by parse_file().

00207 {
00208    char* cp;
00209    unsigned int warn_found = 0;
00210 
00211    error_report[0] = 0;
00212    
00213    for (cp = buffer; *cp; ++cp)
00214    {
00215       switch (*cp)
00216       {
00217          case '"':
00218             /* skip to the other end */
00219             while (*(++cp) && *cp != '"') ;
00220 
00221             if (*cp == 0)
00222             {
00223                fprintf(stderr,
00224                   "Trouble? Unterminated double quote found at line %d\n",
00225                   global_lineno);
00226             }
00227             break;
00228             
00229          case '>':
00230          case '<':
00231          case '!':
00232             if (   (*(cp + 1) == '=')
00233                && ( ( (cp > buffer) && (*(cp - 1) != ' ') ) || (*(cp + 2) != ' ') ) )
00234             {
00235                char msg[200];
00236                snprintf(msg,
00237                   sizeof(msg),
00238                   "WARNING: line %d: '%c%c' operator not separated by spaces. This may lead to confusion. You may wish to use double quotes to quote the grouping it is in. Please check!\n",
00239                   global_lineno, *cp, *(cp + 1));
00240                strcat(error_report, msg);
00241                ++global_warn_count;
00242                ++warn_found;
00243             }
00244             break;
00245             
00246          case '|':
00247          case '&':
00248          case '=':
00249          case '+':
00250          case '-':
00251          case '*':
00252          case '/':
00253          case '%':
00254          case '?':
00255          case ':':
00256             if ( ( (cp > buffer) && (*(cp - 1) != ' ') ) || (*(cp + 1) != ' ') )
00257             {
00258                char msg[200];
00259                snprintf(msg,
00260                   sizeof(msg),
00261                   "WARNING: line %d: '%c' operator not separated by spaces. This may lead to confusion. You may wish to use double quotes to quote the grouping it is in. Please check!\n",
00262                   global_lineno, *cp );
00263                strcat(error_report, msg);
00264                ++global_warn_count;
00265                ++warn_found;
00266             }
00267             break;
00268       }
00269    }
00270 
00271    return warn_found;
00272 }

char * find_var ( const char *  varname  ) 

Definition at line 182 of file check_expr.c.

References varz::next, varz::varname, and varz::varval.

Referenced by check_eval().

00183 {
00184    struct varz *t;
00185    for (t= global_varlist; t; t = t->next) {
00186       if (!strcmp(t->varname, varname)) {
00187          return t->varval;
00188       }
00189    }
00190    return 0;
00191 }

int main ( int  argc,
char **  argv 
)

Definition at line 447 of file check_expr.c.

References parse_file(), and set_var().

00448 {
00449    int argc1;
00450    char *eq;
00451    
00452    if (argc < 2) {
00453       printf("check_expr -- a program to look thru extensions.conf files for $[...] expressions,\n");
00454       printf("              and run them thru the parser, looking for problems\n");
00455       printf("Hey-- give me a path to an extensions.conf file!\n");
00456       printf(" You can also follow the file path with a series of variable decls,\n");
00457       printf("     of the form, varname=value, each separated from the next by spaces.\n");
00458       printf("     (this might allow you to avoid division by zero messages, check that math\n");
00459       printf("      is being done correctly, etc.)\n");
00460       printf(" Note that messages about operators not being surrounded by spaces is merely to alert\n");
00461       printf("  you to possible problems where you might be expecting those operators as part of a string.\n");
00462         printf("  (to include operators in a string, wrap with double quotes!)\n");
00463       
00464       exit(19);
00465    }
00466    global_varlist = 0;
00467    for (argc1=2;argc1 < argc; argc1++) {
00468       if ((eq = strchr(argv[argc1],'='))) {
00469          *eq = 0;
00470          set_var(argv[argc1],eq+1);
00471       }
00472    }
00473 
00474    /* parse command args for x=y and set varz */
00475    
00476    parse_file(argv[1]);
00477    return 0;
00478 }

void parse_file ( const char *  fname  ) 

Definition at line 356 of file check_expr.c.

References check_eval(), check_expr(), f, and retval.

Referenced by main().

00357 {
00358    FILE *f = fopen(fname,"r");
00359    FILE *l = fopen("expr2_log","w");
00360    int c1;
00361    char last_char= 0;
00362    char buffer[30000]; /* I sure hope no expr gets this big! */
00363    
00364    if (!f) {
00365       fprintf(stderr,"Couldn't open %s for reading... need an extensions.conf file to parse!\n",fname);
00366       exit(20);
00367    }
00368    if (!l) {
00369       fprintf(stderr,"Couldn't open 'expr2_log' file for writing... please fix and re-run!\n");
00370       exit(21);
00371    }
00372    
00373    global_lineno = 1;
00374    
00375    while ((c1 = fgetc(f)) != EOF) {
00376       if (c1 == '\n')
00377          global_lineno++;
00378       else if (c1 == '[') {
00379          if (last_char == '$') {
00380             /* bingo, an expr */
00381             int bracklev = 1;
00382             int bufcount = 0;
00383             int retval;
00384             char error_report[30000];
00385             
00386             while ((c1 = fgetc(f)) != EOF) {
00387                if (c1 == '[')
00388                   bracklev++;
00389                else if (c1 == ']')
00390                   bracklev--;
00391                if (c1 == '\n') {
00392                   fprintf(l, "ERROR-- A newline in an expression? Weird! ...at line %d\n", global_lineno);
00393                   fclose(f);
00394                   fclose(l);
00395                   printf("--- ERROR --- A newline in the middle of an expression at line %d!\n", global_lineno);
00396                }
00397                
00398                if (bracklev == 0)
00399                   break;
00400                buffer[bufcount++] = c1;
00401             }
00402             if (c1 == EOF) {
00403                fprintf(l, "ERROR-- End of File Reached in the middle of an Expr at line %d\n", global_lineno);
00404                fclose(f);
00405                fclose(l);
00406                printf("--- ERROR --- EOF reached in middle of an expression at line %d!\n", global_lineno);
00407                exit(22);
00408             }
00409             
00410             buffer[bufcount] = 0;
00411             /* update stats */
00412             global_expr_tot_size += bufcount;
00413             global_expr_count++;
00414             if (bufcount > global_expr_max_size)
00415                global_expr_max_size = bufcount;
00416             
00417             retval = check_expr(buffer, error_report); /* check_expr should bump the warning counter */
00418             if (retval != 0) {
00419                /* print error report */
00420                printf("Warning(s) at line %d, expression: $[%s]; see expr2_log file for details\n", 
00421                      global_lineno, buffer);
00422                fprintf(l, "%s", error_report);
00423             }
00424             else {
00425                printf("OK -- $[%s] at line %d\n", buffer, global_lineno);
00426                global_OK_count++;
00427             }
00428             error_report[0] = 0;
00429             retval = check_eval(buffer, error_report);
00430             fprintf(l, "%s", error_report);
00431          }
00432       }
00433       last_char = c1;
00434    }
00435    printf("Summary:\n  Expressions detected: %d\n  Expressions OK:  %d\n  Total # Warnings:   %d\n  Longest Expr:   %d chars\n  Ave expr len:  %d chars\n",
00436          global_expr_count,
00437          global_OK_count,
00438          global_warn_count,
00439          global_expr_max_size,
00440          (global_expr_count) ? global_expr_tot_size/global_expr_count : 0);
00441    
00442    fclose(f);
00443    fclose(l);
00444 }

void set_var ( const char *  varname,
const char *  varval 
)

Definition at line 195 of file check_expr.c.

References calloc, varz::next, varz::varname, and varz::varval.

00196 {
00197    struct varz *t = (struct varz*)calloc(1,sizeof(struct varz));
00198    if (!t)
00199       return;
00200    strcpy(t->varname, varname);
00201    strcpy(t->varval, varval);
00202    t->next = global_varlist;
00203    global_varlist = t;
00204 }


Variable Documentation

int global_expr_count = 0 [static]

Definition at line 125 of file check_expr.c.

int global_expr_max_size = 0 [static]

Definition at line 126 of file check_expr.c.

int global_expr_tot_size = 0 [static]

Definition at line 127 of file check_expr.c.

int global_lineno = 1 [static]

Definition at line 124 of file check_expr.c.

int global_OK_count = 0 [static]

Definition at line 129 of file check_expr.c.

Definition at line 138 of file check_expr.c.

int global_warn_count = 0 [static]

Definition at line 128 of file check_expr.c.


Generated on Thu Apr 16 06:30:12 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6