1 /*
2 ** Splint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2003 University of Virginia,
4 **         Massachusetts Institute of Technology
5 **
6 ** This program is free software; you can redistribute it and/or modify it
7 ** under the terms of the GNU General Public License as published by the
8 ** Free Software Foundation; either version 2 of the License, or (at your
9 ** option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful, but
12 ** WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 ** General Public License for more details.
15 **
16 ** The GNU General Public License is available from http://www.gnu.org/ or
17 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18 ** MA 02111-1307, USA.
19 **
20 ** For information on splint: info@splint.org
21 ** To report a bug: splint-bug@splint.org
22 ** For more information: http://www.splint.org
23 */
24 /*
25 ** cstring.c
26 */
27 
28 /*
29  * Herbert 06/12/2000
30  * - use drive spec specials with OS2 like with WIN32
31  * - cstring_replaceAll () needed in cpplib.c
32  */
33 
34 # include "splintMacros.nf"
35 # include "basic.h"
36 # include "osd.h"
37 
38 /*@only@*/ /*@notnull@*/
cstring_newEmpty(void)39 cstring cstring_newEmpty (void)
40 {
41   return (cstring_create (0));
42 }
43 
cstring_firstChar(cstring s)44 char cstring_firstChar (cstring s)
45 {
46   llassert (cstring_isDefined (s));
47   llassert (cstring_length (s) > 0);
48 
49   return (s[0]);
50 }
51 
cstring_getChar(cstring s,size_t n)52 char cstring_getChar (cstring s, size_t n)
53 {
54   size_t length = cstring_length (s);
55 
56   llassert (cstring_isDefined (s));
57   llassert (n >= 1 && n <= length);
58 
59   return (s[n - 1]);
60 }
61 
cstring_suffix(cstring s,size_t n)62 cstring cstring_suffix (cstring s, size_t n)
63 {
64   llassert (cstring_isDefined (s));
65   llassert (n <= cstring_length (s));
66 
67   return (s + n);
68 }
69 
cstring_prefix(cstring s,size_t n)70 cstring cstring_prefix (cstring s, size_t n)
71    /*@requires maxRead(s) >= n /\ maxSet(s) >= n @*/
72    /*@ensures maxRead(result) == n /\ maxSet(result) == n @*/
73 {
74   cstring t;
75   char c;
76   llassert (cstring_isDefined (s));
77   llassert (n <= cstring_length (s));
78 
79   c = *(s + n);
80   /*@-mods@*/  /* The modifications cancel out. */
81   *(s + n) = '\0';
82   t = cstring_copy (s);
83   *(s + n) = c;
84   /*@=mods@*/
85 
86   return t;
87 }
88 
89 /* effects If s = [0-9]*, returns s as an int.
90 **         else returns -1.
91 */
92 
cstring_toPosInt(cstring s)93 int cstring_toPosInt (cstring s)
94 {
95   int val = 0;
96 
97   cstring_chars (s, c)
98     {
99       if (isdigit ((unsigned char) c))
100 	{
101 	  val = (val * 10) + (int)(c - '0');
102 	}
103       else
104 	{
105 	  return -1;
106 	}
107     } end_cstring_chars ;
108 
109   return val;
110 }
111 
cstring_afterChar(cstring s,char c)112 cstring cstring_afterChar (cstring s, char c)
113 {
114   llassert (cstring_isDefined (s));
115   return strchr (s, c);
116 }
117 
cstring_beforeChar(cstring s,char c)118 cstring cstring_beforeChar (cstring s, char c)
119 {
120   if (cstring_isDefined (s))
121     {
122       char *cp = strchr (s, c);
123 
124       if (cp != NULL)
125 	{
126 	  cstring ret;
127 
128 	  /*@-mods@*/
129 	  *cp = '\0';
130 	  ret = cstring_copy (s);
131 	  *cp = c;
132 	  /*@=mods@*/ /* modification is undone */
133 
134 	  return ret;
135 	}
136     }
137 
138   return cstring_undefined;
139 }
140 
cstring_setChar(cstring s,size_t n,char c)141 void cstring_setChar (cstring s, size_t n, char c) /*@requires maxRead(s) >= (n - 1) /\ maxSet(s) >= (n - 1) @*/
142 {
143   llassert (cstring_isDefined (s));
144   llassert (n > 0 && n <= cstring_length (s));
145 
146   s[n - 1] = c;
147 }
148 
cstring_lastChar(cstring s)149 char cstring_lastChar (cstring s)
150 {
151   size_t length;
152 
153   llassert (cstring_isDefined (s));
154 
155   length = cstring_length (s);
156   llassert (length > 0);
157 
158   return (s[length - 1]);
159 }
160 
cstring_copy(cstring s)161 /*@only@*/ cstring cstring_copy (cstring s) /*@ensures maxSet(result) == maxRead(s) /\ maxRead(result) == maxRead(s) @*/
162 {
163   if (cstring_isDefined (s))
164     {
165       return (mstring_copy (s));
166     }
167   else
168     {
169       return cstring_undefined;
170     }
171 }
172 
cstring_copyLength(char * s,size_t len)173 /*@only@*/ cstring cstring_copyLength (char *s, size_t len) /*@requires maxSet(s) >= (len - 1) @*/
174 {
175   char *res = mstring_create (len + 1);
176 
177   strncpy (res, s, len);
178   res[len] = '\0';
179   return res;
180 }
181 
cstring_containsChar(cstring c,char ch)182 bool cstring_containsChar (cstring c, char ch)
183 {
184   if (cstring_isDefined (c))
185     {
186       return (strchr (c, ch) != NULL);
187     }
188   else
189     {
190       return FALSE;
191     }
192 }
193 
194 /*
195 ** Replaces all occurances of old in s with new.
196 */
197 
cstring_replaceAll(cstring s,char old,char snew)198 void cstring_replaceAll (cstring s, char old, char snew)
199 {
200 
201   llassert (old != snew);
202 
203   if (cstring_isDefined (s))
204     {
205       char *sp = strchr (s, old);
206 
207       while (sp != NULL)
208 	{
209 	  *sp = snew;
210 	  sp = strchr (sp, old);
211 	}
212 
213           }
214 }
215 
cstring_replaceLit(cstring s,char * old,char * snew)216 void cstring_replaceLit (/*@unique@*/ cstring s, char *old, char *snew)
217    /*@requires maxRead(snew) >= 0 /\ maxRead(old) >= 0 /\ maxRead(old) >= maxRead(snew) @*/
218 {
219   llassert (strlen (old) >= strlen (snew));
220 
221   if (cstring_isDefined (s))
222     {
223       char *sp = strstr (s, old);
224 
225       while (sp != NULL)
226 	{
227 	  int lendiff = size_toInt (strlen (old) - strlen (snew));
228 	  char *tsnew = snew;
229 
230 	  llassert (lendiff >= 0);
231 
232 	  while (*tsnew != '\0')
233 	    {
234 	      llassert (*sp != '\0');
235 	      *sp++ = *tsnew++;
236 	    }
237 
238 	  if (lendiff > 0)
239 	    {
240 	      while (*(sp + lendiff) != '\0')
241 		{
242 		  *sp = *(sp + lendiff);
243 		  sp++;
244 		}
245 
246 	      *sp = '\0';
247 	    }
248 
249 	  sp = strstr (s, old);
250 	}
251     }
252 }
253 
254 /*
255 ** removes all chars in clist from s
256 */
257 
cstring_stripChars(cstring s,const char * clist)258 void cstring_stripChars (cstring s, const char *clist)
259 {
260   if (cstring_isDefined (s))
261     {
262       int i;
263       size_t size = cstring_length (s);
264 
265       for (i = 0; i < size_toInt (size); i++)
266 	{
267 
268 	  char c = s[i];
269 
270 	  if (strchr (clist, c) != NULL)
271 	    {
272 	      /* strip this char */
273 	      int j;
274 
275 	      size--;
276 
277 	      for (j = i; j < size_toInt (size); j++)
278 		{
279 		  s[j] = s[j+1];
280 		}
281 
282 	      s[size] = '\0';
283 	      i--;
284 	    }
285 	}
286     }
287 }
288 
cstring_contains(cstring c,cstring sub)289 bool cstring_contains (/*@unique@*/ cstring c, cstring sub)
290 {
291   if (cstring_isDefined (c))
292     {
293       llassert (cstring_isDefined (sub));
294 
295       return (strstr (c, sub) != NULL);
296     }
297   else
298     {
299       return FALSE;
300     }
301 }
302 
lookLike(char c)303 static char lookLike (char c) /*@*/
304 {
305   if (c == 'I' || c == 'l')
306     {
307       return '1';
308     }
309   else if (c == 'O' || c == 'o')
310     {
311       return '0';
312     }
313   else if (c == 'Z')
314     {
315       return '2';
316     }
317   else if (c == 'S')
318     {
319       return '5';
320     }
321   else
322     {
323       return c;
324     }
325 }
326 
cstring_genericEqual(cstring s,cstring t,size_t nchars,bool caseinsensitive,bool lookalike)327 cmpcode cstring_genericEqual (cstring s, cstring t,
328 			      size_t nchars,
329 			      bool caseinsensitive,
330 			      bool lookalike)
331   /*@requires maxRead(s) >= nchars /\ maxRead(t) >= nchars @*/
332 {
333   if (s == t) return CGE_SAME;
334   else if (cstring_isUndefined (s))
335     {
336       return cstring_isEmpty (t) ? CGE_SAME : CGE_DISTINCT;
337     }
338   else if (cstring_isUndefined (t))
339     {
340       return cstring_isEmpty (s) ? CGE_SAME : CGE_DISTINCT;
341     }
342   else
343     {
344       int i = 0;
345       bool diffcase = FALSE;
346       bool difflookalike = FALSE;
347 
348       while (*s != '\0')
349 	{
350 	  if (nchars > 0 && i >= size_toInt (nchars))
351 	    {
352 	      break;
353 	    }
354 
355 	  if (*t == *s)
356 	    {
357 	      ; /* no difference */
358 	    }
359 	  else if (caseinsensitive
360 		   && (toupper ((int) *t) == toupper ((int) *s)))
361 	    {
362 	      diffcase = TRUE;
363 	    }
364 	  else if (lookalike && (lookLike (*t) == lookLike (*s)))
365 	    {
366 	      difflookalike = TRUE;
367 	    }
368 	  else
369 	    {
370 	      return CGE_DISTINCT;
371 	    }
372 	  i++;
373 	  s++;
374 	  t++;
375 	}
376 
377 
378       if (*s == '\0' && *t != '\0')
379 	{
380 	  return CGE_DISTINCT;
381 	}
382 
383       if (diffcase)
384 	{
385 	  return CGE_CASE;
386 	}
387       else if (difflookalike)
388 	{
389 	  return CGE_LOOKALIKE;
390 	}
391       else
392 	{
393 	  return CGE_SAME;
394 	}
395     }
396 }
397 
398 
399 
cstring_equalFree(cstring c1,cstring c2)400 bool cstring_equalFree (/*@only@*/ cstring c1, /*@only@*/ cstring c2)
401 {
402   bool res = cstring_equal (c1, c2);
403   cstring_free (c1);
404   cstring_free (c2);
405   return res;
406 }
407 
cstring_equal(cstring c1,cstring c2)408 bool cstring_equal (cstring c1, cstring c2)
409 {
410   if (c1 == c2) return TRUE;
411   else if (cstring_isUndefined (c1)) return cstring_isEmpty (c2);
412   else if (cstring_isUndefined (c2)) return cstring_isEmpty (c1);
413   else return (strcmp (c1, c2) == 0);
414 }
415 
cstring_equalLen(cstring c1,cstring c2,size_t len)416 bool cstring_equalLen (cstring c1, cstring c2, size_t len)
417 {
418   if (c1 == c2) return TRUE;
419   else if (cstring_isUndefined (c1)) return cstring_isEmpty (c2);
420   else if (cstring_isUndefined (c2)) return cstring_isEmpty (c1);
421   else return (strncmp (c1, c2, len) == 0);
422 }
423 
cstring_equalCaseInsensitive(cstring c1,cstring c2)424 bool cstring_equalCaseInsensitive (cstring c1, cstring c2)
425 {
426   if (c1 == c2) return TRUE;
427   else if (cstring_isUndefined (c1)) return cstring_isEmpty (c2);
428   else if (cstring_isUndefined (c2)) return cstring_isEmpty (c1);
429   else return (cstring_genericEqual (c1, c2, 0, TRUE, FALSE) != CGE_DISTINCT);
430 }
431 
cstring_equalLenCaseInsensitive(cstring c1,cstring c2,size_t len)432 bool cstring_equalLenCaseInsensitive (cstring c1, cstring c2, size_t len)
433 {
434   if (c1 == c2) return TRUE;
435   else if (cstring_isUndefined (c1)) return cstring_isEmpty (c2);
436   else if (cstring_isUndefined (c2)) return cstring_isEmpty (c1);
437   else return (cstring_genericEqual (c1, c2, len, TRUE, FALSE) != CGE_DISTINCT);
438 }
439 
cstring_equalPrefix(cstring c1,cstring c2)440 bool cstring_equalPrefix (cstring c1, cstring c2)
441 {
442   llassert (c2 != NULL);
443 
444   if (cstring_isUndefined (c1))
445     {
446       return (strlen (c2) == 0);
447     }
448 
449   return (strncmp (c1, c2, strlen (c2)) == 0);
450 }
451 
cstring_equalPrefixLit(cstring c1,const char * c2)452 bool cstring_equalPrefixLit (cstring c1, const char *c2)
453 {
454   llassert (c2 != NULL);
455 
456   if (cstring_isUndefined (c1))
457     {
458       return (strlen (c2) == 0);
459     }
460 
461   return (strncmp (c1, c2, strlen (c2)) == 0);
462 }
463 
cstring_xcompare(cstring * c1,cstring * c2)464 int cstring_xcompare (cstring *c1, cstring *c2)
465 {
466   return (cstring_compare (*c1, *c2));
467 }
468 
cstring_compare(cstring c1,cstring c2)469 int cstring_compare (cstring c1, cstring c2)
470 {
471   int res;
472 
473   if (c1 == c2)
474     {
475       res = 0;
476     }
477   else if (cstring_isUndefined (c1))
478     {
479       if (cstring_isEmpty (c2))
480 	{
481 	  res = 0;
482 	}
483       else
484 	{
485 	  res = 1;
486 	}
487     }
488   else if (cstring_isUndefined (c2))
489     {
490       if (cstring_isEmpty (c1))
491 	{
492 	  res = 0;
493 	}
494       else
495 	{
496 	  res = -1;
497 	}
498     }
499   else
500     {
501       res = strcmp (c1, c2);
502     }
503 
504     return (res);
505 }
506 
cstring_markOwned(cstring s)507 void cstring_markOwned (/*@owned@*/ cstring s)
508 {
509   sfreeEventually (s);
510 }
511 
cstring_free(cstring s)512 void cstring_free (/*@only@*/ cstring s)
513 {
514   if (cstring_isDefined (s))
515     {
516       /*drl 2/3/2002*/
517       s[0] = '\0';
518 
519       sfree (s);
520     }
521 }
522 
cstring_fromChars(const char * cp)523 cstring cstring_fromChars (/*@exposed@*/ const char *cp)
524 {
525   return (cstring) cp;
526 }
527 
cstring_toCharsSafe(cstring s)528 /*@exposed@*/ char *cstring_toCharsSafe (cstring s)
529 {
530   static /*@only@*/ cstring emptystring = cstring_undefined;
531 
532   if (cstring_isDefined (s))
533     {
534       return (char *) s;
535     }
536   else
537     {
538       if (cstring_isUndefined (emptystring))
539 	{
540 	  emptystring = cstring_newEmpty ();
541 	}
542 
543       return emptystring;
544     }
545 }
546 
cstring_length(cstring s)547 size_t cstring_length (cstring s)
548 {
549   if (cstring_isDefined (s))
550     {
551       return strlen (s);
552     }
553 
554   return 0;
555 }
556 
557 cstring
cstring_capitalize(cstring s)558 cstring_capitalize (cstring s) /*@requires maxSet(s) >= 0 @*/
559 {
560   if (!cstring_isEmpty (s))
561     {
562       cstring ret = cstring_copy (s);
563 
564       cstring_setChar (ret, 1, (char) toupper ((int) cstring_firstChar (ret)));
565       return ret;
566     }
567 
568   return cstring_undefined;
569 }
570 
571 cstring
cstring_capitalizeFree(cstring s)572 cstring_capitalizeFree (cstring s) /*@requires maxSet(s) >= 0 /\ maxRead(s) >= 0 @*/
573 {
574   if (!cstring_isEmpty (s))
575     {
576       cstring_setChar (s, 1, (char) toupper ((int) cstring_firstChar (s)));
577       return s;
578     }
579 
580   return s;
581 }
582 
583 cstring
cstring_clip(cstring s,size_t len)584 cstring_clip (cstring s, size_t len)
585 {
586   if (cstring_isUndefined (s) || cstring_length (s) <= len)
587     {
588       ;
589     }
590   else
591     {
592       llassert (s != NULL);
593 
594       *(s + len) = '\0';
595     }
596 
597   return s;
598 }
599 
600 /*@only@*/ cstring
cstring_elide(cstring s,size_t len)601 cstring_elide (cstring s, size_t len)
602 {
603   if (cstring_isUndefined (s) || cstring_length (s) <= len)
604     {
605       return cstring_copy (s);
606     }
607   else
608     {
609       cstring sc = cstring_create (len);
610 
611       strncpy (sc, s, len);
612 
613       *(sc + len - 1) = '\0';
614       *(sc + len - 2) = '.';
615       *(sc + len - 3) = '.';
616       *(sc + len - 4) = '.';
617 
618       return sc;
619     }
620 }
621 
622 /*@only@*/ cstring
cstring_fill(cstring s,size_t n)623 cstring_fill (cstring s, size_t n) /*@requires n >= 0 @*/
624 {
625   cstring t = cstring_create (n + 1);
626   cstring ot = t;
627   size_t len = cstring_length (s);
628   size_t i;
629 
630   if (len > n)
631     {
632       for (i = 0; i < n; i++)
633 	{
634 
635 	  *t++ = *s++;
636 	}
637       *t = '\0';
638     }
639   else
640     {
641       for (i = 0; i < len; i++)
642 	{
643 
644 	  *t++ = *s++;
645 	}
646       for (i = 0; i < n - len; i++)
647 	{
648 
649 	  *t++ = ' ';
650 	}
651       *t = '\0';
652     }
653 
654   return ot;
655 }
656 
657 cstring
cstring_downcase(cstring s)658 cstring_downcase (cstring s)
659 {
660   if (cstring_isDefined (s))
661     {
662       cstring t = cstring_create (strlen (s) + 1);
663       cstring ot = t;
664       char c;
665 
666       while ((c = *s) != '\0')
667 	{
668 	  if (c >= 'A' && c <= 'Z')
669 	    {
670 	      c = c - 'A' + 'a';
671 	    }
672 	  *t++ = c;
673 	  s++;
674 	}
675       *t = '\0';
676 
677       return ot;
678     }
679   else
680     {
681       return cstring_undefined;
682     }
683 }
684 
685 /*@notnull@*/ cstring
cstring_appendChar(cstring s1,char c)686 cstring_appendChar (/*@only@*/ cstring s1, char c)
687 {
688   size_t l = cstring_length (s1);
689   char *s;
690 
691   s = (char *) dmalloc (sizeof (*s) * (l + 2));
692 
693   if (cstring_isDefined (s1))
694     {
695       strcpy (s, s1);
696       *(s + l) = c;
697       *(s + l + 1) = '\0';
698       sfree (s1);
699     }
700   else
701     {
702       *(s) = c;
703        *(s + 1) = '\0';
704     }
705 
706   return s;
707 }
708 
709 /*@only@*/ cstring
cstring_concatFree(cstring s,cstring t)710 cstring_concatFree (cstring s, cstring t)
711 {
712   cstring res = cstring_concat (s, t);
713   cstring_free (s);
714   cstring_free (t);
715   return res;
716 }
717 
718 /*@only@*/ cstring
cstring_concatFree1(cstring s,cstring t)719 cstring_concatFree1 (cstring s, cstring t)
720 {
721   cstring res = cstring_concat (s, t);
722   cstring_free (s);
723   return res;
724 }
725 
726 /*@only@*/ cstring
cstring_concatChars(cstring s,char * t)727 cstring_concatChars (cstring s, char *t)
728 {
729   cstring res = cstring_concat (s, cstring_fromChars (t));
730   cstring_free (s);
731   return res;
732 }
733 
734 /*@only@*/ cstring
cstring_concatLength(cstring s1,char * s2,size_t len)735 cstring_concatLength (cstring s1, char *s2, size_t len) /*@requires maxSet(s2) >= (len - 1) @*/
736 {
737   cstring tmp = cstring_copyLength (s2, len);
738   cstring res = cstring_concat (s1, tmp);
739   cstring_free (tmp);
740   cstring_free (s1);
741 
742   return res;
743 }
744 
745 /*@only@*/ cstring
cstring_concat(cstring s,cstring t)746 cstring_concat (cstring s, cstring t) /*@requires maxSet(s) >= 0 @*/
747 {
748   char *ret = mstring_create (cstring_length (s) + cstring_length (t));
749 
750   if (cstring_isDefined (s))
751     {
752       strcpy (ret, s);
753     }
754   if (cstring_isDefined (t))
755     {
756       strcat (ret, t);
757     }
758 
759   return ret;
760 }
761 
762 /*@notnull@*/ /*@only@*/ cstring
cstring_prependCharO(char c,cstring s1)763 cstring_prependCharO (char c, /*@only@*/ cstring s1)
764 {
765   cstring res = cstring_prependChar (c, s1);
766 
767   cstring_free (s1);
768   return (res);
769 }
770 
771 /*@notnull@*/ /*@only@*/ cstring
cstring_prependChar(char c,cstring s1)772 cstring_prependChar (char c, /*@temp@*/ cstring s1)
773 {
774   size_t l = cstring_length (s1);
775   char *s = (char *) dmalloc (sizeof (*s) * (l + 2));
776 
777   *(s) = c;
778 
779   if (cstring_isDefined (s1))
780     {
781       /*@-mayaliasunique@*/
782       strcpy (s + 1, s1);
783       /*@=mayaliasunique@*/
784     }
785 
786  *(s + l + 1) = '\0';
787   return s;
788 }
789 
790 bool
cstring_hasNonAlphaNumBar(cstring s)791 cstring_hasNonAlphaNumBar (cstring s)
792 {
793   int c;
794 
795   if (cstring_isUndefined (s)) return FALSE;
796 
797  while ((c = (int) *s) != (int) '\0')
798     {
799       if ((isalnum (c) == 0) && (c != (int) '_')
800 	  && (c != (int) '.') && (c != (int) CONNECTCHAR))
801 	{
802 	  return TRUE;
803 	}
804 
805       s++;
806     }
807   return FALSE;
808 }
809 
810 /*@only@*/ /*@notnull@*/ cstring
cstring_create(size_t n)811 cstring_create (size_t n)
812 {
813   char *s = dmalloc (sizeof (*s) * (n + 1));
814 
815   *s = '\0';
816   return s;
817 }
818 
819 /*@only@*/ /*@notnull@*/ cstring
cstring_copySegment(cstring s,size_t findex,size_t tindex)820 cstring_copySegment (cstring s, size_t findex, size_t tindex)
821 {
822   cstring res = cstring_create (tindex - findex + 1);
823 
824   llassert (cstring_isDefined (s));
825   llassert (cstring_length (s) > tindex);
826 
827   strncpy (res, (s + findex), size_fromInt (size_toInt (tindex - findex) + 1));
828   return res;
829 }
830 
cstring_toSymbol(cstring s)831 lsymbol cstring_toSymbol (cstring s)
832 {
833   lsymbol res = lsymbol_fromString (s);
834 
835   cstring_free (s);
836   return res;
837 }
838 
cstring_bsearch(cstring key,char ** table,int nentries)839 cstring cstring_bsearch (cstring key, char **table, int nentries)
840 {
841   if (cstring_isDefined (key))
842     {
843       int low = 0;
844       int high = nentries;
845       int mid = (high + low + 1) / 2;
846       int last = -1;
847       cstring res = cstring_undefined;
848 
849       while (low <= high && mid < nentries)
850 	{
851 	  int cmp;
852 
853 	  llassert (mid != last);
854 	  llassert (mid >= 0 && mid < nentries);
855 
856 	  cmp = cstring_compare (key, table[mid]);
857 
858 	  if (cmp == 0)
859 	    {
860 	      res = table[mid];
861 	      break;
862 	    }
863 	  else if (cmp < 0) /* key is before table[mid] */
864 	    {
865 	      high = mid - 1;
866 	    }
867 	  else /* key of after table[mid] */
868 	    {
869 	      low = mid + 1;
870 	    }
871 
872 	  last = mid;
873 	  mid = (high + low + 1) / 2;
874 	}
875 
876       if (mid != 0 && mid < nentries - 1)
877 	{
878 	  llassert (cstring_compare (key, table[mid - 1]) > 0);
879 	 llassert (cstring_compare (key, table[mid + 1]) < 0);
880 	}
881 
882       return res;
883     }
884 
885   return cstring_undefined;
886 }
887 
cstring_advanceWhiteSpace(cstring s)888 extern /*@observer@*/ cstring cstring_advanceWhiteSpace (cstring s)
889 {
890   if (cstring_isDefined (s)) {
891     char *t = s;
892 
893    while (*t != '\0' && isspace ((int) *t)) {
894       t++;
895     }
896 
897     return t;
898   }
899 
900   return cstring_undefined;
901 }
902 
903 /* changes strings like "sdf" "sdfsd" into "sdfsdfsd"*/
904 /* This function understands that "sdf\"  \"sdfsdf" is okay*/
doMergeString(cstring s)905 static mstring doMergeString (cstring s)
906 {
907   char *ptr;
908   mstring ret;
909   char * retPtr;
910   bool escape;
911 
912   llassert(cstring_isDefined (s));
913 
914   ret = mstring_create (cstring_length(s) );
915 
916   ptr = s;
917 
918   retPtr = ret;
919   /*
920   llassert(*ptr == '\"');
921 
922   *retPtr = *ptr;
923 
924   retPtr++;
925   ptr++;
926   */
927 
928   while (*ptr != '\0')
929     {
930       escape = FALSE;
931 
932       if (*ptr == '\\')
933 	{
934 	  *retPtr = *ptr;
935 
936 	  if (!escape)
937 	    escape = TRUE;
938 	  else
939 	    /* case of escaped \ ('\\')  */
940 	    escape = FALSE;
941 	}
942       else if ( (*ptr == '\"') && (!escape) )
943 	{
944 	  while ( (ptr[1] != '\"') && (ptr[1] != '\0') )
945 	    {
946 	      ptr++;
947 	    }
948 	  if (ptr[1] == '\0')
949 	    {
950 	      llassert(*ptr == '\"');
951 	      *retPtr =  '\"';
952 	      retPtr++;
953 	      *retPtr = '\0';
954 	      BADEXIT;
955 
956 	      /*@notreached@*/ return ret;
957 	    }
958 	  else
959 	    {
960 	      ptr++;
961 	    }
962 	}
963       else
964 	{
965 	  *retPtr = *ptr;
966 	}
967 
968       retPtr++;
969       ptr++;
970 
971     }/* end while */
972   *retPtr = '\0';
973   return ret;
974 }
975 
doExpandEscapes(cstring s,size_t * len)976 static mstring doExpandEscapes (cstring s, /*@out@*/ size_t *len)
977 {
978   char *ptr;
979   mstring ret;
980   char * retPtr;
981 
982   llassert(cstring_isDefined (s));
983 
984   ret = mstring_create (cstring_length(s));
985 
986   ptr = s;
987 
988   retPtr = ret;
989   while (*ptr != '\0')
990     {
991       if (*ptr != '\\')
992 	{
993 	  *retPtr = *ptr;
994 	  retPtr++;
995 	  ptr++;
996 	  continue;
997 	}
998 
999       if (*ptr == '\\')
1000 	{
1001 	  ptr++;
1002 	  if (*ptr == '\0')
1003 	    {
1004 	      /*not a legal escape sequence but try to handle it in a sesible way*/
1005 	      *retPtr = '\\';
1006 	      retPtr++;
1007 	    }
1008 
1009 	  /* Handle Octal escapes  */
1010 	  else if (*ptr >= '0' && *ptr <= '9' )
1011 	    {
1012 	      int total;
1013 	      total = (int)(*ptr - '0');
1014 	      ptr++;
1015 	      /*octal can only be 3 characters long */
1016 	      if (*ptr != '\0' &&  (*ptr >= '0' && *ptr <= '9' ) )
1017 		{
1018 		  total *= 8;
1019 		  ptr++;
1020 		  if (*ptr != '\0' &&  (*ptr >= '0' && *ptr <= '9' ) )
1021 		    {
1022 		      total *= 8;
1023 		      total += (int) (*ptr - '0');
1024 		      ptr++;
1025 		    }
1026 		}
1027 
1028 	      *retPtr =  (char) total;
1029 	      retPtr++;
1030 	    }
1031 
1032 	  else if (*ptr == 'x')
1033 	    {
1034 	      int total;
1035 	      total = 0;
1036 	      ptr++;
1037 	      if (!(*ptr != '\0' &&
1038 		    ( (*ptr >= '0' && *ptr <= '9' ) ||
1039 		      (toupper(*ptr) >= (int)('A') && toupper(*ptr) <= (int)('F') ) )
1040 		      ))
1041 		{
1042 		  total = (int)'x';
1043 		}
1044 	      else
1045 		{
1046 		  while (*ptr != '\0' &&
1047 		    ( (*ptr >= '0' && *ptr <= '9' ) ||
1048 		      (toupper(*ptr) >= ((int)('A')) && toupper(*ptr) <= ((int)'F') ) )
1049 			 )
1050 		    {
1051 		      total *= 16;
1052 		      if (*ptr >= '0' && *ptr <= '9' )
1053 			total += (int)(*ptr - '0');
1054 		      else
1055 			total += ( (toupper(*ptr) - 'A') + 10);
1056 		      ptr++;
1057 		    }
1058 		}
1059 	      *retPtr =  (char) total;
1060 	      retPtr++;
1061 	    }
1062 	  else
1063 	    {
1064 	      switch ( *ptr )
1065 		{
1066 		case 'a':
1067 		  *retPtr = '\a';
1068 		  retPtr++;
1069 		  /*@switchbreak@*/ break;
1070 
1071 		case 'b':
1072 		  *retPtr = '\b';
1073 		  retPtr++;
1074 		  /*@switchbreak@*/ break;
1075 
1076 		case 'f':
1077 		  *retPtr = '\f';
1078 		  retPtr++;
1079 		  /*@switchbreak@*/ break;
1080 
1081 		case 'n':
1082 		  *retPtr = '\n';
1083 		  retPtr++;
1084 		  /*@switchbreak@*/ break;
1085 
1086 		case 'r':
1087 		  *retPtr = '\r';
1088 		  retPtr++;
1089 		  /*@switchbreak@*/ break;
1090 
1091 		case 't':
1092 		  *retPtr = '\t';
1093 		  retPtr++;
1094 		  /*@switchbreak@*/ break;
1095 		  /* ' " ? \ */
1096 		  /* we assume invalid sequences are handled somewhere else
1097 		     so we handle an invalid sequence of the form \char by replacing
1098 		     it with char (this is what gcc does) the C standard says a diagnostic is
1099 		     required..*/
1100 		default:
1101 		  *retPtr = *ptr;
1102 		  retPtr++;
1103 		}
1104 	      ptr++;
1105 	    }
1106 
1107 	}/*end outer if*/
1108 
1109     }/*end while */
1110 
1111   /* add the null character */
1112   *retPtr = '\0';
1113 
1114   llassert(  (retPtr-ret) >= 0 );
1115   *len = (size_t)(retPtr - ret);
1116   return ret;
1117 }
1118 
1119 
1120 /*this function is like sctring_expandEscapses */
cstring_expandEscapes(cstring s)1121 mstring cstring_expandEscapes (cstring s)
1122 {
1123   size_t len;
1124 
1125   mstring ret;
1126   ret = doExpandEscapes (s, &len);
1127   return ret;
1128 }
1129 
cstring_lengthExpandEscapes(cstring s)1130 size_t cstring_lengthExpandEscapes (cstring s)
1131 {
1132   size_t len;
1133   mstring tmpStr, tmpStr2;
1134 
1135   tmpStr = doMergeString (s);
1136   tmpStr2 = doExpandEscapes (tmpStr, &len);
1137 
1138   cstring_free(tmpStr);
1139   cstring_free(tmpStr2);
1140 
1141   return len;
1142 }
1143 
cstring_replaceChar(cstring c,char oldChar,char newChar)1144 cstring cstring_replaceChar(/*@returned@*/ cstring c, char oldChar, char newChar)
1145 {
1146   char *ptr;
1147   llassert(oldChar != '\0');
1148   if (cstring_isUndefined(c) )
1149     {
1150       llcontbug(cstring_makeLiteral("cstring_replaceChar called with undefined string"));
1151       return c;
1152     }
1153 
1154   ptr = c;
1155   while (*ptr != '\0')
1156     {
1157       if (*ptr == oldChar)
1158 	*ptr = newChar;
1159       ptr++;
1160     }
1161 
1162   return c;
1163 }
1164 
1165 
1166 
1167 
1168 
1169 
1170 
1171 
1172