]> andersk Git - splint.git/blame - src/cstring.c
Fixed inclusion problems with osd.h.
[splint.git] / src / cstring.c
CommitLineData
616915dd 1/*
11db3170 2** Splint - annotation-assisted static program checker
c59f5181 3** Copyright (C) 1994-2003 University of Virginia,
616915dd 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**
155af98d 20** For information on splint: info@splint.org
21** To report a bug: splint-bug@splint.org
11db3170 22** For more information: http://www.splint.org
616915dd 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
1b8ae690 34# include "splintMacros.nf"
616915dd 35# include "basic.h"
36# include "osd.h"
616915dd 37
2934b455 38/*@only@*/ /*@notnull@*/
616915dd 39cstring cstring_newEmpty (void)
40{
41 return (cstring_create (0));
42}
43
44char cstring_firstChar (cstring s)
45{
46 llassert (cstring_isDefined (s));
47 llassert (cstring_length (s) > 0);
48
49 return (s[0]);
50}
51
abd7f895 52char cstring_getChar (cstring s, size_t n)
616915dd 53{
abd7f895 54 size_t length = cstring_length (s);
616915dd 55
56 llassert (cstring_isDefined (s));
57 llassert (n >= 1 && n <= length);
58
59 return (s[n - 1]);
60}
61
abd7f895 62cstring cstring_suffix (cstring s, size_t n)
616915dd 63{
64 llassert (cstring_isDefined (s));
65 llassert (n <= cstring_length (s));
66
67 return (s + n);
68}
69
abd7f895 70cstring cstring_prefix (cstring s, size_t n)
71 /*@requires maxRead(s) >= n /\ maxSet(s) >= n @*/
72 /*@ensures maxRead(result) == n /\ maxSet(result) == n @*/
616915dd 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
93int 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
68de3f33 112cstring cstring_afterChar (cstring s, char c)
113{
114 llassert (cstring_isDefined (s));
115 return strchr (s, c);
116}
117
616915dd 118cstring 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
abd7f895 141void cstring_setChar (cstring s, size_t n, char c) /*@requires maxRead(s) >= (n - 1) /\ maxSet(s) >= (n - 1) @*/
616915dd 142{
143 llassert (cstring_isDefined (s));
144 llassert (n > 0 && n <= cstring_length (s));
145
146 s[n - 1] = c;
147}
148
149char cstring_lastChar (cstring s)
150{
abd7f895 151 size_t length;
616915dd 152
153 llassert (cstring_isDefined (s));
154
155 length = cstring_length (s);
156 llassert (length > 0);
157
158 return (s[length - 1]);
159}
160
86d93ed3 161/*@only@*/ cstring cstring_copy (cstring s) /*@ensures maxSet(result) == maxRead(s) /\ maxRead(result) == maxRead(s) @*/
616915dd 162{
163 if (cstring_isDefined (s))
164 {
165 return (mstring_copy (s));
166 }
167 else
168 {
169 return cstring_undefined;
170 }
171}
172
abd7f895 173/*@only@*/ cstring cstring_copyLength (char *s, size_t len) /*@requires maxSet(s) >= (len - 1) @*/
616915dd 174{
175 char *res = mstring_create (len + 1);
176
abd7f895 177 strncpy (res, s, len);
616915dd 178 res[len] = '\0';
179 return res;
180}
181
182bool 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
616915dd 198void 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}
616915dd 215
92b2ba2c 216void cstring_replaceLit (/*@unique@*/ cstring s, char *old, char *snew)
217 /*@requires maxRead(snew) >= 0 /\ maxRead(old) >= 0 /\ maxRead(old) >= maxRead(snew) @*/
616915dd 218{
616915dd 219 llassert (strlen (old) >= strlen (snew));
92b2ba2c 220
616915dd 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;
92b2ba2c 229
230 llassert (lendiff >= 0);
231
616915dd 232 while (*tsnew != '\0')
233 {
92b2ba2c 234 llassert (*sp != '\0');
616915dd 235 *sp++ = *tsnew++;
236 }
92b2ba2c 237
616915dd 238 if (lendiff > 0)
239 {
240 while (*(sp + lendiff) != '\0')
241 {
242 *sp = *(sp + lendiff);
243 sp++;
244 }
dcdc46c8 245
616915dd 246 *sp = '\0';
247 }
248
249 sp = strstr (s, old);
250 }
dcdc46c8 251 }
616915dd 252}
253
254/*
255** removes all chars in clist from s
256*/
257
258void cstring_stripChars (cstring s, const char *clist)
259{
260 if (cstring_isDefined (s))
261 {
262 int i;
abd7f895 263 size_t size = cstring_length (s);
616915dd 264
abd7f895 265 for (i = 0; i < size_toInt (size); i++)
616915dd 266 {
8fd556fb 267
abd7f895 268 char c = s[i];
616915dd 269
270 if (strchr (clist, c) != NULL)
271 {
272 /* strip this char */
273 int j;
274
275 size--;
abd7f895 276
277 for (j = i; j < size_toInt (size); j++)
616915dd 278 {
8fd556fb 279 s[j] = s[j+1];
616915dd 280 }
abd7f895 281
8fd556fb 282 s[size] = '\0';
616915dd 283 i--;
284 }
285 }
286 }
287}
288
289bool 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
303static 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
327cmpcode cstring_genericEqual (cstring s, cstring t,
abd7f895 328 size_t nchars,
616915dd 329 bool caseinsensitive,
abd7f895 330 bool lookalike)
331 /*@requires maxRead(s) >= nchars /\ maxRead(t) >= nchars @*/
616915dd 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 {
abd7f895 350 if (nchars > 0 && i >= size_toInt (nchars))
616915dd 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
8fd556fb 377
616915dd 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
400bool 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
408bool 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
abd7f895 416bool cstring_equalLen (cstring c1, cstring c2, size_t len)
616915dd 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);
abd7f895 421 else return (strncmp (c1, c2, len) == 0);
616915dd 422}
423
424bool 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
abd7f895 432bool cstring_equalLenCaseInsensitive (cstring c1, cstring c2, size_t len)
616915dd 433{
616915dd 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
68de3f33 440bool cstring_equalPrefix (cstring c1, cstring c2)
616915dd 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
68de3f33 452bool cstring_equalPrefixLit (cstring c1, const char *c2)
616915dd 453{
454 llassert (c2 != NULL);
455
456 if (cstring_isUndefined (c1))
457 {
458 return (strlen (c2) == 0);
459 }
460
616915dd 461 return (strncmp (c1, c2, strlen (c2)) == 0);
616915dd 462}
463
464int cstring_xcompare (cstring *c1, cstring *c2)
465{
466 return (cstring_compare (*c1, *c2));
467}
468
469int 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
507void cstring_markOwned (/*@owned@*/ cstring s)
508{
509 sfreeEventually (s);
510}
511
512void cstring_free (/*@only@*/ cstring s)
513{
514 if (cstring_isDefined (s))
515 {
c21b4c87 516 /*drl 2/3/2002*/
517 s[0] = '\0';
518
616915dd 519 sfree (s);
520 }
521}
522
523cstring 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
abd7f895 547size_t cstring_length (cstring s)
616915dd 548{
549 if (cstring_isDefined (s))
550 {
abd7f895 551 return strlen (s);
616915dd 552 }
abd7f895 553
616915dd 554 return 0;
555}
556
557cstring
86d93ed3 558cstring_capitalize (cstring s) /*@requires maxSet(s) >= 0 @*/
616915dd 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
571cstring
86d93ed3 572cstring_capitalizeFree (cstring s) /*@requires maxSet(s) >= 0 /\ maxRead(s) >= 0 @*/
616915dd 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
583cstring
abd7f895 584cstring_clip (cstring s, size_t len)
616915dd 585{
586 if (cstring_isUndefined (s) || cstring_length (s) <= len)
587 {
588 ;
589 }
590 else
591 {
592 llassert (s != NULL);
8fd556fb 593
abd7f895 594 *(s + len) = '\0';
616915dd 595 }
abd7f895 596
616915dd 597 return s;
598}
599
600/*@only@*/ cstring
abd7f895 601cstring_elide (cstring s, size_t len)
616915dd 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);
abd7f895 610
611 strncpy (sc, s, len);
8fd556fb 612
abd7f895 613 *(sc + len - 1) = '\0';
616915dd 614 *(sc + len - 2) = '.';
615 *(sc + len - 3) = '.';
616 *(sc + len - 4) = '.';
abd7f895 617
616915dd 618 return sc;
619 }
620}
621
622/*@only@*/ cstring
abd7f895 623cstring_fill (cstring s, size_t n) /*@requires n >= 0 @*/
616915dd 624{
625 cstring t = cstring_create (n + 1);
626 cstring ot = t;
abd7f895 627 size_t len = cstring_length (s);
628 size_t i;
616915dd 629
630 if (len > n)
631 {
632 for (i = 0; i < n; i++)
633 {
8fd556fb 634
616915dd 635 *t++ = *s++;
636 }
637 *t = '\0';
638 }
639 else
640 {
641 for (i = 0; i < len; i++)
642 {
8fd556fb 643
616915dd 644 *t++ = *s++;
645 }
646 for (i = 0; i < n - len; i++)
647 {
8fd556fb 648
616915dd 649 *t++ = ' ';
650 }
651 *t = '\0';
652 }
653
654 return ot;
655}
656
657cstring
658cstring_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
8fd556fb 666 while ((c = *s) != '\0')
616915dd 667 {
668 if (c >= 'A' && c <= 'Z')
669 {
670 c = c - 'A' + 'a';
671 }
672 *t++ = c;
673 s++;
674 }
8fd556fb 675 *t = '\0';
616915dd 676
677 return ot;
678 }
679 else
680 {
681 return cstring_undefined;
682 }
683}
684
685/*@notnull@*/ cstring
686cstring_appendChar (/*@only@*/ cstring s1, char c)
687{
abd7f895 688 size_t l = cstring_length (s1);
616915dd 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;
8fd556fb 697 *(s + l + 1) = '\0';
616915dd 698 sfree (s1);
699 }
700 else
701 {
702 *(s) = c;
8fd556fb 703 *(s + 1) = '\0';
616915dd 704 }
705
706 return s;
707}
708
709/*@only@*/ cstring
710cstring_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
719cstring_concatFree1 (cstring s, cstring t)
720{
721 cstring res = cstring_concat (s, t);
722 cstring_free (s);
723 return res;
724}
725
616915dd 726/*@only@*/ cstring
727cstring_concatChars (cstring s, char *t)
728{
729 cstring res = cstring_concat (s, cstring_fromChars (t));
730 cstring_free (s);
731 return res;
732}
616915dd 733
734/*@only@*/ cstring
abd7f895 735cstring_concatLength (cstring s1, char *s2, size_t len) /*@requires maxSet(s2) >= (len - 1) @*/
616915dd 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
86d93ed3 746cstring_concat (cstring s, cstring t) /*@requires maxSet(s) >= 0 @*/
616915dd 747{
748 char *ret = mstring_create (cstring_length (s) + cstring_length (t));
749
750 if (cstring_isDefined (s))
751 {
8fd556fb 752 strcpy (ret, s);
616915dd 753 }
754 if (cstring_isDefined (t))
755 {
756 strcat (ret, t);
757 }
758
759 return ret;
760}
761
762/*@notnull@*/ /*@only@*/ cstring
763cstring_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
772cstring_prependChar (char c, /*@temp@*/ cstring s1)
773{
abd7f895 774 size_t l = cstring_length (s1);
616915dd 775 char *s = (char *) dmalloc (sizeof (*s) * (l + 2));
776
8fd556fb 777 *(s) = c;
616915dd 778
779 if (cstring_isDefined (s1))
780 {
781 /*@-mayaliasunique@*/
782 strcpy (s + 1, s1);
783 /*@=mayaliasunique@*/
784 }
785
8fd556fb 786 *(s + l + 1) = '\0';
616915dd 787 return s;
788}
789
616915dd 790bool
791cstring_hasNonAlphaNumBar (cstring s)
792{
793 int c;
794
795 if (cstring_isUndefined (s)) return FALSE;
796
8fd556fb 797 while ((c = (int) *s) != (int) '\0')
616915dd 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}
616915dd 809
810/*@only@*/ /*@notnull@*/ cstring
abd7f895 811cstring_create (size_t n)
616915dd 812{
813 char *s = dmalloc (sizeof (*s) * (n + 1));
abd7f895 814
8fd556fb 815 *s = '\0';
616915dd 816 return s;
817}
818
2934b455 819/*@only@*/ /*@notnull@*/ cstring
abd7f895 820cstring_copySegment (cstring s, size_t findex, size_t tindex)
2934b455 821{
822 cstring res = cstring_create (tindex - findex + 1);
823
824 llassert (cstring_isDefined (s));
825 llassert (cstring_length (s) > tindex);
826
e5081f8c 827 strncpy (res, (s + findex), size_fromInt (size_toInt (tindex - findex) + 1));
2934b455 828 return res;
829}
830
616915dd 831lsymbol cstring_toSymbol (cstring s)
832{
2934b455 833 lsymbol res = lsymbol_fromString (s);
616915dd 834
835 cstring_free (s);
836 return res;
837}
616915dd 838
839cstring 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);
8fd556fb 879 llassert (cstring_compare (key, table[mid + 1]) < 0);
616915dd 880 }
881
882 return res;
883 }
884
885 return cstring_undefined;
886}
887
888extern /*@observer@*/ cstring cstring_advanceWhiteSpace (cstring s)
889{
890 if (cstring_isDefined (s)) {
891 char *t = s;
892
8fd556fb 893 while (*t != '\0' && isspace ((int) *t)) {
616915dd 894 t++;
895 }
896
897 return t;
898 }
899
900 return cstring_undefined;
901}
1810fe2a 902
46edc85c 903/* changes strings like "sdf" "sdfsd" into "sdfsdfsd"*/
904/* This function understands that "sdf\" \"sdfsdf" is okay*/
905static 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;
846c7865 955
956 /*@notreached@*/ return ret;
46edc85c 957 }
958 else
959 {
960 ptr++;
961 }
962 }
963 else
964 {
965 *retPtr = *ptr;
966 }
967
968 retPtr++;
969 ptr++;
970
971 }/* end while */
846c7865 972 *retPtr = '\0';
46edc85c 973 return ret;
974}
975
37ae0b5e 976static mstring doExpandEscapes (cstring s, /*@out@*/ size_t *len)
1810fe2a 977{
978 char *ptr;
979 mstring ret;
980 char * retPtr;
1810fe2a 981
982 llassert(cstring_isDefined (s));
983
abd7f895 984 ret = mstring_create (cstring_length(s));
1810fe2a 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
0e5499ac 1009 /* Handle Octal escapes */
1810fe2a 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
846c7865 1114 llassert( (retPtr-ret) >= 0 );
1115 *len = (size_t)(retPtr - ret);
1810fe2a 1116 return ret;
1117}
1118
1119
1120/*this function is like sctring_expandEscapses */
1121mstring cstring_expandEscapes (cstring s)
1122{
37ae0b5e 1123 size_t len;
1810fe2a 1124
1125 mstring ret;
1810fe2a 1126 ret = doExpandEscapes (s, &len);
1127 return ret;
1128}
1129
37ae0b5e 1130size_t cstring_lengthExpandEscapes (cstring s)
1810fe2a 1131{
37ae0b5e 1132 size_t len;
46edc85c 1133 mstring tmpStr, tmpStr2;
1134
1135 tmpStr = doMergeString (s);
1136 tmpStr2 = doExpandEscapes (tmpStr, &len);
46edc85c 1137
1810fe2a 1138 cstring_free(tmpStr);
46edc85c 1139 cstring_free(tmpStr2);
1810fe2a 1140
1141 return len;
1142}
1143
9276a168 1144cstring 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}
b941db6b 1164
393e573f 1165
1166
1167
1168
1169
1170
1171
This page took 0.25628 seconds and 5 git commands to generate.