Index: /trunk/Makefile.in
===================================================================
--- /trunk/Makefile.in	(revision 141)
+++ /trunk/Makefile.in	(revision 142)
@@ -32,8 +32,8 @@
 	$(INSTALL) -d $(DESTDIR)$(SBIN_DIR)
 	$(INSTALL) -d $(DESTDIR)$(BIN_DIR)
-	$(INSTALL) -m 755 -o root pxeconfigd $(DESTDIR)$(SBIN_DIR)
+	$(INSTALL) -m 755 -o root src/pxeconfigd $(DESTDIR)$(SBIN_DIR)
 	for script in $(PYTHON_FILES) ; \
 	do \
-	  $(INSTALL) -m 755 -o root $$script  $(DESTDIR)$(BIN_DIR)/$$script ;\
+	  $(INSTALL) -m 755 -o root src/$$script  $(DESTDIR)$(BIN_DIR)/$$script ;\
 	done
 
Index: /trunk/configure
===================================================================
--- /trunk/configure	(revision 141)
+++ /trunk/configure	(revision 142)
@@ -577,5 +577,5 @@
 PACKAGE_BUGREPORT=
 
-ac_unique_file="pxeconfig.in"
+ac_unique_file="src/pxeconfig.in"
 ac_subst_vars='SHELL
 PATH_SEPARATOR
@@ -1800,5 +1800,5 @@
 
 
-ac_config_files="$ac_config_files Makefile pxeconfig.py pxeconfigd hexls examples/pxeconfigd.xinetd"
+ac_config_files="$ac_config_files Makefile src/pxeconfig.py src/pxeconfig src/pxeconfigd src/hexls examples/pxeconfigd.xinetd"
 
 cat >confcache <<\_ACEOF
@@ -2370,7 +2370,8 @@
   case $ac_config_target in
     "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
-    "pxeconfig.py") CONFIG_FILES="$CONFIG_FILES pxeconfig.py" ;;
-    "pxeconfigd") CONFIG_FILES="$CONFIG_FILES pxeconfigd" ;;
-    "hexls") CONFIG_FILES="$CONFIG_FILES hexls" ;;
+    "src/pxeconfig.py") CONFIG_FILES="$CONFIG_FILES src/pxeconfig.py" ;;
+    "src/pxeconfig") CONFIG_FILES="$CONFIG_FILES src/pxeconfig" ;;
+    "src/pxeconfigd") CONFIG_FILES="$CONFIG_FILES src/pxeconfigd" ;;
+    "src/hexls") CONFIG_FILES="$CONFIG_FILES src/hexls" ;;
     "examples/pxeconfigd.xinetd") CONFIG_FILES="$CONFIG_FILES examples/pxeconfigd.xinetd" ;;
 
Index: /trunk/configure.in
===================================================================
--- /trunk/configure.in	(revision 141)
+++ /trunk/configure.in	(revision 142)
@@ -6,5 +6,5 @@
 #
 #
-AC_INIT(pxeconfig.in)
+AC_INIT(src/pxeconfig.in)
 AC_SUBST(prefix)
 AC_SUBST(exec_prefix)
@@ -59,7 +59,8 @@
 AC_OUTPUT(
         Makefile
-	pxeconfig.py
-	pxeconfigd
-	hexls
+	src/pxeconfig.py
+	src/pxeconfig
+	src/pxeconfigd
+	src/hexls
 	examples/pxeconfigd.xinetd
 	)
Index: /trunk/setup.py
===================================================================
--- /trunk/setup.py	(revision 141)
+++ /trunk/setup.py	(revision 142)
@@ -21,5 +21,5 @@
 
 	extra_path = 'pxeconfig',
-		#package_dir = { '' : 'src' }, 
+		package_dir = { '' : 'src' }, 
 		py_modules = [ 'pxeconfig', 'AdvancedParser' ], 
 )
Index: /trunk/src/AdvancedParser.py
===================================================================
--- /trunk/src/AdvancedParser.py	(revision 142)
+++ /trunk/src/AdvancedParser.py	(revision 142)
@@ -0,0 +1,155 @@
+#
+# Author: Dennis Stam
+# Date  : 09-04-2009
+# Desc. : This class allows you use ranges within the given arguments. Very
+#         useful for specifying mutliple hosts. This class extends the
+#         OptionParser class.
+#
+# SVN Info:
+#       $Id: AdvancedParser.py 3667 2009-04-15 12:02:04Z dennis $
+#       $URL: https://subtrac.sara.nl/hpcv/svn/beowulf/trunk/sara_python_modules/AdvancedParser.py $
+#
+from optparse import OptionParser
+import re
+import types
+
+class AdvancedParser(OptionParser):
+        """
+        This class extends from OptionParser, where the method check_values has been
+        overrided.
+
+        In this function a extra parsing is done on the the rest of the arguments. This
+        extra parsing is the creating of multiple hostnames from a pattern/range.
+
+        When a user specifies this argument dr-r[15,17-20]n[1-5,10] then this class
+        returns 24 hosts. Besides using numbers you can also specify lower cased
+        letters from a-z.
+
+        Doctest:
+        >>> parser = AdvancedParser()
+        >>> parser.return_range('12-15,20')
+        [12, 13, 14, 15, '20']
+
+        >>> option, args = parser.parse_args(['dr-r7n[1-5]'])
+        >>> print args
+        ['dr-r7n1', 'dr-r7n2', 'dr-r7n3', 'dr-r7n4', 'dr-r7n5']
+        """
+
+        def return_range(self, string):
+                """
+                This method uses the given numbers and converts them to ranges. When
+                ower cased letters are specified they will be converted to integer 
+                ordinal of a one-character string.
+                (ie. a = 97, z = 122)
+
+                The ranges will be return as lists
+                """
+                parts = string.split( ',' )
+                numbers_chars = list()
+                equal_width_length = 0
+
+                for part in parts:
+                        part_range = part.split( '-' )
+                        if len( part_range ) == 2:
+                                try:
+                                        if part_range[0][0] == '0' or part_range[1][0] == '0':
+                                                if len( part_range[0] ) > len( part_range[1] ):
+                                                        equal_width_length = len( part_range[0] )
+                                                else:
+                                                        equal_width_length = len( part_range[1] )
+
+                                        numbers_chars += range( int( part_range[0] ), int( part_range[1] ) + 1 )
+                                except ValueError:
+                                        begin = ord( part_range[0] )
+                                        end = ord( part_range[1] )
+                                        tmplist = list()
+
+                                        if begin > 96 and end < 123:
+                                                tmplist = range( begin, end + 1)
+
+                                                for letter in tmplist:
+                                                        numbers_chars.append( chr( letter ) )
+                        else:
+                                if equal_width_length != 0 and len( part ) > equal_width_length:
+                                        equal_width_length = len( part )
+
+                                numbers_chars.append( part )
+
+                if equal_width_length > 0:
+                        tmplist = list()
+
+                        for number_char in numbers_chars:
+                                try:
+                                        nnum = int( number_char )
+                                        tmplist.append( '%0*d' % (equal_width_length, nnum) )
+                                except ValueError:
+                                        tmplist.append( number_char )
+                        
+                        numbers_chars = tmplist
+
+                return numbers_chars
+
+        def combine( self, pre, post):
+                '''
+                This method is used to combine a possibility of a combination
+                '''
+                if pre == '':
+                        return post
+                else:
+                        return '%s %s' % (pre, post)
+
+        def combinations( self, listin, prefix=''):
+                '''
+                This method creates from the given ranges all possible combinations
+                '''
+                outlist = list()
+
+                if len( listin ) > 1:
+                        for item in listin[0]:
+                                outlist += self.combinations( listin[1:], self.combine( prefix, str( item ) ) )
+                else:
+                        for item in listin[0]:
+                                outlist.append( tuple( self.combine( prefix, str( item ) ).split( ' ') ) )
+
+                return outlist
+
+        def args_parser(self, args):
+                '''
+                This method checks all given extra arguments for the given ranges between the
+                [ and ]
+                '''
+                findregex = re.compile( r'\[([0-9a-z\-,]+)\]', re.VERBOSE )
+                nodenames = list()
+
+                for arg in args:
+                        found = findregex.findall( arg )
+                        ranges = list()
+
+                        if found:
+                                pattern = findregex.sub( '%s', arg )
+
+                                for part in found:
+                                        ranges.append( self.return_range( part ) )
+
+                                combs = self.combinations( ranges )
+
+                                for comb in combs:
+                                        # Here the %s in the pattern are
+                                        # replaced by the correct value
+                                        nodenames.append( pattern % comb )
+                        else:
+                                nodenames.append( arg )
+
+                return nodenames
+
+        def check_values(self, values, args):
+                '''
+                Here we override the default method in OptionParser to
+                enable our extra parsing on the given Arguments
+                '''
+                return values, self.args_parser( args )
+
+if __name__ == "__main__":
+        import doctest
+        print 'Starting doctest'
+        doctest.testmod()
