1411 lines
42 KiB
C
1411 lines
42 KiB
C
/*
|
|
Input and output parsing tools.
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include "logger.h"
|
|
#include "version.h"
|
|
#include "parsers.h"
|
|
#include "constants.h"
|
|
#include "geometry.h"
|
|
|
|
|
|
/* Parse basic command line arguments for programs */
|
|
int parse_basic_args(int argc, char **argv, const char *progname,
|
|
BASIC_ARGS *args, void (*print_help)(void))
|
|
{
|
|
int bad_args = 0, parsed_args = 0, total_args = 1, i;
|
|
char *params;
|
|
|
|
/* Default values for options */
|
|
args->verbose = 0;
|
|
args->logtofile = 0;
|
|
/* Parse arguments */
|
|
for(i = 1; i < argc; i++)
|
|
{
|
|
if(argv[i][0] == '-')
|
|
{
|
|
switch(argv[i][1])
|
|
{
|
|
case 'h':
|
|
if(argv[i][2] != '\0')
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
break;
|
|
}
|
|
print_help();
|
|
return 2;
|
|
case 'v':
|
|
if(argv[i][2] != '\0')
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
break;
|
|
}
|
|
if(args->verbose)
|
|
{
|
|
log_error("repeated option -v");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
args->verbose = 1;
|
|
break;
|
|
case 'l':
|
|
{
|
|
if(args->logtofile)
|
|
{
|
|
log_error("repeated option -l");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
params = &argv[i][2];
|
|
if(strlen(params) == 0)
|
|
{
|
|
log_error("bad input argument -l. Missing filename.");
|
|
bad_args++;
|
|
}
|
|
else
|
|
{
|
|
args->logtofile = 1;
|
|
args->logfname = params;
|
|
}
|
|
break;
|
|
}
|
|
case '-':
|
|
{
|
|
params = &argv[i][2];
|
|
if(strcmp(params, "version"))
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
}
|
|
else
|
|
{
|
|
print_version(progname);
|
|
return 2;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(parsed_args == 0)
|
|
{
|
|
args->inputfname = argv[i];
|
|
parsed_args++;
|
|
}
|
|
else
|
|
{
|
|
log_error("invalid argument '%s'. Already given model file %s",
|
|
argv[i], args->inputfname);
|
|
bad_args++;
|
|
}
|
|
}
|
|
}
|
|
/* Check if parsing went well */
|
|
if(parsed_args > total_args)
|
|
{
|
|
log_error("%s: too many input arguments. given %d, max %d.",
|
|
progname, parsed_args, total_args);
|
|
}
|
|
if(bad_args > 0)
|
|
{
|
|
log_error("%d bad input argument(s)", bad_args);
|
|
return 1;
|
|
}
|
|
if(parsed_args < total_args)
|
|
{
|
|
return 3;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* Parse command line arguments for tess2prism program */
|
|
int parse_tess2prism_args(int argc, char **argv, const char *progname,
|
|
TESS2PRISM_ARGS *args, void (*print_help)(void))
|
|
{
|
|
int bad_args = 0, parsed_args = 0, total_args = 1, i;
|
|
char *params;
|
|
|
|
/* Default values for options */
|
|
args->verbose = 0;
|
|
args->logtofile = 0;
|
|
args->flatten = 0;
|
|
/* Parse arguments */
|
|
for(i = 1; i < argc; i++)
|
|
{
|
|
if(argv[i][0] == '-')
|
|
{
|
|
switch(argv[i][1])
|
|
{
|
|
case 'h':
|
|
if(argv[i][2] != '\0')
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
break;
|
|
}
|
|
print_help();
|
|
return 2;
|
|
case 'v':
|
|
if(argv[i][2] != '\0')
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
break;
|
|
}
|
|
if(args->verbose)
|
|
{
|
|
log_error("repeated option -v");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
args->verbose = 1;
|
|
break;
|
|
|
|
case 'l':
|
|
{
|
|
if(args->logtofile)
|
|
{
|
|
log_error("repeated option -l");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
params = &argv[i][2];
|
|
if(strlen(params) == 0)
|
|
{
|
|
log_error("bad input argument -l. Missing filename.");
|
|
bad_args++;
|
|
}
|
|
else
|
|
{
|
|
args->logtofile = 1;
|
|
args->logfname = params;
|
|
}
|
|
break;
|
|
}
|
|
case '-':
|
|
{
|
|
params = &argv[i][2];
|
|
if(!strcmp(params, "version"))
|
|
{
|
|
print_version(progname);
|
|
return 2;
|
|
}
|
|
else if(!strcmp(params, "flatten"))
|
|
{
|
|
args->flatten = 1;
|
|
}
|
|
else
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(parsed_args == 0)
|
|
{
|
|
args->inputfname = argv[i];
|
|
parsed_args++;
|
|
}
|
|
else
|
|
{
|
|
log_error("invalid argument '%s'. Already given model file %s",
|
|
argv[i], args->inputfname);
|
|
bad_args++;
|
|
}
|
|
}
|
|
}
|
|
/* Check if parsing went well */
|
|
if(parsed_args > total_args)
|
|
{
|
|
log_error("%s: too many input arguments. given %d, max %d.",
|
|
progname, parsed_args, total_args);
|
|
}
|
|
if(bad_args > 0)
|
|
{
|
|
log_error("%d bad input argument(s)", bad_args);
|
|
return 1;
|
|
}
|
|
if(parsed_args < total_args)
|
|
{
|
|
return 3;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* Parse command line arguments for tessmass program */
|
|
int parse_tessmass_args(int argc, char **argv, const char *progname,
|
|
TESSMASS_ARGS *args, void (*print_help)(void))
|
|
{
|
|
int bad_args = 0, parsed_args = 0, total_args = 1, parsed_r = 0, i, nchar,
|
|
nread;
|
|
char *params;
|
|
|
|
/* Default values for options */
|
|
args->verbose = 0;
|
|
args->logtofile = 0;
|
|
args->use_range = 0;
|
|
/* Parse arguments */
|
|
for(i = 1; i < argc; i++)
|
|
{
|
|
if(argv[i][0] == '-')
|
|
{
|
|
switch(argv[i][1])
|
|
{
|
|
case 'h':
|
|
if(argv[i][2] != '\0')
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
break;
|
|
}
|
|
print_help();
|
|
return 2;
|
|
case 'v':
|
|
if(argv[i][2] != '\0')
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
break;
|
|
}
|
|
if(args->verbose)
|
|
{
|
|
log_error("repeated option -v");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
args->verbose = 1;
|
|
break;
|
|
|
|
case 'l':
|
|
{
|
|
if(args->logtofile)
|
|
{
|
|
log_error("repeated option -l");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
params = &argv[i][2];
|
|
if(strlen(params) == 0)
|
|
{
|
|
log_error("bad input argument -l. Missing filename.");
|
|
bad_args++;
|
|
}
|
|
else
|
|
{
|
|
args->logtofile = 1;
|
|
args->logfname = params;
|
|
}
|
|
break;
|
|
}
|
|
case '-':
|
|
{
|
|
params = &argv[i][2];
|
|
if(strcmp(params, "version"))
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
}
|
|
else
|
|
{
|
|
print_version(progname);
|
|
return 2;
|
|
}
|
|
break;
|
|
}
|
|
case 'r':
|
|
{
|
|
if(parsed_r)
|
|
{
|
|
log_error("repeated argument -r");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
params = &argv[i][2];
|
|
nchar = 0;
|
|
nread = sscanf(params, "%lf/%lf%n", &(args->low_dens),
|
|
&(args->high_dens), &nchar);
|
|
if(nread != 2 || *(params + nchar) != '\0')
|
|
{
|
|
log_error("bad input argument '%s'", argv[i]);
|
|
bad_args++;
|
|
}
|
|
parsed_r = 1;
|
|
args->use_range = 1;
|
|
break;
|
|
}
|
|
default:
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(parsed_args == 0)
|
|
{
|
|
args->inputfname = argv[i];
|
|
parsed_args++;
|
|
}
|
|
else
|
|
{
|
|
log_error("invalid argument '%s'. Already given model file %s",
|
|
argv[i], args->inputfname);
|
|
bad_args++;
|
|
}
|
|
}
|
|
}
|
|
/* Check if parsing went well */
|
|
if(parsed_args > total_args)
|
|
{
|
|
log_error("%s: too many input arguments. given %d, max %d.",
|
|
progname, parsed_args, total_args);
|
|
}
|
|
if(bad_args > 0)
|
|
{
|
|
log_error("%d bad input argument(s)", bad_args);
|
|
return 1;
|
|
}
|
|
if(parsed_args < total_args)
|
|
{
|
|
return 3;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* Parse command line arguments for tessmodgen program */
|
|
int parse_tessmodgen_args(int argc, char **argv, const char *progname,
|
|
TESSMODGEN_ARGS *args, void (*print_help)(void))
|
|
{
|
|
int bad_args = 0, parsed_args = 0, total_args = 2, parsed_s = 0,
|
|
parsed_z = 0, parsed_d = 0, i, nchar, nread;
|
|
char *params;
|
|
|
|
/* Default values for options */
|
|
args->verbose = 0;
|
|
args->logtofile = 0;
|
|
args->fix_density = 0;
|
|
/* Parse arguments */
|
|
for(i = 1; i < argc; i++)
|
|
{
|
|
if(argv[i][0] == '-')
|
|
{
|
|
switch(argv[i][1])
|
|
{
|
|
case 'h':
|
|
if(argv[i][2] != '\0')
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
break;
|
|
}
|
|
print_help();
|
|
return 2;
|
|
case 'v':
|
|
if(argv[i][2] != '\0')
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
break;
|
|
}
|
|
if(args->verbose)
|
|
{
|
|
log_error("repeated option -v");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
args->verbose = 1;
|
|
break;
|
|
case 'l':
|
|
{
|
|
if(args->logtofile)
|
|
{
|
|
log_error("repeated option -l");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
params = &argv[i][2];
|
|
if(strlen(params) == 0)
|
|
{
|
|
log_error("bad input argument -l. Missing filename.");
|
|
bad_args++;
|
|
}
|
|
else
|
|
{
|
|
args->logtofile = 1;
|
|
args->logfname = params;
|
|
}
|
|
break;
|
|
}
|
|
case '-':
|
|
{
|
|
params = &argv[i][2];
|
|
if(strcmp(params, "version"))
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
}
|
|
else
|
|
{
|
|
print_version(progname);
|
|
return 2;
|
|
}
|
|
break;
|
|
}
|
|
case 's':
|
|
{
|
|
if(parsed_s)
|
|
{
|
|
log_error("repeated argument -s");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
params = &argv[i][2];
|
|
nchar = 0;
|
|
nread = sscanf(params, "%lf/%lf%n", &(args->dlon),
|
|
&(args->dlat), &nchar);
|
|
if(nread != 2 || *(params + nchar) != '\0')
|
|
{
|
|
log_error("bad input argument '%s'", argv[i]);
|
|
bad_args++;
|
|
}
|
|
parsed_s = 1;
|
|
parsed_args++;
|
|
break;
|
|
}
|
|
case 'z':
|
|
{
|
|
if(parsed_z)
|
|
{
|
|
log_error("repeated argument -z");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
params = &argv[i][2];
|
|
nchar = 0;
|
|
nread = sscanf(params, "%lf%n", &(args->ref), &nchar);
|
|
if(nread != 1 || *(params + nchar) != '\0')
|
|
{
|
|
log_error("bad input argument '%s'", argv[i]);
|
|
bad_args++;
|
|
}
|
|
parsed_z = 1;
|
|
parsed_args++;
|
|
break;
|
|
}
|
|
case 'd':
|
|
{
|
|
if(parsed_d)
|
|
{
|
|
log_error("repeated argument -d");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
params = &argv[i][2];
|
|
nchar = 0;
|
|
nread = sscanf(params, "%lf%n", &(args->dens), &nchar);
|
|
if(nread != 1 || *(params + nchar) != '\0')
|
|
{
|
|
log_error("bad input argument '%s'", argv[i]);
|
|
bad_args++;
|
|
}
|
|
parsed_d = 1;
|
|
args->fix_density = 1;
|
|
break;
|
|
}
|
|
default:
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
}
|
|
}
|
|
/* Check if parsing went well */
|
|
if(bad_args > 0 || parsed_args != total_args)
|
|
{
|
|
if(parsed_args < total_args)
|
|
{
|
|
log_error("%s: missing input arguments. given %d out of %d.",
|
|
progname, parsed_args, total_args);
|
|
}
|
|
if(parsed_args > total_args)
|
|
{
|
|
log_error("%s: too many input arguments. given %d, max %d.",
|
|
progname, parsed_args, total_args);
|
|
}
|
|
if(bad_args > 0)
|
|
{
|
|
log_error("%d bad input argument(s)", bad_args);
|
|
}
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* Parse command line arguments for tesslayers program */
|
|
int parse_tesslayers_args(int argc, char **argv, const char *progname,
|
|
TESSLAYERS_ARGS *args, void (*print_help)(void))
|
|
{
|
|
int bad_args = 0, parsed_args = 0, total_args = 1, parsed_s = 0,
|
|
i, nchar, nread;
|
|
char *params;
|
|
|
|
/* Default values for options */
|
|
args->verbose = 0;
|
|
args->logtofile = 0;
|
|
/* Parse arguments */
|
|
for(i = 1; i < argc; i++)
|
|
{
|
|
if(argv[i][0] == '-')
|
|
{
|
|
switch(argv[i][1])
|
|
{
|
|
case 'h':
|
|
if(argv[i][2] != '\0')
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
break;
|
|
}
|
|
print_help();
|
|
return 2;
|
|
case 'v':
|
|
if(argv[i][2] != '\0')
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
break;
|
|
}
|
|
if(args->verbose)
|
|
{
|
|
log_error("repeated option -v");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
args->verbose = 1;
|
|
break;
|
|
case 'l':
|
|
{
|
|
if(args->logtofile)
|
|
{
|
|
log_error("repeated option -l");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
params = &argv[i][2];
|
|
if(strlen(params) == 0)
|
|
{
|
|
log_error("bad input argument -l. Missing filename.");
|
|
bad_args++;
|
|
}
|
|
else
|
|
{
|
|
args->logtofile = 1;
|
|
args->logfname = params;
|
|
}
|
|
break;
|
|
}
|
|
case '-':
|
|
{
|
|
params = &argv[i][2];
|
|
if(strcmp(params, "version"))
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
}
|
|
else
|
|
{
|
|
print_version(progname);
|
|
return 2;
|
|
}
|
|
break;
|
|
}
|
|
case 's':
|
|
{
|
|
if(parsed_s)
|
|
{
|
|
log_error("repeated argument -s");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
params = &argv[i][2];
|
|
nchar = 0;
|
|
nread = sscanf(params, "%lf/%lf%n", &(args->dlon),
|
|
&(args->dlat), &nchar);
|
|
if(nread != 2 || *(params + nchar) != '\0')
|
|
{
|
|
log_error("bad input argument '%s'", argv[i]);
|
|
bad_args++;
|
|
}
|
|
parsed_s = 1;
|
|
parsed_args++;
|
|
break;
|
|
}
|
|
default:
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
}
|
|
}
|
|
/* Check if parsing went well */
|
|
if(bad_args > 0 || parsed_args != total_args)
|
|
{
|
|
if(parsed_args < total_args)
|
|
{
|
|
log_error("%s: missing input arguments. given %d out of %d.",
|
|
progname, parsed_args, total_args);
|
|
}
|
|
if(parsed_args > total_args)
|
|
{
|
|
log_error("%s: too many input arguments. given %d, max %d.",
|
|
progname, parsed_args, total_args);
|
|
}
|
|
if(bad_args > 0)
|
|
{
|
|
log_error("%d bad input argument(s)", bad_args);
|
|
}
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* Parse command line arguments for tessg* programs */
|
|
int parse_tessg_args(int argc, char **argv, const char *progname,
|
|
TESSG_ARGS *args, void (*print_help)(const char *))
|
|
{
|
|
int bad_args = 0, parsed_args = 0, total_args = 1, parsed_order = 0,
|
|
parsed_ratio = 0, i, nchar, nread;
|
|
char *params;
|
|
|
|
/* Default values for options */
|
|
args->verbose = 0;
|
|
args->logtofile = 0;
|
|
args->lon_order = 2;
|
|
args->lat_order = 2;
|
|
args->r_order = 2;
|
|
args->adaptative = 1;
|
|
args->ratio = 0; /* zero means use the default for the program */
|
|
/* Parse arguments */
|
|
for(i = 1; i < argc; i++)
|
|
{
|
|
if(argv[i][0] == '-')
|
|
{
|
|
switch(argv[i][1])
|
|
{
|
|
case 'h':
|
|
if(argv[i][2] != '\0')
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
break;
|
|
}
|
|
print_help(progname);
|
|
return 2;
|
|
case 'v':
|
|
if(argv[i][2] != '\0')
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
break;
|
|
}
|
|
if(args->verbose)
|
|
{
|
|
log_error("repeated option -v");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
args->verbose = 1;
|
|
break;
|
|
case 'l':
|
|
{
|
|
if(args->logtofile)
|
|
{
|
|
log_error("repeated option -l");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
params = &argv[i][2];
|
|
if(strlen(params) == 0)
|
|
{
|
|
log_error("bad input argument -l. Missing filename.");
|
|
bad_args++;
|
|
}
|
|
else
|
|
{
|
|
args->logtofile = 1;
|
|
args->logfname = params;
|
|
}
|
|
break;
|
|
}
|
|
case '-':
|
|
{
|
|
params = &argv[i][2];
|
|
if(strcmp(params, "version"))
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
}
|
|
else
|
|
{
|
|
print_version(progname);
|
|
return 2;
|
|
}
|
|
break;
|
|
}
|
|
case 'a':
|
|
if(argv[i][2] != '\0')
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
break;
|
|
}
|
|
if(!args->adaptative)
|
|
{
|
|
log_error("repeated option -a");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
args->adaptative = 0;
|
|
break;
|
|
case 'o':
|
|
{
|
|
if(parsed_order)
|
|
{
|
|
log_error("repeated option -o");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
params = &argv[i][2];
|
|
nchar = 0;
|
|
nread = sscanf(params, "%d/%d/%d%n", &(args->lon_order),
|
|
&(args->lat_order), &(args->r_order), &nchar);
|
|
if(nread != 3 || *(params + nchar) != '\0')
|
|
{
|
|
log_error("bad input argument '%s'", argv[i]);
|
|
bad_args++;
|
|
}
|
|
parsed_order = 1;
|
|
break;
|
|
}
|
|
case 't':
|
|
{
|
|
if(parsed_ratio)
|
|
{
|
|
log_error("repeated option -t");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
params = &argv[i][2];
|
|
nchar = 0;
|
|
nread = sscanf(params, "%lf%n", &(args->ratio), &nchar);
|
|
if(nread != 1 || *(params + nchar) != '\0')
|
|
{
|
|
log_error("bad input argument '%s'", argv[i]);
|
|
bad_args++;
|
|
}
|
|
parsed_ratio = 1;
|
|
break;
|
|
}
|
|
default:
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(parsed_args == 0)
|
|
{
|
|
args->modelfname = argv[i];
|
|
parsed_args++;
|
|
}
|
|
else
|
|
{
|
|
log_error("invalid argument '%s'. Already given model file %s",
|
|
argv[i], args->modelfname);
|
|
bad_args++;
|
|
}
|
|
}
|
|
}
|
|
/* Check if parsing went well */
|
|
if(bad_args > 0 || parsed_args != total_args)
|
|
{
|
|
if(parsed_args < total_args)
|
|
{
|
|
log_error("%s: missing input file.",
|
|
progname, parsed_args, total_args);
|
|
}
|
|
if(parsed_args > total_args)
|
|
{
|
|
log_error("%s: too many input arguments. given %d, max %d.",
|
|
progname, parsed_args, total_args);
|
|
}
|
|
if(bad_args > 0)
|
|
{
|
|
log_error("%d bad input argument(s)", bad_args);
|
|
}
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* Parse command line arguments for tessgrd program */
|
|
int parse_tessgrd_args(int argc, char **argv, TESSGRD_ARGS *args,
|
|
void (*print_help)(void))
|
|
{
|
|
int bad_args = 0, parsed_args = 0, total_args = 3, parsed_r = 0,
|
|
parsed_b = 0, parsed_z = 0, i, nchar, nread;
|
|
char progname[] = "tessgrd", *params;
|
|
|
|
/* Default values for options */
|
|
args->verbose = 0;
|
|
args->logtofile = 0;
|
|
/* Parse arguments */
|
|
for(i = 1; i < argc; i++)
|
|
{
|
|
if(argv[i][0] == '-')
|
|
{
|
|
switch(argv[i][1])
|
|
{
|
|
case 'h':
|
|
if(argv[i][2] != '\0')
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
break;
|
|
}
|
|
print_help();
|
|
return 2;
|
|
case 'v':
|
|
if(argv[i][2] != '\0')
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
break;
|
|
}
|
|
if(args->verbose)
|
|
{
|
|
log_error("repeated option -v");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
args->verbose = 1;
|
|
break;
|
|
|
|
case 'l':
|
|
{
|
|
if(args->logtofile)
|
|
{
|
|
log_error("repeated option -l");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
params = &argv[i][2];
|
|
if(strlen(params) == 0)
|
|
{
|
|
log_error("bad input argument -l. Missing filename.");
|
|
bad_args++;
|
|
}
|
|
else
|
|
{
|
|
args->logtofile = 1;
|
|
args->logfname = params;
|
|
}
|
|
break;
|
|
}
|
|
case '-':
|
|
{
|
|
params = &argv[i][2];
|
|
if(strcmp(params, "version"))
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
}
|
|
else
|
|
{
|
|
print_version(progname);
|
|
return 2;
|
|
}
|
|
break;
|
|
}
|
|
case 'r':
|
|
{
|
|
if(parsed_r)
|
|
{
|
|
log_error("repeated argument -r");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
params = &argv[i][2];
|
|
nchar = 0;
|
|
nread = sscanf(params, "%lf/%lf/%lf/%lf%n", &(args->w),
|
|
&(args->e), &(args->s), &(args->n), &nchar);
|
|
if(nread != 4 || *(params + nchar) != '\0')
|
|
{
|
|
log_error("bad input argument '%s'", argv[i]);
|
|
bad_args++;
|
|
}
|
|
parsed_args++;
|
|
parsed_r = 1;
|
|
break;
|
|
}
|
|
case 'b':
|
|
{
|
|
if(parsed_b)
|
|
{
|
|
log_error("repeated argument -b");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
params = &argv[i][2];
|
|
nchar = 0;
|
|
nread = sscanf(params, "%d/%d%n", &(args->nlon),
|
|
&(args->nlat), &nchar);
|
|
if(nread != 2 || *(params + nchar) != '\0')
|
|
{
|
|
log_error("bad input argument '%s'", argv[i]);
|
|
bad_args++;
|
|
}
|
|
parsed_args++;
|
|
parsed_b = 1;
|
|
break;
|
|
}
|
|
case 'z':
|
|
{
|
|
if(parsed_z)
|
|
{
|
|
log_error("repeated argument -z");
|
|
bad_args++;
|
|
break;
|
|
}
|
|
params = &argv[i][2];
|
|
nchar = 0;
|
|
nread = sscanf(params, "%lf%n", &(args->height), &nchar);
|
|
if(nread != 1 || *(params + nchar) != '\0')
|
|
{
|
|
log_error("bad input argument '%s'", argv[i]);
|
|
bad_args++;
|
|
}
|
|
parsed_args++;
|
|
parsed_z = 1;
|
|
break;
|
|
}
|
|
default:
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
log_error("invalid argument '%s'", argv[i]);
|
|
bad_args++;
|
|
}
|
|
}
|
|
/* Check if parsing went well */
|
|
if(bad_args > 0 || parsed_args != total_args)
|
|
{
|
|
if(parsed_args < total_args)
|
|
{
|
|
log_error("%s: missing input arguments. given %d out of %d.",
|
|
progname, parsed_args, total_args);
|
|
}
|
|
if(parsed_args > total_args)
|
|
{
|
|
log_error("%s: too many input arguments. given %d, max %d.",
|
|
progname, parsed_args, total_args);
|
|
}
|
|
if(bad_args > 0)
|
|
{
|
|
log_error("%d bad input argument(s)", bad_args);
|
|
}
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* Strip trailing spaces and newlines from the end of a string */
|
|
void strstrip(char *str)
|
|
{
|
|
int i;
|
|
for(i = strlen(str) - 1; i >= 0; i--)
|
|
{
|
|
if(str[i] != ' ' && str[i] != '\n' && str[i] != '\r' && str[i] != '\0')
|
|
break;
|
|
}
|
|
str[i + 1] = '\0';
|
|
}
|
|
|
|
|
|
/* Read a single tesseroid from a string */
|
|
int gets_tess(const char *str, TESSEROID *tess)
|
|
{
|
|
double w, e, s, n, top, bot, dens;
|
|
int nread, nchars;
|
|
|
|
nread = sscanf(str, "%lf %lf %lf %lf %lf %lf %lf%n", &w, &e, &s,
|
|
&n, &top, &bot, &dens, &nchars);
|
|
if(nread != 7 || str[nchars] != '\0')
|
|
{
|
|
/* Something wrong with the tesseroid string */
|
|
return 1;
|
|
}
|
|
if((w > e) || (s > n) || (top < bot))
|
|
{
|
|
/* Model bounds in wrong order */
|
|
return 2;
|
|
}
|
|
if((w == e) || (s == n) || (top == bot))
|
|
{
|
|
/* Tesseroid has zero volume */
|
|
return 3;
|
|
}
|
|
tess->w = w;
|
|
tess->e = e;
|
|
tess->s = s;
|
|
tess->n = n;
|
|
tess->r1 = MEAN_EARTH_RADIUS + bot;
|
|
tess->r2 = MEAN_EARTH_RADIUS + top;
|
|
tess->density = dens;
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* Read tesseroids from an open file and store them in an array */
|
|
TESSEROID * read_tess_model(FILE *modelfile, int *size)
|
|
{
|
|
TESSEROID *model, *tmp;
|
|
int buffsize = 100, line, badinput = 0, error_exit = 0, gets_error;
|
|
char sbuff[10000];
|
|
|
|
/* Start with a single buffer allocation and expand later if necessary */
|
|
model = (TESSEROID *)malloc(buffsize*sizeof(TESSEROID));
|
|
if(model == NULL)
|
|
{
|
|
log_error("problem allocating initial memory to load tesseroid model.");
|
|
return NULL;
|
|
}
|
|
*size = 0;
|
|
for(line = 1; !feof(modelfile); line++)
|
|
{
|
|
if(fgets(sbuff, 10000, modelfile) == NULL)
|
|
{
|
|
if(ferror(modelfile))
|
|
{
|
|
log_error("problem encountered reading line %d.", line);
|
|
error_exit = 1;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Check for comments and blank lines */
|
|
if(sbuff[0] == '#' || sbuff[0] == '\r' || sbuff[0] == '\n')
|
|
{
|
|
continue;
|
|
}
|
|
if(*size == buffsize)
|
|
{
|
|
buffsize += buffsize;
|
|
tmp = (TESSEROID *)realloc(model, buffsize*sizeof(TESSEROID));
|
|
if(tmp == NULL)
|
|
{
|
|
/* Need to free because realloc leaves unchanged in case of
|
|
error */
|
|
free(model);
|
|
log_error("problem expanding memory for tesseroid model. Model is too big.");
|
|
return NULL;
|
|
}
|
|
model = tmp;
|
|
}
|
|
/* Remove any trailing spaces or newlines */
|
|
strstrip(sbuff);
|
|
gets_error = gets_tess(sbuff, &model[*size]);
|
|
if(gets_error == 1)
|
|
{
|
|
log_error("bad/invalid tesseroid at line %d.", line);
|
|
badinput = 1;
|
|
continue;
|
|
}
|
|
if(gets_error == 2)
|
|
{
|
|
log_error("invalid tesseroid dimensions at line %d. Must be w < e, s < n, top > bottom.", line);
|
|
badinput = 1;
|
|
continue;
|
|
}
|
|
if(gets_error == 3)
|
|
{
|
|
log_warning("ignoring tesseroid with zero volume at line %d. This should not impact the computations.", line);
|
|
continue;
|
|
}
|
|
(*size)++;
|
|
}
|
|
}
|
|
if(badinput || error_exit)
|
|
{
|
|
free(model);
|
|
return NULL;
|
|
}
|
|
/* Adjust the size of the model */
|
|
if(*size != 0)
|
|
{
|
|
tmp = (TESSEROID *)realloc(model, (*size)*sizeof(TESSEROID));
|
|
if(tmp == NULL)
|
|
{
|
|
/* Need to free because realloc leaves unchanged in case of
|
|
error */
|
|
free(model);
|
|
log_error("problem freeing excess memory for tesseroid model.");
|
|
return NULL;
|
|
}
|
|
model = tmp;
|
|
}
|
|
return model;
|
|
}
|
|
|
|
|
|
/* Read a single rectangular prism from a string */
|
|
int gets_prism(const char *str, PRISM *prism)
|
|
{
|
|
double x1, x2, y1, y2, z1, z2, dens;
|
|
int nread, nchars;
|
|
|
|
nread = sscanf(str, "%lf %lf %lf %lf %lf %lf %lf%n", &x1, &x2, &y1, &y2,
|
|
&z1, &z2, &dens, &nchars);
|
|
/* Check if there are extra characters in the line. This indicates
|
|
* that the model is wrong or was generated by tess2prism without the
|
|
* --flatten flag */
|
|
if(nread != 7 || str[nchars] != '\0')
|
|
{
|
|
return 1;
|
|
}
|
|
prism->x1 = x1;
|
|
prism->x2 = x2;
|
|
prism->y1 = y1;
|
|
prism->y2 = y2;
|
|
prism->z1 = z1;
|
|
prism->z2 = z2;
|
|
prism->density = dens;
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* Read a single rectangular prism and the spherical coordinates of its top
|
|
from a string */
|
|
int gets_prism_sph(const char *str, PRISM *prism)
|
|
{
|
|
double dx, dy, dz, dens, lon, lat, r;
|
|
int nread, nchars;
|
|
|
|
nread = sscanf(str, "%lf %lf %lf %lf %lf %lf %lf%n",
|
|
&dx, &dy, &dz, &dens, &lon, &lat, &r, &nchars);
|
|
/* Check if there are extra characters in the line. This indicates
|
|
* that the model is wrong or was generated by tess2prism without the
|
|
* --flatten flag */
|
|
if(nread != 7 || str[nchars] != '\0')
|
|
{
|
|
return 1;
|
|
}
|
|
prism->x1 = -0.5*dx;
|
|
prism->x2 = 0.5*dx;
|
|
prism->y1 = -0.5*dy;
|
|
prism->y2 = 0.5*dy;
|
|
prism->z1 = 0.;
|
|
prism->z2 = dz;
|
|
prism->density = dens;
|
|
prism->lon = lon;
|
|
prism->lat = lat;
|
|
prism->r = r;
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* Read rectangular prisms from an open file and store them in an array. */
|
|
PRISM * read_prism_model(FILE *modelfile, int pos, int *size)
|
|
{
|
|
PRISM *model, *tmp;
|
|
int buffsize = 100, line, badinput = 0, error_exit = 0;
|
|
char sbuff[10000];
|
|
|
|
/* Start with a single buffer allocation and expand later if necessary */
|
|
model = (PRISM *)malloc(buffsize*sizeof(PRISM));
|
|
if(model == NULL)
|
|
{
|
|
log_error("problem allocating initial memory to load prism model.");
|
|
return NULL;
|
|
}
|
|
*size = 0;
|
|
for(line = 1; !feof(modelfile); line++)
|
|
{
|
|
if(fgets(sbuff, 10000, modelfile) == NULL)
|
|
{
|
|
if(ferror(modelfile))
|
|
{
|
|
log_error("problem encountered reading line %d.", line);
|
|
error_exit = 1;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Check for comments and blank lines */
|
|
if(sbuff[0] == '#' || sbuff[0] == '\r' || sbuff[0] == '\n')
|
|
{
|
|
continue;
|
|
}
|
|
if(*size == buffsize)
|
|
{
|
|
buffsize += buffsize;
|
|
tmp = (PRISM *)realloc(model, buffsize*sizeof(PRISM));
|
|
if(tmp == NULL)
|
|
{
|
|
/* Need to free because realloc leaves unchanged in case of
|
|
error */
|
|
free(model);
|
|
log_error("problem expanding memory for prism model.\nModel is too big.");
|
|
return NULL;
|
|
}
|
|
model = tmp;
|
|
}
|
|
/* Remove any trailing spaces or newlines */
|
|
strstrip(sbuff);
|
|
/* Check if r, lon, lat are expected as well */
|
|
if(pos)
|
|
{
|
|
if(gets_prism_sph(sbuff, &model[*size]))
|
|
{
|
|
log_warning(
|
|
"bad/invalid prism at line %d.",
|
|
line);
|
|
badinput = 1;
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(gets_prism(sbuff, &model[*size]))
|
|
{
|
|
log_warning("bad/invalid prism at line %d", line);
|
|
badinput = 1;
|
|
continue;
|
|
}
|
|
}
|
|
(*size)++;
|
|
}
|
|
}
|
|
if(badinput || error_exit)
|
|
{
|
|
free(model);
|
|
return NULL;
|
|
}
|
|
/* Adjust the size of the model */
|
|
if(*size != 0)
|
|
{
|
|
tmp = (PRISM *)realloc(model, (*size)*sizeof(PRISM));
|
|
if(tmp == NULL)
|
|
{
|
|
/* Need to free because realloc leaves unchanged in case of
|
|
error */
|
|
free(model);
|
|
log_error("problem freeing excess memory for prism model");
|
|
return NULL;
|
|
}
|
|
model = tmp;
|
|
}
|
|
return model;
|
|
}
|
|
|
|
|
|
/* Read the coordinates, height, thickness and densities of the layers */
|
|
int gets_layers(const char *str, double dlon, double dlat,
|
|
TESSEROID *tessbuff, int buffsize)
|
|
{
|
|
int nlayers, end, nchars, argsread;
|
|
double lon, lat, height, top, thickness, density;
|
|
|
|
argsread = sscanf(str, "%lf %lf %lf%n", &lon, &lat, &height, &nchars);
|
|
if(argsread != 3)
|
|
{
|
|
log_error("failed to read lon, lat, and height");
|
|
return -1;
|
|
}
|
|
if(str[nchars] == '\0')
|
|
{
|
|
log_error("missing thickness and density values");
|
|
return -1;
|
|
}
|
|
|
|
top = height + MEAN_EARTH_RADIUS;
|
|
end = nchars;
|
|
for(nlayers = 0; str[end] != '\0'; nlayers++)
|
|
{
|
|
if(nlayers == buffsize)
|
|
{
|
|
log_error("too many layers! Max = %d", buffsize);
|
|
return -1;
|
|
}
|
|
argsread = sscanf(str + end, "%lf %lf%n", &thickness, &density,
|
|
&nchars);
|
|
if(argsread != 2)
|
|
{
|
|
log_error("missing thickness or density value");
|
|
return -1;
|
|
}
|
|
if(thickness < 0)
|
|
{
|
|
log_error("can't have negative thickness");
|
|
return -1;
|
|
}
|
|
|
|
tessbuff[nlayers].density = density;
|
|
tessbuff[nlayers].w = lon - 0.5*dlon;
|
|
tessbuff[nlayers].e = lon + 0.5*dlon;
|
|
tessbuff[nlayers].s = lat - 0.5*dlat;
|
|
tessbuff[nlayers].n = lat + 0.5*dlat;
|
|
tessbuff[nlayers].r2 = top;
|
|
tessbuff[nlayers].r1 = top - thickness;
|
|
|
|
top -= thickness;
|
|
end += nchars;
|
|
}
|
|
return nlayers;
|
|
}
|
|
|