1 /* GNU SED, a batch stream editor.
2 Copyright (C) 1989-1991 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
27 #define isblank(c) ((c) == ' ' || (c) == '\t')
32 #if defined(STDC_HEADERS)
35 #if defined(USG) || defined(STDC_HEADERS)
38 #define bcopy(s, d, n) (memcpy((d), (s), (n)))
44 char *version_string
= "GNU sed version 1.08";
46 /* Struct vector is used to describe a chunk of a sed program. There is one
47 vector for the main program, and one for each { } pair. */
52 struct vector
*up_one
;
53 struct vector
*next_one
;
57 /* Goto structure is used to hold both GOTO's and labels. There are two
58 separate lists, one of goto's, called 'jumps', and one of labels, called
60 the V element points to the descriptor for the program-chunk in which the
62 the v_index element counts which element of the vector actually IS the
63 goto/label. The first element of the vector is zero.
64 the NAME element is the null-terminated name of the label.
65 next is the next goto/label in the list. */
71 struct sed_label
*next
;
74 /* ADDR_TYPE is zero for a null address,
75 one if addr_number is valid, or
76 two if addr_regex is valid,
77 three, if the address is '$'
79 Other values are undefined.
89 struct re_pattern_buffer
*addr_regex
;
94 /* Aflags: If the low order bit is set, a1 has been
95 matched; apply this command until a2 matches.
96 If the next bit is set, apply this command to all
97 lines that DON'T match the address(es).
100 #define A1_MATCHED_BIT 01
101 #define ADDR_BANG_BIT 02
111 /* This structure is used for a, i, and c commands */
117 /* This is used for b and t commands */
118 struct sed_cmd
*label
;
120 /* This for r and w commands */
123 /* This for the hairy s command */
124 /* For the flags var:
125 low order bit means the 'g' option was given,
126 next bit means the 'p' option was given,
127 and the next bit means a 'w' option was given,
128 and wio_file contains the file to write to. */
130 #define S_GLOBAL_BIT 01
131 #define S_PRINT_BIT 02
132 #define S_WRITE_BIT 04
133 #define S_NUM_BIT 010
136 struct re_pattern_buffer
*regx
;
144 /* This for the y command */
145 unsigned char *translate
;
149 struct sed_label
*jump
;
153 /* Sed operates a line at a time. */
155 char *text
; /* Pointer to line allocated by malloc. */
156 int length
; /* Length of text. */
157 int alloc
; /* Allocated space for text. */
160 /* This structure holds information about files opend by the 'r', 'w',
161 and 's///w' commands. In paticular, it holds the FILE pointer to
162 use, the file's name, a flag that is non-zero if the file is being
163 read instead of written. */
170 } file_ptrs
[NUM_FPS
];
173 #if defined(__STDC__)
179 void panic
P_((char *str
, ...));
180 char *__fp_name
P_((FILE *fp
));
181 FILE *ck_fopen
P_((char *name
, char *mode
));
182 void ck_fwrite
P_((char *ptr
, int size
, int nmemb
, FILE *stream
));
183 void ck_fclose
P_((FILE *stream
));
184 VOID
*ck_malloc
P_((int size
));
185 VOID
*ck_realloc
P_((VOID
*ptr
, int size
));
186 char *ck_strdup
P_((char *str
));
187 VOID
*init_buffer
P_((void));
188 void flush_buffer
P_((VOID
*bb
));
189 int size_buffer
P_((VOID
*b
));
190 void add_buffer
P_((VOID
*bb
, char *p
, int n
));
191 void add1_buffer
P_((VOID
*bb
, int ch
));
192 char *get_buffer
P_((VOID
*bb
));
194 void compile_string
P_((char *str
));
195 void compile_file
P_((char *str
));
196 struct vector
*compile_program
P_((struct vector
*vector
));
197 void bad_prog
P_((char *why
));
198 int inchar
P_((void));
199 void savchar
P_((int ch
));
200 int compile_address
P_((struct addr
*addr
));
201 void compile_regex
P_((int slash
));
202 struct sed_label
*setup_jump
P_((struct sed_label
*list
, struct sed_cmd
*cmd
, struct vector
*vec
));
203 FILE *compile_filename
P_((int readit
));
204 void read_file
P_((char *name
));
205 void execute_program
P_((struct vector
*vec
));
206 int match_address
P_((struct addr
*addr
));
207 int read_pattern_space
P_((void));
208 void append_pattern_space
P_((void));
209 void line_copy
P_((struct line
*from
, struct line
*to
));
210 void line_append
P_((struct line
*from
, struct line
*to
));
211 void str_append
P_((struct line
*to
, char *string
, int length
));
212 void usage
P_((void));
216 /* If set, don't write out the line unless explictly told to */
217 int no_default_output
= 0;
219 /* Current input line # */
220 int input_line_number
= 0;
222 /* Are we on the last input file? */
223 int last_input_file
= 0;
225 /* Have we hit EOF on the last input file? This is used to decide if we
226 have hit the '$' address yet. */
229 /* non-zero if a quit command has been executed. */
232 /* Have we done any replacements lately? This is used by the 't' command. */
235 /* How many '{'s are we executing at the moment */
236 int program_depth
= 0;
238 /* The complete compiled SED program that we are going to run */
239 struct vector
*the_program
= 0;
241 /* information about labels and jumps-to-labels. This is used to do
242 the required backpatching after we have compiled all the scripts. */
243 struct sed_label
*jumps
= 0;
244 struct sed_label
*labels
= 0;
246 /* The 'current' input line. */
249 /* An input line that's been stored by later use by the program */
252 /* A 'line' to append to the current line when it comes time to write it out */
256 /* When we're reading a script command from a string, 'prog_start' and
257 'prog_end' point to the beginning and end of the string. This
258 would allow us to compile script strings that contain nulls, except
259 that script strings are only read from the command line, which is
264 /* When we're reading a script command from a string, 'prog_cur' points
265 to the current character in the string */
268 /* This is the name of the current script file.
269 It is used for error messages. */
272 /* This is the current script file. If it is zero, we are reading
273 from a string stored in 'prog_start' instead. If both 'prog_file'
274 and 'prog_start' are zero, we're in trouble! */
277 /* this is the number of the current script line that we're compiling. It is
278 used to give out useful and informative error messages. */
281 /* This is the file pointer that we're currently reading data from. It may
285 /* If this variable is non-zero at exit, one or more of the input
286 files couldn't be opened. */
290 /* 'an empty regular expression is equivalent to the last regular
291 expression read' so we have to keep track of the last regex used.
292 Here's where we store a pointer to it (it is only malloc()'d once) */
293 struct re_pattern_buffer
*last_regex
;
295 /* Various error messages we may want to print */
296 static char ONE_ADDR
[] = "Command only uses one address";
297 static char NO_ADDR
[] = "Command doesn't take any addresses";
298 static char LINE_JUNK
[] = "Extra characters after command";
299 static char BAD_EOF
[] = "Unexpected End-of-file";
300 static char NO_REGEX
[] = "No previous regular expression";
302 static struct option longopts
[] =
304 {"expression", 1, NULL
, 'e'},
305 {"file", 1, NULL
, 'f'},
306 {"quiet", 0, NULL
, 'n'},
307 {"silent", 0, NULL
, 'n'},
308 {"version", 0, NULL
, 'V'},
312 /* Yes, the main program, which parses arguments, and does the right
313 thing with them; it also inits the temporary storage, etc. */
320 char *e_strings
= NULL
;
322 struct sed_label
*go
,*lbl
;
325 while((opt
=getopt_long(argc
,argv
,"ne:f:V", longopts
, (int *) 0))
329 no_default_output
= 1;
332 if(e_strings
== NULL
) {
333 e_strings
=ck_malloc(strlen(optarg
)+2);
334 strcpy(e_strings
,optarg
);
336 e_strings
=ck_realloc(e_strings
,strlen(e_strings
)+strlen(optarg
)+2);
337 strcat(e_strings
,optarg
);
339 strcat(e_strings
,"\n");
343 compile_file(optarg
);
347 fprintf(stderr
, "%s\n", version_string
);
354 compile_string(e_strings
);
360 compile_string(argv
[optind
++]);
363 for(go
=jumps
;go
;go
=go
->next
) {
364 for(lbl
=labels
;lbl
;lbl
=lbl
->next
)
365 if(!strcmp(lbl
->name
,go
->name
))
367 if(*go
->name
&& !lbl
)
368 panic("Can't find label for jump to '%s'",go
->name
);
369 go
->v
->v
[go
->v_index
].x
.jump
=lbl
;
374 line
.text
=ck_malloc(50);
378 append
.text
=ck_malloc(50);
382 hold
.text
=ck_malloc(50);
387 } else while(optind
<argc
) {
390 read_file(argv
[optind
]);
400 /* 'str' is a string (from the command line) that contains a sed command.
401 Compile the command, and add it to the end of 'the_program' */
408 prog_start
=prog_cur
=str
;
409 prog_end
=str
+strlen(str
);
410 the_program
=compile_program(the_program
);
413 /* 'str' is the name of a file containing sed commands. Read them in
414 and add them to the end of 'the_program' */
421 prog_start
=prog_cur
=prog_end
=0;
424 if(str
[0]=='-' && str
[1]=='\0')
427 prog_file
=ck_fopen(str
,"r");
433 while(ch
!=EOF
&& ch
!='\n')
436 ungetc(ch
,prog_file
);
437 the_program
=compile_program(the_program
);
442 /* Read a program (or a subprogram within '{' '}' pairs) in and store
443 the compiled form in *'vector' Return a pointer to the new vector. */
445 compile_program(vector
)
446 struct vector
*vector
;
448 struct sed_cmd
*cur_cmd
;
452 unsigned char *string
;
456 vector
=(struct vector
*)ck_malloc(sizeof(struct vector
));
457 vector
->v
=(struct sed_cmd
*)ck_malloc(MORE_CMDS
*sizeof(struct sed_cmd
));
458 vector
->v_allocated
=MORE_CMDS
;
461 vector
->next_one
= 0;
466 while(ch
!=EOF
&& (isblank(ch
) || ch
=='\n' || ch
==';'));
471 if(vector
->v_length
==vector
->v_allocated
) {
472 vector
->v
=(struct sed_cmd
*)ck_realloc((VOID
*)vector
->v
,(vector
->v_length
+MORE_CMDS
)*sizeof(struct sed_cmd
));
473 vector
->v_allocated
+=MORE_CMDS
;
475 cur_cmd
=vector
->v
+vector
->v_length
;
478 cur_cmd
->a1
.addr_type
=0;
479 cur_cmd
->a2
.addr_type
=0;
483 if(compile_address(&(cur_cmd
->a1
))) {
487 while(ch
!=EOF
&& isblank(ch
));
489 if(compile_address(&(cur_cmd
->a2
)))
492 bad_prog("Unexpected ','");
502 if(cur_cmd
->a1
.addr_type
!=0)
505 while(ch
!=EOF
&& ch
!='\n');
509 if(cur_cmd
->aflags
& ADDR_BANG_BIT
)
510 bad_prog("Multiple '!'s");
511 cur_cmd
->aflags
|= ADDR_BANG_BIT
;
513 while(ch
!=EOF
&& isblank(ch
));
522 if(cur_cmd
->a2
.addr_type
!=0)
527 if(inchar()!='\\' || inchar()!='\n')
530 while((ch
=inchar())!=EOF
&& ch
!='\n') {
538 string
=(unsigned char *)ck_malloc(num
);
539 bcopy(get_buffer(b
),string
,num
);
541 cur_cmd
->x
.cmd_txt
.text_len
=num
;
542 cur_cmd
->x
.cmd_txt
.text
=(char *)string
;
548 while((ch
=inchar())!=EOF
&& ch
!='\n')
552 cur_cmd
->x
.sub
=compile_program((struct vector
*)0);
553 /* FOO JF is this the right thing to do? */
557 bad_prog("Unexpected '}'");
558 --(vector
->v_length
);
559 while((ch
=inchar())!=EOF
&& ch
!='\n' && ch
!=';')
565 if(cur_cmd
->a1
.addr_type
!=0)
566 bad_prog(": doesn't want any addresses");
567 labels
=setup_jump(labels
,cur_cmd
,vector
);
572 jumps
=setup_jump(jumps
,cur_cmd
,vector
);
576 if(cur_cmd
->a2
.addr_type
)
593 while(ch
!=EOF
&& isblank(ch
) && ch
!='\n' && ch
!=';');
594 if(ch
!='\n' && ch
!=';' && ch
!=EOF
)
599 if(cur_cmd
->a2
.addr_type
!=0)
604 cur_cmd
->x
.io_file
=compile_filename(ch
=='r');
610 compile_regex(slash
);
612 cur_cmd
->x
.cmd_regex
.regx
=last_regex
;
615 while((ch
=inchar())!=EOF
&& ch
!=slash
) {
628 cur_cmd
->x
.cmd_regex
.replace_length
=size_buffer(b
);
629 cur_cmd
->x
.cmd_regex
.replacement
=ck_malloc(cur_cmd
->x
.cmd_regex
.replace_length
);
630 bcopy(get_buffer(b
),cur_cmd
->x
.cmd_regex
.replacement
,cur_cmd
->x
.cmd_regex
.replace_length
);
633 cur_cmd
->x
.cmd_regex
.flags
=0;
634 cur_cmd
->x
.cmd_regex
.numb
=0;
642 if(cur_cmd
->x
.cmd_regex
.flags
&S_PRINT_BIT
)
643 bad_prog("multiple 'p' options to 's' command");
644 cur_cmd
->x
.cmd_regex
.flags
|=S_PRINT_BIT
;
647 if(cur_cmd
->x
.cmd_regex
.flags
&S_NUM_BIT
)
648 cur_cmd
->x
.cmd_regex
.flags
&= ~S_NUM_BIT
;
649 if(cur_cmd
->x
.cmd_regex
.flags
&S_GLOBAL_BIT
)
650 bad_prog("multiple 'g' options to 's' command");
651 cur_cmd
->x
.cmd_regex
.flags
|=S_GLOBAL_BIT
;
654 cur_cmd
->x
.cmd_regex
.flags
|=S_WRITE_BIT
;
655 cur_cmd
->x
.cmd_regex
.wio_file
=compile_filename(0);
658 case '0': case '1': case '2': case '3':
659 case '4': case '5': case '6': case '7':
661 if(cur_cmd
->x
.cmd_regex
.flags
&S_NUM_BIT
)
662 bad_prog("multiple number options to 's' command");
663 if((cur_cmd
->x
.cmd_regex
.flags
&S_GLOBAL_BIT
)==0)
664 cur_cmd
->x
.cmd_regex
.flags
|=S_NUM_BIT
;
671 cur_cmd
->x
.cmd_regex
.numb
=num
;
678 bad_prog("Unknown option to 's'");
681 } while(ch
!=EOF
&& ch
!='\n' && ch
!=';');
688 string
=(unsigned char *)ck_malloc(256);
689 for(num
=0;num
<256;num
++)
693 while((ch
=inchar())!=EOF
&& ch
!=slash
)
695 cur_cmd
->x
.translate
=string
;
696 string
=(unsigned char *)get_buffer(b
);
697 for(num
=size_buffer(b
);num
;--num
) {
702 bad_prog("strings for y command are different lengths");
703 cur_cmd
->x
.translate
[*string
++]=ch
;
706 if(inchar()!=slash
|| ((ch
=inchar())!=EOF
&& ch
!='\n' && ch
!=';'))
711 bad_prog("Unknown command");
717 /* Complain about a programming error and exit. */
723 fprintf(stderr
,"%s: file %s line %d: %s\n",myname
,prog_name
,prog_line
,why
);
725 fprintf(stderr
,"%s: %s\n",myname
,why
);
729 /* Read the next character from the program. Return EOF if there isn't
730 anything to read. Keep prog_line up to date, so error messages can
744 else if(prog_cur
==prog_end
) {
750 if(ch
=='\n' && prog_line
)
755 /* unget 'ch' so the next call to inchar will return it. 'ch' must not be
756 EOF or anything nasty like that. */
763 if(ch
=='\n' && prog_line
>1)
766 ungetc(ch
,prog_file
);
772 /* Try to read an address for a sed command. If it succeeeds,
773 return non-zero and store the resulting address in *'addr'.
774 If the input doesn't look like an address read nothing
777 compile_address(addr
)
787 while((ch
=inchar())!=EOF
&& isdigit(ch
))
789 while(ch
!=EOF
&& isblank(ch
))
792 addr
->addr_type
=ADDR_NUM
;
793 addr
->addr_number
= num
;
796 addr
->addr_type
=ADDR_REGEX
;
798 addr
->addr_regex
=last_regex
;
800 while(ch
!=EOF
&& isblank(ch
));
804 addr
->addr_type
=ADDR_LAST
;
806 while(ch
!=EOF
&& isblank(ch
));
815 compile_regex (slash
)
820 int in_char_class
= 0;
823 while((ch
=inchar())!=EOF
&& (ch
!=slash
|| in_char_class
)) {
825 if(size_buffer(b
)==0) {
840 } else if(ch
== '[') {
844 } else if(ch
== ']') {
848 } else if(ch
!='\\') {
882 last_regex
=(struct re_pattern_buffer
*)ck_malloc(sizeof(struct re_pattern_buffer
));
883 last_regex
->allocated
=size_buffer(b
)+10;
884 last_regex
->buffer
=ck_malloc(last_regex
->allocated
);
885 last_regex
->fastmap
=ck_malloc(256);
886 last_regex
->translate
=0;
887 re_compile_pattern(get_buffer(b
),size_buffer(b
),last_regex
);
888 } else if(!last_regex
)
893 /* Store a label (or label reference) created by a ':', 'b', or 't'
894 comand so that the jump to/from the lable can be backpatched after
895 compilation is complete */
897 setup_jump(list
,cmd
,vec
)
898 struct sed_label
*list
;
902 struct sed_label
*tmp
;
907 while((ch
=inchar()) != EOF
&& isblank(ch
))
909 while(ch
!=EOF
&& ch
!='\n') {
915 tmp
=(struct sed_label
*)ck_malloc(sizeof(struct sed_label
));
917 tmp
->v_index
=cmd
-vec
->v
;
918 tmp
->name
=ck_strdup(get_buffer(b
));
924 /* read in a filename for a 'r', 'w', or 's///w' command, and
925 update the internal structure about files. The file is
926 opened if it isn't already open. */
928 compile_filename(readit
)
937 bad_prog("missing ' ' before filename");
939 while((ch
=inchar())!=EOF
&& ch
!='\n')
942 file_name
=get_buffer(b
);
943 for(n
=0;n
<NUM_FPS
;n
++) {
944 if(!file_ptrs
[n
].name
)
946 if(!strcmp(file_ptrs
[n
].name
,file_name
)) {
947 if(file_ptrs
[n
].readit
!=readit
)
948 bad_prog("Can't open file for both reading and writing");
950 return file_ptrs
[n
].phile
;
954 file_ptrs
[n
].name
=ck_strdup(file_name
);
955 file_ptrs
[n
].readit
=readit
;
957 file_ptrs
[n
].phile
=ck_fopen(file_name
,"a");
958 else if (access(file_name
, 4) == 0)
959 file_ptrs
[n
].phile
=ck_fopen(file_name
,"r");
961 file_ptrs
[n
].phile
=ck_fopen("/dev/null", "r");
963 return file_ptrs
[n
].phile
;
965 bad_prog("Hopelessely evil compiled in limit on number of open files. re-compile sed");
970 /* Parse a filename given by a 'r' 'w' or 's///w' command. */
975 if(*name
=='-' && name
[1]=='\0')
978 input_file
=fopen(name
,"r");
981 extern char *sys_errlist
[];
986 ptr
=(errno
>=0 && errno
<sys_nerr
) ? sys_errlist
[errno
] : "Unknown error code";
988 fprintf(stderr
,"%s: can't read %s: %s\n",myname
,name
,ptr
);
993 while(read_pattern_space()) {
994 execute_program(the_program
);
995 if(!no_default_output
)
996 ck_fwrite(line
.text
,1,line
.length
,stdout
);
998 ck_fwrite(append
.text
,1,append
.length
,stdout
);
1004 ck_fclose(input_file
);
1007 /* Execute the program 'vec' on the current input line. */
1009 execute_program(vec
)
1012 struct sed_cmd
*cur_cmd
;
1015 static int end_cycle
;
1021 static struct line tmp
;
1023 char *rep
,*rep_end
,*rep_next
,*rep_cur
;
1025 struct re_registers regs
;
1030 for(cur_cmd
=vec
->v
,n
=vec
->v_length
;n
;cur_cmd
++,n
--) {
1034 if(cur_cmd
->aflags
&A1_MATCHED_BIT
) {
1036 if(match_address(&(cur_cmd
->a2
)))
1037 cur_cmd
->aflags
&=~A1_MATCHED_BIT
;
1038 } else if(match_address(&(cur_cmd
->a1
))) {
1040 if(cur_cmd
->a2
.addr_type
!=ADDR_NULL
)
1041 cur_cmd
->aflags
|=A1_MATCHED_BIT
;
1043 if(cur_cmd
->aflags
&ADDR_BANG_BIT
)
1044 addr_matched
= !addr_matched
;
1047 switch(cur_cmd
->cmd
) {
1048 case '{': /* Execute sub-program */
1049 execute_program(cur_cmd
->x
.sub
);
1052 case ':': /* Executing labels is easy. */
1056 printf("%d\n",input_line_number
);
1060 while(append
.alloc
-append
.length
<cur_cmd
->x
.cmd_txt
.text_len
) {
1062 append
.text
=ck_realloc(append
.text
,append
.alloc
);
1064 bcopy(cur_cmd
->x
.cmd_txt
.text
,append
.text
+append
.length
,cur_cmd
->x
.cmd_txt
.text_len
);
1065 append
.length
+=cur_cmd
->x
.cmd_txt
.text_len
;
1069 if(!cur_cmd
->x
.jump
)
1072 struct sed_label
*j
= cur_cmd
->x
.jump
;
1074 n
= j
->v
->v_length
- j
->v_index
;
1075 cur_cmd
= j
->v
->v
+ j
->v_index
;
1082 if(!(cur_cmd
->aflags
&A1_MATCHED_BIT
))
1083 ck_fwrite(cur_cmd
->x
.cmd_txt
.text
,1,cur_cmd
->x
.cmd_txt
.text_len
,stdout
);
1097 tmp
=memchr(line
.text
,'\n',line
.length
);
1098 newlength
=line
.length
-(tmp
-line
.text
);
1100 memmove(line
.text
,tmp
,newlength
);
1101 line
.length
=newlength
;
1107 line_copy(&hold
,&line
);
1111 line_append(&hold
,&line
);
1115 line_copy(&line
,&hold
);
1119 line_append(&line
,&hold
);
1123 ck_fwrite(cur_cmd
->x
.cmd_txt
.text
,1,cur_cmd
->x
.cmd_txt
.text_len
,stdout
);
1134 /* Use --n so this'll skip the trailing newline */
1143 } else if(isprint(*tmp
)) {
1146 } else switch(*tmp
) {
1148 /* Should print \00 instead of \0 because (a) POSIX requires it, and
1149 (b) this way \01 is unambiguous. */
1184 printf("\\%02x",(*tmp
)&0xFF);
1195 if (feof(input_file
)) goto quit
;
1196 ck_fwrite(line
.text
,1,line
.length
,stdout
);
1197 read_pattern_space();
1201 if (feof(input_file
)) goto quit
;
1202 append_pattern_space();
1206 ck_fwrite(line
.text
,1,line
.length
,stdout
);
1213 tmp
=memchr(line
.text
,'\n',line
.length
);
1214 ck_fwrite(line
.text
, 1,
1215 tmp
? tmp
- line
.text
+ 1
1216 : line
.length
, stdout
);
1229 rewind(cur_cmd
->x
.io_file
);
1232 if(append
.length
==append
.alloc
) {
1234 append
.text
= ck_realloc(append
.text
, append
.alloc
);
1236 } while((n
=fread(append
.text
+append
.length
,sizeof(char),append
.alloc
-append
.length
,cur_cmd
->x
.io_file
))>0);
1237 if(ferror(cur_cmd
->x
.io_file
))
1238 panic("Read error on input file to 'r' command");
1245 tmp
.text
=ck_malloc(50);
1249 remain
=line
.length
-1;
1251 rep
= cur_cmd
->x
.cmd_regex
.replacement
;
1252 rep_end
=rep
+cur_cmd
->x
.cmd_regex
.replace_length
;
1254 while((offset
= re_search(cur_cmd
->x
.cmd_regex
.regx
,
1262 str_append(&tmp
,line
.text
+start
,offset
-start
);
1264 if(cur_cmd
->x
.cmd_regex
.flags
&S_NUM_BIT
) {
1265 if(count
!=cur_cmd
->x
.cmd_regex
.numb
) {
1266 str_append(&tmp
,line
.text
+regs
.start
[0],regs
.end
[0]-regs
.start
[0]);
1267 start
= (offset
== regs
.end
[0] ? offset
+ 1 : regs
.end
[0]);
1268 remain
= (line
.length
-1) - start
;
1273 for(rep_next
=rep_cur
=rep
;rep_next
<rep_end
;rep_next
++) {
1274 if(*rep_next
=='&') {
1275 if(rep_next
-rep_cur
)
1276 str_append(&tmp
,rep_cur
,rep_next
-rep_cur
);
1277 str_append(&tmp
,line
.text
+regs
.start
[0],regs
.end
[0]-regs
.start
[0]);
1279 } else if(*rep_next
=='\\') {
1280 if(rep_next
-rep_cur
)
1281 str_append(&tmp
,rep_cur
,rep_next
-rep_cur
);
1283 if(rep_next
!=rep_end
) {
1286 if(*rep_next
>='0' && *rep_next
<='9') {
1288 str_append(&tmp
,line
.text
+regs
.start
[n
],regs
.end
[n
]-regs
.start
[n
]);
1290 str_append(&tmp
,rep_next
,1);
1295 if(rep_next
-rep_cur
)
1296 str_append(&tmp
,rep_cur
,rep_next
-rep_cur
);
1297 if (offset
== regs
.end
[0]) {
1298 str_append(&tmp
, line
.text
+ offset
, 1);
1301 start
= regs
.end
[0];
1303 remain
= (line
.length
-1) - start
;
1306 if(!(cur_cmd
->x
.cmd_regex
.flags
&S_GLOBAL_BIT
))
1312 str_append(&tmp
,line
.text
+start
,remain
+1);
1314 t
.length
=line
.length
;
1317 line
.length
=tmp
.length
;
1318 line
.alloc
=tmp
.alloc
;
1320 tmp
.length
=t
.length
;
1322 if(cur_cmd
->x
.cmd_regex
.flags
&S_WRITE_BIT
)
1323 ck_fwrite(line
.text
,1,line
.length
,cur_cmd
->x
.cmd_regex
.wio_file
);
1324 if(cur_cmd
->x
.cmd_regex
.flags
&S_PRINT_BIT
)
1325 ck_fwrite(line
.text
,1,line
.length
,stdout
);
1331 if(!cur_cmd
->x
.jump
)
1334 struct sed_label
*j
= cur_cmd
->x
.jump
;
1336 n
= j
->v
->v_length
- j
->v_index
;
1337 cur_cmd
= j
->v
->v
+ j
->v_index
;
1344 ck_fwrite(line
.text
,1,line
.length
,cur_cmd
->x
.io_file
);
1359 unsigned char *p
,*e
;
1361 for(p
=(unsigned char *)(line
.text
),e
=p
+line
.length
;p
<e
;p
++)
1362 *p
=cur_cmd
->x
.translate
[*p
];
1367 panic("INTERNAL ERROR: Bad cmd %c",cur_cmd
->cmd
);
1375 /* Return non-zero if the current line matches the address
1376 pointed to by 'addr'. */
1381 switch(addr
->addr_type
) {
1385 return (input_line_number
==addr
->addr_number
);
1388 return (re_search(addr
->addr_regex
,
1393 (struct re_registers
*)0)>=0) ? 1 : 0;
1396 return (input_EOF
) ? 1 : 0;
1399 panic("INTERNAL ERROR: bad address type");
1405 /* Read in the next line of input, and store it in the
1406 pattern space. Return non-zero if this is the last line of input */
1409 read_pattern_space()
1418 if(feof(input_file
))
1420 input_line_number
++;
1424 line
.text
=ck_realloc(line
.text
,line
.alloc
*2);
1425 p
=line
.text
+line
.alloc
;
1429 ch
=getc(input_file
);
1435 line
.length
=line
.alloc
-n
;
1443 line
.length
=line
.alloc
-n
;
1447 ch
=getc(input_file
);
1449 ungetc(ch
,input_file
);
1450 else if(last_input_file
)
1455 /* Inplement the 'N' command, which appends the next line of input to
1456 the pattern space. */
1458 append_pattern_space()
1464 p
=line
.text
+line
.length
;
1465 n
=line
.alloc
-line
.length
;
1467 input_line_number
++;
1470 ch
=getc(input_file
);
1476 line
.length
=line
.alloc
-n
;
1484 line
.length
=line
.alloc
-n
;
1488 line
.text
=ck_realloc(line
.text
,line
.alloc
*2);
1489 p
=line
.text
+line
.alloc
;
1494 ch
=getc(input_file
);
1496 ungetc(ch
,input_file
);
1497 else if(last_input_file
)
1501 /* Copy the contents of the line 'from' into the line 'to'.
1502 This destroys the old contents of 'to'. It will still work
1503 if the line 'from' contains nulls. */
1506 struct line
*from
,*to
;
1508 if(from
->length
>to
->alloc
) {
1509 to
->alloc
=from
->length
;
1510 to
->text
=ck_realloc(to
->text
,to
->alloc
);
1512 bcopy(from
->text
,to
->text
,from
->length
);
1513 to
->length
=from
->length
;
1516 /* Append the contents of the line 'from' to the line 'to'.
1517 This routine will work even if the line 'from' contains nulls */
1519 line_append(from
,to
)
1520 struct line
*from
,*to
;
1522 if(from
->length
>(to
->alloc
-to
->length
)) {
1523 to
->alloc
+=from
->length
;
1524 to
->text
=ck_realloc(to
->text
,to
->alloc
);
1526 bcopy(from
->text
,to
->text
+to
->length
,from
->length
);
1527 to
->length
+=from
->length
;
1530 /* Append 'length' bytes from 'string' to the line 'to'
1531 This routine *will* append bytes with nulls in them, without
1534 str_append(to
,string
,length
)
1539 if(length
>to
->alloc
-to
->length
) {
1541 to
->text
=ck_realloc(to
->text
,to
->alloc
);
1543 bcopy(string
,to
->text
+to
->length
,length
);
1551 Usage: %s [-nV] [+quiet] [+silent] [+version] [-e script] [-f script-file]\n\
1552 [+expression=script] [+file=script-file] [file...]\n", myname
);