@@ -2239,10 +2239,10 @@ fetchvalue(Value v, char **pptr, int bracks, int flags)
22392239 }
22402240 Param p1 = (Param )gethashnode2 (paramtab , ref );
22412241 if (p1 ) {
2242- int scope = (( pm -> node .flags & PM_NAMEREF ) ?
2243- (( pm -> node . flags & PM_UPPER ) ? - ( pm -> base ) :
2244- pm -> base ) : locallevel );
2245- pm = upscope (p1 , scope );
2242+ if ( pm -> node .flags & PM_UPPER )
2243+ pm = upscope_upper ( p1 , pm -> level - 1 );
2244+ else
2245+ pm = upscope (p1 , pm -> base );
22462246 pm = (Param )loadparamnode (paramtab , pm , ref );
22472247 }
22482248 if (!(p1 && pm ) ||
@@ -3324,7 +3324,11 @@ assignsparam(char *s, char *val, int flags)
33243324 }
33253325 }
33263326
3327+ if (v -> pm -> node .flags & PM_NAMEREF )
3328+ v -> pm -> node .flags |= PM_NEWREF ;
33273329 assignstrvalue (v , val , flags );
3330+ if (v -> pm -> node .flags & PM_NAMEREF )
3331+ v -> pm -> node .flags &= ~PM_NEWREF ;
33283332 unqueue_signals ();
33293333 return v -> pm ;
33303334}
@@ -6314,12 +6318,13 @@ resolve_nameref(Param pm, const Asgment stop)
63146318 } else if ((hn = gethashnode2 (realparamtab , seek ))) {
63156319 if (pm ) {
63166320 if (!(stop && (stop -> flags & (PM_LOCAL )))) {
6317- int scope = ((pm -> node .flags & PM_NAMEREF ) ?
6318- ((pm -> node .flags & PM_UPPER ) ?
6319- /* pm->base == 0 means not set yet */
6320- - (pm -> base ? pm -> base : pm -> level ) :
6321- pm -> base ) : ((Param )hn )-> level );
6322- hn = (HashNode )upscope ((Param )hn , scope );
6321+ if ((pm -> node .flags & PM_NAMEREF ) &&
6322+ (pm -> node .flags & PM_UPPER ))
6323+ hn = (HashNode )upscope_upper ((Param )hn , pm -> level - 1 );
6324+ else
6325+ hn = (HashNode )upscope ((Param )hn ,
6326+ (pm -> node .flags & PM_NAMEREF ) ?
6327+ (pm -> base ) : ((Param )hn )-> level );
63236328 }
63246329 hn = loadparamnode (paramtab , (Param )hn , seek );
63256330 /* user can't tag a nameref, safe for loop detection */
@@ -6374,24 +6379,44 @@ setscope(Param pm)
63746379 char * t = refname ? itype_end (refname , INAMESPC , 0 ) : NULL ;
63756380 int q = queue_signal_level ();
63766381
6382+ /* Compute pm->width */
63776383 /* Temporarily change nameref to array parameter itself */
63786384 if (t && * t == '[' )
63796385 * t = 0 ;
63806386 else
63816387 t = 0 ;
6382- stop .name = "" ;
6388+ if (t ) {
6389+ pm -> width = t - refname ;
6390+ * t = '[' ;
6391+ refname = dupstrpfx (refname , pm -> width );
6392+ }
6393+
6394+ /* Compute pm->base */
6395+ if (!(pm -> node .flags & PM_UPPER ) && refname &&
6396+ (basepm = (Param )gethashnode2 (realparamtab , refname )) &&
6397+ (basepm = (Param )loadparamnode (realparamtab , basepm , refname )) &&
6398+ (!(basepm -> node .flags & PM_NEWREF ) || (basepm = basepm -> old ))) {
6399+ pm -> base = basepm -> level ;
6400+ }
6401+ if (pm -> base > pm -> level ) {
6402+ if (EMULATION (EMULATE_KSH )) {
6403+ zerr ("%s: global reference cannot refer to local variable" ,
6404+ pm -> node .nam );
6405+ unsetparam_pm (pm , 0 , 1 );
6406+ } else if (isset (WARNNESTEDVAR ))
6407+ zwarn ("reference %s in enclosing scope set to local variable %s" ,
6408+ pm -> node .nam , refname );
6409+ }
6410+
6411+ /* Check for self references */
6412+ stop .name = pm -> node .nam ;
63836413 stop .value .scalar = NULL ;
63846414 stop .flags = PM_NAMEREF ;
63856415 if (locallevel && !(pm -> node .flags & PM_UPPER ))
63866416 stop .flags |= PM_LOCAL ;
63876417 dont_queue_signals (); /* Prevent unkillable loops */
63886418 basepm = (Param )resolve_nameref (pm , & stop );
63896419 restore_queue_signals (q );
6390- if (t ) {
6391- pm -> width = t - refname ;
6392- * t = '[' ;
6393- refname = dupstrpfx (refname , pm -> width );
6394- }
63956420 if (basepm ) {
63966421 if (basepm -> node .flags & PM_NAMEREF ) {
63976422 if (pm == basepm ) {
@@ -6419,27 +6444,7 @@ setscope(Param pm)
64196444 break ;
64206445 }
64216446 }
6422- } else if (!pm -> base ) {
6423- pm -> base = basepm -> level ;
6424- if ((pm -> node .flags & PM_UPPER ) &&
6425- (basepm = upscope (basepm , - (pm -> level ))))
6426- pm -> base = basepm -> level ;
64276447 }
6428- } else if (pm -> base < locallevel && refname &&
6429- (basepm = (Param )getparamnode (realparamtab , refname ))) {
6430- pm -> base = basepm -> level ;
6431- if ((pm -> node .flags & PM_UPPER ) &&
6432- (basepm = upscope (basepm , - (pm -> level ))))
6433- pm -> base = basepm -> level ;
6434- }
6435- if (pm -> base > pm -> level ) {
6436- if (EMULATION (EMULATE_KSH )) {
6437- zerr ("%s: global reference cannot refer to local variable" ,
6438- pm -> node .nam );
6439- unsetparam_pm (pm , 0 , 1 );
6440- } else if (isset (WARNNESTEDVAR ))
6441- zwarn ("reference %s in enclosing scope set to local variable %s" ,
6442- pm -> node .nam , refname );
64436448 }
64446449 if (refname && upscope (pm , pm -> base ) == pm &&
64456450 strcmp (pm -> node .nam , refname ) == 0 ) {
@@ -6456,13 +6461,18 @@ upscope(Param pm, int reflevel)
64566461{
64576462 Param up = pm -> old ;
64586463 while (up && up -> level >= reflevel ) {
6459- if (reflevel < 0 && up -> level < - (reflevel ))
6460- break ;
64616464 pm = up ;
64626465 up = up -> old ;
64636466 }
6464- if (reflevel < 0 && locallevel > 0 )
6465- return pm -> level == locallevel ? up : pm ;
6467+ return pm ;
6468+ }
6469+
6470+ /**/
6471+ mod_export Param
6472+ upscope_upper (Param pm , int reflevel )
6473+ {
6474+ while (pm && pm -> level > reflevel )
6475+ pm = pm -> old ;
64666476 return pm ;
64676477}
64686478
0 commit comments