aboutsummaryrefslogtreecommitdiffstats
path: root/flx/arg.c
blob: 8b7c112f9055d7ea0672c6c8746a8ead55c63f4d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>

#include "flx.h"
#include "arg.h"


#define TUNDEF   1
#define TSHORT   2
#define TLONG    4

char    *Progname ;


/* show usage for program with ParamOptions global pointer 
 * message : message to see (stdarg form), NULL mean no message
 * exit with value 1
 */
void arg_usage(t_param *p, char *message, ...) {
    va_list argp;
    
    if (message) {
	va_start(argp, message);
	fprintf(stderr, "Error: ");
	vfprintf(stderr, message, argp);
	fprintf(stderr, "\n");
	va_end(argp);
    }
    fprintf(stderr, "%s %s, %s\n", PROGRAM_NAME, PROGRAM_VERSION, COPYRIGHT);
    fprintf(stderr, "usage: %s [options] [...]\n", Progname);
    while(p && p->optnum) {
	fprintf(stderr, "\t%s\n", p->help);
	p++;
    }
    exit(1);
}

/* return programme name
 * pathprogname : argv[0]
 * (return) pointer to the programme name in this string
 */
char *progname(char *pathprogname) {
    if (Progname) return (Progname);
    if ((Progname = strrchr(pathprogname, '/'))) 
	Progname++;   
    else 
	Progname = pathprogname;
    return (Progname);
}

/* argument checking
 * argc, argv : main parameters 
 * (return): 1 if no error
 */
int arg_init(int argc, char **argv, t_param *paramoptions, int (*paramfct)()) {
    char    *flag;
    int     ft = TUNDEF, opt, ret, nbargc = 1;
    t_param *p = NULL;
    
    argc--; argv++; flag = *argv;
    while (argc > 0) {

	opt = -1;
	// printf("%d,%d: %s -> %s\n", argc, ft, *argv, flag);
	if (*flag == '-' && ft == TUNDEF)      ft = TSHORT; 
	else if (*flag == '-' && ft == TSHORT) ft = TLONG;
	else if (*flag == 0 && ft == TLONG)    break;
	else if (*flag == 0 && ft == TSHORT)   break;
	else if (ft == TSHORT) {
	    for (p = paramoptions; p->optnum && p->shortopt != *flag; p++);
	    opt = p->optnum;
	}
	else if (ft == TLONG) {
	    for (p = paramoptions; p->optnum && 
		     (!p->longopt || strcmp(flag, p->longopt)); p++);
	    opt = p->optnum;
	}
	if (opt == -1 && ft != TUNDEF ) { flag++; continue; }
	if (opt == 0 && ft == TSHORT) 
	    arg_usage(paramoptions, "Unkwnon short argument: -%c", *flag);
	if (opt == 0 && ft == TLONG) 
	    arg_usage(paramoptions, "Unkwnon long argument: --%s", flag);
	if (opt > 0 && p && argc < p->minarg)
	    arg_usage(paramoptions, "Missing argument: %s", p->help);
	
	if ((ret = paramfct(opt, p, &flag, argv)) == -1 && ft != TUNDEF)
	    arg_usage(paramoptions, "Bad argument: %s", p->help);
	else if (ret == -1) 
	    break;
	else {
	    argc -= ret; argv += ret;
	    nbargc += ret;
	}

	if (!*(flag+1) || ft != TSHORT) {
	    argc--; argv++;
	    nbargc++;
	    ft = TUNDEF;
	    flag = *argv;
	} 
	else
	    flag++;
    }
    return (nbargc);
}