Index: config.json
===================================================================
--- config.json	(revision 338)
+++ config.json	(revision 342)
@@ -32,5 +32,5 @@
   {
     "APPLICATION"  : "pf",
-    "QOOXDOO_PATH" : "/usr/local/share/qooxdoo/2.1.2",
+    "QOOXDOO_PATH" : "/usr/local/share/qooxdoo/3.0.2",
     "QXTHEME"      : "pf.theme.Modern",
     "API_EXCLUDE"  : ["qx.test.*", "${APPLICATION}.theme.*"],
Index: generate.py
===================================================================
--- generate.py	(revision 139)
+++ generate.py	(revision 342)
@@ -1,3 +1,4 @@
 #!/usr/bin/env python
+# -*- coding: utf-8 -*-
 ################################################################################
 #
@@ -7,5 +8,5 @@
 #
 #  Copyright:
-#    2008 - 2009 1&1 Internet AG, Germany, http://www.1und1.de
+#    2008 - 2012 1&1 Internet AG, Germany, http://www.1und1.de
 #
 #  License:
@@ -23,22 +24,96 @@
 ##
 
-import sys, os, re, subprocess
+import sys, os, re, subprocess, codecs, optparse
 
-CMD_PYTHON = 'python'
-QOOXDOO_PATH = ''
+CMD_PYTHON = sys.executable
+QOOXDOO_PATH = '..'
+QX_PYLIB = "tool/pylib"
+
+##
+# A derived OptionParser class that ignores unknown options (The parent
+# class raises in those cases, and stops further processing).
+# We need this, as we are only interested in -c/--config on this level, and
+# want to ignore pot. other options.
+#
+class IgnoringUnknownOptionParser(optparse.OptionParser):
+    ##
+    # <rargs> is the raw argument list. The original _process_args mutates
+    # rargs, processing options into <values> and copying interspersed args
+    # into <largs>. This overridden version ignores unknown or ambiguous
+    # options.
+    def _process_args(self, largs, rargs, values):
+        while rargs:
+            try:
+                optparse.OptionParser._process_args(self, largs, rargs, values)
+            except (optparse.BadOptionError, optparse.AmbiguousOptionError):
+                pass
+
+
+def parseArgs():
+    parser = IgnoringUnknownOptionParser(add_help_option=False)
+    parser.add_option(
+        "-c", "--config", dest="config", metavar="CFGFILE",
+        default="config.json", help="path to configuration file"
+    )
+    parser.add_option(
+        "-v", "--verbose", dest="verbose", action="store_true",
+        default=False, help="run in verbose mode"
+    )
+    (options, args) = parser.parse_args(sys.argv[1:])
+    return options, args
+
+ShellOptions, ShellArgs = parseArgs()
+
+
+# this is from misc.json, duplicated for decoupling
+_eolComment = re.compile(r'(?<![a-zA-Z]:)//.*$', re.M) # double $ for string.Template
+_mulComment = re.compile(r'/\*.*?\*/', re.S)
+def stripComments(s):
+    b = _eolComment.sub('',s)
+    b = _mulComment.sub('',b)
+    return b
 
 def getQxPath():
     path = QOOXDOO_PATH
-    # try updating from config file
-    if os.path.exists('config.json'):
-        # "using QOOXDOO_PATH from config.json"
-        qpathr=re.compile(r'"QOOXDOO_PATH"\s*:\s*"([^"]*)"\s*,?')
-        conffile = open('config.json')
-        aconffile = conffile.readlines()
-        for line in aconffile:
-            mo = qpathr.search(line)
-            if mo:
-                path = mo.group(1)
-                break # assume first occurrence is ok
+    # OS env takes precedence
+    if os.environ.has_key("QOOXDOO_PATH"):
+        path = os.environ["QOOXDOO_PATH"]
+
+    # else use QOOXDOO_PATH from config.json
+    else:
+        config_file = ShellOptions.config
+        if os.path.exists(config_file):
+            # try json parsing with qx json
+            if not path.startswith('${'): # template macro has been resolved
+                sys.path.insert(0, os.path.join(path, QX_PYLIB))
+                try:
+                    from misc import json
+                    got_json = True
+                except:
+                    got_json = False
+
+            got_path = False
+            if got_json:
+                config_str = codecs.open(config_file, "r", "utf-8").read()
+                #config_str = stripComments(config_str)  # not necessary under demjson
+                config = json.loads(config_str)
+                p = config.get("let")
+                if p:
+                    p = p.get("QOOXDOO_PATH")
+                    if p:
+                        path = p
+                        got_path = True
+
+            # regex parsing - error prone
+            if not got_path:
+                qpathr=re.compile(r'"QOOXDOO_PATH"\s*:\s*"([^"]*)"\s*,?')
+                conffile = codecs.open(config_file, "r", "utf-8")
+                aconffile = conffile.readlines()
+                for line in aconffile:
+                    mo = qpathr.search(line)
+                    if mo:
+                        path = mo.group(1)
+                        break # assume first occurrence is ok
+
     path = os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), path))
 
@@ -52,4 +127,6 @@
     print "Cannot find real generator script under: \"%s\"; aborting" % REAL_GENERATOR
     sys.exit(1)
+elif ShellOptions.verbose:
+    print "\nInvoking real generator under %s ..." % REAL_GENERATOR
 
 argList = []
@@ -67,5 +144,5 @@
 else:
     argList = ['"%s"' % x for x in argList]  # quote argv elements
-    
+
 cmd = " ".join(argList)
 retval = subprocess.call(cmd, shell=True)
