Wireshark 4.7.0
The Wireshark network protocol analyzer
Loading...
Searching...
No Matches
uat.h
Go to the documentation of this file.
1
14#pragma once
15#include <stdlib.h>
16
17#include "ws_symbol_export.h"
18#include <wsutil/strtoi.h>
19#include <wsutil/dtoa.h>
20
21#ifdef __cplusplus
22extern "C" {
23#endif /* __cplusplus */
24
25/*
26 * UAT maintains a dynamically allocated table accessible to the user
27 * via a file and/or via GUI preference dialogs.
28 *
29 * The file is read from and written in the personal configuration directory. If
30 * there is no such file, defaults will be loaded from the global data
31 * directory.
32 *
33 * The behaviour of the table is controlled by a series of callbacks which
34 * the caller (e.g. a dissector) must provide.
35 *
36 * BEWARE that the user can change an UAT at (almost) any time (via the GUI).
37 * That is, pointers to records in an UAT are valid only during the call
38 * to the function that obtains them (do not store pointers to these records).
39 * The records contents are only guaranteed to be valid in the post_update_cb
40 * function. (Implementation detail: currently a race condition is possible
41 * where the UAT consumer (dissector code) tries to use the UAT while the GUI
42 * user frees a record resulting in use-after-free. This is not ideal and might
43 * be fixed later.)
44 *
45 * UATs are meant for short tables of user data (passwords and such), there is
46 * no quick access, you must iterate through them each time to fetch the record
47 * you are looking for.
48 *
49 * Only users via GUI or editing the file can add/remove records, your
50 * (dissector) code cannot.
51 */
52
53/* opaque data type to handle an uat */
54typedef struct epan_uat uat_t;
55/********************************************
56 * Callbacks:
57 * these instruct uat on how to deal with user info and data in records
58 ********************************************/
59
60/********
61 * Callbacks dealing with the entire table
62 ********/
63
64/*
65 * Post-Update CB
66 *
67 * To be called by the GUI code after to the table has being edited.
68 * Will be called once the user clicks the Apply or OK button
69 * optional
70 */
71typedef void (*uat_post_update_cb_t)(void);
72
73
74/********
75 * Callbacks dealing with records (these deal with entire records)
76 ********/
77
85typedef void* (*uat_copy_cb_t)(void *dest, const void *source, size_t len);
86
95typedef void (*uat_free_cb_t)(void *record);
96
103typedef void (*uat_reset_cb_t)(void);
104
123typedef bool (*uat_update_cb_t)(void *record, char **error);
124
125
126/*******
127 * Callbacks for single fields (these deal with single values)
128 * the caller should provide one of these for every field!
129 ********/
130
131/*
132 * Check CB
133 * chk(record, ptr, len, chk_data, fld_data, &error)
134 *
135 * given an input string (ptr, len) checks if the value is OK for a field in the record.
136 * it will return true if OK or else
137 * it will return false and set *error to inform the user on what's
138 * wrong with the given input
139 * The error string must be allocated with g_malloc() or
140 * a routine that calls it.
141 * optional, if not given any input is considered OK and the set cb will be called
142 */
143typedef bool (*uat_fld_chk_cb_t)(void *record, const char *ptr, unsigned len, const void *chk_data, const void *fld_data, char **error);
144
145/*
146 * Set Field CB
147 * set(record, ptr, len, set_data, fld_data)
148 *
149 * given an input string (ptr, len) sets the value of a field in the record,
150 * it is mandatory
151 */
152typedef void (*uat_fld_set_cb_t)(void *record, const char *ptr, unsigned len, const void *set_data, const void *fld_data);
153
154/*
155 * Convert-to-string CB
156 * tostr(record, &out_ptr, &out_len, tostr_data, fld_data)
157 *
158 * given a record returns a string representation of the field
159 * mandatory
160 */
161typedef void (*uat_fld_tostr_cb_t)(void *record, char **out_ptr, unsigned *out_len, const void *tostr_data, const void *fld_data);
162
163/***********
164 * Text Mode
165 *
166 * used for file and dialog representation of fields in columns,
167 * when the file is read it modifies the way the value is passed back to the fld_set_cb
168 * (see definition bellow for description)
169 ***********/
170
175typedef enum _uat_text_mode_t {
176 PT_TXTMOD_NONE,
177 /* not used */
178
179 PT_TXTMOD_STRING,
180 /*
181 file:
182 reads:
183 ,"\x20\x00\x30", as " \00",3 ("space nil zero" of length 3)
184 ,"", as "",0
185 ,, as NULL,0
186 writes:
187 ,"\x20\x30\x00\x20", for " 0\0 ",4
188 ,"", for *, 0
189 ,, for NULL, *
190 dialog:
191 accepts \x?? and other escapes
192 gets "",0 on empty string
193 */
194 PT_TXTMOD_HEXBYTES,
195 /*
196 file:
197 reads:
198 ,A1b2C3d4, as "\xa1\xb2\xc3\xd4",4
199 ,, as NULL,0
200 writes:
201 ,, on NULL, *
202 ,a1b2c3d4, on "\xa1\xb2\xc3\xd4",4
203 dialog:
204 interprets the following input ... as ...:
205 "a1b2c3d4" as "\xa1\xb2\xc3\xd4",4
206 "a1 b2:c3d4" as "\xa1\xb2\xc3\xd4",4
207 "" as NULL,0
208 "invalid" as NULL,3
209 "a1b" as NULL, 1
210 */
211 PT_TXTMOD_ENUM,
212 /* Read/Writes/displays the string value (not number!) */
213 PT_TXTMOD_DISSECTOR,
214 /* Shows a combobox of dissectors */
215
216 PT_TXTMOD_COLOR,
217 /* Reads/Writes/display color in #RRGGBB format */
218
219 PT_TXTMOD_FILENAME,
220 /* processed like a PT_TXTMOD_STRING, but shows a filename dialog */
221 PT_TXTMOD_DIRECTORYNAME,
222 /* processed like a PT_TXTMOD_STRING, but shows a directory dialog */
223 PT_TXTMOD_DISPLAY_FILTER,
224 /* processed like a PT_TXTMOD_STRING, but verifies display filter */
225 PT_TXTMOD_PROTO_FIELD,
226 /* processed like a PT_TXTMOD_STRING, but verifies protocol field name (e.g tcp.flags.syn) */
227 PT_TXTMOD_BOOL
228 /* Displays a checkbox for value */
230
234typedef struct _uat_field_t {
235 const char *name;
236 const char *title;
240 struct {
241 uat_fld_chk_cb_t chk;
242 uat_fld_set_cb_t set;
243 uat_fld_tostr_cb_t tostr;
244 } cb;
245
247 struct {
248 const void *chk;
249 const void *set;
250 const void *tostr;
252
253 const void *fld_data;
254 const char *desc;
257
258#define FLDFILL NULL
259#define UAT_END_FIELDS {NULL,NULL,PT_TXTMOD_NONE,{0,0,0},{0,0,0},0,0,FLDFILL}
260
261/*
262 * Flags to indicate what the settings in this UAT affect.
263 * This is used when UATs are changed interactively, to indicate what needs
264 * to be redone when the UAT is changed.
265 *
266 * UAT_AFFECTS_FIELDS does *not* trigger a redissection, so usually one
267 * will also want UAT_AFFECTS_DISSECTION. A rare exception is changing
268 * the defined dfilter macros.
269 */
270#define UAT_AFFECTS_DISSECTION 0x00000001 /* affects packet dissection */
271#define UAT_AFFECTS_FIELDS 0x00000002 /* affects what named fields exist */
272
292WS_DLL_PUBLIC
293uat_t* uat_new(const char* name,
294 size_t size,
295 const char* filename,
296 bool from_profile,
297 void* data_ptr,
298 unsigned* num_items_ptr,
299 unsigned flags,
300 const char* help,
301 uat_copy_cb_t copy_cb,
302 uat_update_cb_t update_cb,
303 uat_free_cb_t free_cb,
304 uat_post_update_cb_t post_update_cb,
305 uat_reset_cb_t reset_cb,
306 uat_field_t* flds_array);
307
312WS_DLL_PUBLIC
313void uat_destroy(uat_t *uat);
314
319void uat_cleanup(void);
320
331WS_DLL_PUBLIC
332bool uat_load(uat_t* uat_in, const char *filename, const char* app_env_var_prefix, char** err);
333
344WS_DLL_PUBLIC
345bool uat_load_str(uat_t* uat_in, const char* entry, char** err);
346
354uat_t *uat_find(char *name);
355
362WS_DLL_PUBLIC
363uat_t* uat_get_table_by_name(const char* name);
364
378WS_DLL_PUBLIC
379void uat_set_default_values(uat_t *uat_in, const char *default_values[]);
380
381/*
382 * Some common uat_fld_chk_cbs
383 */
399WS_DLL_PUBLIC
400bool uat_fld_chk_str(void *record, const char *ptr, unsigned len,
401 const void *chk_data, const void *fld_data, char **err);
402
417WS_DLL_PUBLIC
418bool uat_fld_chk_oid(void *record, const char *ptr, unsigned len,
419 const void *chk_data, const void *fld_data, char **err);
420
436WS_DLL_PUBLIC
437bool uat_fld_chk_proto(void *record, const char *ptr, unsigned len,
438 const void *chk_data, const void *fld_data, char **err);
439
451WS_DLL_PUBLIC
452bool uat_fld_chk_field(void* u1, const char* strptr, unsigned len, const void* u2, const void* u3, char** err);
453
465WS_DLL_PUBLIC
466bool uat_fld_chk_num_dec(void* u1, const char* strptr, unsigned len, const void* u2, const void* u3, char** err);
467
479WS_DLL_PUBLIC
480bool uat_fld_chk_num_dec64(void* u1, const char* strptr, unsigned len, const void* u2, const void* u3, char** err);
481
493WS_DLL_PUBLIC
494bool uat_fld_chk_num_hex(void* u1, const char* strptr, unsigned len, const void* u2, const void* u3, char** err);
495
507WS_DLL_PUBLIC
508bool uat_fld_chk_num_hex64(void* u1, const char* strptr, unsigned len, const void* u2, const void* u3, char** err);
509
521WS_DLL_PUBLIC
522bool uat_fld_chk_num_signed_dec(void* u1, const char* strptr, unsigned len, const void* u2, const void* u3, char** err);
523
535WS_DLL_PUBLIC
536bool uat_fld_chk_num_signed_dec64(void* u1, const char* strptr, unsigned len, const void* u2, const void* u3, char** err);
537
549WS_DLL_PUBLIC
550bool uat_fld_chk_num_dbl(void* u1, const char* strptr, unsigned len, const void* u2, const void* u3, char** err);
551
563WS_DLL_PUBLIC
564bool uat_fld_chk_bool(void* u1, const char* strptr, unsigned len, const void* u2, const void* u3, char** err);
565
577WS_DLL_PUBLIC
578bool uat_fld_chk_enum(void* u1, const char* strptr, unsigned len, const void* v, const void* u3, char** err);
579
591WS_DLL_PUBLIC
592bool uat_fld_chk_range(void* u1, const char* strptr, unsigned len, const void* u2, const void* u3, char** err);
593
605WS_DLL_PUBLIC
606bool uat_fld_chk_color(void* u1, const char* strptr, unsigned len, const void* u2, const void* u3, char** err);
607
608typedef void (*uat_cb_t)(void* uat,void* user_data);
609
616WS_DLL_PUBLIC
617void uat_foreach_table(uat_cb_t cb,void* user_data);
618
624void uat_unload_all(void);
625
640uint8_t *uat_unesc(const char *si, unsigned in_len, unsigned *len_p);
641
660char *uat_undquote(const char *si, unsigned in_len, unsigned *len_p);
661
673char *uat_esc(const uint8_t *buf, unsigned len);
674
689char *uat_unbinstring(const char *si, unsigned in_len, unsigned *len_p);
690
691/* Some strings entirely made of ... already declared */
692
704WS_DLL_PUBLIC
705bool uat_fld_chk_str_isprint(void* u1, const char* strptr, unsigned len, const void* u2, const void* u3, char** err);
706
718WS_DLL_PUBLIC
719bool uat_fld_chk_str_isalpha(void* u1, const char* strptr, unsigned len, const void* u2, const void* u3, char** err);
720
732WS_DLL_PUBLIC
733bool uat_fld_chk_str_isalnum(void* u1, const char* strptr, unsigned len, const void* u2, const void* u3, char** err);
734
746WS_DLL_PUBLIC
747bool uat_fld_chk_str_isdigit(void* u1, const char* strptr, unsigned len, const void* u2, const void* u3, char** err);
748
760WS_DLL_PUBLIC
761bool uat_fld_chk_str_isxdigit(void* u1, const char* strptr, unsigned len, const void* u2, const void* u3, char** err);
762
763
764/*
765 * Macros
766 * to define basic uat_fld_set_cbs, uat_fld_tostr_cbs
767 * for those elements in uat_field_t array
768 */
769
770#ifdef __cplusplus
771#define UNUSED_PARAMETER(n)
772#else
773#define UNUSED_PARAMETER(n) n _U_
774#endif
775
776/*
777 * CSTRING macros,
778 * a simple c-string contained in (((rec_t*)rec)->(field_name))
779 */
780#define UAT_CSTRING_CB_DEF(basename,field_name,rec_t) \
781static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
782 char* new_buf = g_strndup(buf,len); \
783 g_free((((rec_t*)rec)->field_name)); \
784 (((rec_t*)rec)->field_name) = new_buf; } \
785static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
786 if (((rec_t*)rec)->field_name ) { \
787 *out_ptr = g_strdup((((rec_t*)rec)->field_name)); \
788 *out_len = (unsigned)strlen((((rec_t*)rec)->field_name)); \
789 } else { \
790 *out_ptr = g_strdup(""); *out_len = 0; \
791 } }
792
793#define UAT_FLD_CSTRING(basename,field_name,title,desc) \
794 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_str,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
795
796#define UAT_FLD_CSTRING_ISPRINT(basename,field_name,title,desc) \
797 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_str_isprint,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
798
799#define UAT_FLD_CSTRING_OTHER(basename,field_name,title,chk,desc) \
800 {#field_name, title, PT_TXTMOD_STRING,{ chk ,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
801
802/*
803 * FILENAME and DIRECTORYNAME,
804 * a simple c-string contained in (((rec_t*)rec)->(field_name))
805 */
806#define UAT_FILENAME_CB_DEF(basename,field_name,rec_t) UAT_CSTRING_CB_DEF(basename,field_name,rec_t)
807
808/* XXX UAT_FLD_FILENAME is currently unused. */
809#define UAT_FLD_FILENAME(basename,field_name,title,desc) \
810 {#field_name, title, PT_TXTMOD_FILENAME,{uat_fld_chk_str,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
811
812/*
813 * Both the Qt and GTK+ UIs assume that we're opening a preexisting
814 * file. We might want to split the ..._FILENAME defines into
815 * ..._FILE_OPEN and ..._FILE_SAVE if we ever need to specify a
816 * file that we're creating.
817 */
818#define UAT_FLD_FILENAME_OTHER(basename,field_name,title,chk,desc) \
819 {#field_name, title, PT_TXTMOD_FILENAME,{chk,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
820
821#define UAT_DIRECTORYNAME_CB_DEF(basename,field_name,rec_t) UAT_CSTRING_CB_DEF(basename,field_name,rec_t)
822
823#define UAT_FLD_DIRECTORYNAME(basename,field_name,title,desc) \
824 {#field_name, title, PT_TXTMOD_DIRECTORYNAME,{uat_fld_chk_str,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
825
826/*
827 * DISPLAY_FILTER,
828 * a simple c-string contained in (((rec_t*)rec)->(field_name))
829 */
830#define UAT_DISPLAY_FILTER_CB_DEF(basename,field_name,rec_t) UAT_CSTRING_CB_DEF(basename,field_name,rec_t)
831
832#define UAT_FLD_DISPLAY_FILTER(basename,field_name,title,desc) \
833 {#field_name, title, PT_TXTMOD_DISPLAY_FILTER, {uat_fld_chk_str,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
834
835/*
836 * PROTO_FIELD,
837 * a simple c-string contained in (((rec_t*)rec)->(field_name))
838 */
839#define UAT_PROTO_FIELD_CB_DEF(basename,field_name,rec_t) UAT_CSTRING_CB_DEF(basename,field_name,rec_t)
840
841#define UAT_FLD_PROTO_FIELD(basename,field_name,title,desc) \
842 {#field_name, title, PT_TXTMOD_PROTO_FIELD, {uat_fld_chk_field,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
843
844/*
845 * OID - just a CSTRING with a specific check routine
846 */
847#define UAT_FLD_OID(basename,field_name,title,desc) \
848 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_oid,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
849
850
851/*
852 * LSTRING MACROS - a "string" with an explicit length, so it can contain
853 * internal null characters and possibly unprintable characters, that are
854 * displayed to the user and written to the file using C-style escapes. An
855 * alternative to BUFFER for when the data is often but not necessarily an
856 * ASCII printable string, such as in some types of encryption keys.
857 */
858#define UAT_LSTRING_CB_DEF(basename,field_name,rec_t,ptr_element,len_element) \
859static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
860 uint8_t* new_val = uat_unesc(buf,len,&(((rec_t*)rec)->len_element)); \
861 g_free((((rec_t*)rec)->ptr_element)); \
862 (((rec_t*)rec)->ptr_element) = new_val; } \
863static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
864 if (((rec_t*)rec)->ptr_element ) { \
865 *out_ptr = uat_esc(((rec_t*)rec)->ptr_element, (((rec_t*)rec)->len_element)); \
866 *out_len = (unsigned)strlen(*out_ptr); \
867 } else { \
868 *out_ptr = g_strdup(""); \
869 *out_len = 0; \
870 } }
871
872#define UAT_FLD_LSTRING(basename,field_name,title, desc) \
873{#field_name, title, PT_TXTMOD_STRING,{0,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
874
875
876/*
877 * BUFFER macros,
878 * a buffer_ptr contained in (((rec_t*)rec)->(field_name))
879 * and its len in (((rec_t*)rec)->(len_name))
880 */
881#define UAT_BUFFER_CB_DEF(basename,field_name,rec_t,ptr_element,len_element) \
882static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
883 unsigned char* new_buf = len ? (unsigned char *)g_memdup2(buf,len) : NULL; \
884 g_free((((rec_t*)rec)->ptr_element)); \
885 (((rec_t*)rec)->ptr_element) = new_buf; \
886 (((rec_t*)rec)->len_element) = len; } \
887static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
888 *out_ptr = ((rec_t*)rec)->ptr_element ? (char*)g_memdup2(((rec_t*)rec)->ptr_element,((rec_t*)rec)->len_element) : g_strdup(""); \
889 *out_len = ((rec_t*)rec)->len_element; }
890
891#define UAT_FLD_BUFFER(basename,field_name,title,desc) \
892 {#field_name, title, PT_TXTMOD_HEXBYTES,{0,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
893
894
895/*
896 * DEC Macros,
897 * an unsigned decimal number contained in (((rec_t*)rec)->(field_name))
898 */
899#define UAT_DEC_CB_DEF(basename,field_name,rec_t) \
900static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
901 char* tmp_str = g_strndup(buf,len); \
902 ws_strtou32(tmp_str, NULL, &((rec_t*)rec)->field_name); \
903 g_free(tmp_str); } \
904static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
905 *out_ptr = ws_strdup_printf("%u",((rec_t*)rec)->field_name); \
906 *out_len = (unsigned)strlen(*out_ptr); }
907
908#define UAT_FLD_DEC(basename,field_name,title,desc) \
909 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_num_dec,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
910
911 /*
912 * an unsigned 64bit decimal number contained in (((rec_t*)rec)->(field_name))
913 */
914#define UAT_DEC64_CB_DEF(basename,field_name,rec_t) \
915static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
916 char* tmp_str = g_strndup(buf,len); \
917 ws_strtou64(tmp_str, NULL, &((rec_t*)rec)->field_name); \
918 g_free(tmp_str); } \
919static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
920 *out_ptr = ws_strdup_printf("%" PRIu64,((rec_t*)rec)->field_name); \
921 *out_len = (unsigned)strlen(*out_ptr); }
922
923#define UAT_FLD_DEC64(basename,field_name,title,desc) \
924 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_num_dec64,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
925
926/*
927 * a *signed* decimal number contained in (((rec_t*)rec)->(field_name))
928 */
929#define UAT_SIGNED_DEC_CB_DEF(basename,field_name,rec_t) \
930static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
931 char* tmp_str = g_strndup(buf,len); \
932 ws_strtoi32(tmp_str, NULL, &((rec_t*)rec)->field_name); \
933 g_free(tmp_str); } \
934static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
935 *out_ptr = ws_strdup_printf("%d",((rec_t*)rec)->field_name); \
936 *out_len = (unsigned)strlen(*out_ptr); }
937
938#define UAT_FLD_SIGNED_DEC(basename,field_name,title,desc) \
939 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_num_signed_dec,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
940
941 /*
942 * and a *signed* 64bit decimal number contained in (((rec_t*)rec)->(field_name))
943 */
944#define UAT_SIGNED_DEC64_CB_DEF(basename,field_name,rec_t) \
945static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
946 char* tmp_str = g_strndup(buf,len); \
947 ws_strtoi64(tmp_str, NULL, &((rec_t*)rec)->field_name); \
948 g_free(tmp_str); } \
949static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
950 *out_ptr = ws_strdup_printf("%" PRId64,((rec_t*)rec)->field_name); \
951 *out_len = (unsigned)strlen(*out_ptr); }
952
953#define UAT_FLD_SIGNED_DEC64(basename,field_name,title,desc) \
954 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_num_signed_dec64,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
955
956#define UAT_FLD_NONE(basename,field_name,title,desc) \
957 {#field_name, title, PT_TXTMOD_NONE,{uat_fld_chk_num_dec,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
958
959
960/*
961 * HEX Macros,
962 * an unsigned hexadecimal number contained in (((rec_t*)rec)->(field_name))
963 */
964#define UAT_HEX_CB_DEF(basename,field_name,rec_t) \
965static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
966 char* tmp_str = g_strndup(buf,len); \
967 ws_hexstrtou32(tmp_str, NULL, &((rec_t*)rec)->field_name); \
968 g_free(tmp_str); } \
969static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
970 *out_ptr = ws_strdup_printf("%x",((rec_t*)rec)->field_name); \
971 *out_len = (unsigned)strlen(*out_ptr); }
972
973#define UAT_FLD_HEX(basename,field_name,title,desc) \
974{#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_num_hex,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
975
976 /*
977 * HEX Macros for 64bit,
978 * an unsigned long long hexadecimal number contained in (((rec_t*)rec)->(field_name))
979 */
980#define UAT_HEX64_CB_DEF(basename,field_name,rec_t) \
981static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
982 char* tmp_str = g_strndup(buf,len); \
983 ws_hexstrtou64(tmp_str, NULL, &((rec_t*)rec)->field_name); \
984 g_free(tmp_str); } \
985static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
986 *out_ptr = ws_strdup_printf("%" PRIx64,((rec_t*)rec)->field_name); \
987 *out_len = (unsigned)strlen(*out_ptr); }
988
989#define UAT_FLD_HEX64(basename,field_name,title,desc) \
990{#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_num_hex64,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
991
992/*
993 * DBL Macros,
994 * a double precision floating-point number contained in (((rec_t*)rec)->(field_name))
995 *
996 * [using g_ascii_dtostr() would be fine for tostr_cb for storing data, but
997 * produces more ugly looking values when presenting to the user. dtoa_g_fmt
998 * produces the shortest string which also is a unique round-trip for any
999 * particular value.]
1000 */
1001#define UAT_DBL_CB_DEF(basename,field_name,rec_t) \
1002static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
1003 char* tmp_str = g_strndup(buf,len); \
1004 ((rec_t*)rec)->field_name = g_ascii_strtod(tmp_str, NULL); \
1005 g_free(tmp_str); } \
1006static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
1007 char buf[32]; \
1008 *out_ptr = ws_strdup(dtoa_g_fmt(buf, ((rec_t*)rec)->field_name)); \
1009 *out_len = (unsigned)strlen(*out_ptr); }
1010
1011#define UAT_FLD_DBL(basename,field_name,title,desc) \
1012 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_num_dbl,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
1013
1014/*
1015 * BOOL Macros,
1016 * an boolean value contained in (((rec_t*)rec)->(field_name))
1017 *
1018 * Write "TRUE" or "FALSE" for backwards compatibility with pre-4.4
1019 * versions that expect that capitalization.
1020 */
1021#define UAT_BOOL_CB_DEF(basename,field_name,rec_t) \
1022static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
1023 char* tmp_str = g_strndup(buf,len); \
1024 if (tmp_str && g_ascii_strcasecmp(tmp_str, "true") == 0) \
1025 ((rec_t*)rec)->field_name = 1; \
1026 else \
1027 ((rec_t*)rec)->field_name = 0; \
1028 g_free(tmp_str); } \
1029static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
1030 *out_ptr = ws_strdup_printf("%s",((rec_t*)rec)->field_name ? "TRUE" : "FALSE"); \
1031 *out_len = (unsigned)strlen(*out_ptr); }
1032
1033#define UAT_FLD_BOOL(basename,field_name,title,desc) \
1034{#field_name, title, PT_TXTMOD_BOOL,{uat_fld_chk_bool,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
1035
1036/*
1037 * ENUM macros
1038 * enum_t: name = ((enum_t*)ptr)->strptr
1039 * value = ((enum_t*)ptr)->value
1040 * rec_t:
1041 * value
1042 */
1043#define UAT_VS_DEF(basename,field_name,rec_t,default_t,default_val,default_str) \
1044static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* vs, const void* UNUSED_PARAMETER(u2)) {\
1045 unsigned i; \
1046 char* str = g_strndup(buf,len); \
1047 const char* cstr; \
1048 ((rec_t*)rec)->field_name = default_val; \
1049 for(i=0; ( cstr = ((const value_string*)vs)[i].strptr ) ;i++) { \
1050 if (g_str_equal(cstr,str)) { \
1051 ((rec_t*)rec)->field_name = (default_t)((const value_string*)vs)[i].value; \
1052 g_free(str); \
1053 return; \
1054 } \
1055 } \
1056 g_free(str); } \
1057static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* vs, const void* UNUSED_PARAMETER(u2)) {\
1058 unsigned i; \
1059 for(i=0;((const value_string*)vs)[i].strptr;i++) { \
1060 if ( ((const value_string*)vs)[i].value == ((rec_t*)rec)->field_name ) { \
1061 *out_ptr = g_strdup(((const value_string*)vs)[i].strptr); \
1062 *out_len = (unsigned)strlen(*out_ptr); \
1063 return; \
1064 } \
1065 } \
1066 *out_ptr = g_strdup(default_str); \
1067 *out_len = (unsigned)strlen(default_str); }
1068
1069#define UAT_VS_CSTRING_DEF(basename,field_name,rec_t,default_val,default_str) \
1070static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* vs, const void* UNUSED_PARAMETER(u2)) {\
1071 unsigned i; \
1072 char* str = g_strndup(buf,len); \
1073 const char* cstr; \
1074 ((rec_t*)rec)->field_name = default_val; \
1075 for(i=0; ( cstr = ((const value_string*)vs)[i].strptr ) ;i++) { \
1076 if (g_str_equal(cstr,str)) { \
1077 ((rec_t*)rec)->field_name = g_strdup(((const value_string*)vs)[i].strptr); \
1078 g_free(str); \
1079 return; \
1080 } \
1081 } \
1082 g_free(str);} \
1083static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(vs), const void* UNUSED_PARAMETER(u2)) {\
1084 if (((rec_t*)rec)->field_name ) { \
1085 *out_ptr = g_strdup((((rec_t*)rec)->field_name)); \
1086 *out_len = (unsigned)strlen((((rec_t*)rec)->field_name)); \
1087 } else { \
1088 *out_ptr = g_strdup(""); *out_len = 0; } }
1089
1090#define UAT_FLD_VS(basename,field_name,title,enum,desc) \
1091 {#field_name, title, PT_TXTMOD_ENUM,{uat_fld_chk_enum,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{&(enum),&(enum),&(enum)},&(enum),desc,FLDFILL}
1092
1093
1094/*
1095 * Color Macros,
1096 * an #RRGGBB color value contained in (((rec_t*)rec)->(field_name))
1097 */
1098#define UAT_COLOR_CB_DEF(basename,field_name,rec_t) \
1099static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
1100 if (len < 1) { \
1101 ((rec_t*)rec)->field_name = 0; \
1102 return; \
1103 } \
1104 char* tmp_str = g_strndup(buf+1,len-1); \
1105 ((rec_t*)rec)->field_name = (unsigned)strtol(tmp_str,NULL,16); \
1106 g_free(tmp_str); } \
1107static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
1108 *out_ptr = ws_strdup_printf("#%06X",((rec_t*)rec)->field_name); \
1109 *out_len = (unsigned)strlen(*out_ptr); }
1110
1111#define UAT_FLD_COLOR(basename,field_name,title,desc) \
1112{#field_name, title, PT_TXTMOD_COLOR,{uat_fld_chk_color,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
1113
1114
1115/*
1116 * DISSECTOR macros
1117 */
1118
1119#define UAT_DISSECTOR_DEF(basename, field_name, dissector_field, name_field, rec_t) \
1120static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
1121 if (len) { \
1122 ((rec_t*)rec)->name_field = g_strndup(buf, len); \
1123 g_strstrip(((rec_t*)rec)->name_field); \
1124 ((rec_t*)rec)->dissector_field = find_dissector(((rec_t*)rec)->name_field); \
1125 } else { \
1126 ((rec_t*)rec)->dissector_field = find_dissector("data"); \
1127 ((rec_t*)rec)->name_field = NULL; \
1128 } } \
1129static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
1130 if ( ((rec_t*)rec)->name_field ) { \
1131 *out_ptr = g_strdup((((rec_t*)rec)->name_field)); \
1132 *out_len = (unsigned)strlen(*out_ptr); \
1133 } else { \
1134 *out_ptr = g_strdup(""); *out_len = 0; \
1135 } }
1136
1137
1138#define UAT_FLD_DISSECTOR(basename,field_name,title,desc) \
1139 {#field_name, title, PT_TXTMOD_DISSECTOR,{uat_fld_chk_proto,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
1140
1141#define UAT_FLD_DISSECTOR_OTHER(basename,field_name,title,chk,desc) \
1142 {#field_name, title, PT_TXTMOD_DISSECTOR,{chk,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},{0,0,0},0,desc,FLDFILL}
1143
1144/*
1145 * RANGE macros
1146 */
1147
1148#define UAT_RANGE_CB_DEF(basename,field_name,rec_t) \
1149static void basename ## _ ## field_name ## _set_cb(void* rec, const char* buf, unsigned len, const void* UNUSED_PARAMETER(u1), const void* u2) {\
1150 char* rng = g_strndup(buf,len);\
1151 range_convert_str(NULL, &(((rec_t*)rec)->field_name), rng,GPOINTER_TO_UINT(u2)); \
1152 g_free(rng); \
1153 } \
1154static void basename ## _ ## field_name ## _tostr_cb(void* rec, char** out_ptr, unsigned* out_len, const void* UNUSED_PARAMETER(u1), const void* UNUSED_PARAMETER(u2)) {\
1155 if ( ((rec_t*)rec)->field_name ) { \
1156 *out_ptr = range_convert_range(NULL, ((rec_t*)rec)->field_name); \
1157 *out_len = (unsigned)strlen(*out_ptr); \
1158 } else { \
1159 *out_ptr = g_strdup(""); *out_len = 0; \
1160 } }
1161
1162
1163#define UAT_FLD_RANGE(basename,field_name,title,max,desc) \
1164 {#field_name, title, PT_TXTMOD_STRING,{uat_fld_chk_range,basename ## _ ## field_name ## _set_cb,basename ## _ ## field_name ## _tostr_cb},\
1165 {0,0,0},GUINT_TO_POINTER(max),desc,FLDFILL}
1166
1167#ifdef __cplusplus
1168}
1169#endif /* __cplusplus */
1170
1171/*
1172 * Editor modelines
1173 *
1174 * Local Variables:
1175 * c-basic-offset: 4
1176 * tab-width: 8
1177 * indent-tabs-mode: nil
1178 * End:
1179 *
1180 * ex: set shiftwidth=4 tabstop=8 expandtab:
1181 * :indentSize=4:tabSize=8:noTabs=true:
1182 */
Holds per-field display and cleanup state for a single column in a UAT record's GUI representation.
Definition uat-int.h:35
Describes a single editable field within a UAT (User Accessible Table).
Definition uat.h:234
struct _uat_field_t::@506 cb
Callbacks for validating, applying, and serializing this field's value.
uat_fld_chk_cb_t chk
Definition uat.h:241
uat_text_mode_t mode
Definition uat.h:237
const char * desc
Definition uat.h:254
uat_fld_tostr_cb_t tostr
Definition uat.h:243
const char * title
Definition uat.h:236
const void * fld_data
Definition uat.h:253
const char * name
Definition uat.h:235
const void * chk
Definition uat.h:248
struct _fld_data_t * priv
Definition uat.h:255
const void * set
Definition uat.h:249
const void * tostr
Definition uat.h:250
uat_fld_set_cb_t set
Definition uat.h:242
struct _uat_field_t::@507 cbdata
Opaque context pointers passed as auxiliary data to each corresponding callback.
Represents a User Accessible Table (UAT), managing a set of user-editable records exposed to a dissec...
Definition uat-int.h:44
void *(* uat_copy_cb_t)(void *dest, const void *source, size_t len)
Definition uat.h:85
WS_DLL_PUBLIC void uat_set_default_values(uat_t *uat_in, const char *default_values[])
Definition uat.c:283
WS_DLL_PUBLIC bool uat_fld_chk_num_hex64(void *u1, const char *strptr, unsigned len, const void *u2, const void *u3, char **err)
Check if a field contains a valid hexadecimal number.
WS_DLL_PUBLIC bool uat_fld_chk_bool(void *u1, const char *strptr, unsigned len, const void *u2, const void *u3, char **err)
Check if a field value is a boolean.
WS_DLL_PUBLIC uat_t * uat_new(const char *name, size_t size, const char *filename, bool from_profile, void *data_ptr, unsigned *num_items_ptr, unsigned flags, const char *help, uat_copy_cb_t copy_cb, uat_update_cb_t update_cb, uat_free_cb_t free_cb, uat_post_update_cb_t post_update_cb, uat_reset_cb_t reset_cb, uat_field_t *flds_array)
Definition uat.c:43
WS_DLL_PUBLIC bool uat_fld_chk_num_signed_dec(void *u1, const char *strptr, unsigned len, const void *u2, const void *u3, char **err)
Check if a field contains a signed decimal number.
_uat_text_mode_t
Controls how a UAT (User Accessible Table) field is rendered and parsed in both the preferences file ...
Definition uat.h:175
WS_DLL_PUBLIC bool uat_fld_chk_str(void *record, const char *ptr, unsigned len, const void *chk_data, const void *fld_data, char **err)
UAT field validator for generic string values.
WS_DLL_PUBLIC bool uat_fld_chk_num_hex(void *u1, const char *strptr, unsigned len, const void *u2, const void *u3, char **err)
Checks if a field contains a valid hexadecimal number.
uint8_t * uat_unesc(const char *si, unsigned in_len, unsigned *len_p)
Converts an ASCII string using C-style escapes (e.g., for unprintable.
Definition uat.c:961
struct _uat_field_t uat_field_t
Describes a single editable field within a UAT (User Accessible Table).
WS_DLL_PUBLIC bool uat_fld_chk_num_dbl(void *u1, const char *strptr, unsigned len, const void *u2, const void *u3, char **err)
Check if a field value is a numeric double.
WS_DLL_PUBLIC uat_t * uat_get_table_by_name(const char *name)
Retrieve a UAT table by its name.
Definition uat.c:270
WS_DLL_PUBLIC void uat_foreach_table(uat_cb_t cb, void *user_data)
Iterates over all UAT tables and calls a callback function for each.
Definition uat.c:607
WS_DLL_PUBLIC bool uat_fld_chk_oid(void *record, const char *ptr, unsigned len, const void *chk_data, const void *fld_data, char **err)
UAT field validator for ASN.1 Object Identifier strings.
char * uat_undquote(const char *si, unsigned in_len, unsigned *len_p)
Decode a quoted, C-style escaped ASCII string into a raw byte array.
Definition uat.c:1043
WS_DLL_PUBLIC bool uat_fld_chk_proto(void *record, const char *ptr, unsigned len, const void *chk_data, const void *fld_data, char **err)
UAT field validator for Wireshark protocol name strings.
WS_DLL_PUBLIC bool uat_fld_chk_str_isprint(void *u1, const char *strptr, unsigned len, const void *u2, const void *u3, char **err)
Checks if a string contains only printable characters.
void(* uat_free_cb_t)(void *record)
Definition uat.h:95
void uat_cleanup(void)
Cleanup all UATs.
Definition uat.c:589
WS_DLL_PUBLIC bool uat_fld_chk_enum(void *u1, const char *strptr, unsigned len, const void *v, const void *u3, char **err)
Checks if a field value is a valid enum.
WS_DLL_PUBLIC bool uat_fld_chk_color(void *u1, const char *strptr, unsigned len, const void *u2, const void *u3, char **err)
Checks if a color field is valid.
WS_DLL_PUBLIC bool uat_fld_chk_str_isxdigit(void *u1, const char *strptr, unsigned len, const void *u2, const void *u3, char **err)
Checks if a string contains only hexadecimal digits.
WS_DLL_PUBLIC bool uat_load_str(uat_t *uat_in, const char *entry, char **err)
Create or update a single UAT entry using a string.
bool(* uat_update_cb_t)(void *record, char **error)
Definition uat.h:123
WS_DLL_PUBLIC bool uat_fld_chk_str_isalnum(void *u1, const char *strptr, unsigned len, const void *u2, const void *u3, char **err)
Checks if a string is alphanumeric.
WS_DLL_PUBLIC bool uat_fld_chk_field(void *u1, const char *strptr, unsigned len, const void *u2, const void *u3, char **err)
Checks if a field name is valid.
WS_DLL_PUBLIC bool uat_fld_chk_num_dec(void *u1, const char *strptr, unsigned len, const void *u2, const void *u3, char **err)
Checks if a field value is a valid decimal number.
enum _uat_text_mode_t uat_text_mode_t
Controls how a UAT (User Accessible Table) field is rendered and parsed in both the preferences file ...
WS_DLL_PUBLIC bool uat_fld_chk_num_signed_dec64(void *u1, const char *strptr, unsigned len, const void *u2, const void *u3, char **err)
Check if a field value is a signed decimal 64-bit number.
void uat_unload_all(void)
Unloads all UATs that are not loaded from a profile.
Definition uat.c:560
WS_DLL_PUBLIC bool uat_fld_chk_range(void *u1, const char *strptr, unsigned len, const void *u2, const void *u3, char **err)
Checks if a field value is a range object.
char * uat_unbinstring(const char *si, unsigned in_len, unsigned *len_p)
Decode an ASCII hex-digit string into a raw byte array.
Definition uat.c:936
void(* uat_reset_cb_t)(void)
Definition uat.h:103
WS_DLL_PUBLIC bool uat_fld_chk_str_isdigit(void *u1, const char *strptr, unsigned len, const void *u2, const void *u3, char **err)
Checks if a string contains only digits.
WS_DLL_PUBLIC bool uat_fld_chk_num_dec64(void *u1, const char *strptr, unsigned len, const void *u2, const void *u3, char **err)
Checks if a field value is a valid decimal 64-bit number.
char * uat_esc(const uint8_t *buf, unsigned len)
Encode a raw byte array as a NUL-terminated C-style escaped ASCII string.
Definition uat.c:1048
uat_t * uat_find(char *name)
Given a UAT name or filename, find its pointer.
Definition uat.c:520
WS_DLL_PUBLIC void uat_destroy(uat_t *uat)
Free and deregister a single UAT.
Definition uat.c:601
WS_DLL_PUBLIC bool uat_fld_chk_str_isalpha(void *u1, const char *strptr, unsigned len, const void *u2, const void *u3, char **err)
Checks if a string contains only alphabetic characters.
WS_DLL_PUBLIC bool uat_load(uat_t *uat_in, const char *filename, const char *app_env_var_prefix, char **err)
Populate a UAT using its file.