2 /********************************************
4 copyright 1991, Michael D. Brennan
6 This is a source file for mawk, an implementation of
7 the AWK programming language.
9 Mawk is distributed without warranty under the terms of
10 the GNU General Public License, version 2, 1991.
11 ********************************************/
13 /* $Log: re_cmpl.c,v $
14 * Revision 1.6 1994/12/13 00:14:58 mike
15 * \\ -> \ on second replacement scan
17 * Revision 1.5 1994/10/08 19:15:51 mike
20 * Revision 1.4 1993/07/21 01:17:53 mike
21 * handle "&" as replacement correctly
23 * Revision 1.3 1993/07/17 13:23:10 mike
24 * indent and general code cleanup
26 * Revision 1.2 1993/07/15 23:38:23 mike
29 * Revision 1.1.1.1 1993/07/03 18:58:19 mike
32 * Revision 5.2 1993/01/01 21:30:48 mike
33 * split new_STRING() into new_STRING and new_STRING0
35 * Revision 5.1 1991/12/05 07:56:25 brennan
50 static CELL *PROTO(REPL_compile, (STRING *)) ;
52 typedef struct re_node
56 struct re_node *link ;
59 /* a list of compiled regular expressions */
60 static RE_NODE *re_list ;
62 static char efmt[] = "regular expression compile failed (%s)\n%s" ;
64 /* compile a STRING to a regular expression machine.
65 Search a list of pre-compiled strings first
81 if (strcmp(s, p->sval->str) == 0) /* found */
83 if (!q) /* already at front */
85 else /* delete from list for move to front */
87 q->link = p->link ; goto found ;
98 p = ZMALLOC(RE_NODE) ;
102 if (!(p->re = REcompile(s)))
104 if (mawk_state == EXECUTION)
105 rt_error(efmt, REerrlist[REerrno], s) ;
108 compile_error(efmt, REerrlist[REerrno], s) ;
115 /* insert p at the front of the list */
116 p->link = re_list ; re_list = p ;
121 if (dump_RE) REmprint(p->re, stderr) ;
128 /* this is only used by da() */
135 register RE_NODE *p ;
137 for (p = re_list; p; p = p->link)
138 if (p->re == m) return p->sval->str ;
140 bozo("non compiled machine") ;
146 /*=================================================*/
147 /* replacement operations */
149 /* create a replacement CELL from a STRING * */
156 register char *p = sval->str ;
161 q = xbuff = (char *) zmalloc(sval->len + 1) ;
172 if (p[1] == '&'|| p[1] == '\\')
181 /* if empty we don't need to make a node */
185 split_buff[i++] = new_STRING(xbuff) ;
187 /* and a null node for the '&' */
188 split_buff[i++] = (STRING *) 0 ;
201 /* if we have one empty string it will get made now */
202 if (q > xbuff || i == 0) split_buff[i++] = new_STRING(xbuff) ;
204 /* This will never happen */
205 if (i > MAX_SPLIT) overflow("replacement pieces", MAX_SPLIT) ;
208 if (i == 1 && split_buff[0])
211 cp->ptr = (PTR) split_buff[0] ;
215 STRING **sp = (STRING **)
216 (cp->ptr = zmalloc(sizeof(STRING *) * i)) ;
219 while (j < i) *sp++ = split_buff[j++] ;
224 zfree(xbuff, sval->len + 1) ;
228 /* free memory used by a replacement CELL */
234 register STRING **p ;
237 if (cp->type == C_REPL) free_STRING(string(cp)) ;
238 else /* an C_REPLV */
240 p = (STRING **) cp->ptr ;
241 for (cnt = cp->vcnt; cnt; cnt--)
243 if (*p) free_STRING(*p) ;
246 zfree(cp->ptr, cp->vcnt * sizeof(STRING *)) ;
250 /* copy a C_REPLV cell to another CELL */
253 replv_cpy(target, source)
254 CELL *target, *source ;
259 target->type = C_REPLV ;
260 cnt = target->vcnt = source->vcnt ;
261 target->ptr = (PTR) zmalloc(cnt * sizeof(STRING *)) ;
263 t = (STRING **) target->ptr ;
264 s = (STRING **) source->ptr ;
268 if ( *s ) (*s)->ref_cnt++ ;
275 /* here's our old friend linked linear list with move to the front
276 for compilation of replacement CELLs */
278 typedef struct repl_node
280 struct repl_node *link ;
281 STRING *sval ; /* the input */
282 CELL *cp ; /* the output */
285 static REPL_NODE *repl_list ;
287 /* search the list (with move to the front) for a compiled
289 return a ptr to a CELL (C_REPL or C_REPLV)
296 register REPL_NODE *p ;
300 /* search the list */
303 q = (REPL_NODE *) 0 ;
306 if (strcmp(s, p->sval->str) == 0) /* found */
308 if (!q) /* already at front */
310 else /* delete from list for move to front */
319 q = p ; p = p->link ;
324 p = ZMALLOC(REPL_NODE) ;
327 p->cp = REPL_compile(sval) ;
330 /* insert p at the front of the list */
331 p->link = repl_list ; repl_list = p ;
335 /* return the string for a CELL or type REPL or REPLV,
336 this is only used by da() */
343 register REPL_NODE *p = repl_list ;
345 if (cp->type == C_REPL)
349 if (p->cp->type == C_REPL && p->cp->ptr == cp->ptr)
350 return p->sval->str ;
358 if (p->cp->type == C_REPLV &&
359 memcmp(cp->ptr, p->cp->ptr, cp->vcnt * sizeof(STRING *))
361 return p->sval->str ;
367 bozo("unable to uncompile an repl") ;
372 convert a C_REPLV to C_REPL
373 replacing the &s with sval
377 replv_to_repl(cp, sval)
378 CELL *cp ; STRING *sval ;
380 register STRING **p ;
381 STRING **sblock = (STRING **) cp->ptr ;
382 unsigned cnt, vcnt = cp->vcnt ;
387 if (cp->type != C_REPLV) bozo("not replv") ;
390 p = sblock ; cnt = vcnt ; len = 0 ;
393 if (*p) len += (*p++)->len ;
402 cp->ptr = (PTR) new_STRING0(len) ;
404 p = sblock ; cnt = vcnt ; target = string(cp)->str ;
407 memcpy(target, (*p)->str, (*p)->len) ;
408 target += (*p)->len ;
413 zfree(sblock, vcnt * sizeof(STRING *)) ;