package xtc.lang.blink.agent;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.HashMap;
/**
* A hard coded Java class generator. This tool takes Java class files, and
* generates a C source file and optionally a C header file that define a
* character arrays that contain the input class files.
*
* @author Byeongcheol Lee
*/
public class GenerateHardcodedJavaClass {
/**
* Print the reason why this program can not accept a user command line, and
* show the command line usage.
*
* @param reason The reason.
*/
public static void usage(String reason) {
if (reason != null) {
System.out.println(reason);
}
System.out.println(
"usage: " + GenerateHardcodedJavaClass.class.getName()
+ " [-o <output file>] [-h <output header file]"
+ "[<array name> <input file>] [<array name> <input file>] ...\n"
+ " "
);
System.exit(-1);
}
/**
* Parse the user command line arguments and run the application.
*
* @param args The arguments.
*/
public static void main(String[] args) {
//parse arguments
String outputSourceFileName = null;
String outputHeaderFileName = null;
HashMap<String,String> array2ClassFileMap = new HashMap<String,String>();
for(int i = 0;i < args.length;i++) {
if (args[i].equals("-o") ) {
if ((i + 1) < args.length) {
outputSourceFileName = args[++i];
} else {
usage("Please, specify output file after -o");
}
} else if (args[i].equals("-h")) {
if ((i+1) < args.length) {
outputHeaderFileName = args[++i];
} else {
usage("Please, specify output header file name after -h");
}
} else {
if ((i + 1) < args.length) {
String arrayName = args[i];
String inputFileName = args[++i];
File f = new File(inputFileName);
if (f.isFile() && f.canRead()) {
if (array2ClassFileMap.containsKey(arrayName)) {
usage("Duplicated array name: " + arrayName);
} else {
array2ClassFileMap.put(arrayName, inputFileName);
}
} else {
usage("You need a read acess permission: " + inputFileName);
}
} else {
usage("Please, specify input file");
}
}
}
if (array2ClassFileMap.size() <= 0) {
usage("Please, specify at least one <array name, input file> pair");
}
// run this tool and generates a header file and a source file.
try {
// generate header file.
if ( outputHeaderFileName != null) {
PrintWriter headerWriter = new PrintWriter(new FileOutputStream(outputHeaderFileName));
generateHeaderFile(outputHeaderFileName, array2ClassFileMap, headerWriter);
headerWriter.flush();
headerWriter.close();
}
//generate source file.
PrintWriter os = new PrintWriter(
(outputSourceFileName == null) ? System.out : new FileOutputStream(
outputSourceFileName));
generateSourceFile(array2ClassFileMap, os);
os.flush();
os.close();
} catch (IOException e) {
System.err.println("Can not recover from the input or output fault");
}
}
/**
* Generate header file declaring a set of character arrays for the Java class
* files.
*
* @param headerFile The header file name.
* @param map The map.
* @param os The output stream.
*/
private static void generateHeaderFile(String headerFile,
HashMap<String,String> map, PrintWriter os) throws IOException {
String symbolName = "_" + headerFile.toUpperCase().replace('.', '_') + "_";
os.println("#ifndef " + symbolName);
os.println("#define " + symbolName);
for(final String arrayName : map.keySet()) {
String inputFileName = map.get(arrayName);
File inputFile = new File(inputFileName);
long length = inputFile.length();
os.printf("extern const signed char %s[%d];\n", arrayName, length);
}
os.println("#endif /* " + symbolName + " */");
}
/**
* Read Java class files and generate C source lines.
*
* @param map The map.
* @param os The output.
*/
private static void generateSourceFile(HashMap<String,String> map,
PrintWriter os) throws IOException {
os.write("/* This file is generated by "
+ GenerateHardcodedJavaClass.class.getName() + ". */\n");
for(final String arrayName : map.keySet()) {
String inputFileName = map.get(arrayName);
long length = new File(inputFileName).length();
InputStream is = new FileInputStream(inputFileName);
BufferedInputStream bis = new BufferedInputStream(is);
os.write("/* This array is from " + inputFileName + ". */\n");
os.printf("const char signed %s[%d] = {\n", arrayName, length);
int c, i=1;
while ((c = is.read()) >= 0) {
os.printf("0x%02x, ", c);
if (i % 8 == 0) {os.write("\n");}
i++;
}
os.write("\n");
os.write("};\n");
bis.close();
}
}
}