📄 sed.c
字号:
line.length=0;
if(!(cur_cmd->aflags&A1_MATCHED_BIT))
ck_fwrite(cur_cmd->x.cmd_txt.text,1,cur_cmd->x.cmd_txt.text_len,stdout);
end_cycle++;
break;
case 'd':
line.length=0;
end_cycle++;
break;
case 'D':
{
char *tmp;
int newlength;
tmp=memchr(line.text,'\n',line.length);
newlength=line.length-(tmp-line.text);
if(newlength)
memmove(line.text,tmp,newlength);
line.length=newlength;
}
end_cycle++;
break;
case 'g':
line_copy(&hold,&line);
break;
case 'G':
line_append(&hold,&line);
break;
case 'h':
line_copy(&line,&hold);
break;
case 'H':
line_append(&line,&hold);
break;
case 'i':
ck_fwrite(cur_cmd->x.cmd_txt.text,1,cur_cmd->x.cmd_txt.text_len,stdout);
break;
case 'l':
{
char *tmp;
int n;
int width = 0;
n=line.length;
tmp=line.text;
/* Use --n so this'll skip the trailing newline */
while(--n) {
if(width>77) {
width=0;
putchar('\n');
}
if(*tmp == '\\') {
printf("\\\\");
width+=2;
} else if(isprint(*tmp)) {
putchar(*tmp);
width++;
} else switch(*tmp) {
#if 0
/* Should print \00 instead of \0 because (a) POSIX requires it, and
(b) this way \01 is unambiguous. */
case '\0':
printf("\\0");
width+=2;
break;
#endif
case 007:
printf("\\a");
width+=2;
break;
case '\b':
printf("\\b");
width+=2;
break;
case '\f':
printf("\\f");
width+=2;
break;
case '\n':
printf("\\n");
width+=2;
break;
case '\r':
printf("\\r");
width+=2;
break;
case '\t':
printf("\\t");
width+=2;
break;
case '\v':
printf("\\v");
width+=2;
break;
default:
printf("\\%02x",(*tmp)&0xFF);
width+=2;
break;
}
tmp++;
}
putchar('\n');
}
break;
case 'n':
if (feof(input_file)) goto quit;
ck_fwrite(line.text,1,line.length,stdout);
read_pattern_space();
break;
case 'N':
if (feof(input_file)) goto quit;
append_pattern_space();
break;
case 'p':
ck_fwrite(line.text,1,line.length,stdout);
break;
case 'P':
{
char *tmp;
tmp=memchr(line.text,'\n',line.length);
ck_fwrite(line.text, 1,
tmp ? tmp - line.text + 1
: line.length, stdout);
}
break;
case 'q': quit:
quit_cmd++;
end_cycle++;
break;
case 'r':
{
int n = 0;
rewind(cur_cmd->x.io_file);
do {
append.length += n;
if(append.length==append.alloc) {
append.alloc *= 2;
append.text = ck_realloc(append.text, append.alloc);
}
} while((n=fread(append.text+append.length,sizeof(char),append.alloc-append.length,cur_cmd->x.io_file))>0);
if(ferror(cur_cmd->x.io_file))
panic("Read error on input file to 'r' command");
}
break;
case 's':
if(!tmp.alloc) {
tmp.alloc=50;
tmp.text=ck_malloc(50);
}
count=0;
start = 0;
remain=line.length-1;
tmp.length=0;
rep = cur_cmd->x.cmd_regex.replacement;
rep_end=rep+cur_cmd->x.cmd_regex.replace_length;
while((offset = re_search(cur_cmd->x.cmd_regex.regx,
line.text,
line.length-1,
start,
remain,
®s))>=0) {
count++;
if(offset-start)
str_append(&tmp,line.text+start,offset-start);
if(cur_cmd->x.cmd_regex.flags&S_NUM_BIT) {
if(count!=cur_cmd->x.cmd_regex.numb) {
str_append(&tmp,line.text+regs.start[0],regs.end[0]-regs.start[0]);
start = (offset == regs.end[0] ? offset + 1 : regs.end[0]);
remain = (line.length-1) - start;
continue;
}
}
for(rep_next=rep_cur=rep;rep_next<rep_end;rep_next++) {
if(*rep_next=='&') {
if(rep_next-rep_cur)
str_append(&tmp,rep_cur,rep_next-rep_cur);
str_append(&tmp,line.text+regs.start[0],regs.end[0]-regs.start[0]);
rep_cur=rep_next+1;
} else if(*rep_next=='\\') {
if(rep_next-rep_cur)
str_append(&tmp,rep_cur,rep_next-rep_cur);
rep_next++;
if(rep_next!=rep_end) {
int n;
if(*rep_next>='0' && *rep_next<='9') {
n= *rep_next -'0';
str_append(&tmp,line.text+regs.start[n],regs.end[n]-regs.start[n]);
} else
str_append(&tmp,rep_next,1);
}
rep_cur=rep_next+1;
}
}
if(rep_next-rep_cur)
str_append(&tmp,rep_cur,rep_next-rep_cur);
if (offset == regs.end[0]) {
str_append(&tmp, line.text + offset, 1);
++regs.end[0];
}
start = regs.end[0];
remain = (line.length-1) - start;
if(remain<0)
break;
if(!(cur_cmd->x.cmd_regex.flags&S_GLOBAL_BIT))
break;
}
if(!count)
break;
replaced=1;
str_append(&tmp,line.text+start,remain+1);
t.text=line.text;
t.length=line.length;
t.alloc=line.alloc;
line.text=tmp.text;
line.length=tmp.length;
line.alloc=tmp.alloc;
tmp.text=t.text;
tmp.length=t.length;
tmp.alloc=t.alloc;
if(cur_cmd->x.cmd_regex.flags&S_WRITE_BIT)
ck_fwrite(line.text,1,line.length,cur_cmd->x.cmd_regex.wio_file);
if(cur_cmd->x.cmd_regex.flags&S_PRINT_BIT)
ck_fwrite(line.text,1,line.length,stdout);
break;
case 't':
if(replaced) {
replaced = 0;
if(!cur_cmd->x.jump)
end_cycle++;
else {
struct sed_label *j = cur_cmd->x.jump;
n= j->v->v_length - j->v_index;
cur_cmd= j->v->v + j->v_index;
goto exe_loop;
}
}
break;
case 'w':
ck_fwrite(line.text,1,line.length,cur_cmd->x.io_file);
break;
case 'x':
{
struct line tmp;
tmp=line;
line=hold;
hold=tmp;
}
break;
case 'y':
{
unsigned char *p,*e;
for(p=(unsigned char *)(line.text),e=p+line.length;p<e;p++)
*p=cur_cmd->x.translate[*p];
}
break;
default:
panic("INTERNAL ERROR: Bad cmd %c",cur_cmd->cmd);
}
if(end_cycle)
break;
}
}
/* Return non-zero if the current line matches the address
pointed to by 'addr'. */
int
match_address(addr)
struct addr *addr;
{
switch(addr->addr_type) {
case ADDR_NULL:
return 1;
case ADDR_NUM:
return (input_line_number==addr->addr_number);
case ADDR_REGEX:
return (re_search(addr->addr_regex,
line.text,
line.length-1,
0,
line.length-1,
(struct re_registers *)0)>=0) ? 1 : 0;
case ADDR_LAST:
return (input_EOF) ? 1 : 0;
default:
panic("INTERNAL ERROR: bad address type");
break;
}
return -1;
}
/* Read in the next line of input, and store it in the
pattern space. Return non-zero if this is the last line of input */
int
read_pattern_space()
{
int n;
char *p;
int ch;
p=line.text;
n=line.alloc;
if(feof(input_file))
return 0;
input_line_number++;
replaced=0;
for(;;) {
if(n==0) {
line.text=ck_realloc(line.text,line.alloc*2);
p=line.text+line.alloc;
n=line.alloc;
line.alloc*=2;
}
ch=getc(input_file);
if(ch==EOF) {
if(n==line.alloc)
return 0;
*p++='\n';
--n;
line.length=line.alloc-n;
if(last_input_file)
input_EOF++;
return 1;
}
*p++=ch;
--n;
if(ch=='\n') {
line.length=line.alloc-n;
break;
}
}
ch=getc(input_file);
if(ch!=EOF)
ungetc(ch,input_file);
else if(last_input_file)
input_EOF++;
return 1;
}
/* Inplement the 'N' command, which appends the next line of input to
the pattern space. */
void
append_pattern_space()
{
char *p;
int n;
int ch;
p=line.text+line.length;
n=line.alloc-line.length;
input_line_number++;
replaced=0;
for(;;) {
ch=getc(input_file);
if(ch==EOF) {
if(n==line.alloc)
return;
*p++='\n';
--n;
line.length=line.alloc-n;
if(last_input_file)
input_EOF++;
return;
}
*p++=ch;
--n;
if(ch=='\n') {
line.length=line.alloc-n;
break;
}
if(n==0) {
line.text=ck_realloc(line.text,line.alloc*2);
p=line.text+line.alloc;
n=line.alloc;
line.alloc*=2;
}
}
ch=getc(input_file);
if(ch!=EOF)
ungetc(ch,input_file);
else if(last_input_file)
input_EOF++;
}
/* Copy the contents of the line 'from' into the line 'to'.
This destroys the old contents of 'to'. It will still work
if the line 'from' contains nulls. */
void
line_copy(from,to)
struct line *from,*to;
{
if(from->length>to->alloc) {
to->alloc=from->length;
to->text=ck_realloc(to->text,to->alloc);
}
bcopy(from->text,to->text,from->length);
to->length=from->length;
}
/* Append the contents of the line 'from' to the line 'to'.
This routine will work even if the line 'from' contains nulls */
void
line_append(from,to)
struct line *from,*to;
{
if(from->length>(to->alloc-to->length)) {
to->alloc+=from->length;
to->text=ck_realloc(to->text,to->alloc);
}
bcopy(from->text,to->text+to->length,from->length);
to->length+=from->length;
}
/* Append 'length' bytes from 'string' to the line 'to'
This routine *will* append bytes with nulls in them, without
failing. */
void
str_append(to,string,length)
struct line *to;
char *string;
int length;
{
if(length>to->alloc-to->length) {
to->alloc+=length;
to->text=ck_realloc(to->text,to->alloc);
}
bcopy(string,to->text+to->length,length);
to->length+=length;
}
void
usage()
{
fprintf(stderr, "\
Usage: %s [-nV] [+quiet] [+silent] [+version] [-e script] [-f script-file]\n\
[+expression=script] [+file=script-file] [file...]\n", myname);
exit(4);
}
#ifdef WINDOWSNT
/*
* a hack of yet another un*xism so that GNU stuff runs on Windows NT(tm)
*/
int
access(filename, mode)
char *filename;
int mode;
{
HFILE h;
OFSTRUCT o;
if (!mode) {
/*
* test for existence with OpenFile
*/
h = OpenFile(filename, &o, OF_EXIST);
// what do we expect h to be?
// will this test fail if the file exists but the caller is
// not allowed any access to it?
return -1;
}
if (mode & 4) {
/*
* check read access if we need to
*/
h = OpenFile(filename, &o, OF_READ);
if (h == HFILE_ERROR) {
errno = EACCES;
return -1;
}
}
if (mode & 2) {
/*
* check write access if we need to
*/
h = OpenFile(filename, &o, OF_WRITE);
if (h == HFILE_ERROR) {
errno = EACCES;
return -1;
}
}
if (mode & 1) {
/*
* we're hosed; I don't know an easy way to test for this.
*/
// sorry...
return -1;
}
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -