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