sedcomp.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,082 行 · 第 1/4 页

C
1,082
字号
                    firstep[2] = (char)width-1;
                    lastep++;
                    ep++;
                }
                break;
            case CBACK:
                break;
            case CEOF: /* Can't happen - would require * after end of expression WFB 20040813 */
            case CNL:  /* Can't happen - * is literal after special ^ */
            case CDOL: /* Can't happen - $ is literal if not last */
            case CLNUM:/* Can't happen - * after line number is nonsense */
            case CEND: /* Can't happen - CEND is always followed by CEOF */
            default:
                fprintf( stderr, INERR, "Unexpected symbol in RE" ), myexit( 2 );
            }
            break;
        } /* switch( c ) */
    } /* for( ;; ) */
}

/* read next command from -e argument or command file */
static int cmdline( register char *cbuf ) /* uses eflag, eargc, cmdf */
{
    register int        inc;            /* not char because must hold EOF */

    assert( cbuf == cp );
    cbuf--;                             /* so pre-increment points us at cbuf */

                                        /* e command flag is on */
    if( eflag ) {
        register char   *p;             /* ptr to current -e argument */
        static char     *savep;         /* saves previous value of p */

        if( eflag > 0 ) {               /* there are pending -e arguments */
            eflag = -1;
            if( --eargc <= 0 )          /* barf if no argument */
                fprintf( stderr, NEEDB, eargv[0] ), myexit( 2 );
                                        /* else copy next e argument to cbuf */
            p = *++eargv;
            while( ( *++cbuf = *p++ ) != 0 )
                if( *cbuf == '\\' ) {   /* Could not sedtest this! WFB 20040802 */
                    if( ( *++cbuf = *p++ ) == '\0' ) {
                        if( --eargc <= 0 ) /* barf if no argument */
                            fprintf( stderr, NEEDB, eargv[0] ), myexit( 2 );
                        *cbuf = '\n';
                        p = *++eargv;
                    }
                } else if( *cbuf == '\n' ) { /* end of 1 cmd line */
                    *cbuf = '\0';
                    return( savep = p, 1 );
                                        /* we'll be back for the rest... */
                }
                                        /* have string-end;
                                         * can advance to next argument */
            return( savep = NULL, 1 );
        }

        if( ( p = savep ) == NULL )
            return( 0 );

        while( ( *++cbuf = *p++ ) != 0 )
            if( *cbuf == '\\' ) {
                if( ( *++cbuf = *p++ ) == '0' )
                    return( savep = NULL, 0 );
            } else if( *cbuf == '\n' ) {
                *cbuf = '\0';
                return( savep = p, 1 );
            }

        return( savep = NULL, 1 );
    }

                                        /* if no -e flag
                                         * read from command file descriptor */
    while( ( inc = getc( cmdf ) ) != EOF ) { /* get next char */
        switch( *++cbuf = (char)inc ) {
        case '\\':                      /* if it's escape */
            inc = getc( cmdf ),         /* get next char */
            *++cbuf = (char)inc;
            break;
        case '\n':                      /* end on newline */
            return( *cbuf = '\0', 1 );  /* cap the string */
        }
    }

    return( *++cbuf = '\0', cbuf >= cp+1 );       /* end-of-file, no more chars */
}

/* expand an address at *cp... into expbuf, return ptr at following char */
static char *getaddress( register char *expbuf ) /* uses cp, linenum */
{
    static int          numl = 0;       /* current ind in addr-number table */
    register char       *rcp;           /* temp compile ptr for forwd look */
    long                lno;            /* computed value of numeric address */

    switch( *cp ) {
    case '$':                           /* end-of-source address */
        *expbuf++ = CEND;               /* write symbolic end address */
        *expbuf++ = CEOF;               /* and the end-of-address mark (!) */
        cp++;                           /* go to next source character */
        return( expbuf );               /* we're done */
    case '\\':                          /* posix \cBREc address */
        cp++;                           /* Point to delimiter */
    case '/':                           /* start of regular-expression match */
        return( recomp( expbuf, *cp++ ) ); /* compile the RE */
    }
    rcp = cp;
    lno = 0;                            /* now handle a numeric address */
    while( isdigit( *rcp ) )            /* collect digits */
        lno = lno*10 + *rcp++ - '0';    /* compute their value */

    if( rcp > cp ) {                    /* if we caught a number... */
        *expbuf++ = CLNUM;              /* put a numeric-address marker */
        *expbuf++ = (char)numl;         /* and the address table index */
        linenum[numl++] = lno;          /* and set the table entry */
                                        /* Not exercised by sedtest.mak */
        if( numl >= MAXLINES )          /* oh-oh, address table overflow */
            ABORT( TMLNR );             /*   abort with error message */
        *expbuf++ = CEOF;               /* write the end-of-address marker */
        cp = rcp;                       /* point compile past the address */
        return( expbuf );               /* we're done */
    }

    return( NULL );                     /* no legal address was found */
}

/*
 * accept multiline input from *cp... to *fp... ,
 * optionally skipping leading whitespace
 */
static void gettext( int accept_whitespace )
{
    char                c;

    if( !accept_whitespace )
        SKIPWS( cp );                   /* discard whitespace */
    while( fp < poolend && ( c = *fp++ = *cp++ ) != 0 ) {
        switch( c )
        {
        case '\\':                      /* handle escapes */
            fp[-1] = *cp++;
            break;
        case '\n':                      /* SKIPWS after newline */
            SKIPWS( cp );
            break;
        }
    }
    if( fp >= poolend )
        ABORT( TMTXT );                 /* Not exercised by sedtest.mak */
    --cp;
    return;
}

/* find the label matching *ptr, return NULL if none */
static label *search( void )            /* uses globals lablst and curlab */
{
    register label      *rp;
    char const * const  name = curlab->name;
    for( rp = lablst; rp < curlab; rp++ )
        if( strcmp( rp->name, name ) == 0 )
            return( rp );
    return( NULL );
}

/* write label links into the compiled-command space */
static void resolve( void )             /* uses global lablst */
{
    register label const        *rp;
    register sedcmd             *rptr;
    register sedcmd             *trptr;
                                        /* loop through the label table */
    for( rp = lablst; rp < curlab; rp++ )
        if( rp->link == NULL )          /* barf if not defined */
            fprintf( stderr, ULABL, rp->name ), myexit( 2 );
        else if( rp->last ) {           /* if last is non-null */
            for( rptr = rp->last; ( trptr = rptr->u.link ) != 0; rptr = trptr )
                rptr->u.link = rp->link;
            rptr->u.link = rp->link - 1;
        }
}

/* compile a y (transliterate) command */
static char *ycomp(
    register char       *ep,            /* where to compile to */
    char                delim )         /* end delimiter to look for */
{
    register int        c;
    register char       *tp;
    register char const *sp;

    if( delim == 0 || delim == '\\' || delim == '\n' )
        return( BAD );
                                        /* scan 'from' for invalid chars */
    for( sp = tp = cp; *tp != delim; tp++ ) {
        if( *tp == '\\' )
            tp++;
        if( ( *tp == '\n' ) || ( *tp == '\0' ) )
            return( BAD );
    }
    tp++;                               /* tp points at first char of 'to' */

                                        /* now rescan the 'from' section */
    while( ( c = (char)( *sp++ & 0x7F ) ) != delim ) {
        if( c == '\\' )
            switch( c = *sp++ & 0x7F ) {
            case 'n':                   /* '\\''n' -> '\n' */
                c = '\n';
                break;
            case '\\':
                break;
            default:
                if( c != delim )
                    return( BAD );
                c = delim;
                break;
            }
        if( ep[c] != 0 )
            return( BAD );              /* c has already been mapped */
        if( ( ep[c] = *tp++ & 0x7F ) == '\\' ) {
            switch( *tp ) {
            case 'n':                   /* '\\''n' -> '\n' */
                ep[c] = '\n';
                break;
            case '\\':
                break;
            default:
                if( *tp != delim )
                    return( BAD );
                ep[c] = delim;
                break;
            }
            tp++;
        }
        if( ep[c] == '\0' )
            return( BAD );
    }

    if( *tp != delim )                  /* 'to', 'from' lengths unequal */
        return( BAD );

    cp = ++tp;                          /* point compile ptr past translit */

    for( c = 0; c < 128; c++ )          /* fill in self-map entries in table */
        if( ep[c] == 0 )
            ep[c] = c;

    return( ep + 0x80 );                /* first free location past table end */
}

/* Avoid race condition with calls like echo hello | fail */
static void myexit( int status )
{
    assert( status != 0 );              /* Call only needed for failures */
    if( !isatty( fileno( stdin ) ) )
        while( fgets( linebuf, MAXBUF, stdin ) != NULL ) ;
    exit( status );
}

static void usage( void )
{
    const char * const *cpp;

    for( cpp = USAGE; *cpp != NULL; cpp++ )
        fprintf( stderr, "%s\n", *cpp );
    myexit( 2 );
}

/* sedcomp.c ends here */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?