eCodes WsEncoder::encode() { PARROT_ASSERT(_currPkt.get()); eCodes res = eCodes::ST_Ok; auto opCode = _currPkt->getOpCode(); if (opCode == eOpCode::Binary) { // Encode binary data. res = encodeDataPacket(); } else if (opCode == eOpCode::Close) { // Encode close packet. res = encodeClosePacket(); } else if (opCode == eOpCode::Ping || opCode == eOpCode::Pong) { // Encode heartbeat packet. res = encodePingPong(); } else { PARROT_ASSERT(false); } return res; }
void SslServerConn::createSsl() { if (_ssl) { PARROT_ASSERT(false); } _ssl = SslHelper::genSsl(_sslCtx); PARROT_ASSERT(_ssl); BIO* bio = BIO_new_socket(getFd(), BIO_NOCLOSE); SSL_set_bio(_ssl, bio, bio); }
PARROT_EXPORT PARROT_CAN_RETURN_NULL List_Item_Header* Parrot_list_remove(SHIM_INTERP, ARGMOD(Linked_List *list), ARGMOD(List_Item_Header *item)) { ASSERT_ARGS(Parrot_list_remove) List_Item_Header *next = item->next; List_Item_Header *prev = item->prev; PARROT_ASSERT(list == item->owner); /* First item */ if (list->first == item) list->first = next; if (list->last == item) list->last = prev; if (prev) prev->next = next; if (next) next->prev = prev; list->count--; return item; }
PARROT_EXPORT INTVAL Parrot_list_check(SHIM_INTERP, ARGIN(Linked_List *list)) { ASSERT_ARGS(Parrot_list_check) List_Item_Header *tmp = list->first; size_t counter = 0; while (tmp) { List_Item_Header *next = tmp->next; PARROT_ASSERT(tmp->owner == list); tmp = next; ++counter; PARROT_ASSERT(counter <= list->count); } return 1; }
/* =item C<void print_target(lexer_state * const lexer, target * const t)> Print the target C<t>; if C<t> has a key, that key is printed as well. Examples: S1, P1[42] =cut */ void print_target(ARGIN(lexer_state * const lexer), ARGIN(target * const t)) { ASSERT_ARGS(print_target) PARROT_ASSERT(t->info); fprintf(out, "%c%d", pir_register_types[t->info->type], t->info->color); /* if the target has a key, print that too */ if (t->key) print_key(lexer, t->key); }
static void mark_interp(PARROT_INTERP) { ASSERT_ARGS(mark_interp) PObj *obj; /* mark the list of iglobals */ Parrot_gc_mark_PMC_alive(interp, interp->iglobals); /* mark the current continuation */ obj = (PObj *)interp->current_cont; if (obj && obj != (PObj *)NEED_CONTINUATION) Parrot_gc_mark_PMC_alive(interp, (PMC *)obj); /* mark the current context. */ Parrot_gc_mark_PMC_alive(interp, CURRENT_CONTEXT(interp)); /* mark the vtables: the data, Class PMCs, etc. */ Parrot_vtbl_mark_vtables(interp); /* mark the root_namespace */ Parrot_gc_mark_PMC_alive(interp, interp->root_namespace); /* mark the concurrency scheduler */ Parrot_gc_mark_PMC_alive(interp, interp->scheduler); /* mark caches and freelists */ mark_object_cache(interp); /* Now mark the class hash */ Parrot_gc_mark_PMC_alive(interp, interp->class_hash); /* Now mark the HLL stuff */ Parrot_gc_mark_PMC_alive(interp, interp->HLL_info); Parrot_gc_mark_PMC_alive(interp, interp->HLL_namespace); /* Mark the registry */ PARROT_ASSERT(interp->gc_registry); Parrot_gc_mark_PMC_alive(interp, interp->gc_registry); /* Mark the MMD cache. */ if (interp->op_mmd_cache) Parrot_mmd_cache_mark(interp, interp->op_mmd_cache); /* Walk the iodata */ Parrot_IOData_mark(interp, interp->piodata); if (!PMC_IS_NULL(interp->final_exception)) Parrot_gc_mark_PMC_alive(interp, interp->final_exception); if (interp->parent_interpreter) mark_interp(interp->parent_interpreter); }
void imcc_init_tables(PARROT_INTERP) { ASSERT_ARGS(imcc_init_tables) const char *writes[] = { "cleari", "clearn", "clearp", "clears", }; /* init opnums */ if (!w_special[0]) { size_t i; for (i = 0; i < N_ELEMENTS(writes); i++) { const int n = interp->op_lib->op_code(writes[i], 1); PARROT_ASSERT(n); w_special[i] = n; } } }
eCodes WsEncoder::loadBuff() { eCodes res; while (!_pktList.empty()) { if (!_currPkt) { _currPkt = std::move(*_pktList.begin()); _pktList.pop_front(); } res = encode(); // Reset mask begin pointer. The packet was encoded, or the buffer // is full, we need to send the packet next time. _maskBeginPtr = nullptr; if (res == eCodes::ST_BufferFull) { _needSendLen = _currPtr - &(*_sendVec.begin()); _currPtr = &(*_sendVec.begin()); return eCodes::ST_Ok; } else if (res == eCodes::ST_Complete) { _writeState = eWriteState::None; _srcPtr = nullptr; _srcEndPtr = nullptr; _sysJsonStr.clear(); _jsonStr.clear(); _currPkt.reset(); } else { PARROT_ASSERT(false); } } // If here, no packet left in pkt list. return eCodes::ST_Complete; }
void mark_special(PARROT_INTERP, ARGMOD(Memory_Pools *mem_pools), ARGIN(PMC *obj)) { ASSERT_ARGS(mark_special) PObj_get_FLAGS(obj) |= PObj_custom_GC_FLAG; /* clearing the flag is much more expensive then testing */ if (!PObj_needs_early_gc_TEST(obj)) PObj_high_priority_gc_CLEAR(obj); /* mark properties */ Parrot_gc_mark_PMC_alive(interp, PMC_metadata(obj)); if (PObj_custom_mark_TEST(obj)) { PARROT_ASSERT(!PObj_on_free_list_TEST(obj)); VTABLE_mark(interp, obj); } }
int Parrot_gc_trace_root(PARROT_INTERP, ARGMOD(Memory_Pools *mem_pools), Parrot_gc_trace_type trace) { ASSERT_ARGS(Parrot_gc_trace_root) PObj *obj; /* note: adding locals here did cause increased GC runs */ mark_context_start(); if (trace == GC_TRACE_SYSTEM_ONLY) { trace_system_areas(interp, mem_pools); return 0; } /* We have to start somewhere; the interpreter globals is a good place */ if (!mem_pools->gc_mark_start) { mem_pools->gc_mark_start = mem_pools->gc_mark_ptr = interp->iglobals; } /* mark the list of iglobals */ Parrot_gc_mark_PMC_alive(interp, interp->iglobals); /* mark the current continuation */ obj = (PObj *)interp->current_cont; if (obj && obj != (PObj *)NEED_CONTINUATION) Parrot_gc_mark_PMC_alive(interp, (PMC *)obj); /* mark the current context. */ Parrot_gc_mark_PMC_alive(interp, CURRENT_CONTEXT(interp)); /* mark the dynamic environment. */ Parrot_gc_mark_PMC_alive(interp, interp->dynamic_env); /* mark the vtables: the data, Class PMCs, etc. */ mark_vtables(interp); /* mark the root_namespace */ Parrot_gc_mark_PMC_alive(interp, interp->root_namespace); /* mark the concurrency scheduler */ Parrot_gc_mark_PMC_alive(interp, interp->scheduler); /* s. packfile.c */ mark_const_subs(interp); /* mark caches and freelists */ mark_object_cache(interp); /* Now mark the class hash */ Parrot_gc_mark_PMC_alive(interp, interp->class_hash); /* Now mark the HLL stuff */ Parrot_gc_mark_PMC_alive(interp, interp->HLL_info); Parrot_gc_mark_PMC_alive(interp, interp->HLL_namespace); /* Mark the registry */ PARROT_ASSERT(interp->gc_registry); Parrot_gc_mark_PMC_alive(interp, interp->gc_registry); /* Mark the MMD cache. */ if (interp->op_mmd_cache) Parrot_mmd_cache_mark(interp, interp->op_mmd_cache); /* Walk the iodata */ Parrot_IOData_mark(interp, interp->piodata); if (trace == GC_TRACE_FULL) trace_system_areas(interp, mem_pools); /* quick check to see if we have already marked all impatient PMCs. If we have, return 0 and exit here. This will alert other parts of the GC that if we are in a lazy run we can just stop it. */ if (mem_pools->lazy_gc && mem_pools->num_early_PMCs_seen >= mem_pools->num_early_gc_PMCs) return 0; return 1; }
eIoAction SslServerConn::handleIoEvent() { while (true) { switch (_state) { case eSslState::Handshake: { createSsl(); eCodes code = doSslAccept(); if (code == eCodes::ST_RetryWhenWritable) { return eIoAction::Write; } else if (code == eCodes::ST_RetryWhenReadable) { return eIoAction::Read; } else if (code == eCodes::ST_Ok) { _state = eSslState::Connected; return _ioHandler->onConnected(); } else { return eIoAction::Remove; } } break; case eSslState::Connected: { if (isError() || isEof()) { // Todo: Notifier uplayer _ioHandler->onError(_errorCode); return eIoAction::Remove; } eIoAction act; if (isWriteAvail()) { act = _ioHandler->onWritable(); if (act == eIoAction::Remove) { _state = eSslState::Shutdown; continue; } return act; } if (isReadAvail()) { act = _ioHandler->onReadable(); if (act == eIoAction::Remove) { _state = eSslState::Shutdown; continue; } return act; } PARROT_ASSERT(false); return eIoAction::None; } break; case eSslState::Shutdown: { eCodes code = SslHelper::closeSsl(_ssl); if (code == eCodes::ST_RetryWhenReadable) { return eIoAction::Read; } else if (code == eCodes::ST_RetryWhenWritable) { return eIoAction::Write; } else { return eIoAction::Remove; } } break; default: { PARROT_ASSERT(false); } } } }
PARROT_WARN_UNUSED_RESULT PARROT_CANNOT_RETURN_NULL static STRING * to_encoding(PARROT_INTERP, ARGIN(STRING *src), ARGIN_NULLOK(STRING *dest)) { ASSERT_ARGS(to_encoding) #if PARROT_HAS_ICU UErrorCode err; int dest_len; UChar *p; #endif int src_len; int in_place = dest == NULL; STRING *result; if (src->encoding == Parrot_utf16_encoding_ptr || src->encoding == Parrot_ucs2_encoding_ptr) return in_place ? src : Parrot_str_copy(interp, src); /* * TODO adapt string creation functions */ src_len = src->strlen; if (in_place) { result = src; } else { result = dest; } if (!src_len) { result->charset = Parrot_unicode_charset_ptr; result->encoding = Parrot_ucs2_encoding_ptr; result->strlen = result->bufused = 0; return result; } /* u_strFromUTF8(UChar *dest, int32_t destCapacity, int32_t *pDestLength, const char *src, int32_t srcLength, UErrorCode *pErrorCode); */ #if PARROT_HAS_ICU if (in_place) { /* need intermediate memory */ p = (UChar *)mem_sys_allocate(src_len * sizeof (UChar)); } else { Parrot_gc_reallocate_string_storage(interp, dest, sizeof (UChar) * src_len); p = (UChar *)dest->strstart; } if (src->charset == Parrot_iso_8859_1_charset_ptr || src->charset == Parrot_ascii_charset_ptr) { for (dest_len = 0; dest_len < (int)src->strlen; ++dest_len) { p[dest_len] = (UChar)((unsigned char*)src->strstart)[dest_len]; } } else { err = U_ZERO_ERROR; u_strFromUTF8(p, src_len, &dest_len, src->strstart, src->bufused, &err); if (!U_SUCCESS(err)) { /* * have to resize - required len in UChars is in dest_len */ if (in_place) p = (UChar *)mem_sys_realloc(p, dest_len * sizeof (UChar)); else { result->bufused = dest_len * sizeof (UChar); Parrot_gc_reallocate_string_storage(interp, dest, sizeof (UChar) * dest_len); p = (UChar *)dest->strstart; } u_strFromUTF8(p, dest_len, &dest_len, src->strstart, src->bufused, &err); PARROT_ASSERT(U_SUCCESS(err)); } } result->bufused = dest_len * sizeof (UChar); if (in_place) { Parrot_gc_reallocate_string_storage(interp, src, src->bufused); memcpy(src->strstart, p, src->bufused); mem_sys_free(p); } result->charset = Parrot_unicode_charset_ptr; result->encoding = Parrot_utf16_encoding_ptr; result->strlen = src_len; /* downgrade if possible */ if (dest_len == (int)src->strlen) result->encoding = Parrot_ucs2_encoding_ptr; return result; #else Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_LIBRARY_ERROR, "no ICU lib loaded"); #endif }
eCodes WsEncoder::encodeRawPacket() { switch (_writeState) { case eWriteState::None: { auto& raw = _currPkt->getPayload(); PARROT_ASSERT(!raw.empty()); computeComponentLen(raw.size()); _writeState = eWriteState::Header; _srcPtr = &(*raw.begin()); _srcEndPtr = &(*raw.end()); _firstPacket = true; } // No break; case eWriteState::Header: { if ((_sendVecEndPtr - _currPtr) < _headerLen) { // Left space is not enough. return eCodes::ST_BufferFull; } bool fin = true; if (_fragmented) { if (static_cast<uint64_t>(_srcEndPtr - _srcPtr) <= _payloadLen) { // The last packet. fin should be true. _payloadLen = _srcEndPtr - _srcPtr; } else { fin = false; } } writeHeader(_firstPacket, fin); if (_firstPacket) { _firstPacket = false; } _writeState = eWriteState::Raw; _maskKeyIdx = 0; _payloadEncodedLen = 0; } // No break; case eWriteState::Raw: { _maskBeginPtr = _currPtr; for (; _payloadEncodedLen < _payloadLen && _currPtr != _sendVecEndPtr; ++_payloadEncodedLen, ++_currPtr) { *_currPtr = _srcPtr[_payloadEncodedLen]; } if (_needMask) { maskPacket(_maskBeginPtr, _currPtr); } if (_payloadEncodedLen == _payloadLen) { // Encoded one packet. _srcPtr += _payloadEncodedLen; if (_srcPtr == _srcEndPtr) { // WsPacket has been encoded. return eCodes::ST_Complete; } // The WsPacket has been fragmented, we need to encode // another packet, write header next. _writeState = eWriteState::Header; return encodeRawPacket(); } else { // Not enough space to encode a packet. return eCodes::ST_BufferFull; } } break; default: { PARROT_ASSERT(false); } } // Should never be here. PARROT_ASSERT(false); return eCodes::ST_Ok; }
eCodes WsEncoder::encodeMeta() { if (!_maskBeginPtr) { _maskBeginPtr = _currPtr; } uint8_t copyLen = (_sendVecEndPtr - _currPtr > _srcEndPtr - _currPtr) ? (_srcEndPtr - _currPtr) : (_sendVecEndPtr - _currPtr); std::memcpy(_currPtr, _srcPtr, copyLen); _payloadEncodedLen += copyLen; _encodedLen += copyLen; _currPtr += copyLen; _srcPtr += copyLen; PARROT_ASSERT(_payloadEncodedLen < _payloadLen); if (_currPtr == _sendVecEndPtr) { // Not enough space to encode a packet. if (_needMask) { maskPacket(_maskBeginPtr, _currPtr); } return eCodes::ST_BufferFull; } // Meta has been encoded. switch (_writeState) { case eWriteState::SysJsonMeta: { _writeState = eWriteState::SysJson; _srcPtr = reinterpret_cast<unsigned char*>(&(*_sysJsonStr.begin())); _srcEndPtr = reinterpret_cast<unsigned char*>(&(*_sysJsonStr.end())); } break; case eWriteState::JsonMeta: { _writeState = eWriteState::Json; _srcPtr = reinterpret_cast<unsigned char*>(&(*_jsonStr.begin())); _srcEndPtr = reinterpret_cast<unsigned char*>(&(*_jsonStr.end())); } break; case eWriteState::BinaryMeta: { auto& bin = _currPkt->getBinary(); _writeState = eWriteState::Binary; _srcPtr = reinterpret_cast<const unsigned char*>(&(*bin.begin())); _srcEndPtr = reinterpret_cast<const unsigned char*>(&(*bin.end())); } break; default: { PARROT_ASSERT(false); } } return eCodes::ST_Ok; }
void RpcServerThread::run() { uint32_t eventNum = 0; uint32_t idx = 0; IoEvent* ev = nullptr; eIoAction act = eIoAction::None; try { while (!isStopping()) { _now = std::time(nullptr); RSConnMgr::_timeoutMgr->checkTimeout(_now); RSConnMgr::addConnToNotifier(); eventNum = _notifier->waitIoEvents(5000); // Here handle events. for (idx = 0; idx != eventNum; ++idx) { // We are sure that the IoEvnet is WsServerConn, // so we can use static_cast. ev = _notifier->getIoEvent(idx); act = ev->handleIoEvent(); ev->setNextAction(act); switch (act) { case eIoAction::Read: case eIoAction::ReadWrite: { if (ev->isConnection()) { RSConnMgr::updateTimeout( static_cast<RpcServerConn*>( ev->getDerivedPtr()), _now); } } // No break; case eIoAction::Write: { _notifier->updateEventAction(ev); } break; case eIoAction::Remove: { RSConnMgr::removeConn( static_cast<RpcServerConn*>(ev->getDerivedPtr())); } break; default: { PARROT_ASSERT(false); } break; } // switch } // for // Append packet which needs to be sent to connections. handleJobs(); } // while } catch (const std::system_error& e) { LOG_ERROR("RpcServerThread::run: Errno is " << e.code().message() << ". Meaning " << e.what()); // There's nothing we can do here ... PARROT_ASSERT(false); } }
eCodes WsEncoder::encodePlainPacket() { eCodes code = eCodes::ST_Ok; switch (_writeState) { case eWriteState::None: { computeLength(); _writeState = eWriteState::Header; _firstPacket = true; _encodedLen = 0; } // No break; case eWriteState::Header: { if ((_sendVecEndPtr - _currPtr) < _headerLen) { // Left space is not enough. return eCodes::ST_BufferFull; } bool fin = true; if (_fragmented) { if (_totalLen - _encodedLen <= _payloadLen) { // The last packet. fin should be true. _payloadLen = _totalLen - _encodedLen; } else { fin = false; } } writeHeader(_firstPacket, fin); // Reset mask function related variables. _maskKeyIdx = 0; _maskBeginPtr = _currPtr; if (_firstPacket) { _firstPacket = false; getMetaData(ePayloadItem::SysJson, _sysJsonStr.size()); _writeState = eWriteState::SysJsonMeta; _srcPtr = &(*_metaData.begin()); _srcEndPtr = &(*_metaData.end()); } else { _writeState = _prevWriteState; return encodePlainPacket(); } } // No break; case eWriteState::SysJsonMeta: { code = encodeMeta(); if (code == eCodes::ST_BufferFull) { return code; } } // no break; case eWriteState::SysJson: { code = encodeData(); if (code == eCodes::ST_BufferFull || code == eCodes::ST_Complete) { return code; } } // no break; case eWriteState::JsonMeta: { code = encodeMeta(); if (code == eCodes::ST_BufferFull) { return code; } } // no break; case eWriteState::Json: { code = encodeData(); if (code == eCodes::ST_BufferFull || code == eCodes::ST_Complete) { return code; } } // no break; case eWriteState::BinaryMeta: { code = encodeMeta(); if (code == eCodes::ST_BufferFull) { return code; } } // no break; case eWriteState::Binary: { code = encodeData(); if (code == eCodes::ST_BufferFull || code == eCodes::ST_Complete) { return code; } } break; default: { PARROT_ASSERT(false); } } return code; }
eCodes WsEncoder::encodeData() { if (!_maskBeginPtr) { _maskBeginPtr = _currPtr; } uint64_t copyLen = static_cast<uint64_t>(_sendVecEndPtr - _currPtr) > (_payloadLen - _payloadEncodedLen) ? (_payloadLen - _payloadEncodedLen) : (_sendVecEndPtr - _currPtr); copyLen = copyLen > static_cast<uint64_t>(_srcEndPtr - _srcPtr) ? (_srcEndPtr - _srcPtr) : copyLen; std::memcpy(_currPtr, _srcPtr, copyLen); _payloadEncodedLen += copyLen; _currPtr += copyLen; _srcPtr += copyLen; _encodedLen += copyLen; if (_encodedLen == _totalLen) { // Completed, we have encoded all data. if (_needMask) { maskPacket(_maskBeginPtr, _currPtr); } return eCodes::ST_Complete; } if (_currPtr == _sendVecEndPtr) { // Still has data to encode, but buffer is full. if (_needMask) { maskPacket(_maskBeginPtr, _currPtr); } return eCodes::ST_BufferFull; } else { if (_payloadEncodedLen == _payloadLen) { // Packet is fragmented. _prevWriteState = _writeState; _writeState = eWriteState::Header; return encodePlainPacket(); } else { switch (_writeState) { case eWriteState::SysJson: { PARROT_ASSERT(_currPtr == _srcEndPtr); // SysJson is encoded. if (!_jsonStr.empty()) { getMetaData(ePayloadItem::Json, _sysJsonStr.size()); _writeState = eWriteState::JsonMeta; } else if (!_currPkt->getBinary().empty()) { getMetaData(ePayloadItem::Binary, _currPkt->getBinary().size()); _writeState = eWriteState::BinaryMeta; } else { PARROT_ASSERT(false); } _srcPtr = &(*_metaData.begin()); _srcEndPtr = &(*_metaData.end()); } break; case eWriteState::Json: { PARROT_ASSERT(_currPtr == _srcEndPtr); auto& bin = _currPkt->getBinary(); PARROT_ASSERT(!bin.empty()); getMetaData(ePayloadItem::Binary, bin.size()); _writeState = eWriteState::BinaryMeta; _srcPtr = &(*_metaData.begin()); _srcEndPtr = &(*_metaData.end()); } break; case eWriteState::Binary: { } break; default: { PARROT_ASSERT(false); } } } } return eCodes::ST_Ok; }
PARROT_EXPORT PARROT_CANNOT_RETURN_NULL PMC * Parrot_nci_parse_signature(PARROT_INTERP, ARGIN(STRING *sig_str)) { ASSERT_ARGS(Parrot_nci_parse_signature) const size_t sig_length = Parrot_str_byte_length(interp, sig_str); PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, sig_length); size_t i; if (!sig_length) { sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, 1); VTABLE_set_integer_keyed_int(interp, sig_pmc, 0, enum_type_void); return sig_pmc; } for (i = 0; i < sig_length; ++i) { const INTVAL c = Parrot_str_indexed(interp, sig_str, i); PARROT_DATA_TYPE e; PARROT_ASSERT(c == (char)c); switch ((char)c) { case 'f': e = enum_type_float; break; case 'd': e = enum_type_double; break; case 'N': e = enum_type_FLOATVAL; break; case 'c': /* char */ e = enum_type_char; break; case 's': /* short */ e = enum_type_short; break; case 'i': /* int */ e = enum_type_int; break; case 'l': /* long */ e = enum_type_long; break; case 'I': /* INTVAL */ e = enum_type_INTVAL; break; case '2': /* short PMC */ e = enum_type_pshort; break; case '3': /* int PMC */ e = enum_type_pint; break; case '4': /* long PMC */ e = enum_type_plong; break; case 'S': e = enum_type_STRING; break; case 't': /* string as cstring */ e = enum_type_cstr; break; case 'p': /* push pmc->data */ e = enum_type_ptr; break; case 'O': /* PMC invocant */ case 'P': /* push PMC * */ e = enum_type_PMC; break; case 'v': e = enum_type_void; break; default: Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR, "Unknown param Signature %c\n", (char)c); break; } VTABLE_set_integer_keyed_int(interp, sig_pmc, i, e); } return sig_pmc; }
eCodes WsEncoder::encodePingPong() { // According to the RFC6455, the heartbeat may have 'application data'. // But pong must have the extact same data of ping. But the RFC doesn't // point out what the data will be. So we use binary if the payload exists. // And ping pong packets must not be fragmented. switch (_writeState) { case eWriteState::None: { auto payloadLen = _currPkt->getBinary().size(); // No fragment. Up layer should check the length. PARROT_ASSERT(payloadLen <= WsConfig::_maxPayloadLen); // Compute _headerLen and _payloadLen. computeComponentLen(payloadLen); _writeState = eWriteState::Header; if ((_sendVecEndPtr - _currPtr) < _headerLen) { // Buffer is full. Return here and let translayer send // the data. return eCodes::ST_BufferFull; } // Fall through, next, encode header. } // No break; case eWriteState::Header: { writeHeader(true, true); _writeState = eWriteState::Binary; auto& bin = _currPkt->getBinary(); if (bin.empty()) { return eCodes::ST_Complete; } _srcPtr = &(*bin.begin()); _srcEndPtr = &(*bin.end()); _maskKeyIdx = 0; // Fall through here. } // No break; case eWriteState::Binary: { // Encode _maskBeginPtr = _currPtr; for (; _srcPtr != _srcEndPtr && _currPtr != &(*_sendVec.end()); ++_srcPtr, ++_currPtr) { *_currPtr = *_srcPtr; } if (_needMask) { maskPacket(_maskBeginPtr, _currPtr); } if (_srcPtr != _srcEndPtr) { return eCodes::ST_BufferFull; } } break; default: { PARROT_ASSERT(false); } break; } return eCodes::ST_Complete; }
PARROT_EXPORT PARROT_WARN_UNUSED_RESULT PARROT_CANNOT_RETURN_NULL PMC * Parrot_io_open_handle(PARROT_INTERP, ARGIN(PMC *pmc), ARGIN(STRING *path), ARGIN(STRING *mode)) { ASSERT_ARGS(Parrot_io_open_handle) PMC *filehandle; const INTVAL typenum = Parrot_hll_get_ctx_HLL_type(interp, Parrot_PMC_typenum(interp, "FileHandle")); if (PMC_IS_NULL(pmc)) { filehandle = Parrot_pmc_new(interp, typenum); } else filehandle = pmc; if (STRING_IS_NULL(path)) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_PIO_ERROR, "Cannot open filehandle, no path"); if (filehandle->vtable->base_type == typenum) { INTVAL flags = Parrot_io_parse_open_flags(interp, mode); PIOHANDLE os_handle; /* TODO: a filehandle shouldn't allow a NULL path. */ PARROT_ASSERT(filehandle->vtable->base_type == typenum); if (flags & PIO_F_PIPE) { const int f_read = (flags & PIO_F_READ) != 0; const int f_write = (flags & PIO_F_WRITE) != 0; INTVAL pid; if (f_read == f_write) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_PIO_ERROR, "Invalid pipe mode: %X", flags); os_handle = PIO_OPEN_PIPE(interp, path, flags, &pid); /* Save the pid of the child, we'll wait for it when closing */ VTABLE_set_integer_keyed_int(interp, filehandle, 0, pid); } else { if ((flags & (PIO_F_WRITE | PIO_F_READ)) == 0) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "Invalid mode for file open"); os_handle = PIO_OPEN(interp, path, flags); if (os_handle == PIO_INVALID_HANDLE) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_PIO_ERROR, "Unable to open filehandle from path '%Ss'", path); flags |= PIO_F_FILE; /* Set generic flag here if is a terminal then * FileHandle can know how to setup buffering. * STDIN, STDOUT, STDERR would be in this case * so we would setup linebuffering. */ if (PIO_IS_TTY(interp, os_handle)) flags |= PIO_F_CONSOLE; } if (STRING_IS_NULL(mode)) mode = CONST_STRING(interp, "r"); else if (STRING_index(interp, mode, CONST_STRING(interp, "b"), 0) >= 0) SETATTR_FileHandle_encoding(interp, filehandle, CONST_STRING(interp, "binary")); SETATTR_FileHandle_os_handle(interp, filehandle, os_handle); SETATTR_FileHandle_flags(interp, filehandle, flags); SETATTR_FileHandle_filename(interp, filehandle, path); SETATTR_FileHandle_mode(interp, filehandle, mode); Parrot_io_setbuf(interp, filehandle, PIO_UNBOUND); } else Parrot_pcc_invoke_method_from_c_args(interp, filehandle, CONST_STRING(interp, "open"), "SS->P", path, mode, &filehandle); return filehandle; }
SSL_CTX* SslHelper::genSslCtx(const std::string& keyPath, const std::string& certPath, const std::string& caPath, const std::string& caFile, bool verifyPeer, int depth) { /* This method supprots from SSLv3 to newest TLS. SSLv3 will be disabled * below. */ const SSL_METHOD* m = TLS_method(); SSL_CTX* sslCtx = SSL_CTX_new(m); if (!sslCtx) { /* If here, did you forget to call SslHelper::init()? */ PARROT_ASSERT(0); } const char* caFilePtr = nullptr; const char* caPathPtr = nullptr; if (caFile.length() > 0) { caFilePtr = caFile.c_str(); } if (caPath.length() > 0) { caPathPtr = caPath.c_str(); } /* Add ca-cert to SSL_CTX. */ if (caFilePtr || caPathPtr) { /* Add ca-cert file. */ if (SSL_CTX_load_verify_locations(sslCtx, caFilePtr, caPathPtr) != 1) { PARROT_ASSERT(0); } } /* Add cert to SSL_CTX. */ if (caPath.length() > 0 && SSL_CTX_use_certificate_file(sslCtx, certPath.c_str(), SSL_FILETYPE_PEM) <= 0) { PARROT_ASSERT(0); } // Add private key to SSL_CTX. if (keyPath.length() > 0 && SSL_CTX_use_PrivateKey_file(sslCtx, keyPath.c_str(), SSL_FILETYPE_PEM) != 1) { PARROT_ASSERT(0); } // Enable nonblock. SSL_CTX_set_mode(sslCtx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); if (verifyPeer) { /* We need to verify peer, but the client doesn't tell us where * to find the ca-certs, we use default. */ if (caPath.empty()) { if (SSL_CTX_set_default_verify_paths(sslCtx) != 1) { PARROT_ASSERT(0); } } SSL_CTX_set_verify( sslCtx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr); SSL_CTX_set_verify_depth(sslCtx, depth); } else { SSL_CTX_set_verify(sslCtx, SSL_VERIFY_NONE, nullptr); } /* TLSv1.0 is the minimal requirement. SSLv3.0 will not be supported. */ PARROT_ASSERT(SSL_CTX_set_min_proto_version(sslCtx, TLS1_VERSION) == 1); return sslCtx; }
PARROT_CANNOT_RETURN_NULL PMC * Parrot_oo_clone_object(PARROT_INTERP, ARGIN(PMC *pmc), ARGMOD_NULLOK(PMC *dest)) { ASSERT_ARGS(Parrot_oo_clone_object) Parrot_Object_attributes *obj = PARROT_OBJECT(pmc); Parrot_Object_attributes *cloned_guts; Parrot_Class_attributes *_class; PMC *cloned; INTVAL num_classes; INTVAL i, num_attrs; if (!PMC_IS_NULL(dest)) { cloned = dest; } else { cloned = Parrot_pmc_new_noinit(interp, enum_class_Object); } _class = PARROT_CLASS(obj->_class); PARROT_ASSERT(_class); num_classes = VTABLE_elements(interp, _class->all_parents); /* Set custom GC mark and destroy on the object. */ PObj_custom_mark_SET(cloned); PObj_custom_destroy_SET(cloned); /* Flag that it is an object */ PObj_is_object_SET(cloned); /* Now clone attributes list.class. */ cloned_guts = (Parrot_Object_attributes *) PMC_data(cloned); cloned_guts->_class = obj->_class; cloned_guts->attrib_store = VTABLE_clone(interp, obj->attrib_store); num_attrs = VTABLE_elements(interp, cloned_guts->attrib_store); for (i = 0; i < num_attrs; ++i) { PMC * const to_clone = VTABLE_get_pmc_keyed_int(interp, cloned_guts->attrib_store, i); if (!PMC_IS_NULL(to_clone)) { VTABLE_set_pmc_keyed_int(interp, cloned_guts->attrib_store, i, VTABLE_clone(interp, to_clone)); } } /* Some of the attributes may have been the PMCs providing storage for any * PMCs we inherited from; also need to clone those. */ if (CLASS_has_alien_parents_TEST(obj->_class)) { int j; /* Locate any PMC parents. */ for (j = 0; j < num_classes; ++j) { PMC * const cur_class = VTABLE_get_pmc_keyed_int(interp, _class->all_parents, j); if (cur_class->vtable->base_type == enum_class_PMCProxy) { /* Clone this PMC too. */ STRING * const proxy = CONST_STRING(interp, "proxy"); VTABLE_set_attr_keyed(interp, cloned, cur_class, proxy, VTABLE_clone(interp, VTABLE_get_attr_keyed(interp, cloned, cur_class, proxy))); } } } /* And we have ourselves a clone. */ return cloned; }
void Parrot_nci_load_core_thunks(PARROT_INTERP) { PMC * const iglobals = interp->iglobals; PMC *nci_funcs; PMC *temp_pmc; PARROT_ASSERT(!(PMC_IS_NULL(iglobals))); nci_funcs = VTABLE_get_pmc_keyed_int(interp, iglobals, IGLOBALS_NCI_FUNCS); PARROT_ASSERT(!(PMC_IS_NULL(nci_funcs))); { const int n = 1; static const int sig[] = { 5, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_char); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 3; static const int sig[] = { 5, 6, 5, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_char_short_char); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 1; static const int sig[] = { 16, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_double); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 2; static const int sig[] = { 16, 16, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_double_double); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 1; static const int sig[] = { 15, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_float); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 3; static const int sig[] = { 15, 15, 15, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_float_float_float); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 1; static const int sig[] = { 7, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_int); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 4; static const int sig[] = { 7, 7, 7, 7, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_int_int_int_int); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 2; static const int sig[] = { 7, 30, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_int_ptr); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 3; static const int sig[] = { 7, 30, 30, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_int_ptr_ptr); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 3; static const int sig[] = { 7, 6, 5, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_int_short_char); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 2; static const int sig[] = { 7, 31, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_int_cstr); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 1; static const int sig[] = { 8, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_long); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 1; static const int sig[] = { 30, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_ptr); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 2; static const int sig[] = { 30, 7, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_ptr_int); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 3; static const int sig[] = { 30, 7, 7, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_ptr_int_int); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 5; static const int sig[] = { 30, 7, 7, 7, 7, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_ptr_int_int_int_int); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 3; static const int sig[] = { 30, 7, 30, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_ptr_int_ptr); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 2; static const int sig[] = { 30, 30, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_ptr_ptr); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 3; static const int sig[] = { 30, 30, 3, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_ptr_ptr_STRING); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 1; static const int sig[] = { 6, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_short); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 3; static const int sig[] = { 6, 6, 5, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_short_short_char); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 1; static const int sig[] = { 31, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_cstr); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 2; static const int sig[] = { 31, 31, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_cstr_cstr); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 3; static const int sig[] = { 31, 31, 31, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_cstr_cstr_cstr); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 1; static const int sig[] = { 29, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_void); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 4; static const int sig[] = { 29, 15, 15, 15, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_void_float_float_float); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 2; static const int sig[] = { 29, 30, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_void_ptr); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 2; static const int sig[] = { 29, 4, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_void_PMC); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 4; static const int sig[] = { 29, 30, 7, 7, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_void_ptr_int_int); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } { const int n = 3; static const int sig[] = { 29, 30, 4, }; PMC *sig_pmc = Parrot_pmc_new_init_int(interp, enum_class_FixedIntegerArray, n); int i; for (i = 0; i < n; i++) VTABLE_set_integer_keyed_int(interp, sig_pmc, i, sig[i]); temp_pmc = Parrot_pmc_new(interp, enum_class_UnManagedStruct); VTABLE_set_pointer(interp, temp_pmc, (void *)pcf_void_ptr_PMC); VTABLE_set_pmc_keyed(interp, nci_funcs, sig_pmc, temp_pmc); } }
void runops(PARROT_INTERP, size_t offs) { ASSERT_ARGS(runops) volatile size_t offset = offs; const int old_runloop_id = interp->current_runloop_id; int our_runloop_level = interp->current_runloop_level; int our_runloop_id = old_runloop_id; /* It is OK if the runloop ID overflows; we only ever test it for equality, so the chance of collision is slight. */ interp->current_runloop_id = our_runloop_id; #if RUNLOOP_TRACE fprintf(stderr, "[entering loop %d, level %d]\n", interp->current_runloop_id, our_runloop_level); #endif /* * STACKED_EXCEPTIONS are necessary to catch exceptions in reentered * run loops, e.g. if a delegate method throws an exception */ #if ! STACKED_EXCEPTIONS if (!interp->current_runloop) #endif { new_runloop_jump_point(interp); our_runloop_id = interp->current_runloop_id; our_runloop_level = interp->current_runloop_level; reenter: interp->current_runloop->handler_start = NULL; switch (setjmp(interp->current_runloop->resume)) { case 1: /* an exception was handled */ if (STACKED_EXCEPTIONS) free_runloop_jump_point(interp); interp->current_runloop_level = our_runloop_level - 1; interp->current_runloop_id = old_runloop_id; #if RUNLOOP_TRACE fprintf(stderr, "[handled exception; back to loop %d, level %d]\n", interp->current_runloop_id, interp->current_runloop_level); #endif return; case 2: /* Reenter the runloop from a exception thrown from C * with a pir handler */ free_runloops_until(interp, our_runloop_id); PARROT_ASSERT(interp->current_runloop->handler_start); offset = interp->current_runloop->handler_start - interp->code->base.data; /* Prevent incorrect reuse */ goto reenter; case 3: /* Reenter the runloop when finished the handling of a * exception */ free_runloops_until(interp, our_runloop_id); offset = interp->current_runloop->handler_start - interp->code->base.data; goto reenter; default: break; } } runops_int(interp, offset); interp->current_runloop->handler_start = NULL; /* Remove the current runloop marker (put it on the free list). */ if (STACKED_EXCEPTIONS || interp->current_runloop) free_runloop_jump_point(interp); #if RUNLOOP_TRACE fprintf(stderr, "[exiting loop %d, level %d]\n", our_runloop_id, our_runloop_level); #endif }