Commit cb684ec4d3bdc68438f269b6cc611d6ba3ff6aa1
1 parent
fc14bfbb
QPDFJob increment: generate table names
Showing
4 changed files
with
76 additions
and
28 deletions
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"; |