00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "strl.hpp"
00027 #include "xalloc.h"
00028 #include "clargs.h"
00029 #include "uti.h"
00030
00031
00032 #ifdef __OS_UNIX__
00033 #include <unistd.h>
00034 #else
00035 #include <io.h>
00036 #endif
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 VOID clargs2props( int argc, char *argv[], KVStrList &props,
00149 StrList &files, const char *format, const char *options, const char*date )
00150
00151 {
00152 INT i,nsw;
00153 KVStrList opts(options);
00154 KVStrList fmt(format);
00155 Lix p;
00156 clasw *cl;
00157 char *val, *df;
00158 char **sw;
00159 BOOL any, clshow, help, version;
00160
00161 fmt.remove_prefix("-");
00162 p=fmt.seek("*"); any=(p!=NULL); if (any) fmt.del(p);
00163 clshow=opts.bval("CLShow",TRUE);
00164 help=opts.bval("Help",TRUE);
00165 version=strcmp(opts.val("Version","?"),"no");
00166 if (clshow) fmt.add("CLShow","b");
00167 if (help) fmt.add("Help","b");
00168 if (version) fmt.add("Version","b");
00169 LONG nnsw=fmt.length();
00170 nsw = (INT)nnsw;
00171 cdie_beep(nsw!=nnsw,"clargs2props: too many entries (%ld) for this machine's word length",(long)nnsw);
00172 sw = (char**)xmalloc(sizeof(char*)*(nsw+1));
00173 for (i=0, p=fmt.first(); i<nsw; i++, p=fmt.next(p))
00174 sw[i] = xstrdup((const char *)(fmt.itemkey(p)));
00175 sw[nsw]=NULL;
00176
00177 _clargs_case_sensitive=1;
00178 df=NULL;
00179 if (opts.contains("DefCfgFile")) df = xstrdup(opts.val("DefCfgFile"));
00180 else if (! opts.bval("NoDefCfgFile",FALSE))
00181 df=path_src2destp(argv[0]+path_namepos(argv[0]),".cfg","");
00182
00183 cl = clasw_construct(argc, argv, (const char **)sw, df );
00184
00185 clasw_restart(cl);
00186 while (1) {
00187 String k;
00188 i=clasw_getsw(cl,&val,any);
00189 if (i==-1) break;
00190 if (i>=0) {
00191 p=fmt.seek(sw[i]);
00192 k=fmt.itemkey(p);
00193 if (fmt.itemval(p).length()==0) {
00194 cdie_beep(*val!=0,"Error: command line arg doesn't need value (-%s=%s)",(const char*)k,val);
00195 props.add(k,"");
00196 }
00197 else {
00198 if (((const char *)fmt.itemval(p))[0]=='b')
00199 props.add(k,props.tob(k,val));
00200 else {
00201 cdie_beep(*val==0,"Error: incomplete command line arg (-%s=???)",(const char *)k);
00202 switch (((const char *)fmt.itemval(p))[0]) {
00203 case 'i': props.add(k,props.toi(k,val)); break;
00204 case 'l': props.add(k,props.tol(k,val)); break;
00205 case 'f': props.add(k,props.tof(k,val)); break;
00206 case 'd': props.add(k,props.tod(k,val)); break;
00207 case 's': props.add(k,val); break;
00208 case '{': props.add(k,val); break;
00209 default: die_beep("Error: unknown command line switch type (%c)",((const char *)fmt.itemval(p))[0]);
00210 }
00211 }
00212 }
00213 }
00214 else {
00215 char *ss=strchr(val,'=');
00216 cdie_beep(ss==val,"Error: invalid command line arg (-%s)",val);
00217 if (!ss) props.add(val,"");
00218 else { String k(val,(int)(ss-val)); props.add(k,ss+1); }
00219 }
00220
00221 if (help && props.bval("Help",FALSE) && opts.bval("HelpExit",TRUE)) break;
00222 }
00223
00224 if (version) {
00225 if (props.bval("Version",FALSE)) {
00226 std::cerr << "Version " << opts.val("Version","?") << " compiled "
00227 << date << std::endl;
00228 }
00229 if (opts.bval("EraseAuto",TRUE)) props.erase("Version");
00230 }
00231
00232 if (help) {
00233 if (props.bval("Help",FALSE)) {
00234 if (opts.contains("Description"))
00235 std::cerr << opts.val("Description") << std::endl;
00236 std::cerr << "Usage: " << argv[0] << " [-switches]";
00237 if (opts.contains("MyFiles")) std::cerr << " " << opts.val("MyFiles");
00238 if (opts.contains("Files")) std::cerr << " <files>";
00239 else if (opts.contains("File")) std::cerr << " <file>";
00240 if (opts.contains("Dest")) std::cerr << " <dest>";
00241 else if (opts.contains("OpDest")) std::cerr << " [<dest>]";
00242 std::cerr << std::endl << std::endl;
00243 if (opts.bval("HelpSort",TRUE)) fmt.sort();
00244 INT lines=0;
00245 for (Lix q=fmt.first(); q!=0; q=fmt.next(q)) {
00246 std::cerr << " -"<< fmt.itemkey(q);
00247 switch (((const char *)fmt.itemval(q))[0]) {
00248 case 'i': std::cerr << "=<integer>"; break;
00249 case 'l': std::cerr << "=<long integer>"; break;
00250 case 'f': std::cerr << "=<float>"; break;
00251 case 'd': std::cerr << "=<double float>"; break;
00252 case 'b': std::cerr << "=<boolean>"; break;
00253 case 's': std::cerr << "=<string>"; break;
00254 case '{': std::cerr << "=" << fmt.itemval(q); break;
00255 case '\0': break;
00256 default: die_beep("Error: unknown command line switch type (%c)",((const char *)fmt.itemval(q))[0]);
00257 }
00258 std::cerr << std::endl;
00259 lines++;
00260 if ((lines>=15)&&(!opts.bval("NoScrollPause",FALSE))&&isatty(2)) {
00261 lines=0;
00262 fprintf(stderr, "-- Press ENTER key to continue ---");
00263 getchar();
00264 }
00265 }
00266 std::cerr << " -CfgFile=<fname>" << std::endl;
00267 std::cerr << " -ArgFile=<fname>" << std::endl;
00268
00269 if (any) std::cerr << " -???=???"<< std::endl;
00270 std::cerr << "----" << std::endl;
00271 if (opts.bval("HelpPause",FALSE)&&isatty(2)) {
00272 fprintf(stderr, "-- Press ENTER key to continue ---");
00273 getchar();
00274 }
00275 if (opts.bval("HelpExit",TRUE)) exit(0);
00276 }
00277 if (opts.bval("EraseAuto",TRUE)) props.erase("Help");
00278
00279 }
00280
00281 clasw_restart(cl);
00282 while ((val=clasw_getparg(cl))!=NULL) files.append(val);
00283
00284 clasw_destruct(cl);
00285 for (i=0; i<nsw; i++) xfree(sw[i]);
00286 xfree(sw);
00287 if (df) xfree(df);
00288
00289 if (clshow) {
00290 if (props.bval("CLShow",FALSE)) {
00291 if (opts.bval("EraseAuto",TRUE)) props.erase("CLShow");
00292 std::cerr << "Command Line flags:\n" << props
00293 << "Command Line files:\n" << files << "----\n";
00294 }
00295 if (opts.bval("EraseAuto",TRUE)) props.erase("CLShow");
00296 }
00297
00298 const char *hmsg= (help)? ", use -Help to get help":"";
00299 if (opts.contains("MyFiles")) {
00300 }
00301 else if (opts.contains("Files")) {
00302 cdie_beep(files.length()<1,"Error: must specify one or more files%s.",hmsg);
00303 cdie_beep(opts.contains("Dest") && (files.length()<2),"Error: must specify dest%s.",hmsg);
00304 }
00305 else if (opts.contains("File")) {
00306 cdie_beep(files.length()<1,"Error: must specify one file%s.",hmsg);
00307 cdie_beep( (files.length()>2) ||
00308 (!(opts.contains("Dest")||opts.contains("OpDest")) && (files.length()==2)),
00309 "Error: must specify only one file%s.",hmsg);
00310 cdie_beep( (files.length()==1) && opts.contains("Dest"),
00311 "Error: must specify one dest%s.",hmsg);
00312 }
00313 else if (opts.contains("Dest")) {
00314 cdie_beep(files.length()<1,"Error: must specify one dest%s.",hmsg);
00315 cdie_beep(files.length()>1,"Error: must specify only one dest%s.",hmsg);
00316 }
00317 else {
00318 cdie_beep(files.length()>0,"Error: commandline files are not allowed.");
00319 }
00320 }
00321
00322