/*+JMJ
* cmd.c - tir HTML renderer command line interface
* Copyright 2011 David Meyer <[email protected]>
* cmd.c is part of tirrender
*
* 2011-07-28
* cmd.c implements a command line interface for the tirrender
* HTML rendering engine (implemented in common.c). The command
* line interface is intended for testing rendering functionality
* and for static rendering (rendered output saved to .html file
* for later and repeated access). cgi.c will implement CGI
* interface for dynamic rendering (rendered output generated for
* each HTTP request and returned to browser).
*/

#include <stdio.h>
#include <string.h>
#include "krcompat.h"
#include "tirrender.h"

/* IDENTIFICATION: *************************************************/

#define PROGRAM "tirrender"
#define VERSION "0.0"
#define COPYRIGHT "Copyright 2011 David Meyer"
#define CONTACT "David Meyer <[email protected]>"
#define DESCRIPTION "tir HTML renderer for files and directories"
#define USAGE "Usage: tirrender [-hV] [-d <dataset>] [-l <location>] [-f <file>]"

/* CONSTANTS: ******************************************************/

/* MACROS: *********************************************************/

/* GLOBALS: ********************************************************/

/* PROTOTYPES: *****************************************************/

void msghelp ();
void msgversion ();
int parseopts PARAMS((int argc, char* argv[], int optstat, char *optarg[]));

/* MAIN: ***********************************************************/

/* main() parses and validates command line arguments, then calls
* render() if all OK.
*/
int main(argc, argv)
 int argc;
 char *argv[];
{
 int optstat = 0;                /* Specified options:
                                  * Bit 0: -d (dataset)
                                  *     1: -l (location)
                                  *     2: -f (file)
                                  *     3: -h (help)
                                  *     4: -V (version)
                                  */
 char *optarg[3];                /* Option arguments:
                                  * [0]: -d (dataset)
                                  * [1]: -l (location)
                                  * [2]: -f (file)
                                  */

 optstat = parseopts(argc, argv, optstat, optarg);

 if (optstat & 8) {              /* Arg. -h: display help, exit */
   msghelp();
   exit(0);
 }

 if (optstat & 16) {             /* Arg. -V: display version, exit */
   msgversion();
   exit(0);
 }

                                 /* Arg. -d, <dataset> invalid:
                                  * display error, exit
                                  */
 if ((optstat & 1) && baddataset(optarg[0])) {
   printf("Error: invalid dataset\n");
   exit(1);
 }

                                 /* Arg. -l, <location> invalid:
                                  * display error, exit
                                  */
 if ((optstat & 2) && badlocation(optarg[1])) {
   printf("Error: invalid location\n");
   exit(1);
 }

                                 /* Arg. -f, <file> invalid:
                                  * display error, exit
                                  */
 if ((optstat & 4) && badfile(optarg[2])) {
   printf("Error: invalid file\n");
   exit(1);
 }

                                 /* Arg's OK: render specified
                                  * object or default
                                  */
 /* 2011-07-28
  * "specified object": instead of separate location and file
  * options, I could have single "object" option specified
  * with the file/directory path relative to the dataset root.
  * Use file status to determine file or directory rendering.
  */
 return render((optstat & 1) ? optarg[0] : DEFAULT_DATASET,
               (optstat & 2) ? optarg[1] : DEFAULT_LOCATION,
               (optstat & 4) ? optarg[2] : DEFAULT_FILE);

}

/* FUNCTIONS: ******************************************************/

/* msghelp() - display help message
*/
void msghelp ()
{
 printf("%s\n%s
-h                Display this information
-V                Display version
-d <dataset>      Render target dataset
-l <location>     Render target location (directory)
-f <file>         Render target file\n", DESCRIPTION, USAGE);
}

/* msgversion() - display program version message
*/
void msgversion ()
{
 printf("%s %s\n", PROGRAM, VERSION);
}

/* parseopts() - parse options in commnd line arguments
*/
int parseopts (argc, argv, optstat, optarg)
    int argc;
    char *argv[];
    int optstat;
    char *optarg[];
{
 int a, n;

 for (a = 1; a < argc; a++) {    /* for each argument */

                                 /* options d, l, f take arguments
                                  * and must be specified
                                  * individually.
                                  * opt. arg. value is either
                                  * string following opt. char.
                                  * or next argument.
   if (!strcmp(argv[a], "-d")) { /* arg. = -d: */
     optstat = optstat | 1;
     optarg[0] = (char *) malloc(strlen(argv[++a])+1);
     strcpy(optarg[0], argv[a]);
   }
                                 /* arg. = -d*: */
   else if (!strncmp(argv[a], "-d", 2)) {
     optstat = optstat | 1;
     optarg[0] = (char *) malloc(strlen(argv[a])-1);
     strcpy(optarg[0], argv[a]+2);
   }

                                 /* arg. = -l: */
   else if (!strcmp(argv[a], "-l")) {
     optstat = optstat | 2;
     optarg[1] = (char *) malloc(strlen(argv[++a])+1);
     strcpy(optarg[1], argv[a]);
   }
                                 /* arg. = -l*: */
   else if (!strncmp(argv[a], "-l", 2)) {
     optstat = optstat | 2;
     optarg[1] = (char *) malloc(strlen(argv[a])-1);
     strcpy(optarg[1], argv[a]+2);
   }

                                 /* arg. = -f: */
   else if (!strcmp(argv[a], "-f")) {
     optstat = optstat | 4;
     optarg[2] = (char *) malloc(strlen(argv[++a])+1);
     strcpy(optarg[2], argv[a]);
   }
                                 /* arg. = -f*: */
   else if (!strncmp(argv[a], "-f", 2)) {
     optstat = optstat | 4;
     optarg[2] = (char *) malloc(strlen(argv[a])-1);
     strcpy(optarg[2], argv[a]+2);
   }

   else if (argv[a][0] == '-') { /* flag arg. (-*) */
                                 /* for each char. in flag string */
     for (n = 1; n < strlen(argv[a]); n++) {

       if (argv[a][n] == 'h') {  /* flag opt. h */
         optstat = optstat | 8;
       }

                                 /* flag opt. V */
       else if (argv[a][n] == 'V') {
         optstat = optstat | 16;
       }

       else {                    /* unrecognized flag. opt. */
         printf("Invalid option: -%c\n%s\n", argv[a][n], USAGE);
         exit(0);
       }
     }
   }

   else {                        /* unrecognized arg.
                                  * for compatibility with CGI
                                  * query string format, c.l.
                                  * I/F has no non-option args.
                                  */
     printf("Invalid argument: %s\n%s\n", argv[a], USAGE);
     exit(0);
   }
 }
 return optstat;
}