1 /*****************************************************************************
2    Major portions of this software are copyrighted by the Medical College
3    of Wisconsin, 1994-2000, and are released under the Gnu General Public
4    License, Version 2.  See the file README.Copyright for details.
5 ******************************************************************************/
6 
7 #include "mrilib.h"
8 
9 extern int SUMA_IcoNums(int depth, byte bin, char what) ;
10 
11 static void AFNI_prefilter_inclusions( int * , char *** ) ; /* 13 Dec 2021 */
12 
13 #undef DEBUG_ME
14 
15 /*------------------------------------------------------------------------
16    Read an entire file into a character string.  When you are
17    done with the returned string, free() it.  If the string pointer
18    is returned as NULL, something bad happened, and you are doomed.
19 --------------------------------------------------------------------------*/
20 
21 static int nsuck = 0 ;
AFNI_suck_file_len(void)22 int AFNI_suck_file_len(void){ return nsuck; }  /* 27 Feb 2009 */
23 
24 #undef  DBUF
25 #define DBUF 8192       /* how many bytes per fifo read */
26 
27 #undef  MAXBUF
28 #define MAXBUF 8388608  /* 8 Mbytes */
29 
30 /** read from a 'file' whose size cannot be predetermined [27 Aug 2019] **/
31 
AFNI_suck_fifo(char * fname)32 char * AFNI_suck_fifo( char *fname )
33 {
34    int fd , ii , nbuf ;
35    char *buf ;
36 
37 ENTRY("AFNI_suck_fifo") ;
38    nsuck = 0 ;
39    if( fname == NULL || fname[0] == '\0' ) RETURN(NULL);
40 
41    fd = open( fname , O_RDONLY ) ; /* blocking reads */
42    if( fd < 0 ) RETURN(NULL) ;
43 
44    nbuf = 0 ;
45    buf  = (char *)malloc( sizeof(char) * (DBUF+4) ) ;
46 
47    while( nbuf < MAXBUF ){
48      ii = read( fd , buf+nbuf , DBUF ) ;      /* try to read up to DBUF bytes */
49      if( ii <= 0 ) break ;                                     /* read failed */
50      nbuf += ii ;                        /* add in how many bytes we now have */
51      buf = (char *)realloc( buf, sizeof(char)*(nbuf+DBUF+4) ) ; /* resize buf */
52    }
53 
54    close(fd) ;
55    buf = (char *)realloc( buf , sizeof(char)*(nbuf+4) ) ;
56    buf[nbuf] = '\0' ; /* terminate string */
57    nsuck = nbuf ;
58    RETURN(buf) ;
59 }
60 
61 /** read from a file whose size can be found out directly **/
62 
AFNI_suck_file(char * fname)63 char * AFNI_suck_file( char *fname )
64 {
65    int len , fd , ii ;
66    char *buf ;
67 
68 ENTRY("AFNI_suck_file") ;
69    nsuck = 0 ;
70    if( fname == NULL || fname[0] == '\0' ) RETURN(NULL);
71 
72    if( THD_is_fifo(fname) ){
73      buf = AFNI_suck_fifo(fname) ; RETURN(buf) ;
74    }
75 
76    len = THD_filesize( fname ) ;
77    if( len <= 0 ) RETURN(NULL) ;
78 
79    fd = open( fname , O_RDONLY ) ;
80    if( fd < 0 ) RETURN(NULL) ;
81 
82    buf = (char *) malloc( sizeof(char) * (len+4) ) ;
83    ii  = read( fd , buf , len ) ;
84    close( fd ) ;
85    if( ii <= 0 ){ free(buf); RETURN(NULL); }
86 
87    buf[len] = '\0' ;  /* 27 July 1998: 'len' used to be 'ii+1', which is bad */
88    nsuck = len ; RETURN(buf) ;
89 }
90 
91 /*-----------------------------------------------------------------------
92    Read environment section only from an AFNI setup file.
93    [See also afni_setup.c]
94 -------------------------------------------------------------------------*/
95 
96 #define ISTARRED(s) ( (s)[0]=='*' && (s)[1]=='*' && (s)[2]=='*' )
97 
98 #define EOLSKIP                                                          \
99   do{ for( ; fptr[0] != '\n' && fptr[0] != '\0' ; fptr++ ) ; /* nada */  \
100       if( fptr[0] == '\0' ) goto Done ;                                  \
101       fptr++ ; } while(0)
102 
103 #define GETSSS                                                            \
104   do{ int nu=0,qq;                                                        \
105       if( fptr-fbuf >= nbuf || fptr[0] == '\0' ) goto Done ;              \
106       str[0]='\0'; qq=sscanf(fptr,"%127s%n",str,&nu); nused+=nu;fptr+=nu; \
107       if( str[0]=='\0' || qq==0 || nu==0 ) goto Done ;                    \
108     } while(0)
109 
110 #define GETSTR                                                            \
111   do{ GETSSS ;                                                            \
112       while(str[0]=='!' || (str[0]=='/' && str[1]=='/') ||                \
113             (str[0]=='#' && str[1]=='\0') ){EOLSKIP; GETSSS;}             \
114     } while(0)
115 
116 #define GETEQN                                      \
117   do{ GETSTR ; if(ISTARRED(str)) goto SkipSection ; \
118       strcpy(left,str) ;                            \
119       GETSTR ; if(ISTARRED(str)) goto SkipSection ; \
120       strcpy(middle,str) ;                          \
121       GETSTR ; if(ISTARRED(str)) goto SkipSection ; \
122       strcpy(right,str) ; } while(0)
123 
124 #undef  NSBUF
125 #define NSBUF 256
126 
127 static int afni_env_done = 0 ;
128 
129 /*---------------------------------------------------------------------------*/
130 
AFNI_mark_environ_done(void)131 void AFNI_mark_environ_done(void)   { afni_env_done = 1 ; return ; }
AFNI_mark_environ_undone(void)132 void AFNI_mark_environ_undone(void) { afni_env_done = 0 ; return ; }
AFNI_check_environ_done(void)133 int  AFNI_check_environ_done(void)  { return afni_env_done ; }
134 
135 /*---------------------------------------------------------------------------*/
136 
137 static int bloced=0 ;
138 
my_getenv(char * ename)139 char * my_getenv( char *ename )
140 {
141    if( !bloced && !afni_env_done ){
142      char *sysenv = getenv("AFNI_SYSTEM_AFNIRC") ;       /* 16 Apr 2000 */
143      if( sysenv != NULL ) AFNI_process_environ(sysenv) ; /* 16 Apr 2000 */
144      AFNI_process_environ(NULL) ;
145    }
146    return getenv( ename ) ;
147 }
148 
149 /*---------------------------------------------------------------------------*/
150 
AFNI_process_environ(char * fname)151 int AFNI_process_environ( char *fname )
152 {
153    int   nbuf , nused , ii ;
154    char *fbuf , *fptr ;
155    char  str[NSBUF] , left[NSBUF] , middle[NSBUF] ,
156          right[NSBUF], fname_str[NSBUF] = {"not_set"};
157    int nenv=0 , senv=0 ; static int first=1 ;  /* 13 Mar 2008 */
158 
159 ENTRY("AFNI_process_environ") ;
160    bloced = 1 ;
161 
162    if( fname != NULL ){
163      strcpy(str,fname) ;
164    } else {
165      char *home ;
166      if( afni_env_done ) RETURN(nenv) ;
167      home = getenv("HOME") ;
168      if( home != NULL ){ strcpy(str,home) ; strcat(str,"/.afnirc") ; }
169      else              { strcpy(str,".afnirc") ; }
170      if( !THD_is_file(str) ){                      /* 19 Sep 2007 */
171        if( home != NULL ){ strcpy(str,home) ; strcat(str,"/AFNI.afnirc") ; }
172        else              { strcpy(str,"AFNI.afnirc") ; }
173      }
174      afni_env_done = 1 ;
175    }
176    strcpy(fname_str,str) ; /* ZSS: Nov. 25 08 */
177 
178    fbuf = AFNI_suck_file( str ) ;
179    if( fbuf == NULL ){ bloced=0; if(fname==NULL)afni_env_done=0; RETURN(nenv); }
180    nbuf = strlen(fbuf) ;
181    if( nbuf == 0    ){ bloced=0; if(fname==NULL)afni_env_done=0; RETURN(nenv); }
182 
183    fptr = fbuf ; nused = 0 ;
184 
185    /** scan for section strings, which start with "***" **/
186 
187    str[0] = '\0' ;  /* initialize string */
188 
189    while( nused < nbuf ){
190 
191       /**----------------------------------------**/
192       /**-- skip ahead to next section keyword --**/
193 
194       SkipSection: while( ! ISTARRED(str) ){ GETSTR; }
195 
196       /*- 04 Jun 1999 -*/
197 
198       if( strcmp(str,"***END") == 0 ) break ;  /* exit main loop */
199 
200       if( strcmp(str,"***ENVIRONMENT") != 0 ){ GETSTR ; goto SkipSection ; }
201 
202       /**---------------------------------------**/
203       /**-- ENVIRONMENT section [04 Jun 1999] --**/
204 
205       if( strcmp(str,"***ENVIRONMENT") == 0 ){ /* loop: find environment eqns */
206          char *enveqn , *eee; int nl , nr , allow_reset ;
207          senv = 1 ;
208 
209          eee = getenv("AFNI_ENVIRON_RESET") ; allow_reset = YESSISH(eee) ;
210 
211          while(1){                        /* loop, looking for 'name = value' */
212             GETEQN ;
213 
214             if( !THD_filename_pure(left) ) continue ;
215 
216             nl = strlen(left) ; nr = strlen(right) ;
217             enveqn = (char *) malloc(nl+nr+4) ;
218             strcpy(enveqn,left) ; strcat(enveqn,"=") ; strcat(enveqn,right) ;
219             if( !(eee = getenv(left)) || allow_reset ){  /* ZSS Nov 25 2008 */
220                putenv(enveqn) ;
221             } else if( !AFNI_noenv("AFNI_ENVIRON_WARNINGS") &&
222                         strcmp(right, eee)){
223                INFO_message(  "Environment variable %s already set to '%s'. "
224                               "Value of '%s' from %s is ignored. \n"
225                          "To kill such warnings Set AFNI_ENVIRON_WARNINGS to NO",
226                               left, eee, right, fname_str);
227             }
228             nenv++ ;
229          }
230 
231          continue ;  /* to end of outer while */
232       } /* end of ENVIRONMENT */
233 
234    }  /* end of while loop */
235 
236   Done:
237    if( fname == NULL && first ){
238      if( senv == 0 )
239        WARNING_message("didn't find '***ENVIRONMENT' line in ~/.afnirc") ;
240      else if( nenv == 0 )
241        WARNING_message("didn't find any environment equations in ~/.afnirc") ;
242    }
243 
244    first = 0 ; free(fbuf) ; bloced = 0 ; RETURN(nenv) ;
245 }
246 
247 /*-----------------------------------------------------------------*/
248 
AFNI_yesenv(char * ename)249 int AFNI_yesenv( char *ename )     /* 21 Jun 2000 */
250 {
251    char *ept ;
252    if( ename == NULL ) return 0 ;
253    ept = my_getenv(ename) ;
254    return YESSISH(ept) ;
255 }
256 
257 /*------------------------------------------------------------------*/
258 
AFNI_noenv(char * ename)259 int AFNI_noenv( char *ename )     /* 21 Jun 2000 */
260 {
261    char *ept ;
262    if( ename == NULL ) return 0 ;
263    ept = my_getenv(ename) ;
264    return NOISH(ept) ;
265 }
266 
267 /*------------------------------------------------------------------*/
268 
AFNI_numenv(char * ename)269 double AFNI_numenv( char *ename )  /* 23 Aug 2003 */
270 {
271    char *ept,*ccc ; double val ;
272    if( ename == NULL ) return 0.0 ;
273    ept = my_getenv(ename) ;
274    if( ept   == NULL ) return 0.0 ;
275    val = strtod(ept,&ccc) ;
276         if( *ccc == 'k' || *ccc == 'K' ) val *= 1024.0 ;
277    else if( *ccc == 'm' || *ccc == 'M' ) val *= 1024.0*1024.0 ;
278    else if( *ccc == 'g' || *ccc == 'G' ) val *= 1024.0*1024.0*1024.0 ;
279    return val ;
280 }
281 
282 /*------------------------------------------------------------------*/
283 
AFNI_numenv_def(char * ename,double dd)284 double AFNI_numenv_def( char *ename, double dd ) /* 18 Sep 2007 */
285 {
286    char *ept,*ccc ; double val=dd ;
287    if( ename == NULL ) return val ;
288    ept = my_getenv(ename) ;
289    if( ept   == NULL ) return val ;
290    val = strtod(ept,&ccc) ; if( ccc == ept ) val = dd ;
291    return val ;
292 }
293 
294 /*------------------------------------------------------------------*/
295 /*! Input is "name value".  Return is 0 if OK, -1 if not OK. */
296 
AFNI_setenv(char * cmd)297 int AFNI_setenv( char *cmd )
298 {
299    char nam[256]="\0" , val[1024]="\0" , eqn[1280] , *eee ;
300 
301    if( cmd == NULL || strlen(cmd) < 3 ) return(-1) ;
302 
303    sscanf( cmd , "%255s %1023s" , nam , val ) ;
304    if( (nam[0] == '\0' || val[0] == '\0') && strchr(cmd,'=') != NULL ){
305      char *ccc = strdup(cmd) ;
306      eee = strchr(ccc,'=') ; *eee = ' ' ;
307      sscanf( ccc , "%255s %1023s" , nam , val ) ;
308      free((void *)ccc) ;
309    }
310    if( nam[0] == '\0' || val[0] == '\0' ) return(-1) ;
311 
312    sprintf(eqn,"%s=%s",nam,val) ;
313    eee = strdup(eqn) ; putenv(eee) ;  /* note that eee is never free()-ed */
314 
315 #ifdef USE_TRACING  /* else DBG_trace is #defined to 0   2 Jan 2008 [rickr] */
316    if( strcmp(nam,"AFNI_DEBUG") == 0 ){  /* 29 Dec 2008 */
317      switch( val[0] ){
318        default:  DBG_trace = 0 ; break ;
319        case 'y': DBG_trace = 1 ; break ;
320        case 'Y': DBG_trace = 2 ; break ;
321      }
322    }
323 #endif
324 
325    return(0) ;
326 }
327 
328 /*-------------------------------------------------------------------------*/
get_gopt_help()329 char *get_gopt_help() {
330    static char GOPT_HELP[] = {
331 "   -overwrite: Overwrite existing output dataset.\n"
332 "               Equivalent to setting env. AFNI_DECONFLICT=OVERWRITE\n"
333 "   -ok_1D_text: Zero out uncommented text in 1D file.\n"
334 "                Equivalent to setting env. AFNI_1D_ZERO_TEXT=YES\n"
335 "   -Dname=val: Set environment variable 'name' to value 'val'\n"
336 "             For example: -DAFNI_1D_ZERO_TEXT=YES\n"
337 "   -Vname=: Print value of environment variable 'name' to stdout and quit.\n"
338 "            This is more reliable that the shell's env query because it would\n"
339 "            include envs set in .afnirc files and .sumarc files for SUMA\n"
340 "            programs.\n"
341 "             For example: -VAFNI_1D_ZERO_TEXT=\n"
342 "   -skip_afnirc: Do not read the afni resource (like ~/.afnirc) file.\n"
343 "   -pad_to_node NODE: Output a full dset from node 0 to MAX_NODE-1\n"
344 "                   ** Instead of directly setting NODE to an integer you \n"
345 "                      can set NODE to something like:\n"
346 "                   ld120 (or rd17) which sets NODE to be the maximum \n"
347 "                      node index on an Icosahedron with -ld 120. See \n"
348 "                      CreateIcosahedron for details.\n"
349 "                   d:DSET.niml.dset which sets NODE to the maximum node found\n"
350 "                      in dataset DSET.niml.dset.\n"
351 "                   ** This option is for surface-based datasets only.\n"
352 "                      Some programs may not heed it, so check the output if\n"
353 "                      you are not sure.\n"
354 "   -pif SOMETHING: Does absolutely nothing but provide for a convenient\n"
355 "                   way to tag a process and find it in the output of ps -a\n"
356 "   -echo_edu: Echos the entire command line to stdout (without -echo_edu)\n"
357 "              for edification purposes\n"
358 "\n"
359 "   SPECIAL PURPOSE ARGUMENTS TO ADD *MORE* ARGUMENTS TO THE COMMAND LINE\n"
360 "------------------------------------------------------------------------\n"
361 "   Arguments of the following form can be used to create MORE command\n"
362 "   line arguments -- the principal reason for using these type of arguments\n"
363 "   is to create program command lines that are beyond the limit of\n"
364 "   practicable scripting. (For one thing, Unix command lines have an\n"
365 "   upper limit on their length.) This type of expanding argument makes\n"
366 "   it possible to input thousands of files into an AFNI program command line.\n"
367 "\n"
368 "   The generic form of these arguments is (quotes, 'single' or \"double\",\n"
369 "   are required for this type of argument):\n"
370 "     '<<XY list'\n"
371 "   where X = I for Include (include strings from file)\n"
372 "      or X = G for Glob (wildcard expansion)\n"
373 "   where Y = M for Multi-string (create multiple arguments from multiple strings)\n"
374 "      or Y = 1 for One-string   (all strings created are put into one argument)\n"
375 "\n"
376 "   Following the XY modifiers, a list of strings is given, separated by spaces.\n"
377 "   * For X=I, each string in the list is a filename to be read in and\n"
378 "       included on the command line.\n"
379 "   * For X=G, each string in the list is a Unix style filename wildcard\n"
380 "       expression to be expanded and the resulting filenames included\n"
381 "       on the command line.\n"
382 "   In each case, the '<<XY list' command line argument will be removed and\n"
383 "   replaced by the results of the expansion.\n"
384 "\n"
385 "  * '<<GM wildcards'\n"
386 "    Each wildcard string will be 'globbed' -- expanded from the names of\n"
387 "    files -- and the list of files found this way will be stored in a\n"
388 "    sequence of new arguments that replace this argument:\n"
389 "      '<<GM ~/Alice/*.nii ~/Bob/*.nii'\n"
390 "    might expand into a list of hundreds of separate datasets.\n"
391 "    * Why use this instead of just putting the wildcards on the command\n"
392 "      line? Mostly to get around limits on the length of Unix command lines.\n"
393 "\n"
394 "  * '<<G1 wildcards'\n"
395 "    The difference from the above case is that after the wildcard expansion\n"
396 "    strings are found, they are catenated with separating spaces into one\n"
397 "    big string. The only use for this in AFNI is for auto-catenation of\n"
398 "    multiple datasets into one big dataset.\n"
399 "\n"
400 "  * '<<IM filenames'\n"
401 "    Each filename string will result in the contents of that text file being\n"
402 "    read in, broken at whitespace into separate strings, and the resulting\n"
403 "    collection of strings will be stored in a sequence of new arguments\n"
404 "    that replace this argument. This type of argument can be used to input\n"
405 "    large numbers of files which are listed in an external file:\n"
406 "      '<<IM Bob.list.txt'\n"
407 "    which could in principle result in reading in thousands of datasets\n"
408 "    (if you've got the RAM).\n"
409 "    * This type of argument is in essence an internal form of doing something\n"
410 "      like `cat filename` using the back-quote shell operator on the command\n"
411 "      line. The only reason this argument (or the others) was implemented is\n"
412 "      to get around the length limits on the Unix command line.\n"
413 "\n"
414 "  * '<<I1 filenames'\n"
415 "    The difference from the above case is that after the files are read\n"
416 "    and their strings are found, they are catenated with separating spaces\n"
417 "    into one big string. The only use for this in AFNI is for auto-catenation\n"
418 "    of multiple datasets into one big dataset.\n"
419 "\n"
420 "  * 'G', 'M', and 'I' can be lower case, as in '<<gm'.\n"
421 "\n"
422 "  * 'glob' is Unix jargon for wildcard expansion:\n"
423 "    https://en.wikipedia.org/wiki/Glob_(programming)\n"
424 "\n"
425 "  * If you set environment variable AFNI_GLOB_SELECTORS to YES,\n"
426 "    then the wildcard expansion with '<<g' will not use the '[...]'\n"
427 "    construction as a Unix wildcard. Instead, it will expand the rest\n"
428 "    of the wildcard and then append the '[...]' to the results:\n"
429 "      '<<gm fred/*.nii[1..100]'\n"
430 "    would expand to something like\n"
431 "      fred/A.nii[1..100] fred/B.nii[1..100] fred/C.nii[1..100]\n"
432 "    This technique is a way to preserve AFNI-style sub-brick selectors\n"
433 "    and have them apply to a lot of files at once.\n"
434 "    Another example:\n"
435 "      3dttest++ -DAFNI_GLOB_SELECTORS=YES -brickwise -prefix Junk.nii \\\n"
436 "                -setA '<<gm sub-*/func/*rest_bold.nii.gz[0..100]'\n"
437 "\n"
438 "  * However, if you want to put sub-brick selectors on the '<<im' type\n"
439 "    of input, you will have to do that in the input text file itself\n"
440 "    (for each input filename in that file).\n"
441 "\n"
442 "   * BE CAREFUL OUT THERE!\n"
443 "------------------------------------------------------------------------\n"
444 "\n"
445 
446 /* Do not add options for NIML ports here, get them with get_np_help() instead */
447    };
448    return(GOPT_HELP);
449 }
450 
get_help_help()451 char *get_help_help() {
452    static char HELP_HELP[] = {
453 "-h: Mini help, at time, same as -help in many cases.\n"
454 "-help: The entire help output\n"
455 "-HELP: Extreme help, same as -help in majority of cases.\n"
456 "-h_view: Open help in text editor. AFNI will try to find a GUI editor\n"
457 "-hview : on your machine. You can control which it should use by\n"
458 "         setting environment variable AFNI_GUI_EDITOR.\n"
459 "-h_web: Open help in web browser. AFNI will try to find a browser.\n"
460 "-hweb : on your machine. You can control which it should use by\n"
461 "        setting environment variable AFNI_GUI_EDITOR. \n"
462 "-h_find WORD: Look for lines in this programs's -help output that match\n"
463 "              (approximately) WORD.\n"
464 "-h_raw: Help string unedited\n"\
465 "-h_spx: Help string in sphinx loveliness, but do not try to autoformat\n"\
466 "-h_aspx: Help string in sphinx with autoformatting of options, etc.\n"\
467 "-all_opts: Try to identify all options for the program from the\n"
468 "           output of its -help option. Some options might be missed\n"
469 "           and others misidentified. Use this output for hints only.\n"
470    };
471    return(HELP_HELP);
472 }
473 
474 int MRILIB_DomainMaxNodeIndex = -1;
475 
AFNI_prefilter_args(int * argc,char *** argvp)476 int AFNI_prefilter_args( int *argc , char ***argvp )
477 {
478    int narg=*argc , ii,jj , nused , ttt ;
479    char *used , *eee ;
480    char **argv ;
481    static int firstcall=1 ;
482 
483    if( !firstcall || narg <= 1 || argvp == NULL ) return(0) ;
484 
485    argv = *argvp ; if( argv == NULL ) return(0) ;
486 
487    firstcall = 0 ;
488 
489    used = (char *)calloc((size_t)narg,sizeof(char)) ;
490 
491    eee = getenv("AFNI_TRACE") ; ttt = YESSISH(eee) ;
492    if( ttt )
493      fprintf(  stderr,
494                "++ AFNI_prefilter_args() processing argv[1..%d]\n",narg-1) ;
495 
496    /*--- scan thru argv[];
497          see if any should be processed now and marked as 'used up' ---*/
498 
499    for( ii=1 ; ii < narg ; ii++ ){
500 
501      /*** empty argument (should never happen in Unix) ***/
502 
503      if( argv[ii] == NULL ){
504        if( ttt ) fprintf(stderr,"++ argv[%d] is NULL\n",ii) ;
505        used[ii] = 1 ; continue ;
506      }
507 
508 #ifdef DEBUG_ME
509 INFO_message("prefilter [%d] '%s'",ii,argv[ii]) ;
510 #endif
511 
512      /*** -Dname=val to set environment variable ***/
513 
514      if( strncmp(argv[ii],"-D",2) == 0 && strchr(argv[ii],'=') != NULL ){
515        if( ttt ) fprintf(stderr,"++ argv[%d] does setenv %s\n",ii,argv[ii]) ;
516        (void)AFNI_setenv(argv[ii]+2) ; used[ii] = 1 ; continue ;
517      }
518 
519      /*** -Vname to get environment variable ***/
520 
521      if( strncmp(argv[ii],"-V",2) == 0 && strchr(argv[ii],'=') != NULL ){
522        /* wipe out the '=', but let's not modify argv... 13 Aug 2019 [rickr] */
523        char *scpy = strdup(argv[ii]+2);
524        eee = strchr(scpy, '=');
525        *eee = '\0';
526 
527        if( ttt ) fprintf(stderr,"++ argv[%d] does getenv %s\n",ii,scpy) ;
528        fprintf(stdout,"%s\n", (eee = my_getenv(scpy)) ? eee:"") ;
529         used[ii] = 1 ; exit(0) ;
530      }
531 
532      /*** -overwrite to set AFNI_DECONFLICT ***/
533 
534      if( strcmp(argv[ii],"-overwrite") == 0 ){
535        if( ttt ) fprintf(stderr,"++ argv[%d] is -overwrite\n",ii) ;
536        AFNI_setenv("AFNI_DECONFLICT=OVERWRITE") ;
537        THD_set_quiet_overwrite(1); /* no need to kvetch */
538        used[ii] = 1 ; continue ;
539      }
540 
541      /*** echo command ***/
542 
543      if( strcmp(argv[ii],"-echo_edu") == 0 ){
544        if( ttt ) fprintf(stderr,"++ argv[%d] is -echo_edu\n",ii) ;
545        {
546          int jjj=0;
547          fprintf(stdout,"\n+++ Command Echo:\n   ");
548          for (jjj=0; jjj<narg; ++jjj)  {
549             if (jjj != ii) {
550                fprintf(stdout,"%s ", argv[jjj]);
551             }
552          }
553          fprintf(stdout,"\n\n");
554          used[ii] = 1 ; continue ;
555        }
556      }
557 
558      if( strcmp(argv[ii],"-all_opts") == 0 ){
559        if( ttt ) fprintf(stderr,"++ argv[%d] is -all_opts\n",ii) ;
560        print_prog_options(argv[0]); used[ii] = 1 ;
561        exit(0);
562          /* better exit, otherwise output get burried by program's own -help */
563      }
564 
565      if( strcmp(argv[ii],"-h_find") == 0 ){
566        if( ttt ) fprintf(stderr,"++ argv[%d] is -h_find\n",ii) ;
567        if (ii+1 >= narg) {
568          fprintf(stderr,"** -h_find needs a string.\n");
569          exit(1);
570        }
571        used[ii] = 1 ; ii++;
572        suggest_best_prog_option(argv[0], argv[ii]);
573        used[ii] = 1 ;
574        exit(0);
575          /* better exit, otherwise output get burried by program's own -help */
576      }
577 
578      if( strcmp(argv[ii],"-h_aspx") == 0 && ii == 1){
579        char *s=NULL;
580        if( ttt ) fprintf(stderr,"++ argv[%d] is -h_apsx\n",ii) ;
581        if (!(s = sphinxize_prog_help(argv[0], 0))) {
582          fprintf(stderr,"** Failed to get auto-sphinxized string\n");
583          exit(1);
584        }
585        fprintf(stdout,"%s", s); free(s);
586        used[ii] = 1 ;
587        exit(0);
588      }
589 
590 
591      if( strcmp(argv[ii],"-h_view") == 0 || strcmp(argv[ii],"-hview") == 0 ){
592        if( ttt ) fprintf(stderr,"++ argv[%d] is -h_view or -hview \n",ii) ;
593        view_prog_help(argv[0]);
594        used[ii] = 1 ;
595        exit(0);
596          /* better exit, otherwise output get burried by program's own -help */
597      }
598 
599      if( strcmp(argv[ii],"-h_web") == 0  || strcmp(argv[ii],"-hweb") == 0 ){
600        if( ttt ) fprintf(stderr,"++ argv[%d] is -h_web or -hweb\n",ii) ;
601        web_prog_help(argv[0],0);
602        used[ii] = 1 ;
603        exit(0);
604          /* better exit, otherwise output get burried by program's own -help */
605      }
606 
607      /*** -ok_1D_text to set AFNI_1D_ZERO_TEXT ZSS Dec 09 ***/
608 
609      if( strcmp(argv[ii],"-ok_1D_text") == 0 ){
610        if( ttt ) fprintf(stderr,"++ argv[%d] is -ok_1D_text\n",ii) ;
611        AFNI_setenv("AFNI_1D_ZERO_TEXT=YES") ; used[ii] = 1 ; continue ;
612      }
613 
614      /*** -skip_afnirc to avoid .afnirc file ***/
615 
616      if( strcmp(argv[ii],"-skip_afnirc") == 0 ){
617        if( ttt ) fprintf(stderr,"++ argv[%d] is -skip_afnirc\n",ii) ;
618        AFNI_mark_environ_done() ; used[ii] = 1 ; continue ;
619      }
620 
621      /*** -pad_to_node to force sparse data to a particular size ***/
622 
623      if( strcmp(argv[ii],"-pad_to_node") == 0 ){
624        if( ttt ) fprintf(stderr,"++ argv[%d] is -pad_to_node\n",ii) ;
625        if (ii+1 >= narg) {
626          fprintf(stderr,"** -pad_to_node needs a positive integer,\n"
627                         "   or standard mesh description such as ld120\n");
628          exit(1);
629        }
630        used[ii] = 1 ; ii++;
631 
632        if (!strncasecmp(argv[ii],"ld",2)) {
633          if (strlen(argv[ii]) < 3) {
634             fprintf(stderr,"** need a number right after ld (like ld120)\n");
635             exit(1);
636          }
637          MRILIB_DomainMaxNodeIndex = SUMA_IcoNums(atoi(argv[ii]+2), 0, 'n')-1;
638          if( ttt ) fprintf(stderr, "ld pad_to_node %d\n",
639                                     MRILIB_DomainMaxNodeIndex);
640        } else if (!strncasecmp(argv[ii],"rd",2)) {
641          if (strlen(argv[ii]) < 3) {
642             fprintf(stderr,"** need a number right after rd (like rd6)\n");
643             exit(1);
644          }
645          MRILIB_DomainMaxNodeIndex = SUMA_IcoNums(atoi(argv[ii]+2), 1, 'n')-1;
646          if( ttt ) fprintf(stderr, "rd pad_to_node %d\n",
647                                     MRILIB_DomainMaxNodeIndex);
648        } else if (!strncasecmp(argv[ii],"d:",2)) {
649          THD_3dim_dataset *dset=NULL;
650          if (strlen(argv[ii]) < 3) {
651             fprintf(stderr,
652                "** need a dataset right after d: (like d:hello.niml.dset)\n");
653             exit(1);
654          }
655          dset = THD_open_dataset(argv[ii]+2);
656          if (dset) {
657             DSET_MAX_NODE(dset, MRILIB_DomainMaxNodeIndex);
658             DSET_delete(dset); dset = NULL;
659             if( ttt ) fprintf(stderr, "d: pad_to_node %d\n",
660                                     MRILIB_DomainMaxNodeIndex);
661          } else {
662             fprintf(stderr,"** Could not load dset %s to determine padding\n",
663                            argv[ii]+2);
664          }
665        } else {
666          MRILIB_DomainMaxNodeIndex = atoi(argv[ii]);
667          if( ttt ) fprintf(stderr, "pad_to_node %d\n",
668                                     MRILIB_DomainMaxNodeIndex);
669        }
670        if (MRILIB_DomainMaxNodeIndex < 0) {
671          fprintf(stderr,"** parameter for -pad_to_node (%d) is negative!\n",
672                         MRILIB_DomainMaxNodeIndex);
673          exit(1);
674        }else if (MRILIB_DomainMaxNodeIndex > 500000) {
675          fprintf(stderr,
676                   "** parameter for -pad_to_node (%d) is suspiciously large.\n"
677                   "   I hope you know what you're doing.\n",
678                   MRILIB_DomainMaxNodeIndex );
679        }
680        used[ii] = 1;
681        continue ;
682      }
683 
684      if( strcmp(argv[ii],"-np") == 0 ||
685          strcmp(argv[ii],"-npq") == 0 ){   /* ZSS, June 2011 */
686        if( ttt ) fprintf(stderr,"++ argv[%d] is -np\n",ii) ;
687        if (ii+1 >= narg) {
688          fprintf(stderr,
689                "** -np needs an integer NP such that 1024 <= NP <= 65500\n");
690          exit(1);
691        }
692        used[ii] = 1 ; ii++;
693        if (set_user_np(atoi(argv[ii]))<1) {
694          if (strcmp(argv[ii-1],"-npq")) { /* not quiet mode? */
695             fprintf(stderr,
696                "** -np is not an integer such that 1024 <= NP <= 65500\n"
697                "   -np was ignored\n");
698          }
699        } else {
700          if (strcmp(argv[ii-1],"-npq"))
701             fprintf(stderr,"++ -np set to %d\n", get_user_np());
702        }
703        used[ii] = 1;
704        continue ;
705      }
706 
707      if( strcmp(argv[ii],"-npb") == 0 ){   /* ZSS, June 2011 */
708        if( ttt ) fprintf(stderr,"++ argv[%d] is -npb\n",ii) ;
709        if (ii+1 >= narg) {
710          fprintf(stderr,
711                "** -npb needs an integer NPB such that 0 <= NPB <= %d\n",
712                get_max_port_bloc());
713          exit(1);
714        }
715        used[ii] = 1 ; ii++;
716        if (set_user_np_bloc(atoi(argv[ii]))<1) {
717             fprintf(stderr,
718                "** -npb is not an integer such that 0 <= NPB <= %d\n"
719                "   -npb was ignored\n", get_max_port_bloc());
720        }
721        used[ii] = 1;
722        continue ;
723      }
724 
725      if( strcmp(argv[ii],"-pif") == 0 ){   /* ZSS, June 2011 */
726        if( ttt ) fprintf(stderr,"++ argv[%d] is -pif\n",ii) ;
727        if (ii+1 >= narg) {
728          fprintf(stderr,
729                "** -pif needs a string value\n");
730          exit(1);
731        }
732        used[ii] = 1 ; ii++;
733        set_user_pif(argv[ii]);
734        used[ii] = 1;
735        continue ;
736      }
737 
738       /* -max_port_bloc number and quit */
739       if( strncmp(argv[ii],"-max_port_bloc", 8) == 0) {
740          int pp = 0;
741          pp = get_max_port_bloc();
742          if (strcmp(argv[ii-1], "-max_port_bloc_quiet")) {
743             fprintf(stdout, "Maximum port bloc number: %d\n",
744                                 pp);
745          } else {
746             fprintf(stdout, "%d\n", pp);
747          }
748          exit(0);
749       }
750 
751       /* -num_assigned port number and quit */
752       if( strncmp(argv[ii],"-num_assigned_ports", 8) == 0) {
753          int pp = 0;
754          pp = get_max_port_bloc();
755          if (strcmp(argv[ii-1], "-num_assigned_ports_quiet")) {
756             fprintf(stdout, "Number of assigned ports: %d\n",
757                                 pp);
758          } else {
759             fprintf(stdout, "%d\n", pp);
760          }
761          exit(0);
762       }
763 
764 
765      /*** if get to here, argv[ii] is nothing special ***/
766 
767    } /* end of loop over argv[] */
768 
769    /*--- compress out used up argv[] entries ---*/
770 
771    for( nused=0,ii=narg-1 ; ii >= 1 ; ii-- ){
772      if( !used[ii] ) continue ;
773      for( jj=ii+1 ; jj < narg ; jj++ ) argv[jj-1] = argv[jj] ;
774      argv[narg-1] = NULL ; narg-- ; nused++ ;
775    }
776 
777    if( ttt && nused > 0 )
778      fprintf(stderr,"++ 'used up' %d argv[] entries, leaving %d\n",nused,narg) ;
779 
780    if( narg > 0 )
781      AFNI_prefilter_inclusions( &narg , argvp ) ; /* 13 Dec 2021 */
782 
783    free((void *)used) ; *argc = narg ;
784    return(nused);
785 }
786 
787 /*-------------------------------------------------------------------------*/
788 /* These functions moved here: 05 Feb 2008. */
789 
THD_deathcon(void)790 int THD_deathcon(void)  /* 06 Jun 2007 */
791 {
792    char *ppp = my_getenv("AFNI_DECONFLICT") ;
793    if( ppp != NULL && *ppp == 'N' ) return 1 ;
794    return 0 ;
795 }
796 
797 /*-------------------------------------------------------------------------*/
798 
799 static int force_ok_overwrite = 0 ;
THD_force_ok_overwrite(int ii)800 void THD_force_ok_overwrite( int ii ){ force_ok_overwrite = ii; }
THD_get_ok_overwrite(void)801 int THD_get_ok_overwrite (void) { return(force_ok_overwrite); }
802 
THD_ok_overwrite(void)803 int THD_ok_overwrite(void)  /* Jan 2008 */
804 {
805    char *ppp=my_getenv("AFNI_DECONFLICT");
806    if( force_ok_overwrite ) return 1 ;
807    if (ppp && strcmp(ppp,"OVERWRITE")==0) return 1;
808    return 0;
809 }
810 
811 /* accessor functions for setting and getting globalrange variable */
812 static int image_globalrange = -1;
813 
814 /* force globalrange to a specific value - reset with -1 */
THD_set_image_globalrange(int ii)815 void THD_set_image_globalrange(int ii)
816 {
817    image_globalrange = ii;
818 }
819 
820 /* get current value (maybe default value) for image globalrange */
THD_get_image_globalrange()821 int THD_get_image_globalrange()
822 {
823    char *temp_envstr = NULL;
824 
825    if(image_globalrange<0) {
826       if(AFNI_yesenv("AFNI_IMAGE_GLOBALRANGE")) image_globalrange = 1;
827       else {
828          temp_envstr = my_getenv("AFNI_IMAGE_GLOBALRANGE");
829          if(temp_envstr){
830             if((strcasecmp(temp_envstr,"VOLUME")==0) ||
831                (strcasecmp(temp_envstr,"SUBBRICK")==0))
832                image_globalrange = 1;   /* also same as "YES" */
833             else if ((strcasecmp(temp_envstr,"DSET")==0) ||
834                       (strcasecmp(temp_envstr,"DATASET")==0))
835                image_globalrange = 2;   /* apply display LUT based on whole dataset */
836          }
837          if(image_globalrange < 0)
838             image_globalrange = 0;   /* default to slice-based scaling */
839       }
840    }
841 
842    return(image_globalrange);
843 }
844 
845 /* set short string to put in image viewer */
THD_get_image_globalrange_str()846 char *THD_get_image_globalrange_str()
847 {
848    int ig;
849 
850    ig = THD_get_image_globalrange();
851 
852    switch (ig) {
853       default:
854       case 0 : return("Slice");
855       case 1 : return("Vol");
856       case 2 : return("Dset");
857    }
858 }
859 
860 /* cycle to next range setting */
THD_cycle_image_globalrange()861 void THD_cycle_image_globalrange()
862 {
863    int ig;
864 
865    ig = THD_get_image_globalrange();
866    ig++;
867    if(ig>2) ig = 0;
868    THD_set_image_globalrange(ig);
869 }
870 
871 /*--------------------------------------------------------------------*/
872 /* Parse and expand one inclusion argument of the forms
873      '<<XY strings'
874    where 'X' is 'I' for Include or 'G' for Glob (how expansion works),
875    and   'Y' is '1' for 1-string output or 'M' for Multi-string output
876                     (whether the result of expansion is one string, )
877                     (or is separated at whitespace into many strings)
878 *//*------------------------------------------------------------------*/
879 
880 #define INCLUSION_BAD      0
881 #define INCLUSION_ONE      1
882 #define INCLUSION_MANY     2
883 #define INCLUSION_INCLUDE 11
884 #define INCLUSION_GLOB    12
885 
886 #define INCLUSION_COUNT(ccc)                        \
887    (  ( (ccc)        == '1' ) ? INCLUSION_ONE       \
888     : ( toupper(ccc) == 'M' ) ? INCLUSION_MANY      \
889     :                           INCLUSION_BAD )
890 
891 #define INCLUSION_MODE(ccc)                         \
892    (  ( toupper(ccc) == 'I' ) ? INCLUSION_INCLUDE   \
893     : ( toupper(ccc) == 'G' ) ? INCLUSION_GLOB      \
894     :                           INCLUSION_BAD    )
895 
896 /*--------------------------------------------------------------------*/
897 
AFNI_is_valid_inclusion_string(char * astr)898 static int AFNI_is_valid_inclusion_string( char *astr )
899 {
900 ENTRY("AFNI_is_valid_inclusion_string") ;
901 
902    if( astr == NULL              ||
903        strlen(astr) < 6          ||
904        strncmp(astr,"<<",2) != 0 ||
905        !isspace(astr[4])           ) RETURN(0) ;
906 
907    if( INCLUSION_MODE (astr[2]) == INCLUSION_BAD ) RETURN(0) ;
908    if( INCLUSION_COUNT(astr[3]) == INCLUSION_BAD ) RETURN(0) ;
909 
910    RETURN(1) ;
911 }
912 
913 /*--------------------------------------------------------------------*/
914 
AFNI_parse_inclusion(char * astr)915 static NI_str_array * AFNI_parse_inclusion( char *astr )
916 {
917    NI_str_array *nsar_out=NULL , *nsar_in=NULL ;
918    int in_count , in_mode , nstr ;
919 
920 ENTRY("AFNI_parse_inclusion") ;
921 
922    /* check string for criminal behavior */
923 
924    if( ! AFNI_is_valid_inclusion_string(astr) ) RETURN(NULL) ;
925 
926    in_mode  = INCLUSION_MODE ( astr[2] ) ;  /* GLOB or INCLUDE */
927    in_count = INCLUSION_COUNT( astr[3] ) ;  /* ONE  or MANY */
928 
929    /* break input string into substrings, separated by whitespace */
930 
931    nsar_in = NI_decode_string_list( astr , " " ) ;
932 
933    /* didn't get ANYTHING? [shouldn't be possible] */
934 
935    if( nsar_in == NULL ) RETURN(NULL) ;
936 
937    /* need at least 2 substrings or life is meaningless drivel */
938 
939    nstr = nsar_in->num ;
940    if( nstr < 2 ){
941      NI_delete_str_array(nsar_in) ; RETURN(NULL) ;
942    }
943 
944    /* handle the modes (GLOB or INCLUDE) for processing the strings */
945 
946    switch( in_mode ){
947 
948      case INCLUSION_GLOB:{      /* strings = wildcards to expand */
949        int nout ; char **fout ;
950 
951        /* cf. mcw_glob.c */
952        MCW_file_expand( nstr-1 , nsar_in->str + 1 , &nout , &fout ) ;
953 
954        if( nout > 0 ){  /* got something? */
955 
956          nsar_out = (NI_str_array *)malloc(sizeof(NI_str_array)) ;
957 
958          if( in_count == INCLUSION_MANY ){ /* just stuff array of */
959            nsar_out->num = nout ;          /* strings into output */
960            nsar_out->str = fout ;
961          } else {                          /* concat all strings plus blanks */
962            UAint64 ntot=9 ; int ii ; char *apt ;
963            for( ii=0 ; ii < nout ; ii++ )            /* add up lengths */
964              ntot += (UAint64)( strlen(fout[ii]) + 1 ) ;
965            apt = (char *)calloc(sizeof(char),ntot) ; /* output string */
966            for( ii=0 ; ii < nout ; ii++ ){           /* concatenations */
967              strcat( apt , fout[ii] ) ; free(fout[ii]) ;
968              if( ii < nout-1 )
969                strcat( apt , " " ) ;  /* inter-string blank */
970            }
971            free(fout) ;
972            nsar_out->num    = 1 ;
973            nsar_out->str    = (char **)malloc(sizeof(char *)) ;
974            nsar_out->str[0] = apt ;
975          }
976        } else {
977          ERROR_message("No results from wildcard expansion in '%s'",astr) ;
978        }
979      }
980      break ;
981 
982      case INCLUSION_INCLUDE:{  /* strings = filenames to read */
983        char *fstr , *aastr=NULL ;
984        NI_str_array *nsar_file ; int ii ;
985 
986        /* read each file into one big string (fstr),
987           then catenate them into one super-big string (aastr) */
988 
989        for( ii=1 ; ii < nstr ; ii++ ){
990          fstr = AFNI_suck_file( nsar_in->str[ii] ) ;
991          if( fstr == NULL ){
992            ERROR_message("Cannot include data from file %s",nsar_in->str[ii]) ;
993          } else if( aastr == NULL ){
994            aastr = fstr ;
995          } else {
996            size_t nfs = strlen(fstr) + strlen(aastr) + 4 ;
997            aastr = (char *)realloc( aastr , sizeof(char)*nfs ) ;
998            strcat(aastr," ") ; strcat(aastr,fstr) ; free(fstr) ;
999          }
1000        }
1001 
1002        /* put results into output, depending on in_count method */
1003 
1004        if( aastr != NULL ){
1005          nsar_out = (NI_str_array *)malloc(sizeof(NI_str_array)) ;
1006          if( in_count == INCLUSION_ONE ){
1007            nsar_out->num    = 1 ;
1008            nsar_out->str    = (char **)malloc(sizeof(char *)) ;
1009            nsar_out->str[0] = aastr ;
1010          } else {
1011            nsar_out = NI_decode_string_list( aastr , " " ) ;
1012            free(aastr) ;
1013          }
1014        }
1015      }
1016      break ;
1017    }
1018 
1019    NI_delete_str_array(nsar_in) ;
1020 
1021    RETURN(nsar_out) ;
1022 }
1023 
1024 /*--------------------------------------------------------------------*/
1025 
AFNI_prefilter_inclusions(int * nargp,char *** argvp)1026 static void AFNI_prefilter_inclusions( int *nargp , char ***argvp )
1027 {
1028    int narg = *nargp ;
1029    char **old_argv = *argvp ;
1030    char **new_argv = NULL ;
1031    int ii,jj,kk ;
1032    int            incnn = 0    ;  /* number of inclusion args */
1033    int            inctt = 0    ;  /* number of expanded strings */
1034    int           *incii = NULL ;  /* list of indexes that are inclusions */
1035    NI_str_array **incar = NULL ;  /* list of expansions of inclusions */
1036 
1037 ENTRY("AFNI_prefilter_inclusions") ;
1038 
1039    if( narg <= 0 || old_argv == NULL ) EXRETURN ;
1040 
1041    /* count number of inclusion args */
1042 
1043    for( ii=0 ; ii < narg ; ii++ ){
1044      if( AFNI_is_valid_inclusion_string(old_argv[ii]) ) incnn++ ;
1045 #ifdef DEBUG_ME
1046 ININFO_message("scan argv[%d] = '%s' ==> incnn = %d",
1047  ii , old_argv[ii] , incnn ) ;
1048 #endif
1049    }
1050    if( incnn == 0 ) EXRETURN ;  /* None? Why did you disturb my rest!? */
1051 
1052    /* allocate list of expanded inclusions */
1053 
1054    incii = (int *)          malloc( sizeof(int)            * incnn ) ;
1055    incar = (NI_str_array **)malloc( sizeof(NI_str_array *) * incnn ) ;
1056 
1057    /* scan through args and expand each inclusion
1058       into its own string array (incar[kk]),
1059       keeping track of where it came from in the arg list (incii[kk]), and
1060       adding up how many strings resulted from all the inclusions (inctt) */
1061 
1062    for( kk=ii=0 ; ii < narg ; ii++ ){
1063      if( AFNI_is_valid_inclusion_string(old_argv[ii]) ){
1064        incii[kk] = ii ;
1065        incar[kk] = AFNI_parse_inclusion( old_argv[ii] ) ;
1066        if( incar[kk] != NULL && incar[kk]->num > 0 ){
1067 #ifdef DEBUG_ME
1068 ININFO_message("scan argv[%d] = '%s' gives %d output strings" ,
1069  ii , old_argv[ii] , incar[kk]->num ) ;
1070 #endif
1071          inctt += incar[kk]->num ;  /* number strings to add to argv */
1072          kk++ ;
1073        }
1074      }
1075    }
1076 
1077    incnn = kk ; if( incnn == 0 || inctt == 0 ) EXRETURN ; /* got nothing? */
1078 
1079    /* create new arglist if inclusions result in more args */
1080 
1081    if( inctt > incnn ){  /* need more space */
1082 
1083     new_argv = (char **)malloc( sizeof(char *)*(narg+inctt-incnn+1)) ;
1084 
1085    } else { /* one-for-one replacement of all inclusions! */
1086 
1087     new_argv = old_argv ;
1088 
1089    }
1090 
1091    /* In the following loop:
1092         ii = index in old_argv of argument we are dealing with
1093         jj = index in new_argv where results from old_argv[ii] go
1094         kk = index of current inclusion we are looking for;
1095              when incii[kk] == ii, then old_argv[ii] is an inclusion
1096              and so its expansion need to go into new_argv[jj] etc.,
1097              otherwise old_argv[ii] just goes into new_argv[jj]
1098 
1099      Note that if each inclusion expanded to a single string,
1100      then jj==ii at all times, but if some inclusions result in
1101      multiple strings, then at some point jj > ii.
1102 
1103      At the end of this loop, jj is the number of elements in new_argv.
1104 
1105      I hope all that is clear. If not, please seek me out in the BrainVan! */
1106 
1107    for( kk=jj=ii=0 ; ii < narg ; ii++ ){
1108 
1109      if( ii != incii[kk] ){ /* NOT the next inclusion */
1110 
1111        if( new_argv != old_argv ){  /* copy old string into new output */
1112          new_argv[jj++] = strdup( old_argv[ii] ) ;
1113        } /* don't need to copy it if we didn't create a new argv array */
1114 
1115      } else {  /* copy inclusion strings into the output */
1116 
1117        int ss ;
1118        for( ss=0 ; ss < incar[kk]->num ; ss++ ){
1119          if( incar[kk]->str[ss] != NULL ){
1120            new_argv[jj++] = incar[kk]->str[ss] ; /* copy pointer */
1121            incar[kk]->str[ss] = NULL ;           /* NULL to avoid free below */
1122          }
1123        }
1124        NI_delete_str_array( incar[kk] ) ;  /* all used up */
1125        kk++ ;    /* next inclusion index we will look for */
1126 
1127      }
1128 
1129    }
1130 
1131    /* cleanup and run away screaming into the darkness */
1132 
1133    if( new_argv != old_argv ) new_argv[jj] = NULL ;
1134 
1135 #ifdef DEBUG_ME     /* debugging */
1136      INFO_message("--------------------------------------------------------");
1137      INFO_message("AFNI_prefilter_inclusions:") ;
1138    ININFO_message(" narg input=%d output=%d",narg,jj) ;
1139    ININFO_message(" argv input=%p output=%p",(void *)old_argv,(void *)new_argv);
1140    ININFO_message(" Output args:") ;
1141    for( kk=0 ; kk < jj ; kk++ ){
1142      ININFO_message("   [%d] = '%s'",kk,new_argv[kk]) ;
1143    }
1144      INFO_message("--------------------------------------------------------");
1145 #endif
1146 
1147    free(incii) ; free(incar) ;
1148    *nargp = jj ;
1149    *argvp = new_argv ;
1150    EXRETURN ;
1151 }
1152