| 1 | // |
|---|
| 2 | // TxWin, Textmode Windowing Library |
|---|
| 3 | // |
|---|
| 4 | // Original code Copyright (c) 1995-2005 Fsys Software and Jan van Wijk |
|---|
| 5 | // |
|---|
| 6 | // ========================================================================== |
|---|
| 7 | // |
|---|
| 8 | // This file contains Original Code and/or Modifications of Original Code as |
|---|
| 9 | // defined in and that are subject to the GNU Lesser General Public License. |
|---|
| 10 | // You may not use this file except in compliance with the License. |
|---|
| 11 | // BY USING THIS FILE YOU AGREE TO ALL TERMS AND CONDITIONS OF THE LICENSE. |
|---|
| 12 | // A copy of the License is provided with the Original Code and Modifications, |
|---|
| 13 | // and is also available at http://www.dfsee.com/txwin/lgpl.htm |
|---|
| 14 | // |
|---|
| 15 | // This library is free software; you can redistribute it and/or modify |
|---|
| 16 | // it under the terms of the GNU Lesser General Public License as published |
|---|
| 17 | // by the Free Software Foundation; either version 2.1 of the License, |
|---|
| 18 | // or (at your option) any later version. |
|---|
| 19 | // |
|---|
| 20 | // This library is distributed in the hope that it will be useful, |
|---|
| 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
|---|
| 23 | // See the GNU Lesser General Public License for more details. |
|---|
| 24 | // |
|---|
| 25 | // You should have received a copy of the GNU Lesser General Public License |
|---|
| 26 | // along with this library; (lgpl.htm) if not, write to the Free Software |
|---|
| 27 | // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 28 | // |
|---|
| 29 | // Questions on TxWin licensing can be directed to: txwin@fsys.nl |
|---|
| 30 | // |
|---|
| 31 | // ========================================================================== |
|---|
| 32 | // |
|---|
| 33 | // TxLib command, argv/argc and number parsing |
|---|
| 34 | // |
|---|
| 35 | // 21-11-2004 JvW Allow explicit decimal prefix 0n and 0t (DFSee 6.16) |
|---|
| 36 | // 08-08-2003 JvW Long-option support and allow '/' switch (DFSee 5.25) |
|---|
| 37 | // 15-12-2001 JvW No string-value for -tValue type syntax (DFSee 5.08) |
|---|
| 38 | // 04-12-2001 JvW Make numeric 0 the default for option -o (DFSee 4.11) |
|---|
| 39 | // 17-11-2001 JvW Added '' as alternative string syntax (DFSee 4.10) |
|---|
| 40 | // 05-11-2001 JvW Added -tValue and -t- type of syntax (DFSee 4.09) |
|---|
| 41 | // 27-08-2001 JvW Added argv/argc as input alternative (DFSee 4.03) |
|---|
| 42 | // 13-08-2001 JvW First released version (DFSee 4.02) |
|---|
| 43 | |
|---|
| 44 | #include <txlib.h> // TxLib interface |
|---|
| 45 | #include <txwpriv.h> // TXW private interfaces |
|---|
| 46 | #include <txtpriv.h> // TXT private interfaces |
|---|
| 47 | |
|---|
| 48 | #define TXA_SIGNATURE 0xFACEBEEF // valid magic signature value |
|---|
| 49 | |
|---|
| 50 | TXA_ELEMENT *txacur = NULL; // current, top of stack |
|---|
| 51 | TXA_ELEMENT *txa1st = NULL; // first, bottom of stack |
|---|
| 52 | |
|---|
| 53 | typedef char TXA_LONGOPT[ TXA_O_LEN +1]; |
|---|
| 54 | |
|---|
| 55 | static TXA_LONGOPT txalongopt[TXA_LSIZE] = |
|---|
| 56 | { |
|---|
| 57 | "query", // predefined long names |
|---|
| 58 | "menu", |
|---|
| 59 | "debug", |
|---|
| 60 | "test", |
|---|
| 61 | "trace", |
|---|
| 62 | "auto", |
|---|
| 63 | "entry", |
|---|
| 64 | "color", |
|---|
| 65 | "scheme", |
|---|
| 66 | "lines", |
|---|
| 67 | "ini", |
|---|
| 68 | "config", |
|---|
| 69 | "style", |
|---|
| 70 | "keyb", |
|---|
| 71 | "mouse", |
|---|
| 72 | "simulate", |
|---|
| 73 | "list", |
|---|
| 74 | "screen", |
|---|
| 75 | "label", |
|---|
| 76 | "test1", |
|---|
| 77 | "test2", |
|---|
| 78 | "test3", |
|---|
| 79 | "test4", |
|---|
| 80 | "test5", |
|---|
| 81 | "", |
|---|
| 82 | "", |
|---|
| 83 | "", |
|---|
| 84 | "", |
|---|
| 85 | "", |
|---|
| 86 | "" |
|---|
| 87 | }; |
|---|
| 88 | |
|---|
| 89 | |
|---|
| 90 | |
|---|
| 91 | /*****************************************************************************/ |
|---|
| 92 | // Set or query value for a specific LONGNAME value (the LONG option name) |
|---|
| 93 | /*****************************************************************************/ |
|---|
| 94 | char *TxaOptionLongName // RET resulting option name |
|---|
| 95 | ( |
|---|
| 96 | char opt, // IN TXA_O_ option value |
|---|
| 97 | char *name // IN long name for option |
|---|
| 98 | ) // or NULL to query |
|---|
| 99 | { |
|---|
| 100 | char *rc = NULL; // function return |
|---|
| 101 | int lni; |
|---|
| 102 | |
|---|
| 103 | ENTER(); |
|---|
| 104 | |
|---|
| 105 | if ((opt >= TXA_LBASE) && ((lni = (opt - TXA_LBASE)) < TXA_LSIZE)) |
|---|
| 106 | { |
|---|
| 107 | if (name != NULL) |
|---|
| 108 | { |
|---|
| 109 | TxCopy( txalongopt[lni], name, TXA_O_LEN +1); |
|---|
| 110 | } |
|---|
| 111 | rc = &(txalongopt[lni][0]); |
|---|
| 112 | TRACES(("Name for APP%lu option set to '%s'\n", opt - TXA_O_APP0, rc)); |
|---|
| 113 | } |
|---|
| 114 | RETURN (rc); |
|---|
| 115 | } // end 'TxaOptionLongName' |
|---|
| 116 | /*---------------------------------------------------------------------------*/ |
|---|
| 117 | |
|---|
| 118 | |
|---|
| 119 | /*****************************************************************************/ |
|---|
| 120 | // Create new level of command options for a set of argc/argv variables |
|---|
| 121 | /*****************************************************************************/ |
|---|
| 122 | ULONG TxaParseArgcArgv // RET result |
|---|
| 123 | ( |
|---|
| 124 | int argc, // IN argument count |
|---|
| 125 | char *argv[], // IN array of arguments |
|---|
| 126 | char *exename, // IN alternative argv[0] |
|---|
| 127 | BOOL freeform, // IN free format options |
|---|
| 128 | TXHANDLE *txh // OUT TXA handle (optional) |
|---|
| 129 | ) |
|---|
| 130 | { |
|---|
| 131 | ULONG rc; |
|---|
| 132 | TXA_ELEMENT *txa; |
|---|
| 133 | char *item; // parsed item |
|---|
| 134 | int len; // length of item |
|---|
| 135 | int i; |
|---|
| 136 | |
|---|
| 137 | ENTER(); |
|---|
| 138 | |
|---|
| 139 | if ((rc = TxaNewParseElement( &txa)) == NO_ERROR) |
|---|
| 140 | { |
|---|
| 141 | for (i = 0; (i < argc) && (rc == NO_ERROR); i++) |
|---|
| 142 | { |
|---|
| 143 | if ((i == 0) && (exename != NULL)) |
|---|
| 144 | { |
|---|
| 145 | item = exename; // preserve alternative argv[0] |
|---|
| 146 | } |
|---|
| 147 | else |
|---|
| 148 | { |
|---|
| 149 | item = argv[i]; |
|---|
| 150 | } |
|---|
| 151 | len = strlen( item); |
|---|
| 152 | |
|---|
| 153 | rc = txaReadAndStoreItem( item, len, freeform, TRUE, txa); |
|---|
| 154 | } |
|---|
| 155 | } |
|---|
| 156 | if (txh != NULL) |
|---|
| 157 | { |
|---|
| 158 | *txh = (TXHANDLE) txa; |
|---|
| 159 | } |
|---|
| 160 | RETURN( rc); |
|---|
| 161 | } // end 'TxaParseArgcArgv' |
|---|
| 162 | /*---------------------------------------------------------------------------*/ |
|---|
| 163 | |
|---|
| 164 | |
|---|
| 165 | /*****************************************************************************/ |
|---|
| 166 | // Parse a decimal or hex number value from a string |
|---|
| 167 | /*****************************************************************************/ |
|---|
| 168 | ULONG TxaParseNumber // RET number value |
|---|
| 169 | ( |
|---|
| 170 | char *value, // IN value string with nr |
|---|
| 171 | ULONG rclass, // IN HEX/DEC radix class |
|---|
| 172 | BYTE *unit // OUT optional unit char, if |
|---|
| 173 | ) // not needed use NULL |
|---|
| 174 | { |
|---|
| 175 | ULONG rc = 0; // function return |
|---|
| 176 | BOOL prefix = TRUE; // number parsed using prefix |
|---|
| 177 | int distance = 0; // distance to specific char |
|---|
| 178 | int radixclass = rclass; // class to be used for default |
|---|
| 179 | |
|---|
| 180 | TRLEVX(700,( "value: '%s' rclass: 0x%lX\n", value, rclass)); |
|---|
| 181 | |
|---|
| 182 | if (unit != NULL) // read unit char suffix |
|---|
| 183 | { |
|---|
| 184 | if ((( distance = (int) strcspn( value, ", ")) > 0) && |
|---|
| 185 | ( value[ distance] == ',')) // unit specifier present |
|---|
| 186 | { |
|---|
| 187 | *unit = value[ distance +1]; // unit character |
|---|
| 188 | if (strchr( "sS", *unit) != NULL) // 's' unit |
|---|
| 189 | { |
|---|
| 190 | radixclass = TX_RADIX_UN_S_CLASS; // use sector-unit class |
|---|
| 191 | } |
|---|
| 192 | else |
|---|
| 193 | { |
|---|
| 194 | radixclass = TX_RADIX_UNIT_CLASS; // use 'other' unit class |
|---|
| 195 | } |
|---|
| 196 | } |
|---|
| 197 | else |
|---|
| 198 | { |
|---|
| 199 | *unit = TXA_DFUNIT; // assume default unit |
|---|
| 200 | } |
|---|
| 201 | TRLEVX(700,( "Unit for value: '%s' is: '%c'\n", value, *unit)); |
|---|
| 202 | } |
|---|
| 203 | if (*value == '0') // possible hex/oct/dec prefix |
|---|
| 204 | { |
|---|
| 205 | switch (tolower(*(value +1))) |
|---|
| 206 | { |
|---|
| 207 | case 'x': sscanf( value +2, "%lx", &rc); break; // hexadecimal number |
|---|
| 208 | case 'o': sscanf( value +2, "%lo", &rc); break; // octal number base |
|---|
| 209 | case 'n': |
|---|
| 210 | case 't': sscanf( value +2, "%lu", &rc); break; // decimal number base |
|---|
| 211 | default: prefix = FALSE; break; // to be determined |
|---|
| 212 | } |
|---|
| 213 | } |
|---|
| 214 | else |
|---|
| 215 | { |
|---|
| 216 | prefix = FALSE; |
|---|
| 217 | } |
|---|
| 218 | if (prefix == FALSE) // no prefix, test HEX or DEC |
|---|
| 219 | { |
|---|
| 220 | TRLEVX(700,( "value has no prefix ...\n")); |
|---|
| 221 | if ( txIsValidHex( value) && // valid HEX upto separator |
|---|
| 222 | !txIsValidDec( value) ) // and has non-decimal digits |
|---|
| 223 | { |
|---|
| 224 | TRLEVX(700,( "auto-interpret as HEX!\n")); |
|---|
| 225 | sscanf( value, "%lx", &rc); // interpret as HEX |
|---|
| 226 | } |
|---|
| 227 | else // could be both ... |
|---|
| 228 | { |
|---|
| 229 | if (txwa->radixclass & radixclass) // class set to HEX default |
|---|
| 230 | { |
|---|
| 231 | TRLEVX(700,( "Radix-selection HEX!\n")); |
|---|
| 232 | sscanf( value, "%lx", &rc); // interpret as HEX |
|---|
| 233 | } |
|---|
| 234 | else |
|---|
| 235 | { |
|---|
| 236 | TRLEVX(700,( "Radix-selection DEC!\n")); |
|---|
| 237 | sscanf( value, "%lu", &rc); // interpret as DECimal |
|---|
| 238 | } |
|---|
| 239 | } |
|---|
| 240 | } |
|---|
| 241 | else |
|---|
| 242 | { |
|---|
| 243 | TRLEVX(700,( "Selection by prefix '%2.2s'\n", value)); |
|---|
| 244 | } |
|---|
| 245 | return (rc); |
|---|
| 246 | } // end 'TxaParseNumber' |
|---|
| 247 | /*---------------------------------------------------------------------------*/ |
|---|
| 248 | |
|---|
| 249 | |
|---|
| 250 | /*****************************************************************************/ |
|---|
| 251 | // Read one item (option or argument) and store it in the txa element |
|---|
| 252 | /*****************************************************************************/ |
|---|
| 253 | ULONG txaReadAndStoreItem // RET result |
|---|
| 254 | ( |
|---|
| 255 | char *item, // IN item string |
|---|
| 256 | int len, // IN length of item |
|---|
| 257 | BOOL freeform, // IN free format options |
|---|
| 258 | BOOL passthrough, // IN keep parameter quotes |
|---|
| 259 | TXA_ELEMENT *txa // INOUT TXA element |
|---|
| 260 | ) |
|---|
| 261 | { |
|---|
| 262 | ULONG rc = NO_ERROR; |
|---|
| 263 | int arguments = txa->argc; // current number of arguments |
|---|
| 264 | |
|---|
| 265 | ENTER(); |
|---|
| 266 | |
|---|
| 267 | TRACES(( "Freeform: %s Passthrough: %s Args: %d Len:%3.3u, Item: '%*.*s'\n", |
|---|
| 268 | (freeform) ? "YES" : "NO ", (passthrough) ? "YES" : "NO ", |
|---|
| 269 | arguments, len, len, len, item)); |
|---|
| 270 | if ((((txa == txa1st) && // switch on 1st level '/' only |
|---|
| 271 | (*(item) == '/')) || |
|---|
| 272 | (*(item) == '-' )) && // switch or option using '-' |
|---|
| 273 | (*(item +1) != ' ' ) && // allowed at this position ? |
|---|
| 274 | (*(item +1) != '\0' ) && |
|---|
| 275 | (arguments > 0 ) && // never BEFORE 1st word (cmd) |
|---|
| 276 | ((arguments == 1) || freeform)) // possibly after params too |
|---|
| 277 | { |
|---|
| 278 | int index; // index for the option char |
|---|
| 279 | char *value; // ptr to value part of item |
|---|
| 280 | int distance; // distance to specific char |
|---|
| 281 | TXA_LONGOPT lname = {0}; // empty longname to start with |
|---|
| 282 | |
|---|
| 283 | index = *(item +1); |
|---|
| 284 | if ((index >= TXA_BASE) && (index < (TXA_BASE + TXA_SIZE))) |
|---|
| 285 | { |
|---|
| 286 | index -= TXA_BASE; // make it 0 based |
|---|
| 287 | TRACES(( "Direct option index:%3hu\n", index)); |
|---|
| 288 | |
|---|
| 289 | switch (*(item +2)) |
|---|
| 290 | { |
|---|
| 291 | case '"': case '\'': // quoted string |
|---|
| 292 | case '+': case '-': // boolean yes/no |
|---|
| 293 | case '0': case '1': case '2': case '3': case '4': |
|---|
| 294 | case '5': case '6': case '7': case '8': case '9': |
|---|
| 295 | value = item +2; |
|---|
| 296 | break; |
|---|
| 297 | |
|---|
| 298 | default: |
|---|
| 299 | if ((distance = (int) strcspn( item, ": ")) < len) |
|---|
| 300 | { |
|---|
| 301 | value = item + distance +1; // skip the colon ... |
|---|
| 302 | } |
|---|
| 303 | else |
|---|
| 304 | { |
|---|
| 305 | if ((len > 2) && // non-empty option name |
|---|
| 306 | (item[len -1] == '-')) // ending in a '-' |
|---|
| 307 | { |
|---|
| 308 | distance = len -1; // length of the name |
|---|
| 309 | value = item + distance; // '-' is the value |
|---|
| 310 | } |
|---|
| 311 | else |
|---|
| 312 | { |
|---|
| 313 | value = item + len; // no explicit value given |
|---|
| 314 | } |
|---|
| 315 | } |
|---|
| 316 | |
|---|
| 317 | if (distance > 2) // non-trivial longname |
|---|
| 318 | { |
|---|
| 319 | int lni; |
|---|
| 320 | |
|---|
| 321 | strncpy( lname, item +1, distance -1); |
|---|
| 322 | lname[distance -1] = 0; // terminate the name |
|---|
| 323 | TRACES(( "longname '%s' for: '%s'\n", lname, item)); |
|---|
| 324 | |
|---|
| 325 | if (stricmp( "help", lname) == 0) // predefined, map to '?' |
|---|
| 326 | { |
|---|
| 327 | index = '?' - TXA_BASE; |
|---|
| 328 | } |
|---|
| 329 | else |
|---|
| 330 | { |
|---|
| 331 | for (lni = 0; lni < TXA_LSIZE; lni++) |
|---|
| 332 | { |
|---|
| 333 | if (strlen(txalongopt[lni]) != 0) |
|---|
| 334 | { |
|---|
| 335 | if (stricmp( txalongopt[lni], lname) == 0) |
|---|
| 336 | { |
|---|
| 337 | index = lni + TXA_LBASE - TXA_BASE; |
|---|
| 338 | |
|---|
| 339 | TRACES(("Matched defined longname '%s', index: %hu\n", |
|---|
| 340 | txalongopt[lni], index)); |
|---|
| 341 | } |
|---|
| 342 | } |
|---|
| 343 | } |
|---|
| 344 | } |
|---|
| 345 | } |
|---|
| 346 | break; |
|---|
| 347 | } |
|---|
| 348 | TxFreeMem( txa->opt[index].name); // free existing name, if any |
|---|
| 349 | if (strlen( lname) != 0) // new longname available ? |
|---|
| 350 | { |
|---|
| 351 | if ((txa->opt[ index].name = TxAlloc(1, strlen(lname) +1)) != NULL) |
|---|
| 352 | { |
|---|
| 353 | strcpy( txa->opt[ index].name, lname); |
|---|
| 354 | } |
|---|
| 355 | } |
|---|
| 356 | |
|---|
| 357 | if (txa->opt[ index].type == TXA_STRING) // already has a string! |
|---|
| 358 | { |
|---|
| 359 | TRACES(("Free existing string value: '%s'\n", |
|---|
| 360 | txa->opt[ index].value.string)); |
|---|
| 361 | TxFreeMem( txa->opt[ index].value.string); |
|---|
| 362 | } |
|---|
| 363 | txa->opt[ index].type = TXA_NUMBER; |
|---|
| 364 | txa->opt[ index].unit = TXA_DFUNIT; // default unit |
|---|
| 365 | switch (*value) |
|---|
| 366 | { |
|---|
| 367 | case TXk_SPACE: case '\0': |
|---|
| 368 | txa->opt[ index].type = TXA_NO_VAL; |
|---|
| 369 | txa->opt[ index].value.number = 0; |
|---|
| 370 | TRACES(("NoValueOpt (%3hu='%c')\n", index + TXA_BASE, index + TXA_BASE)); |
|---|
| 371 | break; |
|---|
| 372 | |
|---|
| 373 | case '+': txa->opt[ index].value.number = 1; break; |
|---|
| 374 | case '-': txa->opt[ index].value.number = 0; break; |
|---|
| 375 | case '0': case '1': case '2': case '3': case '4': |
|---|
| 376 | case '5': case '6': case '7': case '8': case '9': |
|---|
| 377 | txa->opt[ index].value.number = |
|---|
| 378 | TxaParseNumber( value, TX_RADIX_STD_CLASS, |
|---|
| 379 | &(txa->opt[ index].unit)); |
|---|
| 380 | |
|---|
| 381 | TRACES(("NumericOpt (%3hu='%c'), value: %lu\n", |
|---|
| 382 | index + TXA_BASE, index + TXA_BASE, |
|---|
| 383 | txa->opt[ index].value.number)); |
|---|
| 384 | break; |
|---|
| 385 | |
|---|
| 386 | default: |
|---|
| 387 | txa->opt[ index].type = TXA_STRING; |
|---|
| 388 | if ((txa->opt[ index].value.string = TxAlloc(1, len +1)) != NULL) |
|---|
| 389 | { |
|---|
| 390 | if (passthrough) // straight copy |
|---|
| 391 | { |
|---|
| 392 | strcpy( txa->opt[ index].value.string, value); |
|---|
| 393 | } |
|---|
| 394 | else // space delimited stuff! |
|---|
| 395 | { |
|---|
| 396 | txaCopyItem( txa->opt[ index].value.string, value, len); |
|---|
| 397 | } |
|---|
| 398 | |
|---|
| 399 | TRACES(("String Opt (%3hu='%c') at %8.8lx, value: '%s'\n", |
|---|
| 400 | index + TXA_BASE, index + TXA_BASE, |
|---|
| 401 | txa->opt[ index].value.string, |
|---|
| 402 | txa->opt[ index].value.string)); |
|---|
| 403 | } |
|---|
| 404 | else |
|---|
| 405 | { |
|---|
| 406 | rc = TX_ALLOC_ERROR; |
|---|
| 407 | } |
|---|
| 408 | break; |
|---|
| 409 | } |
|---|
| 410 | txa->optc++; // count the option |
|---|
| 411 | } |
|---|
| 412 | else // option char out of range |
|---|
| 413 | { |
|---|
| 414 | rc = TX_BAD_OPTION_CHAR; |
|---|
| 415 | } |
|---|
| 416 | } |
|---|
| 417 | else // argv 0 .. n |
|---|
| 418 | { |
|---|
| 419 | if (arguments < TXA_ARGC) // room for another ? |
|---|
| 420 | { |
|---|
| 421 | if ((txa->argv[ arguments] = TxAlloc(1, len +1)) != NULL) |
|---|
| 422 | { |
|---|
| 423 | if (passthrough) // straight copy |
|---|
| 424 | { |
|---|
| 425 | strcpy( txa->argv[ arguments], item); |
|---|
| 426 | } |
|---|
| 427 | else // space delimited stuff! |
|---|
| 428 | { |
|---|
| 429 | txaCopyItem( txa->argv[ arguments], item, len); |
|---|
| 430 | } |
|---|
| 431 | TRACES(("Stored argv[%d] at %8.8lx, value: '%s'\n", arguments, |
|---|
| 432 | txa->argv[ arguments], txa->argv[ arguments])); |
|---|
| 433 | arguments++; |
|---|
| 434 | } |
|---|
| 435 | else |
|---|
| 436 | { |
|---|
| 437 | rc = TX_ALLOC_ERROR; |
|---|
| 438 | } |
|---|
| 439 | } |
|---|
| 440 | else |
|---|
| 441 | { |
|---|
| 442 | rc = TX_TOO_MANY_ARGS; |
|---|
| 443 | } |
|---|
| 444 | } |
|---|
| 445 | txa->argc = arguments; |
|---|
| 446 | RETURN( rc); |
|---|
| 447 | } // end 'txaReadAndStoreItem' |
|---|
| 448 | /*---------------------------------------------------------------------------*/ |
|---|
| 449 | |
|---|
| 450 | |
|---|
| 451 | /*****************************************************************************/ |
|---|
| 452 | // Create new level of command options for a set of argc/argv variables |
|---|
| 453 | /*****************************************************************************/ |
|---|
| 454 | ULONG TxaNewParseElement // RET result |
|---|
| 455 | ( |
|---|
| 456 | TXA_ELEMENT **element // OUT TXA element |
|---|
| 457 | ) |
|---|
| 458 | { |
|---|
| 459 | ULONG rc = NO_ERROR; |
|---|
| 460 | TXA_ELEMENT *txa = NULL; |
|---|
| 461 | |
|---|
| 462 | if ((txa = TxAlloc(1, sizeof(TXA_ELEMENT))) != NULL) |
|---|
| 463 | { |
|---|
| 464 | txa->signature = TXA_SIGNATURE; |
|---|
| 465 | txa->prev = txacur; |
|---|
| 466 | |
|---|
| 467 | if (txacur == NULL) // first one ? |
|---|
| 468 | { |
|---|
| 469 | txa1st = txa; |
|---|
| 470 | } |
|---|
| 471 | txacur = txa; |
|---|
| 472 | } |
|---|
| 473 | else |
|---|
| 474 | { |
|---|
| 475 | rc = TX_ALLOC_ERROR; |
|---|
| 476 | } |
|---|
| 477 | *element = txa; |
|---|
| 478 | return( rc); |
|---|
| 479 | } // end 'TxaNewParseElement' |
|---|
| 480 | /*---------------------------------------------------------------------------*/ |
|---|
| 481 | |
|---|
| 482 | |
|---|
| 483 | /*****************************************************************************/ |
|---|
| 484 | // Terminate use of current or all instances of the TXA abstract-data-type |
|---|
| 485 | /*****************************************************************************/ |
|---|
| 486 | BOOL TxaDropParsedCommand // RET more instances left |
|---|
| 487 | ( |
|---|
| 488 | BOOL whole_stack // IN drop all, terminate |
|---|
| 489 | ) |
|---|
| 490 | { |
|---|
| 491 | TXA_ELEMENT *txa; |
|---|
| 492 | int i; |
|---|
| 493 | |
|---|
| 494 | ENTER(); |
|---|
| 495 | |
|---|
| 496 | do |
|---|
| 497 | { |
|---|
| 498 | if ((txa = txacur) != NULL) |
|---|
| 499 | { |
|---|
| 500 | for (i = 0; i < TXA_SIZE; i++) // free allocated options |
|---|
| 501 | { |
|---|
| 502 | if (txa->opt[i].type == TXA_STRING) |
|---|
| 503 | { |
|---|
| 504 | TxFreeMem( txa->opt[i].value.string); |
|---|
| 505 | } |
|---|
| 506 | TxFreeMem( txa->opt[i].name); |
|---|
| 507 | } |
|---|
| 508 | for (i = 0; i < txa->argc; i++) // free argv storage |
|---|
| 509 | { |
|---|
| 510 | if (txa->argv[i] != NULL) |
|---|
| 511 | { |
|---|
| 512 | TxFreeMem( txa->argv[i]); |
|---|
| 513 | } |
|---|
| 514 | } |
|---|
| 515 | txacur = txa->prev; |
|---|
| 516 | if (txacur == NULL) // empty again ? |
|---|
| 517 | { |
|---|
| 518 | txa1st = NULL; |
|---|
| 519 | } |
|---|
| 520 | TxFreeMem( txa); |
|---|
| 521 | } |
|---|
| 522 | } while (txacur && whole_stack); |
|---|
| 523 | |
|---|
| 524 | BRETURN((txacur != NULL)); |
|---|
| 525 | } // end 'TxaDropParsedCommand' |
|---|
| 526 | /*---------------------------------------------------------------------------*/ |
|---|
| 527 | |
|---|
| 528 | |
|---|
| 529 | /*****************************************************************************/ |
|---|
| 530 | // Get reference to specified option data, or NULL if option not set |
|---|
| 531 | /*****************************************************************************/ |
|---|
| 532 | TXA_OPTION *TxaGetOption // RET option ptr or NULL |
|---|
| 533 | ( |
|---|
| 534 | TXHANDLE txh, // IN TXA handle |
|---|
| 535 | char opt // IN option character |
|---|
| 536 | ) |
|---|
| 537 | { |
|---|
| 538 | TXA_OPTION *rc = NULL; |
|---|
| 539 | TXA_ELEMENT *txa; // specified TXA instance |
|---|
| 540 | int i; |
|---|
| 541 | TXA_OPTION *o; |
|---|
| 542 | |
|---|
| 543 | if ((txa = txaHandle2Element( txh)) != NULL) |
|---|
| 544 | { |
|---|
| 545 | if ((opt >= TXA_BASE) && (opt < (TXA_BASE + TXA_SIZE))) |
|---|
| 546 | { |
|---|
| 547 | i = opt - TXA_BASE; // make it 0 based |
|---|
| 548 | o = &txa->opt[ i]; |
|---|
| 549 | if (o->type != TXA_NONE) |
|---|
| 550 | { |
|---|
| 551 | rc = o; |
|---|
| 552 | } |
|---|
| 553 | TRARGS(("TXH (%s): %lx option: %3hu = '%c' value: %lu '%s'\n", |
|---|
| 554 | (txh == TXA_1ST) ? "EXE switch" : "CMD option", txh, opt, opt, |
|---|
| 555 | (o->type == TXA_STRING) ? strlen(o->value.string) : o->value.number, |
|---|
| 556 | (o->type == TXA_NONE ) ? "---NONE---" : |
|---|
| 557 | (o->type != TXA_STRING) ? "--NUMBER--" : o->value.string )); |
|---|
| 558 | } |
|---|
| 559 | } |
|---|
| 560 | return( rc); |
|---|
| 561 | } // end 'TxaGetOption' |
|---|
| 562 | /*---------------------------------------------------------------------------*/ |
|---|
| 563 | |
|---|
| 564 | |
|---|
| 565 | /*****************************************************************************/ |
|---|
| 566 | // Get simple YES/NO status for specified option. Not set is "NO" |
|---|
| 567 | /*****************************************************************************/ |
|---|
| 568 | BOOL TxaOptionYes // RET option set to YES |
|---|
| 569 | ( |
|---|
| 570 | TXHANDLE txh, // IN TXA handle |
|---|
| 571 | char opt // IN option character |
|---|
| 572 | ) |
|---|
| 573 | { |
|---|
| 574 | BOOL rc = FALSE; |
|---|
| 575 | TXA_OPTION *o; |
|---|
| 576 | |
|---|
| 577 | if ((o = TxaGetOption( txh, opt)) != NULL) |
|---|
| 578 | { |
|---|
| 579 | switch (o->type) |
|---|
| 580 | { |
|---|
| 581 | case TXA_NUMBER: |
|---|
| 582 | if (o->value.number != 0) |
|---|
| 583 | { |
|---|
| 584 | rc = TRUE; |
|---|
| 585 | } |
|---|
| 586 | break; |
|---|
| 587 | |
|---|
| 588 | case TXA_STRING: |
|---|
| 589 | if ((stricmp( o->value.string, "NO") != 0) && |
|---|
| 590 | (stricmp( o->value.string, "N") != 0) && |
|---|
| 591 | (stricmp( o->value.string, "0") != 0) && |
|---|
| 592 | (stricmp( o->value.string, "OFF") != 0) && |
|---|
| 593 | (stricmp( o->value.string, "FALSE") != 0) ) |
|---|
| 594 | { |
|---|
| 595 | rc = TRUE; |
|---|
| 596 | } |
|---|
| 597 | break; |
|---|
| 598 | |
|---|
| 599 | default: // no value, but set |
|---|
| 600 | rc = TRUE; |
|---|
| 601 | break; |
|---|
| 602 | } |
|---|
| 603 | } |
|---|
| 604 | return( rc); |
|---|
| 605 | } // end 'TxaOptionYes' |
|---|
| 606 | /*---------------------------------------------------------------------------*/ |
|---|
| 607 | |
|---|
| 608 | |
|---|
| 609 | /*****************************************************************************/ |
|---|
| 610 | // Get string value for specified option, use default if no string (and warn!) |
|---|
| 611 | /*****************************************************************************/ |
|---|
| 612 | char *TxaOptionStr // RET option String value |
|---|
| 613 | ( |
|---|
| 614 | TXHANDLE txh, // IN TXA handle |
|---|
| 615 | char opt, // IN option character |
|---|
| 616 | char *error, // IN error text or NULL |
|---|
| 617 | char *deflt // IN default value |
|---|
| 618 | ) |
|---|
| 619 | { |
|---|
| 620 | char *rc = deflt; |
|---|
| 621 | TXA_OPTION *o; |
|---|
| 622 | |
|---|
| 623 | if ((o = TxaGetOption( txh, opt)) != NULL) |
|---|
| 624 | { |
|---|
| 625 | if (o->type == TXA_STRING) |
|---|
| 626 | { |
|---|
| 627 | rc = o->value.string; |
|---|
| 628 | } |
|---|
| 629 | else // other option type |
|---|
| 630 | { |
|---|
| 631 | if (error != NULL) // give error/warning |
|---|
| 632 | { |
|---|
| 633 | TxPrint( "\n%s %s: %s'-%c'%s has no STRING value, using " |
|---|
| 634 | "default: '%s'\n", |
|---|
| 635 | (txh != TXA_1ST) ? "Option" : "Switch", |
|---|
| 636 | error, CBC, opt, CNN, deflt); |
|---|
| 637 | } |
|---|
| 638 | } |
|---|
| 639 | } |
|---|
| 640 | return( rc); |
|---|
| 641 | } // end 'TxaOptionStr' |
|---|
| 642 | /*---------------------------------------------------------------------------*/ |
|---|
| 643 | |
|---|
| 644 | |
|---|
| 645 | /*****************************************************************************/ |
|---|
| 646 | // Get number value for specified option, use default if no number (and warn!) |
|---|
| 647 | /*****************************************************************************/ |
|---|
| 648 | ULONG TxaOptionNum // RET option Number value |
|---|
| 649 | ( |
|---|
| 650 | TXHANDLE txh, // IN TXA handle |
|---|
| 651 | char opt, // IN option character |
|---|
| 652 | char *error, // IN error text or NULL |
|---|
| 653 | ULONG deflt // IN default value |
|---|
| 654 | ) |
|---|
| 655 | { |
|---|
| 656 | ULONG rc = deflt; |
|---|
| 657 | TXA_OPTION *o; |
|---|
| 658 | |
|---|
| 659 | if ((o = TxaGetOption( txh, opt)) != NULL) |
|---|
| 660 | { |
|---|
| 661 | if (o->type == TXA_NUMBER) |
|---|
| 662 | { |
|---|
| 663 | rc = o->value.number; |
|---|
| 664 | } |
|---|
| 665 | else // other option type |
|---|
| 666 | { |
|---|
| 667 | if (error != NULL) // give error/warning |
|---|
| 668 | { |
|---|
| 669 | TxPrint( "\n%s %s: %s'-%c'%s has no NUMBER value, using " |
|---|
| 670 | "default: 0x%8.8lx = %lu\n", |
|---|
| 671 | (txh != TXA_1ST) ? "Option" : "Switch", |
|---|
| 672 | error, CBC, opt, CNN, deflt, deflt); |
|---|
| 673 | } |
|---|
| 674 | } |
|---|
| 675 | } |
|---|
| 676 | return( rc); |
|---|
| 677 | } // end 'TxaOptionNum' |
|---|
| 678 | /*---------------------------------------------------------------------------*/ |
|---|
| 679 | |
|---|
| 680 | |
|---|
| 681 | /*****************************************************************************/ |
|---|
| 682 | // Get option value num/string, with bytes/kilo/mega/giga modifier and default |
|---|
| 683 | /*****************************************************************************/ |
|---|
| 684 | ULONG TxaOptionBkmg // RET number value in bytes |
|---|
| 685 | ( |
|---|
| 686 | TXHANDLE txh, // IN TXA handle |
|---|
| 687 | char option, // IN option character |
|---|
| 688 | ULONG def, // IN default value |
|---|
| 689 | BYTE mod // IN b,kb,mb,gb modifier |
|---|
| 690 | ) |
|---|
| 691 | { |
|---|
| 692 | ULONG rc = 0; // function return |
|---|
| 693 | BYTE unit = TXA_DFUNIT; |
|---|
| 694 | TXA_OPTION *opt; // option pointer |
|---|
| 695 | |
|---|
| 696 | ENTER(); |
|---|
| 697 | TRACES(("Option: '%c' default: %8.8lx mod:%2.2hx = '%c'\n", |
|---|
| 698 | option, def, mod, mod)); |
|---|
| 699 | |
|---|
| 700 | if ((opt = TxaOptValue( option)) != NULL) // get the option details |
|---|
| 701 | { |
|---|
| 702 | switch (opt->type) |
|---|
| 703 | { |
|---|
| 704 | case TXA_STRING: |
|---|
| 705 | rc = TxaParseNumber( opt->value.string, TX_RADIX_STD_CLASS, &unit); |
|---|
| 706 | case TXA_NO_VAL: |
|---|
| 707 | rc = def; |
|---|
| 708 | break; |
|---|
| 709 | |
|---|
| 710 | default: // convert, default is MiB! |
|---|
| 711 | rc = opt->value.number; |
|---|
| 712 | unit = opt->unit; |
|---|
| 713 | break; |
|---|
| 714 | } |
|---|
| 715 | } |
|---|
| 716 | if (unit == TXA_DFUNIT) |
|---|
| 717 | { |
|---|
| 718 | unit = mod; |
|---|
| 719 | } |
|---|
| 720 | switch (tolower(unit)) |
|---|
| 721 | { |
|---|
| 722 | case 'g': |
|---|
| 723 | if (rc >= 4) |
|---|
| 724 | { |
|---|
| 725 | rc = 0xffffffff; // limit at 4GiB -1 |
|---|
| 726 | break; |
|---|
| 727 | } |
|---|
| 728 | else |
|---|
| 729 | { |
|---|
| 730 | rc *= 1024; // Giga |
|---|
| 731 | |
|---|