Annotation of gpl/axl/knife/exarg.c, revision 1.1.1.2
1.1.1.2 ! misho 1: /**
1.1 misho 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 Allows to calculate the amount of memory required to
455: * store the string that will representing the construction provided
456: * by the printf-like format received and its arguments.
457: *
458: * @param format The printf-like format to be printed.
459: *
460: * @param args The set of arguments that the printf applies to.
461: *
462: * <i><b>NOTE:</b> not all printf specification is supported. Generally, the
463: * following is supported: %s, %d, %f, %g, %ld, %lg and all
464: * combinations that provides precision, number of items inside the
465: * integer part, etc: %6.2f, %+2d, etc. An especial case not supported
466: * is %lld, %llu and %llg.</i>
467: *
468: * @return Return the number of bytes that must be allocated to hold
469: * the string (including the string terminator \0). If the format is
470: * not correct or it is not properly formated according to the value
471: * found at the argument set, the function will return -1.
472: */
473: int exarg_vprintf_len (const char * format, va_list args)
474: {
475: /** IMPLEMENTATION NOTE: in the case this code is update,
476: * update axl_stream_vprintf_len **/
477:
478: # if defined (OS_WIN32) && ! defined (__GNUC__)
479: # if HAVE_VSCPRINTF
480: if (format == NULL)
481: return 0;
482: return _vscprintf (format, args) + 1;
483: # else
484: char buffer[8192];
485: if (format == NULL)
486: return 0;
487: return _vsnprintf (buffer, 8191, format, args) + 1;
488: # endif
489: #else
490: /* gnu gcc case */
491: if (format == NULL)
492: return 0;
493: return vsnprintf (NULL, 0, format, args) + 1;
494:
495: #endif
496: }
497:
498:
499:
500: /**
501: * @internal Allows to produce an string representing the message hold by
502: * chunk with the parameters provided.
503: *
504: * @param chunk The message chunk to print.
505: * @param args The arguments for the chunk.
506: *
507: * @return A newly allocated string.
508: */
509: char * exarg_strdup_printfv (char * chunk, va_list args)
510: {
1.1.1.2 ! misho 511: /** IMPLEMENTATION NOTE: place update axl_stream_strdup_printfv
1.1 misho 512: * code in the case this code is updated **/
513:
514: #ifndef HAVE_VASPRINTF
515: int size;
516: #endif
517: char * result = NULL;
518:
519: if (chunk == NULL)
520: return NULL;
521:
522: #ifdef HAVE_VASPRINTF
523: /* do the operation using the GNU extension */
1.1.1.2 ! misho 524: if (vasprintf (&result, chunk, args) == -1)
! 525: return NULL;
1.1 misho 526: #else
527: /* get the amount of memory to be allocated */
528: size = exarg_vprintf_len (chunk, args);
529:
530: /* check result */
531: if (size == -1) {
532: printf ("error: unable to calculate the amount of memory for the strdup_printf operation");
533: return NULL;
534: } /* end if */
535:
536: /* allocate memory */
537: result = exarg_new (char, size + 2);
538:
539: /* copy current size */
1.1.1.2 ! misho 540: # if defined(OS_WIN32) && ! defined (__GNUC__)
! 541: _vsnprintf_s (result, size + 1, size, chunk, args);
! 542: # else
! 543: vsnprintf (result, size + 1, chunk, args);
! 544: # endif
1.1 misho 545: #endif
546: /* return the result */
547: return result;
548: }
549:
550: /**
551: * @internal Implementation that allows to produce dinamically
552: * allocated strings using printf-like format.
553: *
554: * @param chunk The chunk representing the format.
555: *
556: * @return An dynamically allocated string.
557: */
558: char * exarg_strdup_printf (char * chunk, ...)
559: {
560: char * result = NULL;
561: va_list args;
562:
563: /* return a null value if null chunk is received */
564: if (chunk == NULL)
565: return NULL;
566:
567: /* open std args */
568: va_start (args, chunk);
569:
570: /* get the string */
571: result = exarg_strdup_printfv (chunk, args);
572:
573: /* close std args */
574: va_end (args);
575:
576: return result;
577: }
578:
579: /**
580: * @internal Allows to copy the given chunk, supposing that is a
581: * properly format C string that ends with a '\\0' value.
582: *
583: * This function allows to perform a copy for the given string. If a
584: * copy limited by a size is required, use \ref axl_stream_strdup_n.
585: *
586: * @param chunk The chunk to copy
587: *
588: * @return A newly allocated string or NULL if fails.
589: */
590: char * exarg_strdup (char * chunk)
591: {
592: char * result;
593: int length;
594:
595: /* do not copy if null reference is received */
596: if (chunk == NULL)
597: return NULL;
598:
599: length = strlen (chunk);
600: result = exarg_new (char, length + 1);
601:
602: memcpy (result, chunk, length);
603:
604: return result;
605: }
606:
607: /**
608: * @internal Internal function that allows to dealloc the provided array of chunks.
609: *
610: * @param chunks An array containing pointers to chunks.
611: */
612: void exarg_freev (char ** chunks)
613: {
614: int iterator = 0;
615:
616: /* return if the received reference is null */
617: if (chunks == NULL)
618: return;
619:
620: /* release memory used by all elements inside the chunk */
621: while (chunks[iterator] != 0) {
622: exarg_free (chunks[iterator]);
623: iterator++;
624: }
625:
626: /* now release the chunk inside */
627: exarg_free (chunks);
628:
629: /* nothing more to do */
630: return;
631: }
632:
633:
634: /**
635: * @internal Adds the argument to the current argument list.
636: *
637: * @param argument The argument to add.
638: */
639: void __exarg_add_argument (char * argument)
640: {
641: ExArgument * arg;
642: ExArgument * arg2;
643:
644: /* creates the node */
645: arg = exarg_new (ExArgument, 1);
646: arg->string = argument;
647:
648: if (params == NULL) {
649: /* basic case, only one argument */
650: params = arg;
651:
652: return;
653: } /* end if */
654:
655: /* complex case, lookup for the last node */
656: arg2 = params;
657: while (arg2->next != NULL)
658: arg2 = arg2->next;
659:
660: /* set the argument on the last position */
661: arg2->next = arg;
662:
663: return;
664: }
665:
666: /**
667: * @internal
668: * @brief Perfom a look up inside the argument option installed.
669: *
670: * This function tries to return the ExArgNodeOption using the given
671: * value as index key.
672: *
673: * The given value can represent the long key option or the short
674: * form.
675: *
676: * @param arg_name the key to use on lookup process
677: *
678: * @return the function retuns the argument option if found or NULL if
679: * not.
680: */
681: ExArgNodeOption * exarg_lookup_node (const char * arg_name)
682: {
683: ExArgNodeOption * result = NULL;
684: int arg_name_len;
685:
686: /* check for null value */
687: if (arg_name == NULL)
688: return NULL;
689:
690: /* get length */
691: arg_name_len = strlen (arg_name);
692:
693: /* look up the item on the current argument option */
694: result = argument_options;
695: while (result != NULL) {
696:
697: /* check value with long argument form */
698: if (arg_name_len == strlen (result->arg_name) &&
699: !memcmp (arg_name, result->arg_name, strlen (arg_name))) {
700:
701: /* return found node */
702: return result;
703: }
704:
705: /* check value with short argument form */
706: if ((result->arg_short_name != NULL) &&
707: (arg_name_len == strlen (result->arg_short_name)) &&
708: !memcmp (arg_name, result->arg_short_name, strlen (arg_name))) {
709:
710: /* return node found */
711: return result;
712: }
713:
714: /* update to the next item */
715: result = result->next;
716:
717: } /* end while */
718:
719: /* return that we didn't found an item */
720: return result;
721:
722: } /* end exarg_lookup_node */
723:
724:
725:
726:
727: int exarg_is_argument (char * argument)
728: {
729:
730: int iterator = 1;
731:
732: /* support standard unix format definition */
733: if (CHECK_PARSE_MODE (PARSE_MODE_UNIX) && !memcmp (argument, "--", 2)) {
734:
735: /* update parse mode */
736: UPDATE_PARSE_MODE (PARSE_MODE_UNIX);
737: return 1;
738: }
739:
740: /* support sort argument format definition */
741: if (CHECK_PARSE_MODE (PARSE_MODE_UNIX) && (strlen (argument) == 2) && (argument[0] == '-')) {
742:
743: /* update parse mode */
744: UPDATE_PARSE_MODE (PARSE_MODE_UNIX);
745:
746: return 1;
747: }
748:
749: /* support windows argument format */
750: if (CHECK_PARSE_MODE (PARSE_MODE_WINDOWS) && (strlen (argument) > 2) && (argument[0] == '/')) {
751:
752: /* now check if the argument doesn't have more bars */
753: while (argument[iterator] != 0) {
754: /* check value */
755: if (argument[iterator] == '/')
756: return 0;
757:
758: /* update iterator */
759: iterator++;
760:
761: } /* end while */
762:
763: /* update parse mode */
764: UPDATE_PARSE_MODE (PARSE_MODE_WINDOWS);
765:
766: return 1;
767: }
768:
769: return 0;
770: }
771:
772: char * exarg_get_argument (char * argument)
773: {
774: /* support getting the argument value for unix standard
775: * argument */
776: if (!memcmp (argument, "--", 2))
777: return &(argument[2]);
778:
779: /* support getting the argument value for short def */
780: if ((strlen (argument) == 2) && (argument[0] == '-'))
781: return &(argument[1]);
782:
783: /* support getting the argument value for windows def */
784: if ((strlen (argument) > 2) && (argument[0] == '/'))
785: return &(argument[1]);
786:
787: return NULL;
788: }
789:
790: int exarg_check_help_argument (char * argument)
791: {
792: if (!memcmp (argument, "help", 4) || !memcmp (argument, "?", 1))
793: return 1;
794: return 0;
795: }
796:
797: void exarg_wrap_and_print (const char * text, int size_to_wrap, const char * fill_text)
798: {
799: char ** stringv = NULL;
800: int i = 0;
801: int sum = 0;
802: char * working_line = NULL;
803: char * aux_string = NULL;
804: int first_line = 1;
805:
806: /* do not print anything if a null value is received */
807: if (text == NULL)
808: return;
809:
810: if (strlen (text) <= size_to_wrap) {
811: printf ("%s\n", text);
812: return;
813: }
814:
815: stringv = exarg_split (text, 1, " ");
816: for (i = 0; stringv[i]; i++) {
817: if (working_line) {
818: aux_string = working_line;
819: working_line = exarg_strdup_printf ("%s %s", working_line, stringv[i]);
820: exarg_free (aux_string);
821: }else
822: working_line = exarg_strdup (stringv[i]);
823: sum = sum + strlen (stringv[i]) + 1;
824:
825: if (sum >= size_to_wrap) {
826: sum = 0;
827: if (first_line) {
828: first_line = 0;
829: printf ("%s\n", working_line);
830: }else
831: printf ("%s%s\n", fill_text, working_line);
832: exarg_free (working_line);
833: working_line = NULL;
834: }
835:
836: }
837: if (sum) {
838: printf ("%s%s\n", fill_text, working_line);
839: exarg_free (working_line);
840: }
841: exarg_freev (stringv);
842:
843:
844: return;
845: }
846:
847: void __exarg_show_usage_foreach (epointer key, epointer value, epointer user_data)
848: {
849: char ** string_aux = (char **) user_data;
850: char * str = (* string_aux);
851: char * aux = NULL;
852: ExArgNodeOption * node = (ExArgNodeOption *) value;
853:
854: switch (node->type) {
855: case EXARG_NONE:
856: if (node->arg_short_name)
857: (*string_aux) = exarg_strdup_printf (" [-%s|--%s]", node->arg_short_name, node->arg_name);
858: else
859: (*string_aux) = exarg_strdup_printf (" [--%s]", node->arg_name);
860: break;
861: case EXARG_INT:
862: if (node->arg_short_name)
863: (*string_aux) = exarg_strdup_printf (" [-%s <number>|--%s <number>]", node->arg_short_name, node->arg_name);
864: else
865: (*string_aux) = exarg_strdup_printf (" [--%s <number>]", node->arg_name);
866: break;
867: case EXARG_STRING:
868: if (node->arg_short_name)
869: (*string_aux) = exarg_strdup_printf (" [-%s <string>|--%s <string>]", node->arg_short_name, node->arg_name);
870: else
871: (*string_aux) = exarg_strdup_printf (" [--%s <string>]", node->arg_name);
872: break;
873: } /* end switch */
874:
875: if (str != NULL) {
876: /* get a reference to previous content */
877: aux = (* string_aux);
878: (*string_aux) = exarg_strdup_printf ("%s%s", str, (*string_aux));
879:
880: /* dealloc both pieces that joined are the result */
881: exarg_free (str);
882: exarg_free (aux);
883: }
884: return;
885: }
886:
887: void exarg_show_usage (int show_header)
888: {
889: char * string_aux = NULL;
890: ExArgNodeOption * node;
891:
892: if (show_header && (__exarg_usage_header && (* __exarg_usage_header)))
1.1.1.2 ! misho 893: printf ("%s", __exarg_usage_header);
1.1 misho 894:
895: printf ("Usage: %s ", exarg_exec_name);
896:
897: /* get the first node */
898: node = argument_options;
899: while (node != NULL) {
900: /* call to the foreach function */
901: __exarg_show_usage_foreach ((epointer) node->arg_name, node, &string_aux);
902:
903: /* update to the next */
904: node = node->next;
905:
906: } /* end while */
907:
908: exarg_wrap_and_print (string_aux, 55, " ");
909: printf ("\n");
910:
911: /* free string created */
912: exarg_free (string_aux);
913:
914: if (show_header && (__exarg_post_usage_header && (* __exarg_post_usage_header)))
1.1.1.2 ! misho 915: printf ("%s", __exarg_post_usage_header);
1.1 misho 916:
917: return;
918: }
919:
920: char * __exarg_build_dep_string (ExArgNodeOption * node, int exclude)
921: {
922: char * result;
923: char * aux;
924: ExArgDependency * dep;
925:
926: /* check node dependency */
927: if (!exclude && ! node->depends)
928: return NULL;
929: if (exclude && ! node->excludes)
930: return NULL;
931:
932: if (exclude)
933: result = exarg_strdup ("[excludes: ");
934: else
935: result = exarg_strdup ("[depends on: ");
936:
937: /* foreach each dependency configured */
938: if (exclude)
939: dep = node->excludes;
940: else
941: dep = node->depends;
942: while (dep != NULL) {
943:
944: aux = result;
945: if (dep->next != NULL)
946: result = exarg_strdup_printf ("%s --%s", result, dep->node->arg_name);
947: else
948: result = exarg_strdup_printf ("%s --%s]", result, dep->node->arg_name);
949: exarg_free (aux);
950:
951: /* get next dependency */
952: dep = dep->next;
953:
954: } /* end while */
955:
956: /* return string created */
957: return result;
958: }
959:
960: void __exarg_show_help_foreach (epointer key, epointer value, epointer user_data)
961: {
962: ExArgNodeOption * node = (ExArgNodeOption *) value;
963: char * dep;
964: int chars = 35;
965: int iterator = 0;
966:
967: /* print argument help */
968: if (node->arg_short_name) {
969: printf (" -%s, --%-18s ",
970: node->arg_short_name, node->arg_name);
971: exarg_wrap_and_print (node->description, 40, " ");
972:
973: }else {
974: printf (" --%-22s ", node->arg_name);
975: exarg_wrap_and_print (node->description, 40, " ");
976: }
977:
978: /* print argument dependency */
979: dep = __exarg_build_dep_string (node, 0);
980: if (dep != NULL) {
981: /* write spaces */
982: while (iterator < chars) {
983: printf (" ");
984: iterator++;
985: }
986: exarg_wrap_and_print (dep, 40, " ");
987: }
988: exarg_free (dep);
989:
990: /* print argument exclusion */
991: iterator = 0;
992: dep = __exarg_build_dep_string (node, 1);
993: if (dep != NULL) {
994: /* write spaces */
995: while (iterator < chars) {
996: printf (" ");
997: iterator++;
998: }
999: exarg_wrap_and_print (dep, 40, " ");
1000: }
1001: exarg_free (dep);
1002: return;
1003: }
1004:
1.1.1.2 ! misho 1005: void exarg_show_help (void)
1.1 misho 1006: {
1007: ExArgNodeOption * node;
1008:
1009: if (__exarg_help_header && (* __exarg_help_header))
1.1.1.2 ! misho 1010: printf ("%s", __exarg_help_header);
1.1 misho 1011:
1012: exarg_show_usage (0);
1013:
1014: printf ("\nCommand options:\n");
1015:
1016: /* get first node */
1017: node = argument_options;
1018: while (node != NULL) {
1019: /* call to show the node information */
1020: __exarg_show_help_foreach ((epointer) node->arg_name, node, NULL);
1021:
1022: /* update to the next node */
1023: node = node->next;
1024: } /* end while */
1025:
1026: printf ("\nHelp options:\n");
1027: printf (" -?, --help Show this help message.\n");
1028: printf (" --usage Display brief usage message.\n");
1029:
1030: if (__exarg_post_help_header && (* __exarg_post_help_header))
1.1.1.2 ! misho 1031: printf ("%s", __exarg_post_help_header);
1.1 misho 1032:
1033: return;
1034: }
1035:
1036: void exarg_check_argument_value (char ** argv, int iterator)
1037: {
1038:
1039: if (argv[iterator] == NULL) {
1040: printf ("error: not defined value for argument: %s, exiting..",
1041: argv[iterator - 1]);
1042: fflush (stdout);
1043: exit (-1);
1044: }
1045:
1046: if (exarg_is_argument (argv[iterator])) {
1047: printf ("error: not defined value for argument: %s, instead found another argument: %s, exiting..",
1048: argv[iterator - 1],
1049: argv[iterator]);
1050: fflush (stdout);
1051: exit (-1);
1052: }
1053:
1054: return;
1055: }
1056:
1057:
1.1.1.2 ! misho 1058: void __exarg_parse_check_non_optional (void)
1.1 misho 1059: {
1060: ExArgNodeOption * node = argument_options;
1061:
1062: /* for each node */
1063: while (node != NULL) {
1064: /* check the node */
1065: if (! node->is_optional && ! node->is_defined) {
1066: exarg_msg ("error: argument '%s' is not defined, but it is required for a proper function..\n",
1067: node->arg_name);
1068: } /* end if */
1069:
1070: /* get the next */
1071: node = node->next;
1072:
1073: } /* end while */
1074:
1075: return;
1076: }
1077:
1.1.1.2 ! misho 1078: void __exarg_parse_check_depends (void)
1.1 misho 1079: {
1080: /* first argument */
1081: ExArgNodeOption * node = argument_options;
1082: ExArgDependency * dep;
1083:
1084: /* for each argument defined */
1085: while (node != NULL) {
1086:
1087: /* check if the argument was defined, and hence
1088: * activates its dependencies */
1089: if (! node->is_defined) {
1090: node = node->next;
1091: continue;
1092: }
1093:
1094: /* check depends */
1095: dep = node->depends;
1096: while (dep != NULL) {
1097:
1098: /* check that the dependency is defined */
1099: if (! dep->node->is_defined) {
1100: exarg_msg ("You must define argument (--%s) if used (--%s). Try %s --help.",
1101: dep->node->arg_name, node->arg_name, exarg_exec_name);
1102: return;
1103: } /* end if */
1104:
1105: /* get next dependency */
1106: dep = dep->next;
1107:
1108: } /* end while */
1109:
1110: /* check depends */
1111: dep = node->excludes;
1112: while (dep != NULL) {
1113:
1114: /* check that the dependency is defined */
1115: if (dep->node->is_defined) {
1116: printf ("You can't define argument (--%s) if used (--%s). Try %s --help.\n",
1117: node->arg_name, dep->node->arg_name, exarg_exec_name);
1118: fflush (stdout);
1119: return;
1120: } /* end if */
1121:
1122: /* get next dependency */
1123: dep = dep->next;
1124:
1125: } /* end while */
1126:
1127: /* get next node */
1128: node = node->next;
1129:
1130: } /* end whle */
1131:
1132: /* nothing more to check */
1133: return;
1134: }
1135:
1136:
1137: /**
1138: * \brief Makes exarg to start parsing argument options.
1139: *
1140: * Makes LibExArg to start command line parsing by using arguments
1141: * installed.
1142: *
1143: * Once this functions is called it is posible to call the set of
1144: * function which returns data obtained: \ref exarg_is_defined,
1145: * \ref exarg_get_int, \ref exarg_get_string and \ref exarg_get_params.
1146: *
1147: * The advantage is that LibExArg allows you to get access to command
1148: * line data from any point of your program.
1149: *
1150: * @param argc the argc value the current application have received.
1151: * @param argv the argv value the current application have received.
1152: */
1153: void exarg_parse (int argc,
1154: char ** argv)
1155: {
1156: int iterator = 1;
1157: ExArgNodeOption * node;
1158: char * argument;
1159:
1160: /* check how many argument have been defined */
1161: if (iterator == argc) {
1162: /* once terminated, check if the non optional options
1163: * were defined */
1164:
1165: __exarg_parse_check_non_optional ();
1166: return;
1167: }
1168:
1169: exarg_exec_name = exarg_basename (argv[0]);
1170:
1171: /* iterate over all arguments */
1172: while (iterator < argc) {
1173:
1174: if (!exarg_is_argument (argv[iterator])) {
1175: /* check free argument configuration */
1176: if (__exarg_disable_free_args) {
1177: exarg_msg ("error: provided a free argument='%s', not listed in the accept command line option", argv[iterator]);
1178:
1179: } /* end if */
1180:
1181: /* save and increase iterator */
1182: __exarg_add_argument (argv[iterator]);
1183: iterator++;
1184: continue;
1185: }
1186:
1187: /* get clean argument */
1188: argument = exarg_get_argument (argv[iterator]);
1189:
1190: /* check for help argument */
1191: if (exarg_check_help_argument (argument)){
1192: exarg_show_help ();
1193: exarg_end ();
1194: exit (0);
1195: }
1196:
1197: /* check for usage argument */
1198: if (!memcmp (argument, "usage", 5)) {
1199: exarg_show_usage (1);
1200: exarg_end ();
1201: exit (0);
1202: }
1203:
1204: /* get node argument */
1205: node = exarg_lookup_node (argument);
1206: if (node == NULL) {
1207: exarg_msg ("%s error: argument not found: %s, try: %s --help\n",
1208: exarg_exec_name, argv[iterator], exarg_exec_name);
1209: }
1210:
1211: /* check if node is defined */
1212: if (node->is_defined) {
1213: exarg_msg ("%s error: argument %s already defined, exiting..\n",
1214: exarg_exec_name, argv[iterator]);
1215: }
1216:
1217:
1218: /* set this argument to be defined */
1219: node->is_defined = 1;
1220: switch (node->type) {
1221: case EXARG_NONE:
1222: /* nothing to do */
1223: break;
1224: case EXARG_INT:
1225: /* save int value */
1226: iterator++;
1227:
1228: exarg_check_argument_value (argv, iterator);
1229:
1230: node->int_value = atoi (argv[iterator]);
1231: break;
1232: case EXARG_STRING:
1233: iterator++;
1234:
1235: exarg_check_argument_value (argv, iterator);
1236:
1237: node->string_value = argv[iterator];
1238:
1239: break;
1240: }
1241:
1242: /* update iterator */
1243: iterator++;
1244: }
1245:
1246: /* once terminated, check if the non optional options were
1247: * defined */
1248: __exarg_parse_check_non_optional ();
1249:
1250: /* check argument dependency and argument mutual exclusion. */
1251: __exarg_parse_check_depends ();
1252:
1253: return;
1254: }
1255:
1256: void __exarg_end_free_dep (ExArgDependency * dep)
1257: {
1258: ExArgDependency * next;
1259:
1260: /* foreach dependency established */
1261: while (dep != NULL) {
1262:
1263: /* free the dep node */
1264: next = dep->next;
1265: exarg_free (dep);
1266: dep = next;
1267: } /* end while */
1268:
1269: return;
1270: }
1271:
1272: /**
1273: * \brief Ends exarg library execution.
1274: *
1275: * Terminates the exarg function. This function will free all
1276: * resources allocated so the library cannot be used any more for the
1277: * current execution.
1278: *
1279: * This function is reatrant. Several threads can actually call this
1280: * function. It will take care about making only one thread to
1281: * actually free resources.
1282: **/
1283: void exarg_end ()
1284: {
1285: ExArgNodeOption * node;
1286: ExArgNodeOption * node2;
1287:
1288: ExArgument * params2;
1289:
1290:
1291: if (argument_options != NULL) {
1292: /* get a reference to the table, and dealloc it */
1293: node = argument_options;
1294: argument_options = NULL;
1295:
1296: while (node != NULL) {
1297: /* get a reference to the next */
1298: node2 = node->next;
1299:
1300: /* free node arguments dependencies and mutual
1301: * exclusions */
1302: __exarg_end_free_dep (node->depends);
1303: __exarg_end_free_dep (node->excludes);
1304:
1305: /* free current node */
1306: exarg_free (node);
1307:
1308: /* update the node ref */
1309: node = node2;
1310: } /* end while */
1311:
1312: } /* end if */
1313:
1314: if (params != NULL) {
1315: while (params != NULL) {
1316: /* get a reference to the next node */
1317: params2 = params->next;
1318:
1319: /* free params node */
1320: exarg_free (params);
1321:
1322: /* configure the next argument to dealloc */
1323: params = params2;
1324: } /* end while */
1325: } /* end if */
1326:
1327: return;
1328: }
1329:
1330: /**
1331: * \brief Disable autohelp.
1332: *
1333: * Allows to disable auto help and --help and -? option
1334: * recognition. This is useful if you don't want your program to
1335: * accept --help and --usage options.
1336: **/
1337: void exarg_disable_help ()
1338: {
1339: return;
1340: }
1341:
1342: /**
1343: * \brief Adds user defined header to automatic usage command generated.
1344: *
1345: * Once a program is linked to libexarg is able to produce a usage
1346: * help by accepting the --usage command line option. But that usage
1347: * help is showed as is. This function allows you to define a header
1348: * to be showed preceding the usage info. You can use this, for
1349: * example, to introduce your copyright.
1350: *
1351: * This function doesn't make a copy of the given string so you
1352: * must not free the header provided or use an static string.
1353: **/
1354: void exarg_add_usage_header (char * header)
1355: {
1356: __exarg_usage_header = header;
1357: }
1358:
1359: /**
1360: * \brief Adds user defined header to automatic help command generated.
1361: *
1362: * Once a program is linked to libexarg is able to produce a help by
1363: * accepting the --help or -? command line option. But that help is
1364: * showed as is. This function allows you to define a header to be
1365: * showed preceding the help info. You can use this, for example, to
1366: * introduce your copyright.
1367: *
1368: * This function doesn't make a copy of the given string so you
1369: * must not free the header provided or use an static string.
1370: **/
1371: void exarg_add_help_header (char * header)
1372: {
1373: __exarg_help_header = header;
1374: }
1375:
1376: /**
1377: * \brief Adds user defined post header for usage command.
1378: *
1379: * This function works pretty much like \ref exarg_add_usage_header but
1380: * adding the header provided to be appended at the end of the usage
1381: * automatically generated.
1382: **/
1383: void exarg_post_usage_header (char * post_header)
1384: {
1385: __exarg_post_usage_header = post_header;
1386: }
1387:
1388: /**
1389: * \brief Adds user defined post header for help command.
1390: *
1391: * This function works pretty much like \ref exarg_add_help_header but
1392: * adding the header provided to be appended at the end of the help
1393: * automatically generated.
1394: **/
1395: void exarg_post_help_header (char * post_header)
1396: {
1397: __exarg_post_help_header = post_header;
1398: }
1399:
1400: /**
1401: * \internal
1402: * Internal ExArg function. This function allows \ref exarg_install_arg to
1403: * check if there are already installed an short argument as the one
1404: * been installed.
1405: **/
1406: void __exarg_check_short_arg (epointer key, epointer value, epointer user_data)
1407: {
1408: ExArgNodeOption * node = (ExArgNodeOption *) value;
1409: char * arg_to_check = (char *) user_data;
1410:
1411: if (node->arg_short_name != NULL) {
1412: if (!memcmp (node->arg_short_name, arg_to_check, strlen (arg_to_check))) {
1413: exarg_msg ("error: found that short arg installed is already found: %s\n", arg_to_check);
1414: } /* end if */
1415: } /* end if */
1416:
1417: return;
1418: }
1419:
1420: /**
1421: * \brief Installs a new command line to be accepted.
1422: *
1423: * This functions allows you to install new arguments to be
1424: * accepted. Every argument passed in to the program which is not
1425: * installed throught this function will no be accepted and will
1426: * generate a non recognized command line error.
1427: *
1428: * Let's see an example on how to use exarg to install the --version
1429: * argument. You should call exarg as follows:
1430: *
1431: * \code
1432: * exarg_install_arg ("version", "v", EXARG_NONE,
1433: * "show program version");
1434: *
1435: * \endcode
1436: *
1437: * Previous line have installed a argument called "version" which will
1438: * be invoked by the user as --version. The short alias
1439: * in this case is "v" which as we have see will allow user to invoke
1440: * your program as -v.
1441: *
1442: * Because you could install arguments which may conflict, this
1443: * function will abort the program execution on that case. This will
1444: * ensure you, as programer, to have a binary compiled with no
1445: * problems due to exarg.
1446: *
1447: * Later on, you can use \ref exarg_is_defined to check the status of
1448: * installed arguments. Once you install an argument the user may
1449: * invoke it and you could check that status using previous
1450: * function. Because the "version" argument type is \ref EXARG_NONE you can
1451: * only use \ref exarg_is_defined. But, for other argument types as
1452: * \ref EXARG_STRING, you can also use \ref exarg_get_string function to get the
1453: * value defined by user. Let's see an example.
1454: *
1455: * \code
1456: * exarg_install_arg ("load-library", "l", EXARG_STRING,
1457: * "loads the library defined as argument");
1458: * \endcode
1459: *
1460: * This previous line will allow user to invoke your program as
1461: * --load-library path/to/lib. Then you can use \ref exarg_get_string to get
1462: * the path/to/lib value by using:
1463: *
1464: * \code
1465: * // check user have defined this argument
1466: * if (exarg_is_defined ("load-library")) {
1467: *
1468: * arg_value = exarg_get_string ("load-library");
1469: *
1470: * printf ("The library defined by user was: %s\n",
1471: * arg_value);
1472: * }
1473: *
1474: * \endcode
1475: *
1476: * You must install all argument before calling \ref exarg_parse. That function
1477: * will parse argument options by using installed arguments. Check the info
1478: * about that function.
1479: *
1480: * ExArg is not thread-safe which doesn't means anything wrong but you
1481: * must call all exarg function from the same thread to get the right
1482: * results.
1483: *
1484: * This function will not do a copy from arg_name, arg_short_name or
1485: * description. This means you should not free that values while
1486: * using exarg. To end exarg using check \ref exarg_end. It is recomended to use
1487: * static values and shows on previous examples.
1488: **/
1489: void exarg_install_arg (const char * arg_name,
1490: const char * arg_short_name,
1491: ExArgType type,
1492: const char * description)
1493: {
1494: ExArgNodeOption * node;
1495: ExArgNodeOption * node2;
1496:
1497: /* init hash table */
1498: if (argument_options != NULL) {
1499: /* check if there are an argument with the same name */
1500: if (exarg_lookup_node (arg_name)) {
1501: exarg_end ();
1502: exarg_msg ("error: argument being installed is already defined: %s..",
1503: arg_name);
1504: }
1505:
1506: /* check if there are an shor argument with the same
1507: * name */
1508: if (arg_short_name != NULL) {
1509: node = argument_options;
1510:
1511: /* while there are options to process */
1512: while (node != NULL) {
1513: /* call to check */
1514: __exarg_check_short_arg ((epointer) node->arg_name, node, (epointer) arg_short_name);
1515:
1516: /* update to the next */
1517: node = node->next;
1518: } /* end while */
1519: } /* end if */
1520: } /* end if */
1521:
1522: /* create node option */
1523: node = exarg_new (ExArgNodeOption, 1);
1524: node->arg_name = arg_name;
1525: node->arg_short_name = arg_short_name;
1526: node->type = type;
1527: node->description = description;
1528: node->is_optional = 1;
1529:
1530: /* lookup for the last position */
1531: if (argument_options == NULL)
1532: argument_options = node;
1533: else {
1534: /* lookup for the last */
1535: node2 = argument_options;
1536: while (node2->next != NULL)
1537: node2 = node2->next;
1538:
1539: /* set it */
1540: node2->next = node;
1541: } /* end if */
1542:
1543: return;
1544: }
1545:
1546: /**
1547: * \brief Installs several command lines to be accepted.
1548: *
1549: * This function does the same that \ref exarg_install_arg but making
1550: * group of argument to be installed in one step.
1551: *
1552: * Think about installing two argument. To install them we have to do
1553: * the following:
1554: *
1555: * \code
1556: * exarg_install_arg ("version", "v",
1557: * EXARG_NONE, "show argument version");
1558: * exarg_install_arg ("load-library", "l",
1559: * EXARG_STRING, "load my library");
1560: * \endcode
1561: *
1562: * Because some people doesn't like to perform several calls to the
1563: * same funcion the previous code can be done by using one step as:
1564: *
1565: * \code
1566: * exarg_install_argv (2, "version", "v", EXARG_NONE,
1567: * "show argument version",
1568: * "load-library", "l",
1569: * EXARG_STRING, "load my library");
1570: * \endcode
1571: *
1572: * When you install argument this way you have to specify how many
1573: * argument is going to be installed. In this case that number is
1574: * 2. This allows exarg to know how many arguments needs to search
1575: * inside the argv. If something is wrong while specifying the number
1576: * or argument or the argument information itself you'll get a
1577: * segmentation fault or something similar.
1578: *
1579: * While calling to \ref exarg_install_arg the short_name argument can be
1580: * optional. This is *NOT* applied to this function. If you don't want
1581: * to define a short argument name you must use NULL as value.
1582: *
1583: * @param num_arg Must be at least 1 or error will happen and library will abort
1584: * application execution.
1585: **/
1586: void exarg_install_argv (int num_arg, ...)
1587: {
1588: va_list args;
1589: int iterator;
1590: char * arg_name;
1591: char * arg_short_name;
1592: ExArgType type;
1593: char * description;
1594:
1595: if (num_arg <= 0) {
1596: exarg_end ();
1597: exarg_msg ("error: calling to exarg_install_argv with num_arg equal or less to 0..");
1598: }
1599:
1600: va_start (args, num_arg);
1601:
1602: for (iterator = 0; iterator < num_arg; iterator++) {
1603:
1604: /* get the argument info */
1605: arg_name = va_arg (args, char *);
1606: arg_short_name = va_arg (args, char *);
1607: type = va_arg (args, ExArgType);
1608: description = va_arg (args, char *);
1609:
1610: exarg_install_arg (arg_name, arg_short_name, type, description);
1611: }
1612: va_end (args);
1613: return;
1614: }
1615:
1616: /**
1617: * @brief Allows to define a parameter dependency between the to
1618: * arguments defined. The kind of dependency has direction. This means
1619: * that the first argument will depend on the second argument, forcing
1620: * the user to define the second argument if the first one is defined.
1621: *
1622: * You can call to this function several times making the first
1623: * argument to depend on any number of argument defined. You must not
1624: * call to establish a dependency to the argument itself.
1625: *
1626: * @param arg_name The argument that will be configured with an
1627: * argument dependency.
1628: *
1629: * @param arg_dependency The argument that will receive the
1630: * dependency.
1631: *
1632: *
1633: */
1634: void exarg_add_dependency (const char * arg_name,
1635: const char * arg_dependency)
1636: {
1637: ExArgNodeOption * node;
1638: ExArgNodeOption * node2;
1639: ExArgDependency * dep;
1640: /* check arguments received */
1641: if (arg_name == NULL)
1642: return;
1643: if (arg_dependency == NULL)
1644: return;
1645:
1646: /* check that both arguments aren't equal */
1647: if (strlen (arg_name) == strlen (arg_dependency) &&
1648: !memcmp (arg_name, arg_dependency, strlen (arg_name))) {
1649: exarg_msg ("error: defined argument dependency with an argument itself.");
1650: return;
1651: }
1652:
1653: /* locates the argument node */
1654: node = exarg_lookup_node (arg_name);
1655: if (node == NULL) {
1656: exarg_msg ("error: you did especify an argument that doesn't exists (%s)", arg_name);
1657: return;
1658: }
1659:
1660: /* locates dependecy argument node */
1661: node2 = exarg_lookup_node (arg_dependency);
1662: if (node2 == NULL) {
1663: exarg_msg ("error: you did especify an argument that doesn't exists (%s)", arg_dependency);
1664: return;
1665: }
1666:
1667: /* make the first argument to depend on the second */
1668: dep = node->depends;
1669:
1670: /* create the new dependency node */
1671: node->depends = exarg_new (ExArgDependency, 1);
1672: node->depends->node = node2;
1673: node->depends->next = dep;
1674:
1675: return;
1676: }
1677:
1678: /**
1679: * @brief Allows to configure arguments that are mutually
1680: * excluyents. This function will take the first arguments to be
1681: * muatually excluyen with the second one without direction as it
1682: * happens with \ref exarg_add_dependency function.
1683: *
1684: * Once defined both arguments provided can't be defined at the same
1685: * time at the command line options.
1686: *
1687: * @param arg_name The first argument to make mutual exclusion with
1688: * the second argument.
1689: *
1690: * @param arg_excluded Second argument to make mutual exclusion with
1691: * the first argument.
1692: */
1693: void exarg_add_exclusion (const char * arg_name,
1694: const char * arg_excluded)
1695: {
1696: ExArgNodeOption * node;
1697: ExArgNodeOption * node2;
1698: ExArgDependency * dep;
1699:
1700: /* check arguments received */
1701: if (arg_name == NULL)
1702: return;
1703:
1704: if (arg_excluded == NULL)
1705: return;
1706:
1707: /* check that both arguments aren't equal */
1708: if (strlen (arg_name) == strlen (arg_excluded) &&
1709: !memcmp (arg_name, arg_excluded, strlen (arg_name))) {
1710: exarg_msg ("error: defined argument dependency with an argument itself.");
1711: return;
1712: }
1713:
1714: /* locates the argument node */
1715: node = exarg_lookup_node (arg_name);
1716: if (node == NULL) {
1717: exarg_msg ("error: you did especify an argument that doesn't exists (%s)", arg_name);
1718: return;
1719: }
1720:
1721: /* locates dependecy argument node */
1722: node2 = exarg_lookup_node (arg_excluded);
1723: if (node2 == NULL) {
1724: exarg_msg ("error: you did especify an argument that doesn't exists (%s)", arg_excluded);
1725: return;
1726: }
1727:
1728: /* make the first argument to depend on the second */
1729: dep = node->excludes;
1730:
1731: /* create the new dependency node */
1732: node->excludes = exarg_new (ExArgDependency, 1);
1733: node->excludes->node = node2;
1734: node->excludes->next = dep;
1735:
1736: return;
1737: }
1738:
1739:
1740: /**
1741: * @brief Makes an argument installed to be obligatory (not optional
1742: * at the user command line input).
1743: *
1744: * Once called \ref exarg_install_arg, you can use this function to
1745: * make the program to make the option obligatory.
1746: *
1747: * @param arg_name The argument to make it obligatory.
1748: */
1749: void exarg_set_obligatory (char * arg_name)
1750: {
1751: ExArgNodeOption * node;
1752:
1753: /* perform some environment checks */
1754: if (arg_name == NULL)
1755: return;
1756:
1757: node = exarg_lookup_node (arg_name);
1758: if (node == NULL) {
1759: return;
1760: }
1761:
1762: /* make it to be defined */
1763: node->is_optional = 0;
1764:
1765: return;
1766: }
1767:
1768:
1769: /**
1770: * @brief Allows to configure exarg library to accept or not free
1771: * arguments.
1772: *
1773: * Free arguments are optional parameters provided to the application,
1774: * such files, which aren't associated to a particular option.
1775: *
1776: * If your command line application do not uses free arguments, you
1777: * can use this function to enable exarg library to show an error
1778: * message to the user:
1779: *
1780: * \code
1781: * // disable free arguments
1782: * exarg_accept_free_args (0);
1783: * \endcode
1784: *
1785: * @param accept 1 to accept free arguments. It is the default value,
1786: * so it is not required to enable it. 0 to disable free arguments.
1787: */
1788: void exarg_accept_free_args (int accept)
1789: {
1790: /* configure free arguments */
1791: __exarg_disable_free_args = (accept == 0);
1792:
1793: return;
1794: }
1795:
1796: /**
1797: * @brief Allows to simulate user defined command line options alread
1798: * installed by \ref exarg_install_arg, without requiring the user to
1799: * set those values.
1800: *
1801: * This function allows to install values received or to just define
1802: * the argument to be supported by the program, without requiring the
1803: * user to provide such option. This is a convenient to make some
1804: * options to be default, writting your application relying on
1805: * arguments defined by command line.
1806: *
1807: * The function won't define the argument if not installed
1808: * previously. If the argument isn't found, the function takes no
1809: * action.
1810: *
1811: * @param arg_name The argument o define as provided by the user.
1812: * @param value The value to be associated to the argument. Some
1813: * arguments doesn't require this paremeters (\ref EXARG_NONE), so,
1814: * you can provide NULL to this parameter.
1815: */
1816: void exarg_define (char * arg_name,
1817: char * value)
1818: {
1819: ExArgNodeOption * node;
1820:
1821: /* perform some environment checks */
1822: if (arg_name == NULL)
1823: return;
1824:
1825: node = exarg_lookup_node (arg_name);
1826: if (node == NULL) {
1827: return;
1828: }
1829: /* make it to be defined */
1830: node->is_defined = 1;
1831:
1832: /* check argument value */
1833: if (value != NULL) {
1834: switch (node->type) {
1835: case EXARG_NONE:
1836: /* nothing to set */
1837: break;
1838: case EXARG_INT:
1839: /* integer value */
1840: node->int_value = strtol (value, NULL, 10);
1841: break;
1842: case EXARG_STRING:
1843: /* string value */
1844: node->string_value = value;
1845: break;
1.1.1.2 ! misho 1846: } /* end switch */
1.1 misho 1847: } /* end if */
1848:
1849: /* nothing to do over here */
1850: return;
1851: }
1852:
1853: /**
1.1.1.2 ! misho 1854: * @brief Allows to undef the value associated and the definition
! 1855: * itself of the option provided (arg_name).
! 1856: *
! 1857: * @param arg_name The argument to undef.
! 1858: */
! 1859: void exarg_undef (char * arg_name)
! 1860: {
! 1861: ExArgNodeOption * node;
! 1862:
! 1863: /* perform some environment checks */
! 1864: if (arg_name == NULL)
! 1865: return;
! 1866:
! 1867: node = exarg_lookup_node (arg_name);
! 1868: if (node == NULL)
! 1869: return;
! 1870:
! 1871: /* undef the value */
! 1872: node->is_defined = 0;
! 1873:
! 1874: /* check argument value */
! 1875: switch (node->type) {
! 1876: case EXARG_NONE:
! 1877: /* nothing to set */
! 1878: break;
! 1879: case EXARG_INT:
! 1880: /* integer value */
! 1881: node->int_value = 0;
! 1882: break;
! 1883: case EXARG_STRING:
! 1884: /* string value */
! 1885: node->string_value = NULL;
! 1886: break;
! 1887: } /* end switch */
! 1888:
! 1889: /* nothing to do over here */
! 1890: return;
! 1891: }
! 1892:
! 1893: /**
1.1 misho 1894: * \brief Allows to check if a user have defined a command.
1895: *
1896: * Once an argument is installed the user may or may not define it. To
1897: * define it simply means to use this argument as command line
1898: * option. This function allows to check if an argument was used for
1899: * the current command line option.
1900: *
1901: * This function is expecting to receive the argument name to lookup
1902: * not the short name. User may be using the short name to invoke the
1903: * argument but the lookup is allways done by using the argument name.
1904: *
1905: * \return TRUE if argument was defined or FALSE if not.
1906: **/
1907: int exarg_is_defined (char * arg_name)
1908: {
1909: ExArgNodeOption * node;
1910:
1911: /* perform some environment checks */
1912: if (arg_name == NULL)
1913: return 0;
1914:
1915: if (argument_options == NULL)
1916: return 0;
1917:
1918: node = exarg_lookup_node (arg_name);
1919: if (node == NULL) {
1920: return 0;
1921: }
1922: return node->is_defined;
1923: }
1924:
1925: /**
1926: * @brief Allows to check several values to be defined at the same time.
1927: *
1928: * This allows to check if several command line options have been
1929: * defined at the same time.
1930: * Example:
1931: * \code
1932: * if (exarg_is_definedv ("param1", "param2", NULL)) {
1933: * //param1 and param2 have been defined by the user
1934: * }
1935: * \endcode
1936: *
1937: * This is a short way for actually doing:
1938: * \code
1939: * if (exarg_is_defined ("param1") && exarg_is_defined ("param2")) {
1940: * // param1 and para2 have been defined by the user
1941: * }
1942: * \endcode
1943: *
1944: * Do not forget to pass a NULL value for the last item.
1945: *
1946: * @return TRUE if all values are defined, otherwise FALSE.
1947: */
1948: int exarg_is_definedv (char * first_value, ...)
1949: {
1950: int result = 1;
1951: char * string_value;
1952: va_list args;
1953:
1954: if (first_value == NULL)
1955: return 0;
1956:
1957: /* check first value */
1958: if (!exarg_is_defined (first_value))
1959: return 0;
1960:
1961: /* open stdargs */
1962: va_start (args, first_value);
1963: string_value = va_arg (args, char *);
1964:
1965: /* check for last NULL value */
1966: while ((string_value != NULL) && (* string_value)) {
1967: /* check next value */
1968: result = result && exarg_is_defined (string_value);
1969:
1970: /* get next value */
1971: string_value = va_arg (args, char *);
1972: }
1973:
1974: /* return current value */
1975: va_end (args);
1976: return result;
1977: }
1978:
1979: /**
1980: * \brief Allows to get defined string for a given command line.
1981: *
1982: * Returns the value associated with the argument name. The returned
1983: * value must not be deallocated. If it is needed a string copy use
1984: * \ref exarg_get_string_alloc.
1985: *
1986: * \return The value associated with the param or NULL if fail.
1987: **/
1988: char * exarg_get_string (char * arg_name)
1989: {
1990: ExArgNodeOption * node;
1991:
1992: if (arg_name == NULL)
1993: return NULL;
1994:
1995: if (argument_options == NULL)
1996: return NULL;
1997:
1998: node = exarg_lookup_node (arg_name);
1999: if (node == NULL) {
2000: exarg_msg ("error: calling to get string value for: %s, but this argument isn't defined..",
2001: arg_name);
2002: }
2003: if (node->type != EXARG_STRING) {
2004: exarg_msg ("error: calling to get string value for: %s, but the argument wasn't defined as EXARG_STRING..",
2005: arg_name);
2006: }
2007:
2008: return node->string_value;
2009: }
2010:
2011: /**
2012: * \brief Allows to get defined string for a given command line allocating the result.
2013: *
2014: * Returns the value associated with the argument name. The returned
2015: * value must be <b>deallocated</b> using g_free. You can also use
2016: * \ref exarg_get_string to get a value that doesn't need to be
2017: * unrefered.
2018: *
2019: * \return The value associated with the param or NULL if fail.
2020: **/
2021: char * exarg_get_string_alloc (char * arg_name)
2022: {
2023: char * string_value;
2024:
2025: string_value = exarg_get_string (arg_name);
2026: if (string_value == NULL)
2027: return NULL;
2028: return exarg_strdup (string_value);
2029: }
2030:
2031: /**
2032: * \brief Allows to get int value for a given command line argument.
2033: *
2034: * Returns the value associated with the argument name. The returned
2035: * may be 0 which means the user may not defined that argument or may
2036: * defined it by using the 0 as value. To avoid confusing cases you
2037: * should use \ref exarg_is_defined to know if the user have used that
2038: * argument and then call this function.
2039: *
2040: * \return the value defined for this argument. If the argument
2041: * is null or the exarg is not initialized the function will return -1.
2042: **/
2043: int exarg_get_int (char * arg_name)
2044: {
2045: ExArgNodeOption * node;
2046:
2047: if (arg_name == NULL)
2048: return -1;
2049: if (argument_options == NULL)
2050: return -1;
2051:
2052: node = exarg_lookup_node (arg_name);
2053: if (node == NULL) {
2054: exarg_msg ("error: calling to get int value for: %s, but this argument isn't defined..",
2055: arg_name);
2056: }
2057:
2058: if (node->type != EXARG_INT) {
2059: exarg_msg ("error: calling to get int value for: %s, but the argument wasn't defined as EXARG_INT..",
2060: arg_name);
2061: }
2062:
2063: return node->int_value;
2064: }
2065:
2066: /**
2067: * \brief Returns free params defined at command line.
2068: *
2069: * Every value which is not an argument is considered to be a
2070: * parameter. All of them are stored and retrieved by using this
2071: * function and the following functions:
2072: *
2073: * - \ref exarg_param_get
2074: * - \ref exarg_param_next
2075: *
2076: * An example about using this function could be the next. A program
2077: * have defined several arguments using the function \ref
2078: * exarg_install_arg but that program also needs to receive several
2079: * file path.
2080: *
2081: * Once the \ref exarg_parse have detected all argument, all
2082: * parameters are stored, and this function provides access to the
2083: * first argument *found. Then a call to \ref exarg_param_get is
2084: * required to get the *argument value and a call to \ref
2085: * exarg_param_next to get a *reference to the next argument.
2086: *
2087: *
2088: * A program which may receive the argument --save-all but also several
2089: * files:
2090: *
2091: * \code
2092: * a_program --save-all file1 file2 file3
2093: * \endcode
2094: *
2095: * Will need to call this function to get the list: file1 file2 and
2096: * file3.
2097: *
2098: * \return The first param provided to the program. The returned value
2099: * must not be deallocated.
2100: */
2101: ExArgument * exarg_get_params ()
2102: {
2103: return params;
2104: }
2105:
2106: /**
2107: * @brief Allows to get the string value that is represeting the argument received.
2108: *
2109: * @param arg The argument that was received by the program.
2110: *
2111: * @return An string reference that must not be deallocated.
2112: */
2113: const char * exarg_param_get (ExArgument * arg)
2114: {
2115: /* check for null value received */
2116: if (arg == NULL)
2117: return NULL;
2118:
2119: /* return the string value inside */
2120: return arg->string;
2121: }
2122:
2123: /**
2124: * @brief Allows to get the next parameters defined at the command
2125: * line option that is following the argument provided.
2126: *
2127: * @param arg The argument which is previous to the argument to be
2128: * returned.
2129: *
2130: * @return An argument reference to the next or NULL if there are no
2131: * more arguments.
2132: */
2133: ExArgument * exarg_param_next (ExArgument * arg)
2134: {
2135: /* check for null value received */
2136: if (arg == NULL)
2137: return NULL;
2138:
2139: /* return the next argument */
2140: return arg->next;
2141: }
2142:
2143:
2144: /**
2145: * @brief Allows to get the number of parameters that were defined by
2146: * the user.
2147: *
2148: * Check also the following function \ref exarg_get_params_num.
2149: *
2150: * @return The number of parameters starting from 0.
2151: */
2152: int exarg_get_params_num ()
2153: {
2154: ExArgument * arg = NULL;
2155: int result = 0;
2156:
2157: if (params == NULL)
2158: return 0;
2159:
2160: /* count the number of params */
2161: arg = params;
2162: while (arg != NULL) {
2163: /* update the count */
2164: result++;
2165:
2166: /* update to the next */
2167: arg = arg->next;
2168:
2169: } /* end while */
2170:
2171: /* return current count */
2172: return result;
2173: }
2174:
2175: /* @} */
2176:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>