home *** CD-ROM | disk | FTP | other *** search
/ Best Tools for JAVA / Best Tools for JAVA.iso / CONVERTR / RTF2HTML / SRC / RTF2HTML.TAR / rtftohtml_src / Libs / OTHER / tokenscan.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-05  |  7.8 KB  |  275 lines

  1. /*
  2.         TSScanInit() - initialize scanner to scan  a buffer.
  3.         TSScan() - pull successive tokens out of a character.  Returns
  4.         NULL when there are no more.  Has the property that once it returns
  5.         NULL, succeeding calls continue to return NULL until TSScanInit() is
  6.         called again.
  7.         Default behavior is that tokens are sequences of non-blank characters,
  8.         or quotes can be used to allow whitespace characters in the token.
  9.         The '\' character turns off any special meaning of the following
  10.         character.
  11.  
  12.         TSSetScanner () - install scanner.
  13.         TSGetScanner () - get current scanner.
  14.         TSSetScanPos() - set current position within scan buffer.
  15.         TSGetScanPos() - get current position within scan buffer.
  16.         TSIsScanDelim() - test whether character is in current delimiter set.
  17.         TSIsScanQuote() - test whether character is in current quote set.
  18.         TSIsScanEscape() - test whether character is in current escape set.
  19.         TSIsScanEos() - test whether character is in current EOS set.
  20.         TSTestScanFlags() - test whether scanner flags are set.
  21.  
  22.         The original buffer is destroyed by scanning, since null bytes are
  23.         placed after each token as they are found.
  24.  
  25.         12 Apr 90 Created (as part of NIO).
  26.         25 Sep 90 Reorganized to allow accommodating alternate scanners while
  27.                 preserving current scan position within buffer.
  28.         26 Oct 90 Removed from NIO and made into separate library.
  29.         25 Sep 91 Parameterized the quote and escape characters.
  30.         06 Oct 93 Added scanFlags field to scanner structure.  Only flag so
  31.                 far is to allow all delimiter characters to be significant
  32.                 (so scanner stops on each one, rather than treating sequences
  33.                 of contiguous delimiters as one delimiter).
  34.         14 Oct 93 Parameterized the end-of-string characters.
  35. */
  36.  
  37. # include       <stdio.h>
  38.  
  39. # include       "tokenscan.h"
  40.  
  41.  
  42. typedef void (*VoidProc) ();
  43. typedef char * (*CharPtrProc) ();
  44.  
  45.  
  46. static int      Search ();
  47. static char     *CanonScan ();
  48.  
  49. static TSScanner        defScan =
  50.         { (VoidProc) NULL, CanonScan, " \t", "\"'", "\\", "\n\r", 0 };
  51. static TSScanner        curScan =
  52.         { (VoidProc) NULL, CanonScan, " \t", "\"'", "\\", "\n\r", 0 };
  53.  
  54. static char     *curPos;
  55. static int      emptyToken;
  56.  
  57.  
  58. void
  59. TSScanInit (p)
  60. char    *p;
  61. {
  62.         curPos = p;
  63.         emptyToken = 0;
  64.         if (curScan.scanInit != (VoidProc) NULL)
  65.                 (*curScan.scanInit) (p);
  66. }
  67.  
  68.  
  69. void
  70. TSSetScanner (p)
  71. TSScanner       *p;
  72. {
  73.         if (p == (TSScanner *) NULL || p->scanInit == (VoidProc) NULL)
  74.                 curScan.scanInit = defScan.scanInit;
  75.         else
  76.                 curScan.scanInit = p->scanInit;
  77.         if (p == (TSScanner *) NULL || p->scanScan == (CharPtrProc) NULL)
  78.                 curScan.scanScan = defScan.scanScan;
  79.         else
  80.                 curScan.scanScan = p->scanScan;
  81.  
  82.         if (p == (TSScanner *) NULL || p->scanDelim == (char *) NULL)
  83.                 curScan.scanDelim = defScan.scanDelim;
  84.         else
  85.                 curScan.scanDelim = p->scanDelim;
  86.         if (p == (TSScanner *) NULL || p->scanQuote == (char *) NULL)
  87.                 curScan.scanQuote = defScan.scanQuote;
  88.         else
  89.                 curScan.scanQuote = p->scanQuote;
  90.         if (p == (TSScanner *) NULL || p->scanEscape == (char *) NULL)
  91.                 curScan.scanEscape = defScan.scanEscape;
  92.         else
  93.                 curScan.scanEscape = p->scanEscape;
  94.         if (p == (TSScanner *) NULL || p->scanEos == (char *) NULL)
  95.                 curScan.scanEos = defScan.scanEos;
  96.         else
  97.                 curScan.scanEos = p->scanEos;
  98.  
  99.         if (p == (TSScanner *) NULL || p->scanFlags == 0)
  100.                 curScan.scanFlags = defScan.scanFlags;
  101.         else
  102.                 curScan.scanFlags = p->scanFlags;
  103. }
  104.  
  105.  
  106. void
  107. TSGetScanner (p)
  108. TSScanner       *p;
  109. {
  110.         p->scanInit = curScan.scanInit;
  111.         p->scanScan = curScan.scanScan;
  112.  
  113.         p->scanDelim = curScan.scanDelim;
  114.         p->scanQuote = curScan.scanQuote;
  115.         p->scanEscape = curScan.scanEscape;
  116.         p->scanEos = curScan.scanEos;
  117.  
  118.         p->scanFlags = curScan.scanFlags;
  119. }
  120.  
  121.  
  122. void
  123. TSSetScanPos (p)
  124. char    *p;
  125. {
  126.         curPos = p;
  127. }
  128.  
  129.  
  130. char *
  131. TSGetScanPos ()
  132. {
  133.         return (curPos);
  134. }
  135.  
  136.  
  137. /*
  138.  * Search a (possibly NULL) string for a character.
  139.  */
  140.  
  141. static int
  142. Search (s, c)
  143. char    *s;
  144. char    c;
  145. {
  146. char    c2;
  147.  
  148.         if (s != (char *) NULL)
  149.         {
  150.                 while ((c2 = *s++) != '\0')
  151.                 {
  152.                         if (c == c2)
  153.                                 return (1);
  154.                 }
  155.         }
  156.         return (0);
  157. }
  158.  
  159.  
  160. int
  161. TSIsScanDelim (c)
  162. char    c;
  163. {
  164.         return (Search (curScan.scanDelim, c));
  165. }
  166.  
  167.  
  168. int
  169. TSIsScanQuote (c)
  170. char    c;
  171. {
  172.         return (Search (curScan.scanQuote, c));
  173. }
  174.  
  175.  
  176. int
  177. TSIsScanEscape (c)
  178. char    c;
  179. {
  180.         return (Search (curScan.scanEscape, c));
  181. }
  182.  
  183.  
  184. int
  185. TSIsScanEos (c)
  186. char    c;
  187. {
  188.         if (c == '\0')          /* null character ALWAYS terminates string */
  189.                 return (1);
  190.         return (Search (curScan.scanEos, c));
  191. }
  192.  
  193.  
  194. int
  195. TSTestScanFlags (flags)
  196. int     flags;
  197. {
  198.         return ((curScan.scanFlags & flags) == flags);
  199. }
  200.  
  201.  
  202. char *
  203. TSScan ()
  204. {
  205.         return ((*curScan.scanScan) ());
  206. }
  207.  
  208.  
  209. static char *
  210. CanonScan ()
  211. {
  212. char    *pos, *start, *p, c, quote = 0;
  213. int     escape = 0, haveToken = 0;
  214.  
  215.         if (emptyToken)         /* fix to point into buffer */
  216.         {
  217.                 emptyToken = 0;
  218.                 return ("");
  219.         }
  220.         pos = TSGetScanPos ();
  221.  
  222.         if (!TSTestScanFlags (tsNoConcatDelims))
  223.         {
  224.                 while (TSIsScanDelim (*pos))            /* skip delimiters */
  225.                         ++pos;
  226.         }
  227.         start = p = pos;                        /* start of token */
  228.         while (!TSIsScanEos (c = *pos))         /* eos terminates any token */
  229.         {
  230.                 haveToken = 1;
  231.                 if (escape)                     /* previous char was escape; */
  232.                 {                               /* pass this one literally */
  233.                         *p++ = *pos++;
  234.                         escape = 0;
  235.                 }
  236.                 else if (TSIsScanEscape (c))    /* this char is escape; */
  237.                 {                               /* pass next one literally */
  238.                         ++pos;
  239.                         escape = 1;
  240.                 }
  241.                 else if (quote)                 /* in quote mode */
  242.                 {
  243.                         if (c == quote)         /* end quote mode */
  244.                                 quote = 0;
  245.                         else                    /* no end quote yet */
  246.                                 *p++ = *pos;    /* add char */
  247.                         ++pos;                  /* skip to next char */
  248.                 }
  249.                 else if (TSIsScanQuote (c))     /* begin quote mode */
  250.                 {
  251.                         ++pos;
  252.                         quote = c;
  253.                 }
  254.                 else if (TSIsScanDelim (c))     /* end of token */
  255.                 {
  256.                         ++pos;                  /* skip past delimiter */
  257.                         /*
  258.                          * If also end of string and all delims are significant,
  259.                          * there's an implicit empty token at end.  We won't be
  260.                          * able to tell that from looking at the string itself,
  261.                          * so set a flag for next call.
  262.                          */
  263.                         if (TSIsScanEos (*pos)
  264.                                 && TSTestScanFlags (tsNoConcatDelims))
  265.                                 ++emptyToken;
  266.                         break;
  267.                 }
  268.                 else
  269.                         *p++ = *pos++;
  270.         }
  271.         *p = '\0';
  272.         TSSetScanPos (pos);
  273.         return (haveToken ? start : (char *) NULL);
  274. }
  275.