// outgoing externals
external [
	Dvec
	DefaultArgs1
	]

// incoming externals
external [
	FrameSize; CallersFrame; Usc; errhlt
	]

manifest endCode=#335


let Dvec(caller, newVecs, nil, nil, nil, nil, nil, nil,
  nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
  nil; numargs na)=valof [

	let myArgs=lv caller
	let cf=CallersFrame()
	let cfs=FrameSize(caller)
	let top=cf+cfs

	let length=0
	let i=0
	while i ls na-1 do [
		i=i+1
		if myArgs!i eq 0 then break
		length=length+rv myArgs!i+1
		rv myArgs!i=top-length
		]

	while i ls na-1 do [
		i=i+1
		let t=rv myArgs!i
		if t ge cf & t ls top then rv myArgs!i=t-length
		]

	let newCf=cf-length
	if Usc(newCf, rv endCode) le 0 then errhlt("Stack overflow")

// BMOVE(cf, newCf, cfs-1)
// resultis newCf+cfs
	let DoMove=table [
	#35003	// lda 3 extraArgs,2
	#131400	// inc 1 2
	#173000	// add 3 2
	#61005	// blt
	#121400	// inc 1 0	return address of first new word
	#35001	// lda 3 savedPC,2
	#1401	// jmp 1,3
	]

	DoMove(cf-1, newCf+cfs-1, -cfs)
	]

and DefaultArgs1(lvNa, base, defaultValue, nil, nil, nil, nil,
  nil, nil, nil, nil, nil; numargs na) be [

	if na ls 2 then base=0
	let defaultOnZero=false
	if base ls 0 then [ defaultOnZero=true; base=-base ]

	let dvVec=lv defaultValue-base
	let actualNumDVs=na-3+base
	let defaultDV=(na ls 3 ? 0, dvVec!actualNumDVs)
	let callersFormals=CallersFrame()+4

	if rv lvNa ls base then errhlt("Too few arguments")

	for i=base to (lvNa-callersFormals-1) do
	  if i ge rv lvNa % (defaultOnZero &
	   callersFormals!i eq 0) then
		callersFormals!i=(i le actualNumDVs ?
		  dvVec!i, defaultDV)
	]