Пример #1
0
/*
 * Substitute - perform substitution
 */
vi_rc Substitute( linenum n1, linenum n2, char *data )
{
    char        *sstr, *rstr, *newr;
    char        flag[20], *linedata;
    bool        iflag = false;
    bool        gflag = false;
    bool        undoflag = false;
    bool        restline = false;
    bool        splitpending = false;
    bool        undoline = false;
    int         i, rlen, slen;
    bool        splitme;
    long        changecnt = 0, linecnt = 0;
    linenum     llineno, ll, lastline = 0, extra;
    i_mark      pos;
    vi_rc       rc;

    LastSubstituteCancelled = 0;
    LastChangeCount = 0;
    LastLineCount = 0;

    sstr = alloca( MAX_INPUT_LINE );
    if( sstr == NULL ) {
        return( ERR_NO_STACK );
    }
    strcpy( sstr, data );
    rc = ModificationTest();
    if( rc != ERR_NO_ERR ) {
        return( rc );
    }
    strcpy( data, sstr );
    rstr = alloca( MAX_INPUT_LINE  );
    if( rstr == NULL ) {
        return( ERR_NO_STACK );
    }
    if( NextWordSlash( data, sstr ) < 0 ) {
        return( ERR_INVALID_SUBS_CMD );
    }
    if( NextWordSlash( data, rstr ) < 0 ) {
        return( ERR_INVALID_SUBS_CMD );
    }
    slen = NextWord1( data, flag );
    for( i = 0; i < slen; i++ ) {
        switch( flag[i] ) {
        case 'g':
            gflag = true;
            break;
        case 'i':
        case 'c':
            iflag = true;
            break;
        }
    }
    rc = CurrentRegComp( sstr );
    if( rc != ERR_NO_ERR ) {
        return( rc );
    }

    /*
     * verify last line
     */
    if( n2 > CurrentFile->fcbs.tail->end_line ) {
        rc = CFindLastLine( &ll );
        if( rc != ERR_NO_ERR ) {
            return( rc );
        }
        if( n2 > ll ) {
            return( ERR_INVALID_LINE_RANGE );
        }
    }

    /*
     * set for start of search
     */
    if( EditFlags.Verbose && EditFlags.EchoOn ) {
        ClearWindow( MessageWindow );
    }
    SaveCurrentFilePos();
    llineno = n1 - 1;

    EditFlags.AllowRegSubNewline = true;
    newr = StaticAlloc();
    for( pos.column = 0, pos.line = n1;
        pos.line <= n2;
        nextSearchStartPos( &pos, gflag, rlen ) ) {

        /*
         * get regular expression, and build replacement string
         */
        rc = FindRegularExpression( NULL, &pos, &linedata, n2, 0 );
        if( rc != ERR_NO_ERR || pos.line > n2 ) {
            break;
        }

        slen = GetCurrRegExpLength();
        splitme = RegSub( CurrentRegularExpression, rstr, newr, pos.line );
        rlen = strlen( newr );

        ProcessingMessage( pos.line );

        /*
         * if in global mode, see if we already have an undo for
         * this line
         */
        if( gflag ) {
            if( lastline != pos.line ) {
                undoline = false;
            }
        }

        /*
         * interactive mode? yes, then display text and ask to change
         */
        if( iflag ) {
            change_resp rsp;

            if( !restline ) {
                ClearWindow( MessageWindow );
            }
            restline = true;
            GoToLineNoRelCurs( pos.line );
            if( EditFlags.GlobalInProgress ) {
                EditFlags.DisplayHold = false;
                DCDisplayAllLines();
                EditFlags.DisplayHold = true;
            }
            HilightSearchString( &pos, slen );
            rsp = ChangePrompt();
            if( rsp == CHANGE_NO ) {
                ResetDisplayLine();
                rlen = 1;
                continue;
            } else if( rsp == CHANGE_CANCEL ) {
                ResetDisplayLine();
                LastSubstituteCancelled = 1;
                break;
            } else if( rsp == CHANGE_ALL ) {
                ResetDisplayLine();
                iflag = false;
            }
        }

        /*
         * set up for global undo if we haven't already
         */
        if( !undoflag ) {
            StartUndoGroup( UndoStack );
            undoflag = true;
        }

        /*
         * bump change counts
         */
        changecnt++;
        if( llineno != pos.line ) {
            if( splitpending ) {
                splitpending = false;
                extra = SplitUpLine( llineno );
                n2 += extra;
                pos.line += extra;
            }
            linecnt++;
            llineno = pos.line;
        }

        /*
         * get copy of line, and verify that new stuff fits
         */
        CurrentPos.line = pos.line;
        rc = CGimmeLinePtr( pos.line, &CurrentFcb, &CurrentLine );
        if( rc != ERR_NO_ERR ) {
            break;
        }
        if( CurrentLine->len + rlen - slen >= EditVars.MaxLine ) {
            rc = ERR_LINE_FULL;
            break;
        }

        /*
         * now build the individual undo
         */
        CurrentFcb->non_swappable = true;
        if( !undoline ) {
            CurrentLineReplaceUndoStart();
            CurrentLineReplaceUndoEnd( true );
            if( gflag ) {
                undoline = true;
                lastline = pos.line;
            }
        }

        /*
         * remove the old string
         */
        GetCurrentLine();
        WorkLine->len = ReplaceSubString( WorkLine->data, WorkLine->len,
                                          pos.column, pos.column + slen - 1, newr, rlen );
        if( iflag ) {
            DisplayWorkLine( true );
        }
        ReplaceCurrentLine();

        /*
         * if not global, only do this change on this line
         */
        if( splitme ) {
            splitpending = true;
        }
        CurrentFcb->non_swappable = false;
    }
    StaticFree( newr );
    EditFlags.AllowRegSubNewline = false;
    /*
    * is there still a split line pending?
    */
    if( splitpending ) {
        SplitUpLine( llineno );
    }
    RestoreCurrentFilePos();
    if( restline ) {
        SetCurrentLine( CurrentPos.line );
        GoToColumnOK( CurrentPos.column );
    }
    if( undoflag ) {
        EndUndoGroup( UndoStack );
    }
    switch( rc ) {
    case ERR_NO_ERR:
    case ERR_LINE_FULL:
    case ERR_FIND_PAST_TERM_LINE:
    case ERR_FIND_NOT_FOUND:
    case ERR_FIND_END_OF_FILE:
        /*
        * display results
        */
        if( rc == ERR_LINE_FULL ) {
            Message1( "Stopped at line %l - line full", pos.line );
        } else {
            Message1( "%l changes on %l lines", changecnt, linecnt );
            LastLineCount = linecnt;
            LastChangeCount = changecnt;
        }
        DCDisplayAllLines();
        rc = ERR_NO_ERR;
        break;
    default:
        break;
    }
    return( rc );

} /* Substitute */
Пример #2
0
/*
 * SrcAssign - assign a value to a variable
 */
vi_rc SrcAssign( const char *data, vlist *vl )
{
    int         i, j, k, l;
    long        val;
    bool        rxflag = false;
    bool        envflag = false;
    bool        setflag = false;
    bool        expflag = false;
    bool        timeflag = false;
    bool        lnumflag = false;
    char        tmp[MAX_SRC_LINE], tmp1[MAX_SRC_LINE], name[MAX_SRC_LINE];
    const char  *v1;
    char        *t;
    vars        *v;
    jmp_buf     jmpaddr;
    time_t      tod;
    bool        check_end;
    char        tmpstr[MAX_STR];

    /*
     * get assign syntax :
     * ASSIGN %v = /v1/(r)($)(@)(x)(l)(t)
     * possible v1:
     *  strlen %a
     *  strchr %a ch
     *  substr %a n1 n2
     */
    data = GetNextWord1( data, tmp );
    if( *tmp == '\0' ) {
        return( ERR_SRC_INVALID_ASSIGN );
    }
    if( !VarName( name, tmp, vl ) ) {
        return( ERR_SRC_INVALID_ASSIGN );
    }
    data = GetNextWord1( data, tmp );
    if( *tmp == '\0' ) {
        return( ERR_SRC_INVALID_ASSIGN );
    }
    if( stricmp( tmp, "=" ) != 0 ) {
        return( ERR_SRC_INVALID_ASSIGN );
    }
    data = SkipLeadingSpaces( data );

    if( data[0] == '/' || data[0] == '"' ) {
        check_end = false;
        if( data[0] == '"' ) {
            data = GetNextWord( data, tmp, SingleQuote );
            if( data[0] == '"' ) {
                check_end = true;
            }
        } else {
            data = GetNextWord( data, tmp, SingleSlash );
            if( data[0] == '/' ) {
                check_end = true;
            }
        }
        if( check_end ) {
            for( ++data; data[0] != '\0'; data++ ) {
                switch( data[0] ) {
                case 't':
                    timeflag = true;
                    break;
                case 'r':
                    rxflag = true;
                    break;
                case '$':
                    envflag = true;
                    break;
                case '@':
                    setflag = true;
                    break;
                case 'x':
                    expflag = true;
                    break;
                case 'l':
                    lnumflag = true;
                    break;
                }
            }
        }
        Expand( tmp1, tmp, vl );
    } else {
        data = GetNextWord1( data, tmp );
        if( *tmp == '\0' ) {
            return( ERR_SRC_INVALID_ASSIGN );
        }
        j = Tokenize( StrTokens, tmp, false );
        if( j != TOK_INVALID ) {
            data = GetNextWord1( data, tmp );
            if( *tmp == '\0' ) {
                return( ERR_SRC_INVALID_ASSIGN );
            }
            if( !VarName( tmp1, tmp, vl ) ) {
                return( ERR_SRC_INVALID_ASSIGN );
            }
            v = VarFind( tmp1, vl );
            switch( j ) {
            case STR_T_STRLEN:
                if( v != NULL ) {
                    sprintf( tmp1, "%d", v->len );
                } else {
                    strcpy( tmp1, "0" );
                }
                break;
            case STR_T_SUBSTR:
                data = GetNextWord1( data, tmp );
                if( *tmp == '\0' ) {
                    return( ERR_SRC_INVALID_ASSIGN );
                }
                Expand( tmp1, tmp, vl );
                i = atoi( tmp1 ) - 1;
                data = GetNextWord1( data, tmp );
                if( *tmp == '\0' ) {
                    return( ERR_SRC_INVALID_ASSIGN );
                }
                Expand( tmp1, tmp, vl );
                j = atoi( tmp1 ) - 1;
                if( v == NULL ) {
                    tmp1[0] = '\0';
                    break;
                }
                if( j >= v->len || i < 0 ) {
                    tmp1[0] = '\0';
                } else {
                    l = 0;
                    for( k = i; k <= j; k++ ) {
                        tmp1[l++] = v->value[k];
                    }
                    tmp1[l] = '\0';
                }
                break;
            case STR_T_STRCHR:
                data = GetNextWord1( data, tmp );
                if( *tmp == '\0' ) {
                    return( ERR_SRC_INVALID_ASSIGN );
                }
                Expand( tmp1, tmp, vl );
                if( v == NULL ) {
                    j = -1;
                } else {
                    t = strchr( v->value, tmp1[0] );
                    if( t != NULL ) {
                        j = t - v->value;
                    } else {
                        j = -1;
                    }
                    j++;
                }
                sprintf( tmp1, "%d", j );
                break;
            }
        } else {
            Expand( tmp1, tmp, vl );
        }

    }
    /*
     * regular expression subs.
     */
    if( rxflag && CurrentRegularExpression != NULL ) {
        RegSub( CurrentRegularExpression, tmp1, tmp, CurrentPos.line );
        strcpy( tmp1, tmp );
    }

    /*
     * special processing
     */
    if( envflag ) {
        v1 = getenv( tmp1 );
        if( v1 == NULL ) {
            v1 = "";
        }
    } else if( setflag ) {
        v1 = GetASetVal( tmp1, tmpstr );
    } else if( timeflag ) {
        tod = time( NULL );
        strftime( tmp, sizeof( tmp ), tmp1, localtime( &tod ) );
        v1 = tmp;
    } else if( expflag || lnumflag ) {
        i = setjmp( jmpaddr );
        if( i != 0 ) {
            return( (vi_rc)i );
        }
        StartExprParse( tmp1, jmpaddr );
        val = GetConstExpr();
        if( lnumflag ) {
            fcb         *cfcb;
            line        *cline;
            vi_rc       rc;
            rc = CGimmeLinePtr( val, &cfcb, &cline );
            v1 = cline->data;
            if( rc != ERR_NO_ERR ) {
                v1 = "";
            }
        } else {
            v1 = ltoa( val, tmp1, EditVars.Radix );
        }
    } else {
        v1 = tmp1;
    }

    VarAddStr( name, v1, vl );
    return( ERR_NO_ERR );

} /* SrcAssign */