static const UBuffer* _execBuf( UThread* ut, const UCell* cell, int fd ) { static const char* name[3] = { "input", "output", "error" }; const UBuffer* buf; if( fd == 0 ) buf = ur_bufferSer(cell); else if( ! (buf = ur_bufferSerM(cell)) ) return 0; if( buf->type == UT_BINARY ) { return buf; } else if( buf->type == UT_STRING ) { if( ! ur_strIsUcs2(buf) ) return buf; ur_error( ut, UR_ERR_TYPE, "execute does not handle UCS2 strings" ); } else { ur_error( ut, UR_ERR_TYPE, "execute expected binary!/string! for %s", name[fd] ); } return 0; }
static void ledit_dispatch( UThread* ut, GWidget* wp, const GLViewEvent* ev ) { EX_PTR; //printf( "KR ledit %d\n", ev->type ); switch( ev->type ) { case GLV_EVENT_BUTTON_DOWN: if( (ev->code == GLV_BUTTON_LEFT) || (ev->code == GLV_BUTTON_MIDDLE) ) { ledit_setState( ut, ep, LEDIT_STATE_EDIT ); gui_setKeyFocus( wp ); if( ev->code == GLV_BUTTON_LEFT ) { // Don't have access to font here so just notify render. ep->newCursorX = ev->x; setFlag( NEW_CURSORX ); } else // if( ev->code == GLV_BUTTON_MIDDLE ) { ledit_paste( ut, ep ); setFlag( CHANGED ); } } break; case GLV_EVENT_BUTTON_UP: case GLV_EVENT_MOTION: break; case GLV_EVENT_KEY_DOWN: if( ep->strN ) { UBuffer* str = ur_buffer( ep->strN ); if( ev->state & GLV_MASK_CTRL ) { if( ev->code == KEY_k ) { // Remove from cursor to end (from Bash). int len = str->used - ep->editPos; if( len > 0 ) { ur_arrErase( str, ep->editPos, len ); setFlag( CHANGED ); } } else if( ev->code == KEY_v ) { ledit_paste( ut, ep ); setFlag( CHANGED ); } break; } switch( ev->code ) { case KEY_Return: goto activate; case KEY_Left: if( ep->editPos > 0 ) { --ep->editPos; setFlag( CHANGED ); } break; case KEY_Right: if( ep->editPos < str->used ) { ++ep->editPos; setFlag( CHANGED ); } break; case KEY_Home: ep->editPos = 0; setFlag( CHANGED ); break; case KEY_End: ep->editPos = str->used; setFlag( CHANGED ); break; case KEY_Insert: break; case KEY_Delete: if( ep->editPos < str->used ) { ur_arrErase( str, ep->editPos, 1 ); setFlag( CHANGED ); } break; case KEY_Back_Space: if( ep->editPos > 0 ) { --ep->editPos; ur_arrErase( str, ep->editPos, 1 ); setFlag( CHANGED ); } break; default: if( str->used < ep->maxChars ) { int key = KEY_ASCII(ev); if( key >= ' ' ) { if( ep->filterN ) { UBuffer* bin = ur_buffer( ep->filterN ); if( ! _bitIsSet( bin->ptr.b, key ) ) break; } ur_arrExpand( str, ep->editPos, 1 ); if( ur_strIsUcs2(str) ) str->ptr.u16[ ep->editPos ] = key; else str->ptr.b[ ep->editPos ] = key; ++ep->editPos; setFlag( CHANGED ); } else { gui_ignoreEvent( ev ); } } break; } } break; case GLV_EVENT_KEY_UP: gui_ignoreEvent( ev ); break; case GLV_EVENT_FOCUS_IN: break; case GLV_EVENT_FOCUS_OUT: ledit_setState( ut, ep, LEDIT_STATE_DISPLAY ); break; } return; activate: if( ep->codeN ) gui_doBlockN( ut, ep->codeN ); }
/* Returns zero if matching rule not found or exception occured. */ static const UCell* _parseBin( UThread* ut, BinaryParser* pe, const UCell* rit, const UCell* rend, UIndex* spos ) { const UCell* set = 0; const UCell* tval; uint32_t bitCount; uint32_t field; UBuffer* ibin = ur_buffer( pe->inputBufN ); uint8_t* in = ibin->ptr.b + *spos; uint8_t* inEnd = ibin->ptr.b + pe->inputEnd; match: while( rit != rend ) { switch( ur_type(rit) ) { case UT_INT: bitCount = ur_int(rit); if( bitCount < 1 || bitCount > 32 ) { ur_error( PARSE_ERR, "bit-field size must be 1 to 32" ); goto parse_err; } if( bitCount > 24 ) { uint32_t high; in = pullBits( pe, bitCount - 16, in, inEnd, &high ); if( ! in ) goto failed; in = pullBits( pe, 16, in, inEnd, &field ); if( ! in ) goto failed; field |= high << 16; } else { in = pullBits( pe, bitCount, in, inEnd, &field ); if( ! in ) goto failed; } goto set_field; case UT_WORD: switch( ur_atom(rit) ) { case UR_ATOM_U8: if( in == inEnd ) goto failed; field = *in++; goto set_field; case UR_ATOM_U16: if( (inEnd - in) < 2 ) goto failed; if( pe->bigEndian ) field = (in[0] << 8) | in[1]; else field = (in[1] << 8) | in[0]; in += 2; goto set_field; case UR_ATOM_U32: if( (inEnd - in) < 4 ) goto failed; if( pe->bigEndian ) field = (in[0] << 24) | (in[1] << 16) | (in[2] << 8) | in[3]; else field = (in[3] << 24) | (in[2] << 16) | (in[1] << 8) | in[0]; in += 4; goto set_field; case UR_ATOM_SKIP: ++rit; ++in; break; #if 0 case UR_ATOM_MARK: break; case UR_ATOM_PLACE: ++rit; if( (rit != rend) && ur_is(rit, UT_WORD) ) { tval = ur_wordCell( ut, rit++ ); CHECK_WORD(tval); if( ur_is(tval, UT_BINARY) ) { pos = tval->series.it; break; } } ur_error( PARSE_ERR, "place expected series word" ); goto parse_err; #endif case UR_ATOM_COPY: // copy dest size // word! int!/word! ++rit; if( (rit != rend) && ur_is(rit, UT_WORD) ) { UCell* res = ur_wordCellM( ut, rit ); CHECK_WORD(res); if( ++rit != rend ) { tval = rit++; if( ur_is(tval, UT_WORD) ) { tval = ur_wordCell( ut, tval ); CHECK_WORD(tval); } if( ur_is(tval, UT_INT) ) { UBuffer* cb; int size = ur_int(tval); cb = ur_makeBinaryCell( ut, size, res ); cb->used = size; memCpy( cb->ptr.b, in, size ); in += size; break; } } ur_error( PARSE_ERR, "copy expected int! count" ); goto parse_err; } ur_error( PARSE_ERR, "copy expected word! destination" ); goto parse_err; case UR_ATOM_BIG_ENDIAN: ++rit; pe->bigEndian = 1; break; case UR_ATOM_LITTLE_ENDIAN: ++rit; pe->bigEndian = 0; break; default: tval = ur_wordCell( ut, rit ); CHECK_WORD(tval); if( ur_is(tval, UT_CHAR) ) goto match_char; else if( ur_is(tval, UT_STRING) ) goto match_string; else if( ur_is(tval, UT_BLOCK) ) goto match_block; /* else if( ur_is(tval, UT_BITSET) ) goto match_bitset; */ else { ur_error( PARSE_ERR, "parse expected char!/string!/block!" ); goto parse_err; } break; } break; case UT_SETWORD: set = rit++; while( (rit != rend) && ur_is(rit, UT_SETWORD) ) ++rit; break; #if 0 case UT_GETWORD: break; case UT_INT: repMin = ur_int(rit); ++rit; if( rit == rend ) return 0; if( ur_is(rit, UT_INT) ) { repMax = ur_int(rit); ++rit; } else { repMax = repMin; } goto repeat; #endif case UT_CHAR: match_char: if( *in != ur_int(rit) ) goto failed; ++in; ++rit; break; case UT_BLOCK: tval = rit; match_block: { UBlockIter bi; UIndex pos = in - ibin->ptr.b; UIndex rblkN = tval->series.buf; ur_blkSlice( ut, &bi, tval ); tval = _parseBin( ut, pe, bi.it, bi.end, &pos ); ibin = ur_buffer( pe->inputBufN ); if( ! tval ) { if( pe->exception == PARSE_EX_ERROR ) { ur_appendTrace( ut, rblkN, 0 ); return 0; } if( pe->exception == PARSE_EX_BREAK ) pe->exception = PARSE_EX_NONE; else goto failed; } in = ibin->ptr.b + pos; inEnd = ibin->ptr.b + pe->inputEnd; ++rit; } break; case UT_PAREN: { UIndex pos = in - ibin->ptr.b; if( UR_OK != pe->eval( ut, rit ) ) goto parse_err; /* Re-acquire pointer & check if input modified. */ ibin = ur_buffer( pe->inputBufN ); if( pe->sliced ) { // We have no way to track changes to the end of a slice, // so just make sure we remain in valid memery. if( ibin->used < pe->inputEnd ) pe->inputEnd = ibin->used; } else { // Not sliced, track input end. if( ibin->used != pe->inputEnd ) pe->inputEnd = ibin->used; } in = ibin->ptr.b + pos; inEnd = ibin->ptr.b + pe->inputEnd; ++rit; } break; case UT_STRING: tval = rit; match_string: { UBinaryIter bi; int size; ur_binSlice( ut, &bi, tval ); if( ur_strIsUcs2(bi.buf) ) goto bad_enc; size = bi.end - bi.it; if( size > (inEnd - in) ) goto failed; if( match_pattern_8(in, inEnd, bi.it, bi.end) == bi.end ) { in += size; ++rit; } else goto failed; } break; #if 0 case UT_BITSET: tval = rit; match_bitset: if( pos >= pe->inputEnd ) goto failed; { const UBuffer* bin = ur_bufferSer( tval ); int c = istr->ptr.c[ pos ]; if( bitIsSet( bin->ptr.b, c ) ) { ++rit; ++pos; } else goto failed; } break; #endif default: ur_error( PARSE_ERR, "invalid parse value" ); //orDatatypeName( ur_type(rit) ) ); goto parse_err; } } //complete: *spos = in - ibin->ptr.b; return rit; set_field: if( set ) { UCell* val; while( set != rit ) { val = ur_wordCellM( ut, set++ ); CHECK_WORD(val); ur_setId(val, UT_INT); ur_int(val) = field; } set = 0; } ++rit; goto match; failed: *spos = in - ibin->ptr.b; return 0; bad_enc: ur_error( ut, UR_ERR_INTERNAL, "parse binary does not handle UCS2 strings" ); //goto parse_err; parse_err: pe->exception = PARSE_EX_ERROR; return 0; }