SDDSlib
Loading...
Searching...
No Matches
scanitemlist.c File Reference

This file contains functions for scanning and parsing item lists with various data types. More...

#include "mdb.h"
#include "scan.h"
#include "match_string.h"
#include <stdarg.h>

Go to the source code of this file.

Functions

long scanItemList (unsigned long *flags, char **item, long *items, unsigned long mode,...)
 Scans a list of items and assigns values based on provided keywords and types.
 
long scanItemListLong (unsigned long long *flags, char **item, long *items, unsigned long mode,...)
 Scans a list of items with extended flag support and assigns values based on provided keywords and types.
 
long scan_item_list (unsigned long *flags, char **item, long *items,...)
 Scans a list of items without flag extension and assigns values based on provided keywords and types.
 
long contains_keyword_phrase (char *string)
 Checks if a string contains an unescaped equal sign, indicating a keyword-value phrase.
 

Detailed Description

This file contains functions for scanning and parsing item lists with various data types.

License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Author
M. Borland, C. Saunders, R. Soliday, H. Shang

Definition in file scanitemlist.c.

Function Documentation

◆ contains_keyword_phrase()

long contains_keyword_phrase ( char * string)

Checks if a string contains an unescaped equal sign, indicating a keyword-value phrase.

This function scans the input string for the presence of an equal sign ('=') that is not preceded by a backslash ('\'). It returns 1 if such a keyword-value pair is found, otherwise returns 0. Additionally, it handles escaped equal signs by removing the escape character.

Parameters
stringThe input string to be checked for keyword-value phrases.
Returns
Returns 1 if the string contains an unescaped equal sign, otherwise returns 0.

Definition at line 547 of file scanitemlist.c.

547 {
548 char *ptr, *ptr0;
549 ptr0 = string;
550 while ((ptr = strchr(string, '='))) {
551 if (ptr != ptr0 && *(ptr - 1) != '\\')
552 return 1;
553 if (ptr != ptr0 && *(ptr - 1) == '\\')
554 strcpy_ss(ptr - 1, ptr);
555 string = ptr + 1;
556 }
557 return 0;
558}
char * strcpy_ss(char *dest, const char *src)
Safely copies a string, handling memory overlap.
Definition str_copy.c:34

◆ scan_item_list()

long scan_item_list ( unsigned long * flags,
char ** item,
long * items,
... )

Scans a list of items without flag extension and assigns values based on provided keywords and types.

This version of the scanning function lacks certain functionalities such as flag extension and may not flag entries that don't match any keywords. It is used in various locations within the codebase.

Parameters
flagsPointer to an unsigned long variable where flags will be set based on matched items.
itemArray of strings containing items to be scanned, each in the format "keyword=value" or "keyword".
itemsPointer to a long variable indicating the number of items in the item array. It will be updated based on the scanning process.
...Variable arguments specifying pairs of <keyword>, <SDDS-type>, <pointer>, <number-required>, <set-flag>, etc., ending with NULL.
Returns
Returns 1 on successful scanning and parsing of items, or 0 on failure.

Definition at line 400 of file scanitemlist.c.

401{
402 va_list argptr;
403 long i, j, type, flag, retval, length, match;
404 //long number;
405 char *keyword;
406 void *data;
407 static char **valueptr = NULL;
408 static long *keylength = NULL, *item_matched = NULL;
409 static long maxitems = 0;
410
411 if (!flags)
412 return bombre("null flags pointer seen (scan_item_list)", NULL, 0);
413 if (!item)
414 return bombre("null item pointer seen (scan_item_list)", NULL, 0);
415 if (!items)
416 return bombre("null items pointer seen (scan_item_list)", NULL, 0);
417 if (*items <= 0) {
418 *flags = 0;
419 return 1;
420 }
421 if (*items > maxitems) {
422 valueptr = trealloc(valueptr, sizeof(*valueptr) * (maxitems = *items));
423 keylength = trealloc(keylength, sizeof(*keylength) * maxitems);
424 item_matched = trealloc(item_matched, sizeof(*item_matched) * maxitems);
425 }
426 *flags = 0;
427 for (i = 0; i < *items; i++) {
428 item_matched[i] = 0;
429#if DEBUG
430 fprintf(stderr, "item %ld: %s\n", i, item[i]);
431#endif
432 if ((valueptr[i] = strchr(item[i], '='))) {
433 if ((keylength[i] = valueptr[i] - item[i]) <= 0)
434 return bombre("zero-length keyword seen (scan_item_list)", NULL, 0);
435 *valueptr[i]++ = 0;
436 } else
437 keylength[i] = strlen(item[i]);
438#if DEBUG
439 fprintf(stderr, " keyword: %s valueptr: %s\n", item[i], valueptr[i]);
440#endif
441 }
442
443 va_start(argptr, items);
444 retval = 1;
445 do {
446 if (!(keyword = va_arg(argptr, char *)))
447 break;
448 type = va_arg(argptr, int32_t);
449 data = va_arg(argptr, void *);
450 //number = va_arg(argptr, int32_t);
451 va_arg(argptr, int32_t);
452 flag = va_arg(argptr, uint32_t);
453 length = strlen(keyword);
454 match = -1;
455 for (i = 0; i < *items; i++)
456 if (strncmp_case_insensitive(item[i], keyword, MIN(length, keylength[i])) == 0) {
457 if (match != -1) {
458 fprintf(stderr, "ambiguous item %s seen\n", keyword);
459 retval = 0;
460 }
461 match = i;
462 }
463#if defined(DEBUG)
464 if (match != -1)
465 fprintf(stderr, "keyword %s and item %ld (%s) match\n", keyword, match, item[match]);
466 else
467 fprintf(stderr, "no match for keyword %s\n", keyword);
468#endif
469 if (!retval)
470 break;
471 if (match == -1)
472 continue;
473 if (item_matched[match]) {
474 fprintf(stderr, "error: ambiguous qualifier %s seen\n", item[match]);
475 retval = 0;
476 break;
477 }
478 item_matched[match] = 1;
479 *flags |= flag;
480 if (!valueptr[match]) {
481 if (type == -1)
482 continue;
483 fprintf(stderr, "error: value not given for %s\n", keyword);
484 retval = 0;
485 break;
486 }
487 switch (type) {
488 case SDDS_DOUBLE:
489 *((double *)data) = atof(valueptr[match]);
490 break;
491 case SDDS_FLOAT:
492 *((float *)data) = (float)atof(valueptr[match]);
493 break;
494 case SDDS_LONG:
495 *((int32_t *)data) = atol(valueptr[match]);
496 break;
497 case SDDS_ULONG:
498#if defined(_WIN32)
499 *((uint32_t *)data) = (uint32_t)_atoi64(valueptr[match]);
500#else
501# if defined(vxWorks)
502 epicsParseUInt32(valueptr[match], (uint32_t *)data, 10, NULL);
503# else
504 *((uint32_t *)data) = (uint32_t)atoll(valueptr[match]);
505# endif
506#endif
507 break;
508 case SDDS_SHORT:
509 *((short *)data) = (short)atol(valueptr[match]);
510 break;
511 case SDDS_USHORT:
512 *((unsigned short *)data) = (unsigned short)atol(valueptr[match]);
513 break;
514 case SDDS_STRING:
515 cp_str((char **)data, valueptr[match]);
516 break;
517 case SDDS_CHARACTER:
518 *((char *)data) = valueptr[match][0];
519 break;
520 default:
521 fprintf(stderr, "Error: value not accepted for qualifier %s\n", item[match]);
522 break;
523 }
524 free(item[match]);
525 (*items)--;
526 for (j = match; j < *items; j++) {
527 item[j] = item[j + 1];
528 valueptr[j] = valueptr[j + 1];
529 keylength[j] = keylength[j + 1];
530 }
531 } while (retval == 1 && *items);
532 va_end(argptr);
533 return retval;
534}
#define SDDS_ULONG
Identifier for the unsigned 32-bit integer data type.
Definition SDDStypes.h:67
#define SDDS_FLOAT
Identifier for the float data type.
Definition SDDStypes.h:43
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
#define SDDS_SHORT
Identifier for the signed short integer data type.
Definition SDDStypes.h:73
#define SDDS_CHARACTER
Identifier for the character data type.
Definition SDDStypes.h:91
#define SDDS_USHORT
Identifier for the unsigned short integer data type.
Definition SDDStypes.h:79
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
void * trealloc(void *old_ptr, uint64_t size_of_block)
Reallocates a memory block to a new size.
Definition array.c:181
long bombre(char *error, char *usage, long return_value)
Reports error messages to the terminal and returns a specified value.
Definition bomb.c:44
char * cp_str(char **s, char *t)
Copies a string, allocating memory for storage.
Definition cp_str.c:28
int strncmp_case_insensitive(char *s1, char *s2, long n)
Compares up to a specified number of characters of two strings in a case-insensitive manner.

◆ scanItemList()

long scanItemList ( unsigned long * flags,
char ** item,
long * items,
unsigned long mode,
... )

Scans a list of items and assigns values based on provided keywords and types.

This function processes a list of item strings, each potentially in the format "keyword=value", and assigns the corresponding values to provided data pointers based on specified SDDS types. It supports setting flags and handles various data types as specified in the variable arguments.

Parameters
flagsPointer to an unsigned long variable where flags will be set based on matched items.
itemArray of strings containing items to be scanned, each in the format "keyword=value" or "keyword".
itemsPointer to a long variable indicating the number of items in the item array. It will be updated based on the scanning process.
modeUnsigned long value specifying the scanning mode, used for future expansion and controlling behavior.
...Variable arguments specifying pairs of <keyword>, <SDDS-type>, <pointer>, <number-required>, <set-flag>, etc., ending with NULL.
Returns
Returns 1 on successful scanning and parsing of items, or 0 on failure.

Definition at line 41 of file scanitemlist.c.

42{
43 va_list argptr;
44 long i, j, type, flag, retval, length, number, match;
45 char *keyword;
46 void *data;
47 static char **valueptr = NULL;
48 static long *keylength = NULL;
49 static short *item_matched = NULL, *has_equals = NULL;
50 static long maxitems = 0;
51
52 if (!flags)
53 return bombre("null flags pointer seen (scanItemList)", NULL, 0);
54 if (!item)
55 return bombre("null item pointer seen (scanItemList)", NULL, 0);
56 if (!items)
57 return bombre("null items pointer seen (scanItemList)", NULL, 0);
58 if (*items <= 0) {
59 *flags = 0;
60 return 1;
61 }
62 if (*items > maxitems) {
63 valueptr = trealloc(valueptr, sizeof(*valueptr) * (maxitems = *items));
64 keylength = trealloc(keylength, sizeof(*keylength) * maxitems);
65 item_matched = trealloc(item_matched, sizeof(*item_matched) * maxitems);
66 has_equals = trealloc(has_equals, sizeof(*has_equals) * maxitems);
67 }
68 *flags = 0;
69 for (i = 0; i < *items; i++) {
70 item_matched[i] = 0;
71#if DEBUG
72 fprintf(stderr, "item %ld: %s\n", i, item[i]);
73#endif
74 if ((valueptr[i] = strchr(item[i], '='))) {
75 if ((keylength[i] = valueptr[i] - item[i]) <= 0)
76 return bombre("zero-length keyword seen (scanItemList)", NULL, 0);
77 *valueptr[i]++ = 0;
78 has_equals[i] = 1;
79 } else {
80 keylength[i] = strlen(item[i]);
81 has_equals[i] = 0;
82 }
83
84#if DEBUG
85 fprintf(stderr, " keyword: %s valueptr: %s\n", item[i], valueptr[i]);
86#endif
87 }
88
89 va_start(argptr, mode);
90 retval = 1;
91 do {
92 if (!(keyword = va_arg(argptr, char *)))
93 break;
94 type = va_arg(argptr, int32_t);
95 data = va_arg(argptr, void *);
96 number = va_arg(argptr, int32_t);
97 flag = va_arg(argptr, uint32_t);
98 length = strlen(keyword);
99 match = -1;
100 for (i = 0; i < *items; i++)
101 if (strncmp_case_insensitive(item[i], keyword, MIN(length, keylength[i])) == 0) {
102 if (match != -1) {
103 fprintf(stderr, "ambiguous item %s seen\n", keyword);
104 retval = 0;
105 }
106 match = i;
107 }
108#if defined(DEBUG)
109 if (match != -1)
110 fprintf(stderr, "keyword %s and item %ld (%s) match\n", keyword, match, item[match]);
111 else
112 fprintf(stderr, "no match for keyword %s\n", keyword);
113#endif
114 if (!retval)
115 break;
116 if (match == -1)
117 continue;
118 if (!has_equals[match] && number && mode & SCANITEMLIST_IGNORE_VALUELESS)
119 continue;
120 if (item_matched[match]) {
121 fprintf(stderr, "error: ambiguous qualifier %s seen\n", item[match]);
122 retval = 0;
123 break;
124 }
125 item_matched[match] = 1;
126 *flags |= flag;
127 if (!valueptr[match]) {
128 if (type == -1)
129 continue;
130 fprintf(stderr, "error: value not given for %s\n", keyword);
131 retval = 0;
132 break;
133 }
134 switch (type) {
135 case SDDS_LONGDOUBLE:
136#if defined(vxWorks)
137 fprintf(stderr, "error: SDDS_LONGDOUBLE is not supported on vxWorks yet\n");
138 return 0;
139#else
140 *((long double *)data) = (long double)strtold(valueptr[match], NULL);
141#endif
142 break;
143 case SDDS_DOUBLE:
144 *((double *)data) = atof(valueptr[match]);
145 break;
146 case SDDS_FLOAT:
147 *((float *)data) = (float)atof(valueptr[match]);
148 break;
149 case SDDS_LONG64:
150#if defined(vxWorks)
151 epicsParseInt64(valueptr[match], (int64_t *)data, 10, NULL);
152#else
153 *((int64_t *)data) = (uint64_t)atoll(valueptr[match]);
154#endif
155 break;
156 case SDDS_ULONG64:
157 *((uint64_t *)data) = (uint64_t)strtoull(valueptr[match], NULL, 10);
158 break;
159 case SDDS_LONG:
160 *((int32_t *)data) = (int32_t)atol(valueptr[match]);
161 break;
162 case SDDS_ULONG:
163 *((uint32_t *)data) = (uint32_t)strtoul(valueptr[match], NULL, 10);
164 break;
165 case SDDS_SHORT:
166 *((short *)data) = (short)atol(valueptr[match]);
167 break;
168 case SDDS_USHORT:
169 *((unsigned short *)data) = (unsigned short)atol(valueptr[match]);
170 break;
171 case SDDS_STRING:
172 cp_str((char **)data, valueptr[match]);
173 break;
174 case SDDS_CHARACTER:
175 *((char *)data) = valueptr[match][0];
176 break;
177 default:
178 fprintf(stderr, "Error: value not accepted for qualifier %s\n",
179 item[match]);
180 break;
181 }
182 } while (retval == 1);
183 va_end(argptr);
184 for (i = 0; i < *items; i++) {
185 if (!item_matched[i]) {
186 if (!has_equals[i] && mode & SCANITEMLIST_UNKNOWN_VALUE_OK)
187 continue;
188 if (has_equals[i] && mode & SCANITEMLIST_UNKNOWN_KEYVALUE_OK)
189 continue;
190 fprintf(stderr, "unknown keyword/value given: %s\n", item[i]);
191 return 0;
192 }
193 }
194 if (mode & SCANITEMLIST_REMOVE_USED_ITEMS) {
195 for (i = j = 0; i < *items; i++) {
196 if (!item_matched[i]) {
197 if (i != j) {
198 item_matched[j] = 1;
199 item[j] = item[i];
200 }
201 j++;
202 }
203 }
204 *items = j;
205 }
206 return retval;
207}
#define SDDS_ULONG64
Identifier for the unsigned 64-bit integer data type.
Definition SDDStypes.h:55
#define SDDS_LONGDOUBLE
Identifier for the long double data type.
Definition SDDStypes.h:31
#define SDDS_LONG64
Identifier for the signed 64-bit integer data type.
Definition SDDStypes.h:49

◆ scanItemListLong()

long scanItemListLong ( unsigned long long * flags,
char ** item,
long * items,
unsigned long mode,
... )

Scans a list of items with extended flag support and assigns values based on provided keywords and types.

This function is similar to scanItemList but uses an unsigned long long for flags, allowing for a larger set of flags. It processes a list of item strings, assigns values based on SDDS types, and supports various scanning modes.

Parameters
flagsPointer to an unsigned long long variable where flags will be set based on matched items.
itemArray of strings containing items to be scanned, each in the format "keyword=value" or "keyword".
itemsPointer to a long variable indicating the number of items in the item array. It will be updated based on the scanning process.
modeUnsigned long value specifying the scanning mode, used for future expansion and controlling behavior.
...Variable arguments specifying pairs of <keyword>, <SDDS-type>, <pointer>, <number-required>, <set-flag>, etc., ending with NULL.
Returns
Returns 1 on successful scanning and parsing of items, or 0 on failure.

Definition at line 226 of file scanitemlist.c.

227{
228 va_list argptr;
229 long i, j, type, retval, length, number, match;
230 long long flag;
231 char *keyword;
232 void *data;
233 static char **valueptr = NULL;
234 static long *keylength = NULL;
235 static short *item_matched = NULL, *has_equals = NULL;
236 static long maxitems = 0;
237
238 if (!flags)
239 return bombre("null flags pointer seen (scanItemList)", NULL, 0);
240 if (!item)
241 return bombre("null item pointer seen (scanItemList)", NULL, 0);
242 if (!items)
243 return bombre("null items pointer seen (scanItemList)", NULL, 0);
244 if (*items <= 0) {
245 *flags = 0;
246 return 1;
247 }
248 if (*items > maxitems) {
249 valueptr = trealloc(valueptr, sizeof(*valueptr) * (maxitems = *items));
250 keylength = trealloc(keylength, sizeof(*keylength) * maxitems);
251 item_matched = trealloc(item_matched, sizeof(*item_matched) * maxitems);
252 has_equals = trealloc(has_equals, sizeof(*has_equals) * maxitems);
253 }
254 *flags = 0;
255 for (i = 0; i < *items; i++) {
256 item_matched[i] = 0;
257#if DEBUG
258 fprintf(stderr, "item %ld: %s\n", i, item[i]);
259#endif
260 if ((valueptr[i] = strchr(item[i], '='))) {
261 if ((keylength[i] = valueptr[i] - item[i]) <= 0)
262 return bombre("zero-length keyword seen (scanItemList)", NULL, 0);
263 *valueptr[i]++ = 0;
264 has_equals[i] = 1;
265 } else {
266 keylength[i] = strlen(item[i]);
267 has_equals[i] = 0;
268 }
269
270#if DEBUG
271 fprintf(stderr, " keyword: %s valueptr: %s\n", item[i], valueptr[i]);
272#endif
273 }
274
275 va_start(argptr, mode);
276 retval = 1;
277 do {
278 if (!(keyword = va_arg(argptr, char *)))
279 break;
280 type = va_arg(argptr, int32_t);
281 data = va_arg(argptr, void *);
282 number = va_arg(argptr, int32_t);
283 flag = va_arg(argptr, uint64_t);
284 length = strlen(keyword);
285 match = -1;
286 for (i = 0; i < *items; i++)
287 if (strncmp_case_insensitive(item[i], keyword, MIN(length, keylength[i])) == 0) {
288 if (match != -1) {
289 fprintf(stderr, "ambiguous item %s seen\n", keyword);
290 retval = 0;
291 }
292 match = i;
293 }
294#if defined(DEBUG)
295 if (match != -1)
296 fprintf(stderr, "keyword %s and item %ld (%s) match\n", keyword, match, item[match]);
297 else
298 fprintf(stderr, "no match for keyword %s\n", keyword);
299#endif
300 if (!retval)
301 break;
302 if (match == -1)
303 continue;
304 if (!has_equals[match] && number && mode & SCANITEMLIST_IGNORE_VALUELESS)
305 continue;
306 if (item_matched[match]) {
307 fprintf(stderr, "error: ambiguous qualifier %s seen\n", item[match]);
308 retval = 0;
309 break;
310 }
311 item_matched[match] = 1;
312 *flags |= flag;
313 if (!valueptr[match]) {
314 if (type == -1)
315 continue;
316 fprintf(stderr, "error: value not given for %s\n", keyword);
317 retval = 0;
318 break;
319 }
320 switch (type) {
321 case SDDS_DOUBLE:
322 *((double *)data) = atof(valueptr[match]);
323 break;
324 case SDDS_FLOAT:
325 *((float *)data) = (float)atof(valueptr[match]);
326 break;
327 case SDDS_LONG:
328 *((int32_t *)data) = atol(valueptr[match]);
329 break;
330 case SDDS_ULONG:
331#if defined(_WIN32)
332 *((uint32_t *)data) = (uint32_t)_atoi64(valueptr[match]);
333#else
334# if defined(vxWorks)
335 epicsParseUInt32(valueptr[match], (uint32_t *)data, 10, NULL);
336# else
337 *((uint32_t *)data) = (uint32_t)atoll(valueptr[match]);
338# endif
339#endif
340 break;
341 case SDDS_SHORT:
342 *((short *)data) = (short)atol(valueptr[match]);
343 break;
344 case SDDS_USHORT:
345 *((unsigned short *)data) = (unsigned short)atol(valueptr[match]);
346 break;
347 case SDDS_STRING:
348 cp_str((char **)data, valueptr[match]);
349 break;
350 case SDDS_CHARACTER:
351 *((char *)data) = valueptr[match][0];
352 break;
353 default:
354 fprintf(stderr, "Error: value not accepted for qualifier %s\n",
355 item[match]);
356 break;
357 }
358 } while (retval == 1);
359 va_end(argptr);
360 for (i = 0; i < *items; i++) {
361 if (!item_matched[i]) {
362 if (!has_equals[i] && mode & SCANITEMLIST_UNKNOWN_VALUE_OK)
363 continue;
364 if (has_equals[i] && mode & SCANITEMLIST_UNKNOWN_KEYVALUE_OK)
365 continue;
366 fprintf(stderr, "unknown keyword/value given: %s\n", item[i]);
367 return 0;
368 }
369 }
370 if (mode & SCANITEMLIST_REMOVE_USED_ITEMS) {
371 for (i = j = 0; i < *items; i++) {
372 if (!item_matched[i]) {
373 if (i != j) {
374 item_matched[j] = 1;
375 item[j] = item[i];
376 }
377 j++;
378 }
379 }
380 *items = j;
381 }
382 return retval;
383}