+
+/*@i3534 @*/
+/*@ignore@*/
+
+/* changes strings like "sdf" "sdfsd" into "sdfsdfsd"*/
+/* This function understands that "sdf\" \"sdfsdf" is okay*/
+static mstring doMergeString (cstring s)
+{
+ char *ptr;
+ mstring ret;
+ char * retPtr;
+ bool escape;
+
+ llassert(cstring_isDefined (s));
+
+ ret = mstring_create (cstring_length(s) );
+
+ ptr = s;
+
+ retPtr = ret;
+ /*
+ llassert(*ptr == '\"');
+
+ *retPtr = *ptr;
+
+ retPtr++;
+ ptr++;
+ */
+
+ while (*ptr != '\0')
+ {
+ escape = FALSE;
+
+ if (*ptr == '\\')
+ {
+ *retPtr = *ptr;
+
+ if (!escape)
+ escape = TRUE;
+ else
+ /* case of escaped \ ('\\') */
+ escape = FALSE;
+ }
+ else if ( (*ptr == '\"') && (!escape) )
+ {
+ while ( (ptr[1] != '\"') && (ptr[1] != '\0') )
+ {
+ ptr++;
+ }
+ if (ptr[1] == '\0')
+ {
+ llassert(*ptr == '\"');
+ *retPtr = '\"';
+ retPtr++;
+ *retPtr = '\0';
+ BADEXIT;
+ return ret;
+ }
+ else
+ {
+ ptr++;
+ }
+ }
+ else
+ {
+ *retPtr = *ptr;
+ }
+
+ retPtr++;
+ ptr++;
+
+ }/* end while */
+ retPtr = '\0';
+ return ret;
+}
+
+static mstring doExpandEscapes (cstring s, /*@out@*/ int * len)
+{
+ char *ptr;
+ mstring ret;
+ char * retPtr;
+
+
+ llassert(cstring_isDefined (s));
+
+ ret = mstring_create (cstring_length(s));
+
+ ptr = s;
+
+ retPtr = ret;
+ while (*ptr != '\0')
+ {
+ if (*ptr != '\\')
+ {
+ *retPtr = *ptr;
+ retPtr++;
+ ptr++;
+ continue;
+ }
+
+ if (*ptr == '\\')
+ {
+ ptr++;
+ if (*ptr == '\0')
+ {
+ /*not a legal escape sequence but try to handle it in a sesible way*/
+ *retPtr = '\\';
+ retPtr++;
+ }
+
+ /* Handle Octal escapes */
+ else if (*ptr >= '0' && *ptr <= '9' )
+ {
+ int total;
+ total = (int)(*ptr - '0');
+ ptr++;
+ /*octal can only be 3 characters long */
+ if (*ptr != '\0' && (*ptr >= '0' && *ptr <= '9' ) )
+ {
+ total *= 8;
+ ptr++;
+ if (*ptr != '\0' && (*ptr >= '0' && *ptr <= '9' ) )
+ {
+ total *= 8;
+ total += (int) (*ptr - '0');
+ ptr++;
+ }
+ }
+
+ *retPtr = (char) total;
+ retPtr++;
+ }
+
+ else if (*ptr == 'x')
+ {
+ int total;
+ total = 0;
+ ptr++;
+ if (!(*ptr != '\0' &&
+ ( (*ptr >= '0' && *ptr <= '9' ) ||
+ (toupper(*ptr) >= (int)('A') && toupper(*ptr) <= (int)('F') ) )
+ ))
+ {
+ total = (int)'x';
+ }
+ else
+ {
+ while (*ptr != '\0' &&
+ ( (*ptr >= '0' && *ptr <= '9' ) ||
+ (toupper(*ptr) >= ((int)('A')) && toupper(*ptr) <= ((int)'F') ) )
+ )
+ {
+ total *= 16;
+ if (*ptr >= '0' && *ptr <= '9' )
+ total += (int)(*ptr - '0');
+ else
+ total += ( (toupper(*ptr) - 'A') + 10);
+ ptr++;
+ }
+ }
+ *retPtr = (char) total;
+ retPtr++;
+ }
+ else
+ {
+ switch ( *ptr )
+ {
+ case 'a':
+ *retPtr = '\a';
+ retPtr++;
+ /*@switchbreak@*/ break;
+
+ case 'b':
+ *retPtr = '\b';
+ retPtr++;
+ /*@switchbreak@*/ break;
+
+ case 'f':
+ *retPtr = '\f';
+ retPtr++;
+ /*@switchbreak@*/ break;
+
+ case 'n':
+ *retPtr = '\n';
+ retPtr++;
+ /*@switchbreak@*/ break;
+
+ case 'r':
+ *retPtr = '\r';
+ retPtr++;
+ /*@switchbreak@*/ break;
+
+ case 't':
+ *retPtr = '\t';
+ retPtr++;
+ /*@switchbreak@*/ break;
+ /* ' " ? \ */
+ /* we assume invalid sequences are handled somewhere else
+ so we handle an invalid sequence of the form \char by replacing
+ it with char (this is what gcc does) the C standard says a diagnostic is
+ required..*/
+ default:
+ *retPtr = *ptr;
+ retPtr++;
+ }
+ ptr++;
+ }
+
+ }/*end outer if*/
+
+ }/*end while */
+
+ /* add the null character */
+ *retPtr = '\0';
+
+ *len = retPtr - ret;
+ return ret;
+}
+
+
+/*this function is like sctring_expandEscapses */
+mstring cstring_expandEscapes (cstring s)
+{
+ int len;
+
+ mstring ret;
+
+ ret = doExpandEscapes (s, &len);
+ return ret;
+}
+
+int cstring_lengthExpandEscapes (cstring s)
+{
+ int len;
+
+ mstring tmpStr, tmpStr2;
+
+ tmpStr = doMergeString (s);
+ tmpStr2 = doExpandEscapes (tmpStr, &len);
+
+
+ cstring_free(tmpStr);
+ cstring_free(tmpStr2);
+
+ return len;
+}
+
+
+
+cstring cstring_replaceChar(/*@returned@*/ cstring c, char oldChar, char newChar)
+{
+ char *ptr;
+ llassert(oldChar != '\0');
+ if (cstring_isUndefined(c) )
+ {
+ llcontbug(cstring_makeLiteral("cstring_replaceChar called with undefined string"));
+ return c;
+ }
+
+ ptr = c;
+ while (*ptr != '\0')
+ {
+ if (*ptr == oldChar)
+ *ptr = newChar;
+ ptr++;
+ }
+
+ return c;
+}
+
+/*@end@*/
+
+
+
+
+