aboutsummaryrefslogtreecommitdiffstats
path: root/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/idswitch/Main.java
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/idswitch/Main.java')
-rw-r--r--trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/idswitch/Main.java612
1 files changed, 612 insertions, 0 deletions
diff --git a/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/idswitch/Main.java b/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/idswitch/Main.java
new file mode 100644
index 0000000..ae1d038
--- /dev/null
+++ b/trunk/infrastructure/rhino1_7R1/toolsrc/org/mozilla/javascript/tools/idswitch/Main.java
@@ -0,0 +1,612 @@
+/* -*- Mode: java; tab-width: 4; indent-tabs-mode: 1; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Rhino code, released
+ * May 6, 1999.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1997-1999
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Igor Bukanov
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * the GNU General Public License Version 2 or later (the "GPL"), in which
+ * case the provisions of the GPL are applicable instead of those above. If
+ * you wish to allow use of your version of this file only under the terms of
+ * the GPL and not to allow others to use your version of this file under the
+ * MPL, indicate your decision by deleting the provisions above and replacing
+ * them with the notice and other provisions required by the GPL. If you do
+ * not delete the provisions above, a recipient may use your version of this
+ * file under either the MPL or the GPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+package org.mozilla.javascript.tools.idswitch;
+
+import java.io.*;
+import java.util.*;
+import java.text.SimpleDateFormat;
+
+import org.mozilla.javascript.EvaluatorException;
+import org.mozilla.javascript.tools.ToolErrorReporter;
+
+public class Main {
+
+ private static final String SWITCH_TAG_STR = "string_id_map";
+ private static final String GENERATED_TAG_STR = "generated";
+ private static final String STRING_TAG_STR = "string";
+
+ private static final int
+ NORMAL_LINE = 0,
+ SWITCH_TAG = 1,
+ GENERATED_TAG = 2,
+ STRING_TAG = 3;
+
+ private final Vector all_pairs = new Vector();
+
+ private ToolErrorReporter R;
+ private CodePrinter P;
+ private FileBody body;
+ private String source_file;
+
+ private int tag_definition_end;
+
+ private int tag_value_start;
+ private int tag_value_end;
+
+ private static boolean is_value_type(int id) {
+ if (id == STRING_TAG) { return true; }
+ return false;
+ }
+
+ private static String tag_name(int id) {
+ switch (id) {
+ case SWITCH_TAG: return SWITCH_TAG_STR;
+ case -SWITCH_TAG: return "/" + SWITCH_TAG_STR;
+ case GENERATED_TAG: return GENERATED_TAG_STR;
+ case -GENERATED_TAG: return "/" + GENERATED_TAG_STR;
+ }
+ return "";
+ }
+
+ void process_file(String file_path) throws IOException {
+ source_file = file_path;
+
+ body = new FileBody();
+
+ InputStream is;
+ if (file_path.equals("-")) {
+ is = System.in;
+ }
+ else {
+ is = new FileInputStream(file_path);
+ }
+ try {
+ Reader r = new InputStreamReader(is, "ASCII");
+ body.readData(r);
+ }
+ finally { is.close(); }
+
+ process_file();
+
+ if (body.wasModified()) {
+ OutputStream os;
+ if (file_path.equals("-")) {
+ os = System.out;
+ }
+ else {
+ os = new FileOutputStream(file_path);
+ }
+
+ try {
+ Writer w = new OutputStreamWriter(os);
+ body.writeData(w);
+ w.flush();
+ }
+ finally { os.close(); }
+ }
+ }
+
+ private void process_file() {
+ int cur_state = 0;
+ char[] buffer = body.getBuffer();
+
+ int generated_begin = -1, generated_end = -1;
+ int time_stamp_begin = -1, time_stamp_end = -1;
+
+ body.startLineLoop();
+ while (body.nextLine()) {
+ int begin = body.getLineBegin();
+ int end = body.getLineEnd();
+
+ int tag_id = extract_line_tag_id(buffer, begin, end);
+ boolean bad_tag = false;
+ switch (cur_state) {
+ case NORMAL_LINE:
+ if (tag_id == SWITCH_TAG) {
+ cur_state = SWITCH_TAG;
+ all_pairs.removeAllElements();
+ generated_begin = -1;
+ }
+ else if (tag_id == -SWITCH_TAG) {
+ bad_tag = true;
+ }
+ break;
+ case SWITCH_TAG:
+ if (tag_id == 0) {
+ look_for_id_definitions(buffer, begin, end, false);
+ }
+ else if (tag_id == STRING_TAG) {
+ look_for_id_definitions(buffer, begin, end, true);
+ }
+ else if (tag_id == GENERATED_TAG) {
+ if (generated_begin >= 0) { bad_tag = true; }
+ else {
+ cur_state = GENERATED_TAG;
+ time_stamp_begin = tag_definition_end;
+ time_stamp_end = end;
+ }
+ }
+ else if (tag_id == -SWITCH_TAG) {
+ cur_state = 0;
+ if (generated_begin >= 0 && !all_pairs.isEmpty()) {
+ generate_java_code();
+ String code = P.toString();
+ boolean different = body.setReplacement
+ (generated_begin, generated_end, code);
+ if (different) {
+ String stamp = get_time_stamp();
+ body.setReplacement
+ (time_stamp_begin, time_stamp_end, stamp);
+ }
+ }
+
+ break;
+ }
+ else {
+ bad_tag = true;
+ }
+ break;
+ case GENERATED_TAG:
+ if (tag_id == 0) {
+ if (generated_begin < 0) { generated_begin = begin; }
+ }
+ else if (tag_id == -GENERATED_TAG) {
+ if (generated_begin < 0) { generated_begin = begin; }
+ cur_state = SWITCH_TAG;
+ generated_end = begin;
+ }
+ else {
+ bad_tag = true;
+ }
+ break;
+ }
+ if (bad_tag) {
+ String text = ToolErrorReporter.getMessage(
+ "msg.idswitch.bad_tag_order", tag_name(tag_id));
+ throw R.runtimeError
+ (text, source_file, body.getLineNumber(), null, 0);
+ }
+ }
+
+ if (cur_state != 0) {
+ String text = ToolErrorReporter.getMessage(
+ "msg.idswitch.file_end_in_switch", tag_name(cur_state));
+ throw R.runtimeError
+ (text, source_file, body.getLineNumber(), null, 0);
+ }
+ }
+
+ private String get_time_stamp() {
+ SimpleDateFormat f = new SimpleDateFormat
+ (" 'Last update:' yyyy-MM-dd HH:mm:ss z");
+ return f.format(new Date());
+ }
+
+ private void generate_java_code() {
+
+ P.clear();
+
+ IdValuePair[] pairs = new IdValuePair[all_pairs.size()];
+ all_pairs.copyInto(pairs);
+
+ SwitchGenerator g = new SwitchGenerator();
+ g.char_tail_test_threshold = 2;
+ g.setReporter(R);
+ g.setCodePrinter(P);
+
+ g.generateSwitch(pairs, "0");
+ }
+
+ private int extract_line_tag_id(char[] array, int cursor, int end) {
+ int id = 0;
+ cursor = skip_white_space(array, cursor, end);
+ int after_leading_white_space = cursor;
+ cursor = look_for_slash_slash(array, cursor, end);
+ if (cursor != end) {
+ boolean at_line_start = (after_leading_white_space + 2 == cursor);
+ cursor = skip_white_space(array, cursor, end);
+ if (cursor != end && array[cursor] == '#') {
+ ++cursor;
+
+ boolean end_tag = false;
+ if (cursor != end && array[cursor] == '/') {
+ ++cursor; end_tag = true;
+ }
+
+ int tag_start = cursor;
+
+ for (; cursor != end; ++cursor) {
+ int c = array[cursor];
+ if (c == '#' || c == '=' ||is_white_space(c)) { break; }
+ }
+
+ if (cursor != end) {
+ int tag_end = cursor;
+ cursor = skip_white_space(array, cursor, end);
+ if (cursor != end) {
+ int c = array[cursor];
+ if (c == '=' || c == '#') {
+ id = get_tag_id
+ (array, tag_start, tag_end, at_line_start);
+ if (id != 0) {
+ String bad = null;
+ if (c == '#') {
+ if (end_tag) {
+ id = -id;
+ if (is_value_type(id)) {
+ bad = "msg.idswitch.no_end_usage";
+ }
+ }
+ tag_definition_end = cursor + 1;
+ }
+ else {
+ if (end_tag) {
+ bad = "msg.idswitch.no_end_with_value";
+ }
+ else if (!is_value_type(id)) {
+ bad = "msg.idswitch.no_value_allowed";
+ }
+ id = extract_tag_value
+ (array, cursor + 1, end, id);
+ }
+ if (bad != null) {
+ String s = ToolErrorReporter.getMessage(
+ bad, tag_name(id));
+ throw R.runtimeError
+ (s, source_file, body.getLineNumber(),
+ null, 0);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return id;
+ }
+
+// Return position after first of // or end if not found
+ private int look_for_slash_slash(char[] array, int cursor, int end) {
+ while (cursor + 2 <= end) {
+ int c = array[cursor++];
+ if (c == '/') {
+ c = array[cursor++];
+ if (c == '/') {
+ return cursor;
+ }
+ }
+ }
+ return end;
+ }
+
+ private int extract_tag_value(char[] array, int cursor, int end, int id) {
+ // cursor points after #[^#=]+=
+ // ALERT: implement support for quoted strings
+ boolean found = false;
+ cursor = skip_white_space(array, cursor, end);
+ if (cursor != end) {
+ int value_start = cursor;
+ int value_end = cursor;
+ while (cursor != end) {
+ int c = array[cursor];
+ if (is_white_space(c)) {
+ int after_space = skip_white_space(array, cursor + 1, end);
+ if (after_space != end && array[after_space] == '#') {
+ value_end = cursor;
+ cursor = after_space;
+ break;
+ }
+ cursor = after_space + 1;
+ }
+ else if (c == '#') {
+ value_end = cursor;
+ break;
+ }
+ else {
+ ++cursor;
+ }
+ }
+ if (cursor != end) {
+ // array[cursor] is '#' here
+ found = true;
+ tag_value_start = value_start;
+ tag_value_end = value_end;
+ tag_definition_end = cursor + 1;
+ }
+ }
+ return (found) ? id : 0;
+ }
+
+ private int get_tag_id
+ (char[] array, int begin, int end, boolean at_line_start)
+ {
+ if (at_line_start) {
+ if (equals(SWITCH_TAG_STR, array, begin, end)) {
+ return SWITCH_TAG;
+ }
+ if (equals(GENERATED_TAG_STR, array, begin, end)) {
+ return GENERATED_TAG;
+ }
+ }
+ if (equals(STRING_TAG_STR, array, begin, end)) {
+ return STRING_TAG;
+ }
+ return 0;
+ }
+
+ private void look_for_id_definitions
+ (char[] array, int begin, int end, boolean use_tag_value_as_string)
+ {
+ // Look for the pattern
+ // '^[ \t]+Id_([a-zA-Z0-9_]+)[ \t]*=.*$'
+ // where \1 gives field or method name
+ int cursor = begin;
+ // Skip tab and spaces at the beginning
+ cursor = skip_white_space(array, cursor, end);
+ int id_start = cursor;
+ int name_start = skip_matched_prefix("Id_", array, cursor, end);
+ if (name_start >= 0) {
+ // Found Id_ prefix
+ cursor = name_start;
+ cursor = skip_name_char(array, cursor, end);
+ int name_end = cursor;
+ if (name_start != name_end) {
+ cursor = skip_white_space(array, cursor, end);
+ if (cursor != end) {
+ if (array[cursor] == '=') {
+ int id_end = name_end;
+ if (use_tag_value_as_string) {
+ name_start = tag_value_start;
+ name_end = tag_value_end;
+ }
+ // Got the match
+ add_id(array, id_start, id_end, name_start, name_end);
+ }
+ }
+ }
+ }
+ }
+
+ private void add_id
+ (char[] array, int id_start, int id_end, int name_start, int name_end)
+ {
+ String name = new String(array, name_start, name_end - name_start);
+ String value = new String(array, id_start, id_end - id_start);
+
+ IdValuePair pair = new IdValuePair(name, value);
+
+ pair.setLineNumber(body.getLineNumber());
+
+ all_pairs.addElement(pair);
+ }
+
+ private static boolean is_white_space(int c) {
+ return c == ' ' || c == '\t';
+ }
+
+ private static int skip_white_space(char[] array, int begin, int end) {
+ int cursor = begin;
+ for (; cursor != end; ++cursor) {
+ int c = array[cursor];
+ if (!is_white_space(c)) { break; }
+ }
+ return cursor;
+ }
+
+ private static int skip_matched_prefix
+ (String prefix, char[] array, int begin, int end)
+ {
+ int cursor = -1;
+ int prefix_length = prefix.length();
+ if (prefix_length <= end - begin) {
+ cursor = begin;
+ for (int i = 0; i != prefix_length; ++i, ++cursor) {
+ if (prefix.charAt(i) != array[cursor]) {
+ cursor = -1; break;
+ }
+ }
+ }
+ return cursor;
+ }
+
+ private static boolean equals(String str, char[] array, int begin, int end)
+ {
+ if (str.length() == end - begin) {
+ for (int i = begin, j = 0; i != end; ++i, ++j) {
+ if (array[i] != str.charAt(j)) { return false; }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private static int skip_name_char(char[] array, int begin, int end) {
+ int cursor = begin;
+ for (; cursor != end; ++cursor) {
+ int c = array[cursor];
+ if (!('a' <= c && c <= 'z') && !('A' <= c && c <= 'Z')) {
+ if (!('0' <= c && c <= '9')) {
+ if (c != '_') {
+ break;
+ }
+ }
+ }
+ }
+ return cursor;
+ }
+
+ public static void main(String[] args) {
+ Main self = new Main();
+ int status = self.exec(args);
+ System.exit(status);
+ }
+
+ private int exec(String[] args) {
+ R = new ToolErrorReporter(true, System.err);
+
+ int arg_count = process_options(args);
+
+ if (arg_count == 0) {
+ option_error(ToolErrorReporter.getMessage(
+ "msg.idswitch.no_file_argument"));
+ return -1;
+ }
+ if (arg_count > 1) {
+ option_error(ToolErrorReporter.getMessage(
+ "msg.idswitch.too_many_arguments"));
+ return -1;
+ }
+
+ P = new CodePrinter();
+ P.setIndentStep(4);
+ P.setIndentTabSize(0);
+
+ try {
+ process_file(args[0]);
+ }
+ catch (IOException ex) {
+ print_error(ToolErrorReporter.getMessage(
+ "msg.idswitch.io_error", ex.toString()));
+ return -1;
+ }
+ catch (EvaluatorException ex) {
+ return -1;
+ }
+ return 0;
+ }
+
+ private int process_options(String[] args) {
+
+ int status = 1;
+
+ boolean show_usage = false;
+ boolean show_version = false;
+
+ int N = args.length;
+ L: for (int i = 0; i != N; ++i) {
+ String arg = args[i];
+ int arg_length = arg.length();
+ if (arg_length >= 2) {
+ if (arg.charAt(0) == '-') {
+ if (arg.charAt(1) == '-') {
+ if (arg_length == 2) {
+ args[i] = null; break;
+ }
+ if (arg.equals("--help")) {
+ show_usage = true;
+ }
+ else if (arg.equals("--version")) {
+ show_version = true;
+ }
+ else {
+ option_error(ToolErrorReporter.getMessage(
+ "msg.idswitch.bad_option", arg));
+ status = -1; break L;
+ }
+ }
+ else {
+ for (int j = 1; j != arg_length; ++j) {
+ char c = arg.charAt(j);
+ switch (c) {
+ case 'h': show_usage = true; break;
+ default:
+ option_error(
+ ToolErrorReporter.getMessage(
+ "msg.idswitch.bad_option_char",
+ String.valueOf(c)));
+ status = -1;
+ break L;
+ }
+
+ }
+ }
+ args[i] = null;
+ }
+ }
+ }
+
+ if (status == 1) {
+ if (show_usage) { show_usage(); status = 0; }
+ if (show_version) { show_version(); status = 0; }
+ }
+
+ if (status != 1) { System.exit(status); }
+
+ return remove_nulls(args);
+ }
+
+ private void show_usage() {
+ System.out.println(
+ ToolErrorReporter.getMessage("msg.idswitch.usage"));
+ System.out.println();
+ }
+
+ private void show_version() {
+ System.out.println(
+ ToolErrorReporter.getMessage("msg.idswitch.version"));
+ }
+
+ private void option_error(String str) {
+ print_error(
+ ToolErrorReporter.getMessage("msg.idswitch.bad_invocation", str));
+ }
+
+ private void print_error(String text) {
+ System.err.println(text);
+ }
+
+ private int remove_nulls(String[] array) {
+ int N = array.length;
+ int cursor = 0;
+ for (; cursor != N; ++cursor) {
+ if (array[cursor] == null) { break; }
+ }
+ int destination = cursor;
+ if (cursor != N) {
+ ++cursor;
+ for (; cursor != N; ++cursor) {
+ String elem = array[cursor];
+ if (elem != null) {
+ array[destination] = elem; ++destination;
+ }
+ }
+ }
+ return destination;
+ }
+}
+