Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/pqt/cloptions/OptionProcessor.java


1   //AutoRIB
2   // Copyright © 1998 - 2002, P W Quint
3   //
4   // Contact: autorib00@aol.com
5   //
6   // This library is free software; you can redistribute it and/or
7   // modify it under the terms of the GNU General Public
8   // License as published by the Free Software Foundation; either
9   // version 2 of the License, or (at your option) any later version.
10  //
11  // This library is distributed in the hope that it will be useful,
12  // but WITHOUT ANY WARRANTY; without even the implied warranty of
13  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  // General Public License for more details.
15  //
16  // You should have received a copy of the GNU General Public
17  // License along with this library; if not, write to the Free Software
18  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  
20  package org.pqt.cloptions;
21  
22  import java.util.*;
23  
24  
25  
26  /**
27  
28  a class for handling command line options and parameters. The class contains one
29  
30  central routine, called process, which processes command line arguments. The class
31  
32  must be initialized using an array of items which are subclasses of the class Option.
33  
34  As the command line arguments are processed routines in these option classes are
35  
36  called, and when the process is finished it is the values in these classes which
37  
38  represent the command line options that have been set. The OptionProcessor class
39  
40  also contains various utility routines for reading items from the command line.
41  
42  Options can have either a long form (a word made up of alphabetic characters and
43  
44  '_') or a short form (a single letter). On the command line a single dash ('-')
45  
46  may be followed by one or more options in short form (providing there are no spaces
47  
48  in between the options), while a double dash ('--') is followed by a (single) option
49  
50  in long form.
51  
52  */
53  
54  public class OptionProcessor extends Object
55  
56    {
57  
58  
59  
60      Option[] clOptionArray = null;
61  
62      StringBuffer argString = null;
63  
64      int argPosn = -1;
65  
66      int savedArgPosn = -1;
67  
68      boolean matchCaseShort = true;
69  
70      boolean afterDash = false;
71  
72      /** contains any filenames (words not preceeded by a '-') read on the command
73  
74      line, in the order in which they appear */
75  
76      public Vector fileNames = new Vector(3,3);
77  
78      /** the number of options read*/
79  
80      public int optionsRead = 0;
81  
82  
83  
84      /** initialize using a given array of Option(s)
85  
86      @param optionArray the array of Options to use*/
87  
88      public OptionProcessor(Option[] optionArray)
89  
90        {
91  
92          this.clOptionArray = optionArray;
93  
94        }
95  
96  
97  
98      /**process the given array of string arguments
99  
100     @param argArray an array of String arguments - such as those passed to the
101 
102     'main' routine
103 
104     @return the number of parameters read
105 
106     @exception OptionException will be thrown if some error occurs during
107 
108     processing of an option or if an unrecognized option is found*/
109 
110     public int process(String[] argArray) throws OptionException
111 
112       {
113 
114         argString = new StringBuffer(255);
115 
116         optionsRead = 0;
117 
118         if (argArray.length == 0) return 0;
119 
120         //first convert the argArray into a single long string
121 
122         for (int i = 0; i < argArray.length; i++)
123 
124           {
125 
126             //if the current arg string contains space, put quotes around it
127 
128             boolean containsSpace = false;
129 
130             for (int j = 0; j < argArray[i].length(); j++)
131 
132               if (argArray[i].charAt(j) <= ' ')
133 
134                 {
135 
136                   containsSpace = true;
137 
138                   break;
139 
140                 }
141 
142             if (containsSpace)
143 
144               argString.append('"');
145 
146             argString.append(argArray[i]);
147 
148             if (containsSpace)
149 
150               argString.append('"');
151 
152             argString.append(' ');
153 
154           }
155 
156         //remove the extra space at the end
157 
158         argString.setLength(argString.length() - 1);
159 
160         argPosn = 0;
161 
162         //afterDash = true when we are processing multiple short options after a
163 
164         //single -
165 
166         afterDash = false;
167 
168         while (argPosn < argString.length())
169 
170           //the main loop
171 
172           {
173 
174             int c = peekCharNoSpace();
175 
176             //check if it is an option, else read in a file name (see below)
177 
178             if (c == '-')
179 
180               {
181 
182                 String optionName = null;
183 
184                 int optionChar = 0;
185 
186                 boolean matched = false;
187 
188                 c = getCharNoSpace();  //read the initial -
189 
190                 c = peekChar();
191 
192                 //now either process a single long option or multiple short ones
193 
194                 if (c == '-')
195 
196                   {
197 
198                     if (afterDash)
199 
200                       throw new OptionException("Misplaced '-' on Command Line");
201 
202                     afterDash = false;
203 
204                     optionName = getLongName();
205 
206                     for (int i = 0; i < clOptionArray.length; i++)
207 
208                       {
209 
210                         //check each option in turn for a match
211 
212                         matched = longCheck(clOptionArray[i], optionName);
213 
214                         if (matched)
215 
216                           {
217 
218                             optionsRead++;
219 
220                             //let the option read any extra parameters
221 
222                             clOptionArray[i].read(this);
223 
224                             break;
225 
226                           }
227 
228                       }
229 
230                     if (!matched)
231 
232                       throw new OptionException("Unrecognized Command Line Option --"
233 
234                          + optionName);
235 
236                   }
237 
238                 else
239 
240                   { //multiple short options
241 
242                     afterDash = true;
243 
244                     optionChar = getChar();  //returns -1 if end of line
245 
246                     while (afterDash && (optionChar != ' ') &&
247 
248                       (optionChar >= 0))
249 
250                       {
251 
252                         for (int i = 0; i < clOptionArray.length; i++)
253 
254                           {
255 
256                             //check the option array
257 
258                             matched = shortCheck(clOptionArray[i], optionChar);
259 
260                             if (matched)
261 
262                               {
263 
264                                 optionsRead++;
265 
266                                 //read in any extra params
267 
268                                 clOptionArray[i].read(this);
269 
270                                 break;
271 
272                               }
273 
274                           }
275 
276                         if (!matched)
277 
278                           throw new OptionException("Unrecognized Command Line Option -"
279 
280                             + (char) optionChar);
281 
282                         if (afterDash)
283 
284                           optionChar = getChar();
285 
286                         if ((optionChar < 0) || (optionChar == ' '))
287 
288                           afterDash = false;
289 
290                       }
291 
292                   }
293 
294               }
295 
296             else
297 
298               {
299 
300                 //read in a filename
301 
302                 String fileName = getStringValue();
303 
304                 fileNames.addElement(fileName);
305 
306               }
307 
308           }
309 
310         return optionsRead + fileNames.size();
311 
312       }
313 
314 
315 
316     /** sets whether short options are case sensitive (long options never are)
317 
318     @param flag true if short options are case sensitive, false otherwise
319 
320     */
321 
322 
323 
324     public void matchCase(boolean flag)
325 
326       {
327 
328         matchCaseShort = flag;
329 
330       }
331 
332 
333 
334     /**
335 
336     get a single character from the command line options string
337 
338     @return the character read, or -1 if the end of the string is reached
339 
340     */
341 
342     public int getChar()
343 
344       {
345 
346         int rval = -1;
347 
348         if (argString != null)
349 
350           {
351 
352             if (argPosn < argString.length())
353 
354               rval = argString.charAt(argPosn);
355 
356              argPosn++;
357 
358            }
359 
360         return rval;
361 
362       }
363 
364 
365 
366 
367 
368     /**
369 
370     get a single character from the command line options string, ignoring any
371 
372     white space
373 
374     @return the character read, or -1 if the end of the string is reached
375 
376     */
377 
378     public int getCharNoSpace()
379 
380       {
381 
382         int rval = getChar();
383 
384         while ((rval >= 0) && (rval <= ' '))
385 
386           {
387 
388             rval = getChar();
389 
390             afterDash = false;
391 
392           }
393 
394         return rval;
395 
396       }
397 
398 
399 
400     /**
401 
402     get a single character from the command line options string, without changing
403 
404     the current position in the string (ie a subsequent getChar will return the same
405 
406     character)
407 
408     @return the character read, or -1 if the end of the string is reached
409 
410     */
411 
412      public int peekChar()
413 
414       {
415 
416         int oldArgPosn = argPosn;
417 
418         int rval = getChar();
419 
420         argPosn = oldArgPosn;
421 
422         return rval;
423 
424       }
425 
426     /**
427 
428     get a single character from the command line options string, without changing
429 
430     the current position in the string (ie a subsequent getChar will return the same
431 
432     character) ignore any white space
433 
434     @return the character read, or -1 if the end of the string is reached
435 
436     */
437 
438     public int peekCharNoSpace()
439 
440       {
441 
442         int oldArgPosn = argPosn;
443 
444         int rval = getCharNoSpace();
445 
446         argPosn = oldArgPosn;
447 
448         return rval;
449 
450       }
451 
452 
453 
454     //is c a valid character for a long option name
455 
456     private boolean isIdChar(int c)
457 
458       {
459 
460         return (((c >= 'a') && (c <= 'z')) ||
461 
462                ((c >= 'A') && (c <= 'Z')) ||
463 
464                (c == '_'));
465 
466       }
467 
468 
469 
470     /**
471 
472     read a long option name from the command line string. A long option name consists
473 
474     of alphabetic characters and '_' with no spaces
475 
476     @return the name read */
477 
478     public String getLongName()
479 
480       {
481 
482         StringBuffer rval = new StringBuffer(15);
483 
484         int c = getChar();
485 
486         while (c == '-')
487 
488           c = getChar();
489 
490         while (isIdChar(c))
491 
492           {
493 
494             rval.append((char) c);
495 
496             c = getChar();
497 
498           }
499 
500         if (c >= 0) argPosn--;
501 
502         return rval.toString();
503 
504       }
505 
506 
507 
508     /**
509 
510     read in a string (enclosed in double quotes) from the command line string
511 
512     @return the string read, or null if there is an error in the string
513 
514     */
515 
516 
517 
518     protected String getString()
519 
520       {
521 
522         int c = getCharNoSpace();
523 
524         String rval = null;
525 
526         if (c == '"')
527 
528           rval = getString_();
529 
530         return rval;
531 
532       }
533 
534 
535 
536     //get a string where the initial " has already been read
537 
538     protected String getString_()
539 
540       {
541 
542         StringBuffer rval = new StringBuffer(25);
543 
544         int c = getChar();
545 
546         while ((c >= 0) && (c != '"'))
547 
548            {
549 
550              rval.append((char) c);
551 
552             c = getChar();
553 
554           }
555 
556         if (c < 0) ; //throw an unclosed string error
557 
558         return rval.toString();
559 
560       }
561 
562 
563 
564     /**
565 
566     read a string, either enclosed in quotes (in which case the string can
567 
568     contain spaces) or not enclosed in quotes (in which case spaces are not
569 
570     allowed). Initial whitespace is skipped
571 
572     @return the string read, or null if an error occurs*/
573 
574     public String getStringValue()
575 
576       {
577 
578         afterDash = false;
579 
580         String rval = null;
581 
582         int c = getCharNoSpace();
583 
584         if (c == '"')
585 
586           rval = getString_();
587 
588         else
589 
590           {
591 
592             StringBuffer s = new StringBuffer(25);
593 
594             while ((c != ' ') && (c >= 0))
595 
596               {
597 
598                 s.append((char) c);
599 
600                 c = getChar();
601 
602               }
603 
604             if (c >= 0) argPosn--;
605 
606             rval = s.toString();
607 
608           }
609 
610         return rval;
611 
612       }
613 
614 
615 
616       /**
617 
618       return true if the character c could be part of a floating point number#
619 
620       */
621 
622       public boolean isNumChar(int c)
623 
624         {
625 
626           return (((c >= '0') && (c <= '9')) ||
627 
628               (c == '+') || (c == '-') || (c == '.') ||
629 
630               (c == 'E') || (c == 'e'));
631 
632         }
633 
634 
635 
636       /**
637 
638       read a numeric value (which can be in full floating point form) from the
639 
640       command line string
641 
642       @return the value read, or NaN if an error has occurred */
643 
644       public float getNumValue()
645 
646         {
647 
648           float rval;
649 
650           StringBuffer s = new StringBuffer(10);
651 
652           int c = getCharNoSpace();
653 
654           while (isNumChar(c))
655 
656             {
657 
658               s.append((char) c);
659 
660               c = getChar();
661 
662             }
663 
664           if (c >= 0) argPosn--;
665 
666           try
667 
668             {
669 
670               rval = Float.valueOf(s.toString()).floatValue();
671 
672             }
673 
674           catch (NumberFormatException e)
675 
676             {
677 
678               rval = Float.NaN;
679 
680             }
681 
682           return rval;
683 
684         }
685 
686 
687 
688     /**
689 
690     if the next character in the command string is a '+' or '-' read it
691 
692     @return true if '+' is read, or no character is read, false otherwise
693 
694     */
695 
696 
697 
698     public boolean getBoolean()
699 
700       {
701 
702         boolean rval = true;
703 
704         int c = getChar();
705 
706         if (c == '-')
707 
708           rval = false;
709 
710         else if (c == '+')
711 
712           rval = true;
713 
714         else if (c >= 0) argPosn--;
715 
716         return rval;
717 
718       }
719 
720 
721 
722     /**
723 
724     check a character against an option
725 
726     @param op the Option to check
727 
728     @param the character to check
729 
730     @return true if the character is one of those used as a short name for
731 
732     the given option
733 
734     */
735 
736     public boolean shortCheck(Option op, int c)
737 
738       {
739 
740         boolean rval = false;
741 
742         if ((op != null) && (c > 0))
743 
744           {
745 
746             for (int i = 0; (i < op.shortNames.length()) && !rval; i++)
747 
748               {
749 
750                 char opc = op.shortNames.charAt(i);
751 
752                 if (matchCaseShort)
753 
754                   rval = (c == opc);
755 
756                 else
757 
758                   rval = (Character.toLowerCase((char) c) ==
759 
760                     Character.toLowerCase(opc));
761 
762               }
763 
764           }
765 
766         return rval;
767 
768       }
769 
770     /**
771 
772     check a string against an option
773 
774     @param op the option to check
775 
776     @param the long name to check
777 
778     @return true if the string is one of the long names used by this option
779 
780     */
781 
782     public boolean longCheck(Option op, String s)
783 
784     {
785 
786         int lnpos = 0;
787 
788         boolean rval = false;
789 
790         if ((op != null) && (s != null) && (s.length() > 0))
791 
792           while ((lnpos < op.longNames.length()) && !rval)
793 
794             {
795 
796               int start = lnpos;
797 
798               while ((lnpos < op.longNames.length()) &&
799 
800                 (isIdChar(op.longNames.charAt(lnpos))))
801 
802                 lnpos++;
803 
804               rval = (op.longNames.substring(start, lnpos).equalsIgnoreCase(s));
805 
806               while ((lnpos < op.longNames.length()) &&
807 
808                 (!isIdChar(op.longNames.charAt(lnpos))))
809 
810                 lnpos++;
811 
812             }
813 
814         return rval;
815 
816       }
817 
818 
819 
820     /**
821 
822     save the current position in the command string
823 
824     */
825 
826     public void savePosn()
827 
828       {
829 
830         savedArgPosn = argPosn;
831 
832       }
833 
834 
835 
836     /**
837 
838     restore the current position in the command string, as saved by savePosn
839 
840     */
841 
842 
843 
844     public void restorePosn()
845 
846       {
847 
848         argPosn = savedArgPosn;
849 
850       }
851 
852 
853 
854 
855 
856 
857 
858   }
859 
860 
861