home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 11 / AUCD11B.iso / LANGUAGES / WraithSet / AwkStuff / MawkSrc / c / split < prev    next >
Text File  |  1996-02-01  |  7KB  |  336 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 1.3  1996/02/01  04:39:42  mike
  15.  * dynamic array scheme
  16.  *
  17.  * Revision 1.2  1993/07/15  01:55:03  mike
  18.  * rm SIZE_T & indent
  19.  *
  20.  * Revision 1.1.1.1  1993/07/03     18:58:21  mike
  21.  * move source to cvs
  22.  *
  23.  * Revision 5.4     1993/05/08  18:06:00  mike
  24.  * null_split
  25.  *
  26.  * Revision 5.3     1993/01/01  21:30:48  mike
  27.  * split new_STRING() into new_STRING and new_STRING0
  28.  *
  29.  * Revision 5.2     1992/07/08  21:19:09  brennan
  30.  * patch2
  31.  * change in split() requires that
  32.  * bi_split() call load_array() even
  33.  * when cnt is 0.
  34.  *
  35.  * Revision 5.1     1991/12/05  07:56:31  brennan
  36.  * 1.1 pre-release
  37.  *
  38. */
  39.  
  40. /* split.c */
  41.  
  42.  
  43. /* For all splitting up to MAX_SPLIT fields go into
  44.    split_buff[], the rest go onto split_ov_list ( split
  45.    overflow list)
  46.  
  47.    We can split one of three ways:
  48.      (1) By space:
  49.      space_split() and space_ov_split()
  50.      (2) By regular expression:
  51.      re_split()    and re_ov_split()
  52.      (3) By "" (null -- split into characters)
  53.      null_split() and null_ov_split()
  54. */
  55.  
  56. #define     TEMPBUFF_GOES_HERE
  57.  
  58. #include "mawk.h"
  59. #include "symtype.h"
  60. #include "bi_vars.h"
  61. #include "bi_funct.h"
  62. #include "memory.h"
  63. #include "scan.h"
  64. #include "regexp.h"
  65. #include "field.h"
  66.  
  67. SPLIT_OV *split_ov_list ;
  68.  
  69. static int PROTO(re_ov_split, (char *, PTR)) ;
  70. static int PROTO(space_ov_split, (char *, char *)) ;
  71. static int PROTO(null_ov_split, (char *)) ;
  72.  
  73. /* split string s of length slen on SPACE without changing s.
  74.    load the pieces into STRINGS and ptrs into
  75.    split_buff[]
  76.    return the number of pieces */
  77.  
  78. int
  79. space_split(s, slen)
  80.    register char *s ;
  81.    unsigned slen ;
  82. {
  83.    char *back = s + slen ;
  84.    int i = 0 ;
  85.    int len ;
  86.    char *q ;
  87.    STRING *sval ;
  88.    int lcnt = MAX_SPLIT / 3 ;
  89.  
  90. #define EAT_SPACE()   while ( scan_code[*(unsigned char*)s] ==\
  91.                   SC_SPACE )  s++
  92. #define EAT_NON_SPACE()      \
  93.     *back = ' ' ; /* sentinel */\
  94.     while ( scan_code[*(unsigned char*)s] != SC_SPACE )     s++ ;\
  95.     *back = 0
  96.  
  97.  
  98.    while (lcnt--)
  99.    {
  100.       EAT_SPACE() ;
  101.       if (*s == 0)  goto done ;
  102.       /* mark the front with q */
  103.       q = s++ ;
  104.       EAT_NON_SPACE() ;
  105.       sval = split_buff[i++] = new_STRING0(len = s - q) ;
  106.       memcpy(sval->str, q, len) ;
  107.  
  108.       EAT_SPACE() ;
  109.       if (*s == 0)  goto done ;
  110.       q = s++ ;
  111.       EAT_NON_SPACE() ;
  112.       sval = split_buff[i++] = new_STRING0(len = s - q) ;
  113.       memcpy(sval->str, q, len) ;
  114.  
  115.       EAT_SPACE() ;
  116.       if (*s == 0)  goto done ;
  117.       q = s++ ;
  118.       EAT_NON_SPACE() ;
  119.       sval = split_buff[i++] = new_STRING0(len = s - q) ;
  120.       memcpy(sval->str, q, len) ;
  121.  
  122.    }
  123.    /* we've overflowed */
  124.    return i + space_ov_split(s, back) ;
  125.  
  126.  done:
  127.    return i ;
  128. }
  129.  
  130. static int
  131. space_ov_split(s, back)
  132.    register char *s ;
  133.    char *back ;
  134.  
  135. {
  136.    SPLIT_OV dummy ;
  137.    register SPLIT_OV *tail = &dummy ;
  138.    char *q ;
  139.    int cnt = 0 ;
  140.    unsigned len ;
  141.  
  142.    while (1)
  143.    {
  144.       EAT_SPACE() ;
  145.       if (*s == 0)  break ;            /* done */
  146.       q = s++ ;
  147.       EAT_NON_SPACE() ;
  148.  
  149.       tail = tail->link = ZMALLOC(SPLIT_OV) ;
  150.       tail->sval = new_STRING0(len = s - q) ;
  151.       memcpy(tail->sval->str, q, len) ;
  152.       cnt++ ;
  153.    }
  154.  
  155.    tail->link = (SPLIT_OV *) 0 ;
  156.    split_ov_list = dummy.link ;
  157.    return cnt ;
  158. }
  159.  
  160. /* match a string with a regular expression, but
  161.    only matches of positive length count */
  162. char *
  163. re_pos_match(s, re, lenp)
  164.    register char *s ;
  165. PTR re ; unsigned *lenp ;
  166. {
  167.    while (s = REmatch(s, re, lenp))
  168.       if (*lenp)  return s ;
  169.       else if (*s == 0)     break ;
  170.       else  s++ ;
  171.  
  172.    return (char *) 0 ;
  173. }
  174.  
  175. int
  176. re_split(s, re)
  177.    char *s ;
  178.    PTR re ;
  179. {
  180.    register char *t ;
  181.    int i = 0 ;
  182.    unsigned mlen, len ;
  183.    STRING *sval ;
  184.    int lcnt = MAX_SPLIT / 3 ;
  185.  
  186.    while (lcnt--)
  187.    {
  188.       if (!(t = re_pos_match(s, re, &mlen)))  goto done ;
  189.       sval = split_buff[i++] = new_STRING0(len = t - s) ;
  190.       memcpy(sval->str, s, len) ;
  191.       s = t + mlen ;
  192.  
  193.       if (!(t = re_pos_match(s, re, &mlen)))  goto done ;
  194.       sval = split_buff[i++] = new_STRING0(len = t - s) ;
  195.       memcpy(sval->str, s, len) ;
  196.       s = t + mlen ;
  197.  
  198.       if (!(t = re_pos_match(s, re, &mlen)))  goto done ;
  199.       sval = split_buff[i++] = new_STRING0(len = t - s) ;
  200.       memcpy(sval->str, s, len) ;
  201.       s = t + mlen ;
  202.    }
  203.    /* we've overflowed */
  204.    return i + re_ov_split(s, re) ;
  205.  
  206. done:
  207.    split_buff[i++] = new_STRING(s) ;
  208.    return i ;
  209. }
  210.  
  211. /*
  212.   we've overflowed split_buff[] , put
  213.   the rest on the split_ov_list
  214.   return number of pieces
  215. */
  216.  
  217. static int
  218. re_ov_split(s, re)
  219.    char *s ;
  220.    PTR re ;
  221. {
  222.    SPLIT_OV dummy ;
  223.    register SPLIT_OV *tail = &dummy ;
  224.    int cnt = 1 ;
  225.    char *t ;
  226.    unsigned len, mlen ;
  227.  
  228.    while (t = re_pos_match(s, re, &mlen))
  229.    {
  230.       tail = tail->link = ZMALLOC(SPLIT_OV) ;
  231.       tail->sval = new_STRING0(len = t - s) ;
  232.       memcpy(tail->sval->str, s, len) ;
  233.       s = t + mlen ;
  234.       cnt++ ;
  235.    }
  236.    /* and one more */
  237.    tail = tail->link = ZMALLOC(SPLIT_OV) ;
  238.    tail->sval = new_STRING(s) ;
  239.    tail->link = (SPLIT_OV *) 0 ;
  240.    split_ov_list = dummy.link ;
  241.  
  242.    return cnt ;
  243. }
  244.  
  245.  
  246. int
  247. null_split(s)
  248.    char *s ;
  249. {
  250.    int cnt = 0 ;         /* number of fields split */
  251.    STRING *sval ;
  252.    int i = 0 ;             /* indexes split_buff[] */
  253.  
  254.    while (*s)
  255.    {
  256.       if (cnt == MAX_SPLIT)  return cnt + null_ov_split(s) ;
  257.  
  258.       sval = new_STRING0(1) ;
  259.       sval->str[0] = *s++ ;
  260.       split_buff[i++] = sval ;
  261.       cnt++ ;
  262.    }
  263.    return cnt ;
  264. }
  265.  
  266. static int
  267. null_ov_split(s)
  268.    char *s ;
  269. {
  270.    SPLIT_OV dummy ;
  271.    SPLIT_OV *ovp = &dummy ;
  272.    int cnt = 0 ;
  273.  
  274.    while (*s)
  275.    {
  276.       ovp = ovp->link = ZMALLOC(SPLIT_OV) ;
  277.       ovp->sval = new_STRING0(1) ;
  278.       ovp->sval->str[0] = *s++ ;
  279.       cnt++ ;
  280.    }
  281.    ovp->link = (SPLIT_OV *) 0 ;
  282.    split_ov_list = dummy.link ;
  283.    return cnt ;
  284. }
  285.  
  286.  
  287. /*  split(s, X, r)
  288.     split s into array X on r
  289.  
  290.     entry: sp[0] holds r
  291.        sp[-1] pts at X
  292.        sp[-2] holds s
  293. */
  294. CELL *
  295. bi_split(sp)
  296.    register CELL *sp ;
  297. {
  298.    int cnt ;             /* the number of pieces */
  299.  
  300.  
  301.    if (sp->type < C_RE)     cast_for_split(sp) ;
  302.    /* can be C_RE, C_SPACE or C_SNULL */
  303.    sp -= 2 ;
  304.    if (sp->type < C_STRING)  cast1_to_s(sp) ;
  305.  
  306.    if (string(sp)->len == 0)    /* nothing to split */
  307.       cnt = 0 ;
  308.    else
  309.       switch ((sp + 2)->type)
  310.       {
  311.      case C_RE:
  312.         cnt = re_split(string(sp)->str, (sp + 2)->ptr) ;
  313.         break ;
  314.  
  315.      case C_SPACE:
  316.         cnt = space_split(string(sp)->str, string(sp)->len) ;
  317.         break ;
  318.  
  319.      case C_SNULL:        /* split on empty string */
  320.         cnt = null_split(string(sp)->str) ;
  321.         break ;
  322.  
  323.      default:
  324.         bozo("bad splitting cell in bi_split") ;
  325.       }
  326.  
  327.  
  328.    free_STRING(string(sp)) ;
  329.    sp->type = C_DOUBLE ;
  330.    sp->dval = (double) cnt ;
  331.  
  332.    array_load((ARRAY) (sp + 1)->ptr, cnt) ;
  333.  
  334.    return sp ;
  335. }
  336.