#include "help.h"

int AlH_count = 0;         /* length of current line in usage output buffer */

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

#define AlHelp_cmp_switch(argv_str, full_str, abbrev_str) \
   ((strcmp(argv_str, full_str) == 0) || (strcmp(argv_str, abbrev_str) == 0))

#define AlHelp_cmp_ob_switch(argv_str, full_str) \
   ((*argv_str == *full_str) && (*(argv_str + 1) == *(full_str + 1)) \
    && (*(argv_str + 2) == *(full_str + 2)))


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

void AlHelp_print_info(flags, mask, info_str)
     AlH_MASK flags;     /* all flags of info being requested */
     AlH_MASK mask;      /* a particular switch's mask */
     char *info_str;     /* information string for switch matching the mask */
 {
   if ((flags & mask) != 0)
     printf("%s\n", info_str);

 };         /* end of AlHelp_print_info()  */


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

Bool AlHelp_user_requested_help(argc, argv)
     int argc;
     char *argv[];
 { int i;

   for(i = 1; i <= argc; i++)
     { if (*argv[i] == '-')
	 { if (*(argv[i] + 1) == 'h')
	     return(Bool_TRUE);
	 };
     };
   return(Bool_FALSE);

 };         /* end of AlHelp_user_requested_help()  */


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

void AlHelp_usage(program_name,
		  optional_no_arg_switches, required_no_arg_switches,
		  optional_fixed_arg_switches, required_fixed_arg_switches,
		  optional_object_arg_switches, required_object_arg_switches)
     char *program_name;
     AlH_MASK optional_no_arg_switches, required_no_arg_switches;
     AlH_MASK optional_fixed_arg_switches, required_fixed_arg_switches;
     AlH_MASK optional_object_arg_switches, required_object_arg_switches;
 {
   extern int AlH_count;

   printf("%s%s", ALH_usage, program_name);

   AlH_count = 11 + strlen(program_name);

   /* Do No-Argument Switches first */
   /* ----------------------------- */
   AlHpr_no_arg_switch(optional_no_arg_switches, required_no_arg_switches,
		       ALH_help, ALHfull_help);
   AlHpr_no_arg_switch(optional_no_arg_switches, required_no_arg_switches,
		       ALH_create, ALHfull_create);
   AlHpr_no_arg_switch(optional_no_arg_switches, required_no_arg_switches,
		       ALH_eliminate, ALHfull_elim);
   AlHpr_no_arg_switch(optional_no_arg_switches, required_no_arg_switches,
		       ALH_force, ALHfull_force);
   AlHpr_no_arg_switch(optional_no_arg_switches, required_no_arg_switches,
		       ALH_nest, ALHfull_nest);
   AlHpr_no_arg_switch(optional_no_arg_switches, required_no_arg_switches,
		       ALH_output, ALHfull_output);

   /* Do Fixed-Argument Switches second */
   /* --------------------------------- */
   AlHpr_fixed_arg_switch(optional_fixed_arg_switches,
			  required_fixed_arg_switches,
			  ALH_state, ALHfull_state, ALHarg_state);
   AlHpr_fixed_arg_switch(optional_fixed_arg_switches,
			  required_fixed_arg_switches,
			  ALH_uprop, ALHfull_uprop, ALHarg_uprop);
   AlHpr_fixed_arg_switch(optional_fixed_arg_switches,
			  required_fixed_arg_switches,
			  ALH_data, ALHfull_data, ALHarg_data);
   AlHpr_fixed_arg_switch(optional_fixed_arg_switches,
			  required_fixed_arg_switches,
			  ALH_traffic, ALHfull_traffic, ALHarg_traffic);
   AlHpr_fixed_arg_switch(optional_fixed_arg_switches,
			  required_fixed_arg_switches,
			  ALH_warn, ALHfull_warn, ALHarg_warn);
   AlHpr_fixed_arg_switch(optional_fixed_arg_switches,
			  required_fixed_arg_switches,
			  ALH_after, ALHfull_after, ALHobj_rulenum);
   AlHpr_fixed_arg_switch(optional_fixed_arg_switches,
			  required_fixed_arg_switches,
			  ALH_before, ALHfull_before, ALHobj_rulenum);
   AlHpr_fixed_arg_switch(optional_fixed_arg_switches,
			  required_fixed_arg_switches,
			  ALH_rule, ALHfull_rule, ALHobj_rulenum);

   /* Do Object--Argument Switches lastly */
   /* ----------------------------------- */
   AlHpr_object_arg_switch(optional_object_arg_switches,
			   required_object_arg_switches,
			   ALH_io_filename, ALHfull_io_filename,
			   ALHobj_filename);
   AlHpr_object_arg_switch(optional_object_arg_switches,
			   required_object_arg_switches,
			   ALH_folder, ALHfull_folder, 
			   ALHobj_folder);
   AlHpr_object_arg_switch(optional_object_arg_switches,
			   required_object_arg_switches,
			   ALH_load_filename, ALHfull_load_filename,
			   ALHobj_filename);
   AlHpr_object_arg_switch(optional_object_arg_switches,
			   required_object_arg_switches,
			   ALH_msgsrc, ALHfull_msgsrc,
			   ALHobj_msgsrc);
   AlHpr_object_arg_switch(optional_object_arg_switches,
			   required_object_arg_switches,
			   ALH_std_msgtype, ALHfull_std_msgtype,
			   ALHobj_msgtype);
   AlHpr_object_arg_switch(optional_object_arg_switches,
			   required_object_arg_switches,
			   ALH_new_msgtype, ALHfull_new_msgtype,
			   ALHobj_msgtype);
   AlHpr_object_arg_switch(optional_object_arg_switches,
			   required_object_arg_switches,
			   ALH_ruleset, ALHfull_ruleset,
			   ALHobj_ruleset);
   AlHpr_object_arg_switch(optional_object_arg_switches,
			   required_object_arg_switches,
			   ALH_server, ALHfull_server,
			   ALHobj_server);

   printf("\n");
   AlH_count = 0;

 };         /* end of AlHelp_usage()  */

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

void AlHelp_info(program_name,
		  optional_no_arg_switches, required_no_arg_switches,
		  optional_fixed_arg_switches, required_fixed_arg_switches,
		  optional_object_arg_switches, required_object_arg_switches,
		  notes_array,
		  examples_array,
                  help_example_string)
     char *program_name;
     AlH_MASK optional_no_arg_switches, required_no_arg_switches;
     AlH_MASK optional_fixed_arg_switches, required_fixed_arg_switches;
     AlH_MASK optional_object_arg_switches, required_object_arg_switches;
     char *notes_array[];
     char *examples_array[];
     char *help_example_string;
 {
   AlH_MASK flags;
   int i;

   /* First, print out a Usage line */
   /* ----------------------------- */
   AlHelp_usage(program_name,
		optional_no_arg_switches, required_no_arg_switches,
		optional_fixed_arg_switches, required_fixed_arg_switches,
		optional_object_arg_switches, required_object_arg_switches);

   /* Print out info about Arguments (Argus Objects) */
   /* ---------------------------------------------- */
   AlH_arguments();
   flags = (optional_object_arg_switches | required_object_arg_switches);
   AlHelp_print_info(flags, (ALH_io_filename | ALH_load_filename),
		     ALHinfo_filename);
   AlHelp_print_info(flags, ALH_folder, ALHinfo_folder);
   AlHelp_print_info(flags, ALH_msgsrc, ALHinfo_msgsrc);
   AlHelp_print_info(flags, (ALH_std_msgtype | ALH_new_msgtype),
		     ALHinfo_msgtype);
   flags = (optional_fixed_arg_switches | required_fixed_arg_switches);
   AlHelp_print_info(flags,
		     (ALH_after | ALH_before | ALH_rule),
		     ALHinfo_rulenum);
   flags = (optional_object_arg_switches | required_object_arg_switches);
   AlHelp_print_info(flags, ALH_ruleset, ALHinfo_ruleset);
   AlHelp_print_info(flags, ALH_server, ALHinfo_server);

   /* Print out info about Switches */
   /* ----------------------------- */
   AlH_switches();

   /* Switches that don't take arguments */
   flags = (optional_no_arg_switches | required_no_arg_switches);
   AlHelp_print_info(flags, ALH_help, ALHstr_help);
   AlHelp_print_info(flags, ALH_create, ALHstr_create);
   AlHelp_print_info(flags, ALH_eliminate, ALHstr_elim);
   AlHelp_print_info(flags, ALH_force, ALHstr_force);
   AlHelp_print_info(flags, ALH_nest, ALHstr_nest);
   AlHelp_print_info(flags, ALH_output, ALHstr_output);

   /* Switches that take fixed arguments */
   flags = (optional_fixed_arg_switches | required_fixed_arg_switches);
   AlHelp_print_info(flags, ALH_state, ALHstr_state);
   AlHelp_print_info(flags, ALH_uprop, ALHstr_uprop);
   AlHelp_print_info(flags, ALH_data, ALHstr_data);
   AlHelp_print_info(flags, ALH_traffic, ALHstr_traffic);
   AlHelp_print_info(flags, ALH_warn, ALHstr_warn);
   AlHelp_print_info(flags, ALH_after, ALHstr_after);
   AlHelp_print_info(flags, ALH_before, ALHstr_before);
   AlHelp_print_info(flags, ALH_rule, ALHstr_rule);

   /* Switches that take objects as arguments */
   flags = (optional_object_arg_switches | required_object_arg_switches);
   AlHelp_print_info(flags, ALH_io_filename, ALHstr_io_filename);
   AlHelp_print_info(flags, ALH_folder, ALHstr_folder);
   AlHelp_print_info(flags, ALH_load_filename, ALHstr_load_filename);
   AlHelp_print_info(flags, ALH_msgsrc, ALHstr_msgsrc);
   AlHelp_print_info(flags, ALH_std_msgtype, ALHstr_std_msgtype);
   AlHelp_print_info(flags, ALH_new_msgtype, ALHstr_new_msgtype);
   AlHelp_print_info(flags, ALH_ruleset, ALHstr_ruleset);
   AlHelp_print_info(flags, ALH_server, ALHstr_server);

   /* Print out Notes info */
   /* -------------------- */
   AlH_notes();
   for(i = 0; notes_array[i] != NULL; i++)
     printf("   %s\n", notes_array[i]);

   /* Print out Examples info */
   /* ----------------------- */
   AlH_examples();
   for(i = 0; notes_array[i] != NULL; i++)
     printf("   %s\n", examples_array[i]);

   /* Print out For Help line */
   /* ----------------------- */
   AlH_for_help(help_example_string);

 };         /* end of AlHelp_info()  */


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

Bool AlHelp_get_arg(argv, argc, index, 
			switch_type, switch_code, switch_arg)
     char *argv[];    /* the argv containing command line strings for main() */
     int argc;        /* the argc indicating # of argv strings for main()    */
     int *index;      /* an index into argv, managed by AlHelp_get_arg()     */
     AlH_MASK
       *switch_type,  /* returned mask, for type of switch (ex: fixed_arg )  */
       *switch_code;  /* returned mask, for a switch code (ex: ALH_state )   */
     char 
       **switch_arg;  /* returns string, for the switch's argument (or NULL) */
 { 
   /* ---------------------------------------------------------------------- */
   /* This function updates: index, switch_type, switch_code, & switch_arg   */
   /* It identifies with command-line switch was processed (argv[index]).    */
   /* It returns:  Bool_TRUE   if a command was processed                    */
   /*              Bool_FALSE  if there were no more options left to process */
   /* It alters the following variables passed to it:                        */
   /*         index          <= ready to process next argv string            */
   /*         switch_type    <= As one of the following masks:               */
   /*                               ALH_bad_switch                           */
   /*                               ALH_no_arg_switch                        */
   /*                               ALH_fixed_arg_switch                     */
   /*                               ALH_object_arg_switch                    */
   /*                               ALH_not_a_switch                         */
   /*         switch_code    <= A mask representing which switch was found,  */
   /*                           or ALH_none if no valid switch  was found.   */
   /*         switch_arg     <= The string which was the argument to the     */
   /*                           switch, or NULL if switch takes no arguments */
   /*                           If (switch_type == ALH_not_a_switch) then    */
   /*                           switch_arg is set to the command-line option */
   /*                           If a bad switch or switch argument was       */
   /*                           specified, then switch_arg is set to the bad */
   /*                           string (for debugging purposes for user).    */
   /*                                                                        */
   /* The calling program should check for  (switch_type == ALH_bad_switch)  */
   /* and print a usage message, followed by a fatal error message, and exit */
   /* ---------------------------------------------------------------------- */

   /* Check if there are any argv's left to process */
   /* --------------------------------------------- */
   if (*index >= argc)
     { *switch_type = ALH_not_a_switch;
       *switch_code = ALH_none;
       *switch_arg = NULL;
       (*index)++;
       /* flag that command-line options are all processed */
       return(Bool_FALSE); 
     };

   /* Check if the argv is a switch at all */
   /* ------------------------------------ */
   if (*argv[*index] != '-')
     { *switch_type = ALH_not_a_switch;
       *switch_code = ALH_none;
       *switch_arg = argv[*index];    /* if not a switch, then return string */
       (*index)++;
       return(Bool_TRUE);
     };

   /* Check the switches that don't take arguments */
   /* -------------------------------------------- */
   *switch_type = ALH_no_arg_switch;
   *switch_arg = NULL;
   *switch_code = ALH_none;
   if (AlHelp_cmp_switch(argv[*index], ALHfull_create, ALHabbrev_create))
     *switch_code = ALH_create;
   if (AlHelp_cmp_switch(argv[*index], ALHfull_elim, ALHabbrev_elim))
     *switch_code = ALH_eliminate;
   if (AlHelp_cmp_switch(argv[*index], ALHfull_force, ALHabbrev_force))
     *switch_code = ALH_force;
   if (AlHelp_cmp_switch(argv[*index], ALHfull_help, ALHabbrev_help))
     *switch_code = ALH_help;
   if (AlHelp_cmp_switch(argv[*index], ALHfull_nest, ALHabbrev_nest))
     *switch_code = ALH_nest;
   if (AlHelp_cmp_switch(argv[*index], ALHfull_output, ALHabbrev_output))
     *switch_code = ALH_output;

   if (*switch_code != ALH_none)   /* it was a no_arg switch, done */
     { (*index)++;
       return(Bool_TRUE);
     };

   /* Check the switches that take fixed arguments */
   /* -------------------------------------------- */
   *switch_type = ALH_fixed_arg_switch;
   *switch_code = ALH_none;
   *switch_arg = NULL;
   if (AlHelp_cmp_switch(argv[*index], ALHfull_state, ALHabbrev_state))
     *switch_code = ALH_state;
   if (AlHelp_cmp_switch(argv[*index], ALHfull_uprop, ALHabbrev_uprop))
     *switch_code = ALH_uprop;
   if (AlHelp_cmp_switch(argv[*index], ALHfull_data, ALHabbrev_data))
     *switch_code = ALH_data;
   if (AlHelp_cmp_switch(argv[*index], ALHfull_warn, ALHabbrev_warn))
     *switch_code = ALH_warn;
   if (AlHelp_cmp_switch(argv[*index], ALHfull_after, ALHabbrev_after))
     *switch_code = ALH_after;
   if (AlHelp_cmp_switch(argv[*index], ALHfull_before, ALHabbrev_before))
     *switch_code = ALH_before;
   if (AlHelp_cmp_switch(argv[*index], ALHfull_rule, ALHabbrev_rule))
     *switch_code = ALH_rule;
   if (AlHelp_cmp_switch(argv[*index], ALHfull_traffic, ALHabbrev_traffic))
     *switch_code = ALH_traffic;

   if (*switch_code != ALH_none)   /* it was a fixed_arg switch, done */
     { if ((*index < argc) && (*(argv[*index + 1]) != '-'))
	 { *switch_arg = argv[*index + 1];
	   (*index) += 2;
	   return(Bool_TRUE);
	 }
       else
	 { /* The fixed argument was invalid */
	   *switch_type = ALH_bad_switch;
	   *switch_code = ALH_none;
           *switch_arg = argv[*index];
	   (*index) += 1;
	   return(Bool_TRUE);
	 };
     };

   /* Check the switches that take an object as an argument */
   /* ----------------------------------------------------- */
   *switch_type = ALH_object_arg_switch;
   *switch_code = ALH_none;
   *switch_arg = NULL;
   if (AlHelp_cmp_ob_switch(argv[*index], ALHfull_io_filename))
     *switch_code = ALH_io_filename;
   if (AlHelp_cmp_ob_switch(argv[*index], ALHfull_folder))
     *switch_code = ALH_folder;
   if (AlHelp_cmp_ob_switch(argv[*index], ALHfull_load_filename))
     *switch_code = ALH_load_filename;
   if (AlHelp_cmp_ob_switch(argv[*index], ALHfull_msgsrc))
     *switch_code = ALH_msgsrc;
   if (AlHelp_cmp_ob_switch(argv[*index], ALHfull_std_msgtype))
     *switch_code = ALH_std_msgtype;
   if (AlHelp_cmp_ob_switch(argv[*index], ALHfull_new_msgtype))
     *switch_code = ALH_new_msgtype;
   if (AlHelp_cmp_ob_switch(argv[*index], ALHfull_ruleset))
     *switch_code = ALH_ruleset;
   if (AlHelp_cmp_ob_switch(argv[*index], ALHfull_server))
     *switch_code = ALH_server;

   if (*switch_code != ALH_none)   /* it was an object_arg switch, done */
     { if (*(argv[*index] + 3) != '\0')
	 { *switch_arg = argv[*index] + 3;
	   (*index)++;
	   return(Bool_TRUE);
	 }
       else
	 { /* The object argument was an empty string */
	   *switch_type = ALH_bad_switch;
	   *switch_code = ALH_none;
           *switch_arg = argv[*index];
	   (*index)++;
	   return(Bool_TRUE);
	 };
     };

   /* This was an error. Unknown or bad switch */
   /* ---------------------------------------- */
   *switch_type = ALH_bad_switch;
   *switch_code = ALH_none;
   *switch_arg = argv[*index];
   (*index)++;
   return(Bool_TRUE);

 };         /* end of AlHelp_get_arg()  */


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

char *AlHelp_mask_to_switch(switch_type, switch_code)
     AlH_MASK
       switch_type,  /* returned mask, for type of switch (ex: fixed_arg )  */
       switch_code;  /* returned mask, for a switch code (ex: ALH_state )   */
 {
   switch(switch_type)
     { case ALH_no_arg_switch:
	     switch(switch_code)
	       { case ALH_create:   return(ALHfull_create);    break;
	       case ALH_eliminate:  return(ALHfull_elim);      break;
	       case ALH_force:      return(ALHfull_force);     break;
	       case ALH_help:       return(ALHfull_help);      break;
	       case ALH_nest:       return(ALHfull_nest);      break;
	       case ALH_output:     return(ALHfull_output);    break;
	       default:             return("<not a switch>");  break;
	       };
	     break;

       case ALH_fixed_arg_switch:
	     switch(switch_code)
	       {  case ALH_state:    return(ALHfull_state);    break;
	          case ALH_uprop:    return(ALHfull_uprop);    break;
	          case ALH_data:     return(ALHfull_data);     break;
	          case ALH_warn:     return(ALHfull_warn);     break;
	          case ALH_after:    return(ALHfull_after);    break;
	          case ALH_before:   return(ALHfull_before);   break;
	          case ALH_rule:     return(ALHfull_rule);     break;
	          case ALH_traffic:  return(ALHfull_traffic);  break;
	          default:           return("<not a switch>"); break;
	       };
	     break;

       case ALH_object_arg_switch:
	     switch(switch_code)
	       { case ALH_io_filename:   return(ALHfull_io_filename);    break;
	         case ALH_folder:        return(ALHfull_folder);         break;
	         case ALH_std_msgtype:   return(ALHfull_std_msgtype);    break;
	         case ALH_new_msgtype:   return(ALHfull_new_msgtype);    break;
	         case ALH_load_filename: return(ALHfull_load_filename);  break;
	         case ALH_ruleset:       return(ALHfull_ruleset);        break;
	         case ALH_msgsrc:        return(ALHfull_msgsrc);         break;
	         case ALH_server:        return(ALHfull_server);         break;
	         default:                return("<not a switch>");       break;
	       };
	     break;

       default:
	 return("<not a switch>");
	 break;
     };    /* end of switch()  */

 };         /* end of AlHelp_mask_to_switch()  */


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