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 + -
显示快捷键?