blob: 6a860369b2a5c0e25d8825ea9caf44ea1de21487 [file] [log] [blame]
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* JFlex 1.4.3 *
* Copyright (C) 1998-2009 Gerwin Klein <lsf@jflex.de> *
* All rights reserved. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License. See the file *
* COPYRIGHT for more information. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License along *
* with this program; if not, write to the Free Software Foundation, Inc., *
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package JFlex;
import java.io.*;
import java.net.URL;
import java.util.Vector;
/**
* This class stores the skeleton of generated scanners.
*
* The skeleton consists of several parts that can be emitted to
* a file. Usually there is a portion of generated code
* (produced in class Emitter) between every two parts of skeleton code.
*
* There is a static part (the skeleton code) and state based iterator
* part to this class. The iterator part is used to emit consecutive skeleton
* sections to some <code>PrintWriter</code>.
*
* @see JFlex.Emitter
*
* @author Gerwin Klein
* @version $Revision: 1.4.3 $, $Date: 2009/12/21 15:58:48 $
*/
public class Skeleton {
/** location of default skeleton */
static final private String DEFAULT_LOC = "JFlex/skeleton.default"; //$NON-NLS-1$
/** expected number of sections in the skeleton file */
static final private int size = 21;
/** platform specific newline */
static final private String NL = System.getProperty("line.separator"); //$NON-NLS-1$
/** The skeleton */
public static String line[];
/** initialization */
static { readDefault(); }
// the state based, iterator part of Skeleton:
/**
* The current part of the skeleton (an index of nextStop[])
*/
private int pos;
/**
* The writer to write the skeleton-parts to
*/
private PrintWriter out;
/**
* Creates a new skeleton (iterator) instance.
*
* @param out the writer to write the skeleton-parts to
*/
public Skeleton(PrintWriter out) {
this.out = out;
}
/**
* Emits the next part of the skeleton
*/
public void emitNext() {
out.print( line[pos++] );
}
/**
* Make the skeleton private.
*
* Replaces all occurences of " public " in the skeleton with " private ".
*/
public static void makePrivate() {
for (int i=0; i < line.length; i++) {
line[i] = replace(" public ", " private ", line[i]); //$NON-NLS-1$ //$NON-NLS-2$
}
}
/**
* Reads an external skeleton file for later use with this class.
*
* @param skeletonFile the file to read (must be != null and readable)
*/
public static void readSkelFile(File skeletonFile) {
if (skeletonFile == null)
throw new IllegalArgumentException("Skeleton file must not be null"); //$NON-NLS-1$
if (!skeletonFile.isFile() || !skeletonFile.canRead()) {
Out.error(ErrorMessages.CANNOT_READ_SKEL, skeletonFile.toString());
throw new GeneratorException();
}
Out.println(ErrorMessages.READING_SKEL, skeletonFile.toString());
try {
BufferedReader reader = new BufferedReader(new FileReader(skeletonFile));
readSkel(reader);
}
catch (IOException e) {
Out.error(ErrorMessages.SKEL_IO_ERROR);
throw new GeneratorException();
}
}
/**
* Reads an external skeleton file from a BufferedReader.
*
* @param reader the reader to read from (must be != null)
* @throws IOException if an IO error occurs
* @throws GeneratorException if the number of skeleton sections does not match
*/
public static void readSkel(BufferedReader reader) throws IOException {
Vector lines = new Vector();
StringBuffer section = new StringBuffer();
String ln;
while ((ln = reader.readLine()) != null) {
if (ln.startsWith("---")) { //$NON-NLS-1$
lines.addElement(section.toString());
section.setLength(0);
} else {
section.append(ln);
section.append(NL);
}
}
if (section.length() > 0)
lines.addElement(section.toString());
if (lines.size() != size) {
Out.error(ErrorMessages.WRONG_SKELETON);
throw new GeneratorException();
}
line = new String[size];
for (int i = 0; i < size; i++)
line[i] = (String) lines.elementAt(i);
}
/**
* Replaces a with b in c.
*
* @param a the String to be replaced
* @param b the replacement
* @param c the String in which to replace a by b
* @return a String object with a replaced by b in c
*/
public static String replace(String a, String b, String c) {
StringBuffer result = new StringBuffer(c.length());
int i = 0;
int j = c.indexOf(a);
while (j >= i) {
result.append(c.substring(i,j));
result.append(b);
i = j+a.length();
j = c.indexOf(a,i);
}
result.append(c.substring(i,c.length()));
return result.toString();
}
/**
* (Re)load the default skeleton. Looks in the current system class path.
*/
public static void readDefault() {
ClassLoader l = Skeleton.class.getClassLoader();
URL url;
/* Try to load from same class loader as this class.
* Should work, but does not on OS/2 JDK 1.1.8 (see bug 1065521).
* Use system class loader in this case.
*/
if (l != null) {
url = l.getResource(DEFAULT_LOC);
}
else {
url = ClassLoader.getSystemResource(DEFAULT_LOC);
}
if (url == null) {
Out.error(ErrorMessages.SKEL_IO_ERROR_DEFAULT);
throw new GeneratorException();
}
try {
InputStreamReader reader = new InputStreamReader(url.openStream());
readSkel(new BufferedReader(reader));
} catch (IOException e) {
Out.error(ErrorMessages.SKEL_IO_ERROR_DEFAULT);
throw new GeneratorException();
}
}
}