1 /*
   2  * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 import java.io.*;
  26 import java.util.*;
  27 
  28 public class MacroDefinitions {
  29     private Vector macros;
  30 
  31     public MacroDefinitions() {
  32         macros = new Vector();
  33     }
  34 
  35     private String lookup(String name) throws NoSuchElementException {
  36         for (Iterator iter = macros.iterator(); iter.hasNext(); ) {
  37             Macro macro = (Macro) iter.next();
  38             if (macro.name.equals(name)) {
  39                 return macro.contents;
  40             }
  41         }
  42         throw new NoSuchElementException(name);
  43     }
  44 
  45     public void addMacro(String name, String contents) {
  46         Macro macro = new Macro();
  47         macro.name = name;
  48         macro.contents = contents;
  49         macros.add(macro);
  50     }
  51 
  52     private boolean lineIsEmpty(String s) {
  53         for (int i = 0; i < s.length(); i++) {
  54             if (!Character.isWhitespace(s.charAt(i))) {
  55                 return false;
  56             }
  57         }
  58         return true;
  59     }
  60 
  61     public void readFrom(String fileName, boolean missingOk)
  62         throws FileNotFoundException, FileFormatException, IOException {
  63         BufferedReader reader = null;
  64         try {
  65             reader = new BufferedReader(new FileReader(fileName));
  66         } catch (FileNotFoundException e) {
  67             if (missingOk) {
  68                 return;
  69             } else {
  70                 throw(e);
  71             }
  72         }
  73         String line;
  74         do {
  75             line = reader.readLine();
  76             if (line != null) {
  77                 // This had to be rewritten (compare to Database.java)
  78                 // because the Solaris platform file has been
  79                 // repurposed and now contains "macros" with spaces in
  80                 // them.
  81 
  82                 if ((!line.startsWith("//")) &&
  83                     (!lineIsEmpty(line))) {
  84                     int nameBegin = -1;
  85                     int nameEnd = -1;
  86                     boolean gotEquals = false;
  87                     int contentsBegin = -1;
  88                     int contentsEnd = -1;
  89 
  90                     int i = 0;
  91                     // Scan forward for beginning of name
  92                     while (i < line.length()) {
  93                         if (!Character.isWhitespace(line.charAt(i))) {
  94                             break;
  95                         }
  96                         i++;
  97                     }
  98                     nameBegin = i;
  99 
 100                     // Scan forward for end of name
 101                     while (i < line.length()) {
 102                         if (Character.isWhitespace(line.charAt(i))) {
 103                             break;
 104                         }
 105                         i++;
 106                     }
 107                     nameEnd = i;
 108 
 109                     // Scan forward for equals sign
 110                     while (i < line.length()) {
 111                         if (line.charAt(i) == '=') {
 112                             gotEquals = true;
 113                             break;
 114                         }
 115                         i++;
 116                     }
 117 
 118                     // Scan forward for start of contents
 119                     i++;
 120                     while (i < line.length()) {
 121                         if (!Character.isWhitespace(line.charAt(i))) {
 122                             break;
 123                         }
 124                         i++;
 125                     }
 126                     contentsBegin = i;
 127 
 128                     // Scan *backward* for end of contents
 129                     i = line.length() - 1;
 130                     while (i >= 0) {
 131                         if (!Character.isWhitespace(line.charAt(i))) {
 132                             break;
 133                         }
 134                     }
 135                     contentsEnd = i+1;
 136 
 137                     // Now do consistency check
 138                     if (!((nameBegin < nameEnd) &&
 139                           (nameEnd < contentsBegin) &&
 140                           (contentsBegin < contentsEnd) &&
 141                           (gotEquals == true))) {
 142                         throw new FileFormatException(
 143                             "Expected \"macroname = value\", " +
 144                             "but found: " + line
 145                         );
 146                     }
 147 
 148                     String name = line.substring(nameBegin, nameEnd);
 149                     String contents = line.substring(contentsBegin,
 150                                                      contentsEnd);
 151                     addMacro(name, contents);
 152                 }
 153             }
 154         } while (line != null);
 155         reader.close();
 156     }
 157 
 158     /** Throws IllegalArgumentException if passed token is illegally
 159         formatted */
 160     public String expand(String token)
 161         throws IllegalArgumentException {
 162         // the token may contain one or more <macroName>'s
 163 
 164         String out = "";
 165 
 166         // emacs lingo
 167         int mark = 0;
 168         int point = 0;
 169 
 170         int len = token.length();
 171 
 172         if (len == 0)
 173             return out;
 174 
 175         do {
 176             // Scan "point" forward until hitting either the end of
 177             // the string or the beginning of a macro
 178             if (token.charAt(point) == '<') {
 179                 // Append (point - mark) to out
 180                 if ((point - mark) != 0) {
 181                     out += token.substring(mark, point);
 182                 }
 183                 mark = point + 1;
 184                 // Scan forward from point for right bracket
 185                 point++;
 186                 while ((point < len) &&
 187                        (token.charAt(point) != '>')) {
 188                     point++;
 189                 }
 190                 if (point == len) {
 191                     throw new IllegalArgumentException(
 192                         "Could not find right angle-bracket in token " + token
 193                     );
 194                 }
 195                 String name = token.substring(mark, point);
 196                 if (name == null) {
 197                     throw new IllegalArgumentException(
 198                         "Empty macro in token " + token
 199                     );
 200                 }
 201                 try {
 202                     String contents = lookup(name);
 203                     out += contents;
 204                     point++;
 205                     mark = point;
 206                 } catch (NoSuchElementException e) {
 207                     throw new IllegalArgumentException(
 208                         "Unknown macro " + name + " in token " + token
 209                     );
 210                 }
 211             } else {
 212                 point++;
 213             }
 214         } while (point != len);
 215 
 216         if (mark != point) {
 217             out += token.substring(mark, point);
 218         }
 219 
 220         return out;
 221     }
 222 
 223     public MacroDefinitions copy() {
 224         MacroDefinitions ret = new MacroDefinitions();
 225         for (Iterator iter = macros.iterator();
 226              iter.hasNext(); ) {
 227             Macro orig = (Macro) iter.next();
 228             Macro macro = new Macro();
 229             macro.name = orig.name;
 230             macro.contents = orig.contents;
 231             ret.macros.add(macro);
 232         }
 233         return ret;
 234     }
 235 
 236     public void setAllMacroBodiesTo(String s) {
 237         for (Iterator iter = macros.iterator();
 238              iter.hasNext(); ) {
 239             Macro macro = (Macro) iter.next();
 240             macro.contents = s;
 241         }
 242     }
 243 
 244     /** This returns an Iterator of Macros. You should not mutate the
 245         returned Macro objects or use the Iterator to remove
 246         macros. */
 247     public Iterator getMacros() {
 248         return macros.iterator();
 249     }
 250 
 251     private void error(String text) throws FileFormatException {
 252         throw new FileFormatException(
 253             "Expected \"macroname = value\", but found: " + text
 254         );
 255     }
 256 }