Annotation of gpl/axl/knife/exarg.c, revision 1.1.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>