/* get information on caller and parent of given stack frame (auto block) for PL/I symbolic debugger "the caller" could also be considered the dynamic or execution parent, but "the parent" as used here means the outermost static or lexical parent, in other words, the external procedure containing the definition of the given block used by addrcalc and SHOW CALLS */ uplevel: procedure(thisfp, callerfp, parent_prolog); dcl thisfp fixed bin(15), /*address in user task of given stack frame (dsa)*/ callerfp fixed bin(15), /*returned address in user task of caller stack frame*/ parent_prolog fixed bin(15); /*returned address in user task of parent procedure prolog*/ %include 'knldef.pli'; %include 'rundef.pli'; dcl ( douplv pointer, (ouplfp, ouplcl, ouplpr, ouplfl, ouplco, ouplpo, ouplfo) fixed bin(15) ) external; /*defined in debasm*/ dcl iand entry(fixed bin(15), fixed bin(15)) returns(fixed bin(15)), (parent_fp, flagsnargs, i) fixed bin(15); /**************************************************************************************************************/ parent_fp = thisfp; uplevel_loop: call fillpacket(douplv); packet(ouplfp) = parent_fp; packet(ouplco) = dsa_caller_fp; /*fill in offsets from PL/I include file definition*/ packet(ouplpo) = dsa_prolog; /* so they are only defined once*/ packet(ouplfo) = dsa_flags_nargs; call sendknl; call rcvknl; if parent_fp = thisfp then callerfp = packet(ouplcl); flagsnargs = packet(ouplfl); if iand(internal_procedure_flag, flagsnargs) ^= 0 then do; i = iand(flagsnargs, 'FF'B4); /*low order byte is number of arguments*/ parent_fp = getword(parent_fp + i*2); /*first word after arguments is first static backchain*/ goto uplevel_loop; /*keep following backchains till we reach an external procedure*/ end; parent_prolog = packet(ouplpr); end;