Annotation of gpl/axl/knife/exarg.c, revision 1.1
1.1 ! misho 1: /**
! 2: * LibExploreArguments: a library to parse command line options
! 3: * Copyright (C) 2005 Advanced Software Production Line, S.L.
! 4: *
! 5: * This program is free software; you can redistribute it and/or
! 6: * modify it under the terms of the GNU Lesser General Public License
! 7: * as published by the Free Software Foundation; either version 2.1 of
! 8: * the License, or (at your option) any later version.
! 9: *
! 10: * This program is distributed in the hope that it will be useful,
! 11: * but WITHOUT ANY WARRANTY; without even the implied warranty of
! 12: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 13: * GNU Lesser General Public License for more details.
! 14: *
! 15: * You should have received a copy of the GNU Lesser General Public
! 16: * License along with this program; if not, write to the Free
! 17: * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
! 18: * 02111-1307 USA
! 19: *
! 20: * You may find a copy of the license under this software is released
! 21: * at COPYING file. This is LGPL software: you are wellcome to
! 22: * develop propietary applications using this library withtout any
! 23: * royalty or fee but returning back any change, improvement or
! 24: * addition in the form of source code, project image, documentation
! 25: * patches, etc.
! 26: *
! 27: * Contact us at:
! 28: *
! 29: * Postal address:
! 30: * Advanced Software Production Line, S.L.
! 31: * C/ Dr. Michavila NÂș 14
! 32: * Coslada 28820 Madrid
! 33: * Spain
! 34: *
! 35: * Email address:
! 36: * info@aspl.es - http://fact.aspl.es
! 37: *
! 38: */
! 39: #include <exarg.h>
! 40:
! 41: #if defined(__GNUC__)
! 42: # ifndef _GNU_SOURCE
! 43: # define _GNU_SOURCE
! 44: # endif
! 45: #endif
! 46:
! 47: /* local includes */
! 48: #include <stdio.h>
! 49: #include <string.h>
! 50: #include <stdarg.h>
! 51: #include <stdlib.h>
! 52:
! 53: #define LOG_DOMAIN "exarg"
! 54:
! 55: typedef struct _ExArgNodeOption ExArgNodeOption;
! 56:
! 57: /**
! 58: * @internal Definition for the void *.
! 59: */
! 60: typedef void * epointer;
! 61:
! 62: /**
! 63: * @brief First argument option supported (this is the head of the
! 64: * list of arguments supported).
! 65: */
! 66: ExArgNodeOption * argument_options = NULL;
! 67: ExArgument * params = NULL;
! 68: const char * exarg_exec_name = NULL;
! 69: char * __exarg_usage_header = NULL;
! 70: char * __exarg_help_header = NULL;
! 71: char * __exarg_post_usage_header = NULL;
! 72: char * __exarg_post_help_header = NULL;
! 73: int __exarg_disable_free_args = 0;
! 74:
! 75: typedef enum {
! 76: /**
! 77: * @internal Parse mode not defined.
! 78: */
! 79: PARSE_MODE_NOT_DEF,
! 80: /**
! 81: * @internal Parse mode unix defined.
! 82: */
! 83: PARSE_MODE_UNIX,
! 84: /**
! 85: * @internal Parse module windows defined.
! 86: */
! 87: PARSE_MODE_WINDOWS
! 88: } ExArgParseMode;
! 89:
! 90: /**
! 91: * @internal This allows to know the parse mode used by exarg. Parse
! 92: * mode allows to differenciate arguments that are file path under
! 93: * unix by options under windows. This option is automatic, being the
! 94: * first option parse to configure the parse mode. This means that the
! 95: * user can't mix options provided using the windows and unix mode at
! 96: * the same time.
! 97: */
! 98: ExArgParseMode parse_mode = PARSE_MODE_NOT_DEF;
! 99:
! 100: /**
! 101: * @internal Function used by the exarg library to drop a message.
! 102: *
! 103: * @param format The message to print using a printf format.
! 104: */
! 105: void exarg_msg (char * format, ...)
! 106: {
! 107: va_list args;
! 108:
! 109: /* print the message */
! 110: va_start (args, format);
! 111: vprintf (format, args);
! 112: va_end (args);
! 113:
! 114: /* flush */
! 115: fflush (stdout);
! 116:
! 117: /* exit from the library */
! 118: exit (-1);
! 119:
! 120: return;
! 121: }
! 122:
! 123: /**
! 124: * @brief Allows to check current parse mode, return ok if the parse
! 125: * mode isn't defined or the current parse mode is the one provided.
! 126: *
! 127: * @param mode The parse mode to check.
! 128: *
! 129: * @return 1 if the parse mode is ok or 0 if current parse mode is
! 130: * incompatible.
! 131: */
! 132: #define CHECK_PARSE_MODE(mode) ((parse_mode == PARSE_MODE_NOT_DEF) || (parse_mode == mode))
! 133:
! 134: /**
! 135: * @brief Allows to update current parse mode.
! 136: *
! 137: * @param mode The parse mode to configure.
! 138: *
! 139: */
! 140: #define UPDATE_PARSE_MODE(mode)\
! 141: if (parse_mode == PARSE_MODE_NOT_DEF)\
! 142: parse_mode = mode;
! 143:
! 144: /**
! 145: * \mainpage LibExArg (Explore Arguments Library) Manual
! 146: * \section Introduction
! 147: *
! 148: * LibExArg library is a small, easy to use with a consistent API
! 149: * which allows you to parse command line argument for your program.
! 150: *
! 151: * It doesn't require any external dependency for its function, it
! 152: * really portable and at this point is running on <b>GNU/Linux</b>
! 153: * platforms and <b>Microsoft Windows</b> platforms.
! 154: *
! 155: * For details on how to starting to use LibExarg, you can find the
! 156: * \ref exarg "module documentation for LibExArg here". You can find
! 157: * \ref exarg_example "here an example about using LibExArg".
! 158: *
! 159: * \section licence Library License
! 160: *
! 161: * The library is released under the terms of the GNU LGPL (The GNU
! 162: * Lesser General Public License) licence. You can get a copy of the
! 163: * license http://www.gnu.org/licenses/licenses.html#LGPL.
! 164: *
! 165: * This license allows you to write applications using LibExArg which
! 166: * are using some GPL compatible license or commercial applications.
! 167: *
! 168: */
! 169:
! 170: /**
! 171: * \page exarg_example A simple example on using LibExarg
! 172: *
! 173: * \section Introduction
! 174: *
! 175: * You may find interesting the following example which makes use of
! 176: * LibExArg. This example install 3 arguments to be accepted as valid
! 177: * command line options and the write down to the terminal the result
! 178: * of those command used by the user.
! 179: *
! 180: * Once the arguments are installed, the user can execute
! 181: *
! 182: *
! 183: * \include "test-exarg.c"
! 184: *
! 185: */
! 186:
! 187: /** \defgroup exarg ExArg module: functions to parse command line argument in your program
! 188: *
! 189: */
! 190:
! 191: /**
! 192: * @brief Argument dependency (a list of nodes that each argument has
! 193: * to define for its dependencies and its mutual exclusions).
! 194: */
! 195: typedef struct _ExArgDependency ExArgDependency;
! 196:
! 197: struct _ExArgDependency {
! 198: ExArgNodeOption * node;
! 199: ExArgDependency * next;
! 200: };
! 201:
! 202:
! 203: /**
! 204: * \addtogroup exarg
! 205: * @{
! 206: */
! 207:
! 208: struct _ExArgNodeOption {
! 209: /**
! 210: * @brief Holds the argument name (long value recognized by
! 211: * --long-option and /long-option).
! 212: */
! 213: const char * arg_name;
! 214: /**
! 215: * @brief Holds the optional short argument option.
! 216: */
! 217: const char * arg_short_name;
! 218: /**
! 219: * @brief Argument type.
! 220: */
! 221: ExArgType type;
! 222: /**
! 223: * @brief Argument description.
! 224: */
! 225: const char * description;
! 226: /**
! 227: * @brief If the argument is \ref EXARG_STRING, this holds the
! 228: * string value associated if defined.
! 229: */
! 230: char * string_value;
! 231: /**
! 232: * @brief If the argument is \ref EXARG_INT, this holds the
! 233: * int value associated if defined.
! 234: */
! 235: int int_value;
! 236: /**
! 237: * @brief Boolean value that allows to know if the argument
! 238: * option was defined
! 239: */
! 240: int is_defined;
! 241:
! 242: /**
! 243: * @brief Allows to configure if the provided argument is
! 244: * optional.
! 245: */
! 246: int is_optional;
! 247:
! 248: /**
! 249: * @brief Pointer to the next argument option stored.
! 250: */
! 251: ExArgNodeOption * next;
! 252:
! 253: /* a reference to the first dependecy argument */
! 254: ExArgDependency * depends;
! 255:
! 256: ExArgDependency * excludes;
! 257: };
! 258:
! 259: struct _ExArgument {
! 260: /**
! 261: * @brief The string value that is encapsulated by the
! 262: * argument.
! 263: */
! 264: char * string;
! 265:
! 266: /**
! 267: * @brief A reference to the next argument in the list.
! 268: */
! 269: ExArgument * next;
! 270: };
! 271:
! 272:
! 273: /**
! 274: * @internal Definition to allocate memory.
! 275: *
! 276: * @param type The type to allocate
! 277: * @param count The amount of memory to allocate.
! 278: *
! 279: * @return Returns a newly allocated memory.
! 280: */
! 281: #define exarg_new(type, count) (type *) calloc (count, sizeof (type))
! 282:
! 283: /**
! 284: * @internal Definition to dealloc an object.
! 285: *
! 286: * @param ref The reference to dealloc.
! 287: */
! 288: void exarg_free (epointer ref)
! 289: {
! 290: if (ref == NULL)
! 291: return;
! 292: free (ref);
! 293:
! 294: return;
! 295: }
! 296:
! 297: /**
! 298: * @internal Allows to get the basename for the file path provided.
! 299: *
! 300: * @param file_path The file path that is requested to return the
! 301: * basename value.
! 302: *
! 303: * @return A reference to the basename (the return must not be
! 304: * dealloc).
! 305: */
! 306: const char * exarg_basename (char * file_path)
! 307: {
! 308: int iterator = strlen (file_path);
! 309:
! 310: while ((iterator != 0) &&
! 311: (file_path [iterator - 1] != '/') &&
! 312: (file_path [iterator - 1] != '\\')) {
! 313: /* decrease iterator */
! 314: iterator--;
! 315: }
! 316:
! 317: /* return the base name */
! 318: return file_path + iterator;
! 319: }
! 320:
! 321: /**
! 322: * @internal Allows to split the provided string using the provided
! 323: * separators.
! 324: *
! 325: * @param chunk The chunk to split.
! 326: * @param separator_num The number of separators.
! 327: *
! 328: * @return A newly allocated set of strings.
! 329: */
! 330: char ** exarg_split (const char * chunk, int separator_num, ...)
! 331: {
! 332: va_list args;
! 333: char ** separators;
! 334: char ** result;
! 335: int iterator;
! 336: int index;
! 337: int previous_index;
! 338: int count = 0;
! 339: int length = 0;
! 340:
! 341: /* check received values */
! 342: if (chunk == NULL)
! 343: return NULL;
! 344: if (separator_num < 1)
! 345: return NULL;
! 346:
! 347: separators = exarg_new (char *, separator_num + 1);
! 348: iterator = 0;
! 349: va_start (args, separator_num);
! 350:
! 351: /* get all separators to be used */
! 352: while (iterator < separator_num) {
! 353: separators[iterator] = va_arg (args, char *);
! 354: iterator++;
! 355: }
! 356:
! 357: va_end (args);
! 358:
! 359: /* now, count the number of strings that we will get by
! 360: * separating the string into several pieces */
! 361: index = 0;
! 362: while (*(chunk + index) != 0) {
! 363:
! 364: /* reset the iterator */
! 365: iterator = 0;
! 366: while (iterator < separator_num) {
! 367:
! 368: /* compare the current index with the current
! 369: * separator */
! 370: length = strlen (separators[iterator]);
! 371: if (! memcmp (chunk + index, separators[iterator], length)) {
! 372:
! 373: /* update items found */
! 374: count++;
! 375:
! 376: /* update index to skip the item found */
! 377: index += length - 1; /* make the last index to be captured the the -1 */
! 378:
! 379: /* break the loop */
! 380: break;
! 381: }
! 382: iterator++;
! 383: }
! 384:
! 385: /* update the index to the next item */
! 386: index++;
! 387: }
! 388:
! 389: /* create the result that will hold items separated */
! 390: result = exarg_new (char *, count + 2);
! 391:
! 392: /* now copy items found */
! 393: count = 0;
! 394: index = 0;
! 395:
! 396: /* remember previous_index */
! 397: previous_index = index;
! 398: while (*(chunk + index) != 0) {
! 399:
! 400: /* reset the iterator */
! 401: iterator = 0;
! 402: while (iterator < separator_num) {
! 403:
! 404: /* compare the current index with the current
! 405: * separator */
! 406: length = strlen (separators[iterator]);
! 407: if (! memcmp (chunk + index, separators[iterator], length)) {
! 408:
! 409: /* copy the chunk found */
! 410: result[count] = exarg_new (char, index - previous_index + 1);
! 411: memcpy (result[count], chunk + previous_index, index - previous_index);
! 412:
! 413: /* update items found */
! 414: count++;
! 415:
! 416: /* update index to skip the item found */
! 417: if (*(chunk + index + length) == 0) {
! 418: /* in the case no more elements to read will be found */
! 419: /* put an empty space at the end */
! 420: result [count] = exarg_new (char, 1);
! 421:
! 422: exarg_free (separators);
! 423: return result;
! 424: }
! 425:
! 426: /* remember previous_index */
! 427: index += length;
! 428: previous_index = index;
! 429: index--; /* make the last index to be captured the the -1 */
! 430: break;
! 431: }
! 432: iterator++;
! 433: }
! 434:
! 435: /* update the index to the next item */
! 436: index++;
! 437: }
! 438:
! 439: /* check for a last chunk */
! 440: if (index != previous_index) {
! 441: /* copy the chunk found */
! 442: result[count] = exarg_new (char, index - previous_index + 1);
! 443: memcpy (result[count], chunk + previous_index, index - previous_index);
! 444: }
! 445:
! 446:
! 447: /* release memory */
! 448: exarg_free (separators);
! 449:
! 450: return result;
! 451: }
! 452:
! 453: /**
! 454: * @internal Proto-type declaration to avoid gcc complaining.
! 455: */
! 456: int vsnprintf(char *str, size_t size, const char *format, va_list ap);
! 457:
! 458: /**
! 459: * @internal Allows to calculate the amount of memory required to
! 460: * store the string that will representing the construction provided
! 461: * by the printf-like format received and its arguments.
! 462: *
! 463: * @param format The printf-like format to be printed.
! 464: *
! 465: * @param args The set of arguments that the printf applies to.
! 466: *
! 467: * <i><b>NOTE:</b> not all printf specification is supported. Generally, the
! 468: * following is supported: %s, %d, %f, %g, %ld, %lg and all
! 469: * combinations that provides precision, number of items inside the
! 470: * integer part, etc: %6.2f, %+2d, etc. An especial case not supported
! 471: * is %lld, %llu and %llg.</i>
! 472: *
! 473: * @return Return the number of bytes that must be allocated to hold
! 474: * the string (including the string terminator \0). If the format is
! 475: * not correct or it is not properly formated according to the value
! 476: * found at the argument set, the function will return -1.
! 477: */
! 478: int exarg_vprintf_len (const char * format, va_list args)
! 479: {
! 480: /** IMPLEMENTATION NOTE: in the case this code is update,
! 481: * update axl_stream_vprintf_len **/
! 482:
! 483: # if defined (OS_WIN32) && ! defined (__GNUC__)
! 484: # if HAVE_VSCPRINTF
! 485: if (format == NULL)
! 486: return 0;
! 487: return _vscprintf (format, args) + 1;
! 488: # else
! 489: char buffer[8192];
! 490: if (format == NULL)
! 491: return 0;
! 492: return _vsnprintf (buffer, 8191, format, args) + 1;
! 493: # endif
! 494: #else
! 495: /* gnu gcc case */
! 496: if (format == NULL)
! 497: return 0;
! 498: return vsnprintf (NULL, 0, format, args) + 1;
! 499:
! 500: #endif
! 501: }
! 502:
! 503:
! 504:
! 505: /**
! 506: * @internal Allows to produce an string representing the message hold by
! 507: * chunk with the parameters provided.
! 508: *
! 509: * @param chunk The message chunk to print.
! 510: * @param args The arguments for the chunk.
! 511: *
! 512: * @return A newly allocated string.
! 513: */
! 514: char * exarg_strdup_printfv (char * chunk, va_list args)
! 515: {
! 516: /** IMPLEMENTATION NOTE: place update axl_stream_printf_buffer
! 517: * code in the case this code is updated **/
! 518:
! 519: #ifndef HAVE_VASPRINTF
! 520: int size;
! 521: #endif
! 522: char * result = NULL;
! 523: int new_size = -1;
! 524:
! 525: if (chunk == NULL)
! 526: return NULL;
! 527:
! 528: #ifdef HAVE_VASPRINTF
! 529: /* do the operation using the GNU extension */
! 530: new_size = vasprintf (&result, chunk, args);
! 531: #else
! 532: /* get the amount of memory to be allocated */
! 533: size = exarg_vprintf_len (chunk, args);
! 534:
! 535: /* check result */
! 536: if (size == -1) {
! 537: printf ("error: unable to calculate the amount of memory for the strdup_printf operation");
! 538: return NULL;
! 539: } /* end if */
! 540:
! 541: /* allocate memory */
! 542: result = exarg_new (char, size + 2);
! 543:
! 544: /* copy current size */
! 545: #if defined(OS_WIN32) && ! defined (__GNUC__)
! 546: new_size = _vsnprintf_s (result, size + 1, size, chunk, args);
! 547: #else
! 548: new_size = vsnprintf (result, size + 1, chunk, args);
! 549: #endif
! 550: #endif
! 551: /* return the result */
! 552: return result;
! 553: }
! 554:
! 555: /**
! 556: * @internal Implementation that allows to produce dinamically
! 557: * allocated strings using printf-like format.
! 558: *
! 559: * @param chunk The chunk representing the format.
! 560: *
! 561: * @return An dynamically allocated string.
! 562: */
! 563: char * exarg_strdup_printf (char * chunk, ...)
! 564: {
! 565: char * result = NULL;
! 566: va_list args;
! 567:
! 568: /* return a null value if null chunk is received */
! 569: if (chunk == NULL)
! 570: return NULL;
! 571:
! 572: /* open std args */
! 573: va_start (args, chunk);
! 574:
! 575: /* get the string */
! 576: result = exarg_strdup_printfv (chunk, args);
! 577:
! 578: /* close std args */
! 579: va_end (args);
! 580:
! 581: return result;
! 582: }
! 583:
! 584: /**
! 585: * @internal Allows to copy the given chunk, supposing that is a
! 586: * properly format C string that ends with a '\\0' value.
! 587: *
! 588: * This function allows to perform a copy for the given string. If a
! 589: * copy limited by a size is required, use \ref axl_stream_strdup_n.
! 590: *
! 591: * @param chunk The chunk to copy
! 592: *
! 593: * @return A newly allocated string or NULL if fails.
! 594: */
! 595: char * exarg_strdup (char * chunk)
! 596: {
! 597: char * result;
! 598: int length;
! 599:
! 600: /* do not copy if null reference is received */
! 601: if (chunk == NULL)
! 602: return NULL;
! 603:
! 604: length = strlen (chunk);
! 605: result = exarg_new (char, length + 1);
! 606:
! 607: memcpy (result, chunk, length);
! 608:
! 609: return result;
! 610: }
! 611:
! 612: /**
! 613: * @internal Internal function that allows to dealloc the provided array of chunks.
! 614: *
! 615: * @param chunks An array containing pointers to chunks.
! 616: */
! 617: void exarg_freev (char ** chunks)
! 618: {
! 619: int iterator = 0;
! 620:
! 621: /* return if the received reference is null */
! 622: if (chunks == NULL)
! 623: return;
! 624:
! 625: /* release memory used by all elements inside the chunk */
! 626: while (chunks[iterator] != 0) {
! 627: exarg_free (chunks[iterator]);
! 628: iterator++;
! 629: }
! 630:
! 631: /* now release the chunk inside */
! 632: exarg_free (chunks);
! 633:
! 634: /* nothing more to do */
! 635: return;
! 636: }
! 637:
! 638:
! 639: /**
! 640: * @internal Adds the argument to the current argument list.
! 641: *
! 642: * @param argument The argument to add.
! 643: */
! 644: void __exarg_add_argument (char * argument)
! 645: {
! 646: ExArgument * arg;
! 647: ExArgument * arg2;
! 648:
! 649: /* creates the node */
! 650: arg = exarg_new (ExArgument, 1);
! 651: arg->string = argument;
! 652:
! 653: if (params == NULL) {
! 654: /* basic case, only one argument */
! 655: params = arg;
! 656:
! 657: return;
! 658: } /* end if */
! 659:
! 660: /* complex case, lookup for the last node */
! 661: arg2 = params;
! 662: while (arg2->next != NULL)
! 663: arg2 = arg2->next;
! 664:
! 665: /* set the argument on the last position */
! 666: arg2->next = arg;
! 667:
! 668: return;
! 669: }
! 670:
! 671: /**
! 672: * @internal
! 673: * @brief Perfom a look up inside the argument option installed.
! 674: *
! 675: * This function tries to return the ExArgNodeOption using the given
! 676: * value as index key.
! 677: *
! 678: * The given value can represent the long key option or the short
! 679: * form.
! 680: *
! 681: * @param arg_name the key to use on lookup process
! 682: *
! 683: * @return the function retuns the argument option if found or NULL if
! 684: * not.
! 685: */
! 686: ExArgNodeOption * exarg_lookup_node (const char * arg_name)
! 687: {
! 688: ExArgNodeOption * result = NULL;
! 689: int arg_name_len;
! 690:
! 691: /* check for null value */
! 692: if (arg_name == NULL)
! 693: return NULL;
! 694:
! 695: /* get length */
! 696: arg_name_len = strlen (arg_name);
! 697:
! 698: /* look up the item on the current argument option */
! 699: result = argument_options;
! 700: while (result != NULL) {
! 701:
! 702: /* check value with long argument form */
! 703: if (arg_name_len == strlen (result->arg_name) &&
! 704: !memcmp (arg_name, result->arg_name, strlen (arg_name))) {
! 705:
! 706: /* return found node */
! 707: return result;
! 708: }
! 709:
! 710: /* check value with short argument form */
! 711: if ((result->arg_short_name != NULL) &&
! 712: (arg_name_len == strlen (result->arg_short_name)) &&
! 713: !memcmp (arg_name, result->arg_short_name, strlen (arg_name))) {
! 714:
! 715: /* return node found */
! 716: return result;
! 717: }
! 718:
! 719: /* update to the next item */
! 720: result = result->next;
! 721:
! 722: } /* end while */
! 723:
! 724: /* return that we didn't found an item */
! 725: return result;
! 726:
! 727: } /* end exarg_lookup_node */
! 728:
! 729:
! 730:
! 731:
! 732: int exarg_is_argument (char * argument)
! 733: {
! 734:
! 735: int iterator = 1;
! 736:
! 737: /* support standard unix format definition */
! 738: if (CHECK_PARSE_MODE (PARSE_MODE_UNIX) && !memcmp (argument, "--", 2)) {
! 739:
! 740: /* update parse mode */
! 741: UPDATE_PARSE_MODE (PARSE_MODE_UNIX);
! 742: return 1;
! 743: }
! 744:
! 745: /* support sort argument format definition */
! 746: if (CHECK_PARSE_MODE (PARSE_MODE_UNIX) && (strlen (argument) == 2) && (argument[0] == '-')) {
! 747:
! 748: /* update parse mode */
! 749: UPDATE_PARSE_MODE (PARSE_MODE_UNIX);
! 750:
! 751: return 1;
! 752: }
! 753:
! 754: /* support windows argument format */
! 755: if (CHECK_PARSE_MODE (PARSE_MODE_WINDOWS) && (strlen (argument) > 2) && (argument[0] == '/')) {
! 756:
! 757: /* now check if the argument doesn't have more bars */
! 758: while (argument[iterator] != 0) {
! 759: /* check value */
! 760: if (argument[iterator] == '/')
! 761: return 0;
! 762:
! 763: /* update iterator */
! 764: iterator++;
! 765:
! 766: } /* end while */
! 767:
! 768: /* update parse mode */
! 769: UPDATE_PARSE_MODE (PARSE_MODE_WINDOWS);
! 770:
! 771: return 1;
! 772: }
! 773:
! 774: return 0;
! 775: }
! 776:
! 777: char * exarg_get_argument (char * argument)
! 778: {
! 779: /* support getting the argument value for unix standard
! 780: * argument */
! 781: if (!memcmp (argument, "--", 2))
! 782: return &(argument[2]);
! 783:
! 784: /* support getting the argument value for short def */
! 785: if ((strlen (argument) == 2) && (argument[0] == '-'))
! 786: return &(argument[1]);
! 787:
! 788: /* support getting the argument value for windows def */
! 789: if ((strlen (argument) > 2) && (argument[0] == '/'))
! 790: return &(argument[1]);
! 791:
! 792: return NULL;
! 793: }
! 794:
! 795: int exarg_check_help_argument (char * argument)
! 796: {
! 797: if (!memcmp (argument, "help", 4) || !memcmp (argument, "?", 1))
! 798: return 1;
! 799: return 0;
! 800: }
! 801:
! 802: void exarg_wrap_and_print (const char * text, int size_to_wrap, const char * fill_text)
! 803: {
! 804: char ** stringv = NULL;
! 805: int i = 0;
! 806: int sum = 0;
! 807: char * working_line = NULL;
! 808: char * aux_string = NULL;
! 809: int first_line = 1;
! 810:
! 811: /* do not print anything if a null value is received */
! 812: if (text == NULL)
! 813: return;
! 814:
! 815: if (strlen (text) <= size_to_wrap) {
! 816: printf ("%s\n", text);
! 817: return;
! 818: }
! 819:
! 820: stringv = exarg_split (text, 1, " ");
! 821: for (i = 0; stringv[i]; i++) {
! 822: if (working_line) {
! 823: aux_string = working_line;
! 824: working_line = exarg_strdup_printf ("%s %s", working_line, stringv[i]);
! 825: exarg_free (aux_string);
! 826: }else
! 827: working_line = exarg_strdup (stringv[i]);
! 828: sum = sum + strlen (stringv[i]) + 1;
! 829:
! 830: if (sum >= size_to_wrap) {
! 831: sum = 0;
! 832: if (first_line) {
! 833: first_line = 0;
! 834: printf ("%s\n", working_line);
! 835: }else
! 836: printf ("%s%s\n", fill_text, working_line);
! 837: exarg_free (working_line);
! 838: working_line = NULL;
! 839: }
! 840:
! 841: }
! 842: if (sum) {
! 843: printf ("%s%s\n", fill_text, working_line);
! 844: exarg_free (working_line);
! 845: }
! 846: exarg_freev (stringv);
! 847:
! 848:
! 849: return;
! 850: }
! 851:
! 852: void __exarg_show_usage_foreach (epointer key, epointer value, epointer user_data)
! 853: {
! 854: char ** string_aux = (char **) user_data;
! 855: char * str = (* string_aux);
! 856: char * aux = NULL;
! 857: ExArgNodeOption * node = (ExArgNodeOption *) value;
! 858:
! 859: switch (node->type) {
! 860: case EXARG_NONE:
! 861: if (node->arg_short_name)
! 862: (*string_aux) = exarg_strdup_printf (" [-%s|--%s]", node->arg_short_name, node->arg_name);
! 863: else
! 864: (*string_aux) = exarg_strdup_printf (" [--%s]", node->arg_name);
! 865: break;
! 866: case EXARG_INT:
! 867: if (node->arg_short_name)
! 868: (*string_aux) = exarg_strdup_printf (" [-%s <number>|--%s <number>]", node->arg_short_name, node->arg_name);
! 869: else
! 870: (*string_aux) = exarg_strdup_printf (" [--%s <number>]", node->arg_name);
! 871: break;
! 872: case EXARG_STRING:
! 873: if (node->arg_short_name)
! 874: (*string_aux) = exarg_strdup_printf (" [-%s <string>|--%s <string>]", node->arg_short_name, node->arg_name);
! 875: else
! 876: (*string_aux) = exarg_strdup_printf (" [--%s <string>]", node->arg_name);
! 877: break;
! 878: } /* end switch */
! 879:
! 880: if (str != NULL) {
! 881: /* get a reference to previous content */
! 882: aux = (* string_aux);
! 883: (*string_aux) = exarg_strdup_printf ("%s%s", str, (*string_aux));
! 884:
! 885: /* dealloc both pieces that joined are the result */
! 886: exarg_free (str);
! 887: exarg_free (aux);
! 888: }
! 889: return;
! 890: }
! 891:
! 892: void exarg_show_usage (int show_header)
! 893: {
! 894: char * string_aux = NULL;
! 895: ExArgNodeOption * node;
! 896:
! 897: if (show_header && (__exarg_usage_header && (* __exarg_usage_header)))
! 898: printf (__exarg_usage_header);
! 899:
! 900: printf ("Usage: %s ", exarg_exec_name);
! 901:
! 902: /* get the first node */
! 903: node = argument_options;
! 904: while (node != NULL) {
! 905: /* call to the foreach function */
! 906: __exarg_show_usage_foreach ((epointer) node->arg_name, node, &string_aux);
! 907:
! 908: /* update to the next */
! 909: node = node->next;
! 910:
! 911: } /* end while */
! 912:
! 913: exarg_wrap_and_print (string_aux, 55, " ");
! 914: printf ("\n");
! 915:
! 916: /* free string created */
! 917: exarg_free (string_aux);
! 918:
! 919: if (show_header && (__exarg_post_usage_header && (* __exarg_post_usage_header)))
! 920: printf (__exarg_post_usage_header);
! 921:
! 922: return;
! 923: }
! 924:
! 925: char * __exarg_build_dep_string (ExArgNodeOption * node, int exclude)
! 926: {
! 927: char * result;
! 928: char * aux;
! 929: ExArgDependency * dep;
! 930:
! 931: /* check node dependency */
! 932: if (!exclude && ! node->depends)
! 933: return NULL;
! 934: if (exclude && ! node->excludes)
! 935: return NULL;
! 936:
! 937: if (exclude)
! 938: result = exarg_strdup ("[excludes: ");
! 939: else
! 940: result = exarg_strdup ("[depends on: ");
! 941:
! 942: /* foreach each dependency configured */
! 943: if (exclude)
! 944: dep = node->excludes;
! 945: else
! 946: dep = node->depends;
! 947: while (dep != NULL) {
! 948:
! 949: aux = result;
! 950: if (dep->next != NULL)
! 951: result = exarg_strdup_printf ("%s --%s", result, dep->node->arg_name);
! 952: else
! 953: result = exarg_strdup_printf ("%s --%s]", result, dep->node->arg_name);
! 954: exarg_free (aux);
! 955:
! 956: /* get next dependency */
! 957: dep = dep->next;
! 958:
! 959: } /* end while */
! 960:
! 961: /* return string created */
! 962: return result;
! 963: }
! 964:
! 965: void __exarg_show_help_foreach (epointer key, epointer value, epointer user_data)
! 966: {
! 967: ExArgNodeOption * node = (ExArgNodeOption *) value;
! 968: char * dep;
! 969: int chars = 35;
! 970: int iterator = 0;
! 971:
! 972: /* print argument help */
! 973: if (node->arg_short_name) {
! 974: printf (" -%s, --%-18s ",
! 975: node->arg_short_name, node->arg_name);
! 976: exarg_wrap_and_print (node->description, 40, " ");
! 977:
! 978: }else {
! 979: printf (" --%-22s ", node->arg_name);
! 980: exarg_wrap_and_print (node->description, 40, " ");
! 981: }
! 982:
! 983: /* print argument dependency */
! 984: dep = __exarg_build_dep_string (node, 0);
! 985: if (dep != NULL) {
! 986: /* write spaces */
! 987: while (iterator < chars) {
! 988: printf (" ");
! 989: iterator++;
! 990: }
! 991: exarg_wrap_and_print (dep, 40, " ");
! 992: }
! 993: exarg_free (dep);
! 994:
! 995: /* print argument exclusion */
! 996: iterator = 0;
! 997: dep = __exarg_build_dep_string (node, 1);
! 998: if (dep != NULL) {
! 999: /* write spaces */
! 1000: while (iterator < chars) {
! 1001: printf (" ");
! 1002: iterator++;
! 1003: }
! 1004: exarg_wrap_and_print (dep, 40, " ");
! 1005: }
! 1006: exarg_free (dep);
! 1007: return;
! 1008: }
! 1009:
! 1010: void exarg_show_help ()
! 1011: {
! 1012: ExArgNodeOption * node;
! 1013:
! 1014: if (__exarg_help_header && (* __exarg_help_header))
! 1015: printf (__exarg_help_header);
! 1016:
! 1017: exarg_show_usage (0);
! 1018:
! 1019: printf ("\nCommand options:\n");
! 1020:
! 1021: /* get first node */
! 1022: node = argument_options;
! 1023: while (node != NULL) {
! 1024: /* call to show the node information */
! 1025: __exarg_show_help_foreach ((epointer) node->arg_name, node, NULL);
! 1026:
! 1027: /* update to the next node */
! 1028: node = node->next;
! 1029: } /* end while */
! 1030:
! 1031: printf ("\nHelp options:\n");
! 1032: printf (" -?, --help Show this help message.\n");
! 1033: printf (" --usage Display brief usage message.\n");
! 1034:
! 1035: if (__exarg_post_help_header && (* __exarg_post_help_header))
! 1036: printf (__exarg_post_help_header);
! 1037:
! 1038: return;
! 1039: }
! 1040:
! 1041: void exarg_check_argument_value (char ** argv, int iterator)
! 1042: {
! 1043:
! 1044: if (argv[iterator] == NULL) {
! 1045: printf ("error: not defined value for argument: %s, exiting..",
! 1046: argv[iterator - 1]);
! 1047: fflush (stdout);
! 1048: exit (-1);
! 1049: }
! 1050:
! 1051: if (exarg_is_argument (argv[iterator])) {
! 1052: printf ("error: not defined value for argument: %s, instead found another argument: %s, exiting..",
! 1053: argv[iterator - 1],
! 1054: argv[iterator]);
! 1055: fflush (stdout);
! 1056: exit (-1);
! 1057: }
! 1058:
! 1059: return;
! 1060: }
! 1061:
! 1062:
! 1063: void __exarg_parse_check_non_optional ()
! 1064: {
! 1065: ExArgNodeOption * node = argument_options;
! 1066:
! 1067: /* for each node */
! 1068: while (node != NULL) {
! 1069: /* check the node */
! 1070: if (! node->is_optional && ! node->is_defined) {
! 1071: exarg_msg ("error: argument '%s' is not defined, but it is required for a proper function..\n",
! 1072: node->arg_name);
! 1073: } /* end if */
! 1074:
! 1075: /* get the next */
! 1076: node = node->next;
! 1077:
! 1078: } /* end while */
! 1079:
! 1080: return;
! 1081: }
! 1082:
! 1083: void __exarg_parse_check_depends ()
! 1084: {
! 1085: /* first argument */
! 1086: ExArgNodeOption * node = argument_options;
! 1087: ExArgDependency * dep;
! 1088:
! 1089: /* for each argument defined */
! 1090: while (node != NULL) {
! 1091:
! 1092: /* check if the argument was defined, and hence
! 1093: * activates its dependencies */
! 1094: if (! node->is_defined) {
! 1095: node = node->next;
! 1096: continue;
! 1097: }
! 1098:
! 1099: /* check depends */
! 1100: dep = node->depends;
! 1101: while (dep != NULL) {
! 1102:
! 1103: /* check that the dependency is defined */
! 1104: if (! dep->node->is_defined) {
! 1105: exarg_msg ("You must define argument (--%s) if used (--%s). Try %s --help.",
! 1106: dep->node->arg_name, node->arg_name, exarg_exec_name);
! 1107: return;
! 1108: } /* end if */
! 1109:
! 1110: /* get next dependency */
! 1111: dep = dep->next;
! 1112:
! 1113: } /* end while */
! 1114:
! 1115: /* check depends */
! 1116: dep = node->excludes;
! 1117: while (dep != NULL) {
! 1118:
! 1119: /* check that the dependency is defined */
! 1120: if (dep->node->is_defined) {
! 1121: printf ("You can't define argument (--%s) if used (--%s). Try %s --help.\n",
! 1122: node->arg_name, dep->node->arg_name, exarg_exec_name);
! 1123: fflush (stdout);
! 1124: return;
! 1125: } /* end if */
! 1126:
! 1127: /* get next dependency */
! 1128: dep = dep->next;
! 1129:
! 1130: } /* end while */
! 1131:
! 1132: /* get next node */
! 1133: node = node->next;
! 1134:
! 1135: } /* end whle */
! 1136:
! 1137: /* nothing more to check */
! 1138: return;
! 1139: }
! 1140:
! 1141:
! 1142: /**
! 1143: * \brief Makes exarg to start parsing argument options.
! 1144: *
! 1145: * Makes LibExArg to start command line parsing by using arguments
! 1146: * installed.
! 1147: *
! 1148: * Once this functions is called it is posible to call the set of
! 1149: * function which returns data obtained: \ref exarg_is_defined,
! 1150: * \ref exarg_get_int, \ref exarg_get_string and \ref exarg_get_params.
! 1151: *
! 1152: * The advantage is that LibExArg allows you to get access to command
! 1153: * line data from any point of your program.
! 1154: *
! 1155: * @param argc the argc value the current application have received.
! 1156: * @param argv the argv value the current application have received.
! 1157: */
! 1158: void exarg_parse (int argc,
! 1159: char ** argv)
! 1160: {
! 1161: int iterator = 1;
! 1162: ExArgNodeOption * node;
! 1163: char * argument;
! 1164:
! 1165: /* check how many argument have been defined */
! 1166: if (iterator == argc) {
! 1167: /* once terminated, check if the non optional options
! 1168: * were defined */
! 1169:
! 1170: __exarg_parse_check_non_optional ();
! 1171: return;
! 1172: }
! 1173:
! 1174: exarg_exec_name = exarg_basename (argv[0]);
! 1175:
! 1176: /* iterate over all arguments */
! 1177: while (iterator < argc) {
! 1178:
! 1179: if (!exarg_is_argument (argv[iterator])) {
! 1180: /* check free argument configuration */
! 1181: if (__exarg_disable_free_args) {
! 1182: exarg_msg ("error: provided a free argument='%s', not listed in the accept command line option", argv[iterator]);
! 1183:
! 1184: } /* end if */
! 1185:
! 1186: /* save and increase iterator */
! 1187: __exarg_add_argument (argv[iterator]);
! 1188: iterator++;
! 1189: continue;
! 1190: }
! 1191:
! 1192: /* get clean argument */
! 1193: argument = exarg_get_argument (argv[iterator]);
! 1194:
! 1195: /* check for help argument */
! 1196: if (exarg_check_help_argument (argument)){
! 1197: exarg_show_help ();
! 1198: exarg_end ();
! 1199: exit (0);
! 1200: }
! 1201:
! 1202: /* check for usage argument */
! 1203: if (!memcmp (argument, "usage", 5)) {
! 1204: exarg_show_usage (1);
! 1205: exarg_end ();
! 1206: exit (0);
! 1207: }
! 1208:
! 1209: /* get node argument */
! 1210: node = exarg_lookup_node (argument);
! 1211: if (node == NULL) {
! 1212: exarg_msg ("%s error: argument not found: %s, try: %s --help\n",
! 1213: exarg_exec_name, argv[iterator], exarg_exec_name);
! 1214: }
! 1215:
! 1216: /* check if node is defined */
! 1217: if (node->is_defined) {
! 1218: exarg_msg ("%s error: argument %s already defined, exiting..\n",
! 1219: exarg_exec_name, argv[iterator]);
! 1220: }
! 1221:
! 1222:
! 1223: /* set this argument to be defined */
! 1224: node->is_defined = 1;
! 1225: switch (node->type) {
! 1226: case EXARG_NONE:
! 1227: /* nothing to do */
! 1228: break;
! 1229: case EXARG_INT:
! 1230: /* save int value */
! 1231: iterator++;
! 1232:
! 1233: exarg_check_argument_value (argv, iterator);
! 1234:
! 1235: node->int_value = atoi (argv[iterator]);
! 1236: break;
! 1237: case EXARG_STRING:
! 1238: iterator++;
! 1239:
! 1240: exarg_check_argument_value (argv, iterator);
! 1241:
! 1242: node->string_value = argv[iterator];
! 1243:
! 1244: break;
! 1245: }
! 1246:
! 1247: /* update iterator */
! 1248: iterator++;
! 1249: }
! 1250:
! 1251: /* once terminated, check if the non optional options were
! 1252: * defined */
! 1253: __exarg_parse_check_non_optional ();
! 1254:
! 1255: /* check argument dependency and argument mutual exclusion. */
! 1256: __exarg_parse_check_depends ();
! 1257:
! 1258: return;
! 1259: }
! 1260:
! 1261: void __exarg_end_free_dep (ExArgDependency * dep)
! 1262: {
! 1263: ExArgDependency * next;
! 1264:
! 1265: /* foreach dependency established */
! 1266: while (dep != NULL) {
! 1267:
! 1268: /* free the dep node */
! 1269: next = dep->next;
! 1270: exarg_free (dep);
! 1271: dep = next;
! 1272: } /* end while */
! 1273:
! 1274: return;
! 1275: }
! 1276:
! 1277: /**
! 1278: * \brief Ends exarg library execution.
! 1279: *
! 1280: * Terminates the exarg function. This function will free all
! 1281: * resources allocated so the library cannot be used any more for the
! 1282: * current execution.
! 1283: *
! 1284: * This function is reatrant. Several threads can actually call this
! 1285: * function. It will take care about making only one thread to
! 1286: * actually free resources.
! 1287: **/
! 1288: void exarg_end ()
! 1289: {
! 1290: ExArgNodeOption * node;
! 1291: ExArgNodeOption * node2;
! 1292:
! 1293: ExArgument * params2;
! 1294:
! 1295:
! 1296: if (argument_options != NULL) {
! 1297: /* get a reference to the table, and dealloc it */
! 1298: node = argument_options;
! 1299: argument_options = NULL;
! 1300:
! 1301: while (node != NULL) {
! 1302: /* get a reference to the next */
! 1303: node2 = node->next;
! 1304:
! 1305: /* free node arguments dependencies and mutual
! 1306: * exclusions */
! 1307: __exarg_end_free_dep (node->depends);
! 1308: __exarg_end_free_dep (node->excludes);
! 1309:
! 1310: /* free current node */
! 1311: exarg_free (node);
! 1312:
! 1313: /* update the node ref */
! 1314: node = node2;
! 1315: } /* end while */
! 1316:
! 1317: } /* end if */
! 1318:
! 1319: if (params != NULL) {
! 1320: while (params != NULL) {
! 1321: /* get a reference to the next node */
! 1322: params2 = params->next;
! 1323:
! 1324: /* free params node */
! 1325: exarg_free (params);
! 1326:
! 1327: /* configure the next argument to dealloc */
! 1328: params = params2;
! 1329: } /* end while */
! 1330: } /* end if */
! 1331:
! 1332: return;
! 1333: }
! 1334:
! 1335: /**
! 1336: * \brief Disable autohelp.
! 1337: *
! 1338: * Allows to disable auto help and --help and -? option
! 1339: * recognition. This is useful if you don't want your program to
! 1340: * accept --help and --usage options.
! 1341: **/
! 1342: void exarg_disable_help ()
! 1343: {
! 1344: return;
! 1345: }
! 1346:
! 1347: /**
! 1348: * \brief Adds user defined header to automatic usage command generated.
! 1349: *
! 1350: * Once a program is linked to libexarg is able to produce a usage
! 1351: * help by accepting the --usage command line option. But that usage
! 1352: * help is showed as is. This function allows you to define a header
! 1353: * to be showed preceding the usage info. You can use this, for
! 1354: * example, to introduce your copyright.
! 1355: *
! 1356: * This function doesn't make a copy of the given string so you
! 1357: * must not free the header provided or use an static string.
! 1358: **/
! 1359: void exarg_add_usage_header (char * header)
! 1360: {
! 1361: __exarg_usage_header = header;
! 1362: }
! 1363:
! 1364: /**
! 1365: * \brief Adds user defined header to automatic help command generated.
! 1366: *
! 1367: * Once a program is linked to libexarg is able to produce a help by
! 1368: * accepting the --help or -? command line option. But that help is
! 1369: * showed as is. This function allows you to define a header to be
! 1370: * showed preceding the help info. You can use this, for example, to
! 1371: * introduce your copyright.
! 1372: *
! 1373: * This function doesn't make a copy of the given string so you
! 1374: * must not free the header provided or use an static string.
! 1375: **/
! 1376: void exarg_add_help_header (char * header)
! 1377: {
! 1378: __exarg_help_header = header;
! 1379: }
! 1380:
! 1381: /**
! 1382: * \brief Adds user defined post header for usage command.
! 1383: *
! 1384: * This function works pretty much like \ref exarg_add_usage_header but
! 1385: * adding the header provided to be appended at the end of the usage
! 1386: * automatically generated.
! 1387: **/
! 1388: void exarg_post_usage_header (char * post_header)
! 1389: {
! 1390: __exarg_post_usage_header = post_header;
! 1391: }
! 1392:
! 1393: /**
! 1394: * \brief Adds user defined post header for help command.
! 1395: *
! 1396: * This function works pretty much like \ref exarg_add_help_header but
! 1397: * adding the header provided to be appended at the end of the help
! 1398: * automatically generated.
! 1399: **/
! 1400: void exarg_post_help_header (char * post_header)
! 1401: {
! 1402: __exarg_post_help_header = post_header;
! 1403: }
! 1404:
! 1405: /**
! 1406: * \internal
! 1407: * Internal ExArg function. This function allows \ref exarg_install_arg to
! 1408: * check if there are already installed an short argument as the one
! 1409: * been installed.
! 1410: **/
! 1411: void __exarg_check_short_arg (epointer key, epointer value, epointer user_data)
! 1412: {
! 1413: ExArgNodeOption * node = (ExArgNodeOption *) value;
! 1414: char * arg_to_check = (char *) user_data;
! 1415:
! 1416: if (node->arg_short_name != NULL) {
! 1417: if (!memcmp (node->arg_short_name, arg_to_check, strlen (arg_to_check))) {
! 1418: exarg_msg ("error: found that short arg installed is already found: %s\n", arg_to_check);
! 1419: } /* end if */
! 1420: } /* end if */
! 1421:
! 1422: return;
! 1423: }
! 1424:
! 1425: /**
! 1426: * \brief Installs a new command line to be accepted.
! 1427: *
! 1428: * This functions allows you to install new arguments to be
! 1429: * accepted. Every argument passed in to the program which is not
! 1430: * installed throught this function will no be accepted and will
! 1431: * generate a non recognized command line error.
! 1432: *
! 1433: * Let's see an example on how to use exarg to install the --version
! 1434: * argument. You should call exarg as follows:
! 1435: *
! 1436: * \code
! 1437: * exarg_install_arg ("version", "v", EXARG_NONE,
! 1438: * "show program version");
! 1439: *
! 1440: * \endcode
! 1441: *
! 1442: * Previous line have installed a argument called "version" which will
! 1443: * be invoked by the user as --version. The short alias
! 1444: * in this case is "v" which as we have see will allow user to invoke
! 1445: * your program as -v.
! 1446: *
! 1447: * Because you could install arguments which may conflict, this
! 1448: * function will abort the program execution on that case. This will
! 1449: * ensure you, as programer, to have a binary compiled with no
! 1450: * problems due to exarg.
! 1451: *
! 1452: * Later on, you can use \ref exarg_is_defined to check the status of
! 1453: * installed arguments. Once you install an argument the user may
! 1454: * invoke it and you could check that status using previous
! 1455: * function. Because the "version" argument type is \ref EXARG_NONE you can
! 1456: * only use \ref exarg_is_defined. But, for other argument types as
! 1457: * \ref EXARG_STRING, you can also use \ref exarg_get_string function to get the
! 1458: * value defined by user. Let's see an example.
! 1459: *
! 1460: * \code
! 1461: * exarg_install_arg ("load-library", "l", EXARG_STRING,
! 1462: * "loads the library defined as argument");
! 1463: * \endcode
! 1464: *
! 1465: * This previous line will allow user to invoke your program as
! 1466: * --load-library path/to/lib. Then you can use \ref exarg_get_string to get
! 1467: * the path/to/lib value by using:
! 1468: *
! 1469: * \code
! 1470: * // check user have defined this argument
! 1471: * if (exarg_is_defined ("load-library")) {
! 1472: *
! 1473: * arg_value = exarg_get_string ("load-library");
! 1474: *
! 1475: * printf ("The library defined by user was: %s\n",
! 1476: * arg_value);
! 1477: * }
! 1478: *
! 1479: * \endcode
! 1480: *
! 1481: * You must install all argument before calling \ref exarg_parse. That function
! 1482: * will parse argument options by using installed arguments. Check the info
! 1483: * about that function.
! 1484: *
! 1485: * ExArg is not thread-safe which doesn't means anything wrong but you
! 1486: * must call all exarg function from the same thread to get the right
! 1487: * results.
! 1488: *
! 1489: * This function will not do a copy from arg_name, arg_short_name or
! 1490: * description. This means you should not free that values while
! 1491: * using exarg. To end exarg using check \ref exarg_end. It is recomended to use
! 1492: * static values and shows on previous examples.
! 1493: **/
! 1494: void exarg_install_arg (const char * arg_name,
! 1495: const char * arg_short_name,
! 1496: ExArgType type,
! 1497: const char * description)
! 1498: {
! 1499: ExArgNodeOption * node;
! 1500: ExArgNodeOption * node2;
! 1501:
! 1502: /* init hash table */
! 1503: if (argument_options != NULL) {
! 1504: /* check if there are an argument with the same name */
! 1505: if (exarg_lookup_node (arg_name)) {
! 1506: exarg_end ();
! 1507: exarg_msg ("error: argument being installed is already defined: %s..",
! 1508: arg_name);
! 1509: }
! 1510:
! 1511: /* check if there are an shor argument with the same
! 1512: * name */
! 1513: if (arg_short_name != NULL) {
! 1514: node = argument_options;
! 1515:
! 1516: /* while there are options to process */
! 1517: while (node != NULL) {
! 1518: /* call to check */
! 1519: __exarg_check_short_arg ((epointer) node->arg_name, node, (epointer) arg_short_name);
! 1520:
! 1521: /* update to the next */
! 1522: node = node->next;
! 1523: } /* end while */
! 1524: } /* end if */
! 1525: } /* end if */
! 1526:
! 1527: /* create node option */
! 1528: node = exarg_new (ExArgNodeOption, 1);
! 1529: node->arg_name = arg_name;
! 1530: node->arg_short_name = arg_short_name;
! 1531: node->type = type;
! 1532: node->description = description;
! 1533: node->is_optional = 1;
! 1534:
! 1535: /* lookup for the last position */
! 1536: if (argument_options == NULL)
! 1537: argument_options = node;
! 1538: else {
! 1539: /* lookup for the last */
! 1540: node2 = argument_options;
! 1541: while (node2->next != NULL)
! 1542: node2 = node2->next;
! 1543:
! 1544: /* set it */
! 1545: node2->next = node;
! 1546: } /* end if */
! 1547:
! 1548: return;
! 1549: }
! 1550:
! 1551: /**
! 1552: * \brief Installs several command lines to be accepted.
! 1553: *
! 1554: * This function does the same that \ref exarg_install_arg but making
! 1555: * group of argument to be installed in one step.
! 1556: *
! 1557: * Think about installing two argument. To install them we have to do
! 1558: * the following:
! 1559: *
! 1560: * \code
! 1561: * exarg_install_arg ("version", "v",
! 1562: * EXARG_NONE, "show argument version");
! 1563: * exarg_install_arg ("load-library", "l",
! 1564: * EXARG_STRING, "load my library");
! 1565: * \endcode
! 1566: *
! 1567: * Because some people doesn't like to perform several calls to the
! 1568: * same funcion the previous code can be done by using one step as:
! 1569: *
! 1570: * \code
! 1571: * exarg_install_argv (2, "version", "v", EXARG_NONE,
! 1572: * "show argument version",
! 1573: * "load-library", "l",
! 1574: * EXARG_STRING, "load my library");
! 1575: * \endcode
! 1576: *
! 1577: * When you install argument this way you have to specify how many
! 1578: * argument is going to be installed. In this case that number is
! 1579: * 2. This allows exarg to know how many arguments needs to search
! 1580: * inside the argv. If something is wrong while specifying the number
! 1581: * or argument or the argument information itself you'll get a
! 1582: * segmentation fault or something similar.
! 1583: *
! 1584: * While calling to \ref exarg_install_arg the short_name argument can be
! 1585: * optional. This is *NOT* applied to this function. If you don't want
! 1586: * to define a short argument name you must use NULL as value.
! 1587: *
! 1588: * @param num_arg Must be at least 1 or error will happen and library will abort
! 1589: * application execution.
! 1590: **/
! 1591: void exarg_install_argv (int num_arg, ...)
! 1592: {
! 1593: va_list args;
! 1594: int iterator;
! 1595: char * arg_name;
! 1596: char * arg_short_name;
! 1597: ExArgType type;
! 1598: char * description;
! 1599:
! 1600: if (num_arg <= 0) {
! 1601: exarg_end ();
! 1602: exarg_msg ("error: calling to exarg_install_argv with num_arg equal or less to 0..");
! 1603: }
! 1604:
! 1605: va_start (args, num_arg);
! 1606:
! 1607: for (iterator = 0; iterator < num_arg; iterator++) {
! 1608:
! 1609: /* get the argument info */
! 1610: arg_name = va_arg (args, char *);
! 1611: arg_short_name = va_arg (args, char *);
! 1612: type = va_arg (args, ExArgType);
! 1613: description = va_arg (args, char *);
! 1614:
! 1615: exarg_install_arg (arg_name, arg_short_name, type, description);
! 1616: }
! 1617: va_end (args);
! 1618: return;
! 1619: }
! 1620:
! 1621: /**
! 1622: * @brief Allows to define a parameter dependency between the to
! 1623: * arguments defined. The kind of dependency has direction. This means
! 1624: * that the first argument will depend on the second argument, forcing
! 1625: * the user to define the second argument if the first one is defined.
! 1626: *
! 1627: * You can call to this function several times making the first
! 1628: * argument to depend on any number of argument defined. You must not
! 1629: * call to establish a dependency to the argument itself.
! 1630: *
! 1631: * @param arg_name The argument that will be configured with an
! 1632: * argument dependency.
! 1633: *
! 1634: * @param arg_dependency The argument that will receive the
! 1635: * dependency.
! 1636: *
! 1637: *
! 1638: */
! 1639: void exarg_add_dependency (const char * arg_name,
! 1640: const char * arg_dependency)
! 1641: {
! 1642: ExArgNodeOption * node;
! 1643: ExArgNodeOption * node2;
! 1644: ExArgDependency * dep;
! 1645: /* check arguments received */
! 1646: if (arg_name == NULL)
! 1647: return;
! 1648: if (arg_dependency == NULL)
! 1649: return;
! 1650:
! 1651: /* check that both arguments aren't equal */
! 1652: if (strlen (arg_name) == strlen (arg_dependency) &&
! 1653: !memcmp (arg_name, arg_dependency, strlen (arg_name))) {
! 1654: exarg_msg ("error: defined argument dependency with an argument itself.");
! 1655: return;
! 1656: }
! 1657:
! 1658: /* locates the argument node */
! 1659: node = exarg_lookup_node (arg_name);
! 1660: if (node == NULL) {
! 1661: exarg_msg ("error: you did especify an argument that doesn't exists (%s)", arg_name);
! 1662: return;
! 1663: }
! 1664:
! 1665: /* locates dependecy argument node */
! 1666: node2 = exarg_lookup_node (arg_dependency);
! 1667: if (node2 == NULL) {
! 1668: exarg_msg ("error: you did especify an argument that doesn't exists (%s)", arg_dependency);
! 1669: return;
! 1670: }
! 1671:
! 1672: /* make the first argument to depend on the second */
! 1673: dep = node->depends;
! 1674:
! 1675: /* create the new dependency node */
! 1676: node->depends = exarg_new (ExArgDependency, 1);
! 1677: node->depends->node = node2;
! 1678: node->depends->next = dep;
! 1679:
! 1680: return;
! 1681: }
! 1682:
! 1683: /**
! 1684: * @brief Allows to configure arguments that are mutually
! 1685: * excluyents. This function will take the first arguments to be
! 1686: * muatually excluyen with the second one without direction as it
! 1687: * happens with \ref exarg_add_dependency function.
! 1688: *
! 1689: * Once defined both arguments provided can't be defined at the same
! 1690: * time at the command line options.
! 1691: *
! 1692: * @param arg_name The first argument to make mutual exclusion with
! 1693: * the second argument.
! 1694: *
! 1695: * @param arg_excluded Second argument to make mutual exclusion with
! 1696: * the first argument.
! 1697: */
! 1698: void exarg_add_exclusion (const char * arg_name,
! 1699: const char * arg_excluded)
! 1700: {
! 1701: ExArgNodeOption * node;
! 1702: ExArgNodeOption * node2;
! 1703: ExArgDependency * dep;
! 1704:
! 1705: /* check arguments received */
! 1706: if (arg_name == NULL)
! 1707: return;
! 1708:
! 1709: if (arg_excluded == NULL)
! 1710: return;
! 1711:
! 1712: /* check that both arguments aren't equal */
! 1713: if (strlen (arg_name) == strlen (arg_excluded) &&
! 1714: !memcmp (arg_name, arg_excluded, strlen (arg_name))) {
! 1715: exarg_msg ("error: defined argument dependency with an argument itself.");
! 1716: return;
! 1717: }
! 1718:
! 1719: /* locates the argument node */
! 1720: node = exarg_lookup_node (arg_name);
! 1721: if (node == NULL) {
! 1722: exarg_msg ("error: you did especify an argument that doesn't exists (%s)", arg_name);
! 1723: return;
! 1724: }
! 1725:
! 1726: /* locates dependecy argument node */
! 1727: node2 = exarg_lookup_node (arg_excluded);
! 1728: if (node2 == NULL) {
! 1729: exarg_msg ("error: you did especify an argument that doesn't exists (%s)", arg_excluded);
! 1730: return;
! 1731: }
! 1732:
! 1733: /* make the first argument to depend on the second */
! 1734: dep = node->excludes;
! 1735:
! 1736: /* create the new dependency node */
! 1737: node->excludes = exarg_new (ExArgDependency, 1);
! 1738: node->excludes->node = node2;
! 1739: node->excludes->next = dep;
! 1740:
! 1741: return;
! 1742: }
! 1743:
! 1744:
! 1745: /**
! 1746: * @brief Makes an argument installed to be obligatory (not optional
! 1747: * at the user command line input).
! 1748: *
! 1749: * Once called \ref exarg_install_arg, you can use this function to
! 1750: * make the program to make the option obligatory.
! 1751: *
! 1752: * @param arg_name The argument to make it obligatory.
! 1753: */
! 1754: void exarg_set_obligatory (char * arg_name)
! 1755: {
! 1756: ExArgNodeOption * node;
! 1757:
! 1758: /* perform some environment checks */
! 1759: if (arg_name == NULL)
! 1760: return;
! 1761:
! 1762: node = exarg_lookup_node (arg_name);
! 1763: if (node == NULL) {
! 1764: return;
! 1765: }
! 1766:
! 1767: /* make it to be defined */
! 1768: node->is_optional = 0;
! 1769:
! 1770: return;
! 1771: }
! 1772:
! 1773:
! 1774: /**
! 1775: * @brief Allows to configure exarg library to accept or not free
! 1776: * arguments.
! 1777: *
! 1778: * Free arguments are optional parameters provided to the application,
! 1779: * such files, which aren't associated to a particular option.
! 1780: *
! 1781: * If your command line application do not uses free arguments, you
! 1782: * can use this function to enable exarg library to show an error
! 1783: * message to the user:
! 1784: *
! 1785: * \code
! 1786: * // disable free arguments
! 1787: * exarg_accept_free_args (0);
! 1788: * \endcode
! 1789: *
! 1790: * @param accept 1 to accept free arguments. It is the default value,
! 1791: * so it is not required to enable it. 0 to disable free arguments.
! 1792: */
! 1793: void exarg_accept_free_args (int accept)
! 1794: {
! 1795: /* configure free arguments */
! 1796: __exarg_disable_free_args = (accept == 0);
! 1797:
! 1798: return;
! 1799: }
! 1800:
! 1801: /**
! 1802: * @brief Allows to simulate user defined command line options alread
! 1803: * installed by \ref exarg_install_arg, without requiring the user to
! 1804: * set those values.
! 1805: *
! 1806: * This function allows to install values received or to just define
! 1807: * the argument to be supported by the program, without requiring the
! 1808: * user to provide such option. This is a convenient to make some
! 1809: * options to be default, writting your application relying on
! 1810: * arguments defined by command line.
! 1811: *
! 1812: * The function won't define the argument if not installed
! 1813: * previously. If the argument isn't found, the function takes no
! 1814: * action.
! 1815: *
! 1816: * @param arg_name The argument o define as provided by the user.
! 1817: * @param value The value to be associated to the argument. Some
! 1818: * arguments doesn't require this paremeters (\ref EXARG_NONE), so,
! 1819: * you can provide NULL to this parameter.
! 1820: */
! 1821: void exarg_define (char * arg_name,
! 1822: char * value)
! 1823: {
! 1824: ExArgNodeOption * node;
! 1825:
! 1826: /* perform some environment checks */
! 1827: if (arg_name == NULL)
! 1828: return;
! 1829:
! 1830: node = exarg_lookup_node (arg_name);
! 1831: if (node == NULL) {
! 1832: return;
! 1833: }
! 1834: /* make it to be defined */
! 1835: node->is_defined = 1;
! 1836:
! 1837: /* check argument value */
! 1838: if (value != NULL) {
! 1839: switch (node->type) {
! 1840: case EXARG_NONE:
! 1841: /* nothing to set */
! 1842: break;
! 1843: case EXARG_INT:
! 1844: /* integer value */
! 1845: node->int_value = strtol (value, NULL, 10);
! 1846: break;
! 1847: case EXARG_STRING:
! 1848: /* string value */
! 1849: node->string_value = value;
! 1850: break;
! 1851: }
! 1852: } /* end if */
! 1853:
! 1854: /* nothing to do over here */
! 1855: return;
! 1856: }
! 1857:
! 1858: /**
! 1859: * \brief Allows to check if a user have defined a command.
! 1860: *
! 1861: * Once an argument is installed the user may or may not define it. To
! 1862: * define it simply means to use this argument as command line
! 1863: * option. This function allows to check if an argument was used for
! 1864: * the current command line option.
! 1865: *
! 1866: * This function is expecting to receive the argument name to lookup
! 1867: * not the short name. User may be using the short name to invoke the
! 1868: * argument but the lookup is allways done by using the argument name.
! 1869: *
! 1870: * \return TRUE if argument was defined or FALSE if not.
! 1871: **/
! 1872: int exarg_is_defined (char * arg_name)
! 1873: {
! 1874: ExArgNodeOption * node;
! 1875:
! 1876: /* perform some environment checks */
! 1877: if (arg_name == NULL)
! 1878: return 0;
! 1879:
! 1880: if (argument_options == NULL)
! 1881: return 0;
! 1882:
! 1883: node = exarg_lookup_node (arg_name);
! 1884: if (node == NULL) {
! 1885: return 0;
! 1886: }
! 1887: return node->is_defined;
! 1888: }
! 1889:
! 1890: /**
! 1891: * @brief Allows to check several values to be defined at the same time.
! 1892: *
! 1893: * This allows to check if several command line options have been
! 1894: * defined at the same time.
! 1895: * Example:
! 1896: * \code
! 1897: * if (exarg_is_definedv ("param1", "param2", NULL)) {
! 1898: * //param1 and param2 have been defined by the user
! 1899: * }
! 1900: * \endcode
! 1901: *
! 1902: * This is a short way for actually doing:
! 1903: * \code
! 1904: * if (exarg_is_defined ("param1") && exarg_is_defined ("param2")) {
! 1905: * // param1 and para2 have been defined by the user
! 1906: * }
! 1907: * \endcode
! 1908: *
! 1909: * Do not forget to pass a NULL value for the last item.
! 1910: *
! 1911: * @return TRUE if all values are defined, otherwise FALSE.
! 1912: */
! 1913: int exarg_is_definedv (char * first_value, ...)
! 1914: {
! 1915: int result = 1;
! 1916: char * string_value;
! 1917: va_list args;
! 1918:
! 1919: if (first_value == NULL)
! 1920: return 0;
! 1921:
! 1922: /* check first value */
! 1923: if (!exarg_is_defined (first_value))
! 1924: return 0;
! 1925:
! 1926: /* open stdargs */
! 1927: va_start (args, first_value);
! 1928: string_value = va_arg (args, char *);
! 1929:
! 1930: /* check for last NULL value */
! 1931: while ((string_value != NULL) && (* string_value)) {
! 1932: /* check next value */
! 1933: result = result && exarg_is_defined (string_value);
! 1934:
! 1935: /* get next value */
! 1936: string_value = va_arg (args, char *);
! 1937: }
! 1938:
! 1939: /* return current value */
! 1940: va_end (args);
! 1941: return result;
! 1942: }
! 1943:
! 1944: /**
! 1945: * \brief Allows to get defined string for a given command line.
! 1946: *
! 1947: * Returns the value associated with the argument name. The returned
! 1948: * value must not be deallocated. If it is needed a string copy use
! 1949: * \ref exarg_get_string_alloc.
! 1950: *
! 1951: * \return The value associated with the param or NULL if fail.
! 1952: **/
! 1953: char * exarg_get_string (char * arg_name)
! 1954: {
! 1955: ExArgNodeOption * node;
! 1956:
! 1957: if (arg_name == NULL)
! 1958: return NULL;
! 1959:
! 1960: if (argument_options == NULL)
! 1961: return NULL;
! 1962:
! 1963: node = exarg_lookup_node (arg_name);
! 1964: if (node == NULL) {
! 1965: exarg_msg ("error: calling to get string value for: %s, but this argument isn't defined..",
! 1966: arg_name);
! 1967: }
! 1968: if (node->type != EXARG_STRING) {
! 1969: exarg_msg ("error: calling to get string value for: %s, but the argument wasn't defined as EXARG_STRING..",
! 1970: arg_name);
! 1971: }
! 1972:
! 1973: return node->string_value;
! 1974: }
! 1975:
! 1976: /**
! 1977: * \brief Allows to get defined string for a given command line allocating the result.
! 1978: *
! 1979: * Returns the value associated with the argument name. The returned
! 1980: * value must be <b>deallocated</b> using g_free. You can also use
! 1981: * \ref exarg_get_string to get a value that doesn't need to be
! 1982: * unrefered.
! 1983: *
! 1984: * \return The value associated with the param or NULL if fail.
! 1985: **/
! 1986: char * exarg_get_string_alloc (char * arg_name)
! 1987: {
! 1988: char * string_value;
! 1989:
! 1990: string_value = exarg_get_string (arg_name);
! 1991: if (string_value == NULL)
! 1992: return NULL;
! 1993: return exarg_strdup (string_value);
! 1994: }
! 1995:
! 1996: /**
! 1997: * \brief Allows to get int value for a given command line argument.
! 1998: *
! 1999: * Returns the value associated with the argument name. The returned
! 2000: * may be 0 which means the user may not defined that argument or may
! 2001: * defined it by using the 0 as value. To avoid confusing cases you
! 2002: * should use \ref exarg_is_defined to know if the user have used that
! 2003: * argument and then call this function.
! 2004: *
! 2005: * \return the value defined for this argument. If the argument
! 2006: * is null or the exarg is not initialized the function will return -1.
! 2007: **/
! 2008: int exarg_get_int (char * arg_name)
! 2009: {
! 2010: ExArgNodeOption * node;
! 2011:
! 2012: if (arg_name == NULL)
! 2013: return -1;
! 2014: if (argument_options == NULL)
! 2015: return -1;
! 2016:
! 2017: node = exarg_lookup_node (arg_name);
! 2018: if (node == NULL) {
! 2019: exarg_msg ("error: calling to get int value for: %s, but this argument isn't defined..",
! 2020: arg_name);
! 2021: }
! 2022:
! 2023: if (node->type != EXARG_INT) {
! 2024: exarg_msg ("error: calling to get int value for: %s, but the argument wasn't defined as EXARG_INT..",
! 2025: arg_name);
! 2026: }
! 2027:
! 2028: return node->int_value;
! 2029: }
! 2030:
! 2031: /**
! 2032: * \brief Returns free params defined at command line.
! 2033: *
! 2034: * Every value which is not an argument is considered to be a
! 2035: * parameter. All of them are stored and retrieved by using this
! 2036: * function and the following functions:
! 2037: *
! 2038: * - \ref exarg_param_get
! 2039: * - \ref exarg_param_next
! 2040: *
! 2041: * An example about using this function could be the next. A program
! 2042: * have defined several arguments using the function \ref
! 2043: * exarg_install_arg but that program also needs to receive several
! 2044: * file path.
! 2045: *
! 2046: * Once the \ref exarg_parse have detected all argument, all
! 2047: * parameters are stored, and this function provides access to the
! 2048: * first argument *found. Then a call to \ref exarg_param_get is
! 2049: * required to get the *argument value and a call to \ref
! 2050: * exarg_param_next to get a *reference to the next argument.
! 2051: *
! 2052: *
! 2053: * A program which may receive the argument --save-all but also several
! 2054: * files:
! 2055: *
! 2056: * \code
! 2057: * a_program --save-all file1 file2 file3
! 2058: * \endcode
! 2059: *
! 2060: * Will need to call this function to get the list: file1 file2 and
! 2061: * file3.
! 2062: *
! 2063: * \return The first param provided to the program. The returned value
! 2064: * must not be deallocated.
! 2065: */
! 2066: ExArgument * exarg_get_params ()
! 2067: {
! 2068: return params;
! 2069: }
! 2070:
! 2071: /**
! 2072: * @brief Allows to get the string value that is represeting the argument received.
! 2073: *
! 2074: * @param arg The argument that was received by the program.
! 2075: *
! 2076: * @return An string reference that must not be deallocated.
! 2077: */
! 2078: const char * exarg_param_get (ExArgument * arg)
! 2079: {
! 2080: /* check for null value received */
! 2081: if (arg == NULL)
! 2082: return NULL;
! 2083:
! 2084: /* return the string value inside */
! 2085: return arg->string;
! 2086: }
! 2087:
! 2088: /**
! 2089: * @brief Allows to get the next parameters defined at the command
! 2090: * line option that is following the argument provided.
! 2091: *
! 2092: * @param arg The argument which is previous to the argument to be
! 2093: * returned.
! 2094: *
! 2095: * @return An argument reference to the next or NULL if there are no
! 2096: * more arguments.
! 2097: */
! 2098: ExArgument * exarg_param_next (ExArgument * arg)
! 2099: {
! 2100: /* check for null value received */
! 2101: if (arg == NULL)
! 2102: return NULL;
! 2103:
! 2104: /* return the next argument */
! 2105: return arg->next;
! 2106: }
! 2107:
! 2108:
! 2109: /**
! 2110: * @brief Allows to get the number of parameters that were defined by
! 2111: * the user.
! 2112: *
! 2113: * Check also the following function \ref exarg_get_params_num.
! 2114: *
! 2115: * @return The number of parameters starting from 0.
! 2116: */
! 2117: int exarg_get_params_num ()
! 2118: {
! 2119: ExArgument * arg = NULL;
! 2120: int result = 0;
! 2121:
! 2122: if (params == NULL)
! 2123: return 0;
! 2124:
! 2125: /* count the number of params */
! 2126: arg = params;
! 2127: while (arg != NULL) {
! 2128: /* update the count */
! 2129: result++;
! 2130:
! 2131: /* update to the next */
! 2132: arg = arg->next;
! 2133:
! 2134: } /* end while */
! 2135:
! 2136: /* return current count */
! 2137: return result;
! 2138: }
! 2139:
! 2140: /* @} */
! 2141:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>