LCOV - code coverage report
Current view: directory - frmts/grib/degrib18/degrib - myerror.c (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 244 71 29.1 %
Date: 2011-12-18 Functions: 12 4 33.3 %

       1                 : /*****************************************************************************
       2                 :  * myerror.c
       3                 :  *
       4                 :  * DESCRIPTION
       5                 :  *    This file contains the code to handle error messages.  Instead of simply
       6                 :  * printing the error to stdio, it allocates some memory and stores the
       7                 :  * message in it.  This is so that one can pass the error message back to
       8                 :  * Tcl/Tk or another GUI program when there is no stdio.
       9                 :  *    In addition a version of sprintf is provided which allocates memory for
      10                 :  * the calling routine, so that one doesn't have to guess the maximum bounds
      11                 :  * of the message.
      12                 :  *
      13                 :  * HISTORY
      14                 :  *  9/2002 Arthur Taylor (MDL / RSIS): Created.
      15                 :  * 12/2002 Rici Yu, Fangyu Chi, Mark Armstrong, & Tim Boyer
      16                 :  *         (RY,FC,MA,&TB): Code Review 2.
      17                 :  * 12/2005 AAT Added myWarn routines.
      18                 :  *
      19                 :  * NOTES
      20                 :  *   See Kernighan & Ritchie C book (2nd edition) page 156.
      21                 :  *****************************************************************************
      22                 :  */
      23                 : #include <stdarg.h>
      24                 : #include <stdlib.h>
      25                 : #include <string.h>
      26                 : #include "myassert.h"
      27                 : #include "myerror.h"
      28                 : #ifdef MEMWATCH
      29                 : #include "memwatch.h"
      30                 : #endif
      31                 : 
      32                 : /*****************************************************************************
      33                 :  * AllocSprintf() -- Arthur Taylor / MDL (Review 12/2002)
      34                 :  *
      35                 :  * PURPOSE
      36                 :  *   Based on minprintf (see K&R C book (2nd edition) page 156.  This code
      37                 :  * tries to provide some of the functionality of sprintf, while at the same
      38                 :  * time it handles the memory allocation.
      39                 :  *   In addition, it provides a %S option, which allows one to pass in an
      40                 :  * array of strings, and get back a comma delimited string.
      41                 :  *
      42                 :  * ARGUMENTS
      43                 :  *     Ptr = An array of data that is of size LenBuff. (Input/Output)
      44                 :  * LenBuff = The allocated length of Ptr. (Input/Output)
      45                 :  *     fmt = Format similar to the one used by sprintf to define how to
      46                 :  *           print the message (Input)
      47                 :  *      ap = argument list initialized by a call to va_start.  Contains the
      48                 :  *           data needed by fmt. (Input)
      49                 :  *
      50                 :  * RETURNS: void
      51                 :  *
      52                 :  *  9/2002 Arthur Taylor (MDL/RSIS): Created.
      53                 :  * 12/2002 (RY,FC,MA,&TB): Code Review.
      54                 :  * 12/2002 AAT: Fixed the mallocSprintf ("") error.
      55                 :  *  2/2003 AAT: increased bufpart[80] to bufpart[330] because the largest
      56                 :  *         64 bit double is: +1.7E+308, and I want 20 "slots" for stuff
      57                 :  *         after the decimal place. There is the possibility of "Long
      58                 :  *         doubles" (80 bits) which would have a max of: +3.4E+4932, but
      59                 :  *         that is excessive for now.
      60                 :  *  2/2004 AAT: if lenBuff != 0, switch from ipos-- to strlen (buffer);
      61                 :  *  3/2004 AAT: Added %c option.
      62                 :  * 11/2005 AAT: Added %e option.
      63                 :  *  1/2006 AAT: Found a bug with multiple errSprintf.  Doesn't seem to be
      64                 :  *              able to handle lenBuff > strlen(buffer) when procedure is
      65                 :  *              first called.  Something like format = "aaa%s", lenBuff = 3,
      66                 :  *              buff = 'n' would result in 'naaa__<string>', instead of
      67                 :  *              'naaa<string>'.  Simple solution set lenBuff = strlen (buff).
      68                 :  *              better solution: Maybe calculate correct place for ipos
      69                 :  *              before switch.
      70                 :  *
      71                 :  * NOTES
      72                 :  * Supported formats:
      73                 :  *  %0.4f => float, double
      74                 :  *  %03d %ld %10ld => int, sInt4.
      75                 :  *  %s => Null terminated char string. (no range specification)
      76                 :  *  %S => take a char ** and turn it into a comma delimited string.
      77                 :  *
      78                 :  * Assumes that no individual float or int will be more than 80 characters
      79                 :  * Assumes that no % option is more than 20 char.
      80                 :  *****************************************************************************
      81                 :  */
      82              56 : static void AllocSprintf (char **Ptr, size_t *LenBuff, const char *fmt,
      83                 :                           va_list ap)
      84                 : {
      85              56 :    char *buffer = *Ptr; /* Local copy of Ptr. */
      86              56 :    size_t lenBuff = *LenBuff; /* Local copy of LenBuff. */
      87                 :    const char *p;       /* Points to % char in % option. */
      88                 :    const char *p1;      /* Points to end of % option. */
      89                 :    char bufpart[330];   /* Used for formating the int / float options. */
      90                 :    char format[20];     /* Used to store the % option. */
      91                 :    char *sval;          /* For pulling strings off va_list. */
      92                 :    char **Sval;         /* For pulling lists of strings off va_list. */
      93                 :    size_t slen;         /* Length of used part of temp. */
      94                 :    char f_inLoop;       /* Flag to state whether we got into %S , loop. */
      95                 :    char flag;           /* If they have a l,L,h in string. */
      96                 :    /* size_t ipos = *LenBuff; *//* The current index to start storing data. */
      97                 :    size_t ipos;         /* The current index to start storing data. */
      98                 :    int c_type;          /* Used when handling %c option. */
      99                 : 
     100                 :    myAssert (sizeof (char) == 1);
     101                 : 
     102              56 :    if ((fmt == NULL) || (strlen (fmt) == 0)) {
     103               0 :       return;
     104                 :    }
     105              56 :    p = fmt;
     106                 :    /* If lenBuff = 0, then make room for the '\0' character. */
     107              56 :    if (lenBuff == 0) {
     108              56 :       lenBuff++;
     109              56 :       buffer = (char *) realloc ((void *) buffer, lenBuff);
     110                 :       /* Added following 1 line on 1/2006 */
     111              56 :       ipos = 0;
     112                 :    } else {
     113                 :       /* Added following 3 lines on 1/2006 */
     114               0 :       myAssert (lenBuff >= strlen (buffer) + 1);
     115               0 :       lenBuff = strlen (buffer) + 1;
     116               0 :       ipos = lenBuff - 1;
     117                 : /*     ipos = strlen (buffer); */
     118                 :    }
     119             268 :    while (p < fmt + strlen (fmt)) {
     120             188 :       p1 = p;
     121             188 :       p = strchr (p1, '%');
     122                 :       /* Handle simple case when no more % in format string. */
     123             188 :       if (p == NULL) {
     124                 :          /* No more format strings; copy rest of format and return */
     125              32 :          lenBuff += strlen (p1);
     126              32 :          buffer = (char *) realloc ((void *) buffer, lenBuff);
     127              32 :          strcpy (buffer + ipos, p1);
     128              32 :          goto done;
     129                 :       }
     130                 :       /* Handle data up to the current % in format string. */
     131             156 :       lenBuff += p - p1;
     132             156 :       buffer = (char *) realloc ((void *) buffer, lenBuff);
     133             156 :       strncpy (buffer + ipos, p1, p - p1);
     134             156 :       ipos = lenBuff - 1;
     135                 :       /* Start dealing with % of format. */
     136             156 :       p1 = p + strspn (p + 1, "0123456789.");
     137             156 :       p1++;
     138                 :       /* p1 points to first letter after %. */
     139             156 :       switch (*p1) {
     140                 :          case 'h':
     141                 :          case 'l':
     142                 :          case 'L':
     143               0 :             flag = *p1;
     144               0 :             p1++;
     145               0 :             break;
     146                 :          case '\0':
     147                 :             /* Handle improper use of '%' for example: '%##' */
     148               0 :             lenBuff += p1 - p - 1;
     149               0 :             buffer = (char *) realloc ((void *) buffer, lenBuff);
     150               0 :             strncpy (buffer + ipos, p + 1, p1 - p - 1);
     151               0 :             goto done;
     152                 :          default:
     153             156 :             flag = ' ';
     154                 :       }
     155             156 :       if ((p1 - p + 1) > (int) (sizeof (format)) - 1) {
     156                 :          /* Protect against overflow of format string. */
     157               0 :          lenBuff += p1 - p + 1;
     158               0 :          buffer = (char *) realloc ((void *) buffer, lenBuff);
     159               0 :          strncpy (buffer + ipos, p, p1 - p + 1);
     160               0 :          ipos = lenBuff - 1;
     161                 :       } else {
     162             156 :          strncpy (format, p, p1 - p + 1);
     163             156 :          format[p1 - p + 1] = '\0';
     164             156 :          switch (*p1) {
     165                 :             case 'd':
     166              40 :                switch (flag) {
     167                 :                   case 'l':
     168                 :                   case 'L':
     169               0 :                      sprintf (bufpart, format, va_arg (ap, sInt4));
     170               0 :                      break;
     171                 :                      /* 
     172                 :                       * gcc warning for 'h': "..." promotes short int to
     173                 :                       * int.  Could get rid of 'h' option but decided to
     174                 :                       * leave it in since we might have a different
     175                 :                       * compiler.
     176                 :                       */
     177                 : /*
     178                 :               case 'h':
     179                 :                 sprintf (bufpart, format, va_arg(ap, short int));
     180                 :                 break;
     181                 : */
     182                 :                   default:
     183              40 :                      sprintf (bufpart, format, va_arg (ap, int));
     184                 :                }
     185              40 :                slen = strlen (bufpart);
     186              40 :                lenBuff += slen;
     187              40 :                buffer = (char *) realloc ((void *) buffer, lenBuff);
     188              40 :                strncpy (buffer + ipos, bufpart, slen);
     189              40 :                ipos = lenBuff - 1;
     190              40 :                break;
     191                 :             case 'f':
     192               0 :                sprintf (bufpart, format, va_arg (ap, double));
     193               0 :                slen = strlen (bufpart);
     194               0 :                lenBuff += slen;
     195               0 :                buffer = (char *) realloc ((void *) buffer, lenBuff);
     196               0 :                strncpy (buffer + ipos, bufpart, slen);
     197               0 :                ipos = lenBuff - 1;
     198               0 :                break;
     199                 :             case 'e':
     200               0 :                sprintf (bufpart, format, va_arg (ap, double));
     201               0 :                slen = strlen (bufpart);
     202               0 :                lenBuff += slen;
     203               0 :                buffer = (char *) realloc ((void *) buffer, lenBuff);
     204               0 :                strncpy (buffer + ipos, bufpart, slen);
     205               0 :                ipos = lenBuff - 1;
     206               0 :                break;
     207                 :             case 'g':
     208               0 :                sprintf (bufpart, format, va_arg (ap, double));
     209               0 :                slen = strlen (bufpart);
     210               0 :                lenBuff += slen;
     211               0 :                buffer = (char *) realloc ((void *) buffer, lenBuff);
     212               0 :                strncpy (buffer + ipos, bufpart, slen);
     213               0 :                ipos = lenBuff - 1;
     214               0 :                break;
     215                 :             case 'c':
     216               0 :                c_type = va_arg (ap, int);
     217               0 :                lenBuff += 1;
     218               0 :                buffer = (char *) realloc ((void *) buffer, lenBuff);
     219               0 :                buffer[ipos] = (char) c_type;
     220               0 :                buffer[ipos + 1] = '\0';
     221               0 :                ipos = lenBuff - 1;
     222               0 :                break;
     223                 :             case 's':
     224             116 :                if ((p1 - p) == 1) {
     225             116 :                   sval = va_arg (ap, char *);
     226                 : /*    printf (":: sval :: '%s'\n", sval);*/
     227             116 :                   slen = strlen (sval);
     228             116 :                   lenBuff += slen;
     229             116 :                   buffer = (char *) realloc ((void *) buffer, lenBuff);
     230             116 :                   strncpy (buffer + ipos, sval, slen);
     231             116 :                   ipos = lenBuff - 1;
     232             116 :                   break;
     233                 :                }
     234                 :                /* Intentionally fall through. */
     235                 :             case 'S':
     236               0 :                if ((p1 - p) == 1) {
     237               0 :                   f_inLoop = 0;
     238               0 :                   for (Sval = va_arg (ap, char **); *Sval; Sval++) {
     239               0 :                      slen = strlen (*Sval);
     240               0 :                      lenBuff += slen + 1;
     241               0 :                      buffer = (char *) realloc ((void *) buffer, lenBuff);
     242               0 :                      strcpy (buffer + ipos, *Sval);
     243               0 :                      strcat (buffer + ipos + slen, ",");
     244               0 :                      ipos = lenBuff - 1;
     245               0 :                      f_inLoop = 1;
     246                 :                   }
     247               0 :                   if (f_inLoop) {
     248               0 :                      lenBuff--;
     249               0 :                      buffer[lenBuff] = '\0';
     250               0 :                      ipos = lenBuff - 1;
     251                 :                   }
     252               0 :                   break;
     253                 :                }
     254                 :                /* Intentionally fall through. */
     255                 :             default:
     256               0 :                lenBuff += p1 - p;
     257               0 :                buffer = (char *) realloc ((void *) buffer, lenBuff);
     258               0 :                strncpy (buffer + ipos, p + 1, p1 - p);
     259               0 :                ipos = lenBuff - 1;
     260                 :          }
     261                 :       }
     262             156 :       p = p1 + 1;
     263                 :    }
     264                 :  done:
     265              56 :    buffer[lenBuff - 1] = '\0';
     266              56 :    *Ptr = buffer;
     267              56 :    *LenBuff = lenBuff;
     268                 : }
     269                 : 
     270                 : /*****************************************************************************
     271                 :  * mallocSprintf() -- Arthur Taylor / MDL (Review 12/2002)
     272                 :  *
     273                 :  * PURPOSE
     274                 :  *   This is a front end for AllocSprintf, when you want to malloc memory.
     275                 :  * In other words when the pointer is not pointing to anything in particular.
     276                 :  * It allocates the memory, prints the message, and then sets Ptr to point to
     277                 :  * it.
     278                 :  *
     279                 :  * ARGUMENTS
     280                 :  * Ptr = Place to point to new memory which contains the message (Output)
     281                 :  * fmt = Format similar to the one used by sprintf to define how to print the
     282                 :  *       message (Input)
     283                 :  *
     284                 :  * RETURNS: void
     285                 :  *
     286                 :  *  9/2002 Arthur Taylor (MDL/RSIS): Created.
     287                 :  * 12/2002 (RY,FC,MA,&TB): Code Review.
     288                 :  *
     289                 :  * NOTES
     290                 :  * Supported formats:  See AllocSprintf
     291                 :  *****************************************************************************
     292                 :  */
     293               8 : void mallocSprintf (char **Ptr, const char *fmt, ...)
     294                 : {
     295                 :    va_list ap;          /* Contains the data needed by fmt. */
     296               8 :    size_t buff_len = 0; /* Allocated length of buffer. */
     297                 : 
     298               8 :    *Ptr = NULL;
     299               8 :    if (fmt != NULL) {
     300               8 :       va_start (ap, fmt); /* make ap point to 1st unnamed arg. */
     301               8 :       AllocSprintf (Ptr, &buff_len, fmt, ap);
     302               8 :       va_end (ap);      /* clean up when done. */
     303                 :    }
     304               8 : }
     305                 : 
     306                 : /*****************************************************************************
     307                 :  * reallocSprintf() -- Arthur Taylor / MDL (Review 12/2002)
     308                 :  *
     309                 :  * PURPOSE
     310                 :  *   This is a front end for AllocSprintf, when you want to realloc memory.
     311                 :  * In other words, the pointer is pointing to NULL, or to some memory that
     312                 :  * you want to tack a message onto the end of.  It allocates extra memory,
     313                 :  * and prints the message.
     314                 :  *
     315                 :  *   KEY WORDS: "Tack a message onto the end of"
     316                 :  *
     317                 :  * ARGUMENTS
     318                 :  * Ptr = Pointer to memory to add the message to. (Input/Output)
     319                 :  * fmt = Format similar to the one used by sprintf to define how to print the
     320                 :  *       message (Input)
     321                 :  *
     322                 :  * RETURNS: void
     323                 :  *
     324                 :  *  9/2002 Arthur Taylor (MDL/RSIS): Created.
     325                 :  * 12/2002 (RY,FC,MA,&TB): Code Review.
     326                 :  *
     327                 :  * NOTES
     328                 :  * Supported formats:  See AllocSprintf
     329                 :  *****************************************************************************
     330                 :  */
     331              48 : void reallocSprintf (char **Ptr, const char *fmt, ...)
     332                 : {
     333                 :    va_list ap;          /* Contains the data needed by fmt. */
     334                 :    size_t buff_len;     /* Allocated length of buffer. */
     335                 : 
     336              48 :    if (fmt != NULL) {
     337              48 :       va_start (ap, fmt); /* make ap point to 1st unnamed arg. */
     338              48 :       if (*Ptr == NULL) {
     339              48 :          buff_len = 0;
     340                 :       } else {
     341               0 :          buff_len = strlen (*Ptr) + 1;
     342                 :       }
     343              48 :       AllocSprintf (Ptr, &buff_len, fmt, ap);
     344              48 :       va_end (ap);      /* clean up when done. */
     345                 :    }
     346              48 : }
     347                 : 
     348                 : /*****************************************************************************
     349                 :  * errSprintf() -- Arthur Taylor / MDL (Review 12/2002)
     350                 :  *
     351                 :  * PURPOSE
     352                 :  *   This uses AllocSprintf to generate a message, which it stores in a static
     353                 :  * variable.  If it is called with a (NULL), it returns the built up message,
     354                 :  * and resets its pointer to NULL.  The idea being that errors can be stacked
     355                 :  * up, and you pop them off when you need to report them.  The reporting could
     356                 :  * be done by printing them to stdio, or by passing them back to Tcl/Tk.
     357                 :  *   Note: It is the caller's responsibility to free the memory, and it is
     358                 :  * the caller's responsibility to make sure the last call to this is with
     359                 :  * (NULL), or else the memory won't get freed.
     360                 :  *
     361                 :  * ARGUMENTS
     362                 :  * fmt = Format similar to the one used by sprintf to define how to print the
     363                 :  *       message (Input)
     364                 :  *
     365                 :  * RETURNS: char *
     366                 :  *   if (fmt == NULL) returns built up string
     367                 :  *   else             returns NULL.
     368                 :  *
     369                 :  *  9/2002 Arthur Taylor (MDL/RSIS): Created.
     370                 :  * 12/2002 (RY,FC,MA,&TB): Code Review.
     371                 :  *
     372                 :  * NOTES
     373                 :  * Supported formats:  See AllocSprintf
     374                 :  *****************************************************************************
     375                 :  */
     376                 : /* Following 2 variables used in both errSprintf and preErrSprintf */
     377                 : static char *errBuffer = NULL; /* Stores the current built up message. */
     378                 : static size_t errBuff_len = 0; /* Allocated length of errBuffer. */
     379                 : 
     380               6 : char *errSprintf (const char *fmt, ...)
     381                 : {
     382                 :    va_list ap;          /* Contains the data needed by fmt. */
     383                 :    char *ans;           /* Pointer to the final message while we reset
     384                 :                          * buffer. */
     385                 : 
     386               6 :    if (fmt == NULL) {
     387               6 :       ans = errBuffer;
     388               6 :       errBuffer = NULL;
     389               6 :       errBuff_len = 0;
     390               6 :       return ans;
     391                 :    }
     392               0 :    va_start (ap, fmt);  /* make ap point to 1st unnamed arg. */
     393               0 :    AllocSprintf (&errBuffer, &errBuff_len, fmt, ap);
     394               0 :    va_end (ap);         /* clean up when done. */
     395               0 :    return NULL;
     396                 : }
     397                 : 
     398                 : /*****************************************************************************
     399                 :  * preErrSprintf() -- Arthur Taylor / MDL
     400                 :  *
     401                 :  * PURPOSE
     402                 :  *   This uses AllocSprintf to generate a message, which it prepends to the
     403                 :  * static variable used by errSprinf.  If it is called with a (NULL), it
     404                 :  * does nothing... Use errSprintf (NULL) to get the message, and reset the
     405                 :  * pointer to NULL.
     406                 :  *   The idea here is that we want to prepend calling info when there was an
     407                 :  * error.
     408                 :  *   Note: It is the caller's responsibility to free the memory, by
     409                 :  * eventually making one last call to errSprintf (NULL) and freeing the
     410                 :  * returned memory.
     411                 :  *
     412                 :  * ARGUMENTS
     413                 :  * fmt = Format similar to the one used by sprintf to define how to print the
     414                 :  *       message (Input)
     415                 :  *
     416                 :  * RETURNS: void
     417                 :  *
     418                 :  * 12/2002 Arthur Taylor (MDL/RSIS): Created.
     419                 :  *
     420                 :  * NOTES
     421                 :  * Supported formats:  See AllocSprintf
     422                 :  *****************************************************************************
     423                 :  */
     424               0 : void preErrSprintf (const char *fmt, ...)
     425                 : {
     426               0 :    char *preBuffer = NULL; /* Stores the prepended message. */
     427               0 :    size_t preBuff_len = 0; /* Allocated length of preBuffer. */
     428                 :    va_list ap;          /* Contains the data needed by fmt. */
     429                 : 
     430                 :    myAssert (sizeof (char) == 1);
     431                 : 
     432               0 :    if (fmt == NULL) {
     433               0 :       return;
     434                 :    }
     435               0 :    va_start (ap, fmt);  /* make ap point to 1st unnamed arg. */
     436               0 :    AllocSprintf (&preBuffer, &preBuff_len, fmt, ap);
     437               0 :    va_end (ap);         /* clean up when done. */
     438                 : 
     439               0 :    if (errBuff_len != 0) {
     440                 :       /* Increase preBuffer to have enough room for errBuffer */
     441               0 :       preBuff_len += errBuff_len;
     442               0 :       preBuffer = (char *) realloc ((void *) preBuffer, preBuff_len);
     443                 :       /* concat errBuffer to end of preBuffer, and free errBuffer */
     444               0 :       strcat (preBuffer, errBuffer);
     445               0 :       free (errBuffer);
     446                 :    }
     447                 :    /* Finally point errBuffer to preBuffer, and update errBuff_len. */
     448               0 :    errBuffer = preBuffer;
     449               0 :    errBuff_len = preBuff_len;
     450               0 :    return;
     451                 : }
     452                 : 
     453                 : /*****************************************************************************
     454                 :  * _myWarn() -- Arthur Taylor / MDL
     455                 :  *
     456                 :  * PURPOSE
     457                 :  *   This is an update to my errSprintf routines.  This procedure uses
     458                 :  * AllocSprintf to generate a message, which it stores in a static variable.
     459                 :  * It allows for prepending or appending error messages, and allows one to
     460                 :  * set the error level of a message.
     461                 :  *
     462                 :  * ARGUMENTS
     463                 :  * f_errCode = 0 => append notation msg, 1 => append warning msg
     464                 :  *             2 => append error msg, 3 => prepend notation msg
     465                 :  *             4 => prepend warning msg, 5 => prepend error msg (Input)
     466                 :  *       fmt = Format to define how to print the msg (Input)
     467                 :  *        ap = The arguments for the message. (Input)
     468                 :  *
     469                 :  * RETURNS: void
     470                 :  *
     471                 :  * 12/2005 Arthur Taylor (MDL): Created.
     472                 :  *
     473                 :  * NOTES:
     474                 :  *****************************************************************************
     475                 :  */
     476                 : /* Following variables used in the myWarn routines */
     477                 : static char *warnBuff = NULL; /* Stores the current built up message. */
     478                 : static size_t warnBuffLen = 0; /* Allocated length of warnBuff. */
     479                 : static sChar warnLevel = -1; /* Current warning level. */
     480                 : static uChar warnOutType = 0; /* Output type as set in myWarnSet. */
     481                 : static uChar warnDetail = 0; /* Detail level as set in myWarnSet. */
     482                 : static uChar warnFileDetail = 0; /* Detail level as set in myWarnSet. */
     483                 : static FILE *warnFP = NULL; /* Warn File as set in myWarnSet. */
     484                 : 
     485               0 : static void _myWarn (uChar f_errCode, const char *fmt, va_list ap)
     486                 : {
     487               0 :    char *buff = NULL;   /* Stores the message. */
     488               0 :    size_t buffLen = 0;  /* Allocated length of buff. */
     489               0 :    uChar f_prepend = 0; /* Flag to prepend (or not) the message. */
     490               0 :    uChar f_filePrt = 1; /* Flag to print to file. */
     491               0 :    uChar f_memPrt = 1;  /* Flag to print to memory. */
     492                 : 
     493               0 :    if (fmt == NULL) {
     494               0 :       return;
     495                 :    }
     496               0 :    if (f_errCode > 5) {
     497               0 :       f_errCode = 0;
     498                 :    }
     499               0 :    if (f_errCode > 2) {
     500               0 :       f_errCode -= (uChar) 3;
     501               0 :       f_prepend = 1;
     502                 :    }
     503                 :    /* Update the warning level */
     504               0 :    if (f_errCode > warnLevel) {
     505               0 :       warnLevel = f_errCode;
     506                 :    }
     507                 : 
     508                 :    /* Check if the warnDetail level allows this message. */
     509               0 :    if ((warnOutType >= 4) ||
     510               0 :        (warnDetail == 2) || ((warnDetail == 1) && (f_errCode < 2))) {
     511               0 :       f_memPrt = 0;
     512                 :    }
     513               0 :    if ((warnOutType == 0) ||
     514               0 :        (warnFileDetail == 2) || ((warnFileDetail == 1) && (f_errCode < 2))) {
     515               0 :       if (!f_memPrt) {
     516               0 :          return;
     517                 :       }
     518               0 :       f_filePrt = 0;
     519                 :    }
     520                 : 
     521               0 :    AllocSprintf (&buff, &buffLen, fmt, ap);
     522                 : 
     523                 :    /* Handle the file writing. */
     524               0 :    if (f_filePrt) {
     525               0 :       fprintf (warnFP, "%s", buff);
     526                 :    }
     527                 :    /* Handle the memory writing.  */
     528               0 :    if (f_memPrt) {
     529               0 :       if (f_prepend) {
     530               0 :          if (warnBuffLen != 0) {
     531                 :             /* Add warnBuff to end of buff, and free warnBuff. */
     532               0 :             buffLen += warnBuffLen;
     533                 :             myAssert (sizeof (char) == 1);
     534               0 :             buff = (char *) realloc (buff, buffLen);
     535               0 :             strcat (buff, warnBuff);
     536               0 :             free (warnBuff);
     537                 :          }
     538                 :          /* Point warnBuff to buff. */
     539               0 :          warnBuff = buff;
     540               0 :          warnBuffLen = buffLen;
     541                 :       } else {
     542               0 :          if (warnBuffLen == 0) {
     543               0 :             warnBuff = buff;
     544               0 :             warnBuffLen = buffLen;
     545                 :          } else {
     546               0 :             warnBuffLen += buffLen;
     547                 :             myAssert (sizeof (char) == 1);
     548               0 :             warnBuff = (char *) realloc (warnBuff, warnBuffLen);
     549               0 :             strcat (warnBuff, buff);
     550               0 :             free (buff);
     551                 :          }
     552                 :       }
     553                 :    }
     554                 : }
     555                 : 
     556                 : /*****************************************************************************
     557                 :  * myWarn() -- Arthur Taylor / MDL
     558                 :  *
     559                 :  * PURPOSE
     560                 :  *   This does the transformation of the "..." parameters, and calls _myWarn.
     561                 :  * This was broken out when we started to implement myWarnRet, so we had two
     562                 :  * ways to call _myWarn.  A complicated way (myWarnRet), and a simpler way
     563                 :  * (myWarn).  After creating the myWarnW# #defines, thought to depricate use
     564                 :  * of myWarn by making it static.  Still need it, because myWarnRet uses it.
     565                 :  *
     566                 :  * ARGUMENTS
     567                 :  * f_errCode = 0 => append notation msg, 1 => append warning msg
     568                 :  *             2 => append error msg, 3 => prepend notation msg
     569                 :  *             4 => prepend warning msg, 5 => prepend error msg (Input)
     570                 :  *       fmt = Format to define how to print the msg (Input)
     571                 :  *       ... = The actual message arguments. (Input)
     572                 :  *
     573                 :  * RETURNS: void
     574                 :  *
     575                 :  * 12/2005 Arthur Taylor (MDL): Created.
     576                 :  *
     577                 :  * NOTES:
     578                 :  *****************************************************************************
     579                 :  */
     580               0 : static void myWarn (uChar f_errCode, const char *fmt, ...)
     581                 : {
     582                 :    va_list ap;          /* Contains the data needed by fmt. */
     583                 : 
     584                 :    /* Create the message in buff. */
     585               0 :    va_start (ap, fmt);  /* make ap point to 1st unnamed arg. */
     586               0 :    _myWarn (f_errCode, fmt, ap);
     587               0 :    va_end (ap);         /* clean up when done. */
     588               0 : }
     589                 : 
     590                 : /*****************************************************************************
     591                 :  * myWarnRet() -- Arthur Taylor / MDL
     592                 :  *
     593                 :  * PURPOSE
     594                 :  *   This does the transformation of the "..." parameters, and calls _myWarn.
     595                 :  * This was created, so that the user could pass in where (file and line
     596                 :  * number) the error took place, and get a uniform handling of the file and
     597                 :  * line numbers.  In addition the user could pass in a value for the procedure
     598                 :  * to return, which allows the user to have something like:
     599                 :  *   "return myWarnW2 (-1, "foobar\n");"
     600                 :  * Which after the #define is evaluated becomes:
     601                 :  *   "return myWarnRet (1, -1, __FILE__, __LINE__, "foobar\n");
     602                 :  *
     603                 :  * Without myWarnRet, one would need something like:
     604                 :  *   "myWarn (1, "(%s line %d) foobar\n", __FILE__, __LINE__);"
     605                 :  *   "return (-1);
     606                 :  * Trying to come up with a #define to make that easier on the user was
     607                 :  * difficult.  The first attempt was:
     608                 :  *   #define myWarnLine myWarn(1, "(%s, line %d) " __FILE__, __LINE__); myWarn
     609                 :  * but this had difficulties with "if () myWarnLine" since it became two
     610                 :  * statements, which could confuse the use of {}.  A better solition was:
     611                 :  *   #define myWarnLineW1(f) myWarnLine (1, __FILE__, __LINE__, f)
     612                 :  * Particularly since the user didn't have to remember that Warn is flag of 1,
     613                 :  * and error is flag of 2.  Since I already had to create myWarnW# #defines,
     614                 :  * it was easy to add the user specified return values.
     615                 :  *
     616                 :  * ARGUMENTS
     617                 :  *  f_errCode = 0 => append notation msg, 1 => append warning msg
     618                 :  *              2 => append error msg, 3 => prepend notation msg
     619                 :  *              4 => prepend warning msg, 5 => prepend error msg (Input)
     620                 :  * appErrCode = User defined error code for myWarnRet to return.
     621                 :  *       file = Filename that the call to myWarnRet was in. (Input)
     622                 :  *              If NULL, then it skips the __FILE__, __LINE__ print routine.
     623                 :  *    lineNum = Line number of call to myWarnRet. (Input)
     624                 :  *        fmt = Format to define how to print the msg (Input)
     625                 :  *        ... = The actual message arguments. (Input)
     626                 :  *
     627                 :  * RETURNS: int
     628                 :  *   The value of appErrCode.
     629                 :  *
     630                 :  * 12/2005 Arthur Taylor (MDL): Created.
     631                 :  *
     632                 :  * NOTES:
     633                 :  *   Is in "Quiet" mode if "file" is NULL (no __FILE__, __LINE__ prints)
     634                 :  *****************************************************************************
     635                 :  */
     636               0 : int myWarnRet (uChar f_errCode, int appErrCode, const char *file,
     637                 :                int lineNum, const char *fmt, ...)
     638                 : {
     639                 :    va_list ap;          /* Contains the data needed by fmt. */
     640                 : 
     641               0 :    if (fmt != NULL) {
     642               0 :       if (file != NULL) {
     643               0 :          myWarn (f_errCode, "(%s, line %d) ", file, lineNum);
     644                 :       }
     645                 :       /* Create the message in buff. */
     646               0 :       va_start (ap, fmt); /* make ap point to 1st unnamed arg. */
     647               0 :       _myWarn (f_errCode, fmt, ap);
     648               0 :       va_end (ap);      /* clean up when done. */
     649               0 :    } else if (file != NULL) {
     650               0 :       myWarn (f_errCode, "(%s, line %d)\n", file, lineNum);
     651                 :    }
     652               0 :    return appErrCode;
     653                 : }
     654                 : 
     655                 : /*****************************************************************************
     656                 :  * myWarnSet() -- Arthur Taylor / MDL
     657                 :  *
     658                 :  * PURPOSE
     659                 :  *   This sets warnOutType, warnDetail, and warnFile for myWarn.
     660                 :  *
     661                 :  * ARGUMENTS
     662                 :  *    f_outType = 0 => memory, 1 => memory + stdout, 2 => memory + stderr,
     663                 :  *                3 => memory + warnFile, 4 => stdout, 5 => stderr,
     664                 :  *                6 => warnFile. (Input)
     665                 :  *     f_detail = 0 => report all, 1 => report errors, 2 => silent. (Input)
     666                 :  * f_fileDetail = 0 => report all, 1 => report errors, 2 => silent. (Input)
     667                 :  *     warnFile = An already opened alternate file to log errors to. (Input)
     668                 :  *
     669                 :  * RETURNS: void
     670                 :  *
     671                 :  * 12/2005 Arthur Taylor (MDL): Created.
     672                 :  *
     673                 :  * NOTES:
     674                 :  *   The reason someone may want memory + warnFile is so that they can log the
     675                 :  * errors in a logFile, but still have something come to stdout.
     676                 :  *****************************************************************************
     677                 :  */
     678               0 : void myWarnSet (uChar f_outType, uChar f_detail, uChar f_fileDetail,
     679                 :                 FILE *warnFile)
     680                 : {
     681               0 :    if (f_outType > 6) {
     682               0 :       f_outType = 0;
     683                 :    }
     684               0 :    if (f_detail > 2) {
     685               0 :       f_detail = 0;
     686                 :    }
     687               0 :    warnOutType = f_outType;
     688               0 :    warnDetail = f_detail;
     689               0 :    warnFileDetail = f_fileDetail;
     690               0 :    if ((f_outType == 1) || (f_outType == 4)) {
     691               0 :       warnFP = stdout;
     692               0 :    } else if ((f_outType == 2) || (f_outType == 5)) {
     693               0 :       warnFP = stderr;
     694               0 :    } else if ((f_outType == 3) || (f_outType == 6)) {
     695               0 :       if (warnFile == NULL) {
     696               0 :          warnFP = stderr;
     697                 :       } else {
     698               0 :          warnFP = warnFile;
     699                 :       }
     700                 :    } else {
     701               0 :       warnFP = NULL;
     702                 :    }
     703               0 : }
     704                 : 
     705                 : /*****************************************************************************
     706                 :  * myWarnClear() -- Arthur Taylor / MDL
     707                 :  *
     708                 :  * PURPOSE
     709                 :  *   This clears the warning stack, returns what is on there in msg, resets
     710                 :  * the memory to NULL, and returns the error code.
     711                 :  *
     712                 :  * ARGUMENTS
     713                 :  *         msg = Whatever has been written to the warning memory
     714                 :  *               (NULL, or allocated memory) (Out)
     715                 :  * f_closeFile = flag to close the warnFile or not (Input)
     716                 :  *
     717                 :  * RETURNS: sChar
     718                 :  *   -1 means no messages in msg (msg should be null)
     719                 :  *    0 means upto notation msg in msg, but msg should not be null.
     720                 :  *    1 means upto warning messages in msg, msg should not be null.
     721                 :  *    2 means upto error messages in msg, msg should not be null.
     722                 :  *
     723                 :  * 12/2005 Arthur Taylor (MDL): Created.
     724                 :  *
     725                 :  * NOTES:
     726                 :  *****************************************************************************
     727                 :  */
     728               0 : sChar myWarnClear (char **msg, uChar f_closeFile)
     729                 : {
     730                 :    sChar ans;
     731                 : 
     732               0 :    *msg = warnBuff;
     733               0 :    warnBuff = NULL;
     734               0 :    warnBuffLen = 0;
     735               0 :    ans = warnLevel;
     736               0 :    warnLevel = -1;
     737               0 :    if (f_closeFile) {
     738               0 :       fclose (warnFP);
     739                 :    }
     740               0 :    return ans;
     741                 : }
     742                 : 
     743                 : /*****************************************************************************
     744                 :  * myWarnNotEmpty() -- Arthur Taylor / MDL
     745                 :  *
     746                 :  * PURPOSE
     747                 :  *   This returns whether the warning message is null or not.
     748                 :  *
     749                 :  * ARGUMENTS
     750                 :  *
     751                 :  * RETURNS: uChar
     752                 :  *   0 => msg == null, 1 => msg != null
     753                 :  *
     754                 :  * 12/2005 Arthur Taylor (MDL): Created.
     755                 :  *
     756                 :  * NOTES:
     757                 :  *****************************************************************************
     758                 :  */
     759               0 : uChar myWarnNotEmpty ()
     760                 : {
     761               0 :    return (uChar) ((warnBuff != NULL) ? 1 : 0);
     762                 : }
     763                 : 
     764                 : /*****************************************************************************
     765                 :  * myWarnLevel() -- Arthur Taylor / MDL
     766                 :  *
     767                 :  * PURPOSE
     768                 :  *   This returns the status of the warnLevel.
     769                 :  *
     770                 :  * ARGUMENTS
     771                 :  *
     772                 :  * RETURNS: sChar
     773                 :  *   -1 means no messages in msg (msg should be null)
     774                 :  *    0 means upto notation msg in msg, but msg should not be null.
     775                 :  *    1 means upto warning messages in msg, msg should not be null.
     776                 :  *    2 means upto error messages in msg, msg should not be null.
     777                 :  *
     778                 :  * 12/2005 Arthur Taylor (MDL): Created.
     779                 :  *
     780                 :  * NOTES:
     781                 :  *****************************************************************************
     782                 :  */
     783               0 : sChar myWarnLevel ()
     784                 : {
     785               0 :    return warnLevel;
     786                 : }
     787                 : 
     788                 : #ifdef TEST_MYERROR
     789                 : /*****************************************************************************
     790                 :  * The following 2 procedures are included only to test myerror.c, and only
     791                 :  * if TEST_MYERROR is defined.
     792                 :  *****************************************************************************
     793                 :  */
     794                 : 
     795                 : /*****************************************************************************
     796                 :  * checkAns() -- Arthur Taylor / MDL (Review 12/2002)
     797                 :  *
     798                 :  * PURPOSE
     799                 :  *   To verify that a test gives the expected result.
     800                 :  *
     801                 :  * ARGUMENTS
     802                 :  *  ptr = The results of the test. (Input)
     803                 :  *  Ans = An array of correct answers. (Input)
     804                 :  * test = Which test we are checking. (Input)
     805                 :  *
     806                 :  * RETURNS: void
     807                 :  *
     808                 :  *  9/2002 Arthur Taylor (MDL/RSIS): Created.
     809                 :  * 12/2002 (RY,FC,MA,&TB): Code Review.
     810                 :  *
     811                 :  * NOTES
     812                 :  *****************************************************************************
     813                 :  */
     814                 : static void checkAns (char *ptr, char **Ans, int test)
     815                 : {
     816                 :    if (ptr == NULL) {
     817                 :       printf ("-----Check test (%d)--(ptr == NULL)-----\n", test);
     818                 :       return;
     819                 :    }
     820                 :    if (strcmp (ptr, Ans[test]) != 0) {
     821                 :       printf ("-----Failed test %d-------\n", test);
     822                 :       printf ("%s %d =?= %s %d\n", ptr, strlen (ptr),
     823                 :               Ans[test], strlen (Ans[test]));
     824                 :    } else {
     825                 :       printf ("passed test %d\n", test);
     826                 :    }
     827                 : }
     828                 : 
     829                 : /*****************************************************************************
     830                 :  * main() -- Arthur Taylor / MDL (Review 12/2002)
     831                 :  *
     832                 :  * PURPOSE
     833                 :  *   To test reallocSprint, mallocSprint, and errSprintf, to make sure that
     834                 :  * they pass certain basic tests.  I will be adding more tests, as more bugs
     835                 :  * are found, and features added.
     836                 :  *
     837                 :  * ARGUMENTS
     838                 :  * argc = The number of arguments on the command line. (Input)
     839                 :  * argv = The arguments on the command line. (Input)
     840                 :  *
     841                 :  * RETURNS: int
     842                 :  *
     843                 :  *  9/2002 Arthur Taylor (MDL/RSIS): Created.
     844                 :  * 12/2002 (RY,FC,MA,&TB): Code Review.
     845                 :  *
     846                 :  * NOTES
     847                 :  *****************************************************************************
     848                 :  */
     849                 : int main (int argc, char **argv)
     850                 : {
     851                 :    char *ptr;
     852                 :    uChar warn;
     853                 :    static char *Cmd[] = { "configure", "inquire", "convert", NULL };
     854                 :    sInt4 li_temp = 100000L;
     855                 :    short int sect = 5;
     856                 :    char varName[] = "Helium is a gas";
     857                 :    sInt4 lival = 22;
     858                 :    char unit[] = "km", sval[] = "ans";
     859                 :    double dval = 2.71828;
     860                 : 
     861                 :    char *buffer = NULL;
     862                 :    short int ssect = 0;
     863                 :    char vvarName[] = "DataType";
     864                 :    sInt4 llival = 0;
     865                 :    char ssval[] = "Meteorological products";
     866                 : 
     867                 :    static char *Ans[] = { "S0 | DataType | 0 (Meteorological products)\n",
     868                 :       "<testing>", "<05><3.1415><D><20>",
     869                 :       "<configure,inquire,convert> ?options?",
     870                 :       "100000", "25.123", "02s", "01234567890123456789012345",
     871                 :       "25.123,05, hello world",
     872                 :       "This is a test 5... Here I am\n",
     873                 :       "Parse error Section 0\nErrorERROR: Problems opening c:--goober for "
     874                 :             "write.Projection code requires Earth with Rad = 6367.47 not "
     875                 :             "6400.010000",
     876                 :       "ERROR IS1 not labeled correctly. 5000000\n"
     877                 :             "Should be 1196575042 2 25\nERROR IS0 has unexpected values: "
     878                 :             "100000 100000 100000\n",
     879                 :       "S5 | Helium is a gas | 22 (ans)\nS5 | Helium is a gas | 22\n"
     880                 :             "S5 | Helium is a gas | 22 (ans (km))\nS5 | Helium is a gas | ans\n"
     881                 :             "S5 | Helium is a gas | 2.718280\nS5 | Helium is a gas | "
     882                 :             "2.718280 (km)\n",
     883                 :       "ERROR IS1 not labeled correctly. 5000000\n"
     884                 :             "Should be 1196575042 2 25\nERROR IS0 has unexpected values: "
     885                 :             "100000 100000 100000\n",
     886                 :       "5.670000e+001"
     887                 :    };
     888                 : 
     889                 : /* Test -2. (See if it can handle blank). */
     890                 :    mallocSprintf (&ptr, "");
     891                 :    free (ptr);
     892                 :    ptr = NULL;
     893                 : 
     894                 :    mallocSprintf (&ptr, " ");
     895                 :    free (ptr);
     896                 :    ptr = NULL;
     897                 : 
     898                 : 
     899                 : /* Test -1. (see if checkAns is ok) */
     900                 :    ptr = errSprintf (NULL);
     901                 :    checkAns (ptr, Ans, -1);
     902                 : 
     903                 : /* Test 0 */
     904                 :    reallocSprintf (&buffer, "S%d | %s | %ld (%s)\n", ssect, vvarName,
     905                 :                    llival, ssval);
     906                 :    checkAns (buffer, Ans, 0);
     907                 :    free (buffer);
     908                 : 
     909                 : /* Test 1. */
     910                 :    ptr = NULL;
     911                 :    reallocSprintf (&ptr, "<testing>");
     912                 :    checkAns (ptr, Ans, 1);
     913                 :    free (ptr);
     914                 : 
     915                 : /* Test 2. */
     916                 :    ptr = NULL;
     917                 :    reallocSprintf (&ptr, "<%02d><%.4f><%D><%ld>", 5, 3.1415, 20, 24);
     918                 :    checkAns (ptr, Ans, 2);
     919                 :    free (ptr);
     920                 : 
     921                 : /* Test 3. */
     922                 :    ptr = NULL;
     923                 :    reallocSprintf (&ptr, "<%S> ?options?", Cmd);
     924                 :    checkAns (ptr, Ans, 3);
     925                 :    free (ptr);
     926                 : 
     927                 : /* Test 4. */
     928                 :    ptr = NULL;
     929                 :    reallocSprintf (&ptr, "%ld", li_temp);
     930                 :    checkAns (ptr, Ans, 4);
     931                 :    free (ptr);
     932                 : 
     933                 : /* Test 5. */
     934                 :    ptr = NULL;
     935                 :    reallocSprintf (&ptr, "%.3f", 25.1234);
     936                 :    checkAns (ptr, Ans, 5);
     937                 :    free (ptr);
     938                 : 
     939                 : /* Test 6. */
     940                 :    ptr = NULL;
     941                 :    reallocSprintf (&ptr, "%02s", 25.1234);
     942                 :    checkAns (ptr, Ans, 6);
     943                 :    free (ptr);
     944                 : 
     945                 : /* Test 7. */
     946                 :    ptr = NULL;
     947                 :    reallocSprintf (&ptr, "%01234567890123456789012345");
     948                 :    checkAns (ptr, Ans, 7);
     949                 :    free (ptr);
     950                 : 
     951                 : /* Test 8. */
     952                 :    mallocSprintf (&ptr, "%.3f", 25.1234);
     953                 :    reallocSprintf (&ptr, ",%02d", 5);
     954                 :    reallocSprintf (&ptr, ", %s", "hello world");
     955                 :    checkAns (ptr, Ans, 8);
     956                 :    free (ptr);
     957                 :    ptr = NULL;
     958                 : 
     959                 : /* Test 9. */
     960                 :    errSprintf ("This is a test %d... ", 5);
     961                 :    errSprintf ("Here I am\n");
     962                 :    ptr = errSprintf (NULL);
     963                 :    checkAns (ptr, Ans, 9);
     964                 :    free (ptr);
     965                 : 
     966                 : /* Test 10. */
     967                 :    errSprintf ("Parse error Section 0\n%s", "Error");
     968                 :    errSprintf ("ERROR: Problems opening %s for write.", "c:--goober");
     969                 :    errSprintf ("Projection code requires Earth with Rad = 6367.47 not %f",
     970                 :                6400.01);
     971                 :    ptr = errSprintf (NULL);
     972                 :    checkAns (ptr, Ans, 10);
     973                 :    free (ptr);
     974                 : 
     975                 : /* Test 11. */
     976                 :    errSprintf ("ERROR IS1 not labeled correctly. %ld\n", 5000000L);
     977                 :    errSprintf ("Should be %ld %d %ld\n", 1196575042L, 2, 25);
     978                 :    errSprintf ("ERROR IS0 has unexpected values: %ld %ld %ld\n", li_temp,
     979                 :                li_temp, li_temp);
     980                 :    ptr = errSprintf (NULL);
     981                 :    checkAns (ptr, Ans, 11);
     982                 :    free (ptr);
     983                 : 
     984                 : /* Test 12. */
     985                 :    ptr = NULL;
     986                 :    reallocSprintf (&ptr, "S%d | %s | %ld (%s)\n", sect, varName, lival, sval);
     987                 :    reallocSprintf (&ptr, "S%d | %s | %ld\n", sect, varName, lival);
     988                 :    reallocSprintf (&ptr, "S%d | %s | %ld (%s (%s))\n", sect, varName, lival,
     989                 :                    sval, unit);
     990                 :    reallocSprintf (&ptr, "S%d | %s | %s\n", sect, varName, sval);
     991                 :    reallocSprintf (&ptr, "S%d | %s | %f\n", sect, varName, dval);
     992                 :    reallocSprintf (&ptr, "S%d | %s | %f (%s)\n", sect, varName, dval, unit);
     993                 :    checkAns (ptr, Ans, 12);
     994                 :    free (ptr);
     995                 : 
     996                 : /* Test 13. */
     997                 :    preErrSprintf ("Should be %ld %d %ld\n", 1196575042L, 2, 25);
     998                 :    errSprintf ("ERROR IS0 has unexpected values: %ld %ld %ld\n", li_temp,
     999                 :                li_temp, li_temp);
    1000                 :    preErrSprintf ("ERROR IS1 not labeled correctly. %ld\n", 5000000L);
    1001                 :    ptr = errSprintf (NULL);
    1002                 :    checkAns (ptr, Ans, 13);
    1003                 :    free (ptr);
    1004                 : 
    1005                 : /* Test 14. */
    1006                 :    ptr = NULL;
    1007                 :    reallocSprintf (&ptr, "%e", 56.7);
    1008                 :    checkAns (ptr, Ans, 14);
    1009                 :    free (ptr);
    1010                 : 
    1011                 :    myWarnSet (1, 0, 1, NULL);
    1012                 :    myWarnW2 (0, "This is a test of Warn\n");
    1013                 :    myWarnE2 (0, "This is a test of Err\n");
    1014                 :    myWarnQ2 (0, "This is a quiet note\n");
    1015                 :    myWarnPW2 (0, "This is a test2 of Error\n");
    1016                 :    myWarnW4 (0, "This is a test of WarnLnW3 %d %d\n", 10, 20);
    1017                 :    myWarnE3 (0, "This is a test of WarnLnE2 %d\n", 10);
    1018                 :    printf ("\tTest myWarnRet: %d\n", myWarnW1 (-1));
    1019                 :    printf ("\tTest myWarnRet: %d\n", myWarnE2 (-2, "Hello nurse\n"));
    1020                 :    if (myWarnNotEmpty ()) {
    1021                 :       ptr = NULL;
    1022                 :       warn = myWarnClear (&ptr, 0);
    1023                 :       printf ("WarnLevel=%d\n%s", warn, ptr);
    1024                 :       free (ptr);
    1025                 :    }
    1026                 : 
    1027                 :    return 0;
    1028                 : }
    1029                 : #endif

Generated by: LCOV version 1.7