14#define COMMAS_SEPARATE_FILENAMES 0
18# define HAS_WILDCARDS(s) (strchr(s, '*') != NULL || strchr(s, '%') != NULL)
21# define HAS_WILDCARDS(s) (strchr(s, '*') != NULL || strchr(s, '?') != NULL)
24int parseList(
char ***list,
char *
string);
25long add_file_arguments(
int argc,
char **argv,
char ***argvNew);
26int parse_string(
char ***list,
char *
string);
36int scanargs(SCANNED_ARG **scanned,
int argc,
char **argv) {
37 SCANNED_ARG *sc_arg_ptr;
38 int i, i_store, argLimit;
41 void prompt_for_arguments(
int *argc,
char ***argv);
42#if !defined(UNIX) && !defined(_WIN32) && !defined(vxWorks)
48 if (argv[argc - 1][0] ==
'&') {
51 prompt_for_arguments(&argc, &argv);
56 argc = add_file_arguments(argc, argv, &argvNew);
61 printf(
"%ld argv strings:\n", argc);
62 for (i = 0; i < argc; i++)
63 printf(
"%ld: %s\n", i, argv[i]);
66 sc_arg_ptr =
tmalloc((
unsigned)argc *
sizeof(*sc_arg_ptr));
67 *scanned = sc_arg_ptr;
68 arg =
tmalloc(
sizeof(*arg) * (argLimit = 1024));
72 for (i = i_store = 0; i < argc; i++) {
73 if ((
long)strlen(argv[i]) > argLimit - 1)
74 arg =
trealloc(arg,
sizeof(*arg) * (argLimit = 2 * strlen(argv[i])));
80 sc_arg_ptr[i_store].arg_type = OPTION;
82 while (*ptr && (*ptr !=
'=' && *ptr !=
':' && *ptr !=
','))
84 if (*ptr ==
'=' || *ptr ==
':' || *ptr ==
',') {
88 sc_arg_ptr[i_store].n_items = parseList(&(sc_arg_ptr[i_store].list), arg + 1);
89 }
else if (ptr - arg > 1) {
91 sc_arg_ptr[i_store].n_items = parseList(&(sc_arg_ptr[i_store].list), arg + 1);
93 sc_arg_ptr[i_store].n_items = 0;
94 sc_arg_ptr[i_store].list =
tmalloc(
sizeof(*sc_arg_ptr[i_store].list) * 1);
95 sc_arg_ptr[i_store].list[0] =
tmalloc(
sizeof(**sc_arg_ptr[i_store].list));
96 sc_arg_ptr[i_store].list[0][0] = 0;
100#if !defined(UNIX) && !defined(_WIN32) && !defined(vxWorks)
104 else if (arg[0] ==
'>') {
107 if ((fp = fopen(arg + 2,
"a+")) == NULL) {
108 printf(
"unable to open %s for appending\n", arg + 2);
112 if ((fp = fopen(arg + 1,
"w")) == NULL) {
113 printf(
"unable to open %s for writing\n", arg + 1);
119 }
else if (arg[0] ==
'<') {
121 if ((fp = fopen(arg + 1,
"r")) == NULL) {
122 printf(
"unable to open %s for reading\n", arg + 1);
131 sc_arg_ptr[i_store].arg_type = A_LIST;
132#if COMMAS_SEPARATE_FILENAMES
133 sc_arg_ptr[i_store].n_items = parseList(&(sc_arg_ptr[i_store].list), arg);
135 sc_arg_ptr[i_store].n_items = 1;
136 sc_arg_ptr[i_store].list =
tmalloc(
sizeof(*sc_arg_ptr[i_store].list) * 1);
137 cp_str(&sc_arg_ptr[i_store].list[0], arg);
144 for (i = 0; i < argc; i++) {
163int scanargsg(SCANNED_ARG **scanned,
int argc,
char **argv) {
173 argc =
scanargs(scanned, argc, argv);
176 for (i = 0; i < argc; i++) {
177 if ((*scanned)[i].arg_type != OPTION) {
178 if ((*scanned)[i].n_items != 1) {
180 list = (*scanned)[i].list;
181 n_items = (*scanned)[i].n_items;
182 *scanned =
trealloc(*scanned,
sizeof(**scanned) * (argc + n_items - 1));
183 for (j = argc - 1; j > i; j--) {
184 (*scanned)[j + n_items - 1].list = (*scanned)[j].list;
185 (*scanned)[j + n_items - 1].n_items = (*scanned)[j].n_items;
186 (*scanned)[j + n_items - 1].arg_type = (*scanned)[j].arg_type;
188 for (j = 0; j < n_items; j++) {
189 (*scanned)[i + j].arg_type = A_LIST;
190 (*scanned)[i + j].n_items = 1;
191 (*scanned)[i + j].list =
tmalloc(
sizeof(
char **));
192 (*scanned)[i + j].list[0] = list[j];
197 if (HAS_WILDCARDS((*scanned)[i].list[0])) {
198 list = wild_list(&n_items, &origin, (*scanned)[i].list, 1);
199 *scanned =
trealloc(*scanned,
sizeof(**scanned) * (argc + n_items - 1));
200 for (j = argc - 1; j > i; j--) {
201 (*scanned)[j + n_items - 1].list = (*scanned)[j].list;
202 (*scanned)[j + n_items - 1].n_items = (*scanned)[j].n_items;
203 (*scanned)[j + n_items - 1].arg_type = (*scanned)[j].arg_type;
205 for (j = 0; j < n_items; j++) {
206 (*scanned)[i + j].arg_type = A_LIST;
207 (*scanned)[i + j].n_items = 1;
208 (*scanned)[i + j].list =
tmalloc(
sizeof(
char **));
209 (*scanned)[i + j].list[0] = list[j];
220#define ITEMS_BUFSIZE 10
222int parseList(
char ***list,
char *
string) {
223 static char **items = NULL;
224 char *ptr, *ptr1, *ptr2, last_char;
225 int i, n_items, depth;
226 static int items_max = 0;
230 if (*(ptr =
string) == 0) {
237 printf(
"ptr1 = \"%s\"\n", ptr1);
239 if (*ptr1 ==
'(' && (ptr1 == ptr || *(ptr1 - 1) !=
'\\')) {
244 while (*ptr1 && !(*ptr1 ==
')' && *(ptr1 - 1) !=
'\\' && (*(ptr1 + 1) ==
',' || *(ptr1 + 1) == 0)))
246 if (*(ptr1 + 1) ==
',')
249 while (*ptr1 && !(*ptr1 ==
',' && (ptr1 == ptr || *(ptr1 - 1) !=
'\\'))) {
250 if (*ptr1 ==
'=' && *(ptr1 + 1) ==
'(') {
259 while (*ptr1 && depth) {
260 if (*ptr1 ==
'(' && *(ptr1 - 1) !=
'\\') {
262 }
else if (*ptr1 ==
')' && *(ptr1 - 1) !=
'\\')
267 if (*ptr1 ==
',' || *ptr1 == 0) {
280 if (n_items >= items_max)
281 items =
trealloc(items,
sizeof(*items) * (items_max += ITEMS_BUFSIZE));
283 printf(
"item = \"%s\"\n", ptr);
285 items[n_items++] = ptr;
288 }
while (*ptr && last_char);
289 if (last_char ==
',')
290 items[n_items++] = ptr;
292 *list =
tmalloc((
unsigned)
sizeof(ptr) * n_items);
293 for (i = 0; i < n_items; i++) {
296 if (*ptr ==
'\\' && (*(ptr + 1) ==
',' || *(ptr + 1) ==
'"' || *(ptr + 1) ==
'(' || *(ptr + 1) ==
')'))
300 *(*list + i) =
tmalloc((
unsigned)strlen(items[i]) + 1);
301 strcpy(*(*list + i), items[i]);
306void prompt_for_arguments(
int *argc,
char ***argv) {
307 char *ptr, **cmd_line_arg;
313 cmd_line_arg = *argv;
314 *argv =
tmalloc(
sizeof(**argv) * (maxargs = (*argc > 10 ? *argc : 10)));
315 for (i = 0; i < *argc; i++)
316 (*argv)[i] = cmd_line_arg[i];
320 fgets(buffer, 1024, stdin);
321 buffer[strlen(buffer) - 1] = 0;
322 while ((ptr =
get_token_tq(buffer,
" ",
" ",
"\"",
"\""))) {
328 if (*(ptr1 + 1) ==
'"') {
341 if (*argc == maxargs)
342 *argv =
trealloc(*argv,
sizeof(**argv) * (maxargs += 10));
343 (*argv)[(*argc)++] = ptr;
345 }
while (ptr && *ptr ==
'&');
357 char *keyword[2] = {
"input",
"output"};
362 *flags = USE_STDIN + USE_STDOUT;
365 for (i = 0; i < items; i++) {
371 *flags |= USE_STDOUT;
390void processFilenames(
char *programName,
char **input,
char **output,
unsigned long pipeFlags,
long noWarnings,
long *tmpOutputUsed) {
396 if (pipeFlags & DEFAULT_STDIN)
397 pipeFlags |= USE_STDIN;
398 if (!(pipeFlags & USE_STDIN)) {
399 fprintf(stderr,
"error: too few filenames (%s)\n", programName);
403 if (*input && pipeFlags & USE_STDIN) {
408 fprintf(stderr,
"error: too many filenames (%s)\n", programName);
409 fprintf(stderr,
" offending argument is %s\n", *output);
414 if (*output && pipeFlags & USE_STDOUT) {
415 fprintf(stderr,
"error: too many filenames (%s)\n", programName);
416 fprintf(stderr,
" offending argument is %s\n", *output);
419 if (!*output && pipeFlags & DEFAULT_STDOUT)
420 pipeFlags |= USE_STDOUT;
422 if ((*input && *output && strcmp(*input, *output) == 0) || (!*output && !(pipeFlags & USE_STDOUT))) {
424 fprintf(stderr,
"error: no output filename---give output filename or -pipe=output (%s)\n", programName);
427 if (!tmpOutputUsed) {
428 fprintf(stderr,
"error: input and output are identical (%s)\n", programName);
431 if (
PackSuffixType(*input, &unpackedName, UNPACK_REQUIRE_SDDS) >= 0) {
432 if (!unpackedName || !strlen(unpackedName)) {
433 fprintf(stderr,
"error: can't unpack %s---name too short for automatic name generation (%s)\n", *input, programName);
435 }
else if (
fexists(unpackedName)) {
436 fprintf(stderr,
"error: can't unpack %s and create %s---%s exists (%s)\n", *input, unpackedName, unpackedName, programName);
438 }
else if (!noWarnings)
439 fprintf(stderr,
"warning: creating new file %s while leaving compressed file %s intact (%s)\n", unpackedName, *input, programName);
441 cp_str(output, unpackedName);
444 tempName = malloc(
sizeof(
char) * (strlen(*input) + 11));
445 sprintf(tempName,
"%s.tmpXXXXXX", *input);
450 fprintf(stderr,
"warning: existing file %s will be replaced (%s)\n", *input, programName);
455long add_file_arguments(
int argc,
char **argv,
char ***argvNew) {
456 long iarg, isSDDS, dataIndex = 0, comment = 0;
457 int64_t iNew, argcMax;
459 char buffer[16384], *ptr, *filename, *
class, *dataName = NULL;
462 char *classOption[2] = {
463 "column",
"parameter"};
465 *argvNew =
tmalloc(
sizeof(**argvNew) * argc);
468 for (iarg = 0; iarg < argc; iarg++) {
470 if ((argv[iarg][0] ==
'=') && (strlen(argv[iarg]) == 1)) {
475 if (argv[iarg][0] ==
'@' && argv[iarg][1] ==
'@') {
477 if ((ptr = strchr(filename = argv[iarg] + 2,
',')) && *(ptr - 1) !=
'\\') {
484 if (!(ptr = strchr(
class,
'='))) {
486 fprintf(stderr,
"Bad argument file option: %s (%s)\n", argv[iarg] + 2, argv[0]);
500 fprintf(stderr,
"Bad argument file option: %s (%s)\n", argv[iarg] + 2, argv[0]);
505 fprintf(stderr,
"Error: %s %s not found in file %s (%s)\n", isParameter ?
"parameter" :
"column", dataName, filename, argv[0]);
509 fprintf(stderr,
"Error: %s %s in file %s is not string type (%s)\n", isParameter ?
"parameter" :
"column", dataName, filename, argv[0]);
515 fprintf(stderr,
"error: argument file not found: %s (%s)\n", filename, argv[0]);
519 if (!(fp = fopen(filename,
"r"))) {
520 fprintf(stderr,
"couldn't read argument file: %s\n", filename);
523 while (fgets(buffer, 16384, fp)) {
524 buffer[strlen(buffer) - 1] = 0;
527 if (iNew >= argcMax) {
528 *argvNew =
trealloc(*argvNew,
sizeof(**argvNew) * (argcMax = iNew + 10));
544 if ((iNew + rows) >= argcMax)
545 *argvNew =
trealloc(*argvNew,
sizeof(**argvNew) * (argcMax = iNew + rows + 1));
546 for (iRow = 0; iRow < rows; iRow++) {
548 (*argvNew)[iNew] = column[iRow];
559 *argvNew =
trealloc(*argvNew,
sizeof(**argvNew) * (argcMax = argcMax + 10));
560 (*argvNew)[iNew] = parameter;
566 }
else if ((argv[iarg][0] ==
'=') && (strlen(argv[iarg]) == 1)) {
570 *argvNew =
trealloc(*argvNew,
sizeof(**argvNew) * (argcMax = argcMax + 10));
587 for (i_store = 0; i_store < argc; i_store++) {
588 if ((*scanned)[i_store].list) {
589 for (i = 0; i < (*scanned)[i_store].n_items; i++) {
590 if ((*scanned)[i_store].list[i]) {
591 free((*scanned)[i_store].list[i]);
592 (*scanned)[i_store].list[i] = NULL;
595 free((*scanned)[i_store].list);
596 (*scanned)[i_store].list = NULL;
605int parse_string(
char ***list,
char *
string) {
606 char *ptr = NULL, *ptr1, *ptr2, *buffer;
615 while ((ptr =
get_token_tq(buffer,
" ",
" ",
"\"",
"\""))) {
621 if (*(ptr1 + 1) ==
'"') {
634 *list =
trealloc(*list,
sizeof(**list) * (n_items + 1));
635 cp_str(&(*list)[n_items], ptr);
642 }
while (ptr && *ptr ==
'&');
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_GetParameterType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of a parameter in the SDDS dataset by its index.
int32_t SDDS_GetParameterIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named parameter in the SDDS dataset.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
int32_t SDDS_GetColumnType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of a column in the SDDS dataset by its index.
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
#define SDDS_STRING
Identifier for the string data type.
void * trealloc(void *old_ptr, uint64_t size_of_block)
Reallocates a memory block to a new size.
int tfree(void *ptr)
Frees a memory block and records the deallocation if tracking is enabled.
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
char * cp_str(char **s, char *t)
Copies a string, allocating memory for storage.
char * delete_chars(char *s, char *t)
Removes all occurrences of characters found in string t from string s.
long fexists(const char *filename)
Checks if a file exists.
char * get_token_tq(char *s, char *ts, char *te, char *qs, char *qe)
Extracts a token from a string with support for multiple delimiter and quotation sets.
void interpret_escapes(char *s)
Interpret C escape sequences in a string.
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
int scanargsg(SCANNED_ARG **scanned, int argc, char **argv)
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
long processPipeOption(char **item, long items, unsigned long *flags)
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
void free_scanargs(SCANNED_ARG **scanned, int argc)
char * strcpy_ss(char *dest, const char *src)
Safely copies a string, handling memory overlap.
char * strslide(char *s, long distance)
Slides character data within a string by a specified distance.
char * mktempOAG(char *template)
Generates a unique temporary filename based on a template.
long PackSuffixType(char *filename, char **unpackedName, unsigned long mode)
Determines the unpacking type based on the file extension.