home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xtrapv33.zip / extensions / lib / xtrap / chparse.c next >
C/C++ Source or Header  |  1992-09-14  |  10KB  |  401 lines

  1. /*****************************************************************************
  2. Copyright 1987, 1988, 1989, 1990, 1991 by Digital Equipment Corp., Maynard, MA
  3.  
  4. Permission to use, copy, modify, and distribute this software and its 
  5. documentation for any purpose and without fee is hereby granted, 
  6. provided that the above copyright notice appear in all copies and that
  7. both that copyright notice and this permission notice appear in 
  8. supporting documentation, and that the name of Digital not be
  9. used in advertising or publicity pertaining to distribution of the
  10. software without specific, written prior permission.  
  11.  
  12. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  13. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  14. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  15. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  16. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  17. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  18. SOFTWARE.
  19.  
  20. *****************************************************************************/
  21. /*
  22. **++
  23. **  FACILITY:  chparse - ASCII ESC & CSI parser
  24. **
  25. **  MODULE DESCRIPTION:
  26. **
  27. **      This module accepts single character I/O from
  28. **      stdin and returns a parsed character or sequence
  29. **      of characters.  This is to be used in conjunction
  30. **      with passing data from dragon-speak to XTrap.
  31. **
  32. **  AUTHORS:
  33. **
  34. **      Roy Lomicka (revised by Martin Minow & later Kenneth B. Miller)
  35. **
  36. **  CREATION DATE:  March 26, 1991
  37. **
  38. **  DESIGN ISSUES:
  39. **
  40. **      The algorithm is rather obscure.  However, it was decided
  41. **      that it should be left in its original condition since it
  42. **      closely depicts the state transition diagram for ASCII
  43. **      sequences (about the only good thing goto's are for;) .
  44. **      The old-fashioned bracketing and tabbing schemed were
  45. **      also preserved for posterity.
  46. **
  47. **--
  48. */
  49.  
  50. #include    <stdio.h>
  51. #include    <ctype.h>
  52. #ifdef vms
  53. #include    <ssdef.h>
  54. #include    <stsdef.h>
  55. #include    <iodef.h>
  56. #include    <descrip.h>
  57. #else
  58. #include    <sys/types.h>
  59. #include    <sys/time.h>
  60. #endif
  61.  
  62. #ifndef    VERBOSE
  63. #define    VERBOSE    0
  64. #endif
  65.  
  66. #ifndef FALSE
  67. #define    FALSE    0
  68. #define    TRUE    1
  69. #endif
  70. #define    EOS    '\0'
  71. #define    ERROR    (-1)
  72. #define    TIMEOUT    (-2)
  73. #define    NPARAM    8
  74. #define    NINTER    8
  75. #define    BUFFLEN    10            /* Size of typeahead buffer    */
  76. #ifndef    EXIT_SUCCESS
  77. #ifdef vms
  78. #define    EXIT_SUCCESS    (SS$_NORMAL | STS$M_INHIB_MSG)
  79. #define    EXIT_FAILURE    (SS$_ABORT)
  80. #else
  81. #define EXIT_SUCCESS    0
  82. #define EXIT_FAILURE    1
  83. #endif
  84. #endif
  85.  
  86. #define    NUL    0x00
  87. #define    CAN    0x18
  88. #define    SUB    0x1A
  89. #define    ESC    0x1B
  90. #define DEL    0x7F
  91. #define SS3     0x8f
  92. #define    DCS    0x90
  93. #define    CSI    0x9B
  94. #define    ST    0x9C
  95. #define    OSC    0x9D
  96. #define    PM    0x9E
  97. #define    APC    0x9F
  98.  
  99. /*
  100.  * Escape sequence parser, obscure but useful.
  101.  */
  102. int chparse(max_delay, rest_delay, state,
  103.     private, param, nparam, inter, ninter, final)
  104. int        max_delay;
  105. int        rest_delay;
  106. int        *state;        /* Parser state (n.z. if incomplete)    */
  107. int        *private;    /* Sequence private char, 'X' if error    */
  108. int        param[];    /* numeric param, starting at param[1]    */
  109. int        *nparam;    /* Number of parameters            */
  110. int        inter[];    /* intermediate char, starting at [1]    */
  111. int        *ninter;    /* Number of intermediates        */
  112. int        *final;        /* Sequence terminator            */
  113. {
  114.         int  present[NPARAM]; /* TRUE if param[i] is not defaulted    */
  115.     register int        c;
  116.     register int        i;
  117.  
  118.     if (*state == 0)
  119.         *private = 0;
  120. label1:    c = kbinr(max_delay);
  121. #if 0
  122.     printf("c %02x, *state %02x, *nparam %d\n", c, *state, *nparam);
  123. #endif
  124.     max_delay = rest_delay;
  125. label2:    switch (c) {
  126.     case NUL:
  127.     case DEL:
  128.         goto label5;
  129.     case ESC:
  130.     case CSI:
  131.         case SS3:
  132.     case DCS:
  133.     case OSC:
  134.     case PM:
  135.     case APC:
  136.         *state = c;
  137.         *private = 0;
  138.         for (i = 0; i < NPARAM; i++)
  139.         param[i] = present[i] = 0;
  140.         for (i = 0; i < NINTER; i++)
  141.         inter[i] = EOS;
  142.         *nparam = *ninter = 0;
  143.         goto label1;
  144.     }
  145.     if (*state == 0)
  146.         goto label5;
  147.     if ((c >= 0x80 && c < 0xA0)
  148.      || c == TIMEOUT
  149.      || c == ERROR
  150.      || c == CAN
  151.      || c == SUB) {
  152.         *state = 0;
  153.         goto label5;
  154.     }
  155.     if (c < 0x20)                /* Doesn't stop seq.    */
  156.         goto label5;
  157.     if (c <= 0x2F) {
  158.         if (*ninter < 7)
  159.         inter[++*ninter] = c;
  160.         goto label1;
  161.     }
  162.     if (*state == ESC) {
  163.         if (*ninter == 0
  164.          && (c & 0x3F) < 0x20) {
  165.         c = (c & 0x3F) + 0x80;
  166.         goto label2;
  167.         }
  168.         goto label4;
  169.     }
  170.     if (c >= 0x40)
  171.         goto label3;
  172.     else if (c >= 0x3C) {            /* Private introducer    */
  173.         if (*nparam != 0)
  174.          *private = 'X';
  175.         else {
  176.         *private = c;
  177.         *nparam = 1;
  178.         }
  179.         goto label1;
  180.     }
  181.     if (*nparam == 0)
  182.         *nparam = 1;
  183.     if (*ninter != 0) {
  184.         *ninter = 0;
  185.         *private = 'X';
  186.     }
  187.     if (c == ';') {
  188.         if (*nparam >= (NPARAM - 1))
  189.         *private = 'X';
  190.         else {
  191.         ++*nparam;
  192.         }
  193.         goto label1;
  194.     }
  195.     if (c > '9') {
  196.         *private = 'X';
  197.         goto label1;
  198.     }
  199.     present[*nparam] = 1;
  200.     param[*nparam] = (param[*nparam] * 10) + (c - '0');
  201.     goto label1;
  202. label3:    if (*nparam == 0)
  203.         *nparam = 1;
  204. label4:    *final = c;
  205.     c = *state;
  206.     *state = 0;
  207. label5:    return (c);
  208. }
  209.  
  210. dumpsequence(state, c, private, param, nparam, inter, ninter, final, column)
  211. int            state;
  212. int        c;
  213. int        private;    /* Sequence private char, 'X' if error    */
  214. int        param[];    /* numeric param, starting at param[1]    */
  215. int        nparam;        /* Number of parameters            */
  216. int        inter[];    /* intermediate char, starting at [1]    */
  217. int        ninter;        /* Number of intermediates        */
  218. int        final;        /* Sequence terminator            */
  219. short           *column;        /* column display count                 */
  220. {
  221.     register int    i;
  222.  
  223.     if (isascii(c) && isprint(c)) {
  224.         *column +=2;
  225.         if (*column >= 79) {
  226.             printf("\n");
  227.             *column = 2;
  228.         }
  229.         printf("%c ", c);
  230.     }
  231.     else if (private == 'X') {
  232.         *column += strlen("bad sequence ");
  233.         if (*column >= 79) {
  234.             printf("\n");
  235.             *column = strlen("bad sequence ");
  236.         }
  237.         printf("bad sequence ");
  238.     }
  239.     else if (state != NUL) {
  240.         *column += 32;
  241.         if (*column >= 79) {
  242.             printf("\n");
  243.             *column = 32;
  244.         }
  245.         printf("incomplete sequence (type <%02x>) ", state);
  246.     }
  247.     else {
  248.         *column += 5;    /* update total chars printed */ 
  249.         if (*column >= 79) {
  250.             printf("\n");
  251.             *column = 6;
  252.         }
  253.         switch (c) {
  254.         case ESC:    printf("<ESC>");    break;
  255.         case DCS:    printf("<DCS>");    break;
  256.         case CSI:    printf("<CSI>");    break;
  257.         case SS3:    printf("<SS3>");    break;
  258.         default:    printf("<02x>", c & 0xFF);
  259.         }
  260.         if (c == ESC || c == DCS || c == CSI || c == SS3) {
  261.             *column += 1 + nparam*2 + ninter + 1;    /* total chars printed */ 
  262.             if (*column >= 79) {
  263.                 printf("\n");
  264.                 *column = 1 + nparam*2 + ninter + 1;
  265.             }
  266.             if (private != NUL && private != 'X')
  267.                 printf("%c", private);
  268.             for (i = 1; i <= nparam; i++)
  269.                 printf("%s%d", (i > 1) ? "," : " ", param[i]);
  270.         for (i = 1; i <= ninter; i++)
  271.             printf("%c", inter[i]);
  272.         printf("%c", final);
  273.         }
  274.         *column++;
  275.         if (*column >= 79) {
  276.             printf("\n");
  277.             *column = 1;
  278.         }
  279.         printf(" ");
  280.     }
  281. }
  282.  
  283. #ifdef vms
  284. /*
  285.  * Read a character from the terminal (with selectable timeout)
  286.  */
  287.  
  288. int
  289. kbinr(timeout)
  290. int        timeout;        /* In seconds, 0 == immediately    */
  291. /*
  292.  * Get one byte without echoing, if available.  Returns
  293.  *    ERROR        Something is dwrong
  294.  *    TIMEOUT        Nothing read within limit.
  295.  * Note:
  296.  *    timeout = 0    return immediately if nothing is present
  297.  *    timeout = 1    Indeterminate, do not use
  298.  *    timeout = 2    Wait at least one second.
  299.  */
  300. {
  301.     register int    incount;
  302.     static char    buffer[BUFFLEN];
  303.     static char    *bufptr = buffer;
  304.     static char    *bufend = buffer;
  305.  
  306.     if (bufptr >= bufend) {
  307.         bufptr = bufend = buffer;
  308.         incount = vmsread(buffer, BUFFLEN, 0);
  309.         if (incount == TIMEOUT)
  310.         incount = vmsread(buffer, 1, timeout);
  311.         if (incount <= 0)
  312.         return (incount);
  313.         bufend = &buffer[incount];
  314.     }
  315.     return (*bufptr++ & 0xFF);
  316. }
  317.  
  318. static int        tt_channel;    /* Gets channel number        */
  319. typedef    struct {
  320.     short int    status;
  321.     short int    term_offset;
  322.     short int    terminator;
  323.     short int    term_size;
  324. } IOSTAB;
  325.  
  326. int
  327. vmsread(buffer, size, timeout)
  328. char        *buffer;
  329. int        size;
  330. int        timeout;
  331. {
  332.     register int        status;
  333.     IOSTAB            iostab;
  334.     static $DESCRIPTOR(tt_device, "SYS$COMMAND");
  335.     static long    termset[2] = { 0, 0 };    /* No terminator    */
  336.     static short    opened = FALSE;        /* TRUE when opened    */
  337.  
  338.     if (!opened) {
  339.         status = sys$assign(&tt_device, &tt_channel, 0, 0);
  340.         if (status != SS$_NORMAL)
  341.         lib$stop(status);
  342.             opened = TRUE;
  343.     }
  344.     status = sys$qiow(
  345.         0,            /* Event flag             */
  346.         tt_channel,        /* Input channel        */
  347.         IO$_READLBLK | IO$M_NOECHO | IO$M_NOFILTR | IO$M_TIMED,
  348.                     /* Read, no echo, no translate    */
  349.         &iostab,        /* I/O status block        */
  350.         NULL,            /* AST block (none)        */
  351.         0,            /* AST parameter        */
  352.         buffer,            /* P1 - input buffer        */
  353.         size,            /* P2 - buffer length        */
  354.         timeout,        /* P3 - timeout            */
  355.         &termset,        /* P4 - terminator set        */
  356.         NULL,            /* P5 - ignored (prompt buffer)    */
  357.         0            /* P6 - ignored (prompt size)    */
  358.     );
  359.     if (status == SS$_TIMEOUT)
  360.         return (TIMEOUT);
  361.     else if (status != SS$_NORMAL)
  362.         return (ERROR);
  363.     else {
  364.         if ((status = iostab.term_offset + iostab.term_size) > 0)
  365.         return (status);
  366.         return (TIMEOUT);
  367.     }
  368. }
  369. #else
  370. int
  371. kbinr(max_delay)
  372. int        max_delay;
  373. {
  374.     auto int        fdmask;
  375.     struct timeval        timeout;
  376.     int            count;
  377.     static unsigned char    buffer[80];
  378.     static unsigned char    *bend;
  379.     static unsigned char    *bptr;
  380.  
  381.     if (bptr >= bend) {
  382.         fdmask = 1 << fileno(stdin);
  383.         timeout.tv_usec = 0;
  384.         timeout.tv_sec = max_delay;
  385.         count = select(fileno(stdin) + 1, &fdmask, NULL, NULL, &timeout);
  386.         if (count < 0)
  387.         return (ERROR);
  388.         else if (count == 0)
  389.         return (TIMEOUT);
  390.         if (count >= sizeof buffer)
  391.         count = sizeof buffer;
  392.         count = read(fileno(stdin), buffer, count);
  393.         if (count <= 0)
  394.         return (ERROR);
  395.         bptr = buffer;
  396.         bend = buffer + count;
  397.     }
  398.     return (*bptr++);
  399. }
  400. #endif
  401.