]> andersk Git - splint.git/blob - src/cstring.c
Renamed lclintMacros.nf splintMacros.nf
[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: splint@cs.virginia.edu
21 ** To report a bug: splint-bug@cs.virginia.edu
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) 
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) 
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) 
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)
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 {
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           while (*tsnew != '\0')
230             {
231               *sp++ = *tsnew++;
232             }
233
234           if (lendiff > 0)
235             {
236               while (*(sp + lendiff) != '\0')
237                 {
238                   *sp = *(sp + lendiff);
239                   sp++;
240                 }
241               
242               *sp = '\0';
243             }
244
245           sp = strstr (s, old);
246         }
247     }
248 }
249
250 /*
251 ** removes all chars in clist from s
252 */
253
254 void cstring_stripChars (cstring s, const char *clist)
255 {
256   if (cstring_isDefined (s))
257     {
258       int i;
259       int size = cstring_length (s);
260
261       for (i = 0; i < size; i++)
262         {
263           char c = s[i];
264           
265           if (strchr (clist, c) != NULL)
266             {
267               /* strip this char */
268               int j;
269               
270               size--;
271
272               for (j = i; j < size; j++)
273                 {
274                   s[j] = s[j+1];
275                 }
276
277               s[size] = '\0'; 
278               i--;
279             }
280         }
281     }
282 }
283
284 bool cstring_contains (/*@unique@*/ cstring c, cstring sub)
285 {
286   if (cstring_isDefined (c))
287     {
288       llassert (cstring_isDefined (sub));
289       
290       return (strstr (c, sub) != NULL);
291     }
292   else
293     {
294       return FALSE;
295     }
296 }
297
298 static char lookLike (char c) /*@*/
299 {
300   if (c == 'I' || c == 'l')
301     {
302       return '1';
303     }
304   else if (c == 'O' || c == 'o')
305     {
306       return '0';
307     }
308   else if (c == 'Z')
309     {
310       return '2';
311     }
312   else if (c == 'S')
313     {
314       return '5';
315     }
316   else
317     {
318       return c;
319     }
320 }
321
322 cmpcode cstring_genericEqual (cstring s, cstring t,
323                               int nchars,
324                               bool caseinsensitive,
325                               bool lookalike)
326 {
327   if (s == t) return CGE_SAME;
328   else if (cstring_isUndefined (s))
329     {
330       return cstring_isEmpty (t) ? CGE_SAME : CGE_DISTINCT;
331     }
332   else if (cstring_isUndefined (t))
333     {
334       return cstring_isEmpty (s) ? CGE_SAME : CGE_DISTINCT;
335     }
336   else
337     {
338       int i = 0;
339       bool diffcase = FALSE;
340       bool difflookalike = FALSE;
341
342       while (*s != '\0')
343         {
344           if (nchars > 0 && i >= nchars)
345             {
346               break;
347             }
348
349           if (*t == *s)
350             {
351               ; /* no difference */
352             }
353           else if (caseinsensitive 
354                    && (toupper ((int) *t) == toupper ((int) *s)))
355             {
356               diffcase = TRUE;
357             }
358           else if (lookalike && (lookLike (*t) == lookLike (*s)))
359             {
360               difflookalike = TRUE;
361             }
362           else 
363             {
364               return CGE_DISTINCT;
365             }
366           i++;
367           s++;
368           t++;
369         }
370
371       if (*s == '\0' && *t != '\0')
372         {
373           return CGE_DISTINCT;
374         }
375
376       if (diffcase)
377         {
378           return CGE_CASE;
379         }
380       else if (difflookalike)
381         {
382           return CGE_LOOKALIKE;
383         }
384       else
385         {
386           return CGE_SAME;
387         }
388     }
389 }
390
391
392
393 bool cstring_equalFree (/*@only@*/ cstring c1, /*@only@*/ cstring c2)
394 {
395   bool res = cstring_equal (c1, c2);
396   cstring_free (c1);
397   cstring_free (c2);
398   return res;
399 }
400
401 bool cstring_equal (cstring c1, cstring c2)
402 {
403   if (c1 == c2) return TRUE;
404   else if (cstring_isUndefined (c1)) return cstring_isEmpty (c2);
405   else if (cstring_isUndefined (c2)) return cstring_isEmpty (c1);
406   else return (strcmp (c1, c2) == 0);
407 }
408
409 bool cstring_equalLen (cstring c1, cstring c2, int len)
410 {
411   if (c1 == c2) return TRUE;
412   else if (cstring_isUndefined (c1)) return cstring_isEmpty (c2);
413   else if (cstring_isUndefined (c2)) return cstring_isEmpty (c1);
414   else return (strncmp (c1, c2, size_fromInt (len)) == 0);
415 }
416
417 bool cstring_equalCaseInsensitive (cstring c1, cstring c2)
418 {
419   if (c1 == c2) return TRUE;
420   else if (cstring_isUndefined (c1)) return cstring_isEmpty (c2);
421   else if (cstring_isUndefined (c2)) return cstring_isEmpty (c1);
422   else return (cstring_genericEqual (c1, c2, 0, TRUE, FALSE) != CGE_DISTINCT);
423 }
424
425 bool cstring_equalLenCaseInsensitive (cstring c1, cstring c2, int len)
426 {
427   llassert (len >= 0);
428
429   if (c1 == c2) return TRUE;
430   else if (cstring_isUndefined (c1)) return cstring_isEmpty (c2);
431   else if (cstring_isUndefined (c2)) return cstring_isEmpty (c1);
432   else return (cstring_genericEqual (c1, c2, len, TRUE, FALSE) != CGE_DISTINCT);
433 }
434
435 bool cstring_equalPrefix (cstring c1, cstring c2)
436 {
437   llassert (c2 != NULL);
438
439   if (cstring_isUndefined (c1)) 
440     {
441       return (strlen (c2) == 0);
442     }
443
444   return (strncmp (c1, c2, strlen (c2)) == 0);
445 }
446
447 bool cstring_equalPrefixLit (cstring c1, const char *c2)
448 {
449   llassert (c2 != NULL);
450
451   if (cstring_isUndefined (c1)) 
452     {
453       return (strlen (c2) == 0);
454     }
455
456   return (strncmp (c1, c2, strlen (c2)) == 0);
457 }
458
459 int cstring_xcompare (cstring *c1, cstring *c2)
460 {
461   return (cstring_compare (*c1, *c2));
462 }
463
464 int cstring_compare (cstring c1, cstring c2)
465 {
466   int res;
467
468   if (c1 == c2)
469     {
470       res = 0;
471     }
472   else if (cstring_isUndefined (c1))
473     {
474       if (cstring_isEmpty (c2))
475         {
476           res = 0;
477         }
478       else
479         {
480           res = 1;
481         }
482     }
483   else if (cstring_isUndefined (c2))
484     {
485       if (cstring_isEmpty (c1))
486         {
487           res = 0;
488         }
489       else
490         {
491           res = -1;
492         }
493     }
494   else
495     {
496       res = strcmp (c1, c2);
497     }
498
499     return (res);
500 }
501
502 void cstring_markOwned (/*@owned@*/ cstring s)
503 {
504   sfreeEventually (s);
505 }
506
507 void cstring_free (/*@only@*/ cstring s)
508 {
509   if (cstring_isDefined (s)) 
510     {
511       sfree (s);
512     }
513 }
514
515 cstring cstring_fromChars (/*@exposed@*/ const char *cp)
516 {
517   return (cstring) cp;
518 }
519
520 /*@exposed@*/ char *cstring_toCharsSafe (cstring s)
521 {
522   static /*@only@*/ cstring emptystring = cstring_undefined;
523
524   if (cstring_isDefined (s))
525     {
526       return (char *) s;
527     }
528   else
529     {
530       if (cstring_isUndefined (emptystring))
531         {
532           emptystring = cstring_newEmpty ();
533         }
534
535       return emptystring;
536     }
537 }
538
539 int cstring_length (cstring s)
540 {
541   if (cstring_isDefined (s))
542     {
543       return size_toInt (strlen (s));
544     }
545   return 0;
546 }
547
548 cstring
549 cstring_capitalize (cstring s)
550 {
551   if (!cstring_isEmpty (s))
552     {
553       cstring ret = cstring_copy (s);
554
555       cstring_setChar (ret, 1, (char) toupper ((int) cstring_firstChar (ret)));
556       return ret;
557     }
558   
559   return cstring_undefined;
560 }
561
562 cstring
563 cstring_capitalizeFree (cstring s)
564 {
565   if (!cstring_isEmpty (s))
566     {
567       cstring_setChar (s, 1, (char) toupper ((int) cstring_firstChar (s)));
568       return s;
569     }
570   
571   return s;
572 }
573
574 cstring
575 cstring_clip (cstring s, int len)
576 {
577   if (cstring_isUndefined (s) || cstring_length (s) <= len)
578     {
579       ;
580     }
581   else
582     {
583       llassert (s != NULL);
584       *(s + len) = '\0';
585     }
586
587   return s;
588 }
589
590 /*@only@*/ cstring
591 cstring_elide (cstring s, int len)
592 {
593   if (cstring_isUndefined (s) || cstring_length (s) <= len)
594     {
595       return cstring_copy (s);
596     }
597   else
598     {
599       cstring sc = cstring_create (len);
600      
601       strncpy (sc, s, size_fromInt (len));
602       *(sc + len - 1) = '\0';
603       *(sc + len - 2) = '.';      
604       *(sc + len - 3) = '.';      
605       *(sc + len - 4) = '.';      
606       return sc;
607     }
608 }
609
610 /*@only@*/ cstring
611 cstring_fill (cstring s, int n)
612 {
613   cstring t = cstring_create (n + 1);
614   cstring ot = t;
615   int len = cstring_length (s);
616   int i;
617   
618   if (len > n)
619     {
620       for (i = 0; i < n; i++)
621         {
622           *t++ = *s++;
623         }
624       *t = '\0';
625     }
626   else
627     {
628       for (i = 0; i < len; i++)
629         {
630           *t++ = *s++;
631         }
632       for (i = 0; i < n - len; i++)
633         {
634           *t++ = ' ';
635         }
636       *t = '\0';
637     }
638
639   return ot;
640 }
641
642 cstring
643 cstring_downcase (cstring s)
644 {
645   if (cstring_isDefined (s))
646     {
647       cstring t = cstring_create (strlen (s) + 1);
648       cstring ot = t;
649       char c;
650       
651       while ((c = *s) != '\0')
652         {
653           if (c >= 'A' && c <= 'Z')
654             {
655               c = c - 'A' + 'a';
656             }
657           *t++ = c;
658           s++;
659         }
660       *t = '\0';
661       
662       return ot;
663     }
664   else
665     {
666       return cstring_undefined;
667     }
668 }
669
670 /*@notnull@*/ cstring 
671 cstring_appendChar (/*@only@*/ cstring s1, char c)
672 {
673   int l = cstring_length (s1);
674   char *s;
675
676   s = (char *) dmalloc (sizeof (*s) * (l + 2));
677
678   if (cstring_isDefined (s1))
679     {  
680       strcpy (s, s1);
681       *(s + l) = c;
682       *(s + l + 1) = '\0';
683       sfree (s1); 
684     }
685   else
686     {
687       *(s) = c;
688       *(s + 1) = '\0';
689     } 
690
691   return s;
692 }
693
694 /*@only@*/ cstring 
695 cstring_concatFree (cstring s, cstring t)
696 {
697   cstring res = cstring_concat (s, t);
698   cstring_free (s);
699   cstring_free (t);
700   return res;
701 }
702
703 /*@only@*/ cstring 
704 cstring_concatFree1 (cstring s, cstring t)
705 {
706   cstring res = cstring_concat (s, t);
707   cstring_free (s);
708   return res;
709 }
710
711 # ifndef NOLCL
712 /*@only@*/ cstring 
713 cstring_concatChars (cstring s, char *t)
714 {
715   cstring res = cstring_concat (s, cstring_fromChars (t));
716   cstring_free (s);
717   return res;
718 }
719 # endif
720
721 /*@only@*/ cstring 
722 cstring_concatLength (cstring s1, char *s2, int len)
723 {
724   cstring tmp = cstring_copyLength (s2, len);
725   cstring res = cstring_concat (s1, tmp);
726   cstring_free (tmp);
727   cstring_free (s1);
728
729   return res;
730 }
731
732 /*@only@*/ cstring 
733 cstring_concat (cstring s, cstring t)
734 {
735   char *ret = mstring_create (cstring_length (s) + cstring_length (t));
736
737   if (cstring_isDefined (s))
738     {
739       strcpy (ret, s);
740     }
741   if (cstring_isDefined (t))
742     {
743       strcat (ret, t);
744     }
745
746   return ret;
747 }
748
749 /*@notnull@*/ /*@only@*/ cstring 
750 cstring_prependCharO (char c, /*@only@*/ cstring s1)
751 {
752   cstring res = cstring_prependChar (c, s1);
753
754   cstring_free (s1);
755   return (res);
756 }
757
758 /*@notnull@*/ /*@only@*/ cstring 
759 cstring_prependChar (char c, /*@temp@*/ cstring s1)
760 {
761   int l = cstring_length (s1);
762   char *s = (char *) dmalloc (sizeof (*s) * (l + 2));
763   
764   *(s) = c;
765
766   if (cstring_isDefined (s1)) 
767     {
768       /*@-mayaliasunique@*/ 
769       strcpy (s + 1, s1);
770       /*@=mayaliasunique@*/ 
771     }
772
773   *(s + l + 1) = '\0';
774   return s;
775 }
776
777 # ifndef NOLCL
778 bool
779 cstring_hasNonAlphaNumBar (cstring s)
780 {
781   int c;
782
783   if (cstring_isUndefined (s)) return FALSE;
784
785   while ((c = (int) *s) != (int) '\0')
786     {
787       if ((isalnum (c) == 0) && (c != (int) '_')
788           && (c != (int) '.') && (c != (int) CONNECTCHAR))
789         {
790           return TRUE;
791         }
792
793       s++;
794     }
795   return FALSE;
796 }
797 # endif
798
799 /*@only@*/ /*@notnull@*/ cstring 
800 cstring_create (int n)
801 {
802   char *s = dmalloc (sizeof (*s) * (n + 1));
803
804   *s = '\0';
805   return s;
806 }
807
808 /*@only@*/ /*@notnull@*/ cstring
809 cstring_copySegment (cstring s, int findex, int tindex)
810 {
811   cstring res = cstring_create (tindex - findex + 1);
812
813   llassert (cstring_isDefined (s));
814   llassert (cstring_length (s) > tindex);
815
816   strncpy (res, (s + findex), size_fromInt ((tindex - findex + 1)));
817   return res;
818 }
819
820 # ifndef NOLCL
821 lsymbol cstring_toSymbol (cstring s)
822 {
823   lsymbol res = lsymbol_fromString (s);
824
825   cstring_free (s);
826   return res;
827 }
828 # endif
829
830 cstring cstring_bsearch (cstring key, char **table, int nentries)
831 {
832   if (cstring_isDefined (key))
833     {
834       int low = 0;
835       int high = nentries;
836       int mid = (high + low + 1) / 2;
837       int last = -1;
838       cstring res = cstring_undefined;
839
840       while (low <= high && mid < nentries)
841         {
842           int cmp;
843
844           llassert (mid != last);
845           llassert (mid >= 0 && mid < nentries);
846
847           cmp = cstring_compare (key, table[mid]);
848           
849           if (cmp == 0)
850             {
851               res = table[mid];
852               break;
853             }
854           else if (cmp < 0) /* key is before table[mid] */
855             {
856               high = mid - 1;
857             }
858           else /* key of after table[mid] */
859             {
860               low = mid + 1;
861             }
862
863           last = mid;
864           mid = (high + low + 1) / 2;
865         }
866
867       if (mid != 0 && mid < nentries - 1)
868         {
869           llassert (cstring_compare (key, table[mid - 1]) > 0);
870           llassert (cstring_compare (key, table[mid + 1]) < 0);
871         }
872
873       return res;
874     }
875   
876   return cstring_undefined;
877 }
878
879 extern /*@observer@*/ cstring cstring_advanceWhiteSpace (cstring s)
880 {
881   if (cstring_isDefined (s)) {
882     char *t = s;
883
884     while (*t != '\0' && isspace ((int) *t)) {
885       t++;
886     }
887
888     return t;
889   }
890   
891   return cstring_undefined;
892 }
893     
894
895
This page took 0.282347 seconds and 5 git commands to generate.