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") ;
148 /*=================================================*/
149 /* replacement operations */
151 /* create a replacement CELL from a STRING * */
158 register char *p = sval->str ;
163 q = xbuff = (char *) zmalloc(sval->len + 1) ;
174 if (p[1] == '&'|| p[1] == '\\')
183 /* if empty we don't need to make a node */
187 split_buff[i++] = new_STRING(xbuff) ;
189 /* and a null node for the '&' */
190 split_buff[i++] = (STRING *) 0 ;
203 /* if we have one empty string it will get made now */
204 if (q > xbuff || i == 0) split_buff[i++] = new_STRING(xbuff) ;
206 /* This will never happen */
207 if (i > MAX_SPLIT) overflow("replacement pieces", MAX_SPLIT) ;
210 if (i == 1 && split_buff[0])
213 cp->ptr = (PTR) split_buff[0] ;
217 STRING **sp = (STRING **)
218 (cp->ptr = zmalloc(sizeof(STRING *) * i)) ;
221 while (j < i) *sp++ = split_buff[j++] ;
226 zfree(xbuff, sval->len + 1) ;
230 /* free memory used by a replacement CELL */
236 register STRING **p ;
239 if (cp->type == C_REPL) free_STRING(string(cp)) ;
240 else /* an C_REPLV */
242 p = (STRING **) cp->ptr ;
243 for (cnt = cp->vcnt; cnt; cnt--)
245 if (*p) { free_STRING(*p) ; }
248 zfree(cp->ptr, cp->vcnt * sizeof(STRING *)) ;
252 /* copy a C_REPLV cell to another CELL */
255 replv_cpy(target, source)
256 CELL *target, *source ;
261 target->type = C_REPLV ;
262 cnt = target->vcnt = source->vcnt ;
263 target->ptr = (PTR) zmalloc(cnt * sizeof(STRING *)) ;
265 t = (STRING **) target->ptr ;
266 s = (STRING **) source->ptr ;
270 if ( *s ) (*s)->ref_cnt++ ;
277 /* here's our old friend linked linear list with move to the front
278 for compilation of replacement CELLs */
280 typedef struct repl_node
282 struct repl_node *link ;
283 STRING *sval ; /* the input */
284 CELL *cp ; /* the output */
287 static REPL_NODE *repl_list ;
289 /* search the list (with move to the front) for a compiled
291 return a ptr to a CELL (C_REPL or C_REPLV)
298 register REPL_NODE *p ;
302 /* search the list */
305 q = (REPL_NODE *) 0 ;
308 if (strcmp(s, p->sval->str) == 0) /* found */
310 if (!q) /* already at front */
312 else /* delete from list for move to front */
321 q = p ; p = p->link ;
326 p = ZMALLOC(REPL_NODE) ;
329 p->cp = REPL_compile(sval) ;
332 /* insert p at the front of the list */
333 p->link = repl_list ; repl_list = p ;
337 /* return the string for a CELL or type REPL or REPLV,
338 this is only used by da() */
345 register REPL_NODE *p = repl_list ;
347 if (cp->type == C_REPL)
351 if (p->cp->type == C_REPL && p->cp->ptr == cp->ptr)
352 return p->sval->str ;
360 if (p->cp->type == C_REPLV &&
361 memcmp(cp->ptr, p->cp->ptr, cp->vcnt * sizeof(STRING *))
363 return p->sval->str ;
369 bozo("unable to uncompile an repl") ;
376 convert a C_REPLV to C_REPL
377 replacing the &s with sval
381 replv_to_repl(cp, sval)
382 CELL *cp ; STRING *sval ;
384 register STRING **p ;
385 STRING **sblock = (STRING **) cp->ptr ;
386 unsigned cnt, vcnt = cp->vcnt ;
391 if (cp->type != C_REPLV) bozo("not replv") ;
394 p = sblock ; cnt = vcnt ; len = 0 ;
397 if (*p) len += (*p++)->len ;
406 cp->ptr = (PTR) new_STRING0(len) ;
408 p = sblock ; cnt = vcnt ; target = string(cp)->str ;
411 memcpy(target, (*p)->str, (*p)->len) ;
412 target += (*p)->len ;
417 zfree(sblock, vcnt * sizeof(STRING *)) ;