home *** CD-ROM | disk | FTP | other *** search
/ BURKS 2 / BURKS_AUG97.ISO / BURKS / SOFTWARE / SOURCES / MAWK11AS.ZIP / FIELD.C (.txt) < prev    next >
C/C++ Source or Header  |  1991-12-18  |  14KB  |  608 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 5.1  91/12/05  07:55:57  brennan
  15.  * 1.1 pre-release
  16.  * 
  17. */
  18.  
  19.  
  20. /* field.c */
  21.  
  22. #include "mawk.h"
  23. #include "field.h"
  24. #include "init.h"
  25. #include "memory.h"
  26. #include "scan.h"
  27. #include "bi_vars.h"
  28. #include "repl.h"
  29. #include "regexp.h"
  30.  
  31. CELL  field[FBANK_SZ+NUM_PFIELDS] ;
  32.  
  33. CELL  *fbank[NUM_FBANK] = {field} ;
  34.  
  35. static int max_field = MAX_SPLIT ; /* maximum field actually created*/
  36.  
  37. static void PROTO( build_field0, (void) ) ;
  38. static void PROTO( set_rs_shadow, (void) ) ;
  39. static void PROTO( load_pfield, (char*, CELL*)) ;
  40. static void PROTO( load_field_ov, (void)) ;
  41.  
  42.  
  43.  
  44. /* a description of how to split based on RS.
  45.    If RS is changed, so is rs_shadow */
  46. SEPARATOR rs_shadow = {SEP_CHAR, '\n'} ;
  47. /* a splitting CELL version of FS */
  48. CELL fs_shadow = {C_SPACE} ;
  49. int   nf ;  
  50.   /* nf holds the true value of NF.  If nf < 0 , then
  51.      NF has not been computed, i.e., $0 has not been split
  52.   */
  53.  
  54. static void set_rs_shadow()
  55. { CELL c ;
  56.   STRING  *sval ;
  57.   char *s ;
  58.   unsigned len ;
  59.  
  60.   if ( posix_space_flag && mawk_state == EXECUTION ) 
  61.           scan_code['\n'] = SC_UNEXPECTED ;
  62.  
  63.   if ( rs_shadow.type == SEP_STR )  free_STRING((STRING*) rs_shadow.ptr) ;
  64.  
  65.   cast_for_split( cellcpy(&c, RS) ) ;
  66.   switch( c.type )
  67.   {
  68.     case C_RE :
  69.         if ( s = is_string_split(c.ptr, &len) )
  70.             if ( len == 1 )
  71.             { rs_shadow.type = SEP_CHAR ;
  72.               rs_shadow.c = s[0] ;
  73.             }
  74.             else
  75.             { rs_shadow.type = SEP_STR ;
  76.               rs_shadow.ptr = (PTR) new_STRING(s) ;
  77.             }
  78.         else
  79.         { rs_shadow.type = SEP_RE ;
  80.           rs_shadow.ptr = c.ptr ;
  81.         }
  82.         break ;
  83.  
  84.     case C_SPACE :
  85.         rs_shadow.type = SEP_CHAR ;
  86.         rs_shadow.c = ' ' ;
  87.         break ;
  88.  
  89.     case C_SNULL : /* RS becomes one or more blank lines */
  90.     if ( mawk_state == EXECUTION ) scan_code['\n'] = SC_SPACE ;
  91.         rs_shadow.type = SEP_MLR ;
  92.         sval = new_STRING( "\n\n+" ) ;
  93.         rs_shadow.ptr = re_compile(sval) ;
  94.         free_STRING(sval) ;
  95.         break ;
  96.  
  97.     default : bozo("bad cell in set_rs_shadow") ;
  98.   }
  99. }
  100.  
  101. static  void load_pfield(name, cp)
  102.   char *name ;
  103.   CELL *cp ;
  104. { SYMTAB *stp ;
  105.  
  106.   stp = insert(name) ; stp->type = ST_FIELD ;
  107.   stp->stval.cp = cp ;
  108. }
  109.  
  110. /* initialize $0 and the pseudo fields */
  111. void  field_init()
  112.   field[0].type = C_STRING ;
  113.   field[0].ptr = (PTR) & null_str ;
  114.   null_str.ref_cnt++ ;
  115.  
  116.   load_pfield("NF",NF) ;
  117.   NF->type = C_DOUBLE ;
  118.   NF->dval = 0.0 ;
  119.  
  120.   load_pfield("RS", RS) ;
  121.   RS->type = C_STRING ;
  122.   RS->ptr =  (PTR) new_STRING( "\n" ) ;
  123.   /* rs_shadow already set */
  124.  
  125.   load_pfield("FS", FS) ;
  126.   FS->type = C_STRING ;
  127.   FS->ptr = (PTR) new_STRING( " " ) ;
  128.   /* fs_shadow is already set */
  129.  
  130.   load_pfield("OFMT", OFMT) ;
  131.   OFMT->type = C_STRING ;
  132.   OFMT->ptr = (PTR) new_STRING( "%.6g" ) ;
  133.  
  134.   load_pfield("CONVFMT", CONVFMT) ;
  135.   CONVFMT->type = C_STRING ;
  136.   CONVFMT->ptr = OFMT->ptr ;
  137.   string(OFMT)->ref_cnt++ ;
  138. }
  139.  
  140.  
  141.  
  142. void  set_field0( s, len)
  143.   char *s ;
  144.   unsigned len ;
  145.   cell_destroy( & field[0] ) ;
  146.   nf = -1 ;
  147.  
  148.   if ( len )
  149.   {
  150.     field[0].type = C_MBSTRN ;
  151.     field[0].ptr = (PTR) new_STRING( (char *) 0, len) ;
  152.     (void) memcpy( string(&field[0])->str, s, SIZE_T(len) ) ;
  153.   }
  154.   else
  155.   {
  156.     field[0].type = C_STRING ;
  157.     field[0].ptr = (PTR) &null_str ;
  158.     null_str.ref_cnt++ ;
  159.   }
  160. }
  161.  
  162.  
  163.  
  164. /* split field[0] into $1, $2 ... and set NF  */
  165.  
  166. void  split_field0()
  167. { register CELL *cp ;
  168.   register int cnt ;
  169.   CELL  c ;  /* copy field[0] here if not string */
  170.  
  171.  
  172.   if ( field[0].type < C_STRING )
  173.   { cast1_to_s(cellcpy(&c, field+0)) ;
  174.     cp = &c ;
  175.   }
  176.   else   cp = &field[0] ;
  177.  
  178.   if ( string(cp)->len == 0 )  nf = 0 ;
  179.   else
  180.   {
  181.     switch( fs_shadow.type )
  182.     {
  183.       case   C_SNULL :  /* FS == "" */
  184.           nf = 1 ;
  185.           cell_destroy(NF) ;
  186.           NF->type = C_DOUBLE ;
  187.           NF->dval = 1.0 ;
  188.           field[1].type = C_MBSTRN ;
  189.           field[1].ptr = cp->ptr ;
  190.  
  191.           if ( cp == field )  string(cp)->ref_cnt++ ;
  192.           /* else we gain one ref_cnt and lose one for a wash */
  193.  
  194.           return ;
  195.  
  196.       case  C_SPACE :
  197.           nf = space_split(string(cp)->str, string(cp)->len) ;
  198.           break ;
  199.  
  200.       default :
  201.           nf = re_split(string(cp)->str, fs_shadow.ptr) ;
  202.           break ;
  203.     }
  204.         
  205.   }
  206.   
  207.   cell_destroy(NF) ;
  208.   NF->type = C_DOUBLE ;
  209.   NF->dval = (double) nf ;
  210.  
  211.   if ( nf > MAX_SPLIT )  
  212.   {
  213.     cnt = MAX_SPLIT ; load_field_ov() ;
  214.   }
  215.   else cnt = nf ;
  216.  
  217.   while ( cnt > 0 )
  218.   {
  219.     cell_destroy(field+cnt) ;
  220.     field[cnt].ptr = (PTR) split_buff[cnt-1] ;
  221.     field[cnt--].type = C_MBSTRN ;
  222.   }
  223.  
  224.   if ( cp == &c )  free_STRING( string(cp) ) ;
  225. }
  226.  
  227. /*
  228.   assign CELL *cp to field or pseudo field
  229.   and take care of all side effects
  230. */
  231.  
  232. void  field_assign( fp, cp)
  233.   register CELL *fp ;
  234.   CELL *cp ;
  235.   CELL c ;
  236.   int i , j ;
  237.  
  238.   /* the most common case first */
  239.   if ( fp == field )
  240.   { cell_destroy(field) ;
  241.     (void) cellcpy(fp, cp) ;
  242.     nf = -1 ;
  243.     return ;
  244.   }
  245.  
  246.   /* its not important to do any of this fast */
  247.  
  248.   if ( nf < 0 )  split_field0() ;
  249.  
  250. #if  LM_DOS
  251.   if ( !SAMESEG(fp,field) )  goto lm_dos_label ;
  252. #endif
  253.  
  254.   switch( i = (fp - field) )
  255.   {
  256.  
  257.     case  NF_field :
  258.  
  259.         cell_destroy(NF) ;
  260.         (void) cellcpy(NF, cellcpy(&c,cp) ) ;
  261.         if ( c.type != C_DOUBLE )  cast1_to_d(&c) ;
  262.  
  263.         if ( (j = (int) c.dval) < 0 )
  264.             rt_error("negative value assigned to NF") ;
  265.  
  266.         if ( j > nf )
  267.             for ( i = nf+1 ; i <= j ; i++ )
  268.             { 
  269.           cp = field_ptr(i) ;
  270.           cell_destroy(cp) ;
  271.           cp->type = C_STRING ;
  272.               cp->ptr = (PTR) &null_str ;
  273.               null_str.ref_cnt++ ;
  274.             }
  275.  
  276.         nf = j ;
  277.         build_field0() ;
  278.         break ;
  279.  
  280.     case  RS_field :
  281.         cell_destroy(RS) ;
  282.         (void) cellcpy(RS, cp) ;
  283.         set_rs_shadow() ;
  284.         break ;
  285.  
  286.     case  FS_field :
  287.         cell_destroy(FS) ;
  288.         cast_for_split( cellcpy(&fs_shadow, cellcpy(FS, cp)) ) ;
  289.         break ;
  290.  
  291.     case OFMT_field : 
  292.     case CONVFMT_field:
  293.         /* If the user does something stupid with OFMT or CONVFMT,
  294.        we could crash.
  295.            We'll make an attempt to protect ourselves here.  This is
  296.            why OFMT and CONVFMT are pseudo fields.
  297.  
  298.            The ptrs of OFMT and CONVFMT always have a valid STRING,
  299.        even if assigned a DOUBLE or NOINIT
  300.         */
  301.  
  302.         free_STRING( string(fp) ) ;
  303.         (void) cellcpy(fp, cp) ;
  304.         if ( fp->type < C_STRING ) /* !! */
  305.              fp->ptr = (PTR) new_STRING( "%.6g" ) ;
  306.         else
  307.     if ( fp == CONVFMT )
  308.         {
  309.           /* It's a string, but if it's really goofy and CONVFMT,
  310.          it could still damage us. Test it .
  311.       */
  312.           string_buff[256] = 0 ;
  313.           (void) sprintf(string_buff, 
  314.              string(fp)->str, 3.1459) ;
  315.           if ( string_buff[256] )
  316.                 rt_error("CONVFMT assigned unusable value") ;
  317.         }
  318.         break ;
  319.  
  320. #if LM_DOS
  321. lm_dos_label :
  322. #endif
  323.  
  324.     default:  /* $1 or $2 or ... */
  325.  
  326.  
  327.         cell_destroy(fp) ;
  328.         (void) cellcpy(fp, cp) ;
  329.  
  330.     if ( i < 0 || i > MAX_SPLIT ) i = field_addr_to_index(fp) ;    
  331.  
  332.         if ( i > nf )
  333.         { for ( j = nf+1 ; j < i ; j++ )
  334.           { 
  335.         cp = field_ptr(j) ;
  336.         cell_destroy(cp) ;
  337.             cp->type = C_STRING ;
  338.         cp->ptr = (PTR) &null_str ;
  339.             null_str.ref_cnt++ ;
  340.           }
  341.           nf = i ;
  342.           cell_destroy(NF) ;
  343.           NF->type = C_DOUBLE ;
  344.           NF->dval = (double) i ;
  345.         }
  346.  
  347.         build_field0() ;
  348.  
  349.   }
  350. }
  351.  
  352.  
  353. /* construct field[0] from the ot