 /*
  * Khoros: $Id: gw_struct.c,v 1.3 1991/10/02 00:11:41 khoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: gw_struct.c,v 1.3 1991/10/02 00:11:41 khoros Exp $";
#endif

 /*
  * $Log: gw_struct.c,v $
 * Revision 1.3  1991/10/02  00:11:41  khoros
 * HellPatch2
 *
  */ 

/*
 *----------------------------------------------------------------------
 *
 * Copyright 1990, University of New Mexico.  All rights reserved.
 * 
 * Permission to copy and modify this software and its documen-
 * tation only for internal use in your organization is hereby
 * granted, provided that this notice is retained thereon and
 * on all copies.  UNM makes no representations as too the sui-
 * tability and operability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 * 
 * UNM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
 * NESS.  IN NO EVENT SHALL UNM BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY OTHER DAMAGES WHAT-
 * SOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER-
 * FORMANCE OF THIS SOFTWARE.
 * 
 * No other rights, including for example, the right to redis-
 * tribute this software and its documentation or the right to
 * prepare derivative works, are granted unless specifically
 * provided in a separate license agreement.
 *----------------------------------------------------------------------
 */

#include "unmcopyright.h"	 /* Copyright 1990 by UNM */
#include "writer.h"

/* >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
   >>>>                                                       <<<<
   >>>>    Ghostwriter Routines to Generate *.h file          <<<<
   >>>>                                                       <<<<
   >>>>                gw_generate_hfile()                    <<<<
   >>>>                gw_print_struct_fields()               <<<<
   >>>>                gw_print_field()  	              <<<<
   >>>>                gw_print_toggle()  	              <<<<
   >>>>                                                       <<<<
   >>>>>>>>>>>>>>>>>>>>>>>>>>>>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< */


/************************************************************
*
*  Routine Name: gw_generate_hfile
*
*      Purpose:  This routine creates the C structure that provides the
*		 link between the command line user interface and the
*		 application program, in the *.h file
*
*        Input: pane_file:  the .pane file to use for generation
*               prog_file:  the .prog file to use for generation
*		     name:  the name of the program being generated
*    Called by: lwriter()
*
*   Written By:  Danielle Argiro
*
*************************************************************/

int gw_generate_hfile(database, prog_spec, name, filename, type)
char **database;
char **prog_spec;
char *name;
char *filename;
char *type;
{
     time_t clock;
     FILE *file, *tmpfile;
     char hfile[15], temp[MaxLength], resp; 
     char *copyright, *filepath;

#include "gw_str.h"  /* strings to help with code generation */

     /*
      *  determine name of .h file
      */
     sprintf(hfile, "%s.h", name);

     /*
      *  see if .h file already exists.  If so, prompt to over-write,
      *  return true if the answer is NO
      */
     if (!writer->force)
     {
        if (tmpfile = fopen(filename, "r"))
        {
            fprintf(stderr, "\nOverwrite file '%s'?  [y/n]: ", filename);
            fgets(temp, MaxLength, stdin);
            sscanf(temp, "%c", &resp);
            if ((resp != 'y') && (resp != 'Y')) return(true);
        }
     }

     /*
      *  create & open .h file
      */
     if ((file = fopen(filename, "w"))== NULL)
     {
          fprintf(stderr, "\nghostwriter:\n");
          fprintf(stderr, "  Could not create file '%s'\n", filename);
          return(false);
     }

    /*
     * begin *.h file with RCS header
     */
     fprintf(file, " /*\n  * Khoros: %cId%c\n  */\n\n", '$','$');
     fprintf(file, " /*\n  * %cLog%c\n  */\n\n", '$','$');

    /*
     *  follow RCS header with UNM copyright
     */
     if ((writer->cp_flag) && (writer->cp != NULL))
        filepath = xvf_strcpy(writer->cp);
     else
	filepath = xvf_strcpy("KHOROS_HOME/repos/utils/cpright.ghost");  
     copyright = gw_copyright(filepath,"long");
     if (copyright != NULL) 
         fprintf(file, "%s\n", copyright);

    /*
     *  add header for .h file
     */
     fprintf(file, "\n%s", filehdr_top);
     fprintf(file, " >>>>\n%s%s\n", filehdr_file, hfile);

     if (xvf_strlen(prog_spec[Authors]) > 0) 
          fprintf(file, "%s%s", filehdr_auth, prog_spec[Authors]);
     else 
          fprintf(file, "%s\n", filehdr_auth);

     clock = (time_t) time(NULL);
     sprintf(temp, "%s%s\n", filehdr_date, ctime(&clock));
     temp[xvf_strlen(temp)-2] = '\0';
     fprintf(file, "%s\n >>>> \n", temp);
     fprintf(file, "%s\n\n", filehdr_bottom);

    /*
     *  don't want .h file multiply defined
     */
     fprintf(file, "#ifndef _%s_h_\n", name);
     fprintf(file, "#define _%s_h_\n\n", name);

    /*
     *  add in #includes
     */
     if ((strcmp(type, "prog") == 0) || (strcmp(type, "fprog") == 0))
        fprintf(file, "%s", includevin);
     else
        fprintf(file, "%s", includexvin);

     fprintf(file, "\n\n");

    /*
     *  add in -include_includes from .prog file
     */ 
     fprintf(file,  "/* -include_includes */\n");
     if (xvf_strlen(prog_spec[IncludeIncludes]) > 0) 
          fprintf(file, "%s",prog_spec[IncludeIncludes]);
     fprintf(file,  "/* -include_includes_end */\n\n");

    /*
     *  put in necessary global variables
     */
     fprintf(file, "%s", glob1);
     fprintf(file, "%s\n", glob2);

    /*
     *  comment box for args structure
     */
     fprintf(file, "%s", comm_beg);
     fprintf(file, "*\n*                    %s Argument Structure\n", name); 
     fprintf(file, "*\n%s\n", comm_end);

    /*
     *  generate C structure for command-line user interface
     */ 
     if (arg_total != 0)
     {
        fprintf(file, "typedef struct _%s  {\n\n", name);
        gw_print_struct_fields(file, database);
        fprintf(file, "}  %s_struct;\n\n", name);
        fprintf(file, "%s_struct *%s;\n\n", name, name);
     }
     
    /*
     *  add in -include_additions from .prog file
     */ 
     fprintf(file,  "/* -include_additions */\n");
     if (xvf_strlen(prog_spec[IncludeAdd]) > 0) 
          fprintf(file, "%s",prog_spec[IncludeAdd]);
     fprintf(file,  "/* -include_additions_end */\n\n");

    /*
     *  add in -include_macros from .prog file
     */ 
     fprintf(file,  "/* -include_macros */\n");
     if (xvf_strlen(prog_spec[IncludeMacros]) > 0) 
          fprintf(file, "%s",prog_spec[IncludeMacros]);
     fprintf(file,  "/* -include_macros_end */\n\n");

    /*
     *  end include file
     */
     fprintf(file, "#endif\n");

     fclose(file);

     fprintf(stderr, "ghostwriter:  done generating '%s'\n", filename);
     return(true);

}

/************************************************************
*
*  Routine Name: gw_print_struct_fields
*
*      Purpose:  This routine prints the necessary fields to the 
*		 C structure generated in the .h file
*
*        Input:  file     - open stream to man1 page
*		 database - pointer to the internal database struct
*		 name     - name of the program being generated
*
*       Output:  prints the required arguments to the man1 file
*
*    Called by:  ghost_h()
*
*   Written By:  Danielle Argiro
*
*************************************************************/

gw_print_struct_fields(file, database)
FILE *file;
char **database;
{
     int index = 0, mut_excl_count = 0, toggle_count = 0;
     mut_excl_link *mut_excl_ptr;
     gw_toggle_struct *toggle_ptr;

    /*
     * print out fields corresponding to required arguments
     */
     while (index < gw_num_req)
     {
        gw_print_field(file, database, gw_req_args[index], true);
        index++;
     }

    /*
     * print out fields corresponding to required toggles
     */
     while (toggle_count < gw_toggle_num)
     {
	toggle_ptr = gw_toggle[toggle_count];
	if (toggle_ptr->req == true)
	    gw_print_toggle(file, toggle_ptr);
        toggle_count++;
     }

    /*
     * print out fields corresponding to required mutually exclusive groups
     */
     while (mut_excl_count < gw_mut_excl_num)
     {
        mut_excl_ptr = gw_mut_excl[mut_excl_count];
	if (mut_excl_ptr->type == true)  /* mut excl group is required */
        {
	   fprintf(file, "/*----- these are a Required mutually exclusive group ----*/\n");
	   mut_excl_ptr = mut_excl_ptr->next;
	   while (mut_excl_ptr != NULL)
           {
               index = mut_excl_ptr->index;
               gw_print_field(file, database, index, true);
	       mut_excl_ptr = mut_excl_ptr->next;
	   }
	   fprintf(file, "/*-------------------------------------------*/\n\n");
        }
        mut_excl_count++;
     }

    /*
     * print out fields corresponding to optional arguments
     */
     index = 0;
     while (index < gw_num_opt)
     {
        gw_print_field(file, database, gw_opt_args[index], false);
        index++;
     }

    /*
     * print out fields corresponding to optional toggles
     */
     toggle_count = 0;
     while (toggle_count < gw_toggle_num)
     {
	toggle_ptr = gw_toggle[toggle_count];
	if (toggle_ptr->req == false)
	    gw_print_toggle(file, toggle_ptr);
        toggle_count++;
     }

    /*
     * print out fields corresponding to optional mutually exclusive groups
     */
     mut_excl_count = 0;
     while (mut_excl_count < gw_mut_excl_num)
     {
        mut_excl_ptr = gw_mut_excl[mut_excl_count];
	if (mut_excl_ptr->type == false)  /* mut excl group is required */
        {
	   mut_excl_ptr = mut_excl_ptr->next;
	   fprintf(file, "/*----  these are an Optional mutually exclusive group ----*/\n");
	   while (mut_excl_ptr != NULL)
           {
               index = mut_excl_ptr->index;
               gw_print_field(file, database, index, true);
	       mut_excl_ptr = mut_excl_ptr->next;
	   }
	   fprintf(file, "/*-------------------------------------------*/\n\n");
        }
        mut_excl_count++;
     }

}


/************************************************************
*
*  Routine Name: gw_print_field
*
*      Purpose:  This routine prints a single field to the C structure 
*		 being generated in the .h file
*
*        Input:  file     - open stream to man1 page
*		 database - pointer to the internal database struct
*		 name     - name of the program being generated
*
*       Output:  prints the required arguments to the man1 file
*
*    Called by:  gw_print_struct_fields()
*
*   Written By:  Danielle Argiro
*
*************************************************************/

gw_print_field(file, database, index, required)
FILE *file;
char **database;
int    index;
int    required;
{
    Line_Info line_info;
    char *type;

    xvf_clear_line_info(&line_info);

    xvf_gen_parse(database[index], &line_info);
    if (required == true)
       type = xvf_strcpy("Required");
    else
       type = xvf_strcpy("Optional");

    switch (line_info.typeflag) {
	    
         case InputFile:
	      fprintf(file, "/*\n *  %s (%s infile)\n */\n",
			   line_info.description, type);
	      if (writer->tag)
       	           fprintf(file, "char\t*%s_file;\t/* %s FILENAME */\n", 
		      line_info.variable, line_info.description);
	      else
       	           fprintf(file, "char\t*%s;     \t/* %s FILENAME */\n", 
		      line_info.variable, line_info.description);
			
       	      fprintf(file, "int\t %s_flag;\t/* %s FLAG */\n\n", 
		      line_info.variable, line_info.description);
	      break;

         case OutputFile:
	      fprintf(file, "/*\n *  %s (%s outfile)\n */\n",
			   line_info.description, type);
	      if (writer->tag)
       	          fprintf(file, "char\t*%s_file;\t/* %s FILENAME */\n", 
		      line_info.variable, line_info.description);
	      else
       	          fprintf(file, "char\t*%s     ;\t/* %s FILENAME */\n", 
		      line_info.variable, line_info.description);

       	      fprintf(file, "int\t %s_flag;\t/* %s FLAG */\n\n", 
		      line_info.variable, line_info.description);
	      break;

         case FloatOpt:
	      fprintf(file, "/*\n *  %s (%s float)\n */\n",
			   line_info.description, type);

	      if (writer->tag)
	           fprintf(file, "float\t %s_float;\t/* %s FLOAT */\n",
                                  line_info.variable, line_info.description);
	      else
	           fprintf(file, "float\t %s;      \t/* %s FLOAT */\n",
                                  line_info.variable, line_info.description);

              fprintf(file, "int\t %s_flag;   \t/* %s FLAG */\n\n",
                             line_info.variable, line_info.description);
              break;

         case IntegerOpt:
	      fprintf(file, "/*\n *  %s (%s integer)\n */\n",
			   line_info.description, type);

	      if (writer->tag)
	           fprintf(file, "int\t %s_int; \t/* %s INT */\n",
                                 line_info.variable, line_info.description);
	      else
	           fprintf(file, "int\t %s;    \t/* %s INT */\n",
                                 line_info.variable, line_info.description);

              fprintf(file, "int\t %s_flag;\t/* %s FLAG */\n\n",
                            line_info.variable, line_info.description);
              break;
		
         case StringOpt:
	      fprintf(file, "/*\n *  %s (%s string)\n */\n",
			   line_info.description, type);
	      if (writer->tag)
	          fprintf(file, "char\t*%s_string;\t/* %s STRING */\n",
                              line_info.variable, line_info.description);
	      else
	          fprintf(file, "char\t*%s;       \t/* %s STRING */\n",
                              line_info.variable, line_info.description);

              fprintf(file, "int\t %s_flag;   \t/* %s FLAG */\n\n",
                              line_info.variable, line_info.description);
              break;

         case LogicOpt:
	      fprintf(file, "/*\n *  %s (%s logical)\n */\n",
			   line_info.description, type);

	      if (writer->tag)
	          fprintf(file, "int\t %s_logic;\t/* %s LOGIC */\n",
                             line_info.variable, line_info.description);
	      else
	          fprintf(file, "int\t %s;      \t/* %s LOGIC */\n",
                             line_info.variable, line_info.description);

              fprintf(file, "int\t %s_flag;  \t/* %s FLAG */\n\n",
                              line_info.variable, line_info.description);
              break;
     }

}
		

/************************************************************
*
*  Routine Name: gw_print_toggle
*
*      Purpose:  This routine prints a toggle field to the C structure 
*		 being generated in the .h file
*
*        Input:  file       - open stream to man1 page
*		 toggle_ptr - pointer to the toggle struct
*
*       Output:  prints the toggle fields to the man1 file
*
*     Comments:  Note that only the header of the toggle list (from -T line)
*		 is sent to this routine - the rest of the list is not needed.
*
*    Called by:  gw_print_struct_fields()
*
*   Written By:  Danielle Argiro
*
*************************************************************/

gw_print_toggle(file, toggle_ptr)

FILE *file;
gw_toggle_struct *toggle_ptr;
{
	char *type;

	if (toggle_ptr->req == true) type = xvf_strcpy("Required");
	else type = xvf_strcpy("Optional");

	fprintf(file, "/*\n * %s (%s %s toggle - )",
                     toggle_ptr->desc, type, ascii_name(toggle_ptr->type));
        gw_print_toggle_vals(file, toggle_ptr);
	fprintf(file, "\n */\n");

	switch(toggle_ptr->type) {
	    case IntegerOpt:
		 if (writer->tag)
                     fprintf(file, "int\t %s_toggle;\t\t/* %s INT TOGGLE */\n",
                               toggle_ptr->variable, toggle_ptr->desc);
		 else
                     fprintf(file, "int\t %s;  \t\t/* %s INT TOGGLE */\n",
                               toggle_ptr->variable, toggle_ptr->desc);
       	         fprintf(file, "int\t %s_flag;\t\t/* %s FLAG */\n\n", 
	                       toggle_ptr->variable, toggle_ptr->desc);
	         break;

	    case FloatOpt:
		 if (writer->tag)
                     fprintf(file,"float\t %s_toggle;\t\t/* %s FLOAT TOGGLE */\n",
                               toggle_ptr->variable, toggle_ptr->desc);
		 else
                     fprintf(file,"float\t %s;    \t\t/* %s FLOAT TOGGLE */\n",
                               toggle_ptr->variable, toggle_ptr->desc);
       	         fprintf(file, "int\t %s_flag;\t\t/* %s FLAG */\n\n", 
	                       toggle_ptr->variable, toggle_ptr->desc);
	         break;

	    case StringOpt:
		 if (writer->tag)
                     fprintf(file,"char\t*%s_toggle;\t\t/* %s STRING TOGGLE */\n",
                               toggle_ptr->variable, toggle_ptr->desc);
		 else
                     fprintf(file,"char\t*%s;  \t\t/* %s STRING TOGGLE */\n",
                               toggle_ptr->variable, toggle_ptr->desc);
       	         fprintf(file, "int\t %s_flag;\t\t/* %s FLAG */\n\n", 
	                       toggle_ptr->variable, toggle_ptr->desc);
	         break;

	    case LogicOpt:
		 if (writer->tag)
                    fprintf(file, "int\t %s_toggle;\t\t/* %s LOGICAL TOGGLE */\n",
                               toggle_ptr->variable, toggle_ptr->desc);
		 else
                    fprintf(file, "int\t %s;   \t\t/* %s LOGICAL TOGGLE */\n",
                               toggle_ptr->variable, toggle_ptr->desc);
       	         fprintf(file, "int\t %s_flag;\t\t/* %s FLAG */\n\n", 
	                       toggle_ptr->variable, toggle_ptr->desc);
	         break;
	 }

}
