sedna 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. data/{CHANGES → CHANGES.rdoc} +9 -0
  2. data/{README → README.rdoc} +23 -25
  3. data/Rakefile +32 -9
  4. data/ext/{extconf.rb → sedna/extconf.rb} +33 -21
  5. data/ext/{sedna.c → sedna/sedna.c} +48 -40
  6. data/test/sedna_test.rb +9 -9
  7. data/vendor/sedna/AUTHORS +18 -0
  8. data/vendor/sedna/COPYRIGHT +90 -0
  9. data/vendor/sedna/LICENSE +202 -0
  10. data/vendor/sedna/Makefile.include +423 -0
  11. data/vendor/sedna/Makefile.platform +31 -0
  12. data/vendor/sedna/depend.sed +48 -0
  13. data/vendor/sedna/driver/c/Makefile +98 -0
  14. data/vendor/sedna/driver/c/libsedna.c +1998 -0
  15. data/vendor/sedna/driver/c/libsedna.h +199 -0
  16. data/vendor/sedna/driver/c/sednamt.def +21 -0
  17. data/vendor/sedna/driver/c/sp_defs.h +186 -0
  18. data/vendor/sedna/kernel/common/FastXptrHash.cpp +101 -0
  19. data/vendor/sedna/kernel/common/IntHash.h +314 -0
  20. data/vendor/sedna/kernel/common/IntList.h +224 -0
  21. data/vendor/sedna/kernel/common/Makefile +30 -0
  22. data/vendor/sedna/kernel/common/SSMMsg.cpp +459 -0
  23. data/vendor/sedna/kernel/common/SSMMsg.h +142 -0
  24. data/vendor/sedna/kernel/common/XptrHash.h +435 -0
  25. data/vendor/sedna/kernel/common/argtable.c +972 -0
  26. data/vendor/sedna/kernel/common/argtable.h +896 -0
  27. data/vendor/sedna/kernel/common/base.cpp +339 -0
  28. data/vendor/sedna/kernel/common/base.h +226 -0
  29. data/vendor/sedna/kernel/common/bit_set.cpp +157 -0
  30. data/vendor/sedna/kernel/common/bit_set.h +55 -0
  31. data/vendor/sedna/kernel/common/commutil.h +67 -0
  32. data/vendor/sedna/kernel/common/config.h +62 -0
  33. data/vendor/sedna/kernel/common/counted_ptr.h +74 -0
  34. data/vendor/sedna/kernel/common/errdbg/ErrorCodes.java +1056 -0
  35. data/vendor/sedna/kernel/common/errdbg/Makefile +34 -0
  36. data/vendor/sedna/kernel/common/errdbg/assert.c +133 -0
  37. data/vendor/sedna/kernel/common/errdbg/d_printf.c +150 -0
  38. data/vendor/sedna/kernel/common/errdbg/d_printf.h +91 -0
  39. data/vendor/sedna/kernel/common/errdbg/error.codes +1743 -0
  40. data/vendor/sedna/kernel/common/errdbg/error_codes.c +531 -0
  41. data/vendor/sedna/kernel/common/errdbg/error_codes.h +549 -0
  42. data/vendor/sedna/kernel/common/errdbg/error_codes_scm.scm +527 -0
  43. data/vendor/sedna/kernel/common/errdbg/event_log.c +956 -0
  44. data/vendor/sedna/kernel/common/errdbg/event_log.h +226 -0
  45. data/vendor/sedna/kernel/common/errdbg/exceptions.cpp +155 -0
  46. data/vendor/sedna/kernel/common/errdbg/exceptions.h +559 -0
  47. data/vendor/sedna/kernel/common/errdbg/gen_error_codes +0 -0
  48. data/vendor/sedna/kernel/common/errdbg/gen_error_codes.c +345 -0
  49. data/vendor/sedna/kernel/common/gmm.cpp +192 -0
  50. data/vendor/sedna/kernel/common/gmm.h +29 -0
  51. data/vendor/sedna/kernel/common/ipc_ops.cpp +435 -0
  52. data/vendor/sedna/kernel/common/ipc_ops.h +51 -0
  53. data/vendor/sedna/kernel/common/lfsGlobals.h +12 -0
  54. data/vendor/sedna/kernel/common/lm_base.h +90 -0
  55. data/vendor/sedna/kernel/common/mmgr/Makefile +11 -0
  56. data/vendor/sedna/kernel/common/mmgr/aset.c +1185 -0
  57. data/vendor/sedna/kernel/common/mmgr/mcxt.c +741 -0
  58. data/vendor/sedna/kernel/common/mmgr/memnodes.h +70 -0
  59. data/vendor/sedna/kernel/common/mmgr/memutils.h +145 -0
  60. data/vendor/sedna/kernel/common/mmgr/se_alloc.h +321 -0
  61. data/vendor/sedna/kernel/common/mmgr/track.c +214 -0
  62. data/vendor/sedna/kernel/common/pping.cpp +672 -0
  63. data/vendor/sedna/kernel/common/pping.h +119 -0
  64. data/vendor/sedna/kernel/common/rcv_test.cpp +273 -0
  65. data/vendor/sedna/kernel/common/rcv_test.h +19 -0
  66. data/vendor/sedna/kernel/common/sedna.c +128 -0
  67. data/vendor/sedna/kernel/common/sedna.h +49 -0
  68. data/vendor/sedna/kernel/common/sedna_ef.h +52 -0
  69. data/vendor/sedna/kernel/common/sm_vmm_data.h +144 -0
  70. data/vendor/sedna/kernel/common/sp.c +93 -0
  71. data/vendor/sedna/kernel/common/sp.h +36 -0
  72. data/vendor/sedna/kernel/common/st/Makefile +20 -0
  73. data/vendor/sedna/kernel/common/st/os_linux/stacktrace.c +213 -0
  74. data/vendor/sedna/kernel/common/st/os_nt/stacktrace.c +338 -0
  75. data/vendor/sedna/kernel/common/st/os_other/stacktrace.c +39 -0
  76. data/vendor/sedna/kernel/common/st/stacktrace.h +72 -0
  77. data/vendor/sedna/kernel/common/st/stacktrfmt.c +64 -0
  78. data/vendor/sedna/kernel/common/tr_debug.cpp +112 -0
  79. data/vendor/sedna/kernel/common/tr_debug.h +22 -0
  80. data/vendor/sedna/kernel/common/u/Makefile +14 -0
  81. data/vendor/sedna/kernel/common/u/u.c +268 -0
  82. data/vendor/sedna/kernel/common/u/u.h +715 -0
  83. data/vendor/sedna/kernel/common/u/uatomic.h +12 -0
  84. data/vendor/sedna/kernel/common/u/udl.h +31 -0
  85. data/vendor/sedna/kernel/common/u/uevent.c +406 -0
  86. data/vendor/sedna/kernel/common/u/uevent.h +71 -0
  87. data/vendor/sedna/kernel/common/u/ugnames.cpp +330 -0
  88. data/vendor/sedna/kernel/common/u/ugnames.h +134 -0
  89. data/vendor/sedna/kernel/common/u/uhash_map.h +77 -0
  90. data/vendor/sedna/kernel/common/u/uhdd.c +1018 -0
  91. data/vendor/sedna/kernel/common/u/uhdd.h +206 -0
  92. data/vendor/sedna/kernel/common/u/ummap.cpp +268 -0
  93. data/vendor/sedna/kernel/common/u/ummap.h +60 -0
  94. data/vendor/sedna/kernel/common/u/umutex.c +145 -0
  95. data/vendor/sedna/kernel/common/u/umutex.h +65 -0
  96. data/vendor/sedna/kernel/common/u/upipe.cpp +244 -0
  97. data/vendor/sedna/kernel/common/u/upipe.h +74 -0
  98. data/vendor/sedna/kernel/common/u/uprocess.c +767 -0
  99. data/vendor/sedna/kernel/common/u/uprocess.h +91 -0
  100. data/vendor/sedna/kernel/common/u/usafesync.h +41 -0
  101. data/vendor/sedna/kernel/common/u/usecurity.c +150 -0
  102. data/vendor/sedna/kernel/common/u/usecurity.h +55 -0
  103. data/vendor/sedna/kernel/common/u/usem.c +891 -0
  104. data/vendor/sedna/kernel/common/u/usem.h +83 -0
  105. data/vendor/sedna/kernel/common/u/ushm.c +222 -0
  106. data/vendor/sedna/kernel/common/u/ushm.h +46 -0
  107. data/vendor/sedna/kernel/common/u/usocket.c +541 -0
  108. data/vendor/sedna/kernel/common/u/usocket.h +118 -0
  109. data/vendor/sedna/kernel/common/u/usystem.c +57 -0
  110. data/vendor/sedna/kernel/common/u/usystem.h +46 -0
  111. data/vendor/sedna/kernel/common/u/uthread.c +259 -0
  112. data/vendor/sedna/kernel/common/u/uthread.h +95 -0
  113. data/vendor/sedna/kernel/common/u/utime.c +65 -0
  114. data/vendor/sedna/kernel/common/u/utime.h +40 -0
  115. data/vendor/sedna/kernel/common/u/uutils.c +142 -0
  116. data/vendor/sedna/kernel/common/u/uutils.h +65 -0
  117. data/vendor/sedna/kernel/common/ugc.cpp +156 -0
  118. data/vendor/sedna/kernel/common/ugc.h +15 -0
  119. data/vendor/sedna/kernel/common/utils.cpp +156 -0
  120. data/vendor/sedna/kernel/common/utils.h +133 -0
  121. data/vendor/sedna/kernel/common/version.c +16 -0
  122. data/vendor/sedna/kernel/common/version.h +21 -0
  123. data/vendor/sedna/kernel/common/wustructures.h +18 -0
  124. data/vendor/sedna/kernel/common/wutypes.h +34 -0
  125. data/vendor/sedna/kernel/common/xptr.cpp +17 -0
  126. data/vendor/sedna/kernel/common/xptr.h +211 -0
  127. data/vendor/sedna/ver +1 -0
  128. metadata +142 -14
@@ -0,0 +1,972 @@
1
+ /*********************************************************************
2
+ This file is part of the argtable library. It contains the definitions
3
+ of the argtable library functions as well as specially formatted
4
+ comments that constitute the source text for the manual pages
5
+ pertaining to those functions.
6
+
7
+ Copyright (C) 2003,2004 ISP RAS (modis@ispras.ru)
8
+ Copyright (C) 1998,1999,2001 Stewart Heitmann (sheitmann@users.sourceforge.net)
9
+
10
+ The argtable library is free software; you can redistribute it and/or
11
+ modify it under the terms of the GNU Library General Public License as
12
+ published by the Free Software Foundation; either version 2 of the
13
+ License, or (at your option) any later version.
14
+
15
+ This software is distributed in the hope that it will be useful,
16
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
+ Library General Public License for more details.
19
+
20
+ You should have received a copy of the GNU Library General Public
21
+ License along with this library; if not, write to the Free Software
22
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
23
+ USA.
24
+ *********************************************************************/
25
+
26
+ #include <stdio.h>
27
+ #include <stdlib.h>
28
+ #include <string.h>
29
+ #include <ctype.h>
30
+ #include <errno.h>
31
+ #include "common/argtable.h"
32
+
33
+ #define ARGSTRLEN 1024
34
+ #define NAMESTRING(A) ((A.argname)?(A.argname):(arg_typestr[A.argtype]))
35
+ #define NULLSAFE(S) ((S)?(S):(""))
36
+
37
+ /* Need a pointer distinct from NULL and any valid string address.
38
+ I admit this particular hack is THE UGLY ONE.
39
+ ZN*/
40
+ const char *arg_no_default_value = (const char *)&malloc;
41
+
42
+ static
43
+ const char whitespace[] = " \f\n\r\v\t";
44
+
45
+ static
46
+ int arg_convertbool(const char *str)
47
+ {
48
+ /************************************************************
49
+ Returns 0 if *str satisfies a case-insensitive match on a
50
+ leading substring of "FALSE", "NO", or "OFF". Leading whitespace
51
+ is ignored.
52
+ Returns 1 if *str matches "TRUE", "YES", or "ON".
53
+ Returns -1 otherwise.
54
+ Handles str==NULL safely.
55
+ **************************************************************/
56
+ char buff[ARGSTRLEN];
57
+ int i,n;
58
+
59
+ /*-- handle NULL str */
60
+ if (str==NULL)
61
+ return -1;
62
+
63
+ /*-- skip leading whitespace --*/
64
+ while (isspace((int)*str))
65
+ str++;
66
+
67
+ /*-- handle empty string --*/
68
+ if (strcmp(str,"")==0)
69
+ return -1;
70
+
71
+ /*-- put an upper case copy of *str in buff[] --*/
72
+ n = strlen(str);
73
+ strncpy(buff,str,ARGSTRLEN);
74
+ for (i=0; i<n; i++)
75
+ buff[i]=toupper(str[i]);
76
+
77
+ /*-- match on "FALSE", "NO", or "OFF" --*/
78
+ if (strncmp(buff,"FALSE",n)==0)
79
+ return 0;
80
+ if (strncmp(buff,"NO",n)==0)
81
+ return 0;
82
+ if (strncmp(buff,"OFF",n)==0 && n>1)
83
+ return 0;
84
+
85
+ /*-- match on "TRUE", "YES", or "ON" --*/
86
+ if (strncmp(buff,"TRUE",n)==0)
87
+ return 1;
88
+ if (strncmp(buff,"YES",n)==0)
89
+ return 1;
90
+ if (strncmp(buff,"ON",n)==0 && n>1)
91
+ return 1;
92
+
93
+ /*-- no match --*/
94
+ return -1;
95
+ }
96
+
97
+
98
+ static
99
+ int arg_set_defaults(arg_rec *argtable, int n, char* ErrMsg)
100
+ {
101
+ /***************************************************************************
102
+ Converts the default argument values from strings into the appropriate data
103
+ type for that argument.
104
+ Argument table entries with NULL default strings are ignored.
105
+ Default values of arguments with NULL valueptrs are converted but then
106
+ discarded. This is for consistent behaviour, rather than absolute necessity.
107
+
108
+ Should a default value be invalid, then an error message is written into
109
+ *ErrMsg and the function returns 0. Should ErrMsg==NULL then the error
110
+ message is omitted.
111
+ The funtion returns 1 upon success.
112
+ ***************************************************************************/
113
+ int i;
114
+
115
+ /*-- clear *ErrMsg --*/
116
+ if (ErrMsg)
117
+ ErrMsg[0]='\0';
118
+
119
+ for (i=0; i<n; i++)
120
+ {
121
+ /*-- skip over NULL defaults --*/
122
+ if (argtable[i].defaultstr==NULL || argtable[i].defaultstr == ARGTABLE_NO_DEFAULT_VALUE)
123
+ continue;
124
+
125
+ /*-- convert default value to appropriate data type --*/
126
+ switch (argtable[i].argtype)
127
+ {
128
+ case arg_bool:
129
+ {
130
+ int x = arg_convertbool(argtable[i].defaultstr);
131
+ if (!(x==0 || x==1))
132
+ {
133
+ if (ErrMsg)
134
+ sprintf(ErrMsg,"arg[%d].defaultstr == \"%s\", invalid bool",
135
+ i,argtable[i].defaultstr);
136
+ return 0;
137
+ }
138
+ if (argtable[i].valueptr!=NULL)
139
+ *((int*)argtable[i].valueptr) = x;
140
+ break;
141
+ }
142
+
143
+ case arg_int:
144
+ case arg_lit:
145
+ {
146
+ char *p=NULL;
147
+ int x;
148
+ //printf("errno %d\n",errno);
149
+ x = (int)strtol(argtable[i].defaultstr,&p,10);
150
+ //printf("arg x=%d\n\n", x);
151
+ //printf("argtable[i].defaultstr=%s\n\n", argtable[i].defaultstr);
152
+ //printf("errno %d, p \"%s\"\n",errno,p);
153
+ if (errno!=0 || strlen(p)>0 || p==argtable[i].defaultstr)
154
+ {
155
+ if (ErrMsg)
156
+ sprintf(ErrMsg,"arg[%d].defaultstr == \"%s\", invalid int",
157
+ i,argtable[i].defaultstr);
158
+ return 0;
159
+ }
160
+ if (argtable[i].valueptr!=NULL)
161
+ *((int*)argtable[i].valueptr) = x;
162
+ break;
163
+ }
164
+
165
+ case arg_dbl:
166
+ {
167
+ char *p;
168
+ double x;
169
+ x = strtod(argtable[i].defaultstr,&p);
170
+ if (errno!=0 || strlen(p)>0 || p==argtable[i].defaultstr)
171
+ {
172
+ if (ErrMsg)
173
+ sprintf(ErrMsg,"arg[%d].defaultstr == \"%s\", invalid double",
174
+ i,argtable[i].defaultstr);
175
+ return 0;
176
+ }
177
+ if (argtable[i].valueptr!=NULL)
178
+ *((double*)argtable[i].valueptr) = x;
179
+ break;
180
+ }
181
+
182
+ case arg_str:
183
+ if (argtable[i].valueptr!=NULL)
184
+ strcpy((char*)(argtable[i].valueptr), argtable[i].defaultstr);
185
+ break;
186
+
187
+ };
188
+
189
+ }
190
+
191
+ return 1;
192
+ }
193
+
194
+
195
+ static
196
+ int arg_scanf(const char* str, arg_rec* argrec)
197
+ {
198
+ /*************************************************************
199
+ Scans *src for the argument specified in *argrec and writes
200
+ the result into *(argrec->valueptr). The function returns the
201
+ number of characters that were read.
202
+ If (argrec->valueptr)==NULL then the scanned value is discarded.
203
+ Should an error occur, the function returns -1 and leaves
204
+ *(argrec->valueptr) unaltered.
205
+ Note: Strings which are enclosed by single quotes are automatically
206
+ stripped of the enclosing quotes.
207
+ **************************************************************/
208
+ int length = 0;
209
+
210
+ switch (argrec->argtype)
211
+ {
212
+ case arg_bool:
213
+ {
214
+ char boolstr[ARGSTRLEN];
215
+ int boolval;
216
+
217
+ /*-- scan a boolean string value --*/
218
+ if ( sscanf(str,"%s%n",boolstr,&length) != 1 )
219
+ return -1;
220
+
221
+ /*-- convert string to boolean int value --*/
222
+ boolval = arg_convertbool(boolstr);
223
+ if (boolval==-1)
224
+ return -1;
225
+
226
+ /*-- write scanned value into *argrec --*/
227
+ if (argrec->valueptr)
228
+ *((int*)argrec->valueptr) = boolval;
229
+ break;
230
+ }
231
+
232
+ case arg_lit:
233
+ {
234
+ /*-- if arg has a tag then presume it was located just prior to --*/
235
+ /*-- this function. Thus we have found a literal tag. Set the arg --*/
236
+ /*-- value (presuming it also is non-NULL) to 1. --*/
237
+ if (argrec->tagstr && argrec->valueptr)
238
+ *((int*)argrec->valueptr) = 1;
239
+
240
+ /*-- if argname!=NULL then scan a literal from the command line. --*/
241
+ if (argrec->argname)
242
+ {
243
+ /*char fmtstr[ARGSTRLEN];*/
244
+ char litstr[ARGSTRLEN];
245
+
246
+ /*-- scan a literal string value --*/
247
+ if ( sscanf(str,"%s%n",litstr,&length) != 1 )
248
+ return -1;
249
+
250
+ /*-- compare literal value to expected value --*/
251
+ /*-- (ignores possibility of leading whitespace in argname) --*/
252
+ if (strcmp(argrec->argname,litstr)!=0)
253
+ return -1;
254
+
255
+ /*-- scan succeeded --*/
256
+ if (argrec->valueptr)
257
+ *((int*)argrec->valueptr) = 1;
258
+ /*printf("...ok (%d)\n",length);*/
259
+ }
260
+ break;
261
+ }
262
+
263
+ case arg_int:
264
+ {
265
+ int intval;
266
+
267
+ /*-- scan an int value --*/
268
+ if (sscanf(str,"%i %n",&intval,&length) !=1)
269
+ return -1;
270
+
271
+ /*-- write scanned value into *argrec --*/
272
+ if (argrec->valueptr)
273
+ *((int*)argrec->valueptr) = intval;
274
+ break;
275
+ }
276
+
277
+ case arg_dbl:
278
+ {
279
+ double dblval;
280
+
281
+ /*-- scan for double value --*/
282
+ if ( sscanf(str,"%lf%n",&dblval,&length) != 1)
283
+ return -1;
284
+
285
+ /*-- write scanned value into *argrec --*/
286
+ if (argrec->valueptr)
287
+ *((double*)argrec->valueptr) = dblval;
288
+ break;
289
+ }
290
+
291
+ case arg_str:
292
+ {
293
+ char strval[ARGSTRLEN];
294
+
295
+ /*-- scan for quoted string fist, if no good then try unquoted --*/
296
+ if (sscanf(str," \"%[^\"]\"%n",strval,&length) != 1 &&
297
+ sscanf(str," '%[^']'%n",strval,&length) != 1)
298
+ if (sscanf(str,"%s%n",strval,&length) != 1 ||
299
+ (length != 0 && strval[0] == '-'))
300
+ return -1;
301
+
302
+ /*-- write the string into *argrec --*/
303
+ if (argrec->valueptr)
304
+ strcpy((char*)argrec->valueptr,strval);
305
+ break;
306
+ }
307
+ }
308
+
309
+ return length;
310
+ }
311
+
312
+
313
+ static
314
+ char* arg_extract_tag(char* str, const char* tag)
315
+ {
316
+ /**********************************************************************
317
+ Searches 'str' for the first occurrence of 'tag'.
318
+ If found, the tag is erased from str by overwriting it with
319
+ spaces. The function then returns a pointer to the next char in 'str'
320
+ immediately after the tag.
321
+ If the tag cannot be found in cmdline then NULL is returned.
322
+ **********************************************************************/
323
+ char* p;
324
+ restart:
325
+ p = strstr(str,tag);
326
+ if (p)
327
+ {
328
+ int n = strlen(tag);
329
+ if (p!=str && !isspace(p[-1]))
330
+ {
331
+ str = p+1;
332
+ goto restart;
333
+ }
334
+ if (p[n] == '=') n+=1;
335
+ memset(p,' ',n);
336
+ p+=n;
337
+ }
338
+ return p;
339
+ }
340
+
341
+
342
+
343
+ static
344
+ char* arg_extract_value(char* str, arg_rec* argrec)
345
+ {
346
+ /************************************************************
347
+ Scans the leading characters of str for an argument value as
348
+ specified by 'argrec'. If successful, the scanned value is
349
+ written into *(argrec->valueptr). The scanned characters are then
350
+ erased from str by overwriting them with spaces. The function
351
+ then returns a pointer to the next char in 'str' following the
352
+ scanned chars.
353
+ If argrec->valueptr==NULL then the scanned value is discarded.
354
+ If the scan was unsuccessful, both 'str' and *(argrec-valueptr)
355
+ remain unaltered and the function returns NULL.
356
+ **************************************************************/
357
+ int nscan = arg_scanf(str, argrec);
358
+ if (nscan==-1)
359
+ return NULL;
360
+ memset(str,' ',nscan);
361
+ return (str+nscan);
362
+ }
363
+
364
+
365
+ static
366
+ void arg_sprint_marker(int i, int n, char *ErrMark)
367
+ {
368
+ /************************************************************
369
+ Writes i leading spaces, followed by n carets '^' into *ErrMark.
370
+ **************************************************************/
371
+ while (i-->0)
372
+ *ErrMark++ = ' ';
373
+ while (n-->0)
374
+ *ErrMark++ = '^';
375
+ *ErrMark='\0';
376
+ }
377
+
378
+
379
+ static
380
+ int arg_extract_tagged_args(char* cmdline, arg_rec* argtable, int n,
381
+ char* ErrMsg, char* ErrMark)
382
+ {
383
+ /****************************************************************
384
+ Steps thru each entry in the argument table. For each entry that
385
+ has a non-NULL tag string, the string in *cmdline is scanned for
386
+ a sequence of chars that match the tag. If found, the argument
387
+ value that is associated with the tag is scanned from *cmdline
388
+ and written into the memory location pointed to by the argument
389
+ table entry.
390
+ Having done so, the tag + value is then erased from *cmdline by
391
+ overwriting them with spaces.
392
+ If the valueptr field of the argument table entry is NULL then
393
+ the scanned value is discarded.
394
+ The function returns 1 upon success, 0 upon failure.
395
+ If the tag is not found in *cmdline and there is no default
396
+ argument value for that argument table entry then an error is
397
+ returned.
398
+ If the tag is found, but the argument value could not be scanned
399
+ then an error is returned.
400
+ If multiple occurrences of the tag are found then an error is
401
+ returned.
402
+ Error messages are written into a user supplied string buffer at
403
+ *ErrMsg.
404
+ A marker string that indicates the position of the error in *cmdline
405
+ is written into a user supplied string buffer at *ErrMark.
406
+ Both ErrMsg and ErrMark are optional. If they are given as NULL
407
+ they are ignored.
408
+ ****************************************************************/
409
+ int i;
410
+
411
+ /*-- init ErrMsg and ErrMark if given non-NULL ptrs --*/
412
+ if (ErrMsg)
413
+ *ErrMsg = '\0';
414
+ if (ErrMark)
415
+ *ErrMark = '\0';
416
+
417
+ /*-- iterate thru the tagged entries in argtable[]--*/
418
+ for (i=0; i<n; i++)
419
+ {
420
+ const char* argtag = NULLSAFE(argtable[i].tagstr);
421
+ const char* argname = NAMESTRING(argtable[i]);
422
+ char *p;
423
+ /*printf("scanning arg %d in \"%s\"\n",i,cmdline);*/
424
+
425
+ /*-- skip entries with NULL tags --*/
426
+ if (argtable[i].tagstr==NULL)
427
+ continue;
428
+
429
+ /*-- extract 1st occurrence of argument tag from cmdline string. --*/
430
+ /*-- if successful, the return char* points to the char immediately --*/
431
+ /*-- following the tag that just extracted from *cmdline. --*/
432
+ p = arg_extract_tag(cmdline,argtable[i].tagstr);
433
+
434
+ /*-- if tag was not found then... --*/
435
+ if (!p)
436
+ {
437
+ /*-- if a default argument value is supplied then skip, else error --*/
438
+ if (argtable[i].defaultstr!=NULL)
439
+ continue;
440
+ else
441
+ {
442
+ if (ErrMsg)
443
+ sprintf(ErrMsg,"missing argument: %s%s", argtag,argname);
444
+ if (ErrMark)
445
+ arg_sprint_marker(strlen(cmdline),1,ErrMark);
446
+ return 0;
447
+ }
448
+ }
449
+
450
+ /*-- tag was found, now scan the arg value --*/
451
+ if (!arg_extract_value(p,&argtable[i]))
452
+ {
453
+ if (ErrMsg)
454
+ sprintf(ErrMsg,"invalid argument: %s%s", argtag,argname);
455
+ if (ErrMark)
456
+ arg_sprint_marker((int)(p-cmdline),1,ErrMark);
457
+ return 0;
458
+ }
459
+
460
+ /*-- check for other occurrences of same tag --*/
461
+ p = arg_extract_tag(cmdline,argtable[i].tagstr);
462
+ if (p)
463
+ {
464
+ if (ErrMsg)
465
+ sprintf(ErrMsg,"repeat tag");
466
+ if (ErrMark)
467
+ {
468
+ int taglen = strlen(argtable[i].tagstr);
469
+ arg_sprint_marker((int)(p-cmdline-taglen),taglen,ErrMark);
470
+ }
471
+ return 0;
472
+ }
473
+ }
474
+
475
+ return 1;
476
+ }
477
+
478
+
479
+ static
480
+ int arg_extract_untagged_args(char* cmdline, arg_rec* argtable, int n, char* ErrMsg, char * ErrMark)
481
+ {
482
+ /****************************************************************
483
+ Steps thru each entry in the argument table. For each entry that
484
+ has a NULL tag string, cmdline[] is scanned from left to right for
485
+ the first occuring argument. The value of that argument is written
486
+ into the location specified by the valueptr field of the appropriate
487
+ argtable entry. The argument is then erased from cmdline[] by
488
+ overwriting it with spaces.
489
+ If the valueptr field is NULL then the scanned value is discarded.
490
+ Upon successful completion of the function, all scanned arguments
491
+ will have been erased from cmdline[]. Any extraneous arguments
492
+ remain in cmdline[] intact.
493
+ If an argument value does not match the expected type and that
494
+ argument is optional (ie: it has a non-NULL default value) then
495
+ we give the user the benefit of the doubt and assume that the
496
+ value given was not intended for this argument. On the other
497
+ hand, if the argument is not optional, then we know immediately
498
+ that the value is invalid and an error should be generated.
499
+ Error messages are written into a user supplied string buffer at
500
+ *ErrMsg.
501
+ A marker string that indicates the position of the error in *cmdline
502
+ is written into a user supplied string buffer at *ErrMark.
503
+ Both ErrMsg and ErrMark are optional. If they are given as NULL
504
+ they are ignored.
505
+ The function returns 1 upon success, 0 upon failure.
506
+ ****************************************************************/
507
+ char* p = cmdline;
508
+ int i;
509
+
510
+ /*-- init ErrMsg and ErrMark if given non-NULL ptrs --*/
511
+ if (ErrMsg)
512
+ *ErrMsg = '\0';
513
+ if (ErrMark)
514
+ *ErrMark = '\0';
515
+
516
+ /*-- iterate thru each untagged entry in argtable[] --*/
517
+ for (i=0; i<n; i++)
518
+ {
519
+ const char* argname = NAMESTRING(argtable[i]);
520
+
521
+ /*printf("scanning arg %d in \"%s\"\n",i,cmdline);*/
522
+
523
+ /*-- skip entries with non-NULL tags --*/
524
+ if (argtable[i].tagstr!=NULL)
525
+ continue;
526
+
527
+ /*-- skip leading whitespace --*/
528
+ while (isspace((int)*p))
529
+ p++;
530
+
531
+ /*-- if there are no more arguments on the command line then... --*/
532
+ if (*p=='\0')
533
+ {
534
+ /*-- if a default argument is given then skip arg, else error --*/
535
+ if (argtable[i].defaultstr!=NULL)
536
+ continue;
537
+ else
538
+ {
539
+ if (ErrMsg)
540
+ sprintf(ErrMsg,"%s argument expected", argname);
541
+ if (ErrMark)
542
+ {
543
+ int m = strspn(cmdline,whitespace);
544
+ arg_sprint_marker(m,1,ErrMark);
545
+ }
546
+ return 0;
547
+ }
548
+ }
549
+
550
+ /*-- extract leading argument value from cmdline string --*/
551
+ /*-- if successfull then skip to next arg --*/
552
+ if (arg_extract_value(cmdline,&argtable[i]))
553
+ continue;
554
+
555
+ /*-- we get to here only if argument value extraction failed. --*/
556
+ /*-- if the arg is optional (ie: has a default) then we presume that --*/
557
+ /*-- the value was not intended for this arg, so skip to next arg. --*/
558
+ if (argtable[i].defaultstr!=NULL)
559
+ continue;
560
+
561
+ /*-- we get here only if the command line value is invalid and --*/
562
+ /*-- the expected argument is not optional. the value given must --*/
563
+ /*-- therefore be erroneous so generate an error and return zero --*/
564
+ if (ErrMsg)
565
+ sprintf(ErrMsg,"invalid %s argument", argname);
566
+ if (ErrMark)
567
+ {
568
+ int m = strspn(cmdline,whitespace);
569
+ int n = strcspn(cmdline+m,whitespace);
570
+ arg_sprint_marker(m,n,ErrMark);
571
+ }
572
+ return 0;
573
+ }
574
+
575
+ return 1;
576
+ }
577
+
578
+
579
+
580
+ static
581
+ int arg_checktable(arg_rec *argtable, /* ptr to argument table */
582
+ int n, /* number of entries in argtable[] */
583
+ char *ErrMsg) /* ptr to target error string (may be NULL)*/
584
+ {
585
+ /************************************************************
586
+ Checks the validity of an argument table.
587
+
588
+ DESCRIPTION:
589
+ Each of the 'n' entries in 'argtable[]' are tested for validity;
590
+ any errors will cause a one-line description of the failure to be
591
+ written into *ErrMsg, after which the function will return zero.
592
+ *ErrMsg is assumed to be big enough to hold the result, unless it
593
+ is given as NULL in which case the error messages are suppressed.
594
+
595
+ There is little, or no, reason to call this function directly as
596
+ both arg_scanargv() and arg_scanstr() call it automatically.
597
+
598
+ The function also converts the default value of each argument from
599
+ a string into its appropriate data type and stores the result in
600
+ the location designated for that argument. Any invalid default
601
+ values are reported in the same manner as invalid arguments.
602
+
603
+ RETURN VALUE:
604
+ Returns 1 if the argument table is valid, otherwise returns 0.
605
+
606
+ VALIDITY CONSTRAINTS:
607
+ An argument tag can be NULL, but it cannot be an empty string or
608
+ comprise entirely of whitespace. Whitespace is allowed provided
609
+ there is at least one non-whitespace character in the tag.
610
+
611
+ **************************************************************/
612
+ int i;
613
+
614
+ for (i=0; i<n; i++)
615
+ {
616
+ /*-- check validity of non-NULL tag strings --*/
617
+ if (argtable[i].tagstr!=NULL)
618
+ {
619
+ if (strcmp(argtable[i].tagstr,"")==0 ||
620
+ strcspn(argtable[i].tagstr,whitespace)==0)
621
+ {
622
+ if (ErrMsg)
623
+ sprintf(ErrMsg,"arg[%d], invalid tag \"%s\"",i,argtable[i].tagstr);
624
+ return 0;
625
+ }
626
+ }
627
+ }
628
+
629
+ /*-- check and set defaults --*/
630
+ if (!arg_set_defaults(argtable,n,ErrMsg))
631
+ return 0;
632
+
633
+ return 1;
634
+ }
635
+
636
+
637
+
638
+
639
+
640
+
641
+ /*=============== publicly accessable functions follow ===================*/
642
+ /*================ these are documented in argtable.h ====================*/
643
+
644
+
645
+ void arg_catargs(int argc, char **argv, char *str)
646
+ {
647
+ int i,j;
648
+ str[0]='\0';
649
+ for (i=0; i<argc; i++)
650
+ {
651
+ /*-- if argv[i] has any whitespace then... --*/
652
+ if (strpbrk(argv[i],whitespace))
653
+ {
654
+ strcat(str,"\"");
655
+ for (j=0; j<strlen(argv[i]); j++)
656
+ if (argv[i][j] == '\"')
657
+ strcat(str,"'");
658
+ else
659
+ strncat(str,argv[i]+j,1);
660
+ strcat(str,"\"");
661
+ }
662
+ else
663
+ strcat(str,argv[i]);
664
+
665
+ strcat(str," ");
666
+ }
667
+ }
668
+
669
+
670
+ void arg_dump(FILE* fp, const arg_rec* argtable, int n)
671
+ {
672
+ int i;
673
+
674
+ for (i=0; i<n; i++)
675
+ {
676
+ char tag[ARGSTRLEN], name[ARGSTRLEN], type[ARGSTRLEN], value[ARGSTRLEN],
677
+ descr[ARGSTRLEN];
678
+
679
+ /*-- tag --*/
680
+ if (argtable[i].tagstr)
681
+ sprintf(tag, "\"%s\"", argtable[i].tagstr);
682
+ else
683
+ sprintf(tag,"NULL");
684
+
685
+ /*-- name --*/
686
+ if (argtable[i].argname)
687
+ sprintf(name, "\"%s\"", argtable[i].argname);
688
+ else
689
+ sprintf(name,"NULL");
690
+
691
+ /*-- type and value--*/
692
+ sprintf(value, "NULL");
693
+ switch (argtable[i].argtype)
694
+ {
695
+ case arg_int:
696
+ sprintf(type,"arg_int");
697
+ if (argtable[i].valueptr)
698
+ sprintf(value, "%d", *((int*)argtable[i].valueptr));
699
+ break;
700
+ case arg_dbl:
701
+ sprintf(type,"arg_dbl");
702
+ if (argtable[i].valueptr)
703
+ sprintf(value, "%f", *((double*)argtable[i].valueptr));
704
+ break;
705
+ case arg_str:
706
+ sprintf(type,"arg_str");
707
+ if (argtable[i].valueptr)
708
+ sprintf(value, "\"%s\"", (char*)argtable[i].valueptr);
709
+ break;
710
+ case arg_bool:
711
+ sprintf(type,"arg_bool");
712
+ if (argtable[i].valueptr)
713
+ sprintf(value, "%d", *((int*)argtable[i].valueptr));
714
+ break;
715
+ case arg_lit:
716
+ sprintf(type,"arg_lit");
717
+ if (argtable[i].valueptr)
718
+ sprintf(value, "%d", *((int*)argtable[i].valueptr));
719
+ break;
720
+ };
721
+
722
+ /*-- description --*/
723
+ if (argtable[i].argdescrip)
724
+ sprintf(descr,"\"%s\"",argtable[i].argdescrip);
725
+ else
726
+ sprintf(descr,"NULL");
727
+
728
+ fprintf(fp,"%3d: %-15s %-15s %10s = %-10s %s\n", i, tag, name, type, value, descr);
729
+ }
730
+ }
731
+
732
+
733
+
734
+ const char* arg_glossary(const arg_rec* argtable, /**< pointer to the argument table */
735
+ int n, /**< number of array elements in argtable[] */
736
+ const char* prefix) /**< a string to be prefixed to each line of the output */
737
+ {
738
+ static char str[3000];
739
+ static char NULLprefix[]="";
740
+ const char *fmt = "%s%s\n";
741
+ int i;
742
+
743
+ /*-- handle case of NULL prefix string --*/
744
+ if (prefix==NULL) prefix=NULLprefix;
745
+ else if (prefix[0]=='\001')
746
+ {
747
+ fmt = prefix+1;
748
+ prefix = NULLprefix;
749
+ }
750
+
751
+ /*-- initialise str to "" --*/
752
+ str[0]='\0';
753
+
754
+ for (i=0; i<n; i++)
755
+ if (argtable[i].argdescrip!=NULL)
756
+ {
757
+ char tempstr[ARGSTRLEN]="";
758
+ char tagname[ARGSTRLEN]="";
759
+
760
+ strcpy(tagname, NULLSAFE(argtable[i].tagstr));
761
+ strcat(tagname, NAMESTRING(argtable[i]));
762
+
763
+ strcat(str, prefix);
764
+ sprintf(tempstr, fmt, tagname, argtable[i].argdescrip);
765
+ strcat(str,tempstr);
766
+ }
767
+ return (const char*)str;
768
+ }
769
+
770
+
771
+ /**
772
+ * \brief Builds and returns an argument table record.
773
+ *
774
+ * Returns an arg_rec structure containing the values passed to
775
+ * the function. It is useful for building argument tables dynamically.
776
+ */
777
+ arg_rec arg_record(char *tagstr, /**< argument tag string */
778
+ char *argname, /**< argument name string */
779
+ arg_type argtype, /**< argument data type */
780
+ void *valueptr, /**< pointer to user-supplied storage location */
781
+ char *defaultstr, /**< default argument value, as a string */
782
+ char *argdescrip) /**< argument description string */
783
+ {
784
+ arg_rec result;
785
+ result.tagstr = tagstr;
786
+ result.argname = argname;
787
+ result.argtype = argtype;
788
+ result.valueptr = valueptr;
789
+ result.defaultstr = defaultstr;
790
+ result.argdescrip = argdescrip;
791
+ return result;
792
+ }
793
+
794
+
795
+ int (arg_scanargv)(int argc, /**< number of entries in 'argv'. */
796
+ char **argv, /**< pointer to command line arguments. */
797
+ arg_rec *argtable, /**< pointer to the argument table. */
798
+ int n, /**< number of entries in argtable[]. */
799
+ char* CmdLine, /**< pointer to storage for command line (may be NULL). */
800
+ char* ErrMsg, /**< pointer to storage for error message (may be NULL). */
801
+ char* ErrMark) /**< pointer to storage for error marker (may be NULL). */
802
+ {
803
+ char cmdline[10000], *p;
804
+
805
+ /*-- init CmdLine, ErrMsg and ErrMark if given --*/
806
+ if (CmdLine) *CmdLine='\0';
807
+ if (ErrMsg) *ErrMsg='\0';
808
+ if (ErrMark) *ErrMark='\0';
809
+
810
+ /*-- concat arguments in argv[] into one line in cmdline[] --*/
811
+ arg_catargs(argc,argv,cmdline);
812
+
813
+ /*-- give user a copy of cmdline if requested --*/
814
+ if (CmdLine)
815
+ strcpy(CmdLine,cmdline);
816
+
817
+ errno = 0;
818
+
819
+ /*-- check argtable validity and convert default values --*/
820
+ if (!arg_checktable(argtable,n,ErrMsg))
821
+ return 0;
822
+
823
+ /*-- erase the first word, it is the program name and we dont want it. --*/
824
+ /*-- dont forget enclosing quotes on prog names containing spaces! --*/
825
+ if (strpbrk(argv[0],whitespace))
826
+ memset(cmdline,' ',strlen(argv[0])+2);
827
+ else
828
+ memset(cmdline,' ',strlen(argv[0]));
829
+
830
+ /*-- extract arguments from cmdline[] --*/
831
+ if (!arg_scanstr(cmdline,argtable,n,ErrMsg,ErrMark))
832
+ return 0;
833
+
834
+ /*-- check cmdline[] for extraneous arguments --*/
835
+ p = cmdline;
836
+ while (isspace((int)*p))
837
+ p++;
838
+ if (*p!='\0')
839
+ {
840
+ if (ErrMsg)
841
+ sprintf(ErrMsg,"unexpected argument: %.*s", strcspn(p, " \n\t"),p);
842
+ if (ErrMark)
843
+ {
844
+ int n = strcspn(p,whitespace);
845
+ arg_sprint_marker((int)(p-cmdline),n,ErrMark);
846
+ }
847
+ return 0;
848
+ }
849
+
850
+ return 1;
851
+ }
852
+
853
+
854
+
855
+ int (arg_scanargv_10)(int argc, char **argv, arg_rec *argtable, int n,
856
+ char* CmdLine, char* ErrMsg, char* ErrMark)
857
+ {
858
+ char cmdline[10000], *p;
859
+
860
+ /*-- init CmdLine, ErrMsg and ErrMark if given --*/
861
+ if (CmdLine) *CmdLine='\0';
862
+ if (ErrMsg) *ErrMsg='\0';
863
+ if (ErrMark) *ErrMark='\0';
864
+
865
+ /*-- concat arguments in argv[] into one line in cmdline[] --*/
866
+ arg_catargs(argc,argv,cmdline);
867
+
868
+ /*-- give user a copy of cmdline if requested --*/
869
+ if (CmdLine)
870
+ strcpy(CmdLine,cmdline);
871
+
872
+ /*-- check argtable validity and convert default values --*/
873
+ if (!arg_checktable(argtable,n,ErrMsg))
874
+ return 0;
875
+
876
+ /*-- extract arguments from cmdline[] --*/
877
+ if (!arg_scanstr(cmdline,argtable,n,ErrMsg,ErrMark))
878
+ return 0;
879
+
880
+ /*-- check cmdline[] for extraneous arguments --*/
881
+ p = cmdline;
882
+ while (isspace((int)*p))
883
+ p++;
884
+ if (*p!='\0')
885
+ {
886
+ if (ErrMsg)
887
+ sprintf(ErrMsg,"unexpected argument");
888
+ if (ErrMark)
889
+ {
890
+ int n = strcspn(p,whitespace);
891
+ arg_sprint_marker((int)(p-cmdline),n,ErrMark);
892
+ }
893
+ return 0;
894
+ }
895
+
896
+ return 1;
897
+ }
898
+
899
+
900
+ int arg_scanstr(char* str, /**< pointer to command line string. */
901
+ arg_rec *argtable, /**< pointer to the argument table. */
902
+ int n, /**< number of array elements in argtable[]. */
903
+ char* ErrMsg, /**< pointer to storage for error message (may be NULL). */
904
+ char* ErrMark) /**< pointer to storage for error marker (may be NULL). */
905
+ {
906
+ /*-- init ErrMsg and ErrMark if given --*/
907
+ if (ErrMsg) *ErrMsg='\0';
908
+ if (ErrMark) *ErrMark='\0';
909
+
910
+ /*-- check argtable validity and convert default values --*/
911
+ if (!arg_checktable(argtable,n,ErrMsg))
912
+ return 0;
913
+
914
+ /*-- extract tagged arguments from str --*/
915
+ if (!arg_extract_tagged_args(str,argtable,n,ErrMsg,ErrMark))
916
+ return 0;
917
+
918
+ /*-- extract untagged arguments from str --*/
919
+ if (!arg_extract_untagged_args(str,argtable,n,ErrMsg,ErrMark))
920
+ return 0;
921
+
922
+ return 1;
923
+ }
924
+
925
+
926
+ const char* arg_syntax(const arg_rec* argtable, /**< pointer to the argument table */
927
+ int n) /**< number of array elements in argtable[] */
928
+ {
929
+ static char str[ARGSTRLEN];
930
+ int addspace=0;
931
+ int i;
932
+
933
+ /*-- initialise str to "" --*/
934
+ str[0]='\0';
935
+
936
+ /*-- concatenate consecutive argument descriptions to str. --*/
937
+ /*-- ignore those arguments whose tag and name strings are both "". --*/
938
+ for (i=0; i<n; i++)
939
+ if (strcmp(NULLSAFE(argtable[i].argdescrip),"")!=0)
940
+ {
941
+ const int has_default =
942
+ (argtable[i].defaultstr==NULL ||
943
+ argtable[i].defaultstr==ARGTABLE_NO_DEFAULT_VALUE);
944
+
945
+ /*-- prefix all but first argument with space separator --*/
946
+ if (addspace)
947
+ strcat(str," ");
948
+ else
949
+ addspace=1;
950
+
951
+ /*-- write opening [ for optional arguments--*/
952
+ if (has_default)
953
+ strcat(str,"[");
954
+
955
+ /*-- write tag string --*/
956
+ strcat(str,NULLSAFE(argtable[i].tagstr));
957
+
958
+ /*-- write arg name --*/
959
+ strcat(str,NAMESTRING(argtable[i]));
960
+
961
+ /*-- write closing ] for optional args --*/
962
+ if (has_default)
963
+ strcat(str,"]");
964
+ }
965
+
966
+ return (const char*)str;
967
+ }
968
+
969
+
970
+ const char* arg_typestr[] = { "<int>", "<double>", "<string>", "<bool>", "" };
971
+
972
+