Index: /pjproject/trunk/pjlib-util/build/pjlib_util.dsp
===================================================================
--- /pjproject/trunk/pjlib-util/build/pjlib_util.dsp	(revision 76)
+++ /pjproject/trunk/pjlib-util/build/pjlib_util.dsp	(revision 77)
@@ -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 /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 CPP /nologo /MD /W3 /GX /Zi /O2 /Oy /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"
Index: /pjproject/trunk/pjlib-util/include/pjlib-util/scanner.h
===================================================================
--- /pjproject/trunk/pjlib-util/include/pjlib-util/scanner.h	(revision 76)
+++ /pjproject/trunk/pjlib-util/include/pjlib-util/scanner.h	(revision 77)
@@ -194,10 +194,10 @@
 typedef struct pj_scanner
 {
-    char *begin;        /**< Start of input buffer. */
-    char *end;          /**< End of input buffer.   */
-    char *curptr;       /**< Current pointer.       */
-    int  line;          /**< Current line.          */
-    int  col;           /**< Current column.        */
-    int  skip_ws;       /**< Skip whitespace flag.  */
+    char *begin;        /**< Start of input buffer.	*/
+    char *end;          /**< End of input buffer.	*/
+    char *curptr;       /**< Current pointer.		*/
+    int   line;         /**< Current line.		*/
+    char *start_line;   /**< Where current line starts.	*/
+    int   skip_ws;      /**< Skip whitespace flag.	*/
     pj_syn_err_func_ptr callback;   /**< Syntax error callback. */
 } pj_scanner;
@@ -211,6 +211,6 @@
 {
     char *curptr;       /**< Current scanner's pointer. */
-    int   line;         /**< Current line.      */
-    int   col;          /**< Current column.    */
+    int   line;         /**< Current line.		*/
+    char *start_line;   /**< Start of current line.	*/
 } pj_scan_state;
 
@@ -326,5 +326,6 @@
 /** 
  * Get characters between quotes. If current input doesn't match begin_quote,
- * syntax error will be thrown.
+ * syntax error will be thrown. Note that the resulting string will contain
+ * the enclosing quote.
  *
  * @param scanner	The scanner.
@@ -334,6 +335,6 @@
  */
 PJ_DECL(void) pj_scan_get_quote( pj_scanner *scanner,
-				  int begin_quote, int end_quote, 
-				  pj_str_t *out);
+				 int begin_quote, int end_quote, 
+				 pj_str_t *out);
 
 /** 
@@ -356,13 +357,4 @@
  */
 PJ_DECL(int) pj_scan_get_char( pj_scanner *scanner );
-
-
-/** 
- * Get a newline from the scanner. A newline is defined as '\\n', or '\\r', or
- * "\\r\\n". If current input is not newline, syntax error will be thrown.
- *
- * @param scanner   The scanner.
- */
-PJ_DECL(void) pj_scan_get_newline( pj_scanner *scanner );
 
 
@@ -439,4 +431,32 @@
 PJ_DECL(int) pj_scan_stricmp( pj_scanner *scanner, const char *s, int len);
 
+/**
+ * Perform case insensitive string comparison of string in current position,
+ * knowing that the string to compare only consists of alphanumeric
+ * characters.
+ *
+ * Note that unlike #pj_scan_stricmp, this function can only return zero or
+ * -1.
+ *
+ * @param scanner   The scanner.
+ * @param s	    The string to compare with.
+ * @param len	    Length of the string to compare with.
+ *
+ * @return	    zero if equal or -1.
+ *
+ * @see strnicmp_alnum, pj_stricmp_alnum
+ */
+PJ_DECL(int) pj_scan_stricmp_alnum( pj_scanner *scanner, const char *s, 
+				    int len);
+
+
+/** 
+ * Get a newline from the scanner. A newline is defined as '\\n', or '\\r', or
+ * "\\r\\n". If current input is not newline, syntax error will be thrown.
+ *
+ * @param scanner   The scanner.
+ */
+PJ_DECL(void) pj_scan_get_newline( pj_scanner *scanner );
+
 
 /** 
@@ -448,4 +468,11 @@
 PJ_DECL(void) pj_scan_skip_whitespace( pj_scanner *scanner );
 
+
+/**
+ * Skip current line.
+ *
+ * @param scanner   The scanner.
+ */
+PJ_DECL(void) pj_scan_skip_line( pj_scanner *scanner );
 
 /** 
@@ -470,4 +497,16 @@
 
 /**
+ * Get current column position.
+ *
+ * @param scanner   The scanner.
+ *
+ * @return	    The column position.
+ */
+PJ_INLINE(int) pj_scan_get_col( pj_scanner *scanner )
+{
+    return scanner->curptr - scanner->start_line;
+}
+
+/**
  * @}
  */
Index: /pjproject/trunk/pjlib-util/src/pjlib-util/scanner.c
===================================================================
--- /pjproject/trunk/pjlib-util/src/pjlib-util/scanner.c	(revision 76)
+++ /pjproject/trunk/pjlib-util/src/pjlib-util/scanner.c	(revision 77)
@@ -24,7 +24,8 @@
 #include <pj/assert.h>
 
-#define PJ_SCAN_IS_SPACE(c)	((c)==' ' || (c)=='\t')
-#define PJ_SCAN_IS_NEWLINE(c)	((c)=='\r' || (c)=='\n')
-#define PJ_SCAN_CHECK_EOF(s)	(s != end)
+#define PJ_SCAN_IS_SPACE(c)		((c)==' ' || (c)=='\t')
+#define PJ_SCAN_IS_NEWLINE(c)		((c)=='\r' || (c)=='\n')
+#define PJ_SCAN_IS_PROBABLY_SPACE(c)	((c) <= 32)
+#define PJ_SCAN_CHECK_EOF(s)		(*s)
 
 
@@ -108,5 +109,5 @@
     scanner->end = bufstart + buflen;
     scanner->line = 1;
-    scanner->col = 1;
+    scanner->start_line = scanner->begin;
     scanner->callback = callback;
     scanner->skip_ws = options;
@@ -114,6 +115,4 @@
     if (scanner->skip_ws) 
 	pj_scan_skip_whitespace(scanner);
-
-    scanner->col = scanner->curptr - scanner->begin + 1;
 }
 
@@ -129,11 +128,9 @@
     register char *s = scanner->curptr;
 
-    PJ_CHECK_STACK();
-
     while (PJ_SCAN_IS_SPACE(*s)) {
 	++s;
     }
 
-    if ((scanner->skip_ws & PJ_SCAN_AUTOSKIP_NEWLINE) && PJ_SCAN_IS_NEWLINE(*s)) {
+    if (PJ_SCAN_IS_NEWLINE(*s) && (scanner->skip_ws & PJ_SCAN_AUTOSKIP_NEWLINE)) {
 	for (;;) {
 	    if (*s == '\r') {
@@ -141,11 +138,9 @@
 		if (*s == '\n') ++s;
 		++scanner->line;
-		scanner->col = 1;
-		scanner->curptr = s;
+		scanner->curptr = scanner->start_line = s;
 	    } else if (*s == '\n') {
 		++s;
 		++scanner->line;
-		scanner->col = 1;
-		scanner->curptr = s;
+		scanner->curptr = scanner->start_line = s;
 	    } else if (PJ_SCAN_IS_SPACE(*s)) {
 		do {
@@ -160,5 +155,4 @@
     if (PJ_SCAN_IS_NEWLINE(*s) && (scanner->skip_ws & PJ_SCAN_AUTOSKIP_WS_HEADER)==PJ_SCAN_AUTOSKIP_WS_HEADER) {
 	/* Check for header continuation. */
-	scanner->col += s - scanner->curptr;
 	scanner->curptr = s;
 
@@ -169,4 +163,6 @@
 	    ++s;
 	}
+	scanner->start_line = s;
+
 	if (PJ_SCAN_IS_SPACE(*s)) {
 	    register char *t = s;
@@ -176,10 +172,22 @@
 
 	    ++scanner->line;
-	    scanner->col = t-s;
 	    scanner->curptr = t;
 	}
     } else {
-	scanner->col += s - scanner->curptr;
 	scanner->curptr = s;
+    }
+}
+
+PJ_DEF(void) pj_scan_skip_line( pj_scanner *scanner )
+{
+    char *s = pj_native_strchr(scanner->curptr, '\n');
+    if (!s) {
+	scanner->curptr = scanner->end;
+    } else {
+	scanner->curptr = scanner->start_line = s+1;
+	scanner->line++;
+	if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) {
+	    pj_scan_skip_whitespace(scanner);    
+	}
     }
 }
@@ -189,18 +197,16 @@
 {
     register char *s = scanner->curptr;
-    register char *end = scanner->end;
-
-    PJ_CHECK_STACK();
-
-    if (pj_scan_is_eof(scanner)) {
+
+    if (s >= scanner->end) {
 	pj_scan_syntax_err(scanner);
 	return -1;
     }
 
-    while (PJ_SCAN_CHECK_EOF(s) && pj_cis_match(spec, *s))
-	++s;
-
-    pj_strset3(out, scanner->curptr, s);
-    return s < scanner->end ? *s : 0;
+    /* Don't need to check EOF with PJ_SCAN_CHECK_EOF(s) */
+    while (pj_cis_match(spec, *s))
+	++s;
+
+    pj_strset3(out, scanner->curptr, s);
+    return *s;
 }
 
@@ -210,6 +216,4 @@
 {
     char *endpos = scanner->curptr + len;
-
-    PJ_CHECK_STACK();
 
     if (endpos > scanner->end) {
@@ -228,9 +232,6 @@
 {
     register char *s = scanner->curptr;
-    register char *end = scanner->end;
-
-    PJ_CHECK_STACK();
-
-    if (pj_scan_is_eof(scanner)) {
+
+    if (s >= scanner->end) {
 	pj_scan_syntax_err(scanner);
 	return -1;
@@ -241,5 +242,5 @@
 
     pj_strset3(out, scanner->curptr, s);
-    return s!=scanner->end ? *s : 0;
+    return *s;
 }
 
@@ -249,12 +250,9 @@
 {
     register char *s = scanner->curptr;
-    register char *end = scanner->end;
-    char *start = s;
-
-    PJ_CHECK_STACK();
 
     pj_assert(pj_cis_match(spec,0)==0);
 
-    if (pj_scan_is_eof(scanner) || !pj_cis_match(spec, *s)) {
+    /* EOF is detected implicitly */
+    if (!pj_cis_match(spec, *s)) {
 	pj_scan_syntax_err(scanner);
 	return;
@@ -271,8 +269,7 @@
     pj_strset3(out, scanner->curptr, s);
 
-    scanner->col += (s - start);
     scanner->curptr = s;
 
-    if (scanner->skip_ws) {
+    if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) {
 	pj_scan_skip_whitespace(scanner);    
     }
@@ -285,9 +282,5 @@
 {
     register char *s = scanner->curptr;
-    register char *end = scanner->end;
-    char *start = s;
     
-    PJ_CHECK_STACK();
-
     /* Check and eat the begin_quote. */
     if (*s != begin_quote) {
@@ -301,7 +294,7 @@
     do {
 	/* loop until end_quote is found. */
-	do {
+	while (*s && *s != '\n' && *s != end_quote) {
 	    ++s;
-	} while (s != end && *s != '\n' && *s != end_quote);
+	}
 
 	/* check that no backslash character precedes the end_quote. */
@@ -319,6 +312,8 @@
 		    /* break from main loop if we have odd number of backslashes */
 		    if (((unsigned)(q-r) & 0x01) == 1) {
+			++s;
 			break;
 		    }
+		    ++s;
 		}
 	    } else {
@@ -341,8 +336,7 @@
     pj_strset3(out, scanner->curptr, s);
 
-    scanner->col += (s - start);
     scanner->curptr = s;
 
-    if (scanner->skip_ws) {
+    if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) {
 	pj_scan_skip_whitespace(scanner);
     }
@@ -350,11 +344,6 @@
 
 PJ_DEF(void) pj_scan_get_n( pj_scanner *scanner,
-			     unsigned N, pj_str_t *out)
-{
-    register char *s = scanner->curptr;
-    char *start = scanner->curptr;
-
-    PJ_CHECK_STACK();
-
+			    unsigned N, pj_str_t *out)
+{
     if (scanner->curptr + N > scanner->end) {
 	pj_scan_syntax_err(scanner);
@@ -362,11 +351,9 @@
     }
 
-    pj_strset(out, s, N);
+    pj_strset(out, scanner->curptr, N);
     
-    s += N;
-    scanner->col += (s - start);
-    scanner->curptr = s;
-
-    if (scanner->skip_ws) {
+    scanner->curptr += N;
+
+    if (PJ_SCAN_IS_PROBABLY_SPACE(*scanner->curptr) && scanner->skip_ws) {
 	pj_scan_skip_whitespace(scanner);
     }
@@ -376,10 +363,7 @@
 PJ_DEF(int) pj_scan_get_char( pj_scanner *scanner )
 {
-    char *start = scanner->curptr;
-    int chr = *start;
-
-    PJ_CHECK_STACK();
-
-    if (pj_scan_is_eof(scanner)) {
+    int chr = *scanner->curptr;
+
+    if (!chr) {
 	pj_scan_syntax_err(scanner);
 	return 0;
@@ -387,7 +371,6 @@
 
     ++scanner->curptr;
-    scanner->col += (scanner->curptr - start);
-
-    if (scanner->skip_ws) {
+
+    if (PJ_SCAN_IS_PROBABLY_SPACE(*scanner->curptr) && scanner->skip_ws) {
 	pj_scan_skip_whitespace(scanner);
     }
@@ -398,6 +381,4 @@
 PJ_DEF(void) pj_scan_get_newline( pj_scanner *scanner )
 {
-    PJ_CHECK_STACK();
-
     if (!PJ_SCAN_IS_NEWLINE(*scanner->curptr)) {
 	pj_scan_syntax_err(scanner);
@@ -413,7 +394,7 @@
 
     ++scanner->line;
-    scanner->col = 1;
-
-    if (scanner->skip_ws) {
+    scanner->start_line = scanner->curptr;
+
+    if (PJ_SCAN_IS_PROBABLY_SPACE(*scanner->curptr) && scanner->skip_ws) {
 	pj_scan_skip_whitespace(scanner);
     }
@@ -425,10 +406,6 @@
 {
     register char *s = scanner->curptr;
-    register char *end = scanner->end;
-    char *start = s;
-
-    PJ_CHECK_STACK();
-
-    if (pj_scan_is_eof(scanner)) {
+
+    if (s >= scanner->end) {
 	pj_scan_syntax_err(scanner);
 	return;
@@ -441,8 +418,7 @@
     pj_strset3(out, scanner->curptr, s);
 
-    scanner->col += (s - start);
     scanner->curptr = s;
 
-    if (scanner->skip_ws) {
+    if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) {
 	pj_scan_skip_whitespace(scanner);
     }
@@ -454,10 +430,6 @@
 {
     register char *s = scanner->curptr;
-    register char *end = scanner->end;
-    char *start = s;
-
-    PJ_CHECK_STACK();
-
-    if (pj_scan_is_eof(scanner)) {
+
+    if (s >= scanner->end) {
 	pj_scan_syntax_err(scanner);
 	return;
@@ -470,8 +442,7 @@
     pj_strset3(out, scanner->curptr, s);
 
-    scanner->col += (s - start);
     scanner->curptr = s;
 
-    if (scanner->skip_ws) {
+    if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) {
 	pj_scan_skip_whitespace(scanner);
     }
@@ -483,24 +454,21 @@
 {
     register char *s = scanner->curptr;
-    register char *end = scanner->end;
-    char *start = scanner->curptr;
-
-    PJ_CHECK_STACK();
-
-    if (pj_scan_is_eof(scanner)) {
-	pj_scan_syntax_err(scanner);
-	return;
-    }
-
-    while (PJ_SCAN_CHECK_EOF(s) && !strchr(until_spec, *s)) {
-	++s;
-    }
-
-    pj_strset3(out, scanner->curptr, s);
-
-    scanner->col += (s - start);
+    int speclen;
+
+    if (s >= scanner->end) {
+	pj_scan_syntax_err(scanner);
+	return;
+    }
+
+    speclen = strlen(until_spec);
+    while (PJ_SCAN_CHECK_EOF(s) && !memchr(until_spec, *s, speclen)) {
+	++s;
+    }
+
+    pj_strset3(out, scanner->curptr, s);
+
     scanner->curptr = s;
 
-    if (scanner->skip_ws) {
+    if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) {
 	pj_scan_skip_whitespace(scanner);
     }
@@ -512,6 +480,4 @@
     char *start = scanner->curptr;
 
-    PJ_CHECK_STACK();
-
     if (scanner->curptr + N > scanner->end) {
 	pj_scan_syntax_err(scanner);
@@ -520,7 +486,6 @@
 
     scanner->curptr += N;
-    scanner->col += (scanner->curptr - start);
-
-    if (skip_ws) {
+
+    if (PJ_SCAN_IS_PROBABLY_SPACE(*scanner->curptr) && skip_ws) {
 	pj_scan_skip_whitespace(scanner);
     }
@@ -547,12 +512,19 @@
 }
 
+PJ_DEF(int) pj_scan_stricmp_alnum( pj_scanner *scanner, const char *s, 
+				   int len)
+{
+    if (scanner->curptr + len > scanner->end) {
+	pj_scan_syntax_err(scanner);
+	return -1;
+    }
+    return strnicmp_alnum(scanner->curptr, s, len);
+}
 
 PJ_DEF(void) pj_scan_save_state( pj_scanner *scanner, pj_scan_state *state)
 {
-    PJ_CHECK_STACK();
-
     state->curptr = scanner->curptr;
     state->line = scanner->line;
-    state->col = scanner->col;
+    state->start_line = scanner->start_line;
 }
 
@@ -561,10 +533,8 @@
 				     pj_scan_state *state)
 {
-    PJ_CHECK_STACK();
-
     scanner->curptr = state->curptr;
     scanner->line = state->line;
-    scanner->col = state->col;
-}
-
-
+    scanner->start_line = state->start_line;
+}
+
+
Index: /pjproject/trunk/pjlib-util/src/pjlib-util/xml.c
===================================================================
--- /pjproject/trunk/pjlib-util/src/pjlib-util/xml.c	(revision 76)
+++ /pjproject/trunk/pjlib-util/src/pjlib-util/xml.c	(revision 77)
@@ -174,5 +174,5 @@
     PJ_CATCH_ANY {
 	PJ_LOG(4,(THIS_FILE, "Syntax error parsing XML in line %d column %d",
-		  scanner.line, scanner.col));
+		  scanner.line, pj_scan_get_col(&scanner)));
     }
     PJ_END;
Index: /pjproject/trunk/pjlib/include/pj/string.h
===================================================================
--- /pjproject/trunk/pjlib/include/pj/string.h	(revision 76)
+++ /pjproject/trunk/pjlib/include/pj/string.h	(revision 77)
@@ -343,9 +343,27 @@
  * Perform lowercase comparison to the strings which consists of only
  * alnum characters. More over, it will only return non-zero if both
- * strings are not equal, and is not able to detect which string is
- * 'less'.
+ * strings are not equal, not the usual negative or positive value.
  *
  * If non-alnum inputs are given, then the function may mistakenly 
- * treat two strings as equal while they're not.
+ * treat two strings as equal.
+ *
+ * @param str1	    The string to compare.
+ * @param str2	    The string to compare.
+ * @param len	    The length to compare.
+ *
+ * @return 
+ *      - 0	    if str1 is equal to str2
+ *      - (-1)	    if not equal.
+ */
+PJ_IDECL(int) strnicmp_alnum(const char *str1, const char *str2,
+			     int len);
+
+/**
+ * Perform lowercase comparison to the strings which consists of only
+ * alnum characters. More over, it will only return non-zero if both
+ * strings are not equal, not the usual negative or positive value.
+ *
+ * If non-alnum inputs are given, then the function may mistakenly 
+ * treat two strings as equal.
  *
  * @param str1	    The string to compare.
Index: /pjproject/trunk/pjlib/include/pj/string_i.h
===================================================================
--- /pjproject/trunk/pjlib/include/pj/string_i.h	(revision 76)
+++ /pjproject/trunk/pjlib/include/pj/string_i.h	(revision 77)
@@ -170,4 +170,37 @@
 }
 
+PJ_IDEF(int) strnicmp_alnum( const char *str1, const char *str2,
+			     int len)
+{
+    if (len==0)
+	return 0;
+    else {
+	register const pj_uint32_t *p1 = (pj_uint32_t*)str1, 
+		                   *p2 = (pj_uint32_t*)str2;
+	while (len > 3 && (*p1 & 0x5F5F5F5F)==(*p2 & 0x5F5F5F5F))
+	    ++p1, ++p2, len-=4;
+
+	if (len > 3)
+	    return -1;
+#if defined(PJ_IS_LITTLE_ENDIAN) && PJ_IS_LITTLE_ENDIAN!=0
+	else if (len==3)
+	    return ((*p1 & 0x005F5F5F)==(*p2 & 0x005F5F5F)) ? 0 : -1;
+	else if (len==2)
+	    return ((*p1 & 0x00005F5F)==(*p2 & 0x00005F5F)) ? 0 : -1;
+	else if (len==1)
+	    return ((*p1 & 0x0000005F)==(*p2 & 0x0000005F)) ? 0 : -1;
+#else
+	else if (len==3)
+	    return ((*p1 & 0x5F5F5F00)==(*p2 & 0x5F5F5F00)) ? 0 : -1;
+	else if (len==2)
+	    return ((*p1 & 0x5F5F0000)==(*p2 & 0x5F5F0000)) ? 0 : -1;
+	else if (len==1)
+	    return ((*p1 & 0x5F000000)==(*p2 & 0x5F000000)) ? 0 : -1;
+#endif
+	else 
+	    return 0;
+    }
+}
+
 PJ_IDEF(int) pj_stricmp_alnum(const pj_str_t *str1, const pj_str_t *str2)
 {
@@ -181,5 +214,5 @@
 	register const pj_uint32_t *p1 = (pj_uint32_t*)str1->ptr, 
 		                   *p2 = (pj_uint32_t*)str2->ptr;
-	while (len > 3 && (*p1 & 0x1F1F1F1F)==(*p2 & 0x1F1F1F1F))
+	while (len > 3 && (*p1 & 0x5F5F5F5F)==(*p2 & 0x5F5F5F5F))
 	    ++p1, ++p2, len-=4;
 
@@ -188,16 +221,16 @@
 #if defined(PJ_IS_LITTLE_ENDIAN) && PJ_IS_LITTLE_ENDIAN!=0
 	else if (len==3)
-	    return ((*p1 & 0x001F1F1F)==(*p2 & 0x001F1F1F)) ? 0 : -1;
-	else if (len==2)
-	    return ((*p1 & 0x00001F1F)==(*p2 & 0x00001F1F)) ? 0 : -1;
-	else if (len==1)
-	    return ((*p1 & 0x0000001F)==(*p2 & 0x0000001F)) ? 0 : -1;
+	    return ((*p1 & 0x005F5F5F)==(*p2 & 0x005F5F5F)) ? 0 : -1;
+	else if (len==2)
+	    return ((*p1 & 0x00005F5F)==(*p2 & 0x00005F5F)) ? 0 : -1;
+	else if (len==1)
+	    return ((*p1 & 0x0000005F)==(*p2 & 0x0000005F)) ? 0 : -1;
 #else
 	else if (len==3)
-	    return ((*p1 & 0x1F1F1F00)==(*p2 & 0x1F1F1F00)) ? 0 : -1;
-	else if (len==2)
-	    return ((*p1 & 0x1F1F0000)==(*p2 & 0x1F1F0000)) ? 0 : -1;
-	else if (len==1)
-	    return ((*p1 & 0x1F000000)==(*p2 & 0x1F000000)) ? 0 : -1;
+	    return ((*p1 & 0x5F5F5F00)==(*p2 & 0x5F5F5F00)) ? 0 : -1;
+	else if (len==2)
+	    return ((*p1 & 0x5F5F0000)==(*p2 & 0x5F5F0000)) ? 0 : -1;
+	else if (len==1)
+	    return ((*p1 & 0x5F000000)==(*p2 & 0x5F000000)) ? 0 : -1;
 #endif
 	else 
Index: /pjproject/trunk/pjlib/src/pjlib-test/string.c
===================================================================
--- /pjproject/trunk/pjlib/src/pjlib-test/string.c	(revision 76)
+++ /pjproject/trunk/pjlib/src/pjlib-test/string.c	(revision 77)
@@ -104,4 +104,5 @@
     STRTEST( 0, "a",buf+0,-510);
     STRTEST( 0, "a",buf+1,-512);
+    STRTEST( -1, "0", "P", -514);
 
     /* equal, length=2 
Index: /pjproject/trunk/pjsip/build/pjsip_core.dsp
===================================================================
--- /pjproject/trunk/pjsip/build/pjsip_core.dsp	(revision 76)
+++ /pjproject/trunk/pjsip/build/pjsip_core.dsp	(revision 77)
@@ -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 /W4 /Zi /O2 /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /c
+# ADD CPP /nologo /MD /W4 /Zi /O2 /Oy /I "../include" /I "../../pjlib/include" /I "../../pjlib-util/include" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "_LIB" /D PJ_WIN32=1 /D PJ_M_I386=1 /FR /FD /c
 # SUBTRACT CPP /YX
 # ADD BASE RSC /l 0x409 /d "NDEBUG"
Index: /pjproject/trunk/pjsip/include/pjsip/print_util.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsip/print_util.h	(revision 76)
+++ /pjproject/trunk/pjsip/include/pjsip/print_util.h	(revision 77)
@@ -20,27 +20,10 @@
 #define __PJSIP_PRINT_H__
 
-/* Minimum space left in the buffer */
-#define MIN_SPACE	10
-
 #define copy_advance_check(buf,str)   \
 	do { \
-	    if ((str).slen+MIN_SPACE >= (endbuf-buf)) return -1;	\
+	    if ((str).slen >= (endbuf-buf)) return -1;	\
 	    pj_memcpy(buf, (str).ptr, (str).slen); \
 	    buf += (str).slen; \
 	} while (0)
-
-/*
-static char *imp_copy_advance_pair(char *buf, char *endbuf, const char *str1, int len1, const pj_str_t *str2)
-{
-    if (str2->slen) {
-	int printed = len1+str2->slen;
-	if (printed+MIN_SPACE >= (endbuf-buf)) return NULL;
-	pj_memcpy(buf,str1,len1);
-	pj_memcpy(buf+len1, str2->ptr, str2->slen);
-	return buf + printed;
-    } else
-	return buf;
-}
-*/
 
 #define copy_advance_pair_check(buf,str1,len1,str2)   \
@@ -48,5 +31,5 @@
 	    if (str2.slen) { \
 		printed = len1+str2.slen; \
-		if (printed+MIN_SPACE >= (endbuf-buf)) return -1;	\
+		if (printed >= (endbuf-buf)) return -1;	\
 		pj_memcpy(buf,str1,len1); \
 		pj_memcpy(buf+len1, str2.ptr, str2.slen); \
@@ -54,11 +37,4 @@
 	    } \
 	} while (0)
-/*
-#define copy_advance_pair(buf,str1,len1,str2)   \
-	do { \
-	    buf = imp_copy_advance_pair(buf, endbuf, str1, len1, &str2); \
-	    if (buf == NULL) return -1; \
-	} while (0)
-*/
 
 #define copy_advance_pair_quote_check(buf,str1,len1,str2,quotebegin,quoteend) \
@@ -66,5 +42,5 @@
 	    if (str2.slen) { \
 		printed = len1+str2.slen+2; \
-		if (printed+MIN_SPACE >= (endbuf-buf)) return -1;	\
+		if (printed >= (endbuf-buf)) return -1;	\
 		pj_memcpy(buf,str1,len1); \
 		*(buf+len1)=quotebegin; \
@@ -77,14 +53,11 @@
 #define copy_advance_pair_escape(buf,str1,len1,str2,unres)	\
 	do { \
-	    if (str2.slen) { \
-		pj_ssize_t esc_len; \
-		if (len1+str2.slen+MIN_SPACE >= (endbuf-buf)) return -1; \
-		pj_memcpy(buf,str1,len1); \
-		buf += len1; \
-		esc_len=pj_strncpy2_escape(buf, &str2, (endbuf-buf), &unres); \
-		if (esc_len < 0) return -1; \
-		buf += esc_len; \
-		if (endbuf-buf < MIN_SPACE) return -1; \
-	    } \
+	  if (str2.slen) { \
+	    if (len1+str2.slen >= (endbuf-buf)) return -1; \
+	    pj_memcpy(buf,str1,len1); \
+	    printed=pj_strncpy2_escape(buf,&str2,(endbuf-buf-len1),&unres);\
+	    if (printed < 0) return -1; \
+	    buf += (printed+len1); \
+	  } \
 	} while (0)
 
@@ -98,9 +71,8 @@
 #define copy_advance_escape(buf,str,unres)    \
 	do { \
-	    pj_ssize_t len = \
+	    printed = \
 		pj_strncpy2_escape(buf, &(str), (endbuf-buf), &(unres)); \
-	    if (len < 0) return -1; \
-	    buf += len; \
-	    if (endbuf-buf < MIN_SPACE) return -1; \
+	    if (printed < 0) return -1; \
+	    buf += printed; \
 	} while (0)
 
@@ -118,8 +90,8 @@
 #define copy_advance_pair_quote_cond(buf,str1,len1,str2,quotebegin,quoteend) \
 	do {	\
-	    if (str2.slen && *str2.ptr!=quotebegin) \
-		copy_advance_pair_quote(buf,str1,len1,str2,quotebegin,quoteend); \
-	    else \
-		copy_advance_pair(buf,str1,len1,str2); \
+	  if (str2.slen && *str2.ptr!=quotebegin) \
+	    copy_advance_pair_quote(buf,str1,len1,str2,quotebegin,quoteend); \
+	  else \
+	    copy_advance_pair(buf,str1,len1,str2); \
 	} while (0)
 
Index: /pjproject/trunk/pjsip/include/pjsip/sip_parser.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsip/sip_parser.h	(revision 76)
+++ /pjproject/trunk/pjsip/include/pjsip/sip_parser.h	(revision 77)
@@ -308,6 +308,8 @@
     pjsip_PASSWD_SPEC,		/**< Password. */
     pjsip_USER_SPEC,		/**< User */
-    pjsip_NEWLINE_OR_EOF_SPEC,  /**< For eating up header.*/
-    pjsip_DISPLAY_SCAN_SPEC;    /**< Used when searching for display name. */
+    pjsip_NOT_NEWLINE,		/**< For eating up header, basicly any chars
+				     except newlines or zero. */
+    pjsip_NOT_COMMA_OR_NEWLINE, /**< Array elements. */
+    pjsip_DISPLAY_SPEC;		/**< Used when searching for display name. */
 
 /*
Index: /pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c	(revision 76)
+++ /pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c	(revision 77)
@@ -105,4 +105,5 @@
 				     pj_status_t, pjsip_rx_data*);
 
+void init_sip_parser(void);
 
 /*
@@ -373,4 +374,7 @@
     endpt->pool = pool;
     endpt->pf = pf;
+
+    /* Init parser. */
+    init_sip_parser();
 
     /* Get name. */
Index: /pjproject/trunk/pjsip/src/pjsip/sip_parser.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip/sip_parser.c	(revision 76)
+++ /pjproject/trunk/pjsip/src/pjsip/sip_parser.c	(revision 77)
@@ -66,5 +66,4 @@
 static int parser_is_initialized;
 
-
 /*
  * Global vars (also extern).
@@ -102,7 +101,7 @@
 	    pjsip_PASSWD_SPEC,	        /* Password. */
 	    pjsip_USER_SPEC,	        /* User */
-	    pjsip_ARRAY_ELEMENTS,       /* Array separator. */
-	    pjsip_NEWLINE_OR_EOF_SPEC,  /* For eating up header.*/
-	    pjsip_DISPLAY_SCAN_SPEC;    /* Used when searching for display name
+	    pjsip_NOT_COMMA_OR_NEWLINE, /* Array separator. */
+	    pjsip_NOT_NEWLINE,		/* For eating up header.*/
+	    pjsip_DISPLAY_SPEC;         /* Used when searching for display name
                                          * in URL. */
 
@@ -259,12 +258,13 @@
     pj_cis_add_num( &pjsip_ALNUM_SPEC );
 
-    status = pj_cis_init(&cis_buf, &pjsip_NEWLINE_OR_EOF_SPEC);
-    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
-    pj_cis_add_str(&pjsip_NEWLINE_OR_EOF_SPEC, "\r\n");
-    //pj_cs_set(pjsip_NEWLINE_OR_EOF_SPEC, 0);
-
-    status = pj_cis_init(&cis_buf, &pjsip_ARRAY_ELEMENTS);
-    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
-    pj_cis_add_str( &pjsip_ARRAY_ELEMENTS, ",\r\n");
+    status = pj_cis_init(&cis_buf, &pjsip_NOT_NEWLINE);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+    pj_cis_add_str(&pjsip_NOT_NEWLINE, "\r\n");
+    pj_cis_invert(&pjsip_NOT_NEWLINE);
+
+    status = pj_cis_init(&cis_buf, &pjsip_NOT_COMMA_OR_NEWLINE);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+    pj_cis_add_str( &pjsip_NOT_COMMA_OR_NEWLINE, ",\r\n");
+    pj_cis_invert(&pjsip_NOT_COMMA_OR_NEWLINE);
 
     status = pj_cis_dup(&pjsip_TOKEN_SPEC, &pjsip_ALNUM_SPEC);
@@ -301,7 +301,8 @@
     pj_cis_invert( &pjsip_PROBE_USER_HOST_SPEC );
 
-    status = pj_cis_init(&cis_buf, &pjsip_DISPLAY_SCAN_SPEC);
-    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
-    pj_cis_add_str( &pjsip_DISPLAY_SCAN_SPEC, ":\r\n<");
+    status = pj_cis_init(&cis_buf, &pjsip_DISPLAY_SPEC);
+    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
+    pj_cis_add_str( &pjsip_DISPLAY_SPEC, ":\r\n<");
+    pj_cis_invert(&pjsip_DISPLAY_SPEC);
 
     status = pjsip_register_hdr_parser( "Accept", NULL, &parse_hdr_accept);
@@ -375,5 +376,5 @@
 }
 
-static void init_sip_parser(void)
+void init_sip_parser(void)
 {
     if (!parser_is_initialized) {
@@ -393,20 +394,24 @@
  * - >0 if handler is 'greater' than header name.
  */
-static int compare_handler( const handler_rec *r1, 
+PJ_INLINE(int) compare_handler( const handler_rec *r1, 
 			    const char *name, 
 			    pj_size_t name_len,
 			    pj_uint32_t hash )
 {
+    PJ_UNUSED_ARG(name_len);
+
+    /* Compare hashed value. */
+    if (r1->hname_hash < hash)
+	return -1;
+    if (r1->hname_hash > hash)
+	return 1;
+
     /* Compare length. */
+    /*
     if (r1->hname_len < name_len)
 	return -1;
     if (r1->hname_len > name_len)
 	return 1;
-
-    /* Length is equal, compare hashed value. */
-    if (r1->hname_hash < hash)
-	return -1;
-    if (r1->hname_hash > hash)
-	return 1;
+     */
 
     /* Equal length and equal hash. compare the strings. */
@@ -610,8 +615,9 @@
 
     /* Find the end of header area by finding an empty line. */
-    if ((pos = pj_native_strstr(buf, "\n\r\n")) == NULL) {
+    pos = pj_native_strstr(buf, "\n\r\n");
+    if (pos == NULL) {
 	return PJSIP_EPARTIALMSG;
     }
-
+ 
     hdr_end = pos+1;
     body_start = pos+3;
@@ -619,8 +625,8 @@
     /* Find "Content-Length" header the hard way. */
     line = pj_native_strchr(buf, '\n');
-    while (line && line < hdr_end-14) {
+    while (line && line < hdr_end) {
 	++line;
 	if ( ((*line=='C' || *line=='c') && 
-              pj_native_strncasecmp(line, "Content-Length", 14) == 0) ||
+              strnicmp_alnum(line, "Content-Length", 14) == 0) ||
 	     ((*line=='l' || *line=='L') && 
               (*(line+1)==' ' || *(line+1)=='\t' || *(line+1)==':')))
@@ -745,6 +751,6 @@
 				 pjsip_parser_err_report *err_list)
 {
-    int ch;
     pjsip_msg *msg;
+    pj_str_t hname;
     pjsip_ctype_hdr *ctype_hdr = NULL;
     pj_scanner *scanner = ctx->scanner;
@@ -753,12 +759,10 @@
 
     /* Skip leading newlines. */
-    ch = *scanner->curptr;
-    while (ch=='\r' || ch=='\n') {
-	pj_scan_get_char(scanner);
-	ch = *scanner->curptr;
+    while (*scanner->curptr=='\r' || *scanner->curptr=='\n') {
+	pj_scan_get_newline(scanner);
     }
 
     /* Parse request or status line */
-    if (pj_scan_stricmp( scanner, PJSIP_VERSION, 7) == 0) {
+    if (pj_scan_stricmp_alnum( scanner, PJSIP_VERSION, 7) == 0) {
 	msg = pjsip_msg_create(pool, PJSIP_RESPONSE_MSG);
 	int_parse_status_line( scanner, &msg->line.status );
@@ -769,20 +773,21 @@
 
     /* Parse headers. */
-    do {
-	pj_str_t hname;
-	pjsip_parse_hdr_func * handler;
-	pjsip_hdr *hdr = NULL;
-
-	/* Get hname. */
-	pj_scan_get( scanner, &pjsip_TOKEN_SPEC, &hname);
-	ch = pj_scan_get_char( scanner );
-	if (ch != ':') {
-	    PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
-	}
-
-	/* Find handler. */
-	handler = find_handler(&hname);
-
-	PJ_TRY {
+parse_headers:
+
+    PJ_TRY 
+    {
+	do {
+	    pjsip_parse_hdr_func * handler;
+	    pjsip_hdr *hdr = NULL;
+	    
+	    /* Get hname. */
+	    pj_scan_get( scanner, &pjsip_TOKEN_SPEC, &hname);
+	    if (pj_scan_get_char( scanner ) != ':') {
+		PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
+	    }
+	    
+	    /* Find handler. */
+	    handler = find_handler(&hname);
+	    
 	    /* Call the handler if found.
 	     * If no handler is found, then treat the header as generic
@@ -796,44 +801,13 @@
 		hdr->name = hdr->sname = hname;
 	    }
-
+	    
 	    /* Check if we've just parsed a Content-Type header. 
-	     * We will check for a message body if we've got Content-Type header.
+	     * We will check for a message body if we've got Content-Type 
+	     * header.
 	     */
 	    if (hdr->type == PJSIP_H_CONTENT_TYPE) {
 		ctype_hdr = (pjsip_ctype_hdr*)hdr;
 	    }
-
-	}
-	PJ_CATCH_ANY {
-	    /* Exception was thrown during parsing. 
-	     * Skip until newline, and parse next header. 
-	     */
-	    pj_str_t token;
-	    hdr = NULL;
-
-	    //PJ_LOG(4,("sipparser", 
-            //          "Syntax error in line %d col %d (hname=%.*s)",
-	    //	      scanner->line, scanner->col, hname.slen, hname.ptr));
-
-	    if (err_list) {
-		pjsip_parser_err_report *err_info;
 		
-		err_info = pj_pool_alloc(pool, sizeof(*err_info));
-		err_info->except_code = PJ_GET_EXCEPTION();
-		err_info->line = scanner->line;
-		err_info->col = scanner->col;
-		err_info->hname = hname;
-
-		pj_list_insert_before(err_list, err_info);
-	    }
-
-	    if (!pj_scan_is_eof(scanner)) {
-		pj_scan_get_until(scanner, &pjsip_NEWLINE_OR_EOF_SPEC, &token);
-		parse_hdr_end(scanner);
-	    }
-	}
-	PJ_END;
-
-	if (hdr) {
 	    /* Single parse of header line can produce multiple headers.
 	     * For example, if one Contact: header contains Contact list
@@ -843,9 +817,42 @@
 	     */
 	    pj_list_insert_nodes_before(&msg->hdr, hdr);
-	}
-
-	/* Parse until EOF or an empty line is found. */
-    } while (!pj_scan_is_eof(scanner) && 
-	      *scanner->curptr != '\r' && *scanner->curptr != '\n');
+	    
+	    /* Parse until EOF or an empty line is found. */
+	} while (!pj_scan_is_eof(scanner) && 
+		  *scanner->curptr != '\r' && *scanner->curptr != '\n');
+	
+    }
+    PJ_CATCH_ANY 
+    {
+	/* Exception was thrown during parsing. 
+	 * Skip until newline, and parse next header. 
+	 */
+	pj_str_t token;
+	
+	if (err_list) {
+	    pjsip_parser_err_report *err_info;
+	    
+	    err_info = pj_pool_alloc(pool, sizeof(*err_info));
+	    err_info->except_code = PJ_GET_EXCEPTION();
+	    err_info->line = scanner->line;
+	    err_info->col = pj_scan_get_col(scanner);
+	    err_info->hname = hname;
+	    
+	    pj_list_insert_before(err_list, err_info);
+	}
+	
+	if (!pj_scan_is_eof(scanner)) {
+	    pj_scan_get(scanner, &pjsip_NOT_NEWLINE, &token);
+	    parse_hdr_end(scanner);
+	}
+
+	if (!pj_scan_is_eof(scanner) && 
+	    *scanner->curptr != '\r' && *scanner->curptr != '\n');
+	{
+	    goto parse_headers;
+	}
+    }
+    PJ_END;
+
 
     /* If empty line is found, eat it. */
@@ -859,7 +866,8 @@
     if (ctype_hdr && scanner->curptr!=scanner->end) {
 	pjsip_msg_body *body = pj_pool_alloc(pool, sizeof(pjsip_msg_body));
-	pj_strdup(pool, &body->content_type.type, &ctype_hdr->media.type);
-	pj_strdup(pool, &body->content_type.subtype, &ctype_hdr->media.subtype);
-	pj_strdup(pool, &body->content_type.param, &ctype_hdr->media.param);
+	body->content_type.type = ctype_hdr->media.type;
+	body->content_type.subtype = ctype_hdr->media.subtype;
+	body->content_type.param = ctype_hdr->media.param;
+
 	body->data = scanner->curptr;
 	body->len = scanner->end - scanner->curptr;
@@ -1002,14 +1010,10 @@
 	is_name_addr = 1;
     } else {
-	pj_scan_state backtrack;
 	pj_str_t scheme;
-	int colon;
-
-	pj_scan_save_state( scanner, &backtrack);
-	pj_scan_get( scanner, &pjsip_TOKEN_SPEC, &scheme);
-	colon = pj_scan_get_char( scanner );
-	pj_scan_restore_state( scanner, &backtrack);
-
-	if (colon==':' && 
+	int next_ch;
+
+	next_ch = pj_scan_peek( scanner, &pjsip_DISPLAY_SPEC, &scheme);
+
+	if (next_ch==':' && 
             (parser_stricmp(scheme, pjsip_SIP_STR)==0 || 
              parser_stricmp(scheme, pjsip_SIPS_STR)==0)) 
@@ -1019,5 +1023,5 @@
 				   (opt & PJSIP_PARSE_URI_IN_FROM_TO_HDR)== 0);
 
-	} else if (colon==':' && parser_stricmp( scheme, pjsip_TEL_STR)==0) {
+	} else if (next_ch==':') {
 
 	    /* Not supported. */
@@ -1190,5 +1194,5 @@
 	 * will be parser later.
 	 */
-	next = pj_scan_peek_until(scanner, &pjsip_DISPLAY_SCAN_SPEC, &dummy);
+	next = pj_scan_peek(scanner, &pjsip_DISPLAY_SPEC, &dummy);
 	if (next == '<') {
 	    /* Ok, this is what we're looking for, a display name. */
@@ -1206,6 +1210,8 @@
 	pj_scan_get_char(scanner);
     name_addr->uri = int_parse_uri( scanner, pool, PJ_TRUE );
-    if (has_bracket)
-	pj_scan_get_char(scanner);
+    if (has_bracket) {
+	if (pj_scan_get_char(scanner) != '>')
+	    PJ_THROW( PJSIP_SYN_ERR_EXCEPTION);
+    }
 
     return name_addr;
@@ -1223,5 +1229,5 @@
 
     req_line->uri = int_parse_uri(scanner, pool, PJ_TRUE);
-    if (pj_scan_stricmp( scanner, PJSIP_VERSION, 7) != 0)
+    if (pj_scan_stricmp_alnum( scanner, PJSIP_VERSION, 7) != 0)
 	PJ_THROW( PJSIP_SYN_ERR_EXCEPTION);
     pj_scan_advance_n (scanner, 7, 1);
@@ -1235,5 +1241,5 @@
     pj_str_t token;
 
-    if (pj_scan_stricmp(scanner, PJSIP_VERSION, 7) != 0)
+    if (pj_scan_stricmp_alnum(scanner, PJSIP_VERSION, 7) != 0)
 	PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
     pj_scan_advance_n( scanner, 7, 1);
@@ -1241,6 +1247,5 @@
     pj_scan_get( scanner, &pjsip_DIGIT_SPEC, &token);
     status_line->code = pj_strtoul(&token);
-    pj_scan_get_until( scanner, &pjsip_NEWLINE_OR_EOF_SPEC, 
-                       &status_line->reason);
+    pj_scan_get( scanner, &pjsip_NOT_NEWLINE, &status_line->reason);
     pj_scan_get_newline( scanner );
 }
@@ -1268,11 +1273,11 @@
 				     pj_scanner *scanner)
 {
-    pj_scan_get_until( scanner, &pjsip_ARRAY_ELEMENTS, &hdr->values[0]);
+    pj_scan_get( scanner, &pjsip_NOT_COMMA_OR_NEWLINE, &hdr->values[0]);
     hdr->count++;
 
     while (*scanner->curptr == ',') {
 	pj_scan_get_char(scanner);
-	pj_scan_get_until( scanner, &pjsip_ARRAY_ELEMENTS, 
-                           &hdr->values[hdr->count]);
+	pj_scan_get( scanner, &pjsip_NOT_COMMA_OR_NEWLINE, 
+		     &hdr->values[hdr->count]);
 	hdr->count++;
     }
@@ -1284,5 +1289,9 @@
 				      pj_scanner *scanner )
 {
-    pj_scan_get_until( scanner, &pjsip_NEWLINE_OR_EOF_SPEC, &hdr->hvalue);
+    if (pj_cis_match(&pjsip_NOT_NEWLINE, *scanner->curptr))
+	pj_scan_get( scanner, &pjsip_NOT_NEWLINE, &hdr->hvalue);
+    else
+	hdr->hvalue.slen = 0;
+
     parse_hdr_end(scanner);
 }
@@ -1293,5 +1302,5 @@
 {
     pj_str_t tmp;
-    pj_scan_get_until( scanner, &pjsip_NEWLINE_OR_EOF_SPEC, &tmp);
+    pj_scan_get( scanner, &pjsip_DIGIT_SPEC, &tmp);
     hdr->ivalue = pj_strtoul(&tmp);
     parse_hdr_end(scanner);
@@ -1319,5 +1328,5 @@
 {
     pjsip_cid_hdr *hdr = pjsip_cid_hdr_create(ctx->pool);
-    pj_scan_get_until( ctx->scanner, &pjsip_NEWLINE_OR_EOF_SPEC, &hdr->id);
+    pj_scan_get( ctx->scanner, &pjsip_NOT_NEWLINE, &hdr->id);
     parse_hdr_end(ctx->scanner);
 
@@ -1701,5 +1710,5 @@
 	    pj_list_insert_before(first, hdr);
 
-	if (pj_scan_stricmp( scanner, PJSIP_VERSION "/", 8) != 0)
+	if (pj_scan_stricmp_alnum( scanner, PJSIP_VERSION "/", 8) != 0)
 	    PJ_THROW(PJSIP_SYN_ERR_EXCEPTION);
 
Index: /pjproject/trunk/pjsip/src/pjsip/sip_uri.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip/sip_uri.c	(revision 76)
+++ /pjproject/trunk/pjsip/src/pjsip/sip_uri.c	(revision 77)
@@ -90,9 +90,17 @@
 					 int sep)
 {
-    const pjsip_param *p = param_list->next;
-    char *startbuf = buf;
-    char *endbuf = buf + size;
-
-    while (p != param_list) {
+    const pjsip_param *p;
+    char *startbuf;
+    char *endbuf;
+    int printed;
+
+    p = param_list->next;
+    if (p == param_list)
+	return 0;
+
+    startbuf = buf;
+    endbuf = buf + size;
+
+    do {
 	*buf++ = (char)sep;
 	copy_advance_escape(buf, p->name, pjsip_PARAM_CHAR_SPEC);
@@ -102,5 +110,6 @@
 	}
 	p = p->next;
-    }
+    } while (p != param_list);
+
     return buf-startbuf;
 }
@@ -249,4 +258,7 @@
     //PJ_TODO(SHOULD_DISALLOW_URI_PORT_IN_FROM_TO_HEADER)
     if (url->port && context != PJSIP_URI_IN_FROMTO_HDR) {
+	if (endbuf - buf < 10)
+	    return -1;
+
 	*buf++ = ':';
 	printed = pj_utoa(url->port, buf);
@@ -271,6 +283,8 @@
     /* TTL param is not allowed in From, To, Route, and Record-Route header. */
     if (url->ttl_param >= 0 && context != PJSIP_URI_IN_FROMTO_HDR &&
-	context != PJSIP_URI_IN_ROUTING_HDR && (endbuf-buf) > 15) 
+	context != PJSIP_URI_IN_ROUTING_HDR) 
     {
+	if (endbuf - buf < 15)
+	    return -1;
 	pj_memcpy(buf, ";ttl=", 5);
 	printed = pj_utoa(url->ttl_param, buf+5);
@@ -289,4 +303,6 @@
     {
 	pj_str_t lr = { ";lr", 3 };
+	if (endbuf - buf < 3)
+	    return -1;
 	copy_advance_check(buf, lr);
     }
@@ -301,4 +317,6 @@
     param = url->header_param.next;
     while (param != &url->header_param) {
+	if (endbuf - buf < param->name.slen+2)
+	    return -1;
 	*buf++ = hparam_char;
 	copy_advance_escape(buf, param->name, pjsip_HDR_CHAR_SPEC);
Index: /pjproject/trunk/pjsip/src/test-pjsip/msg.c
===================================================================
--- /pjproject/trunk/pjsip/src/test-pjsip/msg.c	(revision 76)
+++ /pjproject/trunk/pjsip/src/test-pjsip/msg.c	(revision 77)
@@ -35,5 +35,5 @@
 #define FLAG_PRINT_ONLY		8
 
-static int flag = FLAG_PARSE_ONLY;
+static int flag = 0;
 
 struct test_msg
@@ -106,4 +106,5 @@
 {
     pjsip_msg *parsed_msg, *ref_msg;
+    static pjsip_msg *print_msg;
     pj_status_t status = PJ_SUCCESS;
     int len;
@@ -115,5 +116,4 @@
     char msgbuf1[PJSIP_MAX_PKT_LEN];
     char msgbuf2[PJSIP_MAX_PKT_LEN];
-
     enum { BUFLEN = 512 };
 
@@ -122,6 +122,10 @@
     if (flag & FLAG_PARSE_ONLY)
 	goto parse_msg;
-    if (flag & FLAG_PRINT_ONLY)
+
+    if (flag & FLAG_PRINT_ONLY) {
+	if (print_msg == NULL)
+	    print_msg = entry->creator(pool);
 	goto print_msg;
+    }
 
     /* Detect message. */
@@ -145,5 +149,5 @@
     pj_add_timestamp(&detect_time, &t2);
 
-    if (flag & FLAG_PARSE_ONLY)
+    if (flag & FLAG_DETECT_ONLY)
 	return PJ_SUCCESS;
     
@@ -303,5 +307,7 @@
     print_len = print_len + entry->len;
     pj_get_timestamp(&t1);
-    len = pjsip_msg_print(parsed_msg, msgbuf1, PJSIP_MAX_PKT_LEN);
+    if (flag && FLAG_PRINT_ONLY)
+	ref_msg = print_msg;
+    len = pjsip_msg_print(ref_msg, msgbuf1, PJSIP_MAX_PKT_LEN);
     if (len < 1) {
 	status = -150;
Index: /pjproject/trunk/pjsip/src/test-pjsip/test.c
===================================================================
--- /pjproject/trunk/pjsip/src/test-pjsip/test.c	(revision 76)
+++ /pjproject/trunk/pjsip/src/test-pjsip/test.c	(revision 77)
@@ -82,6 +82,6 @@
     PJ_LOG(3,("",""));
 
-    //DO_TEST(uri_test());
-    DO_TEST(msg_test());
+    DO_TEST(uri_test());
+    //DO_TEST(msg_test());
 
 on_return:
