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

message.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 ** message.c
00026 */
00027 
00028 # include "lclintMacros.nf"
00029 # include "basic.h"
00030  
00031 /* patch for linux? solaris? */
00032 
00033 static char strbuf[64];
00034 static int modcode;
00035 
00036 typedef enum
00037 {
00038   XINVALID, 
00039   XCHAR, XSTRING, XSTRINGFREE, XTSTRINGFREE, XINT, XFLOAT, XBOOL, XUENTRY,
00040   XPERCENT, XCTYPE, XPLURAL, XREPREFIX, XFILELOC
00041 } ccode;
00042 
00043 /* char *s, anytype v */
00044 /*@notfunction@*/
00045 # define GETPRINTF(s,v) (sprintf (strbuf, s, v), mstring_copy (strbuf))
00046 
00047 /*
00048 ** returns control code indicated by *c, and
00049 ** advances *c to next character.
00050 */
00051 
00052 static ccode
00053   identify_control (char **s)
00054 {
00055   char c;
00056 
00057   modcode = 0;
00058 
00059   c = **s;
00060   if (c == '\0')
00061     {
00062       return (XINVALID);
00063     }
00064 
00065   if (c >= '0' && c <= '9')
00066     {
00067       modcode = getInt (s);
00068     }
00069 
00070   c = **s;
00071 
00072   (*s)++;
00073 
00074  /*
00075  ** handle single-char codes
00076  */
00077 
00078   switch (c)
00079     {
00080     case '%':
00081       return (XPERCENT);
00082     case 'h':
00083     case 'c':
00084       return (XCHAR);
00085     case 's':
00086       return (XSTRING);
00087     case 'q':
00088       return (XSTRINGFREE);
00089     case 'x':
00090       return (XSTRINGFREE);
00091     case 'd':
00092       return (XINT);
00093     case 'u':
00094       return (XINT); /* unsigned */
00095     case 'w':
00096       return (XINT); /* unsigned long */
00097     case 'f':
00098       return (XFLOAT);
00099     case 'b':
00100       return (XBOOL);
00101     case 't':
00102       return (XCTYPE);
00103     case 'l':
00104       return (XFILELOC);
00105     case 'p':
00106       return (XPLURAL);
00107     case 'r':
00108       return (XREPREFIX);
00109     default:
00110       llcontbug (message ("Message: invalid code: %h (%s)", c, 
00111                           cstring_fromChars (*s)));
00112       return (XINVALID);
00113     }
00114 }
00115 
00116 /*
00117 ** message
00118 **
00119 ** returns a cstring containing the message, as formated by s.
00120 **
00121 ** the format codes are similar to printf:
00122 **
00123 **         %s    cstring (don't free after print)
00124 **         %q    cstring (free after print)
00125 **         %d    int
00126 **         %f    float
00127 **         %b    bool     (uses bool_unparse)
00128 **         %u    uentry
00129 **         %l    fileloc
00130 **         %t    ctype
00131 */
00132 
00133 
00134 # if USEVARARGS
00135 cstring
00136 message (fmt, va_alist)
00137      char *fmt;
00138      va_dcl
00139 # else
00140 /*@messagelike@*/ /*@only@*/ cstring
00141 message (/*@temp@*/ char *fmt, ...)
00142 # endif
00143 {
00144   char c;
00145   int lastint = 0;
00146   char *ret = mstring_createEmpty ();
00147   char *ofmt = fmt;
00148   va_list pvar;
00149 
00150 # if USEVARARGS
00151   va_start (pvar);
00152 # else
00153   va_start (pvar, fmt);
00154 # endif  
00155 
00156   while ((c = *fmt++) != '\0')
00157     {
00158       if (c == '%')
00159         {
00160           /*@-loopswitchbreak@*/
00161 
00162           switch (identify_control (&fmt))
00163             {
00164             case XPERCENT:
00165               {
00166                 ret = mstring_concatFree1 (ret, "%");
00167                 break;
00168               }
00169             case XCHAR:
00170               {
00171                 /*
00172                 ** some systems don't handle char va_arg correctly, so it must be
00173                 ** passed as an int here
00174                 */
00175 
00176                 char lc = (char) va_arg (pvar, int);
00177 
00178                 ret = mstring_append (ret, lc);
00179                 break;
00180               }
00181             case XSTRING:
00182               {
00183                 cstring s = va_arg (pvar, cstring);
00184                 
00185                 if (modcode != 0)
00186                   {
00187                     ret = mstring_concatFree (ret, cstring_toCharsSafe 
00188                                           (cstring_fill (s, modcode)));
00189                   }
00190                 else
00191                   {
00192                     if (cstring_isDefined (s))
00193                       {
00194                         ret = mstring_concatFree1 (ret, cstring_toCharsSafe (s));
00195                       }
00196                   }
00197               }
00198               break;
00199             case XSTRINGFREE:
00200             case XTSTRINGFREE:
00201               {
00202                 cstring s = va_arg (pvar, cstring);
00203                 
00204                 if (modcode != 0)
00205                   {
00206                     ret = mstring_concatFree (ret, cstring_toCharsSafe 
00207                                               (cstring_fill (s, modcode)));
00208                   }
00209                 else
00210                   {
00211                     if (cstring_isDefined (s))
00212                       {
00213                         ret = mstring_concatFree 
00214                           (ret, cstring_toCharsSafe (s));
00215                       }
00216                   }
00217               }
00218               break;
00219             case XREPREFIX:
00220               lastint = va_arg (pvar, int);
00221 
00222               if (lastint != 0)
00223                 {
00224                   ret = mstring_concatFree1 (ret, "re");
00225                 }
00226               break;
00227             case XPLURAL:
00228               if (lastint != 1)
00229                 {
00230                   ret = mstring_concatFree1 (ret, "s");
00231                 }
00232               break;
00233             case XINT:
00234               lastint = va_arg (pvar, int);
00235               ret = mstring_concatFree (ret, GETPRINTF ("%d", lastint));
00236               break;
00237             case XFLOAT:
00238               ret = mstring_concatFree (ret, GETPRINTF ("%e", va_arg (pvar, double)));
00239               break;
00240             case XBOOL:
00241               ret = mstring_concatFree1 (ret, cstring_toCharsSafe 
00242                                     (bool_unparse (va_arg (pvar, bool))));
00243               break;
00244             case XUENTRY:
00245               ret = mstring_concatFree (ret, cstring_toCharsSafe 
00246                                    (uentry_unparse (va_arg (pvar, uentry))));
00247               break;
00248             case XCTYPE:
00249               /* cannot free ctype_unparse */
00250               ret = mstring_concatFree1 (ret, cstring_toCharsSafe 
00251                                    (ctype_unparse (va_arg (pvar, ctype)))); 
00252               break;
00253             case XFILELOC:
00254               ret = mstring_concatFree (ret, cstring_toCharsSafe 
00255                                    (fileloc_unparse (va_arg (pvar, fileloc))));
00256               break;
00257             case XINVALID:
00258             default:
00259               llcontbug (cstring_makeLiteral ("message: bad control flag"));
00260               fprintf (stdout, "\tFormat string: %s", ofmt);
00261             }
00262           /*@=loopswitchbreak@*/
00263         }
00264       else
00265         {
00266           ret = mstring_append (ret, c);
00267         }
00268     }
00269 
00270   va_end (pvar);
00271 
00272   /*
00273   ** cstring_fromChars returns the same storage (exposed)
00274   */
00275 
00276   /*@-mustfree@*/ return (cstring_fromChars (ret)); /*@=mustfree@*/
00277 }

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