Skip to content

Commit

Permalink
Command line tool.
Browse files Browse the repository at this point in the history
  • Loading branch information
eerimoq committed Aug 22, 2019
1 parent 15e6eaf commit fdca9c6
Show file tree
Hide file tree
Showing 8 changed files with 1,007 additions and 0 deletions.
37 changes: 37 additions & 0 deletions pbtools/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,39 @@
import sys
import argparse

from .parser import parse_file
from .version import __version__

__author__ = 'Erik Moqvist'


def _main():
parser = argparse.ArgumentParser(
description='Various Google Protobuf utilities.')

parser.add_argument('-d', '--debug', action='store_true')
parser.add_argument('--version',
action='version',
version=__version__,
help='Print version information and exit.')

# Workaround to make the subparser required in Python 3.
subparsers = parser.add_subparsers(title='subcommands',
dest='subcommand')
subparsers.required = True

# Import when used for less dependencies. For example, curses is
# not part of all Python builds.
from .subparsers import generate_c_source

generate_c_source.add_subparser(subparsers)

args = parser.parse_args()

if args.debug:
args.func(args)
else:
try:
args.func(args)
except BaseException as e:
sys.exit('error: ' + str(e))
5 changes: 5 additions & 0 deletions pbtools/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Execute as "python -m cantools"

from . import _main as main

main()
133 changes: 133 additions & 0 deletions pbtools/c_source.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import re
import time

from .version import __version__


HEADER_FMT = '''\
/**
* The MIT License (MIT)
*
* Copyright (c) 2019 Erik Moqvist
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* This file was generated by pbtools version {version} {date}.
*/
#ifndef {include_guard}
#define {include_guard}
#include <stdint.h>
#include <stdbool.h>
{structs}
{declarations}
#endif
'''

SOURCE_FMT = '''\
/**
* The MIT License (MIT)
*
* Copyright (c) 2019 Erik Moqvist
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* This file was generated by pbtools version {version} {date}.
*/
#include <string.h>
#include "{header}"
{helpers}
{definitions}\
'''


def canonical(value):
"""Replace anything but 'a-z', 'A-Z' and '0-9' with '_'.
"""

return re.sub(r'[^a-zA-Z0-9]', '_', value)


def camel_to_snake_case(value):
value = re.sub(r'(.)([A-Z][a-z]+)', r'\1_\2', value)
value = re.sub(r'(_+)', '_', value)
value = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', value).lower()
value = canonical(value)

return value


def generate(namespace, parsed):
"""Generate C source code from given parsed proto-file.
"""

date = time.ctime()
namespace = camel_to_snake_case(namespace)
include_guard = '{}_H'.format(namespace.upper())

structs = ''
declarations = ''
header_name = ''
helpers = ''
definitions = ''

header = HEADER_FMT.format(version=__version__,
date=date,
include_guard=include_guard,
structs=structs,
declarations=declarations)

source = SOURCE_FMT.format(version=__version__,
date=date,
header=header_name,
helpers=helpers,
definitions=definitions)

return header, source
Empty file added pbtools/subparsers/__init__.py
Empty file.
36 changes: 36 additions & 0 deletions pbtools/subparsers/generate_c_source.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import os

from ..parser import parse_file
from ..c_source import camel_to_snake_case
from ..c_source import generate


def _do_generate_c_source(args):
parsed = parse_file(args.infile)

basename = os.path.basename(args.infile)
name = os.path.splitext(basename)[0]
name = camel_to_snake_case(name)

filename_h = f'{name}.h'
filename_c = f'{name}.c'

header, source = generate(name, parsed)

with open(filename_h, 'w') as fout:
fout.write(header)

with open(filename_c, 'w') as fout:
fout.write(source)

print('Successfully generated {} and {}.'.format(filename_h, filename_c))


def add_subparser(subparsers):
generate_c_source_parser = subparsers.add_parser(
'generate_c_source',
description='Generate C source code from given protobuf file.')
generate_c_source_parser.add_argument(
'infile',
help='Input protobuf file.')
generate_c_source_parser.set_defaults(func=_do_generate_c_source)

0 comments on commit fdca9c6

Please sign in to comment.