ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/gclib/gclib/GArgs.cpp
Revision: 2
Committed: Mon Mar 22 22:03:27 2010 UTC (9 years, 8 months ago) by gpertea
File size: 7464 byte(s)
Log Message:
added my gclib source files

Line File contents
1 #include <stdlib.h>
2 #include <string.h>
3 #include "GArgs.h"
4 #include <ctype.h>
5
6 #define TRACE 1
7
8 #include "GBase.h"
9
10 //GArgs::is_opt="1"; //just to have a non-NULL value for switch testing
11
12
13 GArgs::GArgs(int argc, char* const argv[], const char* format, bool nodigitopts) {
14 /* format is:
15 <letter>[:] for e.g. p:hT <- -p testing -ptesting -h -T
16 <string>= for e.g. PID=S= <- PID=50 S=3.5
17 This means that the = options, if present, must NEVER be given after
18 dashed switches (non-value) directly
19 */
20
21 //parse format string first:
22 const char* fstr=format;
23 fmtcount=0;
24 count=0;
25 nonOptCount=0;
26 nonOptPos=0;
27 optPos=0;
28 errarg=0;
29 args=NULL;
30 fmt=NULL;
31 int fmtlen=strlen(format);
32 while (fstr-format < fmtlen ) {
33 int l=strcspn(fstr, ":=");
34 if (fstr[l]=='\0') { //end of string reached
35 //all previous chars are just switches:
36 GREALLOC(fmt, (fmtcount+l)*sizeof(fmtdef));
37 //store each switches
38 for (int i=0; i<l;i++) {
39 GCALLOC(fmt[fmtcount+i].opt, 2); //one char length
40 fmt[fmtcount+i].opt[0]=fstr[i];
41 fmt[fmtcount+i].type = 0;
42 }
43 fmtcount+=l;
44 break;
45 }
46 else {
47 if (fstr[l]==':') {
48 //fstr[l-1] is an argument, but all the previous are just switches
49 GREALLOC(fmt, (fmtcount+l)*sizeof(fmtdef));
50 //store each switches AND the option
51 for (int i=0; i<l;i++) {
52 GCALLOC(fmt[fmtcount+i].opt, 2); //one char length
53 fmt[fmtcount+i].opt[0]=fstr[i];
54 fmt[fmtcount+i].type = (i==l-1)?1:0;
55 }
56 fmtcount+=l;
57 }
58 else { // fstr[l]=='=' case!
59 //all these chars are one = style argument
60 GREALLOC(fmt, (fmtcount+1)*sizeof(fmtdef));
61 GMALLOC(fmt[fmtcount].opt, l+1);
62 strncpy(fmt[fmtcount].opt, fstr, l);
63 fmt[fmtcount].opt[l]='\0';
64 fmt[fmtcount].type=2;
65 fmtcount++;
66 }
67 fstr+=l+1;
68 }
69 }
70 //---- that was the parsing of the format string
71 //now parse the arguments based on given format specification
72 int p=1; //skip program name
73 int f=0;
74 //GMessage("argc=%d\n", argc);
75 while (p<argc) {
76 if (argv[p][0]=='-') { //dashed argument ?
77 int cpos=1;
78 char c=argv[p][cpos];
79 if (c==0 || (nodigitopts && isdigit(c))) {
80 //special case: plain argument '-' or negative number
81 GREALLOC(args, (count+1)*sizeof(argdata));
82 args[count].opt=NULL;
83 if (c==0) {
84 GCALLOC(args[count].value, 2);
85 args[count].value[0]='-';
86 }
87 else {
88 args[count].value=Gstrdup(argv[p]);
89 }
90 count++;
91 nonOptCount++;
92 }
93 else { //dashed argument or switch
94 COLLAPSED:
95 if ((f=validOpt(c))>=0) {
96 if (fmt[f].type==0) {//switch type
97 GREALLOC(args, (count+1)*sizeof(argdata));
98 GCALLOC(args[count].opt, 2);
99 args[count].opt[0]=c;
100 GCALLOC(args[count].value, 1);
101 count++;
102 // only switches can be grouped with some other switches or options
103 if (argv[p][cpos+1]!='\0') {
104 cpos++;
105 c=argv[p][cpos];
106 goto COLLAPSED;
107 }
108 }
109 else
110 if (fmt[f].type==1) { //dash argument
111 GREALLOC(args, (count+1)*sizeof(argdata));
112 GCALLOC(args[count].opt, 2);
113 args[count].opt[0]=c;
114 if (argv[p][cpos+1]=='\0') {
115 if (p+1<argc) { //value is the whole next argument
116 p++;
117 GMALLOC(args[count].value, strlen(argv[p])+1);
118 strcpy(args[count].value, argv[p]);
119 }
120 else {
121 errarg=p;
122 return;
123 }
124 }
125 else { //value immediately follows the dash-option
126 GMALLOC(args[count].value, strlen(argv[p])-cpos);
127 strcpy(args[count].value, (argv[p]+cpos+1));
128 //GMessage("args[%d].value = '%s'",count, args[count].value);
129 }
130 count++;
131 }
132 else {//inconsistent type
133 errarg=p;
134 return;
135 }
136 } //was validOpt
137 else { //option not found in format definition!
138 errarg=p;
139 return;
140 }
141 }
142 }
143 else {//not a dashed argument
144 char* e=strchr(argv[p],'=');
145 if (e!=NULL && strchr(format,'=')!=NULL && e!=argv[p] && *(e-1)!='\\') {
146 //this must be an '=' option
147 //yet the '=' char can be preceded by a '\' in order to not be parsed
148 //as a = option
149 char part[128];
150 strncpy(part, argv[p], e-argv[p]);
151 part[e-argv[p]]='\0';
152 if ((f=validOpt(part))>=0 && fmt[f].type==2) {
153 GREALLOC(args, (count+1)*sizeof(argdata));
154 args[count].opt=Gstrdup(part);
155 if (strlen(argv[p])-strlen(part)>0) {
156 GMALLOC(args[count].value, strlen(argv[p])-strlen(part)+1);
157 strcpy(args[count].value, e+1);
158 }
159 else {
160 args[count].value=NULL;
161 }
162 count++;
163 }
164 else { //error - format does not match this '=' argument
165 errarg=p;
166 return;
167 }
168 }
169 else { //it seems it's just a plain argument, like a filename, etc.
170 GREALLOC(args, (count+1)*sizeof(argdata));
171 args[count].opt=NULL; //it's not an option
172 args[count].value=Gstrdup(argv[p]);
173 count++;
174 nonOptCount++;
175 }
176 }
177 p++;//check next arg string
178 }
179 }
180
181 GArgs::~GArgs() {
182 int i;
183 for (i=0; i<fmtcount; i++)
184 GFREE(fmt[i].opt);
185 GFREE(fmt);
186 for (i=0; i<count; i++) {
187 GFREE(args[i].opt);
188 GFREE(args[i].value);
189 }
190 GFREE(args);
191 }
192
193 int GArgs::validOpt(char o) {
194 for (int i=0; i<fmtcount; i++)
195 if (fmt[i].opt[0]==o && fmt[i].opt[1]=='\0') return i;
196 return -1;
197 }
198
199 int GArgs::validOpt(char* o) {
200 for (int i=0; i<fmtcount; i++)
201 if (strcmp(fmt[i].opt, o)==0) return i;
202 return -1;
203 }
204
205 int GArgs::isError() { // returns the offending argv position or 0 if no error
206 return errarg;
207 }
208
209 char* GArgs::getOpt(const char* o) { /* retrieve the value for option o
210 returns
211 NULL if option not given at all
212 !=NULL if boolean option was given
213 opt.value if value option was given
214 */
215 for (int i=0; i<count; i++)
216 if (args[i].opt!=NULL && strcmp(args[i].opt, o)==0)
217 return args[i].value;
218 return NULL;
219 }
220
221 char* GArgs::getOpt(const char o) {
222 for (int i=0; i<count; i++)
223 if (args[i].opt!=NULL && args[i].opt[0]==o && args[i].opt[1]=='\0')
224 return args[i].value;
225 return NULL;
226 }
227
228 int GArgs::startNonOpt(){ //reset iteration through non-dashed arguments
229 //returns the number of non-dashed arguments
230 nonOptPos=0;
231 return nonOptCount;
232 }
233
234
235 char* GArgs::nextNonOpt() { //get the next non-dashed argument
236 //or NULL if no more
237 for (int i=nonOptPos;i<count;i++)
238 if (args[i].opt==NULL) {
239 nonOptPos=i+1;
240 return args[i].value;
241 }
242 return NULL;
243 }
244
245 int GArgs::startOpt(){ //reset iteration through non-dashed arguments
246 //returns the number of non-dashed arguments
247 optPos=0;
248 return count-nonOptCount;
249 }
250
251
252 char* GArgs::nextOpt() { //get the next non-dashed argument
253 //or NULL if no more
254 for (int i=optPos;i<count;i++)
255 if (args[i].opt!=NULL) {
256 optPos=i+1;
257 return args[i].opt;
258 }
259 return NULL;
260 }