/* * Jakelib2 - General purpose C++ library * Copyright (C) 2001 Florian Wolff (florian@donuz.de) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * $Id: jlpp.cpp,v 1.44 2003/03/23 14:52:40 florian Exp $ */ #include "include/jlpplib.h" #include ZString originalCode; ZArrayList strings(100); boolean allowJavaSyntax = FALSE; ZString inputFilename; ZString outputFilename; void usage() { printf("jlpp \n"); printf("\n"); } void error(char* msg) { fprintf(stderr, "%s: %s\n", inputFilename.getChars(), msg); exit(1); } void error(ZString* msg) { error((char*) msg->getChars()); } void readFile() { FILE* f = fopen(inputFilename.getChars(), "rb"); if (f == NULL) { fprintf(stderr, "%s: %s\n\n", inputFilename.getChars(), strerror(errno)); exit(2); } char* buf = (char*) malloc(sizeof(char) * 8192); int bytesRead = 0; do { for (int x = 0; x < bytesRead; x++) { switch(buf[x]) { case '\r': break; case '\t': originalCode.append(' '); break; default: originalCode.append(buf[x]); } } bytesRead = (int) fread(buf, sizeof(char), 8192, f); } while (bytesRead > 0); free(buf); fclose(f); } ZString parseCppString(ZString& input) { ZString buf; char c; char number[10]; int len = 0; if (input.length() == 0) { buf.append("0"); } else { for (int idx = 0; idx < input.length(); idx++) { c = input.charAt(idx); if (c == '\\') { if (idx +1 < input.length()) switch(input.charAt(idx +1)) { case 'n': buf.append("10"); len ++; break; case 'r': buf.append("13"); len ++; break; case 'b': buf.append("8"); len ++; break; case 'f': buf.append("12"); len ++; break; case 't': buf.append("9"); len ++; break; case '\\': case '\"': case '\'': sprintf(number, "%u", input.charAt(idx +1) & 0xff); buf.append(number); len ++; break; case 'u': case 'U': { ZString unicode = input.substring(idx+2, idx+6); //fprintf(stderr, "UniCode: 0x%s\n", unicode.getChars()); idx+=4; buf.append("0x").append(&unicode); len ++; } break; default: { ZString err; err.printf("Unknown escape sequence: '\\%c'\n", input.charAt(idx +1)&0xff); error(&err); } break; } idx ++; } else { len ++; sprintf(number, "%u", c & 0xff); buf.append(number); } buf.append(","); } // Remove the last comma: if (input.length() > 0) buf.remove(buf.length() -1); } return buf; } int getCppStringLength(ZString& input) { char c; int len = 0; for (int idx = 0; idx < input.length(); idx++) { c = input.charAt(idx); if (c == '\\') { if (idx +1 < input.length()) switch(input.charAt(idx +1)) { case 'n': case 'r': case 'b': case 'f': case 't': case '\\': case '\"': case '\'': len ++; break; case 'u': case 'U': idx+=4; len ++; break; default: break; } idx ++; } else { len ++; } } return len; } void printCode() { FILE* f = fopen(outputFilename.getChars(), "wb"); if (f == NULL) { fprintf(stderr, "%s: %s\n\n", outputFilename.getChars(), strerror(errno)); exit(2); } fprintf(f, "%s", originalCode.getChars()); fclose(f); } ZString stringName(int idx, int len) { ZString name; name.printf("JAKELIB_ONDEMAND(jakelib2_strings[%u], new jakelib::lang::String(chars_jakelib2_str_%u, 0, %u))", idx, idx, len); return name; } void filterComments() { boolean justSpaces = TRUE; int prepPos = 0; for (int x = 0; x < originalCode.length() -1; x++) { switch(originalCode.charAt(x)) { case '#': if (justSpaces) { ZString prep; prepPos = x; for (; x < originalCode.length(); x++) { if (originalCode.charAt(x) != '\n') prep.append(originalCode.charAt(x)); else break; } if (prep.startsWith("#pragma ")) { ZString pragma = prep.substring(prep.indexOf(' ') + 1); pragma.trim(); //fprintf(stderr, "#PRAGMA '%s'\n", pragma.getChars()); if (pragma.equals("javasyntax")) { allowJavaSyntax = TRUE; originalCode.insert(prepPos, "//"); } else if (pragma.equals("cppsyntax")) { allowJavaSyntax = FALSE; originalCode.insert(prepPos, "//"); } } } break; case '\'': justSpaces = FALSE; for (; x < originalCode.length(); x++) { if (originalCode.charAt(x) == '\\') x++; else if (originalCode.charAt(x) == '\'') break; } break; case '\"': { justSpaces = FALSE; if (allowJavaSyntax) { int start = ++x; int end; for (; x < originalCode.length(); x++) { if (originalCode.charAt(x) == '\\') x++; else if (originalCode.charAt(x) == '\"') break; } end = x; ZString str = originalCode.substring(start, end); ZString ins = stringName(strings.size(), getCppStringLength(str)); originalCode.remove(start -1, end +1); originalCode.insert(start -1, ins.getChars()); strings.add(new ZString(str)); x += ins.length() - str.length() -1; } else { for (; x < originalCode.length(); x++) { if (originalCode.charAt(x) == '\\') x++; else if (originalCode.charAt(x) == '\"') break; } } } break; case '`': { justSpaces = FALSE; char quoteChar = originalCode.charAt(++x); if (quoteChar == '\"') { int start = ++x; int end; for (; x < originalCode.length(); x++) { if (originalCode.charAt(x) == '\\') x++; else if (originalCode.charAt(x) == '\"') break; } end = x; ZString str = originalCode.substring(start, end); ZString ins = stringName(strings.size(), getCppStringLength(str)); char endQuoteChar = originalCode.charAt(end +1); originalCode.remove(start -2, end +2); originalCode.insert(start -2, ins.getChars()); strings.add(new ZString(str)); x += ins.length() - str.length() -1; if (endQuoteChar != '`') { ZString err("Unterminated java-syntax string: \""); err.append(&str); err.append("\""); error(&err); } } } break; case '/': justSpaces = FALSE; if (originalCode.charAt(x +1) == '/') { for (;x < originalCode.length(); x++) if (originalCode.charAt(x) == '\n') break; justSpaces = TRUE; } else if (originalCode.charAt(x +1) == '*') { for (x+=2; x < originalCode.length(); x++) { if (originalCode.charAt(x) == '*' && originalCode.charAt(x + 1) == '/') break; } } break; case '\n': justSpaces = TRUE; break; case ' ': case '\t': break; default: justSpaces = FALSE; break; } } } void filterConcatOperator() { boolean justSpaces = TRUE; for (int x = 0; x < originalCode.length() -1; x++) { switch(originalCode.charAt(x)) { case '#': if (justSpaces) { for (; x < originalCode.length(); x++) { if (originalCode.charAt(x) == '\n') break; } } break; case '\'': case '\"': { char quoteChar = originalCode.charAt(x); justSpaces = FALSE; for (x++; x < originalCode.length(); x++) { if (originalCode.charAt(x) == '\\') x++; else if (originalCode.charAt(x) == quoteChar) break; } } break; case '.': justSpaces = FALSE; if (originalCode.charAt(x +1) == '.' && originalCode.charAt(x +2) != '.' && originalCode.charAt(x -1) != '.') { //printf("FOUND ..\n"); int startIndex = x; int endIndex = -1; int braceDepth = 0; for (x ++; x < originalCode.length() && endIndex == -1; x++) { char c = originalCode.charAt(x); switch(c) { case '(': braceDepth++; break; case ')': braceDepth--; if (braceDepth < 0) endIndex = x; break; case ',': case ';': if (braceDepth == 0) endIndex = x; break; case '.': if (originalCode.charAt(x +1) == '.') endIndex = x; break; case '\'': case '\"': case '`': { char quoteChar = originalCode.charAt(x); for (x++; x < originalCode.length(); x++) { if (originalCode.charAt(x) == '\\') { x++; } else if (originalCode.charAt(x) == quoteChar) { //printf(" ... EOL\n"); break; } else { // printf(" ... >>%c<<\n", originalCode.charAt(x)); } } } break; case '/': if (originalCode.charAt(x +1) == '/') { for (;x < originalCode.length(); x++) if (originalCode.charAt(x) == '\n') break; } else if (originalCode.charAt(x +1) == '*') { for (x+=2; x < originalCode.length(); x++) { if (originalCode.charAt(x) == '*' && originalCode.charAt(x + 1) == '/') break; } } break; } } if (endIndex == -1) error("Unterminated string concatenation"); ZString operand = originalCode.substring(startIndex+2, endIndex); //printf("Operand: %s\n", operand.getChars()); originalCode.remove(startIndex, endIndex); ZString ins; ins.printf("->plus(%s)", operand.getChars()); originalCode.insert(startIndex, ins.getChars()); //printf("INS: '%s'\n", ins.getChars()); x = startIndex + ins.length() -1; //printf("OriginalCode: >>%c%c%c%c%c<<\n", originalCode.charAt(x), originalCode.charAt(x+1), originalCode.charAt(x+2), originalCode.charAt(x+3), originalCode.charAt(x+4)); } break; case '/': justSpaces = FALSE; if (originalCode.charAt(x +1) == '/') { for (;x < originalCode.length(); x++) if (originalCode.charAt(x) == '\n') break; justSpaces = TRUE; } else if (originalCode.charAt(x +1) == '*') { for (x+=2; x < originalCode.length(); x++) { if (originalCode.charAt(x) == '*' && originalCode.charAt(x + 1) == '/') break; } } break; case '\n': justSpaces = TRUE; break; case ' ': case '\t': break; default: justSpaces = FALSE; break; } } } void createStaticStrings() { ZString statics; int idx; statics.append("/* Generated automatically by jlpp - do not edit. */\n\n"); if (strings.size() > 0) { statics.append("#include \n"); ZString tmp; if (strings.size() > 0) { tmp.printf("static jakelib::lang::String* jakelib2_strings[] = {"); statics.append(&tmp); for (idx = 0; idx < strings.size(); idx++) { statics.append("null"); if (idx < strings.size() -1) statics.append(", "); } statics.append("};\n\n"); for (idx = 0; idx < strings.size(); idx++) { ZString* str = (ZString*) strings.get(idx); ZString name; name.printf("chars_jakelib2_str_%u", idx); tmp.printf("// \"%s\"\n", str->getChars()); statics.append(&tmp); statics.append("static jchar ") .append(&name).append("[] = {"); //int len = parseCppString(statics, *str); ZString parsedString = parseCppString(*str); statics.append(&parsedString); statics.append("};\n"); } } } ZString encodedFilename = inputFilename.toCppString(); statics.append("#line 1 \"").append(&encodedFilename).append("\"\n"); statics.append(&originalCode); originalCode = statics; } int main(int argc, char* argv[]) { if (argc < 3) { usage(); return 1; } inputFilename = argv[1]; outputFilename = argv[2]; readFile(); filterComments(); filterConcatOperator(); createStaticStrings(); printCode(); return 0; }