aboutsummaryrefslogtreecommitdiff
path: root/compute_scripts.awk
diff options
context:
space:
mode:
authorWojtek Kosior <koszko@koszko.org>2021-12-22 16:39:34 +0100
committerWojtek Kosior <koszko@koszko.org>2021-12-22 16:39:34 +0100
commitb590eaa2f64ead3384eadc6fe58f6358aa1a0478 (patch)
tree8f1e9403c1a75246c2a9a0afc4ab30706ea7afbe /compute_scripts.awk
parentb7378a9994724750198e0d165c575be8538334fb (diff)
downloadbrowser-extension-b590eaa2f64ead3384eadc6fe58f6358aa1a0478.tar.gz
browser-extension-b590eaa2f64ead3384eadc6fe58f6358aa1a0478.zip
reworked build system; added missing license notices
Diffstat (limited to 'compute_scripts.awk')
-rwxr-xr-x[-rw-r--r--]compute_scripts.awk748
1 files changed, 619 insertions, 129 deletions
diff --git a/compute_scripts.awk b/compute_scripts.awk
index 3d8a5b0..9edc56d 100644..100755
--- a/compute_scripts.awk
+++ b/compute_scripts.awk
@@ -1,3 +1,5 @@
+#!/usr/bin/awk -f
+#
# SPDX-License-Identifier: CC0-1.0
#
# Process javascript files and resolve dependencies between them
@@ -15,195 +17,683 @@
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# CC0 1.0 Universal License for more details.
-function read_file(filename,
- imports_state, exports_state, line, record, result) {
- imports_state = "not_started"
- exports_state = "not_started"
+BEGIN {
+ true = 1
+ false = 0
+}
+
+BEGIN {
+ identifier_re = "[_a-zA-Z][_a-zA-Z0-9]*"
+ path_dir_re = "([-_a-zA-Z0-9][-._a-zA-Z0-9]*/)*"
+ path_ext_re = "(\\.[-_.a-zA-Z0-9]*)?"
+ path_re = "^" path_dir_re identifier_re path_ext_re "$"
+
+ directive_args_patterns["IF"] = "^(NOT[[:space:]]+)?" identifier_re "$"
+ directive_args_patterns["ENDIF"] = "^$"
+ directive_args_patterns["ELSE"] = "^$"
+ directive_args_patterns["ELIF"] = "^(NOT[[:space:]]+)?" identifier_re "$"
+ directive_args_patterns["ERROR"] = "^.*$"
+ directive_args_patterns["COPY"] = "^[^[:space:]]+$"
+ directive_args_patterns["INCLUDE"] = "^[^[:space:]]+$"
+ directive_args_patterns["INCLUDE_VERBATIM"] = "^[^[:space:]]+$"
+
+ AS_re = "AS[[:space:]]+" identifier_re
+ maybe_AS_re = "([[:space:]]+" AS_re ")?"
+ FROM_clause_re = identifier_re maybe_AS_re
+ more_FROM_clauses_re = "([[:space:]]*,[[:space:]]*" FROM_clause_re ")*"
+ FROM_IMPORT_re = "[^[:space:]]+[[:space:]]+IMPORT[[:space:]]+"
+ EXPORT_AS_re = ".*[^[:space:]][[:space:]]+" AS_re
+
+ directive_args_patterns["IMPORT"] = "^[^[:space:]]+" maybe_AS_re "$"
+ directive_args_patterns["FROM"] = ("^" FROM_IMPORT_re FROM_clause_re \
+ more_FROM_clauses_re "$")
+ directive_args_patterns["EXPORT"] = "^(" EXPORT_AS_re "|" identifier_re ")$"
+
+ directive_args_patterns["LOADJS"] = "^[^[:space:]]+$"
+}
+
+function validate_path(read_path, path, line) {
+ if (path !~ (path_re)) {
+ printf "ERROR: File path in %s does not match '%s': %s\n",
+ read_path, path_re, line > "/dev/stderr"
+ return 1
+ }
+
+ return 0
+}
+
+function identifier_from_path(path) {
+ sub("^" path_dir_re, "", path)
+ sub(path_ext_re "$", "", path)
+
+ return path
+}
+
+function last_token(line) {
+ sub("^.*[[:space:]]", "", line)
+
+ return line
+}
+
+function first_token(line) {
+ sub("[[:space:]].*$", "", line)
+
+ return line
+}
+
+function is_empty(array, key) {
+ for (key in array)
+ return false
+ return true
+}
- do {
- result = (getline line < filename)
+function clear_array(array, key) {
+ for (key in array)
+ delete array[key]
+}
+
+function add_line(path, line, where) {
+ if (where != "amalgamation_root_file")
+ lines[path,++lines_count[path]] = line
+
+ if (where != "non_amalgamation_file" &&
+ path == js_to_amalgamate)
+ main_js_lines[++main_js_lines_count] = line
+}
+
+BEGIN {
+ delete page_js_deps[0]
+ page_js_deps_count = 0
+}
+
+function process_file(path, read_path, mode,
+ line, result, line_part, directive, directive_args,
+ if_nesting, if_nesting_true, if_branch_processed) {
+ if (path in modes && modes[path] != mode) {
+ printf "ERROR: File %s used multiple times in different contexts\n",
+ path > "/dev/stderr"
+ return 1
+ }
+
+ if (mode == "html" && path == read_path) {
+ clear_array(page_js_deps)
+ page_js_deps_count = 0
+ }
+
+ modes[path] = mode
+
+ if (!(path in reading)) {
+ if (path in lines_count)
+ return 0
+ lines_count[path]
+ }
+
+ reading[read_path]
+
+ if (mode == "js" && path == read_path) {
+ add_line(path, "\"use strict\";")
+ add_line(path, "this.haketilo_exports = this.haketilo_exports || {};")
+ add_line(path, "this.haketilo_exports[\"" path "\"] = {};")
+
+ add_line(path, "window.globalThis = this", "amalgamation_root_file")
+
+ add_line(path, "")
+
+ add_line(path, "(function() {", "non_amalgamation_file")
+ add_line(path, "var globalThis = this.haketilo_this",
+ "non_amalgamation_file")
+ add_line(path, "{", "non_amalgamation_file")
+ }
+
+ while (true) {
+ result = (getline line < read_path)
if (result < 0) {
- printf "error reading %s", filename
- exit 1
+ printf "ERROR: Could not read %s\n", read_path > "/dev/stderr"
+ return 1
}
+ if (result == 0)
+ break
- if (imports_state == "started" &&
- line ~ /^([[:space:]]*\*[[:space:]]+)?IMPORT[[:space:]]+[_a-zA-Z][_a-zA-Z0-9]*[[:space:]]*$/) {
- record = line
+ if (line !~ /^#/) {
+ if (if_nesting_true == if_nesting)
+ add_line(path, line)
+ continue
+ }
- sub(/^([[:space:]]*\*[[:space:]]+)?IMPORT[[:space:]]+/, "", record)
- sub(/([[:space:]]+$)/, "", record)
+ while (line ~ /\\$/) {
+ sub(/\\$/, "", line)
- imports[filename,++import_counts[filename]] = record
+ result = (getline line_part < read_path)
+ if (result < 0) {
+ printf "ERROR: Could not read %s\n", read_path > "/dev/stderr"
+ return 1
+ }
+ if (result == 0) {
+ printf "ERROR: Unexpected EOF in %s\n",
+ read_path > "/dev/stderr"
+ return 1
+ }
+
+ line = line " " line_part
+ }
+
+ directive = substr(line, 2)
+ sub(/[[:space:]].*$/, "", directive)
+
+ if (directive !~ \
+ /^(IF|ENDIF|ELSE|ELIF|ERROR|INCLUDE|INCLUDE_VERBATIM|COPY_FILE)$/ &&
+ (mode != "js" || directive !~ /^(IMPORT|FROM|EXPORT)$/) &&
+ (mode != "html" || directive !~ /^LOADJS$/) &&
+ (mode != "manifest" || directive !~ /^(LOADJS|LOADHTML)$/)) {
+ printf "ERROR: Invalid # directive in %s: %s\n",
+ read_path, line > "/dev/stderr"
+ return 1
+ }
+
+ directive_args = line
+ sub(/^#[^[:space:]]*[[:space:]]*/, "", directive_args)
+ sub(/[[:space:]]*$/, "", directive_args)
+
+ if (directive_args !~ directive_args_patterns[directive]) {
+ printf "ERROR: #%s arguments in %s do not match '%s': %s\n",
+ directive, read_path, directive_args_patterns[directive], line \
+ > "/dev/stderr"
+ return 1
}
- if (imports_state == "started" &&
- line ~ /^([[:space:]]*\*[[:space:]]+)?IMPORTS_END[[:space:]]*$/)
- imports_state = "finished"
- if (imports_state == "not_started" &&
- line ~ /^([[:space:]]*\*[[:space:]]+)?IMPORTS_START[[:space:]]*$/)
- imports_state = "started"
-
- if (exports_state == "started" &&
- line ~ /^([[:space:]]*\*[[:space:]]+)?EXPORT[[:space:]]+[_a-zA-Z][_a-zA-Z0-9]*[[:space:]]*$/) {
- record = line
-
- sub(/^([[:space:]]*\*[[:space:]]+)?EXPORT[[:space:]]+/, "", record)
- sub(/([[:space:]]+$)/, "", record)
-
- if (record in exports) {
- printf "ERROR: '%s' exported by both %s and %s\n",
- exports[record], filename > "/dev/stderr"
+
+ if (directive == "IF") {
+ if (if_nesting_true == if_nesting) {
+ if ((last_token(directive_args) in defines) == \
+ (directive_args ~ /^[^[:space:]]+$/))
+ if_nesting_true++
+ else
+ if_branch_processed = false
}
- provides[record] = filename
- exports[filename,++export_counts[filename]] = record
+ if_nesting++
+ } else if (directive == "ENDIF") {
+ if (if_nesting == 0) {
+ printf "ERROR: Spurious #ENDIF in %s\n",
+ read_path > "/dev/stderr"
+ return 1
+ }
+
+ if (if_nesting_true == if_nesting)
+ if_nesting_true--
+
+ if_nesting--
+ } else if (directive == "ELSE") {
+ if (if_nesting == 0) {
+ printf "ERROR: Spurious #ELSE in %s\n",
+ read_path > "/dev/stderr"
+ return 1
+ }
+
+ if (if_nesting == if_nesting_true + 1 && !if_branch_processed) {
+ if_nesting_true++
+ } else if (if_nesting == if_nesting_true) {
+ if_branch_processed = true
+ if_nesting_true--
+ }
+ } else if (directive == "ELIF") {
+ if (if_nesting == 0) {
+ printf "ERROR: Spurious #ELIF in %s\n",
+ read_path > "/dev/stderr"
+ return 1
+ }
+
+ if (if_nesting == if_nesting_true + 1 && !if_branch_processed &&
+ (last_token(directive_args) in defines) == \
+ (directive_args ~ /^[^[:space:]]+$/)) {
+ if_nesting_true++
+ } else if (if_nesting == if_nesting_true) {
+ if_branch_processed = true
+ if_nesting_true--
+ }
+ } else if (if_nesting_true != if_nesting) {
+ continue
+ } else if (directive == "ERROR") {
+ printf "ERROR: File %s says: %s\n",
+ read_path, directive_args > "/dev/stderr"
+ return 1
+ } else if (directive == "INCLUDE") {
+ if (include_file(path, read_path, directive_args, line))
+ return 1
+ } else if (directive == "INCLUDE_VERBATIM") {
+ if (include_file(path, read_path, directive_args, line, true))
+ return 1
+ } else if (directive == "COPY_FILE") {
+ if (mark_copy_file(path, read_path, directive_args, line))
+ return 1
+ } else if (directive == "IMPORT") {
+ if (import_js_file(path, read_path, directive_args, line))
+ return 1
+ } else if (directive == "FROM") {
+ if (import_from_js_file(path, read_path, directive_args, line))
+ return 1
+ } else if (directive == "EXPORT") {
+ if (export_from_js_file(path, read_path, directive_args, line))
+ return 1
+ } else if (directive == "LOADJS") {
+ if (mode == "html") {
+ page_js_deps_count = \
+ load_js_file(path, read_path, directive_args, line,
+ page_js_deps, page_js_deps_count)
+ if (page_js_deps_count < 1)
+ return 1
+ } else if (mode == "manifest") {
+ if (load_js_file(path, read_path, directive_args, line) < 1)
+ return 1
+ }
+ } else if (directive == "LOADHTML") {
+ if (load_html_file(path, read_path, directive_args, line))
+ return 1
}
- if (exports_state == "started" &&
- line ~ /^([[:space:]]*\*[[:space:]]+)?EXPORTS_END[[:space:]]*$/)
- exports_state = "finished"
- if (exports_state == "not_started" &&
- line ~ /^([[:space:]]*\*[[:space:]]+)?EXPORTS_START[[:space:]]*$/)
- exports_state = "started"
- } while (result > 0)
+ }
+
+ close(read_path)
- if (imports_state == "started") {
- printf "ERROR: Unclosed IMPORTS list in '%s'\n", filename \
- > "/dev/stderr"
- exit 1
+ if (if_nesting) {
+ printf "ERROR: Unterminated #IF in %s\n", read_path > "/dev/stderr"
+ return 1
}
- if (exports_state == "started") {
- printf "ERROR: Unclosed EXPORTS list in '%s'\n", filename \
- > "/dev/stderr"
- exit 1
+ if (mode == "js" && path == read_path) {
+ add_line(path, "}", "non_amalgamation_file")
+ add_line(path, "}).call({", "non_amalgamation_file")
+ add_line(path, " haketilo_exports: this.haketilo_exports,",
+ "non_amalgamation_file")
+ add_line(path, " haketilo_this: this",
+ "non_amalgamation_file")
+ add_line(path, "});", "non_amalgamation_file")
}
- close(filename)
+ delete reading[read_path]
}
-function print_file(filename, line) {
- while ((getline line < filename) > 0)
- print(line)
+function include_file(root_path, read_path, included_path, line, verbatim,
+ read_line, result) {
+ if (validate_path(read_path, included_path, line))
+ return 1
+
+ if (included_path in reading) {
+ printf "ERROR: Inclusion loop when including %s in %s\n",
+ included_path, read_path > "/dev/stderr"
+ return 1
+ }
+
+ if (verbatim) {
+ while(true) {
+ result = (getline read_line < included_path)
+ if (result > 0)
+ add_line(root_path, read_line)
+ else
+ break
+ }
+
+ if (result == 0) {
+ close(included_path)
+ return 0
+ }
- close(filename)
+ printf "ERROR: Could not read %s\n", included_path > "/dev/stderr"
+ } else {
+ if (process_file(root_path, included_path, modes[root_path]) == 0)
+ return 0
+ }
+
+ printf " when including %s in %s\n",
+ included_path, read_path > "/dev/stderr"
+
+ return 1
}
-function print_imports_code(filename, declarator, i, count, import_name) {
- count = import_counts[filename]
- for (i = 1; i <= count; i++) {
- import_name = imports[filename,i]
- printf "%s %s = window.haketilo_exports.%s;\n",
- declarator, import_name, import_name
+function mark_copy_file(root_path, read_path, copied_path, line) {
+ if (validate_path(read_path, copied_path, line))
+ return 1
+
+ to_copy[copied_path]
+
+ return 0
+}
+
+function satisfy_import(root_path, imported_path, as, what,
+ added_line, description, count) {
+ if ((root_path,as) in imports_from) {
+ printf "ERROR: Multiple items imported under the name '%s' in %s\n",
+ as, root_path > "/dev/stderr"
+ return 1
}
+
+ added_line = " " as " = haketilo_exports[\"" imported_path "\"]"
+ if (what)
+ added_line = added_line "." what
+
+ add_line(root_path, "const" added_line ";", "non_amalgamation_file")
+ add_line(root_path, "let" added_line ";", "amalgamation_root_file")
+
+ count = ++import_counts[root_path]
+
+ imports_as [root_path,count] = as
+ imports_from[root_path,as] = imported_path
+ imports_what[root_path,as] = what
+
+ if (what)
+ description = "'" what "' from " imported_path
+ else
+ description = imported_path
+
+ description = description " needed by " root_path
+
+ if (imported_path in reading) {
+ printf "ERROR: dependency loop when importing %s\n",
+ description > "/dev/stderr"
+ return 1
+ } else if (process_file(imported_path, imported_path, "js")) {
+ printf " when importing %s\n", description > "/dev/stderr"
+ return 1
+ }
+
+ if (what && !((imported_path,what) in exports)) {
+ printf "ERROR: %s doesn't export '%s' needed by %s\n",
+ imported_path, what, root_path > "/dev/stderr"
+ return 1
+ }
+
+ return 0
}
-function print_exports_code(filename, i, count, export_name) {
- count = export_counts[filename]
- for (i = 1; i <= count; i++) {
- export_name = exports[filename,i]
- printf "window.haketilo_exports.%s = %s;\n", export_name, export_name
+function import_js_file(root_path, read_path, directive_args, line,
+ imported_path, as) {
+ imported_path = first_token(directive_args)
+ if (validate_path(read_path, imported_path, line))
+ return 1
+
+ if (line ~ (AS_re "$"))
+ as = last_token(directive_args)
+ else
+ as = identifier_from_path(imported_path)
+
+ return satisfy_import(root_path, imported_path, as)
+}
+
+function import_from_js_file(root_path, read_path, directive_args, line,
+ imported_path, args_copy, FROM_clause, as) {
+ imported_path = first_token(directive_args)
+ if (validate_path(read_path, imported_path, line))
+ return 1
+
+ args_copy = directive_args
+ sub("^" FROM_IMPORT_re, "", args_copy)
+ args_copy = "," args_copy
+
+ while (args_copy ~ /,/) {
+ sub(/^[^,]*,[[:space:]]*/, "", args_copy)
+
+ FROM_clause = args_copy
+ sub(/[[:space:]]*,.*$/, "", FROM_clause)
+
+ if (satisfy_import(root_path, imported_path,
+ last_token(FROM_clause), first_token(FROM_clause)))
+ return 1
}
+
+ return 0
}
-function partially_wrap_file(filename, declarator) {
- if (!declarator)
- declarator = "const"
+function export_from_js_file(root_path, read_path, directive_args, line,
+ as, exported_item, added_line) {
+ as = last_token(directive_args)
+
+ if (directive_args ~ ("^" identifier_re "$")) {
+ exported_item = as
+ } else {
+ exported_item = directive_args
+ sub("[[:space:]]+" AS_re "$", "", exported_item)
+ }
+
+ if ((root_path,as) in exports) {
+ printf "ERROR: Multiple values exported under the name '%s' in %s\n",
+ as, root_path > "/dev/stderr"
+ return 1
+ }
- print_imports_code(filename, declarator)
- printf "\n\n"
+ added_line = \
+ "this.haketilo_exports[\"" root_path "\"]." as " = (" exported_item ");"
+ add_line(root_path, added_line)
- print_file(filename)
+ exports[root_path,as]
- printf "\n\n"
- print_exports_code(filename)
+ return 0
}
-function wrap_file(filename) {
- print "\"use strict\";\n\n({fun: (function() {\n"
+function compute_deps(js_path, dependencies, count, dependencies_added,
+ i_max, i, as, next_path) {
+ delete dependencies_added[0]
- partially_wrap_file(filename)
+ if (process_file(js_path, js_path, "js"))
+ return 0
- print "\n})}).fun();"
+ i_max = import_counts[js_path]
+ for (i = 1; i <= i_max; i++) {
+ as = imports_as[js_path,i]
+ next_path = imports_from[js_path,as]
+ if (next_path in dependencies_added)
+ continue
+
+ count = compute_deps(next_path, dependencies, count, dependencies_added)
+ if (count < 1)
+ return 0
+ }
+
+ dependencies_added[js_path]
+ dependencies[++count] = js_path
+
+ return count
}
-function compute_dependencies(filename, i, count, import_name, next_file) {
- if (processed[filename] == "used")
+# Here js_deps and js_deps_count are optional args, used when loading scripts
+# into an HTML page to avoid having th same script loaded twice in multiple
+# places.
+function load_js_file(root_path, read_path, loaded_path, line,
+ js_deps, js_deps_count,
+ js_deps_already_added, i, added_line) {
+ delete js_deps[""]
+ delete js_deps_already_added[0]
+
+ if (validate_path(read_path, loaded_path, line))
return 0
- if (processed[filename] == "on_stack") {
- printf "import loop on %s\n", filename > "/dev/stderr"
+ for (i = 1; i <= js_deps_count; i++)
+ js_deps_already_added[js_deps[i]]
+
+ i = js_deps_count
+
+ js_deps_count = compute_deps(loaded_path, js_deps,
+ js_deps_count, js_deps_already_added)
+
+ if (js_deps_count < 1) {
+ printf " when loading %s from %s\n",
+ loaded_path, read_path > "/dev/stderr"
+ return 0
+ }
+
+ while (++i <= js_deps_count) {
+ if (modes[root_path] == "html") {
+ added_line = "<script src=\"/" js_deps[i] "\"></script>"
+ } else { #if (modes[root_path] == "manifest") {
+ added_line = "\"" js_deps[i] "\""
+ if (i != js_deps_count)
+ added_line = added_line ","
+ }
+ add_line(root_path, added_line)
+ }
+
+ return js_deps_count
+}
+
+function load_html_file(root_path, read_path, loaded_path, line) {
+ if (validate_path(read_path, loaded_path, line))
+ return 1
+
+ if (process_file(loaded_path, loaded_path, "html")) {
+ printf " when loading %s from %s\n",
+ loaded_path, read_path, line > "/dev/stderr"
return 1
}
- processed[filename] = "on_stack"
+ return 0
+}
- count = import_counts[filename]
- for (i = 1; i <= count; i++) {
- import_name = imports[filename,i]
- if (!(import_name in provides)) {
- printf "nothing exports %s, required by %s\n",
- import_name, filename > "/dev/stderr"
- return 1
- }
+function print_amalgamation(js_deps, js_deps_count,
+ js_dep_nr, path, max_line_nr, line_nr) {
+ delete js_deps[0]
- if (compute_dependencies(provides[import_name]) > 0) {
- printf "when satisfying %s for %s\n",
- import_name, filename > "/dev/stderr"
- return 1
- }
+ js_deps_count = compute_deps(js_to_amalgamate, js_deps, 0)
+ if (js_deps_count < 1)
+ return 1
+
+ # '<' instead of '<=' because we print the main js file below instead
+ for (js_dep_nr = 1; js_dep_nr < js_deps_count; js_dep_nr++) {
+ path = js_deps[js_dep_nr]
+ max_line_nr = lines_count[path]
+
+ for (line_nr = 1; line_nr <= max_line_nr; line_nr++)
+ print lines[path, line_nr]
}
- processed[filename] = "used"
- print filename
+ for (line_nr = 1; line_nr <= main_js_lines_count; line_nr++)
+ print main_js_lines[line_nr]
return 0
}
function print_usage() {
- printf "usage: %2 compute_scripts.awk script_dependencies|wrapped_code|partially_wrapped_code FILENAME[...]\n",
+ printf "USAGE: %s compute_scripts.awk -- [-D PREPROCESSOR_DEFINITION]... [-M manifest/to/process/manifest.json]... [-H html/to/process.html]... [-J js/to/process.js]... [--help|-h] [--output-dir=./build] [--write-js-deps] [--write-html-deps] [--output=files-to-copy|--output=amalgamate-js:js/to/process.js]\n",
ARGV[0] > "/dev/stderr"
- exit 1
}
-function mock_exports_init() {
- provides["browser"] = "exports_init.js"
- provides["is_chrome"] = "exports_init.js"
- provides["is_mozilla"] = "exports_init.js"
- provides["initial_data"] = "exports_init.js"
-
- processed["exports_init.js"] = "used"
+BEGIN {
+ option_arg_patterns["D"] = "^" identifier_re "$"
+ option_arg_patterns["M"] = path_re
+ option_arg_patterns["H"] = path_re
+ option_arg_patterns["J"] = path_re
}
-BEGIN {
- operation = ARGV[1]
+function main(i, path, letter, dir, max_line_nr, js_deps, js_deps_count) {
+ output_dir = "./build"
+ write_js_deps = false
+ write_html_deps = false
- if (ARGC < 3)
- print_usage()
+ output = ""
+ js_to_amalgamate = ""
+ delete main_js_lines[0]
- root_filename = ARGV[2]
+ delete manifests_to_process[0]
+ delete html_to_process[0]
+ delete js_to_process[0]
- for (i = 2; i < ARGC; i++)
- filenames[ARGV[i]]
+ delete explicitly_requested[0]
- mock_exports_init()
+ for (i = 1; i < ARGC; i++) {
+ if (ARGV[i] ~ /^-[DMHJ]$/) {
+ letter = substr(ARGV[i++], 2)
+ if (i == ARGC || ARGV[i] !~ option_arg_patterns[letter]) {
+ printf "ERROR: '-%s' option should be followed by an argument matching '%s'\n",
+ letter, option_arg_patterns[letter] > "/dev/stderr"
+ return 1
+ }
- for (filename in filenames) {
- # A filename is allowed to appear multiple times in the list.
- # Let's only process it once.
- if (!(filename in processed))
- read_file(filename)
- processed[filename] = "not_used"
+ if (letter == "D")
+ defines[ARGV[i]]
+ else
+ explicitly_requested[ARGV[i]]
+
+ if (letter == "M")
+ manifests_to_process[ARGV[i]]
+ if (letter == "H")
+ html_to_process[ARGV[i]]
+ if (letter == "J")
+ js_to_process[ARGV[i]]
+ } else if (ARGV[i] ~ /^-(-help|h)$/ ) {
+ print_usage()
+ return 0
+ } else if (ARGV[i] ~ /^--output-dir=/) {
+ output_dir = ARGV[i]
+ sub(/^--output-dir=/, "", output_dir)
+ } else if (ARGV[i] ~ /^--write-js-deps$/) {
+ write_js_deps = true
+ } else if (ARGV[i] ~ /^--write-html-deps$/) {
+ write_html_deps = true
+ } else if (ARGV[i] ~ /^--output=files-to-copy$/) {
+ output = "files-to-copy"
+ } else if (ARGV[i] ~ /^--output=amalgamate-js:/) {
+ output = "amalgamate-js"
+ js_to_amalgamate = ARGV[i]
+ sub(/^--output=amalgamate-js:/, "", js_to_amalgamate)
+ if (js_to_amalgamate !~ path_re) {
+ printf "ERROR: amalgamate-js path does not match '%s': %s\n",
+ path_re, js_to_amalgamate > "/dev/stderr"
+ return 1
+ }
+ } else {
+ printf "ERROR: Unknown option '%s'\n", ARGV[i] > "/dev/stderr"
+ print_usage()
+ return 1
+ }
}
- if (operation == "script_dependencies") {
- print("exports_init.js")
- if (compute_dependencies(root_filename) > 0)
- exit 1
- } else if (operation == "partially_wrapped_code") {
- partially_wrap_file(root_filename, "let")
- } else if (operation == "wrapped_code") {
- wrap_file(root_filename)
- } else {
- print_usage()
+ if (is_empty(explicitly_requested) && output != "amalgamate-js") {
+ explicitly_requested["manifest.json"]
+ manifests_to_process["manifest.json"]
}
+
+ for (path in manifests_to_process) {
+ if (process_file(path, path, "manifest"))
+ return 1
+ }
+ for (path in html_to_process) {
+ if (process_file(path, path, "html"))
+ return 1
+ }
+ for (path in js_to_process) {
+ if (process_file(path, path, "js"))
+ return 1
+ }
+
+ for (path in lines_count) {
+ if (!(path in explicitly_requested) &&
+ !(modes[path] == "js" && write_js_deps) &&
+ !(modes[path] == "html" && write_html_deps))
+ continue
+
+ dir = path
+ sub(/[^/]*$/, "", dir)
+ dir = output_dir "/" dir
+ sub("'", "'\\''", dir)
+
+ system("mkdir -p '" dir "'")
+
+ printf "" > (output_dir "/" path)
+
+ max_line_nr = lines_count[path]
+ for (i = 1; i <= max_line_nr; i++)
+ print lines[path, i] >> (output_dir "/" path)
+ }
+
+ if (output == "files-to-copy") {
+ for (path in to_copy)
+ print path
+ }
+
+ if (output == "amalgamate-js") {
+ if (print_amalgamation())
+ return 1
+ }
+
+ return 0
+}
+
+BEGIN {
+ exit main()
}