/******************************************** re_cmpl.c copyright 1991, Michael D. Brennan This is a source file for mawk, an implementation of the AWK programming language. Mawk is distributed without warranty under the terms of the GNU General Public License, version 2, 1991. ********************************************/ /* $Log: re_cmpl.c,v $ /* Revision 1.1.1.1 1993/03/21 09:45:37 cgd /* initial import of 386bsd-0.1 sources /* * Revision 5.1 91/12/05 07:56:25 brennan * 1.1 pre-release * */ /* re_cmpl.c */ #include "mawk.h" #include "memory.h" #include "scan.h" #include "regexp.h" #include "repl.h" static CELL *PROTO( REPL_compile, (STRING *) ) ; typedef struct re_node { STRING *sval ; PTR re ; struct re_node *link ; } RE_NODE ; static RE_NODE *re_list ; /* a list of compiled regular expressions */ static char efmt[] = "regular expression compile failed (%s)\n%s" ; PTR re_compile( sval ) STRING *sval ; { register RE_NODE *p ; RE_NODE *q ; char *s ; /* search list */ s = sval->str ; p = re_list ; q = (RE_NODE *) 0 ; while ( p ) if ( strcmp(s, p->sval->str) == 0 ) /* found */ if ( !q ) /* already at front */ goto _return ; else /* delete from list for move to front */ { q->link = p->link ; goto found ; } else { q = p ; p = p->link ; } /* not found */ p = (RE_NODE *) zmalloc( sizeof(RE_NODE) ) ; p->sval = sval ; sval->ref_cnt++ ; if( !(p->re = REcompile(s)) ) if ( mawk_state == EXECUTION ) rt_error(efmt, REerrlist[REerrno] , s) ; else /* compiling */ { compile_error(efmt, REerrlist[REerrno] , s) ; return (PTR) 0 ; } found : /* insert p at the front of the list */ p->link = re_list ; re_list = p ; _return : #ifdef DEBUG if ( dump_RE ) REmprint(p->re, stderr) ; #endif return p->re ; } /* this is only used by da() */ #if ! SM_DOS char *re_uncompile( m ) PTR m ; { register RE_NODE *p ; for( p = re_list ; p ; p = p->link ) if ( p->re == m ) return p->sval->str ; #ifdef DEBUG bozo("non compiled machine") ; #endif } #endif /* not SM_DOS */ /*=================================================*/ /* replacement operations */ /* create a replacement CELL from a STRING * */ static CELL *REPL_compile( sval ) STRING *sval ; { int i = 0 ; register char *p = sval->str ; register char *q ; char *xbuff ; CELL *cp ; q = xbuff = (char *) zmalloc( sval->len + 1 ) ; while ( 1 ) { switch( *p ) { case 0 : *q = 0 ; goto done ; case '\\': if ( p[1] == '&' ) { *q++ = '&' ; p += 2 ; continue ; } else break ; case '&': /* if empty we don't need to make a node */ if ( q != xbuff ) { *q = 0 ; split_buff[i++] = new_STRING(xbuff) ; } /* and a null node for the '&' */ split_buff[i++] = (STRING *) 0 ; /* reset */ p++ ; q = xbuff ; continue ; default : break ; } *q++ = *p++ ; } done : /* if we have one empty string it will get made now */ if ( q > xbuff || i == 0 ) split_buff[i++] = new_STRING(xbuff) ; /* This will never happen */ if ( i > MAX_SPLIT ) overflow("replacement pieces", MAX_SPLIT) ; cp = new_CELL() ; if ( i == 1 ) { cp->type = C_REPL ; cp->ptr = (PTR) split_buff[0] ; } else { STRING **sp = (STRING**) (cp->ptr = zmalloc(sizeof(STRING *)*i)) ; int j = 0 ; while ( j < i ) *sp++ = split_buff[j++] ; cp->type = C_REPLV ; cp->vcnt = i ; } zfree(xbuff, sval->len+1) ; return cp ; } /* free memory used by a replacement CELL */ void repl_destroy( cp ) register CELL *cp ; { register STRING **p ; unsigned cnt ; if ( cp->type == C_REPL ) free_STRING(string(cp)) ; else /* an C_REPLV */ { p = (STRING **) cp->ptr ; for( cnt = cp->vcnt ; cnt ; cnt--) { if ( *p ) free_STRING( *p ) ; p++ ; } zfree( cp->ptr, cp->vcnt * sizeof(STRING *) ) ; } } /* copy a C_REPLV cell to another CELL */ CELL *replv_cpy( target, source ) CELL *target , *source ; { STRING **t, **s ; unsigned cnt ; target->type = C_REPLV ; target->vcnt = source->vcnt ; target->ptr = (PTR) zmalloc( target->vcnt * sizeof(STRING *) ) ; cnt = target->vcnt ; t = (STRING **) target->ptr ; s = (STRING **) source->ptr ; while ( cnt-- ) { if ( *t = *s++ ) (*t)->ref_cnt++ ; t++ ; } return target ; } /* here's our old friend linked linear list with move to the front for compilation of replacement CELLs */ typedef struct repl_node { struct repl_node *link ; STRING *sval ; /* the input */ CELL *cp ; /* the output */ } REPL_NODE ; static REPL_NODE *repl_list ; /* search the list (with move to the front) for a compiled separator. return a ptr to a CELL (C_REPL or C_REPLV) */ CELL *repl_compile( sval ) STRING *sval ; { register REPL_NODE *p ; REPL_NODE *q ; char *s ; /* search the list */ s = sval->str ; p = repl_list ; q = (REPL_NODE *) 0 ; while ( p ) if ( strcmp(s, p->sval->str) == 0 ) /* found */ if ( !q ) /* already at front */ return p->cp ; else /* delete from list for move to front */ { q->link = p->link ; goto found ; } else { q = p ; p = p->link ; } /* not found */ p = (REPL_NODE *) zmalloc( sizeof(REPL_NODE) ) ; p->sval = sval ; sval->ref_cnt++ ; p->cp = REPL_compile(sval) ; found : /* insert p at the front of the list */ p->link = repl_list ; repl_list = p ; return p->cp ; } /* return the string for a CELL or type REPL or REPLV, this is only used by da() */ #if ! SM_DOS char *repl_uncompile( cp ) CELL *cp ; { register REPL_NODE *p = repl_list ; if ( cp->type == C_REPL ) while ( p ) if ( p->cp->type == C_REPL && p->cp->ptr == cp->ptr ) return p->sval->str ; else p = p->link ; else while ( p ) if ( p->cp->type == C_REPLV && memcmp( cp->ptr, p->cp->ptr, SIZE_T(cp->vcnt * sizeof(STRING*))) == 0 ) return p->sval->str ; else p = p->link ; #if DEBUG bozo("unable to uncompile an repl") ; #endif } #endif /* ! SM_DOS */ /* convert a C_REPLV to C_REPL replacing the &s with sval */ CELL *replv_to_repl( cp, sval) CELL *cp ; STRING *sval ; { register STRING **p ; STRING **sblock = (STRING **) cp->ptr ; unsigned cnt , vcnt = cp->vcnt ; unsigned len ; char *target ; #ifdef DEBUG if ( cp->type != C_REPLV ) bozo("not replv") ; #endif p = sblock ; cnt = vcnt ; len = 0 ; while ( cnt-- ) if ( *p ) len += (*p++)->len ; else { *p++ = sval ; sval->ref_cnt++ ; len += sval->len ; } cp->type = C_REPL ; cp->ptr = (PTR) new_STRING((char *) 0, len) ; p = sblock ; cnt = vcnt ; target = string(cp)->str ; while ( cnt-- ) { (void) memcpy(target, (*p)->str, SIZE_T((*p)->len)) ; target += (*p)->len ; free_STRING(*p) ; p++ ; } zfree( sblock, vcnt * sizeof(STRING *) ) ; return cp ; }