home *** CD-ROM | disk | FTP | other *** search
- #include "pt.h"
- #include "malloc.h"
- #include "string.h"
-
- /* Sizes of things */
- #define RESIZE 100
- #define STACKSIZE 100
- #define CODESIZE 1000
-
- /* parse action codes */
- #define ACT_ERROR 0
- #define ACT_JUXTA 1
- #define ACT_STOP 2
- #define ACT_PUSH 3
- #define ACT_POP 4
- #define ACT_POP2 5
-
- /* symbol codes */
- #define SYM_OTHER 0
- #define SYM_END 1
- #define SYM_CLOSE 2
- #define SYM_OR 3
- #define SYM_JUXTA 4
- #define SYM_REP0 5
- #define SYM_OPEN 6
-
- /* re_scan return codes */
- #define NOT_FOUND 0
- #define FOUND 1
- #define PARTIAL_MATCH 2
-
- /* 8086 op-codes */
- #define OP_AND 0x80
- #define OP_CALL 0xE8
- #define OP_CMP 0x3C
- #define OP_CMPI 0x80
- #define OP_JE 0x74
- #define OP_JNE 0x75
- #define OP_JMP 0xE9
- #define OP_MOV 0x8A
- #define OP_RET 0xC3
- #define OP_SHR 0xD2
-
- /* special RE character codes */
- #define RE_OR 1
- #define RE_REP0 2
- #define RE_REP1 3
- #define RE_REP01 4
- #define RE_BEGIN_LINE 5
- #define RE_END_LINE 6
- #define RE_BEGIN_WORD 7
- #define RE_END_WORD 8
- #define RE_OPEN_GROUP 9
- #define RE_CLOSE_GROUP 10
- #define RE_OPEN_CLASS 11
- #define RE_CLOSE_CLASS 12
- #define RE_NEGATE_CLASS 13
- #define RE_ANY_CHAR 14
- #define RE_ESCAPE_CHAR 15
- #define RE_LAST_ONE 16
-
- /* buffers to hold the regular expressions (REs) */
- char reIn[RESIZE];
- int reIndex; /* index into RE buffer */
-
- /* buffer to hold the assembled code */
- char code[CODESIZE];
- char *pcCode; /* next free location in code buffer */
-
- /* parse stacks */
- short stackChar[STACKSIZE]; /* character on stack */
- char stackCode[STACKSIZE]; /* symbol type of the char on the stack */
- char *stackClass[STACKSIZE]; /* bit map for character classes (only) */
- int stackTop; /* stack pointer */
-
- /* characters for special RE symbols */
- char reChars[20];
-
- /* code generation stack -- holds adds of partially assembled REs */
- char *stackPc[STACKSIZE];
- int pcTop; /* code generation stack pointer */
-
- /* retyped addresses of locations in "code" - used for code generation */
- char *re_code2;
- char *re_cnode2;
- char *re_nnode2;
- char *re_found2;
- char *re_clist2;
- char *re_sidechars2;
- char *re_wordtable2;
-
- /* address of the last instruction in RE code */
- char *addrJmpFound;
-
- /* used to speed up searches when the first character can only be one */
- /* of two characters. Two chosen to accommodate case insensitivity */
- char reFast1, reFast2;
-
- /* This is a kludge to handle the case where there is an or "|" or */
- /* an end-of-word "\>" in the string. In those cases the length */
- /* returned is one too long. So we just reduce it by one! */
- /* To do that we must remember if one of those two things is in the */
- /* re. This variable does that. */
- unsigned char orOrEOW;
-
- char encode[256]; /* array to convert characters to symbol codes */
-
- /* parsing transition table for the operator precedence parser */
- char TransitionTable[7][7] = {
- /* A \0 ) | . * ( */
- {ACT_JUXTA, ACT_POP, ACT_POP, ACT_POP, ACT_POP, ACT_POP, ACT_JUXTA},
- {ACT_PUSH, ACT_STOP, ACT_ERROR, ACT_PUSH, ACT_PUSH, ACT_PUSH, ACT_PUSH},
- {ACT_JUXTA, ACT_POP2, ACT_POP2, ACT_POP2, ACT_POP2, ACT_POP2, ACT_JUXTA},
- {ACT_PUSH, ACT_POP, ACT_POP, ACT_POP, ACT_PUSH, ACT_PUSH, ACT_PUSH},
- {ACT_PUSH, ACT_POP, ACT_POP, ACT_POP, ACT_POP, ACT_PUSH, ACT_PUSH},
- {ACT_JUXTA, ACT_POP, ACT_POP, ACT_POP, ACT_POP, ACT_POP, ACT_JUXTA},
- {ACT_PUSH, ACT_ERROR, ACT_PUSH, ACT_PUSH, ACT_PUSH, ACT_PUSH, ACT_PUSH}
- };
-
- long pascal
- /* XTAG:reSpans */
- reSpans(fileId, startCp, stopCp, reLength, linesPassed)
- int fileId, *reLength, *linesPassed;
- long startCp, stopCp;
- {
- extern unsigned char msgBuffer[];
- extern unsigned char textBuffer[];
- extern int findWholeWords;
- extern struct SREGS segRegs;
- extern int debug;
-
- unsigned char *pat, *p, *savedP;
- unsigned char far *firstChar;
- unsigned char far *lastChar;
- int leftOver, matched, len, nLines;
- long cp;
-
- nLines = 0;
-
- /* set things up so getSpan is called right away */
- firstChar = (unsigned char far *)1;
- lastChar = (unsigned char far *)0;
-
- /* each iteration of this loop scans one span */
- while( 1 ) {
- if( (stopCp - startCp) <= 0 )
- break;
-
- if( firstChar > lastChar ) {
- if( getSpan(fileId,startCp,&firstChar,&lastChar,0) )
- /* getSpan says startCp at EOF */
- break;
- /* check to see if the span is longer than the */
- /* area we are supposed to search */
- if( (long)(lastChar-firstChar) > (stopCp-startCp) ) {
- /* if it is too long then adjust lastChar */
- lastChar = firstChar + (stopCp - startCp);
- }
- }
-
- matched = re_scan(
- (unsigned int)firstChar,
- (unsigned int)lastChar,
- (unsigned int)(((long)firstChar)>>16),
- &p, &pat, &len );
- nLines += len;
- if( 0 == matched ) { /* not found */
- notFound:
- startCp += (int)(lastChar - firstChar) + 1;
- firstChar = (unsigned char far *)1;
- lastChar = (unsigned char far *)0;
- continue;
- }
-
- if( 2 == matched ) { /* found a partial match */
- /* where does the match begin */
- cp = startCp +
- ((unsigned int)p - (unsigned int)firstChar);
- leftOver = (unsigned int)lastChar - (unsigned int)p;
- /* fill textBuffer with the characters that */
- /* are in two or more spans */
- for( len = 0; len < MSGBUFFERSIZE; ++len )
- textBuffer[len] = readChar( fileId, cp++ );
- savedP = p;
- matched = re_scan(
- (unsigned int)textBuffer,
- (unsigned int)(textBuffer+255),
- segRegs.ds,
- &p, &pat, &len );
- if( 1 == matched && (p - textBuffer) < leftOver ) {
- *reLength = pat - p + 1;
- *linesPassed = nLines;
- return startCp + ((unsigned)savedP
- - (unsigned)firstChar);
- } else
- goto notFound;
- }
-
- /* we found the string */
- if( orOrEOW )
- /* There was an "|" or a "\>" in the string which */
- /* caused re_scan to return "pat" 1 too large. */
- --pat;
- *reLength = pat - p + 1;
- *linesPassed = nLines;
- return startCp + ((unsigned)p - (unsigned)firstChar);
- }
- *linesPassed = nLines;
- return (long)(-1);
- }
-
- void pascal
- /* XTAG:RETableSetup */
- RETableSetup()
- {
- extern char encode[];
- extern char reChars[];
-
- int i;
-
- for( i = 0; i < 256; ++i )
- encode[i] = SYM_OTHER;
- encode['\0'] = SYM_END;
- encode[')'] = SYM_CLOSE;
- encode['|'] = SYM_OR;
- encode['*'] = SYM_REP0;
- encode['('] = SYM_OPEN;
- reChars[RE_OR] = '|';
- reChars[RE_REP0] = '*';
- reChars[RE_REP1] = '+';
- reChars[RE_REP01] = '?';
- reChars[RE_BEGIN_LINE] = '^';
- reChars[RE_END_LINE] = '$';
- reChars[RE_BEGIN_WORD] = '<';
- reChars[RE_END_WORD] = '>';
- reChars[RE_OPEN_GROUP] = '(';
- reChars[RE_CLOSE_GROUP] = ')';
- reChars[RE_OPEN_CLASS] = '[';
- reChars[RE_CLOSE_CLASS] = ']';
- reChars[RE_NEGATE_CLASS] = '^';
- reChars[RE_ANY_CHAR] = '.';
- reChars[RE_ESCAPE_CHAR] = '\\';
- };
-
- /* locations in re_scan (in re2.asm) */
- extern void re_code( void );
- extern void re_cnode( void );
- extern void re_nnode( void );
- extern void re_found( void );
- extern void re_clist( void );
- extern void re_sidechars( void );
- extern void re_wordtable( void );
-
- int pascal
- /* XTAG:RECompile */
- RECompile()
- {
- extern char encode[];
- extern short stackChar[];
- extern char stackCode[];
- extern char *stackClass[];
- extern char *stackPc[];
- extern char code[];
- extern int pcTop, stackTop, reIndex;
- extern char *pcCode;
- extern char TransitionTable[][7];
- extern char *addrJmpFound;
-
- extern int findWholeWords;
- extern unsigned char msgBuffer[];
- extern struct SREGS segRegs;
-
- /* retyped versions of these addresses */
- extern char *re_code2;
- extern char *re_cnode2;
- extern char *re_nnode2;
- extern char *re_found2;
- extern char *re_clist2;
- extern char *re_sidechars2;
-
- /* re-typed versions of the external locations */
- int i, codeIn, codeStack, action;
- short charIn;
- char negated;
- int firstCharIndex;
- char *classIn;
- char ch;
- char *p;
-
- re_code2 = (char *)re_code;
- re_cnode2 = (char *)re_cnode;
- re_nnode2 = (char *)re_nnode;
- re_found2 = (char *)re_found;
- re_clist2 = (char *)re_clist;
- re_sidechars2 = (char *)re_sidechars;
- re_wordtable2 = (char *)re_wordtable;
- stackChar[0] = '\0';
- stackCode[0] = SYM_END;
- stackTop = 0;
- pcTop = 0;
- pcCode = &code[0];
- reIndex = 0;
- orOrEOW = 0; /* no OR "|" or end-of-word "\>" seen yet */
-
- /* handle the -w option */
- if( findWholeWords ) {
- /* move the RE in reIn down two characters */
- codeIn = strlen(reIn);
- for( i = codeIn-1; i >= 0; --i )
- reIn[i+2] = reIn[i];
- /* then insert the \< and the \> */
- reIn[0] = '\\';
- reIn[1] = '<';
- reIn[codeIn+2] = '\\';
- reIn[codeIn+3] = '>';
- reIn[codeIn+4] = '\0';
- }
- while( 1 ) {
- charIn = (short)(signed char)(reIn[reIndex++]);
- codeIn = SYM_OTHER; /* this is the most common case */
- if( charIn == reChars[RE_ANY_CHAR] )
- charIn = -RE_ANY_CHAR;
- else if( charIn == reChars[RE_OPEN_CLASS] ) {
- charIn = -RE_OPEN_CLASS;
- classIn = (char *)malloc(32);
- for( i = 0; i < 32; ++i )
- classIn[i] = 0;
- if( '^' == reIn[reIndex] ) {
- ++reIndex;
- negated = 1;
- } else
- negated = 0;
- firstCharIndex = reIndex;
- while( 1 ) {
- ch = reIn[reIndex++];
- switch( ch ) {
- case ']':
- if( reIndex != firstCharIndex )
- goto ClassEnded;
- /* else drop through to default */
- default:
- AllOthers:
- classIn[ch>>3] |= 1 << (ch&7);
- break;
- case '-':
- if( reIndex == firstCharIndex ||
- ']' == reIn[reIndex] )
- goto AllOthers;
- for( ch = reIn[reIndex-2];
- ch <= reIn[reIndex];
- ++ch )
- classIn[ch>>3] |= 1<<(ch&7);
- ++reIndex;
- break;
- }
- }
- ClassEnded:
- if( negated ) {
- for( i = 0; i < 32; ++i )
- classIn[i] = ~classIn[i];
- }
- reIn[reIndex-1] = -RE_OPEN_CLASS;
- } else if( charIn == reChars[RE_BEGIN_LINE] && 1 == reIndex )
- /* this must occur as the first character in the RE */
- charIn = -RE_BEGIN_LINE;
- else if( charIn == reChars[RE_END_LINE]
- && '\0' == reIn[reIndex] )
- /* this must occur as the last character in the RE */
- charIn = -RE_END_LINE;
- else if( charIn == reChars[RE_ESCAPE_CHAR] ) {
- charIn = reIn[reIndex++];
- switch( charIn ) {
- case '<':
- charIn = -RE_BEGIN_WORD;
- break;
- case '>':
- charIn = -RE_END_WORD;
- /* The end-word construct will cause the */
- /* final string length to be 1 too large. */
- /* This variable will cause it to be */
- /* reduced by 1 before it is returned. */
- orOrEOW = 1;
- break;
- case 'n':
- charIn = '\n';
- break;
- case 'r':
- charIn = '\r';
- break;
- case 't':
- charIn = '\t';
- break;
- case 'b':
- charIn = '\b';
- break;
- case 'a':
- charIn = '\a';
- break;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7':
- charIn -= '0'; /* convert to a number */
- while( 1 ) {
- ch = (short)(unsigned)reIn[reIndex++];
- if( ch < '0' || ch > '7' )
- break;
- charIn = 8*charIn + ch - '0';
- }
- --reIndex;
- break;
- case 'x':
- /* hex number */
- charIn = 0;
- while( 1 ) {
- ch = (short)(unsigned)reIn[reIndex++];
- if( !isxdigit(ch) )
- break;
- if( isupper(ch) )
- ch = tolower(ch);
- if( islower(ch) )
- ch += '0' + 10 - 'a';
- charIn = 16*charIn + ch - '0';
- }
- --reIndex;
- break;
- }
- /* replace the character with it escaped version */
- /* so that the -reIndex backup in ACT_JUXTA will */
- /* pick up the correct character */
- /* LATER: be sure that this fix works in all cases */
- reIn[reIndex-1] = charIn;
- } else
- codeIn = encode[charIn];
- NoCharRead:
- codeStack = stackCode[stackTop];
- action = TransitionTable[codeStack][codeIn];
- switch( action ) {
-
- case ACT_ERROR:
- sprintf(msgBuffer,
- "RE error near character %d of `%s'\n",
- reIndex-1, reIn);
- msg(msgBuffer, 2);
- return 0;
-
- case ACT_JUXTA:
- codeIn = SYM_JUXTA;
- --reIndex; /* undo the read of the character */
- goto NoCharRead;
-
- case ACT_STOP:
- addrJmpFound = pcCode - code + re_code2;
- *pcCode++ = OP_JMP;
- *(short *)pcCode = (short)(re_found2
- - (pcCode+2-code+re_code2));
- pcCode += 2;
- goto ret1;
-
- case ACT_PUSH:
- ++stackTop;
- stackChar[stackTop] = charIn;
- stackCode[stackTop] = codeIn;
- stackClass[stackTop] = classIn;
- break;
-
- case ACT_POP:
- switch( codeStack ) {
- case SYM_OPEN:
- /* LATER: code to record sub-re's */
- break;
- case SYM_CLOSE:
- /* LATER: code to record sub-re's */
- break;
- case SYM_END:
- /* code emitted in case ACT_STOP */
- break;
- case SYM_JUXTA:
- --pcTop;
- break;
- case SYM_OTHER:
- HandleSymOther();
- break;
- case SYM_REP0:
- *pcCode++ = OP_CALL;
- *(short *)pcCode = (short)(re_cnode2
- - (pcCode+2-code+re_code2));
- pcCode += 2;
- p = stackPc[pcTop-1];
- *((short *)(p+1)) += (p - pcCode);
- for( i = 0; i < 3; ++i )
- *pcCode++ = *p++;
- p = stackPc[pcTop-1];
- *p++ = OP_JMP;
- *(short *)p = (pcCode-6) - (p+2);
- break;
- case SYM_OR:
- /* The "or" construct will cause the */
- /* final string length to be 1 too large. */
- /* This variable will cause it to be */
- /* reduced by 1 before it is returned. */
- orOrEOW = 1;
- *pcCode++ = OP_JMP;
- *(short *)pcCode = 9;
- pcCode += 2;
- *pcCode++ = OP_CALL;
- *(short *)pcCode = (short)(re_cnode2
- - (pcCode+2-code+re_code2));
- pcCode += 2;
- p = stackPc[pcTop-1];
- *((short *)(p+1)) += (p - pcCode);
- for( i = 0; i < 3; ++i )
- *pcCode++ = *p++;
- p = stackPc[pcTop-2];
- *((short *)(p+1)) += (p - pcCode);
- for( i = 0; i < 3; ++i )
- *pcCode++ = *p++;
- p = stackPc[pcTop-2];
- *((short *)(p+1)) += (p - pcCode);
- *p++ = OP_JMP;
- *(short *)p = (pcCode-9) - (p+2);
- p = stackPc[pcTop-1];
- *p++ = OP_JMP;
- *(short *)p = pcCode - (p+2);
- --pcTop;
- break;
- }
- --stackTop; /* pop the character */
- goto NoCharRead;
-
- case ACT_POP2:
- stackTop -= 2;
- goto NoCharRead;
- }
- }
- ret1:
- /* see if the first character of the RE is a */
- /* constant character if so the RE scanner can go */
- /* very fast by using the scasb assembly language */
- /* instruction. This triples the search speed */
- reFast1 = reFast2 = '\0';
- /* check for the code pattern of a char constant */
- if( 0 == *(short *)(code + 1) && OP_CMP==code[3] ) {
- /* code pattern of merged case character */
- reFast1 = code[4];
- if( OP_CMP == code[7] ) {
- reFast1 = code[8];
- reFast2 = code[4];
- }
- }
-
- /* now move the bytes into the code segment */
- movedata( segRegs.ds, (unsigned)(&code[0]),
- (unsigned)((long)re_code>>16), (unsigned)re_code,
- pcCode - &code[0] );
- return 1;
- }
-
- void pascal
- /* XTAG:HandleSymOther */
- HandleSymOther()
- {
- extern int ignoreCase;
-
- short ch;
- int i;
- char *p, *bitmapAddr;
-
- ch = stackChar[stackTop];
- stackPc[pcTop++] = pcCode;
- *pcCode++ = OP_JMP;
- *(short *)pcCode = 0;
- pcCode += 2;
- if( ch >= 0 ) {
-
- FindChar:
- /* handle case insensitivity */
- if( ignoreCase && isascii(ch) && isalpha(ch) ) {
- /* underscored versions are a bit faster */
- *pcCode++ = OP_CMP;
- *pcCode++ = (isupper(ch) ?
- _tolower(ch) : _toupper(ch));
- *pcCode++ = OP_JE;
- *pcCode++ = 7;
- }
- *pcCode++ = OP_CMP;
- *pcCode++ = ch;
- *pcCode++ = OP_JE;
- *pcCode++ = 3;
- *pcCode++ = OP_JMP;
- *(short *)pcCode = (short)(re_clist2
- - (pcCode+2-code
- +(char *)re_code2));
- pcCode += 2;
- *pcCode++ = OP_CALL;
- *(short *)pcCode = (short)(re_nnode2
- - (pcCode+2-code+re_code2));
- pcCode += 2;
- } else switch( -ch ) {
- case RE_OPEN_CLASS:
-
- /* change the jump to jump over the bit map */
- *(short *)(pcCode-2) = 32;
-
- /* now insert the bit map */
- bitmapAddr = pcCode - code + re_code2;
- p = stackClass[stackTop];
- for( i = 0; i < 32; ++i )
- *pcCode++ = *p++;
-
- /* now the code to handle the bit map */
- *pcCode++ = 0x32;
- *pcCode++ = 0xFF; /* xor bh,bh */
- *pcCode++ = OP_MOV;
- *pcCode++ = 0xD8; /* mov bl,al */
- *pcCode++ = 0xB1;
- *pcCode++ = 0x03; /* mov cl,3 */
- *pcCode++ = OP_SHR;
- *pcCode++ = 0xEB; /* shr bl,cl */
- *pcCode++ = OP_MOV;
- *pcCode++ = 0xA7; /* mov ah,bitmapAddr[bx] */
- *(char* *)pcCode = bitmapAddr;
- pcCode += 2;
- *pcCode++ = OP_MOV;
- *pcCode++ = 0xC8; /* mov cl,al */
- *pcCode++ = OP_AND;
- *pcCode++ = 0xE1;
- *pcCode++ = 0x07; /* and cl,7 */
- *pcCode++ = OP_SHR;
- *pcCode++ = 0xEC; /* shr ah,cl */
- *pcCode++ = OP_AND;
- *pcCode++ = 0xE4;
- *pcCode++ = 0x01; /* and ah,1 */
- *pcCode++ = OP_JNE;
- *pcCode++ = 3;
- *pcCode++ = OP_JMP;
- *(short *)pcCode = (short)(re_clist2
- - (pcCode+2-code+(char *)re_code2));
- pcCode += 2;
- *pcCode++ = OP_CALL;
- *(short *)pcCode = (short)(re_nnode2
- - (pcCode+2-code+re_code2));
- pcCode += 2;
- free( stackClass[stackTop] );
- break;
- case RE_ANY_CHAR:
- /* no filtering code -- anything matches */
- *pcCode++ = OP_CALL;
- *(short *)pcCode = (short)(re_nnode2
- - (pcCode+2-code+re_code2));
- pcCode += 2;
- break;
- case RE_BEGIN_LINE:
- *pcCode++ = OP_CMPI;
- *pcCode++ = 0x3E; /* mod/r/m byte: direct address */
- *(short *)pcCode = (short)re_sidechars2;
- pcCode += 2;
- *pcCode++ = '\n'; /* immediate data -- a NL */
- *pcCode++ = OP_JE;
- *pcCode++ = 3;
- *pcCode++ = OP_JMP;
- *(short *)pcCode = (short)(re_clist2
- - (pcCode+2-code+(char *)re_code2));
- pcCode += 2;
- break;
- case RE_BEGIN_WORD:
- *pcCode++ = 0x32;
- *pcCode++ = 0xFF; /* xor bh,bh */
- *pcCode++ = OP_MOV;
- *pcCode++ = 0x1E; /* mov bl,BYTE PTR re_sidechars */
- *(short *)pcCode = (short)re_sidechars2;
- pcCode += 2;
- *pcCode++ = 0xB1;
- *pcCode++ = 0x03; /* mov cl,3 */
- *pcCode++ = OP_SHR;
- *pcCode++ = 0xEB; /* shr bl,cl */
- *pcCode++ = OP_MOV;
- *pcCode++ = 0xA7; /* mov ah,re_wordtable[bx] */
- *(short *)pcCode = (short)re_wordtable2;
- pcCode += 2;
- *pcCode++ = OP_MOV;
- *pcCode++ = 0x0E; /* mov cl,BYTE PTR re_sidechars */
- *(short *)pcCode = (short)re_sidechars2;
- pcCode += 2;
- *pcCode++ = OP_AND;
- *pcCode++ = 0xE1;
- *pcCode++ = 0x07; /* and cl,7 */
- *pcCode++ = OP_SHR;
- *pcCode++ = 0xEC; /* shr ah,cl */
- *pcCode++ = OP_AND;
- *pcCode++ = 0xE4;
- *pcCode++ = 0x01; /* and ah,1 */
- *pcCode++ = OP_JE;
- *pcCode++ = 3;
- *pcCode++ = OP_JMP;
- *(short *)pcCode = (short)(re_clist2
- - (pcCode+2-code+(char *)re_code2));
- pcCode += 2;
- break;
- case RE_END_LINE:
- /* LATER: THIS NEEDS FIXING. We need to correct three things: */
- /* 1. The '\r' should NOT be part of the matched string. */
- /* 2. It should work for lines that end with '\n' also. */
- /* 3. It should work if we are at the end of the file, even */
- /* if the file does not end in a CRNL or a NL. */
- ch = '\r';
- goto FindChar;
- case RE_END_WORD:
- *pcCode++ = 0x32;
- *pcCode++ = 0xFF; /* xor bh,bh */
- *pcCode++ = OP_MOV;
- *pcCode++ = 0xD8; /* mov bl,al */
- *pcCode++ = 0xB1;
- *pcCode++ = 0x03; /* mov cl,3 */
- *pcCode++ = OP_SHR;
- *pcCode++ = 0xEB; /* shr bl,cl */
- *pcCode++ = OP_MOV;
- *pcCode++ = 0xA7; /* mov ah,re_wordtable[bx] */
- *(short *)pcCode = (short)re_wordtable2;
- pcCode += 2;
- *pcCode++ = OP_MOV;
- *pcCode++ = 0xC8; /* mov cl,al */
- *pcCode++ = OP_AND;
- *pcCode++ = 0xE1;
- *pcCode++ = 0x07; /* and cl,7 */
- *pcCode++ = OP_SHR;
- *pcCode++ = 0xEC; /* shr ah,cl */
- *pcCode++ = OP_AND;
- *pcCode++ = 0xE4;
- *pcCode++ = 0x01; /* and ah,1 */
- *pcCode++ = OP_JE;
- *pcCode++ = 3;
- *pcCode++ = OP_JMP;
- *(short *)pcCode = (short)(re_clist2
- - (pcCode+2-code+(char *)re_code2));
- pcCode += 2;
- break;
- }
- }
-