]>
Dogcows Code - chaz/tar/blob - src/transform.c
1 /* This file is part of GNU tar.
2 Copyright (C) 2006 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 2, or (at your option) any later
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
12 Public License for more details.
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
28 transform_type
= transform_none
;
30 static struct obstack stk
;
32 enum replace_segm_type
34 segm_literal
, /* Literal segment */
35 segm_backref
, /* Back-reference segment */
40 struct replace_segm
*next
;
41 enum replace_segm_type type
;
53 static struct replace_segm
*repl_head
, *repl_tail
;
56 static struct replace_segm
*
59 struct replace_segm
*segm
= xmalloc (sizeof *segm
);
62 repl_tail
->next
= segm
;
71 add_literal_segment (char *str
, char *end
)
73 size_t len
= end
- str
;
76 struct replace_segm
*segm
= add_segment ();
77 segm
->type
= segm_literal
;
78 segm
->v
.literal
.ptr
= xmalloc (len
+ 1);
79 memcpy (segm
->v
.literal
.ptr
, str
, len
);
80 segm
->v
.literal
.ptr
[len
] = 0;
81 segm
->v
.literal
.size
= len
;
86 add_char_segment (int chr
)
88 struct replace_segm
*segm
= add_segment ();
89 segm
->type
= segm_literal
;
90 segm
->v
.literal
.ptr
= xmalloc (2);
91 segm
->v
.literal
.ptr
[0] = chr
;
92 segm
->v
.literal
.ptr
[1] = 0;
93 segm
->v
.literal
.size
= 2;
97 add_backref_segment (size_t ref
)
99 struct replace_segm
*segm
= add_segment ();
100 segm
->type
= segm_backref
;
105 set_transform_expr (const char *expr
)
109 char *str
, *beg
, *cur
;
113 if (transform_type
== transform_none
)
117 /* Redefinition of the transform expression */
122 USAGE_ERROR ((0, 0, _("Invalid transform expression")));
126 /* Scan regular expression */
127 for (i
= 2; expr
[i
] && expr
[i
] != delim
; i
++)
128 if (expr
[i
] == '\\' && expr
[i
+1])
131 if (expr
[i
] != delim
)
132 USAGE_ERROR ((0, 0, _("Invalid transform expression")));
134 /* Scan replacement expression */
135 for (j
= i
+ 1; expr
[j
] && expr
[j
] != delim
; j
++)
136 if (expr
[j
] == '\\' && expr
[j
+1])
139 if (expr
[j
] != delim
)
140 USAGE_ERROR ((0, 0, _("Invalid transform expression")));
143 transform_type
= transform_first
;
144 for (p
= expr
+ j
+ 1; *p
; p
++)
148 transform_type
= transform_global
;
156 cflags
|= REG_EXTENDED
;
160 USAGE_ERROR ((0, 0, _("Unknown flag in transform expression")));
163 /* Extract and compile regex */
164 str
= xmalloc (i
- 1);
165 memcpy (str
, expr
+ 2, i
- 2);
168 rc
= regcomp (®ex
, str
, cflags
);
173 regerror (rc
, ®ex
, errbuf
, sizeof (errbuf
));
174 USAGE_ERROR ((0, 0, _("Invalid transform expression: %s"), errbuf
));
177 if (str
[0] == '^' || str
[strlen (str
) - 1] == '$')
178 transform_type
= transform_first
;
182 /* Extract and compile replacement expr */
184 str
= xmalloc (j
- i
+ 1);
185 memcpy (str
, expr
+ i
, j
- i
);
188 for (cur
= beg
= str
; *cur
;)
194 add_literal_segment (beg
, cur
);
197 case '0': case '1': case '2': case '3': case '4':
198 case '5': case '6': case '7': case '8': case '9':
199 n
= strtoul (cur
, &cur
, 10);
200 if (n
> regex
.re_nsub
)
201 USAGE_ERROR ((0, 0, _("Invalid transform replacement: back reference out of range")));
202 add_backref_segment (n
);
206 add_char_segment ('\\');
211 add_char_segment ('\a');
216 add_char_segment ('\b');
221 add_char_segment ('\f');
226 add_char_segment ('\n');
231 add_char_segment ('\r');
236 add_char_segment ('\t');
241 add_char_segment ('\v');
246 add_char_segment ('&');
256 add_literal_segment (buf
, buf
+ 2);
263 else if (*cur
== '&')
265 add_literal_segment (beg
, cur
);
266 add_backref_segment (0);
272 add_literal_segment (beg
, cur
);
277 _transform_name_to_obstack (char *input
)
283 if (transform_type
== transform_none
)
286 rmp
= xmalloc ((regex
.re_nsub
+ 1) * sizeof (*rmp
));
292 rc
= regexec (®ex
, input
, regex
.re_nsub
+ 1, rmp
, 0);
296 struct replace_segm
*segm
;
301 obstack_grow (&stk
, input
, rmp
[0].rm_so
);
303 for (segm
= repl_head
; segm
; segm
= segm
->next
)
307 case segm_literal
: /* Literal segment */
308 obstack_grow (&stk
, segm
->v
.literal
.ptr
,
309 segm
->v
.literal
.size
);
312 case segm_backref
: /* Back-reference segment */
313 if (rmp
[segm
->v
.ref
].rm_so
!= -1
314 && rmp
[segm
->v
.ref
].rm_eo
!= -1)
316 input
+ rmp
[segm
->v
.ref
].rm_so
,
317 rmp
[segm
->v
.ref
].rm_eo
- rmp
[segm
->v
.ref
].rm_so
);
324 disp
= strlen (input
);
325 obstack_grow (&stk
, input
, disp
);
330 if (transform_type
== transform_first
)
332 obstack_grow (&stk
, input
, strlen (input
));
337 obstack_1grow (&stk
, 0);
343 transform_name_fp (char **pinput
, char *(*fun
)(char *))
346 bool ret
= _transform_name_to_obstack (*pinput
);
349 str
= obstack_finish (&stk
);
350 assign_string (pinput
, fun
? fun (str
) : str
);
351 obstack_free (&stk
, str
);
357 transform_name (char **pinput
)
359 return transform_name_fp (pinput
, NULL
);
364 read_and_transform_loop ()
367 while (fgets (buf
, sizeof buf
, stdin
))
369 char *p
= buf
+ strlen (buf
);
372 if (transform_name (buf
, &p
))
373 printf ("=> %s\n", p
);
This page took 0.04862 seconds and 4 git commands to generate.