]> andersk Git - splint.git/blob - src/general.c
Readded files.
[splint.git] / src / general.c
1 /*
2 ** LCLint - annotation-assisted static program checker
3 ** Copyright (C) 1994-2000 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 lclint: lclint-request@cs.virginia.edu
21 ** To report a bug: lclint-bug@cs.virginia.edu
22 ** For more information: http://lclint.cs.virginia.edu
23 */
24 /*
25 ** general.c
26 */
27
28 # include "lclintMacros.nf"
29 # include "basic.h"
30 # undef malloc
31 # undef realloc
32 # undef calloc
33
34 # ifdef USEDMALLOC
35 # include "dmalloc.h"
36 # endif
37
38 # include "portab.h"
39
40 /*
41 ** redefine undef'd memory ops
42 */
43
44 # ifndef USEDMALLOC
45 # include <stdlib.h> 
46
47 /*@-mustdefine@*/
48
49 void sfree (void *x)
50 {
51   if (x != NULL)
52     {
53       /*
54       fprintf (stderr, "Freeing: %ld\n", x);
55       if ((unsigned long) x < 136000000 && (unsigned long) x > 135000000) {
56         fprintf (stderr, "Looks bad!\n");
57       }
58       */
59       free (x);
60       /* fprintf (stderr, "Done.\n"); */
61     }
62 }
63 # endif
64
65 void sfreeEventually (void *x)
66 {
67   if (x != NULL)
68     {
69       ; /* should keep in a table */
70     }
71 /*@-mustfree@*/
72 } /*@=mustfree@*/
73
74 /*
75 ** all memory should be allocated from dimalloc
76 */
77
78 static long unsigned size_toLongUnsigned (size_t x)
79 {
80   long unsigned res = (long unsigned) x;
81
82   llassert ((size_t) res == x);
83   return res;
84 }
85
86 /*@out@*/ void *dimalloc (size_t size, char *name, int line)
87 {
88   /*
89   static void *lastaddr = 0;
90   static int numallocs = 0;
91   static int numbad = 0;
92   */
93
94   /* was malloc, use calloc to initialize to zero */
95   void *ret = (void *) calloc (1, size);
96
97   /*
98   numallocs++;
99
100   if (ret < lastaddr)
101     {
102       numbad++;
103       fprintf (stderr, "Bad alloc: %d / %d\n", numbad, numallocs);
104     }
105
106   lastaddr = ret;
107   */
108
109   if (ret == NULL)
110     {
111       if (size == 0)
112         {
113           llbug (message ("Zero allocation at %q.",
114                           fileloc_unparseRaw (cstring_fromChars (name), line)));
115         }
116       else
117         {
118           llfatalerrorLoc
119             (message ("Out of memory.  Allocating %w bytes at %s:%d.", 
120                       size_toLongUnsigned (size),
121                       cstring_fromChars (name), line));
122         }
123     }
124       
125   /*@-null@*/ /* null okay for size = 0 */
126   return ret; 
127   /*@=null@*/
128 }
129
130 void *dicalloc (size_t num, size_t size, char *name, int line)
131 {
132   void *ret = (void *) calloc (num, size);
133
134   if (ret == NULL)
135     {
136       llfatalerrorLoc 
137         (message ("Out of memory.  Allocating %w bytes at %s:%d.", 
138                   size_toLongUnsigned (size),
139                   cstring_fromChars (name), line));
140     }
141   
142   return ret;
143 }
144
145 void *direalloc (/*@out@*/ /*@null@*/ void *x, size_t size, 
146                  char *name, int line)
147 {
148   void *ret;
149
150   if (x == NULL)
151     {                                  
152       ret = (void *) dmalloc (size);
153     }
154   else
155     {
156       ret = (void *) realloc (x, size);
157     }
158
159   if (ret == NULL)
160     {
161       llfatalerrorLoc
162         (message ("Out of memory.  Allocating %w bytes at %s:%d.", 
163                   size_toLongUnsigned (size),
164                   cstring_fromChars (name), line));
165     }
166   
167   return ret;
168 }
169
170 /*@=mustdefine@*/
171
172 # ifndef NOLCL
173 char *FormatInt (int i)
174 {
175   char temp[255]; /* assume the integer has at most 254 digits */
176   char *outs;
177
178   sprintf (temp, "%i", i);
179   outs = (char *) dmalloc (sizeof (*outs) * (1 + strlen (temp)));
180   strcpy (outs, temp);
181
182   return (outs);
183 }
184 # endif
185
186 bool
187 isCext (char *ext)
188 {
189   return (!mstring_equal (ext, ".lcl") && 
190           !mstring_equal (ext, ".spc") &&
191           !mstring_equal (ext, ".ll"));
192 }
193
194 bool
195 isLCLfile (cstring s)
196 {
197   char *ext;
198
199   ext = filenameExtension (cstring_toCharsSafe (s));
200
201   if (ext != NULL)
202     {
203       return (!(isCext (ext)));
204     }
205
206   return (TRUE);
207 }
208
209 char *removeExtension (/*@temp@*/ char *s, const char *suffix)
210 {
211   char *t = strrchr (s, '.');
212   char *s2;
213
214   if (t == (char *) 0 || !mstring_equal (t, suffix))
215     {
216       return mstring_copy (s);
217     }
218
219   /*@-mods@*/ 
220   *t = '\0';
221   s2 = mstring_copy (s);
222   *t = '.';
223   /*@=mods@*/  /* Modification is undone. */
224   return s2;
225 }
226
227 # ifndef NOLCL
228 bool firstWord (char *s, char *w)
229 {
230   llassert (s != NULL);
231   llassert (w != NULL);
232   
233   for (; *w != '\0'; w++, s++)
234     {
235       if (*w != *s || *s == '\0')
236         return FALSE;
237     }
238   return TRUE;
239 }
240 # endif
241
242 # ifndef NOLCL
243 /*@only@*/ char *removePath (char *s)
244 {
245   char *t = strrchr (s, CONNECTCHAR);
246
247   if (t == NULL) return (mstring_copy (s));
248   else return (mstring_copy (t + 1));
249 }
250 # endif
251
252 /*@only@*/ char *
253 removePathFree (/*@only@*/ char *s)
254 {
255   char *t = strrchr (s, CONNECTCHAR);
256
257 # ifdef ALTCONNECTCHAR
258   {
259     char *at = strrchr (s, ALTCONNECTCHAR);
260     if (t == NULL || (at > t)) {
261       t = at;
262     }
263   }
264 # endif
265
266   if (t == NULL) 
267     {
268       return (s);
269     }
270   else
271     {
272       char *res = mstring_copy (t + 1);
273       mstring_free (s);
274       return res;
275     }
276 }
277
278 void mstring_markFree (char *s)
279 {
280     sfreeEventually (s);
281 }
282
283 /*@only@*/ char *
284 removeAnyExtension (char *s)
285 {
286   char *ret;
287   char *t = strrchr (s, '.');
288
289   if (t == (char *) 0)
290     {
291       return mstring_copy (s);
292     }
293
294   /*@-mods@*/
295   *t = '\0';
296   ret = mstring_copy (s);
297   *t = '.';
298   /*@=mods@*/ /* modification is undone */
299
300   return ret;
301 }
302
303 /*@only@*/ char *
304 addExtension (char *s, const char *suffix)
305 {
306   if (strrchr (s, '.') == (char *) 0)
307     {
308       /* <<< was mstring_concatFree1 --- bug detected by lclint >>> */
309       return (mstring_concat (s, suffix));
310     }
311   else
312     {
313       return mstring_copy (s);
314     }
315 }
316
317 int
318 getInt (char **s)
319 {
320   bool gotOne = FALSE;
321   int i = 0;
322
323   while (**s == ' ')
324     {
325       (*s)++;
326     }
327
328   if (**s == '-')
329     {
330       (*s)++;
331       if (**s < '0' || **s > '9')
332         {
333           llbug (message ("getInt: bad int: %s", cstring_fromChars (*s))); 
334         }
335       else
336         {
337           i = -1 * (int) (**s - '0');
338           gotOne = TRUE;
339         }
340
341       (*s)++;
342     }
343
344   while (**s >= '0' && **s <= '9')
345     {
346       i *= 10;
347       i += (int) (**s - '0');
348       (*s)++;
349       gotOne = TRUE;
350     }
351
352   if (!gotOne)
353     {
354       llbug (message ("No int to read: %s", cstring_fromChars (*s)));
355     }
356
357   while (**s == '\n' || **s == ' ' || **s == '\t')
358     {
359       (*s)++;
360     }
361
362   return i;
363 }
364
365 char
366 loadChar (char **s)
367 {
368   char ret;
369
370   while (**s == ' ')
371     {
372       (*s)++;
373     }
374   
375   ret = **s;
376   (*s)++;
377   return ret;
378 }
379
380 /*
381 ** not sure if this works...
382 */
383
384 double
385 getDouble (char **s)
386 {
387   char *end = mstring_createEmpty ();
388   double ret;
389
390   ret = strtod (*s, &end);
391
392   *s = end;
393   return ret;
394 }
395
396 /*
397 ** read to ' ', '\t'. '\n', '#', ',' or '\0'
398 */
399
400 char *
401 getWord (char **s)
402 {
403   char *res;
404   char *t = *s;
405   char c;
406
407   while ((c = **s) != '\0' && (c != ' ') && (c != ',') 
408          && (c != '\n') && (c != '\t') && (c != '#'))
409     {
410       (*s)++;
411     }
412
413   if (*s == t)  
414     {
415       return NULL;
416     }
417
418   **s = '\0';
419   res = mstring_copy (t);
420   **s = c;
421   return res;
422 }
423
424 bool
425 optCheckChar (char **s, char c)
426 {
427   if (**s == c)
428     {
429       (*s)++;
430       return TRUE;
431     }
432   else
433     {
434       return FALSE;
435     }
436 }
437
438 void
439 docheckChar (char **s, char c, char *file, int line)
440 {
441   /*@unchecked@*/ static int nbadchars = 0;
442
443   if (**s == c)
444     {
445       (*s)++;
446     }
447   else
448     {
449       nbadchars++;
450
451       if (nbadchars > 5)
452         {
453           llfatalbug (cstring_makeLiteral 
454                       ("checkChar: Too many errors.  Check library is up to date."));
455         }
456       else
457         {
458           llbug (message ("checkChar: %q: Bad char, expecting %h: %s",
459                           fileloc_unparseRaw (cstring_fromChars (file), line),
460                           c,
461                           cstring_fromChars (*s)));
462         }
463     }
464 }
465
466 char *mstring_spaces (int n)
467 {
468   int i;
469   char *ret;
470   char *ptr;
471
472   llassert (n >= 0);
473
474   ret = (char *) dmalloc (size_fromInt (n + 1));
475   ptr = ret;
476
477   for (i = 0; i < n; i++)
478     {
479       *ptr++ = ' ';
480     }
481
482   *ptr = '\0';
483
484   return ret;
485 }
486  
487 char *mstring_concat (const char *s1, const char *s2)
488 {
489   char *s = (char *) dmalloc (strlen (s1) + strlen (s2) + 1);
490   strcpy (s, s1);
491   strcat (s, s2);
492   return s;
493 }
494
495 extern /*@only@*/ char *
496 mstring_concatFree (/*@only@*/ char *s1, /*@only@*/ char *s2)
497 {
498   /* like mstring_concat but deallocates old strings */
499   char *s = (char *) dmalloc (strlen (s1) + strlen (s2) + 1);
500   strcpy (s, s1);
501   strcat (s, s2);
502
503   sfree (s1);
504   sfree (s2);
505   return s;
506 }
507
508 extern /*@only@*/ char *
509 mstring_concatFree1 (/*@only@*/ char *s1, const char *s2)
510 {
511   char *s = (char *) dmalloc (strlen (s1) + strlen (s2) + 1);
512   strcpy (s, s1);
513   strcat (s, s2);
514   sfree (s1);
515
516   return s;
517 }
518
519 extern /*@only@*/ char *
520 mstring_append (/*@only@*/ char *s1, char c)
521 {
522   size_t l = strlen (s1);
523   char *s;
524
525   s = (char *) dmalloc (sizeof (*s) * (l + 2));
526
527   strcpy (s, s1);
528   *(s + l) = c;
529   *(s + l + 1) = '\0';
530   sfree (s1); 
531   return s;
532 }
533
534 extern 
535 char *mstring_copy (char *s1)
536 {
537   if (s1 == NULL)
538     {
539       return NULL;
540     }
541   else
542     {
543       char *s = (char *) dmalloc ((strlen (s1) + 1) * sizeof (*s));
544       strcpy (s, s1);
545       return s;
546     }
547 }
548
549 extern
550 char *mstring_safePrint (char *s)
551 {
552   if (s == NULL)
553     {
554       return ("<undefined>");
555     }
556   else
557     {
558       return s;
559     }
560 }
561
562 extern
563 char *mstring_create (int n)
564 {
565   char *s;
566
567   s = dmalloc (sizeof (*s) * (n + 1));
568   *s = '\0';
569   return s;
570 }
571
572 void
573 fputline (FILE *out, char *s)
574 {
575   if (strlen (s) > 0) 
576     {
577       check (fputs (s, out) != EOF);
578     }
579
580   check (fputc ('\n', out) == (int) '\n');
581 }
582
583 int int_log (int x)
584 {
585   int ret = 1;
586
587   while (x > 10)
588     {
589       ret++;
590       x /= 10;
591     }
592
593   return ret;
594 }
595
596 /*@-czechfcns@*/
597 long unsigned int 
598 longUnsigned_fromInt (int x)
599 {
600   llassert (x >= 0);
601   
602   return (long unsigned) x;
603 }
604
605 size_t size_fromInt (int x)
606 {
607   size_t res = (size_t) x;
608
609   llassert ((int) res == x);
610   return res;
611 }
612
613 int size_toInt (size_t x)
614 {
615   int res = (int) x;
616
617   llassert ((size_t) res == x);
618   return res;
619 }
620
621 long size_toLong (size_t x)
622 {
623   long res = (long) x;
624
625   llassert ((size_t) res == x);
626   return res;
627 }
628
629 /*@=czechfcns@*/
630
631 char
632 char_fromInt (int x)
633 {
634   llassert ((x >= (int)'\0') && (x <= (int)'~'));
635
636   return ((char) x);
637 }
638
639 /*@-czechfcns@*/
640 int
641 longUnsigned_toInt (long unsigned int x)
642 {
643   int res = (int) x;
644
645   llassert ((long unsigned) res == x);
646   return res;
647 }
648
649 int
650 long_toInt (long int x)
651 {
652   int res = (int) x;
653
654   /*@+ignorequals@*/ llassert (res == x); /*@=ignorequals@*/
655   return res;
656 }
657
658 /*@+czechfcns@*/
659
660 bool mstring_equalPrefix (const char *c1, const char *c2)
661 {
662   llassert (c1 != NULL);
663   llassert (c2 != NULL);
664
665   if (strncmp(c1, c2, strlen(c2)) == 0)
666     {
667       return TRUE;
668     }
669   else
670     {
671       return FALSE;
672     }
673 }
674
675 bool mstring_equal (/*@null@*/ const char *s1, /*@null@*/ const char *s2)
676 {
677   if (s1 == NULL)
678     {
679       return (s2 == NULL);
680     }
681   else
682     {
683       if (s2 == NULL)
684         {
685           return FALSE;
686         }
687       else
688         {
689           return (strcmp(s1, s2) == 0);
690         }
691     }
692 }
693
694 /*@observer@*/ char *filenameExtension (/*@returned@*/ char *s)
695 {
696   llassert (s != NULL);
697
698   return (strrchr(s, '.'));
699 }
700
701 char *removePreDirs (char *s)
702 {
703   while (*s == '.' && *(s + 1) == CONNECTCHAR) 
704     {
705       s += 2;
706     }
707
708 # if defined(OS2) || defined(MSDOS)
709   /* remove remainders from double path delimiters... */
710   while (*s == CONNECTCHAR) 
711     {
712       ++s;
713     }
714 # endif /* !defined(OS2) && !defined(MSDOS) */
715
716   return s;
717 }
718
719 void checkUngetc (int c, FILE *f)
720 {
721   int res;
722
723   llassert (c != EOF);
724   res = ungetc (c, f);
725   llassert (res == c);
726 }
727
728 bool isHeaderFile (cstring fname)
729 {
730   char *ext = filenameExtension (cstring_toCharsSafe (fname));
731   
732   return (mstring_equal (ext, ".h")
733           || mstring_equal (ext, ".H")
734           || mstring_equal (ext, ".lh"));
735 }
736
This page took 0.082373 seconds and 5 git commands to generate.