00001 
00002 #define IFM_VERSION "version 3.3a (March 22, 2005)"
00003 
00004 static char g_history[] =
00005     "----------------------------------------------------------------------\n"
00006     " history:\n"
00007     "\n"
00008     " 1.0  November 21, 2002\n"
00009     "   - initial release\n"
00010     "\n"
00011     " 1.1  November 27, 2002\n"
00012     "   - renamed from Hfile to Imon (I-file monitor)\n"
00013     "\n"
00014     " 1.2  November 27, 2002\n"
00015     "   - after N idle mid-run TRs, print warning message\n"
00016     "   - added '-nice INCR' option\n"
00017     "   - added BEEP on error\n"
00018     "   - replaced '-status' with '-quiet', so '-debug 1' is default\n"
00019     "   - no fatal error during volume search, try to recover\n"
00020     "   - display that the user should use <ctrl-c> to quit\n"
00021     "   - adjust globbing to be '...[0-9][02468]?/I.*'  (or w/[13579])\n"
00022     "\n"
00023     " 1.3  December 13, 2002\n"
00024     "   - compile as standalone (include mcw_glob, but not mcw_malloc)\n"
00025     "   - added l_THD_filesize (local copy of THD_filesize)\n"
00026     "   - removed dependance on mrilib.h and r_idisp.h\n"
00027     "\n"
00028     " 2.0  January 15, 2003\n"
00029     "   - rtfeedme feature\n"
00030     "       o added -rt   option: pass data to afni as collected\n"
00031     "       o added -host option: specify afni host for real-time\n"
00032     "       o added -swap option: byte swap pairs before sending to afni\n"
00033     "       o created realtime.[ch] for all RT processing functions\n"
00034     "       o (see gAC struct and ART_ functions)\n"
00035     "   - actually read and store images (to be sent to afni)\n"
00036     "   - moved function declarations to Imon.c (from Imon.h)\n"
00037     "\n"
00038     " 2.1  January 27, 2003\n"
00039     "   - added '-nt VOLUMES_PER_RUN' option (for checking stalled runs)\n"
00040     "\n"
00041     " 2.2  February 2, 2003\n"
00042     "   - allow IFM_MAX_GE_FAILURES file reading failures\n"
00043     "\n"
00044     " 2.3  February 14, 2003\n"
00045     "   - added -start_file option\n"
00046     "   - created opts_t struct for user options\n"
00047     "\n"
00048     " 2.4  February 18, 2003\n"
00049     "   - added DRIVE_AFNI command to open a graph window\n"
00050     "   - added -drive_afni option\n"
00051     "   - added NOTE command to append Imon command to any new dataset\n"
00052     "\n"
00053     " 2.5  February 20, 2003\n"
00054     "   - deal better with missing first slice of first volume\n"
00055     "   - make each DRIVE_AFNI command separate\n"
00056     "\n"
00057     " 2.6  March 25, 2003\n"
00058     "   - added -GERT_Reco2 option\n"
00059     "   - RT: only send good volumes to afni\n"
00060     "   - RT: added -rev_byte_order option\n"
00061     "   - RT: also open relevant image window\n"
00062     "   - RT: mention starting file in NOTE command\n"
00063     "\n"
00064     " 2.7  June 25, 2003\n"
00065     "   - added axes offsets (see xorg and realtime.c: XYZFIRST)\n"
00066     "\n"
00067     " 2.8  June 27, 2003\n"
00068     "   - BYTEORDER is now operational in plug_realtime\n"
00069     "   - implemented -rev_byte_order option\n"
00070     "\n"
00071     " 2.9  July 27, 2003\n"
00072     "   - wrap unknown printed strings in NULL check\n"
00073     "   - only print newer files in debug check\n"
00074     "\n"
00075     " 2.10 August 5, 2003\n"
00076     "   - added '-sp SLICE_PATTERN' option (see spat and opts.sp)\n"
00077     "\n"
00078     " 2.11 August 14, 2003\n"
00079     "   - added '-quit' option\n"
00080     "   - changed CHECK_NULL_STR() output to (NULL) (to see when used)\n"
00081     "   - change exit status to 0 (why the heck did I use 1?)\n"
00082     "   - allow I.* or i.* filename expansions\n"
00083     "\n"
00084     " 3.0 August 20, 2003\n"
00085     "   - It seems that the GE scanners may write the files for a volume\n"
00086     "     out of order.  To handle that possibility, volume_match() will\n"
00087     "     re-test any volume for error conditions (separated by sleep()).\n"
00088     "     Errors will be reported only if they persist (i.e. the scanner\n"
00089     "     is not still working on the volume).\n"
00090     "\n"
00091     " 3.1 September 02, 2003\n"
00092     "   - Add option '-od OUTPUT_DIRECTORY' for the GERT_Reco2 case.\n"
00093     "\n"
00094     " 3.2 January 13, 2004\n"
00095     "   - added '-zorder ORDER' option to specify slice timing in the\n"
00096     "     real-time mode (the real-time default is now 'alt')\n"
00097     "   - added '-hist' option for history display\n"
00098     "\n"
00099     " 3.3 February 13, 2004\n"
00100     "   - added '-rt_cmd' option for passing commands to the realtime plugin\n"
00101     "       (this option may be used multiple times)\n"
00102     "   - '-drive_cmd' option can now be used multiple times\n"
00103     "   - realtime.c: changed default zorder back to seq\n"
00104     "       (affects slice order in the RT plugin)\n"
00105     "   - realtime.c: passed list of drive and rt commands to RT plugin\n"
00106     "   - added add_to_string_list() and empty_string_list()\n"
00107     "\n"
00108     " 3.3a March 22, 2005 - removed all tabs\n"
00109     " 3.3b May   16, 2005 - incorporate some Dimon changes\n"
00110     " 3.4  July   5, 2005 - removed tabs\n"
00111     "----------------------------------------------------------------------\n";
00112 
00113 
00114 
00115 
00116 
00117 
00118 
00119 
00120 
00121 
00122 
00123 
00124 
00125 
00126 
00127 
00128 
00129 
00130 
00131 
00132 
00133 
00134 
00135 
00136 
00137 
00138 
00139 
00140 
00141 
00142 
00143 
00144 
00145 
00146 
00147 
00148 
00149 #include <stdio.h>
00150 #include <ctype.h>
00151 #include <dirent.h>
00152 #include <errno.h>
00153 #include <math.h>
00154 #include <signal.h>
00155 #include <stdlib.h>
00156 #include <string.h>
00157 #include <sys/types.h>
00158 #include <sys/stat.h>
00159 #include <unistd.h>
00160 
00161 #include "Imon.h"
00162 #include "l_mcw_glob.h"
00163 #include "thd_iochan.h"
00164 #include "realtime.h"
00165 
00166 #define IFM_PROG_NAME   "Imon"
00167 
00168 
00169 
00170 
00171 static int add_to_string_list  ( string_list * list, char * str );
00172 static int alloc_x_im          ( im_store_t * is, int bytes );
00173 static int check_error         ( int * retry, float tr, char * note );
00174 static int check_im_byte_order ( int * order, vol_t * v, param_t * p );
00175 static int check_im_store_space( im_store_t * is, int num_images );
00176 static int check_stalled_run   ( int run, int seq_num, int naps, int nap_time );
00177 static int complete_orients_str( vol_t * v, param_t * p );
00178 static int create_gert_script  ( stats_t * s, opts_t * opts );
00179 static int dir_expansion_form  ( char * sin, char ** sexp );
00180 static int empty_string_list   ( string_list * list, int free_mem );
00181 static int find_first_volume   ( vol_t * v, param_t * p, ART_comm * ac );
00182 static int find_fl_file_index  ( param_t * p, char * file );
00183 static int find_more_volumes   ( vol_t * v, param_t * p, ART_comm * ac );
00184 static int find_next_zoff      ( param_t * p, int start, float zoff );
00185 static int init_extras         ( param_t * p, ART_comm * ac );
00186 static int init_options        ( param_t * p, ART_comm * a, int argc,
00187                                  char * argv[] );
00188 static int nap_time_from_tr    ( float tr );
00189 static int path_to_dir_n_suffix( char * dir, char * suff, char * path );
00190 static int read_ge_files       ( param_t * p, int start, int max );
00191 static int read_ge_image       ( char * pathname, finfo_t * fp,
00192                                  int get_image, int need_memory );
00193 static int scan_ge_files       ( param_t * p, int next, int nfiles );
00194 static int set_nice_level      ( int level );
00195 static int set_volume_stats    ( param_t * p, stats_t * s, vol_t * v );
00196 static int show_run_stats      ( stats_t * s );
00197 static int str_char_count      ( char * str, int len, char target );
00198 static int swap_4              ( void * ptr );
00199 
00200 static void hf_signal          ( int signum );
00201 
00202 
00203 static int volume_match  ( vol_t * vin, vol_t * vout, param_t * p, int start );
00204 static int volume_search ( vol_t * V, param_t * p, int start, int maxsl,
00205                            int * fl_start );
00206 
00207 
00208 static int idisp_hf_opts_t      ( char * info, opts_t * opt );
00209 static int idisp_hf_param_t     ( char * info, param_t * p );
00210 static int idisp_hf_vol_t       ( char * info, vol_t * v );
00211 static int idisp_ge_extras      ( char * info, ge_extras * E );
00212 static int idisp_ge_header_info ( char * info, ge_header_info * I );
00213 static int idisp_im_store_t     ( char * info, im_store_t * is );
00214 
00215 static int usage                ( char * prog, int level );
00216 
00217 
00218 static unsigned long l_THD_filesize( char * pathname );
00219 
00220 
00221 
00222 #define MAIN
00223 
00224 
00225 
00226 
00227 IFM_debug gD;           
00228 param_t   gP;           
00229 stats_t   gS;           
00230 ART_comm  gAC;          
00231 
00232 
00233 int main( int argc, char * argv[] )
00234 {
00235     ART_comm * ac = &gAC;               
00236     param_t  * p  = &gP;                
00237     vol_t      baseV;                   
00238     int        ret_val;
00239 
00240     
00241     if ( (ret_val = init_options( p, ac, argc, argv )) != 0 )
00242         return ret_val;
00243 
00244     if ( (ret_val = init_extras( p, ac )) != 0 )
00245         return ret_val;
00246 
00247     if ( (ret_val = find_first_volume( &baseV, p, ac )) != 0 )
00248         return ret_val;
00249 
00250     if ( (ret_val = find_more_volumes( &baseV, p, ac )) != 0 )
00251         return ret_val;
00252 
00253     return 0;
00254 }
00255 
00256 
00257 
00258 
00259 
00260 
00261 
00262 
00263 
00264 
00265 
00266 
00267 static int find_first_volume( vol_t * v, param_t * p, ART_comm * ac )
00268 {
00269     int max_im_alloc = IFM_MAX_IM_ALLOC;
00270     int ret_val;
00271     int fl_start = 0;  
00272 
00273     if ( gD.level > 0 )                 
00274         fprintf( stderr, "-- scanning for first volume\n" );
00275 
00276     ret_val = 0;
00277     while ( ret_val == 0 )
00278     {
00279         ret_val = read_ge_files( p, fl_start, max_im_alloc );
00280 
00281         if ( ret_val > 0 )
00282         {
00283             ret_val = volume_search( v, p, 0, 0, &fl_start );
00284 
00285             if ( ret_val == -1 )   
00286                 ret_val = 0;
00287 
00288             if ( (ret_val == 0) && (p->nused > (max_im_alloc / 2)) )
00289             {
00290                 
00291 
00292 
00293 
00294 
00295                 max_im_alloc *= 2;
00296             }
00297         }
00298 
00299         if ( ret_val == 0 )                     
00300         {
00301             if ( gD.level > 0 )                              
00302                 fprintf( stderr, "." );
00303 
00304             sleep( 4 );                                   
00305         }
00306         else if ( ret_val > 0 )         
00307         {
00308             if ( gD.level > 0 )
00309             {
00310                 fprintf( stderr, "\n-- first volume found\n" );
00311                 if ( gD.level > 1 )
00312                 {
00313                     idisp_hf_vol_t( "first volume : ", v );
00314                     idisp_hf_param_t( "first vol - new params : ", p );
00315                 }
00316             }
00317 
00318             
00319             if ( p->nalloc < (4 * v->nim) )
00320             {
00321                 p->nalloc = 4 * v->nim;
00322                 p->flist = (finfo_t *)realloc( p->flist,
00323                                                p->nalloc*sizeof(finfo_t) );
00324                 if ( p->flist == NULL )
00325                 {
00326                     fprintf( stderr, "** FFV: failure to allocate %d finfo_t "
00327                                      "structs!\n", p->nalloc );
00328                     return -1;
00329                 }
00330 
00331                 if ( gD.level > 1 )
00332                     idisp_hf_param_t( "++ final realloc of flist : ", p );
00333             }
00334 
00335             
00336             if ( complete_orients_str( v, p ) < 0 )
00337                 return -1;
00338 
00339             
00340             if ( check_im_byte_order( &ac->byte_order, v, p ) < 0 )
00341                 return -1;
00342 
00343             
00344             if ( ac->state == ART_STATE_TO_OPEN )
00345                 ART_open_afni_link( ac, 5, 0, gD.level );
00346 
00347             if ( ac->state == ART_STATE_TO_SEND_CTRL )
00348                 ART_send_control_info( ac, v, gD.level );
00349 
00350             if ( ac->state == ART_STATE_IN_USE )
00351                     ART_send_volume( ac, v, gD.level );
00352 
00353             if ( gD.level > 1 )
00354             {
00355                 ART_idisp_ART_comm( "-- first vol ", ac );
00356                 idisp_im_store_t( "-- first vol ", &p->im_store );
00357             }
00358         }
00359         else
00360             return ret_val;             
00361     }
00362 
00363     if ( ret_val > 0 )
00364         return 0;
00365     else
00366         return ret_val;
00367 }
00368 
00369 
00370 
00371 
00372 
00373 
00374 
00375 
00376 
00377 
00378 
00379 static int find_more_volumes( vol_t * v0, param_t * p, ART_comm * ac )
00380 {
00381     vol_t vn;
00382     int   ret_val, done;
00383     int   run, seq_num, next_im;
00384     int   fl_index;                     
00385     int   naps;                         
00386     int   nap_time;                     
00387 
00388     if ( v0 == NULL || p == NULL )
00389     {
00390         fprintf( stderr, "error: IFM:FMV() lacking parameters\n" );
00391         return -1;
00392     }
00393 
00394     done     = 0;
00395     naps     = 0;
00396 
00397     run      = v0->run;
00398     seq_num  = v0->seq_num = 1;         
00399     fl_index = v0->fn_n + 1;            
00400     next_im  = v0->fn_n + 1;            
00401 
00402     nap_time = nap_time_from_tr( v0->geh.tr );
00403 
00404     if ( gD.level > 0 )                 
00405     {
00406         fprintf( stderr, "-- scanning for additional volumes...\n" );
00407         fprintf( stderr, "-- run %d: %d ", run, seq_num );
00408     }
00409 
00410     
00411     signal( SIGTERM, hf_signal );
00412     signal( SIGINT,  hf_signal );
00413 
00414     if ( set_volume_stats( p, &gS, v0 ) )
00415         return -1;
00416 
00417     while ( ! done )
00418     {
00419         
00420         ret_val = 1;
00421         while ( (ret_val == 1) || (ret_val == -1) )
00422         {
00423             ret_val = volume_match( v0, &vn, p, fl_index );
00424 
00425             if ( ret_val < -1 )                 
00426                 return ret_val;
00427 
00428             if ( (ret_val == 1) || (ret_val == -1) )
00429             {
00430                 if ( gD.level > 2 )
00431                     idisp_hf_vol_t( "-- new volume: ", &vn );
00432 
00433                 fl_index += vn.nim;             
00434                 next_im   = vn.fn_n + 1;        
00435 
00436                 if ( vn.run != run )            
00437                 {
00438                     
00439                     if ( ac->state == ART_STATE_IN_USE )
00440                         ART_send_end_of_run( ac, run, seq_num, gD.level );
00441 
00442                     run = vn.run;               
00443                     seq_num = 1;
00444 
00445                     if ( gD.level > 0 )
00446                         fprintf( stderr, "\n-- run %d: %d ", run, seq_num );
00447                 }
00448                 else
00449                 {
00450                     seq_num++;
00451 
00452                     if ( gD.level > 0 )
00453                         fprintf( stderr, "%d ", seq_num );
00454                 }
00455 
00456                 vn.seq_num = seq_num;
00457 
00458                 if ( set_volume_stats( p, &gS, &vn ) )
00459                     return -1;
00460 
00461                 if ( complete_orients_str( &vn, p ) < 0 )
00462                     return -1;
00463 
00464                 if ( ac->state == ART_STATE_TO_SEND_CTRL )
00465                     ART_send_control_info( ac, &vn, gD.level );
00466 
00467                 
00468                 if ( (ac->state == ART_STATE_IN_USE) && (ret_val == 1) )
00469                     ART_send_volume( ac, &vn, gD.level );
00470 
00471                 naps = 0;                       
00472             }
00473         }
00474 
00475         
00476 
00477         ret_val = read_ge_files( p, next_im, p->nalloc );
00478         fl_index = 0;                   
00479 
00480         while ( (ret_val >= 0 ) &&      
00481                 (ret_val < v0->nim) )   
00482         {
00483             if ( naps > 0 )
00484             {
00485                 if ( p->opts.quit )     
00486                 {
00487                     if ( ac->state == ART_STATE_IN_USE )
00488                         ART_send_end_of_run( ac, run, seq_num, gD.level );
00489 
00490                     show_run_stats( &gS );
00491                     return 0;
00492                 }
00493 
00494                 
00495                 if ( check_stalled_run( run, seq_num, naps, nap_time ) > 0 )
00496                     if ( ac->state == ART_STATE_IN_USE )
00497                         ART_send_end_of_run( ac, run, seq_num, gD.level );
00498 
00499                 if ( gD.level > 0 )     
00500                     fprintf( stderr, ". " );
00501             }
00502 
00503             sleep( nap_time );          
00504             naps ++;
00505 
00506             ret_val = read_ge_files( p, next_im, p->nalloc );
00507         }
00508 
00509         if ( ret_val < 0 )              
00510         {
00511             fprintf( stderr, "\n** failure: IFM:RGF fatal error\n" );
00512             return -1;
00513         }
00514     }
00515 
00516     return 0;   
00517 }
00518 
00519 
00520 
00521 
00522 
00523 
00524 
00525 
00526 
00527 
00528 
00529 
00530 
00531 
00532 static int volume_search(
00533         vol_t   * V,                    
00534         param_t * p,                    
00535         int       start,                
00536         int       maxsl,                
00537         int     * fl_start )            
00538 {
00539     finfo_t * fp;
00540     float     z_orig, delta, dz, prev_z;
00541     int       bound;                    
00542     int       next;
00543     int       run0, run1;               
00544     int       first = start;            
00545     int       last;                     
00546 
00547     if ( V == NULL || p == NULL || p->flist == NULL || start < 0 )
00548     {
00549         fprintf( stderr, "failure: FNV: bad parameter data\n" );
00550         return -2;
00551     }
00552 
00553     
00554     if ( (maxsl <= 0) || ((maxsl + first) >= p->nused) )
00555         bound = p->nused;
00556     else
00557         bound = first + maxsl;
00558 
00559     if ( (bound - first) < 4 )          
00560         return 0;
00561 
00562     delta = p->flist[first+1].geh.zoff - p->flist[first].geh.zoff;
00563 
00564     run0  = p->flist[first  ].geh.uv17;
00565     run1  = p->flist[first+1].geh.uv17;
00566 
00567     
00568     if ( (fabs(delta) < IFM_EPSILON) || (run1 != run0) )
00569     {
00570         if ( gD.level > 1 )
00571             fprintf( stderr, "-- skipping single slice volume <%s>\n",
00572                      p->fnames[p->flist[first].index] );
00573 
00574         first++;
00575         delta = p->flist[first+1].geh.zoff - p->flist[first].geh.zoff;
00576         run0  = run1;
00577 
00578         if ( fabs(delta) < IFM_EPSILON )
00579         {
00580             fprintf( stderr, "Error: 3 slices with 0 delta, beginning with"
00581                      "file <%s>\n", p->fnames[p->flist[start].index] );
00582 
00583             *fl_start = p->flist[start+2].index;
00584 
00585             return -1;
00586         }
00587     }
00588 
00589     fp     = p->flist + first;                  
00590     z_orig = fp->geh.zoff;                      
00591 
00592     
00593     fp++;
00594     prev_z = fp->geh.zoff;
00595     run1   = fp->geh.uv17;
00596     dz     = delta;
00597 
00598     
00599     next = first + 2;                           
00600     while ( (next < bound) && (fabs(dz - delta) < IFM_EPSILON) &&
00601             (run1 == run0) )
00602     {
00603         fp++;                             
00604 
00605         dz     = fp->geh.zoff - prev_z;
00606         run1   = fp->geh.uv17;
00607         prev_z = fp->geh.zoff;
00608 
00609         next++;
00610     }
00611 
00612     last = next - 2;                        
00613 
00614     if ( fabs(fp->geh.zoff - p->flist[first].geh.zoff) < IFM_EPSILON )
00615     {
00616         
00617 
00618         
00619 
00620         V->geh      = p->flist[first].geh;         
00621         V->gex      = p->flist[first].gex;         
00622         V->nim      = last - first + 1;
00623         V->fl_1     = first;
00624         V->fn_1     = p->flist[first].index;
00625         V->fn_n     = p->flist[last].index;
00626         strncpy( V->first_file, p->fnames[V->fn_1], IFM_MAX_FLEN );
00627         strncpy( V->last_file,  p->fnames[V->fn_n], IFM_MAX_FLEN );
00628         V->z_first  = p->flist[first].geh.zoff;
00629         V->z_last   = p->flist[last].geh.zoff;
00630         V->z_delta  = delta;
00631         V->seq_num  = -1;                               
00632         V->run      = V->geh.uv17;
00633 
00634         return 1;
00635     }
00636     else if ( (fabs(dz - delta) < IFM_EPSILON) && (run1 == run0) )
00637         return 0;                           
00638     else if ( dz * delta < 0.0 )
00639     {
00640         
00641 
00642 
00643 
00644         
00645         fprintf( stderr, "\n"
00646                 "*************************************************\n"
00647                 "Error: missing slice(s) in first volume!\n"
00648                 "       attempting to re-start at file: %s\n"
00649                 "*************************************************\n",
00650                 p->fnames[p->flist[last+1].index] );
00651 
00652         *fl_start = p->flist[last+1].index;
00653     }
00654     else    
00655     {
00656         
00657         int testc;
00658 
00659         for ( testc = next - 1; testc < bound; testc++ )
00660             if ( abs( p->flist[first].geh.zoff -
00661                       p->flist[testc].geh.zoff ) < IFM_EPSILON )
00662             {
00663                 
00664                 
00665                 fprintf( stderr, "\n"
00666                         "*************************************************\n"
00667                         "Error: missing slice in first volume!\n"
00668                         "       detected    at file: %s\n"
00669                         "       re-starting at file: %s\n"
00670                         "*************************************************\n",
00671                         p->fnames[p->flist[last+1].index],
00672                         p->fnames[p->flist[testc].index] );
00673 
00674                 
00675                 *fl_start = p->flist[testc].index;
00676 
00677                 return -1;
00678             }
00679 
00680         
00681         return 0;
00682     }
00683 
00684     return -1;  
00685 }
00686 
00687 
00688 
00689 
00690 
00691 
00692 
00693 
00694 
00695 
00696 
00697 
00698 
00699 static int volume_match( vol_t * vin, vol_t * vout, param_t * p, int start )
00700 {
00701     static int   retry = 1;                             
00702     finfo_t    * fp;
00703     finfo_t    * fp_test;
00704     float        z;
00705     int          count, next_start = -1;
00706     int          missing = 0;
00707 
00708     if ( vin == NULL || vout == NULL ||
00709          p == NULL || p->flist == NULL || start < 0 )
00710     {
00711         fprintf( stderr, "failure: FMV: bad parameter data\n" );
00712         return -2;
00713     }
00714 
00715     if ( (p->nused - start) < vin->nim )        
00716         return 0;
00717 
00718     
00719 
00720     fp = p->flist+start;
00721     for ( count = 0; count < vin->nim - 1; count++ )   
00722     {
00723         z = vin->z_first + count * vin->z_delta;        
00724 
00725         if ( fabs( z - fp->geh.zoff ) > IFM_EPSILON )
00726         {
00727             
00728 
00729             fp_test = fp + 1;                          
00730             if ( fabs( z + vin->z_delta - fp_test->geh.zoff ) < IFM_EPSILON )
00731             {
00732                 
00733                 if ( !check_error(&retry, vin->geh.tr, "slice out of order") )
00734                     return 0;
00735 
00736                 
00737                 
00738 
00739                 IFM_BIG_ERROR_MESG( "slice out of order!",
00740                         p->fnames[fp->index], z, fp->geh.zoff,
00741                         fp->geh.uv17, count + 1, vin->nim );
00742             }
00743             else if ( fabs(z + vin->z_delta - fp->geh.zoff) < IFM_EPSILON )
00744             {
00745                 
00746 
00747                 
00748                 if ( !check_error(&retry, vin->geh.tr, "slice missing") )
00749                     return 0;
00750 
00751                 
00752                 missing++;
00753 
00754                 IFM_BIG_ERROR_MESG( "slice missing!",
00755                         p->fnames[fp->index], z, fp->geh.zoff,
00756                         fp->geh.uv17, count + 1, vin->nim );
00757 
00758                 count++;    
00759             }
00760             else        
00761             {
00762                 
00763                 next_start = find_next_zoff( p, start+count, vin->z_first );
00764 
00765                 if ( next_start < 0 )   
00766                     return 0;
00767                 else
00768                 {
00769                     
00770                     if ( !check_error(&retry, vin->geh.tr, "vol toasted") )
00771                         return 0;
00772 
00773                     IFM_BIG_ERROR_MESG( "volume severely toasted!",
00774                             p->fnames[fp->index], z, fp->geh.zoff,
00775                             fp->geh.uv17, count + 1, vin->nim );
00776 
00777                     break;      
00778                 }
00779             }
00780         }
00781 
00782         fp++;
00783     }
00784 
00785     z = vin->z_first + count * vin->z_delta;      
00786 
00787     if ( count >= vin->nim )    
00788         next_start = start + vin->nim - missing;
00789     else if ( (next_start < 0) && (fabs( z - fp->geh.zoff ) > IFM_EPSILON) )
00790     {
00791         
00792         if ( (p->nused - start) <= vin->nim )   
00793             return 0;                           
00794         
00795         fp_test = fp + 1;                              
00796         if ( fabs( vin->z_first - fp_test->geh.zoff ) < IFM_EPSILON )
00797         {
00798             
00799 
00800             
00801             if ( !check_error(&retry, vin->geh.tr, "last slice out of order") )
00802                 return 0;
00803 
00804             IFM_BIG_ERROR_MESG( "last slice out of order!",
00805                     p->fnames[fp->index], z, fp->geh.zoff,
00806                     fp->geh.uv17, count + 1, vin->nim );
00807         }
00808         else if ( fabs(vin->z_first - fp->geh.zoff) < IFM_EPSILON )
00809         {
00810             
00811 
00812             
00813             if ( !check_error(&retry, vin->geh.tr, "last slice missing") )
00814                 return 0;
00815 
00816             missing++;
00817 
00818             IFM_BIG_ERROR_MESG( "last slice missing!",
00819                     p->fnames[fp->index], z, fp->geh.zoff,
00820                     fp->geh.uv17, count + 1, vin->nim );
00821         }
00822         else    
00823         {
00824             
00825             next_start = find_next_zoff( p, start+count+1, vin->z_first );
00826 
00827             if ( next_start < 0 )       
00828                 return 0;
00829             else
00830             {
00831                 
00832                 if ( !check_error(&retry, vin->geh.tr, "Vol toasted") )
00833                     return 0;
00834 
00835                 IFM_BIG_ERROR_MESG( "Volume severely toasted!",
00836                         p->fnames[fp->index], z, fp->geh.zoff,
00837                         fp->geh.uv17, count + 1, vin->nim );
00838             }
00839         }
00840     }
00841 
00842     if ( next_start < 0)
00843         next_start = start + vin->nim - missing;
00844 
00845     if ( retry == 0 && gD.level > 0 )                   
00846         fprintf(stderr," (retry OK - no errors)\n");
00847 
00848     retry = 1;                          
00849 
00850     
00851 
00852     vout->geh      = p->flist[start].geh;
00853     vout->gex      = p->flist[start].gex;
00854     vout->nim      = next_start - start;
00855     vout->fl_1     = start;
00856     vout->fn_1     = p->flist[start].index;
00857     vout->fn_n     = p->flist[start+vout->nim-1].index;
00858     strncpy( vout->first_file, p->fnames[vout->fn_1], IFM_MAX_FLEN );
00859     strncpy( vout->last_file,  p->fnames[vout->fn_n],  IFM_MAX_FLEN );
00860     vout->z_first  = vin->z_first;
00861     vout->z_last   = vin->z_last;
00862     vout->z_delta  = vin->z_delta;
00863     vout->seq_num  = -1;                                
00864     vout->run      = vout->geh.uv17;
00865 
00866     if ( vout->nim != vin->nim )
00867         return -1;
00868     else
00869         return 1;
00870 }
00871 
00872 
00873 
00874 
00875 
00876 
00877 
00878 
00879 
00880 static int check_error( int * retry, float tr, char * note )
00881 {
00882     if ( !retry )
00883         return -1;
00884 
00885     if ( *retry == 1 )
00886     {
00887         
00888         if ( gD.level > 0 )
00889             fprintf(stderr," (volume retry test for warning '%s'...)\n",
00890                     CHECK_NULL_STR(note));
00891 
00892         *retry = 0;
00893         sleep( nap_time_from_tr(tr) );
00894         return 0;
00895     }
00896 
00897     
00898 
00899     *retry = 2;
00900 
00901     return 1;
00902 }
00903 
00904 
00905 
00906 
00907 
00908 
00909 
00910 
00911 
00912 
00913 
00914 
00915 
00916 
00917 
00918 static int read_ge_files(
00919         param_t * p,            
00920         int       start,        
00921         int       max )         
00922 {
00923     int n2scan;                 
00924     int next = start;           
00925 
00926     if ( p == NULL )
00927     {
00928         fputs( "failure: RAF: no param_t struct\n", stderr  );
00929         return -1;
00930     }
00931 
00932     
00933     if ( p->fnames != NULL )
00934     {
00935         if ( p->nfiles <= 0 )
00936         {
00937             fputs( "failure: RAF: fnames does not match nfiles\n", stderr );
00938             return -1;
00939         }
00940 
00941         MCW_free_expand( p->nfiles, p->fnames );
00942         p->fnames = NULL;
00943     }
00944 
00945     
00946     MCW_file_expand( 1, &p->glob_dir, &p->nfiles, &p->fnames );
00947 
00948     
00949     if ( (next == 0 ) && (p->opts.start_file != NULL) )
00950     {
00951         next = find_fl_file_index( p, p->opts.start_file );
00952 
00953         if ( next < 0 )         
00954         {
00955             if ( gD.level > 0 ) 
00956             {
00957                 static int attempts = 0;
00958 
00959                 if ( attempts == 0 )
00960                     fprintf(stderr, "-- still searching for start_file, '%s'\n",
00961                             p->opts.start_file );
00962 
00963                 attempts++;
00964             }
00965             return 0;
00966         }
00967     }
00968     
00969     if ( gD.level > 3 )
00970     {
00971         int fnum;
00972         for ( fnum = next; fnum < p->nfiles; fnum++ )
00973             printf( "file %4d: %s\n", fnum, p->fnames[fnum] );
00974     }
00975 
00976     if ( p->nfiles <= 0 )
00977         return 0;
00978 
00979     
00980     if ( (max > 0) && (max <= (p->nfiles - next)) )
00981         n2scan = max;                           
00982     else
00983         n2scan = p->nfiles - next;              
00984 
00985     
00986     if ( (n2scan > p->nalloc) || (max > p->nalloc) )
00987     {
00988         int nalloc;
00989 
00990         
00991         nalloc = (n2scan >= max) ? n2scan : max;
00992 
00993         p->flist = (finfo_t *)realloc( p->flist, nalloc * sizeof(finfo_t) );
00994 
00995         if ( p->flist == NULL )
00996         {
00997             fprintf(stderr, "failure to allocate %d finfo_t structs\n", nalloc);
00998             return -1;
00999         }
01000 
01001         p->nalloc = nalloc;
01002 
01003         if ( gD.level > 1 )
01004         {
01005             idisp_hf_param_t( "++ realloc of flist : ", p );
01006             fprintf( stderr,  "-- n2scan = %d, max = %d\n", n2scan, max );
01007         }
01008     }
01009 
01010     p->nused = scan_ge_files( p, next, n2scan );
01011 
01012     if ( gD.level > 2 )
01013         idisp_hf_param_t( "end read_ge_files : ", p );
01014 
01015     
01016     return p->nused;
01017 }
01018 
01019 
01020 
01021 
01022 
01023 
01024 
01025 
01026 static int scan_ge_files (
01027         param_t  * p,                   
01028         int        next,                
01029         int        nfiles )             
01030 {
01031     finfo_t    * fp;
01032     int          im_num, fnum;
01033     int          files_read, rv;
01034     int          need_M;                
01035 
01036     if ( nfiles <= 0 )
01037         return 0;
01038 
01039     if ( check_im_store_space( &p->im_store, nfiles ) < 0 )
01040         return -1;
01041 
01042     p->im_store.nused = 0;
01043     
01044     for ( im_num = 0, fnum = next, fp = p->flist;
01045           im_num < nfiles;
01046           im_num++, fnum++, fp++ )
01047     {
01048         if ( im_num < p->im_store.nalloc )      
01049         {
01050             fp->image = p->im_store.im_ary[im_num];
01051             need_M    = 0;
01052         }
01053         else                                    
01054         {
01055             fp->image = NULL;
01056             need_M    = 1;
01057         }
01058 
01059         rv = read_ge_image( p->fnames[fnum], fp, 1, need_M );
01060 
01061         
01062         if ( (need_M == 1) && (fp->image != NULL) )
01063         {
01064             p->im_store.im_ary[im_num] = fp->image;
01065             p->im_store.nalloc++;
01066 
01067             
01068             if ( p->im_store.im_size == 0 )
01069             {
01070                 if ( alloc_x_im( &p->im_store, fp->bytes ) < 0 )
01071                     return -1;
01072             }
01073 
01074             if ( gD.level > 1 )
01075                 fprintf( stderr, "++ allocated image %d at address %p\n",
01076                          im_num, p->im_store.im_ary[im_num] );
01077         }
01078 
01079         if ( (rv != 0) || (fp->geh.good != 1) )
01080         {
01081             static int read_failure = -1;  
01082             static int fail_count   =  0;  
01083 
01084             
01085             if ( read_failure != fnum )
01086             {
01087                 read_failure = fnum;
01088                 fail_count   = 1;
01089             }
01090             else
01091                 fail_count++;
01092 
01093             
01094             if ( fail_count > IFM_MAX_GE_FAILURES )
01095             {
01096                 fprintf( stderr, "\n** failure: cannot read GE header for "
01097                          "file <%s>\n", p->fnames[fnum] );
01098                 return -1;
01099             }
01100 
01101             
01102             if ( gD.level > 1 )
01103                 fprintf( stderr, "\n-- (%d) failures to read GE header for "
01104                          "file <%s>, trying again...\n",
01105                          fail_count, p->fnames[fnum] );
01106 
01107             break;
01108         }
01109         else
01110         {
01111             p->im_store.nused++;        
01112             fp->index = fnum;           
01113 
01114             if ( gD.level > 2 )
01115             {
01116                 idisp_ge_header_info( p->fnames[fp->index], &fp->geh );
01117                 idisp_ge_extras( p->fnames[fp->index], &fp->gex );
01118             }
01119         }
01120     }
01121 
01122     
01123     files_read = fnum - next;
01124 
01125     if ( gD.level > 1 )
01126         printf( "-- scanned %d GE files, from <%s> to <%s>\n",
01127                 files_read, p->fnames[next], p->fnames[next+files_read-1] );
01128 
01129     return files_read;
01130 }
01131 
01132 
01133 
01134 
01135 
01136 
01137 
01138 
01139 
01140 static int init_options( param_t * p, ART_comm * A, int argc, char * argv[] )
01141 {
01142     int ac, errors = 0;
01143 
01144     if ( p == NULL )
01145         return 2;
01146 
01147     if ( argc < 2 )
01148     {
01149         usage( IFM_PROG_NAME, IFM_USE_SHORT );
01150         return 1;
01151     }
01152 
01153     
01154 
01155     memset(  p,  0, sizeof(*p)  );      
01156     memset( &gD, 0, sizeof(gD)  );      
01157     memset( &gS, 0, sizeof(gS)  );      
01158     memset(  A,  0, sizeof(gAC) );      
01159 
01160     ART_init_AC_struct( A );            
01161     A->param = p;                       
01162 
01163     empty_string_list( &p->opts.drive_list, 0 );
01164     empty_string_list( &p->opts.rt_list, 0 );
01165 
01166     
01167     gD.level = 1;
01168 
01169     for ( ac = 1; ac < argc; ac++ )
01170     {
01171         if ( ! strncmp( argv[ac], "-debug", 4 ) )
01172         {
01173             if ( ++ac >= argc )
01174             {
01175                 fputs( "option usage: -debug LEVEL\n", stderr );
01176                 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01177                 return 1;
01178             }
01179 
01180             p->opts.debug = atoi(argv[ac]);
01181             gD.level      = p->opts.debug;
01182             if ( gD.level < 0 || gD.level > IFM_MAX_DEBUG )
01183             {
01184                 fprintf( stderr, "error: debug level must be in [0,%d]\n",
01185                          IFM_MAX_DEBUG );
01186                 errors++;
01187             }
01188         }
01189         else if ( ! strncmp( argv[ac], "-GERT_Reco2", 7 ) )
01190         {
01191             p->opts.gert_reco = 1;      
01192         }
01193         else if ( ! strncmp( argv[ac], "-help", 5 ) )
01194         {
01195             usage( IFM_PROG_NAME, IFM_USE_LONG );
01196             return 1;
01197         }
01198         else if ( ! strncmp( argv[ac], "-hist", 5 ) )
01199         {
01200             usage( IFM_PROG_NAME, IFM_USE_HIST );
01201             return 1;
01202         }
01203         else if ( ! strncmp( argv[ac], "-nice", 4 ) )
01204         {
01205             if ( ++ac >= argc )
01206             {
01207                 fputs( "option usage: -nice INCREMENT\n", stderr );
01208                 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01209                 return 1;
01210             }
01211 
01212             p->opts.nice = atoi(argv[ac]);
01213             if ( (p->opts.nice < IFM_MIN_NICE_INC) ||
01214                  (p->opts.nice > IFM_MAX_NICE_INC) )
01215             {
01216                 fprintf( stderr, "error: nice incrment must be in [%d,%d]\n",
01217                          IFM_MIN_NICE_INC, IFM_MAX_NICE_INC );
01218                 errors++;
01219             }
01220         }
01221         else if ( ! strncmp( argv[ac], "-nt", 3 ) )
01222         {
01223             if ( ++ac >= argc )
01224             {
01225                 fputs( "option usage: -nt VOLUMES_PER_RUN\n", stderr );
01226                 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01227                 return 1;
01228             }
01229 
01230             p->opts.nt = atoi(argv[ac]);
01231             if ( p->opts.nt < 0 || p->opts.nt > IFM_MAX_NT )
01232             {
01233                 fprintf( stderr,
01234                     "option usage: -nt VOLUMES_PER_RUN\n"
01235                     "       error: VOLUMES_PER_RUN must be in [%d,%d]\n",
01236                     0, IFM_MAX_NT );
01237                 errors++;
01238             }
01239         }
01240         else if ( ! strncmp( argv[ac], "-od", 3 ) ||
01241                   ! strncmp( argv[ac], "-gert_outdir", 9 ) )
01242         {
01243             if ( ++ac >= argc )
01244             {
01245                 fputs( "option usage: -gert_outdir OUTPUT_DIR\n", stderr );
01246                 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01247                 return 1;
01248             }
01249 
01250             p->opts.gert_outdir = argv[ac];
01251         }
01252         else if ( ! strncmp( argv[ac], "-quiet", 6 ) )
01253         {
01254             
01255             if ( gD.level == IFM_DEBUG_DEFAULT )
01256                 gD.level = 0;
01257         }
01258         else if ( ! strncmp( argv[ac], "-quit", 5 ) )
01259         {
01260             p->opts.quit = 1;
01261         }
01262         else if ( ! strncmp( argv[ac], "-sp", 3 ) )
01263         {
01264             if ( ++ac >= argc )
01265             {
01266                 fputs( "option usage: -sp PATTERN\n", stderr );
01267                 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01268                 return 1;
01269             }
01270 
01271             p->opts.sp = argv[ac];
01272         }
01273         else if ( ! strncmp( argv[ac], "-start_dir", 8 ) )
01274         {
01275             if ( ++ac >= argc )
01276             {
01277                 fputs( "option usage: -start_dir DIRECTORY\n", stderr );
01278                 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01279                 return 1;
01280             }
01281 
01282             p->opts.start_dir = argv[ac];
01283         }
01284         else if ( ! strncmp( argv[ac], "-start_file", 8 ) )
01285         {
01286             if ( ++ac >= argc )
01287             {
01288                 fputs( "option usage: -start_file DIR/FIRST_FILE\n", stderr );
01289                 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01290                 return 1;
01291             }
01292 
01293             p->opts.start_file = argv[ac];
01294         }
01295         else if ( ! strncmp( argv[ac], "-version", 2 ) )
01296         {
01297             usage( IFM_PROG_NAME, IFM_USE_VERSION );
01298             return 1;
01299         }
01300         
01301         else if ( ! strncmp( argv[ac], "-drive_afni", 6 ) )
01302         {
01303             if ( ++ac >= argc )
01304             {
01305                 fputs( "option usage: -drive_afni COMMAND\n", stderr );
01306                 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01307                 return 1;
01308             }
01309 
01310             if ( add_to_string_list( &p->opts.drive_list, argv[ac] ) != 0 )
01311             {
01312                 fprintf(stderr,"** failed add '%s' to drive_list\n",argv[ac]);
01313                 return 1;
01314             }
01315         }
01316         else if ( ! strncmp( argv[ac], "-host", 4 ) )
01317         {
01318             if ( ++ac >= argc )
01319             {
01320                 fputs( "option usage: -host HOSTNAME\n", stderr );
01321                 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01322                 return 1;
01323             }
01324 
01325             p->opts.host = argv[ac];    
01326             strncpy( A->host, argv[ac], ART_NAME_LEN-1 );
01327             A->host[ART_NAME_LEN-1] = '\0';     
01328         }
01329         else if ( ! strncmp( argv[ac], "-rev_byte_order", 4 ) )
01330         {
01331             p->opts.rev_bo = 1;           
01332         }
01333         else if ( ! strncmp( argv[ac], "-rt_cmd", 6 ) )
01334         {
01335             if ( ++ac >= argc )
01336             {
01337                 fputs( "option usage: -rt_cmd COMMAND\n", stderr );
01338                 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01339                 return 1;
01340             }
01341 
01342             if ( add_to_string_list( &p->opts.rt_list, argv[ac] ) != 0 )
01343             {
01344                 fprintf(stderr,"** failed add '%s' to rt_list\n",argv[ac]);
01345                 return 1;
01346             }
01347         }
01348         else if ( ! strncmp( argv[ac], "-rt", 3 ) )
01349         {
01350             A->state = ART_STATE_TO_OPEN; 
01351             p->opts.rt = 1;               
01352         }
01353         else if ( ! strncmp( argv[ac], "-swap", 5 ) )
01354         {
01355             A->swap = 1;                
01356             p->opts.swap = 1;           
01357         }
01358         else if ( ! strncmp( argv[ac], "-zorder", 6 ) )
01359         {
01360             if ( ++ac >= argc )
01361             {
01362                 fputs( "option usage: -zorder ORDER\n", stderr );
01363                 usage( IFM_PROG_NAME, IFM_USE_SHORT );
01364                 return 1;
01365             }
01366 
01367             A->zorder = argv[ac];
01368         }
01369         else
01370         {
01371             fprintf( stderr, "error: invalid option <%s>\n\n", argv[ac] );
01372             usage( IFM_PROG_NAME, IFM_USE_SHORT );
01373             return 1;
01374         }
01375     }
01376 
01377     if ( errors > 0 )          
01378     {
01379         usage( IFM_PROG_NAME, IFM_USE_SHORT );
01380         return 1;
01381     }
01382 
01383     if ( p->opts.start_dir == NULL )
01384     {
01385         fputs( "error: missing '-start_dir DIR' option\n", stderr );
01386         usage( IFM_PROG_NAME, IFM_USE_SHORT );
01387         return 1;
01388     }
01389 
01390     if ( p->opts.rev_bo && p->opts.swap )
01391     {
01392         fprintf( stderr, "error: options '-rev_byte_order' and '-swap' "
01393                  "cannot both be used\n");
01394         usage( IFM_PROG_NAME, IFM_USE_SHORT );
01395         return 1;
01396     }
01397 
01398     if ( A->zorder )
01399     {
01400         if ( strcmp(A->zorder, "alt") && strcmp(A->zorder, "seq") )
01401         {
01402             fprintf(stderr,"** order '%s' is invalid for '-zorder' option,\n"
01403                     "   must be either 'alt' or 'seq'\n", A->zorder);
01404             return -1;
01405         }
01406     }
01407 
01408     
01409 
01410     if ( dir_expansion_form( p->opts.start_dir, &p->glob_dir ) != 0 )
01411         return 2;
01412 
01413     
01414     p->opts.argv = argv;
01415     p->opts.argc = argc;
01416 
01417     p->ftype     = IFM_IM_FTYPE_GEMS5;   
01418 
01419     if ( gD.level > 1 )
01420     {
01421         idisp_hf_opts_t ( "end init_options : ", &p->opts );
01422         idisp_hf_param_t( "end init_options : ", p );
01423     }
01424 
01425     if ( gD.level > 0 )
01426         fprintf( stderr, "\n%s running, use <ctrl-c> to quit...\n\n",
01427                  IFM_PROG_NAME );
01428 
01429     return 0;
01430 }
01431 
01432 
01433 
01434 
01435 
01436 
01437 
01438 
01439 
01440 
01441 static int init_extras( param_t * p, ART_comm * ac )
01442 {
01443     if ( p->opts.nice && set_nice_level(p->opts.nice) )
01444         return 1;
01445 
01446     if ( ac->state == ART_STATE_TO_OPEN )            
01447     {
01448         atexit( ART_exit );
01449         ac->mode = AFNI_OPEN_CONTROL_MODE;
01450         ART_open_afni_link( ac, 2, 1, gD.level );
01451     }
01452     
01453     
01454     if ( p->opts.start_file != NULL )
01455     {
01456         char * sf     = p->opts.start_file;
01457         char * gd     = p->glob_dir;
01458         int    flevel = str_char_count( sf, strlen(sf), (char)'/' );
01459 
01460         
01461         if ( flevel != str_char_count( gd, strlen(gd), (char)'/' ) )
01462         {
01463             fprintf( stderr,
01464                      "** warning : relative path to       : '-start_dir  %s'\n"
01465                      "             does not seem to match : '-start_file %s'\n"
01466                      "             (so 'start_file' may never be found)\n\n",
01467                      p->opts.start_file, p->opts.start_dir );
01468         }
01469         else if ( gD.level > 1 )
01470             fprintf( stderr, "-- '-start_file %s' and\n"
01471                              "   '-start_dir  %s' match at dir level %d\n",
01472                              p->opts.start_file, p->opts.start_dir, flevel );
01473     }
01474 
01475     return 0;
01476 }
01477 
01478 
01479 
01480 
01481 
01482 
01483 
01484 
01485 
01486 static int set_nice_level( int level )
01487 {
01488     int rv;
01489 
01490     rv = nice( level );
01491     if ( rv != 0 )
01492     {
01493         if ( level < 0 )
01494             fprintf( stderr, "error: only root may decrement nice value\n"
01495                              "       (errno = %d, rv = %d)\n", errno, rv );
01496         else
01497             fprintf( stderr,
01498                      "error: failure to adjust nice by %d\n"
01499                      "       (errno = %d, rv = %d)\n", level, errno, rv );
01500     }
01501     else if ( gD.level > 1 )
01502         fprintf( stderr, "-- nice value incremented by %d\n", level );
01503 
01504     return rv;
01505 }
01506 
01507 
01508 
01509 
01510 
01511 
01512 
01513 
01514 
01515 
01516 
01517 
01518 
01519 
01520 int dir_expansion_form( char * sin, char ** sexp )
01521 {
01522     char * out;
01523     char * cp;
01524     char   d0, d1, d2;                  
01525     int    len;
01526 
01527     if ( (sin == NULL) || (sexp == NULL) )
01528         return -1;
01529 
01530     *sexp = NULL;
01531     len = strlen(sin);
01532 
01533     out = (char *)malloc((len + IFM_PAD_LEN) * sizeof(char));
01534     if ( out == NULL )
01535     {
01536         fprintf( stderr, "failure: dir_expansion_form malloc\n" );
01537         return -1;
01538     }
01539 
01540     *sexp = out;                        
01541 
01542     strcpy( out,sin );
01543 
01544     cp = out + len - 1;                         
01545 
01546     
01547     while ( (cp > (out+2)) && !isdigit( *cp ) )
01548         cp--;
01549 
01550     if ( !isdigit(*cp) )                        
01551     {
01552         fprintf( stderr, "error: dir <%s> is not of the form 00n (e.g. 003)\n",
01553                  sin );
01554         free(out);
01555         return -1;
01556     }
01557 
01558     cp -= 2;                                    
01559 
01560     d0 = cp[0];                                 
01561     d1 = cp[1];
01562     d2 = cp[2];
01563 
01564     if ( (d0 != '0') ||                         
01565          ( (d1 != '0') && (d1 != '1')) )        
01566     {
01567         fprintf( stderr, "error: dir <%s> is not of the form 0[01]n"
01568                          " (e.g. 003)\n", sin );
01569         free(out);
01570         return -1;
01571     }
01572 
01573     
01574     
01575 
01576     strcpy( cp, "[0-9]" );                      
01577     cp += strlen( "[0-9]" );
01578 
01579     if ( d1 == '0' )                            
01580         strcpy( cp, "[02468]" );
01581     else
01582         strcpy( cp, "[13579]" );
01583     cp += strlen( "[02468]" );
01584 
01585     *cp++ = d2;                                 
01586 
01587     
01588     strcpy( cp, "/[Ii].*" );                    
01589 
01590     return 0;
01591 }
01592 
01593 
01594 
01595 
01596 
01597 
01598 
01599 
01600 
01601 static int read_ge_image( char * pathname, finfo_t * fp,
01602                           int get_image, int need_memory )
01603 {
01604    ge_header_info * hi  = &fp->geh;
01605 
01606    FILE *imfile ;
01607    int  length , skip , swap=0 ;
01608    char orients[8] , str[8] ;
01609    int nx , ny , bpp , cflag , hdroff ;
01610         float uv17 = -1.0;
01611         
01612    if( hi == NULL ) return -1;            
01613    hi->good = 0 ;                       
01614    if( pathname    == NULL ||
01615        pathname[0] == '\0'   ) return -1; 
01616 
01617    length = l_THD_filesize( pathname ) ;
01618    if( length < 1024 ) return -1;         
01619 
01620    imfile = fopen( pathname , "r" ) ;
01621    if( imfile == NULL ) return -1;        
01622 
01623    strcpy(str,"JUNK") ;     
01624    fread(str,1,4,imfile) ;  
01625 
01626    if( str[0]!='I' || str[1]!='M' || str[2]!='G' || str[3]!='F' ){ 
01627       fclose(imfile) ; return -2;
01628    }
01629 
01630    
01631 
01632    fread( &skip , 4,1, imfile ) ; 
01633    fread( &nx   , 4,1, imfile ) ; 
01634    fread( &ny   , 4,1, imfile ) ; 
01635    fread( &bpp  , 4,1, imfile ) ; 
01636    fread( &cflag, 4,1, imfile ) ; 
01637 
01638         
01639 
01640    if( nx < 0 || nx > 8192 ){      
01641      swap = 1 ;                    
01642      swap_4(&skip); swap_4(&nx); swap_4(&ny); swap_4(&bpp); swap_4(&cflag);
01643    } else {
01644      swap = 0 ;  
01645    }
01646    if( nx < 0 || nx > 8192 || ny < 0 || ny > 8192 ){  
01647       fclose(imfile) ; return -1;
01648    }
01649 
01650    hi->nx = nx ;
01651    hi->ny = ny ;
01652 
01653    if( skip+2*nx*ny >  length ||               
01654        skip         <= 0      ||               
01655        cflag        != 1      ||               
01656        bpp          != 16        ){
01657       fclose(imfile); return -1;    
01658    }
01659 
01660    
01661 
01662    fseek( imfile , 148L , SEEK_SET ) ; 
01663    fread( &hdroff , 4,1 , imfile ) ;   
01664    if( swap ) swap_4(&hdroff) ;
01665 
01666    if( hdroff > 0 && hdroff+256 < length ){   
01667        float dx,dy,dz, xyz[9], zz ; int itr, ii,jj,kk ;
01668 
01669        
01670 
01671        fseek( imfile , hdroff+26 , SEEK_SET ) ;    
01672        fread( &dz , 4,1 , imfile ) ;
01673 
01674        fseek( imfile , hdroff+50 , SEEK_SET ) ;    
01675        fread( &dx , 4,1 , imfile ) ;
01676        fread( &dy , 4,1 , imfile ) ;
01677 
01678        if( swap ){ swap_4(&dx); swap_4(&dy); swap_4(&dz); }
01679 
01680        hi->dx = dx ; hi->dy = dy ; hi->dz = dz ;
01681 
01682        
01683        
01684        
01685        
01686        
01687 
01688        fseek( imfile , hdroff+154 , SEEK_SET ) ;  
01689        fread( xyz , 4,9 , imfile ) ;
01690        if( swap ){
01691           swap_4(xyz+0); swap_4(xyz+1); swap_4(xyz+2);
01692           swap_4(xyz+3); swap_4(xyz+4); swap_4(xyz+5);
01693           swap_4(xyz+6); swap_4(xyz+7); swap_4(xyz+8);
01694        }
01695 
01696        
01697        
01698        
01699        
01700 
01701        dx = fabs(xyz[3]-xyz[0]) ; ii = 1 ;
01702        dy = fabs(xyz[4]-xyz[1]) ; if( dy > dx ){ ii=2; dx=dy; }
01703        dz = fabs(xyz[5]-xyz[2]) ; if( dz > dx ){ ii=3;        }
01704        dx = xyz[ii+2]-xyz[ii-1] ; if( dx < 0. ){ ii = -ii;    }
01705        switch( ii ){
01706         case  1: orients[0]= 'L'; orients[1]= 'R'; break;
01707         case -1: orients[0]= 'R'; orients[1]= 'L'; break;
01708         case  2: orients[0]= 'P'; orients[1]= 'A'; break;
01709         case -2: orients[0]= 'A'; orients[1]= 'P'; break;
01710         case  3: orients[0]= 'I'; orients[1]= 'S'; break;
01711         case -3: orients[0]= 'S'; orients[1]= 'I'; break;
01712         default: orients[0]='\0'; orients[1]='\0'; break;
01713        }
01714 
01715        
01716        
01717        
01718        
01719 
01720        dx = fabs(xyz[6]-xyz[3]) ; jj = 1 ;
01721        dy = fabs(xyz[7]-xyz[4]) ; if( dy > dx ){ jj=2; dx=dy; }
01722        dz = fabs(xyz[8]-xyz[5]) ; if( dz > dx ){ jj=3;        }
01723        dx = xyz[jj+5]-xyz[jj+2] ; if( dx < 0. ){ jj = -jj;    }
01724        switch( jj ){
01725          case  1: orients[2] = 'L'; orients[3] = 'R'; break;
01726          case -1: orients[2] = 'R'; orients[3] = 'L'; break;
01727          case  2: orients[2] = 'P'; orients[3] = 'A'; break;
01728          case -2: orients[2] = 'A'; orients[3] = 'P'; break;
01729          case  3: orients[2] = 'I'; orients[3] = 'S'; break;
01730          case -3: orients[2] = 'S'; orients[3] = 'I'; break;
01731          default: orients[2] ='\0'; orients[3] ='\0'; break;
01732        }
01733 
01734        orients[4] = '\0' ;   
01735 
01736        kk = 6 - abs(ii)-abs(jj) ;   
01737                                     
01738                                     
01739 
01740        zz = xyz[kk-1] ;             
01741 
01742        hi->zoff = zz ;
01743        strcpy(hi->orients,orients) ;
01744 
01745        
01746        
01747        fp->gex.xorg = xyz[abs(ii)-1];
01748        fp->gex.yorg = xyz[abs(jj)-1];
01749 
01750        
01751 
01752        fseek( imfile , hdroff+194 , SEEK_SET ) ;
01753        fread( &itr , 4,1 , imfile ) ; 
01754        if( swap ) swap_4(&itr) ;
01755        hi->tr = 1.0e-6 * itr ;        
01756 
01757        
01758 
01759        fseek( imfile , hdroff+202 , SEEK_SET ) ;
01760        fread( &itr , 4,1 , imfile ) ; 
01761        if( swap ) swap_4(&itr) ;
01762        hi->te = 1.0e-6 * itr ;
01763 
01764        
01765 
01766 
01767 
01768 
01769         
01770         fseek ( imfile , hdroff+272+202, SEEK_SET ) ;
01771         fread( &uv17 , 4, 1 , imfile ) ;
01772         if( swap ) swap_4(&uv17) ;
01773         
01774         hi->uv17 = (int)uv17; 
01775         
01776 
01777         
01778         fp->gex.bpp    = bpp;
01779         fp->gex.cflag  = cflag;
01780         fp->gex.hdroff = hdroff;
01781         fp->gex.skip   = skip;
01782         fp->gex.swap   = swap;
01783         fp->gex.kk     = kk;
01784 
01785         memcpy( fp->gex.xyz, xyz, sizeof(xyz) );
01786         
01787         hi->good = 1 ;                  
01788 
01789     } 
01790 
01791     
01792     if ( get_image )
01793     {
01794         int elements = hi->nx * hi->ny;
01795 
01796         fp->bytes = elements * 2;                       
01797 
01798         if ( need_memory )
01799             fp->image = malloc( fp->bytes );
01800 
01801         if ( fp->image == NULL )
01802         {
01803             fprintf(stderr, "** RGI: no memory for %d byte image\n", fp->bytes);
01804             hi->good = 0;
01805             return -1;
01806         }
01807 
01808         fseek ( imfile, skip, SEEK_SET );
01809         if ( fread( fp->image , 2, elements, imfile ) != elements )
01810         {
01811             fprintf( stderr, "** RGI: failed to read %d shorts from %s\n",
01812                      elements, pathname );
01813             hi->good = 0;               
01814             return -1;
01815         }
01816     }
01817 
01818     fclose(imfile);
01819     return 0;
01820 }
01821 
01822 
01823 
01824 
01825 
01826 
01827 static int swap_4( void * ptr )            
01828 {
01829     unsigned char * addr = ptr;
01830 
01831     addr[0] ^= addr[3]; addr[3] ^= addr[0]; addr[0] ^= addr[3];
01832     addr[1] ^= addr[2]; addr[2] ^= addr[1]; addr[1] ^= addr[2];
01833 
01834     return 0;
01835 }
01836 
01837 
01838 
01839 
01840 
01841 
01842 static int idisp_im_store_t( char * info, im_store_t * is )
01843 {
01844     if ( info )
01845         fputs( info, stdout );
01846 
01847     if ( is == NULL )
01848     {
01849         printf( "idisp_im_store_t: is == NULL\n" );
01850         return -1;
01851     }
01852 
01853     printf( "im_store_t struct at %p :\n"
01854             "   (nalloc, nused)    = (%d, %d)\n"
01855             "   (ary_len, im_size) = (%d, %d)\n"
01856             "   (im_ary, x_im)     = (%p, %p)\n",
01857             is, is->nalloc, is->nused,
01858             is->ary_len, is->im_size, is->im_ary, is->x_im );
01859 
01860     return 0;
01861 }
01862 
01863 
01864 
01865 
01866 
01867 
01868 static int idisp_hf_param_t( char * info, param_t * p )
01869 {
01870     if ( info )
01871         fputs( info, stdout );
01872 
01873     if ( p == NULL )
01874     {
01875         printf( "idisp_hf_param_t: p == NULL\n" );
01876         return -1;
01877     }
01878 
01879     printf( "param_t struct at %p :\n"
01880             "   ftype             =%d\n"
01881             "   (nused, nalloc)   = (%d, %d)\n"
01882             "   flist             = %p\n"
01883             "   glob_dir          = %s\n"
01884             "   nfiles            = %d\n"
01885             "   fnames            = %p\n",
01886             p, p->ftype, p->nused, p->nalloc, p->flist,
01887             CHECK_NULL_STR(p->glob_dir),
01888             p->nfiles, p->fnames );
01889 
01890     return 0;
01891 }
01892 
01893 
01894 
01895 
01896 
01897 
01898 static int idisp_hf_opts_t( char * info, opts_t * opt )
01899 {
01900     if ( info )
01901         fputs( info, stdout );
01902 
01903     if ( opt == NULL )
01904     {
01905         printf( "idisp_hf_opts_t: opt == NULL\n" );
01906         return -1;
01907     }
01908 
01909     printf( "opts_t struct at %p :\n"
01910             "   start_file         = %s\n"
01911             "   start_dir          = %s\n"
01912             "   sp                 = %s\n"
01913             "   gert_outdir        = %s\n"
01914             "   (argv, argc)       = (%p, %d)\n"
01915             "   (nt, nice)         = (%d, %d)\n"
01916             "   (debug, gert_reco) = (%d, %d)\n"
01917             "   quit               = %d\n"
01918             "   (rt, swap, rev_bo) = (%d, %d, %d)\n"
01919             "   host               = %s\n"
01920             "   drive_list(u,a,p)  = %d, %d, %p\n"
01921             "   rt_list   (u,a,p)  = %d, %d, %p\n",
01922             opt,
01923             CHECK_NULL_STR(opt->start_file),
01924             CHECK_NULL_STR(opt->start_dir),
01925             CHECK_NULL_STR(opt->sp),
01926             CHECK_NULL_STR(opt->gert_outdir),
01927             opt->argv, opt->argc,
01928             opt->nt, opt->nice,
01929             opt->debug, opt->gert_reco, opt->quit,
01930             opt->rt, opt->swap, opt->rev_bo,
01931             CHECK_NULL_STR(opt->host),
01932             opt->drive_list.nused, opt->drive_list.nalloc, opt->drive_list.str,
01933             opt->rt_list.nused, opt->rt_list.nalloc, opt->rt_list.str
01934             );
01935 
01936     return 0;
01937 }
01938 
01939 
01940 
01941 
01942 
01943 
01944 static int idisp_hf_vol_t( char * info, vol_t * v )
01945 {
01946     if ( info )
01947         fputs( info, stdout );
01948 
01949     if ( v == NULL )
01950     {
01951         printf( "idisp_hf_vol_t: v == NULL\n" );
01952         return -1;
01953     }
01954 
01955     printf( "vol_t struct at %p :\n"
01956             "   nim                 = %d\n"
01957             "   (fl_1, fn_1, fn_n)  = (%d, %d, %d)\n"
01958             "   first_file          = %s\n"
01959             "   last_file           = %s\n"
01960             "   (z_first, z_last)   = (%f, %f)\n"
01961             "   z_delta             = %f\n"
01962             "   (seq_num, run)      = (%d, %d)\n",
01963             v, v->nim, v->fl_1, v->fn_1, v->fn_n,
01964             v->first_file, v->last_file,
01965             v->z_first, v->z_last, v->z_delta,
01966             v->seq_num, v->run );
01967 
01968     idisp_ge_header_info( info, &v->geh );
01969     idisp_ge_extras( info, &v->gex );
01970 
01971     return 0;
01972 }
01973 
01974 
01975 
01976 
01977 
01978 
01979 
01980 static int idisp_ge_extras( char * info, ge_extras * E )
01981 {
01982     if ( info )
01983         fputs( info, stdout );
01984 
01985     if ( E == NULL )
01986     {
01987         printf( "idisp_ge_extras: E == NULL\n" );
01988         return -1;
01989     }
01990 
01991     printf( "ge_extras at %p :\n"
01992             "    bpp              = %d\n"
01993             "    cflag            = %d\n"
01994             "    hdroff           = %d\n"
01995             "    skip             = %d\n"
01996             "    swap             = %d\n"
01997             "    kk               = %d\n"
01998             "    xorg             = %f\n"
01999             "    yorg             = %f\n"
02000             "    (xyz0,xyz1,xyz2) = (%f,%f,%f)\n"
02001             "    (xyz3,xyz4,xyz5) = (%f,%f,%f)\n"
02002             "    (xyz6,xyz7,xyz8) = (%f,%f,%f)\n",
02003             E, E->bpp, E->cflag, E->hdroff, E->skip, E->swap, E->kk,
02004             E->xorg,   E->yorg,
02005             E->xyz[0], E->xyz[1], E->xyz[2],
02006             E->xyz[3], E->xyz[4], E->xyz[5],
02007             E->xyz[6], E->xyz[7], E->xyz[8]
02008           );
02009     return 0;
02010 }
02011 
02012 
02013 
02014 
02015 
02016 
02017 static int idisp_ge_header_info( char * info, ge_header_info * I )
02018 {
02019     if ( info )
02020         fputs( info, stdout );
02021 
02022     if ( I == NULL )
02023     {
02024         printf( "idisp_ge_header_info: I == NULL\n" );
02025         return -1;
02026     }
02027 
02028     printf( "ge_header_info at %p :\n"
02029             "    good        = %d\n"
02030             "    (nx,ny)     = (%d,%d)\n"
02031             "    uv17        = %d\n"
02032             "    (dx,dy,dz)  = (%f,%f,%f)\n"
02033             "    zoff        = %f\n"
02034             "    (tr,te)     = (%f,%f)\n"
02035             "    orients     = %-8s\n",
02036             I, I->good, I->nx, I->ny, I->uv17,
02037             I->dx, I->dy, I->dz, I->zoff, I->tr, I->te,
02038             CHECK_NULL_STR(I->orients)
02039           );
02040 
02041     return 0;
02042 }
02043 
02044 
02045 
02046 
02047 
02048 static int usage ( char * prog, int level )
02049 {
02050     if ( level == IFM_USE_SHORT )
02051     {
02052         fprintf( stderr,
02053             "usage: %s [options] -start_dir DIR\n"
02054             "usage: %s -help\n",
02055             prog, prog );
02056         return 0;
02057     }
02058     else if ( level == IFM_USE_LONG )
02059     {
02060         printf(
02061           "\n"
02062           "%s - monitor real-time acquisition of I-files\n"
02063           "\n"
02064           "    This program is intended to be run during a scanning session\n"
02065           "    on a GE scanner, to monitor the collection of I-files.  The\n"
02066           "    user will be notified of any missing slice or any slice that\n"
02067           "    is aquired out of order.\n"
02068           "\n"
02069           "    It is recommended that the user runs '%s' just after the\n"
02070           "    scanner is first prepped, and then watches for error messages\n"
02071           "    during the scanning session.  The user should terminate the\n"
02072           "    program whey they are done with all runs.\n"
02073           "\n"
02074           "    Note that '%s' can also be run separate from scanning, either\n"
02075           "    to verify the integrity of I-files, or to create a GERT_Reco2\n"
02076           "    script, which is used to create AFNI datasets.\n"
02077           "\n"
02078           "    At the present time, the user must use <ctrl-c> to terminate\n"
02079           "    the program.\n"
02080           "\n"
02081           "  ---------------------------------------------------------------\n"
02082           "  usage: %s [options] -start_dir DIR\n"
02083           "\n"
02084           "  ---------------------------------------------------------------\n"
02085           "  examples (no real-time options):\n"
02086           "\n"
02087           "    %s -start_dir 003\n"
02088           "    %s -help\n"
02089           "    %s -start_dir 003 -GERT_reco2 -quit\n"
02090           "    %s -start_dir 003 -nt 120 -start_file 043/I.901\n"
02091           "    %s -debug 2 -nice 10 -start_dir 003\n"
02092           "\n"
02093           "  examples (with real-time options):\n"
02094           "\n"
02095           "    %s -start_dir 003 -rt\n"
02096           "    %s -start_dir 003 -rt -host pickle\n"
02097           "    %s -start_dir 003 -nt 120 -rt -host pickle\n"
02098           "\n"
02099           "  ** detailed real-time example:\n"
02100           "\n"
02101           "    This example scans data starting from directory 003, expects\n"
02102           "    160 repetitions (TRs), and invokes the real-time processing,\n"
02103           "    sending data to a computer called some.remote.computer.name\n"
02104           "    (where afni is running, and which considers THIS computer to\n"
02105           "    be trusted - see the AFNI_TRUSTHOST environment variable).\n"
02106           "\n"
02107           "    Multiple DRIVE_AFNI commands are passed through '-drive_afni'\n"
02108           "    options, one requesting to open an axial image window, and\n"
02109           "    another requesting an axial graph, with 160 data points.\n"
02110           "\n"
02111           "    See README.driver for acceptable DRIVE_AFNI commands.\n"
02112           "\n"
02113           "    Also, multiple commands specific to the real-time plugin are\n"
02114           "    passed via the '-rt_cmd' options.  The 'REFIX command sets the\n"
02115           "    prefix for the datasets output by afni.  The GRAPH_XRANGE and\n"
02116           "    GRAPH_YRANGE commands set the graph dimensions for the 3D\n"
02117           "    motion correction graph (only).  And the GRAPH_EXPR command\n"
02118           "    is used to replace the 6 default motion correction graphs with\n"
02119           "    a single graph, according to the given expression, the square\n"
02120           "    root of the average squared entry of the 3 rotaion parameters,\n"
02121           "    roll, pitch and yaw, ignoring the 3 shift parameters, dx, dy\n"
02122           "    and dz.\n"
02123           "\n"
02124           "    See README.realtime for acceptable DRIVE_AFNI commands.\n"
02125           "\n"
02126           "    %s                                                   \\\n"
02127           "       -start_dir 003                                      \\\n"
02128           "       -nt 160                                             \\\n"
02129           "       -rt                                                 \\\n"
02130           "       -host some.remote.computer.name                     \\\n"
02131           "       -drive_afni 'OPEN_WINDOW axialimage'                \\\n"
02132           "       -drive_afni 'OPEN_WINDOW axialgraph pinnum=160'     \\\n"
02133           "       -rt_cmd 'PREFIX eat.more.cheese'                    \\\n"
02134           "       -rt_cmd 'GRAPH_XRANGE 160'                          \\\n"
02135           "       -rt_cmd 'GRAPH_YRANGE 1.02'                         \\\n"
02136           "       -rt_cmd 'GRAPH_EXPR sqrt((d*d+e*e+f*f)/3)'            \n"
02137           "\n"
02138           "  ---------------------------------------------------------------\n"
02139           "  notes:\n"
02140           "\n"
02141           "    - Once started, this program exits only when a fatal error\n"
02142           "      occurs (single missing or out of order slices are not\n"
02143           "      considered fatal).\n"
02144           "\n"
02145           "      ** This has been modified.  The '-quit' option tells Imon\n"
02146           "         to terminate once it runs out of new data to use.\n"
02147           "\n"
02148           "    - To terminate this program, use <ctrl-c>.\n"
02149           "\n"
02150           "  ---------------------------------------------------------------\n"
02151           "  main option:\n"
02152           "\n"
02153           "    -start_dir DIR     : (REQUIRED) specify starting directory\n"
02154           "\n"
02155           "        e.g. -start_dir 003\n"
02156           "\n"
02157           "        The starting directory, DIR, must be of the form 00n,\n"
02158           "        where n is a digit.  The program then monitors all\n"
02159           "        directories of the form ??n, created by the GE scanner.\n"
02160           "\n"
02161           "        For instance, with the option '-start_dir 003', this\n"
02162           "        program watches for new directories 003, 023, 043, etc.\n"
02163           "\n"
02164           "  ---------------------------------------------------------------\n"
02165           "  real-time options:\n"
02166           "\n"
02167           "    -rt                : specify to use the real-time facility\n"
02168           "\n"
02169           "        With this option, the user tells '%s' to use the real-time\n"
02170           "        facility, passing each volume of images to an existing\n"
02171           "        afni process on some machine (as specified by the '-host'\n"
02172           "        option).  Whenever a new volume is aquired, it will be\n"
02173           "        sent to the afni program for immediate update.\n"
02174           "\n"
02175           "        Note that afni must also be started with the '-rt' option\n"
02176           "        to make use of this.\n"
02177           "\n"
02178           "        Note also that the '-host HOSTNAME' option is not required\n"
02179           "        if afni is running on the same machine.\n"
02180           "\n"
02181           "    -drive_afni CMND   : send 'drive afni' command, CMND\n"
02182           "\n"
02183           "        e.g.  -drive_afni 'OPEN_WINDOW axialimage'\n"
02184           "\n"
02185           "        This option is used to pass a single DRIVE_AFNI command\n"
02186           "        to afni.  For example, 'OPEN_WINDOW axialimage' will open\n"
02187           "        such an axial view window on the afni controller.\n"
02188           "\n"
02189           "        Note: the command 'CMND' must be given in quotes, so that\n"
02190           "              the shell will send it as a single parameter.\n"
02191           "\n"
02192           "        Note: this option may be used multiple times.\n"
02193           "\n"
02194           "        See README.driver for more details.\n"
02195           "\n"
02196           "    -host HOSTNAME     : specify the host for afni communication\n"
02197           "\n"
02198           "        e.g.  -host mycomputer.dot.my.network\n"
02199           "        e.g.  -host 127.0.0.127\n"
02200           "        e.g.  -host mycomputer\n"
02201           "        the default host is 'localhost'\n"
02202           "\n"
02203           "        The specified HOSTNAME represents the machine that is\n"
02204           "        running afni.  Images will be sent to afni on this machine\n"
02205           "        during the execution of '%s'.\n"
02206           "\n"
02207           "        Note that the enviroment variable AFNI_TRUSTHOST must be\n"
02208           "        set on the machine running afni.  Set this equal to the\n"
02209           "        name of the machine running Imon (so that afni knows to\n"
02210           "        accept the data from the sending machine).\n"
02211           "\n"
02212           "    -rev_byte_order   : pass the reverse of the BYTEORDER to afni\n"
02213           "\n"
02214           "        Reverse the byte order that is given to afni.  In case the\n"
02215           "        detected byte order is not what is desired, this option\n"
02216           "        can be used to reverse it.\n"
02217           "\n"
02218           "        See the (obsolete) '-swap' option for more details.\n"
02219           "\n"
02220           "    -rt_cmd COMMAND   : send COMMAND(s) to realtime plugin\n"
02221           "\n"
02222           "        e.g.  -rt_cmd 'GRAPH_XRANGE 120'\n"
02223           "        e.g.  -rt_cmd 'GRAPH_XRANGE 120 \\n GRAPH_YRANGE 2.5'\n"
02224           "\n"
02225           "        This option is used to pass commands to the realtime\n"
02226           "        plugin.  For example, 'GRAPH_XRANGE 120' will set the\n"
02227           "        x-scale of the motion graph window to 120 (repetitions).\n"
02228           "\n"
02229           "        Note: the command 'COMMAND' must be given in quotes, so\n"
02230           "        that the shell will send it as a single parameter.\n"
02231           "\n"
02232           "        Note: this option may be used multiple times.\n"
02233           "\n"
02234           "        See README.realtime for more details.\n"
02235           "\n"
02236           "    -swap  (obsolete) : swap data bytes before sending to afni\n"
02237           "\n"
02238           "        Since afni may be running on a different machine, the byte\n"
02239           "        order may differ there.  This option will force the bytes\n"
02240           "        to be reversed, before sending the data to afni.\n"
02241           "\n"
02242           "        ** As of version 3.0, this option should not be necessary.\n"
02243           "           '%s' detects the byte order of the image data, and then\n"
02244           "           passes that information to afni.  The realtime plugin\n"
02245           "           will (now) decide whether to swap bytes in the viewer.\n"
02246           "\n"
02247           "           If for some reason the user wishes to reverse the order\n"
02248           "           from what is detected, '-rev_byte_order' can be used.\n"
02249           "\n"
02250           "    -zorder ORDER     : slice order over time\n"
02251           "\n"
02252           "        e.g. -zorder alt\n"
02253           "        e.g. -zorder seq\n"
02254           "        the default is 'alt'\n"
02255           "\n"
02256           "        This options allows the user to alter the slice\n"
02257           "        acquisition order in real-time mode, simliar to the slice\n"
02258           "        pattern of the '-sp' option.  The main differences are:\n"
02259           "            o  only two choices are presently available\n"
02260           "            o  the syntax is intentionally different (from that\n"
02261           "               of 'to3d' or the '-sp' option)\n"
02262           "\n"
02263           "        ORDER values:\n"
02264           "            alt   : alternating in the Z direction (over time)\n"
02265           "            seq   : sequential in the Z direction (over time)\n"
02266           "\n"
02267           "  ---------------------------------------------------------------\n"
02268           "  other options:\n"
02269           "\n"
02270           "    -debug LEVEL       : show debug information during execution\n"
02271           "\n"
02272           "        e.g.  -debug 2\n"
02273           "        the default level is 1, the domain is [0,3]\n"
02274           "        the '-quiet' option is equivalent to '-debug 0'\n"
02275           "\n"
02276           "    -help              : show this help information\n"
02277           "\n"
02278           "    -hist              : display a history of program changes\n"
02279           "\n"
02280           "    -nice INCREMENT    : adjust the nice value for the process\n"
02281           "\n"
02282           "        e.g.  -nice 10\n"
02283           "        the default is 0, and the maximum is 20\n"
02284           "        a superuser may use down to the minimum of -19\n"
02285           "\n"
02286           "        A positive INCREMENT to the nice value of a process will\n"
02287           "        lower its priority, allowing other processes more CPU\n"
02288           "        time.\n"
02289           "\n"
02290           "    -nt VOLUMES_PER_RUN : set the number of time points per run\n"
02291           "\n"
02292           "        e.g.  -nt 120\n"
02293           "\n"
02294           "        With this option, if a run stalls before the specified\n"
02295           "        VOLUMES_PER_RUN is reached (notably including the first\n"
02296           "        run), the user will be notified.\n"
02297           "\n"
02298           "        Without this option, %s will compute the expected number\n"
02299           "        of time points per run based on the first run (and will\n"
02300           "        allow the value to increase based on subsequent runs).\n"
02301           "        Therefore %s would not detect a stalled first run.\n"
02302           "\n"
02303           "    -quiet             : show only errors and final information\n"
02304           "\n"
02305           "    -quit              : quit when there is no new data\n"
02306           "\n"
02307           "        With this option, the program will terminate once a delay\n"
02308           "        in new data occurs.  This is most appropriate to use when\n"
02309           "        the image files have already been collected.\n"
02310           "\n"
02311           "    -start_file S_FILE : have %s process starting at S_FILE\n"
02312           "\n"
02313           "        e.g.  -start_file 043/I.901\n"
02314           "\n"
02315           "        With this option, any earlier I-files will be ignored\n"
02316           "        by %s.  This is a good way to start processing a later\n"
02317           "        run, if it desired not to look at the earlier data.\n"
02318           "\n"
02319           "        In this example, all files in directories 003 and 023\n"
02320           "        would be ignored, along with everything in 043 up through\n"
02321           "        I.900.  So 043/I.901 might be the first file in run 2.\n"
02322           "\n"
02323           "    -version           : show the version information\n"
02324           "\n"
02325           "  ---------------------------------------------------------------\n"
02326           "  GERT_Reco2 options:\n"
02327           "\n"
02328           "    -GERT_Reco2        : output a GERT_Reco2 script\n"
02329           "\n"
02330           "        Create a script called 'GERT_Reco2', similar to the one\n"
02331           "        that Ifile creates.  This script may be run to create the\n"
02332           "        AFNI datasets corresponding to the I-files.\n"
02333           "\n"
02334           "    -gert_outdir OUTPUT_DIR  : set output directory in GERT_Reco2\n"
02335           "\n"
02336           "        e.g. -gert_outdir subject_A7\n"
02337           "        e.g. -od subject_A7\n"
02338           "        the default is '-gert_outdir afni'\n"
02339           "\n"
02340           "        This will add '-od OUTPUT_DIR' to the @RenamePanga command\n"
02341           "        in the GERT_Reco2 script, creating new datasets in the\n"
02342           "        OUTPUT_DIR directory, instead of the 'afni' directory.\n"
02343           "\n"
02344           "    -sp SLICE_PATTERN  : set output slice pattern in GERT_Reco2\n"
02345           "\n"
02346           "        e.g. -sp alt-z\n"
02347           "        the default is 'alt+z'\n"
02348           "\n"
02349           "        This options allows the user to alter the slice\n"
02350           "        acquisition pattern in the GERT_Reco2 script.\n"
02351           "\n"
02352           "        See 'to3d -help' for more information.\n"
02353           "\n"
02354           "  ---------------------------------------------------------------\n"
02355           "\n"
02356           "  Author: R. Reynolds - %s\n"
02357           "\n"
02358           "                        (many thanks to R. Birn)\n"
02359           "\n",
02360           prog, prog, prog, prog,
02361           prog, prog, prog, prog, prog, prog, prog, prog, prog,
02362           prog, prog, prog, prog, prog, prog, prog,
02363           IFM_VERSION
02364         );
02365 
02366         return 0;
02367     }
02368     else if ( level == IFM_USE_HIST )
02369     {
02370         fputs( g_history, stdout );
02371         return 0;
02372     }
02373     else if ( level == IFM_USE_VERSION )
02374     {
02375         printf( "%s: %s, compile date: %s\n",
02376                 prog, IFM_VERSION, __DATE__ );
02377         return 0;
02378     }
02379 
02380     fprintf( stderr, "error: usage() called with illegal level <%d>\n", level );
02381 
02382     return -1;
02383 }
02384 
02385 
02386 
02387 
02388 
02389 
02390 static void hf_signal( int signum )
02391 {
02392     switch ( signum )
02393     {
02394         default :
02395             fprintf( stderr, "\nError: received unknown signal, %d\n",
02396                      signum );
02397             break;
02398 
02399         case SIGINT  :
02400         case SIGTERM :
02401             show_run_stats( &gS );
02402             break;
02403     }
02404 
02405     exit(0);
02406 }
02407 
02408 
02409 
02410 
02411 
02412 
02413 static int set_volume_stats( param_t * p, stats_t * s, vol_t * v )
02414 {
02415     run_t * rp;           
02416 
02417     if ( v == NULL || v->seq_num < 0 || v->run < 0 )
02418     {
02419         fprintf( stderr, "failure: SVS - insufficient data\n\n" );
02420         idisp_hf_vol_t ( "-- VOLUME FAILURE INFO : ", v );
02421     }
02422 
02423     
02424     if ( s->nalloc == 0 )
02425     {
02426         s->runs = (run_t *)calloc( IFM_STAT_ALLOC, sizeof(run_t) );
02427         if ( s->runs == NULL )
02428         {
02429             fprintf( stderr, "failure: cannot allocate space for run info\n" );
02430             return -1;
02431         }
02432 
02433         
02434         s->slices  = v->nim;
02435         s->z_first = v->z_first;
02436         s->z_last  = v->z_last;
02437         s->z_delta = v->z_delta;
02438 
02439         s->nalloc  = IFM_STAT_ALLOC;
02440         s->nused   = 0;
02441         s->nvols   = gP.opts.nt;        
02442 
02443         if ( gD.level > 1 )
02444             fprintf( stderr, "\n-- svs: init alloc - vol %d, run %d, file %s\n",
02445                      v->seq_num, v->run, v->first_file );
02446     }
02447 
02448     if ( v->run >= s->nalloc )          
02449     {
02450         
02451         s->runs = (run_t *)realloc( s->runs, (v->run + IFM_STAT_ALLOC) *
02452                                              sizeof(run_t) );
02453         if ( s->runs == NULL )
02454         {
02455             fprintf( stderr, "failure: cannot realloc space for run info\n" );
02456             return -1;
02457         }
02458 
02459         s->nalloc = v->run + IFM_STAT_ALLOC;
02460 
02461         
02462         memset( s->runs + s->nused, 0, (s->nalloc - s->nused)*sizeof(run_t) );
02463 
02464         if ( gD.level > 1 )
02465             fprintf( stderr,
02466                 "\n-- svs: realloc (%d entries) - vol %d, run %d, file %s\n",
02467                 s->nalloc, v->seq_num, v->run, v->first_file );
02468 
02469     }
02470 
02471     
02472 
02473     rp = s->runs + v->run;
02474 
02475     if ( s->nused < v->run+1 )
02476         s->nused = v->run+1;
02477 
02478     if ( rp->volumes == 0 )
02479         strncpy( rp->f1name, v->first_file, IFM_MAX_FLEN );
02480 
02481     rp->volumes = v->seq_num;
02482 
02483     
02484     if ( (p->opts.nt <= 0) && (s->nvols < v->seq_num) )
02485         s->nvols = v->seq_num;
02486 
02487     if ( gD.level > 2 )
02488         fprintf( stderr, "\n-- svs: run %d, seq_num %d\n", v->run, v->seq_num );
02489 
02490     return 0;
02491 }
02492 
02493 
02494 
02495 
02496 
02497 
02498 
02499 
02500 static int create_gert_script( stats_t * s, opts_t * opts )
02501 {
02502     FILE * fp;
02503     char * spat;                        
02504     char   cdir[4], csuff[IFM_SUFFIX_LEN];
02505     int    num_valid, c;
02506 
02507     
02508     spat = opts->sp ? opts->sp : IFM_SLICE_PAT;
02509 
02510     for ( c = 0, num_valid = 0; c < s->nused; c++ )
02511         if ( s->runs[c].volumes > 0 )
02512             num_valid++;
02513 
02514     if ( num_valid == 0 )
02515     {
02516         fprintf( stderr, "-- no runs to use for '%s'\n", IFM_GERT_SCRIPT );
02517         return 0;
02518     }
02519 
02520     if ( (fp = fopen( IFM_GERT_SCRIPT, "w" )) == NULL )
02521     {
02522         fprintf( stderr, "failure: cannot open '%s' for writing, "
02523                  "check permissions\n", IFM_GERT_SCRIPT );
02524         return -1;
02525     }
02526 
02527     
02528     fprintf( fp,
02529              "#!/bin/tcsh\n"
02530              "\n"
02531              "# This script was automatically generated by '%s'.\n"
02532              "# The script format was, uh, borrowed from Ziad's Ifile.c.\n"
02533              "#\n"
02534              "# Please modify the following options for your own evil uses.\n"
02535              "\n"
02536              "set OutlierCheck = '-oc'         # use '' to skip outlier check\n"
02537              "set OutPrefix    = 'OutBrick'    # prefix for datasets\n"
02538              "set OutputDir    = '-od %s'    # where to put output datasets\n"
02539              "\n"
02540              "\n",
02541              IFM_PROG_NAME,
02542              opts->gert_outdir ? opts->gert_outdir : "afni"
02543            );
02544 
02545     for ( c = 0; c < s->nused; c++ )
02546         if ( s->runs[c].volumes > 0 )
02547         {
02548             if ( path_to_dir_n_suffix(cdir, csuff, s->runs[c].f1name) < 0 )
02549             {
02550                 fclose( fp );
02551                 return -1;
02552             }
02553 
02554             fprintf( fp, "@RenamePanga %s %s %d %d $OutPrefix "
02555                          "-sp %s $OutlierCheck $OutputDir\n",
02556                      cdir, csuff, s->slices, s->runs[c].volumes, spat );
02557         }
02558 
02559     fputc( '\n', fp );
02560     fclose( fp );
02561 
02562     
02563     system( "chmod u+x " IFM_GERT_SCRIPT );
02564 
02565     return 0;
02566 }
02567 
02568 
02569 
02570 
02571 
02572 
02573 
02574 static int show_run_stats( stats_t * s )
02575 {
02576     int c;
02577 
02578     if ( s == NULL )
02579     {
02580         fprintf( stderr, "failure, SRS - no stats struct!\n" );
02581         return -1;
02582     }
02583 
02584     if ( s->nalloc <= 0 || s->nused <= 0 )
02585         return 0;
02586 
02587     printf( "\n\n"
02588             "final run statistics:\n"
02589             "    volume info :\n"
02590             "        slices  : %d\n"
02591             "        z_first : %.4f\n"
02592             "        z_last  : %.4f\n"
02593             "        z_delta : %.4f\n"
02594             "\n",
02595             s->slices, s->z_first, s->z_last, s->z_delta );
02596 
02597     for ( c = 0; c < s->nused; c++ )
02598     {
02599         if ( s->runs[c].volumes > 0 )
02600             printf( "    run #%4d : volumes = %3d, first file = %s\n",
02601                     c, s->runs[c].volumes, s->runs[c].f1name );
02602     }
02603 
02604     putchar( '\n' );
02605 
02606     if ( gP.opts.gert_reco )
02607         (void)create_gert_script( s, &gP.opts );
02608 
02609     fflush( stdout );
02610 
02611     return 0;
02612 }
02613 
02614 
02615 
02616 
02617 
02618 
02619 static int nap_time_from_tr( float tr )
02620 {
02621     float tr2 = 2 * tr;
02622 
02623     if ( tr2 < 1 )
02624         return 1;
02625 
02626     if ( tr2 > 10 )
02627         return 10;                      
02628 
02629     return( (int)(tr2 + 0.9) );         
02630 }
02631 
02632 
02633 
02634 
02635 
02636 
02637 
02638 
02639 
02640 
02641 
02642 
02643 
02644 static int find_next_zoff( param_t * p, int start, float zoff )
02645 {
02646     int count;
02647 
02648     if ( (p == NULL) || (start < 0) )
02649         return -2;
02650 
02651     if ( start > p->nused )                     
02652         return -1;
02653 
02654     for ( count = start; count <= p->nused; count++ )
02655         if ( fabs( zoff - p->flist[count].geh.zoff ) < IFM_EPSILON )
02656             return count;                       
02657 
02658     return -1;
02659 }
02660 
02661 
02662 
02663 
02664 
02665 
02666 
02667 
02668 
02669 
02670 
02671 
02672 
02673 
02674 
02675 
02676 
02677 
02678 
02679 
02680 static int check_stalled_run ( int run, int seq_num, int naps, int nap_time )
02681 {
02682     static int func_failure =  0;
02683     static int prev_run     = -1;
02684     static int prev_seq     = -1;
02685 
02686     if ( func_failure != 0 )
02687         return 0;
02688 
02689     if ( ( run < 1 ) || ( seq_num < 1 ) || ( naps <= IFM_MAX_RUN_NAPS ) )
02690         return 0;
02691 
02692     
02693     if ( (((gS.nused + 1) < run) || (gS.runs[run].volumes < seq_num)) &&
02694          ( func_failure == 0 ) )
02695     {
02696         fprintf( stderr, "** warning: CSR - stats inconsistancy!\n" );
02697         func_failure = 1;
02698 
02699         return -1;
02700     }
02701 
02702     if ( seq_num < gS.nvols )      
02703     {
02704         
02705         if ( (run != prev_run) || (seq_num != prev_seq) )
02706         {
02707             fprintf( stderr, "\007\n"
02708                      "****************************************************\n"
02709                      "Warning: run seems to be stalled\n"
02710                      "\n"
02711                      "    run                    : %d\n"
02712                      "    TRs completed          : %d (of %d)\n"
02713                      "    approximate idle time  : %d seconds\n"
02714                      "    first file of this run : %s\n"
02715                      "****************************************************\n",
02716                      run, seq_num, gS.nvols,
02717                      naps*nap_time, gS.runs[run].f1name );
02718 
02719             prev_run = run;
02720             prev_seq = seq_num;
02721 
02722             return 2;
02723         }
02724     }
02725     
02726     else if ( (run != prev_run) || (seq_num != prev_seq) )
02727     {
02728         
02729         prev_run = run;
02730         prev_seq = seq_num;
02731 
02732         return 1;
02733     }
02734 
02735     return 0;
02736 }
02737 
02738 
02739 
02740 
02741 
02742 static unsigned long l_THD_filesize( char * pathname )
02743 {
02744     static struct stat buf ; int ii ;
02745 
02746     if( pathname == NULL ) return -1 ;
02747         ii = stat( pathname , &buf ) ; if( ii != 0 ) return -1 ;
02748 
02749     return buf.st_size ;
02750 }
02751 
02752 
02753 
02754 
02755 
02756 
02757 
02758 
02759 
02760 static int check_im_store_space( im_store_t * is, int num_images )
02761 {
02762     if ( (is == NULL) || (num_images <= 0) )
02763     {
02764         fprintf( stderr, "** CISS: invalid parameters (%p,%d)\n",
02765                  is, num_images );
02766         return -1;
02767     }
02768 
02769     if ( is->ary_len >= num_images )
02770         return 0;
02771 
02772     
02773 
02774     if ( gD.level > 2 )
02775         fprintf( stderr, "++ allocating %d image pointers (was %d)\n",
02776                  num_images, is->ary_len );
02777 
02778     is->im_ary = realloc(is->im_ary, num_images * sizeof(void *));
02779 
02780     if ( is->im_ary == NULL )
02781     {
02782         fprintf( stderr, "** failure: cannot allocate %d image pointers\n",
02783                  num_images );
02784         return -1;
02785     }
02786 
02787     is->ary_len = num_images;
02788 
02789     return 1;
02790 }
02791 
02792 
02793 
02794 
02795 
02796 
02797 
02798 
02799 
02800 static int alloc_x_im( im_store_t * is, int bytes )
02801 {
02802     if ( (is == NULL) || (bytes <= 0) )
02803     {
02804         fprintf( stderr, "** bad params to AXI (%p,%d)\n", is, bytes );
02805         return -1;
02806     }
02807 
02808     is->im_size = bytes;
02809 
02810     if ( (is->x_im = malloc( bytes )) == NULL )
02811     {
02812         fprintf( stderr, "** AXI: failed to malloc %d bytes for x_im\n",
02813                  bytes );
02814         return -1;
02815     }
02816 
02817     if ( gD.level > 1 )
02818         fprintf( stderr, "++ allocating %d bytes for is->x_im\n", bytes );
02819 
02820     return 0;
02821 }
02822 
02823 
02824 
02825 
02826 
02827 
02828 
02829 
02830 
02831 
02832 
02833 
02834 static int check_im_byte_order( int * order, vol_t * v, param_t * p )
02835 {
02836     int one = 1;
02837 
02838     if ( (order == NULL) || (v == NULL) || (p == NULL) )
02839     {
02840         fprintf( stderr, "** invalid paramters to CIBO (%p,%p,%p)\n",
02841                  order, v, p );
02842         return -1;
02843     }
02844 
02845     
02846     *order = (*(char *)&one == 1) ? LSB_FIRST : MSB_FIRST;
02847 
02848     if ( gD.level > 1 )
02849         fprintf( stderr, "-- system order is %s, ",
02850                  (*order == MSB_FIRST) ? "MSB_FIRST" : "LSB_FIRST" );
02851 
02852     
02853     if ( p->flist[v->fl_1].gex.swap ^ p->opts.rev_bo )
02854         *order = LSB_FIRST + MSB_FIRST - *order;      
02855 
02856     if ( gD.level > 1 )
02857         fprintf( stderr, "image order is %s\n",
02858                  (*order == MSB_FIRST) ? "MSB_FIRST" : "LSB_FIRST" );
02859 
02860     return 0;
02861 }
02862 
02863 
02864 
02865 
02866 
02867 
02868 
02869 
02870 
02871 
02872 
02873 
02874 
02875 
02876 static int complete_orients_str( vol_t * v, param_t * p )
02877 {
02878     int kk;
02879 
02880     if ( (v == NULL) || (p == NULL) )
02881     {
02882         fprintf( stderr, "** invalid paramters to COS (%p,%p)\n", v, p );
02883         return -1;
02884     }
02885 
02886     kk = p->flist[v->fl_1].gex.kk;
02887 
02888     switch( kk )
02889     {
02890         case 1:                                 
02891             if ( v->z_delta > 0 )
02892             {
02893                 v->geh.orients[4] = 'L';
02894                 v->geh.orients[5] = 'R';
02895             }
02896             else
02897             {
02898                 v->geh.orients[4] = 'R';
02899                 v->geh.orients[5] = 'L';
02900             }
02901             break;
02902 
02903         case 2:                                 
02904             if ( v->z_delta > 0 )
02905             {
02906                 v->geh.orients[4] = 'P';
02907                 v->geh.orients[5] = 'A';
02908             }
02909             else
02910             {
02911                 v->geh.orients[4] = 'A';
02912                 v->geh.orients[5] = 'P';
02913             }
02914             break;
02915             
02916         case 3:                                 
02917             if ( v->z_delta > 0 )
02918             {
02919                 v->geh.orients[4] = 'I';
02920                 v->geh.orients[5] = 'S';
02921             }
02922             else
02923             {
02924                 v->geh.orients[4] = 'S';
02925                 v->geh.orients[5] = 'I';
02926             }
02927             break;
02928             
02929         default:
02930         {
02931             fprintf(stderr, "** COS failure: kk (%d) out of [1,3] range\n", kk);
02932             return -1;
02933         }
02934     }
02935 
02936     v->geh.orients[6] = '\0';
02937 
02938     return 0;
02939 }
02940 
02941 
02942 
02943 
02944 
02945 
02946 
02947 
02948 
02949 static int find_fl_file_index( param_t * p, char * file )
02950 {
02951     char ** nlp;
02952     int     index;
02953 
02954     if ( (p == NULL) || (file == NULL) )
02955         return 0;
02956 
02957     for ( index = 0, nlp = p->fnames; index < p->nfiles; index++, nlp++ )
02958         if ( ! strcmp( *nlp, file ) )
02959             return index;
02960 
02961     return -1;
02962 }
02963 
02964 
02965 
02966 
02967 
02968 static int str_char_count( char * str, int len, char target )
02969 {
02970     char * cp;
02971     char * last = str + len;
02972     int    num = 0;
02973 
02974     if ( (str == NULL) || (len <= 0) )
02975         return 0;
02976 
02977     for ( cp = str; cp < last; cp++ )
02978         if ( *cp == target )
02979             num++;
02980 
02981     return num;
02982 }
02983 
02984 
02985 
02986 
02987 
02988 
02989 
02990 
02991 
02992 
02993 
02994 
02995 
02996 static int path_to_dir_n_suffix( char * dir, char * suff, char * path )
02997 {
02998     char * cp, *cp2;
02999 
03000     if ( (dir == NULL) || (suff == NULL) || (path == NULL) )
03001     {
03002         fprintf( stderr, "failure: PTDNS - invalid params (%p,%p,%p)\n",
03003                  dir, suff, path );
03004         return -1;
03005     }
03006 
03007     
03008     for ( cp = path + strlen(path) - 1; (*cp != '.') && (cp > path); cp-- )
03009         ;
03010 
03011     if ( *cp != '.' )
03012     {
03013         fprintf( stderr, "failure: cannot find suffix in '%s'\n", path );
03014         return -1;
03015     }
03016     else if ( strlen( cp ) > IFM_SUFFIX_LEN )          
03017     {
03018         fprintf( stderr, "failure: suffix too long in '%s'\n", path );
03019         return -1;
03020     }
03021 
03022     strcpy( suff, cp+1 );               
03023 
03024     
03025     for ( cp2 = suff; (*cp2 != '\0') && isdigit(*cp2); cp2++ )
03026        ;
03027 
03028     if ( *cp2 != '\0' )
03029     {
03030         fprintf( stderr, "failure: suffix not integer in '%s'\n", path );
03031         return -1;
03032     }
03033 
03034     
03035     cp -= 5;
03036     if ( ( cp < path )          ||    
03037          ( ! isdigit( cp[0] ) ) ||    
03038          ( ! isdigit( cp[1] ) ) ||
03039          ( ! isdigit( cp[2] ) ) ||
03040          (   cp[3] != '/'     ) ||
03041          (   cp[4] != 'I'     ) )
03042     {
03043         fprintf( stderr, "failure: PTDNS - ill-formed path '%s'\n", path );
03044         return -1;
03045     }
03046 
03047     
03048     strncpy( dir, cp, 3 );
03049     dir[3] = '\0';
03050 
03051     return 0;
03052 }
03053 
03054 
03055 
03056 
03057 
03058 
03059 
03060 
03061 
03062 static int add_to_string_list( string_list * list, char * str )
03063 {
03064     if ( !list || !str )
03065         return -1;
03066 
03067     
03068     if ( list->nalloc == 0 || (list->nalloc <= list->nused) )
03069     {
03070         list->nalloc += 10;
03071         list->str = (char **)realloc(list->str, list->nalloc*sizeof(char *));
03072         if ( !list->str )
03073         {
03074             fprintf(stderr,"** failed to allocate for %d (char *)s\n",
03075                     list->nalloc);
03076             return -1;
03077         }
03078     }
03079 
03080     list->str[list->nused] = str;
03081     list->nused++;
03082 
03083     return 0;
03084 }
03085 
03086 
03087 
03088 
03089 
03090 
03091 static int empty_string_list( string_list * list, int free_mem )
03092 {
03093     if ( list->str && free_mem )
03094         free( list->str );
03095 
03096     list->str    = NULL;
03097     list->nalloc = 0;
03098     list->nused  = 0;
03099 
03100     return 0;
03101 }
03102