home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume3 / xprompt / part01 / trexp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-10  |  4.6 KB  |  219 lines

  1. /* vi: set tabstop=4 : */
  2.  
  3. #include <stdio.h>
  4.  
  5. #include "trexp.h"
  6.  
  7. #ifdef DEBUG
  8. main()
  9. {
  10.     int st;
  11.     char buf[BUFSIZ];
  12.     trexp *t;
  13.  
  14.     printf("Enter the expression:\n");
  15.     gets(buf);
  16.     if ((t = trcomp(buf)) == NULL) {
  17.         fprintf(stderr, "Compile error.\n");
  18.         exit(1);
  19.     }
  20.     printf("Number in set: %d\n", trnset(t));
  21.     trshow(stdout, t);
  22.     while (1) {
  23.         printf("Character?\n");
  24.         if (gets(buf) == NULL)
  25.             break;
  26.         if (trexec(t, buf[0]))
  27.             printf("Yes.\n");
  28.         else
  29.             printf("No.\n");
  30.     }
  31. }
  32. #endif DEBUG
  33.  
  34. /*
  35.  * trcomp - compile a transliteration string
  36.  *
  37.  * Returns a pointer to a trexp structure if successful and NULL
  38.  * if the control string is improperly formed.
  39.  *
  40.  * The macro trexec may subsequently be used with the compiled expression
  41.  * and a single character.
  42.  * The value is 1 if the character is in the set, 0 otherwise.
  43.  * The value of the macro trnset, passed the pointer to the compiled
  44.  * expression, is the number of elements specified by the expression.
  45.  *
  46.  * The argument to trcomp is a string specifying individual characters
  47.  * and ranges of characters as used in the tr(1) command:
  48.  * a) a backslash followed by 1, 2, or 3 octal digits stands for the ASCII
  49.  *    character corresponding to the octal value.  The value is limited to
  50.  *    8 bits.
  51.  * b) a backslash followed by a non-octal digit character stands for the
  52.  *    character.
  53.  * c) other ASCII characters stand for themselves
  54.  * d) the range of characters between two characters, <c1> and <c2>,
  55.  *    is specified by sequence of the form <c1>-<c2> when <c1> comes before
  56.  *    <c2> in the ASCII character set
  57.  *
  58.  * The space allocated by trcomp() may be released using free()
  59.  */
  60.  
  61. static int next_token();
  62.  
  63. trexp *
  64. trcomp(exp)
  65. char *exp;
  66. {
  67.     register int i, low, high;
  68.     char *ptr, *save;
  69.     trexp *t;
  70.     char *malloc();
  71.  
  72.     if ((t = (trexp *) malloc(sizeof(trexp))) == NULL)
  73.         return(NULL);
  74.     for (i = 0; i < sizeof(trexp); i++)
  75.         t->exp[i] = 0;
  76.     t->nset = 0;
  77.     ptr = exp;
  78.     while (*ptr != '\0') {
  79.         if ((low = next_token(&ptr)) < 0)
  80.             return(NULL);
  81.         if (*ptr == '-') {
  82.             save = ptr++;
  83.             if ((high = next_token(&ptr)) < 0)
  84.                 return(NULL);
  85.             if (low < high) {
  86.                 for (i = low; i <= high; i++) {
  87.                     if (!t->exp[i]) {
  88.                         t->exp[i] = 1;
  89.                         t->nset++;
  90.                     }
  91.                 }
  92.             }
  93.             else {
  94.                 ptr = save;
  95.                 if (!t->exp[low]) {
  96.                     t->exp[low] = 1;
  97.                     t->nset++;
  98.                 }
  99.             }
  100.         }
  101.         else {
  102.             if (!t->exp[low]) {
  103.                 t->exp[low] = 1;
  104.                 t->nset++;
  105.             }
  106.         }
  107.     }
  108.     return(t);
  109. }
  110.  
  111. #define isoctdigit(d)    (d >= '0' && d <= '7')
  112.  
  113. static int
  114. next_token(str)
  115. char **str;
  116. {
  117.     register char *p;
  118.     int val;
  119.  
  120.     p = *str;
  121.     if (*p == '\\') {
  122.         p++;
  123.         if (isoctdigit(*p)) {
  124.             val = *p++ - '0';
  125.             if (isoctdigit(*p)) {
  126.                 val = val * 8 + *p++ - '0';
  127.                 if (isoctdigit(*p))
  128.                     val = val * 8 + *p++ - '0';
  129.             }
  130.             *str = p;
  131.             return(val & 0377);
  132.         }
  133.         else {
  134.             if (*p == '\0')        /* Premature eos */
  135.                 return(-1);
  136.             *str = p + 1;
  137.             return(*p & 0377);
  138.         }
  139.     }
  140.     *str = p + 1;
  141.     return(*p & 0377);
  142. }
  143.  
  144. void
  145. trshow(f, t)
  146. FILE *f;
  147. trexp *t;
  148. {
  149.     register int i, j, k;
  150.     static char *ascii_tab[] = {
  151.         "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
  152.         "BS",  "HT",  "NL",  "VT",  "NP",  "CR",  "SO",  "SI",
  153.         "DEL", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB",
  154.         "CAN", "EM",  "SUB", "ESC", "FS",  "GS",  "RS",  "US",
  155.         "SP",  "!",   "\"",  "#",   "$",   "%",   "&",   "'",
  156.         "(",   ")",   "*",   "+",   ",",   "-",   ".",   "/",
  157.         "0",   "1",   "2",   "3",   "4",   "5",   "6",   "7",
  158.         "8",   "9",   ":",   ";",   "<",   "=",   ">",   "?",
  159.         "@",   "A",   "B",   "C",   "D",   "E",   "F",   "G",
  160.         "H",   "I",   "J",   "K",   "L",   "M",   "N",   "O",
  161.         "P",   "Q",   "R",   "S",   "T",   "U",   "V",   "W",
  162.         "X",   "Y",   "Z",   "[",   "\\",  "]",   "^",   "_",
  163.         "`",   "a",   "b",   "c",   "d",   "e",   "f",   "g",
  164.         "h",   "i",   "j",   "k",   "l",   "m",   "n",   "o",
  165.         "p",   "q",   "r",   "s",   "t",   "u",   "v",   "w",
  166.         "x",   "y",   "z",   "{",   "|",   "}",   "~",   "DEL"
  167.     };
  168.  
  169.     for (i = 0; i < 32; i++) {
  170.         for (j = 0; j < 8; j++) {
  171.             k = i * 8 + j;
  172.             if (t->exp[k]) {
  173.                 if (k > 0177)
  174.                     fprintf(f, "|%03o    ", k, t->exp[k]);
  175.                 else
  176.                     fprintf(f, "|%03o %3s", k, ascii_tab[k]);
  177.             }
  178.             else
  179.                 fprintf(f, "|       ");
  180.         }
  181.         fprintf(f, "|\n");
  182.     }
  183. }
  184.  
  185. #ifdef NOTDEF
  186. /*
  187.  * This is the old, non-compiling version
  188.  */
  189. strrange(str, ch)
  190. char *str;
  191. int ch;
  192. {
  193.     int low, high;
  194.     char *ptr, *save;
  195.  
  196.     ch &= 0377;
  197.     ptr = str;
  198.     while (*ptr != '\0') {
  199.         if ((low = next_token(&ptr)) < 0)
  200.             return(-1);
  201.         if (ch == low)
  202.             return(1);
  203.         if (*ptr == '-') {
  204.             save = ptr++;
  205.             if ((high = next_token(&ptr)) < 0)
  206.                 return(-1);
  207.             if (low < high) {
  208.                 if (ch >= low && ch <= high)
  209.                     return(1);
  210.             }
  211.             else
  212.                 ptr = save;
  213.         }
  214.     }
  215.     return(0);
  216. }
  217. #endif NOTDEF
  218.  
  219.