SDDSlib
Loading...
Searching...
No Matches
scanargs.c
Go to the documentation of this file.
1/**
2 * @file scanargs.c
3 * @brief Command-line argument parsing utilities for handling options and arguments.
4 */
5
6#include "scan.h"
7#include "mdb.h"
8#include "SDDS.h"
9#if defined(_WIN32)
10# include <io.h>
11#endif
12
13#define DEBUG 0
14#define COMMAS_SEPARATE_FILENAMES 0
15
16#ifdef VAX_VMS
17/* check for VAX/VMS wildcards */
18# define HAS_WILDCARDS(s) (strchr(s, '*') != NULL || strchr(s, '%') != NULL)
19#endif
20#ifdef UNIX
21# define HAS_WILDCARDS(s) (strchr(s, '*') != NULL || strchr(s, '?') != NULL)
22#endif
23
24int parseList(char ***list, char *string);
25long add_file_arguments(int argc, char **argv, char ***argvNew);
26int parse_string(char ***list, char *string);
27
28/**
29 * Scans and parses command-line arguments into options and argument lists.
30 *
31 * @param[out] scanned Pointer to an array where the parsed arguments will be stored.
32 * @param[in] argc The number of command-line arguments.
33 * @param[in] argv The array of command-line arguments.
34 * @return The number of parsed arguments stored in 'scanned'.
35 */
36int scanargs(SCANNED_ARG **scanned, int argc, char **argv) {
37 SCANNED_ARG *sc_arg_ptr;
38 int i, i_store, argLimit;
39 char *ptr, *arg;
40 char **argvNew;
41 void prompt_for_arguments(int *argc, char ***argv);
42#if !defined(UNIX) && !defined(_WIN32) && !defined(vxWorks)
43 FILE *fp;
44#endif
45 argvNew = NULL;
46
47 if (argc >= 2) {
48 if (argv[argc - 1][0] == '&') {
49 /* prompt for arguments from command line--continuation character is & */
50 argc--;
51 prompt_for_arguments(&argc, &argv);
52 }
53 }
54
55 if (argc >= 1) {
56 argc = add_file_arguments(argc, argv, &argvNew);
57 argv = argvNew;
58 }
59
60#if DEBUG
61 printf("%ld argv strings:\n", argc);
62 for (i = 0; i < argc; i++)
63 printf("%ld: %s\n", i, argv[i]);
64#endif
65
66 sc_arg_ptr = tmalloc((unsigned)argc * sizeof(*sc_arg_ptr));
67 *scanned = sc_arg_ptr;
68 arg = tmalloc(sizeof(*arg) * (argLimit = 1024));
69#if 0
70 ptr = 2000; /*this is useless statement to force the compiler to allocate memory for ptr. */
71#endif
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])));
75 strcpy(arg, argv[i]);
77 if (arg[0] == '-') {
78 /* it's an option or switch: "-key[=item1[,item2]...]". / may be subsituted
79 * for -, and : or , may be substituted for = */
80 sc_arg_ptr[i_store].arg_type = OPTION;
81 ptr = arg;
82 while (*ptr && (*ptr != '=' && *ptr != ':' && *ptr != ','))
83 ptr++;
84 if (*ptr == '=' || *ptr == ':' || *ptr == ',') {
85 /* there's a list of items. separate list into an array
86 * with the key in the first position */
87 *ptr = ',';
88 sc_arg_ptr[i_store].n_items = parseList(&(sc_arg_ptr[i_store].list), arg + 1);
89 } else if (ptr - arg > 1) {
90 /* no list, just scan key */
91 sc_arg_ptr[i_store].n_items = parseList(&(sc_arg_ptr[i_store].list), arg + 1);
92 } else {
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;
97 }
98 i_store++;
99 }
100#if !defined(UNIX) && !defined(_WIN32) && !defined(vxWorks)
101 /* Set up IO redirection for non-UNIX platforms.
102 * Used to work on VMS, still may...
103 */
104 else if (arg[0] == '>') {
105 /* output redirection */
106 if (arg[1] == '>') {
107 if ((fp = fopen(arg + 2, "a+")) == NULL) {
108 printf("unable to open %s for appending\n", arg + 2);
109 exit(1);
110 }
111 } else {
112 if ((fp = fopen(arg + 1, "w")) == NULL) {
113 printf("unable to open %s for writing\n", arg + 1);
114 exit(1);
115 }
116 }
117 /* for other systems, may need to make a different assignment */
118 stdout = fp;
119 } else if (arg[0] == '<') {
120 /* input redirection */
121 if ((fp = fopen(arg + 1, "r")) == NULL) {
122 printf("unable to open %s for reading\n", arg + 1);
123 exit(1);
124 }
125 /* for other systems, may need to make a different assignment */
126 stdin = fp;
127 }
128#endif
129 else {
130 /* not an option or switch */
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);
134#else
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);
138#endif
139 i_store++;
140 }
141 }
142
143 if (argvNew) {
144 for (i = 0; i < argc; i++) {
145 if (argvNew[i])
146 free(argvNew[i]);
147 }
148 free(argvNew);
149 }
150 if (arg)
151 free(arg);
152 return i_store;
153}
154
155/**
156 * Scans and parses command-line arguments, expanding any wildcard or list arguments.
157 *
158 * @param[out] scanned Pointer to an array where the parsed arguments will be stored.
159 * @param[in] argc The number of command-line arguments.
160 * @param[in] argv The array of command-line arguments.
161 * @return The number of parsed arguments stored in 'scanned'.
162 */
163int scanargsg(SCANNED_ARG **scanned, int argc, char **argv) {
164 int i, j;
165 int n_items;
166#ifdef VAX_VMS
167 int *origin;
168#endif
169 char **list;
170
171 /* first get the command-line arguments and parse them into the
172 SCANNED_ARG format */
173 argc = scanargs(scanned, argc, argv);
174
175 /* go through and find any non-option arguments with lists or wildcards */
176 for (i = 0; i < argc; i++) {
177 if ((*scanned)[i].arg_type != OPTION) {
178 if ((*scanned)[i].n_items != 1) {
179 /* turn each element of the list into a separate argument */
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;
187 }
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];
193 }
194 argc += n_items - 1;
195 }
196#ifdef VAX_VMS
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;
204 }
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];
210 }
211 argc += n_items - 1;
212 i += n_items - 1;
213 }
214#endif
215 }
216 }
217 return (argc);
218}
219
220#define ITEMS_BUFSIZE 10
221
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;
227
228 n_items = 0;
229
230 if (*(ptr = string) == 0) {
231 *list = 0;
232 return (0);
233 }
234 do {
235 ptr1 = ptr;
236#if DEBUG
237 printf("ptr1 = \"%s\"\n", ptr1);
238#endif
239 if (*ptr1 == '(' && (ptr1 == ptr || *(ptr1 - 1) != '\\')) {
240 /* this item starts with a ( so search for the matching ")," or ")\0"
241 to find the end of the item
242 */
243 ptr = ++ptr1;
244 while (*ptr1 && !(*ptr1 == ')' && *(ptr1 - 1) != '\\' && (*(ptr1 + 1) == ',' || *(ptr1 + 1) == 0)))
245 ptr1++;
246 if (*(ptr1 + 1) == ',')
247 *ptr1++ = 0;
248 } else {
249 while (*ptr1 && !(*ptr1 == ',' && (ptr1 == ptr || *(ptr1 - 1) != '\\'))) {
250 if (*ptr1 == '=' && *(ptr1 + 1) == '(') {
251 /* if this option contains =( or (, then search for matching ), and remove the boundary parentheses */
252 if (*ptr1 == '=') {
253 ptr2 = ptr1 + 1;
254 } else {
255 ptr2 = ptr1;
256 }
257 ptr1 = ptr2 + 1;
258 depth = 1;
259 while (*ptr1 && depth) {
260 if (*ptr1 == '(' && *(ptr1 - 1) != '\\') {
261 depth += 1;
262 } else if (*ptr1 == ')' && *(ptr1 - 1) != '\\')
263 depth -= 1;
264 ptr1++;
265 }
266 if (depth == 0) {
267 if (*ptr1 == ',' || *ptr1 == 0) {
268 strslide(ptr1 - 1, -1);
269 strslide(ptr2, -1);
270 ptr1 -= 2;
271 }
272 }
273 } else {
274 ptr1++;
275 }
276 }
277 }
278 last_char = *ptr1;
279 *ptr1 = 0;
280 if (n_items >= items_max)
281 items = trealloc(items, sizeof(*items) * (items_max += ITEMS_BUFSIZE));
282#if DEBUG
283 printf("item = \"%s\"\n", ptr);
284#endif
285 items[n_items++] = ptr;
286 if (last_char)
287 ptr = ptr1 + 1;
288 } while (*ptr && last_char);
289 if (last_char == ',')
290 items[n_items++] = ptr;
291
292 *list = tmalloc((unsigned)sizeof(ptr) * n_items);
293 for (i = 0; i < n_items; i++) {
294 ptr = items[i];
295 while (*ptr) {
296 if (*ptr == '\\' && (*(ptr + 1) == ',' || *(ptr + 1) == '"' || *(ptr + 1) == '(' || *(ptr + 1) == ')'))
297 strcpy_ss(ptr, ptr + 1);
298 ptr++;
299 }
300 *(*list + i) = tmalloc((unsigned)strlen(items[i]) + 1);
301 strcpy(*(*list + i), items[i]);
302 }
303 return (n_items);
304}
305
306void prompt_for_arguments(int *argc, char ***argv) {
307 char *ptr, **cmd_line_arg;
308 char *ptr1, *ptr2;
309 char buffer[1024];
310 int maxargs, i;
311
312 /* copy command-line arguments into new argv array */
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];
317 tfree(cmd_line_arg);
318
319 do {
320 fgets(buffer, 1024, stdin);
321 buffer[strlen(buffer) - 1] = 0;
322 while ((ptr = get_token_tq(buffer, " ", " ", "\"", "\""))) {
323 if (*ptr == '&')
324 break;
325 ptr1 = ptr2 = ptr;
326 while (*ptr1) {
327 if (*ptr1 == '"') {
328 if (*(ptr1 + 1) == '"') {
329 ptr1++;
330 while (*ptr1 == '"')
331 ptr1++;
332 } else {
333 while (*ptr1 != '"')
334 *ptr2++ = *ptr1++;
335 ptr1++;
336 }
337 } else
338 *ptr2++ = *ptr1++;
339 }
340 *ptr2 = 0;
341 if (*argc == maxargs)
342 *argv = trealloc(*argv, sizeof(**argv) * (maxargs += 10));
343 (*argv)[(*argc)++] = ptr;
344 }
345 } while (ptr && *ptr == '&');
346}
347
348/**
349 * Processes the pipe option for input/output redirection.
350 *
351 * @param[in] item Array of option items to process.
352 * @param[in] items Number of items in the array.
353 * @param[out] flags Pointer to an unsigned long where the pipe flags will be stored.
354 * @return Non-zero on success, zero on failure.
355 */
356long processPipeOption(char **item, long items, unsigned long *flags) {
357 char *keyword[2] = {"input", "output"};
358 long i;
359
360 *flags = 0;
361 if (items < 1) {
362 *flags = USE_STDIN + USE_STDOUT;
363 return 1;
364 }
365 for (i = 0; i < items; i++) {
366 switch (match_string(item[i], keyword, 2, 0)) {
367 case 0:
368 *flags |= USE_STDIN;
369 break;
370 case 1:
371 *flags |= USE_STDOUT;
372 break;
373 default:
374 return 0;
375 }
376 }
377 return 1;
378}
379
380/**
381 * Processes input and output filenames, handling defaults and temporary files if necessary.
382 *
383 * @param[in] programName Name of the program, used in error messages.
384 * @param[in,out] input Pointer to the input filename; may be modified.
385 * @param[in,out] output Pointer to the output filename; may be modified.
386 * @param[in] pipeFlags Flags indicating input/output redirection options.
387 * @param[in] noWarnings Non-zero to suppress warning messages.
388 * @param[out] tmpOutputUsed Pointer to a flag that indicates whether a temporary output file is used.
389 */
390void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed) {
391 char *unpackedName;
392 char *tempName;
393 if (tmpOutputUsed)
394 *tmpOutputUsed = 0;
395 if (!(*input)) {
396 if (pipeFlags & DEFAULT_STDIN)
397 pipeFlags |= USE_STDIN;
398 if (!(pipeFlags & USE_STDIN)) {
399 fprintf(stderr, "error: too few filenames (%s)\n", programName);
400 exit(1);
401 }
402 }
403 if (*input && pipeFlags & USE_STDIN) {
404 if (!*output) {
405 *output = *input;
406 *input = NULL;
407 } else {
408 fprintf(stderr, "error: too many filenames (%s)\n", programName);
409 fprintf(stderr, " offending argument is %s\n", *output);
410 exit(1);
411 }
412 }
413
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);
417 exit(1);
418 }
419 if (!*output && pipeFlags & DEFAULT_STDOUT)
420 pipeFlags |= USE_STDOUT;
421
422 if ((*input && *output && strcmp(*input, *output) == 0) || (!*output && !(pipeFlags & USE_STDOUT))) {
423 if (!*input) {
424 fprintf(stderr, "error: no output filename---give output filename or -pipe=output (%s)\n", programName);
425 exit(1);
426 }
427 if (!tmpOutputUsed) {
428 fprintf(stderr, "error: input and output are identical (%s)\n", programName);
429 exit(1);
430 }
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);
434 exit(1);
435 } else if (fexists(unpackedName)) {
436 fprintf(stderr, "error: can't unpack %s and create %s---%s exists (%s)\n", *input, unpackedName, unpackedName, programName);
437 exit(1);
438 } else if (!noWarnings)
439 fprintf(stderr, "warning: creating new file %s while leaving compressed file %s intact (%s)\n", unpackedName, *input, programName);
440 *tmpOutputUsed = 0;
441 cp_str(output, unpackedName);
442 } else {
443 *tmpOutputUsed = 1;
444 tempName = malloc(sizeof(char) * (strlen(*input) + 11));
445 sprintf(tempName, "%s.tmpXXXXXX", *input);
446 cp_str(output, mktempOAG(tempName));
447 free(tempName);
448 /*cp_str(output, tmpname(NULL)); */
449 if (!noWarnings)
450 fprintf(stderr, "warning: existing file %s will be replaced (%s)\n", *input, programName);
451 }
452 }
453}
454
455long add_file_arguments(int argc, char **argv, char ***argvNew) {
456 long iarg, isSDDS, dataIndex = 0, comment = 0;
457 int64_t iNew, argcMax;
458 FILE *fp;
459 char buffer[16384], *ptr, *filename, *class, *dataName = NULL;
460 int isParameter = 0;
461 SDDS_DATASET SDDSinput;
462 char *classOption[2] = {
463 "column", "parameter"};
464
465 *argvNew = tmalloc(sizeof(**argvNew) * argc);
466 argcMax = argc;
467 iNew = 0;
468 for (iarg = 0; iarg < argc; iarg++) {
469 if (comment) {
470 if ((argv[iarg][0] == '=') && (strlen(argv[iarg]) == 1)) {
471 comment = 0;
472 }
473 continue;
474 }
475 if (argv[iarg][0] == '@' && argv[iarg][1] == '@') {
476 isSDDS = 0;
477 if ((ptr = strchr(filename = argv[iarg] + 2, ',')) && *(ptr - 1) != '\\') {
478 *ptr = 0;
479 if (!SDDS_InitializeInput(&SDDSinput, filename)) {
480 *ptr = ',';
481 } else {
482 isSDDS = 1;
483 class = ptr + 1;
484 if (!(ptr = strchr(class, '='))) {
485 *ptr = ',';
486 fprintf(stderr, "Bad argument file option: %s (%s)\n", argv[iarg] + 2, argv[0]);
487 exit(1);
488 }
489 dataName = ptr + 1;
490 switch (match_string(class, classOption, 2, 0)) {
491 case 0:
492 /* column */
493 isParameter = 0;
494 break;
495 case 1:
496 /* parameter */
497 isParameter = 1;
498 break;
499 default:
500 fprintf(stderr, "Bad argument file option: %s (%s)\n", argv[iarg] + 2, argv[0]);
501 exit(1);
502 break;
503 }
504 if ((isParameter && (dataIndex = SDDS_GetParameterIndex(&SDDSinput, dataName)) < 0) || (!isParameter && (dataIndex = SDDS_GetColumnIndex(&SDDSinput, dataName)) < 0)) {
505 fprintf(stderr, "Error: %s %s not found in file %s (%s)\n", isParameter ? "parameter" : "column", dataName, filename, argv[0]);
506 exit(1);
507 }
508 if ((isParameter && SDDS_GetParameterType(&SDDSinput, dataIndex) != SDDS_STRING) || (!isParameter && SDDS_GetColumnType(&SDDSinput, dataIndex) != SDDS_STRING)) {
509 fprintf(stderr, "Error: %s %s in file %s is not string type (%s)\n", isParameter ? "parameter" : "column", dataName, filename, argv[0]);
510 exit(1);
511 }
512 }
513 }
514 if (!fexists(filename)) {
515 fprintf(stderr, "error: argument file not found: %s (%s)\n", filename, argv[0]);
516 exit(1);
517 }
518 if (!isSDDS) {
519 if (!(fp = fopen(filename, "r"))) {
520 fprintf(stderr, "couldn't read argument file: %s\n", filename);
521 exit(1);
522 }
523 while (fgets(buffer, 16384, fp)) {
524 buffer[strlen(buffer) - 1] = 0;
525 if (!strlen(buffer))
526 continue;
527 if (iNew >= argcMax) {
528 *argvNew = trealloc(*argvNew, sizeof(**argvNew) * (argcMax = iNew + 10));
529 }
530 delete_chars(buffer, "\"");
531 SDDS_CopyString((*argvNew) + iNew, buffer);
532 iNew++;
533 }
534 fclose(fp);
535 } else {
536 if (!isParameter) {
537 while (SDDS_ReadPage(&SDDSinput) > 0) {
538 char **column;
539 int64_t iRow, rows;
540 if ((rows = SDDS_CountRowsOfInterest(&SDDSinput)) <= 0)
541 continue;
542 if (!(column = SDDS_GetColumn(&SDDSinput, dataName)))
543 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
544 if ((iNew + rows) >= argcMax)
545 *argvNew = trealloc(*argvNew, sizeof(**argvNew) * (argcMax = iNew + rows + 1));
546 for (iRow = 0; iRow < rows; iRow++) {
547 delete_chars(column[iRow], "\"");
548 (*argvNew)[iNew] = column[iRow];
549 iNew++;
550 }
551 free(column);
552 }
553 } else {
554 while (SDDS_ReadPage(&SDDSinput) > 0) {
555 char *parameter;
556 if (!SDDS_GetParameter(&SDDSinput, dataName, &parameter))
557 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
558 if (iNew >= argcMax)
559 *argvNew = trealloc(*argvNew, sizeof(**argvNew) * (argcMax = argcMax + 10));
560 (*argvNew)[iNew] = parameter;
561 iNew++;
562 }
563 }
564 SDDS_Terminate(&SDDSinput);
565 }
566 } else if ((argv[iarg][0] == '=') && (strlen(argv[iarg]) == 1)) {
567 comment = 1;
568 } else {
569 if (iNew >= argcMax)
570 *argvNew = trealloc(*argvNew, sizeof(**argvNew) * (argcMax = argcMax + 10));
571 SDDS_CopyString((*argvNew) + iNew, argv[iarg]);
572 iNew++;
573 }
574 }
575 return iNew;
576}
577
578/**
579 * Frees the memory allocated by scanargs or scanargsg functions.
580 *
581 * @param[in,out] scanned Pointer to the array of scanned arguments to free; set to NULL on return.
582 * @param[in] argc The number of arguments in the scanned array.
583 */
584void free_scanargs(SCANNED_ARG **scanned, int argc) {
585 int i, i_store;
586 if (*scanned) {
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;
593 }
594 }
595 free((*scanned)[i_store].list);
596 (*scanned)[i_store].list = NULL;
597 }
598 }
599 free(*scanned);
600 *scanned = NULL;
601 }
602}
603
604/* Simulates command line argument parseing */
605int parse_string(char ***list, char *string) {
606 char *ptr = NULL, *ptr1, *ptr2, *buffer;
607 int n_items = 0;
608
609 cp_str(&buffer, string);
610 *list = NULL;
611 do {
612 if (ptr)
613 free(ptr);
614 ptr = NULL;
615 while ((ptr = get_token_tq(buffer, " ", " ", "\"", "\""))) {
616 if (*ptr == '&')
617 break;
618 ptr1 = ptr2 = ptr;
619 while (*ptr1) {
620 if (*ptr1 == '"') {
621 if (*(ptr1 + 1) == '"') {
622 ptr1++;
623 while (*ptr1 == '"')
624 ptr1++;
625 } else {
626 while (*ptr1 != '"')
627 *ptr2++ = *ptr1++;
628 ptr1++;
629 }
630 } else
631 *ptr2++ = *ptr1++;
632 }
633 *ptr2 = 0;
634 *list = trealloc(*list, sizeof(**list) * (n_items + 1));
635 cp_str(&(*list)[n_items], ptr);
636 /* (*list)[n_items] = ptr; */
637 n_items++;
638 if (ptr)
639 free(ptr);
640 ptr = NULL;
641 }
642 } while (ptr && *ptr == '&');
643 if (ptr)
644 free(ptr);
645 ptr = NULL;
646 if (buffer)
647 free(buffer);
648 return (n_items);
649}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
void * SDDS_GetColumn(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves a copy of the data for a specified column, including only rows marked as "of interest".
int64_t SDDS_CountRowsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of rows marked as "of interest" in the current data table.
void * SDDS_GetParameter(SDDS_DATASET *SDDS_dataset, char *parameter_name, void *memory)
Retrieves the value of a specified parameter from the current data table of a data set.
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:49
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_ReadPage(SDDS_DATASET *SDDS_dataset)
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.
Definition SDDS_utils.c:432
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.
Definition SDDS_utils.c:856
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
void * trealloc(void *old_ptr, uint64_t size_of_block)
Reallocates a memory block to a new size.
Definition array.c:181
int tfree(void *ptr)
Frees a memory block and records the deallocation if tracking is enabled.
Definition array.c:230
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
Definition array.c:59
char * cp_str(char **s, char *t)
Copies a string, allocating memory for storage.
Definition cp_str.c:28
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.
Definition fexists.c:27
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)
Definition scanargs.c:163
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
Definition scanargs.c:36
long processPipeOption(char **item, long items, unsigned long *flags)
Definition scanargs.c:356
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:390
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:584
char * strcpy_ss(char *dest, const char *src)
Safely copies a string, handling memory overlap.
Definition str_copy.c:34
char * strslide(char *s, long distance)
Slides character data within a string by a specified distance.
Definition strslide.c:32
char * mktempOAG(char *template)
Generates a unique temporary filename based on a template.
Definition tmpname.c:85
long PackSuffixType(char *filename, char **unpackedName, unsigned long mode)
Determines the unpacking type based on the file extension.
Definition unpack.c:47