Rename `msg`/`ctx` properties 👉 `message`/`context`
[barectf.git] / barectf / cli.py
1 # The MIT License (MIT)
2 #
3 # Copyright (c) 2014-2020 Philippe Proulx <pproulx@efficios.com>
4 #
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:
12 #
13 # The above copyright notice and this permission notice shall be
14 # included in all copies or substantial portions of the Software.
15 #
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.
23
24 import barectf.tsdl182gen
25 import barectf.config
26 import pkg_resources
27 import barectf.gen
28 import termcolor
29 import argparse
30 import os.path
31 import barectf
32 import sys
33 import os
34
35
36 def _perror(msg):
37 termcolor.cprint('Error: ', 'red', end='', file=sys.stderr)
38 termcolor.cprint(msg, 'red', attrs=['bold'], file=sys.stderr)
39 sys.exit(1)
40
41
42 def _pconfig_error(exc):
43 termcolor.cprint('Error:', 'red', file=sys.stderr)
44
45 for ctx in reversed(exc.context):
46 if ctx.message is not None:
47 msg = f' {ctx.message}'
48 else:
49 msg = ''
50
51 termcolor.cprint(f' {ctx.name}:{msg}', 'red', attrs=['bold'],
52 file=sys.stderr)
53
54 sys.exit(1)
55
56
57 def _psuccess(msg):
58 termcolor.cprint(msg, 'green', attrs=['bold'])
59
60
61 def _parse_args():
62 ap = argparse.ArgumentParser()
63
64 ap.add_argument('-c', '--code-dir', metavar='DIR', action='store',
65 default=os.getcwd(),
66 help='output directory of C source file')
67 ap.add_argument('--dump-config', action='store_true',
68 help='also dump the effective YAML configuration file used for generation')
69 ap.add_argument('-H', '--headers-dir', metavar='DIR', action='store',
70 default=os.getcwd(),
71 help='output directory of C header files')
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')
77 ap.add_argument('-m', '--metadata-dir', metavar='DIR', action='store',
78 default=os.getcwd(),
79 help='output directory of CTF metadata')
80 ap.add_argument('-p', '--prefix', metavar='PREFIX', action='store',
81 help='override configuration\'s prefix')
82 ap.add_argument('-V', '--version', action='version',
83 version='%(prog)s {}'.format(barectf.__version__))
84 ap.add_argument('config', metavar='CONFIG', action='store',
85 help='barectf YAML configuration file')
86
87 # parse args
88 args = ap.parse_args()
89
90 # validate output directories
91 for d in [args.code_dir, args.headers_dir, args.metadata_dir] + args.include_dir:
92 if not os.path.isdir(d):
93 _perror(f'`{d}` is not an existing directory')
94
95 # validate that configuration file exists
96 if not os.path.isfile(args.config):
97 _perror(f'`{args.config}` is not an existing, regular file')
98
99 # append current working directory and provided include directory
100 args.include_dir += [
101 os.getcwd(),
102 pkg_resources.resource_filename(__name__, 'include')
103 ]
104
105 return args
106
107
108 def _write_file(d, name, content):
109 with open(os.path.join(d, name), 'w') as f:
110 f.write(content)
111
112
113 def run():
114 # parse arguments
115 args = _parse_args()
116
117 # create configuration
118 try:
119 config = barectf.config.from_file(args.config, args.include_dir,
120 args.ignore_include_not_found,
121 args.dump_config)
122 except barectf.config._ConfigParseError as exc:
123 _pconfig_error(exc)
124 except Exception as exc:
125 import traceback
126
127 traceback.print_exc()
128 _perror(f'Unknown exception: {exc}')
129
130 # replace prefix if needed
131 if args.prefix:
132 config = barectf.config.Config(config.metadata, args.prefix,
133 config.options)
134
135 # generate metadata
136 metadata = barectf.tsdl182gen.from_metadata(config.metadata)
137
138 try:
139 _write_file(args.metadata_dir, 'metadata', metadata)
140 except Exception as exc:
141 _perror(f'Cannot write metadata file: {exc}')
142
143 # create generator
144 generator = barectf.gen.CCodeGenerator(config)
145
146 # generate C headers
147 header = generator.generate_header()
148 bitfield_header = generator.generate_bitfield_header()
149
150 try:
151 _write_file(args.headers_dir, generator.get_header_filename(), header)
152 _write_file(args.headers_dir, generator.get_bitfield_header_filename(),
153 bitfield_header)
154 except Exception as exc:
155 _perror(f'Cannot write header files: {exc}')
156
157 # generate C source
158 c_src = generator.generate_c_src()
159
160 try:
161 _write_file(args.code_dir, '{}.c'.format(config.prefix.rstrip('_')),
162 c_src)
163 except Exception as exc:
164 _perror(f'Cannot write C source file: {exc}')
This page took 0.048094 seconds and 5 git commands to generate.