Example #1
0
struct InstrSeq * doPrintsp(struct ExprRes * Expr){
    if(Expr->Type != TYPE_INT){
        TypeError();
    }
    struct InstrSeq * code;
    code = Expr->Instrs;
    char * end = GenLabel();
    char * next = GenLabel();
    int i = AvailTmpReg();
    int one = AvailTmpReg();


    AppendSeq(code, GenInstr(NULL, "addi", TmpRegName(one), "$0", "1"));
    AppendSeq(code, GenInstr(NULL, "blt", TmpRegName(Expr->Reg), "$0", end));
    AppendSeq(code, GenInstr(NULL, "li", TmpRegName(i), "0", NULL));
    AppendSeq(code, GenInstr(next, NULL,NULL,NULL,NULL));
   
    AppendSeq(code, GenInstr(NULL, "li", "$v0", "4", NULL));
    AppendSeq(code, GenInstr(NULL, "la", "$a0", "_sp", NULL));
    AppendSeq(code, GenInstr(NULL, "syscall", NULL, NULL,NULL));

    AppendSeq(code, GenInstr(NULL, "addi", TmpRegName(i), TmpRegName(i), "1"));
    AppendSeq(code, GenInstr(NULL, "blt", TmpRegName(i), TmpRegName(Expr->Reg), next));
    
    AppendSeq(code, GenInstr(end, NULL,NULL,NULL,NULL));
    ReleaseTmpReg(i);
    ReleaseTmpReg(one);
    ReleaseTmpReg(Expr->Reg);
    free(Expr);
    free(end);
    free(next);
    
    return code;

}
Example #2
0
extern struct ExprRes * doRelOp(struct ExprRes * Res1, struct ExprRes * Res2, int op){
    
    if(Res1->Type != TYPE_INT || Res2->Type != TYPE_INT){
        TypeError();
    }

    struct InstrSeq * iseq;
    char * t_res = GenLabel();
   
    char * end = GenLabel();
    int reg = AvailTmpReg();

    if (op == 0 ){
        iseq = GenInstr(NULL, "beq", TmpRegName(Res1->Reg), TmpRegName(Res2->Reg), t_res);
    }
    else if (op == 1){
        iseq = GenInstr(NULL, "beq", TmpRegName(Res1->Reg), TmpRegName(Res2->Reg), t_res);
        AppendSeq(iseq, GenInstr(NULL, "bgt", TmpRegName(Res1->Reg), TmpRegName(Res2->Reg), t_res));
    }
    else if (op == 2) {
        iseq = GenInstr(NULL, "beq", TmpRegName(Res1->Reg), TmpRegName(Res2->Reg), t_res);
        AppendSeq(iseq, GenInstr(NULL, "blt", TmpRegName(Res1->Reg), TmpRegName(Res2->Reg), t_res));
    }
    else if (op == 3) {
        iseq = GenInstr(NULL, "bne", TmpRegName(Res1->Reg), TmpRegName(Res2->Reg), t_res);
    }
    else if (op == 4) {
        iseq = GenInstr(NULL, "blt", TmpRegName(Res1->Reg), TmpRegName(Res2->Reg),t_res);
    }
    else if (op == 5) {
        iseq = GenInstr(NULL, "bgt", TmpRegName(Res1->Reg), TmpRegName(Res2->Reg), t_res);
    }

    AppendSeq(iseq, GenInstr(NULL, "li", TmpRegName(reg), "0", NULL));
    AppendSeq(iseq, GenInstr(NULL, "b", end, NULL,NULL));
    AppendSeq(iseq, GenInstr(t_res, NULL,NULL,NULL,NULL));
    AppendSeq(iseq, GenInstr(NULL, "li", TmpRegName(reg), "1", NULL));
    AppendSeq(iseq, GenInstr(end, NULL,NULL,NULL,NULL));

    AppendSeq(Res1->Instrs, Res2->Instrs);
    AppendSeq(Res1->Instrs, iseq);
    ReleaseTmpReg(Res1->Reg);
    ReleaseTmpReg(Res2->Reg);
    free(t_res);
    free(end);
    free(Res2);
    Res1->Reg = reg;
    Res1->Type = TYPE_BOOL;
    return Res1;
}
Example #3
0
int CodeGenerator::GenDoStart()
{
   GenBlockHeader( "Do loop" );
   int newLabel = CreateLabel();
   GenLabel( newLabel );
   return newLabel;
}
Example #4
0
struct ExprRes * doNot(struct ExprRes * Res){
    if(Res->Type != TYPE_BOOL){
        TypeError();
    }
    char * fal = GenLabel();
    char * end = GenLabel();

    AppendSeq(Res->Instrs, GenInstr(NULL, "beq", "$0", TmpRegName(Res->Reg), fal));
    AppendSeq(Res->Instrs, GenInstr(NULL, "li", TmpRegName(Res->Reg), "0", NULL ));
    AppendSeq(Res->Instrs, GenInstr(NULL, "b", end, NULL,NULL));
    AppendSeq(Res->Instrs, GenInstr(fal, NULL, NULL, NULL, NULL));
    AppendSeq(Res->Instrs, GenInstr(NULL, "li", TmpRegName(Res->Reg), "1", NULL ));
    AppendSeq(Res->Instrs, GenInstr(end, NULL,NULL,NULL,NULL));
    
    return Res;

}
Example #5
0
extern struct InstrSeq * doWhile(struct ExprRes *res, struct InstrSeq *seq){
    if( res->Type != TYPE_BOOL){
        TypeError();
    }
    struct InstrSeq * code;
    char * loop = GenLabel();
    char * end = GenLabel();
    code = GenInstr(loop, NULL, NULL, NULL, NULL);
    AppendSeq(code, res->Instrs);
    AppendSeq(code, GenInstr(NULL, "beq", TmpRegName(res->Reg), "$0", end));
    AppendSeq(code, seq);
    AppendSeq(code, GenInstr(NULL, "b", loop, NULL, NULL));
    AppendSeq(code, GenInstr(end, NULL, NULL, NULL, NULL));
    ReleaseTmpReg(res->Reg);
    free(res);
    free(loop);
    free(end);
    return code;
}
Example #6
0
void CodeGenerator::GenFuncEnd( std::string funcName, int retLabel )
{
   funcName = '_' + funcName;
   GenLine();
   GenLabel( retLabel );
   GenMov( "esp", "ebp" );
   GenPop( "ebp" );
   GenLine( "RET" );
   GenLine( funcName + " ENDP" );
}
Example #7
0
void CodeGenerator::GenNot()
{
   GenBlockHeader( "Not" );
   GenPop( "eax" );
   GenMov( "edx", "0" );
   GenLine( "cmp eax, 0" );
   GenLine( "JNE L" + toString( ++mLabelCount ) );
   GenLine( "inc edx" );
   GenLabel( mLabelCount );
   GenPush( "edx" );
}
Example #8
0
struct InstrSeq * doPrint(struct ExprRes * Expr) { 

   struct InstrSeq *code;
   
   code = Expr->Instrs;
   char * end = GenLabel();

   if (Expr->Type == TYPE_BOOL){
       
        char * fal = GenLabel();

        AppendSeq(code,GenInstr(NULL,"li","$v0","4",NULL));
        
        AppendSeq(code, GenInstr(NULL, "beq", "$0", TmpRegName(Expr->Reg), fal));

        AppendSeq(code,GenInstr(NULL,"la","$a0","_tru",NULL));
        AppendSeq(code,GenInstr(NULL,"syscall",NULL,NULL,NULL));
        AppendSeq(code, GenInstr(NULL, "b", end, NULL, NULL));       
 
        AppendSeq(code, GenInstr(fal, NULL, NULL, NULL, NULL));
        AppendSeq(code,GenInstr(NULL,"la","$a0","_fal",NULL));
        AppendSeq(code,GenInstr(NULL,"syscall",NULL,NULL,NULL));    
   
   }  
   else if(Expr->Type == TYPE_INT){

        AppendSeq(code,GenInstr(NULL,"li","$v0","1",NULL));
        AppendSeq(code,GenInstr(NULL,"move","$a0",TmpRegName(Expr->Reg),NULL));
        AppendSeq(code,GenInstr(NULL,"syscall",NULL,NULL,NULL));
   }
   else if (Expr->Type == TYPE_STR){
        AppendSeq(code, GenInstr(NULL, "li", "$v0", "4", NULL));
        AppendSeq(code, GenInstr(NULL, "move", "$a0", TmpRegName(Expr->Reg), NULL));
        AppendSeq(code, GenInstr(NULL, "syscall", NULL, NULL, NULL));
   }    
    AppendSeq(code, GenInstr(end,NULL,NULL,NULL,NULL));   
    ReleaseTmpReg(Expr->Reg);
    free(Expr);

  return code;
}
Example #9
0
void CodeGenerator::GenOr()
{
   GenBlockHeader( "Or" );
   GenPop( "ecx" );
   GenPop( "eax" );
   GenMov( "edx", "0" );
   GenLine( "or eax, ecx" );
   GenLine( "cmp eax, 0" );
   GenLine( "JE L" + toString( ++mLabelCount ) );
   GenLine( "inc edx" );
   GenLabel( mLabelCount );
   GenPush( "edx" );
}
Example #10
0
void CodeGenerator::GenAnd()
{
   GenBlockHeader( "And" );
   GenPop( "ecx" );
   GenPop( "eax" );
   GenLine( "imul ecx" );
   GenMov( "edx", "0" );
   GenLine( "cmp eax, 0" );
   mAsmCode += "JE";
   mAsmCode += " L" + toString( ++mLabelCount ) + "\n";
   GenLine( "inc edx" );
   GenLabel( mLabelCount );
   GenPush( "edx" );
}
Example #11
0
struct ExprRes * doStrLit(char * str){
    struct ExprRes *res;
    struct StrLabels * strl;
    strl =  malloc(sizeof(struct StrLabels));
    strl->SLabel = GenLabel();
    strl->Str = strdup( str);
    strl->next = slabels;
    slabels = strl; 
    res = (struct ExprRes *) malloc(sizeof(struct ExprRes));
    res->Reg = AvailTmpReg();
    res->Instrs = GenInstr(NULL, "la", TmpRegName(res->Reg),strl->SLabel, NULL);
    res->Type = TYPE_STR;   
    return res;
}
Example #12
0
extern struct InstrSeq * doIfElse(struct ExprRes *res, struct InstrSeq * iseq, struct InstrSeq *eseq){
    if(res->Type != TYPE_BOOL){
        TypeError();
    }
    struct InstrSeq * code;
    code = res->Instrs;
    char * else_label = GenLabel();
    char *end = GenLabel();
   
    AppendSeq(code, GenInstr(NULL, "beq", TmpRegName(res->Reg), "$0", else_label));
    AppendSeq(code, iseq);
    AppendSeq(code, GenInstr(NULL, "b", end,NULL,NULL));
    AppendSeq(code, GenInstr(else_label, NULL,NULL,NULL,NULL));
    AppendSeq(code, eseq);
    AppendSeq(code, GenInstr(end, NULL,NULL,NULL,NULL));

    ReleaseTmpReg(res->Reg);
    free(res);
    free(else_label);
    free(end);
    return code;

}
Example #13
0
struct ExprRes * doPower(struct ExprRes * Res1, struct ExprRes * Res2) {
    if(Res1->Type != TYPE_INT || Res2->Type != TYPE_INT){
        TypeError();
    }
    int reg;
    reg = AvailTmpReg();
    
    struct InstrSeq* iseq;
    int pow = AvailTmpReg();
    int current = AvailTmpReg();
    char * l1 = GenLabel();
    char * l2 = GenLabel();

    iseq = GenInstr(NULL, "move", TmpRegName(pow), "$0", NULL);
    AppendSeq(iseq, GenInstr(NULL, "addi", TmpRegName(current), "$0", "1"));
    AppendSeq(iseq, GenInstr(NULL, "beq", TmpRegName(Res2->Reg), "$0", l2));
    AppendSeq(iseq, GenInstr(l1, NULL, NULL, NULL, NULL));
    AppendSeq(iseq, GenInstr(NULL, "mul", TmpRegName(current), TmpRegName(current), TmpRegName(Res1->Reg)));
    AppendSeq(iseq, GenInstr(NULL, "addi", TmpRegName(pow), TmpRegName(pow), "1"));
    AppendSeq(iseq, GenInstr(NULL, "blt", TmpRegName(pow), TmpRegName(Res2->Reg), l1));
    AppendSeq(iseq, GenInstr(l2, NULL, NULL, NULL, NULL));

    AppendSeq(Res1->Instrs, Res2->Instrs);
    AppendSeq(Res1->Instrs, iseq);
    ReleaseTmpReg(Res1->Reg);
    ReleaseTmpReg(Res2->Reg);
    ReleaseTmpReg(pow);
    Res1->Reg = current;
    free(l1);
    free(l2);
    free(Res2);

    return Res1;
        
    

  }
Example #14
0
void CodeGenerator::GenCompare( std::string sign )
{
   GenBlockHeader( "Compare" );
   GenPop( "ecx" );
   GenPop( "eax" );
   GenMov( "edx", "0" );
   GenLine( "cmp eax, ecx" );
   if( sign == "==" ) mAsmCode += "JNE ";
   if( sign == "!=" ) mAsmCode += "JE";
   if( sign == ">" ) mAsmCode += "JLE";
   if( sign == "<" ) mAsmCode += "JGE";
   if( sign == ">=" ) mAsmCode += "JL";
   if( sign == "<=" ) mAsmCode += "JG";
   mAsmCode += " L" + toString( ++mLabelCount ) + "\n";
   GenLine( "inc edx" );
   GenLabel( mLabelCount );
   GenPush( "edx" );
}
Example #15
0
extern struct InstrSeq * doIf(struct ExprRes *res, struct InstrSeq *seq){
    if(res->Type != TYPE_BOOL){
        TypeError();
    }

    
    struct InstrSeq *code;
    code = res->Instrs;
    char * label;
    label = GenLabel();
    AppendSeq(code, GenInstr(NULL, "beq", TmpRegName(res->Reg), "$0",label ));
    AppendSeq(code, seq);
    AppendSeq(code, GenInstr(label, NULL,NULL,NULL,NULL));
    ReleaseTmpReg(res->Reg);
    free(res);
    free(label);
    return code;

}
Example #16
0
void GenFin(void)
{
  if (StructCpyLabel)
  {
    char s[1 + 2 + (2 + CHAR_BIT * sizeof StructCpyLabel) / 3];
    char *p = s + sizeof s;
    int lbl = LabelCnt++;

    *--p = '\0';
    p = lab2str(p, StructCpyLabel);
    *--p = '_';
    *--p = '_';

    if (OutputFormat != FormatFlat)
      puts2(CodeHeader);

    GenLabel(p, 1);

    puts2("\tmove\t$2, $6\n"
          "\tmove\t$3, $6");
    GenNumLabel(lbl);
    puts2("\tlbu\t$6, 0($5)\n"
          "\taddiu\t$5, $5, 1\n"
          "\taddiu\t$4, $4, -1\n"
          "\tsb\t$6, 0($3)\n"
          "\taddiu\t$3, $3, 1");
    printf2("\tbne\t$4, $0, "); GenPrintNumLabel(lbl);
    puts2("");
#ifndef NO_REORDER_WORKAROUND
    GenNop();
#endif
    puts2("\tj\t$31");
#ifndef NO_REORDER_WORKAROUND
    GenNop();
#endif

    if (OutputFormat != FormatFlat)
      puts2(CodeFooter);
  }
}
Example #17
0
/*
 * PreProcess - pre-process source file
 */
vi_rc PreProcess( const char *fn, sfile **sf, labels *lab )
{
    GENERIC_FILE        gf;
    int                 i, token, k, len;
    sfile               *tsf;
    char                tmp[MAX_SRC_LINE], tmp2[MAX_SRC_LINE];
    char                tmp3[MAX_SRC_LINE];
    bool                ret;
#ifdef VICOMP
    bool                AppendingFlag = FALSE;
#else
    #define             AppendingFlag   EditFlags.Appending
#endif

    /*
     * get source file
     */
#ifdef VICOMP
    ret = SpecialOpen( fn, &gf );
#else
    if( EditFlags.CompileScript ) {
        EditFlags.OpeningFileToCompile = TRUE;
        ret = SpecialOpen( fn, &gf, FALSE );
        EditFlags.OpeningFileToCompile = FALSE;
    } else {
        ret = SpecialOpen( fn, &gf, EditFlags.BoundData );
    }
#endif
    if( !ret ) {
        return( ERR_FILE_NOT_FOUND );
    }

    /*
     * init control
     */
    CSInit();
    CurrentSrcLine = 0L;

    tsf = MemAlloc( sizeof( sfile ) );
    tsf->next = NULL;
    tsf->prev = NULL;
    tsf->arg1 = NULL;
    tsf->arg2 = NULL;
    tsf->data = NULL;
    tsf->token = SRC_T_NULL;
    *sf = tmpTail = tsf;
    cLab = lab;

    /*
     * set up error handler
     */
    i = setjmp( genExit );
    if( i != 0 ) {
        SpecialFclose( &gf );
        return( (vi_rc)i );
    }

    /*
     * process each line
     */
    while( SpecialFgets( tmp, MAX_SRC_LINE - 1, &gf ) >= 0 ) {

        /*
         * prepare this line
         */
        CurrentSrcLine++;
#ifndef VICOMP
        if( !EditFlags.ScriptIsCompiled ) {
#endif
            RemoveLeadingSpaces( tmp );
            k = strlen( tmp );
            memcpy( tmp3, tmp, k + 1 );
            if( (len = NextWord1( tmp, tmp2 )) <= 0 ) {
                continue;
            }
            if( tmp2[0] == '#' ) {
                continue;
            }
            hasVar = FALSE;
            for( i = 0; i < k; i++ ){
                if( tmp3[i] == '%' ) {
                    hasVar = TRUE;
                    break;
                }
            }

            /*
             * if we are appending (ie, an append token was encounterd
             * before, stop tokenizing
             */
            if( !AppendingFlag ) {
                token = Tokenize( SourceTokens, tmp2, TRUE );
#ifndef VICOMP
                if( token == SRC_T_VBJ__ ) {
                    EditFlags.ScriptIsCompiled = TRUE;
                    continue;
                }
#endif
            } else {
                token = TOK_INVALID;
            }
#ifndef VICOMP
        } else {
            len = NextWord1( tmp, tmp2 );
            hasVar = (bool) tmp2[0] - '0';
            token = atoi( &tmp2[1] );
        }
#endif
        /*
         * process recognized tokens
         */
        if( token != TOK_INVALID ) {

            RemoveLeadingSpaces( tmp );
            if( token > SRC_T_NULL ) {
                genItem( token, tmp );
                continue;
            }

            /*
             * get parm
             */
            AddString( &CurrentSrcData, tmp );
            freeSrcData = TRUE;

            /*
             * process token
             */
            switch( token ) {
            case SRC_T_EXPR:
                genExpr();
                break;
            case SRC_T_LABEL:
                GenLabel( tmp );
                break;
            case SRC_T_IF:
                CSIf();
                break;
            case SRC_T_QUIF:
                CSQuif();
                break;
            case SRC_T_ELSEIF:
                CSElseIf();
                break;
            case SRC_T_ELSE:
                CSElse();
                break;
            case SRC_T_ENDIF:
                CSEndif();
                break;
            case SRC_T_LOOP:
                CSLoop();
                break;
            case SRC_T_ENDLOOP:
            case SRC_T_ENDWHILE:
                CSEndLoop();
                break;
            case SRC_T_WHILE:
                CSWhile();
                break;
            case SRC_T_UNTIL:
                CSUntil();
                break;
            case SRC_T_BREAK:
                CSBreak();
                break;
            case SRC_T_CONTINUE:
                CSContinue();
                break;
            default:
                genItem( token, NULL );
                if( token == SRC_T_GOTO ) {
#ifndef VICOMP
                    if( EditFlags.ScriptIsCompiled ) {
                        NextWord1( CurrentSrcData, tmp );
                        tmpTail->branchcond = atoi( CurrentSrcData );
                        strcpy( CurrentSrcData, tmp );
                    } else {
#endif
                        tmpTail->branchcond = COND_JMP;
#ifndef VICOMP
                    }
#endif
                }
                tmpTail->data = CurrentSrcData;
                freeSrcData = FALSE;
                break;
            }
            if( freeSrcData ) {
                MemFree( CurrentSrcData );
            }
        /*
         * set all other tokens to be processed at run time
         */
        } else {
#ifndef VICOMP
            if( EditFlags.ScriptIsCompiled ) {
                RemoveLeadingSpaces( tmp );
                genItem( token, tmp );
                continue;
            }
#endif
            if( !AppendingFlag ) {
                token = Tokenize( TokensCmdLine, tmp2, TRUE );
            } else {
                token = TOK_INVALID;
            }
            switch( token ) {
            case PCL_T_COMMANDWINDOW:
            case PCL_T_STATUSWINDOW:
            case PCL_T_COUNTWINDOW:
            case PCL_T_EDITWINDOW:
            case PCL_T_EXTRAINFOWINDOW:
            case PCL_T_FILECWINDOW:
            case PCL_T_LINENUMBERWINDOW:
            case PCL_T_DIRWINDOW:
            case PCL_T_FILEWINDOW:
            case PCL_T_SETWINDOW:
            case PCL_T_SETVALWINDOW:
            case PCL_T_MESSAGEWINDOW:
            case PCL_T_MENUWINDOW:
            case PCL_T_MENUBARWINDOW:
            case PCL_T_ENDWINDOW:
            case PCL_T_SETCOLOR:
            case PCL_T_MATCH:
            case PCL_T_DIMENSION:
            case PCL_T_BORDER:
            case PCL_T_HILIGHT:
            case PCL_T_TEXT:
            case PCL_T_ALIAS:
            case PCL_T_ABBREV:
            case PCL_T_MENU:
            case PCL_T_MENUITEM:
            case PCL_T_ENDMENU:
            case PCL_T_WHITESPACE:
            case PCL_T_SELECTION:
            case PCL_T_EOFTEXT:
            case PCL_T_KEYWORD:
            case PCL_T_OCTAL:
            case PCL_T_HEX:
            case PCL_T_INTEGER:
            case PCL_T_CHAR:
            case PCL_T_PREPROCESSOR:
            case PCL_T_SYMBOL:
            case PCL_T_INVALIDTEXT:
            case PCL_T_IDENTIFIER:
            case PCL_T_JUMPLABEL:
            case PCL_T_COMMENT:
            case PCL_T_FLOAT:
            case PCL_T_STRING:
            case PCL_T_VARIABLE:
            case PCL_T_FILETYPESOURCE:
            case PCL_T_ENDFILETYPESOURCE:
            case PCL_T_LOCATE:
            case PCL_T_MAP:
            case PCL_T_MAP_DMT:

            case PCL_T_MENUFILELIST:
            case PCL_T_MENULASTFILES:

            case PCL_T_DEFAULTWINDOW:
            case PCL_T_ACTIVEMENUWINDOW:
            case PCL_T_GREYEDMENUWINDOW:
            case PCL_T_ACTIVEGREYEDMENUWINDOW:
                RemoveLeadingSpaces( tmp );
                token += SRC_T_NULL + 1;
                genItem( token, tmp );
                break;

            case PCL_T_SET:
                token += SRC_T_NULL + 1;
#ifdef VICOMP
                WorkLine->data[0] = 0;
                Set( tmp );
                genItem( token, WorkLine->data );
#else
                if( EditFlags.CompileScript ) {
                    vi_rc   rc;

                    WorkLine->data[0] = 0;
                    rc = Set( tmp );
                    if( rc != ERR_NO_ERR ) {
                        Error( GetErrorMsg( rc ) );
                    }
                    genItem( token, WorkLine->data );
                } else {
                    genItem( token, tmp );
                }
#endif
                break;

            default:
                if( AppendingFlag ) {
                    if( tmp3[0] == '.' && tmp3[1] == 0 ) {
                        AppendingFlag = FALSE;
                    }
                } else if( token == TOK_INVALID ) {
                    /*
                     * see if the current token is a Ex token.  If
                     * it isn't, then see if the next one is
                     * (i.e., look for <n> append)
                     */
                    token = Tokenize( TokensEx, tmp2, FALSE );
                    if( token == TOK_INVALID ) {
                        if( NextWord1( tmp, tmp2 ) >= 0 ) {
                            token = Tokenize( TokensEx, tmp2, FALSE );
                            if( token == EX_T_APPEND ) {
                                AppendingFlag = TRUE;
                            }
                        }
                    }
                }
                if( tmp3[0] == '>' ) {
                    tmp3[0] = ' ';
                }
                genItem( TOK_INVALID, tmp3 );
                break;
            }
        }

    }

    SpecialFclose( &gf );
    AppendingFlag = FALSE;
    return( CSFini() );

} /* PreProcess */
Example #18
0
void GenExportLabel( instruction *lbl )
{
    GenLabel( lbl );
    lbl->operand++;     /* so it never gets deleted */
}