ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/gclib/tophat_cpp/GArgs.cpp
Revision: 29
Committed: Tue Aug 2 21:24:54 2011 UTC (8 years, 2 months ago) by gpertea
File size: 7332 byte(s)
Log Message:
adding tophat source work

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