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