home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 11 / AUCD11B.iso / LANGUAGES / WraithSet / AwkStuff / MawkSrc / c / field < prev    next >
Text File  |  1995-06-18  |  14KB  |  687 lines

  1.  
  2. /********************************************
  3. field.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: field.c,v $
  14.  * Revision 1.5  1995/06/18  19:17:47  mike
  15.  * Create a type Int which on most machines is an int, but on machines
  16.  * with 16bit ints, i.e., the PC is a long.  This fixes implicit assumption
  17.  * that int==long.
  18.  *
  19.  * Revision 1.4  1994/10/08  19:15:38  mike
  20.  * remove SM_DOS
  21.  *
  22.  * Revision 1.3  1993/07/14  12:32:39  mike
  23.  * run thru indent
  24.  *
  25.  * Revision 1.2     1993/07/14  12:22:11  mike
  26.  * rm SIZE_T and (void) casts
  27.  *
  28.  * Revision 1.1.1.1  1993/07/03     18:58:12  mike
  29.  * move source to cvs
  30.  *
  31.  * Revision 5.7     1993/05/08  18:06:00  mike
  32.  * null_split
  33.  *
  34.  * Revision 5.6     1993/02/13  21:57:25  mike
  35.  * merge patch3
  36.  *
  37.  * Revision 5.5     1993/01/01  21:30:48  mike
  38.  * split new_STRING() into new_STRING and new_STRING0
  39.  *
  40.  * Revision 5.4.1.2  1993/01/20     12:53:08  mike
  41.  * d_to_l()
  42.  *
  43.  * Revision 5.4.1.1  1993/01/15     03:33:42  mike
  44.  * patch3: safer double to int conversion
  45.  *
  46.  * Revision 5.4     1992/11/29  22:52:11  mike
  47.  * double->string conversions uses long ints for 16/32 bit
  48.  * compatibility.
  49.  * Fixed small LM_DOS bozo.
  50.  *
  51.  * Revision 5.3     1992/08/17  14:21:10  brennan
  52.  * patch2: After parsing, only bi_sprintf() uses string_buff.
  53.  *
  54.  * Revision 5.2     1992/07/10  16:17:10  brennan
  55.  * MsDOS: remove NO_BINMODE macro
  56.  *
  57.  * Revision 5.1     1991/12/05  07:55:57  brennan
  58.  * 1.1 pre-release
  59.  *
  60. */
  61.  
  62.  
  63. /* field.c */
  64.  
  65. #include "mawk.h"
  66. #include "field.h"
  67. #include "init.h"
  68. #include "memory.h"
  69. #include "scan.h"
  70. #include "bi_vars.h"
  71. #include "repl.h"
  72. #include "regexp.h"
  73.  
  74. CELL field[FBANK_SZ + NUM_PFIELDS] ;
  75.  
  76. CELL *fbank[NUM_FBANK] =
  77. {field} ;
  78.  
  79. static int max_field = MAX_SPLIT ;     /* maximum field actually created*/
  80.  
  81. static void PROTO(build_field0, (void)) ;
  82. static void PROTO(set_rs_shadow, (void)) ;
  83. static void PROTO(load_pfield, (char *, CELL *)) ;
  84. static void PROTO(load_field_ov, (void)) ;
  85.  
  86.  
  87.  
  88. /* a description of how to split based on RS.
  89.    If RS is changed, so is rs_shadow */
  90. SEPARATOR rs_shadow =
  91. {SEP_CHAR, '\n'} ;
  92. /* a splitting CELL version of FS */
  93. CELL fs_shadow =
  94. {C_SPACE} ;
  95. int nf ;
  96.  /* nf holds the true value of NF.  If nf < 0 , then
  97.      NF has not been computed, i.e., $0 has not been split
  98.   */
  99.  
  100. static void
  101. set_rs_shadow()
  102. {
  103.    CELL c ;
  104.    STRING *sval ;
  105.    char *s ;
  106.    unsigned len ;
  107.  
  108.    if (posix_space_flag && mawk_state == EXECUTION)
  109.       scan_code['\n'] = SC_UNEXPECTED ;
  110.  
  111.    if (rs_shadow.type == SEP_STR)
  112.       free_STRING((STRING *) rs_shadow.ptr) ;
  113.  
  114.    cast_for_split(cellcpy(&c, RS)) ;
  115.    switch (c.type)
  116.    {
  117.       case C_RE:
  118.      if (s = is_string_split(c.ptr, &len))
  119.      {
  120.         if (len == 1)
  121.         {
  122.            rs_shadow.type = SEP_CHAR ;
  123.            rs_shadow.c = s[0] ;
  124.         }
  125.         else
  126.         {
  127.            rs_shadow.type = SEP_STR ;
  128.            rs_shadow.ptr = (PTR) new_STRING(s) ;
  129.         }
  130.      }
  131.      else
  132.      {
  133.         rs_shadow.type = SEP_RE ;
  134.         rs_shadow.ptr = c.ptr ;
  135.      }
  136.      break ;
  137.  
  138.       case C_SPACE:
  139.      rs_shadow.type = SEP_CHAR ;
  140.      rs_shadow.c = ' ' ;
  141.      break ;
  142.  
  143.       case C_SNULL:        /* RS becomes one or more blank lines */
  144.      if (mawk_state == EXECUTION)  scan_code['\n'] = SC_SPACE ;
  145.      rs_shadow.type = SEP_MLR ;
  146.      sval = new_STRING("\n\n+") ;
  147.      rs_shadow.ptr = re_compile(sval) ;
  148.      free_STRING(sval) ;
  149.      break ;
  150.  
  151.       default:
  152.      bozo("bad cell in set_rs_shadow") ;
  153.    }
  154. }
  155.  
  156. static void
  157. load_pfield(name, cp)
  158.    char *name ;
  159.    CELL *cp ;
  160. {
  161.    SYMTAB *stp ;
  162.  
  163.    stp = insert(name) ; stp->type = ST_FIELD ;
  164.    stp->stval.cp = cp ;
  165. }
  166.  
  167. /* initialize $0 and the pseudo fields */
  168. void
  169. field_init()
  170. {
  171.    field[0].type = C_STRING ;
  172.    field[0].ptr = (PTR) & null_str ;
  173.    null_str.ref_cnt++ ;
  174.  
  175.    load_pfield("NF", NF) ;
  176.    NF->type = C_DOUBLE ;
  177.    NF->dval = 0.0 ;
  178.  
  179.    load_pfield("RS", RS) ;
  180.    RS->type = C_STRING ;
  181.    RS->ptr = (PTR) new_STRING("\n") ;
  182.    /* rs_shadow already set */
  183.  
  184.    load_pfield("FS", FS) ;
  185.    FS->type = C_STRING ;
  186.    FS->ptr = (PTR) new_STRING(" ") ;
  187.    /* fs_shadow is already set */
  188.  
  189.    load_pfield("OFMT", OFMT) ;
  190.    OFMT->type = C_STRING ;
  191.    OFMT->ptr = (PTR) new_STRING("%.6g") ;
  192.  
  193.    load_pfield("CONVFMT", CONVFMT) ;
  194.    CONVFMT->type = C_STRING ;
  195.    CONVFMT->ptr = OFMT->ptr ;
  196.    string(OFMT)->ref_cnt++ ;
  197. }
  198.  
  199.  
  200.  
  201. void
  202. set_field0(s, len)
  203.    char *s ;
  204.    unsigned len ;
  205. {
  206.    cell_destroy(&field[0]) ;
  207.    nf = -1 ;
  208.  
  209.    if (len)
  210.    {
  211.       field[0].type = C_MBSTRN ;
  212.       field[0].ptr = (PTR) new_STRING0(len) ;
  213.       memcpy(string(&field[0])->str, s, len) ;
  214.    }
  215.    else
  216.    {
  217.       field[0].type = C_STRING ;
  218.       field[0].ptr = (PTR) & null_str ;
  219.       null_str.ref_cnt++ ;
  220.    }
  221. }
  222.  
  223.  
  224.  
  225. /* split field[0] into $1, $2 ... and set NF  */
  226.  
  227. void
  228. split_field0()
  229. {
  230.    register CELL *cp ;
  231.    register int cnt ;
  232.    CELL c ;             /* copy field[0] here if not string */
  233.  
  234.  
  235.    if (field[0].type < C_STRING)
  236.    {
  237.       cast1_to_s(cellcpy(&c, field + 0)) ;
  238.       cp = &c ;
  239.    }
  240.    else     cp = &field[0] ;
  241.  
  242.    if (string(cp)->len == 0)  nf = 0 ;
  243.    else
  244.    {
  245.       switch (fs_shadow.type)
  246.       {
  247.      case C_SNULL:        /* FS == "" */
  248.         nf = null_split(string(cp)->str) ;
  249.         break ;
  250.  
  251.      case C_SPACE:
  252.         nf = space_split(string(cp)->str, string(cp)->len) ;
  253.         break ;
  254.  
  255.      default:
  256.         nf = re_split(string(cp)->str, fs_shadow.ptr) ;
  257.         break ;
  258.       }
  259.  
  260.    }
  261.  
  262.    cell_destroy(NF) ;
  263.    NF->type = C_DOUBLE ;
  264.    NF->dval = (double) nf ;
  265.  
  266.    if (nf > MAX_SPLIT)
  267.    {
  268.       cnt = MAX_SPLIT ; load_field_ov() ;
  269.    }
  270.    else     cnt = nf ;
  271.  
  272.    while (cnt > 0)
  273.    {
  274.       cell_destroy(field + cnt) ;
  275.       field[cnt].ptr = (PTR) split_buff[cnt - 1] ;
  276.       field[cnt--].type = C_MBSTRN ;
  277.    }
  278.  
  279.    if (cp == &c)  free_STRING(string(cp)) ;
  280. }
  281.  
  282. /*
  283.   assign CELL *cp to field or pseudo field
  284.   and take care of all side effects
  285. */
  286.  
  287. void
  288. field_assign(fp, cp)
  289.    register CELL *fp ;
  290.    CELL *cp ;
  291. {
  292.    CELL c ;
  293.    int i, j ;
  294.  
  295.    /* the most common case first */
  296.    if (fp == field)
  297.    {
  298.       cell_destroy(field) ;
  299.       cellcpy(fp, cp) ;
  300.       nf = -1 ;
  301.       return ;
  302.    }
  303.  
  304.    /* its not important to do any of this fast */
  305.  
  306.    if (nf < 0)    split_field0() ;
  307.  
  308. #ifdef  MSDOS
  309.    if (!SAMESEG(fp, field))
  310.    {
  311.       i = -1 ;
  312.       goto lm_dos_label ;
  313.    }
  314. #endif
  315.  
  316.    switch (i = (fp - field))
  317.    {
  318.  
  319.       case NF_field:
  320.  
  321.      cell_destroy(NF) ;
  322.      cellcpy(NF, cellcpy(&c, cp)) ;
  323.      if (c.type != C_DOUBLE)  cast1_to_d(&c) ;
  324.  
  325.      if ((j = d_to_i(c.dval)) < 0)
  326.         rt_error("negative value assigned to NF") ;
  327.  
  328.      if (j > nf)
  329.         for (i = nf + 1; i <= j; i++)
  330.         {
  331.            cp = field_ptr(i) ;
  332.            cell_destroy(cp) ;
  333.            cp->type = C_STRING ;
  334.            cp->ptr = (PTR) & null_str ;
  335.            null_str.ref_cnt++ ;
  336.         }
  337.  
  338.      nf = j ;
  339.      build_field0() ;
  340.      break ;
  341.  
  342.       case RS_field:
  343.      cell_destroy(RS) ;
  344.      cellcpy(RS, cp) ;
  345.      set_rs_shadow() ;
  346.      break ;
  347.  
  348.       case FS_field:
  349.      cell_destroy(FS) ;
  350.      cast_for_split(cellcpy(&fs_shadow, cellcpy(FS, cp))) ;
  351.      break ;
  352.  
  353.       case OFMT_field:
  354.       case CONVFMT_field:
  355.      /* If the user does something stupid with OFMT or CONVFMT,
  356.        we could crash.
  357.        We'll make an attempt to protect ourselves here.  This is
  358.        why OFMT and CONVFMT are pseudo fields.
  359.  
  360.        The ptrs of OFMT and CONVFMT always have a valid STRING,
  361.        even if assigned a DOUBLE or NOINIT
  362.     */
  363.  
  364.      free_STRING(string(fp)) ;
  365.      cellcpy(fp, cp) ;
  366.      if (fp->type < C_STRING)    /* !! */
  367.         fp->ptr = (PTR) new_STRING("%.6g") ;
  368.      else if (fp == CONVFMT)
  369.      {
  370.         /* It's a string, but if it's really goofy and CONVFMT,
  371.          it could still damage us. Test it .
  372.       */
  373.         char xbuff[512] ;
  374.  
  375.         xbuff[256] = 0 ;
  376.         sprintf(xbuff, string(fp)->str, 3.1459) ;
  377.         if (xbuff[256])
  378.            rt_error("CONVFMT assigned unusable value") ;
  379.      }
  380.      break ;
  381.  
  382. #ifdef MSDOS
  383.        lm_dos_label:
  384. #endif
  385.  
  386.       default:            /* $1 or $2 or ... */
  387.  
  388.  
  389.      cell_destroy(fp) ;
  390.      cellcpy(fp, cp) ;
  391.  
  392.      if (i < 0 || i > MAX_SPLIT)  i = field_addr_to_index(fp) ;
  393.  
  394.      if (i > nf)
  395.      {
  396.         for (j = nf + 1; j < i; j++)
  397.         {
  398.            cp = field_ptr(j) ;
  399.            cell_destroy(cp) ;
  400.            cp->type = C_STRING ;
  401.            cp->ptr = (PTR) & null_str ;
  402.            null_str.ref_cnt++ ;
  403.         }
  404.         nf = i ;
  405.         cell_destroy(NF) ;
  406.         NF->type = C_DOUBLE ;
  407.         NF->dval = (double) i ;
  408.      }
  409.  
  410.      build_field0() ;
  411.  
  412.    }
  413. }
  414.  
  415.  
  416. /* construct field[0] from the other fields */
  417.  
  418. static void
  419. build_field0()
  420. {
  421.  
  422.  
  423. #ifdef DEBUG
  424.    if (nf < 0)    bozo("nf <0 in build_field0") ;
  425. #endif
  426.  
  427.    cell_destroy(field + 0) ;
  428.  
  429.    if (nf == 0)
  430.    {
  431.       field[0].type = C_STRING ;
  432.       field[0].ptr = (PTR) & null_str ;
  433.       null_str.ref_cnt++ ;
  434.    }
  435.    else if (nf == 1)
  436.    {
  437.       cellcpy(field, field + 1) ;
  438.    }
  439.    else
  440.    {
  441.       CELL c ;
  442.       STRING *ofs, *tail ;
  443.       unsigned len ;
  444.       register CELL *cp ;
  445.       register char *p, *q ;
  446.       int cnt ;
  447.       CELL **fbp, *cp_limit ;
  448.  
  449.  
  450.       cast1_to_s(cellcpy(&c, OFS)) ;
  451.       ofs = (STRING *) c.ptr ;
  452.       cast1_to_s(cellcpy(&c, field_ptr(nf))) ;
  453.       tail = (STRING *) c.ptr ;
  454.       cnt = nf - 1 ;
  455.  
  456.       len = cnt * ofs->len + tail->len ;
  457.  
  458.       fbp = fbank ; cp_limit = field + FBANK_SZ ;
  459.       cp = field + 1 ;
  460.  
  461.       while (cnt-- > 0)
  462.       {
  463.      if (cp->type < C_STRING)
  464.      {            /* use the string field temporarily */
  465.         if (cp->type == C_NOINIT)
  466.         {
  467.            cp->ptr = (PTR) & null_str ;
  468.            null_str.ref_cnt++ ;
  469.         }
  470.         else  /* its a double */
  471.         {
  472.            Int ival ;
  473.            char xbuff[260] ;
  474.  
  475.            ival = d_to_I(cp->dval) ;
  476.            if (ival == cp->dval)  sprintf(xbuff, INT_FMT, ival) ;
  477.            else  sprintf(xbuff, string(CONVFMT)->str, cp->dval) ;
  478.  
  479.            cp->ptr = (PTR) new_STRING(xbuff) ;
  480.         }
  481.      }
  482.  
  483.      len += string(cp)->len ;
  484.  
  485.      if (++cp == cp_limit)
  486.      {
  487.         cp = *++fbp ;
  488.         cp_limit = cp + FBANK_SZ ;
  489.      }
  490.  
  491.       }
  492.  
  493.       field[0].type = C_STRING ;
  494.       field[0].ptr = (PTR) new_STRING0(len) ;
  495.  
  496.       p = string(field)->str ;
  497.  
  498.       /* walk it again , putting things together */
  499.       cnt = nf-1 ; fbp = fbank ;
  500.       cp = field+1 ; cp_limit = field + FBANK_SZ ;
  501.       while (cnt-- > 0)
  502.       {
  503.      memcpy(p, string(cp)->str, string(cp)->len) ;
  504.      p += string(cp)->len ;
  505.      /* if not really string, free temp use of ptr */
  506.      if (cp->type < C_STRING)  free_STRING(string(cp)) ;
  507.      if (++cp == cp_limit)
  508.      {
  509.         cp = *++fbp ;
  510.         cp_limit = cp + FBANK_SZ ;
  511.      }
  512.      /* add the separator */
  513.      q = ofs->str ;     while( *q )  *p++ = *q++ ;
  514.       }
  515.       /* tack tail on the end */
  516.       memcpy(p, tail->str, tail->len) ;
  517.  
  518.       /* cleanup */
  519.       free_STRING(tail) ; free_STRING(ofs) ;
  520.    }
  521. }
  522.  
  523. /* We are assigning to a CELL and we aren't sure if its
  524.    a field */
  525.  
  526. void
  527. slow_cell_assign(target, source)
  528.    register CELL *target ;
  529.    CELL *source ;
  530. {
  531.    if (
  532.  
  533. #ifdef MSDOS        /* the dreaded segment nonsense */
  534.      SAMESEG(target, field) &&
  535. #endif
  536.      target >= field && target <= LAST_PFIELD)
  537.       field_assign(target, source) ;
  538.    else
  539.    {
  540.       CELL **p = fbank + 1 ;
  541.  
  542.       while (*p)
  543.       {
  544.      if (
  545. #ifdef  MSDOS
  546.            SAMESEG(target, *p) &&
  547. #endif
  548.            target >= *p && target < *p + FBANK_SZ)
  549.      {
  550.         field_assign(target, source) ;
  551.         return ;
  552.      }
  553.      p++ ;
  554.       }
  555.       /* its not a field */
  556.       cell_destroy(target) ;
  557.       cellcpy(target, source) ;
  558.    }
  559. }
  560.  
  561. int
  562. field_addr_to_index(cp)
  563.    CELL *cp ;
  564. {
  565.    CELL **p = fbank ;
  566.  
  567.    while (
  568.  
  569. #ifdef MSDOS
  570.         !SAMESEG(cp, *p) ||
  571. #endif
  572.  
  573.         cp < *p || cp >= *p + FBANK_SZ)
  574.       p++ ;
  575.  
  576.    return ((p - fbank) << FB_SHIFT) + (cp - *p) ;
  577. }
  578.  
  579. /*------- more than 1 fbank needed  ------------*/
  580.  
  581. /*
  582.   compute the address of a field with index
  583.   > MAX_SPLIT
  584. */
  585.  
  586. CELL *
  587. slow_field_ptr(i)
  588.    register int i ;
  589. {
  590.  
  591.    if (i > max_field)
  592.    {
  593.       int j ;
  594.  
  595.       if (i > MAX_FIELD)
  596.      rt_overflow("maximum number of fields", MAX_FIELD) ;
  597.  
  598.       j = 1 ;
  599.       while (fbank[j])    j++ ;
  600.  
  601.       do
  602.       {
  603.      fbank[j] = (CELL *) zmalloc(sizeof(CELL) * FBANK_SZ) ;
  604.      memset(fbank[j], 0, sizeof(CELL) * FBANK_SZ) ;
  605.      j++ ;
  606.      max_field += FBANK_SZ ;
  607.       }
  608.       while (i > max_field);
  609.    }
  610.  
  611.    return &fbank[i >> FB_SHIFT][i & (FBANK_SZ - 1)] ;
  612. }
  613.  
  614. /*
  615.   $0 split into more than MAX_SPLIT fields,
  616.   $(MAX_FIELD+1) ... are on the split_ov_list.
  617.   Copy into fields which start at fbank[1]
  618. */
  619.  
  620. static void
  621. load_field_ov()
  622. {
  623.    register SPLIT_OV *p ;     /* walks split_ov_list */
  624.    register CELL *cp ;         /* target of copy */
  625.    int j ;             /* current fbank[] */
  626.    CELL *cp_limit ;         /* change fbank[] */
  627.    SPLIT_OV *q ;         /* trails p */
  628.  
  629.    /* make sure the fields are allocated */
  630.    slow_field_ptr(nf) ;
  631.  
  632.    p = split_ov_list ; split_ov_list = (SPLIT_OV*) 0 ;
  633.    j = 1 ; cp = fbank[j] ; cp_limit = cp + FBANK_SZ ;
  634.    while (p)
  635.    {
  636.       cell_destroy(cp) ;
  637.       cp->type = C_MBSTRN ;
  638.       cp->ptr = (PTR) p->sval ;
  639.  
  640.       if (++cp == cp_limit)
  641.       {
  642.      cp = fbank[++j] ; cp_limit = cp + FBANK_SZ ;
  643.       }
  644.  
  645.       q = p ; p = p->link ; ZFREE(q) ;
  646.    }
  647. }
  648.  
  649.  
  650. #if  MSDOS
  651.  
  652. int
  653. binmode()            /* read current value of BINMODE */
  654. {
  655.    CELL c ;
  656.  
  657.    cast1_to_d(cellcpy(&c, BINMODE)) ;
  658.    return d_to_i(c.dval) ;
  659. }
  660.  
  661. /* set BINMODE and RS and ORS
  662.    from environment or -W binmode=   */
  663.  
  664. void
  665. set_binmode(x)
  666.    int x ;
  667. {
  668.    CELL c ;
  669.  
  670.    /* set RS */
  671.    c.type = C_STRING ;
  672.    c.ptr = (PTR) new_STRING((x & 1) ? "\r\n" : "\n") ;
  673.    field_assign(RS, &c) ;
  674.    free_STRING(string(&c)) ;
  675.  
  676.    /* set ORS */
  677.    cell_destroy(ORS) ;
  678.    ORS->type = C_STRING ;
  679.    ORS->ptr = (PTR) new_STRING((x & 2) ? "\r\n" : "\n") ;
  680.  
  681.    cell_destroy(BINMODE) ;
  682.    BINMODE->type = C_DOUBLE ;
  683.    BINMODE->dval = (double) x ;
  684. }
  685.  
  686. #endif /* MSDOS */
  687.