Commit | Line | Data |
---|---|---|
dcdbb941 PP |
1 | # The MIT License (MIT) |
2 | # | |
4a90140d | 3 | # Copyright (c) 2014-2020 Philippe Proulx <pproulx@efficios.com> |
dcdbb941 | 4 | # |
1378f213 PP |
5 | # Permission is hereby granted, free of charge, to any person obtaining |
6 | # a copy of this software and associated documentation files (the | |
7 | # "Software"), to deal in the Software without restriction, including | |
8 | # without limitation the rights to use, copy, modify, merge, publish, | |
9 | # distribute, sublicense, and/or sell copies of the Software, and to | |
10 | # permit persons to whom the Software is furnished to do so, subject to | |
11 | # the following conditions: | |
dcdbb941 | 12 | # |
1378f213 PP |
13 | # The above copyright notice and this permission notice shall be |
14 | # included in all copies or substantial portions of the Software. | |
dcdbb941 | 15 | # |
1378f213 PP |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
18 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
19 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
20 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
21 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
22 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
0f5c653b | 23 | |
79750125 | 24 | from pkg_resources import resource_filename |
dcdbb941 | 25 | from termcolor import cprint, colored |
e5aa0be3 PP |
26 | import barectf.tsdl182gen |
27 | import barectf.config | |
28 | import barectf.gen | |
e9094528 | 29 | import argparse |
e5aa0be3 | 30 | import os.path |
0f5c653b | 31 | import barectf |
dcdbb941 PP |
32 | import sys |
33 | import os | |
34 | import re | |
35 | ||
36 | ||
e5aa0be3 PP |
37 | def _perror(msg): |
38 | cprint('Error: ', 'red', end='', file=sys.stderr) | |
39 | cprint(msg, 'red', attrs=['bold'], file=sys.stderr) | |
40 | sys.exit(1) | |
dcdbb941 PP |
41 | |
42 | ||
6b5a6c2f | 43 | def _pconfig_error(exc): |
e5aa0be3 PP |
44 | cprint('Error:', 'red', file=sys.stderr) |
45 | ||
6b5a6c2f PP |
46 | for ctx in reversed(exc.ctx): |
47 | if ctx.msg is not None: | |
6605ffed | 48 | msg = f' {ctx.msg}' |
6b5a6c2f PP |
49 | else: |
50 | msg = '' | |
6605ffed PP |
51 | |
52 | cprint(f' {ctx.name}:{msg}', 'red', attrs=['bold'], file=sys.stderr) | |
e5aa0be3 PP |
53 | |
54 | sys.exit(1) | |
6b1365c7 PP |
55 | |
56 | ||
57 | def _psuccess(msg): | |
6605ffed | 58 | cprint(msg, 'green', attrs=['bold']) |
dcdbb941 PP |
59 | |
60 | ||
61 | def _parse_args(): | |
62 | ap = argparse.ArgumentParser() | |
63 | ||
e5aa0be3 PP |
64 | ap.add_argument('-c', '--code-dir', metavar='DIR', action='store', |
65 | default=os.getcwd(), | |
66 | help='output directory of C source file') | |
f58be68f PP |
67 | ap.add_argument('--dump-config', action='store_true', |
68 | help='also dump the effective YAML configuration file used for generation') | |
e5aa0be3 PP |
69 | ap.add_argument('-H', '--headers-dir', metavar='DIR', action='store', |
70 | default=os.getcwd(), | |
71 | help='output directory of C header files') | |
f58be68f PP |
72 | ap.add_argument('-I', '--include-dir', metavar='DIR', action='append', |
73 | default=[], | |
74 | help='add directory DIR to the list of directories to be searched for include files') | |
75 | ap.add_argument('--ignore-include-not-found', action='store_true', | |
76 | help='continue to process the configuration file when included files are not found') | |
e5aa0be3 | 77 | ap.add_argument('-m', '--metadata-dir', metavar='DIR', action='store', |
dcdbb941 | 78 | default=os.getcwd(), |
e5aa0be3 | 79 | help='output directory of CTF metadata') |
dcdbb941 | 80 | ap.add_argument('-p', '--prefix', metavar='PREFIX', action='store', |
e5aa0be3 | 81 | help='override configuration\'s prefix') |
0f5c653b | 82 | ap.add_argument('-V', '--version', action='version', |
e5aa0be3 PP |
83 | version='%(prog)s {}'.format(barectf.__version__)) |
84 | ap.add_argument('config', metavar='CONFIG', action='store', | |
85 | help='barectf YAML configuration file') | |
dcdbb941 PP |
86 | |
87 | # parse args | |
88 | args = ap.parse_args() | |
89 | ||
e5aa0be3 | 90 | # validate output directories |
f58be68f | 91 | for d in [args.code_dir, args.headers_dir, args.metadata_dir] + args.include_dir: |
e5aa0be3 | 92 | if not os.path.isdir(d): |
6605ffed | 93 | _perror(f'`{d}` is not an existing directory') |
dcdbb941 | 94 | |
e5aa0be3 PP |
95 | # validate that configuration file exists |
96 | if not os.path.isfile(args.config): | |
6605ffed | 97 | _perror(f'`{args.config}` is not an existing, regular file') |
dcdbb941 | 98 | |
79750125 PP |
99 | # append current working directory and provided include directory |
100 | args.include_dir += [os.getcwd(), resource_filename(__name__, 'include')] | |
101 | ||
dcdbb941 PP |
102 | return args |
103 | ||
104 | ||
e5aa0be3 PP |
105 | def _write_file(d, name, content): |
106 | with open(os.path.join(d, name), 'w') as f: | |
107 | f.write(content) | |
e9094528 | 108 | |
67bd189f | 109 | |
e5aa0be3 PP |
110 | def run(): |
111 | # parse arguments | |
112 | args = _parse_args() | |
8a70d9fb | 113 | |
e5aa0be3 PP |
114 | # create configuration |
115 | try: | |
7f4429f2 PP |
116 | config = barectf.config.from_file(args.config, args.include_dir, |
117 | args.ignore_include_not_found, | |
118 | args.dump_config) | |
0615a491 PP |
119 | except barectf.config._ConfigParseError as exc: |
120 | _pconfig_error(exc) | |
121 | except Exception as exc: | |
f74236f8 PP |
122 | import traceback |
123 | ||
124 | traceback.print_exc() | |
0615a491 | 125 | _perror(f'Unknown exception: {exc}') |
6b1365c7 | 126 | |
e5aa0be3 PP |
127 | # replace prefix if needed |
128 | if args.prefix: | |
feac2269 | 129 | config = barectf.config.Config(config.metadata, args.prefix, |
7f4429f2 | 130 | config.options) |
e5aa0be3 PP |
131 | |
132 | # generate metadata | |
133 | metadata = barectf.tsdl182gen.from_metadata(config.metadata) | |
134 | ||
135 | try: | |
136 | _write_file(args.metadata_dir, 'metadata', metadata) | |
0615a491 PP |
137 | except Exception as exc: |
138 | _perror(f'Cannot write metadata file: {exc}') | |
e5aa0be3 PP |
139 | |
140 | # create generator | |
141 | generator = barectf.gen.CCodeGenerator(config) | |
142 | ||
143 | # generate C headers | |
144 | header = generator.generate_header() | |
145 | bitfield_header = generator.generate_bitfield_header() | |
146 | ||
147 | try: | |
148 | _write_file(args.headers_dir, generator.get_header_filename(), header) | |
149 | _write_file(args.headers_dir, generator.get_bitfield_header_filename(), | |
150 | bitfield_header) | |
0615a491 PP |
151 | except Exception as exc: |
152 | _perror(f'Cannot write header files: {exc}') | |
e5aa0be3 PP |
153 | |
154 | # generate C source | |
155 | c_src = generator.generate_c_src() | |
156 | ||
157 | try: | |
158 | _write_file(args.code_dir, '{}.c'.format(config.prefix.rstrip('_')), | |
159 | c_src) | |
0615a491 PP |
160 | except Exception as exc: |
161 | _perror(f'Cannot write C source file: {exc}') |