001    /*
002     * The JastAdd Extensible Java Compiler (http://jastadd.org) is covered
003     * by the modified BSD License. You should have received a copy of the
004     * modified BSD license with this compiler.
005     * 
006     * Copyright (c) 2005-2008, Torbjorn Ekman
007     * All rights reserved.
008     */
009    
010    import java.util.*;
011    
012    aspect AddOptionsToProgram {
013      public Options ASTNode$State.options = new Options();
014      public Options ASTNode.options() {
015        return state().options;
016      }
017    }
018    
019    public class Options {
020      static class Option {
021        public String name;
022        public boolean hasValue;
023        public boolean isCollection;
024        public Option(String name, boolean hasValue, boolean isCollection) {
025          this.name = name;
026          this.hasValue = hasValue;
027          this.isCollection = isCollection;
028        }
029      }
030      private Map options = new HashMap();
031      private Map optionDescriptions = new HashMap();
032    
033      private HashSet files = new HashSet();
034      public Collection files() {
035        return files;
036      }
037    
038      public void initOptions() {
039        options = new HashMap();
040        optionDescriptions = new HashMap();
041        files = new HashSet();
042      }
043    
044      public void addKeyOption(String name) {
045        if(optionDescriptions.containsKey(name))
046          throw new Error("Command line definition error: option description for " + name + " is multiply declared");
047        optionDescriptions.put(name, new Option(name, false, false));
048      }
049      
050      public void addKeyValueOption(String name) {
051        if(optionDescriptions.containsKey(name))
052          throw new Error("Command line definition error: option description for " + name + " is multiply declared");
053        optionDescriptions.put(name, new Option(name, true, false));
054      }
055      
056      public void addKeyCollectionOption(String name) {
057        if(optionDescriptions.containsKey(name))
058          throw new Error("Command line definition error: option description for " + name + " is multiply declared");
059        optionDescriptions.put(name, new Option(name, true, true));
060      }
061     
062      public void addOptionDescription(String name, boolean value) {
063        if(optionDescriptions.containsKey(name))
064          throw new Error("Command line definition error: option description for " + name + " is multiply declared");
065        optionDescriptions.put(name, new Option(name, value, false));
066      }
067      public void addOptionDescription(String name, boolean value, boolean isCollection) {
068        if(optionDescriptions.containsKey(name))
069          throw new Error("Command line definition error: option description for " + name + " is multiply declared");
070        optionDescriptions.put(name, new Option(name, value, isCollection));
071      }
072      
073      public void addOptions(String[] args) {
074        for(int i = 0; i < args.length; i++) {
075          String arg = args[i];
076          if(arg.startsWith("@")) {
077            try {
078              String fileName = arg.substring(1,arg.length());
079              java.io.StreamTokenizer tokenizer = new java.io.StreamTokenizer(new java.io.FileReader(fileName));
080              tokenizer.resetSyntax();
081              tokenizer.whitespaceChars(' ',' ');
082              tokenizer.whitespaceChars('\t','\t');
083              tokenizer.whitespaceChars('\f','\f');
084              tokenizer.whitespaceChars('\n','\n');
085              tokenizer.whitespaceChars('\r','\r');
086              tokenizer.wordChars(33,255);
087              ArrayList list = new ArrayList();
088              int next = tokenizer.nextToken();
089              while(next != java.io.StreamTokenizer.TT_EOF) {
090                if(next == java.io.StreamTokenizer.TT_WORD) {
091                  list.add(tokenizer.sval);
092                }
093                next = tokenizer.nextToken();
094              }
095              String[] newArgs = new String[list.size()];
096              int index = 0;
097              for(Iterator iter = list.iterator(); iter.hasNext(); index++) {
098                newArgs[index] = (String)iter.next();
099              }
100              addOptions(newArgs);
101            } catch (java.io.FileNotFoundException e) {
102              System.err.println("File not found: "+arg.substring(1));
103            } catch (java.io.IOException e) {
104              System.err.println("Exception: "+e.getMessage());
105            }
106          }
107          else if(arg.startsWith("-")) {
108            if(!optionDescriptions.containsKey(arg))
109              throw new Error("Command line argument error: option " + arg + " is not defined");
110            Option o = (Option)optionDescriptions.get(arg);
111            
112            if(!o.isCollection && options.containsKey(arg))
113              throw new Error("Command line argument error: option " + arg + " is multiply defined");
114            
115            if(o.hasValue && !o.isCollection) {
116              String value = null;
117              if(i + 1 > args.length - 1)
118                throw new Error("Command line argument error: value missing for key " + arg);
119              value = args[i+1];
120              if(value.startsWith("-"))
121                throw new Error("Command line argument error: value missing for key " + arg);
122              i++;
123              options.put(arg, value);
124            }
125            else if(o.hasValue && o.isCollection) {
126              String value = null;
127              if(i + 1 > args.length - 1)
128                throw new Error("Command line argument error: value missing for key " + arg);
129              value = args[i+1];
130              if(value.startsWith("-"))
131                throw new Error("Command line argument error: value missing for key " + arg);
132              i++;
133              Collection c = (Collection)options.get(arg);
134              if(c == null)
135                c = new ArrayList();
136              c.add(value);
137              options.put(arg, c);
138            }
139            else {
140              options.put(arg, null);
141            }
142          }
143          else {
144            files.add(arg);
145          }
146        }
147      }
148      public boolean hasOption(String name) {
149        return options.containsKey(name);
150      }
151      public void setOption(String name) {
152        options.put(name, null);
153      }
154      public boolean hasValueForOption(String name) {
155        return options.containsKey(name) && options.get(name) != null;
156      }
157      public String getValueForOption(String name) {
158        if(!hasValueForOption(name))
159          throw new Error("Command line argument error: key " + name + " does not have a value");
160        return (String)options.get(name);
161      }
162      public void setValueForOption(String value, String option) {
163        options.put(option, value);
164      }
165      public Collection getValueCollectionForOption(String name) {
166        if(!hasValueForOption(name))
167          throw new Error("Command line argument error: key " + name + " does not have a value");
168        return (Collection)options.get(name);
169      }
170    
171      public boolean verbose() {
172        return hasOption("-verbose");
173      }
174    }