1 #define MAIN
2 #define SUMA_noFunc
3
4 #include "mrilib.h"
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include "matrix.h"
8 #include "suma_objs.h" /* 21 Apr 2020 */
9 /*------------------------------------------------------------*/
10
11 #define zischar(ch) ( ( ((ch) >= 'A' && (ch) <= 'Z' ) || ((ch) >= 'a' && (ch) <= 'z' ) ) ? 1 : 0 )
12 #define isnakedarg(s) ( ( (s)[0] == '-' && strlen(s) > 1 && zischar((s)[1]) ) ? 0 : 1 )
13
count_procs(char * pname)14 int count_procs(char *pname)
15 {
16 char sbuf[1024]={""};
17 int nproc, jj;
18 FILE *fp=NULL;
19 int verb=0;
20
21 if (!pname) pname = "apsearch";
22
23 if (SUMA_isEnv("SUMA_CountProcs_Verb","YES")) verb = 1;
24
25 if (verb) {
26 fprintf(stderr," Checking ps:\n");
27 sprintf(sbuf, "\\ps -caA | \\grep %s", pname);
28 system(sbuf);
29 }
30
31 /* afni_util.py main moved to afni_python_wrapper.py 19 Feb 2020 [rickr] */
32 sprintf(sbuf, "afni_python_wrapper.py -print \"get_process_depth(prog='%s')\"", pname);
33 if (verb) fprintf(stderr," Executing %s\n", sbuf);
34
35 fp = popen( sbuf , "r" ) ;
36 if( fp == NULL ){
37 ERROR_message(" popen fails\n");
38 exit(1);
39 }
40
41 jj = fscanf(fp,"%d",&nproc) ;
42 if( jj != 1 ){
43 ERROR_message(" 1st fscanf fails\n");
44 pclose(fp);
45 exit(1);
46 }
47
48 pclose(fp);
49 if (verb) fprintf(stderr,"Got %d\n", nproc);
50 return(nproc);
51 }
52
update_help_for_afni_programs(int force_recreate,byte verb,byte clean,THD_string_array ** hlist)53 int update_help_for_afni_programs(int force_recreate,
54 byte verb, byte clean,
55 THD_string_array **hlist )
56 {
57 int ii, iaf, icomm, estat;
58 char hout[128], houtc[128], scomm[256], *etr=NULL, *hdir=NULL, *etm=NULL;
59 THD_string_array *progs=NULL;
60
61
62 ENTRY("produce_help_for_afni_programs");
63
64 if (hlist && *hlist) {
65 ERROR_message("if hlist then must have *hlist = NULL\n");
66 RETURN(0);
67 }
68
69 if (!(hdir = THD_get_helpdir(0))) {
70 ERROR_message("Have no help directory\n");
71 RETURN(0);
72 }
73
74 if (!(progs = THD_get_all_afni_executables())) {
75 ERROR_message("Cannot get list of programs");
76 RETURN(0);
77 }
78
79 if (hlist) INIT_SARR((*hlist));
80 icomm=0;
81 for (ii=0, iaf=0; ii<progs->num ; ii++ ){
82 /* ------------------------------------------------------------*/
83 /* THIS BLOCK is essentially get_updated_help_file()
84 But I keep it separate because of the need for
85 nap time. Knowing when to sleep in get_updated_help_file()
86 is not that simple. */
87 etr = THD_trailname( progs->ar[ii] , 0 ) ;
88 if (!etr || strlen(etr) < 2) {
89 WARNING_message("Fishy executable named %s\n",progs->ar[ii]);
90 continue;
91 }
92 etm = THD_filetime(progs->ar[ii]);
93 if (etm[0] == '\0') {
94 etm = "NoTimeStamp";
95 }
96 snprintf(hout, 120*sizeof(char),
97 "%s/%s.%s.help", hdir, etr, etm);
98 snprintf(houtc, 120*sizeof(char),
99 "%s/%s.complete", hdir, etr);
100 if (!force_recreate && THD_is_file(hout)) {
101 if (verb)
102 fprintf(stderr,"Reusing %s (%d/%d)\n", hout, ii, progs->num );
103 if (!THD_is_file(houtc)) {
104 prog_complete_command(etr, houtc, -1);
105 }
106 } else {
107 if (verb)
108 fprintf(stderr,"Creating %s (%d/%d)\n", hout, ii, progs->num);
109 if (icomm > 25) { /* sleep a little to allow
110 forked processes to end */
111 NI_sleep(250); icomm = 0;
112 }
113 /* The echo below is there to make programs that
114 don't like -help and expect stdin to shut up and quit
115 As a result, it is hard to get the status of -help
116 command and use it wisely here without risking
117 trouble.
118 */
119 if (THD_is_file( hout)) {
120 snprintf(scomm, 250*sizeof(char),
121 "chmod u+w %s", hout);
122 system(scomm);
123 }
124 snprintf(scomm, 250*sizeof(char),
125 "\\echo '' 2>&1 | %s -help > %s 2>&1 ", etr, hout);
126 system(scomm);
127 snprintf(scomm, 250*sizeof(char),
128 "chmod a-w %s", hout);
129 system(scomm);
130 prog_complete_command(etr, houtc, -1);
131 ++icomm;
132 }
133 /* ------------------------------------------------------------*/
134
135 if (hlist) ADDTO_SARR((*hlist), hout);
136
137 }
138 /* cleanup hdir */
139 if (verb) fprintf(stderr,"Cleaning help directory %s\n",hdir);
140 if (clean && system("@clean_help_dir")) {
141 WARNING_message("Failed cleaning help directory");
142 }
143
144 DESTROY_SARR(progs) ;
145
146 RETURN(1);
147 }
148
149
apsearch_usage(TFORM targ,int detail)150 int apsearch_usage(TFORM targ, int detail)
151 {
152 int i = 0;
153
154 ENTRY("apsearch_usage");
155 /* print help message in three sections */
156 sphinx_fprintf(targ, stdout,
157 "\n"
158 "A program to perform simple approximate string searching. It's primary\n"
159 "purpose is to test string matching for atlas area locations.\n"
160 "\n"
161 " apsearch <-word WORD> <[-file FILE] | [-text TEXT] | [-phelp PROG]> \n"
162 " [OPTIONS]\n"
163 "\n%s", detail ? "":"use -h or -help for more help detail.\n");
164 if (detail) {
165 sphinx_printf (targ,
166 "Parameters:\n"
167 "===========\n"
168 " -word WORD: WORD being sought\n"
169 " -w WORD: Abbreviated version of -word WORD\n"
170 " -file FILE: Search for WORD in text file FILE\n"
171 " -files FILE1 FILE2 ...: Search for WORD in text files FILE1 FILE2 ...\n"
172 " -text TEXT: Search for WORD in string TEXT\n"
173 " -stdin: Search for WORD in text from stdin\n"
174 " -: Same as -stdin\n"
175 " -phelp PROG: Search for WORD in output of command PROG -help\n"
176 " -popt PROG: Search for possible options of PROG that match WORD\n"
177 " Make sure you add the '-' to WORD if you are looking\n"
178 " for an actual option.\n"
179 " -raw_phelp PROG: Spit out the help string for PROG without modification.\n"
180 " -txt_phelp PROG: Format the output of PROG -help for simple text.\n"
181 " -sphinx_phelp PROG: Format the output of PROG -help in a sphinxized way.\n"
182 " -asphinx_phelp PROG: Format the output of PROG -help in an auto sphinxized\n"
183 " way.\n"
184 " -doc_2_txt: Format AFNI markups from -file/-files/-stdin content for text\n"
185 " output.\n"
186 " -doc_2_spx: Format AFNI markups from -file/-files/-stdin content for\n"
187 " Sphinx output.\n"
188 " -hdoc_2_txt PNAME: Format program help output in -file/-files/-stdin \n"
189 " content for text output. PNAME is needed wherever the program\n"
190 " name is needed in the output.\n"
191 " -hdoc_2_spx PNAME: Format program help output in -file/-files/-stdin \n"
192 " content for Sphinx output. PNAME is needed wherever the program\n"
193 " name is needed in the output.\n"
194 " -hdoc_2_aspx PNAME: Format program help output in -file/-files/-stdin \n"
195 " content for Sphinx output with autoformatting of options.\n"
196 " PNAME is needed wherever the program name is needed in the \n"
197 " output.:LR:\n"
198 " Now, why use such an option as opposed to -asphinx_phelp ?\n"
199 " That's because the -help option in some programs cannot handle\n"
200 " any special markup within it so we write out that string as is\n"
201 " to standard out and pipe it to apsearch with:LIT:\n"
202 " 3dinfo -h_raw | apsearch -hdoc_2_aspx 3dinfo -\n\n"
203 " -race_check PNAME RMAX: Debugging option to test for race conditions where\n"
204 " apsearch calls a program which for some reason ends up calling\n"
205 " it back until you chew up all allowed processes -- not fun --!\n"
206 " This program will now check for such recursive craziness using\n"
207 " Rick Reynold's afni_util.py program. To see it in action, \n"
208 " create the following script and call it @rory:LIT:\n"
209 " #!/bin/tcsh -f\n"
210 " echo \"Called! `date`\"\n"
211 " apsearch -DSUMA_CountProcs_Verb=YES -race_check `basename $0`\n"
212 "\n"
213 " @rory should be executable and in your path.\n"
214 " Now run @rory and watch it go.\n\n"
215 " -doc_markup_sample: Shown an example of the types of markups available for\n"
216 " the documentation.\n"
217 " -all_afni_help: Search for WORD in all afni help files.\n"
218 " This option is not all that clever at the moment.\n"
219 " -all_popts PROG: TRY to guess at all the options for PROG\n"
220 " The list of options is not guaranteed to be full\n"
221 " or accurate. It is created by parsing the program's\n"
222 " -help output for likely candidates. \n"
223 " It is meant to act as an aid in locating\n"
224 " certain options.\n"
225 " -list_popts PROG: Like -all_popts, but preserve unique set of options\n"
226 " only, no chunks of help output are preserved.\n"
227 " -popts_complete_command PROG: Generate a csh command that can be sourced\n"
228 " to allow option autocompletion for program\n"
229 " PROG.\n"
230 " See also option -bash and -update_all_afni_help\n"
231 " See also option -zsh and -update_all_afni_help\n"
232 " -bash: Use bash format for the complete command. Default is csh/tcsh\n"
233 " This option MUST PRECEDE option -popts_complete_command\n"
234 " -zsh: Use zsh format for the complete command. Default is csh/tcsh\n"
235 " This option MUST PRECEDE option -popts_complete_command\n"
236 " -ci: Case insensitive search (default)\n"
237 " -cs: Case sensitive search\n"
238 " -global_help: Show help for global options.\n"
239 " -gopts_help: Show help for global options.\n"
240 " -max_hits MH: Return best MH hits only. Default MH = 3.\n"
241 " Use -1 to get all results back.\n"
242 " -m MH: Abbreviated version of -max_hits MH.\n"
243 " -min_different_hits mDH: Keep outputing hits until you have dDH\n"
244 " dissimilar matches. \n"
245 " Default is -1 (no minimum).\n"
246 " -unique_hits_only: Restrict output to novel hits only.\n"
247 " -show_score: Show matching word's distance.\n"
248 " -show_score_detail: That's right.\n"
249 " -list_all_afni_progs: List all executables in AFNI's bin directory\n"
250 " -list_all_afni_P_progs: Same as -list_all_afni_progs but with path\n"
251 " -list_all_afni_readmes: List all README files in AFNI's bin directory\n"
252 " -list_all_afni_P_readmes: Same as -list_all_afni_readmes but with path\n"
253 " -list_all_afni_dsets: List all datasets in AFNI's bin directory\n"
254 " -list_all_afni_P_dsets: Same as -list_all_afni_dsets but with path\n"
255 " -update_all_afni_help: Build/update -help output under directory:\n"
256 " %s\n"
257 " If older help files differ by little they are deleted\n"
258 " Little differences would be the compile date or the\n"
259 " version number. See @clean_help_dir code for details.\n"
260 " This option also creates autocompletion code for \n"
261 " csh/tcsh, bash and zsh shells.\n"
262 " -recreate_all_afni_help: Like -update_all_afni_help but force receration\n"
263 " even if nothing changed in the help\n"
264 " -afni_help_dir: Print afni help directory location and quit.\n"
265 " -afni_data_dir: Print afni data directory location and quit.\n"
266 " -afni_bin_dir: Print afni's binaries directory location and quit.\n"
267 " -afni_home_dir: Print afni's home directory and quit.\n"
268 " -afni_rc_file: Pathname to .afnirc. You'll get one even if none exists.\n"
269 " -afni_custom_atlas_dir: Print your afni's custom atlas directory \n"
270 " and quit.\n"
271 " -afni_custom_atlas_file: Print your afni's custom atlas file (if any)\n"
272 " and quit.\n"
273 " -afni_text_editor: Print the name of the GUI editor. Priority goes to \n"
274 " env. variable AFNI_GUI_EDITOR, otherwise afni\n"
275 " will try to find something suitable.\n"
276 " -afni_web_browser: Print the name of the browser used by AFNI. \n"
277 " Priority goes to env. variable AFNI_WEB_BROWSER, \n"
278 " otherwise afni will try to find something suitable.\n"
279 " -afni_web_downloader: Print the name of the downloader used by AFNI. \n"
280 " Priority goes to env. variable AFNI_WEB_DOWNLOADER, \n"
281 " otherwise afni will try to find something suitable.\n"
282 " -view_text_file FILE: Open FILE with editor of -afni_text_editor\n"
283 " -view_readme SOMETHING: Find a readme.SOMETHINGISH and open it\n"
284 " -apsearch_log_file: Print the name of the logfile that is used to save\n"
285 " some results of apsearch's functions. This option\n"
286 " is for debugging purposes and is only activated if\n"
287 " the environment variable AFNI_LOG_BEST_PROG_OPTION\n"
288 " is set to YES.\n"
289 " -view_prog_help PROG: Open the help file for PROG in a GUI editor.\n"
290 " This is like the option -hview in C programs.\n"
291 " -web_prog_help PROG: Open the help file for PROG in a web brower.\n"
292 " This is like the option -hweb in C programs.\n"
293 " Use ALL to view the page containing help for all programs.\n"
294 " -web_class_docs: Open the webpage with latest class pdfs.\n"
295 "\n"
296 " NOTE: The maximum number of results depends on the combination of\n"
297 " -max_hits, -min_different_hits, and -unique_hits_only. \n"
298 " Withoug -unique_hits_only, the output will continue \n"
299 " while neither -max_hits or -min_different_hits conditions \n"
300 " are met.\n"
301 "\n"
302 " -func_test: Run sample function testing and quit. Debugging only.\n"
303 "\n"
304 "Wildcard expansion tools:\n"
305 "=========================\n"
306 "-wild_files 'PAT1 PAT2 ...' : Find files matching PAT1, or PAT2, etc.\n"
307 " Should include PAT1, etc. between quotes or \n"
308 " the shell will do the expansion for you.\n"
309 " Note that in addition to wildcard expansion, \n"
310 " the function also sorts the output so the order\n"
311 " is alphabetical. It also dumps duplicate names\n"
312 " which can happen when you start to remove \n"
313 " extensions known to AFNI. See -wild* options\n"
314 " below.\n"
315 " Example: -wild_files '*.do *.HEAD'\n"
316 "-wild_files_noAext: After compiling list, remove all known AFNI extensions \n"
317 " and preserve unique set of resultant names\n"
318 "-wild_files_noAext_noAview: After compiling list, remove all known AFNI\n"
319 " extensions and any view such as +tlrc, +orig, +acpc, \n"
320 " and preserve unique set of resultant names\n"
321 "-wild_files_orig_name: Output unique list using orignal (full) filename, \n"
322 " rather than the names after extensions or views were\n"
323 " removed. This option makes a difference when using\n"
324 " one of -wild_files_noAext* options.\n"
325 "-wild_all_files: Show all files from wildcard expansion. Do not sort, do not\n"
326 " trim names, etc.\n"
327 "-wild_files_debug: Output results in debugging mode.\n"
328 "-wild_files_ci: When searching for unique set, use case insensitive matching\n"
329 "-test_unique_str: Run debugging tests for function unique_str().\n"
330 "\n"
331 "For hard coders only:\n"
332 "=====================\n"
333 "-C_all_prog_opt_array : Output all program options as an array of C structs.\n"
334 " Debugging is output to stderr, the beef is in stdout.\n"
335 " Executables not found in the afni binaries directory \n"
336 " (now %s) will be ignored.\n"
337 "-C_all_append_prog_opt_array: Keep programs already in C struct but no longer\n"
338 " in the new list of executables.\n"
339 "-C_prog_opt_array PROG: Insert/update PROG's options in an array of C \n"
340 " and output the results to stdout as for\n"
341 " option -C_all_prog_opt_array\n\n"
342 " Example: apsearch -C_prog_opt_array 3dToyProg > prog_opts.c\n"
343 "\n"
344 "Examples:\n"
345 "=========\n"
346 " 1- Search help output of program whereami for the word '-atlas'\n"
347 " apsearch -ci -phelp whereami -word -atlas\n"
348 " 2- Search all atlas area names for some name (mistakes on purpose)\n"
349 " whereami -show_atlas_code > all_atlas_area_names.txt\n"
350 " apsearch -file all_atlas_area_names.txt -word hepp\n"
351 " apsearch -file all_atlas_area_names.txt -word zipp \\\n"
352 " -min_different_hits 5 -unique_hits_only \n"
353 " apsearch -file all_atlas_area_names.txt -word hipp \\\n"
354 " -min_different_hits 5 -unique_hits_only \n"
355 " 3- Debug stupid string matcher:\n"
356 " apsearch -text 'u:Hippocampus' -word hipp -show_score_detail\n"
357 " apsearch -text 'u:IPC' -word hipp -show_score_detail\n"
358 " 4- Search help of AFNI programs:\n"
359 " apsearch -phelp afni -word port\n"
360 " apsearch -phelp 3dSkullStrip -word hull\n"
361 " apsearch -phelp afni -word xt\n"
362 " 5- Suggest a valid option from a program:\n"
363 " apsearch -popt afni -word xt\n"
364 " apsearch -popt @ROI_Corr_Mat -word sel\n"
365 " apsearch -popt @ROI_Corr_Mat -word -sel\n"
366 " 6- Show all(*) options for a program:\n"
367 " apsearch -all_popts 3dSkullStrip\n"
368 " (*) see -all_popts in help section\n"
369 " 7- Look for some area named something or other in some atlas:\n"
370 " whereami -show_atlas_code -atlas DKD_Desai_MPM |\\\n"
371 " apsearch -stdin -word insola\n"
372 " If you really screw up the spelling, you should help the search\n"
373 " program a little as in:\n"
374 " whereami -show_atlas_code -atlas DKD_Desai_MPM |\\\n"
375 " sed 's/[-_]/ /g' |\\\n"
376 " apsearch -stdin -word insolent\n"
377 " 8- Find 10 afni programs with something like 'Surface' in their names:\n"
378 " apsearch -list_all_afni_progs | \\\n"
379 " apsearch -stdin -word surface -max_hits 10\n"
380 " 9- Open the readme for driving AFNI:\n"
381 " apsearch -view_readme driv\n"
382 " 10- Wildcard expansion and sorting:\n"
383 " apsearch -wild_files '*.1D*' '*.HEAD *.BRIK*' \\\n"
384 " -wild_all_files \n"
385 " apsearch -wild_files '*.1D*' '*.HEAD *.BRIK*' \\\n"
386 " -wild_files_noAext_noAview \n"
387 " apsearch -wild_files '*.1D*' '*.HEAD *.BRIK*' \\\n"
388 " -wild_files_noAext_noAview -wild_files_orig_name \n"
389 "\n"
390 "Global Options:\n"
391 "===============\n"
392 "%s\n%s",
393 THD_helpdir(0), THD_abindir(1),
394 detail > 1 ? get_gopt_help():"",
395 detail > 1 ? SUMA_Offset_SLines(get_help_help(),2):"");
396 PRINT_COMPILE_DATE ;
397 }
398 return 0;
399 }
400
401
402 /*----------------------------------------------------------------------------*/
text_from_stdin(int * nread)403 char *text_from_stdin(int *nread)
404 {
405 int N_lbuf = 30000;
406 char lbuf[N_lbuf+1];
407 char *txt=NULL, *cpt=NULL;
408 int ex = 0, i, N_alloc=0, nchar=0, nnew;
409
410
411 if (nread) *nread = -1;
412
413 i = 0; N_alloc=0; nchar=0, nnew=0;
414 do{
415 cpt = afni_fgets(lbuf,N_lbuf,stdin) ;
416 lbuf[N_lbuf] = '\0';
417 ex = feof(stdin);
418 if( cpt==NULL && !ex){
419 free(txt);
420 ERROR_message("Failure reading from stdin");
421 return(NULL);
422 }
423 if (!ex) {
424 nnew = strlen(lbuf);
425 if (nchar+nnew >= N_alloc) {
426 N_alloc += (nnew+10000);
427 txt = (char *)realloc(txt, sizeof(char)*N_alloc);
428 }
429 /* fprintf(stderr,"%d- %s",nchar, lbuf);*/
430 strcat(txt, lbuf); nchar += nnew;
431 }
432 } while (!ex);
433
434
435 txt = (char *)realloc(txt, sizeof(char)*(1+nchar));
436 txt[nchar]='\0';
437
438 if (nread) *nread = nchar;
439
440 return(txt);
441 }
442
443 /* A function to test function unique_str. Use for debugging only */
Test_unique_str(void)444 int Test_unique_str(void)
445 {
446 /* dirty test for sorting */
447 char **ww, **ws;
448 int i, N_words=10, N_unq, *isrt=NULL;
449 ww = (char **)calloc(N_words, sizeof(char *));
450 i = 0;
451 ww[i++] = strdup("hello+orig.HEAD");
452 ww[i++] = strdup("hello+orig.BRIK.gz");
453 ww[i++] = NULL;
454 ww[i++] = strdup("HELLO+orig.HEAD");
455 ww[i++] = NULL;
456 ww[i++] = strdup("hello.nii");
457 ww[i++] = strdup("HELLO+orig.HEAD");
458 ww[i++] = strdup("james.nii");
459 if (i >= N_words) {
460 ERROR_message("Too many strings for allocated space"); return(1);
461 }
462
463 fprintf(stdout,
464 "\nInitial list of %d strings:\n", N_words);
465 for (i=0; i<N_words; ++i) {
466 fprintf(stdout,"%d %s\n", i, ww[i]?ww[i]:"NULL");
467 }
468
469 if ((ws = unique_str(ww, N_words, 0, 0, &N_unq, &isrt))) {
470 fprintf(stdout,
471 "\n%d/%d unique strings, case sensisitve, names as is:\n",
472 N_unq, N_words);
473 for (i=0; i<N_words; ++i) {
474 fprintf(stdout,"%d %s (ww[%d]=%s)\n",
475 i, ws[i]?ws[i]:"NULL - what follows is legit garbage",
476 isrt[i], ww[isrt[i]]?ww[isrt[i]]:"NULL" );
477 }
478 if (isrt) free(isrt); isrt = NULL;
479 for (i=0; i<N_words; ++i) if (ws[i]) free(ws[i]);
480 free(ws); ws = NULL;
481 }
482 if ((ws = unique_str(ww, N_words, 1, 0, &N_unq, &isrt))) {
483 fprintf(stdout,
484 "\n%d/%d unique strings, case insensitive, names as is:\n",
485 N_unq, N_words);
486 for (i=0; i<N_words; ++i) {
487 fprintf(stdout,"%d %s (ww[%d]=%s)\n",
488 i, ws[i]?ws[i]:"NULL - what follows is legit garbage",
489 isrt[i], ww[isrt[i]]?ww[isrt[i]]:"NULL" );
490 }
491 if (isrt) free(isrt); isrt = NULL;
492 for (i=0; i<N_words; ++i) if (ws[i]) free(ws[i]);
493 free(ws); ws = NULL;
494 }
495 if ((ws = unique_str(ww, N_words, 1, 1, &N_unq, &isrt))) {
496 fprintf(stdout,"\n%d/%d unique strings, case insensitive, noext\n",
497 N_unq, N_words);
498 for (i=0; i<N_words; ++i) {
499 fprintf(stdout,"%d %s (ww[%d]=%s)\n",
500 i, ws[i]?ws[i]:"NULL - what follows is legit garbage",
501 isrt[i], ww[isrt[i]]?ww[isrt[i]]:"NULL" );
502 }
503 if (isrt) free(isrt); isrt = NULL;
504 for (i=0; i<N_words; ++i) if (ws[i]) free(ws[i]);
505 free(ws); ws = NULL;
506 }
507 if ((ws = unique_str(ww, N_words, 1, 2, &N_unq, &isrt))) {
508 fprintf(stdout,
509 "\n%d/%d unique strings, case insensitive, noext noview\n",
510 N_unq, N_words);
511 for (i=0; i<N_words; ++i) {
512 fprintf(stdout,"%d %s (ww[%d]=%s)\n",
513 i, ws[i]?ws[i]:"NULL - what follows is legit garbage",
514 isrt[i], ww[isrt[i]]?ww[isrt[i]]:"NULL" );
515 }
516 if (isrt) free(isrt); isrt = NULL;
517 for (i=0; i<N_words; ++i) if (ws[i]) free(ws[i]);
518 free(ws); ws = NULL;
519 }
520
521 if ((ws = unique_str(ww, N_words, 0, 2, &N_unq, &isrt))) {
522 fprintf(stdout,
523 "\n%d/%d unique strings, case sensitive, noext noview\n",
524 N_unq, N_words);
525 for (i=0; i<N_words; ++i) {
526 fprintf(stdout,"%d %s (ww[%d]=%s)\n",
527 i, ws[i]?ws[i]:"NULL - what follows is legit garbage",
528 isrt[i], ww[isrt[i]]?ww[isrt[i]]:"NULL" );
529 }
530 if (isrt) free(isrt); isrt = NULL;
531 for (i=0; i<N_words; ++i) if (ws[i]) free(ws[i]);
532 free(ws); ws = NULL;
533 }
534
535 for (i=0; i<N_words; ++i) if (ww[i]) free(ww[i]);
536 free(ww); ww = NULL;
537 return(0);
538 }
539
main(int argc,char ** argv)540 int main(int argc, char **argv)
541 {
542 int iarg, N_ws, i, max_hits, test_only, new_score=0,
543 i_unique_score=0, min_different_hits=0, unq_only=0,
544 show_score=0, N_fnamev=0, MAX_FNAMES = 0, uopts=0,
545 compcom = 0, shtp = 0;
546 float *ws_score=NULL, last_score=-1.0;
547 char *fname=NULL, *text=NULL, *prog=NULL, *word="Ma fich haga", **ws=NULL,
548 *all_popts=NULL, *popt=NULL, stdinflag[] = " [+.-STDIN-.+] ",
549 *pname=NULL;
550 THD_string_array *fnamev = NULL;
551 APPROX_STR_DIFF *D=NULL;
552 THD_string_array *sar = NULL;
553 byte ci = 1;
554 char *wild_list=NULL, **wglob=NULL, **wsort=NULL;
555 int nglob, nsort, *isrt=NULL, wild_noext=0, nproc=0,
556 wild_all_files = 0, wild_orig_name = 0, wild_ci=0;
557 TFORM spx_tar = TFORM_NOT_SET;
558
559 mainENTRY("apsearch main"); machdep() ;
560
561 /* Check for race conditions, but do allow this program to call itself once
562 to accomodate the automatic handling of -h_apsx in mainENTRY(). */
563 if ((nproc = count_procs("apsearch")) > 2) {
564 ERROR_message("Race condition detected. I'm out");
565 exit(1);
566 }
567
568 max_hits = 3;
569 test_only=0;
570 min_different_hits = -1;
571 if (argc <= 1) {
572 apsearch_usage(TXT, 0);
573 return(1);
574 }
575
576 iarg = 1 ;
577 while( iarg < argc ){
578 CHECK_HELP(argv[iarg], apsearch_usage);
579 if (strcmp(argv[iarg],"-ci") == 0) {
580 ci = 1;
581 ++iarg;
582 continue;
583 }
584
585 if (strcmp(argv[iarg],"-cs") == 0) {
586 ci = 0;
587 ++iarg;
588 continue;
589 }
590
591 if (strcmp(argv[iarg],"-afni_help_dir") == 0) {
592 fprintf(stdout,"%s\n", THD_helpdir(0));
593 return(0);
594 }
595
596 if (strcmp(argv[iarg],"-test_unique_str") == 0) {
597 Test_unique_str();
598 return(0);
599 }
600
601 if (strcmp(argv[iarg],"-afni_data_dir") == 0) {
602 fprintf(stdout,"%s\n", THD_datadir(0));
603 return(0);
604 }
605
606 if (strcmp(argv[iarg],"-afni_rc_file") == 0) {
607 fprintf(stdout,"%s\n", THD_afnirc());
608 return(0);
609 }
610
611 if (strcmp(argv[iarg],"-afni_home_dir") == 0) {
612 fprintf(stdout,"%s\n", THD_homedir(0));
613 return(0);
614 }
615
616 if (strcmp(argv[iarg],"-afni_custom_atlas_dir") == 0) {
617 fprintf(stdout,"%s\n", THD_custom_atlas_dir(0));
618 return(0);
619 }
620
621 if (strcmp(argv[iarg],"-afni_custom_atlas_file") == 0) {
622 fprintf(stdout,"%s\n", THD_custom_atlas_file(NULL));
623 return(0);
624 }
625
626 if (strcmp(argv[iarg],"-afni_bin_dir") == 0) {
627 fprintf(stdout,"%s\n", THD_abindir(0));
628 return(0);
629 }
630
631 if (strcmp(argv[iarg],"-apsearch_log_file") == 0) {
632 fprintf(stdout,"%s\n", THD_helpsearchlog(0));
633 return(0);
634 }
635
636 if (strcmp(argv[iarg],"-afni_text_editor") == 0) {
637 char *ss = GetAfniTextEditor();
638 fprintf(stdout,"%s\n", ss?ss:"NONE FOUND");
639 return(0);
640 }
641
642 if (strcmp(argv[iarg],"-afni_web_downloader") == 0) {
643 char *ss = GetAfniWebDownloader();
644 fprintf(stdout,"%s\n", ss?ss:"NONE FOUND");
645 return(0);
646 }
647
648 if (strcmp(argv[iarg],"-afni_web_browser") == 0) {
649 char *ss = GetAfniWebBrowser();
650 fprintf(stdout,"%s\n", ss?ss:"NONE FOUND");
651 return(0);
652 }
653
654 if (strcmp(argv[iarg],"-show_score") == 0) {
655 show_score=1;
656 ++iarg;
657 continue;
658 }
659
660 if (strcmp(argv[iarg],"-show_score_detail") == 0) {
661 show_score=2;
662 ++iarg;
663 continue;
664 }
665
666 if (strcmp(argv[iarg],"-func_test") == 0) {
667 test_only = 0;
668 ++iarg;
669 continue;
670 }
671
672 /* 3 Feb 2014 [rickr] */
673 if (strcmp(argv[iarg],"-global_help") == 0 ||
674 strcmp(argv[iarg],"-gopts_help") == 0) {
675 printf(
676 "--------------------------------------------------------------------\n"
677 "Global Options: options available to most AFNI programs, but usually\n"
678 " not found in the -help output.\n"
679 "--------------------------------------------------------------------\n"
680 "%s\n%s", SUMA_Offset_SLines(get_help_help(),2), get_gopt_help());
681 return(0);
682 }
683
684 if (strcmp(argv[iarg],"-race_check") == 0) {
685 char sbuf[100];
686 ++iarg;
687 if (iarg >= argc) {
688 fprintf( stderr,
689 "** Error: Need a program name after -race_check\n");
690 return(1);
691 }
692 sprintf(sbuf,"%s -race_test",argv[iarg]);
693 fprintf(stderr,"Calling %s after a sec. nap\n", sbuf);
694 NI_sleep(1000);
695 system(sbuf);
696 ++iarg;
697 continue;
698 }
699
700
701
702 if (strcmp(argv[iarg],"-file") == 0) {
703 ++iarg;
704 if (iarg >= argc) {
705 fprintf( stderr,
706 "** Error: Need text file after -file\n"); return(1);
707 }
708
709 fname = argv[iarg];
710 ++iarg;
711 continue;
712 }
713
714 if (strcmp(argv[iarg],"-has-h_raw") == 0) {
715 char *s=NULL;
716 int ans;
717
718 ++iarg;
719 if (iarg >= argc) {
720 fprintf( stderr,
721 "** Error: Need a program name after"
722 " -has-h_raw\n");
723 return(1);
724 }
725 ans = program_supports(argv[iarg], "-h_raw", NULL, 1);
726 fprintf(stdout, "%d\n", ans);
727 return(0);
728 }
729
730 if (strcmp(argv[iarg],"-sphinx_phelp") == 0 ||
731 strcmp(argv[iarg],"-txt_phelp") == 0 ||
732 strcmp(argv[iarg],"-raw_phelp") == 0 ||
733 strcmp(argv[iarg],"-asphinx_phelp") == 0) {
734 TFORM form=NO_FORMAT;
735 char *s=NULL;
736 ++iarg;
737 if (iarg >= argc) {
738 fprintf( stderr,
739 "** Error: Need a program name after"
740 " -sphinx_phelp/-txt_phelp/-raw_phelp\n");
741 return(1);
742 }
743
744 if (strcmp(argv[iarg-1],"-txt_phelp") == 0) form = TXT;
745 else if (strcmp(argv[iarg-1],"-sphinx_phelp") == 0) form = SPX;
746 else if (strcmp(argv[iarg-1],"-asphinx_phelp") == 0) form = ASPX;
747 else if (strcmp(argv[iarg-1],"-raw_phelp") == 0) form = NO_FORMAT;
748 else {
749 ERROR_message("Who wrote this thing?!?");
750 return(1);
751 }
752 if ((s = phelp(argv[iarg], form, 0))) {
753 fprintf(stdout, "%s", s);
754 free(s); s = NULL;
755 }
756 ++iarg;
757 return(0);
758 continue;
759 }
760
761
762
763 if (!strcmp(argv[iarg],"-doc_markup_sample")) {
764 SUMA_Sphinx_String_Edit_Help(NULL,0);
765 ++iarg;
766 return(0);
767 continue;
768 }
769
770 if (!strcmp(argv[iarg],"-doc_markup_sample_web")) {
771 SUMA_Sphinx_String_Edit_Help(NULL,1);
772 ++iarg;
773 return(0);
774 continue;
775 }
776
777 if (!strcmp(argv[iarg],"-doc_2_txt")) {
778 spx_tar = TXT;
779 ++iarg; continue;
780 }
781
782 if (!strcmp(argv[iarg],"-doc_2_spx")) {
783 spx_tar = SPX;
784 ++iarg; continue;
785 }
786
787 if (!strcmp(argv[iarg],"-doc_2_aspx")) {
788 spx_tar = ASPX;
789 ++iarg; continue;
790 }
791
792 if (!strcmp(argv[iarg],"-hdoc_2_txt")) {
793 ++iarg;
794 if (iarg >= argc || !strcmp(argv[iarg],"-")) {
795 fprintf( stderr,
796 "** Error: Need a program name after -hdoc_*\n"); return(1);
797 }
798 pname = argv[iarg];
799 spx_tar = TXT;
800 ++iarg; continue;
801 }
802
803 if (!strcmp(argv[iarg],"-hdoc_2_spx")) {
804 ++iarg;
805 if (iarg >= argc || !strcmp(argv[iarg],"-")) {
806 fprintf( stderr,
807 "** Error: Need a program name after -hdoc_*\n"); return(1);
808 }
809 pname = argv[iarg];
810
811 spx_tar = SPX;
812 ++iarg; continue;
813 }
814
815 if (!strcmp(argv[iarg],"-hdoc_2_aspx")) {
816 ++iarg;
817 if (iarg >= argc || !strcmp(argv[iarg],"-")) {
818 fprintf( stderr,
819 "** Error: Need a program name after -hdoc_*\n"); return(1);
820 }
821 pname = argv[iarg];
822
823 spx_tar = ASPX;
824 ++iarg; continue;
825 }
826
827
828 if (strcmp(argv[iarg],"-files") == 0) {
829 ++iarg;
830 if (iarg >= argc) {
831 fprintf( stderr,
832 "** Error: Need text files after -files\n"); return(1);
833 }
834 while (iarg < argc && argv[iarg][0] != '-') {
835 if ( ! fnamev ) INIT_SARR(fnamev);
836 if (!THD_is_file(argv[iarg])) {
837 ERROR_exit("Argument %s for -files is not a file on disk\n",
838 argv[iarg]);
839 }
840 ADDUTO_SARR(fnamev, argv[iarg]);
841 ++iarg;
842 }
843 continue;
844 }
845
846 if (!strcmp(argv[iarg],"-wild_files_noAext")) {
847 wild_noext = 1;
848 ++iarg; continue;
849 }
850
851 if (!strcmp(argv[iarg],"-wild_files_noAext_noAview")) {
852 wild_noext = 2;
853 ++iarg; continue;
854 }
855
856 if (!strcmp(argv[iarg],"-wild_files_orig_name")) {
857 wild_orig_name = 1;
858 ++iarg; continue;
859 }
860
861 if (!strcmp(argv[iarg],"-wild_files_debug")) {
862 wild_orig_name = -1;
863 ++iarg; continue;
864 }
865
866 if (!strcmp(argv[iarg],"-wild_all_files")) {
867 wild_all_files = 1;
868 ++iarg; continue;
869 }
870 if (!strcmp(argv[iarg],"-wild_files_ci")) {
871 wild_ci = 1;
872 ++iarg; continue;
873 }
874 if (!strcmp(argv[iarg],"-wild_files")) {
875 ++iarg;
876 if (iarg >= argc) {
877 fprintf( stderr,
878 "** Error: Need wildcards files after -wild_files\n"); return(1);
879 }
880 while (iarg < argc && argv[iarg][0] != '-') {
881 wild_list =
882 SUMA_append_replace_string(wild_list, argv[iarg], " ", 1);
883 ++iarg;
884 }
885 continue;
886 }
887
888 if (strcmp(argv[iarg],"-stdin") == 0 || strcmp(argv[iarg],"-") == 0) {
889 fname = stdinflag;
890 ++iarg;
891 continue;
892 }
893
894 if (strcmp(argv[iarg],"-view_prog_help") == 0) {
895 ++iarg;
896 if (iarg >= argc) {
897 fprintf( stderr,
898 "** Error: Need program name after -view_prog_help\n");
899 return(1);
900 }
901 view_prog_help(argv[iarg]);
902 return(0);
903 continue;
904 }
905
906 if (strcmp(argv[iarg],"-web_prog_help") == 0) {
907 ++iarg;
908 if (iarg >= argc) {
909 fprintf( stderr,
910 "** Error: Need program name after -web_prog_help\n");
911 return(1);
912 }
913 web_prog_help(argv[iarg],0);
914 return(0);
915 continue;
916 }
917
918 if (strcmp(argv[iarg],"-web_class_docs") == 0) {
919 web_class_docs(NULL);
920 return(0);
921 continue;
922 }
923
924 if (strcmp(argv[iarg],"-view_readme") == 0) {
925 char *rout=NULL, **ws=NULL;
926 int N_ws, i;
927 ++iarg;
928 if (iarg >= argc) {
929 fprintf( stderr,
930 "** Error: Need README name after -view_readme\n");
931 return(1);
932 }
933 if ((rout = find_readme_file(argv[iarg]))) {
934 view_text_file(rout); free(rout);
935 } else {
936 fprintf( stderr,
937 "** Error: Could not find solid match for readme %s\n"
938 "Try to pick a good one using apsearch -list_all_afni_readmes\n",
939 argv[iarg]);
940 ws = approx_str_sort_readmes(argv[iarg], &N_ws);
941 if (N_ws) {
942 fprintf( stderr, " Perhaps you're looking for:\n");
943 for (i=0; i< N_ws; ++i) {
944 if (i<max_hits) fprintf( stderr, " %d- %s\n", i, ws[i]);
945 free(ws[i]);
946 }
947 free(ws);
948 }
949 }
950 return(0);
951 }
952
953 if (strcmp(argv[iarg],"-view_text_file") == 0) {
954 char *rout=NULL, **ws=NULL;
955 int N_ws, i;
956 ++iarg;
957 if (iarg >= argc) {
958 fprintf( stderr,
959 "** Error: Need a filename after -view_text_file\n");
960 return(1);
961 }
962 if (!THD_is_file(argv[iarg])) {
963 fprintf( stderr,
964 "** Error: File %s not found.\n", argv[iarg]);
965 return(1);
966 }
967 view_text_file(argv[iarg]);
968 return(0);
969 }
970
971 if (strcmp(argv[iarg],"-text") == 0) {
972 ++iarg;
973 if (iarg >= argc) {
974 fprintf( stderr,
975 "** Error: Need string after -text\n"); return(1);
976 }
977
978 text = argv[iarg];
979 ++iarg;
980 continue;
981 }
982
983 if (strcmp(argv[iarg],"-phelp") == 0 ||
984 strcmp(argv[iarg],"-popt") == 0 ) {
985 ++iarg;
986 if (iarg >= argc) {
987 fprintf( stderr,
988 "** Error: Need program name after -phelp or -popt\n"); return(1);
989 }
990
991 if (strcmp(argv[iarg-1],"-popt") == 0) popt = argv[iarg];
992 else prog = argv[iarg];
993
994 ++iarg;
995 continue;
996 }
997
998 if (strcmp(argv[iarg],"-all_popts") == 0 ) {
999 ++iarg;
1000 if (iarg >= argc) {
1001 fprintf( stderr,
1002 "** Error: Need program name after -all_popts\n"); return(1);
1003 }
1004
1005 all_popts = argv[iarg];
1006 uopts = 0;
1007 max_hits = -1;
1008 word = "-";
1009 ++iarg;
1010 continue;
1011 }
1012
1013 if (strcmp(argv[iarg],"-list_popts") == 0 ) {
1014 ++iarg;
1015 if (iarg >= argc) {
1016 fprintf( stderr,
1017 "** Error: Need program name after -list_popts\n"); return(1);
1018 }
1019
1020 all_popts = argv[iarg];
1021 uopts = 1;
1022 max_hits = -1;
1023 word = "-";
1024 ++iarg;
1025 continue;
1026 }
1027
1028 if (strcmp(argv[iarg],"-C_all_prog_opt_array") == 0) {
1029 progopt_C_array(NULL, 1, NULL, 0);
1030 return(0);
1031 ++iarg;
1032 continue;
1033 }
1034
1035 if (strcmp(argv[iarg],"-C_all_append_prog_opt_array") == 0) {
1036 progopt_C_array(NULL, 1, NULL, 1);
1037 return(0);
1038 ++iarg;
1039 continue;
1040 }
1041
1042 if (strcmp(argv[iarg],"-C_prog_opt_array") == 0) {
1043 ++iarg;
1044 if (iarg >= argc) {
1045 fprintf( stderr,
1046 "** Error: Need program name after -C_prog_opt_array\n");
1047 return(1);
1048 }
1049 progopt_C_array(NULL, 1, argv[iarg], 1);
1050 return(0);
1051 ++iarg;
1052 continue;
1053 }
1054
1055
1056 if (strcmp(argv[iarg],"-bash") == 0) {
1057 shtp = 1;
1058 ++iarg;
1059 continue;
1060 }
1061
1062 if (strcmp(argv[iarg],"-zsh") == 0) {
1063 shtp = 1;
1064 ++iarg;
1065 continue;
1066 }
1067
1068 if (strcmp(argv[iarg],"-popts_complete_command") == 0 ) {
1069 ++iarg;
1070 if (iarg >= argc) {
1071 fprintf( stderr,
1072 "** Error: Need program name after -popts_complete_command\n");
1073 return(1);
1074 }
1075
1076 all_popts = argv[iarg];
1077 if (1) {
1078 prog_complete_command(all_popts, NULL, shtp);
1079 return(0);
1080 }
1081
1082 uopts = 1;
1083 compcom = 1;
1084 max_hits = -1;
1085 word = "-";
1086
1087 ++iarg;
1088 continue;
1089 }
1090
1091 if (strcmp(argv[iarg],"-word") == 0 || strcmp(argv[iarg],"-w") == 0) {
1092 ++iarg;
1093 if (iarg >= argc) {
1094 fprintf( stderr,
1095 "** Error: Need text file after -file\n"); return(1);
1096 }
1097
1098 word = argv[iarg];
1099 ++iarg;
1100 continue;
1101 }
1102
1103 if (strcmp(argv[iarg],"-max_hits") == 0 || strcmp(argv[iarg],"-m") == 0) {
1104 ++iarg;
1105 if (iarg >= argc) {
1106 fprintf( stderr,
1107 "** Error: Need an integer after -max_hits\n"); return(1);
1108 }
1109
1110 max_hits = atoi(argv[iarg]);
1111 ++iarg;
1112 continue;
1113 }
1114
1115 if (strcmp(argv[iarg],"-min_different_hits") == 0) {
1116 ++iarg;
1117 if (iarg >= argc) {
1118 fprintf( stderr,
1119 "** Error: Need an integer after -min_different_hits\n");
1120 return(1);
1121 }
1122
1123 min_different_hits = atoi(argv[iarg]);
1124 ++iarg;
1125 continue;
1126 }
1127
1128 if (strcmp(argv[iarg],"-unique_hits_only") == 0) {
1129 unq_only = 1;
1130 ++iarg;
1131 continue;
1132 }
1133
1134 if (strcmp(argv[iarg],"-update_all_afni_help") == 0) {
1135 update_help_for_afni_programs(0, 1, 1, NULL); return(0);
1136 ++iarg;
1137 continue;
1138 }
1139
1140 if (strcmp(argv[iarg],"-recreate_all_afni_help") == 0) {
1141 update_help_for_afni_programs(1, 1, 1, NULL); return(0);
1142 ++iarg;
1143 continue;
1144 }
1145
1146 if (strcmp(argv[iarg],"-all_afni_help") == 0) {
1147 update_help_for_afni_programs(0, 0, 0, &fnamev);
1148 ++iarg;
1149 continue;
1150 }
1151
1152 if (strcmp(argv[iarg],"-list_all_afni_progs") == 0) {
1153 list_afni_programs(0, 0); return(0);
1154 ++iarg;
1155 continue;
1156 }
1157
1158 if (strcmp(argv[iarg],"-list_all_afni_P_progs") == 0) {
1159 list_afni_programs(1, 0); return(0);
1160 ++iarg;
1161 continue;
1162 }
1163
1164 if (strcmp(argv[iarg],"-list_all_afni_readmes") == 0) {
1165 list_afni_readmes(0, 0); return(0);
1166 ++iarg;
1167 continue;
1168 }
1169
1170 if (strcmp(argv[iarg],"-list_all_afni_P_readmes") == 0) {
1171 list_afni_readmes(1, 0); return(0);
1172 ++iarg;
1173 continue;
1174 }
1175
1176 if (strcmp(argv[iarg],"-list_all_afni_dsets") == 0) {
1177 list_afni_dsets(0, 0); return(0);
1178 ++iarg;
1179 continue;
1180 }
1181
1182 if (strcmp(argv[iarg],"-list_all_afni_P_dsets") == 0) {
1183 list_afni_dsets(1, 0); return(0);
1184 ++iarg;
1185 continue;
1186 }
1187
1188 { /* bad news in tennis shoes */
1189 fprintf(stderr,"** Error %s: bad option %s\n", argv[0], argv[iarg]);
1190 suggest_best_prog_option(argv[0], argv[iarg]);
1191 return 1;
1192 }
1193
1194 }
1195
1196 if (fname && text) {
1197 ERROR_message("-file and -text are mutually exclusive");
1198 return 1;
1199 }
1200
1201 if (min_different_hits<=0) min_different_hits = -1;
1202 if (max_hits <=0) max_hits = MRI_maxint;
1203
1204 if (test_only) {
1205 test_approx_str_match();
1206 return 0;
1207 }
1208
1209 if (wild_list) { /* some globbing action only */
1210 MCW_wildcards(wild_list, &nglob, &wglob);
1211 if (!wglob || nglob == 0) {
1212 SUMA_ifree(wild_list);
1213 exit(1); /* no files found */
1214 }
1215 if (wild_all_files) { /* No sorting */
1216 for (i=0; i<nglob; ++i) {
1217 fprintf(stdout,"%s\n", wglob[i]);
1218 }
1219 SUMA_ifree(wild_list);
1220 MCW_free_wildcards( nglob , wglob ) ;
1221 exit(0);
1222 }
1223 /* some sorting needed */
1224 if ((wsort = unique_str(wglob, nglob, wild_ci, wild_noext,
1225 &nsort, &isrt))) {
1226 if (wild_orig_name == -1) {/* verbose output */
1227 fprintf(stdout, "\n%d/%d unique strings, noext = %d:\n",
1228 nsort, nglob, wild_noext);
1229 for (i=0; i<nsort; ++i) {
1230 fprintf(stdout,"%d %s (wglob[%d]=%s)\n",
1231 i, wsort[i]?wsort[i]:"NULL - what followsort is legit garbage",
1232 isrt[i], wglob[isrt[i]]?wglob[isrt[i]]:"NULL" );
1233 }
1234 } else {
1235 if (wild_orig_name) { /* output original strings */
1236 for (i=0; i<nsort; ++i) {
1237 fprintf(stdout,"%s\n", wglob[isrt[i]]);
1238 }
1239 } else { /* output trimmed strings */
1240 for (i=0; i<nsort; ++i) {
1241 fprintf(stdout,"%s\n", wsort[i]);
1242 }
1243 }
1244 }
1245 if (isrt) free(isrt); isrt = NULL;
1246 for (i=0; i<nglob; ++i) if (wsort[i]) free(wsort[i]);
1247 free(wsort); wsort = NULL;
1248 SUMA_ifree(wild_list);
1249 MCW_free_wildcards( nglob , wglob ) ;
1250 exit(0);
1251 } else {
1252 ERROR_message("Failed to sort");
1253 SUMA_ifree(wild_list);
1254 MCW_free_wildcards( nglob , wglob ) ;
1255 exit(1);
1256 }
1257 }
1258
1259 if ((fnamev || fname || text || prog || popt || all_popts)) {
1260 if (!strcmp(word,"Ma fich haga") && spx_tar == TFORM_NOT_SET) {
1261 ERROR_message(
1262 "I'd search the world over for you, if only you gave me -word");
1263 return 1;
1264 }
1265 if (fnamev) {
1266 fprintf(stderr,"Have %d files\n", fnamev->num);
1267 if (spx_tar != TFORM_NOT_SET) {
1268 for (i=0; i<fnamev->num; ++i) {
1269 char *sso=SUMA_Sphinx_File_Edit(fnamev->ar[i], spx_tar, 0);
1270 if (sso) {
1271 fprintf(stdout,"%s", sso); free(sso); sso = NULL;
1272 } else {
1273 ERROR_message("Failed to sphinx edit string in %s",
1274 fnamev->ar[i]);
1275 return 1;
1276 }
1277 }
1278 return 0;
1279 } else {
1280 sar = approx_str_sort_Ntfile(
1281 fnamev->ar, fnamev->num, word, ci, &ws_score,
1282 NULL,
1283 &D, 0, '\0');
1284 ws = sar->ar; N_ws = sar->num;
1285 }
1286 } else if (fname) {
1287 if (strcmp(fname,stdinflag)) {
1288 if (spx_tar != TFORM_NOT_SET) {
1289 char *sso=NULL;
1290 if (!pname) {
1291 sso = SUMA_Sphinx_File_Edit(fname, spx_tar, 0);
1292 } else {
1293 sso = AFNI_suck_file(fname);
1294 sso = sphelp(pname, &sso, spx_tar, 0);
1295 }
1296 if (sso) {
1297 fprintf(stdout,"%s", sso); free(sso); sso = NULL;
1298 } else {
1299 ERROR_message("Failed to sphinx edit string in %s", fname);
1300 return 1;
1301 }
1302 return 0;
1303 } else {
1304 ws = approx_str_sort_tfile(fname, 0, &N_ws, word,
1305 ci, &ws_score,
1306 NULL, &D, 1, '\0');
1307 }
1308 } else {
1309 char *stdtext=NULL;
1310 if (!(stdtext = text_from_stdin(&N_ws))) {
1311 ERROR_message("Failed to read from stdin");
1312 return 0;
1313 }
1314 if (spx_tar != TFORM_NOT_SET) {
1315 if (!pname) {
1316 stdtext = SUMA_Sphinx_String_Edit(&stdtext, spx_tar, 0);
1317 } else {
1318 stdtext = sphelp(pname, &stdtext, spx_tar, 0);
1319 }
1320 if (stdtext) {
1321 fprintf(stdout,"%s", stdtext);
1322 free(stdtext); stdtext=NULL;
1323 }
1324 return 0;
1325 } else {
1326 ws = approx_str_sort_text(stdtext, &N_ws, word,
1327 ci, &ws_score,
1328 NULL, &D, '\0');
1329 free(stdtext); stdtext=NULL;
1330 }
1331 }
1332 } else if (text) {
1333 ws = approx_str_sort_text(text, &N_ws, word,
1334 ci, &ws_score,
1335 NULL, &D, '\0');
1336 } else if (prog) {
1337 ws = approx_str_sort_phelp(prog, 0, &N_ws, word,
1338 ci, &ws_score,
1339 NULL, &D, 1, '\\');
1340 } else if (popt) {
1341 suggest_best_prog_option(popt, word);
1342 return 0;
1343 } else if (all_popts) {
1344 /* one can also use print_prog_options(all_popts); return(0); */
1345 ws = approx_str_sort_all_popts(all_popts, 0, &N_ws,
1346 ci, &ws_score,
1347 NULL, &D, uopts, 1, '\\');
1348 }
1349
1350 i_unique_score = 0; last_score = -1.0; new_score=1;
1351 for (i=0; i<N_ws; ++i) {
1352 if (ws[i]) {
1353 new_score=0;
1354 if (ws_score[i] != last_score) {
1355 last_score = ws_score[i];
1356 new_score=1;
1357 ++i_unique_score;
1358 }
1359 if (i<max_hits || i_unique_score<=min_different_hits) {
1360 if (!unq_only || new_score) {
1361 switch(show_score) {
1362 case 0:
1363 fprintf(stdout," ");
1364 if ((D+i)->srcfile &&
1365 strncmp((D+i)->srcfile,APSEARCH_TMP_PREF,
1366 strlen(APSEARCH_TMP_PREF)))
1367 fprintf(stdout,"(%s) ",(D+i)->srcfile);
1368 break;
1369 case 1:
1370 fprintf(stdout,"%03f ",
1371 ws_score[i]);
1372 if ((D+i)->srcfile &&
1373 strncmp((D+i)->srcfile,APSEARCH_TMP_PREF,
1374 strlen(APSEARCH_TMP_PREF)))
1375 fprintf(stdout,"(%s) ",(D+i)->srcfile);
1376 break;
1377 case 2:
1378 fprintf(stdout,"%s ",
1379 approx_string_diff_info(D+i, NULL));
1380 break;
1381 default:
1382 ERROR_exit("Bad show_score value");
1383 break;
1384 }
1385 fprintf(stdout,"%s\n", ws[i]);
1386 }
1387 }
1388 free(ws[i]); ws[i]=NULL;
1389 }
1390 } free(ws); if (ws_score) free(ws_score); ws_score=NULL;
1391 if (D) free(D); D=NULL;
1392 }
1393
1394 if (fnamev) DESTROY_SARR(fnamev); fnamev=NULL;
1395 return 0;
1396 }
1397