*/ static int Event_Actor(REBVAL *ds, REBSER *port, REBCNT action) /* ***********************************************************************/ { REBVAL *spec; REBVAL *state; REBCNT result; REBVAL *arg; REBVAL save_port; Validate_Port(port, action); arg = D_ARG(2); *D_RET = *D_ARG(1); // Validate and fetch relevant PORT fields: state = BLK_SKIP(port, STD_PORT_STATE); spec = BLK_SKIP(port, STD_PORT_SPEC); if (!IS_OBJECT(spec)) Trap1(RE_INVALID_SPEC, spec); // Get or setup internal state data: if (!IS_BLOCK(state)) Set_Block(state, Make_Block(127)); switch (action) { case A_UPDATE: return R_NONE; // Normal block actions done on events: case A_POKE: if (!IS_EVENT(D_ARG(3))) Trap_Arg(D_ARG(3)); goto act_blk; case A_INSERT: case A_APPEND: //case A_PATH: // not allowed: port/foo is port object field access //case A_PATH_SET: // not allowed: above if (!IS_EVENT(arg)) Trap_Arg(arg); case A_PICK: act_blk: save_port = *D_ARG(1); // save for return *D_ARG(1) = *state; result = T_Block(ds, action); SET_FLAG(Eval_Signals, SIG_EVENT_PORT); if (action == A_INSERT || action == A_APPEND || action == A_REMOVE) { *D_RET = save_port; break; } return result; // return condition case A_CLEAR: VAL_TAIL(state) = 0; VAL_BLK_TERM(state); CLR_FLAG(Eval_Signals, SIG_EVENT_PORT); break; case A_LENGTHQ: SET_INTEGER(D_RET, VAL_TAIL(state)); break; case A_OPEN: if (!req) { //!!! req = OS_MAKE_DEVREQ(RDI_EVENT); SET_OPEN(req); OS_DO_DEVICE(req, RDC_CONNECT); // stays queued } break; default: Trap_Action(REB_PORT, action); } return R_RET; }
*/ static REB_R Event_Actor(struct Reb_Call *call_, REBSER *port, REBCNT action) /* ** Internal port handler for events. ** ***********************************************************************/ { REBVAL *spec; REBVAL *state; REB_R result; REBVAL *arg; REBVAL save_port; Validate_Port(port, action); arg = D_ARG(2); *D_OUT = *D_ARG(1); // Validate and fetch relevant PORT fields: state = BLK_SKIP(port, STD_PORT_STATE); spec = BLK_SKIP(port, STD_PORT_SPEC); if (!IS_OBJECT(spec)) Trap1_DEAD_END(RE_INVALID_SPEC, spec); // Get or setup internal state data: if (!IS_BLOCK(state)) Set_Block(state, Make_Block(EVENTS_CHUNK - 1)); switch (action) { case A_UPDATE: return R_NONE; // Normal block actions done on events: case A_POKE: if (!IS_EVENT(D_ARG(3))) Trap_Arg_DEAD_END(D_ARG(3)); goto act_blk; case A_INSERT: case A_APPEND: //case A_PATH: // not allowed: port/foo is port object field access //case A_PATH_SET: // not allowed: above if (!IS_EVENT(arg)) Trap_Arg_DEAD_END(arg); case A_PICK: act_blk: save_port = *D_ARG(1); // save for return *D_ARG(1) = *state; result = T_Block(call_, action); SET_SIGNAL(SIG_EVENT_PORT); if (action == A_INSERT || action == A_APPEND || action == A_REMOVE) { *D_OUT = save_port; break; } return result; // return condition case A_CLEAR: VAL_TAIL(state) = 0; VAL_BLK_TERM(state); CLR_SIGNAL(SIG_EVENT_PORT); break; case A_LENGTHQ: SET_INTEGER(D_OUT, VAL_TAIL(state)); break; case A_OPEN: if (!req) { //!!! req = OS_MAKE_DEVREQ(RDI_EVENT); if (req) { SET_OPEN(req); OS_DO_DEVICE(req, RDC_CONNECT); // stays queued } } break; case A_CLOSE: OS_ABORT_DEVICE(req); OS_DO_DEVICE(req, RDC_CLOSE); // free req!!! SET_CLOSED(req); req = 0; break; case A_FIND: // add it default: Trap_Action_DEAD_END(REB_PORT, action); } return R_OUT; }