1 /*
2 * regsub @(#)regsub.c 1.3 of 2 April 86
3 *
4 * Copyright (c) 1986 by University of Toronto. Written by Henry Spencer. Not
5 * derived from licensed software.
6 *
7 * Permission is granted to anyone to use this software for any purpose on any
8 * computer system, and to redistribute it freely, subject to the following
9 * restrictions:
10 *
11 * 1. The author is not responsible for the consequences of use of this
12 * software, no matter how awful, even if they arise from defects in it.
13 *
14 * 2. The origin of this software must not be misrepresented, either by explicit
15 * claim or by omission.
16 *
17 * 3. Altered versions must be plainly marked as such, and must not be
18 * misrepresented as being the original software.
19 */
20
21 #define _GNU_SOURCE
22
23 #define rep_NEED_REGEXP_INTERNALS
24 #include "repint.h"
25
26 #include <stdio.h>
27 #include <string.h>
28
29 /*
30 * CHANGED, 14-Jan-93, by J.Harper,
31 * added #ifdef __STDC__ prototype sections so I can use registerized
32 * arguments
33 *
34 * also, I added the regsublen() function for safety & general usefulness
35 * (regsub() has no checks for overstepping its dest string)
36 */
37
38 #ifndef CHARBITS
39 #define UCHARAT(p) ((int)*(unsigned char *)(p))
40 #else
41 #define UCHARAT(p) ((int)*(p)&CHARBITS)
42 #endif
43
44 /*
45 * - regsub - perform substitutions after a regexp match
46 *
47 * data is null if the last match was a string, or the TX if the last
48 * match was on a buffer.
49 */
50 void
rep_default_regsub(lasttype,matches,source,dest,data)51 rep_default_regsub(lasttype, matches, source, dest, data)
52 int lasttype;
53 rep_regsubs *matches;
54 char *source;
55 char *dest;
56 void *data;
57 {
58 register char *src;
59 register char *dst;
60 register char c;
61 register int no;
62 register int len;
63
64 if (matches == NULL || source == NULL || dest == NULL) {
65 rep_regerror("NULL parm to regsub");
66 return;
67 }
68 if ((lasttype == rep_reg_string && !rep_STRINGP(rep_VAL(data)))
69 || (lasttype == rep_reg_obj))
70 {
71 rep_regerror("Bad type of data to regsub");
72 return;
73 }
74 src = source;
75 dst = dest;
76 while ((c = *src++) != '\0')
77 {
78 if (c == '&')
79 no = 0;
80 else if (c == '\\' && '0' <= *src && *src <= '9')
81 no = *src++ - '0';
82 else
83 no = -1;
84
85 if (no < 0) { /* Ordinary character. */
86 if (c == '\\' && (*src == '\\' || *src == '&'))
87 c = *src++;
88 *dst++ = c;
89 } else {
90 if(lasttype == rep_reg_string)
91 {
92 if (matches->string.startp[no] != NULL
93 && matches->string.endp[no] != NULL)
94 {
95 len = matches->string.endp[no]
96 - matches->string.startp[no];
97 (void) strncpy(dst, matches->string.startp[no], len);
98 dst += len;
99 if (len != 0 && *(dst - 1) == '\0')
100 {
101 /* strncpy hit NUL. */
102 rep_regerror("damaged match string");
103 return;
104 }
105 }
106 }
107 }
108 }
109 *dst++ = '\0';
110 }
111
112 /*
113 * - regsublen - dummy regsub() returning length of contructed string,
114 * including terminating '\0'
115 */
116 int
rep_default_regsublen(lasttype,matches,source,data)117 rep_default_regsublen(lasttype, matches, source, data)
118 int lasttype;
119 rep_regsubs *matches;
120 char *source;
121 void *data;
122 {
123 register char *src;
124 register char c;
125 register int no;
126 register int dstlen = 1;
127
128 if (matches == NULL || source == NULL) {
129 rep_regerror("NULL parm to regsublen");
130 return(0);
131 }
132 if ((lasttype == rep_reg_string && !rep_STRINGP(rep_VAL(data)))
133 || (lasttype == rep_reg_obj))
134 {
135 rep_regerror("Bad type of data to regsublen");
136 return (0);
137 }
138 src = source;
139 while ((c = *src++) != '\0') {
140 if (c == '&')
141 no = 0;
142 else if (c == '\\' && '0' <= *src && *src <= '9')
143 no = *src++ - '0';
144 else
145 no = -1;
146
147 if (no < 0) { /* Ordinary character. */
148 if (c == '\\' && (*src == '\\' || *src == '&'))
149 c = *src++;
150 dstlen++;
151 } else {
152 if(lasttype == rep_reg_string)
153 {
154 if (matches->string.startp[no] != NULL
155 && matches->string.endp[no] != NULL)
156 {
157 dstlen += matches->string.endp[no]
158 - matches->string.startp[no];
159 }
160 }
161 }
162 }
163 return(dstlen);
164 }
165