gen-rdatacode.py.in 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. #!@PYTHON@
  2. # Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
  3. #
  4. # Permission to use, copy, modify, and/or distribute this software for any
  5. # purpose with or without fee is hereby granted, provided that the above
  6. # copyright notice and this permission notice appear in all copies.
  7. #
  8. # THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  9. # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  10. # AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  11. # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  12. # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  13. # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  14. # PERFORMANCE OF THIS SOFTWARE.
  15. # $Id$
  16. """\
  17. This is a supplemental script to (half) auto-generate DNS Rdata related
  18. classes and constants.
  19. """
  20. import os
  21. import re
  22. import sys
  23. re_typecode = re.compile('([a-z]+)_(\d+)')
  24. classcode2txt = {}
  25. typecode2txt = {}
  26. typeandclass = []
  27. generic_code = 65536 # something larger than any code value
  28. class_declarations = ''
  29. class_definitions = ''
  30. copyright_file = '@top_srcdir@' + os.sep + 'COPYING'
  31. def import_classdef(class_txt, file):
  32. rdata_source = open(file, 'r')
  33. content = ''
  34. for line in rdata_source.readlines():
  35. if re.match('// BEGIN_ISC_NAMESPACE', line):
  36. content += 'namespace isc {\n'
  37. content += 'namespace dns {\n'
  38. continue
  39. if re.match('// BEGIN_RDATA_NAMESPACE', line):
  40. content += 'namespace rdata {\n'
  41. content += 'namespace ' + class_txt + ' {\n'
  42. continue
  43. if re.match('// END_ISC_NAMESPACE', line):
  44. content += '} // end of namespace "dns"\n'
  45. content += '} // end of namespace "isc"\n'
  46. continue
  47. if re.match('// END_RDATA_NAMESPACE', line):
  48. content += '} // end of namespace "' + class_txt +'"\n'
  49. content += '} // end of namespace "rdata"\n'
  50. continue
  51. content += line
  52. rdata_source.close()
  53. return content
  54. def import_classheader(class_txt, type_txt, type_code, file):
  55. # for each CLASS_n/TYPE_m.h
  56. rdata_header = open(file, 'r')
  57. content = ''
  58. guard_macro = '__' + class_txt.upper() + '_' + type_txt.upper()
  59. guard_macro += '_' + type_code + '_H'
  60. for line in rdata_header.readlines():
  61. if re.match('// BEGIN_HEADER_GUARD', line):
  62. content += '#ifndef ' + guard_macro + '\n'
  63. content += '#define ' + guard_macro + ' 1\n'
  64. continue
  65. if re.match('// END_HEADER_GUARD', line):
  66. content += '#endif // ' + guard_macro + '\n'
  67. continue
  68. if re.match('// BEGIN_ISC_NAMESPACE', line):
  69. content += 'namespace isc {\n'
  70. content += 'namespace dns {\n'
  71. continue
  72. if re.match('// BEGIN_RDATA_NAMESPACE', line):
  73. content += 'namespace rdata {\n'
  74. content += 'namespace ' + class_txt + ' {\n'
  75. continue
  76. if re.match('// END_ISC_NAMESPACE', line):
  77. content += '} // end of namespace "dns"\n'
  78. content += '} // end of namespace "isc"\n'
  79. continue
  80. if re.match('// END_RDATA_NAMESPACE', line):
  81. content += '} // end of namespace "' + class_txt +'"\n'
  82. content += '} // end of namespace "rdata"\n'
  83. continue
  84. if re.match('// Local Variables:', line):
  85. break
  86. content += line
  87. if re.match('// BEGIN_COMMON_DECLARATIONS', line):
  88. content += '''
  89. class InputBuffer;
  90. class OutputBuffer;
  91. class MessageRenderer;\n\n'''
  92. if re.match('\s+// BEGIN_COMMON_MEMBERS$', line):
  93. content += '''
  94. explicit ''' + type_utxt + '''(const std::string& type_str);
  95. explicit ''' + type_utxt + '''(InputBuffer& buffer, size_t rdata_len);
  96. ''' + type_utxt + '''(const ''' + type_utxt + '''& other);
  97. virtual std::string toText() const;
  98. virtual void toWire(OutputBuffer& buffer) const;
  99. virtual void toWire(MessageRenderer& renderer) const;
  100. virtual int compare(const Rdata& other) const;\n\n'''
  101. rdata_header.close()
  102. return content
  103. def import_copyright():
  104. copyright_txt = ''
  105. f = open(copyright_file, 'r')
  106. for line in f.readlines():
  107. copyright_txt += '// ' + line
  108. f.close()
  109. copyright_txt += '''
  110. ///////////////
  111. ///////////////
  112. /////////////// THIS FILE IS AUTOMATICALLY GENERATED BY gen-rdatacode.py.
  113. /////////////// DO NOT EDIT!
  114. ///////////////
  115. ///////////////
  116. '''
  117. return copyright_txt
  118. if __name__ == "__main__":
  119. copyright_txt = import_copyright()
  120. for dir in list(os.listdir('@srcdir@/rdata')):
  121. classdir = '@srcdir@/rdata' + os.sep + dir
  122. m = re_typecode.match(dir)
  123. if os.path.isdir(classdir) and (m != None or dir == 'generic'):
  124. if dir == 'generic':
  125. class_txt = 'generic'
  126. class_code = generic_code
  127. else:
  128. class_txt = m.group(1)
  129. class_code = m.group(2)
  130. if not class_code in classcode2txt:
  131. classcode2txt[class_code] = class_txt
  132. for file in list(os.listdir(classdir)):
  133. file = classdir + os.sep + file
  134. m = re_typecode.match(os.path.split(file)[1])
  135. if m != None:
  136. type_txt = m.group(1)
  137. type_code = m.group(2)
  138. type_utxt = type_txt.upper()
  139. class_utxt = class_txt.upper()
  140. if not type_code in typecode2txt:
  141. typecode2txt[type_code] = type_txt
  142. if re.search('\cc$', file):
  143. class_definitions += import_classdef(class_txt, file)
  144. elif re.search('\h$', file):
  145. class_declarations += import_classheader(class_txt,
  146. type_txt,
  147. type_code,
  148. file)
  149. typeandclass.append((type_txt, int(type_code),
  150. (class_txt, class_txt),
  151. int(class_code)))
  152. if class_txt == 'generic':
  153. typeandclass.append((type_txt, int(type_code),
  154. (class_txt, 'in'), 1))
  155. rdata_deffile = open('rdataclass.cc', 'w')
  156. rdata_deffile.write(copyright_txt)
  157. rdata_deffile.write(class_definitions)
  158. rdata_deffile.close()
  159. class_declarations += '''
  160. // Local Variables:
  161. // mode: c++
  162. // End:
  163. '''
  164. rdata_header = open('rdataclass.h', 'w')
  165. rdata_header.write(copyright_txt)
  166. rdata_header.write(class_declarations)
  167. rdata_header.close()
  168. declarationtxt = ''
  169. deftxt = ''
  170. for code in typecode2txt.keys():
  171. # for rrtype.h
  172. rrtype = typecode2txt[code].upper()
  173. declarationtxt += ' ' * 4 + 'static const RRType& ' + rrtype + '();\n'
  174. deftxt += '''inline const RRType&
  175. RRType::''' + rrtype + '''()
  176. {
  177. static RRType rrtype(''' + code + ''');
  178. return (rrtype);
  179. }\n
  180. '''
  181. rrtype_header_temp = open('@srcdir@/rrtype-placeholder.h', 'r')
  182. rrtype_header_out = open('rrtype.h', 'w')
  183. rrtype_header_out.write(copyright_txt)
  184. for line in rrtype_header_temp.readlines():
  185. rrtype_header_out.write(line)
  186. if re.match('\s+// BEGIN_WELL_KNOWN_TYPE_DECLARATIONS$', line):
  187. rrtype_header_out.write(declarationtxt)
  188. if re.match('// BEGIN_WELL_KNOWN_TYPE_DEFINITIONS$', line):
  189. rrtype_header_out.write('\n' + deftxt)
  190. rrtype_header_out.close()
  191. rrtype_header_temp.close()
  192. declarationtxt = ''
  193. deftxt = ''
  194. for code in classcode2txt.keys():
  195. # for rrclass.h
  196. rrclass = classcode2txt[code].upper()
  197. declarationtxt += ' ' * 4 + 'static const RRClass& ' + rrclass + '();\n'
  198. deftxt += '''inline const RRClass&
  199. RRClass::''' + rrclass + '''()
  200. {
  201. static RRClass rrclass(''' + code + ''');
  202. return (rrclass);
  203. }\n
  204. '''
  205. rrclass_header_temp = open('@srcdir@/rrclass-placeholder.h', 'r')
  206. rrclass_header_out = open('rrclass.h', 'w')
  207. rrclass_header_out.write(copyright_txt)
  208. for line in rrclass_header_temp.readlines():
  209. rrclass_header_out.write(line)
  210. if re.match('\s+// BEGIN_WELL_KNOWN_CLASS_DECLARATIONS$', line):
  211. rrclass_header_out.write(declarationtxt)
  212. if re.match('// BEGIN_WELL_KNOWN_CLASS_DEFINITIONS$', line):
  213. rrclass_header_out.write('\n' + deftxt)
  214. rrclass_header_out.close()
  215. rrclass_header_temp.close()
  216. # sort by class, then by type
  217. typeandclassparams = ''
  218. typeandclass.sort(key = lambda x: (x[3], x[1]))
  219. for param in typeandclass:
  220. # for rdata.cc
  221. # each param is a tuple of (type_txt, type_code, class_tuple, class_code)
  222. (type_txt, type_code, class_tuple, class_code) = param
  223. type_utxt = type_txt.upper()
  224. class_txt = class_tuple[0]
  225. class_utxt = class_tuple[1].upper()
  226. indent = ' ' * 8
  227. typeandclassparams += indent
  228. if class_tuple[1] != 'generic':
  229. typeandclassparams += 'add("' + type_utxt + '", '
  230. typeandclassparams += str(type_code) + ', "' + class_utxt
  231. typeandclassparams += '", ' + str(class_code)
  232. typeandclassparams += ', RdataFactoryPtr(new RdataFactory<'
  233. typeandclassparams += class_txt + '::' + type_utxt + '>()));\n'
  234. else:
  235. typeandclassparams += 'add("' + type_utxt + '", ' + str(type_code)
  236. typeandclassparams += ', RdataFactoryPtr(new RdataFactory<'
  237. typeandclassparams += class_txt + '::' + type_utxt + '>()));\n'
  238. rrparam_temp = open('@srcdir@/rrparamregistry-placeholder.cc', 'r')
  239. rrparam_out = open('rrparamregistry.cc', 'w')
  240. rrparam_out.write(copyright_txt)
  241. for line in rrparam_temp.readlines():
  242. rrparam_out.write(line)
  243. if re.match('\s+// BEGIN_WELL_KNOWN_PARAMS', line):
  244. rrparam_out.write(typeandclassparams)
  245. rrparam_temp.close()
  246. rrparam_out.close()