[asterisk-commits] murf: trunk r114423 - in /trunk: ./ doc/tex/ main/ pbx/ael/ael-test/ pbx/ael/...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Apr 21 16:13:02 CDT 2008


Author: murf
Date: Mon Apr 21 16:13:02 2008
New Revision: 114423

URL: http://svn.digium.com/view/asterisk?view=rev&rev=114423
Log:
(closes issue #12467)
Reported by: atis
Tested by: murf

This upgrade adds the ~~ (concatenation) string operator to expr2.
While not needed in normal runtime pbx operation, it is needed when
raw exprs are being syntax checked. This plays into future syntax-
unification plans. By permission of atis, this addition in trunk 
and the reason of why things are as they are will suffice to close
this bug.



Added:
    trunk/pbx/ael/ael-test/ael-ntest24/
    trunk/pbx/ael/ael-test/ael-ntest24/extensions.ael   (with props)
    trunk/pbx/ael/ael-test/ref.ael-ntest24   (with props)
Modified:
    trunk/CHANGES
    trunk/doc/tex/ael.tex
    trunk/doc/tex/channelvariables.tex
    trunk/main/ast_expr2.c
    trunk/main/ast_expr2.fl
    trunk/main/ast_expr2.h
    trunk/main/ast_expr2.y
    trunk/main/ast_expr2f.c
    trunk/pbx/ael/ael-test/ref.ael-ntest10
    trunk/pbx/ael/ael-test/ref.ael-test1
    trunk/pbx/ael/ael-test/ref.ael-test18
    trunk/pbx/ael/ael-test/ref.ael-test19
    trunk/pbx/ael/ael-test/ref.ael-test3
    trunk/pbx/ael/ael-test/ref.ael-test5
    trunk/pbx/ael/ael-test/ref.ael-test8
    trunk/pbx/ael/ael-test/ref.ael-vtest13
    trunk/pbx/ael/ael-test/ref.ael-vtest17

Modified: trunk/CHANGES
URL: http://svn.digium.com/view/asterisk/trunk/CHANGES?view=diff&rev=114423&r1=114422&r2=114423
==============================================================================
--- trunk/CHANGES (original)
+++ trunk/CHANGES Mon Apr 21 16:13:02 2008
@@ -167,6 +167,10 @@
   * Added a CLI command, "devstate change", which allows you to set custom device
      states from the func_devstate module that provides the DEVICE_STATE() function
      and handling of the "Custom:" devices.
+  * New CLI command: "sip show sched" which shows all ast_sched entries for sip,
+    sorted into the different possible callbacks, with the number of entries
+    currently scheduled for each. Gives you a feel for how busy the sip channel
+    driver is.
 
 SIP changes
 -----------
@@ -500,6 +504,17 @@
      first pass at conversion.
   * aelparse will now read extensions.conf to see if a referenced
      macro or context is there before issueing a warning.
+  * AEL parser sets a local channel variable ~~EXTEN~~, to 
+    preserve the value of ${EXTEN} thru switch statements.
+  * New operator in $[...] expressions: the ~~ operator serves
+    as a concatenation operator. AT THE MOMENT, it is really only
+    necessary and useful in AEL, especially in if() expressions.
+    Operation: ${a} ~~ ${b|  with force both a and b to strings, strip 
+    any enclosing double-quotes, and evaluate to the value of a
+    concatenated with the value of b.  For example if a is set to
+    "xyz"  and b has the value "abc", then ${a} ~~ ${b| would
+    evaluate to xyzabc .
+
 
 Call Features (res_features) Changes
 ------------------------------------

Modified: trunk/doc/tex/ael.tex
URL: http://svn.digium.com/view/asterisk/trunk/doc/tex/ael.tex?view=diff&rev=114423&r1=114422&r2=114423
==============================================================================
--- trunk/doc/tex/ael.tex (original)
+++ trunk/doc/tex/ael.tex Mon Apr 21 16:13:02 2008
@@ -38,7 +38,7 @@
       language, that AEL will compile into.
 \end{itemize}
 
-Any programmer of AEL should be familiar with it's syntax, of course,
+Any programmer of AEL should be familiar with its syntax, of course,
 as well as the Expression syntax, and the Variable syntax.
 
 
@@ -114,9 +114,9 @@
 
 \section{Getting Started}
 
-The AEL parser (pbx\_ael.so) is completely separate from the module
+The AEL parser (res\_ael.so) is completely separate from the module
 that parses extensions.conf (pbx\_config.so). To use AEL, the only
-thing that has to be done is the module pbx\_ael.so must be loaded by
+thing that has to be done is the module res\_ael.so must be loaded by
 Asterisk. This will be done automatically if using 'autoload=yes' in
 \path{/etc/asterisk/modules.conf}. When the module is loaded, it will look
 for 'extensions.ael' in \path{/etc/asterisk/}. extensions.conf and

Modified: trunk/doc/tex/channelvariables.tex
URL: http://svn.digium.com/view/asterisk/trunk/doc/tex/channelvariables.tex?view=diff&rev=114423&r1=114422&r2=114423
==============================================================================
--- trunk/doc/tex/channelvariables.tex (original)
+++ trunk/doc/tex/channelvariables.tex Mon Apr 21 16:13:02 2008
@@ -302,6 +302,27 @@
        will be the result of the "evaluation" of this
        expression.  expr3 will be the result otherwise. This
        operator has the lowest precedence.
+
+   \item \verb!expr1 ~~ expr2!
+
+	Concatenation operator. The two exprs are evaluated and
+	turned into strings, stripped of surrounding double quotes,
+        and are turned into a single string with no invtervening spaces. 
+        This operator is new to trunk after 1.6.0; it is not needed 
+	in existing extensions.conf code. Because of the way asterisk
+	evaluates ${ } and $[ ] constructs (recursively, bottom-
+	up), no $[] or ${} is ever present when the contents
+	of a ${} or $[] is evaluated. Thus, tokens are usually
+	already merged at evaluation time. But, in AEL, various
+	exprs are evaluated raw, and ${} and $[] are gathered
+	and treated as tokens. And in AEL, no two tokens can
+	sit side by side without an intervening operator.
+	So, in AEL, concatenation must be explicitly specified
+	in expressions. This new operator will play well into
+	future plans, where expressions ($[] constructs, and
+	variable references (${} constructs) are merged into a 
+	single grammar. 
+
 \end{itemize}
 
 Parentheses are used for grouping in the usual manner.

Modified: trunk/main/ast_expr2.c
URL: http://svn.digium.com/view/asterisk/trunk/main/ast_expr2.c?view=diff&rev=114423&r1=114422&r2=114423
==============================================================================
--- trunk/main/ast_expr2.c (original)
+++ trunk/main/ast_expr2.c Mon Apr 21 16:13:02 2008
@@ -1,7 +1,9 @@
-/* A Bison parser, made by GNU Bison 2.1a.  */
-
-/* Skeleton parser for Yacc-like parsing with Bison,
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+/* A Bison parser, made by GNU Bison 2.3.  */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+   Free Software Foundation, Inc.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -18,10 +20,18 @@
    Foundation, Inc., 51 Franklin Street, Fifth Floor,
    Boston, MA 02110-1301, USA.  */
 
-/* As a special exception, when this file is copied by Bison into a
-   Bison output file, you may use that output file without restriction.
-   This special exception was added by the Free Software Foundation
-   in version 1.24 of Bison.  */
+/* As a special exception, you may create a larger work that contains
+   part or all of the Bison parser skeleton and distribute that work
+   under terms of your choice, so long as that work isn't itself a
+   parser generator using the skeleton or a modified version thereof
+   as a parser skeleton.  Alternatively, if you modify or redistribute
+   the parser skeleton itself, you may (at your option) remove this
+   special exception, which will cause the skeleton and the resulting
+   Bison output files to be licensed under the GNU General Public
+   License without this special exception.
+
+   This special exception was added by the Free Software Foundation in
+   version 2.2 of Bison.  */
 
 /* C LALR(1) parser skeleton written by Richard Stallman, by
    simplifying the original so-called "semantic" parser.  */
@@ -37,7 +47,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.1a"
+#define YYBISON_VERSION "2.3"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -81,11 +91,12 @@
      TOK_DIV = 272,
      TOK_MULT = 273,
      TOK_COMPL = 274,
-     TOK_EQTILDE = 275,
-     TOK_COLON = 276,
-     TOK_LP = 277,
-     TOK_RP = 278,
-     TOKEN = 279
+     TOK_TILDETILDE = 275,
+     TOK_EQTILDE = 276,
+     TOK_COLON = 277,
+     TOK_LP = 278,
+     TOK_RP = 279,
+     TOKEN = 280
    };
 #endif
 /* Tokens.  */
@@ -106,11 +117,12 @@
 #define TOK_DIV 272
 #define TOK_MULT 273
 #define TOK_COMPL 274
-#define TOK_EQTILDE 275
-#define TOK_COLON 276
-#define TOK_LP 277
-#define TOK_RP 278
-#define TOKEN 279
+#define TOK_TILDETILDE 275
+#define TOK_EQTILDE 276
+#define TOK_COLON 277
+#define TOK_LP 278
+#define TOK_RP 279
+#define TOKEN 280
 
 
 
@@ -403,6 +415,7 @@
 static struct val	*op_and __P((struct val *, struct val *));
 static struct val	*op_colon __P((struct val *, struct val *));
 static struct val	*op_eqtilde __P((struct val *, struct val *));
+static struct val	*op_tildetilde __P((struct val *, struct val *));
 static struct val	*op_div __P((struct val *, struct val *));
 static struct val	*op_eq __P((struct val *, struct val *));
 static struct val	*op_ge __P((struct val *, struct val *));
@@ -470,13 +483,13 @@
 
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 typedef union YYSTYPE
-#line 341 "ast_expr2.y"
+#line 342 "ast_expr2.y"
 {
 	struct val *val;
 	struct expr_node *arglist;
 }
-/* Line 198 of yacc.c.  */
-#line 480 "ast_expr2.c"
+/* Line 187 of yacc.c.  */
+#line 493 "ast_expr2.c"
 	YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
@@ -498,13 +511,13 @@
 
 
 /* Copy the second part of user declarations.  */
-#line 346 "ast_expr2.y"
+#line 347 "ast_expr2.y"
 
 extern int		ast_yylex __P((YYSTYPE *, YYLTYPE *, yyscan_t));
 
 
-/* Line 221 of yacc.c.  */
-#line 508 "ast_expr2.c"
+/* Line 216 of yacc.c.  */
+#line 521 "ast_expr2.c"
 
 #ifdef short
 # undef short
@@ -634,8 +647,13 @@
 #  ifndef YYSTACK_ALLOC_MAXIMUM
 #   define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
 #  endif
-#  ifdef __cplusplus
-extern "C" {
+#  if (defined __cplusplus && ! defined _STDLIB_H \
+       && ! ((defined YYMALLOC || defined malloc) \
+	     && (defined YYFREE || defined free)))
+#   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+#   ifndef _STDLIB_H
+#    define _STDLIB_H 1
+#   endif
 #  endif
 #  ifndef YYMALLOC
 #   define YYMALLOC malloc
@@ -650,9 +668,6 @@
      || defined __cplusplus || defined _MSC_VER)
 void free (void *); /* INFRINGES ON USER NAME SPACE */
 #   endif
-#  endif
-#  ifdef __cplusplus
-}
 #  endif
 # endif
 #endif /* ! defined yyoverflow || YYERROR_VERBOSE */
@@ -719,20 +734,20 @@
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  11
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   150
+#define YYLAST   159
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  25
+#define YYNTOKENS  26
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  4
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  26
+#define YYNRULES  27
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  52
+#define YYNSTATES  54
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   279
+#define YYMAXUTOK   280
 
 #define YYTRANSLATE(YYX)						\
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -767,7 +782,8 @@
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+      25
 };
 
 #if YYDEBUG
@@ -777,30 +793,30 @@
 {
        0,     0,     3,     5,     6,     8,    12,    17,    19,    23,
       27,    31,    35,    39,    43,    47,    51,    55,    59,    63,
-      66,    69,    73,    77,    81,    85,    89
+      66,    69,    73,    77,    81,    85,    89,    95
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
-      26,     0,    -1,    28,    -1,    -1,    28,    -1,    27,     3,
-      28,    -1,    24,    22,    27,    23,    -1,    24,    -1,    22,
-      28,    23,    -1,    28,     6,    28,    -1,    28,     7,    28,
-      -1,    28,    13,    28,    -1,    28,    12,    28,    -1,    28,
-      11,    28,    -1,    28,    10,    28,    -1,    28,     9,    28,
-      -1,    28,     8,    28,    -1,    28,    15,    28,    -1,    28,
-      14,    28,    -1,    14,    28,    -1,    19,    28,    -1,    28,
-      18,    28,    -1,    28,    17,    28,    -1,    28,    16,    28,
-      -1,    28,    21,    28,    -1,    28,    20,    28,    -1,    28,
-       5,    28,     4,    28,    -1
+      27,     0,    -1,    29,    -1,    -1,    29,    -1,    28,     3,
+      29,    -1,    25,    23,    28,    24,    -1,    25,    -1,    23,
+      29,    24,    -1,    29,     6,    29,    -1,    29,     7,    29,
+      -1,    29,    13,    29,    -1,    29,    12,    29,    -1,    29,
+      11,    29,    -1,    29,    10,    29,    -1,    29,     9,    29,
+      -1,    29,     8,    29,    -1,    29,    15,    29,    -1,    29,
+      14,    29,    -1,    14,    29,    -1,    19,    29,    -1,    29,
+      18,    29,    -1,    29,    17,    29,    -1,    29,    16,    29,
+      -1,    29,    22,    29,    -1,    29,    21,    29,    -1,    29,
+       5,    29,     4,    29,    -1,    29,    20,    29,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   372,   372,   380,   387,   388,   397,   403,   404,   408,
-     412,   416,   420,   424,   428,   432,   436,   440,   444,   448,
-     452,   456,   460,   464,   468,   472,   476
+       0,   371,   371,   379,   386,   387,   396,   402,   403,   407,
+     411,   415,   419,   423,   427,   431,   435,   439,   443,   447,
+     451,   455,   459,   463,   467,   471,   475,   480
 };
 #endif
 
@@ -812,8 +828,8 @@
   "$end", "error", "$undefined", "TOK_COMMA", "TOK_COLONCOLON",
   "TOK_COND", "TOK_OR", "TOK_AND", "TOK_NE", "TOK_LE", "TOK_GE", "TOK_LT",
   "TOK_GT", "TOK_EQ", "TOK_MINUS", "TOK_PLUS", "TOK_MOD", "TOK_DIV",
-  "TOK_MULT", "TOK_COMPL", "TOK_EQTILDE", "TOK_COLON", "TOK_LP", "TOK_RP",
-  "TOKEN", "$accept", "start", "arglist", "expr", 0
+  "TOK_MULT", "TOK_COMPL", "TOK_TILDETILDE", "TOK_EQTILDE", "TOK_COLON",
+  "TOK_LP", "TOK_RP", "TOKEN", "$accept", "start", "arglist", "expr", 0
 };
 #endif
 
@@ -824,16 +840,16 @@
 {
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
-     275,   276,   277,   278,   279
+     275,   276,   277,   278,   279,   280
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    25,    26,    26,    27,    27,    28,    28,    28,    28,
-      28,    28,    28,    28,    28,    28,    28,    28,    28,    28,
-      28,    28,    28,    28,    28,    28,    28
+       0,    26,    27,    27,    28,    28,    29,    29,    29,    29,
+      29,    29,    29,    29,    29,    29,    29,    29,    29,    29,
+      29,    29,    29,    29,    29,    29,    29,    29
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
@@ -841,7 +857,7 @@
 {
        0,     2,     1,     0,     1,     3,     4,     1,     3,     3,
        3,     3,     3,     3,     3,     3,     3,     3,     3,     2,
-       2,     3,     3,     3,     3,     3,     5
+       2,     3,     3,     3,     3,     3,     5,     3
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -851,16 +867,16 @@
 {
        3,     0,     0,     0,     7,     0,     2,    19,    20,     0,
        0,     1,     0,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,     0,     0,     0,     0,     8,     0,
-       4,     0,     9,    10,    16,    15,    14,    13,    12,    11,
-      18,    17,    23,    22,    21,    25,    24,     0,     6,     0,
-       5,    26
+       0,     0,     0,     0,     0,     0,     0,     0,     0,     8,
+       0,     4,     0,     9,    10,    16,    15,    14,    13,    12,
+      11,    18,    17,    23,    22,    21,    27,    25,    24,     0,
+       6,     0,     5,    26
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int8 yydefgoto[] =
 {
-      -1,     5,    29,     6
+      -1,     5,    30,     6
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
@@ -868,12 +884,12 @@
 #define YYPACT_NINF -18
 static const yytype_int16 yypact[] =
 {
-     112,   112,   112,   112,   -16,     5,    62,   -17,   -17,    24,
-     112,   -18,   112,   112,   112,   112,   112,   112,   112,   112,
-     112,   112,   112,   112,   112,   112,   112,   112,   -18,     4,
-      62,    45,    93,   107,   123,   123,   123,   123,   123,   123,
-     129,   129,   -17,   -17,   -17,   -18,   -18,   112,   -18,   112,
-      62,    78
+     118,   118,   118,   118,   -15,     6,    65,   -17,   -17,    25,
+     118,   -18,   118,   118,   118,   118,   118,   118,   118,   118,
+     118,   118,   118,   118,   118,   118,   118,   118,   118,   -18,
+       4,    65,    47,    98,   113,   130,   130,   130,   130,   130,
+     130,   137,   137,   -17,   -17,   -17,   -18,   -18,   -18,   118,
+     -18,   118,    65,    82
 };
 
 /* YYPGOTO[NTERM-NUM].  */
@@ -889,54 +905,54 @@
 #define YYTABLE_NINF -1
 static const yytype_uint8 yytable[] =
 {
-       7,     8,     9,    26,    27,    11,    10,    47,     0,    30,
-       0,    31,    32,    33,    34,    35,    36,    37,    38,    39,
-      40,    41,    42,    43,    44,    45,    46,    48,     0,    12,
-      13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
-      23,    24,    25,     0,    26,    27,    50,    28,    51,    49,
+       7,     8,     9,    26,    27,    28,    11,    49,    10,    31,
+       0,    32,    33,    34,    35,    36,    37,    38,    39,    40,
+      41,    42,    43,    44,    45,    46,    47,    48,    50,     0,
       12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
-      22,    23,    24,    25,     0,    26,    27,    12,    13,    14,
+      22,    23,    24,    25,     0,    26,    27,    28,    52,    29,
+      53,    51,    12,    13,    14,    15,    16,    17,    18,    19,
+      20,    21,    22,    23,    24,    25,     0,    26,    27,    28,
+      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
+      22,    23,    24,    25,     0,    26,    27,    28,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,     0,    26,    27,    13,    14,    15,    16,    17,    18,
+      25,     0,    26,    27,    28,    14,    15,    16,    17,    18,
       19,    20,    21,    22,    23,    24,    25,     0,    26,    27,
-      14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
-      24,    25,     0,    26,    27,    15,    16,    17,    18,    19,
-      20,    21,    22,    23,    24,    25,     1,    26,    27,     0,
-       0,     2,     0,     0,     3,     0,     4,    21,    22,    23,
-      24,    25,     0,    26,    27,    23,    24,    25,     0,    26,
-      27
+      28,    15,    16,    17,    18,    19,    20,    21,    22,    23,
+      24,    25,     1,    26,    27,    28,     0,     2,     0,     0,
+       0,     3,     0,     4,    21,    22,    23,    24,    25,     0,
+      26,    27,    28,    23,    24,    25,     0,    26,    27,    28
 };
 
 static const yytype_int8 yycheck[] =
 {
-       1,     2,     3,    20,    21,     0,    22,     3,    -1,    10,
+       1,     2,     3,    20,    21,    22,     0,     3,    23,    10,
       -1,    12,    13,    14,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,    24,    25,    26,    27,    23,    -1,     5,
-       6,     7,     8,     9,    10,    11,    12,    13,    14,    15,
-      16,    17,    18,    -1,    20,    21,    47,    23,    49,     4,
+      21,    22,    23,    24,    25,    26,    27,    28,    24,    -1,
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    16,    17,    18,    -1,    20,    21,     5,     6,     7,
+      15,    16,    17,    18,    -1,    20,    21,    22,    49,    24,
+      51,     4,     5,     6,     7,     8,     9,    10,    11,    12,
+      13,    14,    15,    16,    17,    18,    -1,    20,    21,    22,
+       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
+      15,    16,    17,    18,    -1,    20,    21,    22,     6,     7,
        8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
-      18,    -1,    20,    21,     6,     7,     8,     9,    10,    11,
+      18,    -1,    20,    21,    22,     7,     8,     9,    10,    11,
       12,    13,    14,    15,    16,    17,    18,    -1,    20,    21,
-       7,     8,     9,    10,    11,    12,    13,    14,    15,    16,
-      17,    18,    -1,    20,    21,     8,     9,    10,    11,    12,
-      13,    14,    15,    16,    17,    18,    14,    20,    21,    -1,
-      -1,    19,    -1,    -1,    22,    -1,    24,    14,    15,    16,
-      17,    18,    -1,    20,    21,    16,    17,    18,    -1,    20,
-      21
+      22,     8,     9,    10,    11,    12,    13,    14,    15,    16,
+      17,    18,    14,    20,    21,    22,    -1,    19,    -1,    -1,
+      -1,    23,    -1,    25,    14,    15,    16,    17,    18,    -1,
+      20,    21,    22,    16,    17,    18,    -1,    20,    21,    22
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,    14,    19,    22,    24,    26,    28,    28,    28,    28,
-      22,     0,     5,     6,     7,     8,     9,    10,    11,    12,
-      13,    14,    15,    16,    17,    18,    20,    21,    23,    27,
-      28,    28,    28,    28,    28,    28,    28,    28,    28,    28,
-      28,    28,    28,    28,    28,    28,    28,     3,    23,     4,
-      28,    28
+       0,    14,    19,    23,    25,    27,    29,    29,    29,    29,
+      23,     0,     5,     6,     7,     8,     9,    10,    11,    12,
+      13,    14,    15,    16,    17,    18,    20,    21,    22,    24,
+      28,    29,    29,    29,    29,    29,    29,    29,    29,    29,
+      29,    29,    29,    29,    29,    29,    29,    29,    29,     3,
+      24,     4,    29,    29
 };
 
 #define yyerrok		(yyerrstatus = 0)
@@ -1063,14 +1079,14 @@
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, const YYSTYPE * const yyvaluep, const YYLTYPE * const yylocationp)
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp)
 #else
 static void
 yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp)
     FILE *yyoutput;
     int yytype;
-    const YYSTYPE * const yyvaluep;
-    const YYLTYPE * const yylocationp;
+    YYSTYPE const * const yyvaluep;
+    YYLTYPE const * const yylocationp;
 #endif
 {
   if (!yyvaluep)
@@ -1097,14 +1113,14 @@
 #if (defined __STDC__ || defined __C99__FUNC__ \
      || defined __cplusplus || defined _MSC_VER)
 static void
-yy_symbol_print (FILE *yyoutput, int yytype, const YYSTYPE * const yyvaluep, const YYLTYPE * const yylocationp)
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp)
 #else
 static void
 yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp)
     FILE *yyoutput;
     int yytype;
-    const YYSTYPE * const yyvaluep;
-    const YYLTYPE * const yylocationp;
+    YYSTYPE const * const yyvaluep;
+    YYLTYPE const * const yylocationp;
 #endif
 {
   if (yytype < YYNTOKENS)
@@ -1157,8 +1173,7 @@
 yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule)
 #else
 static void
-yy_reduce_print (yyvsp, yylsp, yyrule
-		   )
+yy_reduce_print (yyvsp, yylsp, yyrule)
     YYSTYPE *yyvsp;
     YYLTYPE *yylsp;
     int yyrule;
@@ -1281,7 +1296,7 @@
 {
   if (*yystr == '"')
     {
-      size_t yyn = 0;
+      YYSIZE_T yyn = 0;
       char const *yyp = yystr;
 
       for (;;)
@@ -1328,7 +1343,7 @@
 {
   int yyn = yypact[yystate];
 
-  if (! (YYPACT_NINF < yyn && yyn < YYLAST))
+  if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
     return 0;
   else
     {
@@ -1366,7 +1381,7 @@
       int yyxbegin = yyn < 0 ? -yyn : 0;
 
       /* Stay within bounds of both yycheck and yytname.  */
-      int yychecklim = YYLAST - yyn;
+      int yychecklim = YYLAST - yyn + 1;
       int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
       int yycount = 1;
 
@@ -1454,114 +1469,119 @@
   switch (yytype)
     {
       case 4: /* "TOK_COLONCOLON" */
-#line 366 "ast_expr2.y"
-	{  free_value((yyvaluep->val)); };
-#line 1460 "ast_expr2.c"
-	break;
-      case 5: /* "TOK_COND" */
-#line 366 "ast_expr2.y"
-	{  free_value((yyvaluep->val)); };
-#line 1465 "ast_expr2.c"
-	break;
-      case 6: /* "TOK_OR" */
-#line 366 "ast_expr2.y"
-	{  free_value((yyvaluep->val)); };
-#line 1470 "ast_expr2.c"
-	break;
-      case 7: /* "TOK_AND" */
-#line 366 "ast_expr2.y"
+#line 365 "ast_expr2.y"
 	{  free_value((yyvaluep->val)); };
 #line 1475 "ast_expr2.c"
 	break;
-      case 8: /* "TOK_NE" */
-#line 366 "ast_expr2.y"
+      case 5: /* "TOK_COND" */
+#line 365 "ast_expr2.y"
 	{  free_value((yyvaluep->val)); };
 #line 1480 "ast_expr2.c"
 	break;
-      case 9: /* "TOK_LE" */
-#line 366 "ast_expr2.y"
+      case 6: /* "TOK_OR" */
+#line 365 "ast_expr2.y"
 	{  free_value((yyvaluep->val)); };
 #line 1485 "ast_expr2.c"
 	break;
-      case 10: /* "TOK_GE" */
-#line 366 "ast_expr2.y"
+      case 7: /* "TOK_AND" */
+#line 365 "ast_expr2.y"
 	{  free_value((yyvaluep->val)); };
 #line 1490 "ast_expr2.c"
 	break;
-      case 11: /* "TOK_LT" */
-#line 366 "ast_expr2.y"
+      case 8: /* "TOK_NE" */
+#line 365 "ast_expr2.y"
 	{  free_value((yyvaluep->val)); };
 #line 1495 "ast_expr2.c"
 	break;
-      case 12: /* "TOK_GT" */
-#line 366 "ast_expr2.y"
+      case 9: /* "TOK_LE" */
+#line 365 "ast_expr2.y"
 	{  free_value((yyvaluep->val)); };
 #line 1500 "ast_expr2.c"
 	break;
-      case 13: /* "TOK_EQ" */
-#line 366 "ast_expr2.y"
+      case 10: /* "TOK_GE" */
+#line 365 "ast_expr2.y"
 	{  free_value((yyvaluep->val)); };
 #line 1505 "ast_expr2.c"
 	break;
-      case 14: /* "TOK_MINUS" */
-#line 366 "ast_expr2.y"
+      case 11: /* "TOK_LT" */
+#line 365 "ast_expr2.y"
 	{  free_value((yyvaluep->val)); };
 #line 1510 "ast_expr2.c"
 	break;
-      case 15: /* "TOK_PLUS" */
-#line 366 "ast_expr2.y"
+      case 12: /* "TOK_GT" */
+#line 365 "ast_expr2.y"
 	{  free_value((yyvaluep->val)); };
 #line 1515 "ast_expr2.c"
 	break;
-      case 16: /* "TOK_MOD" */
-#line 366 "ast_expr2.y"
+      case 13: /* "TOK_EQ" */
+#line 365 "ast_expr2.y"
 	{  free_value((yyvaluep->val)); };
 #line 1520 "ast_expr2.c"
 	break;
-      case 17: /* "TOK_DIV" */
-#line 366 "ast_expr2.y"
+      case 14: /* "TOK_MINUS" */
+#line 365 "ast_expr2.y"
 	{  free_value((yyvaluep->val)); };
 #line 1525 "ast_expr2.c"
 	break;
-      case 18: /* "TOK_MULT" */
-#line 366 "ast_expr2.y"
+      case 15: /* "TOK_PLUS" */
+#line 365 "ast_expr2.y"
 	{  free_value((yyvaluep->val)); };
 #line 1530 "ast_expr2.c"
 	break;
-      case 19: /* "TOK_COMPL" */
-#line 366 "ast_expr2.y"
+      case 16: /* "TOK_MOD" */
+#line 365 "ast_expr2.y"
 	{  free_value((yyvaluep->val)); };
 #line 1535 "ast_expr2.c"
 	break;
-      case 20: /* "TOK_EQTILDE" */
-#line 366 "ast_expr2.y"
+      case 17: /* "TOK_DIV" */
+#line 365 "ast_expr2.y"
 	{  free_value((yyvaluep->val)); };
 #line 1540 "ast_expr2.c"
 	break;
-      case 21: /* "TOK_COLON" */
-#line 366 "ast_expr2.y"
+      case 18: /* "TOK_MULT" */
+#line 365 "ast_expr2.y"
 	{  free_value((yyvaluep->val)); };
 #line 1545 "ast_expr2.c"
 	break;
-      case 22: /* "TOK_LP" */
-#line 366 "ast_expr2.y"
+      case 19: /* "TOK_COMPL" */
+#line 365 "ast_expr2.y"
 	{  free_value((yyvaluep->val)); };
 #line 1550 "ast_expr2.c"
 	break;
-      case 23: /* "TOK_RP" */
-#line 366 "ast_expr2.y"
+      case 20: /* "TOK_TILDETILDE" */
+#line 365 "ast_expr2.y"
 	{  free_value((yyvaluep->val)); };
 #line 1555 "ast_expr2.c"
 	break;
-      case 24: /* "TOKEN" */
-#line 366 "ast_expr2.y"
+      case 21: /* "TOK_EQTILDE" */
+#line 365 "ast_expr2.y"
 	{  free_value((yyvaluep->val)); };
 #line 1560 "ast_expr2.c"
 	break;
-      case 28: /* "expr" */
-#line 366 "ast_expr2.y"
+      case 22: /* "TOK_COLON" */
+#line 365 "ast_expr2.y"
 	{  free_value((yyvaluep->val)); };
 #line 1565 "ast_expr2.c"
+	break;
+      case 23: /* "TOK_LP" */
+#line 365 "ast_expr2.y"
+	{  free_value((yyvaluep->val)); };
+#line 1570 "ast_expr2.c"
+	break;
+      case 24: /* "TOK_RP" */
+#line 365 "ast_expr2.y"
+	{  free_value((yyvaluep->val)); };
+#line 1575 "ast_expr2.c"
+	break;
+      case 25: /* "TOKEN" */
+#line 365 "ast_expr2.y"
+	{  free_value((yyvaluep->val)); };
+#line 1580 "ast_expr2.c"
+	break;
+      case 29: /* "expr" */
+#line 365 "ast_expr2.y"
+	{  free_value((yyvaluep->val)); };
+#line 1585 "ast_expr2.c"
 	break;
 
       default:
@@ -1884,7 +1904,7 @@
   switch (yyn)
     {
         case 2:
-#line 372 "ast_expr2.y"
+#line 371 "ast_expr2.y"
     { ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(struct val),1);
               ((struct parse_io *)parseio)->val->type = (yyvsp[(1) - (1)].val)->type;
               if( (yyvsp[(1) - (1)].val)->type == AST_EXPR_number )
@@ -1896,7 +1916,7 @@
     break;
 
   case 3:
-#line 380 "ast_expr2.y"
+#line 379 "ast_expr2.y"
     {/* nothing */ ((struct parse_io *)parseio)->val = (struct val *)calloc(sizeof(struct val),1);
               ((struct parse_io *)parseio)->val->type = AST_EXPR_string;
 			  ((struct parse_io *)parseio)->val->u.s = strdup(""); 
@@ -1904,12 +1924,12 @@
     break;
 
   case 4:
-#line 387 "ast_expr2.y"
+#line 386 "ast_expr2.y"
     { (yyval.arglist) = alloc_expr_node(AST_EXPR_NODE_VAL); (yyval.arglist)->val = (yyvsp[(1) - (1)].val);;}
     break;
 
   case 5:
-#line 388 "ast_expr2.y"
+#line 387 "ast_expr2.y"
     {struct expr_node *x = alloc_expr_node(AST_EXPR_NODE_VAL);
                                  struct expr_node *t;
 								 DESTROY((yyvsp[(2) - (3)].val));
@@ -1919,7 +1939,7 @@
     break;
 
   case 6:
-#line 397 "ast_expr2.y"
+#line 396 "ast_expr2.y"
     { (yyval.val) = op_func((yyvsp[(1) - (4)].val),(yyvsp[(3) - (4)].arglist), ((struct parse_io *)parseio)->chan);
 		                            DESTROY((yyvsp[(2) - (4)].val));
 									DESTROY((yyvsp[(4) - (4)].val));
@@ -1929,12 +1949,12 @@
     break;
 
   case 7:
-#line 403 "ast_expr2.y"
+#line 402 "ast_expr2.y"
     {(yyval.val) = (yyvsp[(1) - (1)].val);;}
     break;
 
   case 8:
-#line 404 "ast_expr2.y"
+#line 403 "ast_expr2.y"
     { (yyval.val) = (yyvsp[(2) - (3)].val);
 	                       (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
 						   (yyloc).first_line=0; (yyloc).last_line=0;
@@ -1942,7 +1962,7 @@
     break;
 
   case 9:
-#line 408 "ast_expr2.y"
+#line 407 "ast_expr2.y"
     { (yyval.val) = op_or ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val));
 						DESTROY((yyvsp[(2) - (3)].val));	
                          (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
@@ -1950,7 +1970,7 @@
     break;
 
   case 10:
-#line 412 "ast_expr2.y"
+#line 411 "ast_expr2.y"
     { (yyval.val) = op_and ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
 						DESTROY((yyvsp[(2) - (3)].val));	
 	                      (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
@@ -1958,7 +1978,7 @@
     break;
 
   case 11:
-#line 416 "ast_expr2.y"
+#line 415 "ast_expr2.y"
     { (yyval.val) = op_eq ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val));
 						DESTROY((yyvsp[(2) - (3)].val));	
 	                     (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column;
@@ -1966,7 +1986,7 @@
     break;
 
   case 12:
-#line 420 "ast_expr2.y"
+#line 419 "ast_expr2.y"
     { (yyval.val) = op_gt ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val));
 						DESTROY((yyvsp[(2) - (3)].val));	
                          (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column;
@@ -1974,7 +1994,7 @@
     break;
 
   case 13:
-#line 424 "ast_expr2.y"
+#line 423 "ast_expr2.y"
     { (yyval.val) = op_lt ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
 						DESTROY((yyvsp[(2) - (3)].val));	
 	                     (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
@@ -1982,7 +2002,7 @@
     break;
 
   case 14:
-#line 428 "ast_expr2.y"
+#line 427 "ast_expr2.y"
     { (yyval.val) = op_ge ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
 						DESTROY((yyvsp[(2) - (3)].val));	
 	                      (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
@@ -1990,7 +2010,7 @@
     break;
 
   case 15:
-#line 432 "ast_expr2.y"
+#line 431 "ast_expr2.y"
     { (yyval.val) = op_le ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
 						DESTROY((yyvsp[(2) - (3)].val));	
 	                      (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
@@ -1998,7 +2018,7 @@
     break;
 
   case 16:
-#line 436 "ast_expr2.y"
+#line 435 "ast_expr2.y"
     { (yyval.val) = op_ne ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
 						DESTROY((yyvsp[(2) - (3)].val));	
 	                      (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
@@ -2006,7 +2026,7 @@
     break;
 
   case 17:
-#line 440 "ast_expr2.y"
+#line 439 "ast_expr2.y"
     { (yyval.val) = op_plus ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
 						DESTROY((yyvsp[(2) - (3)].val));	
 	                       (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
@@ -2014,7 +2034,7 @@
     break;
 
   case 18:
-#line 444 "ast_expr2.y"
+#line 443 "ast_expr2.y"
     { (yyval.val) = op_minus ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
 						DESTROY((yyvsp[(2) - (3)].val));	
 	                        (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
@@ -2022,7 +2042,7 @@
     break;
 
   case 19:
-#line 448 "ast_expr2.y"
+#line 447 "ast_expr2.y"
     { (yyval.val) = op_negate ((yyvsp[(2) - (2)].val)); 
 						DESTROY((yyvsp[(1) - (2)].val));	
 	                        (yyloc).first_column = (yylsp[(1) - (2)]).first_column; (yyloc).last_column = (yylsp[(2) - (2)]).last_column; 
@@ -2030,7 +2050,7 @@
     break;
 
   case 20:
-#line 452 "ast_expr2.y"
+#line 451 "ast_expr2.y"
     { (yyval.val) = op_compl ((yyvsp[(2) - (2)].val)); 
 						DESTROY((yyvsp[(1) - (2)].val));	
 	                        (yyloc).first_column = (yylsp[(1) - (2)]).first_column; (yyloc).last_column = (yylsp[(2) - (2)]).last_column; 
@@ -2038,7 +2058,7 @@
     break;
 
   case 21:
-#line 456 "ast_expr2.y"
+#line 455 "ast_expr2.y"
     { (yyval.val) = op_times ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
 						DESTROY((yyvsp[(2) - (3)].val));	
 	                       (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
@@ -2046,7 +2066,7 @@
     break;
 
   case 22:
-#line 460 "ast_expr2.y"
+#line 459 "ast_expr2.y"
     { (yyval.val) = op_div ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
 						DESTROY((yyvsp[(2) - (3)].val));	
 	                      (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
@@ -2054,7 +2074,7 @@
     break;
 
   case 23:
-#line 464 "ast_expr2.y"
+#line 463 "ast_expr2.y"
     { (yyval.val) = op_rem ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
 						DESTROY((yyvsp[(2) - (3)].val));	
 	                      (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
@@ -2062,7 +2082,7 @@
     break;
 
   case 24:
-#line 468 "ast_expr2.y"
+#line 467 "ast_expr2.y"
     { (yyval.val) = op_colon ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
 						DESTROY((yyvsp[(2) - (3)].val));	
 	                        (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
@@ -2070,7 +2090,7 @@
     break;
 
   case 25:
-#line 472 "ast_expr2.y"
+#line 471 "ast_expr2.y"
     { (yyval.val) = op_eqtilde ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
 						DESTROY((yyvsp[(2) - (3)].val));	
 	                        (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
@@ -2078,7 +2098,7 @@
     break;
 
   case 26:
-#line 476 "ast_expr2.y"
+#line 475 "ast_expr2.y"
     { (yyval.val) = op_cond ((yyvsp[(1) - (5)].val), (yyvsp[(3) - (5)].val), (yyvsp[(5) - (5)].val)); 
 						DESTROY((yyvsp[(2) - (5)].val));	
 						DESTROY((yyvsp[(4) - (5)].val));	
@@ -2086,9 +2106,17 @@
 							(yyloc).first_line=0; (yyloc).last_line=0;;}
     break;
 
-
-/* Line 1270 of yacc.c.  */
-#line 2092 "ast_expr2.c"
+  case 27:
+#line 480 "ast_expr2.y"
+    { (yyval.val) = op_tildetilde ((yyvsp[(1) - (3)].val), (yyvsp[(3) - (3)].val)); 
+						DESTROY((yyvsp[(2) - (3)].val));	
+	                        (yyloc).first_column = (yylsp[(1) - (3)]).first_column; (yyloc).last_column = (yylsp[(3) - (3)]).last_column; 
+							(yyloc).first_line=0; (yyloc).last_line=0;;}
+    break;
+
+
+/* Line 1267 of yacc.c.  */
+#line 2120 "ast_expr2.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -2303,11 +2331,12 @@
   if (yymsg != yymsgbuf)
     YYSTACK_FREE (yymsg);
 #endif
-  return yyresult;
-}
-
-
-#line 483 "ast_expr2.y"
+  /* Make sure YYID is used.  */
+  return YYID (yyresult);
+}
+
+
+#line 486 "ast_expr2.y"
 
 
 static struct expr_node *alloc_expr_node(enum node_type nt)
@@ -3446,3 +3475,29 @@
 	return v;
 }
 
+static struct val *  /* this is a string concat operator */
+op_tildetilde (struct val *a, struct val *b)
+{
+	struct val *v;
+	char *vs;
+
+	/* coerce to both arguments to strings */
+	to_string(a);
+	to_string(b);
+	/* strip double quotes from both -- */
+	strip_quotes(a);
+	strip_quotes(b);
+	
+	vs = malloc(strlen(a->u.s)+strlen(b->u.s)+1);
+	strcpy(vs,a->u.s);
+	strcat(vs,b->u.s);
+
+	v = make_str(vs);
+
+	/* free arguments */
+	free_value(a);
+	free_value(b);
+
+	return v;
+}
+

Modified: trunk/main/ast_expr2.fl
URL: http://svn.digium.com/view/asterisk/trunk/main/ast_expr2.fl?view=diff&rev=114423&r1=114422&r2=114423
==============================================================================
--- trunk/main/ast_expr2.fl (original)
+++ trunk/main/ast_expr2.fl Mon Apr 21 16:13:02 2008
@@ -133,6 +133,7 @@
 \&\&	{ SET_COLUMNS; SET_STRING; return TOK_AND;}
 \=\=	{ SET_COLUMNS; SET_STRING; return TOK_EQ;}
 \=~	{ SET_COLUMNS; SET_STRING; return TOK_EQTILDE;}
+\~~	{ SET_COLUMNS; SET_STRING; return TOK_TILDETILDE;}
 \>	{ SET_COLUMNS; SET_STRING; return TOK_GT;}
 \<	{ SET_COLUMNS; SET_STRING; return TOK_LT;}

[... 6132 lines stripped ...]



More information about the asterisk-commits mailing list