From e0a6b233dc6880a357024b5d7955902f01b0c7cb Mon Sep 17 00:00:00 2001
From: Brendan Dahl <brendan.dahl@gmail.com>
Date: Wed, 1 Aug 2012 14:27:42 -0700
Subject: [PATCH] Move builder/preprocessor into its own file.

---
 external/builder/builder.js | 142 ++++++++++++++++++++++++++++++++
 make.js                     | 160 +++---------------------------------
 2 files changed, 155 insertions(+), 147 deletions(-)
 create mode 100644 external/builder/builder.js

diff --git a/external/builder/builder.js b/external/builder/builder.js
new file mode 100644
index 000000000..6eb0cd6ae
--- /dev/null
+++ b/external/builder/builder.js
@@ -0,0 +1,142 @@
+require('../shelljs/make');
+var fs = require('fs'),
+    path = require('path'),
+    vm = require('vm');
+
+/**
+ * A simple preprocessor that is based on the firefox preprocessor
+ * see (https://developer.mozilla.org/en/Build/Text_Preprocessor).  The main
+ * difference is that this supports a subset of the commands and it supports
+ * preproccesor commands in html style comments.
+ * Currently Supported commands:
+ * - if
+ * - else
+ * - endif
+ * - include
+ * - expand
+ */
+function preprocess(inFilename, outFilename, defines) {
+  // TODO make this really read line by line.
+  var lines = fs.readFileSync(inFilename).toString().split('\n');
+  var totalLines = lines.length;
+  var out = '';
+  var i = 0;
+  function readLine() {
+    if (i < totalLines) {
+      return lines[i++];
+    }
+    return null;
+  }
+  var writeLine = typeof outFilename === 'function' ? outFilename : function(line) {
+    out += line + '\n';
+  }
+  function include(file) {
+    var realPath = fs.realpathSync(inFilename);
+    var dir = path.dirname(realPath);
+    preprocess(path.join(dir, file), writeLine, defines);
+  }
+  function expand(line) {
+    line = line.replace(/__[\w]+__/g, function(variable) {
+      variable = variable.substring(2, variable.length - 2);
+      if (variable in defines) {
+        return defines[variable];
+      }
+      return '';
+    });
+    writeLine(line);
+  }
+
+  var s, state = 0, stack = [];
+  var control = /^(?:\/\/|<!--)\s*#(if|else|endif|expand|include)(?:\s+(.*?)(?:-->)?$)?/;
+  var lineNumber = 0;
+  while ((s = readLine()) !== null) {
+    ++lineNumber;
+    var m = control.exec(s);
+    if (m) {
+      switch (m[1]) {
+        case 'if':
+          stack.push(state);
+          try {
+            state = vm.runInNewContext(m[2], defines) ? 3 : 1;
+          } catch (e) {
+            console.error('Could not evalute line \'' + m[2] + '\' at ' +
+                          fs.realpathSync(inFilename) + ':' + lineNumber);
+            throw e;
+          }
+          break;
+        case 'else':
+          state = state === 1 ? 3 : 2;
+          break;
+        case 'endif':
+          state = stack.pop();
+          break;
+        case 'expand':
+          if (state === 0 || state === 3)
+            expand(m[2]);
+          break;
+        case 'include':
+          if (state === 0 || state === 3)
+            include(m[2]);
+          break;
+      }
+    } else {
+      if (state === 0) {
+        writeLine(s);
+      } else if(state === 3) {
+        writeLine(s.replace(/^\/\/|^<!--|-->/g, "  "));
+      }
+    }
+  }
+  if (state !== 0 || stack.length !== 0)
+    throw new Error('Missing endif in preprocessor.');
+  if (typeof outFilename !== 'function')
+    fs.writeFileSync(outFilename, out);
+}
+exports.preprocess = preprocess;
+
+/**
+ * Simplifies common build steps.
+ * @param setup
+ *        .defines defines for preprocessors
+ *        .copy array of arrays of source and destination pairs of files to copy
+ *        .preprocess array of arrays of source and destination pairs of files
+ *                    run through preprocessor
+ */
+function build(setup) {
+  var defines = setup.defines;
+
+  setup.copy.forEach(function(option) {
+    var source = option[0];
+    var destination = option[1];
+    cp('-R', source, destination);
+  });
+
+  setup.preprocess.forEach(function(option) {
+    var sources = option[0];
+    var destination = option[1];
+
+    sources = ls('-R', sources);
+    sources.forEach(function(source) {
+      // ??? Warn if the source is wildcard and dest is file?
+      var destWithFolder = destination;
+      if (test('-d', destination))
+        destWithFolder += '/' + path.basename(source);
+      preprocess(source, destWithFolder, defines);
+    });
+  });
+}
+exports.build = build;
+
+/**
+ * Merge two defines arrays. Values in the second param will override values in
+ * the first.
+ */
+function merge(defaults, defines) {
+  var ret = {};
+  for (var key in defaults)
+    ret[key] = defaults[key];
+  for (key in defines)
+    ret[key] = defines[key];
+  return ret;
+}
+exports.merge = merge;
diff --git a/make.js b/make.js
index 670aa6645..1d2e5cfcf 100755
--- a/make.js
+++ b/make.js
@@ -1,8 +1,6 @@
 #!/usr/bin/env node
 require('./external/shelljs/make');
-var fs = require('fs');
-var path = require('path');
-var vm = require('vm');
+var builder = require('./external/builder/builder.js');
 
 var ROOT_DIR = __dirname + '/', // absolute path to project's root
     BUILD_DIR = 'build/',
@@ -29,138 +27,6 @@ var DEFINES = {
   CHROME: false
 };
 
-function extendDefines(obj) {
-  var ret = {};
-  for (var key in DEFINES)
-    ret[key] = DEFINES[key];
-  for (key in obj)
-    ret[key] = obj[key];
-  return ret;
-}
-
-var BuildHelper = {
-  /**
-   * A simple preprocessor that is based on the firefox preprocessor
-   * see (https://developer.mozilla.org/en/Build/Text_Preprocessor).  The main
-   * difference is that this supports a subset of the commands and it supports
-   * preproccesor commands in html style comments.
-   * Currently Supported commands:
-   * - if
-   * - else
-   * - endif
-   * - include
-   * - expand
-   */
-  preprocess: function preprocess(inFilename, outFilename, defines) {
-    // TODO make this really read line by line.
-    var lines = fs.readFileSync(inFilename).toString().split('\n');
-    var totalLines = lines.length;
-    var out = '';
-    var i = 0;
-    function readLine() {
-      if (i < totalLines) {
-        return lines[i++];
-      }
-      return null;
-    }
-    var writeLine = typeof outFilename === 'function' ? outFilename : function(line) {
-      out += line + '\n';
-    }
-    function include(file) {
-      var realPath = fs.realpathSync(inFilename);
-      var dir = path.dirname(realPath);
-      preprocess(path.join(dir, file), writeLine, defines);
-    }
-    function expand(line) {
-      line = line.replace(/__[\w]+__/g, function(variable) {
-        variable = variable.substring(2, variable.length - 2);
-        if (variable in defines) {
-          return defines[variable];
-        }
-        return '';
-      });
-      writeLine(line);
-    }
-
-    var s, state = 0, stack = [];
-    var control = /^(?:\/\/|<!--)\s*#(if|else|endif|expand|include)(?:\s+(.*?)(?:-->)?$)?/;
-    var lineNumber = 0;
-    while ((s = readLine()) !== null) {
-      ++lineNumber;
-      var m = control.exec(s);
-      if (m) {
-        switch (m[1]) {
-          case 'if':
-            stack.push(state);
-            try {
-              state = vm.runInNewContext(m[2], defines) ? 3 : 1;
-            } catch (e) {
-              console.error('Could not evalute line \'' + m[2] + '\' at ' +
-                            fs.realpathSync(inFilename) + ':' + lineNumber);
-              throw e;
-            }
-            break;
-          case 'else':
-            state = state === 1 ? 3 : 2;
-            break;
-          case 'endif':
-            state = stack.pop();
-            break;
-          case 'expand':
-            if (state === 0 || state === 3)
-              expand(m[2]);
-            break;
-          case 'include':
-            if (state === 0 || state === 3)
-              include(m[2]);
-            break;
-        }
-      } else {
-        if (state === 0) {
-          writeLine(s);
-        } else if(state === 3) {
-          writeLine(s.replace(/^\/\/|^<!--|-->/g, "  "));
-        }
-      }
-    }
-    if (state !== 0 || stack.length !== 0)
-      throw new Error('Missing endif in preprocessor.');
-    if (typeof outFilename !== 'function')
-      fs.writeFileSync(outFilename, out);
-  },
-  /**
-   * Simplifies common build steps.
-   * @param setup
-   *        .defines defines for preprocessors
-   *        .copy array of arrays of source and destination pairs of files to copy
-   *        .preprocess array of arrays of source and destination pairs of files
-   *                    run through preprocessor
-   */
-  build: function build(setup) {
-    var defines = setup.defines;
-
-    setup.copy.forEach(function(option) {
-      var source = option[0];
-      var destination = option[1];
-      cp('-R', source, destination);
-    });
-
-    setup.preprocess.forEach(function(option) {
-      var sources = option[0];
-      var destination = option[1];
-
-      sources = ls('-R', sources);
-      sources.forEach(function(source) {
-        // ??? Warn if the source is wildcard and dest is file?
-        var destWithFolder = destination;
-        if (test('-d', destination))
-          destWithFolder += '/' + path.basename(source);
-        BuildHelper.preprocess(source, destWithFolder, defines);
-      });
-    });
-  }
-};
-
 //
 // make all
 //
@@ -204,7 +70,7 @@ target.generic = function() {
   mkdir('-p', GENERIC_DIR + BUILD_DIR);
   mkdir('-p', GENERIC_DIR + '/web');
 
-  var defines = extendDefines({GENERIC: true});
+  var defines = builder.merge(DEFINES, {GENERIC: true});
 
   var setup = {
     defines: defines,
@@ -220,7 +86,7 @@ target.generic = function() {
       [COMMON_WEB_FILES_PREPROCESS, GENERIC_DIR + '/web']
     ]
   };
-  BuildHelper.build(setup);
+  builder.build(setup);
 };
 
 //
@@ -354,7 +220,7 @@ target.bundle = function() {
 
   // This just preprocesses the empty pdf.js file, we don't actually want to
   // preprocess everything yet since other build targets use this file.
-  BuildHelper.preprocess('pdf.js', ROOT_DIR + BUILD_TARGET,
+  builder.preprocess('pdf.js', ROOT_DIR + BUILD_TARGET,
                          {BUNDLE: bundle, BUNDLE_VERSION: bundleVersion});
 };
 
@@ -435,7 +301,7 @@ target.firefox = function() {
   cd(ROOT_DIR);
   echo();
   echo('### Building Firefox extension');
-  var defines = extendDefines({FIREFOX: true});
+  var defines = builder.merge(DEFINES, {FIREFOX: true});
 
   var FIREFOX_BUILD_CONTENT_DIR = FIREFOX_BUILD_DIR + '/content/',
       FIREFOX_EXTENSION_DIR = 'extensions/firefox/',
@@ -488,7 +354,7 @@ target.firefox = function() {
       [COMMON_WEB_FILES_PREPROCESS, FIREFOX_BUILD_CONTENT_DIR + '/web']
     ]
   };
-  BuildHelper.build(setup);
+  builder.build(setup);
 
   // Remove '.DS_Store' and other hidden files
   find(FIREFOX_BUILD_DIR).forEach(function(file) {
@@ -531,7 +397,7 @@ target.mozcentral = function() {
   cd(ROOT_DIR);
   echo();
   echo('### Building mozilla-central extension');
-  var defines = extendDefines({MOZCENTRAL: true});
+  var defines = builder.merge(DEFINES, {MOZCENTRAL: true});
 
   var MOZCENTRAL_DIR = BUILD_DIR + 'mozcentral/',
       MOZCENTRAL_EXTENSION_DIR = MOZCENTRAL_DIR + 'browser/extensions/pdfjs/',
@@ -586,7 +452,7 @@ target.mozcentral = function() {
       [COMMON_WEB_FILES_PREPROCESS, MOZCENTRAL_CONTENT_DIR + '/web']
     ]
   };
-  BuildHelper.build(setup);
+  builder.build(setup);
 
   // Remove '.DS_Store' and other hidden files
   find(MOZCENTRAL_DIR).forEach(function(file) {
@@ -624,9 +490,9 @@ target.b2g = function() {
   echo('### Building B2G (Firefox OS App)');
   var B2G_BUILD_DIR = BUILD_DIR + '/b2g/',
       B2G_BUILD_CONTENT_DIR = B2G_BUILD_DIR + '/content/';
-  var defines = extendDefines({ B2G: true });
+  var defines = builder.merge(DEFINES, { B2G: true });
   target.bundle();
-  
+
   // Clear out everything in the b2g build directory
   cd(ROOT_DIR);
   rm('-Rf', B2G_BUILD_DIR);
@@ -646,7 +512,7 @@ target.b2g = function() {
       [BUILD_TARGET, B2G_BUILD_CONTENT_DIR + BUILD_TARGET]
     ]
   };
-  BuildHelper.build(setup);
+  builder.build(setup);
 };
 
 //
@@ -656,7 +522,7 @@ target.chrome = function() {
   cd(ROOT_DIR);
   echo();
   echo('### Building Chrome extension');
-  var defines = extendDefines({CHROME: true});
+  var defines = builder.merge(DEFINES, {CHROME: true});
 
   var CHROME_BUILD_DIR = BUILD_DIR + '/chrome/',
       CHROME_BUILD_CONTENT_DIR = CHROME_BUILD_DIR + '/content/';
@@ -684,7 +550,7 @@ target.chrome = function() {
       ['web/locale.properties', CHROME_BUILD_CONTENT_DIR + '/web']
     ]
   };
-  BuildHelper.build(setup);
+  builder.build(setup);
 };