]> andersk Git - splint.git/blob - src/cstring.c
Fixed inclusion problems with osd.h.
[splint.git] / src / cstring.c
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@*/ 
39 cstring cstring_newEmpty (void)
40 {
41   return (cstring_create (0));
42 }
43
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
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
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
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
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
112 cstring cstring_afterChar (cstring s, char c) 
113 {
114   llassert (cstring_isDefined (s));
115   return strchr (s, c);
116 }
117
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 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
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
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
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
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
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
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 
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 
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 
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 
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 
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 
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 
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   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
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 
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
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
831 lsymbol cstring_toSymbol (cstring s)
832 {
833   lsymbol res = lsymbol_fromString (s);
834
835   cstring_free (s);
836   return res;
837 }
838
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
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*/
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
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 */
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
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
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
This page took 0.131436 seconds and 5 git commands to generate.