home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / MAWK113.ZIP / mawk113 / re_cmpl.c < prev    next >
C/C++ Source or Header  |  1991-12-04  |  7KB  |  335 lines

  1.  
  2. /********************************************
  3. re_cmpl.c
  4. copyright 1991, Michael D. Brennan
  5.  
  6. This is a source file for mawk, an implementation of
  7. the AWK programming language.
  8.  
  9. Mawk is distributed without warranty under the terms of
  10. the GNU General Public License, version 2, 1991.
  11. ********************************************/
  12.  
  13. /* $Log: re_cmpl.c,v $
  14.  * Revision 5.1  1991/12/05  07:56:25  brennan
  15.  * 1.1 pre-release
  16.  *
  17. */
  18.  
  19.  
  20. /*  re_cmpl.c  */
  21.  
  22. #include "mawk.h"
  23. #include "memory.h"
  24. #include "scan.h"
  25. #include "regexp.h"
  26. #include "repl.h"
  27.  
  28.  
  29. static  CELL *PROTO( REPL_compile, (STRING *) ) ;
  30.  
  31. typedef struct re_node {
  32. STRING  *sval ;
  33. PTR     re ;
  34. struct re_node *link ;
  35. }  RE_NODE ;
  36.  
  37. static RE_NODE *re_list ;  /* a list of compiled regular expressions */
  38.  
  39. static char efmt[] = "regular expression compile failed (%s)\n%s" ;
  40.  
  41. PTR re_compile( sval )
  42.   STRING *sval ;
  43. { register RE_NODE *p ;
  44.   RE_NODE *q ;
  45.   char *s ;
  46.  
  47.   /* search list */
  48.   s = sval->str ;
  49.   p = re_list ;
  50.   q = (RE_NODE *) 0 ;
  51.   while ( p )
  52.     if ( strcmp(s, p->sval->str) == 0 )  /* found */
  53.         if ( !q ) /* already at front */  goto _return ;
  54.         else /* delete from list for move to front */
  55.         { q->link = p->link ; goto found ; }
  56.     else
  57.     { q = p ; p = p->link ; }
  58.  
  59.   /* not found */
  60.   p = (RE_NODE *) zmalloc( sizeof(RE_NODE) ) ;
  61.   p->sval = sval ;
  62.  
  63.   sval->ref_cnt++ ;
  64.   if( !(p->re = REcompile(s)) )
  65.         if ( mawk_state == EXECUTION )
  66.             rt_error(efmt, REerrlist[REerrno] , s) ;
  67.         else /* compiling */
  68.         { compile_error(efmt, REerrlist[REerrno] , s) ;
  69.           return (PTR) 0 ;
  70.         }
  71.  
  72.  
  73. found :
  74. /* insert p at the front of the list */
  75.   p->link = re_list ; re_list = p ;
  76.  
  77. _return :
  78.   
  79. #ifdef  DEBUG
  80.   if ( dump_RE )  REmprint(p->re, stderr) ;
  81. #endif
  82.   return p->re ;
  83. }
  84.  
  85.  
  86.  
  87. /* this is only used by da() */
  88.  
  89. #if  ! SM_DOS
  90.  
  91. char *re_uncompile( m )
  92.   PTR  m ;
  93. { register RE_NODE *p ;
  94.  
  95.   for( p = re_list ; p ; p = p->link )
  96.         if ( p->re == m )  return  p->sval->str ;
  97. #ifdef  DEBUG
  98.   bozo("non compiled machine") ;
  99. #endif
  100. }
  101. #endif /* not SM_DOS */
  102.   
  103.  
  104.  
  105. /*=================================================*/
  106. /*  replacement  operations   */
  107.  
  108. /* create a replacement CELL from a STRING *  */
  109.  
  110. static CELL *REPL_compile( sval )
  111.   STRING  *sval ;
  112. { int i = 0 ;
  113.   register char *p = sval->str ;
  114.   register char *q ;
  115.   char *xbuff ;
  116.   CELL *cp ;
  117.  
  118.   q = xbuff = (char *) zmalloc( sval->len + 1 ) ;
  119.  
  120.   while ( 1 )
  121.   {
  122.       switch( *p )
  123.       {
  124.         case  0  :  *q = 0 ;
  125.                     goto  done  ;
  126.  
  127.         case  '\\':
  128.                 if ( p[1] == '&' )
  129.                 { *q++ = '&' ; p += 2 ; continue ; }
  130.                 else  break ;
  131.  
  132.         case  '&':
  133.                 /* if empty we don't need to make a node */
  134.                 if ( q != xbuff )
  135.                 { *q = 0 ;
  136.                   split_buff[i++] = new_STRING(xbuff) ;
  137.                 }
  138.                 /* and a null node for the '&'  */
  139.                 split_buff[i++] = (STRING *) 0  ;
  140.                 /*  reset  */
  141.                 p++ ;  q = xbuff ;
  142.                 continue ;
  143.  
  144.         default :
  145.                 break ;
  146.       }
  147.  
  148.       *q++ = *p++ ;
  149.   }
  150.  
  151. done :   
  152.   /* if we have one empty string it will get made now */
  153.   if ( q > xbuff || i == 0 )
  154.           split_buff[i++] =  new_STRING(xbuff) ;
  155.  
  156.   /* This will never happen */
  157.   if ( i > MAX_SPLIT )
  158.       overflow("replacement pieces", MAX_SPLIT) ;
  159.  
  160.   cp = new_CELL() ;
  161.   if ( i == 1 )
  162.   {
  163.     cp->type = C_REPL ;
  164.     cp->ptr = (PTR) split_buff[0] ;
  165.   }
  166.   else
  167.   {
  168.     STRING **sp = (STRING**)
  169.                   (cp->ptr = zmalloc(sizeof(STRING *)*i)) ;
  170.     int j = 0 ;
  171.  
  172.     while ( j < i ) *sp++ = split_buff[j++] ;
  173.  
  174.     cp->type = C_REPLV ;
  175.     cp->vcnt = i ;
  176.   }
  177.   zfree(xbuff, sval->len+1) ;
  178.   return cp ;
  179. }
  180.  
  181. /* free memory used by a replacement CELL  */
  182.  
  183. void  repl_destroy( cp )
  184.   register CELL *cp ;
  185. { register STRING **p ;
  186.   unsigned cnt ;
  187.  
  188.   if ( cp->type == C_REPL )  free_STRING(string(cp)) ;
  189.   else  /* an C_REPLV  */
  190.   {
  191.     p = (STRING **) cp->ptr ;
  192.     for( cnt = cp->vcnt ; cnt ; cnt--) 
  193.     {
  194.       if ( *p ) free_STRING( *p ) ;
  195.       p++ ;
  196.     }
  197.     zfree( cp->ptr, cp->vcnt * sizeof(STRING *) ) ;
  198.   }
  199. }
  200.  
  201. /* copy a C_REPLV cell to another CELL */
  202.  
  203. CELL  *replv_cpy( target, source )
  204.   CELL *target , *source ;
  205. { STRING **t, **s ;
  206.   unsigned cnt ;
  207.  
  208.   target->type = C_REPLV ;
  209.   target->vcnt = source->vcnt ;
  210.  
  211.   target->ptr = (PTR) zmalloc( target->vcnt * sizeof(STRING *) ) ;
  212.   cnt = target->vcnt ;
  213.   t = (STRING **) target->ptr ;
  214.   s = (STRING **) source->ptr ;
  215.   while ( cnt-- )
  216.   { 
  217.     if ( *t = *s++ )   (*t)->ref_cnt++ ;
  218.     t++ ;
  219.   }
  220.   return target ;
  221. }
  222.  
  223. /* here's our old friend linked linear list with move to the front
  224.    for compilation of replacement CELLs  */
  225.  
  226. typedef  struct repl_node {
  227.   struct repl_node  *link ;
  228.   STRING  *sval  ;  /* the input */
  229.   CELL    *cp ;  /* the output */
  230. }  REPL_NODE  ;
  231.  
  232. static  REPL_NODE  *repl_list ;
  233.  
  234. /* search the list (with move to the front) for a compiled
  235.    separator.
  236.    return a ptr to a CELL (C_REPL or C_REPLV)
  237. */
  238.  
  239. CELL *repl_compile( sval )
  240.   STRING *sval ;
  241. { register REPL_NODE *p ;
  242.   REPL_NODE *q ;
  243.   char *s ;
  244.  
  245.   /* search the list */
  246.   s = sval->str ;
  247.   p = repl_list ;
  248.   q = (REPL_NODE *) 0 ;
  249.   while ( p )
  250.     if ( strcmp(s, p->sval->str) == 0 )  /* found */
  251.         if ( !q ) /* already at front */  return p->cp ;
  252.         else /* delete from list for move to front */
  253.         { q->link = p->link ; goto found ; }
  254.     else
  255.     { q = p ; p = p->link ; }
  256.  
  257.   /* not found */
  258.   p = (REPL_NODE *) zmalloc( sizeof(REPL_NODE) ) ;
  259.   p->sval = sval ;
  260.   sval->ref_cnt++ ;
  261.   p->cp = REPL_compile(sval) ;
  262.  
  263. found :
  264. /* insert p at the front of the list */
  265.   p->link = repl_list ; repl_list = p ;
  266.   return p->cp ;
  267. }
  268.  
  269. /* return the string for a CELL or type REPL or REPLV,
  270.    this is only used by da()  */
  271.  
  272. #if  ! SM_DOS
  273.  
  274. char *repl_uncompile( cp )
  275.   CELL *cp ;
  276. {
  277.   register REPL_NODE *p = repl_list ;
  278.  
  279.   if ( cp->type == C_REPL )
  280.     while ( p )
  281.       if ( p->cp->type == C_REPL &&
  282.            p->cp->ptr  == cp->ptr )   return p->sval->str ;
  283.       else  p = p->link ;
  284.   else
  285.     while ( p )
  286.       if ( p->cp->type == C_REPLV &&
  287.            memcmp( cp->ptr, p->cp->ptr, SIZE_T(cp->vcnt * sizeof(STRING*))) 
  288.            == 0  )   return  p->sval->str ;
  289.       else  p = p->link ;
  290.  
  291. #if  DEBUG
  292.   bozo("unable to uncompile an repl") ;
  293. #endif
  294. }
  295. #endif /* ! SM_DOS */
  296.  
  297. /*
  298.   convert a C_REPLV to  C_REPL
  299.      replacing the &s with sval
  300. */
  301.  
  302. CELL  *replv_to_repl( cp, sval)
  303.   CELL *cp ; STRING *sval ;
  304. { register STRING **p ;
  305.   STRING **sblock = (STRING **) cp->ptr ;
  306.   unsigned cnt , vcnt = cp->vcnt ;
  307.   unsigned len ;
  308.   char *target ;
  309.  
  310. #ifdef  DEBUG
  311.   if ( cp->type != C_REPLV ) bozo("not replv") ;
  312. #endif
  313.  
  314.   p = sblock ; cnt = vcnt ; len = 0 ;
  315.   while ( cnt-- )
  316.       if ( *p )  len += (*p++)->len ;
  317.       else
  318.       { *p++ = sval ; sval->ref_cnt++ ; len += sval->len ; }
  319.  
  320.   cp->type = C_REPL ;
  321.   cp->ptr = (PTR) new_STRING((char *) 0, len) ;
  322.  
  323.   p = sblock ; cnt = vcnt ; target = string(cp)->str ;
  324.   while ( cnt-- )
  325.   { (void) memcpy(target, (*p)->str, SIZE_T((*p)->len)) ;
  326.     target += (*p)->len ;
  327.     free_STRING(*p) ;
  328.     p++ ;
  329.   }
  330.  
  331.   zfree( sblock, vcnt * sizeof(STRING *) ) ;
  332.   return cp ;
  333. }
  334.  
  335.