⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sed.c

📁 GNU Sed GNU Sed GNU Sed
💻 C
📖 第 1 页 / 共 3 页
字号:
			num=size_buffer(b);
			string=(unsigned char *)ck_malloc(num);
			bcopy(get_buffer(b),string,num);
			flush_buffer(b);
			cur_cmd->x.cmd_txt.text_len=num;
			cur_cmd->x.cmd_txt.text=(char *)string;
			break;
		case '{':
			cur_cmd->cmd=ch;
			program_depth++;
#if 0
			while((ch=inchar())!=EOF && ch!='\n')
				if(!isblank(ch))
					bad_prog(LINE_JUNK);
#endif
			cur_cmd->x.sub=compile_program((struct vector *)0);
			/* FOO JF is this the right thing to do? */
			break;
		case '}':
			if(!program_depth)
				bad_prog("Unexpected '}'");
			--(vector->v_length);
			while((ch=inchar())!=EOF && ch!='\n' && ch!=';')
				if(!isblank(ch))
					bad_prog(LINE_JUNK);
			return vector;
		case ':':
			cur_cmd->cmd=ch;
			if(cur_cmd->a1.addr_type!=0)
				bad_prog(": doesn't want any addresses");
			labels=setup_jump(labels,cur_cmd,vector);
			break;
		case 'b':
		case 't':
			cur_cmd->cmd=ch;
			jumps=setup_jump(jumps,cur_cmd,vector);
			break;
		case 'q':
		case '=':
			if(cur_cmd->a2.addr_type)
				bad_prog(ONE_ADDR);
			/* Fall Through */
		case 'd':
		case 'D':
		case 'g':
		case 'G':
		case 'h':
		case 'H':
		case 'l':
		case 'n':
		case 'N':
		case 'p':
		case 'P':
		case 'x':
			cur_cmd->cmd=ch;
			do	ch=inchar();
			while(ch!=EOF && isblank(ch) && ch!='\n' && ch!=';');
			if(ch!='\n' && ch!=';' && ch!=EOF)
				bad_prog(LINE_JUNK);
			break;

		case 'r':
			if(cur_cmd->a2.addr_type!=0)
				bad_prog(ONE_ADDR);
			/* FALL THROUGH */
		case 'w':
			cur_cmd->cmd=ch;
			cur_cmd->x.io_file=compile_filename(ch=='r');
			break;

		case 's':
			cur_cmd->cmd=ch;
			slash=inchar();
			compile_regex(slash);

			cur_cmd->x.cmd_regex.regx=last_regex;

			b=init_buffer();
			while((ch=inchar())!=EOF && ch!=slash) {
				if(ch=='\\') {
					int ci;

					ci=inchar();
					if(ci!=EOF) {
						if(ci!='\n')
							add1_buffer(b,ch);
						add1_buffer(b,ci);
					}
				} else
					add1_buffer(b,ch);
			}
			cur_cmd->x.cmd_regex.replace_length=size_buffer(b);
			cur_cmd->x.cmd_regex.replacement=ck_malloc(cur_cmd->x.cmd_regex.replace_length);
			bcopy(get_buffer(b),cur_cmd->x.cmd_regex.replacement,cur_cmd->x.cmd_regex.replace_length);
			flush_buffer(b);

			cur_cmd->x.cmd_regex.flags=0;
			cur_cmd->x.cmd_regex.numb=0;

			if(ch==EOF)
				break;
			do {
				ch=inchar();
				switch(ch) {
				case 'p':
					if(cur_cmd->x.cmd_regex.flags&S_PRINT_BIT)
						bad_prog("multiple 'p' options to 's' command");
					cur_cmd->x.cmd_regex.flags|=S_PRINT_BIT;
					break;
				case 'g':
					if(cur_cmd->x.cmd_regex.flags&S_NUM_BIT)
						cur_cmd->x.cmd_regex.flags&= ~S_NUM_BIT;
					if(cur_cmd->x.cmd_regex.flags&S_GLOBAL_BIT)
						bad_prog("multiple 'g' options to 's' command");
					cur_cmd->x.cmd_regex.flags|=S_GLOBAL_BIT;
					break;
				case 'w':
					cur_cmd->x.cmd_regex.flags|=S_WRITE_BIT;
					cur_cmd->x.cmd_regex.wio_file=compile_filename(0);
					ch='\n';
					break;
				case '0': case '1': case '2': case '3':
				case '4': case '5': case '6': case '7':
				case '8': case '9':
					if(cur_cmd->x.cmd_regex.flags&S_NUM_BIT)
						bad_prog("multiple number options to 's' command");
					if((cur_cmd->x.cmd_regex.flags&S_GLOBAL_BIT)==0)
						cur_cmd->x.cmd_regex.flags|=S_NUM_BIT;
					num = 0;
					while(isdigit(ch)) {
						num=num*10+ch-'0';
						ch=inchar();
					}
					savchar(ch);
					cur_cmd->x.cmd_regex.numb=num;
					break;
				case '\n':
				case ';':
				case EOF:
					break;
				default:
					bad_prog("Unknown option to 's'");
					break;
				}
			} while(ch!=EOF && ch!='\n' && ch!=';');
			if(ch==EOF)
				break;
			break;

		case 'y':
			cur_cmd->cmd=ch;
			string=(unsigned char *)ck_malloc(256);
			for(num=0;num<256;num++)
				string[num]=num;
			b=init_buffer();
			slash=inchar();
			while((ch=inchar())!=EOF && ch!=slash)
				add1_buffer(b,ch);
			cur_cmd->x.translate=string;
			string=(unsigned char *)get_buffer(b);
			for(num=size_buffer(b);num;--num) {
				ch=inchar();
				if(ch==EOF)
					bad_prog(BAD_EOF);
				if(ch==slash)
					bad_prog("strings for y command are different lengths");
				cur_cmd->x.translate[*string++]=ch;
			}
			flush_buffer(b);
			if(inchar()!=slash || ((ch=inchar())!=EOF && ch!='\n' && ch!=';'))
				bad_prog(LINE_JUNK);
			break;

		default:
			bad_prog("Unknown command");
		}
	}
	return vector;
}

/* Complain about a programming error and exit. */
void
bad_prog(why)
char *why;
{
	if(prog_line)
		fprintf(stderr,"%s: file %s line %d: %s\n",myname,prog_name,prog_line,why);
	else
		fprintf(stderr,"%s: %s\n",myname,why);
	exit(1);
}

/* Read the next character from the program.  Return EOF if there isn't
   anything to read.  Keep prog_line up to date, so error messages can
   be meaningful. */
int
inchar()
{
	int	ch;
	if(prog_file) {
		if(feof(prog_file))
			return EOF;
		else
			ch=getc(prog_file);
	} else {
		if(!prog_cur)
			return EOF;
		else if(prog_cur==prog_end) {
			ch=EOF;
			prog_cur=0;
		} else
			ch= *prog_cur++;
	}
	if(ch=='\n' && prog_line)
		prog_line++;
	return ch;
}

/* unget 'ch' so the next call to inchar will return it.  'ch' must not be
   EOF or anything nasty like that. */
void
savchar(ch)
int ch;
{
	if(ch==EOF)
		return;
	if(ch=='\n' && prog_line>1)
		--prog_line;
	if(prog_file)
		ungetc(ch,prog_file);
	else
		*--prog_cur=ch;
}


/* Try to read an address for a sed command.  If it succeeeds,
   return non-zero and store the resulting address in *'addr'.
   If the input doesn't look like an address read nothing
   and return zero. */
int
compile_address(addr)
struct addr *addr;
{
	int	ch;
	int	num;

	ch=inchar();

	if(isdigit(ch)) {
		num=ch-'0';
		while((ch=inchar())!=EOF && isdigit(ch))
			num=num*10+ch-'0';
		while(ch!=EOF && isblank(ch))
			ch=inchar();
		savchar(ch);
		addr->addr_type=ADDR_NUM;
		addr->addr_number = num;
		return 1;
	} else if(ch=='/') {
		addr->addr_type=ADDR_REGEX;
		compile_regex('/');
		addr->addr_regex=last_regex;
		do ch=inchar();
		while(ch!=EOF && isblank(ch));
		savchar(ch);
		return 1;
	} else if(ch=='$') {
		addr->addr_type=ADDR_LAST;
		do ch=inchar();
		while(ch!=EOF && isblank(ch));
		savchar(ch);
		return 1;
	} else
		savchar(ch);
	return 0;
}

void
compile_regex (slash)
     int slash;
{
	VOID *b;
	int ch;
	int in_char_class = 0;

	b=init_buffer();
	while((ch=inchar())!=EOF && (ch!=slash || in_char_class)) {
		if(ch=='^') {
			if(size_buffer(b)==0) {
				add1_buffer(b,'\\');
				add1_buffer(b,'`');
			} else
				add1_buffer(b,ch);
			continue;
		} else if(ch=='$') {
			ch=inchar();
			savchar(ch);
			if(ch==slash) {
				add1_buffer(b,'\\');
				add1_buffer(b,'\'');
			} else
				add1_buffer(b,'$');
			continue;
		} else if(ch == '[') {
			add1_buffer(b,ch);
			in_char_class = 1;
			continue;
		} else if(ch == ']') {
			add1_buffer(b,ch);
			in_char_class = 0;
			continue;
		} else if(ch!='\\') {
			add1_buffer(b,ch);
			continue;
		}
		ch=inchar();
		switch(ch) {
		case 'n':
			add1_buffer(b,'\n');
			break;
#if 0
		case 'b':
			add1_buffer(b,'\b');
			break;
		case 'f':
			add1_buffer(b,'\f');
			break;
		case 'r':
			add1_buffer(b,'\r');
			break;
		case 't':
			add1_buffer(b,'\t');
			break;
#endif /* 0 */
		case EOF:
			break;
		default:
			add1_buffer(b,'\\');
			add1_buffer(b,ch);
			break;
		}
	}
	if(ch==EOF)
		bad_prog(BAD_EOF);
	if(size_buffer(b)) {
		last_regex=(struct re_pattern_buffer *)ck_malloc(sizeof(struct re_pattern_buffer));
		last_regex->allocated=size_buffer(b)+10;
		last_regex->buffer=ck_malloc(last_regex->allocated);
		last_regex->fastmap=ck_malloc(256);
		last_regex->translate=0;
		re_compile_pattern(get_buffer(b),size_buffer(b),last_regex);
	} else if(!last_regex)
		bad_prog(NO_REGEX);
	flush_buffer(b);
}

/* Store a label (or label reference) created by a ':', 'b', or 't'
   comand so that the jump to/from the lable can be backpatched after
   compilation is complete */
struct sed_label *
setup_jump(list,cmd,vec)
struct sed_label *list;
struct sed_cmd *cmd;
struct vector *vec;
{
	struct sed_label *tmp;
	VOID *b;
	int ch;

	b=init_buffer();
	while((ch=inchar()) != EOF && isblank(ch))
		;
	while(ch!=EOF && ch!='\n') {
		add1_buffer(b,ch);
		ch=inchar();
	}
	savchar(ch);
	add1_buffer(b,'\0');
	tmp=(struct sed_label *)ck_malloc(sizeof(struct sed_label));
	tmp->v=vec;
	tmp->v_index=cmd-vec->v;
	tmp->name=ck_strdup(get_buffer(b));
	tmp->next=list;
	flush_buffer(b);
	return tmp;
}

/* read in a filename for a 'r', 'w', or 's///w' command, and
   update the internal structure about files.  The file is
   opened if it isn't already open. */
FILE *
compile_filename(readit)
     int readit;
{
	char *file_name;
	int n;
	VOID *b;
	int ch;

	if(inchar()!=' ')
		bad_prog("missing ' ' before filename");
	b=init_buffer();
	while((ch=inchar())!=EOF && ch!='\n')
		add1_buffer(b,ch);
	add1_buffer(b,'\0');
	file_name=get_buffer(b);
	for(n=0;n<NUM_FPS;n++) {
		if(!file_ptrs[n].name)
			break;
		if(!strcmp(file_ptrs[n].name,file_name)) {
			if(file_ptrs[n].readit!=readit)
				bad_prog("Can't open file for both reading and writing");
			flush_buffer(b);
			return file_ptrs[n].phile;
		}
	}
	if(n<NUM_FPS) {
		file_ptrs[n].name=ck_strdup(file_name);
		file_ptrs[n].readit=readit;
		if (!readit)
			file_ptrs[n].phile=ck_fopen(file_name,"a");
		else if (access(file_name, 4) == 0)
			file_ptrs[n].phile=ck_fopen(file_name,"r");
		else if (access(file_name, 4) == 0)
			file_ptrs[n].phile=ck_fopen(file_name,"r");
		else
			file_ptrs[n].phile=ck_fopen("/dev/null", "r");
		flush_buffer(b);
		return file_ptrs[n].phile;
	} else {
		bad_prog("Hopelessely evil compiled in limit on number of open files.  re-compile sed");
		return 0;
	}
}

/* Parse a filename given by a 'r' 'w' or 's///w' command. */
void
read_file(name)
char *name;
{
	if(*name=='-' && name[1]=='\0')
		input_file=stdin;
	else {
		input_file=fopen(name,"r");
		if(input_file==0) {
			extern int errno;
			extern char *sys_errlist[];
			extern int sys_nerr;

			char *ptr;

			ptr=(errno>=0 && errno<sys_nerr) ? sys_errlist[errno] : "Unknown error code";
			bad_input++;
			fprintf(stderr,"%s: can't read %s: %s\n",myname,name,ptr);

			return;
		}
	}
	while(read_pattern_space()) {
		execute_program(the_program);
		if(!no_default_output)
			ck_fwrite(line.text,1,line.length,stdout);
		if(append.length) {
			ck_fwrite(append.text,1,append.length,stdout);
			append.length=0;
		}
		if(quit_cmd)
			break;
	}
	ck_fclose(input_file);
}

/* Execute the program 'vec' on the current input line. */
void
execute_program(vec)
struct vector *vec;
{
	struct sed_cmd *cur_cmd;
	int	n;
	int addr_matched;
	static int end_cycle;

	int start;
	int remain;
	int offset;

	static struct line tmp;
	struct line t;
	char *rep,*rep_end,*rep_next,*rep_cur;

	struct re_registers regs;
	int count = 0;

	end_cycle = 0;

	for(cur_cmd=vec->v,n=vec->v_length;n;cur_cmd++,n--) {

	exe_loop:
		addr_matched=0;
		if(cur_cmd->aflags&A1_MATCHED_BIT) {
			addr_matched=1;
			if(match_address(&(cur_cmd->a2)))
				cur_cmd->aflags&=~A1_MATCHED_BIT;
		} else if(match_address(&(cur_cmd->a1))) {
			addr_matched=1;
			if(cur_cmd->a2.addr_type!=ADDR_NULL)
				cur_cmd->aflags|=A1_MATCHED_BIT;
		}
		if(cur_cmd->aflags&ADDR_BANG_BIT)
			addr_matched= !addr_matched;
		if(!addr_matched)
			continue;
		switch(cur_cmd->cmd) {
		case '{':	/* Execute sub-program */
			execute_program(cur_cmd->x.sub);
			break;

		case ':':	/* Executing labels is easy. */
			break;

		case '=':
			printf("%d\n",input_line_number);
			break;

		case 'a':
			while(append.alloc-append.length<cur_cmd->x.cmd_txt.text_len) {
				append.alloc *= 2;
				append.text=ck_realloc(append.text,append.alloc);
			}
			bcopy(cur_cmd->x.cmd_txt.text,append.text+append.length,cur_cmd->x.cmd_txt.text_len);
			append.length+=cur_cmd->x.cmd_txt.text_len;
			break;

		case 'b':
			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 'c':

⌨️ 快捷键说明

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