text:
package proc

import (
	"debug/dwarf"
	"encoding/binary"
	"errors"
	"fmt"
	"go/ast"
	"go/constant"
	"go/token"
	"reflect"
	"sort"
	"strconv"
	"strings"

	"github.com/go-delve/delve/pkg/dwarf/godwarf"
	"github.com/go-delve/delve/pkg/dwarf/op"
	"github.com/go-delve/delve/pkg/dwarf/reader"
	"github.com/go-delve/delve/pkg/dwarf/regnum"
	"github.com/go-delve/delve/pkg/goversion"
	"github.com/go-delve/delve/pkg/logflags"
)

// This file implements the function call injection introduced in go1.11.
//
// The protocol is described in $GOROOT/src/runtime/asm_amd64.s in the
// comments for function runtime·debugCallV1.
//
// The main entry point is EvalExpressionWithCalls which will start a goroutine to
// evaluate the provided expression.
// This goroutine can either return immediately, if no function calls were
// needed, or write a continue request to the scope.callCtx.continueRequest
// channel. When this happens EvalExpressionWithCalls will call Continue and
// return.
//
// The Continue loop will write to scope.callCtx.continueCompleted when it
// hits a breakpoint in the call injection protocol.
//
// The work of setting up the function call and executing the protocol is
// done by evalFunctionCall and funcCallStep.

const (
	debugCallFunctionNamePrefix1 = "debugCall"
	debugCallFunctionNamePrefix2 = "runtime.debugCall"
	maxDebugCallVersion          = 2
	maxArgFrameSize              = 65535
)

var (
	errFuncCallUnsupported        = errors.New("function calls not supported by this version of Go")
	errFuncCallUnsupportedBackend = errors.New("backend does not support function calls")
	errFuncCallInProgress         = errors.New("cannot call function while another function call is already in progress")
	errNoGoroutine                = errors.New("no goroutine selected")
	errGoroutineNotRunning        = errors.New("selected goroutine not running")
	errNotEnoughStack             = errors.New("not enough stack space")
	errTooManyArguments           = errors.New("too many arguments")
	errNotEnoughArguments         = errors.New("not enough arguments")
	errNotAGoFunction             = errors.New("not a Go function")
	errFuncCallNotAllowed         = errors.New("function calls not allowed without using 'call'")
	errFuncCallNotAllowedStrAlloc = errors.New("literal string can not be allocated because function calls are not allowed without using 'call'")
)

type functionCallState struct {
	// savedRegs contains the saved registers
	savedRegs Registers
	// err contains a saved error
	err error
	// expr is the expression being evaluated
	expr *ast.CallExpr
	// fn is the function that is being called
	fn *Function
	// receiver is the receiver argument for the function
	receiver *Variable
	// closureAddr is the address of the closure being called
	closureAddr uint64
	// formalArgs are the formal arguments of fn
	formalArgs []funcCallArg
	// argFrameSize contains the size of the arguments
	argFrameSize int64
	// retvars contains the return variables after the function call terminates without panic'ing
	retvars []*Variable
	// panicvar is a variable used to store the value of the panic, if the
	// called function panics.
	panicvar *Variable
	// lateCallFailure is set to true if the function call could not be
	// completed after we started evaluating the arguments.
	lateCallFailure bool
}

type callContext struct {
	p *Target

	// checkEscape is true if the escape check should be performed.
	// See service/api.DebuggerCommand.UnsafeCall in service/api/types.go.
	checkEscape bool

	// retLoadCfg is the load configuration used to load return values
	retLoadCfg LoadConfig

	// Write to continueRequest to request a call to Continue from the
	// debugger's main goroutine.
	// Read from continueCompleted to wait for the target process to stop at
	// one of the interaction point of the function call protocol.
	// To signal that evaluation is completed a value will be written to
	// continueRequest having cont == false and the return values in ret.
	continueRequest   chan<- continueRequest
	continueCompleted <-chan *G

	// injectionThread is the thread to use for nested call injections if the
	// original injection goroutine isn't running (because we are in Go 1.15)
	injectionThread Thread

	// stacks is a slice of known goroutine stacks used to check for
	// inappropriate escapes
	stacks []stack
}

type continueRequest struct {
	cont bool
	err  error
	ret  *Variable
}

type callInjection struct {
	// if continueCompleted is not nil it means we are in the process of
	// executing an injected function call, see comments throughout
	// pkg/proc/fncall.go for a description of how this works.
	continueCompleted chan<- *G
	continueRequest   <-chan continueRequest
	startThreadID     int
	endCallInjection  func()
}

func (callCtx *callContext) doContinue() *G {
	callCtx.continueRequest <- continueRequest{cont: true}
	return <-callCtx.continueCompleted
}

func (callCtx *callContext) doReturn(ret *Variable, err error) {
	if callCtx == nil {
		return
	}
	callCtx.continueRequest <- continueRequest{cont: false, ret: ret, err: err}
}

// EvalExpressionWithCalls is like EvalExpression but allows function calls in 'expr'.
// Because this can only be done in the current goroutine, unlike
// EvalExpression, EvalExpressionWithCalls is not a method of EvalScope.
func EvalExpressionWithCalls(grp *TargetGroup, g *G, expr string, retLoadCfg LoadConfig, checkEscape bool) error {
	t := grp.Selected
	bi := t.BinInfo()
	if !t.SupportsFunctionCalls() {
		return errFuncCallUnsupportedBackend
	}

	// check that the target goroutine is running
	if g == nil {
		return errNoGoroutine
	}
	if g.Status != Grunning || g.Thread == nil {
		return errGoroutineNotRunning
	}

	if callinj := t.fncallForG[g.ID]; callinj != nil && callinj.continueCompleted != nil {
		return errFuncCallInProgress
	}

	dbgcallfn, _ := debugCallFunction(bi)
	if dbgcallfn == nil {
		return errFuncCallUnsupported
	}

	scope, err := GoroutineScope(t, g.Thread)
	if err != nil {
		return err
	}

	continueRequest := make(chan continueRequest)
	continueCompleted := make(chan *G)

	scope.callCtx = &callContext{
		p:                 t,
		checkEscape:       checkEscape,
		retLoadCfg:        retLoadCfg,
		continueRequest:   continueRequest,
		continueCompleted: continueCompleted,
	}

	endCallInjection, err := t.proc.StartCallInjection()
	if err != nil {
		return err
	}

	t.fncallForG[g.ID] = &callInjection{
		continueCompleted: continueCompleted,
		continueRequest:   continueRequest,
		startThreadID:     0,
		endCallInjection:  endCallInjection,
	}

	go scope.EvalExpression(expr, retLoadCfg)

	contReq, ok := <-continueRequest
	if contReq.cont {
		return grp.Continue()
	}

	return finishEvalExpressionWithCalls(t, g, contReq, ok)
}

func finishEvalExpressionWithCalls(t *Target, g *G, contReq continueRequest, ok bool) error {
	fncallLog("stashing return values for %d in thread=%d", g.ID, g.Thread.ThreadID())
	g.Thread.Common().CallReturn = true
	var err error
	if !ok {
		err = errors.New("internal error EvalExpressionWithCalls didn't return anything")
	} else if contReq.err != nil {
		if fpe, ispanic := contReq.err.(fncallPanicErr); ispanic {
			g.Thread.Common().returnValues = []*Variable{fpe.panicVar}
		} else {
			err = contReq.err
		}
	} else if contReq.ret == nil {
		g.Thread.Common().returnValues = nil
	} else if contReq.ret.Addr == 0 && contReq.ret.DwarfType == nil && contReq.ret.Kind == reflect.Invalid {
		// this is a variable returned by a function call with multiple return values
		r := make([]*Variable, len(contReq.ret.Children))
		for i := range contReq.ret.Children {
			r[i] = &contReq.ret.Children[i]
		}
		g.Thread.Common().returnValues = r
	} else {
		g.Thread.Common().returnValues = []*Variable{contReq.ret}
	}

	close(t.fncallForG[g.ID].continueCompleted)
	callinj := t.fncallForG[g.ID]
	for goid := range t.fncallForG {
		if t.fncallForG[goid] == callinj {
			delete(t.fncallForG, goid)
		}
	}
	callinj.endCallInjection()
	return err
}

// evalFunctionCall evaluates a function call.
// If this is a built-in function it's evaluated directly.
// Otherwise this will start the function call injection protocol and
// request that the target process resumes.
// See the comment describing the field EvalScope.callCtx for a description
// of the preconditions that make starting the function call protocol
// possible.
// See runtime.debugCallV1 in $GOROOT/src/runtime/asm_amd64.s for a
// description of the protocol.
func evalFunctionCall(scope *EvalScope, node *ast.CallExpr) (*Variable, error) {
	r, err := scope.evalBuiltinCall(node)
	if r != nil || err != nil {
		// it was a builtin call
		return r, err
	}
	if scope.callCtx == nil {
		return nil, errFuncCallNotAllowed
	}
	thread := scope.g.Thread
	stacklo := scope.g.stack.lo
	if thread == nil {
		// We are doing a nested function call and using Go 1.15, the original
		// injection goroutine was suspended and now we are using a different
		// goroutine, evaluation still happened on the original goroutine but we
		// need to use a different thread to do the nested call injection.
		thread = scope.callCtx.injectionThread
		g2, err := GetG(thread)
		if err != nil {
			return nil, err
		}
		stacklo = g2.stack.lo
	}
	if thread == nil {
		return nil, errGoroutineNotRunning
	}

	p := scope.callCtx.p
	bi := scope.BinInfo
	if !p.SupportsFunctionCalls() {
		return nil, errFuncCallUnsupportedBackend
	}

	dbgcallfn, dbgcallversion := debugCallFunction(bi)
	if dbgcallfn == nil {
		return nil, errFuncCallUnsupported
	}

	// check that there are at least 256 bytes free on the stack
	regs, err := thread.Registers()
	if err != nil {
		return nil, err
	}
	regs, err = regs.Copy()
	if err != nil {
		return nil, err
	}
	if regs.SP()-bi.Arch.debugCallMinStackSize <= stacklo {
		return nil, errNotEnoughStack
	}
	protocolReg, ok := debugCallProtocolReg(bi.Arch.Name, dbgcallversion)
	if !ok {
		return nil, errFuncCallUnsupported
	}
	if bi.Arch.RegistersToDwarfRegisters(0, regs).Reg(protocolReg) == nil {
		return nil, errFuncCallUnsupportedBackend
	}

	fncall := functionCallState{
		expr:      node,
		savedRegs: regs,
	}

	err = funcCallEvalFuncExpr(scope, &fncall, false)
	if err != nil {
		return nil, err
	}

	switch bi.Arch.Name {
	case "amd64":
		if err := callOP(bi, thread, regs, dbgcallfn.Entry); err != nil {
			return nil, err
		}
		// write the desired argument frame size at SP-(2*pointer_size) (the extra pointer is the saved PC)
		if err := writePointer(bi, scope.Mem, regs.SP()-3*uint64(bi.Arch.PtrSize()), uint64(fncall.argFrameSize)); err != nil {
			return nil, err
		}
	case "arm64":
		// debugCallV2 on arm64 needs a special call sequence, callOP can not be used
		sp := regs.SP()
		sp -= 2 * uint64(bi.Arch.PtrSize())
		if err := setSP(thread, sp); err != nil {
			return nil, err
		}
		if err := writePointer(bi, scope.Mem, sp, regs.LR()); err != nil {
			return nil, err
		}
		if err := setLR(thread, regs.PC()); err != nil {
			return nil, err
		}
		if err := writePointer(bi, scope.Mem, sp-uint64(2*bi.Arch.PtrSize()), uint64(fncall.argFrameSize)); err != nil {
			return nil, err
		}
		regs, err = thread.Registers()
		if err != nil {
			return nil, err
		}
		regs, err = regs.Copy()
		if err != nil {
			return nil, err
		}
		fncall.savedRegs = regs
		err = setPC(thread, dbgcallfn.Entry)
		if err != nil {
			return nil, err
		}
	}

	fncallLog("function call initiated %v frame size %d goroutine %d (thread %d)", fncall.fn, fncall.argFrameSize, scope.g.ID, thread.ThreadID())

	thread.Breakpoint().Clear() // since we moved address in PC the thread is no longer stopped at a breakpoint, leaving the breakpoint set will confuse Continue
	p.fncallForG[scope.g.ID].startThreadID = thread.ThreadID()

	spoff := int64(scope.Regs.Uint64Val(scope.Regs.SPRegNum)) - int64(scope.g.stack.hi)
	bpoff := int64(scope.Regs.Uint64Val(scope.Regs.BPRegNum)) - int64(scope.g.stack.hi)
	fboff := scope.Regs.FrameBase - int64(scope.g.stack.hi)

	for {
		scope.callCtx.injectionThread = nil
		g := scope.callCtx.doContinue()
		// Go 1.15 will move call injection execution to a different goroutine,
		// but we want to keep evaluation on the original goroutine.
		if g.ID == scope.g.ID {
			scope.g = g
		} else {
			// We are in Go 1.15 and we switched to a new goroutine, the original
			// goroutine is now parked and therefore does not have a thread
			// associated.
			scope.g.Thread = nil
			scope.g.Status = Gwaiting
			scope.callCtx.injectionThread = g.Thread
		}

		// adjust the value of registers inside scope
		pcreg, bpreg, spreg := scope.Regs.Reg(scope.Regs.PCRegNum), scope.Regs.Reg(scope.Regs.BPRegNum), scope.Regs.Reg(scope.Regs.SPRegNum)
		scope.Regs.ClearRegisters()
		scope.Regs.AddReg(scope.Regs.PCRegNum, pcreg)
		scope.Regs.AddReg(scope.Regs.BPRegNum, bpreg)
		scope.Regs.AddReg(scope.Regs.SPRegNum, spreg)
		scope.Regs.Reg(scope.Regs.SPRegNum).Uint64Val = uint64(spoff + int64(scope.g.stack.hi))
		scope.Regs.Reg(scope.Regs.BPRegNum).Uint64Val = uint64(bpoff + int64(scope.g.stack.hi))
		scope.Regs.FrameBase = fboff + int64(scope.g.stack.hi)
		scope.Regs.CFA = scope.frameOffset + int64(scope.g.stack.hi)

		finished := funcCallStep(scope, &fncall, g.Thread, protocolReg, dbgcallfn.Name)
		if finished {
			break
		}
	}

	if fncall.err != nil {
		return nil, fncall.err
	}

	if fncall.panicvar != nil {
		return nil, fncallPanicErr{fncall.panicvar}
	}
	switch len(fncall.retvars) {
	case 0:
		r := newVariable("", 0, nil, scope.BinInfo, nil)
		r.loaded = true
		r.Unreadable = errors.New("no return values")
		return r, nil
	case 1:
		return fncall.retvars[0], nil
	default:
		// create a fake variable without address or type to return multiple values
		r := newVariable("", 0, nil, scope.BinInfo, nil)
		r.loaded = true
		r.Children = make([]Variable, len(fncall.retvars))
		for i := range fncall.retvars {
			r.Children[i] = *fncall.retvars[i]
		}
		return r, nil
	}
}

// fncallPanicErr is the error returned if a called function panics
type fncallPanicErr struct {
	panicVar *Variable
}

func (err fncallPanicErr) Error() string {
	return "panic calling a function"
}

func fncallLog(fmtstr string, args ...interface{}) {
	logflags.FnCallLogger().Infof(fmtstr, args...)
}

// writePointer writes val as an architecture pointer at addr in mem.
func writePointer(bi *BinaryInfo, mem MemoryReadWriter, addr, val uint64) error {
	ptrbuf := make([]byte, bi.Arch.PtrSize())

	// TODO: use target architecture endianness instead of LittleEndian
	switch len(ptrbuf) {
	case 4:
		binary.LittleEndian.PutUint32(ptrbuf, uint32(val))
	case 8:
		binary.LittleEndian.PutUint64(ptrbuf, val)
	default:
		panic(fmt.Errorf("unsupported pointer size %d", len(ptrbuf)))
	}
	_, err := mem.WriteMemory(addr, ptrbuf)
	return err
}

// callOP simulates a call instruction on the given thread:
// * pushes the current value of PC on the stack (adjusting SP)
// * changes the value of PC to callAddr
// Note: regs are NOT updated!
func callOP(bi *BinaryInfo, thread Thread, regs Registers, callAddr uint64) error {
	switch bi.Arch.Name {
	case "amd64":
		sp := regs.SP()
		// push PC on the stack
		sp -= uint64(bi.Arch.PtrSize())
		if err := setSP(thread, sp); err != nil {
			return err
		}
		if err := writePointer(bi, thread.ProcessMemory(), sp, regs.PC()); err != nil {
			return err
		}
		return setPC(thread, callAddr)
	case "arm64":
		if err := setLR(thread, regs.PC()); err != nil {
			return err
		}
		return setPC(thread, callAddr)
	default:
		panic("not implemented")
	}
}

// funcCallEvalFuncExpr evaluates expr.Fun and returns the function that we're trying to call.
// If allowCalls is false function calls will be disabled even if scope.callCtx != nil
func funcCallEvalFuncExpr(scope *EvalScope, fncall *functionCallState, allowCalls bool) error {
	bi := scope.BinInfo

	if !allowCalls {
		callCtx := scope.callCtx
		scope.callCtx = nil
		defer func() {
			scope.callCtx = callCtx
		}()
	}

	fnvar, err := scope.evalAST(fncall.expr.Fun)
	if err == errFuncCallNotAllowed {
		// we can't determine the frame size because callexpr.Fun can't be
		// evaluated without enabling function calls, just set up an argument
		// frame for the maximum possible argument size.
		fncall.argFrameSize = maxArgFrameSize
		return nil
	} else if err != nil {
		return err
	}
	if fnvar.Kind != reflect.Func {
		return fmt.Errorf("expression %q is not a function", exprToString(fncall.expr.Fun))
	}
	fnvar.loadValue(LoadConfig{false, 0, 0, 0, 0, 0})
	if fnvar.Unreadable != nil {
		return fnvar.Unreadable
	}
	if fnvar.Base == 0 {
		return errors.New("nil pointer dereference")
	}
	fncall.fn = bi.PCToFunc(uint64(fnvar.Base))
	if fncall.fn == nil {
		return fmt.Errorf("could not find DIE for function %q", exprToString(fncall.expr.Fun))
	}
	if !fncall.fn.cu.isgo {
		return errNotAGoFunction
	}
	fncall.closureAddr = fnvar.closureAddr

	fncall.argFrameSize, fncall.formalArgs, err = funcCallArgs(fncall.fn, bi, false)
	if err != nil {
		return err
	}

	argnum := len(fncall.expr.Args)

	// If the function variable has a child then that child is the method
	// receiver. However, if the method receiver is not being used (e.g.
	// func (_ X) Foo()) then it will not actually be listed as a formal
	// argument. Ensure that we are really off by 1 to add the receiver to
	// the function call.
	if len(fnvar.Children) > 0 && argnum == (len(fncall.formalArgs)-1) {
		argnum++
		fncall.receiver = &fnvar.Children[0]
		fncall.receiver.Name = exprToString(fncall.expr.Fun)
	}

	if argnum > len(fncall.formalArgs) {
		return errTooManyArguments
	}
	if argnum < len(fncall.formalArgs) {
		return errNotEnoughArguments
	}

	return nil
}

type funcCallArg struct {
	name       string
	typ        godwarf.Type
	off        int64
	dwarfEntry *godwarf.Tree // non-nil if Go 1.17+
	isret      bool
}

// funcCallEvalArgs evaluates the arguments of the function call, copying
// them into the argument frame starting at argFrameAddr.
func funcCallEvalArgs(scope *EvalScope, fncall *functionCallState, formalScope *EvalScope) error {
	if scope.g == nil {
		// this should never happen
		return errNoGoroutine
	}

	if fncall.receiver != nil {
		err := funcCallCopyOneArg(scope, fncall, fncall.receiver, &fncall.formalArgs[0], formalScope)
		if err != nil {
			return err
		}
		fncall.formalArgs = fncall.formalArgs[1:]
	}

	for i := range fncall.formalArgs {
		formalArg := &fncall.formalArgs[i]

		actualArg, err := scope.evalAST(fncall.expr.Args[i])
		if err != nil {
			if _, ispanic := err.(fncallPanicErr); ispanic {
				return err
			}
			return fmt.Errorf("error evaluating %q as argument %s in function %s: %v", exprToString(fncall.expr.Args[i]), formalArg.name, fncall.fn.Name, err)
		}
		actualArg.Name = exprToString(fncall.expr.Args[i])

		err = funcCallCopyOneArg(scope, fncall, actualArg, formalArg, formalScope)
		if err != nil {
			return err
		}
	}

	return nil
}

func funcCallCopyOneArg(scope *EvalScope, fncall *functionCallState, actualArg *Variable, formalArg *funcCallArg, formalScope *EvalScope) error {
	if scope.callCtx.checkEscape {
		//TODO(aarzilli): only apply the escapeCheck to leaking parameters.
		if err := escapeCheck(actualArg, formalArg.name, scope.g.stack); err != nil {
			return fmt.Errorf("cannot use %s as argument %s in function %s: %v", actualArg.Name, formalArg.name, fncall.fn.Name, err)
		}
		for _, stack := range scope.callCtx.stacks {
			if err := escapeCheck(actualArg, formalArg.name, stack); err != nil {
				return fmt.Errorf("cannot use %s as argument %s in function %s: %v", actualArg.Name, formalArg.name, fncall.fn.Name, err)
			}
		}
	}

	//TODO(aarzilli): autmoatic wrapping in interfaces for cases not handled
	// by convertToEface.

	var formalArgVar *Variable
	if formalArg.dwarfEntry != nil {
		var err error
		formalArgVar, err = extractVarInfoFromEntry(scope.target, formalScope.BinInfo, formalScope.image(), formalScope.Regs, formalScope.Mem, formalArg.dwarfEntry, 0)
		if err != nil {
			return err
		}
	} else {
		formalArgVar = newVariable(formalArg.name, uint64(formalArg.off+int64(formalScope.Regs.CFA)), formalArg.typ, scope.BinInfo, scope.Mem)
	}
	if err := scope.setValue(formalArgVar, actualArg, actualArg.Name); err != nil {
		return err
	}

	return nil
}

func funcCallArgs(fn *Function, bi *BinaryInfo, includeRet bool) (argFrameSize int64, formalArgs []funcCallArg, err error) {
	dwarfTree, err := fn.cu.image.getDwarfTree(fn.offset)
	if err != nil {
		return 0, nil, fmt.Errorf("DWARF read error: %v", err)
	}

	producer := bi.Producer()
	trustArgOrder := producer != "" && goversion.ProducerAfterOrEqual(bi.Producer(), 1, 12)

	if bi.regabi && fn.cu.optimized && fn.Name != "runtime.mallocgc" {
		// Debug info for function arguments on optimized functions is currently
		// too incomplete to attempt injecting calls to arbitrary optimized
		// functions.
		// Prior to regabi we could do this because the ABI was simple enough to
		// manually encode it in Delve.
		// Runtime.mallocgc is an exception, we specifically patch it's DIE to be
		// correct for call injection purposes.
		return 0, nil, fmt.Errorf("can not call optimized function %s when regabi is in use", fn.Name)
	}

	varEntries := reader.Variables(dwarfTree, fn.Entry, int(^uint(0)>>1), reader.VariablesSkipInlinedSubroutines)

	// typechecks arguments, calculates argument frame size
	for _, entry := range varEntries {
		if entry.Tag != dwarf.TagFormalParameter {
			continue
		}
		argname, typ, err := readVarEntry(entry.Tree, fn.cu.image)
		if err != nil {
			return 0, nil, err
		}
		typ = resolveTypedef(typ)

		var formalArg *funcCallArg
		if bi.regabi {
			formalArg, err = funcCallArgRegABI(fn, bi, entry, argname, typ, &argFrameSize)
		} else {
			formalArg, err = funcCallArgOldABI(fn, bi, entry, argname, typ, trustArgOrder, &argFrameSize)
		}
		if err != nil {
			return 0, nil, err
		}
		if !formalArg.isret || includeRet {
			formalArgs = append(formalArgs, *formalArg)
		}
	}

	if bi.regabi {
		// The argument frame size is computed conservatively, assuming that
		// there's space for each argument on the stack even if its passed in
		// registers. Unfortunately this isn't quite enough because the register
		// assignment algorithm Go uses can result in an amount of additional
		// space used due to alignment requirements, bounded by the number of argument registers.
		// Because we currently don't have an easy way to obtain the frame size,
		// let's be even more conservative.
		// A safe lower-bound on the size of the argument frame includes space for
		// each argument plus the total bytes of register arguments.
		// This is derived from worst-case alignment padding of up to
		// (pointer-word-bytes - 1) per argument passed in registers.
		// See: https://github.com/go-delve/delve/pull/2451#discussion_r665761531
		// TODO: Make this generic for other platforms.
		argFrameSize = alignAddr(argFrameSize, 8)
		argFrameSize += int64(bi.Arch.maxRegArgBytes)
	}

	sort.Slice(formalArgs, func(i, j int) bool {
		return formalArgs[i].off < formalArgs[j].off
	})

	return argFrameSize, formalArgs, nil
}

func funcCallArgOldABI(fn *Function, bi *BinaryInfo, entry reader.Variable, argname string, typ godwarf.Type, trustArgOrder bool, pargFrameSize *int64) (*funcCallArg, error) {
	const CFA = 0x1000
	var off int64

	locprog, _, err := bi.locationExpr(entry, dwarf.AttrLocation, fn.Entry)
	if err != nil {
		err = fmt.Errorf("could not get argument location of %s: %v", argname, err)
	} else {
		var pieces []op.Piece
		off, pieces, err = op.ExecuteStackProgram(op.DwarfRegisters{CFA: CFA, FrameBase: CFA}, locprog, bi.Arch.PtrSize(), nil)
		if err != nil {
			err = fmt.Errorf("unsupported location expression for argument %s: %v", argname, err)
		}
		if pieces != nil {
			err = fmt.Errorf("unsupported location expression for argument %s (uses DW_OP_piece)", argname)
		}
		off -= CFA
	}
	if err != nil {
		if !trustArgOrder {
			return nil, err
		}

		// With Go version 1.12 or later we can trust that the arguments appear
		// in the same order as declared, which means we can calculate their
		// address automatically.
		// With this we can call optimized functions (which sometimes do not have
		// an argument address, due to a compiler bug) as well as runtime
		// functions (which are always optimized).
		off = *pargFrameSize
		off = alignAddr(off, typ.Align())
	}

	if e := off + typ.Size(); e > *pargFrameSize {
		*pargFrameSize = e
	}

	isret, _ := entry.Val(dwarf.AttrVarParam).(bool)
	return &funcCallArg{name: argname, typ: typ, off: off, isret: isret}, nil
}

func funcCallArgRegABI(fn *Function, bi *BinaryInfo, entry reader.Variable, argname string, typ godwarf.Type, pargFrameSize *int64) (*funcCallArg, error) {
	// Conservatively calculate the full stack argument space for ABI0.
	*pargFrameSize = alignAddr(*pargFrameSize, typ.Align())
	*pargFrameSize += typ.Size()

	isret, _ := entry.Val(dwarf.AttrVarParam).(bool)
	return &funcCallArg{name: argname, typ: typ, dwarfEntry: entry.Tree, isret: isret}, nil
}

// alignAddr rounds up addr to a multiple of align. Align must be a power of 2.
func alignAddr(addr, align int64) int64 {
	return (addr + int64(align-1)) &^ int64(align-1)
}

func escapeCheck(v *Variable, name string, stack stack) error {
	switch v.Kind {
	case reflect.Ptr:
		var w *Variable
		if len(v.Children) == 1 {
			// this branch is here to support pointers constructed with typecasts from ints or the '&' operator
			w = &v.Children[0]
		} else {
			w = v.maybeDereference()
		}
		return escapeCheckPointer(w.Addr, name, stack)
	case reflect.Chan, reflect.String, reflect.Slice:
		return escapeCheckPointer(v.Base, name, stack)
	case reflect.Map:
		sv := v.clone()
		sv.RealType = resolveTypedef(&(v.RealType.(*godwarf.MapType).TypedefType))
		sv = sv.maybeDereference()
		return escapeCheckPointer(sv.Addr, name, stack)
	case reflect.Struct:
		t := v.RealType.(*godwarf.StructType)
		for _, field := range t.Field {
			fv, _ := v.toField(field)
			if err := escapeCheck(fv, fmt.Sprintf("%s.%s", name, field.Name), stack); err != nil {
				return err
			}
		}
	case reflect.Array:
		for i := int64(0); i < v.Len; i++ {
			sv, _ := v.sliceAccess(int(i))
			if err := escapeCheck(sv, fmt.Sprintf("%s[%d]", name, i), stack); err != nil {
				return err
			}
		}
	case reflect.Func:
		if err := escapeCheckPointer(v.funcvalAddr(), name, stack); err != nil {
			return err
		}
	}

	return nil
}

func escapeCheckPointer(addr uint64, name string, stack stack) error {
	if uint64(addr) >= stack.lo && uint64(addr) < stack.hi {
		return fmt.Errorf("stack object passed to escaping pointer: %s", name)
	}
	return nil
}

const (
	debugCallRegPrecheckFailed   = 8
	debugCallRegCompleteCall     = 0
	debugCallRegReadReturn       = 1
	debugCallRegReadPanic        = 2
	debugCallRegRestoreRegisters = 16
)

// funcCallStep executes one step of the function call injection protocol.
func funcCallStep(callScope *EvalScope, fncall *functionCallState, thread Thread, protocolReg uint64, debugCallName string) bool {
	p := callScope.callCtx.p
	bi := p.BinInfo()

	regs, err := thread.Registers()
	if err != nil {
		fncall.err = err
		return true
	}

	regval := bi.Arch.RegistersToDwarfRegisters(0, regs).Uint64Val(protocolReg)

	if logflags.FnCall() {
		loc, _ := thread.Location()
		var pc uint64
		var fnname string
		if loc != nil {
			pc = loc.PC
			if loc.Fn != nil {
				fnname = loc.Fn.Name
			}
		}
		fncallLog("function call interrupt gid=%d (original) thread=%d regval=%#x (PC=%#x in %s)", callScope.g.ID, thread.ThreadID(), regval, pc, fnname)
	}

	switch regval {
	case debugCallRegPrecheckFailed: // 8
		archoff := uint64(0)
		if bi.Arch.Name == "arm64" {
			archoff = 8
		}
		// get error from top of the stack and return it to user
		errvar, err := readStackVariable(p, thread, regs, archoff, "string", loadFullValue)
		if err != nil {
			fncall.err = fmt.Errorf("could not get precheck error reason: %v", err)
			break
		}
		errvar.Name = "err"
		fncall.err = fmt.Errorf("%v", constant.StringVal(errvar.Value))

	case debugCallRegCompleteCall: // 0
		p.fncallForG[callScope.g.ID].startThreadID = 0

		// evaluate arguments of the target function, copy them into its argument frame and call the function
		if fncall.fn == nil || fncall.receiver != nil || fncall.closureAddr != 0 {
			// if we couldn't figure out which function we are calling before
			// (because the function we are calling is the return value of a call to
			// another function) now we have to figure it out by recursively
			// evaluating the function calls.
			// This also needs to be done if the function call has a receiver
			// argument or a closure address (because those addresses could be on the stack
			// and have changed position between the start of the call and now).

			err := funcCallEvalFuncExpr(callScope, fncall, true)
			if err != nil {
				fncall.err = err
				fncall.lateCallFailure = true
				break
			}
			//TODO: double check that function call size isn't too big
		}

		// instead of evaluating the arguments we start first by pushing the call
		// on the stack, this is the opposite of what would happen normally but
		// it's necessary because otherwise the GC wouldn't be able to deal with
		// the argument frame.
		if fncall.closureAddr != 0 {
			// When calling a function pointer we must set the DX register to the
			// address of the function pointer itself.
			setClosureReg(thread, fncall.closureAddr)
		}
		cfa := regs.SP()
		oldpc := regs.PC()
		var oldlr uint64
		if bi.Arch.Name == "arm64" {
			oldlr = regs.LR()
		}
		callOP(bi, thread, regs, fncall.fn.Entry)
		formalScope, err := GoroutineScope(callScope.target, thread)
		if formalScope != nil && formalScope.Regs.CFA != int64(cfa) {
			// This should never happen, checking just to avoid hard to figure out disasters.
			err = fmt.Errorf("mismatch in CFA %#x (calculated) %#x (expected)", formalScope.Regs.CFA, int64(cfa))
		}
		if err == nil {
			err = funcCallEvalArgs(callScope, fncall, formalScope)
		}

		if err != nil {
			// rolling back the call, note: this works because we called regs.Copy() above
			switch bi.Arch.Name {
			case "amd64":
				setSP(thread, cfa)
				setPC(thread, oldpc)
			case "arm64":
				setLR(thread, oldlr)
				setPC(thread, oldpc)
			default:
				panic("not implemented")
			}
			fncall.err = err
			fncall.lateCallFailure = true
			break
		}

	case debugCallRegRestoreRegisters: // 16
		// runtime requests that we restore the registers (all except pc and sp),
		// this is also the last step of the function call protocol.
		pc, sp := regs.PC(), regs.SP()
		if err := thread.RestoreRegisters(fncall.savedRegs); err != nil {
			fncall.err = fmt.Errorf("could not restore registers: %v", err)
		}
		if err := setPC(thread, pc); err != nil {
			fncall.err = fmt.Errorf("could not restore PC: %v", err)
		}
		if err := setSP(thread, sp); err != nil {
			fncall.err = fmt.Errorf("could not restore SP: %v", err)
		}
		if err := stepInstructionOut(p, thread, debugCallName, debugCallName); err != nil {
			fncall.err = fmt.Errorf("could not step out of %s: %v", debugCallName, err)
		}
		if bi.Arch.Name == "amd64" {
			// The tail of debugCallV2 corrupts the state of RFLAGS, we must restore
			// it one extra time after stepping out of it.
			// See https://github.com/go-delve/delve/issues/2985 and
			// TestCallInjectionFlagCorruption
			rflags := bi.Arch.RegistersToDwarfRegisters(0, fncall.savedRegs).Uint64Val(regnum.AMD64_Rflags)
			err := thread.SetReg(regnum.AMD64_Rflags, op.DwarfRegisterFromUint64(rflags))
			if err != nil {
				fncall.err = fmt.Errorf("could not restore RFLAGS register: %v", err)
			}
		}
		return true

	case debugCallRegReadReturn: // 1
		// read return arguments from stack
		if fncall.panicvar != nil || fncall.lateCallFailure {
			break
		}
		retScope, err := ThreadScope(p, thread)
		if err != nil {
			fncall.err = fmt.Errorf("could not get return values: %v", err)
			break
		}

		// pretend we are still inside the function we called
		fakeFunctionEntryScope(retScope, fncall.fn, int64(regs.SP()), regs.SP()-uint64(bi.Arch.PtrSize()))
		var flags localsFlags
		flags |= localsNoDeclLineCheck // if the function we are calling is an autogenerated stub then declaration lines have no meaning
		if !bi.regabi {
			flags |= localsTrustArgOrder
		}

		fncall.retvars, err = retScope.Locals(flags)
		if err != nil {
			fncall.err = fmt.Errorf("could not get return values: %v", err)
			break
		}
		fncall.retvars = filterVariables(fncall.retvars, func(v *Variable) bool {
			return (v.Flags & VariableReturnArgument) != 0
		})

		loadValues(fncall.retvars, callScope.callCtx.retLoadCfg)
		for _, v := range fncall.retvars {
			v.Flags |= VariableFakeAddress
		}

		// Store the stack span of the currently running goroutine (which in Go >=
		// 1.15 might be different from the original injection goroutine) so that
		// later on we can use it to perform the escapeCheck
		if threadg, _ := GetG(thread); threadg != nil {
			callScope.callCtx.stacks = append(callScope.callCtx.stacks, threadg.stack)
		}
		if bi.Arch.Name == "arm64" {
			oldlr, err := readUintRaw(thread.ProcessMemory(), regs.SP(), int64(bi.Arch.PtrSize()))
			if err != nil {
				fncall.err = fmt.Errorf("could not restore LR: %v", err)
				break
			}
			if err = setLR(thread, oldlr); err != nil {
				fncall.err = fmt.Errorf("could not restore LR: %v", err)
				break
			}
		}

	case debugCallRegReadPanic: // 2
		// read panic value from stack
		archoff := uint64(0)
		if bi.Arch.Name == "arm64" {
			archoff = 8
		}
		fncall.panicvar, err = readStackVariable(p, thread, regs, archoff, "interface {}", callScope.callCtx.retLoadCfg)
		if err != nil {
			fncall.err = fmt.Errorf("could not get panic: %v", err)
			break
		}
		fncall.panicvar.Name = "~panic"

	default:
		// Got an unknown protocol register value, this is probably bad but the safest thing
		// possible is to ignore it and hope it didn't matter.
		fncallLog("unknown value of protocol register %#x", regval)
	}

	return false
}

func readStackVariable(t *Target, thread Thread, regs Registers, off uint64, typename string, loadCfg LoadConfig) (*Variable, error) {
	bi := thread.BinInfo()
	scope, err := ThreadScope(t, thread)
	if err != nil {
		return nil, err
	}
	typ, err := bi.findType(typename)
	if err != nil {
		return nil, err
	}
	v := newVariable("", regs.SP()+off, typ, scope.BinInfo, scope.Mem)
	v.loadValue(loadCfg)
	if v.Unreadable != nil {
		return nil, v.Unreadable
	}
	v.Flags |= VariableFakeAddress
	return v, nil
}

// fakeFunctionEntryScope alters scope to pretend that we are at the entry point of
// fn and CFA and SP are the ones passed as argument.
// This function is used to create a scope for a call frame that doesn't
// exist anymore, to read the return variables of an injected function call,
// or after a stepout command.
func fakeFunctionEntryScope(scope *EvalScope, fn *Function, cfa int64, sp uint64) error {
	scope.PC = fn.Entry
	scope.Fn = fn
	scope.File, scope.Line, _ = scope.BinInfo.PCToLine(fn.Entry)

	scope.Regs.CFA = cfa
	scope.Regs.Reg(scope.Regs.SPRegNum).Uint64Val = sp
	scope.Regs.Reg(scope.Regs.PCRegNum).Uint64Val = fn.Entry

	fn.cu.image.dwarfReader.Seek(fn.offset)
	e, err := fn.cu.image.dwarfReader.Next()
	if err != nil {
		return err
	}
	scope.Regs.FrameBase, _, _, _ = scope.BinInfo.Location(e, dwarf.AttrFrameBase, scope.PC, scope.Regs, nil)
	return nil
}

// allocString allocates spaces for the contents of v if it needs to be allocated
func allocString(scope *EvalScope, v *Variable) error {
	if v.Base != 0 || v.Len == 0 {
		// already allocated
		return nil
	}

	if scope.callCtx == nil {
		return errFuncCallNotAllowedStrAlloc
	}
	savedLoadCfg := scope.callCtx.retLoadCfg
	scope.callCtx.retLoadCfg = loadFullValue
	defer func() {
		scope.callCtx.retLoadCfg = savedLoadCfg
	}()
	mallocv, err := evalFunctionCall(scope, &ast.CallExpr{
		Fun: &ast.SelectorExpr{
			X:   &ast.Ident{Name: "runtime"},
			Sel: &ast.Ident{Name: "mallocgc"},
		},
		Args: []ast.Expr{
			&ast.BasicLit{Kind: token.INT, Value: strconv.Itoa(int(v.Len))},
			&ast.Ident{Name: "nil"},
			&ast.Ident{Name: "false"},
		},
	})
	if err != nil {
		return err
	}
	if mallocv.Unreadable != nil {
		return mallocv.Unreadable
	}
	if mallocv.DwarfType.String() != "*void" {
		return fmt.Errorf("unexpected return type for mallocgc call: %v", mallocv.DwarfType.String())
	}
	if len(mallocv.Children) != 1 {
		return errors.New("internal error, could not interpret return value of mallocgc call")
	}
	v.Base = mallocv.Children[0].Addr
	_, err = scope.Mem.WriteMemory(v.Base, []byte(constant.StringVal(v.Value)))
	return err
}

func isCallInjectionStop(t *Target, thread Thread, loc *Location) bool {
	if loc.Fn == nil {
		return false
	}
	if !strings.HasPrefix(loc.Fn.Name, debugCallFunctionNamePrefix1) && !strings.HasPrefix(loc.Fn.Name, debugCallFunctionNamePrefix2) {
		return false
	}
	if loc.PC == loc.Fn.Entry {
		// call injection just started, did not make any progress before being interrupted by a concurrent breakpoint.
		return false
	}
	off := int64(0)
	if thread.BinInfo().Arch.breakInstrMovesPC {
		off = -int64(len(thread.BinInfo().Arch.breakpointInstruction))
	}
	text, err := disassembleCurrentInstruction(t, thread, off)
	if err != nil || len(text) <= 0 {
		return false
	}
	return text[0].IsHardBreak()
}

// callInjectionProtocol is the function called from Continue to progress
// the injection protocol for all threads.
// Returns true if a call injection terminated
func callInjectionProtocol(t *Target, threads []Thread) (done bool, err error) {
	if len(t.fncallForG) == 0 {
		// we aren't injecting any calls, no need to check the threads.
		return false, nil
	}
	for _, thread := range threads {
		loc, err := thread.Location()
		if err != nil {
			continue
		}
		if !isCallInjectionStop(t, thread, loc) {
			continue
		}

		g, callinj, err := findCallInjectionStateForThread(t, thread)
		if err != nil {
			return false, err
		}

		arch := thread.BinInfo().Arch
		if !arch.breakInstrMovesPC {
			setPC(thread, loc.PC+uint64(len(arch.breakpointInstruction)))
		}

		fncallLog("step for injection on goroutine %d (current) thread=%d (location %s)", g.ID, thread.ThreadID(), loc.Fn.Name)
		callinj.continueCompleted <- g
		contReq, ok := <-callinj.continueRequest
		if !contReq.cont {
			err := finishEvalExpressionWithCalls(t, g, contReq, ok)
			if err != nil {
				return done, err
			}
			done = true
		}
	}
	return done, nil
}

func findCallInjectionStateForThread(t *Target, thread Thread) (*G, *callInjection, error) {
	g, err := GetG(thread)
	if err != nil {
		return nil, nil, fmt.Errorf("could not determine running goroutine for thread %#x currently executing the function call injection protocol: %v", thread.ThreadID(), err)
	}
	fncallLog("findCallInjectionStateForThread thread=%d goroutine=%d", thread.ThreadID(), g.ID)
	notfound := func() error {
		return fmt.Errorf("could not recover call injection state for goroutine %d (thread %d)", g.ID, thread.ThreadID())
	}
	callinj := t.fncallForG[g.ID]
	if callinj != nil {
		if callinj.continueCompleted == nil {
			return nil, nil, notfound()
		}
		return g, callinj, nil
	}

	// In Go 1.15 and later the call injection protocol will switch to a
	// different goroutine.
	// Here we try to recover the injection goroutine by checking the injection
	// thread.

	for goid, callinj := range t.fncallForG {
		if callinj != nil && callinj.continueCompleted != nil && callinj.startThreadID != 0 && callinj.startThreadID == thread.ThreadID() {
			t.fncallForG[g.ID] = callinj
			fncallLog("goroutine %d is the goroutine executing the call injection started in goroutine %d", g.ID, goid)
			return g, callinj, nil
		}
	}

	return nil, nil, notfound()
}

// debugCallFunction searches for the debug call function in the binary and
// uses this search to detect the debug call version.
// Returns the debug call function and its version as an integer (the lowest
// valid version is 1) or nil and zero.
func debugCallFunction(bi *BinaryInfo) (*Function, int) {
	for version := maxDebugCallVersion; version >= 1; version-- {
		name := debugCallFunctionNamePrefix2 + "V" + strconv.Itoa(version)
		fn, ok := bi.LookupFunc[name]
		if ok && fn != nil {
			return fn, version
		}
	}
	return nil, 0
}

// debugCallProtocolReg returns the register ID (as defined in pkg/dwarf/regnum)
// of the register used in the debug call protocol, given the debug call version.
// Also returns a bool indicating whether the version is supported.
func debugCallProtocolReg(archName string, version int) (uint64, bool) {
	switch archName {
	case "amd64":
		var protocolReg uint64
		switch version {
		case 1:
			protocolReg = regnum.AMD64_Rax
		case 2:
			protocolReg = regnum.AMD64_R12
		default:
			return 0, false
		}
		return protocolReg, true
	case "arm64":
		if version == 2 {
			return regnum.ARM64_X0 + 20, true
		}
		return 0, false
	default:
		return 0, false
	}
}

type fakeEntry map[dwarf.Attr]interface{}

func (e fakeEntry) Val(attr dwarf.Attr) interface{} {
	return e[attr]
}

func regabiMallocgcWorkaround(bi *BinaryInfo) ([]*godwarf.Tree, error) {
	var err1 error

	t := func(name string) godwarf.Type {
		if err1 != nil {
			return nil
		}
		typ, err := bi.findType(name)
		if err != nil {
			err1 = err
			return nil
		}
		return typ
	}

	m := func(name string, typ godwarf.Type, reg int, isret bool) *godwarf.Tree {
		if err1 != nil {
			return nil
		}
		var e fakeEntry = map[dwarf.Attr]interface{}{
			dwarf.AttrName:     name,
			dwarf.AttrType:     typ.Common().Offset,
			dwarf.AttrLocation: []byte{byte(op.DW_OP_reg0) + byte(reg)},
			dwarf.AttrVarParam: isret,
		}

		return &godwarf.Tree{
			Entry: e,
			Tag:   dwarf.TagFormalParameter,
		}
	}

	switch bi.Arch.Name {
	case "amd64":
		r := []*godwarf.Tree{
			m("size", t("uintptr"), regnum.AMD64_Rax, false),
			m("typ", t("*runtime._type"), regnum.AMD64_Rbx, false),
			m("needzero", t("bool"), regnum.AMD64_Rcx, false),
			m("~r1", t("unsafe.Pointer"), regnum.AMD64_Rax, true),
		}
		return r, err1
	case "arm64":
		r := []*godwarf.Tree{
			m("size", t("uintptr"), regnum.ARM64_X0, false),
			m("typ", t("*runtime._type"), regnum.ARM64_X0+1, false),
			m("needzero", t("bool"), regnum.ARM64_X0+2, false),
			m("~r1", t("unsafe.Pointer"), regnum.ARM64_X0, true),
		}
		return r, err1
	default:
		// do nothing
		return nil, nil
	}
}


text:
from django.apps import AppConfig

class DjangoSitesSwitchConfig(AppConfig):
    name = 'django_sites_switch'

redpajama_set_name: RedPajamaGithub


text:
ACCEPTED

#### According to
Index Fungorum

#### Published in
Docums Mycol. 16(no. 61): 22 (1985)

#### Original name
Cortinarius mairei var. juranus Rob. Henry

### Remarks
null


text:
package org.hisp.dhis.metadata.orgunits;

import static org.hamcrest.CoreMatchers.*;

import java.io.File;

import org.hamcrest.Matchers;
import org.hisp.dhis.ApiTest;
import org.hisp.dhis.actions.LoginActions;
import org.hisp.dhis.actions.RestApiActions;
import org.hisp.dhis.actions.metadata.MetadataActions;
import org.hisp.dhis.actions.metadata.OrgUnitActions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

/**
 * @author Gintare Vilkelyte <vilkelyte.gintare@gmail.com>
 */
public class OrgUnitsRemovalTest
    extends ApiTest
{
    private OrgUnitActions orgUnitActions;

    private MetadataActions metadataActions;

    private RestApiActions orgUnitGroupActions;

    private RestApiActions orgUnitSetActions;

    private String parentId = "PIBHO8qBw9o";

    private String groupId = "IViMsXfUyWn";

    private String setId = "XcKGktFuGFj";

    @BeforeEach
    public void beforeAll()
    {
        orgUnitActions = new OrgUnitActions();
        orgUnitGroupActions = new RestApiActions( "/organisationUnitGroups" );
        orgUnitSetActions = new RestApiActions( "/organisationUnitGroupSets" );
        metadataActions = new MetadataActions();

        new LoginActions().loginAsSuperUser();

        metadataActions
            .importAndValidateMetadata( new File( "src/test/resources/metadata/orgunits/ou_with_group_and_set.json" ) );

    }

    @Test
    public void shouldRemoveGroupReferenceWhenGroupIsDeleted()
    {
        orgUnitGroupActions.delete( groupId )
            .validate()
            .statusCode( 200 );

        orgUnitActions.get( parentId )
            .validate()
            .statusCode( 200 )
            .body( "organisationUnitGroups.id", is( Matchers.empty() ) );
    }

    @Test
    public void shouldRemoveSetReferenceWhenSetIsDeleted()
    {
        orgUnitSetActions.delete( setId )
            .validate()
            .statusCode( 200 );

        orgUnitActions.get( parentId )
            .validate()
            .statusCode( 200 )
            .body( "organisationUnitGroups.id", Matchers.contains( groupId ) );

        orgUnitGroupActions.get( groupId )
            .validate()
            .statusCode( 200 )
            .body( "groupSets.id", is( Matchers.empty() ) );
    }

    @Test
    public void shouldNotRemoveParentOrgUnit()
    {
        orgUnitActions.delete( parentId )
            .validate()
            .statusCode( 409 )
            .body( "message",
                containsStringIgnoringCase(
                    "Object could not be deleted because it is associated with another object: OrganisationUnit" ) )
            .body( "errorCode", equalTo( "E4030" ) );

    }

}


text:
This reference assumes that you are using the default can function that ships with Lonamic. If you have developed your own can function, you will need to reference that for more details!

### Can User X Do Action Y

As we saw in the [Creating Roles](/usage/creating-roles.md) section, fetching User X is outside the scope of these tutorials. For our purposes, we will assume that somehow you have the user:

```js
const user = { role: 'user' }
const guest = { role = 'guest' }
```

And of course our acl definition:

```js
const Lonamic = require('lonamic').lonamic

const roles = {
  user: {
    can: ['post:write'],
    inherits: ['guest']
  },
  guest: {
    can: ['post:read'],
    inherits: []
  }
}

let lonamic = Lonamic(roles)
```

Great. Using lonamic, we can easily check to see if our guest user can write a post:

```js
console.log(lonamic.can(guest.role, 'post:write')) // Promise { false }
```

Huh. That's not quite what we expected. What is that Promise keyword doing in there? As it turns out, the default Can method in Lonamic returns a promise! This allows us to create some pretty neat things without breaking too much of a sweat. For now, rewrite the above like so:

```js
lonamic.can(guest.role, 'post:write')
  .then(can => {
    console.log(can) // false
  })
```

Or, if you are on the bleeding edge:

```js
async function main() {
    const can = await lonamic.can(guest.role, 'post:write')
    console.log(can) // false
}

main()
```

Or, if you hate promises:

```js
lonamic.can(guest.role, 'post:write', (err, can) => {
  console.log(can) // false
})
```

The important thing to note is that Lonamic does not return the answer directly. You should use the promise interface whenever possible, but Lonamic supports the Callback interface via the common \(err, result\) signature wherever a promise might be returned.

### What About Inheritance?

We still haven't remade that big ugly hydrate function from the first tutorial. Where do we put our hydrator in this Can function?

```js
lonamic.can(user.role, 'post:read').then(console.log) // true
```

Whoa.

The inheritance pattern is so common that, by default, Lonamic will pre-hydrate calls by calling lonamic.hydrate. Of course, just like the Can method, you can also pass in your own Hydrator!

If you would like to directly hydrate a role:

```js
hydrated = lonamic.hydrate('user')
console.log(hydrated.toString()) // rbacl[user] => {"incl":["user","guest"],"can":["post:write","post:read"]}
console.log(hydrated.target) // user
console.log(hydrated.res) // { incl: [ 'user', 'guest' ], can: [ 'post:write', 'post:read' ] }
```

### Next Steps

So far we have finished 2 of the three challenges at the bottom of [Creating Roles](/usage/creating-roles.md). In the [previous article](/usage/lonamic-roles.md), we discovered how to dynamically add roles to our acl \(lonamic returns lonamic on add!\). In this article, we have seen that, by default, calls to our internal lonamic functions return promises. This mindset allows us to bring in asynchronous calls to our system later, without worrying about it now.

Next, let's tackle post edits.


text:
import crypto from 'crypto'
import { parse, ParsedPacket } from 'coap-packet'
import { or, isOption } from './helpers'
import { MiddlewareParameters } from '../models/models'

type middlewareCallback = (nullOrError: null | Error) => void

class MiddleWareError extends Error {
    /**
     * Creates a new `MiddleWareError`.
     *
     * @param middlewareName The middleware function throwing this error.
     */
    constructor (middlewareName: string) {
        super(`${middlewareName}: No CoAP Packet found!`)
    }
}

export function parseRequest (request: MiddlewareParameters, next: middlewareCallback): void {
    try {
        request.packet = parse(request.raw)
        next(null)
    } catch (err) {
        next(err)
    }
}

export function handleServerRequest (request: MiddlewareParameters, next: middlewareCallback): void {
    if (request.proxy != null) {
        return next(null)
    }

    if (request.packet == null) {
        return next(new MiddleWareError('handleServerRequest'))
    }

    try {
        request.server._handle(request.packet, request.rsinfo)
        next(null)
    } catch (err) {
        next(err)
    }
}

export function proxyRequest (request: MiddlewareParameters, next: middlewareCallback): void {
    if (request.packet == null) {
        return next(new MiddleWareError('proxyRequest'))
    }

    for (let i = 0; i < request.packet.options.length; i++) {
        const option = request.packet.options[i]
        if (typeof option.name !== 'string') {
            continue
        } else if (option.name.toLowerCase() === 'proxy-uri') {
            request.proxy = option.value.toString()
        }
    }

    if (request.proxy != null) {
        if (request.packet.token.length === 0) {
            request.packet.token = crypto.randomBytes(8)
        }

        request.server._proxiedRequests.set(request.packet.token.toString('hex'), request)
        request.server._sendProxied(request.packet, request.proxy, next)
    } else {
        next(null)
    }
}

function isObserve (packet: ParsedPacket): boolean {
    return packet.options.map(isOption('Observe')).reduce(or, false)
}

export function handleProxyResponse (request: MiddlewareParameters, next: middlewareCallback): void {
    if (request.proxy != null) {
        return next(null)
    }

    if (request.packet == null) {
        return next(new MiddleWareError('handleProxyResponse'))
    }

    const originalProxiedRequest = request.server._proxiedRequests.get(request.packet.token.toString('hex'))
    if (originalProxiedRequest != null) {
        request.server._sendReverseProxied(request.packet, originalProxiedRequest.rsinfo)

        if (!isObserve(request.packet)) {
            request.server._proxiedRequests.delete(request.packet.token.toString('hex'))
        }
    }

    next(null)
}


text:
import React, { Component } from 'react';
import styles from './StatusBar.css'; // eslint-disable-line flowtype-errors/show-errors

export default class StatusBar extends Component {
  props: {
    selectedFilename: string,
    lines: number,
    characters: number,
    loadedIn: number,
    isEdited: boolean,
    isSaved: boolean
  }

  determineStatus(): string {
    if (this.props.isSaved) {
      return styles.statusBarSaved;
    }

    if (this.props.isEdited) {
      return styles.statusBarEdited;
    }

    return styles.statusBar;
  }

  determineNotification(): string {
    if (this.props.isEdited) {
      return 'NOT SAVED';
    }

    if (this.props.isSaved) {
      return 'SAVED SUCCESSFULLY';
    }
  }

  render() {
    return (

          {this.props.selectedFilename ? this.props.selectedFilename : 'Template not loaded'}
          {this.props.isEdited ? ' (EDITED)' : ''}

          {this.determineNotification()}

          Lines: {this.props.lines} |
          Characters: {this.props.characters} |
          Loaded in ~{this.props.loadedIn}ms

);
  }
}


text:
import $ from 'jquery';
import Auth from './Auth';
import request from 'superagent';

const BASE_URL = 'http://localhost:3001';
const CONTENT_TYPE = 'application/json';
const CLOUDINARY_UPLOAD_URL = 'https://api.cloudinary.com/v1_1/showdown/image/upload';
const COMBATANT_IMAGE_PRESET = 'combatant_image';
// const FILE_NAME_PREFIX = 'sd_combatant_image_';

export default class Requester {
    static get({ url, authenticated }) {
        let request = {
            type: 'get',
            url: `${BASE_URL}/${url}`
        };
        if (authenticated) {
            let authenticationHeader = `barear ${Auth.getToken()}`;
            request.headers = { 'Authentication': authenticationHeader }
        }

        return $.ajax(request);
    }

    static post({ url, data }) {
        let authenticationHeader = `barear ${Auth.getToken()}`;
        let request = {
            type: 'post',
            url: `${BASE_URL}/${url}`,
            data: JSON.stringify(data),
            headers: {
                'Content-Type': CONTENT_TYPE,
                'Authentication': authenticationHeader
            }
        };

        return $.ajax(request);
    }

    static uploadImage(file) {
        return new Promise((resolve, reject) => {
            let upload = request.post(CLOUDINARY_UPLOAD_URL)
                        .field('upload_preset', COMBATANT_IMAGE_PRESET)
                        .field('file', file);

            upload.end((err, response) => {
                if (err) {
                    reject(err);
                }

                if (response.body.secure_url !== '') {
                    resolve(response.body.secure_url);
                }
            });
        });
    }
}


text:
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/file.h>
#include <linux/signal.h>
#include <linux/resource.h>
#include <linux/times.h>
#include <linux/smp.h>
#include <linux/smp_lock.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
#include <linux/poll.h>
#include <linux/personality.h>
#include <linux/stat.h>
#include <linux/mman.h>
#include <linux/in.h>
#include <linux/syscalls.h>
#include <linux/unistd.h>
#include <linux/sysctl.h>
#include <linux/binfmts.h>
#include <linux/security.h>
#include <linux/compat.h>
#include <linux/ptrace.h>
#include <linux/elf.h>
#include <linux/ipc.h>

#include <asm/ptrace.h>
#include <asm/types.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include <asm/time.h>
#include <asm/mmu_context.h>
#include <asm/ppc-pci.h>
#include <asm/syscalls.h>

asmlinkage long ppc32_select(u32 n, compat_ulong_t __user *inp,
		compat_ulong_t __user *outp, compat_ulong_t __user *exp,
		compat_uptr_t tvp_x)
{
	/* sign extend n */
	return compat_sys_select((int)n, inp, outp, exp, compat_ptr(tvp_x));
}

/* Note: it is necessary to treat option as an unsigned int,
 * with the corresponding cast to a signed int to insure that the
 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 */
asmlinkage long compat_sys_sysfs(u32 option, u32 arg1, u32 arg2)
{
	return sys_sysfs((int)option, arg1, arg2);
}

#ifdef CONFIG_SYSVIPC
long compat_sys_ipc(u32 call, u32 first, u32 second, u32 third, compat_uptr_t ptr,
	       u32 fifth)
{
	int version;

	version = call >> 16; /* hack for backward compatibility */
	call &= 0xffff;

	switch (call) {

	case SEMTIMEDOP:
		if (fifth)
			/* sign extend semid */
			return compat_sys_semtimedop((int)first,
						     compat_ptr(ptr), second,
						     compat_ptr(fifth));
		/* else fall through for normal semop() */
	case SEMOP:
		/* struct sembuf is the same on 32 and 64bit :)) */
		/* sign extend semid */
		return sys_semtimedop((int)first, compat_ptr(ptr), second,
				      NULL);
	case SEMGET:
		/* sign extend key, nsems */
		return sys_semget((int)first, (int)second, third);
	case SEMCTL:
		/* sign extend semid, semnum */
		return compat_sys_semctl((int)first, (int)second, third,
					 compat_ptr(ptr));

	case MSGSND:
		/* sign extend msqid */
		return compat_sys_msgsnd((int)first, (int)second, third,
					 compat_ptr(ptr));
	case MSGRCV:
		/* sign extend msqid, msgtyp */
		return compat_sys_msgrcv((int)first, second, (int)fifth,
					 third, version, compat_ptr(ptr));
	case MSGGET:
		/* sign extend key */
		return sys_msgget((int)first, second);
	case MSGCTL:
		/* sign extend msqid */
		return compat_sys_msgctl((int)first, second, compat_ptr(ptr));

	case SHMAT:
		/* sign extend shmid */
		return compat_sys_shmat((int)first, second, third, version,
					compat_ptr(ptr));
	case SHMDT:
		return sys_shmdt(compat_ptr(ptr));
	case SHMGET:
		/* sign extend key_t */
		return sys_shmget((int)first, second, third);
	case SHMCTL:
		/* sign extend shmid */
		return compat_sys_shmctl((int)first, second, compat_ptr(ptr));

	default:
		return -ENOSYS;
	}

	return -ENOSYS;
}
#endif

/* Note: it is necessary to treat out_fd and in_fd as unsigned ints,
 * with the corresponding cast to a signed int to insure that the
 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 */
asmlinkage long compat_sys_sendfile(u32 out_fd, u32 in_fd, compat_off_t __user * offset, u32 count)
{
	mm_segment_t old_fs = get_fs();
	int ret;
	off_t of;
	off_t __user *up;

	if (offset && get_user(of, offset))
		return -EFAULT;

	/* The __user pointer cast is valid because of the set_fs() */
	set_fs(KERNEL_DS);
	up = offset ? (off_t __user *) &of : NULL;
	ret = sys_sendfile((int)out_fd, (int)in_fd, up, count);
	set_fs(old_fs);

	if (offset && put_user(of, offset))
		return -EFAULT;

	return ret;
}

asmlinkage int compat_sys_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset, s32 count)
{
	mm_segment_t old_fs = get_fs();
	int ret;
	loff_t lof;
	loff_t __user *up;

	if (offset && get_user(lof, offset))
		return -EFAULT;

	/* The __user pointer cast is valid because of the set_fs() */
	set_fs(KERNEL_DS);
	up = offset ? (loff_t __user *) &lof : NULL;
	ret = sys_sendfile64(out_fd, in_fd, up, count);
	set_fs(old_fs);

	if (offset && put_user(lof, offset))
		return -EFAULT;

	return ret;
}

long compat_sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
		  unsigned long a3, unsigned long a4, unsigned long a5,
		  struct pt_regs *regs)
{
	int error;
	char * filename;

	filename = getname((char __user *) a0);
	error = PTR_ERR(filename);
	if (IS_ERR(filename))
		goto out;
	flush_fp_to_thread(current);
	flush_altivec_to_thread(current);

	error = compat_do_execve(filename, compat_ptr(a1), compat_ptr(a2), regs);

	putname(filename);

out:
	return error;
}

/* Note: it is necessary to treat option as an unsigned int,
 * with the corresponding cast to a signed int to insure that the
 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 */
asmlinkage long compat_sys_prctl(u32 option, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
{
	return sys_prctl((int)option,
			 (unsigned long) arg2,
			 (unsigned long) arg3,
			 (unsigned long) arg4,
			 (unsigned long) arg5);
}

/* Note: it is necessary to treat pid as an unsigned int,
 * with the corresponding cast to a signed int to insure that the
 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 */
asmlinkage long compat_sys_sched_rr_get_interval(u32 pid, struct compat_timespec __user *interval)
{
	struct timespec t;
	int ret;
	mm_segment_t old_fs = get_fs ();

	/* The __user pointer cast is valid because of the set_fs() */
	set_fs (KERNEL_DS);
	ret = sys_sched_rr_get_interval((int)pid, (struct timespec __user *) &t);
	set_fs (old_fs);
	if (put_compat_timespec(&t, interval))
		return -EFAULT;
	return ret;
}

/* Note: it is necessary to treat mode as an unsigned int,
 * with the corresponding cast to a signed int to insure that the
 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 */
asmlinkage long compat_sys_access(const char __user * filename, u32 mode)
{
	return sys_access(filename, (int)mode);
}

/* Note: it is necessary to treat mode as an unsigned int,
 * with the corresponding cast to a signed int to insure that the
 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 */
asmlinkage long compat_sys_creat(const char __user * pathname, u32 mode)
{
	return sys_creat(pathname, (int)mode);
}

/* Note: it is necessary to treat pid and options as unsigned ints,
 * with the corresponding cast to a signed int to insure that the
 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 */
asmlinkage long compat_sys_waitpid(u32 pid, unsigned int __user * stat_addr, u32 options)
{
	return sys_waitpid((int)pid, stat_addr, (int)options);
}

/* Note: it is necessary to treat gidsetsize as an unsigned int,
 * with the corresponding cast to a signed int to insure that the
 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 */
asmlinkage long compat_sys_getgroups(u32 gidsetsize, gid_t __user *grouplist)
{
	return sys_getgroups((int)gidsetsize, grouplist);
}

/* Note: it is necessary to treat pid as an unsigned int,
 * with the corresponding cast to a signed int to insure that the
 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 */
asmlinkage long compat_sys_getpgid(u32 pid)
{
	return sys_getpgid((int)pid);
}

/* Note: it is necessary to treat pid as an unsigned int,
 * with the corresponding cast to a signed int to insure that the
 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 */
asmlinkage long compat_sys_getsid(u32 pid)
{
	return sys_getsid((int)pid);
}

/* Note: it is necessary to treat pid and sig as unsigned ints,
 * with the corresponding cast to a signed int to insure that the
 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 */
asmlinkage long compat_sys_kill(u32 pid, u32 sig)
{
	return sys_kill((int)pid, (int)sig);
}

/* Note: it is necessary to treat mode as an unsigned int,
 * with the corresponding cast to a signed int to insure that the
 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 */
asmlinkage long compat_sys_mkdir(const char __user * pathname, u32 mode)
{
	return sys_mkdir(pathname, (int)mode);
}

long compat_sys_nice(u32 increment)
{
	/* sign extend increment */
	return sys_nice((int)increment);
}

off_t ppc32_lseek(unsigned int fd, u32 offset, unsigned int origin)
{
	/* sign extend n */
	return sys_lseek(fd, (int)offset, origin);
}

long compat_sys_truncate(const char __user * path, u32 length)
{
	/* sign extend length */
	return sys_truncate(path, (int)length);
}

long compat_sys_ftruncate(int fd, u32 length)
{
	/* sign extend length */
	return sys_ftruncate(fd, (int)length);
}

/* Note: it is necessary to treat bufsiz as an unsigned int,
 * with the corresponding cast to a signed int to insure that the
 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 */
asmlinkage long compat_sys_readlink(const char __user * path, char __user * buf, u32 bufsiz)
{
	return sys_readlink(path, buf, (int)bufsiz);
}

/* Note: it is necessary to treat option as an unsigned int,
 * with the corresponding cast to a signed int to insure that the
 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 */
asmlinkage long compat_sys_sched_get_priority_max(u32 policy)
{
	return sys_sched_get_priority_max((int)policy);
}

/* Note: it is necessary to treat policy as an unsigned int,
 * with the corresponding cast to a signed int to insure that the
 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 */
asmlinkage long compat_sys_sched_get_priority_min(u32 policy)
{
	return sys_sched_get_priority_min((int)policy);
}

/* Note: it is necessary to treat pid as an unsigned int,
 * with the corresponding cast to a signed int to insure that the
 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 */
asmlinkage long compat_sys_sched_getparam(u32 pid, struct sched_param __user *param)
{
	return sys_sched_getparam((int)pid, param);
}

/* Note: it is necessary to treat pid as an unsigned int,
 * with the corresponding cast to a signed int to insure that the
 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 */
asmlinkage long compat_sys_sched_getscheduler(u32 pid)
{
	return sys_sched_getscheduler((int)pid);
}

/* Note: it is necessary to treat pid as an unsigned int,
 * with the corresponding cast to a signed int to insure that the
 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 */
asmlinkage long compat_sys_sched_setparam(u32 pid, struct sched_param __user *param)
{
	return sys_sched_setparam((int)pid, param);
}

/* Note: it is necessary to treat pid and policy as unsigned ints,
 * with the corresponding cast to a signed int to insure that the
 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 */
asmlinkage long compat_sys_sched_setscheduler(u32 pid, u32 policy, struct sched_param __user *param)
{
	return sys_sched_setscheduler((int)pid, (int)policy, param);
}

/* Note: it is necessary to treat len as an unsigned int,
 * with the corresponding cast to a signed int to insure that the
 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 */
asmlinkage long compat_sys_setdomainname(char __user *name, u32 len)
{
	return sys_setdomainname(name, (int)len);
}

/* Note: it is necessary to treat gidsetsize as an unsigned int,
 * with the corresponding cast to a signed int to insure that the
 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 */
asmlinkage long compat_sys_setgroups(u32 gidsetsize, gid_t __user *grouplist)
{
	return sys_setgroups((int)gidsetsize, grouplist);
}

asmlinkage long compat_sys_sethostname(char __user *name, u32 len)
{
	/* sign extend len */
	return sys_sethostname(name, (int)len);
}

/* Note: it is necessary to treat pid and pgid as unsigned ints,
 * with the corresponding cast to a signed int to insure that the
 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 */
asmlinkage long compat_sys_setpgid(u32 pid, u32 pgid)
{
	return sys_setpgid((int)pid, (int)pgid);
}

long compat_sys_getpriority(u32 which, u32 who)
{
	/* sign extend which and who */
	return sys_getpriority((int)which, (int)who);
}

long compat_sys_setpriority(u32 which, u32 who, u32 niceval)
{
	/* sign extend which, who and niceval */
	return sys_setpriority((int)which, (int)who, (int)niceval);
}

long compat_sys_ioprio_get(u32 which, u32 who)
{
	/* sign extend which and who */
	return sys_ioprio_get((int)which, (int)who);
}

long compat_sys_ioprio_set(u32 which, u32 who, u32 ioprio)
{
	/* sign extend which, who and ioprio */
	return sys_ioprio_set((int)which, (int)who, (int)ioprio);
}

/* Note: it is necessary to treat newmask as an unsigned int,
 * with the corresponding cast to a signed int to insure that the
 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 */
asmlinkage long compat_sys_ssetmask(u32 newmask)
{
	return sys_ssetmask((int) newmask);
}

asmlinkage long compat_sys_syslog(u32 type, char __user * buf, u32 len)
{
	/* sign extend len */
	return sys_syslog(type, buf, (int)len);
}

/* Note: it is necessary to treat mask as an unsigned int,
 * with the corresponding cast to a signed int to insure that the
 * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode)
 * and the register representation of a signed int (msr in 64-bit mode) is performed.
 */
asmlinkage long compat_sys_umask(u32 mask)
{
	return sys_umask((int)mask);
}

#ifdef CONFIG_SYSCTL_SYSCALL
struct __sysctl_args32 {
	u32 name;
	int nlen;
	u32 oldval;
	u32 oldlenp;
	u32 newval;
	u32 newlen;
	u32 __unused[4];
};

asmlinkage long compat_sys_sysctl(struct __sysctl_args32 __user *args)
{
	struct __sysctl_args32 tmp;
	int error;
	size_t oldlen;
	size_t __user *oldlenp = NULL;
	unsigned long addr = (((unsigned long)&args->__unused[0]) + 7) & ~7;

	if (copy_from_user(&tmp, args, sizeof(tmp)))
		return -EFAULT;

	if (tmp.oldval && tmp.oldlenp) {
		/* Duh, this is ugly and might not work if sysctl_args
		   is in read-only memory, but do_sysctl does indirectly
		   a lot of uaccess in both directions and we'd have to
		   basically copy the whole sysctl.c here, and
		   glibc's __sysctl uses rw memory for the structure
		   anyway.  */
		oldlenp = (size_t __user *)addr;
		if (get_user(oldlen, (compat_size_t __user *)compat_ptr(tmp.oldlenp)) ||
		    put_user(oldlen, oldlenp))
			return -EFAULT;
	}

	lock_kernel();
	error = do_sysctl(compat_ptr(tmp.name), tmp.nlen,
			  compat_ptr(tmp.oldval), oldlenp,
			  compat_ptr(tmp.newval), tmp.newlen);
	unlock_kernel();
	if (oldlenp) {
		if (!error) {
			if (get_user(oldlen, oldlenp) ||
			    put_user(oldlen, (compat_size_t __user *)compat_ptr(tmp.oldlenp)))
				error = -EFAULT;
		}
		copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
	}
	return error;
}
#endif

unsigned long compat_sys_mmap2(unsigned long addr, size_t len,
			  unsigned long prot, unsigned long flags,
			  unsigned long fd, unsigned long pgoff)
{
	/* This should remain 12 even if PAGE_SIZE changes */
	return sys_mmap(addr, len, prot, flags, fd, pgoff << 12);
}

long compat_sys_tgkill(u32 tgid, u32 pid, int sig)
{
	/* sign extend tgid, pid */
	return sys_tgkill((int)tgid, (int)pid, sig);
}

/*
 * long long munging:
 * The 32 bit ABI passes long longs in an odd even register pair.
 */

compat_ssize_t compat_sys_pread64(unsigned int fd, char __user *ubuf, compat_size_t count,
			     u32 reg6, u32 poshi, u32 poslo)
{
	return sys_pread64(fd, ubuf, count, ((loff_t)poshi << 32) | poslo);
}

compat_ssize_t compat_sys_pwrite64(unsigned int fd, char __user *ubuf, compat_size_t count,
			      u32 reg6, u32 poshi, u32 poslo)
{
	return sys_pwrite64(fd, ubuf, count, ((loff_t)poshi << 32) | poslo);
}

compat_ssize_t compat_sys_readahead(int fd, u32 r4, u32 offhi, u32 offlo, u32 count)
{
	return sys_readahead(fd, ((loff_t)offhi << 32) | offlo, count);
}

asmlinkage int compat_sys_truncate64(const char __user * path, u32 reg4,
				unsigned long high, unsigned long low)
{
	return sys_truncate(path, (high << 32) | low);
}

asmlinkage long compat_sys_fallocate(int fd, int mode, u32 offhi, u32 offlo,
				     u32 lenhi, u32 lenlo)
{
	return sys_fallocate(fd, mode, ((loff_t)offhi << 32) | offlo,
			     ((loff_t)lenhi << 32) | lenlo);
}

asmlinkage int compat_sys_ftruncate64(unsigned int fd, u32 reg4, unsigned long high,
				 unsigned long low)
{
	return sys_ftruncate(fd, (high << 32) | low);
}

long ppc32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char __user *buf,
			  size_t len)
{
	return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low,
				  buf, len);
}

long ppc32_fadvise64(int fd, u32 unused, u32 offset_high, u32 offset_low,
		     size_t len, int advice)
{
	return sys_fadvise64(fd, (u64)offset_high << 32 | offset_low, len,
			     advice);
}

asmlinkage long compat_sys_add_key(const char __user *_type,
			      const char __user *_description,
			      const void __user *_payload,
			      u32 plen,
			      u32 ringid)
{
	return sys_add_key(_type, _description, _payload, plen, ringid);
}

asmlinkage long compat_sys_request_key(const char __user *_type,
				  const char __user *_description,
				  const char __user *_callout_info,
				  u32 destringid)
{
	return sys_request_key(_type, _description, _callout_info, destringid);
}

asmlinkage long compat_sys_sync_file_range2(int fd, unsigned int flags,
				   unsigned offset_hi, unsigned offset_lo,
				   unsigned nbytes_hi, unsigned nbytes_lo)
{
	loff_t offset = ((loff_t)offset_hi << 32) | offset_lo;
	loff_t nbytes = ((loff_t)nbytes_hi << 32) | nbytes_lo;

	return sys_sync_file_range(fd, offset, nbytes, flags);
}


text:
import os
from contextlib import contextmanager
import pytest
from astropy.io.ascii.tests.common import assert_equal
from ... import besancon
from ...utils import commons
from ...utils.testing_tools import MockResponse

# SKIP - don't run tests because Besancon folks don't want them (based on
# the fact that your@email.net is now rejected)
# def test_besancon_reader():
# assert os.path.exists('besancon_test.txt')
#     B = asciitable.read('t/besancon_test.txt',
#                         Reader=besancon.BesanconFixed, guess=False)
#     assert_equal(len(B),12)
#
# def test_basic():
#     besancon_model = besancon.request_besancon(
#         'astropy.astroquery@gmail.com',10.5,0.0,soli=0.0001)
#     B = asciitable.read(besancon_model,
#                         Reader=besancon.BesanconFixed, guess=False)
#     B.pprint()

# to prevent test hanging
besancon.Besancon.TIMEOUT = 1
besancon.Besancon.ping_delay = 1

DATA_FILES = ('besancon_test.txt', 'besancon_test2.txt')

def data_path(filename):
    data_dir = os.path.join(os.path.dirname(__file__), 'data')
    return os.path.join(data_dir, filename)

@pytest.mark.parametrize(('filename', 'length', 'ncols', 'd1', 'mv1'),
                         zip(DATA_FILES, (13, 6), (18, 24), (0.091, 0.111),
                             (10.20, 9.70)))
def test_reader(filename, length, ncols, d1, mv1):
    besancon_model = data_path(filename)
    with open(besancon_model, 'r') as f:
        data = f.read()
    B = besancon.core.parse_besancon_model_string(data)
    B.pprint()
    assert_equal(len(B), length)
    assert_equal(len(B.columns), ncols)
    assert B['Dist'][0] == d1
    assert B['Mv'][0] == mv1

@pytest.fixture
def patch_post(request):
    mp = request.getfixturevalue("monkeypatch")

    mp.setattr(besancon.Besancon, '_request', post_mockreturn)
    return mp

@pytest.fixture
def patch_get_readable_fileobj(request):
    @contextmanager
    def get_readable_fileobj_mockreturn(filename, **kwargs):
        if isinstance(filename, str):
            if '1376235131.430670' in filename:
                is_binary = kwargs.get('encoding', None) == 'binary'
                file_obj = open(data_path('1376235131.430670.resu'),
                                "r" + ('b' if is_binary else ''))
        else:
            file_obj = filename
        yield file_obj

    mp = request.getfixturevalue("monkeypatch")

    mp.setattr(commons, 'get_readable_fileobj',
               get_readable_fileobj_mockreturn)
    return mp

def post_mockreturn(method, url, data, timeout=10, stream=True, **kwargs):
    filename = data_path('query_return.iframe.html')
    content = open(filename, 'rb').read()
    return MockResponseBesancon(content, filename, **kwargs)

def test_query(patch_post, patch_get_readable_fileobj):
    result = besancon.Besancon.query(0, 0, 'a@b.com')
    assert result is not None

def test_default_params():
    """ Ensure that the default parameters of the query match the default
    parameters on the web form (excepting coordinates and e-mail address) """
    data = besancon.Besancon.query_async(0, 0, 'a@b.com',
                                         get_query_payload=True)

    with open(data_path('default_params.txt')) as f:
        dp = eval(f.read())

    for k in dp:
        assert dp[k] == data[k]

class MockResponseBesancon(MockResponse):

    def __init__(self, content=None, url=None, headers={}, **kwargs):
        super(MockResponseBesancon, self).__init__(content)
        self.raw = url  # StringIO.StringIO(url)
        self.headers = headers


text:
from js2py.base import *

def _get_conts(idl):
    def is_valid(c):
        try:
            exec(c)
            return 1
        except:
            pass
    return '\n'.join(filter(is_valid, (' '.join(e.strip(' ;').split()[-3:]) for e in idl.splitlines())))

default_attrs = {'writable':True, 'enumerable':True, 'configurable':True}

def compose_prototype(Class, attrs=default_attrs):
    prototype = Class()
    for i in dir(Class):
        e = getattr(Class, i)
        if hasattr(e, '__func__'):
            temp = PyJsFunction(e.__func__, FunctionPrototype)
            attrs = {k:v for k,v in attrs.iteritems()}
            attrs['value'] = temp
            prototype.define_own_property(i, attrs)
    return prototype

# Error codes

INDEX_SIZE_ERR = 1
DOMSTRING_SIZE_ERR = 2
HIERARCHY_REQUEST_ERR = 3
WRONG_DOCUMENT_ERR = 4
INVALID_CHARACTER_ERR = 5
NO_DATA_ALLOWED_ERR = 6
NO_MODIFICATION_ALLOWED_ERR = 7
NOT_FOUND_ERR = 8
NOT_SUPPORTED_ERR = 9
INUSE_ATTRIBUTE_ERR = 10
INVALID_STATE_ERR = 11
SYNTAX_ERR = 12
INVALID_MODIFICATION_ERR = 13
NAMESPACE_ERR = 14
INVALID_ACCESS_ERR = 15
VALIDATION_ERR = 16
TYPE_MISMATCH_ERR = 17


text:
import { RcModuleV2 } from '@ringcentral-integration/core';
import EventEmitter from 'events';
import { Module } from 'ringcentral-integration/lib/di';
import {
  EvClientCallBackValueType,
  EvClientCallMapping,
} from '../../lib/EvClient/interfaces';
import { DepsModules, Subscription } from './EvSubscription.interface';

@Module({
  name: 'EvSubscription',
  deps: ['EvClient', { dep: 'EvSubscriptionOptions', optional: true }],
})
class EvSubscription extends RcModuleV2<DepsModules> implements Subscription {
  protected eventEmitters = new EventEmitter();

  constructor({ evClient }) {
    super({
      modules: {
        evClient,
      },
    });
  }

  emit<T extends EvClientCallBackValueType, K extends EvClientCallMapping[T]>(
    event: T,
    value: K,
  ) {
    this.eventEmitters.emit(event, value);
  }

  subscribe<
    T extends EvClientCallBackValueType,
    K extends EvClientCallMapping[T]
  >(event: T, listener: (data?: K) => any) {
    if (!this._modules.evClient.getEventCallback(event)) {
      this._modules.evClient.on(event, (...args: any[]) => {
        this.eventEmitters.emit(event, ...args);
      });
    }
    this.eventEmitters.on(event, listener);
  }
}

export { EvSubscription };


text:
<?php namespace CodeIgniter\Log\Exceptions;

use CodeIgniter\Exceptions\ExceptionInterface;
use CodeIgniter\Exceptions\FrameworkException;

class LogException extends FrameworkException implements ExceptionInterface
{
	public static function forInvalidLogLevel(string $level)
	{
		return new static(lang('Log.invalidLogLevel', [$level]));
	}

}


text:
/*=========================
  Init/Destroy
  ===========================*/
s.init = function () {
    if (s.params.loop) s.createLoop();
    s.updateContainerSize();
    s.updateSlidesSize();
    s.updatePagination();
    if (s.params.scrollbar && s.scrollbar) {
        s.scrollbar.set();
    }
    if (s.params.effect !== 'slide' && s.effects[s.params.effect]) {
        if (!s.params.loop) s.updateProgress();
        s.effects[s.params.effect].setTranslate();
    }
    if (s.params.loop) {
        s.slideTo(s.params.initialSlide + s.loopedSlides, 0, s.params.runCallbacksOnInit);
    }
    else {
        s.slideTo(s.params.initialSlide, 0, s.params.runCallbacksOnInit);
        if (s.params.initialSlide === 0) {
            if (s.parallax && s.params.parallax) s.parallax.setTranslate();
            if (s.lazy && s.params.lazyLoading) {
                s.lazy.load();
                s.lazy.initialImageLoaded = true;
            }
        }
    }
    s.attachEvents();
    if (s.params.observer && s.support.observer) {
        s.initObservers();
    }
    if (s.params.preloadImages && !s.params.lazyLoading) {
        s.preloadImages();
    }
    if (s.params.autoplay) {
        s.startAutoplay();
    }
    if (s.params.keyboardControl) {
        if (s.enableKeyboardControl) s.enableKeyboardControl();
    }
    if (s.params.mousewheelControl) {
        if (s.enableMousewheelControl) s.enableMousewheelControl();
    }
    if (s.params.hashnav) {
        if (s.hashnav) s.hashnav.init();
    }
    if (s.params.a11y && s.a11y) s.a11y.init();
    s.emit('onInit', s);
};

// Cleanup dynamic styles
s.cleanupStyles = function () {
    // Container
    s.container.removeClass(s.classNames.join(' ')).removeAttr('style');

    // Wrapper
    s.wrapper.removeAttr('style');

    // Slides
    if (s.slides && s.slides.length) {
        s.slides
            .removeClass([
              s.params.slideVisibleClass,
              s.params.slideActiveClass,
              s.params.slideNextClass,
              s.params.slidePrevClass
            ].join(' '))
            .removeAttr('style')
            .removeAttr('data-swiper-column')
            .removeAttr('data-swiper-row');
    }

    // Pagination/Bullets
    if (s.paginationContainer && s.paginationContainer.length) {
        s.paginationContainer.removeClass(s.params.paginationHiddenClass);
    }
    if (s.bullets && s.bullets.length) {
        s.bullets.removeClass(s.params.bulletActiveClass);
    }

    // Buttons
    if (s.params.prevButton) $(s.params.prevButton).removeClass(s.params.buttonDisabledClass);
    if (s.params.nextButton) $(s.params.nextButton).removeClass(s.params.buttonDisabledClass);

    // Scrollbar
    if (s.params.scrollbar && s.scrollbar) {
        if (s.scrollbar.track && s.scrollbar.track.length) s.scrollbar.track.removeAttr('style');
        if (s.scrollbar.drag && s.scrollbar.drag.length) s.scrollbar.drag.removeAttr('style');
    }
};

// Destroy
s.destroy = function (deleteInstance, cleanupStyles) {
    // Detach evebts
    s.detachEvents();
    // Stop autoplay
    s.stopAutoplay();
    // Destroy loop
    if (s.params.loop) {
        s.destroyLoop();
    }
    // Cleanup styles
    if (cleanupStyles) {
        s.cleanupStyles();
    }
    // Disconnect observer
    s.disconnectObservers();
    // Disable keyboard/mousewheel
    if (s.params.keyboardControl) {
        if (s.disableKeyboardControl) s.disableKeyboardControl();
    }
    if (s.params.mousewheelControl) {
        if (s.disableMousewheelControl) s.disableMousewheelControl();
    }
    // Disable a11y
    if (s.params.a11y && s.a11y) s.a11y.destroy();
    // Destroy callback
    s.emit('onDestroy');
    // Delete instance
    if (deleteInstance !== false) s = null;
};

s.init();


text:
Describe "Supervisor restarts on abrupt exit" {
    $exit_file = New-TemporaryFile
    $env:HAB_FEAT_TEST_EXIT = $exit_file
    $supLog = New-SupervisorLogFile("supervisor_restarts_on_abrupt_exit")
    $launcher_proc = Start-Supervisor -Timeout 45 -LogFile $supLog
    $supervisor_proc = Get-Process hab-sup
    Set-Content $exit_file -Value 1

    $testScript = { $supervisor_proc.HasExited }
    $timeoutScript = { Write-Error "Timed out waiting for Supervisor to exit" }
    Wait-True -TestScript $testScript -TimeoutScript $timeoutScript -Timeout 45

    $testScript = { Get-Process hab-sup -ErrorAction SilentlyContinue }
    $timeoutScript = { Write-Error "Timed out waiting for Supervisor to be restarted" }
    Wait-True -TestScript $testScript -TimeoutScript $timeoutScript -Timeout 45

    $new_supervisor_proc = Get-Process hab-sup
    $new_launcher_proc = Get-Process hab-launch

    It "will not exit the launcher" {
        $launcher_proc.HasExited | Should -Be $false
    }
    It "will spawn a new supervisor" {
        $new_supervisor_proc.Id | Should -Not -Be $supervisor_proc.Id
    }
    It "will not spawn a new launcher" {
        $new_launcher_proc.Id | Should -Be $launcher_proc.Id
    }

    AfterAll {
        Stop-Supervisor
    }
}

Describe "Supervisor restarts on 'hab sup restart'" {
    $supLog = New-SupervisorLogFile("supervisor_restarts_on_hab_sup_restart")
    $launcher_proc = Start-Supervisor -Timeout 45 -LogFile $supLog
    $supervisor_proc = Get-Process hab-sup
    Invoke-NativeCommand hab sup restart

    $testScript = { $supervisor_proc.HasExited }
    $timeoutScript = { Write-Error "Timed out waiting for Supervisor to exit" }
    Wait-True -TestScript $testScript -TimeoutScript $timeoutScript -Timeout 45

    $testScript = { Get-Process hab-sup -ErrorAction SilentlyContinue }
    $timeoutScript = { Write-Error "Timed out waiting for Supervisor to be restarted" }
    Wait-True -TestScript $testScript -TimeoutScript $timeoutScript -Timeout 45

    $new_supervisor_proc = Get-Process hab-sup
    $new_launcher_proc = Get-Process hab-launch

    It "will not exit the launcher" {
        $launcher_proc.HasExited | Should -Be $false
    }
    It "will spawn a new supervisor" {
        $new_supervisor_proc.Id | Should -Not -Be $supervisor_proc.Id
    }
    It "will not spawn a new launcher" {
        $new_launcher_proc.Id | Should -Be $launcher_proc.Id
    }

    AfterAll {
        Stop-Supervisor
    }
}


text:
import urllib
from django import template
from django.conf import settings
from journalmanager.models import UserProfile

SIZE_LARGE = 64
SIZE_MEDIUM = 32
SIZE_SMALL = 18

register = template.Library()
def user_avatar_url(user, size):
    size = size.lower()
    if size == 'large':
        size = SIZE_LARGE
    elif size == 'medium':
        size = SIZE_MEDIUM
    elif size == 'small':
        size = SIZE_SMALL
    elif size.isdigit() and int(size) > 0:
        size = int(size)
    else:
        return '' # unknow size, no photo

    try:
        user_gravatar_id = user.get_profile().gravatar_id
    except UserProfile.DoesNotExist:
        return '' # no profile, no photo
    else:
        params = urllib.urlencode({'s': size, 'd': 'mm'})
        gravatar_url = getattr(settings, 'GRAVATAR_BASE_URL', 'https://secure.gravatar.com')
        avartar_url = '{0}/avatar/{1}?{2}'.format(gravatar_url, user_gravatar_id, params)
        return avartar_url

register.simple_tag(user_avatar_url)


text:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <ListView
        android:id="@+id/ClaimListView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_above="@+id/addClaimButton"
        android:layout_below="@+id/textView1"
        android:layout_centerHorizontal="true" >

    </ListView>

    <Button
        android:id="@+id/addClaimButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/ClaimListView"
        android:layout_alignParentBottom="true"
        android:layout_alignRight="@+id/ClaimListView"
        android:onClick="addClaimButtonAction"
        android:text="@string/add_claim" />

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/ClaimListView"
        android:layout_alignParentTop="true"
        android:text="@string/welcome_to_travel_expense_tracker"
        android:textAppearance="?android:attr/textAppearanceLarge" />

</RelativeLayout>


text:
package com.intellij.uiDesigner.radComponents;

import com.intellij.openapi.project.Project;
import com.intellij.uiDesigner.UIDesignerBundle;
import com.intellij.uiDesigner.UIFormXmlConstants;
import com.intellij.uiDesigner.XmlWriter;
import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.uiDesigner.designSurface.ComponentDragObject;
import com.intellij.uiDesigner.designSurface.ComponentDropLocation;
import com.intellij.uiDesigner.designSurface.FeedbackLayer;
import com.intellij.uiDesigner.designSurface.GuiEditor;
import com.intellij.uiDesigner.propertyInspector.Property;
import com.intellij.uiDesigner.propertyInspector.PropertyEditor;
import com.intellij.uiDesigner.propertyInspector.PropertyRenderer;
import com.intellij.uiDesigner.propertyInspector.editors.AbstractTextFieldEditor;
import com.intellij.uiDesigner.propertyInspector.properties.HGapProperty;
import com.intellij.uiDesigner.propertyInspector.properties.VGapProperty;
import com.intellij.uiDesigner.propertyInspector.renderers.LabelPropertyRenderer;
import com.intellij.uiDesigner.snapShooter.SnapshotContext;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.CardLayout;
import java.awt.LayoutManager;
import java.awt.Point;
import java.awt.Rectangle;
import java.lang.reflect.Field;
import java.util.Vector;
import java.util.List;

/**
 * @author yole
 */
public class RadCardLayoutManager extends RadLayoutManager {
  @Nullable
  public String getName() {
    return UIFormXmlConstants.LAYOUT_CARD;
  }

  @Override @Nullable
  public LayoutManager createLayout() {
    return new CardLayout();
  }

  public void writeChildConstraints(final XmlWriter writer, final RadComponent child) {
    writer.startElement(UIFormXmlConstants.ELEMENT_CARD);
    try {
      writer.addAttribute(UIFormXmlConstants.ATTRIBUTE_NAME, (String) child.getCustomLayoutConstraints());
    }
    finally {
      writer.endElement();
    }
  }

  @Override
  public void writeLayout(final XmlWriter writer, final RadContainer radContainer) {
    CardLayout layout = (CardLayout) radContainer.getLayout();
    writer.addAttribute(UIFormXmlConstants.ATTRIBUTE_HGAP, layout.getHgap());
    writer.addAttribute(UIFormXmlConstants.ATTRIBUTE_VGAP, layout.getVgap());
  }

  public void addComponentToContainer(final RadContainer container, final RadComponent component, final int index) {
    container.getDelegee().add(component.getDelegee(), component.getCustomLayoutConstraints());
  }

  @Override public void changeContainerLayout(RadContainer container) throws IncorrectOperationException {
    if (container.getComponentCount() != 0) {
      throw new IncorrectOperationException("Only empty containers can be changed to CardLayout");
    }
    super.changeContainerLayout(container);
  }

  @Override @NotNull
  public ComponentDropLocation getDropLocation(RadContainer container, @Nullable final Point location) {
    return new CardDropLocation(container);
  }

  @Override
  public Property[] getContainerProperties(final Project project) {
    return new Property[] {
      HGapProperty.getInstance(project),
      VGapProperty.getInstance(project) };
  }

  @Override
  public Property[] getComponentProperties(final Project project, final RadComponent component) {
    return new Property[] { CardNameProperty.INSTANCE };
  }

  @Override
  public boolean isSwitchedToChild(RadContainer container, RadComponent child) {
    return child.getDelegee().isVisible();
  }

  @Override
  public boolean switchContainerToChild(RadContainer container, RadComponent child) {
    CardLayout cardLayout = (CardLayout) container.getLayout();
    String card = (String) child.getCustomLayoutConstraints();
    cardLayout.show(container.getDelegee(), card);
    return true;
  }

  @Override
  public boolean areChildrenExclusive() {
    return true;
  }

  @Override public void createSnapshotLayout(final SnapshotContext context,
                                             final JComponent parent,
                                             final RadContainer container,
                                             final LayoutManager layout) {
    CardLayout cardLayout = (CardLayout) layout;
    container.setLayout(new CardLayout(cardLayout.getHgap(), cardLayout.getVgap()));
  }

  @SuppressWarnings({"UseOfObsoleteCollectionType"})
  @Override
  public void addSnapshotComponent(final JComponent parent,
                                   final JComponent child,
                                   final RadContainer container,
                                   final RadComponent component) {
    // unfortunately card can be extracted only through reflection
    String cardName = null;
    try {
      final LayoutManager layout = parent.getLayout();
      Field vectorField = layout.getClass().getDeclaredField("vector");
      vectorField.setAccessible(true);
      Vector vector = (Vector) vectorField.get(parent.getLayout());
      for (Object card : vector) {
        Field nameField = card.getClass().getDeclaredField("name");
        nameField.setAccessible(true);
        Field compField = card.getClass().getDeclaredField("comp");
        compField.setAccessible(true);
        if (compField.get(card) == child) {
          cardName = (String) nameField.get(card);
          break;
        }
      }
    }
    catch (Exception e) {
      // ignore
    }

    if (cardName != null) {
      component.setCustomLayoutConstraints(cardName);
      container.addComponent(component);
    }
  }

  private static class CardDropLocation implements ComponentDropLocation {
    private final RadContainer myContainer;
    @NonNls private static final String CARD_NAME_PREFIX = "Card";

    public CardDropLocation(final RadContainer container) {
      myContainer = container;
    }

    public RadContainer getContainer() {
      return myContainer;
    }

    public boolean canDrop(ComponentDragObject dragObject) {
      return dragObject.getComponentCount() == 1;
    }

    public void placeFeedback(FeedbackLayer feedbackLayer, ComponentDragObject dragObject) {
      Rectangle rc = myContainer.getBounds();
      feedbackLayer.putFeedback(myContainer.getParent().getDelegee(), rc, null);
    }

    public void processDrop(GuiEditor editor,
                            RadComponent[] components,
                            GridConstraints[] constraintsToAdjust,
                            ComponentDragObject dragObject) {
      int cardIndex = 1;
      while(myContainer.findComponentWithConstraints(CARD_NAME_PREFIX + cardIndex) != null) {
        cardIndex++;
      }
      components [0].setCustomLayoutConstraints(CARD_NAME_PREFIX + cardIndex);
      myContainer.addComponent(components [0]);
    }

    @Nullable
    public ComponentDropLocation getAdjacentLocation(Direction direction) {
      return null;
    }
  }

  private static class CardNameProperty extends Property<RadComponent, String> {
    private final LabelPropertyRenderer<String> myRenderer = new LabelPropertyRenderer<String>();

    private final AbstractTextFieldEditor<String> myEditor = new AbstractTextFieldEditor<String>() {
      protected void setValueFromComponent(RadComponent component, String value) {
        myTf.setText((String) component.getCustomLayoutConstraints());
      }

      public String getValue() throws Exception {
        return myTf.getText();
      }
    };

    static CardNameProperty INSTANCE = new CardNameProperty();

    private CardNameProperty() {
      super(null, "Card Name");
    }

    public String getValue(final RadComponent component) {
      return (String) component.getCustomLayoutConstraints();
    }

    protected void setValueImpl(final RadComponent component, final String value) throws Exception {
      if (!value.equals(component.getCustomLayoutConstraints())) {
        if (component.getParent().findComponentWithConstraints(value) != null) {
          throw new Exception(UIDesignerBundle.message("error.card.already.exists", value));
        }
        component.changeCustomLayoutConstraints(value);
        final JComponent parent = component.getParent().getDelegee();
        CardLayout layout = (CardLayout) parent.getLayout();
        layout.show(parent, value);
      }
    }

    @NotNull
    public PropertyRenderer<String> getRenderer() {
      return myRenderer;
    }

    public PropertyEditor<String> getEditor() {
      return myEditor;
    }

    @Override
    public boolean appliesToSelection(final List<RadComponent> selection) {
      return selection.size() == 1;
    }
  }
}