home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / edit / point20 / re.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-04  |  19.4 KB  |  738 lines

  1. #include "pt.h"
  2. #include "malloc.h"
  3. #include "string.h"
  4.  
  5. /* Sizes of things */
  6. #define RESIZE 100
  7. #define STACKSIZE 100
  8. #define CODESIZE 1000
  9.  
  10. /* parse action codes */
  11. #define ACT_ERROR    0
  12. #define ACT_JUXTA    1
  13. #define ACT_STOP    2
  14. #define ACT_PUSH    3
  15. #define ACT_POP        4
  16. #define ACT_POP2    5
  17.  
  18. /* symbol codes */
  19. #define SYM_OTHER    0
  20. #define SYM_END        1
  21. #define SYM_CLOSE    2
  22. #define SYM_OR        3
  23. #define SYM_JUXTA    4
  24. #define SYM_REP0    5
  25. #define SYM_OPEN    6
  26.  
  27. /* re_scan return codes */
  28. #define NOT_FOUND    0
  29. #define FOUND        1
  30. #define PARTIAL_MATCH    2
  31.  
  32. /* 8086 op-codes */
  33. #define OP_AND        0x80
  34. #define OP_CALL        0xE8
  35. #define OP_CMP        0x3C
  36. #define OP_CMPI        0x80
  37. #define OP_JE        0x74
  38. #define OP_JNE        0x75
  39. #define OP_JMP        0xE9
  40. #define OP_MOV        0x8A
  41. #define OP_RET        0xC3
  42. #define OP_SHR        0xD2
  43.  
  44. /* special RE character codes */
  45. #define RE_OR        1
  46. #define RE_REP0        2
  47. #define RE_REP1        3
  48. #define RE_REP01    4
  49. #define RE_BEGIN_LINE    5
  50. #define RE_END_LINE    6
  51. #define RE_BEGIN_WORD    7
  52. #define RE_END_WORD    8
  53. #define RE_OPEN_GROUP    9
  54. #define RE_CLOSE_GROUP    10
  55. #define RE_OPEN_CLASS    11
  56. #define RE_CLOSE_CLASS    12
  57. #define RE_NEGATE_CLASS    13
  58. #define RE_ANY_CHAR    14
  59. #define RE_ESCAPE_CHAR    15
  60. #define RE_LAST_ONE    16
  61.  
  62. /* buffers to hold the regular expressions (REs) */
  63. char reIn[RESIZE];
  64. int reIndex;        /* index into RE buffer */
  65.  
  66. /* buffer to hold the assembled code */
  67. char code[CODESIZE];
  68. char *pcCode;            /* next free location in code buffer */
  69.  
  70. /* parse stacks */
  71. short stackChar[STACKSIZE];    /* character on stack */
  72. char stackCode[STACKSIZE];    /* symbol type of the char on the stack */
  73. char *stackClass[STACKSIZE];    /* bit map for character classes (only) */
  74. int stackTop;            /* stack pointer */
  75.  
  76. /* characters for special RE symbols */
  77. char reChars[20];
  78.  
  79. /* code generation stack -- holds adds of partially assembled REs */
  80. char *stackPc[STACKSIZE];
  81. int pcTop;            /* code generation stack pointer */
  82.  
  83. /* retyped addresses of locations in "code" - used for code generation */
  84. char *re_code2;
  85. char *re_cnode2;
  86. char *re_nnode2;
  87. char *re_found2;
  88. char *re_clist2;
  89. char *re_sidechars2;
  90. char *re_wordtable2;
  91.  
  92. /* address of the last instruction in RE code */
  93. char *addrJmpFound;
  94.  
  95. /* used to speed up searches when the first character can only be one */
  96. /* of two characters.  Two chosen to accommodate case insensitivity */
  97. char reFast1, reFast2;
  98.  
  99. /* This is a kludge to handle the case where there is an or "|" or */
  100. /* an end-of-word "\>" in the string.  In those cases the length */
  101. /* returned is one too long.  So we just reduce it by one! */
  102. /* To do that we must remember if one of those two things is in the */
  103. /* re.  This variable does that. */
  104. unsigned char orOrEOW;
  105.  
  106. char encode[256];    /* array to convert characters to symbol codes */
  107.  
  108. /* parsing transition table for the operator precedence parser */
  109. char TransitionTable[7][7] = {
  110. /*  A          \0         )          |         .         *         (     */
  111. {ACT_JUXTA, ACT_POP,   ACT_POP,   ACT_POP,  ACT_POP,  ACT_POP,  ACT_JUXTA},
  112. {ACT_PUSH,  ACT_STOP,  ACT_ERROR, ACT_PUSH, ACT_PUSH, ACT_PUSH, ACT_PUSH},
  113. {ACT_JUXTA, ACT_POP2,  ACT_POP2,  ACT_POP2, ACT_POP2, ACT_POP2, ACT_JUXTA},
  114. {ACT_PUSH,  ACT_POP,   ACT_POP,   ACT_POP,  ACT_PUSH, ACT_PUSH, ACT_PUSH},
  115. {ACT_PUSH,  ACT_POP,   ACT_POP,   ACT_POP,  ACT_POP,  ACT_PUSH, ACT_PUSH},
  116. {ACT_JUXTA, ACT_POP,   ACT_POP,   ACT_POP,  ACT_POP,  ACT_POP,  ACT_JUXTA},
  117. {ACT_PUSH,  ACT_ERROR, ACT_PUSH,  ACT_PUSH, ACT_PUSH, ACT_PUSH, ACT_PUSH}
  118. };
  119.  
  120. long pascal
  121. /* XTAG:reSpans */
  122. reSpans(fileId, startCp, stopCp, reLength, linesPassed)
  123.     int fileId, *reLength, *linesPassed;
  124.     long startCp, stopCp;
  125. {
  126.     extern unsigned char msgBuffer[];
  127.     extern unsigned char textBuffer[];
  128.     extern int findWholeWords;
  129.     extern struct SREGS segRegs;
  130.     extern int debug;
  131.  
  132.     unsigned char *pat, *p, *savedP;
  133.     unsigned char far *firstChar;
  134.     unsigned char far *lastChar;
  135.     int leftOver, matched, len, nLines;
  136.     long cp;
  137.  
  138.     nLines = 0;
  139.     
  140.     /* set things up so getSpan is called right away */
  141.     firstChar = (unsigned char far *)1;
  142.     lastChar = (unsigned char far *)0;
  143.  
  144.     /* each iteration of this loop scans one span */
  145.     while( 1 ) {
  146.         if( (stopCp - startCp) <= 0 )
  147.             break;
  148.  
  149.         if( firstChar > lastChar ) {
  150.             if( getSpan(fileId,startCp,&firstChar,&lastChar,0) )
  151.                 /* getSpan says startCp at EOF */
  152.                 break;
  153.             /* check to see if the span is longer than the */
  154.             /* area we are supposed to search */
  155.             if( (long)(lastChar-firstChar) > (stopCp-startCp) ) {
  156.                 /* if it is too long then adjust lastChar */
  157.                 lastChar = firstChar + (stopCp - startCp);
  158.             }
  159.         }
  160.  
  161.         matched = re_scan(
  162.             (unsigned int)firstChar,
  163.             (unsigned int)lastChar,
  164.             (unsigned int)(((long)firstChar)>>16),
  165.             &p, &pat, &len );
  166.         nLines += len;
  167.         if( 0 == matched ) {    /* not found */
  168.         notFound:
  169.             startCp += (int)(lastChar - firstChar) + 1;
  170.             firstChar = (unsigned char far *)1;
  171.             lastChar = (unsigned char far *)0;
  172.             continue;
  173.         }
  174.         
  175.         if( 2 == matched ) {    /* found a partial match */
  176.             /* where does the match begin */
  177.             cp = startCp +
  178.                 ((unsigned int)p - (unsigned int)firstChar);
  179.             leftOver = (unsigned int)lastChar - (unsigned int)p;
  180.             /* fill textBuffer with the characters that */
  181.             /* are in two or more spans */
  182.             for( len = 0; len < MSGBUFFERSIZE; ++len )
  183.                 textBuffer[len] = readChar( fileId, cp++ );
  184.             savedP = p;
  185.             matched = re_scan(
  186.                 (unsigned int)textBuffer,
  187.                 (unsigned int)(textBuffer+255),
  188.                 segRegs.ds,
  189.                 &p, &pat, &len );
  190.             if( 1 == matched && (p - textBuffer) < leftOver ) {
  191.                 *reLength = pat - p + 1;
  192.                 *linesPassed = nLines;
  193.                 return startCp + ((unsigned)savedP
  194.                         - (unsigned)firstChar);
  195.             } else
  196.                 goto notFound;
  197.         }
  198.  
  199.         /* we found the string */
  200.         if( orOrEOW )
  201.             /* There was an "|" or a "\>" in the string which */
  202.             /* caused re_scan to return "pat" 1 too large. */
  203.             --pat;
  204.         *reLength = pat - p + 1;
  205.         *linesPassed = nLines;
  206.         return startCp + ((unsigned)p - (unsigned)firstChar);
  207.     }
  208.     *linesPassed = nLines;
  209.     return (long)(-1);
  210. }
  211.  
  212. void pascal
  213. /* XTAG:RETableSetup */
  214. RETableSetup()
  215. {
  216.     extern char encode[];
  217.     extern char reChars[];
  218.  
  219.     int i;
  220.  
  221.     for( i = 0; i < 256; ++i )
  222.         encode[i] = SYM_OTHER;
  223.     encode['\0'] = SYM_END;
  224.     encode[')'] = SYM_CLOSE;
  225.     encode['|'] = SYM_OR;
  226.     encode['*'] = SYM_REP0;
  227.     encode['('] = SYM_OPEN;
  228.     reChars[RE_OR] = '|';
  229.     reChars[RE_REP0] = '*';
  230.     reChars[RE_REP1] = '+';
  231.     reChars[RE_REP01] = '?';
  232.     reChars[RE_BEGIN_LINE] = '^';
  233.     reChars[RE_END_LINE] = '$';
  234.     reChars[RE_BEGIN_WORD] = '<';
  235.     reChars[RE_END_WORD] = '>';
  236.     reChars[RE_OPEN_GROUP] = '(';
  237.     reChars[RE_CLOSE_GROUP] = ')';
  238.     reChars[RE_OPEN_CLASS] = '[';
  239.     reChars[RE_CLOSE_CLASS] = ']';
  240.     reChars[RE_NEGATE_CLASS] = '^';
  241.     reChars[RE_ANY_CHAR] = '.';
  242.     reChars[RE_ESCAPE_CHAR] = '\\';
  243. };
  244.  
  245. /* locations in re_scan (in re2.asm) */
  246. extern void re_code( void );
  247. extern void re_cnode( void );
  248. extern void re_nnode( void );
  249. extern void re_found( void );
  250. extern void re_clist( void );
  251. extern void re_sidechars( void );
  252. extern void re_wordtable( void );
  253.  
  254. int pascal
  255. /* XTAG:RECompile */
  256. RECompile()
  257. {
  258.     extern char encode[];
  259.     extern short stackChar[];
  260.     extern char stackCode[];
  261.     extern char *stackClass[];
  262.     extern char *stackPc[];
  263.     extern char code[];
  264.     extern int pcTop, stackTop, reIndex;
  265.     extern char *pcCode;
  266.     extern char TransitionTable[][7];
  267.     extern char *addrJmpFound;
  268.  
  269.     extern int findWholeWords;
  270.     extern unsigned char msgBuffer[];
  271.     extern struct SREGS segRegs;
  272.  
  273.     /* retyped versions of these addresses */
  274.     extern char *re_code2;
  275.     extern char *re_cnode2;
  276.     extern char *re_nnode2;
  277.     extern char *re_found2;
  278.     extern char *re_clist2;
  279.     extern char *re_sidechars2;
  280.  
  281.     /* re-typed versions of the external locations */
  282.     int i, codeIn, codeStack, action;
  283.     short charIn;
  284.     char negated;
  285.     int firstCharIndex;
  286.     char *classIn;
  287.     char ch;
  288.     char *p;
  289.  
  290.     re_code2  = (char *)re_code;
  291.     re_cnode2 = (char *)re_cnode;
  292.     re_nnode2 = (char *)re_nnode;
  293.     re_found2 = (char *)re_found;
  294.     re_clist2 = (char *)re_clist;
  295.     re_sidechars2 = (char *)re_sidechars;
  296.     re_wordtable2 = (char *)re_wordtable;
  297.     stackChar[0] = '\0';
  298.     stackCode[0] = SYM_END;
  299.     stackTop = 0;
  300.     pcTop = 0;
  301.     pcCode = &code[0];
  302.     reIndex = 0;
  303.     orOrEOW = 0;    /* no OR "|" or end-of-word "\>" seen yet */
  304.  
  305.     /* handle the -w option */
  306.     if( findWholeWords ) {
  307.         /* move the RE in reIn down two characters */
  308.         codeIn = strlen(reIn);
  309.         for( i = codeIn-1; i >= 0; --i )
  310.             reIn[i+2] = reIn[i];
  311.         /* then insert the \< and the \> */
  312.         reIn[0] = '\\';
  313.         reIn[1] = '<';
  314.         reIn[codeIn+2] = '\\';
  315.         reIn[codeIn+3] = '>';
  316.         reIn[codeIn+4] = '\0';
  317.     }
  318.     while( 1 ) {
  319.         charIn = (short)(signed char)(reIn[reIndex++]);
  320.         codeIn = SYM_OTHER;    /* this is the most common case */
  321.         if( charIn == reChars[RE_ANY_CHAR] )
  322.             charIn = -RE_ANY_CHAR;
  323.         else if( charIn == reChars[RE_OPEN_CLASS] ) {
  324.             charIn = -RE_OPEN_CLASS;
  325.             classIn = (char *)malloc(32);
  326.             for( i = 0; i < 32; ++i )
  327.                 classIn[i] = 0;
  328.             if( '^' == reIn[reIndex] ) {
  329.                 ++reIndex;
  330.                 negated = 1;
  331.             } else
  332.                 negated = 0;
  333.             firstCharIndex = reIndex;
  334.             while( 1 ) {
  335.                 ch = reIn[reIndex++];
  336.                 switch( ch ) {
  337.                 case ']':
  338.                     if( reIndex != firstCharIndex )
  339.                         goto ClassEnded;
  340.                     /* else drop through to default */
  341.                 default:
  342.                 AllOthers:
  343.                     classIn[ch>>3] |= 1 << (ch&7);
  344.                     break;
  345.                 case '-':
  346.                     if( reIndex == firstCharIndex ||
  347.                         ']' == reIn[reIndex] )
  348.                         goto AllOthers;
  349.                     for( ch = reIn[reIndex-2];
  350.                          ch <= reIn[reIndex];
  351.                          ++ch )
  352.                         classIn[ch>>3] |= 1<<(ch&7);
  353.                     ++reIndex;
  354.                     break;
  355.                 }
  356.             }
  357.         ClassEnded:
  358.             if( negated ) {
  359.                 for( i = 0; i < 32; ++i )
  360.                     classIn[i] = ~classIn[i];
  361.             }
  362.             reIn[reIndex-1] = -RE_OPEN_CLASS;
  363.         } else if( charIn == reChars[RE_BEGIN_LINE] && 1 == reIndex )
  364.             /* this must occur as the first character in the RE */
  365.             charIn = -RE_BEGIN_LINE;
  366.         else if( charIn == reChars[RE_END_LINE]
  367.              && '\0' == reIn[reIndex] )
  368.             /* this must occur as the last character in the RE */
  369.             charIn = -RE_END_LINE;
  370.         else if( charIn == reChars[RE_ESCAPE_CHAR] ) {
  371.             charIn = reIn[reIndex++];
  372.             switch( charIn ) {
  373.             case '<':
  374.                 charIn = -RE_BEGIN_WORD;
  375.                 break;
  376.             case '>':
  377.                 charIn = -RE_END_WORD;
  378.                 /* The end-word construct will cause the */
  379.                 /* final string length to be 1 too large. */
  380.                 /* This variable will cause it to be */
  381.                 /* reduced by 1 before it is returned. */
  382.                 orOrEOW = 1;
  383.                 break;
  384.             case 'n':
  385.                 charIn = '\n';
  386.                 break;
  387.             case 'r':
  388.                 charIn = '\r';
  389.                 break;
  390.             case 't':
  391.                 charIn = '\t';
  392.                 break;
  393.             case 'b':
  394.                 charIn = '\b';
  395.                 break;
  396.             case 'a':
  397.                 charIn = '\a';
  398.                 break;
  399.             case '0': case '1': case '2': case '3': case '4':
  400.             case '5': case '6': case '7':
  401.                 charIn -= '0';    /* convert to a number */
  402.                 while( 1 ) {
  403.                     ch = (short)(unsigned)reIn[reIndex++];
  404.                     if( ch < '0' || ch > '7' )
  405.                         break;
  406.                     charIn = 8*charIn + ch - '0';
  407.                 }
  408.                 --reIndex;
  409.                 break;
  410.             case 'x':
  411.                 /* hex number */
  412.                 charIn = 0;
  413.                 while( 1 ) {
  414.                     ch = (short)(unsigned)reIn[reIndex++];
  415.                     if( !isxdigit(ch) )
  416.                         break;
  417.                     if( isupper(ch) )
  418.                         ch = tolower(ch);
  419.                     if( islower(ch) )
  420.                         ch += '0' + 10 - 'a';
  421.                     charIn = 16*charIn + ch - '0';
  422.                 }
  423.                 --reIndex;
  424.                 break;
  425.             }
  426.             /* replace the character with it escaped version */
  427.             /* so that the -reIndex backup in ACT_JUXTA will */
  428.             /* pick up the correct character */
  429.             /* LATER: be sure that this fix works in all cases */
  430.             reIn[reIndex-1] = charIn;
  431.         } else
  432.             codeIn = encode[charIn];
  433.     NoCharRead:
  434.         codeStack = stackCode[stackTop];
  435.         action = TransitionTable[codeStack][codeIn];
  436.         switch( action ) {
  437.  
  438.         case ACT_ERROR:
  439.             sprintf(msgBuffer,
  440.                 "RE error near character %d of `%s'\n",
  441.                 reIndex-1, reIn);
  442.             msg(msgBuffer, 2);
  443.             return 0;
  444.  
  445.         case ACT_JUXTA:
  446.             codeIn = SYM_JUXTA;
  447.             --reIndex;    /* undo the read of the character */
  448.             goto NoCharRead;
  449.  
  450.         case ACT_STOP:
  451.             addrJmpFound = pcCode - code + re_code2;
  452.             *pcCode++ = OP_JMP;
  453.             *(short *)pcCode = (short)(re_found2
  454.                 - (pcCode+2-code+re_code2));
  455.             pcCode += 2;
  456.             goto ret1;
  457.  
  458.         case ACT_PUSH:
  459.             ++stackTop;
  460.             stackChar[stackTop] = charIn;
  461.             stackCode[stackTop] = codeIn;
  462.             stackClass[stackTop] = classIn;
  463.             break;
  464.  
  465.         case ACT_POP:
  466.             switch( codeStack ) {
  467.             case SYM_OPEN:
  468.                 /* LATER: code to record sub-re's */
  469.                 break;
  470.             case SYM_CLOSE:
  471.                 /* LATER: code to record sub-re's */
  472.                 break;
  473.             case SYM_END:
  474.                 /* code emitted in case ACT_STOP */
  475.                 break;
  476.             case SYM_JUXTA:
  477.                 --pcTop;
  478.                 break;
  479.             case SYM_OTHER:
  480.                 HandleSymOther();
  481.                 break;
  482.             case SYM_REP0:
  483.                 *pcCode++ = OP_CALL;
  484.                 *(short *)pcCode = (short)(re_cnode2
  485.                     - (pcCode+2-code+re_code2));
  486.                 pcCode += 2;
  487.                 p = stackPc[pcTop-1];
  488.                 *((short *)(p+1)) += (p - pcCode);
  489.                 for( i = 0; i < 3; ++i )
  490.                     *pcCode++ = *p++;
  491.                 p = stackPc[pcTop-1];
  492.                 *p++ = OP_JMP;
  493.                 *(short *)p = (pcCode-6) - (p+2);
  494.                 break;
  495.             case SYM_OR:
  496.                 /* The "or" construct will cause the */
  497.                 /* final string length to be 1 too large. */
  498.                 /* This variable will cause it to be */
  499.                 /* reduced by 1 before it is returned. */
  500.                 orOrEOW = 1;
  501.                 *pcCode++ = OP_JMP;
  502.                 *(short *)pcCode = 9;
  503.                 pcCode += 2;
  504.                 *pcCode++ = OP_CALL;
  505.                 *(short *)pcCode = (short)(re_cnode2
  506.                     - (pcCode+2-code+re_code2));
  507.                 pcCode += 2;
  508.                 p = stackPc[pcTop-1];
  509.                 *((short *)(p+1)) += (p - pcCode);
  510.                 for( i = 0; i < 3; ++i )
  511.                     *pcCode++ = *p++;
  512.                 p = stackPc[pcTop-2];
  513.                 *((short *)(p+1)) += (p - pcCode);
  514.                 for( i = 0; i < 3; ++i )
  515.                     *pcCode++ = *p++;
  516.                 p = stackPc[pcTop-2];
  517.                 *((short *)(p+1)) += (p - pcCode);
  518.                 *p++ = OP_JMP;
  519.                 *(short *)p = (pcCode-9) - (p+2);
  520.                 p = stackPc[pcTop-1];
  521.                 *p++ = OP_JMP;
  522.                 *(short *)p = pcCode - (p+2);
  523.                 --pcTop;
  524.                 break;
  525.             }
  526.             --stackTop;    /* pop the character */
  527.             goto NoCharRead;
  528.  
  529.         case ACT_POP2:
  530.             stackTop -= 2;
  531.             goto NoCharRead;
  532.         }
  533.     }
  534. ret1:
  535.     /* see if the first character of the RE is a */
  536.     /* constant character if so the RE scanner can go */
  537.     /* very fast by using the scasb assembly language */
  538.     /* instruction.  This triples the search speed */
  539.     reFast1 = reFast2 = '\0';
  540.     /* check for the code pattern of a char constant */
  541.     if( 0 == *(short *)(code + 1) && OP_CMP==code[3] ) {
  542.         /* code pattern of merged case character */
  543.         reFast1 = code[4];
  544.         if( OP_CMP == code[7] ) {
  545.             reFast1 = code[8];
  546.             reFast2 = code[4];
  547.         }
  548.     }
  549.  
  550.     /* now move the bytes into the code segment */
  551.     movedata( segRegs.ds, (unsigned)(&code[0]),
  552.         (unsigned)((long)re_code>>16), (unsigned)re_code,
  553.         pcCode - &code[0] );
  554.     return 1;
  555. }
  556.  
  557. void pascal
  558. /* XTAG:HandleSymOther */
  559. HandleSymOther()
  560. {
  561.     extern int ignoreCase;
  562.  
  563.     short ch;
  564.     int i;
  565.     char *p, *bitmapAddr;
  566.  
  567.     ch = stackChar[stackTop];
  568.     stackPc[pcTop++] = pcCode;
  569.     *pcCode++ = OP_JMP;
  570.     *(short *)pcCode = 0;
  571.     pcCode += 2;
  572.     if( ch >= 0 ) {
  573.  
  574.     FindChar:
  575.         /* handle case insensitivity */
  576.         if( ignoreCase && isascii(ch) && isalpha(ch) ) {
  577.             /* underscored versions are a bit faster */
  578.             *pcCode++ = OP_CMP;
  579.             *pcCode++ = (isupper(ch) ?
  580.                 _tolower(ch) : _toupper(ch));
  581.             *pcCode++ = OP_JE;
  582.             *pcCode++ = 7;
  583.         }
  584.         *pcCode++ = OP_CMP;
  585.         *pcCode++ = ch;
  586.         *pcCode++ = OP_JE;
  587.         *pcCode++ = 3;
  588.         *pcCode++ = OP_JMP;
  589.         *(short *)pcCode = (short)(re_clist2
  590.             - (pcCode+2-code
  591.                 +(char *)re_code2));
  592.         pcCode += 2;
  593.         *pcCode++ = OP_CALL;
  594.         *(short *)pcCode = (short)(re_nnode2
  595.             - (pcCode+2-code+re_code2));
  596.         pcCode += 2;
  597.     } else switch( -ch ) {
  598.     case RE_OPEN_CLASS:
  599.  
  600.         /* change the jump to jump over the bit map */
  601.         *(short *)(pcCode-2) = 32;
  602.  
  603.         /* now insert the bit map */
  604.         bitmapAddr = pcCode - code + re_code2;
  605.         p = stackClass[stackTop];
  606.         for( i = 0; i < 32; ++i )
  607.             *pcCode++ = *p++;
  608.  
  609.         /* now the code to handle the bit map */
  610.         *pcCode++ = 0x32;
  611.         *pcCode++ = 0xFF;    /* xor bh,bh */
  612.         *pcCode++ = OP_MOV;
  613.         *pcCode++ = 0xD8;    /* mov bl,al */
  614.         *pcCode++ = 0xB1;
  615.         *pcCode++ = 0x03;    /* mov cl,3 */
  616.         *pcCode++ = OP_SHR;
  617.         *pcCode++ = 0xEB;    /* shr bl,cl */
  618.         *pcCode++ = OP_MOV;
  619.         *pcCode++ = 0xA7;    /* mov ah,bitmapAddr[bx] */
  620.         *(char* *)pcCode = bitmapAddr;
  621.         pcCode += 2;
  622.         *pcCode++ = OP_MOV;
  623.         *pcCode++ = 0xC8;    /* mov cl,al */
  624.         *pcCode++ = OP_AND;
  625.         *pcCode++ = 0xE1;
  626.         *pcCode++ = 0x07;    /* and cl,7 */
  627.         *pcCode++ = OP_SHR;
  628.         *pcCode++ = 0xEC;    /* shr ah,cl */
  629.         *pcCode++ = OP_AND;
  630.         *pcCode++ = 0xE4;
  631.         *pcCode++ = 0x01;    /* and ah,1 */
  632.         *pcCode++ = OP_JNE;
  633.         *pcCode++ = 3;
  634.         *pcCode++ = OP_JMP;
  635.         *(short *)pcCode = (short)(re_clist2
  636.             - (pcCode+2-code+(char *)re_code2));
  637.         pcCode += 2;
  638.         *pcCode++ = OP_CALL;
  639.         *(short *)pcCode = (short)(re_nnode2
  640.             - (pcCode+2-code+re_code2));
  641.         pcCode += 2;
  642.         free( stackClass[stackTop] );
  643.         break;
  644.     case RE_ANY_CHAR:
  645.         /* no filtering code -- anything matches */
  646.         *pcCode++ = OP_CALL;
  647.         *(short *)pcCode = (short)(re_nnode2
  648.             - (pcCode+2-code+re_code2));
  649.         pcCode += 2;
  650.         break;
  651.     case RE_BEGIN_LINE:
  652.         *pcCode++ = OP_CMPI;
  653.         *pcCode++ = 0x3E;    /* mod/r/m byte: direct address */
  654.         *(short *)pcCode = (short)re_sidechars2;
  655.         pcCode += 2;
  656.         *pcCode++ = '\n';    /* immediate data -- a NL */
  657.         *pcCode++ = OP_JE;
  658.         *pcCode++ = 3;
  659.         *pcCode++ = OP_JMP;
  660.         *(short *)pcCode = (short)(re_clist2
  661.             - (pcCode+2-code+(char *)re_code2));
  662.         pcCode += 2;
  663.         break;
  664.     case RE_BEGIN_WORD:
  665.         *pcCode++ = 0x32;
  666.         *pcCode++ = 0xFF;    /* xor bh,bh */
  667.         *pcCode++ = OP_MOV;
  668.         *pcCode++ = 0x1E;    /* mov bl,BYTE PTR re_sidechars */
  669.         *(short *)pcCode = (short)re_sidechars2;
  670.         pcCode += 2;
  671.         *pcCode++ = 0xB1;
  672.         *pcCode++ = 0x03;    /* mov cl,3 */
  673.         *pcCode++ = OP_SHR;
  674.         *pcCode++ = 0xEB;    /* shr bl,cl */
  675.         *pcCode++ = OP_MOV;
  676.         *pcCode++ = 0xA7;    /* mov ah,re_wordtable[bx] */
  677.         *(short *)pcCode = (short)re_wordtable2;
  678.         pcCode += 2;
  679.         *pcCode++ = OP_MOV;
  680.         *pcCode++ = 0x0E;    /* mov cl,BYTE PTR re_sidechars */
  681.         *(short *)pcCode = (short)re_sidechars2;
  682.         pcCode += 2;
  683.         *pcCode++ = OP_AND;
  684.         *pcCode++ = 0xE1;
  685.         *pcCode++ = 0x07;    /* and cl,7 */
  686.         *pcCode++ = OP_SHR;
  687.         *pcCode++ = 0xEC;    /* shr ah,cl */
  688.         *pcCode++ = OP_AND;
  689.         *pcCode++ = 0xE4;
  690.         *pcCode++ = 0x01;    /* and ah,1 */
  691.         *pcCode++ = OP_JE;
  692.         *pcCode++ = 3;
  693.         *pcCode++ = OP_JMP;
  694.         *(short *)pcCode = (short)(re_clist2
  695.             - (pcCode+2-code+(char *)re_code2));
  696.         pcCode += 2;
  697.         break;
  698.     case RE_END_LINE:
  699. /* LATER: THIS NEEDS FIXING.  We need to correct three things: */
  700. /* 1. The '\r' should NOT be part of the matched string. */
  701. /* 2. It should work for lines that end with '\n' also. */
  702. /* 3. It should work if we are at the end of the file, even */
  703. /*    if the file does not end in a CRNL or a NL. */
  704.         ch = '\r';
  705.         goto FindChar;
  706.     case RE_END_WORD:
  707.         *pcCode++ = 0x32;
  708.         *pcCode++ = 0xFF;    /* xor bh,bh */
  709.         *pcCode++ = OP_MOV;
  710.         *pcCode++ = 0xD8;    /* mov bl,al */
  711.         *pcCode++ = 0xB1;
  712.         *pcCode++ = 0x03;    /* mov cl,3 */
  713.         *pcCode++ = OP_SHR;
  714.         *pcCode++ = 0xEB;    /* shr bl,cl */
  715.         *pcCode++ = OP_MOV;
  716.         *pcCode++ = 0xA7;    /* mov ah,re_wordtable[bx] */
  717.         *(short *)pcCode = (short)re_wordtable2;
  718.         pcCode += 2;
  719.         *pcCode++ = OP_MOV;
  720.         *pcCode++ = 0xC8;    /* mov cl,al */
  721.         *pcCode++ = OP_AND;
  722.         *pcCode++ = 0xE1;
  723.         *pcCode++ = 0x07;    /* and cl,7 */
  724.         *pcCode++ = OP_SHR;
  725.         *pcCode++ = 0xEC;    /* shr ah,cl */
  726.         *pcCode++ = OP_AND;
  727.         *pcCode++ = 0xE4;
  728.         *pcCode++ = 0x01;    /* and ah,1 */
  729.         *pcCode++ = OP_JE;
  730.         *pcCode++ = 3;
  731.         *pcCode++ = OP_JMP;
  732.         *(short *)pcCode = (short)(re_clist2
  733.             - (pcCode+2-code+(char *)re_code2));
  734.         pcCode += 2;
  735.         break;
  736.     }
  737. }
  738.