Commit cb684ec4d3bdc68438f269b6cc611d6ba3ff6aa1

Authored by Jay Berkenbilt
1 parent fc14bfbb

QPDFJob increment: generate table names

generate_auto_job
@@ -4,6 +4,7 @@ import sys @@ -4,6 +4,7 @@ import sys
4 import argparse 4 import argparse
5 import hashlib 5 import hashlib
6 import re 6 import re
  7 +import yaml
7 8
8 whoami = os.path.basename(sys.argv[0]) 9 whoami = os.path.basename(sys.argv[0])
9 BANNER = f'''// 10 BANNER = f'''//
@@ -19,6 +20,9 @@ def warn(*args, **kwargs): @@ -19,6 +20,9 @@ def warn(*args, **kwargs):
19 20
20 class Main: 21 class Main:
21 SOURCES = [whoami, 'job.yml'] 22 SOURCES = [whoami, 'job.yml']
  23 + DESTS = {
  24 + 'decl': 'libqpdf/qpdf/auto_job_decl.hh',
  25 + }
22 SUMS = 'job.sums' 26 SUMS = 'job.sums'
23 27
24 def main(self, args=sys.argv[1:], prog=whoami): 28 def main(self, args=sys.argv[1:], prog=whoami):
@@ -49,11 +53,14 @@ class Main: @@ -49,11 +53,14 @@ class Main:
49 53
50 def get_hashes(self): 54 def get_hashes(self):
51 hashes = {} 55 hashes = {}
52 - for i in sorted(self.SOURCES): 56 + for i in sorted([*self.SOURCES, *self.DESTS.values()]):
53 m = hashlib.sha256() 57 m = hashlib.sha256()
54 - with open(i, 'rb') as f:  
55 - m.update(f.read())  
56 - hashes[i] = m.hexdigest() 58 + try:
  59 + with open(i, 'rb') as f:
  60 + m.update(f.read())
  61 + hashes[i] = m.hexdigest()
  62 + except FileNotFoundError:
  63 + pass
57 return hashes 64 return hashes
58 65
59 def check(self): 66 def check(self):
@@ -82,12 +89,51 @@ class Main: @@ -82,12 +89,51 @@ class Main:
82 def generate(self): 89 def generate(self):
83 warn(f'{whoami}: regenerating auto job files') 90 warn(f'{whoami}: regenerating auto job files')
84 91
85 - with open('libqpdf/qpdf/auto_job_decl.hh', 'w') as f:  
86 - print(BANNER, file=f) 92 + with open('job.yml', 'r') as f:
  93 + data = yaml.safe_load(f.read())
  94 + self.validate(data)
  95 + self.generate_decl(data)
87 96
88 # Update hashes last to ensure that this will be rerun in the 97 # Update hashes last to ensure that this will be rerun in the
89 # event of a failure. 98 # event of a failure.
90 self.update_hashes() 99 self.update_hashes()
  100 + # DON'T ADD CODE TO generate AFTER update_hashes
  101 +
  102 + def check_keys(self, what, d, exp):
  103 + if not isinstance(d, dict):
  104 + exit(f'{what} is not a dictionary')
  105 + actual = set(d.keys())
  106 + extra = actual - exp
  107 + if extra:
  108 + exit(f'{what}: unknown keys = {extra}')
  109 +
  110 + def validate(self, data):
  111 + self.check_keys('top', data, set(['choices', 'options']))
  112 + for o in data['options']:
  113 + self.check_keys('top', o, set(
  114 + ['table', 'bare', 'positional',
  115 + 'optional_parameter', 'required_parameter',
  116 + 'required_choices', 'from_table']))
  117 +
  118 + def to_identifier(self, label, prefix, const):
  119 + identifier = re.sub(r'[^a-zA-Z0-9]', '_', label)
  120 + if const:
  121 + identifier = identifier.upper()
  122 + else:
  123 + identifier = identifier.lower()
  124 + identifier = re.sub('_([a-z])', lambda x: x.group(1).upper(),
  125 + identifier)
  126 + return prefix + identifier
  127 +
  128 + def generate_decl(self, data):
  129 + with open(self.DESTS['decl'], 'w') as f:
  130 + print(BANNER, file=f)
  131 + for o in data['options']:
  132 + table = o['table']
  133 + if table in ('main', 'help'):
  134 + continue
  135 + i = self.to_identifier(table, 'O_', True)
  136 + print(f'static constexpr char const* {i} = "{table}";', file=f)
91 137
92 138
93 if __name__ == '__main__': 139 if __name__ == '__main__':
job.sums
1 # Generated by generate_auto_job 1 # Generated by generate_auto_job
2 -generate_auto_job 3905985c383d33f9e8629414d1481724ea67d836749f6dff53859ca558325743 2 +generate_auto_job e0cbb20dade91ebbab5907a53ba83ed3bb4b6cf4bfa75304a4b88e23906fbb6c
3 job.yml 8c66b75eb06be65dfa40058a52cbc0bc18627a3aade5b3d4e034543605c93298 3 job.yml 8c66b75eb06be65dfa40058a52cbc0bc18627a3aade5b3d4e034543605c93298
  4 +libqpdf/qpdf/auto_job_decl.hh b098ee02ec853f47850b6421cc72b08c608f303f74f01d0b3ce3df52cecd5ffa
libqpdf/QPDFJob_argv.cc
@@ -23,14 +23,7 @@ namespace @@ -23,14 +23,7 @@ namespace
23 void parseOptions(); 23 void parseOptions();
24 24
25 private: 25 private:
26 - static constexpr char const* O_PAGES = "pages";  
27 - static constexpr char const* O_ENCRYPT = "encryption";  
28 - static constexpr char const* O_ENCRYPT_40 = "40-bit encryption";  
29 - static constexpr char const* O_ENCRYPT_128 = "128-bit encryption";  
30 - static constexpr char const* O_ENCRYPT_256 = "256-bit encryption";  
31 - static constexpr char const* O_UNDER_OVERLAY = "underlay/overlay";  
32 - static constexpr char const* O_ATTACHMENT = "attachment";  
33 - static constexpr char const* O_COPY_ATTACHMENT = "copy attachment"; 26 +# include <qpdf/auto_job_decl.hh>
34 27
35 void argHelp(); 28 void argHelp();
36 void argVersion(); 29 void argVersion();
@@ -344,16 +337,16 @@ ArgParser::initOptionTable() @@ -344,16 +337,16 @@ ArgParser::initOptionTable()
344 337
345 this->ap.selectMainOptionTable(); 338 this->ap.selectMainOptionTable();
346 this->ap.addBare("encrypt", b(&ArgParser::argEncrypt)); 339 this->ap.addBare("encrypt", b(&ArgParser::argEncrypt));
347 - this->ap.registerOptionTable(O_ENCRYPT, b(&ArgParser::argEndEncrypt)); 340 + this->ap.registerOptionTable(O_ENCRYPTION, b(&ArgParser::argEndEncrypt));
348 this->ap.addPositional(p(&ArgParser::argEncryptPositional)); 341 this->ap.addPositional(p(&ArgParser::argEncryptPositional));
349 - this->ap.registerOptionTable(O_ENCRYPT_40, b(&ArgParser::argEndEncrypt)); 342 + this->ap.registerOptionTable(O_40_BIT_ENCRYPTION, b(&ArgParser::argEndEncrypt));
350 this->ap.addRequiredChoices("extract",p(&ArgParser::arg40Extract), yn); 343 this->ap.addRequiredChoices("extract",p(&ArgParser::arg40Extract), yn);
351 this->ap.addRequiredChoices("annotate",p(&ArgParser::arg40Annotate), yn); 344 this->ap.addRequiredChoices("annotate",p(&ArgParser::arg40Annotate), yn);
352 this->ap.addRequiredChoices("print",p(&ArgParser::arg40Print), yn); 345 this->ap.addRequiredChoices("print",p(&ArgParser::arg40Print), yn);
353 this->ap.addRequiredChoices("modify",p(&ArgParser::arg40Modify), yn); 346 this->ap.addRequiredChoices("modify",p(&ArgParser::arg40Modify), yn);
354 - this->ap.registerOptionTable(O_ENCRYPT_128, b(&ArgParser::argEndEncrypt));  
355 - this->ap.registerOptionTable(O_ENCRYPT_256, b(&ArgParser::argEndEncrypt));  
356 - for (char const* k: {O_ENCRYPT_128, O_ENCRYPT_256}) 347 + this->ap.registerOptionTable(O_128_BIT_ENCRYPTION, b(&ArgParser::argEndEncrypt));
  348 + this->ap.registerOptionTable(O_256_BIT_ENCRYPTION, b(&ArgParser::argEndEncrypt));
  349 + for (char const* k: {O_128_BIT_ENCRYPTION, O_256_BIT_ENCRYPTION})
357 { 350 {
358 this->ap.selectOptionTable(k); 351 this->ap.selectOptionTable(k);
359 this->ap.addRequiredChoices("accessibility", 352 this->ap.addRequiredChoices("accessibility",
@@ -373,15 +366,15 @@ ArgParser::initOptionTable() @@ -373,15 +366,15 @@ ArgParser::initOptionTable()
373 this->ap.addBare("cleartext-metadata", b(&ArgParser::arg128ClearTextMetadata)); 366 this->ap.addBare("cleartext-metadata", b(&ArgParser::arg128ClearTextMetadata));
374 } 367 }
375 368
376 - this->ap.selectOptionTable(O_ENCRYPT_128); 369 + this->ap.selectOptionTable(O_128_BIT_ENCRYPTION);
377 this->ap.addRequiredChoices("use-aes",p(&ArgParser::arg128UseAes), yn); 370 this->ap.addRequiredChoices("use-aes",p(&ArgParser::arg128UseAes), yn);
378 this->ap.addBare("force-V4", b(&ArgParser::arg128ForceV4)); 371 this->ap.addBare("force-V4", b(&ArgParser::arg128ForceV4));
379 372
380 - this->ap.selectOptionTable(O_ENCRYPT_256); 373 + this->ap.selectOptionTable(O_256_BIT_ENCRYPTION);
381 this->ap.addBare("force-R5", b(&ArgParser::arg256ForceR5)); 374 this->ap.addBare("force-R5", b(&ArgParser::arg256ForceR5));
382 this->ap.addBare("allow-insecure", b(&ArgParser::argAllowInsecure)); 375 this->ap.addBare("allow-insecure", b(&ArgParser::argAllowInsecure));
383 376
384 - this->ap.registerOptionTable(O_UNDER_OVERLAY, b(&ArgParser::argEndUnderOverlay)); 377 + this->ap.registerOptionTable(O_UNDERLAY_OVERLAY, b(&ArgParser::argEndUnderOverlay));
385 this->ap.addPositional(p(&ArgParser::argUOpositional)); 378 this->ap.addPositional(p(&ArgParser::argUOpositional));
386 this->ap.addRequiredParameter("to", 379 this->ap.addRequiredParameter("to",
387 p(&ArgParser::argUOto), "page-range"); 380 p(&ArgParser::argUOto), "page-range");
@@ -1089,7 +1082,7 @@ ArgParser::argEncrypt() @@ -1089,7 +1082,7 @@ ArgParser::argEncrypt()
1089 { 1082 {
1090 this->ap.insertCompletion("user-password"); 1083 this->ap.insertCompletion("user-password");
1091 } 1084 }
1092 - this->ap.selectOptionTable(O_ENCRYPT); 1085 + this->ap.selectOptionTable(O_ENCRYPTION);
1093 } 1086 }
1094 1087
1095 void 1088 void
@@ -1120,18 +1113,18 @@ ArgParser::argEncryptPositional(char* arg) @@ -1120,18 +1113,18 @@ ArgParser::argEncryptPositional(char* arg)
1120 if (len_str == "40") 1113 if (len_str == "40")
1121 { 1114 {
1122 o.keylen = 40; 1115 o.keylen = 40;
1123 - this->ap.selectOptionTable(O_ENCRYPT_40); 1116 + this->ap.selectOptionTable(O_40_BIT_ENCRYPTION);
1124 } 1117 }
1125 else if (len_str == "128") 1118 else if (len_str == "128")
1126 { 1119 {
1127 o.keylen = 128; 1120 o.keylen = 128;
1128 - this->ap.selectOptionTable(O_ENCRYPT_128); 1121 + this->ap.selectOptionTable(O_128_BIT_ENCRYPTION);
1129 } 1122 }
1130 else if (len_str == "256") 1123 else if (len_str == "256")
1131 { 1124 {
1132 o.keylen = 256; 1125 o.keylen = 256;
1133 o.use_aes = true; 1126 o.use_aes = true;
1134 - this->ap.selectOptionTable(O_ENCRYPT_256); 1127 + this->ap.selectOptionTable(O_256_BIT_ENCRYPTION);
1135 } 1128 }
1136 else 1129 else
1137 { 1130 {
@@ -2202,7 +2195,7 @@ void @@ -2202,7 +2195,7 @@ void
2202 ArgParser::parseUnderOverlayOptions(QPDFJob::UnderOverlay* uo) 2195 ArgParser::parseUnderOverlayOptions(QPDFJob::UnderOverlay* uo)
2203 { 2196 {
2204 o.under_overlay = uo; 2197 o.under_overlay = uo;
2205 - this->ap.selectOptionTable(O_UNDER_OVERLAY); 2198 + this->ap.selectOptionTable(O_UNDERLAY_OVERLAY);
2206 } 2199 }
2207 2200
2208 void 2201 void
libqpdf/qpdf/auto_job_decl.hh
@@ -3,3 +3,11 @@ @@ -3,3 +3,11 @@
3 // Edits will be automatically overwritten if the build is 3 // Edits will be automatically overwritten if the build is
4 // run in maintainer mode. 4 // run in maintainer mode.
5 // 5 //
  6 +static constexpr char const* O_PAGES = "pages";
  7 +static constexpr char const* O_ENCRYPTION = "encryption";
  8 +static constexpr char const* O_40_BIT_ENCRYPTION = "40-bit encryption";
  9 +static constexpr char const* O_128_BIT_ENCRYPTION = "128-bit encryption";
  10 +static constexpr char const* O_256_BIT_ENCRYPTION = "256-bit encryption";
  11 +static constexpr char const* O_UNDERLAY_OVERLAY = "underlay/overlay";
  12 +static constexpr char const* O_ATTACHMENT = "attachment";
  13 +static constexpr char const* O_COPY_ATTACHMENT = "copy attachment";