/*============================================================================
FILE  read_ifs.c

MEMBER OF process cmpp

Public Domain

Georgia Tech Research Corporation
Atlanta, Georgia 30332
PROJECT A-8503

AUTHORS

    9/12/91  Bill Kuhn and Steve Tynor

MODIFICATIONS

    <date> <person name> <nature of modifications>

SUMMARY

    This file contains top-level functions used in reading information
    from the ifspec.ifs file and building an internal data structure that
    holds the information.  Most of the work in parsing of the
    ifspec.ifs file and in building the structure is handled by
    the UNIX 'lex' and 'yacc' utilities.  This processing is begun
    at the call to yyparse() in read_ifs_table() below.  See also files:

        ifs_lex.l
        ifs_yacc.y

INTERFACES

    read_ifs_file()
    yywrap()
    yyerror()

REFERENCED FILES

    None.

NON-STANDARD FEATURES

    None.

============================================================================*/

#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include  "ifs_yacc_y.h"

extern char *prog_name;
extern int ifs_yyparse (void);
extern void ifs_yyrestart (FILE*);

extern FILE *ifs_yyin;
extern int   ifs_yylineno;
extern char *ifs_yytext;

extern Ifs_Table_t *parser_ifs_table;
extern bool    parser_just_names;

extern int ifs_num_errors;

static int read_ifs_table(FILE *fp, int mode, Ifs_Table_t *ifs_table);

char *current_filename;

/* *********************************************************************** */


/*
  NOTE
  
  The following function may be called either by cmpp -ifs or cmpp -lst with
  mode set to GET_IFS_TABLE or GET_IFS_NAME respectively.
  */


/*
read_ifs_file

Function read_ifs_file() opens the Interface Specification file
(ifspec.ifs) for read access and calls read_ifs_table() with the
assigned file pointer to read and parse the file.  Upon return
from read_ifs_table(), the file is closed.
*/



int read_ifs_file(
    const char  *filename,   /* File to read */
    int         mode,        /* Get names only or get everything? */
    Ifs_Table_t *ifs_table)  /* Table to put info in */
{
   FILE *fp = (FILE *) NULL; /* Ifs file pointer */
   int status = 0; /* returned status from function */
 
 
   /* Open the ifs file for read access */
   
    /* Open the model pathname file */
    if ((current_filename = gen_filename(filename, "r")) == (char *) NULL) {
        print_error("ERROR - Unable to build full file name");
        return -1;
    }
    if ((fp = fopen(current_filename, "r")) == (FILE *) NULL) {
        print_error("ERROR - Unable to open \"%s\": %s",
                current_filename, strerror(errno));
        status = -1;
        goto EXITPOINT;
    }

   /* Get the stuff from the file into the ifs_table struct. Here mode
    * defines the data that will be added to the structure */
   status = read_ifs_table(fp, mode, ifs_table);

   EXITPOINT:
   /* Close file and return */
   if (fp != (FILE *) NULL) {
       if (fclose(fp) != 0) {
            print_error("ERROR - Unable to close \"%s\": %s",
                    current_filename, strerror(errno));
            status = -1;
       }
   }

   free(current_filename);
   current_filename = (char *) NULL;
   return status;
} /* end of function read_ifs_file */




/* *********************************************************************** */


/*
read_ifs_table

Function read_ifs_table() calls yyparse() to read and parse the
Interface Specification file contents and place the information
into an internal data structure.  Function yyparse() is
automatically generated by UNIX lex/yacc.
*/



static int read_ifs_table(
    FILE        *fp,          /* File to read from */
    int         mode,         /* Get names only or get everything? */
    Ifs_Table_t *ifs_table)   /* Table to put info in */
{
   assert (ifs_table);
   assert (fp);

   ifs_table->name.description = 
   ifs_table->name.c_fcn_name = 
   ifs_table->name.model_name = NULL;

   ifs_yylineno = 1;
   ifs_yyin = fp;
   parser_just_names = (mode == GET_IFS_NAME) ? true : false;
   parser_ifs_table = ifs_table;

   ifs_num_errors = 0;

   if (ifs_yyparse() || (ifs_num_errors > 0)) {
      print_error ("Error parsing interface specification file");
      ifs_yyrestart(NULL);
      return -1;
   }
   ifs_yyrestart(NULL);
   return 0;
}

/*---------------------------------------------------------------------------*/
   
void
ifs_yyerror (char *str)
{
   fprintf (stderr, "%s: Error: \"%s\": line %d (near \'%s\'):\n\t%s.\n",
	    prog_name, current_filename, ifs_yylineno, ifs_yytext, str);
}

