[1] | 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",
|
---|
[11] | 75 | "label",
|
---|
[1] | 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 | /*****************************************************************************/
|
---|
[13] | 251 | // Get option value num/string, with bytes/kilo/mega/giga modifier and default
|
---|
| 252 | /*****************************************************************************/
|
---|
| 253 | ULONG TxaOptBkmg // RET number value in bytes
|
---|
| 254 | (
|
---|
| 255 | TXHANDLE txh, // IN TXA handle
|
---|
| 256 | char option, // IN option character
|
---|
| 257 | ULONG def, // IN default value
|
---|
| 258 | BYTE mod // IN b,kb,mb,gb modifier
|
---|
| 259 | )
|
---|
| 260 | {
|
---|
| 261 | ULONG rc = 0; // function return
|
---|
| 262 | BYTE unit = TXA_DFUNIT;
|
---|
| 263 | TXA_OPTION *opt; // option pointer
|
---|
| 264 |
|
---|
| 265 | ENTER();
|
---|
| 266 | TRACES(("Option: '%c' default: %8.8lx mod:%2.2hx = '%c'\n",
|
---|
| 267 | option, def, mod, mod));
|
---|
| 268 |
|
---|
| 269 | if ((opt = TxaOptValue( option)) != NULL) // get the option details
|
---|
| 270 | {
|
---|
| 271 | switch (opt->type)
|
---|
| 272 | {
|
---|
| 273 | case TXA_STRING:
|
---|
| 274 | rc = TxaParseNumber( opt->value.string, TX_RADIX_STD_CLASS, &unit);
|
---|
| 275 | case TXA_NO_VAL:
|
---|
| 276 | rc = def;
|
---|
| 277 | break;
|
---|
| 278 |
|
---|
| 279 | default: // convert, default is MiB!
|
---|
| 280 | rc = opt->value.number;
|
---|
| 281 | unit = opt->unit;
|
---|
| 282 | break;
|
---|
| 283 | }
|
---|
| 284 | }
|
---|
| 285 | if (unit == TXA_DFUNIT)
|
---|
| 286 | {
|
---|
| 287 | unit = mod;
|
---|
| 288 | }
|
---|
| 289 | switch (tolower(unit))
|
---|
| 290 | {
|
---|
| 291 | case 'g':
|
---|
| 292 | if (rc >= 4)
|
---|
| 293 | {
|
---|
| 294 | rc = 0xffffffff;
|
---|
| 295 | break;
|
---|
| 296 | }
|
---|
| 297 | else
|
---|
| 298 | {
|
---|
| 299 | rc *= 1024; // Giga
|
---|
| 300 | }
|
---|
| 301 | case 'm': rc *= 1024; // Mega
|
---|
| 302 | case 'k': rc *= 1024; // Kilo
|
---|
| 303 | default: break; // Bytes, OK
|
---|
| 304 | }
|
---|
| 305 | RETURN (rc);
|
---|
| 306 | } // end 'TxaParseBkmgNumber'
|
---|
| 307 | /*---------------------------------------------------------------------------*/
|
---|
| 308 |
|
---|
| 309 |
|
---|
| 310 | /*****************************************************************************/
|
---|
[1] | 311 | // Read one item (option or argument) and store it in the txa element
|
---|
| 312 | /*****************************************************************************/
|
---|
| 313 | ULONG txaReadAndStoreItem // RET result
|
---|
| 314 | (
|
---|
| 315 | char *item, // IN item string
|
---|
| 316 | int len, // IN length of item
|
---|
| 317 | BOOL freeform, // IN free format options
|
---|
| 318 | BOOL passthrough, // IN keep parameter quotes
|
---|
| 319 | TXA_ELEMENT *txa // INOUT TXA element
|
---|
| 320 | )
|
---|
| 321 | {
|
---|
| 322 | ULONG rc = NO_ERROR;
|
---|
| 323 | int arguments = txa->argc; // current number of arguments
|
---|
| 324 |
|
---|
| 325 | ENTER();
|
---|
| 326 |
|
---|
| 327 | TRACES(( "Freeform: %s Passthrough: %s Args: %d Len:%3.3u, Item: '%*.*s'\n",
|
---|
| 328 | (freeform) ? "YES" : "NO ", (passthrough) ? "YES" : "NO ",
|
---|
| 329 | arguments, len, len, len, item));
|
---|
[11] | 330 | if ((((txa == txa1st) && // switch on 1st level '/' only
|
---|
| 331 | (*(item) == '/')) ||
|
---|
| 332 | (*(item) == '-' )) && // switch or option using '-'
|
---|
| 333 | (*(item +1) != ' ' ) && // allowed at this position ?
|
---|
[1] | 334 | (*(item +1) != '\0' ) &&
|
---|
[11] | 335 | (arguments > 0 ) && // never BEFORE 1st word (cmd)
|
---|
| 336 | ((arguments == 1) || freeform)) // possibly after params too
|
---|
[1] | 337 | {
|
---|
| 338 | int index; // index for the option char
|
---|
| 339 | char *value; // ptr to value part of item
|
---|
| 340 | int distance; // distance to specific char
|
---|
| 341 | TXA_LONGOPT lname = {0}; // empty longname to start with
|
---|
| 342 |
|
---|
| 343 | index = *(item +1);
|
---|
| 344 | if ((index >= TXA_BASE) && (index < (TXA_BASE + TXA_SIZE)))
|
---|
| 345 | {
|
---|
| 346 | index -= TXA_BASE; // make it 0 based
|
---|
| 347 | TRACES(( "Direct option index:%3hu\n", index));
|
---|
| 348 |
|
---|
| 349 | switch (*(item +2))
|
---|
| 350 | {
|
---|
| 351 | case '"': case '\'': // quoted string
|
---|
| 352 | case '+': case '-': // boolean yes/no
|
---|
| 353 | case '0': case '1': case '2': case '3': case '4':
|
---|
| 354 | case '5': case '6': case '7': case '8': case '9':
|
---|
| 355 | value = item +2;
|
---|
| 356 | break;
|
---|
| 357 |
|
---|
| 358 | default:
|
---|
| 359 | if ((distance = (int) strcspn( item, ": ")) < len)
|
---|
| 360 | {
|
---|
| 361 | value = item + distance +1; // skip the colon ...
|
---|
| 362 | }
|
---|
| 363 | else
|
---|
| 364 | {
|
---|
| 365 | if ((len > 2) && // non-empty option name
|
---|
| 366 | (item[len -1] == '-')) // ending in a '-'
|
---|
| 367 | {
|
---|
| 368 | distance = len -1; // length of the name
|
---|
| 369 | value = item + distance; // '-' is the value
|
---|
| 370 | }
|
---|
| 371 | else
|
---|
| 372 | {
|
---|
| 373 | value = item + len; // no explicit value given
|
---|
| 374 | }
|
---|
| 375 | }
|
---|
| 376 |
|
---|
| 377 | if (distance > 2) // non-trivial longname
|
---|
| 378 | {
|
---|
| 379 | int lni;
|
---|
| 380 |
|
---|
| 381 | strncpy( lname, item +1, distance -1);
|
---|
| 382 | lname[distance -1] = 0; // terminate the name
|
---|
| 383 | TRACES(( "longname '%s' for: '%s'\n", lname, item));
|
---|
| 384 |
|
---|
| 385 | if (stricmp( "help", lname) == 0) // predefined, map to '?'
|
---|
| 386 | {
|
---|
| 387 | index = '?' - TXA_BASE;
|
---|
| 388 | }
|
---|
| 389 | else
|
---|
| 390 | {
|
---|
| 391 | for (lni = 0; lni < TXA_LSIZE; lni++)
|
---|
| 392 | {
|
---|
| 393 | if (strlen(txalongopt[lni]) != 0)
|
---|
| 394 | {
|
---|
| 395 | if (stricmp( txalongopt[lni], lname) == 0)
|
---|
| 396 | {
|
---|
| 397 | index = lni + TXA_LBASE - TXA_BASE;
|
---|
| 398 |
|
---|
| 399 | TRACES(("Matched defined longname '%s', index: %hu\n",
|
---|
| 400 | txalongopt[lni], index));
|
---|
| 401 | }
|
---|
| 402 | }
|
---|
| 403 | }
|
---|
| 404 | }
|
---|
| 405 | }
|
---|
| 406 | break;
|
---|
| 407 | }
|
---|
| 408 | TxFreeMem( txa->opt[index].name); // free existing name, if any
|
---|
| 409 | if (strlen( lname) != 0) // new longname available ?
|
---|
| 410 | {
|
---|
| 411 | if ((txa->opt[ index].name = TxAlloc(1, strlen(lname) +1)) != NULL)
|
---|
| 412 | {
|
---|
| 413 | strcpy( txa->opt[ index].name, lname);
|
---|
| 414 | }
|
---|
| 415 | }
|
---|
| 416 |
|
---|
| 417 | if (txa->opt[ index].type == TXA_STRING) // already has a string!
|
---|
| 418 | {
|
---|
| 419 | TRACES(("Free existing string value: '%s'\n",
|
---|
| 420 | txa->opt[ index].value.string));
|
---|
| 421 | TxFreeMem( txa->opt[ index].value.string);
|
---|
| 422 | }
|
---|
| 423 | txa->opt[ index].type = TXA_NUMBER;
|
---|
| 424 | txa->opt[ index].unit = TXA_DFUNIT; // default unit
|
---|
| 425 | switch (*value)
|
---|
| 426 | {
|
---|
| 427 | case TXk_SPACE: case '\0':
|
---|
| 428 | txa->opt[ index].type = TXA_NO_VAL;
|
---|
| 429 | txa->opt[ index].value.number = 0;
|
---|
| 430 | TRACES(("NoValueOpt (%3hu='%c')\n", index + TXA_BASE, index + TXA_BASE));
|
---|
| 431 | break;
|
---|
| 432 |
|
---|
| 433 | case '+': txa->opt[ index].value.number = 1; break;
|
---|
| 434 | case '-': txa->opt[ index].value.number = 0; break;
|
---|
| 435 | case '0': case '1': case '2': case '3': case '4':
|
---|
| 436 | case '5': case '6': case '7': case '8': case '9':
|
---|
| 437 | txa->opt[ index].value.number =
|
---|
| 438 | TxaParseNumber( value, TX_RADIX_STD_CLASS,
|
---|
| 439 | &(txa->opt[ index].unit));
|
---|
| 440 |
|
---|
| 441 | TRACES(("NumericOpt (%3hu='%c'), value: %lu\n",
|
---|
| 442 | index + TXA_BASE, index + TXA_BASE,
|
---|
| 443 | txa->opt[ index].value.number));
|
---|
| 444 | break;
|
---|
| 445 |
|
---|
| 446 | default:
|
---|
| 447 | txa->opt[ index].type = TXA_STRING;
|
---|
| 448 | if ((txa->opt[ index].value.string = TxAlloc(1, len +1)) != NULL)
|
---|
| 449 | {
|
---|
| 450 | if (passthrough) // straight copy
|
---|
| 451 | {
|
---|
| 452 | strcpy( txa->opt[ index].value.string, value);
|
---|
| 453 | }
|
---|
| 454 | else // space delimited stuff!
|
---|
| 455 | {
|
---|
| 456 | txaCopyItem( txa->opt[ index].value.string, value, len);
|
---|
| 457 | }
|
---|
| 458 |
|
---|
| 459 | TRACES(("String Opt (%3hu='%c') at %8.8lx, value: '%s'\n",
|
---|
| 460 | index + TXA_BASE, index + TXA_BASE,
|
---|
| 461 | txa->opt[ index].value.string,
|
---|
| 462 | txa->opt[ index].value.string));
|
---|
| 463 | }
|
---|
| 464 | else
|
---|
| 465 | {
|
---|
| 466 | rc = TX_ALLOC_ERROR;
|
---|
| 467 | }
|
---|
| 468 | break;
|
---|
| 469 | }
|
---|
| 470 | txa->optc++; // count the option
|
---|
| 471 | }
|
---|
| 472 | else // option char out of range
|
---|
| 473 | {
|
---|
| 474 | rc = TX_BAD_OPTION_CHAR;
|
---|
| 475 | }
|
---|
| 476 | }
|
---|
| 477 | else // argv 0 .. n
|
---|
| 478 | {
|
---|
| 479 | if (arguments < TXA_ARGC) // room for another ?
|
---|
| 480 | {
|
---|
| 481 | if ((txa->argv[ arguments] = TxAlloc(1, len +1)) != NULL)
|
---|
| 482 | {
|
---|
| 483 | if (passthrough) // straight copy
|
---|
| 484 | {
|
---|
| 485 | strcpy( txa->argv[ arguments], item);
|
---|
| 486 | }
|
---|
| 487 | else // space delimited stuff!
|
---|
| 488 | {
|
---|
| 489 | txaCopyItem( txa->argv[ arguments], item, len);
|
---|
| 490 | }
|
---|
| 491 | TRACES(("Stored argv[%d] at %8.8lx, value: '%s'\n", arguments,
|
---|
| 492 | txa->argv[ arguments], txa->argv[ arguments]));
|
---|
| 493 | arguments++;
|
---|
| 494 | }
|
---|
| 495 | else
|
---|
| 496 | {
|
---|
| 497 | rc = TX_ALLOC_ERROR;
|
---|
| 498 | }
|
---|
| 499 | }
|
---|
| 500 | else
|
---|
| 501 | {
|
---|
| 502 | rc = TX_TOO_MANY_ARGS;
|
---|
| 503 | }
|
---|
| 504 | }
|
---|
| 505 | txa->argc = arguments;
|
---|
| 506 | RETURN( rc);
|
---|
| 507 | } // end 'txaReadAndStoreItem'
|
---|
| 508 | /*---------------------------------------------------------------------------*/
|
---|
| 509 |
|
---|
| 510 |
|
---|
| 511 | /*****************************************************************************/
|
---|
| 512 | // Create new level of command options for a set of argc/argv variables
|
---|
| 513 | /*****************************************************************************/
|
---|
| 514 | ULONG TxaNewParseElement // RET result
|
---|
| 515 | (
|
---|
| 516 | TXA_ELEMENT **element // OUT TXA element
|
---|
| 517 | )
|
---|
| 518 | {
|
---|
| 519 | ULONG rc = NO_ERROR;
|
---|
| 520 | TXA_ELEMENT *txa = NULL;
|
---|
| 521 |
|
---|
| 522 | if ((txa = TxAlloc(1, sizeof(TXA_ELEMENT))) != NULL)
|
---|
| 523 | {
|
---|
| 524 | txa->signature = TXA_SIGNATURE;
|
---|
| 525 | txa->prev = txacur;
|
---|
| 526 |
|
---|
| 527 | if (txacur == NULL) // first one ?
|
---|
| 528 | {
|
---|
| 529 | txa1st = txa;
|
---|
| 530 | }
|
---|
| 531 | txacur = txa;
|
---|
| 532 | }
|
---|
| 533 | else
|
---|
| 534 | {
|
---|
| 535 | rc = TX_ALLOC_ERROR;
|
---|
| 536 | }
|
---|
| 537 | *element = txa;
|
---|
| 538 | return( rc);
|
---|
| 539 | } // end 'TxaNewParseElement'
|
---|
| 540 | /*---------------------------------------------------------------------------*/
|
---|
| 541 |
|
---|
| 542 |
|
---|
| 543 | /*****************************************************************************/
|
---|
| 544 | // Terminate use of current or all instances of the TXA abstract-data-type
|
---|
| 545 | /*****************************************************************************/
|
---|
| 546 | BOOL TxaDropParsedCommand // RET more instances left
|
---|
| 547 | (
|
---|
| 548 | BOOL whole_stack // IN drop all, terminate
|
---|
| 549 | )
|
---|
| 550 | {
|
---|
| 551 | TXA_ELEMENT *txa;
|
---|
| 552 | int i;
|
---|
| 553 |
|
---|
| 554 | ENTER();
|
---|
| 555 |
|
---|
| 556 | do
|
---|
| 557 | {
|
---|
| 558 | if ((txa = txacur) != NULL)
|
---|
| 559 | {
|
---|
| 560 | for (i = 0; i < TXA_SIZE; i++) // free allocated options
|
---|
| 561 | {
|
---|
| 562 | if (txa->opt[i].type == TXA_STRING)
|
---|
| 563 | {
|
---|
| 564 | TxFreeMem( txa->opt[i].value.string);
|
---|
| 565 | }
|
---|
| 566 | TxFreeMem( txa->opt[i].name);
|
---|
| 567 | }
|
---|
| 568 | for (i = 0; i < txa->argc; i++) // free argv storage
|
---|
| 569 | {
|
---|
| 570 | if (txa->argv[i] != NULL)
|
---|
| 571 | {
|
---|
| 572 | TxFreeMem( txa->argv[i]);
|
---|
| 573 | }
|
---|
| 574 | }
|
---|
| 575 | txacur = txa->prev;
|
---|
| 576 | if (txacur == NULL) // empty again ?
|
---|
| 577 | {
|
---|
| 578 | txa1st = NULL;
|
---|
| 579 | }
|
---|
| 580 | TxFreeMem( txa);
|
---|
| 581 | }
|
---|
| 582 | } while (txacur && whole_stack);
|
---|
| 583 |
|
---|
| 584 | BRETURN((txacur != NULL));
|
---|
| 585 | } // end 'TxaDropParsedCommand'
|
---|
| 586 | /*---------------------------------------------------------------------------*/
|
---|
| 587 |
|
---|
| 588 |
|
---|
| 589 | /*****************************************************************************/
|
---|
| 590 | // Get reference to specified option data, or NULL if option not set
|
---|
| 591 | /*****************************************************************************/
|
---|
| 592 | TXA_OPTION *TxaGetOption // RET option ptr or NULL
|
---|
| 593 | (
|
---|
| 594 | TXHANDLE txh, // IN TXA handle
|
---|
| 595 | char opt // IN option character
|
---|
| 596 | )
|
---|
| 597 | {
|
---|
| 598 | TXA_OPTION *rc = NULL;
|
---|
| 599 | TXA_ELEMENT *txa; // specified TXA instance
|
---|
| 600 | int i;
|
---|
| 601 | TXA_OPTION *o;
|
---|
| 602 |
|
---|
| 603 | if ((txa = txaHandle2Element( txh)) != NULL)
|
---|
| 604 | {
|
---|
| 605 | if ((opt >= TXA_BASE) && (opt < (TXA_BASE + TXA_SIZE)))
|
---|
| 606 | {
|
---|
| 607 | i = opt - TXA_BASE; // make it 0 based
|
---|
| 608 | o = &txa->opt[ i];
|
---|
| 609 | if (o->type != TXA_NONE)
|
---|
| 610 | {
|
---|
| 611 | rc = o;
|
---|
| 612 | }
|
---|
| 613 | TRARGS(("TXH (%s): %lx option: %3hu = '%c' value: %lu '%s'\n",
|
---|
| 614 | (txh == TXA_1ST) ? "EXE switch" : "CMD option", txh, opt, opt,
|
---|
| 615 | (o->type == TXA_STRING) ? strlen(o->value.string) : o->value.number,
|
---|
| 616 | (o->type == TXA_NONE ) ? "---NONE---" :
|
---|
| 617 | (o->type != TXA_STRING) ? "--NUMBER--" : o->value.string ));
|
---|
| 618 | }
|
---|
| 619 | }
|
---|
| 620 | return( rc);
|
---|
| 621 | } // end 'TxaGetOption'
|
---|
| 622 | /*---------------------------------------------------------------------------*/
|
---|
| 623 |
|
---|
| 624 |
|
---|
| 625 | /*****************************************************************************/
|
---|
| 626 | // Get simple YES/NO status for specified option. Not set is "NO"
|
---|
| 627 | /*****************************************************************************/
|
---|
| 628 | BOOL TxaOptionYes // RET option set to YES
|
---|
| 629 | (
|
---|
| 630 | TXHANDLE txh, // IN TXA handle
|
---|
| 631 | char opt // IN option character
|
---|
| 632 | )
|
---|
| 633 | {
|
---|
| 634 | BOOL rc = FALSE;
|
---|
| 635 | TXA_OPTION *o;
|
---|
| 636 |
|
---|
| 637 | if ((o = TxaGetOption( txh, opt)) != NULL)
|
---|
| 638 | {
|
---|
| 639 | switch (o->type)
|
---|
| 640 | {
|
---|
| 641 | case TXA_NUMBER:
|
---|
| 642 | if (o->value.number != 0)
|
---|
| 643 | {
|
---|
| 644 | rc = TRUE;
|
---|
| 645 | }
|
---|
| 646 | break;
|
---|
| 647 |
|
---|
| 648 | case TXA_STRING:
|
---|
| 649 | if ((stricmp( o->value.string, "NO") != 0) &&
|
---|
| 650 | (stricmp( o->value.string, "N") != 0) &&
|
---|
| 651 | (stricmp( o->value.string, "0") != 0) &&
|
---|
| 652 | (stricmp( o->value.string, "OFF") != 0) &&
|
---|
| 653 | (stricmp( o->value.string, "FALSE") != 0) )
|
---|
| 654 | {
|
---|
| 655 | rc = TRUE;
|
---|
| 656 | }
|
---|
| 657 | break;
|
---|
| 658 |
|
---|
| 659 | default: // no value, but set
|
---|
| 660 | rc = TRUE;
|
---|
| 661 | break;
|
---|
| 662 | }
|
---|
| 663 | }
|
---|
| 664 | return( rc);
|
---|
| 665 | } // end 'TxaOptionYes'
|
---|
| 666 | /*---------------------------------------------------------------------------*/
|
---|
| 667 |
|
---|
| 668 |
|
---|
| 669 | /*****************************************************************************/
|
---|
| 670 | // Get string value for specified option, use default if no string (and warn!)
|
---|
| 671 | /*****************************************************************************/
|
---|
| 672 | char *TxaOptionStr // RET option String value
|
---|
| 673 | (
|
---|
| 674 | TXHANDLE txh, // IN TXA handle
|
---|
| 675 | char opt, // IN option character
|
---|
| 676 | char *error, // IN error text or NULL
|
---|
| 677 | char *deflt // IN default value
|
---|
| 678 | )
|
---|
| 679 | {
|
---|
| 680 | char *rc = deflt;
|
---|
| 681 | TXA_OPTION *o;
|
---|
| 682 |
|
---|
| 683 | if ((o = TxaGetOption( txh, opt)) != NULL)
|
---|
| 684 | {
|
---|
| 685 | if (o->type == TXA_STRING)
|
---|
| 686 | {
|
---|
| 687 | rc = o->value.string;
|
---|
| 688 | }
|
---|
| 689 | else // other option type
|
---|
| 690 | {
|
---|
| 691 | if (error != NULL) // give error/warning
|
---|
| 692 | {
|
---|
| 693 | TxPrint( "\n%s %s: %s'-%c'%s has no STRING value, using "
|
---|
| 694 | "default: '%s'\n",
|
---|
| 695 | (txh != TXA_1ST) ? "Option" : "Switch",
|
---|
| 696 | error, CBC, opt, CNN, deflt);
|
---|
| 697 | }
|
---|
| 698 | }
|
---|
| 699 | }
|
---|
| 700 | return( rc);
|
---|
| 701 | } // end 'TxaOptionStr'
|
---|
| 702 | /*---------------------------------------------------------------------------*/
|
---|
| 703 |
|
---|
| 704 |
|
---|
| 705 | /*****************************************************************************/
|
---|
| 706 | // Get number value for specified option, use default if no number (and warn!)
|
---|
| 707 | /*****************************************************************************/
|
---|
| 708 | ULONG TxaOptionNum // RET option Number value
|
---|
| 709 | (
|
---|
| 710 | TXHANDLE txh, // IN TXA handle
|
---|
| 711 | char opt, // IN option character
|
---|
| 712 | char *error, // IN error text or NULL
|
---|
| 713 | ULONG deflt // IN default value
|
---|
| 714 | )
|
---|
| 715 | {
|
---|
| 716 | ULONG rc = deflt;
|
---|
| 717 | TXA_OPTION *o;
|
---|
| 718 |
|
---|
| 719 | if ((o = TxaGetOption( txh, opt)) != NULL)
|
---|
| 720 | {
|
---|
| 721 | if (o->type == TXA_NUMBER)
|
---|
| 722 | {
|
---|
| 723 | rc = o->value.number;
|
---|
| 724 | }
|
---|
| 725 | else // other option type
|
---|
| 726 | {
|
---|
| 727 | if (error != NULL) // give error/warning
|
---|
| 728 | {
|
---|
| 729 | TxPrint( "\n%s %s: %s'-%c'%s has no NUMBER value, using "
|
---|
| 730 | "default: 0x%8.8lx = %lu\n",
|
---|
| 731 | (txh != TXA_1ST) ? "Option" : "Switch",
|
---|
| 732 | error, CBC, opt, CNN, deflt, deflt);
|
---|
| 733 | }
|
---|
| 734 | }
|
---|
| 735 | }
|
---|
| 736 | return( rc);
|
---|
| 737 | } // end 'TxaOptionNum'
|
---|
| 738 | /*---------------------------------------------------------------------------*/
|
---|
| 739 |
|
---|
| 740 |
|
---|
| 741 | /*****************************************************************************/
|
---|
[13] | 742 | // Get option value num/string, with bytes/kilo/mega/giga modifier and default
|
---|
| 743 | /*****************************************************************************/
|
---|
| 744 | ULONG TxaOptionBkmg // RET number value in bytes
|
---|
| 745 | (
|
---|
| 746 | TXHANDLE txh, // IN TXA handle
|
---|
| 747 | char option, // IN option character
|
---|
| 748 | ULONG def, // IN default value
|
---|
| 749 | BYTE mod // IN b,kb,mb,gb modifier
|
---|
| 750 | )
|
---|
| 751 | {
|
---|
| 752 | ULONG rc = 0; // function return
|
---|
| 753 | BYTE unit = TXA_DFUNIT;
|
---|
| 754 | TXA_OPTION *opt; // option pointer
|
---|
| 755 |
|
---|
| 756 | ENTER();
|
---|
| 757 | TRACES(("Option: '%c' default: %8.8lx mod:%2.2hx = '%c'\n",
|
---|
| 758 | option, def, mod, mod));
|
---|
| 759 |
|
---|
| 760 | if ((opt = TxaOptValue( option)) != NULL) // get the option details
|
---|
| 761 | {
|
---|
| 762 | switch (opt->type)
|
---|
| 763 | {
|
---|
| 764 | case TXA_STRING:
|
---|
| 765 | rc = TxaParseNumber( opt->value.string, TX_RADIX_STD_CLASS, &unit);
|
---|
| 766 | case TXA_NO_VAL:
|
---|
| 767 | rc = def;
|
---|
| 768 | break;
|
---|
| 769 |
|
---|
| 770 | default: // convert, default is MiB!
|
---|
| 771 | rc = opt->value.number;
|
---|
| 772 | unit = opt->unit;
|
---|
| 773 | break;
|
---|
| 774 | }
|
---|
| 775 | }
|
---|
| 776 | if (unit == TXA_DFUNIT)
|
---|
| 777 | {
|
---|
| 778 | unit = mod;
|
---|
| 779 | }
|
---|
| 780 | switch (tolower(unit))
|
---|
| 781 | {
|
---|
| 782 | case 'g': rc *= 1024; // Giga
|
---|
| 783 | case 'm': rc *= 1024; // Mega
|
---|
| 784 | case 'k': rc *= 1024; // Kilo
|
---|
| 785 | default: break; // Bytes, OK
|
---|
| 786 | }
|
---|
| 787 | RETURN (rc);
|
---|
| 788 | } // end 'TxaOptionBkmg'
|
---|
| 789 | /*---------------------------------------------------------------------------*/
|
---|
| 790 |
|
---|
| 791 |
|
---|
| 792 | /*****************************************************************************/
|
---|
[1] | 793 | // Get reference to specified argument-string
|
---|
| 794 | /*****************************************************************************/
|
---|
| 795 | char *TxaGetArgv // RET argv string or ""
|
---|
| 796 | (
|
---|
| 797 | TXHANDLE txh, // IN TXA handle
|
---|
| 798 | int argn // IN argument number 0..n
|
---|
| 799 | )
|
---|
| 800 | {
|
---|
| 801 | char *rc = ""; // return empty if not there
|
---|
| 802 | TXA_ELEMENT *txa; // specified TXA instance
|
---|
| 803 |
|
---|
| 804 | if ((txa = txaHandle2Element( txh)) != NULL)
|
---|
| 805 | {
|
---|
| 806 | if ((argn >= 0) && (argn < txa->argc)) // valid argument nr ?
|
---|
| 807 | {
|
---|
| 808 | rc = txa->argv[argn];
|
---|
| 809 | TRACES(("GETARGV argument: %d = '%s'\n", argn, rc));
|
---|
| 810 | }
|
---|
| 811 | }
|
---|
| 812 | return( rc);
|
---|
| 813 | } // end 'TxaGetArgv'
|
---|
| 814 | /*---------------------------------------------------------------------------*/
|
---|
| 815 |
|
---|
| 816 | /*****************************************************************************/
|
---|
| 817 | // Get the number of arguments for specified TXA instance
|
---|
| 818 | /*****************************************************************************/
|
---|
| 819 | int TxaGetArgc // RET argument count
|
---|
| 820 | (
|
---|
| 821 | TXHANDLE txh // IN TXA handle
|
---|
| 822 | )
|
---|
| 823 | {
|
---|
| 824 | int rc = 0;
|
---|
| 825 | TXA_ELEMENT *txa; // specified TXA instance
|
---|
| 826 |
|
---|
| 827 | if ((txa = txaHandle2Element( txh)) != NULL)
|
---|
| 828 | {
|
---|
| 829 | rc = txa->argc;
|
---|
| 830 | }
|
---|
| 831 | return( rc);
|
---|
| 832 | } // end 'TxaGetArgc'
|
---|
| 833 | /*---------------------------------------------------------------------------*/
|
---|
| 834 |
|
---|
| 835 |
|
---|
| 836 | /*****************************************************************************/
|
---|
| 837 | // Get the number of options for specified TXA instance
|
---|
| 838 | /*****************************************************************************/
|
---|
| 839 | int TxaGetOptc // RET option count
|
---|
| 840 | (
|
---|
| 841 | TXHANDLE txh // IN TXA handle
|
---|
| 842 | )
|
---|
| 843 | {
|
---|
| 844 | int rc = 0;
|
---|
| 845 | TXA_ELEMENT *txa; // specified TXA instance
|
---|
| 846 |
|
---|
| 847 | ENTER();
|
---|
| 848 | if ((txa = txaHandle2Element( txh)) != NULL)
|
---|
| 849 | {
|
---|
| 850 | rc = txa->optc;
|
---|
| 851 | }
|
---|
| 852 | RETURN( rc);
|
---|
| 853 | } // end 'TxaGetOptc'
|
---|
| 854 | /*---------------------------------------------------------------------------*/
|
---|
| 855 |
|
---|
| 856 |
|
---|
| 857 | /*****************************************************************************/
|
---|
| 858 | // Take handle value and convert to element, validate signature
|
---|
| 859 | /*****************************************************************************/
|
---|
| 860 | TXA_ELEMENT *txaHandle2Element // RET element ptr or NULL
|
---|
| 861 | (
|
---|
| 862 | TXHANDLE txh // IN TXA handle
|
---|
| 863 | )
|
---|
| 864 | {
|
---|
| 865 | TXA_ELEMENT *txa;
|
---|
| 866 |
|
---|
| 867 | switch (txh)
|
---|
| 868 | {
|
---|
| 869 | case TXA_CUR: txa = txacur; break;
|
---|
| 870 | case TXA_PREV: txa = (txacur) ? txacur->prev : NULL; break;
|
---|
| 871 | case TXA_1ST: txa = txa1st; break;
|
---|
| 872 | default: txa = (TXA_ELEMENT *) txh; break;
|
---|
| 873 | }
|
---|
| 874 | if ((txa) && (txa->signature != TXA_SIGNATURE))
|
---|
| 875 | {
|
---|
| 876 | txa = NULL;
|
---|
| 877 | }
|
---|
| 878 | return( txa);
|
---|
| 879 | } // end 'txaHandle2Element'
|
---|
| 880 | /*---------------------------------------------------------------------------*/
|
---|
| 881 |
|
---|
| 882 |
|
---|
| 883 | /*****************************************************************************/
|
---|
| 884 | // Copy item from string, honor embedded strings, strip quotes and escapes
|
---|
| 885 | /*****************************************************************************/
|
---|
| 886 | char *txaCopyItem // RET copied string
|
---|
| 887 | (
|
---|
| 888 | char *destin, // OUT destination buffer
|
---|
| 889 | char *start, // IN start position
|
---|
| 890 | int length // IN max length to copy
|
---|
| 891 | )
|
---|
| 892 | {
|
---|
| 893 | char *s;
|
---|
| 894 | char *d;
|
---|
| 895 | int l;
|
---|
| 896 | char delim = ' '; // default delimitter
|
---|
| 897 | BOOL escape = FALSE;
|
---|
| 898 |
|
---|
| 899 | if ((start != NULL) && (destin != NULL))
|
---|
| 900 | {
|
---|
| 901 | TRACES(( "COPY: Max length:%3.3u, start:}}}% -*.*s{{{\n",
|
---|
| 902 | length, length, length, start));
|
---|
| 903 | for (s = start, d = destin, l = 0; l < length; l++, s++)
|
---|
| 904 | {
|
---|
| 905 | if (*s == delim)
|
---|
| 906 | {
|
---|
| 907 | if (delim == ' ') // end of item reached
|
---|
| 908 | {
|
---|
| 909 | break;
|
---|
| 910 | }
|
---|
| 911 | else if (((*s == '"') || (*s == '\'')) && (escape))
|
---|
| 912 | {
|
---|
| 913 | *d++ = *s; // copy the character
|
---|
| 914 | }
|
---|
| 915 | else // end-of-string
|
---|
| 916 | {
|
---|
| 917 | delim = ' '; // to end of item ...
|
---|
| 918 | }
|
---|
| 919 | }
|
---|
| 920 | else if ((!escape) && // prev was no escape
|
---|
| 921 | (delim == ' ') && // and not in a string yet
|
---|
| 922 | ((*s == '"') || (*s == '\''))) // double or single quote
|
---|
| 923 | {
|
---|
| 924 | delim = *s; // to end of string
|
---|
| 925 | }
|
---|
| 926 | else if ( (*s == '\\') && // possible escape
|
---|
| 927 | ((*(s+1) == ';') || // for comment
|
---|
| 928 | (*(s+1) == '"') || // for double quote
|
---|
| 929 | (*(s+1) == '\'') )) // or single quote
|
---|
| 930 | {
|
---|
| 931 | escape = TRUE; // indicate escape next char
|
---|
| 932 | continue; // and don't reset too early
|
---|
| 933 | }
|
---|
| 934 | else // normal character
|
---|
| 935 | {
|
---|
| 936 | *d++ = *s; // copy the character
|
---|
| 937 | }
|
---|
| 938 | escape = FALSE;
|
---|
| 939 | // TRACES(( "*s:'%c', esc:%lu, destin:'%s'\n", *s, escape, destin));
|
---|
| 940 | }
|
---|
| 941 | *d = '\0'; // terminate the string
|
---|
| 942 | TRACES(("COPY : '%s'\n", destin));
|
---|
| 943 | }
|
---|
| 944 | return (destin);
|
---|
| 945 | } // end 'txaCopyItem'
|
---|
| 946 | /*---------------------------------------------------------------------------*/
|
---|
| 947 |
|
---|