diff options
Diffstat (limited to 'third_party/js-1.7/jskwgen.c')
-rw-r--r-- | third_party/js-1.7/jskwgen.c | 460 |
1 files changed, 0 insertions, 460 deletions
diff --git a/third_party/js-1.7/jskwgen.c b/third_party/js-1.7/jskwgen.c deleted file mode 100644 index 5ae39bd99db..00000000000 --- a/third_party/js-1.7/jskwgen.c +++ /dev/null @@ -1,460 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set sw=4 ts=8 et tw=80: - * - * ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * 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 String Switch Generator for JavaScript Keywords, - * released 2005-12-09. - * - * The Initial Developer of the Original Code is - * Igor Bukanov. - * Portions created by the Initial Developer are Copyright (C) 2005-2006 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "jsstddef.h" -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> -#include <ctype.h> - -#include "jsconfig.h" - -const char * const keyword_list[] = { -#define JS_KEYWORD(keyword, type, op, version) #keyword, -#include "jskeyword.tbl" -#undef JS_KEYWORD -}; - -struct gen_opt { - FILE *output; /* output file for generated source */ - unsigned use_if_threshold; /* max number of choices to generate - "if" selector instead of "switch" */ - unsigned char_tail_test_threshold; /* max number of unprocessed columns - to use inlined char compare - for remaining chars and not generic - string compare code */ - unsigned indent_level; /* current source identation level */ -}; - -static unsigned column_to_compare; - -static int -length_comparator(const void *a, const void *b) -{ - const char *str1 = keyword_list[*(unsigned *)a]; - const char *str2 = keyword_list[*(unsigned *)b]; - return (int)strlen(str1) - (int)strlen(str2); -} - -static int -column_comparator(const void *a, const void *b) -{ - const char *str1 = keyword_list[*(unsigned *)a]; - const char *str2 = keyword_list[*(unsigned *)b]; - return (int)str1[column_to_compare] - (int)str2[column_to_compare]; -} - -static unsigned -count_different_lengths(unsigned indexes[], unsigned nelem) -{ - unsigned nlength, current_length, i, l; - - current_length = 0; - nlength = 0; - for (i = 0; i != nelem; ++i) { - l = (unsigned)strlen(keyword_list[indexes[i]]); - assert(l != 0); - if (current_length != l) { - ++nlength; - current_length = l; - } - } - return nlength; -} - -static void -find_char_span_and_count(unsigned indexes[], unsigned nelem, unsigned column, - unsigned *span_result, unsigned *count_result) -{ - unsigned i, count; - unsigned char c, prev, minc, maxc; - - assert(nelem != 0); - minc = maxc = prev = (unsigned char)keyword_list[indexes[0]][column]; - count = 1; - for (i = 1; i != nelem; ++i) { - c = (unsigned char)keyword_list[indexes[i]][column]; - if (prev != c) { - prev = c; - ++count; - if (minc > c) { - minc = c; - } else if (maxc < c) { - maxc = c; - } - } - } - - *span_result = maxc - minc + 1; - *count_result = count; -} - -static unsigned -find_optimal_switch_column(struct gen_opt *opt, - unsigned indexes[], unsigned nelem, - unsigned columns[], unsigned unprocessed_columns, - int *use_if_result) -{ - unsigned i; - unsigned span, min_span, min_span_index; - unsigned nchar, min_nchar, min_nchar_index; - - assert(unprocessed_columns != 0); - i = 0; - min_nchar = min_span = (unsigned)-1; - min_nchar_index = min_span_index = 0; - do { - column_to_compare = columns[i]; - qsort(indexes, nelem, sizeof(indexes[0]), column_comparator); - find_char_span_and_count(indexes, nelem, column_to_compare, - &span, &nchar); - assert(span != 0); - if (span == 1) { - assert(nchar == 1); - *use_if_result = 1; - return 1; - } - assert(nchar != 1); - if (min_span > span) { - min_span = span; - min_span_index = i; - } - if (min_nchar > nchar) { - min_nchar = nchar; - min_nchar_index = i; - } - } while (++i != unprocessed_columns); - - if (min_nchar <= opt->use_if_threshold) { - *use_if_result = 1; - i = min_nchar_index; - } else { - *use_if_result = 0; - i = min_span_index; - } - - /* - * Restore order corresponding to i if it was destroyed by - * subsequent sort. - */ - if (i != unprocessed_columns - 1) { - column_to_compare = columns[i]; - qsort(indexes, nelem, sizeof(indexes[0]), column_comparator); - } - - return i; -} - - -static void -p(struct gen_opt *opt, const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - vfprintf(opt->output, format, ap); - va_end(ap); -} - -/* Size for '\xxx' where xxx is octal escape */ -#define MIN_QUOTED_CHAR_BUFFER 7 - -static char * -qchar(char c, char *quoted_buffer) -{ - char *s; - - s = quoted_buffer; - *s++ = '\''; - switch (c) { - case '\n': c = 'n'; goto one_char_escape; - case '\r': c = 'r'; goto one_char_escape; - case '\t': c = 't'; goto one_char_escape; - case '\f': c = 't'; goto one_char_escape; - case '\0': c = '0'; goto one_char_escape; - case '\'': goto one_char_escape; - one_char_escape: - *s++ = '\\'; - break; - default: - if (!isprint(c)) { - *s++ = '\\'; - *s++ = (char)('0' + (0x3 & (((unsigned char)c) >> 6))); - *s++ = (char)('0' + (0x7 & (((unsigned char)c) >> 3))); - c = (char)('0' + (0x7 & ((unsigned char)c))); - } - } - *s++ = c; - *s++ = '\''; - *s = '\0'; - assert(s + 1 <= quoted_buffer + MIN_QUOTED_CHAR_BUFFER); - return quoted_buffer; -} - -static void -nl(struct gen_opt *opt) -{ - putc('\n', opt->output); -} - -static void -indent(struct gen_opt *opt) -{ - unsigned n = opt->indent_level; - while (n != 0) { - --n; - fputs(" ", opt->output); - } -} - -static void -line(struct gen_opt *opt, const char *format, ...) -{ - va_list ap; - - indent(opt); - va_start(ap, format); - vfprintf(opt->output, format, ap); - va_end(ap); - nl(opt); -} - -static void -generate_letter_switch_r(struct gen_opt *opt, - unsigned indexes[], unsigned nelem, - unsigned columns[], unsigned unprocessed_columns) -{ - char qbuf[MIN_QUOTED_CHAR_BUFFER]; - - assert(nelem != 0); - if (nelem == 1) { - unsigned kw_index = indexes[0]; - const char *keyword = keyword_list[kw_index]; - - if (unprocessed_columns == 0) { - line(opt, "JSKW_GOT_MATCH(%u) /* %s */", kw_index, keyword); - } else if (unprocessed_columns > opt->char_tail_test_threshold) { - line(opt, "JSKW_TEST_GUESS(%u) /* %s */", kw_index, keyword); - } else { - unsigned i, column; - - indent(opt); p(opt, "if ("); - for (i = 0; i != unprocessed_columns; ++i) { - column = columns[i]; - qchar(keyword[column], qbuf); - p(opt, "%sJSKW_AT(%u)==%s", (i == 0) ? "" : " && ", - column, qbuf); - } - p(opt, ") {"); nl(opt); - ++opt->indent_level; - line(opt, "JSKW_GOT_MATCH(%u) /* %s */", kw_index, keyword); - --opt->indent_level; - line(opt, "}"); - line(opt, "JSKW_NO_MATCH()"); - } - } else { - unsigned optimal_column_index, optimal_column; - unsigned i; - int use_if; - char current; - - assert(unprocessed_columns != 0); - optimal_column_index = find_optimal_switch_column(opt, indexes, nelem, - columns, - unprocessed_columns, - &use_if); - optimal_column = columns[optimal_column_index]; - columns[optimal_column_index] = columns[unprocessed_columns - 1]; - - if (!use_if) - line(opt, "switch (JSKW_AT(%u)) {", optimal_column); - - current = keyword_list[indexes[0]][optimal_column]; - for (i = 0; i != nelem;) { - unsigned same_char_begin = i; - char next = current; - - for (++i; i != nelem; ++i) { - next = keyword_list[indexes[i]][optimal_column]; - if (next != current) - break; - } - qchar(current, qbuf); - if (use_if) { - line(opt, "if (JSKW_AT(%u) == %s) {", optimal_column, qbuf); - } else { - line(opt, " case %s:", qbuf); - } - ++opt->indent_level; - generate_letter_switch_r(opt, indexes + same_char_begin, - i - same_char_begin, - columns, unprocessed_columns - 1); - --opt->indent_level; - if (use_if) { - line(opt, "}"); - } - current = next; - } - - if (!use_if) { - line(opt, "}"); - } - - columns[optimal_column_index] = optimal_column; - - line(opt, "JSKW_NO_MATCH()"); - } -} - -static void -generate_letter_switch(struct gen_opt *opt, - unsigned indexes[], unsigned nelem, - unsigned current_length) -{ - unsigned *columns; - unsigned i; - - columns = malloc(sizeof(columns[0]) * current_length); - if (!columns) { - perror("malloc"); - exit(EXIT_FAILURE); - } - for (i = 0; i != current_length; ++i) { - columns[i] = i; - } - generate_letter_switch_r(opt, indexes, nelem, columns, current_length); - free(columns); -} - - -static void -generate_switch(struct gen_opt *opt) -{ - unsigned *indexes; - unsigned nlength; - unsigned i, current; - int use_if; - unsigned nelem; - - nelem = sizeof(keyword_list)/sizeof(keyword_list[0]); - - line(opt, "/*"); - line(opt, " * Generating switch for the list of %u entries:", nelem); - for (i = 0; i != nelem; ++i) { - line(opt, " * %s", keyword_list[i]); - } - line(opt, " */"); - - indexes = malloc(sizeof(indexes[0]) * nelem); - if (!indexes) { - perror("malloc"); - exit(EXIT_FAILURE); - } - for (i = 0; i != nelem; ++i) - indexes[i] = i; - qsort(indexes, nelem, sizeof(indexes[i]), length_comparator); - nlength = count_different_lengths(indexes, nelem); - - use_if = (nlength <= opt->use_if_threshold); - - if (!use_if) - line(opt, "switch (JSKW_LENGTH()) {"); - - current = (unsigned)strlen(keyword_list[indexes[0]]); - for (i = 0; i != nelem;) { - unsigned same_length_begin = i; - unsigned next = current; - - for (++i; i != nelem; ++i) { - next = (unsigned)strlen(keyword_list[indexes[i]]); - if (next != current) - break; - } - if (use_if) { - line(opt, "if (JSKW_LENGTH() == %u) {", current); - } else { - line(opt, " case %u:", current); - } - ++opt->indent_level; - generate_letter_switch(opt, indexes + same_length_begin, - i - same_length_begin, - current); - --opt->indent_level; - if (use_if) { - line(opt, "}"); - } - current = next; - } - if (!use_if) - line(opt, "}"); - line(opt, "JSKW_NO_MATCH()"); - free(indexes); -} - -int main(int argc, char **argv) -{ - struct gen_opt opt; - - if (argc < 2) { - opt.output = stdout; - } else { - opt.output = fopen(argv[1], "w"); - if (!opt.output) { - perror("fopen"); - exit(EXIT_FAILURE); - } - } - opt.indent_level = 1; - opt.use_if_threshold = 3; - opt.char_tail_test_threshold = 4; - - generate_switch(&opt); - - if (opt.output != stdout) { - if (fclose(opt.output)) { - perror("fclose"); - exit(EXIT_FAILURE); - } - } - - return EXIT_SUCCESS; -} |