home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume5 / untic / untic.c < prev   
Encoding:
C/C++ Source or Header  |  1986-11-30  |  10.1 KB  |  394 lines

  1. /*
  2.  * Untic.c -- Uncompile a terminfo file
  3.  *
  4.  * Usage:
  5.  *    untic terminal_name . . .
  6.  *
  7.  * This program finds the terminal description in
  8.  *    /usr/lib/terminfo/?/terminal_name
  9.  * It then converts the information into an ASCII file suitable for
  10.  * running into "tic".  The resulting file is written to standard output.
  11.  *
  12.  * Compile by:
  13.  *    cc -O -o untic untic.c
  14.  *
  15.  * It is probably a good idea to ensure that the file produced will compile
  16.  * to the original file before trusting "untic".
  17.  *
  18.  * Structure of terminfo file:
  19.  *    short    magic number
  20.  *    short    length of terminal names + NUL
  21.  *    short    length of booleans
  22.  *    short    length of numerics
  23.  *    short    length of strings
  24.  *    short    length of string table
  25.  *    chars    NUL terminated terminal name
  26.  *    chars    boolean flags for each of the possible booleans
  27.  *    shorts    values for each of the possible numerics
  28.  *    shorts    offsets (from start of strings) for each of the
  29.  *        possible strings
  30.  *    chars    NUL terminated strings for each of the defined strings
  31.  *
  32.  * Most of the variables are in the order that the documentation lists
  33.  * them.  This is important, as the information is stored in the file
  34.  * based upon the ordinal position of the variable.  Some of the string
  35.  * variables are not in order.  Presumably, if they add more variables,
  36.  * it will be to the end of the list, and not in the middle.
  37.  *
  38.  * This has been tested on
  39.  *    Plexus P20 (M68010), System 5 Release 2 (I think)
  40.  *
  41.  * Bugs:
  42.  *    The longest string capability is limited to 4096 bytes.  If a longer
  43.  *    string is encountered, the program will do unpredicatable things.
  44.  *    (Who uses strings that long anyway?)  The longest that the terminfo
  45.  *    file can be is 4096 bytes anyway, so this isn't too big a problem.
  46.  *
  47.  * Credits:
  48.  *    Written by Dave Regan
  49.  *    orstcs!regan
  50.  *    16 May 86
  51.  *
  52.  *    I disclaim that this program does anything useful.  It might also
  53.  *    do accidental damage.  Backup your original terminfo files.
  54.  *
  55.  *    This program is public domain.  That means you can do anything
  56.  *    you want with it.
  57.  */
  58.  
  59.  
  60. #include <stdio.h>
  61. #ifdef QC
  62. #define    OPEN_MODE    "rb"    /* Mode used to open terminfo files    */
  63. #define    void    int        /* Sigh . . .                */
  64. #else        /* QC */
  65. #include <ctype.h>
  66. #define    OPEN_MODE    "r"    /* Mode used to open terminfo files    */
  67. #endif        /* QC */
  68. #ifndef TRUE
  69. #define    TRUE    1
  70. #define    FALSE    0
  71. #endif        /* TRUE */
  72.  
  73. #define    DEBUG    FALSE        /* TRUE/FALSE to enable debugging output */
  74.  
  75. #ifdef BSD
  76. #define    TERMINFO_DIR    "/usr/static/sys5r2v2/usr/lib/terminfo"
  77. #endif        /* BSD */
  78. #ifndef TERMINFO_DIR
  79. #define    TERMINFO_DIR    "/usr/lib/terminfo"
  80. #endif        /* TERMINFO_DIR */
  81.  
  82.  
  83. #define    MAGIC    0x011A        /* Terminfo magic number        */
  84. #define    MAXLINE    65        /* Longest emited line            */
  85. #define    MAX_CAP    4096        /* Longest single capability        */
  86.  
  87. extern    char *strcpy();
  88.  
  89. int    line_len;        /* Current length of line        */
  90.  
  91. main(argc, argv)
  92.   int    argc;            /* Number of paramters            */
  93.   char    *argv[];        /* The parameters themselves        */
  94.     {
  95.     char subdir[2];        /* Subdirectory name            */
  96.     FILE *file;
  97.     extern FILE *fopen();
  98.  
  99. #ifdef CPM
  100.     wildexp(&argc, &argv);
  101. #endif        /* CPM */
  102.  
  103.     /* Change directory to the working directory            */
  104.     (void)chdir(TERMINFO_DIR);
  105.  
  106.     /* Go through the arguments                        */
  107.     subdir[1] = '\0';
  108.     if (argc == 1)
  109.     convert(stdin, "stdin");
  110.     else
  111.     {
  112.     while (--argc)
  113.         {
  114.         ++argv;
  115.         subdir[0] = argv[0][0];
  116.         (void)chdir(subdir);
  117.         if ((file = fopen(*argv, OPEN_MODE)) == NULL)
  118.         {
  119.         perror(*argv);
  120.         }
  121.         else
  122.         {
  123.         convert(file, *argv);
  124.         (void)fclose(file);
  125.         }
  126.         (void)chdir("..");
  127.         }
  128.     }
  129.     }
  130.  
  131.  
  132. /*
  133.  * Addchar -- Add a character
  134.  */
  135. char *
  136. addchar(cptr, ch)
  137.   char    *cptr;
  138.   int    ch;
  139.     {
  140.     char *addstr(), *addoctal();
  141.  
  142.     if (ch == 0x1B)
  143.     return (addstr(cptr, "\\E"));
  144.     if (ch == '\n')
  145.     return (addstr(cptr, "\\n"));
  146.     if (ch == '\r')
  147.     return (addstr(cptr, "\\r"));
  148.     if (ch == '\t')
  149.     return (addstr(cptr, "\\t"));
  150.     if (ch == '\b')
  151.     return (addstr(cptr, "\\b"));
  152.     if (ch == '\f')
  153.     return (addstr(cptr, "\\f"));
  154.     if (ch == ' ')
  155.     return (addstr(cptr, "\\s"));
  156.     if (ch == '^')
  157.     return (addstr(cptr, "\\^"));
  158.     if (ch == '\\')
  159.     return (addstr(cptr, "\\\\"));
  160.     if (ch == ',')
  161.     return (addstr(cptr, "\\,"));
  162.     if (ch == ':')
  163.     return (addstr(cptr, "\\:"));
  164.     if (ch >= ('A' - '@') && ch <= ('Z' - '@'))
  165.     {
  166.     *cptr++ = '^';
  167.     *cptr++ = ch + '@';
  168.     return (cptr);
  169.     }
  170. #ifdef notdef
  171.     /*
  172.      * Did you know that \r \n \f \t are NOT control characters
  173.      * as defined by "iscntrl" under BSD 4.2?  I find that
  174.      * rather odd.
  175.      */
  176. #endif        /* notdef */
  177.     if (iscntrl(ch) || isspace(ch) || ch > 0x7F)
  178.         return (addoctal(cptr, ch));
  179.     *cptr++ = ch;
  180.     return (cptr);
  181.     }
  182.  
  183.  
  184. /*
  185.  * Addoctal -- Add an octal character
  186.  *
  187.  * Use sprintf just in case "0" through "7" are not contiguous.  Some
  188.  * machines are weird.
  189.  */
  190. char *
  191. addoctal(cptr, ch)
  192.   char    *cptr;
  193.   int    ch;
  194.     {
  195.     char *addstr();
  196.  
  197.     ch &= 0xFF;
  198.  
  199.     if (ch == 0x80)
  200.     return (addstr(cptr, "\\0"));
  201.     (void)sprintf(cptr, "\\%03o", ch);
  202.     while (*cptr != '\0')
  203.     cptr++;
  204.     return (cptr);
  205.     }
  206.  
  207.  
  208. /*
  209.  * Addstr -- Add a string to the capability
  210.  */
  211. char *
  212. addstr(cptr, str)
  213.   char    *cptr, *str;
  214.     {
  215.     while (*str)
  216.     *cptr++ = *str++;
  217.     return (cptr);
  218.     }
  219.  
  220.  
  221. /*
  222.  * Convert -- Do the actual conversion
  223.  */
  224. convert(file, name)
  225.   FILE    *file;        /* The file with the compiled information    */
  226.   char    *name;        /* Printable version of the filename        */
  227.     {
  228.     int    ch, val, i, j, fail;
  229.     int name_length, bool_length, num_length, str_length, s_length;
  230.     char capability[MAX_CAP+1], *cptr, *addchar();
  231.  
  232.     static char *booleans[] =    /* Names of boolean variables, in order    */
  233.     { "bw", "am", "xsb", "xhp", "xenl", "eo", "gn", "hc", "km",
  234.       "hs", "in", "da", "db", "mir", "msgr", "os", "eslok", "xt",
  235.       "hz", "ul", "xon" };
  236.     static char *numerics[] =    /* Names of numeric variables, in order    */
  237.     { "cols", "it", "lines", "lm", "xmc", "pb", "vt", "wsl" };
  238.     static char *strings[] =    /* Names of string variables, not in strict
  239.                    order.  Makes things a little harder    */
  240.     { "cbt", "bel", "cr", "csr", "tbc", "clear", "el", "ed", "hpa",
  241.       "cmdch", "cup", "cud1", "home", "civis", "cub1", "mrcup",
  242.       "cnorm", "cuf1", "ll", "cuu1", "cvvis", "dch1", "dl1", "dsl",
  243.       "hd", "smacs", "blink", "bold", "smcup", "smdc", "dim", "smir",
  244.       "invis", "prot", "rev", "smso", "smul", "ech", "rmacs", "sgr0", 
  245.       "rmcup", "rmdc", "rmir", "rmso", "rmul", "flash", "ff", "fsl",
  246.       "is1", "is2", "is3", "if", "ich1", "il1", "ip", "kbs", "ktbc",
  247.       "kclr", "kctab", "kdch1", "kdl1", "kcud1", "krmir", "kel", "ked",
  248.       "kf0", "kf1", "kf10", "kf2", "kf3", "kf4", "kf5", "kf6", "kf7",
  249.       "kf8", "kf9", "khome", "kich1", "kil1", "kcub1", "kll", "knp",
  250.       "kpp", "kcuf1", "kind", "kri", "khts", "kcuu1", "rmkx", "smkx", 
  251.       "lf0", "lf1", "lf10", "lf2", "lf3", "lf4", "lf5", "lf6", "lf7",
  252.       "lf8", "lf9", "rmm", "smm", "nel", "pad", "dch", "dl", "cud",
  253.       "ich", "indn", "il", "cub", "cuf", "rin", "cuu", "pfkey", "pfloc",
  254.       "pfx", "mc0", "mc4", "mc5", "rep", "rs1", "rs2", "rs3", "rf",
  255.       "rc", "vpa", "sc", "ind", "ri", "sgr", "hts", "wind", "ht", "tsl",
  256.       "uc", "hu", "iprog", "ka1", "ka3", "kb2", "kc1", "kc3", "mc5p" };
  257.     int str_cap[sizeof(strings) / sizeof(char *)];
  258.  
  259.     /* Check the magic number out                    */
  260.     if (get2(file) != MAGIC)
  261.     {
  262.     fprintf(stderr, "\"%s\" is not a terminfo file\n", name);
  263.     return;
  264.     }
  265.  
  266.     /* Get the rest of the header information                */
  267.     name_length = get2(file);    /* Get the length of the terminal names    */
  268.     bool_length = get2(file);    /* Get the length of the booleans    */
  269.     num_length = get2(file);    /* Get the length of the numerics    */
  270.     str_length = get2(file);    /* Get the length of the strings    */
  271.     s_length = get2(file);    /* Get the length of the string tables    */
  272.  
  273.     /* Check for too many data items                    */
  274.     fail = FALSE;
  275.     if (bool_length > (sizeof(booleans) / sizeof(char *)))
  276.     {
  277.     fprintf(stderr, "Boolean variables have been added to terminfo.\n");
  278.     fail = TRUE;
  279.     }
  280.     if (num_length > (sizeof(numerics) / sizeof(char *)))
  281.     {
  282.     fprintf(stderr, "Numeric variables have been added to terminfo.\n");
  283.     fail = TRUE;
  284.     }
  285.     if (str_length > (sizeof(strings) / sizeof(char *)))
  286.     {
  287.     fprintf(stderr, "String variables have been added to terminfo.\n");
  288.     fail = TRUE;
  289.     }
  290.     if (fail)
  291.     {
  292.     fprintf(stderr,
  293. "Update the \"untic\" program.  Use \"xxx\" if needed.  Good luck.\n");
  294.     return;
  295.     }
  296.  
  297.     /* Time to get real information                    */
  298.     while ((ch = getc(file)) != '\0' && ch != EOF)
  299.     putchar(ch);
  300.     printf(",\n\t");
  301.  
  302.     /* Send out the non-null boolean variables                */
  303.     line_len = 0;
  304.     for (i = 0; i < bool_length; i++)
  305.     {
  306.     if ((ch = getc(file)) != 0)
  307.         emit(booleans[i]);
  308.     }
  309.  
  310.     /* The rest of the file is on a 16 bit boundary, so adjust the file    */
  311.     if ((name_length + bool_length) & 0x01)
  312.     (void)getc(file);
  313.  
  314.     /* Get the numeric variables                    */
  315.     for (i = 0; i < num_length; i++)
  316.     {
  317.     if ((val = get2(file)) != 0xFFFF)
  318.         {
  319.         (void)sprintf(capability, "%s#%d", numerics[i], val);
  320.         emit(capability);
  321.         }
  322.     }
  323.  
  324.     /* Get the string variables offsets                    */
  325.     for (i = 0; i < str_length; i++)
  326.     str_cap[i] = get2(file);
  327.  
  328.     /* Get the string variables themselves                */
  329.     for (i = 0; i < s_length; i++)
  330.     {
  331.     for (j = 0; j < str_length; j++)    /* Find the name    */
  332.         if (str_cap[j] == i)
  333.         break;
  334. #if DEBUG
  335.     if (j >= str_length)
  336.         fprintf(stderr, "Cannot find address %d\n", i);
  337. #endif        /* DEBUG */
  338.     (void)strcpy(capability, strings[j]);
  339.     cptr = &capability[strlen(capability)];
  340.     *cptr++ = '=';
  341.     for (; (ch = getc(file)) != '\0' && ch != EOF; i++)
  342.         cptr = addchar(cptr, ch);
  343.     *cptr = '\0';
  344.     emit(capability);
  345.     }
  346.  
  347.     printf("\n\n");
  348.     }
  349.  
  350.  
  351. /*
  352.  * Emit -- Emit the string
  353.  *
  354.  * Emit the given string, and append a comma.  If the line gets too long,
  355.  * send out a newline and a tab.
  356.  */
  357. emit(str)
  358.   char    *str;        /* String to emit                */
  359.     {
  360.     if ((line_len += strlen(str) + 2) > MAXLINE)
  361.     {
  362.     line_len = strlen(str) + 2;
  363.     printf("\n\t");
  364.     }
  365.     printf("%s, ", str);
  366.     }
  367.  
  368.  
  369. /*
  370.  * Get2 -- Get a two byte number
  371.  */
  372. get2(file)
  373.   FILE *file;        /* The file with the compiled information    */
  374.     {
  375.     short temp;
  376.  
  377.     temp = getc(file) & 0xFF;
  378.     return (temp + (getc(file) << 8));
  379.     }
  380.  
  381.  
  382. #ifdef CPM
  383. chdir(str)
  384.   char    *str;
  385.     {
  386.     }
  387.  
  388. perror(str)
  389.   char    *str;
  390.     {
  391.     fprintf(stderr, "Cannot open \"%s\"\n", str);
  392.     }
  393. #endif        /* CPM */
  394.