Browse Source

- avoided unnecessary file generation based on time stamps
- handle exceptions in a more sophisticated way
- made it more modular


git-svn-id: svn://bind10.isc.org/svn/bind10/branches/jinmei-dnsrdata2@744 e5f2f494-b856-4b98-b285-d166d9295462

JINMEI Tatuya 15 years ago
parent
commit
227a2d7a3d
1 changed files with 105 additions and 60 deletions
  1. 105 60
      src/lib/dns/cpp/gen-rdatacode.py.in

+ 105 - 60
src/lib/dns/cpp/gen-rdatacode.py.in

@@ -22,6 +22,7 @@ classes and constants.
 """
 
 import os
+from os.path import getmtime
 import re
 import sys
 
@@ -30,13 +31,16 @@ classcode2txt = {}
 typecode2txt = {}
 typeandclass = []
 generic_code = 65536            # something larger than any code value
-class_declarations = ''
+rdata_declarations = ''
 class_definitions = ''
+classdir_mtime = 0
+rdatadef_mtime = 0
+rdatahdr_mtime = 0
 copyright_file = '@top_srcdir@' + os.sep + 'COPYING'
 
 def import_classdef(class_txt, file):
-    rdata_source = open(file, 'r')
     content = ''
+    rdata_source = open(file, 'r')
     for line in rdata_source.readlines():
         if re.match('// BEGIN_ISC_NAMESPACE', line):
             content += 'namespace isc {\n'
@@ -59,6 +63,9 @@ def import_classdef(class_txt, file):
     return content
 
 def import_classheader(class_txt, type_txt, type_code, file):
+    type_utxt = type_txt.upper()
+    class_utxt = class_txt.upper()
+
     # for each CLASS_n/TYPE_m.h
     rdata_header = open(file, 'r')
     content = ''
@@ -125,12 +132,19 @@ def import_copyright():
 '''
     return copyright_txt
 
-if __name__ == "__main__":
-    copyright_txt = import_copyright()
+def import_definitions(classcode2txt, typecode2txt, typeandclass):
+    global rdata_declarations
+    global class_definitions
+    global classdir_mtime
+    global rdatadef_mtime
+    global rdatahdr_mtime
+
     for dir in list(os.listdir('@srcdir@/rdata')):
         classdir = '@srcdir@/rdata' + os.sep + dir
         m = re_typecode.match(dir)
         if os.path.isdir(classdir) and (m != None or dir == 'generic'):
+            if classdir_mtime < getmtime(classdir):
+                classdir_mtime = getmtime(classdir)
             if dir == 'generic':
                 class_txt = 'generic'
                 class_code = generic_code
@@ -145,15 +159,16 @@ if __name__ == "__main__":
                 if m != None:
                     type_txt = m.group(1)
                     type_code = m.group(2)
-                    type_utxt = type_txt.upper()
-                    class_utxt = class_txt.upper()
-
                     if not type_code in typecode2txt:
                         typecode2txt[type_code] = type_txt
                     if re.search('\cc$', file):
+                        if rdatadef_mtime < getmtime(file):
+                            rdatadef_mtime = getmtime(file)
                         class_definitions += import_classdef(class_txt, file)
                     elif re.search('\h$', file):
-                        class_declarations += import_classheader(class_txt,
+                        if rdatahdr_mtime < getmtime(file):
+                            rdatahdr_mtime = getmtime(file)
+                        rdata_declarations += import_classheader(class_txt,
                                                                  type_txt,
                                                                  type_code,
                                                                  file)
@@ -163,78 +178,89 @@ if __name__ == "__main__":
                         if class_txt == 'generic':
                             typeandclass.append((type_txt, int(type_code),
                                                  (class_txt, 'in'), 1))
-    rdata_deffile = open('@srcdir@/rdataclass.cc', 'w')
+
+def need_generate(file, mtime):
+    '''Check if we need to generate the specified file.
+
+    To avoid unnecessary compilation, we skip (re)generating the file when
+    the file already exists and newer than the base file.
+    '''
+    if os.path.exists(file) and getmtime(file) > mtime:
+        return False
+    return True
+
+def generate_rdatadef(file, copyright_txt, basemtime):
+    if not need_generate(file, basemtime):
+        print('skip generating ' + file);
+        return
+    rdata_deffile = open(file, 'w')
     rdata_deffile.write(copyright_txt)
     rdata_deffile.write(class_definitions)
     rdata_deffile.close()
 
-    class_declarations += '''
+def generate_rdatahdr(file, copyright_txt, declarations, basemtime):
+    if not need_generate(file, basemtime):
+        print('skip generating ' + file);
+        return
+    declarations += '''
 // Local Variables:
 // mode: c++
 // End:
 '''
-    rdata_header = open('@srcdir@/rdataclass.h', 'w')
+    rdata_header = open(file, 'w')
     rdata_header.write(copyright_txt)
-    rdata_header.write(class_declarations)
+    rdata_header.write(declarations)
     rdata_header.close()
-    
-    declarationtxt = ''
-    deftxt = ''
-    for code in typecode2txt.keys():
-        # for rrtype.h
-        rrtype = typecode2txt[code].upper()
-        declarationtxt += ' ' * 4 + 'static const RRType& ' + rrtype + '();\n'
-        deftxt += '''inline const RRType&
-RRType::''' + rrtype + '''()
-{
-    static RRType rrtype(''' + code + ''');
-    return (rrtype);
-}\n
-'''
-    rrtype_header_temp = open('@srcdir@/rrtype-placeholder.h', 'r')
-    rrtype_header_out = open('@srcdir@/rrtype.h', 'w')
-    rrtype_header_out.write(copyright_txt)
-    for line in rrtype_header_temp.readlines():
-        rrtype_header_out.write(line)
-        if re.match('\s+// BEGIN_WELL_KNOWN_TYPE_DECLARATIONS$', line):
-            rrtype_header_out.write(declarationtxt)
-        if re.match('// BEGIN_WELL_KNOWN_TYPE_DEFINITIONS$', line):
-            rrtype_header_out.write('\n' + deftxt)
-    rrtype_header_out.close()
-    rrtype_header_temp.close()
+
+def generate_typeclasscode(fileprefix, basemtime, code2txt, type_or_class):
+    placeholder = fileprefix + '-placeholder.h'
+    outputfile = fileprefix + '.h'
+    upper_key = type_or_class.upper() # TYPE or CLASS
+    lower_key = 'rr' + type_or_class.lower() # rrtype or rrclass
+    cap_key = type_or_class           # Type or Class
+
+    if not need_generate(outputfile, basemtime) and getmtime(outputfile) > getmtime(placeholder):
+        print('skip generating ' + outputfile)
+        return
 
     declarationtxt = ''
     deftxt = ''
-    for code in classcode2txt.keys():
-        # for rrclass.h
-        rrclass = classcode2txt[code].upper()
-        declarationtxt += ' ' * 4 + 'static const RRClass& ' + rrclass + '();\n'
-        deftxt += '''inline const RRClass&
-RRClass::''' + rrclass + '''()
+    for code in code2txt.keys():
+        codetxt = code2txt[code].upper()
+        declarationtxt += ' ' * 4 + 'static const RR' + cap_key + '& ' + codetxt + '();\n'
+        deftxt += '''inline const RR''' + cap_key + '''&
+RR''' + cap_key + '''::''' + codetxt + '''()
 {
-    static RRClass rrclass(''' + code + ''');
-    return (rrclass);
+    static RR''' + cap_key + ''' ''' + lower_key + '''(''' + code + ''');
+    return (''' + lower_key + ''');
 }\n
 '''
+    header_temp = open(placeholder, 'r')
+    header_out = open(outputfile, 'w')
+    header_out.write(copyright_txt)
+    for line in header_temp.readlines():
+        header_out.write(line)
+        if re.match('\s+// BEGIN_WELL_KNOWN_' + upper_key + '_DECLARATIONS$', line):
+            header_out.write(declarationtxt)
+        if re.match('// BEGIN_WELL_KNOWN_' + upper_key + '_DEFINITIONS$', line):
+            header_out.write('\n' + deftxt)
+    header_out.close()
+    header_temp.close()
 
-    rrclass_header_temp = open('@srcdir@/rrclass-placeholder.h', 'r')
-    rrclass_header_out = open('@srcdir@/rrclass.h', 'w')
-    rrclass_header_out.write(copyright_txt)
-    for line in rrclass_header_temp.readlines():
-        rrclass_header_out.write(line)
-        if re.match('\s+// BEGIN_WELL_KNOWN_CLASS_DECLARATIONS$', line):
-            rrclass_header_out.write(declarationtxt)
-        if re.match('// BEGIN_WELL_KNOWN_CLASS_DEFINITIONS$', line):
-            rrclass_header_out.write('\n' + deftxt)
-    rrclass_header_out.close()
-    rrclass_header_temp.close()
+def generate_rrparam(fileprefix, basemtime):
+    placeholder = fileprefix + '-placeholder.cc'
+    outputfile = fileprefix + '.cc'
+    if not need_generate(outputfile, basemtime) and getmtime(outputfile) > getmtime(placeholder):
+        print('skip generating ' + outputfile)
+        return
 
     # sort by class, then by type
     typeandclassparams = ''
     typeandclass.sort(key = lambda x: (x[3], x[1]))
     for param in typeandclass:
-        # for rdata.cc
-        # each param is a tuple of (type_txt, type_code, class_tuple, class_code)
+        # for rrparamregistry.cc
+        # each param is a tuple of (type_txt, type_code, class_tuple,
+        #                           class_code)
         (type_txt, type_code, class_tuple, class_code) = param
         type_utxt = type_txt.upper()
         class_txt = class_tuple[0]
@@ -252,8 +278,8 @@ RRClass::''' + rrclass + '''()
             typeandclassparams += ', RdataFactoryPtr(new RdataFactory<'
             typeandclassparams += class_txt + '::' + type_utxt + '>()));\n'
 
-    rrparam_temp = open('@srcdir@/rrparamregistry-placeholder.cc', 'r')
-    rrparam_out = open('@srcdir@/rrparamregistry.cc', 'w')
+    rrparam_temp = open(placeholder, 'r')
+    rrparam_out = open(outputfile, 'w')
     rrparam_out.write(copyright_txt)
     for line in rrparam_temp.readlines():
         rrparam_out.write(line)
@@ -261,3 +287,22 @@ RRClass::''' + rrclass + '''()
             rrparam_out.write(typeandclassparams)
     rrparam_temp.close()
     rrparam_out.close()
+
+if __name__ == "__main__":
+    try:
+        copyright_txt = import_copyright()
+        import_definitions(classcode2txt, typecode2txt, typeandclass)
+        generate_rdatadef('@srcdir@/rdataclass.cc', copyright_txt,
+                          rdatadef_mtime)
+        generate_rdatahdr('@srcdir@/rdataclass.h', copyright_txt,
+                          rdata_declarations, rdatahdr_mtime)
+        generate_typeclasscode('@srcdir@/rrtype',
+                               max(rdatadef_mtime, rdatahdr_mtime),
+                               typecode2txt, 'Type')
+        generate_typeclasscode('@srcdir@/rrclass', classdir_mtime,
+                               classcode2txt, 'Class')
+        generate_rrparam('@srcdir@/rrparamregistry', rdatahdr_mtime)
+    except:
+        sys.stderr.write('Code generation failed due to exception: %s\n' %
+                         sys.exc_info()[1])
+        exit(1)