00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 #include <unistd.h>
00013 #include <stdlib.h>
00014 #include <stdio.h>
00015 #include <string.h>
00016 #include <errno.h>
00017 #include <ctype.h>
00018 #include <sys/types.h>
00019 #include <sys/stat.h>
00020 #include <time.h>
00021 #include <math.h>
00022 
00023 
00024 
00025 time_t THD_file_mtime( char * pathname ) ;
00026 int THD_is_file( char * pathname ) ;
00027 int THD_is_symlink( char * pathname ) ;
00028 long THD_filesize( char * pathname ) ;
00029 int THD_is_directory( char * pathname ) ;
00030 int THD_is_executable( char * pathname ) ;
00031 
00032 void MCW_file_expand( int nin , char ** fin , int * nout , char *** fout ) ;
00033 void MCW_free_expand( int gnum , char ** gout ) ;
00034 void MCW_warn_expand( int www ) ;
00035 void NIH_glob( char *fn , int *nout , char ***fout ) ;
00036 void NIH_glob_free( int gnum , char **gout ) ;
00037 
00038 
00039 
00040 typedef struct {                    
00041   int good  ;                       
00042   int nx,ny ;                       
00043   int uv17;                         
00044   float dx,dy,dz , zoff , tr,te ;   
00045   char orients[8] ;                 
00046 } ge_header_info ;
00047 
00048 void ge_header( char *pathname , ge_header_info *hi ) ;
00049 void Ifile_help ();
00050 
00051 
00052 
00053 
00054 int main( int argc , char *argv[] )
00055 {
00056    int num_I , ii,jj , ngood , nrun , i, UseUv17 = 0;
00057    char **nam_I  ;
00058    char **gnam_I , *PatOpt=NULL, *OutDir = NULL;
00059    int   *time_I , *uv17, lmax=0 , ll , thresh , ibot,itop ;
00060    float *zoff_I , tr , zth1,zth2 , zd ;
00061    ge_header_info geh ;
00062    int Ni, CurVolInd, *New_Vol_Loc, *VolSize, N_Vols, *TroubVolume, iTroub, 
00063       MultiSliceVol, *DupSlice, iDup, BadRun, AllGood = 1, GoodRun, kar = -1,
00064       brk = 0, StrtFiles = 0;
00065    float *Dzv, fact;
00066    char fmt[128] ;
00067    FILE * fout_dbg, *fout_panga;
00068 
00069    if (argc == 1) { Ifile_help(); exit(1); }
00070    kar = 1;
00071         brk = 0;
00072    StrtFiles = 0;
00073         UseUv17 = 0;
00074    while (kar < argc && !StrtFiles) { 
00075       if (strcmp (argv[kar],"-h") == 0 || strcmp (argv[kar],"-help") == 0) { Ifile_help(); exit(1); }
00076       
00077       if (!brk && (strcmp(argv[kar], "-nt") == 0)) {
00078          UseUv17 = 1;
00079                         brk = 1;
00080          ++kar;
00081                 }
00082       
00083       if (!brk && (strcmp(argv[kar], "-od") == 0)) {
00084          kar ++;
00085                         if (kar >= argc)  {
00086                                 fprintf (stderr, "Error: Need argument after -od.\n");
00087                                 exit (1);
00088                         }
00089          OutDir =  (char *)malloc((strlen(argv[kar])+1)*sizeof(char));
00090          
00091          sprintf(OutDir,"%s",argv[kar]);
00092          brk = 1;
00093          ++kar;
00094       }
00095       
00096       if (!brk && (strcmp(argv[kar], "-sp") == 0)) {
00097          kar ++;
00098                         if (kar >= argc)  {
00099                                 fprintf (stderr, "Error: Need argument after -sp.\n");
00100                                 exit (1);
00101                         }
00102          PatOpt =  (char *)malloc((strlen(argv[kar])+1)*sizeof(char));
00103          
00104          sprintf(PatOpt,"%s",argv[kar]);
00105          brk = 1;
00106          ++kar;
00107       }
00108       
00109       
00110       if (!brk) {
00111          
00112          StrtFiles = kar;
00113       } else {
00114          brk = 0;
00115       }
00116    }
00117    
00118    if (UseUv17) { 
00119       fprintf(stderr,"++ using User Variable 17.\n"); } 
00120    else { 
00121       fprintf(stderr,"++ using time stamp.\n");} 
00122    
00123    if (!PatOpt) { 
00124       PatOpt = (char *)malloc(sizeof(char)*10);
00125       sprintf(PatOpt,"alt+z");
00126    }
00127    
00128    if (!OutDir) {
00129       OutDir = (char *)malloc(sizeof(char)*10);
00130       sprintf(OutDir,"afni");
00131    }
00132    
00133    fprintf(stderr,"++ using slice pattern %s\n", PatOpt);
00134    fprintf(stderr,"++ using output directory %s\n", OutDir);
00135    
00136    
00137 
00138 
00139 
00140    fout_panga = fopen("GERT_Reco","w");
00141    if (fout_panga == NULL) { 
00142       fprintf(stderr,"Could not open AutoPanga for writing. Check write permissions.\n");
00143       exit(1);
00144    }
00145    fprintf(fout_panga, "#!/bin/csh -f\n");
00146    fprintf(fout_panga, "#This script was automatically generated by Ifile.\n");
00147    fprintf(fout_panga, "#Change the following options to your liking (see @RenamePanga -help for more info):\n\n");
00148    fprintf(fout_panga, "set OutlierCheck = '-oc' #set to '-oc' to check for outliers, '' to skip checking.\n");
00149    fprintf(fout_panga, "set OutPrefix = 'OutBrick' #Output brick prefix.\n\n");
00150    
00151    
00152    fprintf(stderr,"++ Expanding file list ...\n") ;
00153    MCW_file_expand( argc - StrtFiles, argv + StrtFiles  , &num_I , &nam_I );
00154 
00155    fprintf(stderr,"++ found %d '*/I.*' files\n",num_I) ;
00156 
00157    if( num_I <= 0 ) exit(1) ;
00158 
00159    
00160 
00161    time_I = (int *)   calloc( sizeof(int)    , num_I ) ;
00162    zoff_I = (float *) calloc( sizeof(float)  , num_I ) ;
00163    gnam_I = (char **) calloc( sizeof(char *) , num_I ) ;
00164    uv17 = (int *) calloc( sizeof(int)    , num_I ) ;
00165    ngood  = 0 ;
00166 
00167    fprintf(stderr,"++ Scanning GE headers") ;
00168    #ifdef DBG_FILE   
00169       fout_dbg = fopen("DBG_IfileOut.txt","w");
00170    #endif
00171    
00172    for( ii=0 ; ii < num_I ; ii++ ){
00173       ge_header( nam_I[ii] , &geh ) ;    
00174 
00175       if( ii%1000==999 ) fprintf(stderr,".") ;
00176 
00177       if( geh.good ){                    
00178          zoff_I[ngood] = geh.zoff ;
00179          time_I[ngood] = (int) THD_file_mtime( nam_I[ii] ) ;
00180          gnam_I[ngood] = strdup( nam_I[ii] ) ;
00181          uv17[ngood] = geh.uv17;
00182          
00183          ngood++ ;
00184 
00185          ll = strlen(nam_I[ii]) ; if( ll > lmax ) lmax = ll ;
00186 
00187          tr += geh.tr ;
00188       }
00189       else {
00190       fprintf(stderr,"\tFile %s: !geh.good.\t", nam_I[ii] ) ;
00191       }
00192       #ifdef DBG_FILE   
00193          fprintf(fout_dbg,"%s %d\n", nam_I[ii], time_I[ii]);
00194       #endif
00195    }
00196    
00197   
00198    fprintf(stderr,"\n++ %d files are good images\n",ngood) ;
00199 
00200    MCW_free_expand(  num_I, nam_I ) ;
00201 
00202 
00203    if( ngood < 3 ) exit(1) ;
00204 
00205    
00206 
00207    for( ii=ngood-1 ; ii > 0 ; ii-- ) {
00208         time_I[ii] -= time_I[ii-1] ;
00209       
00210       }
00211    time_I[0] = 0 ;
00212 
00213    
00214 
00215    tr    /= ngood ;                 
00216    thresh = (int)( 3.0*tr+10.5 ) ;  
00217 
00218    if (UseUv17 == 0) {
00219       
00220       fprintf(stderr,"++ File time threshold = %d s\n",thresh) ;
00221    }
00222    
00223    
00224 
00225 
00226    GoodRun = 0;
00227    nrun = 0 ;
00228    ibot = 0 ;
00229    while( ibot < ngood ){  
00230 
00231       
00232 
00233       if (UseUv17) {
00234          for( itop=ibot+1; itop<ngood && uv17[itop]==uv17[ibot]; itop++ ) {}; 
00235       } else { 
00236          for( itop=ibot+1; itop<ngood && time_I[itop]<thresh; itop++ ) ; 
00237       }
00238       
00239       
00240       
00241       
00242       
00243       if( ibot == itop-1 ){                    
00244 
00245          printf("skip:   %s\n",gnam_I[ibot]) ;
00246 
00247       } else {                                 
00248                
00249          nrun++ ;
00250          BadRun = 0; 
00251          printf("\nRUN %02d:\t  %s .. %s\t",nrun,gnam_I[ibot],gnam_I[itop-1]) ;
00252          
00253          
00254          if (0) 
00255             {
00256             
00257             
00258             
00259 
00260             zth1 = fabs( zoff_I[ibot+1] - zoff_I[ibot] ) * 1.01 + 0.01 ;
00261             zth2 = 3.01*zth1 ;
00262 
00263             for( jj=ibot ; jj < itop-1 ; jj++ ){
00264                zd = fabs( zoff_I[jj+1] - zoff_I[jj] ) ;
00265                if( zd > zth1 && zd < zth2 )
00266                   printf("  image %s seems out of place\n",gnam_I[jj+1]) ;
00267             }
00268             }
00269          else
00270             {
00271                               
00272                Ni = itop - ibot; 
00273                Dzv = (float *) calloc( sizeof(float)  , Ni) ;
00274                New_Vol_Loc = (int *) calloc(sizeof(int), Ni); 
00275                VolSize = (int *) calloc(sizeof(int), Ni); 
00276                TroubVolume = (int *) calloc(sizeof(int), Ni); 
00277                DupSlice = (int *) calloc(sizeof(int), Ni); 
00278                
00279                Dzv[0] = 0; 
00280                Dzv[1] = zoff_I[ibot+1] - zoff_I[ibot]; 
00281                if (Dzv[1] < 0) 
00282                   {
00283                      fact = -1; 
00284                      Dzv[1] *= fact;
00285                   }
00286                else fact = 1;
00287                if (Dzv[1] != 0) 
00288                   MultiSliceVol = 1; 
00289                else
00290                   MultiSliceVol = 0;
00291                   
00292                
00293                
00294                iDup = 0;
00295                iTroub = 0;
00296                CurVolInd = 0; 
00297                New_Vol_Loc[CurVolInd] = ibot; 
00298                for (jj = ibot+2 ; jj < itop ; jj++ ){
00299                   Dzv[jj-ibot] = fact * (zoff_I[jj] - zoff_I[jj - 1]);
00300                   #ifdef DBG_FILE
00301                      fprintf(fout_dbg,"Dzv %f \n", Dzv[jj-ibot]);
00302                    #endif
00303                   if (MultiSliceVol && !Dzv[jj-ibot]) {
00304                      DupSlice[iDup] = jj;
00305                      ++iDup;
00306                   }
00307                   
00308                   if (Dzv[jj-ibot] < 0) { 
00309                      ++CurVolInd;
00310                      New_Vol_Loc[CurVolInd] = jj;
00311                      VolSize[CurVolInd-1] = New_Vol_Loc[CurVolInd] - New_Vol_Loc[CurVolInd-1]; 
00312                      if (CurVolInd > 1) { 
00313                         if (VolSize[CurVolInd-1] != VolSize[0]) { 
00314                            TroubVolume[iTroub] = CurVolInd - 1;
00315                            ++iTroub;
00316                         }
00317                      }
00318                   }
00319                } 
00320                VolSize[CurVolInd] = itop - New_Vol_Loc[CurVolInd]; 
00321                if (VolSize[CurVolInd] != VolSize[0]) { 
00322                   TroubVolume[iTroub] = CurVolInd;
00323                   ++iTroub;
00324                }
00325                N_Vols = CurVolInd+1;
00326                printf("%d images %d Volume(s) \n", Ni, N_Vols);
00327                
00328                if (N_Vols > 1) {
00329                   
00330 
00331 
00332 
00333 
00334 
00335                }
00336                else {                     
00337                   
00338                }
00339                if (iTroub > 0) { 
00340                   BadRun = 1;
00341                   fprintf(stderr, "\t\33[1m***************** PANGA! Trouble volumes found. *****************\33[0m\n");
00342                   fprintf(stderr, "\tVol %d %s--%s (%d slices) has a different size from the first volume (%d slices) in the series.\n", \
00343                      TroubVolume[0], gnam_I[New_Vol_Loc[TroubVolume[0]]], gnam_I[New_Vol_Loc[TroubVolume[0]]+VolSize[TroubVolume[0]]-1], VolSize[TroubVolume[0]], VolSize[0]);
00344                   if (iTroub > 1)
00345                      fprintf(stderr, "\t%d other volumes suffer of similar ailments! Think of the children!\n", iTroub - 1);
00346                   
00347 
00348 
00349 
00350 
00351                }
00352                if (iDup > 0) { 
00353                   BadRun = 1;
00354                   fprintf(stderr, "\t\33[1m***************** PANGA! Dupilcated slices found. *****************\33[0m\n");
00355                   for (i=0; i < iDup; i++) {
00356                      fprintf(stderr, "\tSlice %s appears to be a duplicate of slice %s.\n", gnam_I[DupSlice[i]], gnam_I[DupSlice[i]-1]);
00357                   }                  
00358                } 
00359             }
00360             
00361             if (!BadRun) { 
00362                ++ GoodRun;
00363                fprintf(fout_panga,"@RenamePanga %s ", strtok(gnam_I[ibot],"/"));
00364                if (MultiSliceVol)
00365                   fprintf(fout_panga,"%s %d %d $OutPrefix -sp %s $OutlierCheck -od %s\n", 
00366                      strtok(NULL,"/I."), (int)Ni/N_Vols, N_Vols, PatOpt, OutDir);
00367                else
00368                   fprintf(fout_panga,"%s %d %d $OutPrefix -sp %s $OutlierCheck -od %s\n", 
00369                      strtok(NULL,"/I."), N_Vols, (int)Ni/N_Vols, PatOpt, OutDir);
00370             }
00371             else
00372             {
00373                AllGood = 0;
00374             }
00375             free(Dzv);
00376             free(New_Vol_Loc);
00377             free(VolSize);
00378             free(TroubVolume);
00379             free(DupSlice);
00380       }
00381 
00382       ibot = itop ;  
00383    }
00384    
00385    free(PatOpt);
00386    free(OutDir);
00387    
00388    #ifdef DBG_FILE
00389       fclose (fout_dbg);
00390    #endif
00391    fprintf(fout_panga, "\n");
00392    fclose (fout_panga);
00393    system ("chmod u+x GERT_Reco");
00394 #if 0
00395    
00396    sprintf(fmt,"%%-%d.%ds: dt=%%d  zoff=%%g\n",lmax,lmax) ;
00397    for( ii=0 ; ii < ngood ; ii++ )
00398       printf(fmt,gnam_I[ii],time_I[ii],zoff_I[ii]) ;
00399 #endif
00400 
00401    if (!GoodRun) 
00402       system ("rm -f GERT_Reco"); 
00403    else
00404       fprintf(stdout,"\nFound %d complete scans.\nRun\33[1m GERT_Reco \33[0mto create AFNI bricks.\n\n", GoodRun);
00405       
00406    if (AllGood)
00407       exit(0) ;
00408    else
00409       exit(1);
00410 }
00411 
00412 
00413 void Ifile_help ()
00414    {
00415       fprintf(stdout,"\nUsage: Ifile [Options] <File List> \n");
00416       
00417       fprintf(stdout,"\n\t[-nt]: Do not use time stamp to identify complete scans.\n");
00418       fprintf(stdout,"\t       Complete scans are identified from 'User Variable 17'\n"
00419                      "\t       in the image header.\n");
00420       fprintf(stdout,"\t[-sp Pattern]: Slice acquisition pattern.\n"          
00421                      "\t               Sets the slice acquisition pattern.\n"
00422                      "\t               The default option is alt+z.\n"
00423                      "\t               See to3d -help for acceptable options.\n"); 
00424       fprintf(stdout,"\t[-od Output_Directory]: Set the output directory in @RenamePanga.\n"
00425                      "\t                        The default is afni .\n"); 
00426       fprintf(stdout,"\n\t<File List>: Strings of wildcards defining series of\n");
00427       fprintf(stdout,"\t              GE-Real Time (GERT) images to be assembled\n");
00428       fprintf(stdout,"\t              as an afni brick. Example:\n");
00429       fprintf(stdout,"\t              Ifile '*/I.*'\n");
00430       fprintf(stdout,"\t          or  Ifile '083/I.*' '103/I.*' '123/I.*' '143/I.*'\n\n"); 
00431       fprintf(stdout,"\tThe program attempts to identify complete scans from the list\n");
00432       fprintf(stdout,"\tof images supplied on command line and generates the commands\n");
00433       fprintf(stdout,"\tnecessary to turn them into AFNI bricks using the script @RenamePanga.\n");
00434       fprintf(stdout,"\tIf at least one complete scan is identified, a script file named GERT_Reco\n");
00435       fprintf(stdout,"\tis created and executing it creates the afni bricks placed in the afni directory.\n");
00436       fprintf(stdout,"\nHow does it work?\n");
00437       fprintf(stdout,"\tWith the -nt option: Ifile uses the variable 'User Variable 17' in the \n");
00438       fprintf(stdout,"\tI file's header. This option appears to be augmented each time a new\n");
00439       fprintf(stdout,"\tscan is started. (Thanks to S. Marrett for discovering the elusive variable.)\n");
00440       fprintf(stdout,"\tWithout -nt option: Ifile first examines the modification time for each image and \n");
00441       fprintf(stdout,"\tinfers from that which images form a single scan. Consecutive images that are less \n");
00442       fprintf(stdout,"\tthan T seconds apart belong to the same scan. T is set based on the mean\n");
00443       fprintf(stdout,"\ttime delay difference between successive images. The threshold currently\n");
00444       fprintf(stdout,"\tused works for the test data that we have. If it fails for your data, let us\n");
00445       fprintf(stdout,"\tknow and supply us with the data. Once a set of images is grouped into a \n");
00446       fprintf(stdout,"\tscan the sequence of slice location is analysed and duplicate, missing slices,\n");
00447       fprintf(stdout,"\tand incomplete volumes are detected. Sets of images that do not pass these tests\n");
00448       fprintf(stdout,"\tare ignored.\n");
00449       fprintf(stdout,"\nPreserving Time Info: (not necessary with -nt option but does not hurt to preserve anyway)\n");
00450       fprintf(stdout,"\tIt is important to preserve the file modification time info as you copy or untar\n");
00451       fprintf(stdout,"\tthe data. If you neglect to do so and fail to write down where each scan ends\n");
00452       fprintf(stdout,"\tand/or begins, you might have a hell of a time reconstructing your data.\n");
00453       fprintf(stdout,"\tWhen copying image directories, use \33[1m cp -rp ???/* \33[0m and when untaring \n");
00454       fprintf(stdout,"\tthe archive, use \33[1m tar --atime-preserve -xf Archive.tar \33[0m on linux.\n");
00455       fprintf(stdout,"\tOn Sun and SGI, tar -xf Archive.tar preserves the time info.\n"); 
00456       fprintf(stdout,"\nFuture Improvements:\n");
00457       fprintf(stdout,"\tOut of justifiable laziness, and for other less convincing reasons, I have left \n");
00458       fprintf(stdout,"\tIfile and @RenamePanga separate. They can be combined into one program but it's usage\n");
00459       fprintf(stdout,"\twould become more complicated. At any rate, the user should not notice any difference\n");
00460       fprintf(stdout,"\tsince all they have to do is run the script GERT_reco that is created by Ifile.\n\n"); 
00461       fprintf(stdout,"\t   Dec. 12/01 (Last modified July 24/02) SSCC/NIMH \n\tRobert W. Cox(rwcox@nih.gov) and Ziad S. Saad (ziad@nih.gov)\n\n");
00462       
00463    }
00464 
00465 
00466 
00467 time_t THD_file_mtime( char * pathname )
00468 {
00469    static struct stat buf ; int ii ;
00470 
00471    if( pathname == NULL ) return 0 ;
00472    ii = stat( pathname , &buf ) ; if( ii != 0 ) return 0 ;
00473    return buf.st_mtime ;
00474 }
00475 
00476 
00477 
00478 int THD_is_file( char * pathname )
00479 {
00480    static struct stat buf ; int ii ;
00481 
00482    if( pathname == NULL ) return 0 ;
00483    ii = stat( pathname , &buf ) ; if( ii != 0 ) return 0 ;
00484    ii = (buf.st_mode & S_IFREG) != 0 ; return ii ;
00485 }
00486 
00487 
00488 
00489 int THD_is_symlink( char * pathname )
00490 {
00491    char buf[32] ; int ii ;
00492 
00493    ii = readlink( pathname , buf , 32 ) ;
00494    return (ii > 0) ;
00495 }
00496 
00497 
00498 
00499 long THD_filesize( char * pathname )
00500 {
00501    static struct stat buf ; int ii ;
00502 
00503    if( pathname == NULL ) return -1 ;
00504    ii = stat( pathname , &buf ) ; if( ii != 0 ) return -1 ;
00505    return buf.st_size ;
00506 }
00507 
00508 
00509 
00510 int THD_is_directory( char * pathname )
00511 {
00512    static struct stat buf ; int ii ;
00513 
00514    if( pathname == NULL ) return 0 ;
00515    ii = stat( pathname , &buf ) ; if( ii != 0 ) return 0 ;
00516    ii = (buf.st_mode & S_IFDIR) != 0 ; return ii ;
00517 }
00518 
00519 
00520 
00521 int THD_is_executable( char * pathname )
00522 {
00523    static struct stat buf ; int ii ;
00524 
00525    if( pathname == NULL ) return 0 ;
00526    ii = stat( pathname , &buf ) ; if( ii != 0 ) return 0 ;
00527    ii = (buf.st_mode & S_IXOTH) != 0 ; return ii ;
00528 }
00529 
00530 
00531 
00532 
00533 
00534 
00535 
00536 
00537 
00538 
00539 
00540 
00541 
00542 
00543 
00544 
00545 
00546 
00547 
00548 
00549 
00550 
00551 
00552 
00553 
00554 
00555 
00556 
00557 
00558 
00559 
00560 
00561 
00562 
00563 
00564 
00565 
00566 
00567 
00568 
00569 
00570 typedef struct {
00571    int gl_pathc;      
00572    int gl_matchc;      
00573    int gl_offs;      
00574    int gl_flags;      
00575    int (*gl_errfunc)();   
00576    char **gl_pathv;   
00577 } glob_t;
00578 
00579 #define   GLOB_APPEND   0x001   
00580 #define   GLOB_DOOFFS   0x002   
00581 #define   GLOB_ERR   0x004   
00582 #define   GLOB_MAGCHAR   0x008   
00583 #define   GLOB_MARK   0x010   
00584 #define   GLOB_NOCHECK   0x020   
00585 #define   GLOB_NOSORT   0x040   
00586 #define   GLOB_QUOTE   0x080   
00587 #define GLOB_NOMAGIC   0x100   
00588 
00589 #define   GLOB_ALTNOT   0x200   
00590 
00591 #define   GLOB_NOSPACE   (-1)   
00592 #define   GLOB_ABEND   (-2)   
00593 
00594 int glob (const char *, int, int (*)(char *, int), glob_t *);
00595 void globfree (glob_t *);
00596 
00597 
00598 
00599 
00600 
00601 
00602 
00603 
00604 
00605 
00606 
00607 
00608 
00609 
00610 
00611 
00612 
00613 
00614 
00615 
00616 
00617 
00618 
00619 
00620 #undef  __P        
00621 #define __P(a) a
00622 
00623 #define xfree     free
00624 #define xmalloc   malloc
00625 #define xrealloc  realloc
00626 
00627 #ifdef SPARKY
00628 #undef _POSIX_SOURCE
00629 #endif
00630 
00631 #include <sys/types.h>
00632 #include <sys/param.h>
00633 #include <sys/stat.h>
00634 #include <dirent.h>
00635 #include <ctype.h>
00636 typedef void * ptr_t;
00637 
00638 
00639 
00640 #if 0
00641 #  define Char __Char
00642 #  include "sh.h"
00643 #  undef Char
00644 #  undef QUOTE
00645 #  undef TILDE
00646 #  undef META
00647 #  undef CHAR
00648 #  undef ismeta
00649 #  undef Strchr
00650 #endif
00651 
00652 #ifndef S_ISDIR
00653 #define S_ISDIR(a)   (((a) & S_IFMT) == S_IFDIR)
00654 #endif
00655 
00656 #if !defined(S_ISLNK) && defined(S_IFLNK)
00657 #define S_ISLNK(a)   (((a) & S_IFMT) == S_IFLNK)
00658 #endif
00659 
00660 #if !defined(S_ISLNK) && !defined(lstat)
00661 #define lstat stat
00662 #endif
00663 
00664 typedef unsigned short Char;
00665 
00666 static   int    glob1       __P((Char *, glob_t *, int));
00667 static   int    glob2      __P((Char *, Char *, Char *, glob_t *, int));
00668 static   int    glob3      __P((Char *, Char *, Char *, Char *,
00669                  glob_t *, int));
00670 static   int    globextend   __P((Char *, glob_t *));
00671 static   int    match      __P((Char *, Char *, Char *, int));
00672 #ifndef __clipper__
00673 static   int    compare   __P((const ptr_t, const ptr_t));
00674 #endif
00675 static    DIR   *Opendir   __P((Char *));
00676 #ifdef S_IFLNK
00677 static   int    Lstat      __P((Char *, struct stat *));
00678 #endif
00679 static    Char    *Strchr      __P((Char *, int));
00680 #ifdef DEBUG
00681 static   void    qprintf   __P((Char *));
00682 #endif
00683 
00684 #define   DOLLAR      '$'
00685 #define   DOT      '.'
00686 #define   EOS      '\0'
00687 #define   LBRACKET   '['
00688 #define   NOT      '!'
00689 #define ALTNOT      '^'
00690 #define   QUESTION   '?'
00691 #define   QUOTE      '\\'
00692 #define   RANGE      '-'
00693 #define   RBRACKET   ']'
00694 #define   SEP      '/'
00695 #define   STAR      '*'
00696 #define   TILDE      '~'
00697 #define   UNDERSCORE   '_'
00698 
00699 #define   M_META      0x8000
00700 #define M_PROTECT   0x4000
00701 #define   M_MASK      0xffff
00702 #define   M_ASCII      0x00ff
00703 
00704 #define   CHAR(c)      ((c)&M_ASCII)
00705 #define   META(c)      ((c)|M_META)
00706 #define   M_ALL      META('*')
00707 #define   M_END      META(']')
00708 #define   M_NOT      META('!')
00709 #define   M_ALTNOT   META('^')
00710 #define   M_ONE      META('?')
00711 #define   M_RNG      META('-')
00712 #define   M_SET      META('[')
00713 #define   ismeta(c)   (((c)&M_META) != 0)
00714 
00715 #include "machdep.h"
00716 
00717 #if defined(SOLARIS_DIRENT_ZERO) && !defined(SOLARIS_DIRENT_PATCH)
00718 #  define SOLARIS_DIRENT_PATCH
00719 #endif
00720 
00721 #ifdef SOLARIS_DIRENT_PATCH
00722 struct  dirent {
00723      ino_t            d_ino;
00724      off_t            d_off;
00725      unsigned short        d_reclen;
00726      char             d_name[1];
00727 };
00728 #endif
00729 
00730 
00731 
00732 
00733 
00734 
00735 
00736 
00737 static DIR *
00738 Opendir(str)
00739     register Char *str;
00740 {
00741     char    buf[MAXPATHLEN];
00742     register char *dc = buf;
00743 
00744     if (!*str)
00745    return (opendir("."));
00746     while ((*dc++ = *str++) != '\0')
00747    continue;
00748     return (opendir(buf));
00749 }
00750 
00751 #ifdef S_IFLNK
00752 static int
00753 Lstat(fn, sb)
00754     register Char *fn;
00755     struct stat *sb;
00756 {
00757     char    buf[MAXPATHLEN];
00758     register char *dc = buf;
00759 
00760     while ((*dc++ = *fn++) != '\0')
00761    continue;
00762 # ifdef NAMEI_BUG
00763     {
00764    int     st;
00765 
00766    st = lstat(buf, sb);
00767    if (*buf)
00768        dc--;
00769    return (*--dc == '/' && !S_ISDIR(sb->st_mode) ? -1 : st);
00770     }
00771 # else
00772     return (lstat(buf, sb));
00773 # endif   
00774 }
00775 #else
00776 #define Lstat Stat
00777 #endif 
00778 
00779 static int
00780 Stat(fn, sb)
00781     register Char *fn;
00782     struct stat *sb;
00783 {
00784     char    buf[MAXPATHLEN];
00785     register char *dc = buf;
00786 
00787     while ((*dc++ = *fn++) != '\0')
00788    continue;
00789 #ifdef NAMEI_BUG
00790     {
00791    int     st;
00792 
00793    st = stat(buf, sb);
00794    if (*buf)
00795        dc--;
00796    return (*--dc == '/' && !S_ISDIR(sb->st_mode) ? -1 : st);
00797     }
00798 #else
00799     return (stat(buf, sb));
00800 #endif 
00801 }
00802 
00803 static Char *
00804 Strchr(str, ch)
00805     Char *str;
00806     int ch;
00807 {
00808     do
00809    if (*str == ch)
00810        return (str);
00811     while (*str++);
00812     return (NULL);
00813 }
00814 
00815 #ifdef DEBUG
00816 static void
00817 qprintf(s)
00818 Char *s;
00819 {
00820     Char *p;
00821 
00822     for (p = s; *p; p++)
00823    printf("%c", *p & 0xff);
00824     printf("\n");
00825     for (p = s; *p; p++)
00826    printf("%c", *p & M_PROTECT ? '"' : ' ');
00827     printf("\n");
00828     for (p = s; *p; p++)
00829    printf("%c", *p & M_META ? '_' : ' ');
00830     printf("\n");
00831 }
00832 #endif 
00833 
00834 static int
00835 compare(p, q)
00836     const ptr_t  p, q;
00837 {
00838 #if defined(NLS) && !defined(NOSTRCOLL)
00839     errno = 0;  
00840 
00841     return (strcoll(*(char **) p, *(char **) q));
00842 #else
00843     return (strcmp(*(char **) p, *(char **) q));
00844 #endif 
00845 }
00846 
00847 
00848 
00849 
00850 
00851 
00852 
00853 
00854 int
00855 glob(pattern, flags, errfunc, pglob)
00856     const char *pattern;
00857     int     flags;
00858     int     (*errfunc) __P((char *, int));
00859     glob_t *pglob;
00860 {
00861     int     err, oldpathc;
00862     Char *bufnext, *bufend, *compilebuf, m_not;
00863     const unsigned char *compilepat, *patnext;
00864     int     c, not;
00865     Char patbuf[MAXPATHLEN + 1], *qpatnext;
00866     int     no_match;
00867 
00868     patnext = (unsigned char *) pattern;
00869     if (!(flags & GLOB_APPEND)) {
00870    pglob->gl_pathc = 0;
00871    pglob->gl_pathv = NULL;
00872    if (!(flags & GLOB_DOOFFS))
00873        pglob->gl_offs = 0;
00874     }
00875     pglob->gl_flags = flags & ~GLOB_MAGCHAR;
00876     pglob->gl_errfunc = errfunc;
00877     oldpathc = pglob->gl_pathc;
00878     pglob->gl_matchc = 0;
00879 
00880     if (pglob->gl_flags & GLOB_ALTNOT) {
00881    not = ALTNOT;
00882    m_not = M_ALTNOT;
00883     }
00884     else {
00885    not = NOT;
00886    m_not = M_NOT;
00887     }
00888 
00889     bufnext = patbuf;
00890     bufend = bufnext + MAXPATHLEN;
00891     compilebuf = bufnext;
00892     compilepat = patnext;
00893 
00894     no_match = *patnext == not;
00895     if (no_match)
00896    patnext++;
00897 
00898     if (flags & GLOB_QUOTE) {
00899    
00900    while (bufnext < bufend && (c = *patnext++) != EOS)
00901        if (c == QUOTE) {
00902       if ((c = *patnext++) == EOS) {
00903           c = QUOTE;
00904           --patnext;
00905       }
00906       *bufnext++ = (Char) (c | M_PROTECT);
00907        }
00908        else
00909       *bufnext++ = (Char) c;
00910     }
00911     else
00912    while (bufnext < bufend && (c = *patnext++) != EOS)
00913        *bufnext++ = (Char) c;
00914     *bufnext = EOS;
00915 
00916     bufnext = patbuf;
00917     qpatnext = patbuf;
00918     
00919     while ((c = *qpatnext++) != EOS) {
00920    switch (c) {
00921    case LBRACKET:
00922        c = *qpatnext;
00923        if (c == not)
00924       ++qpatnext;
00925        if (*qpatnext == EOS ||
00926       Strchr(qpatnext + 1, RBRACKET) == NULL) {
00927       *bufnext++ = LBRACKET;
00928       if (c == not)
00929           --qpatnext;
00930       break;
00931        }
00932        pglob->gl_flags |= GLOB_MAGCHAR;
00933        *bufnext++ = M_SET;
00934        if (c == not)
00935       *bufnext++ = m_not;
00936        c = *qpatnext++;
00937        do {
00938       *bufnext++ = CHAR(c);
00939       if (*qpatnext == RANGE &&
00940           (c = qpatnext[1]) != RBRACKET) {
00941           *bufnext++ = M_RNG;
00942           *bufnext++ = CHAR(c);
00943           qpatnext += 2;
00944       }
00945        } while ((c = *qpatnext++) != RBRACKET);
00946        *bufnext++ = M_END;
00947        break;
00948    case QUESTION:
00949        pglob->gl_flags |= GLOB_MAGCHAR;
00950        *bufnext++ = M_ONE;
00951        break;
00952    case STAR:
00953        pglob->gl_flags |= GLOB_MAGCHAR;
00954        
00955 
00956 
00957        if (bufnext == patbuf || bufnext[-1] != M_ALL)
00958       *bufnext++ = M_ALL;
00959        break;
00960    default:
00961        *bufnext++ = CHAR(c);
00962        break;
00963    }
00964     }
00965     *bufnext = EOS;
00966 #ifdef DEBUG
00967     qprintf(patbuf);
00968 #endif
00969 
00970     if ((err = glob1(patbuf, pglob, no_match)) != 0)
00971    return (err);
00972 
00973     
00974 
00975 
00976 
00977 
00978 
00979     if (pglob->gl_pathc == oldpathc &&
00980    ((flags & GLOB_NOCHECK) ||
00981     ((flags & GLOB_NOMAGIC) && !(pglob->gl_flags & GLOB_MAGCHAR)))) {
00982    if (!(flags & GLOB_QUOTE)) {
00983        Char *dp = compilebuf;
00984        const unsigned char *sp = compilepat;
00985 
00986        while ((*dp++ = *sp++) != '\0')
00987       continue;
00988    }
00989    else {
00990        
00991 
00992 
00993 
00994        while (*compilepat != EOS) {
00995       if (*compilepat == QUOTE) {
00996           if (*++compilepat == EOS)
00997          --compilepat;
00998       }
00999       *compilebuf++ = (unsigned char) *compilepat++;
01000        }
01001        *compilebuf = EOS;
01002    }
01003    return (globextend(patbuf, pglob));
01004     }
01005     else if (!(flags & GLOB_NOSORT))
01006    qsort((char *) (pglob->gl_pathv + pglob->gl_offs + oldpathc),
01007          pglob->gl_pathc - oldpathc, sizeof(char *),
01008          (int (*) __P((const void *, const void *))) compare);
01009     return (0);
01010 }
01011 
01012 static int
01013 glob1(pattern, pglob, no_match)
01014     Char *pattern;
01015     glob_t *pglob;
01016     int     no_match;
01017 {
01018     Char pathbuf[MAXPATHLEN + 1];
01019 
01020     
01021 
01022 
01023     if (*pattern == EOS)
01024    return (0);
01025     return (glob2(pathbuf, pathbuf, pattern, pglob, no_match));
01026 }
01027 
01028 
01029 
01030 
01031 
01032 
01033 static int
01034 glob2(pathbuf, pathend, pattern, pglob, no_match)
01035     Char *pathbuf, *pathend, *pattern;
01036     glob_t *pglob;
01037     int     no_match;
01038 {
01039     struct stat sbuf;
01040     int anymeta;
01041     Char *p, *q;
01042 
01043     
01044 
01045 
01046 
01047     anymeta = 0;
01048     for (;;) {
01049    if (*pattern == EOS) {   
01050        *pathend = EOS;
01051 
01052        if (Lstat(pathbuf, &sbuf))
01053       return (0);
01054 
01055        if (((pglob->gl_flags & GLOB_MARK) &&
01056        pathend[-1] != SEP) &&
01057       (S_ISDIR(sbuf.st_mode)
01058 #ifdef S_IFLNK
01059        || (S_ISLNK(sbuf.st_mode) &&
01060            (Stat(pathbuf, &sbuf) == 0) &&
01061            S_ISDIR(sbuf.st_mode))
01062 #endif
01063        )) {
01064       *pathend++ = SEP;
01065       *pathend = EOS;
01066        }
01067        ++pglob->gl_matchc;
01068        return (globextend(pathbuf, pglob));
01069    }
01070 
01071    
01072    q = pathend;
01073    p = pattern;
01074    while (*p != EOS && *p != SEP) {
01075        if (ismeta(*p))
01076       anymeta = 1;
01077        *q++ = *p++;
01078    }
01079 
01080    if (!anymeta) {      
01081        pathend = q;
01082        pattern = p;
01083        while (*pattern == SEP)
01084       *pathend++ = *pattern++;
01085    }
01086    else         
01087        return (glob3(pathbuf, pathend, pattern, p, pglob, no_match));
01088     }
01089     
01090 }
01091 
01092 
01093 static int
01094 glob3(pathbuf, pathend, pattern, restpattern, pglob, no_match)
01095     Char *pathbuf, *pathend, *pattern, *restpattern;
01096     glob_t *pglob;
01097     int     no_match;
01098 {
01099     extern int errno;
01100     DIR    *dirp;
01101     struct dirent *dp;
01102     int     err;
01103     Char m_not = (pglob->gl_flags & GLOB_ALTNOT) ? M_ALTNOT : M_NOT;
01104     char cpathbuf[MAXPATHLEN], *ptr;
01105 #ifdef SOLARIS_DIRENT_PATCH
01106     
01107     char dname[255];
01108     int ii;
01109 #endif
01110 
01111     *pathend = EOS;
01112     errno = 0;
01113 
01114     if (!(dirp = Opendir(pathbuf))) {
01115    
01116    for (ptr = cpathbuf; (*ptr++ = (char) *pathbuf++) != EOS;)
01117        continue;
01118    if ((pglob->gl_errfunc && (*pglob->gl_errfunc) (cpathbuf, errno)) ||
01119        (pglob->gl_flags & GLOB_ERR))
01120        return (GLOB_ABEND);
01121    else
01122        return (0);
01123     }
01124 
01125     err = 0;
01126 
01127     
01128     while ((dp = readdir(dirp)) != NULL) {
01129    register unsigned char *sc;
01130    register Char *dc;
01131 
01132 #ifdef SOLARIS_DIRENT_PATCH
01133    
01134 
01135 
01136 
01137 #ifndef SOLARIS_DIRENT_ZERO
01138    for (ii = -2 ; dp->d_name[ii] != '\0' ; ++ii) {
01139      dname[ii+2] = dp->d_name[ii];
01140    }
01141         dname[ii+2] = '\0';
01142 #else
01143         strcpy(dname, dp->d_name); 
01144 #endif
01145    
01146 
01147 
01148 
01149 
01150    
01151    if (dname[0] == DOT && *pattern != DOT)
01152        continue;
01153    for (sc = (unsigned char *) dname, dc = pathend;
01154 #else
01155    if (dp->d_name[0] == DOT && *pattern != DOT)
01156        continue;
01157    for (sc = (unsigned char *) dp->d_name, dc = pathend;
01158 #endif
01159         (*dc++ = *sc++) != '\0';)
01160        continue;
01161    if (match(pathend, pattern, restpattern, (int) m_not) == no_match) {
01162        *pathend = EOS;
01163        continue;
01164    }
01165    err = glob2(pathbuf, --dc, restpattern, pglob, no_match);
01166    if (err)
01167        break;
01168     }
01169     
01170     (void) closedir(dirp);
01171     return (err);
01172 }
01173 
01174 
01175 
01176 
01177 
01178 
01179 
01180 
01181 
01182 
01183 
01184 
01185 
01186 
01187 
01188 
01189 static int
01190 globextend(path, pglob)
01191     Char *path;
01192     glob_t *pglob;
01193 {
01194     register char **pathv;
01195     register int i;
01196     unsigned int newsize;
01197     char   *copy;
01198     Char *p;
01199 
01200     newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
01201     pathv = (char **) (pglob->gl_pathv ?
01202              xrealloc((ptr_t) pglob->gl_pathv, (size_t) newsize) :
01203              xmalloc((size_t) newsize));
01204     if (pathv == NULL)
01205    return (GLOB_NOSPACE);
01206 
01207     if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
01208    
01209    pathv += pglob->gl_offs;
01210    for (i = pglob->gl_offs; --i >= 0;)
01211        *--pathv = NULL;
01212     }
01213     pglob->gl_pathv = pathv;
01214 
01215     for (p = path; *p++;)
01216    continue;
01217     if ((copy = (char *) xmalloc((size_t) (p - path))) != NULL) {
01218    register char *dc = copy;
01219    register Char *sc = path;
01220 
01221    while ((*dc++ = *sc++) != '\0')
01222        continue;
01223    pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
01224     }
01225     pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
01226     return ((copy == NULL) ? GLOB_NOSPACE : 0);
01227 }
01228 
01229 
01230 
01231 
01232 
01233 
01234 static  int
01235 match(name, pat, patend, m_not)
01236     register Char *name, *pat, *patend;
01237     int m_not;
01238 {
01239     int ok, negate_range;
01240     Char c, k;
01241 
01242     while (pat < patend) {
01243    c = *pat++;
01244    switch (c & M_MASK) {
01245    case M_ALL:
01246        if (pat == patend)
01247       return (1);
01248        do
01249       if (match(name, pat, patend, m_not))
01250           return (1);
01251        while (*name++ != EOS);
01252        return (0);
01253    case M_ONE:
01254        if (*name++ == EOS)
01255       return (0);
01256        break;
01257    case M_SET:
01258        ok = 0;
01259        if ((k = *name++) == EOS)
01260       return (0);
01261        if ((negate_range = ((*pat & M_MASK) == m_not)) != 0)
01262       ++pat;
01263        while (((c = *pat++) & M_MASK) != M_END) {
01264       if ((*pat & M_MASK) == M_RNG) {
01265           if (c <= k && k <= pat[1])
01266          ok = 1;
01267           pat += 2;
01268       }
01269       else if (c == k)
01270           ok = 1;
01271        }
01272        if (ok == negate_range)
01273       return (0);
01274        break;
01275    default:
01276        k = *name++;
01277        if (k != c)
01278       return (0);
01279        break;
01280    }
01281     }
01282     return (*name == EOS);
01283 }
01284 
01285 
01286 void
01287 globfree(pglob)
01288     glob_t *pglob;
01289 {
01290     register int i;
01291     register char **pp;
01292 
01293     if (pglob->gl_pathv != NULL) {
01294    pp = pglob->gl_pathv + pglob->gl_offs;
01295    for (i = pglob->gl_pathc; i--; ++pp)
01296        if (*pp)
01297       xfree((ptr_t) *pp), *pp = NULL;
01298    xfree((ptr_t) pglob->gl_pathv), pglob->gl_pathv = NULL;
01299     }
01300 }
01301 
01302 static int warn = 0 ;
01303 void MCW_warn_expand( int www ){ warn = www; return; }
01304 
01305 
01306 
01307 
01308 
01309 
01310 
01311 
01312 
01313 
01314 void NIH_glob( char *fn , int *nout , char ***fout )
01315 {
01316    MCW_file_expand( 1 , &fn , nout , fout ) ;
01317 }
01318 
01319 void NIH_glob_free( int gnum , char **gout )
01320 {
01321    MCW_free_expand( gnum , gout ) ;
01322 }
01323 
01324 
01325 
01326 void MCW_file_expand( int nin , char ** fin , int * nout , char *** fout )
01327 {
01328    glob_t gl ;
01329    int    ii , gnum, gold , ilen ;
01330    char ** gout ;
01331    char *  fn ;
01332    char prefix[4] , fpre[128] , fname[256] ;
01333    int  b1,b2,b3,b4,b5 , ib,ig , lpre ;
01334 
01335    if( nin <= 0 ){ *nout = 0 ; return ; }
01336 
01337    gnum = 0 ;
01338    gout = NULL ;
01339 
01340    for( ii=0 ; ii < nin ; ii++ ){
01341       fn = fin[ii] ;
01342 
01343       ig = 0 ;
01344 
01345 
01346 
01347       if( strlen(fn) > 9 && fn[0] == '3' && fn[1] == 'D' ){
01348          ib = 0 ;
01349          prefix[ib++] = '3' ;
01350          prefix[ib++] = 'D' ;
01351          if( fn[2] == ':' ){ prefix[ib++] = '\0' ; }
01352          else              { prefix[ib++] = fn[2] ; prefix[ib++] = '\0' ; }
01353 
01354          ig = sscanf( fn+ib , "%d:%d:%d:%d:%d:%s" ,     
01355                       &b1,&b2,&b3,&b4,&b5 , fname ) ;   
01356 
01357 
01358 
01359          if( ig == 6 ){
01360             sprintf(fpre , "%s:%d:%d:%d:%d:%d:" , prefix,b1,b2,b3,b4,b5) ;
01361             lpre = strlen(fpre) ;
01362          } else {
01363             ig = 0 ;
01364          }
01365       }
01366 
01367       if( strlen(fn) > 9 && fn[0] == '3' && fn[1] == 'A' && fn[3] == ':' ){
01368          ib = 0 ;
01369          prefix[ib++] = '3' ;
01370          prefix[ib++] = 'A' ;
01371          prefix[ib++] = fn[2] ;
01372          prefix[ib++] = '\0' ;
01373 
01374          ig = sscanf( fn+ib , "%d:%d:%d:%s" ,  
01375                       &b1,&b2,&b3, fname ) ;   
01376 
01377 
01378 
01379          if( ig == 4 ){
01380             sprintf(fpre , "%s:%d:%d:%d:" , prefix,b1,b2,b3) ;
01381             lpre = strlen(fpre) ;
01382          } else {
01383             ig = 0 ;
01384          }
01385       }
01386 
01387       if( ig > 0 ) (void) glob( fname , 0 , NULL ,  &gl ) ;  
01388       else         (void) glob( fn    , 0 , NULL ,  &gl ) ;  
01389 
01390 
01391 
01392       if( gl.gl_pathc > 0 ){
01393 
01394 
01395          gold  = gnum ;
01396          gnum += gl.gl_pathc ;
01397          if( gout == NULL ) gout = (char **) malloc (      sizeof(char *)*gnum);
01398          else               gout = (char **) realloc(gout, sizeof(char *)*gnum);
01399 
01400          for( ib=0 ; ib < gl.gl_pathc ; ib++ ){
01401             ilen = strlen( gl.gl_pathv[ib] ) + 1 ;  
01402             if( ig > 0 ) ilen += lpre ;             
01403 
01404             gout[ib+gold] = (char *) malloc( sizeof(char) * ilen ) ; 
01405 
01406             if( ig > 0 ){
01407                strcpy( gout[ib+gold] , fpre ) ;             
01408                strcat( gout[ib+gold] , gl.gl_pathv[ib] ) ;  
01409             }
01410             else {
01411                strcpy( gout[ib+gold] , gl.gl_pathv[ib] ) ;  
01412             }
01413          }
01414 
01415       } else if( ig == 6 && strcmp(fname,"ALLZERO") == 0 ){ 
01416 
01417          gold = gnum ; gnum++ ;
01418          if( gout == NULL ) gout = (char **) malloc (      sizeof(char *)*gnum);
01419          else               gout = (char **) realloc(gout, sizeof(char *)*gnum);
01420 
01421          ilen = lpre + strlen(fname) + 1 ;
01422          gout[gold] = (char *) malloc( sizeof(char) * ilen ) ; 
01423          strcpy( gout[gold] , fpre ) ;
01424          strcat( gout[gold] , fname ) ;
01425 
01426       } else {  
01427 
01428          if( warn )  
01429            fprintf(stderr,"** Can't find file %s\n", (ig>0) ? fname : fn ) ;
01430       }
01431 
01432       globfree( &gl ) ;
01433    }
01434 
01435    *nout = gnum ; *fout = gout ; return ;
01436 }
01437 
01438 void MCW_free_expand( int gnum , char ** gout )
01439 {
01440    int ii ;
01441 
01442    if( gout == NULL ) return ;
01443 
01444    for( ii=0 ; ii < gnum ; ii++ ) free( gout[ii] ) ;
01445    free( gout ) ;
01446    return ;
01447 }
01448 
01449 
01450 
01451 
01452 
01453 
01454 static void swap_4(void *ppp)
01455 {
01456    unsigned char *pntr = (unsigned char *) ppp ;
01457    unsigned char b0, b1, b2, b3;
01458 
01459    b0 = *pntr; b1 = *(pntr+1); b2 = *(pntr+2); b3 = *(pntr+3);
01460    *pntr = b3; *(pntr+1) = b2; *(pntr+2) = b1; *(pntr+3) = b0;
01461 }
01462 
01463 
01464 
01465 static void swap_8(void *ppp)
01466 {
01467    unsigned char *pntr = (unsigned char *) ppp ;
01468    unsigned char b0, b1, b2, b3;
01469    unsigned char b4, b5, b6, b7;
01470 
01471    b0 = *pntr    ; b1 = *(pntr+1); b2 = *(pntr+2); b3 = *(pntr+3);
01472    b4 = *(pntr+4); b5 = *(pntr+5); b6 = *(pntr+6); b7 = *(pntr+7);
01473 
01474    *pntr     = b7; *(pntr+1) = b6; *(pntr+2) = b5; *(pntr+3) = b4;
01475    *(pntr+4) = b3; *(pntr+5) = b2; *(pntr+6) = b1; *(pntr+7) = b0;
01476 }
01477 
01478 
01479 
01480 static void swap_2(void *ppp)
01481 {
01482    unsigned char *pntr = (unsigned char *) ppp ;
01483    unsigned char b0, b1;
01484 
01485    b0 = *pntr; b1 = *(pntr+1);
01486    *pntr = b1; *(pntr+1) = b0;
01487 }
01488 
01489 
01490 
01491 
01492 void ge_header( char *pathname , ge_header_info *hi )
01493 {
01494    FILE *imfile ;
01495    int  length , skip , swap=0 , gg ;
01496    char orients[8] , str[8] ;
01497    int nx , ny , bpp , cflag , hdroff , stamp=0 , iarg=1 ;
01498    float uv17 = -1.0;
01499    
01500    if( hi == NULL ) return ;            
01501    hi->good = 0 ;                       
01502    if( pathname    == NULL ||
01503        pathname[0] == '\0'   ) return ; 
01504 
01505    length = THD_filesize( pathname ) ;
01506    if( length < 1024 ) return ;         
01507 
01508    imfile = fopen( pathname , "r" ) ;
01509    if( imfile == NULL ) return ;        
01510 
01511    strcpy(str,"JUNK") ;     
01512    fread(str,1,4,imfile) ;  
01513 
01514    if( str[0]!='I' || str[1]!='M' || str[2]!='G' || str[3]!='F' ){ 
01515       fclose(imfile) ; return ;
01516    }
01517 
01518    
01519 
01520    fread( &skip , 4,1, imfile ) ; 
01521    fread( &nx   , 4,1, imfile ) ; 
01522    fread( &ny   , 4,1, imfile ) ; 
01523    fread( &bpp  , 4,1, imfile ) ; 
01524    fread( &cflag, 4,1, imfile ) ; 
01525 
01526    
01527 
01528    if( nx < 0 || nx > 8192 ){      
01529      swap = 1 ;                    
01530      swap_4(&skip); swap_4(&nx); swap_4(&ny); swap_4(&bpp); swap_4(&cflag);
01531    } else {
01532      swap = 0 ;  
01533    }
01534    if( nx < 0 || nx > 8192 || ny < 0 || ny > 8192 ){  
01535       fclose(imfile) ; return ;
01536    }
01537 
01538    hi->nx = nx ;
01539    hi->ny = ny ;
01540 
01541    if( skip+2*nx*ny >  length ||               
01542        skip         <= 0      ||               
01543        cflag        != 1      ||               
01544        bpp          != 16        ) return ;    
01545 
01546    
01547 
01548    fseek( imfile , 148L , SEEK_SET ) ; 
01549    fread( &hdroff , 4,1 , imfile ) ;   
01550    if( swap ) swap_4(&hdroff) ;
01551 
01552    if( hdroff > 0 && hdroff+256 < length ){   
01553        float dx,dy,dz, xyz[9], zz, tr ; int itr, ii,jj,kk ;
01554 
01555        
01556 
01557        fseek( imfile , hdroff+26 , SEEK_SET ) ;    
01558        fread( &dz , 4,1 , imfile ) ;
01559 
01560        fseek( imfile , hdroff+50 , SEEK_SET ) ;    
01561        fread( &dx , 4,1 , imfile ) ;
01562        fread( &dy , 4,1 , imfile ) ;
01563 
01564        if( swap ){ swap_4(&dx); swap_4(&dy); swap_4(&dz); }
01565 
01566        hi->dx = dx ; hi->dy = dy ; hi->dz = dz ;
01567 
01568        
01569        
01570        
01571        
01572        
01573 
01574        fseek( imfile , hdroff+154 , SEEK_SET ) ;  
01575        fread( xyz , 4,9 , imfile ) ;
01576        if( swap ){
01577           swap_4(xyz+0); swap_4(xyz+1); swap_4(xyz+2);
01578           swap_4(xyz+3); swap_4(xyz+4); swap_4(xyz+5);
01579           swap_4(xyz+6); swap_4(xyz+7); swap_4(xyz+8);
01580        }
01581 
01582        
01583        
01584        
01585        
01586 
01587        dx = fabs(xyz[3]-xyz[0]) ; ii = 1 ;
01588        dy = fabs(xyz[4]-xyz[1]) ; if( dy > dx ){ ii=2; dx=dy; }
01589        dz = fabs(xyz[5]-xyz[2]) ; if( dz > dx ){ ii=3;        }
01590        dx = xyz[ii+2]-xyz[ii-1] ; if( dx < 0. ){ ii = -ii;    }
01591        switch( ii ){
01592         case  1: orients[0]= 'L'; orients[1]= 'R'; break; 
01593         case -1: orients[0]= 'R'; orients[1]= 'L'; break; 
01594         case  2: orients[0]= 'P'; orients[1]= 'A'; break; 
01595         case -2: orients[0]= 'A'; orients[1]= 'P'; break; 
01596         case  3: orients[0]= 'I'; orients[1]= 'S'; break; 
01597         case -3: orients[0]= 'S'; orients[1]= 'I'; break; 
01598         default: orients[0]='\0'; orients[1]='\0'; break; 
01599        }
01600 
01601        
01602        
01603        
01604        
01605 
01606        dx = fabs(xyz[6]-xyz[3]) ; jj = 1 ;
01607        dy = fabs(xyz[7]-xyz[4]) ; if( dy > dx ){ jj=2; dx=dy; }
01608        dz = fabs(xyz[8]-xyz[5]) ; if( dz > dx ){ jj=3;        }
01609        dx = xyz[jj+5]-xyz[jj+2] ; if( dx < 0. ){ jj = -jj;    }
01610        switch( jj ){
01611          case  1: orients[2] = 'L'; orients[3] = 'R'; break;
01612          case -1: orients[2] = 'R'; orients[3] = 'L'; break;
01613          case  2: orients[2] = 'P'; orients[3] = 'A'; break;
01614          case -2: orients[2] = 'A'; orients[3] = 'P'; break;
01615          case  3: orients[2] = 'I'; orients[3] = 'S'; break;
01616          case -3: orients[2] = 'S'; orients[3] = 'I'; break;
01617          default: orients[2] ='\0'; orients[3] ='\0'; break;
01618        }
01619 
01620        orients[4] = '\0' ;   
01621 
01622        kk = 6 - abs(ii)-abs(jj) ;   
01623                                     
01624                                     
01625 
01626        zz = xyz[kk-1] ;             
01627 
01628        hi->zoff = zz ;
01629        strcpy(hi->orients,orients) ;
01630 
01631        
01632 
01633        fseek( imfile , hdroff+194 , SEEK_SET ) ;
01634        fread( &itr , 4,1 , imfile ) ; 
01635        if( swap ) swap_4(&itr) ;
01636        hi->tr = 1.0e-6 * itr ;        
01637 
01638        
01639 
01640        fseek( imfile , hdroff+202 , SEEK_SET ) ;
01641        fread( &itr , 4,1 , imfile ) ; 
01642        if( swap ) swap_4(&itr) ;
01643        hi->te = 1.0e-6 * itr ;
01644 
01645        
01646          
01647       
01648       fseek ( imfile , hdroff+272+202, SEEK_SET ) ;
01649       fread( &uv17 , 4, 1 , imfile ) ;
01650       if( swap ) swap_4(&uv17) ;
01651       
01652       hi->uv17 = (int)uv17; 
01653       
01654       
01655        hi->good = 1 ;                 
01656 
01657    } 
01658 
01659    fclose(imfile) ; return ;
01660 }