%option "-nons-low-nocheck-nodiag" %systemroutine copy subprocess data ! This should be called by the child process, once only. ! Copies are made of the own areas of all modules comprising the current ! program, with all the external linkages being adjusted accordingly. ! The effect is that after the call, the own/external variables used by ! parent and child processes will be independent. %recordformat fe02 object fm - (%half flags,extra,%integer type,offset,%string(255)name) %recordformat fe02 header fm - ({%byte type,version) %or}%half tyver,flags,export,import,%integer codesize, %half reset,main, %integer ownsize,stack,%half dlim,chlim,spare1,spare2) %recordformat mar fm - (%record(mar fm)%name next, %record(fe02 header fm)%name header, %integer gla,%string(255)filename) %recordformat par fm - (%record(par fm)%name next, %record(mar fm)%name modules) %recordformat fe02 indir fm - (%integer address %or - %half op1, %integer opd1, %half op2, %integer opd2) %recordformat dyn fm - (%record(fe02 object fm)%name object, %record(par fm)%name program) @16_3e88 %integerfn heapget(%integer bytes) @372(a5) %record (par fm)%name topprog %constinteger procmask=16_3000 %record(fe02objectfm)%map nextobject(%record(fe02objectfm)%name o) ! Get at the next (i.e. adjacent) external object descriptor ! within the current export or import section. %result == record((addr(o[1])-255+length(o_name)+1)&\1) %end %record(*)%map reverse(%record(*)%name list) ! Reverse an arbitrary singly-linked list, provided the FIRST ! field of the records involved are used for linking. %recordformat f(%record(f)%name next) %record(f)%name l == list %record(f)%name s == nil,c %while l##nil %cycle c == l; l == c_next; c_next == s; s == c %repeat %result == s %end %routine relocate module(%record(marfm)%name new,old) ! Fix up cross-references in the external linkage, following duplication ! of a module's own area. OLD and NEW refer to descriptors of the same ! module, except that their respective GLA fields are different. %integer oldarea,newarea,limit %record(marfm)%name mar %record(fe02headerfm)%name hdr %record(fe02objectfm)%name obj %record(fe02indirfm)%name ind %returnif old==nil %or new==nil {safety check} oldarea = old_gla; newarea = new_gla hdr == old_header; %returnif hdr_ownsize<=0 {no data area} limit = oldarea+hdr_ownsize %returnunless hdr==new_header %and old_filename=new_filename {safety} mar == topprog_modules {scan all active modules to see if they import} %while mar##nil %cycle {any external objects from the current module} hdr == mar_header %if hdr_import#0 %start obj == record(addr(hdr[1])+hdr_export) %while obj_flags#0 %cycle ind == record(mar_gla+obj_offset) %if obj_flags&procmask=0 %start {i.e. a data object} %if oldarea<=ind_address0 %start newarea = heapget(count) %while count>0 %cycle count = count-1 byte(newarea+count) = byte(oldarea+count) %repeat %finish item_gla = newarea item_filename = oldlist_filename oldlist == oldlist_next; item_next == newlist; newlist == item %repeat %result == reverse(newlist) %end ! Main part of COPY SUBPROCESS DATA %record(parfm)%name par %record(marfm)%name original,mar par == new(par) {duplicate (only first cell in) program list} par_next == topprog_next original == topprog_modules par_modules == duplicate module list(original) topprog == par mar == topprog_modules {now relocate all modules in the copied list} %while mar##nil %cycle relocate module(mar,original) mar == mar_next; original == original_next %repeat %end