/* char_arr
* Create C header files for the conversion of character tables
* Dr. Burkhard Kirste 1993/07/13
* [email protected]
* usage: char_arr [-h] -f from_table -t to_table [[-o] output_file]]
* requires: sys_def.h, getopt.c, charstab.h
* cc char_arr.c getopt.c -o char_arr
*/
#define VERSION "1.00"
#include "sys_def.h"
#ifdef __ANSI
#include <string.h>
#include <stdlib.h>
#else
#ifdef sun
#include <stdlib.h>
#endif
#endif                          /* stdlib */
#include "charstab.h"           /* character tables */

#ifndef EOF
#define EOF -1
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef MAXPATHLEN
#define MAXPATHLEN 128          /* max. length of path names */
#endif

#define NPERLINE 8              /* array: numbers per line */


/* prototypes */
#ifdef __ANSI
#define PROTO(x) x
#else
#define PROTO(x) ()
#endif

int getopt      PROTO((int argc, char **argv, char *opts));
int write_table
PROTO((FILE *fp, char **from_table, char **to_table,
      int nperline));
 int write_str   PROTO((FILE *fp, char **from_table, int to_type,
                                        int nperline));
 int make_table  PROTO((char ***tablep, int table_type));

#undef PROTO

/* globals */
 static char     sccsid[] = "@(#)char_arr create headers. 93/07/13 BKi";
 extern char    *optarg;       /* option arg. (getopt) */
 extern int      optind, optopt;       /* option index (getopt) */

 int
                 write_table(fp, from_table, to_table, nperline)
 FILE           *fp;
 char          **from_table, **to_table;
 int             nperline;

/*
* write header for character conversion table
* 1993/07/10 BKi
* FILE *fp: output file
* char **from_table: source character table
* char **to_table: aim character table
* int nperline: entries per line
*/
{
 int             i, j;
 char           *ptr;

 fprintf(fp, "char ctable[] = {\n  ");
 for (i = 0; i < 256; i++)
 {
   ptr = from_table[i];
   for (j = 0; j < 256; j++)
     if (strcmp(ptr, to_table[j]) == 0)
       break;
   if (j >= 256)
     j = i;
   if (i > 0)
   {
     if (i % nperline == 0)
       fprintf(fp, ",\n  ");
     else
       fprintf(fp, ",");
   }
   fprintf(fp, "0x%02x", j);
 }                             /* for i */
 fprintf(fp, "};\n");
 fprintf(fp, "\n/* %d entries */\n", i);
 return 0;
}                               /* write_table */

int
write_str(fp, from_table, to_type, nperline)
 FILE           *fp;
 char          **from_table;
 int             to_type;
 int             nperline;

/*
* write header for string-coded character table
* 1993/07/10 BKi
* FILE *fp: output file
* char **from_table: source character table
* int to_type: aim (0 ... 3)
* int nperline: entries per line
* global: trans_string
*/
{
 int             i, j;
 char           *ptr;

 fprintf(fp, "char *stable[] = {\n  ");
 for (i = 0; i < 256; i++)
 {
   ptr = from_table[i];
   if (to_type > 0)
   {
     for (j = 0; j < TRANS_ROW; j++)
       if (strcmp(ptr, trans_string[j][0]) == 0)
       {
         ptr = trans_string[j][to_type];
         break;
       }
     if (j >= 256)
       ptr = NULL;
   }
   if (i % nperline == 0)
     fprintf(fp, ",\n  ");
   else
     fprintf(fp, ",");
   if (ptr != NULL)
   {
     fputc('"', fp);
     for (j = 0; j < strlen(ptr); j++)
     {
       if (ptr[j] == '"' || ptr[j] == '\\')
         fputc('\\', fp);
       fputc(ptr[j], fp);
     }
     fputc('"', fp);
   } else
     fprintf(fp, "\"\\\\%03o\"", i);
 }                             /* for i */
 fprintf(fp, "};\n");
 fprintf(fp, "\n/* %d entries */\n", i);
 return 0;
}                               /* write_str */

int
make_table(tablep, table_type)
 char         ***tablep;
 int             table_type;

/*
* make ASCII or EBCDIC table
* 1993/07/10 BKi
* char ***tablep: pointer to table of strings (output)
* int table_type: 0 (ASCII) or 1 (EBCDIC)
* global: char *iso_table[], char ebc2asc[]
*/
{
 int             i, j;
 char          **table;

 table = (char **) calloc(256, sizeof(char *));
 if (table == NULL)
 {
   fprintf(stderr, "make_table: memory allocation error.\n");
   return 1;
 }
 for (i = 0; i < 256; i++)
 {
   if (table_type == 1)
     j = (int) ebc2asc[i] & 0xff;
   else
     j = i;
   if (j < 128)
   {
     table[i] = (char *) malloc(sizeof(iso_table[j]));
     if (table[i] == NULL)
     {
       fprintf(stderr, "make_table (2): memory allocation error.\n");
       return 1;
     }
     strcpy(table[i], iso_table[j]);
   } else
   {
     table[i] = (char *) malloc(5);
     if (table[i] == NULL)
     {
       fprintf(stderr, "make_table (3): memory allocation error.\n");
       return 1;
     }
     sprintf(table[i], "\\%03o", j);
   }
 }                             /* for i */
 *tablep = table;
 return 0;
}                               /* make_table */

int
main(argc, argv)
 int             argc;
 char          **argv;
{
 static char     opts[] = "hvf:t:o:";  /* options (getopt) */
 static char     allowed[] = "acdehlmrst";     /* known table types */
 int             optcheck = 0; /* check validity of options */
 int             c;            /* character */
 int             i;
 int             from_type, to_type;   /* source and aim type of conversion */
 char            fname[MAXPATHLEN];    /* output file name */
 char          **from_table, **to_table;       /* character conversion
                                                * tables */
 char          **asc_table = NULL;     /* optional ASCII table */
 char          **ebc_table = NULL;     /* optional EBCDIC table */
 FILE           *fp = NULL;    /* output file */

 /* get options */
 fname[0] = '\0';
 do
 {
   if ((c = getopt(argc, argv, opts)) == EOF)
     break;
   switch (c)
   {
   case 'v':
     fprintf(stderr, "%s %s\n", VERSION, sccsid);
   case 'h':
   case '?':
     c = '?';
     optcheck = 0;
     break;
   case 'f':
     from_type = (int) optarg[0] & 0xff;
     optcheck |= 1;
     break;
   case 't':
     to_type = (int) optarg[0] & 0xff;
     optcheck |= 2;
     break;
   case 'o':
     strncpy(fname, optarg, MAXPATHLEN);
     fname[MAXPATHLEN - 1] = '\0';
     /* break; */
   }                           /* options switch */
   if (c == '?')
     break;
 } while (TRUE);
 if (optcheck == 3)
 {
   /* check validity of arguments */
   if (strchr(allowed, from_type) == NULL)
   {
     fprintf(stderr, "Unknown character table '%c' (-f)\n",
             (char) from_type);
     optcheck = 0;
   }
   if (strchr(allowed, to_type) == NULL)
   {
     fprintf(stderr, "Unknown character table '%c' (-t)\n",
             (char) to_type);
     optcheck = 0;
   }
 }
 if (optcheck != 3)
 {
   fprintf(stderr,
         "usage: char_arr -f from_table -t to_table [[-o] output_file]\n");
   fprintf(stderr, "  where from_table/to_table is one of:\n");
   fprintf(stderr, "  a - ASCII (7 bit)\n");
   fprintf(stderr, "  c - transcript (*)\n");
   fprintf(stderr, "  d - DOS code page 437\n");
   fprintf(stderr, "  e - EBCDIC\n");
   fprintf(stderr, "  h - HTML (hypertext) (*)\n");
   fprintf(stderr, "  l - ISO Latin 1 (Unix, ANSI, MS Windows)\n");
   fprintf(stderr, "  m - Apple Macintosh\n");
   fprintf(stderr, "  r - Atari ST\n");
   fprintf(stderr, "  s - Symbol font\n");
   fprintf(stderr, "  t - TeX (*)\n");
   fprintf(stderr, "    (*) string code, output (-t) only!\n");
   return 1;
 }
 if (optind < argc)
 {
   strncpy(fname, argv[optind++], MAXPATHLEN);
   fname[MAXPATHLEN - 1] = '\0';
 }
 /* find conversion tables */
 switch (from_type)
 {
 case 'a':
   if (asc_table == NULL)
   {
     if (make_table(&asc_table, 0) == 0)
       from_table = asc_table;
     else
       from_table = NULL;
   } else
     from_table = asc_table;
   break;
 case 'd':
   from_table = pc_table;
   break;
 case 'e':
   if (ebc_table == NULL)
   {
     if (make_table(&ebc_table, 1) == 0)
       from_table = ebc_table;
     else
       from_table = NULL;
   } else
     from_table = ebc_table;
   break;
 case 'l':
   from_table = iso_table;
   break;
 case 'm':
   from_table = mac_table;
   break;
 case 'r':
   from_table = st_table;
   break;
 case 's':
   from_table = sym_table;
   break;
 default:
   from_table = NULL;
 }                             /* switch */
 switch (to_type)
 {
 case 'a':
   if (asc_table == NULL)
   {
     if (make_table(&asc_table, 0) == 0)
       to_table = asc_table;
     else
       to_table = NULL;
   } else
     to_table = asc_table;
   break;
 case 'd':
   to_table = pc_table;
   break;
 case 'e':
   if (ebc_table == NULL)
   {
     if (make_table(&ebc_table, 1) == 0)
       to_table = ebc_table;
     else
       to_table = NULL;
   } else
     to_table = ebc_table;
   break;
 case 'l':
   to_table = iso_table;
   break;
 case 'm':
   to_table = mac_table;
   break;
 case 'r':
   to_table = st_table;
   break;
 case 's':
   to_table = sym_table;
   break;
 default:
   to_table = NULL;
 }                             /* switch */
 if (from_table == NULL)
   exit(1);
 if (strlen(fname))
 {
   fp = fopen(fname, "w");
   if (fp == NULL)
   {
     fprintf(stderr, "Error opening output file %s\n", fname);
     exit(1);
   }
 } else
   fp = stdout;
 if (to_table != NULL)
   write_table(fp, from_table, to_table, (int) NPERLINE);
 else
 {
   switch (to_type)
   {
   case 'c':
     to_type = 0;
     break;
   case 't':
     to_type = 1;
     break;
   case 'h':
     to_type = 2;
     break;
   default:
     to_type = -1;
   }
   if (to_type >= 0)
     write_str(fp, from_table, to_type, (int) NPERLINE);
 }
 if (fp != stdout && fp != NULL)
   fclose(fp);
 if (ebc_table != NULL)
 {
   for (i = 255; i >= 0; i--)
     if (ebc_table[i] != NULL)
       free(ebc_table[i]);
   if (ebc_table != NULL)
     free(ebc_table);
 }
 if (asc_table != NULL)
 {
   for (i = 255; i >= 0; i--)
     if (asc_table[i] != NULL)
       free(asc_table[i]);
   if (asc_table != NULL)
     free(asc_table);
 }
 return 0;
}                               /* main */