From f0256338b54f833962d8c39a7facf4a941043c05 Mon Sep 17 00:00:00 2001 From: GUAN Xin Date: Thu, 9 Jul 2020 16:06:54 +0800 Subject: [PATCH 1/4] Permit multiple input files on the command line in order to avoid traversing $PATH and $LD_LIBRARY_PATH each time a new search starts --- src/accelsearch.c | 92 ++++++++++++++++++++++++++++++++++++++++++- src/accelsearch_cmd.c | 8 ++-- 2 files changed, 95 insertions(+), 5 deletions(-) diff --git a/src/accelsearch.c b/src/accelsearch.c index d5692cb7d..d83ddbbbe 100644 --- a/src/accelsearch.c +++ b/src/accelsearch.c @@ -1,5 +1,12 @@ #include "accel.h" +#include +#include +#include +#include +#include +#include + /*#undef USEMMAP*/ #ifdef USEMMAP @@ -40,7 +47,8 @@ static void print_percent_complete(int current, int number, char *what, int rese } } -int main(int argc, char *argv[]) +/* subprogram that does the real work; called from the real main function */ +int sub_main(int argc, char *argv[]) { int ii, rstep; double ttim, utim, stim, tott; @@ -312,3 +320,85 @@ int main(int argc, char *argv[]) g_slist_free(cands); return (0); } + +int main(int argc, char *argv[]) +{ + int i_dd; + + /* Check if there exists a double-dash on the command line, + which indicates that the program is called to handle + multiple data files. + + Without a double-dash, it is assumed that the program should + work traditionally and handle exactly one data file. + */ + for(i_dd = argc; i_dd --> 1;) + { + if(strcmp(argv[i_dd], "--") == 0) + { + break; + } + } + if(i_dd < 1) + { + /* "--" not found on the command line */ + return sub_main(argc, argv); + } + else + { + /* argv[i_dd] is "--" */ + int i_dat, sub_argc, err; + char **sub_argv; + + err = 0; + sub_argc = i_dd + 1; + sub_argv = malloc(sizeof(*sub_argv) * sub_argc); + memmove(sub_argv, argv, sizeof(*sub_argv) * i_dd); + for(i_dat = argc; i_dat --> sub_argc;) + { + int pid, child_status; + + pid = fork(); + if(pid == 0) + { + /* This is the child process that does the real work */ + sub_argv[i_dd] = argv[i_dat]; + /* valgrind may complain, but no harm to omit free(sub_argv) */ + return sub_main(sub_argc, sub_argv); + } + /* This is the parent process, let's collect the child status and + stop on error. + */ + if(pid == -1) + { + fprintf(stderr, "%s: error calling worker process: ", argv[0]); + perror("fork"); + return -1; + } + if(waitpid(pid, &child_status, 0) < 1) + { + fprintf(stderr, "%s: error calling worker process: ", argv[0]); + perror("waitpid"); + return -1; + } + if(!WIFEXITED(child_status)) + { + fprintf(stderr, "%s: worker process terminated abnormally, ", argv[0]); + err = -1; + } + else if(err = WEXITSTATUS(child_status)) + { + fprintf(stderr, "%s: error returned from worker process. Aborting ... ", argv[0]); + } + if(err) + { + fprintf(stderr, "%d files left unprocessed.\n", sub_argc - i_dat + 1); + break; + } + } + free(sub_argv); + return err; + } + /* Never reached */ + return 0; +} diff --git a/src/accelsearch_cmd.c b/src/accelsearch_cmd.c index 9869f1b1a..eaca03f57 100644 --- a/src/accelsearch_cmd.c +++ b/src/accelsearch_cmd.c @@ -994,7 +994,7 @@ showOptionValues(void) void usage(void) { - fprintf(stderr,"%s"," [-ncpus ncpus] [-lobin lobin] [-numharm numharm] [-zmax zmax] [-wmax wmax] [-sigma sigma] [-rlo rlo] [-rhi rhi] [-flo flo] [-fhi fhi] [-inmem] [-photon] [-median] [-locpow] [-zaplist zaplist] [-baryv baryv] [-otheropt] [-noharmpolish] [-noharmremove] [--] infile\n"); + fprintf(stderr,"%s"," [-ncpus ncpus] [-lobin lobin] [-numharm numharm] [-zmax zmax] [-wmax wmax] [-sigma sigma] [-rlo rlo] [-rhi rhi] [-flo flo] [-fhi fhi] [-inmem] [-photon] [-median] [-locpow] [-zaplist zaplist] [-baryv baryv] [-otheropt] [-noharmpolish] [-noharmremove] [[[--] infile] | [-- infile...]]\n"); fprintf(stderr,"%s"," Search an FFT or short time series for pulsars using a Fourier domain acceleration search with harmonic summing.\n"); fprintf(stderr,"%s"," -ncpus: Number of processors to use with OpenMP\n"); fprintf(stderr,"%s"," 1 int value between 1 and oo\n"); @@ -1035,9 +1035,9 @@ usage(void) fprintf(stderr,"%s"," -otheropt: Use the alternative optimization (for testing/debugging)\n"); fprintf(stderr,"%s"," -noharmpolish: Do not use 'harmpolish' by default\n"); fprintf(stderr,"%s"," -noharmremove: Do not remove harmonically related candidates (never removed for numharm = 1)\n"); - fprintf(stderr,"%s"," infile: Input file name of the floating point .fft or .[s]dat file. A '.inf' file of the same name must also exist\n"); - fprintf(stderr,"%s"," 1 value\n"); - fprintf(stderr,"%s"," version: 19Sep17\n"); + fprintf(stderr,"%s"," infile|infile...: Input file name[s] of the floating point .fft or .[s]dat file[s]. A '.inf' file of the same name must also exist for each input file\n"); + fprintf(stderr,"%s"," The options list must be terminated by a double-dash if multiple input files are provided\n"); + fprintf(stderr,"%s"," version: 2020-07-09\n"); fprintf(stderr,"%s"," "); exit(EXIT_FAILURE); } From 732d70f9ac9a41f48e2c676e593605779ce29260 Mon Sep 17 00:00:00 2001 From: GUAN Xin Date: Fri, 10 Jul 2020 21:44:44 +0800 Subject: [PATCH 2/4] Revert "Permit multiple input files on the command line in order to avoid" This conflicts with the clig command line parser / doc generator files, and also needs further optimization on command line parsing. This also missed a call to system(3). Leaving it there partly defeated the purpose of this commit, which is to reduce the number of shell executions and associated searched over $PATH and $LD_LIBRARY_PATH. This reverts commit f0256338b54f833962d8c39a7facf4a941043c05. --- src/accelsearch.c | 92 +------------------------------------------ src/accelsearch_cmd.c | 8 ++-- 2 files changed, 5 insertions(+), 95 deletions(-) diff --git a/src/accelsearch.c b/src/accelsearch.c index d83ddbbbe..d5692cb7d 100644 --- a/src/accelsearch.c +++ b/src/accelsearch.c @@ -1,12 +1,5 @@ #include "accel.h" -#include -#include -#include -#include -#include -#include - /*#undef USEMMAP*/ #ifdef USEMMAP @@ -47,8 +40,7 @@ static void print_percent_complete(int current, int number, char *what, int rese } } -/* subprogram that does the real work; called from the real main function */ -int sub_main(int argc, char *argv[]) +int main(int argc, char *argv[]) { int ii, rstep; double ttim, utim, stim, tott; @@ -320,85 +312,3 @@ int sub_main(int argc, char *argv[]) g_slist_free(cands); return (0); } - -int main(int argc, char *argv[]) -{ - int i_dd; - - /* Check if there exists a double-dash on the command line, - which indicates that the program is called to handle - multiple data files. - - Without a double-dash, it is assumed that the program should - work traditionally and handle exactly one data file. - */ - for(i_dd = argc; i_dd --> 1;) - { - if(strcmp(argv[i_dd], "--") == 0) - { - break; - } - } - if(i_dd < 1) - { - /* "--" not found on the command line */ - return sub_main(argc, argv); - } - else - { - /* argv[i_dd] is "--" */ - int i_dat, sub_argc, err; - char **sub_argv; - - err = 0; - sub_argc = i_dd + 1; - sub_argv = malloc(sizeof(*sub_argv) * sub_argc); - memmove(sub_argv, argv, sizeof(*sub_argv) * i_dd); - for(i_dat = argc; i_dat --> sub_argc;) - { - int pid, child_status; - - pid = fork(); - if(pid == 0) - { - /* This is the child process that does the real work */ - sub_argv[i_dd] = argv[i_dat]; - /* valgrind may complain, but no harm to omit free(sub_argv) */ - return sub_main(sub_argc, sub_argv); - } - /* This is the parent process, let's collect the child status and - stop on error. - */ - if(pid == -1) - { - fprintf(stderr, "%s: error calling worker process: ", argv[0]); - perror("fork"); - return -1; - } - if(waitpid(pid, &child_status, 0) < 1) - { - fprintf(stderr, "%s: error calling worker process: ", argv[0]); - perror("waitpid"); - return -1; - } - if(!WIFEXITED(child_status)) - { - fprintf(stderr, "%s: worker process terminated abnormally, ", argv[0]); - err = -1; - } - else if(err = WEXITSTATUS(child_status)) - { - fprintf(stderr, "%s: error returned from worker process. Aborting ... ", argv[0]); - } - if(err) - { - fprintf(stderr, "%d files left unprocessed.\n", sub_argc - i_dat + 1); - break; - } - } - free(sub_argv); - return err; - } - /* Never reached */ - return 0; -} diff --git a/src/accelsearch_cmd.c b/src/accelsearch_cmd.c index eaca03f57..9869f1b1a 100644 --- a/src/accelsearch_cmd.c +++ b/src/accelsearch_cmd.c @@ -994,7 +994,7 @@ showOptionValues(void) void usage(void) { - fprintf(stderr,"%s"," [-ncpus ncpus] [-lobin lobin] [-numharm numharm] [-zmax zmax] [-wmax wmax] [-sigma sigma] [-rlo rlo] [-rhi rhi] [-flo flo] [-fhi fhi] [-inmem] [-photon] [-median] [-locpow] [-zaplist zaplist] [-baryv baryv] [-otheropt] [-noharmpolish] [-noharmremove] [[[--] infile] | [-- infile...]]\n"); + fprintf(stderr,"%s"," [-ncpus ncpus] [-lobin lobin] [-numharm numharm] [-zmax zmax] [-wmax wmax] [-sigma sigma] [-rlo rlo] [-rhi rhi] [-flo flo] [-fhi fhi] [-inmem] [-photon] [-median] [-locpow] [-zaplist zaplist] [-baryv baryv] [-otheropt] [-noharmpolish] [-noharmremove] [--] infile\n"); fprintf(stderr,"%s"," Search an FFT or short time series for pulsars using a Fourier domain acceleration search with harmonic summing.\n"); fprintf(stderr,"%s"," -ncpus: Number of processors to use with OpenMP\n"); fprintf(stderr,"%s"," 1 int value between 1 and oo\n"); @@ -1035,9 +1035,9 @@ usage(void) fprintf(stderr,"%s"," -otheropt: Use the alternative optimization (for testing/debugging)\n"); fprintf(stderr,"%s"," -noharmpolish: Do not use 'harmpolish' by default\n"); fprintf(stderr,"%s"," -noharmremove: Do not remove harmonically related candidates (never removed for numharm = 1)\n"); - fprintf(stderr,"%s"," infile|infile...: Input file name[s] of the floating point .fft or .[s]dat file[s]. A '.inf' file of the same name must also exist for each input file\n"); - fprintf(stderr,"%s"," The options list must be terminated by a double-dash if multiple input files are provided\n"); - fprintf(stderr,"%s"," version: 2020-07-09\n"); + fprintf(stderr,"%s"," infile: Input file name of the floating point .fft or .[s]dat file. A '.inf' file of the same name must also exist\n"); + fprintf(stderr,"%s"," 1 value\n"); + fprintf(stderr,"%s"," version: 19Sep17\n"); fprintf(stderr,"%s"," "); exit(EXIT_FAILURE); } From 54654693c3b0a8b870f335def0b8ec3f7ec8d22b Mon Sep 17 00:00:00 2001 From: GUAN Xin Date: Sat, 11 Jul 2020 13:44:25 +0800 Subject: [PATCH 3/4] Support multiple input files --- clig/accelsearch.1 | 8 +- clig/accelsearch_cmd.cli | 3 +- src/accelsearch.c | 114 ++- src/accelsearch_cmd.c | 1809 ++++++++++++++++++-------------------- 4 files changed, 968 insertions(+), 966 deletions(-) diff --git a/clig/accelsearch.1 b/clig/accelsearch.1 index e2474ffb7..152d84374 100644 --- a/clig/accelsearch.1 +++ b/clig/accelsearch.1 @@ -11,7 +11,7 @@ .\" it edited by clig, remove the respective pair of cligPart-lines. .\" .\" cligPart TITLE -.TH "accelsearch" 1 "09Jul20" "Clig-manuals" "Programmer's Manual" +.TH "accelsearch" 1 "10Jul20" "Clig-manuals" "Programmer's Manual" .\" cligPart TITLE end .\" cligPart NAME @@ -41,7 +41,7 @@ accelsearch \- Search an FFT or short time series for pulsars using a Fourier do [-otheropt] [-noharmpolish] [-noharmremove] -infile ... +[infiles ...] .\" cligPart SYNOPSIS end .\" cligPart OPTIONS @@ -124,8 +124,8 @@ Use the alternative optimization (for testing/debugging). Do not use 'harmpolish' by default. .IP -noharmremove Do not remove harmonically related candidates (never removed for numharm = 1). -.IP infile -Input file name(s) of the floating point .fft or .[s]dat file(s). '.inf' file(s) of the same name must also exist. +.IP infiles +One or more input file name(s) of the floating point .fft or .[s]dat file(s). '.inf' file(s) of the same name must also exist. .\" cligPart OPTIONS end .\" cligPart DESCRIPTION diff --git a/clig/accelsearch_cmd.cli b/clig/accelsearch_cmd.cli index 86d02f595..097a81d85 100644 --- a/clig/accelsearch_cmd.cli +++ b/clig/accelsearch_cmd.cli @@ -45,5 +45,4 @@ Flag -noharmremove noharmremove {Do not remove harmonically related candidate # Rest of command line: -Rest infile {Input file name(s) of the floating point .fft or .[s]dat file(s). '.inf' file(s) of the same name must also exist} \ - -c 1 16384 +Rest infiles {One or more input file name(s) of the floating point .fft or .[s]dat file(s). '.inf' file(s) of the same name must also exist} diff --git a/src/accelsearch.c b/src/accelsearch.c index d5692cb7d..5106ae3e9 100644 --- a/src/accelsearch.c +++ b/src/accelsearch.c @@ -1,5 +1,12 @@ #include "accel.h" +#include +#include +#include +#include +#include +#include + /*#undef USEMMAP*/ #ifdef USEMMAP @@ -40,7 +47,7 @@ static void print_percent_complete(int current, int number, char *what, int rese } } -int main(int argc, char *argv[]) +static void accelsearch(Cmdline *cmd) { int ii, rstep; double ttim, utim, stim, tott; @@ -49,33 +56,11 @@ int main(int argc, char *argv[]) accelobs obs; infodata idata; GSList *cands = NULL; - Cmdline *cmd; /* Prep the timer */ tott = times(&runtimes) / (double) CLK_TCK; - /* Call usage() if we have no command line arguments */ - - if (argc == 1) { - Program = argv[0]; - printf("\n"); - usage(); - exit(1); - } - - /* Parse the command line using the excellent program Clig */ - - cmd = parseCmdline(argc, argv); - -#ifdef DEBUG - showOptionValues(); -#endif - - printf("\n\n"); - printf(" Fourier-Domain Acceleration and Jerk Search Routine\n"); - printf(" by Scott M. Ransom\n\n"); - /* Create the accelobs structure */ create_accelobs(&obs, &idata, cmd, 1); @@ -178,8 +163,8 @@ int main(int argc, char *argv[]) free_ffdotpows(fundamental); startr = nextr; } - } - + } + /* Reset indices if needed and search for real */ startr = obs.rlo; lastr = 0; @@ -276,7 +261,7 @@ int main(int argc, char *argv[]) /* Write the harmonics to the output text file */ output_harmonics(cands, &obs, &idata); - + /* Write the fundamental fourierprops to the cand file */ obs.workfile = chkfopen(obs.candnm, "wb"); chkfwrite(props, sizeof(fourierprops), numcands, obs.workfile); @@ -310,5 +295,80 @@ int main(int argc, char *argv[]) free_accelobs(&obs); g_slist_foreach(cands, free_accelcand, NULL); g_slist_free(cands); - return (0); +} + +int main(int argc, char *argv[]) +{ + int ii, err; + Cmdline *cmd; + + /* Parse the command line using the excellent program Clig */ + /* Call usage() if we have no command line arguments */ + if (argc == 1 || + (cmd = parseCmdline(argc, argv), cmd->argc < 1)) { + Program = argv[0]; + printf("\n"); + usage(); + exit(1); + } + +#ifdef DEBUG + showOptionValues(); +#endif + + printf("\n\n"); + printf(" Fourier-Domain Acceleration and Jerk Search Routine\n"); + printf(" by Scott M. Ransom\n\n"); + + for(ii = 0, err = 0; ii < cmd->argc && !err; ++ii) + { + int child_status; + pid_t pid; + + /* So that fork doesn't duplicate buffer contents ... + workaround for child processes calling exit(3) instead of _exit(2) + */ + fflush(stdout); + fflush(stderr); + + pid = fork(); + if(pid == 0) + { + /* This is the child process that does the real work */ + cmd->argc = 1; + cmd->argv[0] = cmd->argv[ii]; + accelsearch(cmd); + /* TODO: All invocations of exit(3) by accelsearch(...) should be changed to use _exit(2) */ + _exit(0); + } + /* This is the parent process, let's collect the child status and + stop on error. + */ + if(pid == -1) + { + fprintf(stderr, "\n%s: error calling worker process: ", argv[0]); + perror("fork"); + err = -1; + } + else if(waitpid(pid, &child_status, 0) < 1) + { + fprintf(stderr, "\n%s: error calling worker process: ", argv[0]); + perror("waitpid"); + err = -1; + } + else if(!WIFEXITED(child_status)) + { + fprintf(stderr, "\n%s: worker process terminated abnormally,", argv[0]); + err = -1; + } + else if(err = WEXITSTATUS(child_status)) + { + fprintf(stderr, "\n%s: error returned from worker process. Aborting ...", argv[0]); + } + if(err) + { + fprintf(stderr, " %d file%s left unprocessed.\n\n", cmd->argc - ii, cmd->argc - ii > 1 ? "s" : ""); + } + } + return err; } diff --git a/src/accelsearch_cmd.c b/src/accelsearch_cmd.c index 8deedccbc..2ddeea938 100644 --- a/src/accelsearch_cmd.c +++ b/src/accelsearch_cmd.c @@ -1,9 +1,10 @@ /***** command line parser -- generated by clig - (http://wsd.iitb.fhg.de/~kir/clighome/) + (http://BSDforge.com/projects/devel/clig/) The command line parser `clig': (C) 1995-2004 Harald Kirsch (clig@geggus.net) + (C) 2006-2015 Chris Hutchinson (portmaster@BSDforge.com) *****/ #include @@ -23,72 +24,72 @@ char *Program; static Cmdline cmd = { /***** -ncpus: Number of processors to use with OpenMP */ - /* ncpusP = */ 1, - /* ncpus = */ 1, - /* ncpusC = */ 1, + /* ncpusP = */ 1, + /* ncpus = */ 1, + /* ncpusC = */ 1, /***** -lobin: The first Fourier frequency in the data file */ - /* lobinP = */ 1, - /* lobin = */ 0, - /* lobinC = */ 1, + /* lobinP = */ 1, + /* lobin = */ 0, + /* lobinC = */ 1, /***** -numharm: The number of harmonics to sum (power-of-two) */ - /* numharmP = */ 1, - /* numharm = */ 8, - /* numharmC = */ 1, + /* numharmP = */ 1, + /* numharm = */ 8, + /* numharmC = */ 1, /***** -zmax: The max (+ and -) Fourier freq deriv to search */ - /* zmaxP = */ 1, - /* zmax = */ 200, - /* zmaxC = */ 1, + /* zmaxP = */ 1, + /* zmax = */ 200, + /* zmaxC = */ 1, /***** -wmax: The max (+ and -) Fourier freq double derivs to search */ - /* wmaxP = */ 0, - /* wmax = */ (int) 0, - /* wmaxC = */ 0, + /* wmaxP = */ 0, + /* wmax = */ (int)0, + /* wmaxC = */ 0, /***** -sigma: Cutoff sigma for choosing candidates */ - /* sigmaP = */ 1, - /* sigma = */ 2.0, - /* sigmaC = */ 1, + /* sigmaP = */ 1, + /* sigma = */ 2.0, + /* sigmaC = */ 1, /***** -rlo: The lowest Fourier frequency (of the highest harmonic!) to search */ - /* rloP = */ 0, - /* rlo = */ (double) 0, - /* rloC = */ 0, + /* rloP = */ 0, + /* rlo = */ (double)0, + /* rloC = */ 0, /***** -rhi: The highest Fourier frequency (of the highest harmonic!) to search */ - /* rhiP = */ 0, - /* rhi = */ (double) 0, - /* rhiC = */ 0, + /* rhiP = */ 0, + /* rhi = */ (double)0, + /* rhiC = */ 0, /***** -flo: The lowest frequency (Hz) (of the highest harmonic!) to search */ - /* floP = */ 1, - /* flo = */ 1.0, - /* floC = */ 1, + /* floP = */ 1, + /* flo = */ 1.0, + /* floC = */ 1, /***** -fhi: The highest frequency (Hz) (of the highest harmonic!) to search */ - /* fhiP = */ 1, - /* fhi = */ 10000.0, - /* fhiC = */ 1, + /* fhiP = */ 1, + /* fhi = */ 10000.0, + /* fhiC = */ 1, /***** -inmem: Compute full f-fdot plane in memory. Very fast, but only for short time series. */ - /* inmemP = */ 0, + /* inmemP = */ 0, /***** -photon: Data is poissonian so use freq 0 as power normalization */ - /* photonP = */ 0, + /* photonP = */ 0, /***** -median: Use block-median power normalization (default) */ - /* medianP = */ 0, + /* medianP = */ 0, /***** -locpow: Use double-tophat local-power normalization (not usually recommended) */ - /* locpowP = */ 0, + /* locpowP = */ 0, /***** -zaplist: A file of freqs+widths to zap from the FFT (only if the input file is a *.[s]dat file) */ - /* zaplistP = */ 0, - /* zaplist = */ (char *) 0, - /* zaplistC = */ 0, + /* zaplistP = */ 0, + /* zaplist = */ (char*)0, + /* zaplistC = */ 0, /***** -baryv: The radial velocity component (v/c) towards the target during the obs */ - /* baryvP = */ 1, - /* baryv = */ 0.0, - /* baryvC = */ 1, + /* baryvP = */ 1, + /* baryv = */ 0.0, + /* baryvC = */ 1, /***** -otheropt: Use the alternative optimization (for testing/debugging) */ - /* otheroptP = */ 0, + /* otheroptP = */ 0, /***** -noharmpolish: Do not use 'harmpolish' by default */ - /* noharmpolishP = */ 0, + /* noharmpolishP = */ 0, /***** -noharmremove: Do not remove harmonically related candidates (never removed for numharm = 1) */ - /* noharmremoveP = */ 0, + /* noharmremoveP = */ 0, /***** uninterpreted rest of command line */ - /* argc = */ 0, - /* argv = */ (char **) 0, + /* argc = */ 0, + /* argv = */ (char**)0, /***** the original command line concatenated */ - /* full_cmd_line = */ NULL + /* full_cmd_line = */ NULL }; /*@=null*/ @@ -106,1174 +107,1116 @@ static Cmdline cmd = { We don't use fabs to avoid linkage with -lm. *****/ -static void checkFloatConversion(double v, char *option, char *arg) +static void +checkFloatConversion(double v, char *option, char *arg) { - char *err = NULL; - - if ((errno == ERANGE && v != 0.0) /* even double overflowed */ - ||(v < HUGE_VAL && v > -HUGE_VAL && (v < 0.0 ? -v : v) > (double) FLT_MAX)) { - err = "large"; - } else if ((errno == ERANGE && v == 0.0) - || (v != 0.0 && (v < 0.0 ? -v : v) < (double) FLT_MIN)) { - err = "small"; - } - if (err) { - fprintf(stderr, - "%s: parameter `%s' of option `%s' to %s to represent\n", - Program, arg, option, err); - exit(EXIT_FAILURE); - } + char *err = NULL; + + if( (errno==ERANGE && v!=0.0) /* even double overflowed */ + || (v-HUGE_VAL && (v<0.0?-v:v)>(double)FLT_MAX) ) { + err = "large"; + } else if( (errno==ERANGE && v==0.0) + || (v!=0.0 && (v<0.0?-v:v)<(double)FLT_MIN) ) { + err = "small"; + } + if( err ) { + fprintf(stderr, + "%s: parameter `%s' of option `%s' to %s to represent\n", + Program, arg, option, err); + exit(EXIT_FAILURE); + } } -int getIntOpt(int argc, char **argv, int i, int *value, int force) +int +getIntOpt(int argc, char **argv, int i, int *value, int force) { - char *end; - long v; + char *end; + long v; - if (++i >= argc) - goto nothingFound; + if( ++i>=argc ) goto nothingFound; - errno = 0; - v = strtol(argv[i], &end, 0); + errno = 0; + v = strtol(argv[i], &end, 0); /***** check for conversion error */ - if (end == argv[i]) - goto nothingFound; + if( end==argv[i] ) goto nothingFound; /***** check for surplus non-whitespace */ - while (isspace((int) *end)) - end += 1; - if (*end) - goto nothingFound; + while( isspace((int) *end) ) end+=1; + if( *end ) goto nothingFound; /***** check if it fits into an int */ - if (errno == ERANGE || v > (long) INT_MAX || v < (long) INT_MIN) { - fprintf(stderr, - "%s: parameter `%s' of option `%s' to large to represent\n", - Program, argv[i], argv[i - 1]); - exit(EXIT_FAILURE); - } - *value = (int) v; + if( errno==ERANGE || v>(long)INT_MAX || v<(long)INT_MIN ) { + fprintf(stderr, + "%s: parameter `%s' of option `%s' to large to represent\n", + Program, argv[i], argv[i-1]); + exit(EXIT_FAILURE); + } + *value = (int)v; - return i; + return i; - nothingFound: - if (!force) - return i - 1; +nothingFound: + if( !force ) return i-1; - fprintf(stderr, - "%s: missing or malformed integer value after option `%s'\n", - Program, argv[i - 1]); + fprintf(stderr, + "%s: missing or malformed integer value after option `%s'\n", + Program, argv[i-1]); exit(EXIT_FAILURE); } - /**********************************************************************/ -int getIntOpts(int argc, char **argv, int i, int **values, int cmin, int cmax) +int +getIntOpts(int argc, char **argv, int i, + int **values, + int cmin, int cmax) /***** We want to find at least cmin values and at most cmax values. cmax==-1 then means infinitely many are allowed. *****/ { - int alloced, used; - char *end; - long v; - if (i + cmin >= argc) { - fprintf(stderr, - "%s: option `%s' wants at least %d parameters\n", - Program, argv[i], cmin); - exit(EXIT_FAILURE); - } + int alloced, used; + char *end; + long v; + if( i+cmin >= argc ) { + fprintf(stderr, + "%s: option `%s' wants at least %d parameters\n", + Program, argv[i], cmin); + exit(EXIT_FAILURE); + } - /***** + /***** alloc a bit more than cmin values. It does not hurt to have room for a bit more values than cmax. *****/ - alloced = cmin + 4; - *values = (int *) calloc((size_t) alloced, sizeof(int)); - if (!*values) { - outMem: - fprintf(stderr, - "%s: out of memory while parsing option `%s'\n", Program, argv[i]); - exit(EXIT_FAILURE); - } + alloced = cmin + 4; + *values = (int*)calloc((size_t)alloced, sizeof(int)); + if( ! *values ) { +outMem: + fprintf(stderr, + "%s: out of memory while parsing option `%s'\n", + Program, argv[i]); + exit(EXIT_FAILURE); + } - for (used = 0; (cmax == -1 || used < cmax) && used + i + 1 < argc; used++) { - if (used == alloced) { - alloced += 8; - *values = (int *) realloc(*values, alloced * sizeof(int)); - if (!*values) - goto outMem; - } + for(used=0; (cmax==-1 || used (long) INT_MAX || v < (long) INT_MIN) { - fprintf(stderr, - "%s: parameter `%s' of option `%s' to large to represent\n", - Program, argv[i + used + 1], argv[i]); - exit(EXIT_FAILURE); - } - - (*values)[used] = (int) v; - + if( errno==ERANGE || v>(long)INT_MAX || v<(long)INT_MIN ) { + fprintf(stderr, + "%s: parameter `%s' of option `%s' to large to represent\n", + Program, argv[i+used+1], argv[i]); + exit(EXIT_FAILURE); } - if (used < cmin) { - fprintf(stderr, - "%s: parameter `%s' of `%s' should be an " - "integer value\n", Program, argv[i + used + 1], argv[i]); - exit(EXIT_FAILURE); - } + (*values)[used] = (int)v; - return i + used; -} + } + + if( used= argc) - goto nothingFound; + if( ++i>=argc ) goto nothingFound; - errno = 0; - *value = strtol(argv[i], &end, 0); + errno = 0; + *value = strtol(argv[i], &end, 0); /***** check for conversion error */ - if (end == argv[i]) - goto nothingFound; + if( end==argv[i] ) goto nothingFound; /***** check for surplus non-whitespace */ - while (isspace((int) *end)) - end += 1; - if (*end) - goto nothingFound; + while( isspace((int) *end) ) end+=1; + if( *end ) goto nothingFound; /***** check for overflow */ - if (errno == ERANGE) { - fprintf(stderr, - "%s: parameter `%s' of option `%s' to large to represent\n", - Program, argv[i], argv[i - 1]); - exit(EXIT_FAILURE); - } - return i; + if( errno==ERANGE ) { + fprintf(stderr, + "%s: parameter `%s' of option `%s' to large to represent\n", + Program, argv[i], argv[i-1]); + exit(EXIT_FAILURE); + } + return i; - nothingFound: +nothingFound: /***** !force means: this parameter may be missing.*/ - if (!force) - return i - 1; + if( !force ) return i-1; - fprintf(stderr, - "%s: missing or malformed value after option `%s'\n", - Program, argv[i - 1]); + fprintf(stderr, + "%s: missing or malformed value after option `%s'\n", + Program, argv[i-1]); exit(EXIT_FAILURE); } - /**********************************************************************/ -int getLongOpts(int argc, char **argv, int i, long **values, int cmin, int cmax) +int +getLongOpts(int argc, char **argv, int i, + long **values, + int cmin, int cmax) /***** We want to find at least cmin values and at most cmax values. cmax==-1 then means infinitely many are allowed. *****/ { - int alloced, used; - char *end; - - if (i + cmin >= argc) { - fprintf(stderr, - "%s: option `%s' wants at least %d parameters\n", - Program, argv[i], cmin); - exit(EXIT_FAILURE); - } + int alloced, used; + char *end; + + if( i+cmin >= argc ) { + fprintf(stderr, + "%s: option `%s' wants at least %d parameters\n", + Program, argv[i], cmin); + exit(EXIT_FAILURE); + } - /***** + /***** alloc a bit more than cmin values. It does not hurt to have room for a bit more values than cmax. *****/ - alloced = cmin + 4; - *values = (long int *) calloc((size_t) alloced, sizeof(long)); - if (!*values) { - outMem: - fprintf(stderr, - "%s: out of memory while parsing option `%s'\n", Program, argv[i]); - exit(EXIT_FAILURE); - } + alloced = cmin + 4; + *values = (long int *)calloc((size_t)alloced, sizeof(long)); + if( ! *values ) { +outMem: + fprintf(stderr, + "%s: out of memory while parsing option `%s'\n", + Program, argv[i]); + exit(EXIT_FAILURE); + } - for (used = 0; (cmax == -1 || used < cmax) && used + i + 1 < argc; used++) { - if (used == alloced) { - alloced += 8; - *values = (long int *) realloc(*values, alloced * sizeof(long)); - if (!*values) - goto outMem; - } + for(used=0; (cmax==-1 || used= argc) - goto nothingFound; + if( ++i>=argc ) goto nothingFound; - errno = 0; - v = strtod(argv[i], &end); + errno = 0; + v = strtod(argv[i], &end); /***** check for conversion error */ - if (end == argv[i]) - goto nothingFound; + if( end==argv[i] ) goto nothingFound; /***** check for surplus non-whitespace */ - while (isspace((int) *end)) - end += 1; - if (*end) - goto nothingFound; + while( isspace((int) *end) ) end+=1; + if( *end ) goto nothingFound; /***** check for overflow */ - checkFloatConversion(v, argv[i - 1], argv[i]); - - *value = (float) v; + checkFloatConversion(v, argv[i-1], argv[i]); - return i; + *value = (float)v; - nothingFound: - if (!force) - return i - 1; + return i; - fprintf(stderr, - "%s: missing or malformed float value after option `%s'\n", - Program, argv[i - 1]); - exit(EXIT_FAILURE); +nothingFound: + if( !force ) return i-1; + fprintf(stderr, + "%s: missing or malformed float value after option `%s'\n", + Program, argv[i-1]); + exit(EXIT_FAILURE); + } - /**********************************************************************/ -int getFloatOpts(int argc, char **argv, int i, float **values, int cmin, int cmax) +int +getFloatOpts(int argc, char **argv, int i, + float **values, + int cmin, int cmax) /***** We want to find at least cmin values and at most cmax values. cmax==-1 then means infinitely many are allowed. *****/ { - int alloced, used; - char *end; - double v; - - if (i + cmin >= argc) { - fprintf(stderr, - "%s: option `%s' wants at least %d parameters\n", - Program, argv[i], cmin); - exit(EXIT_FAILURE); - } + int alloced, used; + char *end; + double v; + + if( i+cmin >= argc ) { + fprintf(stderr, + "%s: option `%s' wants at least %d parameters\n", + Program, argv[i], cmin); + exit(EXIT_FAILURE); + } - /***** + /***** alloc a bit more than cmin values. *****/ - alloced = cmin + 4; - *values = (float *) calloc((size_t) alloced, sizeof(float)); - if (!*values) { - outMem: - fprintf(stderr, - "%s: out of memory while parsing option `%s'\n", Program, argv[i]); - exit(EXIT_FAILURE); - } + alloced = cmin + 4; + *values = (float*)calloc((size_t)alloced, sizeof(float)); + if( ! *values ) { +outMem: + fprintf(stderr, + "%s: out of memory while parsing option `%s'\n", + Program, argv[i]); + exit(EXIT_FAILURE); + } - for (used = 0; (cmax == -1 || used < cmax) && used + i + 1 < argc; used++) { - if (used == alloced) { - alloced += 8; - *values = (float *) realloc(*values, alloced * sizeof(float)); - if (!*values) - goto outMem; - } + for(used=0; (cmax==-1 || used= argc) - goto nothingFound; + if( ++i>=argc ) goto nothingFound; - errno = 0; - *value = strtod(argv[i], &end); + errno = 0; + *value = strtod(argv[i], &end); /***** check for conversion error */ - if (end == argv[i]) - goto nothingFound; + if( end==argv[i] ) goto nothingFound; /***** check for surplus non-whitespace */ - while (isspace((int) *end)) - end += 1; - if (*end) - goto nothingFound; + while( isspace((int) *end) ) end+=1; + if( *end ) goto nothingFound; /***** check for overflow */ - if (errno == ERANGE) { - fprintf(stderr, - "%s: parameter `%s' of option `%s' to %s to represent\n", - Program, argv[i], argv[i - 1], (*value == 0.0 ? "small" : "large")); - exit(EXIT_FAILURE); - } - - return i; + if( errno==ERANGE ) { + fprintf(stderr, + "%s: parameter `%s' of option `%s' to %s to represent\n", + Program, argv[i], argv[i-1], + (*value==0.0 ? "small" : "large")); + exit(EXIT_FAILURE); + } - nothingFound: - if (!force) - return i - 1; + return i; - fprintf(stderr, - "%s: missing or malformed value after option `%s'\n", - Program, argv[i - 1]); - exit(EXIT_FAILURE); +nothingFound: + if( !force ) return i-1; + fprintf(stderr, + "%s: missing or malformed value after option `%s'\n", + Program, argv[i-1]); + exit(EXIT_FAILURE); + } - /**********************************************************************/ -int getDoubleOpts(int argc, char **argv, int i, double **values, int cmin, int cmax) +int +getDoubleOpts(int argc, char **argv, int i, + double **values, + int cmin, int cmax) /***** We want to find at least cmin values and at most cmax values. cmax==-1 then means infinitely many are allowed. *****/ { - int alloced, used; - char *end; - - if (i + cmin >= argc) { - fprintf(stderr, - "%s: option `%s' wants at least %d parameters\n", - Program, argv[i], cmin); - exit(EXIT_FAILURE); - } + int alloced, used; + char *end; + + if( i+cmin >= argc ) { + fprintf(stderr, + "%s: option `%s' wants at least %d parameters\n", + Program, argv[i], cmin); + exit(EXIT_FAILURE); + } - /***** + /***** alloc a bit more than cmin values. *****/ - alloced = cmin + 4; - *values = (double *) calloc((size_t) alloced, sizeof(double)); - if (!*values) { - outMem: - fprintf(stderr, - "%s: out of memory while parsing option `%s'\n", Program, argv[i]); - exit(EXIT_FAILURE); - } + alloced = cmin + 4; + *values = (double*)calloc((size_t)alloced, sizeof(double)); + if( ! *values ) { +outMem: + fprintf(stderr, + "%s: out of memory while parsing option `%s'\n", + Program, argv[i]); + exit(EXIT_FAILURE); + } - for (used = 0; (cmax == -1 || used < cmax) && used + i + 1 < argc; used++) { - if (used == alloced) { - alloced += 8; - *values = (double *) realloc(*values, alloced * sizeof(double)); - if (!*values) - goto outMem; - } + for(used=0; (cmax==-1 || used= argc) { - if (force) { - fprintf(stderr, "%s: missing string after option `%s'\n", - Program, argv[i - 1]); - exit(EXIT_FAILURE); - } - return i - 1; - } - - if (!force && argv[i][0] == '-') - return i - 1; - *value = argv[i]; - return i; + i += 1; + if( i>=argc ) { + if( force ) { + fprintf(stderr, "%s: missing string after option `%s'\n", + Program, argv[i-1]); + exit(EXIT_FAILURE); + } + return i-1; + } + + if( !force && argv[i][0] == '-' ) return i-1; + *value = argv[i]; + return i; } - /**********************************************************************/ -int getStringOpts(int argc, char **argv, int i, char * **values, int cmin, int cmax) +int +getStringOpts(int argc, char **argv, int i, + char* **values, + int cmin, int cmax) /***** We want to find at least cmin values and at most cmax values. cmax==-1 then means infinitely many are allowed. *****/ { - int alloced, used; - - if (i + cmin >= argc) { - fprintf(stderr, - "%s: option `%s' wants at least %d parameters\n", - Program, argv[i], cmin); - exit(EXIT_FAILURE); - } + int alloced, used; - alloced = cmin + 4; - - *values = (char **) calloc((size_t) alloced, sizeof(char *)); - if (!*values) { - outMem: - fprintf(stderr, - "%s: out of memory during parsing of option `%s'\n", - Program, argv[i]); - exit(EXIT_FAILURE); - } + if( i+cmin >= argc ) { + fprintf(stderr, + "%s: option `%s' wants at least %d parameters\n", + Program, argv[i], cmin); + exit(EXIT_FAILURE); + } + + alloced = cmin + 4; + + *values = (char**)calloc((size_t)alloced, sizeof(char*)); + if( ! *values ) { +outMem: + fprintf(stderr, + "%s: out of memory during parsing of option `%s'\n", + Program, argv[i]); + exit(EXIT_FAILURE); + } - for (used = 0; (cmax == -1 || used < cmax) && used + i + 1 < argc; used++) { - if (used == alloced) { - alloced += 8; - *values = (char **) realloc(*values, alloced * sizeof(char *)); - if (!*values) - goto outMem; - } - - if (used >= cmin && argv[used + i + 1][0] == '-') - break; - (*values)[used] = argv[used + i + 1]; + for(used=0; (cmax==-1 || used=cmin && argv[used+i+1][0]=='-' ) break; + (*values)[used] = argv[used+i+1]; + } + + if( used= min) - continue; - fprintf(stderr, - "%s: parameter %d of option `%s' smaller than min=%d\n", - Program, i + 1, opt, min); - exit(EXIT_FAILURE); - } -} + int i; + for(i=0; i=min ) continue; + fprintf(stderr, + "%s: parameter %d of option `%s' smaller than min=%d\n", + Program, i+1, opt, min); + exit(EXIT_FAILURE); + } +} /**********************************************************************/ -void checkLongLower(char *opt, long *values, int count, long max) +void +checkLongLower(char *opt, long *values, int count, long max) { - int i; - - for (i = 0; i < count; i++) { - if (values[i] <= max) - continue; - fprintf(stderr, - "%s: parameter %d of option `%s' greater than max=%ld\n", - Program, i + 1, opt, max); - exit(EXIT_FAILURE); - } -} + int i; + for(i=0; i= min) - continue; - fprintf(stderr, - "%s: parameter %d of option `%s' smaller than min=%ld\n", - Program, i + 1, opt, min); - exit(EXIT_FAILURE); - } -} + int i; + for(i=0; i=min ) continue; + fprintf(stderr, + "%s: parameter %d of option `%s' smaller than min=%ld\n", + Program, i+1, opt, min); + exit(EXIT_FAILURE); + } +} /**********************************************************************/ -void checkFloatLower(char *opt, float *values, int count, float max) +void +checkFloatLower(char *opt, float *values, int count, float max) { - int i; - - for (i = 0; i < count; i++) { - if (values[i] <= max) - continue; - fprintf(stderr, - "%s: parameter %d of option `%s' greater than max=%f\n", - Program, i + 1, opt, max); - exit(EXIT_FAILURE); - } -} + int i; + for(i=0; i= min) - continue; - fprintf(stderr, - "%s: parameter %d of option `%s' smaller than min=%f\n", - Program, i + 1, opt, min); - exit(EXIT_FAILURE); - } -} + int i; + for(i=0; i=min ) continue; + fprintf(stderr, + "%s: parameter %d of option `%s' smaller than min=%f\n", + Program, i+1, opt, min); + exit(EXIT_FAILURE); + } +} /**********************************************************************/ -void checkDoubleLower(char *opt, double *values, int count, double max) +void +checkDoubleLower(char *opt, double *values, int count, double max) { - int i; - - for (i = 0; i < count; i++) { - if (values[i] <= max) - continue; - fprintf(stderr, - "%s: parameter %d of option `%s' greater than max=%f\n", - Program, i + 1, opt, max); - exit(EXIT_FAILURE); - } -} + int i; + for(i=0; i= min) - continue; - fprintf(stderr, - "%s: parameter %d of option `%s' smaller than min=%f\n", - Program, i + 1, opt, min); - exit(EXIT_FAILURE); - } -} + int i; + for(i=0; i=min ) continue; + fprintf(stderr, + "%s: parameter %d of option `%s' smaller than min=%f\n", + Program, i+1, opt, min); + exit(EXIT_FAILURE); + } +} /**********************************************************************/ -static char *catArgv(int argc, char **argv) +static char * +catArgv(int argc, char **argv) { - int i; - size_t l; - char *s, *t; - - for (i = 0, l = 0; i < argc; i++) - l += (1 + strlen(argv[i])); - s = (char *) malloc(l); - if (!s) { - fprintf(stderr, "%s: out of memory\n", Program); - exit(EXIT_FAILURE); - } - strcpy(s, argv[0]); - t = s; - for (i = 1; i < argc; i++) { - t = t + strlen(t); - *t++ = ' '; - strcpy(t, argv[i]); - } - return s; + int i; + size_t l; + char *s, *t; + + for(i=0, l=0; i cmd.argc) { - fprintf(stderr, "%s: there should be at least 1 non-option argument(s)\n", - Program); - exit(EXIT_FAILURE); + int i; + + Program = argv[0]; + cmd.full_cmd_line = catArgv(argc, argv); + for(i=1, cmd.argc=1; i Date: Thu, 17 Dec 2020 19:10:45 +0800 Subject: [PATCH 4/4] Avoid calling external command for simple file operation to reduce the pressure on the clustered filesystem's metadata server. --- src/accel_utils.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/accel_utils.c b/src/accel_utils.c index cb0e70518..e3a4c2b34 100644 --- a/src/accel_utils.c +++ b/src/accel_utils.c @@ -1,6 +1,8 @@ #include "accel.h" #include "accelsearch_cmd.h" +#include + #if defined (__GNUC__) #define inline __inline__ #else @@ -828,13 +830,27 @@ void output_fundamentals(fourierprops * props, GSList * list, free(notes); } +static void filecat(char *dest, char *src) +{ + FILE *fp_dest, *fp_src; + char buf[4096]; + + fp_dest = chkfopen(dest, "a"); + fp_src = chkfopen(src, "r"); + while(!feof(fp_src) && !ferror(fp_src) && !ferror(fp_dest)) + { + fwrite(buf, 1, fread(buf, 1, sizeof(buf), fp_src), fp_dest); + } + fclose(fp_dest); + fclose(fp_src); +} void output_harmonics(GSList * list, accelobs * obs, infodata * idata) { int ii, jj, numcols = 15, numcands; int widths[15] = { 5, 4, 5, 15, 11, 18, 13, 12, 9, 12, 9, 12, 10, 10, 20 }; int errors[15] = { 0, 0, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 2, 2, 0 }; - char tmpstr[30], ctrstr[30], notes[21], *command; + char tmpstr[30], ctrstr[30], notes[21]; accelcand *cand; GSList *listptr; fourierprops props; @@ -960,10 +976,14 @@ void output_harmonics(GSList * list, accelobs * obs, infodata * idata) } fprintf(obs->workfile, "\n\n"); fclose(obs->workfile); - command = malloc(strlen(obs->rootfilenm) + strlen(obs->accelnm) + 20); - sprintf(command, "cat %s.inf >> %s", obs->rootfilenm, obs->accelnm); - system(command); - free(command); + { + char *infnm; + + infnm = malloc(strlen(obs->rootfilenm) + 5); + sprintf(infnm, "%s.inf", obs->rootfilenm); + filecat(obs->accelnm, infnm); + free(infnm); + } }