Sophie

Sophie

distrib > Mandriva > 2007.0 > i586 > by-pkgid > ad1ba1135a9c9eeffc2e538163e00373 > files > 830

libCommonC++2_1.4-devel-1.4.1-1mdv2007.0.i586.rpm

\section{cmdlineopt.cpp}


\footnotesize\begin{verbatim}1 // Copyright (C) 2001 Gianni Mariani
2 //
3 // This program is free software; you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation; either version 2 of the License, or
6 // (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16 //
17 // As a special exception to the GNU General Public License, permission is
18 // granted for additional uses of the text contained in its release
19 // of Common C++.
20 //
21 // The exception is that, if you link the Common C++ library with other
22 // files to produce an executable, this does not by itself cause the
23 // resulting executable to be covered by the GNU General Public License.
24 // Your use of that executable is in no way restricted on account of
25 // linking the Common C++ library code into it.
26 //
27 // This exception does not however invalidate any other reasons why
28 // the executable file might be covered by the GNU General Public License.
29 //
30 // This exception applies only to the code released under the
31 // name Common C++.  If you copy code from other releases into a copy of
32 // Common C++, as the General Public License permits, the exception does
33 // not apply to the code that you add in this way.  To avoid misleading
34 // anyone as to the status of such modified files, you must delete
35 // this exception notice from them.
36 //
37 // If you write modifications of your own for Common C++, it is your choice
38 // whether to permit this exception to apply to your modifications.
39 // If you do not wish that, delete this exception notice.
40 //
41 
42 
43 //
44 // Example for Common C++ the command line parser interface.
45 //
46 // 
47 // This exmaple code shows how to use the command line parser provided by
48 // CommonC++.  The command line parser provides an interface which is
49 // "object oriented" such that command line parameters are true "objects".
50 //
51 // Each command line option needs to be created.  By defining "CommandOption"s
52 // statically, the C++ constructor is called when the objects are loaded and
53 // before the "main" function is called.  The constructor links itself to
54 // a list of other CommandOptionXXX in the list provided.  If no
55 // list is specified in the constructor, a default one is used. Because of
56 // the undefined nature as to the order in which constructors are called,
57 // no assumption as to the order in which the CommandOptionXXX constructors
58 // are called should be made.
59 //
60 // CommandOptionXXX classes can be used to derive specialized parameter
61 // classes that are specific to applications.  The second example shows
62 // just how this can be done.
63 //
64 
65 //
66 // Include the CommandOption definitions
67 //
68 #include <cc++/common.h>
69 
70 #include <iostream>
71 
72 #ifdef  CCXX_NAMESPACES
73 using namespace std;
74 using namespace ost;
75 #endif  
76 
77 //
78 // The following definition of options all use the list header
79 // defaultCommandOptionList (which is specified as the value of the
80 // default parameter in the constructor.  This convention would
81 // allow other object files to link into the same list and add parameters
82 // to the command line of this executable.
83 
84 CommandOptionArg        test_option1(
85         "test_option1", "p", "This option takes an argument", true
86 );
87 
88 CommandOptionNoArg      test_noarg(
89         "test_noarg", "b", "This option does not take an argument"
90 );
91 
92 CommandOptionNoArg      helparg(
93         "help", "?", "Print help usage"
94 );
95 
96 CommandOptionCollect    restoargs(
97         0, 0, "Collect all the parameters", true
98 );
99 
100 
101 //
102 // Normally this would me the regular main().  In this example
103 // this processes the first command option list.
104 //
105 int Example_main( int argc, char ** argv )
106 {
107 
108         // Create a CommandOptionParse object.  This takes the
109         // defaultCommandOptionList and parses the command line arguments.
110         // 
111         CommandOptionParse * args = makeCommandOptionParse(
112                 argc, argv,
113                 "CommonC++ command like option interface.  This is example\n"
114                 "       code only."
115         );
116 
117         // If the user requested help then suppress all the usage error
118         // messages.
119         if ( helparg.numSet ) {
120                 cerr << args->printUsage();
121                 ::exit(0);
122         }
123 
124         // Print usage your way.
125         if ( args->argsHaveError() ) {
126                 cerr << args->printErrors();
127                 cerr << args->printUsage();
128                 ::exit(1);
129         }
130 
131         // Go off and run any option specific task
132         args->performTask();
133 
134         // print all the -p options
135         for ( int i = 0; i < test_option1.numValue; i ++ ) {
136                 cerr << "test_option1 = " << test_option1.values[ i ] << endl;
137         }
138 
139         // print all the other options.
140         for ( int i = 0; i < restoargs.numValue; i ++ ) {
141                 cerr << "restoargs " << i << " : " << restoargs.values[ i ] << endl;
142         }
143 
144         delete args;
145 
146         return 0;
147 }
148 
149 
150 // 
151 // This shows how to build a second option list.  The example is similar to
152 // the first as well as it shows how to derive a new command object.
153 //
154 
155 CommandOption * TestList = 0;
156 
157 extern CommandOptionRest        test_restoargs;
158 
159 
160 #include <unistd.h>
161 #include <sys/types.h>
162 #include <sys/stat.h>
163 #include <fcntl.h>
164 #include <strstream>
165 #include <errno.h>
166 #include <string.h>
167 #include <stdlib.h>
168 #include <sys/wait.h>
169 
170 
171 //
172 // This is a parameter class derived from CommandOptionArg that takes
173 // a file name parameter and detects wether the file is accessible
174 // flagging an error if the file is inaccessible to read.
175 //
176 class file_option : public CommandOptionArg {
177 public:
178 
179         // the constructor calls the regular CommandOptionArg constructor
180         // and all should be well.
181         file_option(
182                 const char      * in_option_name,
183                 const char      * in_option_letter,
184                 const char      * in_description,
185                 bool              in_required = false,
186                 CommandOption  ** pp_next = & defaultCommandOptionList
187         )
188                 : CommandOptionArg(
189                         in_option_name,
190                         in_option_letter,
191                         in_description,
192                         in_required,
193                         pp_next
194                 )
195         {
196         }
197 
198         //
199         // When parsing is done check if the file is accessible and register
200         // an error with the CommandOptionParse object to let it know so.
201         virtual void parseDone( CommandOptionParse * cop )
202         {
203                 if ( numValue ) {
204                         if ( ::access( values[ numValue - 1 ], R_OK ) ) {
205                                 int     errno_s = errno;
206                                 strstream msg;
207                                 msg << "Error: " << optionName << " '" << values[ numValue - 1 ];
208                                 msg << "' : " << ::strerror( errno_s );
209                                 
210                                 cop->registerError( msg.str() );
211                         }
212                 }
213         }
214 
215         //
216         // Open said file.  Do some operations on things - like open the file.
217         int OpenFile()
218         {
219                 // Should put in way more error handling here ...
220                 return ::open( values[ numValue - 1 ], O_RDONLY );
221         }
222 
223         //
224         // The most elaborate way to spit the contents of a file
225         // to standard output.
226         pid_t   pid;
227         virtual void performTask( CommandOptionParse * cop )
228         {
229                 pid = ::fork();
230 
231                 if ( pid ) {
232                         return;
233                 }
234                 
235                 int fd = OpenFile();
236                 if ( fd < 0 ) {
237                         int errno_s = errno;
238                         cerr
239                                 << "Error:  '"
240                                 << values[ numValue - 1 ]
241                                 << "' : "
242                                 << ::strerror( errno_s )
243                         ;
244 
245                         ::exit( 1 );
246                 }
247                 dup2(fd, 0);
248                 ::execvp( test_restoargs.values[0], (char**) test_restoargs.values );
249                 ::exit(1);
250         }
251 
252         ~file_option()
253         {
254                 if ( pid <= 0 ) return;
255                 int status;
256 		::wait(&status);
257         }
258 };
259 
260 
261 //
262 // This is the linked list head for the options in the second example.
263 // Note that the first example used the default value defined in the
264 // method.  Here it is explicitly specified as TestList in all the following
265 // CommandOption constructors.
266 
267 file_option     test_file(
268         "test_file", "f", "Filename to read from", true, &TestList
269 );
270 
271 CommandOptionNoArg      test_xnoarg(
272         "test_xnoarg", "b", "This option does not take an argument", false, &TestList
273 );
274 
275 CommandOptionNoArg      test_helparg(
276         "help", "?", "Print help usage", false, &TestList
277 );
278 
279 CommandOptionRest       test_restoargs(
280         0, 0, "Command to be executed", true, &TestList
281 );
282 
283 //
284 // in most apps this would be the regular "main" function.
285 int Test_main( int argc, char ** argv )
286 {
287         CommandOptionParse * args = makeCommandOptionParse(
288                 argc, argv,
289                 "Command line parser X test.\n"
290                 "       This example is executed when the command ends in 'x'\n"
291                 "       It shows how the -f parameter can be specialized.\n",
292                 TestList
293         );
294 
295         // If the user requested help then suppress all the usage error
296         // messages.
297         if ( test_helparg.numSet ) {
298                 cerr << args->printUsage();
299                 ::exit(0);
300         }
301 
302         // Print usage your way.
303         if ( args->argsHaveError() ) {
304                 cerr << args->printErrors();
305                 cerr << "Get help by --help\n";
306                 ::exit(1);
307         }
308 
309         // Go off and run any option specific task
310         args->performTask();
311 
312         for ( int i = 0; i < test_file.numValue; i ++ ) {
313                 cerr << "test_file = " << test_file.values[ i ] << endl;
314         }
315         
316         for ( int i = 0; i < test_restoargs.numValue; i ++ ) {
317                 cerr << "test_restoargs " << i << " : " << test_restoargs.values[ i ] << endl;
318         }
319 
320         delete args;
321 
322         return 0;
323 }
324 
325 
326 //
327 // This switches behaviour of this executable depending of wether it is
328 // invoked with a command ending in "x".  This is mimicking for example
329 // the behaviour of bunzip2 and bzip2.  These executables are THE SAME
330 // file i.e.
331 //   0 lrwxrwxrwx    1 root     root    5 Oct 11 14:04 /usr/bin/bunzip2 -> bzip2*
332 // and the behaviour is determined by the executable name.
333 //
334 // This example is way more complex than the way most people will end up
335 // using feature.
336 
337 int main( int argc, char ** argv )
338 {
339 
340         int i = ::strlen( argv[ 0 ] );
341 
342         // determine which real "main" function do I call
343         if ( argv[ 0 ][ i - 1 ] == 'x' ) {
344                 return Test_main( argc, argv );
345         } else {
346                 return Example_main( argc, argv );
347         }
348 
349 }
\end{verbatim}
\normalsize