Index: /pjproject/trunk/pjlib-util/build/pjlib_util.dsp
===================================================================
--- /pjproject/trunk/pjlib-util/build/pjlib_util.dsp	(revision 72)
+++ /pjproject/trunk/pjlib-util/build/pjlib_util.dsp	(revision 73)
@@ -42,5 +42,5 @@
 # PROP Target_Dir ""
 # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
-# ADD CPP /nologo /MD /W3 /GX /O2 /I "../include" /I "../../pjlib/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /Zi /O2 /Ob2 /I "../include" /I "../../pjlib/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /YX /FD /c
 # ADD BASE RSC /l 0x409 /d "NDEBUG"
 # ADD RSC /l 0x409 /d "NDEBUG"
@@ -94,4 +94,14 @@
 # Begin Source File
 
+SOURCE="..\src\pjlib-util\scanner_cis_bitwise.c"
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE="..\src\pjlib-util\scanner_cis_uint.c"
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
 SOURCE="..\src\pjlib-util\string.c"
 # End Source File
@@ -130,4 +140,12 @@
 # Begin Source File
 
+SOURCE="..\include\pjlib-util\scanner_cis_bitwise.h"
+# End Source File
+# Begin Source File
+
+SOURCE="..\include\pjlib-util\scanner_cis_uint.h"
+# End Source File
+# Begin Source File
+
 SOURCE="..\include\pjlib-util\string.h"
 # End Source File
Index: /pjproject/trunk/pjlib-util/include/pjlib-util/scanner.h
===================================================================
--- /pjproject/trunk/pjlib-util/include/pjlib-util/scanner.h	(revision 72)
+++ /pjproject/trunk/pjlib-util/include/pjlib-util/scanner.h	(revision 73)
@@ -27,4 +27,14 @@
 #include <pj/types.h>
 
+/**
+ * Macro PJ_SCANNER_USE_BITWISE is defined and non-zero (by default yes)
+ * will enable the use of bitwise for character input specification (cis).
+ * This would save several kilobytes of .bss memory in the SIP parser.
+ */
+#ifndef PJ_SCANNER_USE_BITWISE
+#  define PJ_SCANNER_USE_BITWISE   1
+#endif
+
+
 PJ_BEGIN_DECL
 
@@ -37,42 +47,9 @@
  * @{
  */
-
-/**
- * This describes the type of individual character specification in
- * #pj_cis_buf_t. Basicly the number of bits here
- */
-#ifndef PJ_CIS_ELEM_TYPE
-#   define PJ_CIS_ELEM_TYPE pj_uint32_t
+#if defined(PJ_SCANNER_USE_BITWISE) && PJ_SCANNER_USE_BITWISE != 0
+#  include <pjlib-util/scanner_cis_bitwise.h>
+#else
+#  include <pjlib-util/scanner_cis_uint.h>
 #endif
-
-/**
- * This describes the type of individual character specification in
- * #pj_cis_buf_t.
- */
-typedef PJ_CIS_ELEM_TYPE pj_cis_elem_t;
-
-/**
- * Maximum number of input specification in a buffer.
- * Effectively this means the number of bits in pj_cis_elem_t.
- */
-#define PJ_CIS_MAX_INDEX   (sizeof(pj_cis_elem_t) << 3)
-
-/**
- * The scanner input specification buffer.
- */
-typedef struct pj_cis_buf_t
-{
-    pj_cis_elem_t    cis_buf[256];  /**< Must be 256 (not 128)! */
-    pj_cis_elem_t    use_mask;      /**< To keep used indexes.  */
-} pj_cis_buf_t;
-
-/**
- * Character input specification.
- */
-typedef struct pj_cis_t
-{
-    pj_cis_elem_t   *cis_buf;       /**< Pointer to buffer.     */
-    int              cis_id;        /**< Id.                    */
-} pj_cis_t;
 
 /**
@@ -107,31 +84,4 @@
  */
 PJ_DECL(pj_status_t) pj_cis_dup(pj_cis_t *new_cis, pj_cis_t *existing);
-
-/**
- * Set the membership of the specified character.
- * Note that this is a macro, and arguments may be evaluated more than once.
- *
- * @param cis       Pointer to character input specification.
- * @param c         The character.
- */
-#define PJ_CIS_SET(cis,c)   ((cis)->cis_buf[(c)] |= (1 << (cis)->cis_id))
-
-/**
- * Remove the membership of the specified character.
- * Note that this is a macro, and arguments may be evaluated more than once.
- *
- * @param cis       Pointer to character input specification.
- * @param c         The character to be removed from the membership.
- */
-#define PJ_CIS_CLR(cis,c)   ((cis)->cis_buf[c] &= ~(1 << (cis)->cis_id))
-
-/**
- * Check the membership of the specified character.
- * Note that this is a macro, and arguments may be evaluated more than once.
- *
- * @param cis       Pointer to character input specification.
- * @param c         The character.
- */
-#define PJ_CIS_ISSET(cis,c) ((cis)->cis_buf[c] & (1 << (cis)->cis_id))
 
 /**
Index: /pjproject/trunk/pjlib-util/include/pjlib-util/scanner_cis_bitwise.h
===================================================================
--- /pjproject/trunk/pjlib-util/include/pjlib-util/scanner_cis_bitwise.h	(revision 73)
+++ /pjproject/trunk/pjlib-util/include/pjlib-util/scanner_cis_bitwise.h	(revision 73)
@@ -0,0 +1,96 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#ifndef __PJLIB_UTIL_SCANNER_CIS_BIT_H__
+#define __PJLIB_UTIL_SCANNER_CIS_BIT_H__
+
+#include <pj/types.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * This describes the type of individual character specification in
+ * #pj_cis_buf_t. Basicly the number of bits here
+ */
+#ifndef PJ_CIS_ELEM_TYPE
+#   define PJ_CIS_ELEM_TYPE pj_uint32_t
+#endif
+
+/**
+ * This describes the type of individual character specification in
+ * #pj_cis_buf_t.
+ */
+typedef PJ_CIS_ELEM_TYPE pj_cis_elem_t;
+
+/**
+ * Maximum number of input specification in a buffer.
+ * Effectively this means the number of bits in pj_cis_elem_t.
+ */
+#define PJ_CIS_MAX_INDEX   (sizeof(pj_cis_elem_t) << 3)
+
+/**
+ * The scanner input specification buffer.
+ */
+typedef struct pj_cis_buf_t
+{
+    pj_cis_elem_t    cis_buf[256];  /**< Must be 256 (not 128)! */
+    pj_cis_elem_t    use_mask;      /**< To keep used indexes.  */
+} pj_cis_buf_t;
+
+/**
+ * Character input specification.
+ */
+typedef struct pj_cis_t
+{
+    pj_cis_elem_t   *cis_buf;       /**< Pointer to buffer.     */
+    int              cis_id;        /**< Id.                    */
+} pj_cis_t;
+
+
+/**
+ * Set the membership of the specified character.
+ * Note that this is a macro, and arguments may be evaluated more than once.
+ *
+ * @param cis       Pointer to character input specification.
+ * @param c         The character.
+ */
+#define PJ_CIS_SET(cis,c)   ((cis)->cis_buf[(c)] |= (1 << (cis)->cis_id))
+
+/**
+ * Remove the membership of the specified character.
+ * Note that this is a macro, and arguments may be evaluated more than once.
+ *
+ * @param cis       Pointer to character input specification.
+ * @param c         The character to be removed from the membership.
+ */
+#define PJ_CIS_CLR(cis,c)   ((cis)->cis_buf[c] &= ~(1 << (cis)->cis_id))
+
+/**
+ * Check the membership of the specified character.
+ * Note that this is a macro, and arguments may be evaluated more than once.
+ *
+ * @param cis       Pointer to character input specification.
+ * @param c         The character.
+ */
+#define PJ_CIS_ISSET(cis,c) ((cis)->cis_buf[c] & (1 << (cis)->cis_id))
+
+
+
+PJ_END_DECL
+
+#endif	/* __PJLIB_UTIL_SCANNER_CIS_BIT_H__ */
Index: /pjproject/trunk/pjlib-util/include/pjlib-util/scanner_cis_uint.h
===================================================================
--- /pjproject/trunk/pjlib-util/include/pjlib-util/scanner_cis_uint.h	(revision 73)
+++ /pjproject/trunk/pjlib-util/include/pjlib-util/scanner_cis_uint.h	(revision 73)
@@ -0,0 +1,83 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2005 Benny Prijono <benny@prijono.org>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+#ifndef __PJLIB_UTIL_SCANNER_CIS_BIT_H__
+#define __PJLIB_UTIL_SCANNER_CIS_BIT_H__
+
+#include <pj/types.h>
+
+PJ_BEGIN_DECL
+
+/**
+ * This describes the type of individual character specification in
+ * #pj_cis_buf_t. Basicly the number of bits here
+ */
+#ifndef PJ_CIS_ELEM_TYPE
+#   define PJ_CIS_ELEM_TYPE int
+#endif
+
+/**
+ * This describes the type of individual character specification in
+ * #pj_cis_buf_t.
+ */
+typedef PJ_CIS_ELEM_TYPE pj_cis_elem_t;
+
+/** pj_cis_buf_t is not used when uint back-end is used. */
+typedef int pj_cis_buf_t;
+
+/**
+ * Character input specification.
+ */
+typedef struct pj_cis_t
+{
+    PJ_CIS_ELEM_TYPE	cis_buf[256];
+} pj_cis_t;
+
+
+/**
+ * Set the membership of the specified character.
+ * Note that this is a macro, and arguments may be evaluated more than once.
+ *
+ * @param cis       Pointer to character input specification.
+ * @param c         The character.
+ */
+#define PJ_CIS_SET(cis,c)   ((cis)->cis_buf[(c)] = 1)
+
+/**
+ * Remove the membership of the specified character.
+ * Note that this is a macro, and arguments may be evaluated more than once.
+ *
+ * @param cis       Pointer to character input specification.
+ * @param c         The character to be removed from the membership.
+ */
+#define PJ_CIS_CLR(cis,c)   ((cis)->cis_buf[c] = 0)
+
+/**
+ * Check the membership of the specified character.
+ * Note that this is a macro, and arguments may be evaluated more than once.
+ *
+ * @param cis       Pointer to character input specification.
+ * @param c         The character.
+ */
+#define PJ_CIS_ISSET(cis,c) ((cis)->cis_buf[c])
+
+
+
+PJ_END_DECL
+
+#endif	/* __PJLIB_UTIL_SCANNER_CIS_BIT_H__ */
Index: /pjproject/trunk/pjlib-util/src/pjlib-util-test/test.c
===================================================================
--- /pjproject/trunk/pjlib-util/src/pjlib-util-test/test.c	(revision 72)
+++ /pjproject/trunk/pjlib-util/src/pjlib-util-test/test.c	(revision 73)
@@ -75,5 +75,5 @@
         return test_inner();
     }
-    PJ_DEFAULT {
+    PJ_CATCH_ANY {
         int id = PJ_GET_EXCEPTION();
         PJ_LOG(3,("test", "FATAL: unhandled exception id %d (%s)", 
Index: /pjproject/trunk/pjlib-util/src/pjlib-util/scanner.c
===================================================================
--- /pjproject/trunk/pjlib-util/src/pjlib-util/scanner.c	(revision 72)
+++ /pjproject/trunk/pjlib-util/src/pjlib-util/scanner.c	(revision 73)
@@ -22,4 +22,5 @@
 #include <pj/os.h>
 #include <pj/errno.h>
+#include <pj/assert.h>
 
 #define PJ_SCAN_IS_SPACE(c)	((c)==' ' || (c)=='\t')
@@ -28,4 +29,11 @@
 
 
+#if defined(PJ_SCANNER_USE_BITWISE) && PJ_SCANNER_USE_BITWISE != 0
+#  include "scanner_cis_bitwise.c"
+#else
+#  include "scanner_cis_uint.c"
+#endif
+
+
 static void pj_scan_syntax_err(pj_scanner *scanner)
 {
@@ -33,50 +41,10 @@
 }
 
-PJ_DEF(void) pj_cis_buf_init( pj_cis_buf_t *cis_buf)
-{
-    pj_memset(cis_buf->cis_buf, 0, sizeof(cis_buf->cis_buf));
-    cis_buf->use_mask = 0;
-}
-
-PJ_DEF(pj_status_t) pj_cis_init(pj_cis_buf_t *cis_buf, pj_cis_t *cis)
-{
-    unsigned i;
-
-    cis->cis_buf = cis_buf->cis_buf;
-
-    for (i=0; i<PJ_CIS_MAX_INDEX; ++i) {
-        if ((cis_buf->use_mask & (1 << i)) == 0) {
-            cis->cis_id = i;
-	    cis_buf->use_mask |= (1 << i);
-            return PJ_SUCCESS;
-        }
-    }
-
-    cis->cis_id = PJ_CIS_MAX_INDEX;
-    return PJ_ETOOMANY;
-}
-
-PJ_DEF(pj_status_t) pj_cis_dup( pj_cis_t *new_cis, pj_cis_t *existing)
-{
-    pj_status_t status;
-    unsigned i;
-
-    /* Warning: typecasting here! */
-    status = pj_cis_init((pj_cis_buf_t*)existing->cis_buf, new_cis);
-    if (status != PJ_SUCCESS)
-        return status;
-
-    for (i=0; i<256; ++i) {
-        if (PJ_CIS_ISSET(existing, i))
-            PJ_CIS_SET(new_cis, i);
-        else
-            PJ_CIS_CLR(new_cis, i);
-    }
-
-    return PJ_SUCCESS;
-}
 
 PJ_DEF(void) pj_cis_add_range(pj_cis_t *cis, int cstart, int cend)
 {
+    /* Can not set zero. This is the requirement of the parser. */
+    pj_assert(cstart > 0);
+
     while (cstart != cend) {
         PJ_CIS_SET(cis, cstart);
@@ -123,5 +91,6 @@
 {
     unsigned i;
-    for (i=0; i<256; ++i) {
+    /* Can not set zero. This is the requirement of the parser. */
+    for (i=1; i<256; ++i) {
 	if (PJ_CIS_ISSET(cis,i))
             PJ_CIS_CLR(cis,i);
@@ -285,4 +254,6 @@
     PJ_CHECK_STACK();
 
+    pj_assert(pj_cis_match(spec,0)==0);
+
     if (pj_scan_is_eof(scanner) || !pj_cis_match(spec, *s)) {
 	pj_scan_syntax_err(scanner);
@@ -292,5 +263,9 @@
     do {
 	++s;
-    } while (PJ_SCAN_CHECK_EOF(s) && pj_cis_match(spec, *s));
+    } while (pj_cis_match(spec, *s));
+    /* No need to check EOF here (PJ_SCAN_CHECK_EOF(s)) because
+     * buffer is NULL terminated and pj_cis_match(spec,0) should be
+     * false.
+     */
 
     pj_strset3(out, scanner->curptr, s);
Index: /pjproject/trunk/pjlib-util/src/pjlib-util/scanner_cis_bitwise.c
===================================================================
--- /pjproject/trunk/pjlib-util/src/pjlib-util/scanner_cis_bitwise.c	(revision 73)
+++ /pjproject/trunk/pjlib-util/src/pjlib-util/scanner_cis_bitwise.c	(revision 73)
@@ -0,0 +1,68 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+
+/*
+ * THIS FILE IS INCLUDED BY scanner.c.
+ * DO NOT COMPILE THIS FILE ALONE!
+ */
+
+PJ_DEF(void) pj_cis_buf_init( pj_cis_buf_t *cis_buf)
+{
+    pj_memset(cis_buf->cis_buf, 0, sizeof(cis_buf->cis_buf));
+    cis_buf->use_mask = 0;
+}
+
+PJ_DEF(pj_status_t) pj_cis_init(pj_cis_buf_t *cis_buf, pj_cis_t *cis)
+{
+    unsigned i;
+
+    cis->cis_buf = cis_buf->cis_buf;
+
+    for (i=0; i<PJ_CIS_MAX_INDEX; ++i) {
+        if ((cis_buf->use_mask & (1 << i)) == 0) {
+            cis->cis_id = i;
+	    cis_buf->use_mask |= (1 << i);
+            return PJ_SUCCESS;
+        }
+    }
+
+    cis->cis_id = PJ_CIS_MAX_INDEX;
+    return PJ_ETOOMANY;
+}
+
+PJ_DEF(pj_status_t) pj_cis_dup( pj_cis_t *new_cis, pj_cis_t *existing)
+{
+    pj_status_t status;
+    unsigned i;
+
+    /* Warning: typecasting here! */
+    status = pj_cis_init((pj_cis_buf_t*)existing->cis_buf, new_cis);
+    if (status != PJ_SUCCESS)
+        return status;
+
+    for (i=0; i<256; ++i) {
+        if (PJ_CIS_ISSET(existing, i))
+            PJ_CIS_SET(new_cis, i);
+        else
+            PJ_CIS_CLR(new_cis, i);
+    }
+
+    return PJ_SUCCESS;
+}
+
Index: /pjproject/trunk/pjlib-util/src/pjlib-util/scanner_cis_uint.c
===================================================================
--- /pjproject/trunk/pjlib-util/src/pjlib-util/scanner_cis_uint.c	(revision 73)
+++ /pjproject/trunk/pjlib-util/src/pjlib-util/scanner_cis_uint.c	(revision 73)
@@ -0,0 +1,43 @@
+/* $Id$ */
+/* 
+ * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
+ *
+ * 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
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ */
+
+/*
+ * THIS FILE IS INCLUDED BY scanner.c.
+ * DO NOT COMPILE THIS FILE ALONE!
+ */
+
+
+PJ_DEF(void) pj_cis_buf_init( pj_cis_buf_t *cis_buf)
+{
+    /* Do nothing. */
+}
+
+PJ_DEF(pj_status_t) pj_cis_init(pj_cis_buf_t *cis_buf, pj_cis_t *cis)
+{
+    pj_memset(cis->cis_buf, 0, sizeof(cis->cis_buf));
+    return PJ_SUCCESS;
+}
+
+PJ_DEF(pj_status_t) pj_cis_dup( pj_cis_t *new_cis, pj_cis_t *existing)
+{
+    pj_memcpy(new_cis, existing, sizeof(pj_cis_t));
+    return PJ_SUCCESS;
+}
+
+
Index: /pjproject/trunk/pjlib-util/src/pjlib-util/xml.c
===================================================================
--- /pjproject/trunk/pjlib-util/src/pjlib-util/xml.c	(revision 72)
+++ /pjproject/trunk/pjlib-util/src/pjlib-util/xml.c	(revision 73)
@@ -172,5 +172,5 @@
 	node =  xml_parse_node(pool, &scanner);
     }
-    PJ_DEFAULT {
+    PJ_CATCH_ANY {
 	PJ_LOG(4,(THIS_FILE, "Syntax error parsing XML in line %d column %d",
 		  scanner.line, scanner.col));
