Main Page   Alphabetical List   Compound List   File List   Compound Members   File Members  

general.c

Go to the documentation of this file.
00001 /*
00002 ** LCLint - annotation-assisted static program checker
00003 ** Copyright (C) 1994-2000 University of Virginia,
00004 **         Massachusetts Institute of Technology
00005 **
00006 ** This program is free software; you can redistribute it and/or modify it
00007 ** under the terms of the GNU General Public License as published by the
00008 ** Free Software Foundation; either version 2 of the License, or (at your
00009 ** option) any later version.
00010 ** 
00011 ** This program is distributed in the hope that it will be useful, but
00012 ** WITHOUT ANY WARRANTY; without even the implied warranty of
00013 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 ** General Public License for more details.
00015 ** 
00016 ** The GNU General Public License is available from http://www.gnu.org/ or
00017 ** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00018 ** MA 02111-1307, USA.
00019 **
00020 ** For information on lclint: lclint-request@cs.virginia.edu
00021 ** To report a bug: lclint-bug@cs.virginia.edu
00022 ** For more information: http://lclint.cs.virginia.edu
00023 */
00024 /*
00025 ** general.c
00026 */
00027 
00028 # include "lclintMacros.nf"
00029 # include "basic.h"
00030 # undef malloc
00031 # undef realloc
00032 # undef calloc
00033 
00034 # ifdef USEDMALLOC
00035 # include "dmalloc.h"
00036 # endif
00037 
00038 # include "portab.h"
00039 
00040 /*
00041 ** redefine undef'd memory ops
00042 */
00043 
00044 # ifndef USEDMALLOC
00045 # include <stdlib.h> 
00046 
00047 /*@-mustdefine@*/
00048 
00049 void sfree (void *x)
00050 {
00051   if (x != NULL)
00052     {
00053       /*
00054       fprintf (stderr, "Freeing: %ld\n", x);
00055       if ((unsigned long) x < 136000000 && (unsigned long) x > 135000000) {
00056         fprintf (stderr, "Looks bad!\n");
00057       }
00058       */
00059       free (x);
00060       /* fprintf (stderr, "Done.\n"); */
00061     }
00062 }
00063 # endif
00064 
00065 void sfreeEventually (void *x)
00066 {
00067   if (x != NULL)
00068     {
00069       ; /* should keep in a table */
00070     }
00071 /*@-mustfree@*/
00072 } /*@=mustfree@*/
00073 
00074 /*
00075 ** all memory should be allocated from dimalloc
00076 */
00077 
00078 static long unsigned size_toLongUnsigned (size_t x)
00079 {
00080   long unsigned res = (long unsigned) x;
00081 
00082   llassert ((size_t) res == x);
00083   return res;
00084 }
00085 
00086 /*@out@*/ void *dimalloc (size_t size, char *name, int line)
00087 {
00088   /*
00089   static void *lastaddr = 0;
00090   static int numallocs = 0;
00091   static int numbad = 0;
00092   */
00093 
00094   /* was malloc, use calloc to initialize to zero */
00095   void *ret = (void *) calloc (1, size);
00096 
00097   /*
00098   numallocs++;
00099 
00100   if (ret < lastaddr)
00101     {
00102       numbad++;
00103       fprintf (stderr, "Bad alloc: %d / %d\n", numbad, numallocs);
00104     }
00105 
00106   lastaddr = ret;
00107   */
00108 
00109   if (ret == NULL)
00110     {
00111       if (size == 0)
00112         {
00113           llbug (message ("Zero allocation at %q.",
00114                           fileloc_unparseRaw (cstring_fromChars (name), line)));
00115         }
00116       else
00117         {
00118           llfatalerrorLoc
00119             (message ("Out of memory.  Allocating %w bytes at %s:%d.", 
00120                       size_toLongUnsigned (size),
00121                       cstring_fromChars (name), line));
00122         }
00123     }
00124       
00125   /*@-null@*/ /* null okay for size = 0 */
00126   return ret; 
00127   /*@=null@*/
00128 }
00129 
00130 void *dicalloc (size_t num, size_t size, char *name, int line)
00131 {
00132   void *ret = (void *) calloc (num, size);
00133 
00134   if (ret == NULL)
00135     {
00136       llfatalerrorLoc 
00137         (message ("Out of memory.  Allocating %w bytes at %s:%d.", 
00138                   size_toLongUnsigned (size),
00139                   cstring_fromChars (name), line));
00140     }
00141   
00142   return ret;
00143 }
00144 
00145 void *direalloc (/*@out@*/ /*@null@*/ void *x, size_t size, 
00146                  char *name, int line)
00147 {
00148   void *ret;
00149 
00150   if (x == NULL)
00151     {                                  
00152       ret = (void *) dmalloc (size);
00153     }
00154   else
00155     {
00156       ret = (void *) realloc (x, size);
00157     }
00158 
00159   if (ret == NULL)
00160     {
00161       llfatalerrorLoc
00162         (message ("Out of memory.  Allocating %w bytes at %s:%d.", 
00163                   size_toLongUnsigned (size),
00164                   cstring_fromChars (name), line));
00165     }
00166   
00167   return ret;
00168 }
00169 
00170 /*@=mustdefine@*/
00171 
00172 # ifndef NOLCL
00173 char *FormatInt (int i)
00174 {
00175   char temp[255]; /* assume the integer has at most 254 digits */
00176   char *outs;
00177 
00178   sprintf (temp, "%i", i);
00179   outs = (char *) dmalloc (sizeof (*outs) * (1 + strlen (temp)));
00180   strcpy (outs, temp);
00181 
00182   return (outs);
00183 }
00184 # endif
00185 
00186 bool
00187 isCext (char *ext)
00188 {
00189   return (!mstring_equal (ext, ".lcl") && 
00190           !mstring_equal (ext, ".spc") &&
00191           !mstring_equal (ext, ".ll"));
00192 }
00193 
00194 bool
00195 isLCLfile (cstring s)
00196 {
00197   char *ext;
00198 
00199   ext = filenameExtension (cstring_toCharsSafe (s));
00200 
00201   if (ext != NULL)
00202     {
00203       return (!(isCext (ext)));
00204     }
00205 
00206   return (TRUE);
00207 }
00208 
00209 char *removeExtension (/*@temp@*/ char *s, const char *suffix)
00210 {
00211   char *t = strrchr (s, '.');
00212   char *s2;
00213 
00214   if (t == (char *) 0 || !mstring_equal (t, suffix))
00215     {
00216       return mstring_copy (s);
00217     }
00218 
00219   /*@-mods@*/ 
00220   *t = '\0';
00221   s2 = mstring_copy (s);
00222   *t = '.';
00223   /*@=mods@*/  /* Modification is undone. */
00224   return s2;
00225 }
00226 
00227 # ifndef NOLCL
00228 bool firstWord (char *s, char *w)
00229 {
00230   llassert (s != NULL);
00231   llassert (w != NULL);
00232   
00233   for (; *w != '\0'; w++, s++)
00234     {
00235       if (*w != *s || *s == '\0')
00236         return FALSE;
00237     }
00238   return TRUE;
00239 }
00240 # endif
00241 
00242 # ifndef NOLCL
00243 /*@only@*/ char *removePath (char *s)
00244 {
00245   char *t = strrchr (s, CONNECTCHAR);
00246 
00247   if (t == NULL) return (mstring_copy (s));
00248   else return (mstring_copy (t + 1));
00249 }
00250 # endif
00251 
00252 /*@only@*/ char *
00253 removePathFree (/*@only@*/ char *s)
00254 {
00255   char *t = strrchr (s, CONNECTCHAR);
00256 
00257 # ifdef ALTCONNECTCHAR
00258   {
00259     char *at = strrchr (s, ALTCONNECTCHAR);
00260     if (t == NULL || (at > t)) {
00261       t = at;
00262     }
00263   }
00264 # endif
00265 
00266   if (t == NULL) 
00267     {
00268       return (s);
00269     }
00270   else
00271     {
00272       char *res = mstring_copy (t + 1);
00273       mstring_free (s);
00274       return res;
00275     }
00276 }
00277 
00278 void mstring_markFree (char *s)
00279 {
00280     sfreeEventually (s);
00281 }
00282 
00283 /*@only@*/ char *
00284 removeAnyExtension (char *s)
00285 {
00286   char *ret;
00287   char *t = strrchr (s, '.');
00288 
00289   if (t == (char *) 0)
00290     {
00291       return mstring_copy (s);
00292     }
00293 
00294   /*@-mods@*/
00295   *t = '\0';
00296   ret = mstring_copy (s);
00297   *t = '.';
00298   /*@=mods@*/ /* modification is undone */
00299 
00300   return ret;
00301 }
00302 
00303 /*@only@*/ char *
00304 addExtension (char *s, const char *suffix)
00305 {
00306   if (strrchr (s, '.') == (char *) 0)
00307     {
00308       /* <<< was mstring_concatFree1 --- bug detected by lclint >>> */
00309       return (mstring_concat (s, suffix));
00310     }
00311   else
00312     {
00313       return mstring_copy (s);
00314     }
00315 }
00316 
00317 int
00318 getInt (char **s)
00319 {
00320   bool gotOne = FALSE;
00321   int i = 0;
00322 
00323   while (**s == ' ')
00324     {
00325       (*s)++;
00326     }
00327 
00328   if (**s == '-')
00329     {
00330       (*s)++;
00331       if (**s < '0' || **s > '9')
00332         {
00333           llbug (message ("getInt: bad int: %s", cstring_fromChars (*s))); 
00334         }
00335       else
00336         {
00337           i = -1 * (int) (**s - '0');
00338           gotOne = TRUE;
00339         }
00340 
00341       (*s)++;
00342     }
00343 
00344   while (**s >= '0' && **s <= '9')
00345     {
00346       i *= 10;
00347       i += (int) (**s - '0');
00348       (*s)++;
00349       gotOne = TRUE;
00350     }
00351 
00352   if (!gotOne)
00353     {
00354       llbug (message ("No int to read: %s", cstring_fromChars (*s)));
00355     }
00356 
00357   while (**s == '\n' || **s == ' ' || **s == '\t')
00358     {
00359       (*s)++;
00360     }
00361 
00362   return i;
00363 }
00364 
00365 char
00366 loadChar (char **s)
00367 {
00368   char ret;
00369 
00370   while (**s == ' ')
00371     {
00372       (*s)++;
00373     }
00374   
00375   ret = **s;
00376   (*s)++;
00377   return ret;
00378 }
00379 
00380 /*
00381 ** not sure if this works...
00382 */
00383 
00384 double
00385 getDouble (char **s)
00386 {
00387   char *end = mstring_createEmpty ();
00388   double ret;
00389 
00390   ret = strtod (*s, &end);
00391 
00392   *s = end;
00393   return ret;
00394 }
00395 
00396 /*
00397 ** read to ' ', '\t'. '\n', '#', ',' or '\0'
00398 */
00399 
00400 char *
00401 getWord (char **s)
00402 {
00403   char *res;
00404   char *t = *s;
00405   char c;
00406 
00407   while ((c = **s) != '\0' && (c != ' ') && (c != ',') 
00408          && (c != '\n') && (c != '\t') && (c != '#'))
00409     {
00410       (*s)++;
00411     }
00412 
00413   if (*s == t)  
00414     {
00415       return NULL;
00416     }
00417 
00418   **s = '\0';
00419   res = mstring_copy (t);
00420   **s = c;
00421   return res;
00422 }
00423 
00424 bool
00425 optCheckChar (char **s, char c)
00426 {
00427   if (**s == c)
00428     {
00429       (*s)++;
00430       return TRUE;
00431     }
00432   else
00433     {
00434       return FALSE;
00435     }
00436 }
00437 
00438 void
00439 docheckChar (char **s, char c, char *file, int line)
00440 {
00441   /*@unchecked@*/ static int nbadchars = 0;
00442 
00443   if (**s == c)
00444     {
00445       (*s)++;
00446     }
00447   else
00448     {
00449       nbadchars++;
00450 
00451       if (nbadchars > 5)
00452         {
00453           llfatalbug (cstring_makeLiteral 
00454                       ("checkChar: Too many errors.  Check library is up to date."));
00455         }
00456       else
00457         {
00458           llbug (message ("checkChar: %q: Bad char, expecting %h: %s",
00459                           fileloc_unparseRaw (cstring_fromChars (file), line),
00460                           c,
00461                           cstring_fromChars (*s)));
00462         }
00463     }
00464 }
00465 
00466 char *mstring_spaces (int n)
00467 {
00468   int i;
00469   char *ret;
00470   char *ptr;
00471 
00472   llassert (n >= 0);
00473 
00474   ret = (char *) dmalloc (size_fromInt (n + 1));
00475   ptr = ret;
00476 
00477   for (i = 0; i < n; i++)
00478     {
00479       *ptr++ = ' ';
00480     }
00481 
00482   *ptr = '\0';
00483 
00484   return ret;
00485 }
00486  
00487 char *mstring_concat (const char *s1, const char *s2)
00488 {
00489   char *s = (char *) dmalloc (strlen (s1) + strlen (s2) + 1);
00490   strcpy (s, s1);
00491   strcat (s, s2);
00492   return s;
00493 }
00494 
00495 extern /*@only@*/ char *
00496 mstring_concatFree (/*@only@*/ char *s1, /*@only@*/ char *s2)
00497 {
00498   /* like mstring_concat but deallocates old strings */
00499   char *s = (char *) dmalloc (strlen (s1) + strlen (s2) + 1);
00500   strcpy (s, s1);
00501   strcat (s, s2);
00502 
00503   sfree (s1);
00504   sfree (s2);
00505   return s;
00506 }
00507 
00508 extern /*@only@*/ char *
00509 mstring_concatFree1 (/*@only@*/ char *s1, const char *s2)
00510 {
00511   char *s = (char *) dmalloc (strlen (s1) + strlen (s2) + 1);
00512   strcpy (s, s1);
00513   strcat (s, s2);
00514   sfree (s1);
00515 
00516   return s;
00517 }
00518 
00519 extern /*@only@*/ char *
00520 mstring_append (/*@only@*/ char *s1, char c)
00521 {
00522   size_t l = strlen (s1);
00523   char *s;
00524 
00525   s = (char *) dmalloc (sizeof (*s) * (l + 2));
00526 
00527   strcpy (s, s1);
00528   *(s + l) = c;
00529   *(s + l + 1) = '\0';
00530   sfree (s1); 
00531   return s;
00532 }
00533 
00534 extern 
00535 char *mstring_copy (char *s1)
00536 {
00537   if (s1 == NULL)
00538     {
00539       return NULL;
00540     }
00541   else
00542     {
00543       char *s = (char *) dmalloc ((strlen (s1) + 1) * sizeof (*s));
00544       strcpy (s, s1);
00545       return s;
00546     }
00547 }
00548 
00549 extern
00550 char *mstring_safePrint (char *s)
00551 {
00552   if (s == NULL)
00553     {
00554       return ("<undefined>");
00555     }
00556   else
00557     {
00558       return s;
00559     }
00560 }
00561 
00562 extern
00563 char *mstring_create (int n)
00564 {
00565   char *s;
00566 
00567   s = dmalloc (sizeof (*s) * (n + 1));
00568   *s = '\0';
00569   return s;
00570 }
00571 
00572 void
00573 fputline (FILE *out, char *s)
00574 {
00575   if (strlen (s) > 0) 
00576     {
00577       check (fputs (s, out) != EOF);
00578     }
00579 
00580   check (fputc ('\n', out) == (int) '\n');
00581 }
00582 
00583 int int_log (int x)
00584 {
00585   int ret = 1;
00586 
00587   while (x > 10)
00588     {
00589       ret++;
00590       x /= 10;
00591     }
00592 
00593   return ret;
00594 }
00595 
00596 /*@-czechfcns@*/
00597 long unsigned int 
00598 longUnsigned_fromInt (int x)
00599 {
00600   llassert (x >= 0);
00601   
00602   return (long unsigned) x;
00603 }
00604 
00605 size_t size_fromInt (int x)
00606 {
00607   size_t res = (size_t) x;
00608 
00609   llassert ((int) res == x);
00610   return res;
00611 }
00612 
00613 int size_toInt (size_t x)
00614 {
00615   int res = (int) x;
00616 
00617   llassert ((size_t) res == x);
00618   return res;
00619 }
00620 
00621 long size_toLong (size_t x)
00622 {
00623   long res = (long) x;
00624 
00625   llassert ((size_t) res == x);
00626   return res;
00627 }
00628 
00629 /*@=czechfcns@*/
00630 
00631 char
00632 char_fromInt (int x)
00633 {
00634   llassert ((x >= (int)'\0') && (x <= (int)'~'));
00635 
00636   return ((char) x);
00637 }
00638 
00639 /*@-czechfcns@*/
00640 int
00641 longUnsigned_toInt (long unsigned int x)
00642 {
00643   int res = (int) x;
00644 
00645   llassert ((long unsigned) res == x);
00646   return res;
00647 }
00648 
00649 int
00650 long_toInt (long int x)
00651 {
00652   int res = (int) x;
00653 
00654   /*@+ignorequals@*/ llassert (res == x); /*@=ignorequals@*/
00655   return res;
00656 }
00657 
00658 /*@+czechfcns@*/
00659 
00660 bool mstring_equalPrefix (const char *c1, const char *c2)
00661 {
00662   llassert (c1 != NULL);
00663   llassert (c2 != NULL);
00664 
00665   if (strncmp(c1, c2, strlen(c2)) == 0)
00666     {
00667       return TRUE;
00668     }
00669   else
00670     {
00671       return FALSE;
00672     }
00673 }
00674 
00675 bool mstring_equal (/*@null@*/ const char *s1, /*@null@*/ const char *s2)
00676 {
00677   if (s1 == NULL)
00678     {
00679       return (s2 == NULL);
00680     }
00681   else
00682     {
00683       if (s2 == NULL)
00684         {
00685           return FALSE;
00686         }
00687       else
00688         {
00689           return (strcmp(s1, s2) == 0);
00690         }
00691     }
00692 }
00693 
00694 /*@observer@*/ char *filenameExtension (/*@returned@*/ char *s)
00695 {
00696   llassert (s != NULL);
00697 
00698   return (strrchr(s, '.'));
00699 }
00700 
00701 char *removePreDirs (char *s)
00702 {
00703   while (*s == '.' && *(s + 1) == CONNECTCHAR) 
00704     {
00705       s += 2;
00706     }
00707 
00708 # if defined(OS2) || defined(MSDOS)
00709   /* remove remainders from double path delimiters... */
00710   while (*s == CONNECTCHAR) 
00711     {
00712       ++s;
00713     }
00714 # endif /* !defined(OS2) && !defined(MSDOS) */
00715 
00716   return s;
00717 }
00718 
00719 void checkUngetc (int c, FILE *f)
00720 {
00721   int res;
00722 
00723   llassert (c != EOF);
00724   res = ungetc (c, f);
00725   llassert (res == c);
00726 }
00727 
00728 bool isHeaderFile (cstring fname)
00729 {
00730   char *ext = filenameExtension (cstring_toCharsSafe (fname));
00731   
00732   return (mstring_equal (ext, ".h")
00733           || mstring_equal (ext, ".H")
00734           || mstring_equal (ext, ".lh"));
00735 }
00736 

Generated at Fri Nov 3 18:57:41 2000 for LCLint by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000