void DiskBackedBlockMap::write_block_to_disk(const BlockId& block_id, ServerBlock* block){ server_timer_.start_timer(current_line(), ServerTimer::WRITETIME); disk_backed_arrays_io_.write_block_to_disk(block_id, block); server_timer_.pause_timer(current_line(), ServerTimer::WRITETIME); block->unset_dirty(); block->set_on_disk(); }
void DiskBackedBlockMap::read_block_from_disk(ServerBlock*& block, const BlockId& block_id, size_t block_size){ /** Allocates space for a block, reads block from disk * into newly allocated space, sets the in_memory flag, * inserts into block_map_ if needed */ block = allocate_block(block, block_size); server_timer_.start_timer(current_line(), ServerTimer::READTIME); disk_backed_arrays_io_.read_block_from_disk(block_id, block); server_timer_.pause_timer(current_line(), ServerTimer::READTIME); block->set_in_memory(); }
void BlockManager::lazy_gpu_read_on_host(const Block::BlockPtr& blk) { if (!blk->is_on_gpu() && !blk->is_on_host()) { fail("block allocated neither on host or gpu", current_line()); } else if (!blk->is_on_host()) { blk->allocate_host_data(); _gpu_device_to_host(blk->get_data(), blk->get_gpu_data(), blk->size()); } else if (blk->is_dirty_on_gpu()) { _gpu_device_to_host(blk->get_data(), blk->get_gpu_data(), blk->size()); } else if (blk->is_dirty_on_all()) { fail("block dirty on host & gpu !", current_line()); } blk->set_on_host(); blk->unset_dirty_on_gpu(); }
void SialOpsParallel::restore_persistent(Interpreter* worker, int array_slot, int string_slot) { SIP_LOG(std::cout << "restore_persistent with array " << sip_tables_.array_name(array_slot) << " in slot " << array_slot << " and string \"" << sip_tables_.string_literal(string_slot) << "\"" << std::endl); if (sip_tables_.is_distributed(array_slot) || sip_tables_.is_served(array_slot)) { int my_server = sip_mpi_attr_.my_server(); if (my_server > 0) { int restore_persistent_tag; restore_persistent_tag = barrier_support_.make_mpi_tag_for_RESTORE_PERSISTENT(); int line_number = current_line(); int buffer[4] = { array_slot, string_slot, line_number, barrier_support_.section_number()}; SIPMPIUtils::check_err( MPI_Send(buffer, 4, MPI_INT, my_server, restore_persistent_tag, MPI_COMM_WORLD)); //expect ack ack_handler_.expect_ack_from(my_server, restore_persistent_tag); } } else { persistent_array_manager_->restore_persistent(worker, array_slot, string_slot); SIP_LOG(std::cout << "returned from restore_persistent" << std::endl << std::flush); } }
Block::BlockPtr BlockManager::get_gpu_block_for_reading(const BlockId& id) { Block::BlockPtr blk = block(id); check(blk != NULL, "attempting to read non-existent gpu block", current_line()); // Lazy copying of data from host to gpu if needed. lazy_gpu_read_on_device(blk); return blk; }
Block::BlockPtr SialOpsParallel::get_block_for_updating(const BlockId& id) { int array_id = id.array_id(); check( !(sip_tables_.is_distributed(array_id) || sip_tables_.is_served(array_id)), "attempting to update distributed or served block", current_line()); return block_manager_.get_block_for_updating(id); }
static table_entry * new_table_entry (open_table * file, table_entry_type type) { table_entry *entry; entry = ZALLOC (table_entry); entry->file = file->root; entry->line = current_line (file); entry->type = type; return entry; }
ServerBlock* DiskBackedBlockMap::allocate_block(ServerBlock* block, size_t block_size, bool initialize){ /** If enough memory remains, allocates block and returns. * Otherwise, frees up memory by writing out dirty blocks * till enough memory has been obtained, then allocates * and returns block. */ std::size_t remaining_mem = max_allocatable_bytes_ - ServerBlock::allocated_bytes(); while (block_size * sizeof(double) > remaining_mem){ try{ BlockId bid = policy_.get_next_block_for_removal(); ServerBlock* blk = block_map_.block(bid); SIP_LOG(std::cout << "S " << sip_mpi_attr_.company_rank() << " : Freeing block " << bid << " and writing to disk to make space for new block" << std::endl); if(blk->is_dirty()){ write_block_to_disk(bid, blk); } blk->free_in_memory_data(); // Junmin's fix : // As a result of freeing up block memory, the remaining memory should // have increased. Otherwise it will go into an infinite loop. if (!(remaining_mem < max_allocatable_bytes_ - ServerBlock::allocated_bytes())) { throw std::out_of_range("Break now."); } remaining_mem = max_allocatable_bytes_ - ServerBlock::allocated_bytes(); } catch (const std::out_of_range& oor){ std::cerr << " In DiskBackedBlockMap::allocate_block" << std::endl; std::cerr << oor.what() << std::endl; std::cerr << *this << std::endl; fail(" Something got messed up in the internal data structures of the Server", current_line()); } catch(const std::bad_alloc& ba){ std::cerr << " In DiskBackedBlockMap::allocate_block" << std::endl; std::cerr << ba.what() << std::endl; std::cerr << *this << std::endl; fail(" Could not allocate ServerBlock, out of memory", current_line()); } } std::stringstream ss; ss << "S " << sip_mpi_attr_.company_rank() << " : Could not allocate memory for block of size " << block_size << ", Memory being used :" << ServerBlock::allocated_bytes() << std::endl; sip :: check (block_size <= max_allocatable_bytes_ - ServerBlock::allocated_bytes(), ss.str()); if (block == NULL) { block = new ServerBlock(block_size, initialize); } else { block->allocate_in_memory_data(); } return block; }
void delete_or_controlAct(Widget, XEvent *e, String *params, Cardinal *num_params) { clear_isearch(); string input = current_line(); strip_trailing_newlines(input); if (input.empty()) XtCallActionProc(gdb_w, "gdb-control", e, params, *num_params); else XtCallActionProc(gdb_w, "delete-next-character", e, params, *num_params); }
char *err_msg_n (struct error_data *err, char *fmt) { char* ret = (char*) MALLOC (BASE_SIZE(err)+strlen(fmt)); if (ret == NULL) { err->ed_error_value = ERR_OUTOFMEMORY; return NULL; } if (current_line()==1) sprintf (ret, "%s[%5d] : %s", err->ed_filename, err->ed_curr_line+1, fmt); else sprintf (ret, "%s[%5d-%5d] : %s", err->ed_filename, err->ed_curr_line+1, err->ed_curr_line+current_line(), fmt); return ret; }
/** creates a new block with the given Id and inserts it into the block map. * It is an error to try to create a new block if a block with that id already exists * exists. */ Block::BlockPtr BlockManager::create_block(const BlockId& block_id, const BlockShape& shape) { try { Block::BlockPtr block_ptr = new Block(shape); insert_into_blockmap(block_id, block_ptr); return block_ptr; } catch (const std::out_of_range& oor){ std::cerr << " Failed in BlockManager::create_block :"<< oor.what() << std::endl; std::cerr << *this << std::endl; fail(" Could not create block, out of memory", current_line()); return NULL; } }
char *err_msg_sn (struct error_data *err, char *fmt, const char *one) { char* temp = (char*) MALLOC (BASE_SIZE(err)+strlen(fmt)); char* ret = (char*) MALLOC (BASE_SIZE(err)+strlen(fmt)+strlen(one)); if (ret == NULL || temp == NULL) { err->ed_error_value = ERR_OUTOFMEMORY; return NULL; } if (current_line()==1) sprintf (temp, "%s[%5d] : %s", err->ed_filename, err->ed_curr_line+current_line(), fmt); else sprintf (temp, "%s[%5d-%5d] : %s", err->ed_filename, err->ed_curr_line+1, err->ed_curr_line+current_line(), fmt); sprintf (ret, temp, one); FREE (temp); return ret; }
void func_l(FILE *fp,int para) { int line = current_line(fp); int pos = ftell(fp); if (para==-1) printf("line:%d %s", line+1, old_pro[line]); else { if (para >= 0 && para <= lin_num) { printf("line:%d %s", para, old_pro[para-1]); } } othercode = 0; return; }
int IS_ARRIVE(FILE *fp) { int line; BP *start; start = PointHead->next; line = current_line(fp)+1; while (start != NULL) { if (start->line_num == line) { return 1; } start = start->next; } return 0; }
/** * A put appears in a SIAL program as * put target(i,j,k,l) += source(i,j,k,l) * So we need the target block id, but the source block data. * Accumulation is done by the server * * The implementation will be more complicated if asynchronous send is * used * * @param target * @param source_ptr */ void SialOpsParallel::put_accumulate(BlockId& target_id, const Block::BlockPtr source_block) { //partial check for data races check_and_set_mode(target_id, WRITE); //send message with target block's id to server int my_rank = sip_mpi_attr_.global_rank(); int server_rank = data_distribution_.get_server_rank(target_id); int put_accumulate_tag, put_accumulate_data_tag; put_accumulate_tag = barrier_support_.make_mpi_tags_for_PUT_ACCUMULATE( put_accumulate_data_tag); sip::check(server_rank>=0&&server_rank<sip_mpi_attr_.global_size(), "invalid server rank",current_line()); SIP_LOG(std::cout<<"W " << sip_mpi_attr_.global_rank() << " : sending PUT_ACCUMULATE for block " << target_id << " to server "<< server_rank << std::endl); // Construct int array to send to server. const int to_send_size = BlockId::MPI_BLOCK_ID_COUNT + 2; const int line_num_offset = BlockId::MPI_BLOCK_ID_COUNT; const int section_num_offset = line_num_offset + 1; int to_send[to_send_size]; // BlockId & line number int *serialized_block_id = target_id.to_mpi_array(); std::copy(serialized_block_id + 0, serialized_block_id + BlockId::MPI_BLOCK_ID_COUNT, to_send); to_send[line_num_offset] = current_line(); to_send[section_num_offset] = barrier_support_.section_number(); //send block id SIPMPIUtils::check_err( MPI_Send(to_send, to_send_size, MPI_INT, server_rank, put_accumulate_tag, MPI_COMM_WORLD)); //immediately follow with the data SIPMPIUtils::check_err( MPI_Send(source_block->get_data(), source_block->size(), MPI_DOUBLE, server_rank, put_accumulate_data_tag, MPI_COMM_WORLD)); //ack ack_handler_.expect_ack_from(server_rank, put_accumulate_data_tag); SIP_LOG( std::cout<< "W " << sip_mpi_attr_.global_rank() << " : Done with PUT_ACCUMULATE for block " << target_id << " to server rank " << server_rank << std::endl); }
//TODO optimize this. Can reduce searches in block map. void SialOpsParallel::get(BlockId& block_id) { //check for "data race" check_and_set_mode(block_id, READ); //if block already exists, or has pending request, just return Block::BlockPtr block = block_manager_.block(block_id); if (block != NULL) return; //send get message to block's server, and post receive int server_rank = data_distribution_.get_server_rank(block_id); int get_tag; get_tag = barrier_support_.make_mpi_tag_for_GET(); sip::check(server_rank>=0&&server_rank<sip_mpi_attr_.global_size(), "invalid server rank",current_line()); SIP_LOG(std::cout<<"W " << sip_mpi_attr_.global_rank() << " : sending GET for block " << block_id << " to server "<< server_rank << std::endl); // Construct int array to send to server. const int to_send_size = BlockId::MPI_BLOCK_ID_COUNT + 2; const int line_num_offset = BlockId::MPI_BLOCK_ID_COUNT; const int section_num_offset = line_num_offset + 1; int to_send[to_send_size]; // BlockId & line number int *serialized_block_id = block_id.to_mpi_array(); std::copy(serialized_block_id + 0, serialized_block_id + BlockId::MPI_BLOCK_ID_COUNT, to_send); to_send[line_num_offset] = current_line(); to_send[section_num_offset] = barrier_support_.section_number(); SIPMPIUtils::check_err( MPI_Send(to_send, to_send_size, MPI_INT, server_rank, get_tag, MPI_COMM_WORLD)); //allocate block, and insert in block map, using block data as buffer block = block_manager_.get_block_for_writing(block_id, true); //post an asynchronous receive and store the request in the //block's state MPI_Request request; SIPMPIUtils::check_err( MPI_Irecv(block->get_data(), block->size(), MPI_DOUBLE, server_rank, get_tag, MPI_COMM_WORLD, &request)); block->state().mpi_request_ = request; }
std::vector<command> commands_queue(std::string file_path) { std::vector<command> output; const std::locale empty_locale = std::locale::empty(); typedef std::codecvt_utf8<wchar_t> converter_type; const converter_type* converter = new converter_type; const std::locale utf8_locale = std::locale(empty_locale, converter); std::wifstream script_file; script_file.imbue(utf8_locale); script_file.open(file_path); wchar_t *buffer = new wchar_t[1024]; while (script_file.getline(buffer, 1024)) { command current_command; std::wstringstream current_line(buffer); std::wstring current_arg; current_line >> current_arg; if (current_arg == L"analize_vocabulary") current_command.type = CMD_TYPE::CMD_ANALIZE_VOCABULARY; else if (current_arg == L"search_word") current_command.type = CMD_TYPE::CMD_WORD_SEARCH; else { current_command.type = CMD_TYPE::CMD_UNKNOWN; continue; } size_t quote_pos = current_line.str().find_first_of(L'\"'); while (!current_line.eof()) { if (quote_pos >= static_cast<size_t>(current_line.tellg()) + 2) { current_line >> current_arg; current_command.args.push_back(current_arg); } else { std::wstring quote_string; quote_pos = current_line.str().find_first_of(L'\"', quote_pos + 1); while (quote_pos > static_cast<size_t>(current_line.tellg()) && !current_line.eof()) { current_line >> current_arg; quote_string.append(current_arg); quote_string.append(L" "); } quote_string.erase(quote_string.size() - 1, 1); quote_pos = quote_string.find_first_of(L'\"'); while (quote_pos != std::wstring::npos) { quote_string.erase(quote_pos, 1); quote_pos = quote_string.find_first_of(L'\"', quote_pos + 1); } current_command.args.push_back(quote_string); } }
/** Removes all the blocks associated with the given array from the block map. * Removing the array from the map will cause its destructor to * be called, which will delete the data. Because of this, we must be very * careful to remove blocks that should not be delete from the block_map_. */ void SialOpsParallel::delete_distributed(int array_id) { //delete any blocks stored locally along with the map block_manager_.block_map_.delete_per_array_map_and_blocks(array_id); //send delete message to server if responsible worker int server_rank = sip_mpi_attr_.my_server(); if (server_rank > 0) { int line_number = current_line(); int to_send[3] = { array_id, line_number, barrier_support_.section_number() }; SIP_LOG(std::cout<<"W " << sip_mpi_attr_.global_rank() << " : sending DELETE to server "<< server_rank << std::endl); int delete_tag = barrier_support_.make_mpi_tag_for_DELETE(); SIPMPIUtils::check_err( MPI_Send(to_send, 3, MPI_INT, server_rank, delete_tag, MPI_COMM_WORLD)); ack_handler_.expect_ack_from(server_rank, delete_tag); } }
void BlockManager::lazy_gpu_write_on_device(Block::BlockPtr& blk, const BlockId &id, const BlockShape& shape) { if (!blk->is_on_gpu() && !blk->is_on_host()) { block_map_.cached_delete_block(id); // Get rid of block, create a new one blk = create_gpu_block(id, shape); // if (is_scope_extent) { // temp_block_list_stack_.back()->push_back(id); // } } else if (!blk->is_on_gpu()) { blk->allocate_gpu_data(); _gpu_host_to_device(blk->get_data(), blk->get_gpu_data(), blk->size()); } else if (blk->is_dirty_on_host()) { _gpu_host_to_device(blk->get_data(), blk->get_gpu_data(), blk->size()); } else if (blk->is_dirty_on_all()) { fail("block dirty on host & gpu !", current_line()); } blk->set_on_gpu(); blk->set_dirty_on_gpu(); blk->unset_dirty_on_host(); }
// Exit i-search mode and return to normal mode void clear_isearch(bool reset, bool show) { if (!gdb->isReadyWithPrompt()) return; if (isearch_state != ISEARCH_NONE) { isearch_state = ISEARCH_NONE; if (show) show_isearch(); if (reset) { set_history_from_line(current_line()); goto_history(); } } isearch_motion_ok = false; }
/** * action depends on whether array is local or remote. If remote, * a message is sent to my_server (if responsible). Otherwise, * a upcall is made to the local persistent_array_manager. * * @param worker * @param array_slot * @param string_slot */ void SialOpsParallel::set_persistent(Interpreter * worker, int array_slot, int string_slot) { if (sip_tables_.is_distributed(array_slot) || sip_tables_.is_served(array_slot)) { int my_server = sip_mpi_attr_.my_server(); if (my_server > 0) { int set_persistent_tag; set_persistent_tag = barrier_support_.make_mpi_tag_for_SET_PERSISTENT(); int line_number = current_line(); int buffer[4] = { array_slot, string_slot, line_number, barrier_support_.section_number()}; SIPMPIUtils::check_err( MPI_Send(buffer, 4, MPI_INT, my_server, set_persistent_tag, MPI_COMM_WORLD)); //ack ack_handler_.expect_ack_from(my_server, set_persistent_tag); } } else { persistent_array_manager_->set_persistent(worker, array_slot, string_slot); } }
bool Spline::Intersects(const Line& line) const { //Perform fast searches first: Point point_one(line.GetPointOne()); bool isOnPointOne = this->Intersects(point_one); if(isOnPointOne) return true; Point point_two(line.GetPointTwo()); bool isOnPointTwo = this->Intersects(point_two); if(isOnPointTwo) return true; //Perform slow O(n) point search: for(std::size_t i = 0; i < _result_points.size(); ++i) { line.Contains(_result_points.at(i)); if(_result_points.at(i).IsOnLine(line)) return true; } //Perform agonizingly slow O(n^2) line search. for(std::size_t i = 0; i < _result_points.size() - 1; ++i) { Line current_line(_result_points.at(i), _result_points.at(i+1), false); if(current_line.Intersects(line)) return true; } return false; }
int work_rr ( struct error_data *errors, struct name_context *context, u_int8_t **rr, char **non_rr) { char first_token[MAXTOKENLENGTH]; int ret_code; int i; struct scratch scratch; /* Memory management clean up */ if (*rr) { FREE (*rr); *rr = NULL; } if (*non_rr) { FREE (*non_rr); *non_rr = NULL; } if ((scratch.s_field = (u_int8_t *) MALLOC(RR_SCRATCH_LENGTH)) == NULL) { errors->ed_error_value = ERR_OUTOFMEMORY; return -1; } scratch.s_length = RR_SCRATCH_LENGTH; /* Source of data is hidden, just use GETWORD() to work my way through it */ /* Initialize errors to 'nothing set' */ errors->ed_error_value = ERR_UNSET; do { GETWORDorEOLN (ret_code, errors, first_token, sizeof(first_token), *non_rr, "First word", FREE_SCRATCH_UPDATE_ERRORS_AND_RETURN_NEG1); if (ret_code == GW_EOLN) { errors->ed_curr_line++; decrement_current_line(); } } while (ret_code == GW_EOLN); /* ret_code must be GW_WORD and first_token is the first word in line */ /* If the beginning of the first word is in special_chars, then get words until GW_EOLN is returned problem - storing the words until we MALLOC non_rr assemble them into *non_rr return ERR_OKBUTNOTRR in error structure, other ancillarys else take the first word as the name and parse the envelope depending on the type value, parse the remainder of the record no matter what happens, read tokens up through GW_EOLN */ /* This takes care of all the specially registered characters, processing and returning anything that is not an RR. */ for (i =0; i < special_count; i++) if (first_token[0]==special_chars[i]) { /* return with all of the upcoming line in *non_rr, *rr = NULL (already is), errors stating OKBUTNOTRR and update its line count. */ *non_rr = collect_words (first_token); errors->ed_curr_line=errors->ed_curr_line+current_line(); if (*non_rr) errors->ed_error_value = ERR_OKBUTNOTRR; else errors->ed_error_value = ERR_OUTOFMEMORY; FREE (scratch.s_field); return -1; } /* Now we can set about the business of parsing RR's */ /* Two parts, the envelope, the rdata */ ret_code = parse_record (&scratch, first_token, errors, context, non_rr); /* Final clean up */ if (ret_code==0) { if ((*rr = (u_int8_t*) MALLOC (scratch.s_index))==NULL) { errors->ed_error_value = ERR_OUTOFMEMORY; return -1; } memcpy (*rr, scratch.s_field, scratch.s_index); } errors->ed_curr_line=errors->ed_curr_line+current_line(); FREE (scratch.s_field); return ret_code; }
// Give a help dependent on current DDD state void WhatNextCB(Widget, XtPointer, XtPointer) { // Special DDD states if (ddd_has_crashed) { hint_on("fatal_dialog"); return; } // Special GDB states if (no_gdb()) { hint_on("no_debugger_dialog"); return; } if (gdb_has_crashed()) { hint_on("terminated_dialog"); return; } if (gdb_asks_yn) { hint_on("yn_dialog"); return; } if (gdb->recording()) { hint_on("recording"); return; } if (debuggee_running) { hint_on("running"); return; } if (!can_do_gdb_command()) { hint_on("busy"); return; } if (undo_buffer.showing_earlier_state()) { hint_on("showing_earlier_state"); return; } // Typical start-up situations ProgramInfo info; if (info.file.empty()) { hint_on("no_program"); return; } if (no_source_and_no_code()) { hint_on("no_source_and_no_code"); return; } // Examine state if (source_view->have_selection()) { hint_on("item_selected"); return; } if (data_disp->have_selection()) { hint_on("display_selected"); return; } if (!current_line().empty()) { hint_on("command_entered"); return; } if (!info.running) { hint_on("program_not_running"); return; } // Program has stopped and nothing is selected. defineConversionMacro("PROGRAM_STATE", info.state.chars()); if (code_but_no_source()) { hint_on("code_but_no_source"); return; } if (gdb->type() == GDB && info.state.contains("signal")) { int p = passed_to_program(info.state); if (p > 0) { hint_on("stopped_at_passed_signal"); return; } else if (p == 0) { hint_on("stopped_at_ignored_signal"); return; } } hint_on("stopped"); }
void TMemo::go_to_line(int line) { int ofs = line_offset(line-1); go_to(ofs,-1,current_line() > line ? -10 : +10); }
//TODO TEMPORARY FIX WHILE SEMANTICS BEING WORKED OUT Block::BlockPtr BlockManager::get_block_for_reading(const BlockId& id) { Block::BlockPtr blk = block(id); sial_check(blk != NULL, "Attempting to read non-existent block " + id.str(sip_tables_), current_line()); //// //#ifdef HAVE_CUDA // // Lazy copying of data from gpu to host if needed. // lazy_gpu_read_on_host(blk); //#endif //HAVE_CUDA return blk; }
// Send completed lines to GDB void gdbChangeCB(Widget w, XtPointer, XtPointer) { if (private_gdb_output) return; string input = current_line(); bool at_prompt = gdb_input_at_prompt; if (at_prompt) input.gsub("\\\n", ""); int newlines = input.freq('\n'); string *lines = new string[newlines + 1]; split(input, lines, newlines, '\n'); private_gdb_input = true; if (newlines == 0 || (gdb_input_at_prompt && input.contains('\\', -1))) { // No newline found - line is still incomplete set_history_from_line(input, true); } else { // Process entered lines clear_isearch(); promptPosition = XmTextGetLastPosition(w); for (int i = 0; i < newlines; i++) { string cmd = lines[i]; tty_out(cmd + "\n"); if (gdb_input_at_prompt) { if (cmd.matches(rxwhite) || cmd.empty()) { // Empty line: repeat last command cmd = last_command_from_history(); } else { // Add new command to history add_to_history(cmd); } } if (at_prompt) { // We're typing at the GDB prompt: place CMD in command queue gdb_command(cmd, w); } else { // Pass anything else right to GDB, clearing the command queue. clearCommandQueue(); gdb->send_user_ctrl_cmd(cmd + "\n"); } } } private_gdb_input = false; delete[] lines; }
/* gets block for reading and writing. The block should already exist.*/ Block::BlockPtr BlockManager::get_block_for_updating(const BlockId& id) { // std::cout << "calling get_block_for_updating for " << id << current_line()<<std::endl << std::flush; Block::BlockPtr blk = block(id); if (blk==NULL){ std::cout << *this; } sial_check(blk != NULL, "Attempting to update non-existent block " + id.str(sip_tables_), current_line()); #ifdef HAVE_CUDA // Lazy copying of data from gpu to host if needed. lazy_gpu_update_on_host(blk); #endif return blk; }
// Handle incremental searches; return true if processed static bool do_isearch(Widget, XmTextVerifyCallbackStruct *change) { if (isearch_state == ISEARCH_NONE) return false; string saved_isearch_string = isearch_string; bool processed = false; if (change->startPos == change->endPos) { // Character insertion string input = string(change->text->ptr, change->text->length); if (!input.contains('\n', -1)) { // Add to current search string isearch_string += input; processed = true; } } else if (change->endPos - change->startPos == 1) { // Backspace - remove last character from search string if (!isearch_string.empty()) isearch_string.after(int(isearch_string.length()) - 2) = ""; else clear_isearch(true, false); processed = true; } if (processed) { int history = -1; if (isearch_string.empty() || current_line().contains(isearch_string)) { // Search string found in current line history = -1; } else { history = search_history(isearch_string, int(isearch_state)); if (history < 0) { // Search string not found in history if (change->event != 0) XtCallActionProc(gdb_w, "beep", change->event, 0, 0); isearch_string = saved_isearch_string; } } // Make this a no-op if (!have_isearch_line) { isearch_line = current_line(); have_isearch_line = true; } // Redraw current line with appropriate prompt. XtAppAddTimeOut(XtWidgetToApplicationContext(gdb_w), 0, isearch_done, XtPointer(history)); // Upon the next call to gdbMotionCB(), clear ISearch mode, // unless it immediately follows this one. isearch_motion_ok = true; XtAppAddTimeOut(XtWidgetToApplicationContext(gdb_w), 10, set_isearch_motion_ok, XtPointer(false)); } return processed; }
// Show prompt according to current mode static void show_isearch() { XmTextPosition start = start_of_line(); if (start == XmTextPosition(-1)) return; string prompt; switch (isearch_state) { case ISEARCH_NONE: prompt = gdb->prompt(); break; case ISEARCH_NEXT: prompt = isearch_prompt; break; case ISEARCH_PREV: prompt = reverse_isearch_prompt; break; } if (isearch_state != ISEARCH_NONE) prompt += "`" + cook(isearch_string) + "': "; string input = current_line(); string line = prompt + input; bool old_private_gdb_output = private_gdb_output; private_gdb_output = true; XmTextReplace(gdb_w, start, XmTextGetLastPosition(gdb_w), XMST(line.chars())); promptPosition = start + prompt.length(); XmTextPosition pos = promptPosition; int index = input.index(isearch_string); if (isearch_state == ISEARCH_NONE || index < 0) { XmTextSetHighlight(gdb_w, 0, XmTextGetLastPosition(gdb_w), XmHIGHLIGHT_NORMAL); } else { XmTextSetHighlight(gdb_w, 0, pos + index, XmHIGHLIGHT_NORMAL); XmTextSetHighlight(gdb_w, pos + index, pos + index + isearch_string.length(), XmHIGHLIGHT_SECONDARY_SELECTED); XmTextSetHighlight(gdb_w, pos + index + isearch_string.length(), XmTextGetLastPosition(gdb_w), XmHIGHLIGHT_NORMAL); } if (index >= 0) pos += index; XmTextSetInsertionPosition(gdb_w, pos); XmTextShowPosition(gdb_w, pos); have_isearch_line = false; private_gdb_output = old_private_gdb_output; }