// // test accessing local bus on HTR // #define HTR_SLOT 12 // default HTR VME slot #define SLB_SITE 3 // default HTR SLB site #define BUS_NAME "caen:0" #define HAL_PATH "/home/daqowner/dist/hal/" #include "VMEDevice.hh" #include "VMEAddressTable.hh" #include "hcal/BusAdapterManager.hh" #include "hcalHTR.hh" #include "log4cplus/logger.h" #include "log4cplus/loglevel.h" #include "log4cplus/configurator.h" using namespace std; #include #include #include #include #include #include #include #include #include #include extern "C" { #include "unistd.h" } using namespace log4cplus; static HAL::VMEDevice* vme_dev; void cfg(char *slb_base,char *Filename); void flash(char *slb_base, char *Filename, int check); char* rl_gets(); bool isMem(char *); int tokenize( char *buff, char **tokens, int maxt); #define MAX_TOKENS 10 int main( int argc, char *argv[] ) { char buff[80]; int htr_slot = HTR_SLOT; int slb_site = SLB_SITE; char *bname = BUS_NAME; char slb_base[12]; bool resync = false; // process some args if( argc > 1) { for(int i = 1; i < argc; i++) { if(argv[i][0] != '-') { htr_slot = strtol( argv[i], NULL, 0); cout << "Slot number " << htr_slot << " specified" << endl; } else { switch(toupper(argv[i][1])) { case 'R': resync = true; break; } } } } // setup a logger log4cplus::BasicConfigurator config; config.configure(); Logger mylog = log4cplus::Logger::getInstance("mylog"); // log everything mylog.setLogLevel( log4cplus::TRACE_LOG_LEVEL); if( !resync) { printf("HTR VME Slot (1-21) [%d] ?", htr_slot); fgets( buff, 79, stdin); if( isdigit( *buff)) htr_slot = strtol( buff, NULL, 0); } // instantiate HTR with slot# and logger hcalHTR* htr = new hcalHTR::hcalHTR( htr_slot, mylog); try { // load address table cout << "Setup HTR VME" << endl; htr->setupVME( bname, (std::string)HAL_PATH + "HTR_r4_series1.dat"); cout << "Get VMEDevice for Altera chip on HTR" << endl; vme_dev = htr->getAltera(); } catch(std::exception& e){ printf("HTR initialization %s\n", e.what()); abort(); } cout << "HTR initialization successful" << endl; try { // check ID uint32_t work = 0; vme_dev->read( "IDRegister", &work); if( work == 0xedcafe) cout << "Read HTR ID= 0x" << hex << work << " (OK)" << endl; else { cout << "Read HTR ID= 0x" << hex << work << " (WRONG)" << endl; abort(); } // printf("SLB site (1-6) [%d] ?", slb_site); // fgets( buff, 79, stdin); // if( isdigit( *buff)) // slb_site = strtol( buff, NULL, 0); sprintf( slb_base, "SLB%d_BASE", slb_site); } catch(std::exception& e){ printf("Read from HTR %s\n", e.what()); abort(); } static char *tokens[MAX_TOKENS]; char *input, *input_copy, *command, *item; uint32_t offset, value,total,next[3]; string dev_mem; int i,j = 0,cn,k; int num_words = 0; bool quit = false; if( resync) goto resync_loop; while( !quit) { input = rl_gets(); input_copy = input; if(input != NULL && strlen(input)>0) { j = tokenize( input, tokens, MAX_TOKENS); command = tokens[0]; switch( toupper( command[0])) { case 'H': cout << "commands: "<< endl; cout << " [h]elp - display this screen" << endl; cout << " [rb]uf address number - reads number of 32-bit " << "words from GOL spy buffer starting at address" << endl; cout << " [r3]2 number - check number of cycles of 32-bit " << "LFSR data from both HTR FPGAs" << endl; cout << " must first set the LUT address " << "accordingly" << endl; cout << " [r2]4 number - check number of cycles of 24-bit" << " LFSR data in all three buffers" << endl; cout << " must first set the LUT address" << " accordingly" << endl; cout << " [r]ead address number - reads number entries starting" << " at location address(auto increase)" << endl; cout << " [w]rite address value - writes value to" << " location address" << endl; cout << " x - reset oSLB " << "(reset QPLL, DCM then enable GOLS)" << endl; cout << " p - period reset (every 10 sec)" << endl; cout << " [q]uit" << endl; break; case 'P': // periodic reset resync_loop: cout << "Reset link periodically when done" << endl; while(1) { vme_dev->write( slb_base, 0, HAL::HAL_NO_VERIFY, 4); usleep( 1000); // send some idle chars vme_dev->write( slb_base, 0x80, HAL::HAL_NO_VERIFY, 4); cout << "link re-synched" << endl; sleep(10); } break; case 'X': cout << "Resetting SLB and GOLS" << endl; vme_dev->write( slb_base, 4, HAL::HAL_NO_VERIFY, 0x48); vme_dev->write( slb_base, 2, HAL::HAL_NO_VERIFY, 0x48); vme_dev->write( slb_base, 0x38, HAL::HAL_NO_VERIFY, 0x48); vme_dev->write( slb_base, 0, HAL::HAL_NO_VERIFY, 4); usleep( 1000); // send some idle chars vme_dev->write( slb_base, 0x80, HAL::HAL_NO_VERIFY, 4); break; case 'R': switch(toupper(command[1])){ case 'B': // read buffer if(j >= 2) { offset = strtoul(tokens[1], NULL,0); if( j > 2) num_words = strtoul(tokens[2], NULL, 0); else num_words = 1; cn = 0; for(i = 0; i < 4*num_words; i++) { vme_dev->read( slb_base, &value, offset); if((cn%4) == 0) total = 0; total += (value & 0xff) << (8*(cn%4)); if((cn%4) == 3) printf("0x%02x : 0x%08x\n",cn/4,total); cn++; } } else { cout << "rbuf
" << endl; } break; case '3': // read buffer and check for 32 bit LFSR if( j == 2) num_words = strtoul(tokens[1], NULL, 0); else num_words = 0x7fffffff; for(cn = 0; cn < num_words; cn++){ //sample a new buffer vme_dev->write( slb_base, 2, HAL::HAL_NO_VERIFY, 0x40); //reset buffer addresses to 0 vme_dev->write( slb_base, 0, HAL::HAL_NO_VERIFY, 0x10); vme_dev->write( slb_base, 0, HAL::HAL_NO_VERIFY, 0x14); vme_dev->write( slb_base, 0, HAL::HAL_NO_VERIFY, 0x18); for(i = 0; i < 256; i++) { total = 0; for(j = 0; j < 4; j++){ vme_dev->read( slb_base, &value, 0x10); if(j < 3) total += (value & 0xff) << (8*j); } vme_dev->read( slb_base, &value, 0x14); total += (value & 0xff) << 24; if(i == 0) next[0] = total; if(next[0] != total) printf("\n error found at TOP0x%02x : expected : 0x%08x got : 0x%08x\n",i,next[0],total); next[0] = (total & 0x7fffffff) << 1; if(!(total%2) ^ ((total >> 1)%2) ^ ((total >> 21)%2) ^ (total >> 31)) next[0]++; for(j = 1; j < 4; j++){ vme_dev->read( slb_base, &value, 0x14); if(j == 1) total = (value & 0xf0) >> 4; if(j == 2) total += (value & 0xff) << 4; } for(j = 0; j < 4 ; j++){ vme_dev->read( slb_base, &value, 0x18); if(j < 2) total += (value & 0xff) << (8*j+12); if(j == 2) total += (value & 0xf) << 28; } if(i == 0) next[1] = total; if(next[1] != total) printf("\n error found at BOTTOM0x%02x : expected : 0x%08x got : 0x%08x\n",i,next[1],total); next[1] = (total & 0x7fffffff) << 1; if(!(total%2) ^ ((total >> 1)%2) ^ ((total >> 21)%2) ^ (total >> 31)) next[1]++; } if(cn%10 == 9){ printf("\r %d cycles checked",cn); fflush(stdout); } } printf("\n"); break; case '2': // read buffer and check for 24 bit LFSR if( j == 2) num_words = strtoul(tokens[1], NULL, 0); else num_words = 0x7fffffff; for(cn = 0; cn < num_words; cn++){ //sample a new buffer vme_dev->write( slb_base, 2, HAL::HAL_NO_VERIFY, 0x40); for(k = 0; k < 3; k++){ //reset buffer addresses to 0 vme_dev->write( slb_base, 0, HAL::HAL_NO_VERIFY, 0x10+k*4); for(i = 0; i < 256; i++) { total = 0; for(j = 0; j < 4; j++){ vme_dev->read( slb_base, &value, 0x10); if(j < 3) total += (value & 0xff) << (8*j); } if(i == 0) next[k] = total; if(next[k] != total) printf("\n error found at GOL%d 0x%02x : expected : 0x%08x got : 0x%08x\n",k,i,next[k],total); next[k] = (total & 0x7fffff) << 1; if(!((total >> 16)%2) ^ ((total >> 21)%2) ^ ((total >> 22)%2) ^ (total >> 23)) next[k]++; } } if(cn%10 == 9){ printf("\r %d cycles checked",cn); fflush(stdout); } } printf("\n"); break; default: if(j >= 2) { offset = strtoul(tokens[1], NULL,0); if( j > 2) num_words = strtoul(tokens[2], NULL, 0); else num_words = 1; for(i = 0; i < num_words; i++) { vme_dev->read( slb_base, &value, offset); printf("0x%03x : 0x%02x\n",offset,value & 0xff); offset += 4; } } else { cout << "read
" << endl; } break; } break; case 'C': cfg(slb_base,tokens[1]); break; case 'F': if(j > 2) flash(slb_base,tokens[1],1); else{ cfg(slb_base,tokens[1]); flash(slb_base,tokens[1],0); } break; case 'W': offset = strtoul(tokens[1], NULL, 0); value = strtoul(tokens[2], NULL, 0); vme_dev->write( slb_base, value, HAL::HAL_NO_VERIFY, offset); if(j != 3) { cout << "write
" << endl; } break; case 'Q': quit = true; break; } } } } void cfg(char *slb_base,char *Filename){ FILE *f; int ln = 0; char line[120]; unsigned buf,crc[24] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},tmp[24]; unsigned long wd_cnt = 0,chksum; uint32_t data; // open input file with Altera code f = fopen(Filename,"r"); if (!f) { printf("cfgFPGA: Cannot open file %s\n",Filename); abort(); } //reprogram FPGA vme_dev->write( slb_base, 3, HAL::HAL_NO_VERIFY, 0x10c); vme_dev->write( slb_base, 1, HAL::HAL_NO_VERIFY, 0x10c); //wait until init_b high do{ vme_dev->read( slb_base, &data, 0x10c); }while(!(data & 0x4)); // loop over record in the file and read them in the array "line" while ( fgets(line, 120, f) != NULL) { char c1[3],c2[5]; uint32_t data[200]; int i,j,byte_count,address,address_bias,rec_type,total; ln++; if(ln%0x1000 == 0)printf("current line: 0x%x\n",ln); // check that the record has more than 9 characters if ( strlen(line) < 9 ) { printf("programChip: Error while reading " "line %d: it has less than 9 characters\n",ln); abort(); } // number of bytes in the record (first two hex numbers) strncpy(c1,line+1,2); c1[2] = '\0'; sscanf(c1,"%x",&byte_count); // address (hex numbers 3-6) strncpy(c2,line+3,4); c2[4] = '\0'; sscanf(c2,"%x",&address); // record type (hex numbers 7-8) strncpy(c1,line+7,2); c1[2] = '\0'; sscanf(c1,"%x",&rec_type); // calculate checksum total = byte_count+address/256+address%256+rec_type; // loop over the rest of the characters in the record and // convert them to int for (i=0; i<(byte_count+1);i++) { strncpy(c1,line+2*i+9,2); c1[2] = '\0'; data[i] = strtol(c1,'\0',16); total = total + data[i]; } // check the checksum for the record if (total%256 != 0) { printf("programChip: Error while reading line " "%d - a checksum error is found\n",ln); abort(); } //byte count must be even if(byte_count%2 == 1)byte_count++; // only data records are written if (rec_type == 0) { for (i=0; iwrite( slb_base, data[i], HAL::HAL_NO_VERIFY, 0); //calculate CRC tmp[0] = data[i]%2+crc[21]+crc[20]+crc[19]+crc[18]+crc[17]+crc[16]; tmp[1] = (data[i]>>1)%2+crc[22]+crc[16]; tmp[2] = (data[i]>>2)%2+crc[23]+crc[17]; tmp[3] = (data[i]>>3)%2+crc[21]+crc[20]+crc[19]+crc[17]+crc[16]; tmp[4] = (data[i]>>4)%2+crc[22]+crc[19]+crc[16]; tmp[5] = (data[i]>>5)%2+crc[23]+crc[21]+crc[19]+crc[18]+crc[16]; tmp[6] = (data[i]>>6)%2+crc[22]+crc[21]+crc[18]+crc[16]; tmp[7] = (data[i]>>7)%2+crc[23]+crc[22]+crc[21]+crc[20]+crc[18]+crc[16]; tmp[8] = crc[23]+crc[22]+crc[21]+crc[19]+crc[17]+crc[0]; tmp[9] = crc[23]+crc[22]+crc[20]+crc[18]+crc[1]; tmp[10] = crc[23]+crc[20]+crc[18]+crc[17]+crc[16]+crc[2]; tmp[11] = crc[20]+crc[16]+crc[3]; tmp[12] = crc[21]+crc[17]+crc[4]; tmp[13] = crc[22]+crc[18]+crc[5]; tmp[14] = crc[23]+crc[21]+crc[20]+crc[18]+crc[17]+crc[16]+crc[6]; tmp[15] = crc[22]+crc[21]+crc[19]+crc[18]+crc[17]+crc[7]; tmp[16] = crc[23]+crc[22]+crc[20]+crc[19]+crc[18]+crc[8]; tmp[17] = crc[23]+crc[18]+crc[17]+crc[16]+crc[9]; tmp[18] = crc[21]+crc[20]+crc[16]+crc[10]; tmp[19] = crc[22]+crc[21]+crc[17]+crc[11]; tmp[20] = crc[23]+crc[22]+crc[18]+crc[12]; tmp[21] = crc[23]+crc[19]+crc[13]; tmp[22] = crc[20]+crc[14]; tmp[23] = crc[20]+crc[19]+crc[18]+crc[17]+crc[16]+crc[15]; for(j=0;j<24;j++) crc[j] = tmp[j]%2; wd_cnt++; if(wd_cnt > 0x33da0){ chksum = 0; for(j=0;j<24;j++) chksum = (chksum << 1) + crc[23-j]; vme_dev->read( slb_base, &data[i], 0x108); total = data[i] & 0xff; vme_dev->read( slb_base, &data[i], 0x104); total = (total << 8) + (data[i] & 0xff); vme_dev->read( slb_base, &data[i], 0x100); total = (total << 8) + (data[i] & 0xff); printf("wd_cnt = 0x%05x rd_back = 0x%06x chksum = 0x%06x\n",wd_cnt,total,chksum); } } // loop over bytes in the line } // rec_type equal to 0 } // loop over lines // close mcs file fclose(f); // reset local mode bit vme_dev->write( slb_base, 0, HAL::HAL_NO_VERIFY, 0x10c); // check done signal vme_dev->read( slb_base, &data, 0x10c); if(data & 0x8) printf("Done is high\n"); return; } void flash(char *slb_base, char *Filename, int check){ FILE *f; int ln = 0; char line[120]; unsigned buf; uint32_t data,blk_cnt = 0; /* vme_dev->read( slb_base,&data, 0xc); if(check == 0 && (data & 0x6) != 0x4){ printf("check ttc clock source please\n"); return; }*/ // open input file f = fopen(Filename,"r"); if (!f) { printf("cfgFPGA: Cannot open file %s\n",Filename); abort(); } //reset buffer address counter to 0 vme_dev->write( slb_base, 1, HAL::HAL_NO_VERIFY, 0x40); // loop over record in the file and read them in the array "line" while ( check == 0 && fgets(line, 120, f) != NULL) { char c1[3],c2[5]; uint32_t data[200],data1,data2; int i,byte_count,address,address_bias,rec_type,total; ln++; if(ln%0x1000 == 0)printf("current line: 0x%x\n",ln); // check that the record has more than 9 characters if ( strlen(line) < 9 ) { printf("programChip: Error while reading " "line %d: it has less than 9 characters\n",ln); abort(); } // number of bytes in the record (first two hex numbers) strncpy(c1,line+1,2); c1[2] = '\0'; sscanf(c1,"%x",&byte_count); // address (hex numbers 3-6) strncpy(c2,line+3,4); c2[4] = '\0'; sscanf(c2,"%x",&address); // record type (hex numbers 7-8) strncpy(c1,line+7,2); c1[2] = '\0'; sscanf(c1,"%x",&rec_type); // calculate checksum total = byte_count+address/256+address%256+rec_type; // loop over the rest of the characters in the record and // convert them to int for (i=0; i<(byte_count+1);i++) { strncpy(c1,line+2*i+9,2); c1[2] = '\0'; data[i] = strtol(c1,'\0',16); total = total + data[i]; } // check the checksum for the record if (total%256 != 0) { printf("programChip: Error while reading line " "%d - a checksum error is found\n",ln); abort(); } //byte count must be even if(byte_count%2 == 1)byte_count++; // only data records are written if (rec_type == 0) { for (i=0; iwrite( slb_base, data[i], HAL::HAL_NO_VERIFY, 0x44); blk_cnt++; //if 256 bytes have been written to buffer, write them to FLASH if(blk_cnt%256 == 0){ //FLASH software write protection vme_dev->write( slb_base,0x55, HAL::HAL_NO_VERIFY, 0x180); vme_dev->write( slb_base,0x55, HAL::HAL_NO_VERIFY, 0x184); vme_dev->write( slb_base,0xaa, HAL::HAL_NO_VERIFY, 0x80); vme_dev->write( slb_base,0xaa, HAL::HAL_NO_VERIFY, 0x180); vme_dev->write( slb_base,0x2a, HAL::HAL_NO_VERIFY, 0x184); vme_dev->write( slb_base,0x55, HAL::HAL_NO_VERIFY, 0x80); vme_dev->write( slb_base,0x55, HAL::HAL_NO_VERIFY, 0x180); vme_dev->write( slb_base,0x55, HAL::HAL_NO_VERIFY, 0x184); vme_dev->write( slb_base,0xa0, HAL::HAL_NO_VERIFY, 0x80); //FLASH block starting address vme_dev->write( slb_base,0, HAL::HAL_NO_VERIFY, 0x180); vme_dev->write( slb_base,(blk_cnt/256-1)%256, HAL::HAL_NO_VERIFY, 0x184); vme_dev->write( slb_base,(blk_cnt-256)/65536, HAL::HAL_NO_VERIFY, 0x188); //polling ctrl_in(1) until all 256 bytes of data transfered to the FLASH do{ vme_dev->read( slb_base,&data1, 0x10c); }while(!(data1 & 0x20)); //polling toggle bit to wait for end of programming do{ vme_dev->read( slb_base,&data1, 0x80); vme_dev->read( slb_base,&data2, 0x80); }while((data1 & 0x40) != (data2 & 0x40)); //reset buffer address counter to 0 vme_dev->write( slb_base, 1, HAL::HAL_NO_VERIFY, 0x40); } } // loop over bytes in the line } // rec_type equal to 0 } // loop over lines // close mcs file fclose(f); //mcs file size is not multiples of 256 bytes if(check == 0 && blk_cnt%256 != 0){ uint32_t data1,data2; //fill the rest with 0xFF while(blk_cnt%256){ vme_dev->write( slb_base, 0xff, HAL::HAL_NO_VERIFY, 0x44); blk_cnt++; } //FLASH software write protection vme_dev->write( slb_base,0x55, HAL::HAL_NO_VERIFY, 0x180); vme_dev->write( slb_base,0x55, HAL::HAL_NO_VERIFY, 0x184); vme_dev->write( slb_base,0xaa, HAL::HAL_NO_VERIFY, 0x80); vme_dev->write( slb_base,0xaa, HAL::HAL_NO_VERIFY, 0x180); vme_dev->write( slb_base,0x2a, HAL::HAL_NO_VERIFY, 0x184); vme_dev->write( slb_base,0x55, HAL::HAL_NO_VERIFY, 0x80); vme_dev->write( slb_base,0x55, HAL::HAL_NO_VERIFY, 0x180); vme_dev->write( slb_base,0x55, HAL::HAL_NO_VERIFY, 0x184); vme_dev->write( slb_base,0xa0, HAL::HAL_NO_VERIFY, 0x80); //FLASH block starting address vme_dev->write( slb_base,0, HAL::HAL_NO_VERIFY, 0x180); vme_dev->write( slb_base,(blk_cnt/256-1)%256, HAL::HAL_NO_VERIFY, 0x184); vme_dev->write( slb_base,(blk_cnt-256)/65536, HAL::HAL_NO_VERIFY, 0x188); //polling ctrl_in(1) until all 256 bytes of data transfered to the FLASH do{ vme_dev->read( slb_base,&data1, 0x10c); }while(!(data1 & 0x20)); //polling toggle bit to wait for end of programming do{ vme_dev->read( slb_base,&data1, 0x80); vme_dev->read( slb_base,&data2, 0x80); }while((data1 & 0x40) != (data2 & 0x40)); } if(check == 0) printf("FLASH writing done\n"); // open input file for checking f = fopen(Filename,"r"); int err_cnt = 0; blk_cnt = 0; ln = 0; //reset flash address counter to 0 vme_dev->write( slb_base, 0, HAL::HAL_NO_VERIFY, 0x18c); // loop over record in the file and read them in the array "line" while ( fgets(line, 120, f) != NULL) { char c1[3],c2[5]; uint32_t data[200],data1,data2; int i,byte_count,address,rec_type; ln++; if(ln%0x1000 == 0)printf("current line: 0x%x\n",ln); // number of bytes in the record (first two hex numbers) strncpy(c1,line+1,2); c1[2] = '\0'; sscanf(c1,"%x",&byte_count); // address (hex numbers 3-6) strncpy(c2,line+3,4); c2[4] = '\0'; sscanf(c2,"%x",&address); // record type (hex numbers 7-8) strncpy(c1,line+7,2); c1[2] = '\0'; sscanf(c1,"%x",&rec_type); //byte count must be even if(byte_count%2 == 1)byte_count++; // loop over the rest of the characters in the record and // convert them to int for (i=0; i<(byte_count+1);i++) { strncpy(c1,line+2*i+9,2); c1[2] = '\0'; data[i] = strtol(c1,'\0',16); } // only data records are written if (rec_type == 0) { for (i=0; iwrite( slb_base,blk_cnt%256, HAL::HAL_NO_VERIFY, 0x180); vme_dev->write( slb_base,(blk_cnt/256)%256, HAL::HAL_NO_VERIFY, 0x184); vme_dev->write( slb_base,blk_cnt/65536, HAL::HAL_NO_VERIFY, 0x188); blk_cnt++; vme_dev->read( slb_base,&data1, 0x80); if(data[i] != (data1 & 0xff)){ data1 &= 0xff; if(err_cnt < 10) printf("error at address 0x%04x: should be: 0x%02x is: 0x%02x\n",address+i,data[i],data1); err_cnt++; } } // loop over bytes in the line } // rec_type equal to 0 } // loop over lines // close mcs file fclose(f); if(err_cnt == 0) printf("FLASH programming check done\n"); return; } /* A static variable for holding the line. */ /* this will probably live somewhere else later. */ static char *line_read = (char *)NULL; /* Read a string, and return a pointer to it. Returns NULL on EOF. * totally stolen from the GNU readline documention. Totally. -MA * don't forget to link with termcap and readline libraries to compile this * You'll get undefined symbols if you don't. */ char *rl_gets() { /* If the buffer has already been allocated, return the memory to the free pool. */ if (line_read) { free (line_read); line_read = (char *)NULL; } /* Get a line from the user. */ line_read = readline ("> "); /* If the line has any text in it, save it on the history. */ if (line_read && *line_read) add_history (line_read); return (line_read); } bool isMem(char *mem) { const char *p[] = {"lc_conf", "mip1_mem", "br2_conf", "log3_conf","lc_mem","mip4_conf","br3_conf","log1_mem","mip2_mem", "u2","mip5_conf","lc_io","log2_mem","mip3_mem","br2_mem","mip1_conf","log3_fmem","log1_conf","log3_mem", "mip2_conf","ip4_mem","br3_mem","log2_conf","mip3_conf","mip5_mem","u2_vrai"}; #define numMEM ((int)(sizeof(p)/sizeof(char *))) int i = 0; for(i = 0; i < numMEM; i++) { if((string)p[i] == (string)mem) return true; } cout << "Error: " << mem << " is not a recognized device." << endl; return false; } int tokenize(char *buff, char **tokens, int maxt) { int i = 0; char *p; // first free leftovers for( i=0; i