/*******************************************************************************
* YORKTOWN ADVANCED SGML PARSER (YASP)                                         *
*         An SGML Parser conforming to International Standard ISO 8879 --      *
*         Standard Generalized Markup Language                                 *
*------------------------------------------------------------------------------*
* Written 1987 - 1993 by                                                       *
*         Pierre G. Richard                                                    *
*         IBM T.J. Watson Research Center                                      *
*         Yorktown Heights, New York                                           *
*         petrus@watson.ibm.com                                                *
*------------------------------------------------------------------------------*
* FUNCTION NAME    = SGML Parser / Message Table creation                      *
* STATUS           = Version 0, Release 1, Level 25 and up                     *
* COMPONENT NAME   = gnmsg.c                                                   *
* DESCRIPTIVE NAME = Build messages.                                           *
* DATE_WR          = 01/29/1990                                                *
* AUTHOR           = Pierre G. Richard - PETRUS at YKTVMX                      *
*                                                                              *
* FUNCTIONAL DESCRIPTION =                                                     *
* Just a tool for me, because I'm making too much mistakes when I'm changing   *
* the messages.                                                                *
*                                                                              *
* IMPLEMENTATION NOTE =                                                        *
*                                                                              *
* DEPENDENCIES =  (see Include list)                                           *
*                                                                              *
* IMPORT=                                                                      *
*                                                                              *
* EXPORT=                                                                      *
*                                                                              *
* CHANGE HISTORY =                                                             *
* Number Date     Inits    Change & Reason (brief)                             *
*******************************************************************************/

/*-------------+
|Include Files |
+-------------*/
#include "machine.h"
#include "portable.h"
#include "gnmsgdef.h"
#if (defined(IBMCAIX) || defined(SUNACC) || defined(GNUCC))
/* If this is true for all UNIX systems, replace by defined (AIX_SYS) */
#include <sys/types.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <time.h>

typedef enum {
#include "msgcode.h"
}MSGCODE;


#define SEPOPT '/'
#define YSP_TXT  "YSP.TXT"
#define MESSAGE_H "message.h"
#define nbrlines(L)   (sizeof(L)/sizeof(char *))

static char beg_of_prod[] =
"/*@ Produced by gnmsg.exe %.24s --- do not change directly */\n";
static char end_of_prod[] =
"/*@ End of production (gnmsg.exe) ------------\
------------------------------- */\n";

static uchar* first_lines[] = {
   "/*******************************************************************************",
   "* YORKTOWN ADVANCED SGML PARSER (YASP)                                         *",
   "*         An SGML Parser conforming to International Standard ISO 8879 --      *",
   "*         Standard Generalized Markup Language                                 *",
   "*------------------------------------------------------------------------------*",
   "* Written 1987 - 1993 by                                                       *",
   "*         Pierre G. Richard                                                    *",
   "*         IBM T.J. Watson Research Center                                      *",
   "*         Yorktown Heights, New York                                           *",
   "*         petrus@watson.ibm.com                                                *",
   "*------------------------------------------------------------------------------*",
   "* FUNCTION NAME    = YASP / SGML Library                                       *",
   "* STATUS           = Version 0, Release 1, Level 25 and up                     *",
   "* COMPONENT NAME   = message.h                                                 *",
   "* DESCRIPTIVE NAME = Define message formats                                    *",
   "* DATE_WR          = 01/28/1990                                                *",
   "* AUTHOR           = Pierre G. Richard - PETRUS at YKTVMX                      *",
   "*                                                                              *",
   "* FUNCTIONAL DESCRIPTION =                                                     *",
   "* Get the format of a message given its message identifier.                    *",
   "*******************************************************************************/",
   "",
   "static unsigned char null_data[] = \"\";",
   "static unsigned char FAR_D const * FAR_D const message_array[] = {"
};

static uchar *null_data = "null_data";

static boolean is_special;   /* for my OWN use */
static uchar *txt_fn;
static uchar *h_fn;

/*--------------+
|Local Functions|
+--------------*/
static void P_FCT format(uchar *, uchar *, uchar *);
static void     print_lines    (FILE *, char **, int);
static boolean  initarg        (int, char **);
static void     usage          (void);

/*STATIC-----------------------------------------------------------------usage-+
|Explain how to use this program                                               |
+-----------------------------------------------------------------------------*/
static void usage(void)
{
   static char *msg[] = {
      "",
      "----------------------------------------------------------------",
      "Usage: GNMSG [options] [tfile hfile]",
      "",
      "   tfile: name of the TXT file to be created (default: YSP.TXT)",
      "   hfile: name of the H file to be created (default: MESSAGE.H)",
      "",
      " options: /d message renumbering ** for YASP developper only **",
      "          /h displays this help text",
      "",
      "Purpose: create a new MESSAGE.H and an associated TXT",
      "         reading MSGSTR.H and MSGCODE.H",
      "         when a new message is added to YASP",
      "----------------------------------------------------------------"
   };
   char **c_pp;
   uint count;

   for (c_pp=msg, count=sizeof(msg)/sizeof(char *); count--; ++c_pp) {
      printf("%s\n",*c_pp);
   }
}


/*STATIC---------------------------------------------------------------initarg-+
|Decode the /options and parameters on the command line                        |
+-----------------------------------------------------------------------------*/
static boolean initarg(int argc, char **argv)
{
   uint prm_pos;
   uchar *c_p;
   boolean bad_syntax = FALSE;

   is_special = FALSE;
   prm_pos = 0;                 /* count for positional parm */
   while (--argc) {
      if (*(c_p = *++argv) == SEPOPT) {
         while (*++c_p) {
            switch(*c_p) {      /* keywords parm */
            case 'h':
            case 'H':
               bad_syntax = TRUE;
               break;
            case 'd':
            case 'D':
               is_special = TRUE;
               break;
            default :
               bad_syntax = TRUE;
               break;
            }
         }
      }else {
         switch(++prm_pos) {                /* Positional parms */
         case 1:
            txt_fn = c_p;                   /* get the file name */
            break;
         case 2:
            h_fn = c_p;
            break;
         default:
            bad_syntax = TRUE;              /* no more than 1 allowed */
            break;
         }
      }
   }
   if (bad_syntax) {                        /* send explanations */
      usage();
      return(FALSE);
   }else {
      switch (prm_pos) {
      case 0:
         txt_fn = YSP_TXT;                  /* default TXT file */
      case 1:
         h_fn = MESSAGE_H;                 /* default H file */
      default:
         break;
      }
      return(TRUE);
   }
}


/*STATIC----------------------------------------------------------------format-+
|                                                                              |
+-----------------------------------------------------------------------------*/
static void P_FCT format(uchar *c_p, uchar *d_p, uchar *s_p)
{
   uchar ivcount = '0';
   uchar *c_p0 = c_p;                   /* save pointer to buffer start */

   --d_p;
   --c_p;
   --s_p;                               /* dummy entry */
   while (*++s_p) {
      if (*s_p != '%') {
         do *++c_p = *s_p; while ((*++s_p) && (*s_p != '%'));
         if (!*s_p) break;
      }
      if (*++s_p == '%') {
         *++c_p = '%';
         continue;
      }
      *++d_p = *++c_p = '%';
      if (*s_p == '-') *(++d_p) = *(s_p++);
      if (*s_p == '0') *(++d_p) = *(s_p++);
      if (isdigit(*s_p)) do *(++d_p) = *(s_p++); while (isdigit(*s_p));
      if (*s_p == '.')   do *(++d_p) = *(s_p++); while (isdigit(*s_p));
      if (*s_p == 'l') *(++d_p) = *(s_p++);
      *++d_p = *s_p;
      *++c_p = ++ivcount;
   }
   if (!ivcount) {
      memcpy(++d_p, null_data, 1 + strlen(null_data));
   }else {
      *++d_p = '\0';
   }
   *++d_p = '\0';
   *++c_p = '\0';
   /* Remove all stuff that is after double_slash */
   c_p = c_p0;
   while ((c_p = strchr(c_p, '/')) != NULL) {
      if (*++c_p == '/') {
         *(c_p - 1) = '\0';
         break;
      }
   }
}

/*-----------------------------------------------------------------------------+
|                                                                              |
+-----------------------------------------------------------------------------*/
static void print_lines(FILE *f_p, char **line, int  count)
{
   for ( ; count--; ++line) fprintf(f_p,"%s\n",*line);
}

/*------------------------------------------------------------------------main-+
|                                                                              |
+-----------------------------------------------------------------------------*/
int main(uint argc, uchar *argv[])
{
   uint i;
   MSGDEF *msgdef_p;
   uchar buffer[150], ivarray[40];
   FILE *txt_f_p, *msg_f_p;
   time_t ltime;

   if (!initarg(argc,argv)) return(4);
   txt_f_p = fopen(txt_fn,"w");
   msg_f_p = fopen(h_fn,"w");

   time(&ltime);
   fprintf(msg_f_p,beg_of_prod,ctime(&ltime));
   print_lines(msg_f_p,first_lines,nbrlines(first_lines));
   if (is_special) {
      fprintf(txt_f_p,"%-10sYSP\n"," ");
   }else {
      fprintf(txt_f_p,"YSP\n");
   }
   for (i=0; i <= UNKNOWN; ++i) {
      msgdef_p = msgdef_get(i);
      format(buffer,ivarray,msgdef_p->lit);
      if (is_special) {
         fprintf(txt_f_p,"%-10sYSP%04dW: %s\n",msgdef_p->cod,i,buffer);
      }else {
         fprintf(txt_f_p,"YSP%04dW: %s\n",i,buffer);
      }
      if (*ivarray) {
         fprintf(msg_f_p,"   (uchar *)\"%s\"",ivarray);
      }else {
         fprintf(msg_f_p,"   %s",null_data);
      }
      fprintf(msg_f_p,"%s",i==UNKNOWN ? "\n};\n" : ",\n");
   }
   fprintf(msg_f_p,end_of_prod,ctime(&ltime));
   fclose(txt_f_p);
   fclose(msg_f_p);
}
/******************************************************************************/
