static size_t mmap_psocket(int op,int idx,int fd,unsigned maxframe,void **map, struct tpacket_req *treq,unsigned blknum){ size_t size; *map = MAP_FAILED; if((size = size_mmap_psocket(treq,maxframe,blknum)) == 0){ return 0; } if(idx >= 0){ struct sockaddr_ll sll; memset(&sll,0,sizeof(sll)); sll.sll_family = AF_PACKET; sll.sll_ifindex = idx; if(bind(fd,(struct sockaddr *)&sll,sizeof(sll)) < 0){ diagnostic("Couldn't bind idx %d (%s?)",idx,strerror(errno)); return 0; } }else if(op != PACKET_RX_RING){ diagnostic("Invalid idx with op %d: %d",op,idx); return -1; } if(op){ if(setsockopt(fd,SOL_PACKET,op,treq,sizeof(*treq)) < 0){ diagnostic("Couldn't set socket option (%s?)",strerror(errno)); return 0; } } if((*map = mmap(0,size,PROT_READ|PROT_WRITE, MAP_SHARED | (op ? 0 : MAP_ANONYMOUS), op ? fd : -1,0)) == MAP_FAILED){ diagnostic("Couldn't mmap %zub (%s?)",size,strerror(errno)); return 0; } // FIXME MADV_HUGEPAGE support was dropped in 2.6.38.4, it seems. #ifdef MADV_HUGEPAGE if(madvise(*map,size,MADV_HUGEPAGE)){ //diagnostic("Couldn't advise hugepages for %zu (%s?)",size,strerror(errno)); } #endif return size; }
void abort_tx_frame(interface *i,void *frame){ const omphalos_ctx *octx = get_octx(); struct tpacket_hdr *thdr = frame; ++i->txaborts; thdr->tp_status = TP_STATUS_AVAILABLE; if(octx->mode != OMPHALOS_MODE_SILENT){ diagnostic("Aborted TX %ju on %s",i->txaborts,i->name); } }
// Take as input everything following the ICMPv6 header void handle_nd_routersol(struct omphalos_packet *op,const void *frame,size_t len){ const interface *i = op->i; if(len < 4){ // First four bytes MUST be ignored by receiver diagnostic("%s data too small (%zu) on %s",__func__,len,i->name); op->malformed = 1; return; } len -= 4; frame = (const char *)frame + 4; while(len){ const struct icmp6_op *iop = frame; if(len < 2){ diagnostic("%s op too small (%zu) on %s",__func__,len,i->name); op->malformed = 1; return; } if(iop->len < 1){ diagnostic("%s bogon oplen (%u)",__func__,iop->len); op->malformed = 1; return; } if(len < iop->len * 8){ diagnostic("%s opdata too small (%zu) on %s",__func__,len,i->name); op->malformed = 1; return; } switch(iop->type){ case ICMP6_OP_SRCLINK: // FIXME do something? break; default: diagnostic("%s unknown option (%u)",__func__,iop->type); op->noproto = 1; // Continue processing the packet } len -= iop->len * 8; frame = (const char *)frame + iop->len * 8; } }
void print(TR_Debug *debug) { if (_next) _next->print(debug); if (_size > 0) { diagnostic(" % 4d: % 4d -> % 4d (% 4d) %5.5s %s\n", _lowOffset, _lowOffset, _lowOffset + _size - 1, _size, _register? debug->getName(_register, TR_DoubleWordReg) : "", _description ); } else { diagnostic(" % 4d: % 4d -> ---- (% 4d) %5.5s %s\n", _lowOffset, _lowOffset, _size, _register? debug->getName(_register, TR_DoubleWordReg) : "", _description ); } }
void app_main() { uint8_t sha_256[HASH_LEN] = { 0 }; esp_partition_t partition; // get sha256 digest for the partition table partition.address = ESP_PARTITION_TABLE_OFFSET; partition.size = ESP_PARTITION_TABLE_MAX_LEN; partition.type = ESP_PARTITION_TYPE_DATA; esp_partition_get_sha256(&partition, sha_256); print_sha256(sha_256, "SHA-256 for the partition table: "); // get sha256 digest for bootloader partition.address = ESP_BOOTLOADER_OFFSET; partition.size = ESP_PARTITION_TABLE_OFFSET; partition.type = ESP_PARTITION_TYPE_APP; esp_partition_get_sha256(&partition, sha_256); print_sha256(sha_256, "SHA-256 for bootloader: "); // get sha256 digest for running partition esp_partition_get_sha256(esp_ota_get_running_partition(), sha_256); print_sha256(sha_256, "SHA-256 for current firmware: "); const esp_partition_t *running = esp_ota_get_running_partition(); esp_ota_img_states_t ota_state; if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK) { if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) { // run diagnostic function ... bool diagnostic_is_ok = diagnostic(); if (diagnostic_is_ok) { ESP_LOGI(TAG, "Diagnostics completed successfully! Continuing execution ..."); esp_ota_mark_app_valid_cancel_rollback(); } else { ESP_LOGE(TAG, "Diagnostics failed! Start rollback to the previous version ..."); esp_ota_mark_app_invalid_rollback_and_reboot(); } } } // Initialize NVS. esp_err_t err = nvs_flash_init(); if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { // OTA app partition table has a smaller NVS partition size than the non-OTA // partition table. This size mismatch may cause NVS initialization to fail. // If this happens, we erase NVS partition and initialize NVS again. ESP_ERROR_CHECK(nvs_flash_erase()); err = nvs_flash_init(); } ESP_ERROR_CHECK( err ); initialise_wifi(); xTaskCreate(&ota_example_task, "ota_example_task", 8192, NULL, 5, NULL); }
/** @brief Writes an arrow representation of a 2D D8 flow direction array @author Richard Barnes @param[in] &filename Name of file to write to @param[in] &elevations 2D array of D8 flow directions @returns 0 upon success */ int write_arrows(const char filename[], const char_2d &flowdirs){ std::locale::global(std::locale("")); std::wofstream fout; Timer write_time; ProgressBar progress; write_time.start(); diagnostic_arg("Opening arrow output file \"%s\"...",filename); fout.open(filename); if(!fout.is_open()){ diagnostic("failed!\n"); exit(-1); //TODO: Need to make this safer! Don't just close after all that work! } diagnostic("succeeded.\n"); diagnostic("%%Writing arrows...\n"); progress.start( flowdirs.width()*flowdirs.height() ); for(int y=0;y<flowdirs.height();++y){ progress.update( y*flowdirs.width() ); for(int x=0;x<flowdirs.width();++x){ if(flowdirs(x,y)==flowdirs.no_data) //TODO: Crude way of detecting chars and bools fout<<L" "; else if (flowdirs(x,y)==NO_FLOW) fout<<fd[0]; else fout<<fd[flowdirs(x,y)]; fout<<L" "; } fout<<std::endl; } diagnostic_arg(SUCCEEDED_IN,progress.stop()); fout.close(); write_time.stop(); diagnostic_arg("Write time was: %lf\n", write_time.accumulated()); return 0; }
static void handle_ieee80211_packet(omphalos_packet *op,const void *frame,size_t len,unsigned freq){ const ieee80211hdr *ihdr = frame; // FIXME certain packets don't have the full 802.11 header (8 bytes, // control/duration/h_dest, seems to be the minimum). if(len < sizeof(ieee80211hdr)){ op->malformed = 1; diagnostic("%s Packet too small (%zu) on %s", __func__,len,op->i->name); return; } if(IEEE80211_VERSION(ihdr->control) != 0){ op->noproto = 1; diagnostic("%s Unknown version (%d) on %s",__func__, IEEE80211_VERSION(ihdr->control),op->i->name); return; } switch(IEEE80211_TYPE(ihdr->control)){ case MANAGEMENT_FRAME:{ unsigned stype = IEEE80211_SUBTYPE(ihdr->control); if(stype != IEEE80211_SUBTYPE_PROBE_REQUEST){ handle_ieee80211_mgmt(op,frame,len,freq); } }break; case CONTROL_FRAME:{ handle_ieee80211_ctrl(op,frame,len); }break; case DATA_FRAME:{ handle_ieee80211_data(op,frame,len); }break; default:{ op->noproto = 1; diagnostic("%s Unknown type %d on %s",__func__, IEEE80211_TYPE(ihdr->control),op->i->name); return; }break; } }
// Returns 1 for a valid SSDP response, -1 for a valid SSDP query, 0 otherwise int handle_ssdp_packet(omphalos_packet *op,const void *frame,size_t len) { if(len < __builtin_strlen(SSDP_METHOD_NOTIFY)) { diagnostic("%s frame too short (%zu)",__func__,len); op->malformed = 1; return 0; } if(strncmp(frame,SSDP_METHOD_NOTIFY,__builtin_strlen(SSDP_METHOD_NOTIFY)) == 0) { return 1; } else if(strncmp(frame,SSDP_METHOD_SEARCH,__builtin_strlen(SSDP_METHOD_SEARCH)) == 0) { return -1; } return 0; }
static int packet_multicast(int fd,int ifindex){ struct packet_mreq pm; memset(&pm,0,sizeof(pm)); pm.mr_ifindex = ifindex; pm.mr_type = PACKET_MR_ALLMULTI; if(setsockopt(fd,SOL_PACKET,PACKET_ADD_MEMBERSHIP,&pm,sizeof(pm))){ diagnostic("Couldn't PACKET_ADD_MEMBERSHIP (%s?)",strerror(errno)); return -1; } return 0; }
int OBJFileReader::parseIndex(const char*& current, int max) { int val = parseInt(current); val += (val < 0) ? max : -1; if(val < 0 || val >= max) { diagnostic(false, current, "index out of range"); val = 0; } return val; }
//function to copy weight values from cell_array to weight_array int munkres::assign(ordered_pair *matching) { //total cost of the matching int total_cost = 0; //did we find a matching? bool matching_found = false; //For Checking if (diag_on) { diagnostic(1); } //try to find a matching matching_found = find_a_matching(); //For Checking if (diag_on) { diagnostic(1); } //total up the weights from matched vertices for (int i = 0; i < num_rows; i++) { for (int j = 0; j < num_columns; j++) { if (cell_array[i][j].starred) { matching[i].col = j; matching[i].row = i; total_cost += weight_array[i][j]; } } } return total_cost; }
static void handle_ieee80211_ctrl(omphalos_packet *op,const void *frame,size_t len){ const ieee80211ctrl *ictrl = frame; if(len < sizeof(*ictrl)){ op->malformed = 1; diagnostic("%s Packet too small (%zu) on %s", __func__,len,op->i->name); return; } op->l2d = lookup_l2host(op->i,ictrl->h_dest); len -= sizeof(*ictrl); }
int import_module(std::string mname) { try { module_name mod(mname); std::string base = "."; bool num_threads = 1; bool keep_proofs = false; env = import_modules(env, base, 1, &mod, num_threads, keep_proofs, ios); } catch (lean::exception & ex) { simple_pos_info_provider pp("import_module"); lean::display_error(diagnostic(env, ios), &pp, ex); return 1; } return 0; }
static int get_block_size(unsigned fsize,unsigned *bsize){ int b; // Ought be a power of two for performance. Must be a multiple of // page size. Ought be a multiple of tp_frame_size for efficiency. // Ought otherwise be as small as possible, or else the allocation // blocks/fails due to need for large VMA's. b = getpagesize(); if(b < 0){ diagnostic("Couldn't get page size (%s?)",strerror(errno)); return -1; } *bsize = b; while(*bsize < fsize){ if((*bsize << 1u) < *bsize){ diagnostic("No valid configurations found"); return -1; } *bsize <<= 1u; } return 0; }
bool WavefrontFileReader::parse(char* buffer, char* end) { onStartParse(); const char* current = buffer; lineNo = 0; errors = 0; // main line loop while(current != end) { curLine = current; lineNo++; errThisLine = false; // find end of line const char* endOfLine = current; while(*endOfLine != '\n') endOfLine++; // terminate line buffer const char* termPos = current + (endOfLine - current); while(termPos >= current && isspace(*termPos)) termPos--; *const_cast<char*>(termPos+1) = 0; // parse it if(*current == '#') // comment current = endOfLine; else if(*current == '\r' || *current == 0) // empty line ; else parseLine(current, termPos+1); // we should now be past the command, at the 0 terminator. if(*current) { if(!errThisLine) diagnostic(true, current, "extra characters on line"); } current = endOfLine+1; // skip past newline/null } if(!errors) onSuccessfulParse(); return !errors; }
// Mark a frame as ready-to-send. Must have come from get_tx_frame() using this // same interface. Yes, we will see packets we generate on the RX ring. int send_tx_frame(interface *i,void *frame){ const omphalos_ctx *octx = get_octx(); struct tpacket_hdr *thdr = frame; int ret = 0; assert(thdr->tp_status == TP_STATUS_PREPARING); if(octx->mode != OMPHALOS_MODE_SILENT){ int self,out; categorize_tx(i,(const char *)frame + thdr->tp_mac,&self,&out); if(self){ int r; r = send_to_self(i,frame); if(r < 0){ ++i->txerrors; }else{ i->txbytes += r; ++i->txframes; } ret |= r < 0 ? -1 : 0; } if(out){ uint32_t tplen = thdr->tp_len; int r; //thdr->tp_status = TP_STATUS_SEND_REQUEST; //r = send(i->fd,NULL,0,0); r = send(i->fd,(const char *)frame + thdr->tp_mac,tplen,0); if(r == 0){ r = tplen; } //diagnostic("Transmitted %d on %s",ret,i->name); if(r < 0){ diagnostic("Error out-TXing %u on %s (%s)",tplen,i->name,strerror(errno)); ++i->txerrors; }else{ i->txbytes += r; ++i->txframes; } ret |= r < 0 ? -1 : 0; } thdr->tp_status = TP_STATUS_AVAILABLE; }else{ abort_tx_frame(i,frame); ret = 0; } return ret; }
int process_file(std::string input_filename) { bool ok = true; try { environment temp_env(env); io_state temp_ios(ios); if (!parse_commands(temp_env, temp_ios, input_filename.c_str(), optional<std::string>(), false, num_threads)) { ok = false; } } catch (lean::exception & ex) { simple_pos_info_provider pp(input_filename.c_str()); ok = false; lean::display_error(diagnostic(env, ios), &pp, ex); } return ok ? 0 : 1; }
/* The main testfunction. Returns 0 if any error is found in the cfg */ int kfg_testit (KFG kfg, int quiet_mode) { cfg = kfg; quiet = (quiet_mode == 1); error_found = 0; diagnostic ("Consistency test of cfg and PAG-interface "); /* do the tests */ if (0 != kfg_num_nodes (cfg)) { if (error_found < 100) test_1 (); if (error_found < 100) test_2 (); if (error_found < 100) test_3 (); if (error_found < 100) test_4 (); if (error_found < 100) test_5 (); if (error_found < 100) test_6 (); if (error_found < 100) test_7 (); if (error_found < 100) test_8 (); if (error_found < 100) test_9 (); if (error_found < 100) test_10 (); if (error_found < 100) test_11 (); if (error_found < 100) test_12 (); if (error_found < 100) test_13 (); } /* tests for empty cfg's */ else test_0 (); if (error_found == 0) diagnostic (" excellent!\n"); else diagnostic (" ** errors found **\n"); return (error_found == 0); }
static void handle_ieee80211_mgmt(omphalos_packet *op,const void *frame,size_t len,unsigned freq){ const ieee80211mgmtdata *ibec = frame; if(len < sizeof(*ibec)){ op->malformed = 1; diagnostic("%s Packet too small (%zu) on %s", __func__,len,op->i->name); return; } op->l2s = lookup_l2host(op->i,ibec->h_src); len -= sizeof(*ibec); op->l3s = lookup_local_l3host(&op->tv,op->i,op->l2s,AF_BSSID,ibec->bssid); handle_ieee80211_mgmtfix(op,(const char *)frame + sizeof(*ibec),len,freq); }
int WavefrontFileReader::parseInt(const char*& current) { #if 1 const char* cur = current; unsigned int magn=0,sgn=0; int digits = 0; while(isspace(*cur)) cur++; if(*cur == '-' || *cur == '+') sgn = *cur++ == '-'; while(*cur >= '0' && *cur <= '9') { unsigned int mago = magn; magn = magn*10 + (*cur++ - '0'); if(magn < mago) diagnostic(false, cur, "int overflow"); digits++; } if(!digits) diagnostic(true, current, "int expected"); current = cur; return sgn ? -static_cast<int>(magn) : static_cast<int>(magn); #else const char* cur = current; long val = strtol(cur, const_cast<char**>(¤t), 10); if(current == cur) diagnostic(true, current, "int expected"); return static_cast<int>(val); #endif }
static void handle_ieee80211_data(omphalos_packet *op,const void *frame,size_t len){ const ieee80211data *idata = frame; if(len < sizeof(*idata)){ op->malformed = 1; diagnostic("%s Packet too small (%zu) on %s", __func__,len,op->i->name); return; } op->l2d = lookup_l2host(op->i,idata->h_dest); op->l2s = lookup_l2host(op->i,idata->h_src); len -= sizeof(*idata); // FIXME and do what?? }
/* * - all nodes of a procedure are reachable from entry/exit node of the corresponding procedure */ static void test_11 (void) { int i, procnum, num, count = 0; KFG_NODE_LIST list; KFG_NODE node; diagnostic ("."); /* create a marker array */ num = kfg_num_nodes (cfg); check = malloc (sizeof (int) * num); assert (NULL != check); /* walk through all-nodes list */ for (list = kfg_all_nodes (cfg); 0 == kfg_node_list_is_empty (list); ) { node = kfg_node_list_head (list); list = kfg_node_list_tail (list); procnum = kfg_procnumnode (cfg, node); for (i = 0; i < num; i++) check[i] = (procnum != kfg_procnum (cfg, i)); /* node must be reachable (forward direction) */ if (0 == test_11_visit (kfg_numproc (cfg, procnum), node, 0)) if (count == 0) { error ("node which is unreachable from its procedure entry node found: id == %d, procedure-number == %d\n", kfg_get_id (cfg, node), procnum); count++; } for (i = 0; i < num; i++) check[i] = (procnum != kfg_procnum (cfg, i)); /* node must be reachable (backward direction) */ if (0 == test_11_visit (kfg_get_end (cfg, kfg_numproc (cfg, procnum)), node, 1)) if (count == 0) { error ("node which is unreachable from its procedure exit node found: id == %d, procedure-number == %d\n", kfg_get_id (cfg, node), procnum); count++; } } /* delete marker array */ free (check); }
//Star zeroes that don't have stars (upon thars :P) in the //same row or column void munkres::step2(void) { //iterate through rows for (int i = 0; i < num_rows; i++) { //iterate through columns for (int j = 0; j < num_columns; j++) { //if the current index is equal to 0 if (cell_array[i][j].weight == 0) { //check for stars in current row if (!row_starred[i]) { //if not try to find one find_star_row(i); } //check for stars in current column if (!column_starred[j]) { //if not try to find one find_star_column(j); } //if no stars in column or row then star current index if (!row_starred[i] && !column_starred[j]) { //star index cell_array[i][j].starred = true; //mark row as having a star row_starred[i] = true; //mark column as having a star column_starred[j] = true; } } } } if (diag_on) { std::cerr << "Step 2" << std::endl; diagnostic(3); } }
//cover all columns with starred zeros //if (num_rows) columns are covered then return true //to signify that we're done bool munkres::step3(void) { //an iterator for our while loop int iter = 0; //loop through columns for (int i = 0; i < num_columns; i++) { //if the column is starred if (column_starred[i]) { //cover it column_cov[i] = true; } } //while every column so far is covered for (int i = 0; i < num_columns; i++) { if (column_cov[i]) { iter++; } } if (diag_on) { std::cerr << "Step 3" << std::endl; diagnostic(6); } //if all the rows were covered if (iter == num_rows) { //exit algorithm return true; } //else goto step 4 else return step4(); }
/// called to identify the branches and their targets in the method /// causes the _blocks array to be filled in with the basic blocks of the method void findAndMarkBranchTargets() { TR::Compilation *comp = this->comp(); if (debug("branchTargets")) diagnostic("findAndMarkBranchTargets for %s\n", comp->signature()); aboutToFindBranchTargets(); for (ByteCode bc = this->first(); bc != BCunknown; bc = this->next()) { if (_printByteCodes) this->printByteCode(); int32_t i = this->bcIndex(); if (this->isBranch()) markTarget(i, this->branchDestination(i) - i); markAnySpecialBranchTargets(bc); } finishedFindingBranchTargets(); }
void d8_flow_flats( const int_2d &flat_mask, const int_2d &groups, array2d<U> &flowdirs ){ ProgressBar progress; diagnostic("%%Calculating D8 flow directions using flat mask...\n"); progress.start( flat_mask.width()*flat_mask.height() ); #pragma omp parallel for for(int x=1;x<flat_mask.width()-1;x++){ progress.update( x*flat_mask.height() ); for(int y=1;y<flat_mask.height()-1;y++) if(flat_mask(x,y)==flat_mask.no_data) continue; else if (flowdirs(x,y)==NO_FLOW) flowdirs(x,y)=d8_masked_FlowDir(flat_mask,groups,x,y); } diagnostic_arg(SUCCEEDED_IN,progress.stop()); }
void trace(expr const & t, expr const & r) { if (!m_C->trace_instances()) return; auto out = diagnostic(m_C->env(), m_C->ios()); if (!m_displayed_trace_header && m_depth == 0) { if (auto fname = m_C->get_file_name()) { out << fname << ":"; } if (auto pos = m_C->get_pos()) { out << pos->first << ":" << pos->second << ":"; } out << " class-instance resolution trace" << endl; m_displayed_trace_header = true; } for (unsigned i = 0; i < m_depth; i++) out << " "; if (m_depth > 0) out << "[" << m_depth << "] "; out << m_meta << " : " << t << " := " << r << endl; }
/* * - mapping (node => id => node) must be correct * - node ids should be in range * - basic blocks should not be empty */ static void test_2 (void) { int i, num, id; KFG_NODE node; KFG_NODE_LIST list; diagnostic ("."); num = kfg_num_nodes (cfg); list = kfg_all_nodes (cfg); /* walk through the list of all nodes */ for (i = 0; 0 == kfg_node_list_is_empty (list); i++) { node = kfg_node_list_head (list); list = kfg_node_list_tail (list); id = kfg_get_id (cfg, node); /* check range of the id */ if (id < 0 || id >= num) { error ("node id out of range: %d not wihtin [0..%d]\n", id, num); return; } /* check mapping */ if (node != kfg_get_node (cfg, id)) { error ("error in mapping from node to id to node: id == %d\n", id); return; } /* empty node */ if (0 == kfg_get_bbsize (cfg, node)) error ("empty basic block found: id == %d\n", id); } /* number of processed nodes must be equal to number of nodes */ assert (i == num); }
void OMR::X86::Instruction::clobberRegsForRematerialisation() { // We assume most instructions modify all registers that appear in their // postconditions, with a few exceptions. // if ( self()->cg()->enableRematerialisation() && self()->getDependencyConditions() && (self()->getOpCodeValue() != ASSOCREGS) // reg associations aren't really instructions, so they don't modify anything && (self()->getOpCodeValue() != LABEL) // labels must already be handled properly for a variety of reasons && (!self()->getOpCode().isShiftOp()) && (!self()->getOpCode().isRotateOp()) // shifts and rotates often have a postcondition on ecx but don't clobber it ){ // Check the live discardable register list to see if this is the first // instruction that kills the rematerialisable range of a register. // TR::ClobberingInstruction *clob = NULL; TR_X86RegisterDependencyGroup *post = self()->getDependencyConditions()->getPostConditions(); for (uint32_t i = 0; i < self()->getDependencyConditions()->getNumPostConditions(); i++) { TR::Register *reg = post->getRegisterDependency(i)->getRegister(); if (reg->isDiscardable()) { if (!clob) { clob = new (self()->cg()->trHeapMemory()) TR::ClobberingInstruction(self(), self()->cg()->trMemory()); self()->cg()->addClobberingInstruction(clob); } clob->addClobberedRegister(reg); self()->cg()->removeLiveDiscardableRegister(reg); self()->cg()->clobberLiveDependentDiscardableRegisters(clob, reg); if (debug("dumpRemat")) diagnostic("---> Clobbering %s discardable postcondition register %s at instruction %s\n", self()->cg()->getDebug()->toString(reg->getRematerializationInfo()), self()->cg()->getDebug()->getName(reg), self()->cg()->getDebug()->getName(self())); } } } }
int OBJFileReader::findMaterial(const char* name) { // binary search size_t l=0, r=materials.size(); while(l<r) { size_t x = l + (r-l)/2; int cmp = materials[x].name.compare(name); if(cmp < 0) // mat[x]<name, continue right l = x+1; else if(cmp > 0) // mat[x]>name, continue left r = x; else // match! return x; } // no match found, report error and revert to default material diagnostic(true, curLine, "material not found, using default material"); return defaultMaterial; }