#include <stdio.h>
#include "io_nc.h"   /* getc_nc(), getword_nc() */
/*****************************************************************************
*                                                                            *
*      COMMON OCEANOGRAPHIC DATA ACCESS SYSTEM (CODAS)                       *
*                                                                            *
*      WRITTEN BY:  RAMON CABRERA, ERIC FIRING, and JULIE RANADA             *
*                   JOINT INSTITUTE FOR MARINE AND ATMOSPHERIC RESEARCH      *
*                   1000 POPE ROAD  MSB 404                                  *
*                   HONOLULU, HI 96822                                       *
*                                                                            *
*      VERSION:     3.00                                                     *
*                                                                            *
*      DATE:        APRIL 1989                                               *
*                                                                            *
*****************************************************************************/
/*

    FILE:  io_nc.c

           Comment-stripping file access routines.

*/
/*-----------------------------------------------------------------------------

    FUNCTION: getc_nc

       This is a routine to read the next character from a file,
       as getc does, but to skip over any areas that are
       commented out with "slash star....star slash".

    PARAMETER:  fp = pointer to input file

    RETURNS:  non-comment character if okay
              EOF on end of file

*/
#if PROTOTYPE_ALLOWED
int getc_nc(FILE *fp)           /* "nc" is for "no comments" */
#else
int getc_nc(fp)           /* "nc" is for "no comments" */
FILE *fp;
#endif
{
   int c1, c2;

   c1 = getc(fp);
   if (c1 != '/') return(c1);
   if ((c2 = getc(fp)) == '*')
   {
      do
      {
         c1 = c2;
         c2 = getc(fp);
      } while ( !((c1 == '*') && (c2 == '/')) && (c2 != EOF));
      if (c2 == EOF) return(EOF);
      c1 = getc_nc(fp);
   }
   else
      ungetc(c2, fp);
   return(c1);
}

/*-----------------------------------------------------------------------------

    FUNCTION:  getword_nc

       It reads the next word in the input file, skipping over any areas
                         that are commented out with "slash asterisk...asterisk slash".
                         The word returned is NULL-terminated.

    PARAMETERS:

       fp      = pointer to input file
       buf     = pointer to storage area for the word to be read (must allow
                 for NULL terminator)
       bufsize = size in bytes of word storage area

    RETURNS:  word length (excluding NULL terminator)

*/
#if PROTOTYPE_ALLOWED
int getword_nc(FILE *fp, char *buf, int bufsize)
#else
int getword_nc(fp, buf, bufsize)
FILE *fp;
char *buf;
int bufsize;
#endif
{
   int i;
   int c;

   /* Make sure there is room for a minimal string (1 char plus null) */
   if (bufsize < 2)
      return(0);
   /* Find the first non-white character. */
   while (((c = getc_nc(fp)) != EOF) &&
      (c == ' ' || c == '\t' || c == '\n' || c == '\r'))
      ;
   /* Fill the string with non-white characters until white space is found. */
   i = 0;
   while (c != EOF && i < bufsize-1 &&
      c != ' ' && c != '\t' && c != '\n' && c != '\r')
   {
      buf[i] = c;
      i++;
      c = getc_nc(fp);
   }
   /* Append a NULL to the string. */
   buf[i] = '\0';
   return(i);     /* Number of characters in string, excluding NULL. */
}                       /* getword_nc() */

/*-----------------------------------------------------------------------------

    FUNCTION:  getwords_nc

        Reads the indicated number of words from an input file, skipping
                                over areas that have been commented out by "slash asterisk...
                                asterisk slash".  The words are delimited by spaces.

    PARAMETERS:

       fp      = pointer to input file
       buf     = pointer to storage area for words to be read
       bufsize = size in bytes of storage area
       nwords  = no. of words to read

    RETURNS:  no. of words actually read  = nwords if okay
                                          < nwords if end-of-file or
                                                      buffer filled

*/
#if PROTOTYPE_ALLOWED
int getwords_nc(FILE *fp, char *buf, int bufsize, int nwords)
#else
int getwords_nc(fp, buf, bufsize, nwords)
FILE *fp;
char *buf;
int bufsize, nwords;
#endif
{
   int i, length;
   char *buf_ptr;

   buf_ptr = buf;
   for (i = 0; i < nwords; i++)
   {
      length = getword_nc(fp, buf_ptr, bufsize);
      if (length == 0)
         return(i);   /* number of words read so far */
      if ((i + 1) < nwords)
      {
         /* Append a space to the buffer and adjust the pointer
            and remaining size.
         */
         buf_ptr[length] = ' ';
         buf_ptr += (length + 1);
         bufsize -= (length + 1);
      }
   }
   buf_ptr[length] = '\0'; /* change last space back to a null */
   return(i);   /* Number of words requested = number supplied. */
}                       /* getwords_nc() */

/*-----------------------------------------------------------------------------

    FUNCTION:  get2eol_nc

       Reads to the end of the current line from a file, skipping over
                         areas that have been commented out by a "slash asterisk...
                         asterisk slash".

    PARAMETERS:

       fp      = pointer to input file
       buf     = pointer to storage area for line to be read
       bufsize = size in bytes of storage area

    RETURNS:  no. of bytes stored in buffer

*/
#if PROTOTYPE_ALLOWED
int get2eol_nc(FILE *fp, char *buf, int bufsize)
#else
int get2eol_nc(fp, buf, bufsize)
FILE *fp;
char *buf;
int bufsize;
#endif
{
   int c, i;

   /* skip over leading spaces/tabs */
   while (((c = getc_nc(fp)) != EOF) && (c == ' ' || c ==  '\t' || c == '\r'))
      ;
   i = 0;
   while ((i < bufsize-1) && (c != EOF) && (c != '\n'))
   {
      if (c != '\r')  buf[i] = c;
      i++;
      c = getc_nc(fp);
   }            /* store to end of current line */
   buf[i] = '\0';
   return(i);
}

/*-----------------------------------------------------------------------------

    FUNCTION:  strip_comments

       It copies the contents of the input file to another file, except
       for comments enclosed by "slash asterisk" and "asterisk slash".

    PARAMETERS:

       fp_in  = pointer to input file
       fp_out = pointer to output file

*/
#if PROTOTYPE_ALLOWED
void strip_comments(FILE *fp_in, FILE *fp_out)
#else
void strip_comments(fp_in, fp_out)
FILE *fp_in, *fp_out;
#endif
{
   int c;

   while ( (c = getc_nc(fp_in)) != EOF)
   {
      if (c == '@')
      {
         char fn[180];
         FILE *fp_incl;
         if (getword_nc(fp_in, fn, 180) > 0)
         {
            fp_incl = fopen(fn, "r");
            if (fp_incl != NULL)
            {
               strip_comments(fp_incl, fp_out); /* recursive */
               putc('\n', fp_out);  /* in case the included file lacked LF */
               fclose(fp_incl);
            }
            else 
            {
               printf("Error opening include file: %s\n", fn);
               return;
            }
         }
         else 
         {
            printf("Error reading include file name.\n");
            return;
         }
      }

      /* Use the character only if it is NOT "@". */
      else if (putc(c, fp_out) == EOF)
      {
         printf("\n Output error in strip_comments.\n");
         return;
      }
   }
   return;
}

/*-----------------------------------------------------------------------------

    FUNCTION: get_quotation

       It searches a file for a phrase delimited by double quotes,
       up to a maximum of n characters.  The phrase, minus the
       quotes, is loaded into the string <buf>, which is then
       NUL terminated.  Escape sequences are appropriately accounted for.

       This function can be used for reading title information
       from a control file and for reading format strings for
       structure printing format specifications.

    PARAMETERS:

       fp      = pointer to input file
       buf     = pointer to storage area for quoted string
       bufsize = size in bytes of storage area

    RETURNS:  pointer to storage area if okay
              NULL otherwise (end of file or insufficient buffer size)

*/
#if PROTOTYPE_ALLOWED
char *get_quotation(FILE *fp, char *buf, int bufsize)
#else
char *get_quotation(fp, buf, bufsize)
FILE *fp;
char *buf;
int bufsize;         /* max number of characters permitted in buf */
#endif
{
   int i, escape_sequence = 0;
   int c;

   for (i = 0; i < bufsize; i++) buf[i] = '\0';  /* Clear buffer */
   /* search for leading quote */
   while ((c = getc_nc(fp)) != '"' && c != EOF)
      ;
   /* read every non-comment character until buffer is full or trailing
      quote is encountered */
   for (i = 0; i < bufsize && c != EOF; i++)
   {
      if (((c = getc(fp)) == '"') && !escape_sequence)
      {
         buf[i] = '\0';
         return(buf);    /* normal exit */
      }
      else if (escape_sequence)
      {
         switch (c)
         {
            case 'n' :  buf[i] = '\n';  break;
            case 't' :  buf[i] = '\t';  break;
            case 'b' :  buf[i] = '\b';  break;
            case 'r' :  buf[i] = '\r';  break;
            case 'f' :  buf[i] = '\f';  break;
            case '\\':  buf[i] = '\\';  break;
            case '\'':  buf[i] = '\'';  break;
            case '"' :  buf[i] = '\"';  break;
            default  :  buf[i] = c;
         }
         escape_sequence = 0;
      }
      else if (c == '\\')
      {
         escape_sequence = 1;
         i--;
      }
      else
         buf[i] = c;
   }
   return(NULL);            /* EOF or too many characters */
}
