home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / MAWK113.ZIP / mawk113 / split.c < prev    next >
C/C++ Source or Header  |  1992-07-08  |  6KB  |  261 lines

  1.  
  2. /********************************************
  3. split.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: split.c,v $
  14.  * Revision 5.2  1992/07/08  21:19:09  brennan
  15.  * patch2
  16.  * change in split() requires that
  17.  * bi_split() call load_array() even
  18.  * when cnt is 0.
  19.  *
  20.  * Revision 5.1  1991/12/05  07:56:31  brennan
  21.  * 1.1 pre-release
  22.  *
  23. */
  24.  
  25. /* split.c */
  26.  
  27. #define  TEMPBUFF_GOES_HERE
  28.  
  29. #include "mawk.h"
  30. #include "symtype.h"
  31. #include "bi_vars.h"
  32. #include "bi_funct.h"
  33. #include "memory.h"
  34. #include "scan.h"
  35. #include "regexp.h"
  36. #include "field.h"
  37.  
  38. SPLIT_OV  *split_ov_list ;
  39.  
  40. static  int  PROTO(re_ov_split, (char *, PTR) ) ;
  41. static  int  PROTO(space_ov_split, (char *, char *) ) ;
  42.  
  43. /* split string s of length slen on SPACE without changing s.
  44.    load the pieces into STRINGS and ptrs into
  45.    split_buff[]
  46.    return the number of pieces */
  47.  
  48. int space_split( s , slen)  
  49.   register char *s ;
  50.   unsigned slen ;
  51. { char *back = s + slen ;
  52.   int i = 0 ;
  53.   int len ;
  54.   char *q ;
  55.   STRING  *sval ;
  56.   int lcnt = MAX_SPLIT/3 ;
  57.  
  58. #define EAT_SPACE()   while ( scan_code[*(unsigned char*)s] ==\
  59.                               SC_SPACE )  s++ 
  60. #define EAT_NON_SPACE()   \
  61.     *back = ' ' ; /* sentinel */\
  62.     while ( scan_code[*(unsigned char*)s] != SC_SPACE )  s++ ;\
  63.     *back = 0 
  64.  
  65.  
  66.   while ( lcnt-- )
  67.   { 
  68.     EAT_SPACE() ;
  69.     if ( *s == 0 )  goto done ;
  70.     /* mark the front with q */
  71.     q = s++ ;
  72.     EAT_NON_SPACE() ;
  73.     sval = split_buff[i++] = new_STRING((char *) 0, len = s - q ) ;
  74.     (void) memcpy(sval->str, q, SIZE_T(len)) ;
  75.  
  76.     EAT_SPACE() ;
  77.     if ( *s == 0 )  goto done ;
  78.     q = s++ ;
  79.     EAT_NON_SPACE() ;
  80.     sval = split_buff[i++] = new_STRING((char *) 0, len = s - q ) ;
  81.     (void) memcpy(sval->str, q, SIZE_T(len)) ;
  82.  
  83.     EAT_SPACE() ;
  84.     if ( *s == 0 )  goto done ;
  85.     q = s++ ;
  86.     EAT_NON_SPACE() ;
  87.     sval = split_buff[i++] = new_STRING((char *) 0, len = s - q ) ;
  88.     (void) memcpy(sval->str, q, SIZE_T(len)) ;
  89.  
  90.   }
  91.   /* we've overflowed */
  92.   return  i + space_ov_split(s, back) ;
  93.  
  94. done:
  95.   return i ;
  96. }
  97.  
  98. static  int  space_ov_split(s, back)
  99.   register char *s ;
  100.   char *back ;
  101.  
  102. {
  103.   SPLIT_OV  dummy ;
  104.   register SPLIT_OV *tail = &dummy ;
  105.   char *q ;
  106.   int cnt = 0 ;
  107.   unsigned len ;
  108.  
  109.   while ( 1 )
  110.   {
  111.     EAT_SPACE() ;
  112.     if ( *s == 0 )  break ; /* done */
  113.     q = s++ ;
  114.     EAT_NON_SPACE() ;
  115.  
  116.     tail = tail->link = (SPLIT_OV*) zmalloc(sizeof(SPLIT_OV)) ;
  117.     tail->sval = new_STRING((char *) 0 , len = s-q) ;
  118.     (void) memcpy(tail->sval->str, q, SIZE_T(len)) ;
  119.     cnt++ ;
  120.   }
  121.  
  122.   tail->link = (SPLIT_OV*) 0 ;
  123.   split_ov_list = dummy.link ;
  124.   return cnt ;
  125. }
  126.  
  127.  
  128. char *re_pos_match(s, re, lenp)
  129.   register char *s ; 
  130.   PTR re ; unsigned *lenp ;
  131. {
  132.   while ( s = REmatch(s, re, lenp) )
  133.         if ( *lenp )   return s ;
  134.         else
  135.         if ( *s == 0 )  break ;
  136.         else s++ ;
  137.  
  138.   return (char *) 0 ;
  139. }
  140.  
  141. int re_split(s, re)
  142.   char *s ;
  143.   PTR  re ;
  144. { register char *t ;
  145.   int i = 0 ;
  146.   unsigned mlen, len ;
  147.   STRING *sval ;
  148.   int lcnt = MAX_SPLIT / 3 ;
  149.  
  150.   while ( lcnt-- )
  151.   {
  152.     if ( !(t = re_pos_match(s, re, &mlen)) )  goto done ;
  153.     sval = split_buff[i++] = new_STRING( (char *)0, len = t-s) ;
  154.     (void) memcpy(sval->str, s, SIZE_T(len)) ;
  155.     s = t + mlen ;
  156.  
  157.     if ( !(t = re_pos_match(s, re, &mlen)) )  goto done ;
  158.     sval = split_buff[i++] = new_STRING( (char *)0, len = t-s) ;
  159.     (void) memcpy(sval->str, s, SIZE_T(len)) ;
  160.     s = t + mlen ;
  161.  
  162.     if ( !(t = re_pos_match(s, re, &mlen)) )  goto done ;
  163.     sval = split_buff[i++] = new_STRING( (char *)0, len = t-s) ;
  164.     (void) memcpy(sval->str, s, SIZE_T(len)) ;
  165.     s = t + mlen ;
  166.   }
  167.   /* we've overflowed */
  168.   return  i + re_ov_split(s, re) ;
  169.  
  170. done:
  171.   split_buff[i++] = new_STRING(s) ;
  172.   return i ;
  173. }
  174.  
  175. /*
  176.   we've overflowed split_buff[] , put
  177.   the rest on the split_ov_list
  178.   return number of pieces
  179. */
  180.  
  181. static int  re_ov_split(s, re)
  182.   char *s ;
  183.   PTR  re ;
  184. {
  185.   SPLIT_OV  dummy ;
  186.   register SPLIT_OV  *tail = &dummy ;
  187.   int cnt = 1 ;
  188.   char *t ;
  189.   unsigned len, mlen ;
  190.  
  191.   while ( t = re_pos_match(s, re, &mlen) )
  192.   {
  193.     tail = tail->link = (SPLIT_OV *) zmalloc(sizeof(SPLIT_OV)) ;
  194.     tail->sval = new_STRING( (char *)0, len = t-s) ;
  195.     (void) memcpy(tail->sval->str, s, SIZE_T(len)) ;
  196.     s = t + mlen ;
  197.     cnt++ ;
  198.   }
  199.   /* and one more */
  200.   tail = tail->link = (SPLIT_OV *) zmalloc(sizeof(SPLIT_OV)) ;
  201.   tail->sval = new_STRING(s) ;
  202.   tail->link = (SPLIT_OV*) 0 ;
  203.   split_ov_list = dummy.link ;
  204.  
  205.   return cnt ;
  206. }
  207.     
  208. /*  split(s, X, r)
  209.     split s into array X on r
  210.  
  211.     entry: sp[0] holds r
  212.            sp[-1] pts at X
  213.            sp[-2] holds s
  214. */
  215. CELL *bi_split(sp)
  216.   register CELL *sp ;
  217.   int cnt ;   /* the number of pieces */
  218.  
  219.  
  220.   if ( sp->type < C_RE )  cast_for_split(sp) ;
  221.         /* can be C_RE, C_SPACE or C_SNULL */
  222.   sp -= 2 ;
  223.   if ( sp->type < C_STRING )  cast1_to_s(sp) ;
  224.  
  225.   if ( string(sp)->len == 0 ) /* nothing to split */
  226.     cnt = 0 ;
  227.   else
  228.   switch ( (sp+2)->type )
  229.   {
  230.     case C_RE :
  231.         cnt = re_split(string(sp)->str, (sp+2)->ptr) ;
  232.         break ;
  233.  
  234.     case C_SPACE :
  235.         cnt = space_split(string(sp)->str, string(sp)->len) ;
  236.         break ;
  237.  
  238.     /* this case could be done by C_RE, but very slowly.
  239.        Since it is the common way to eliminate fields,
  240.        we'll treat the special case for speed */
  241.     case C_SNULL : /* split on empty string */
  242.         cnt = 1 ;
  243.         split_buff[0] = (STRING *) sp->ptr ;
  244.         string(sp)->ref_cnt++ ;
  245.         break ;
  246.  
  247.     default : bozo("bad splitting cell in bi_split") ;
  248.   }
  249.  
  250.  
  251.   free_STRING( string(sp) ) ;
  252.   sp->type = C_DOUBLE ;
  253.   sp->dval = (double) cnt ;
  254.  
  255.   load_array((ARRAY)(sp+1)->ptr, cnt) ;
  256.  
  257.   return sp ;
  258. }
  259.  
  260.