@@ -1888,6 +1888,26 @@ generate_EXECCONCAT(cctx_T *cctx, int count)
18881888 return OK ;
18891889}
18901890
1891+ /*
1892+ * Generate ISN_RANGE. Consumes "range". Return OK/FAIL.
1893+ */
1894+ static int
1895+ generate_RANGE (cctx_T * cctx , char_u * range )
1896+ {
1897+ isn_T * isn ;
1898+ garray_T * stack = & cctx -> ctx_type_stack ;
1899+
1900+ if ((isn = generate_instr (cctx , ISN_RANGE )) == NULL )
1901+ return FAIL ;
1902+ isn -> isn_arg .string = range ;
1903+
1904+ if (ga_grow (stack , 1 ) == FAIL )
1905+ return FAIL ;
1906+ ((type_T * * )stack -> ga_data )[stack -> ga_len ] = & t_number ;
1907+ ++ stack -> ga_len ;
1908+ return OK ;
1909+ }
1910+
18911911 static int
18921912generate_UNPACK (cctx_T * cctx , int var_count , int semicolon )
18931913{
@@ -7098,6 +7118,22 @@ compile_mult_expr(char_u *arg, int cmdidx, cctx_T *cctx)
70987118 return p ;
70997119}
71007120
7121+ /*
7122+ * If "eap" has a range that is not a contstant generate an ISN_RANGE
7123+ * instruction to compute it and return OK.
7124+ * Otherwise return FAIL, the caller must deal with any range.
7125+ */
7126+ static int
7127+ compile_variable_range (exarg_T * eap , cctx_T * cctx )
7128+ {
7129+ char_u * range_end = skip_range (eap -> cmd , TRUE, NULL );
7130+ char_u * p = skipdigits (eap -> cmd );
7131+
7132+ if (p == range_end )
7133+ return FAIL ;
7134+ return generate_RANGE (cctx , vim_strnsave (eap -> cmd , range_end - eap -> cmd ));
7135+ }
7136+
71017137/*
71027138 * :put r
71037139 * :put ={expr}
@@ -7123,17 +7159,23 @@ compile_put(char_u *arg, exarg_T *eap, cctx_T *cctx)
71237159 else if (eap -> regname != NUL )
71247160 ++ line ;
71257161
7126- // "errormsg" will not be set because the range is ADDR_LINES.
7127- // TODO: if the range contains something like "$" or "." need to evaluate
7128- // at runtime
7129- if (parse_cmd_address (eap , & errormsg , FALSE) == FAIL )
7130- return NULL ;
7131- if (eap -> addr_count == 0 )
7132- lnum = -1 ;
7162+ if (compile_variable_range (eap , cctx ) == OK )
7163+ {
7164+ lnum = above ? LNUM_VARIABLE_RANGE_ABOVE : LNUM_VARIABLE_RANGE ;
7165+ }
71337166 else
7134- lnum = eap -> line2 ;
7135- if (above )
7136- -- lnum ;
7167+ {
7168+ // Either no range or a number.
7169+ // "errormsg" will not be set because the range is ADDR_LINES.
7170+ if (parse_cmd_address (eap , & errormsg , FALSE) == FAIL )
7171+ return NULL ;
7172+ if (eap -> addr_count == 0 )
7173+ lnum = -1 ;
7174+ else
7175+ lnum = eap -> line2 ;
7176+ if (above )
7177+ -- lnum ;
7178+ }
71377179
71387180 generate_PUT (cctx , eap -> regname , lnum );
71397181 return line ;
@@ -7960,6 +8002,7 @@ delete_instr(isn_T *isn)
79608002 case ISN_PUSHEXC :
79618003 case ISN_PUSHFUNC :
79628004 case ISN_PUSHS :
8005+ case ISN_RANGE :
79638006 case ISN_STOREB :
79648007 case ISN_STOREENV :
79658008 case ISN_STOREG :
0 commit comments