sedcomp.c

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

C
1,082
字号
    char                ccode;

    for( ;; ) {                         /* main compilation loop */
        if( !cp ) {
            if( !cmdline( cp = linebuf ) )
                break;
            if( *cp == '#' ) {          /* if the first two characters in the script are "#n" , */
                if( cp[1] == 'n' )
                    nflag++;            /* the default output shall be suppressed */
                continue;
            }
        } else if( *cp != ';' )         /* get a new command line */
            if( !cmdline( cp = linebuf ) )
                break;
        SKIPWS( cp );
        if( *cp == '\0' || *cp == '#' ) /* a comment */
            continue;
        while( *cp == ';' || isspace( *cp ) )
            cp++;                       /* ; separates cmds */

                                        /* compile first address */
        if( fp >= poolend )
            ABORT( TMTXT );             /* Not exercised by sedtest.mak */
        if( ( fp = getaddress( cmdp->addr1 = fp ) ) == BAD )
            ABORT( AGMSG );

        if( fp == cmdp->addr1 ) {       /* if empty RE was found */
        } else if( fp == NULL ) {       /* if fp was NULL */
            fp = cmdp->addr1;           /* use current pool location */
            cmdp->addr1 = NULL;
        } else {
            if( *cp == ',' || *cp == ';' ) { /* there's 2nd addr */
                cp++;
                if( fp >= poolend )
                    ABORT( TMTXT );     /* Not exercised by sedtest.mak */
                fp = getaddress( cmdp->addr2 = fp );
                if( fp == BAD || fp == NULL )
                    ABORT( AGMSG );
            } else
                cmdp->addr2 = NULL;     /* no 2nd address */
        }
        if( fp >= poolend )
            ABORT( TMTXT );             /* Not exercised by sedtest.mak */

        SKIPWS( cp );                   /* discard whitespace after address */
        IFEQ( cp, '!' )
            cmdp->flags.allbut = 1;

        SKIPWS( cp );                   /* get cmd char, range-check it */
        if( ( *cp < LOWCMD ) || ( *cp > '~' )
                 || ( ( ccode = cmdmask[*cp - LOWCMD] ) == 0 ) )
            ABORT( NSCAX );

        cmdp->command = ccode & ~H;     /* fill in command value */
        if( ( ccode & H ) == 0 )        /* if no compile-time code */
            cp++;                       /* discard command char */
        else if( cmdcomp( *cp++ ) )     /* execute it; if ret = 1 */
            continue;                   /* skip next line read */

        if( ++cmdp >= cmds + MAXCMDS )
            ABORT( TMCDS );             /* Not exercised by sedtest.mak */

        SKIPWS( cp );                   /* look for trailing stuff */
        if( *cp != '\0' )
            if( *cp == ';' )
                continue;
            else if( *cp != '#' )
                ABORT( TRAIL );
    }
}

/* compile a single command */
static int cmdcomp( register char cchar ) /* character name of command */
{
    static sedcmd       **cmpstk[MAXDEPTH]; /* current cmd stack for {} */
    static char const   *fname[WFILES]; /* w file name pointers */
    static FILE         *fout[WFILES];  /* w file file ptrs */
    static int          nwfiles = 1;    /* count of open w files */
    int                 i;              /* indexing dummy used in w */
    sedcmd              *sp1;           /* temps for label searches */
    sedcmd              *sp2;           /* temps for label searches */
    label               *lpt;           /* ditto, and the searcher */
    char                redelim;        /* current RE delimiter */

    switch( cchar ) {
    case '{':                           /* start command group */
        cmdp->flags.allbut = !cmdp->flags.allbut;
        cmpstk[bdepth++] = &( cmdp->u.link );
        if( ++cmdp >= cmds + MAXCMDS )
            ABORT( TMCDS );             /* Not exercised by sedtest.mak */
        if( *cp != '\0' )
            *--cp = ';';                /* get next cmd w/o lineread */
        return( 1 );

    case '}':                           /* end command group */
        if( cmdp->addr1 )
            ABORT( AD1NG );             /* no addresses allowed */
        if( --bdepth < 0 )
            ABORT( TMRBR );             /* too many right braces */
        *cmpstk[bdepth] = cmdp - 1;     /* set the jump address - (-1) to allow increment */
        return( 1 );

    case '=':                           /* print current source line number */
        break;

    case 'q':                           /* exit the stream editor */
        if( cmdp->addr2 )
            ABORT( AD2NG );
        break;

    case ':':                           /* label declaration */
        if( cmdp->addr1 )
            ABORT( AD1NG );             /* no addresses allowed */
        curlab->name = fp;
        gettext( 0 );                   /* get the label name */
        if( ( lpt = search() ) != 0 ) { /* does it have a double? */
            if( lpt->link )
                ABORT( DLABL );         /* yes, abort */
        } else {                        /* check label table doesn't overflow */
            if( curlab >= labels + MAXLABS )
                ABORT( TMLAB );         /* Not exercised by sedtest.mak */
            curlab->last = NULL;
            lpt = curlab++;
        }
        lpt->link = cmdp;
        return( 1 );

    case 'b':                           /* branch command */
    case 't':                           /* branch-on-succeed command */
    case 'T':                           /* branch-on-fail command */
        SKIPWS( cp );
        if( *cp == '\0' ) {             /* if branch is to start of cmds... */
                                        /* append command to label last */
            if( ( sp1 = lablst->last ) != 0 ) {
                while( ( sp2 = sp1->u.link ) != 0 )
                    sp1 = sp2;
                sp1->u.link = cmdp;
            } else                      /* lablst->last == NULL */
                lablst->last = cmdp;
            break;
        }
        curlab->name = fp;
        gettext( 0 );                   /* get the label name */
        if( ( lpt = search() ) != 0 ) { /* enter branch to it */
            if( lpt->link )
                cmdp->u.link = lpt->link - 1;
            else {
                sp1 = lpt->last;
                while( ( sp2 = sp1->u.link ) != 0 )
                    sp1 = sp2;
                sp1->u.link = cmdp - 1;
            }
        }
        else {                          /* matching named label not found */
            if( curlab >= labels + MAXLABS ) /* overflow if last */
                ABORT( TMLAB );         /* Not exercised by sedtest.mak */
            curlab->last = cmdp;        /* add the new label */
            curlab->link = NULL;        /* it's forward of here */
            curlab++;                   /* Get another label "object" */
        }
        break;

    case 'a':                           /* append text */
    case 'i':                           /* insert text */
    case 'r':                           /* read file into stream */
        if( cmdp->addr2 )
            ABORT( AD2NG );
                                        /* Drop through */
    case 'c':                           /* change text */
        if( *cp == '\\' && *++cp == '\n' )
            cp++;
        cmdp->u.lhs = fp;
        gettext( 1 );
        break;

    case 'D':                           /* delete current line in pattern space */
        cmdp->u.link = cmds;
        break;

    case 's':                           /* substitute regular expression */
        redelim = *cp++;                /* get delimiter from 1st ch */
        if( ( fp = recomp( cmdp->u.lhs = fp, redelim ) ) == BAD )
            ABORT( CGMSG );
        if( ( cmdp->rhs = fp ) >= poolend )
            ABORT( TMTXT );            /* Not exercised by sedtest.mak */
        if( ( fp = rhscomp( cmdp->rhs, redelim ) ) == BAD )
            ABORT( CGMSG );
        if( gflag )
            cmdp->flags.global++;
        while( *cp == 'g' || *cp == 'p' || *cp == 'P' || isdigit( *cp ) ) {
            IFEQ( cp, 'g' )
                cmdp->flags.global++;
            IFEQ( cp, 'p' )
                cmdp->flags.print = 1;
            IFEQ( cp, 'P' )
                cmdp->flags.print = 2;
            if( isdigit( *cp ) ) {
                i = 0;
                while (isdigit(*cp))
                    i = i*10 + *cp++ - '0';
                if (i == 0 || i >= 2048)
                    ABORT(SMCNT);
                cmdp->flags.nthone = (unsigned)i;
            }
        }
                                        /* Drop through */
    case 'l':                           /* list pattern space */
        if( *cp != 'w' )
            break;                      /* s or l is done */
        cp++;                           /* and execute a w command! */
                                        /* drop through */
    case 'w':                           /* write-pattern-space command */
    case 'W':                           /* write-first-line command */
        if( nwfiles >= WFILES )
            ABORT( TMWFI );
        fout[0] = stdout;               /* Not initialized to humor lint */
        fname[0] = "";                  /* Set so strcmp( x, fname[0] ) OK */
        fname[nwfiles] = (const char*)fp; /* filename is in pool */
        gettext( 0 );
        for( i = nwfiles - 1; i >= 0; i-- ) /* match it in table */
            if( strcmp( fname[nwfiles], fname[i] ) == 0 ) {
                cmdp->fout = fout[i];
                return( 0 );
            }
                                        /* if didn't find one, open new file */
        if( ( cmdp->fout = fopen( fname[nwfiles], "w" ) ) == NULL
                                        /* setvbuf() for -w -r combination */
        || 0 != setvbuf( cmdp->fout, NULL, _IOLBF, 0 ) )
            fprintf( stderr, CCOFI, fname[nwfiles] ), myexit( 2 );
        fout[nwfiles++] = cmdp->fout;
        break;

    case 'y':                           /* transliterate text */
        fp = ycomp( cmdp->u.lhs = fp, *cp++ );    /* compile translit */
        if( fp == BAD )                 /* fail on bad form */
            ABORT( CGMSG );
        if( fp >= poolend )             /* fail on overflow */
            ABORT( TMTXT );             /* Not exercised by sedtest.mak */
        break;

    default:
        fprintf( stderr, INERR, "Unmatched command" ), myexit( 2 );
    }
    return( 0 );                        /* interpreted one command */
}

/* generate replacement string for substitute command right hand side */
static char *rhscomp(
    register char       *rhsp,          /* place to compile expression to */
    register char       delim )         /* RE end-mark to find */
                                        /* uses bcount */
{
    register char       *p = cp;        /* strictly for speed */

    for( ;; )
        if( ( *rhsp = *p++ ) == '\\' ) { /* copy; if it's a \, */
            *rhsp = *p++;               /* copy escaped char */
                                        /* check validity of pattern tag */
            if( *rhsp > bcount + '0' && *rhsp <= '9' )
                return( BAD );
            *rhsp++ |= 0x80;            /* mark the good ones */
        } else if( *rhsp == delim ) {   /* found RE end, hooray... */
            *rhsp++ = '\0';             /* cap the expression string */
            cp = p;
            return( rhsp );             /* pt at 1 past the RE */
        } else if( *rhsp++ == '\0' )    /* last ch not RE end, help! */
            return( BAD );
}

/* compile a regular expression to internal form */
static char *recomp(

⌨️ 快捷键说明

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