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