pax_global_header 0000666 0000000 0000000 00000000064 12762341661 0014522 g ustar 00root root 0000000 0000000 52 comment=f4e6ad090934ca0e47b5d68e5047122695d018cd
genlisp-0.4.16/ 0000775 0000000 0000000 00000000000 12762341661 0013253 5 ustar 00root root 0000000 0000000 genlisp-0.4.16/.gitignore 0000664 0000000 0000000 00000000015 12762341661 0015237 0 ustar 00root root 0000000 0000000 *.pyc
._*
*~
genlisp-0.4.16/CMakeLists.txt 0000664 0000000 0000000 00000001257 12762341661 0016020 0 ustar 00root root 0000000 0000000 cmake_minimum_required(VERSION 2.8.3)
project(genlisp)
find_package(catkin REQUIRED COMPONENTS genmsg)
catkin_package(
CATKIN_DEPENDS genmsg
CFG_EXTRAS genlisp-extras.cmake
)
add_subdirectory(scripts)
file(WRITE ${CATKIN_DEVEL_PREFIX}/${GENMSG_LANGS_DESTINATION}/genlisp "LISP")
install(FILES ${CATKIN_DEVEL_PREFIX}/${GENMSG_LANGS_DESTINATION}/genlisp
DESTINATION ${GENMSG_LANGS_DESTINATION})
# drop marker file to prevent rospack from spending time on crawling this folder
file(WRITE ${CATKIN_DEVEL_PREFIX}/share/common-lisp/rospack_nosubdirs "")
install(FILES ${CATKIN_DEVEL_PREFIX}/share/common-lisp/rospack_nosubdirs
DESTINATION share/common-lisp)
catkin_python_setup()
genlisp-0.4.16/cmake/ 0000775 0000000 0000000 00000000000 12762341661 0014333 5 ustar 00root root 0000000 0000000 genlisp-0.4.16/cmake/genlisp-extras.cmake.em 0000664 0000000 0000000 00000004013 12762341661 0020700 0 ustar 00root root 0000000 0000000 @[if DEVELSPACE]@
# bin and template dir variables in develspace
set(GENLISP_BIN "@(CMAKE_CURRENT_SOURCE_DIR)/scripts/gen_lisp.py")
set(GENLISP_TEMPLATE_DIR "@(CMAKE_CURRENT_SOURCE_DIR)/scripts")
@[else]@
# bin and template dir variables in installspace
set(GENLISP_BIN "${genlisp_DIR}/../../../@(CATKIN_PACKAGE_BIN_DESTINATION)/gen_lisp.py")
set(GENLISP_TEMPLATE_DIR "${genlisp_DIR}/..")
@[end if]@
# Generate .msg or .srv -> .lisp
# The generated .lisp files should be added ALL_GEN_OUTPUT_FILES_lisp
macro(_generate_lisp ARG_PKG ARG_MSG ARG_IFLAGS ARG_MSG_DEPS ARG_GEN_OUTPUT_DIR)
file(MAKE_DIRECTORY ${ARG_GEN_OUTPUT_DIR})
#Create input and output filenames
get_filename_component(MSG_NAME ${ARG_MSG} NAME)
get_filename_component(MSG_SHORT_NAME ${ARG_MSG} NAME_WE)
set(MSG_GENERATED_NAME ${MSG_SHORT_NAME}.lisp)
set(GEN_OUTPUT_FILE ${ARG_GEN_OUTPUT_DIR}/${MSG_GENERATED_NAME})
assert(CATKIN_ENV)
add_custom_command(OUTPUT ${GEN_OUTPUT_FILE}
DEPENDS ${GENLISP_BIN} ${ARG_MSG} ${ARG_MSG_DEPS}
COMMAND ${CATKIN_ENV} ${PYTHON_EXECUTABLE} ${GENLISP_BIN} ${ARG_MSG}
${ARG_IFLAGS}
-p ${ARG_PKG}
-o ${ARG_GEN_OUTPUT_DIR}
COMMENT "Generating Lisp code from ${ARG_PKG}/${MSG_NAME}"
)
list(APPEND ALL_GEN_OUTPUT_FILES_lisp ${GEN_OUTPUT_FILE})
endmacro()
#genlisp uses the same program to generate srv and msg files, so call the same macro
macro(_generate_msg_lisp ARG_PKG ARG_MSG ARG_IFLAGS ARG_MSG_DEPS ARG_GEN_OUTPUT_DIR)
_generate_lisp(${ARG_PKG} ${ARG_MSG} "${ARG_IFLAGS}" "${ARG_MSG_DEPS}" "${ARG_GEN_OUTPUT_DIR}/msg")
endmacro()
#genlisp uses the same program to generate srv and msg files, so call the same macro
macro(_generate_srv_lisp ARG_PKG ARG_SRV ARG_IFLAGS ARG_MSG_DEPS ARG_GEN_OUTPUT_DIR)
_generate_lisp(${ARG_PKG} ${ARG_SRV} "${ARG_IFLAGS}" "${ARG_MSG_DEPS}" "${ARG_GEN_OUTPUT_DIR}/srv")
endmacro()
macro(_generate_module_lisp ARG_PKG ARG_GEN_OUTPUT_DIR ARG_GENERATED_FILES)
endmacro()
set(common_lisp_INSTALL_DIR share/common-lisp)
set(genlisp_INSTALL_DIR ${common_lisp_INSTALL_DIR}/ros)
genlisp-0.4.16/package.xml 0000664 0000000 0000000 00000001272 12762341661 0015372 0 ustar 00root root 0000000 0000000
genlisp
0.4.16
Common-Lisp ROS message and service generators.
Dirk Thomas
Georg Bartels
BSD
http://www.ros.org/wiki/roslisp
Bhaskara Marti
catkin
genmsg
genmsg
lisp
genlisp-0.4.16/scripts/ 0000775 0000000 0000000 00000000000 12762341661 0014742 5 ustar 00root root 0000000 0000000 genlisp-0.4.16/scripts/CMakeLists.txt 0000664 0000000 0000000 00000000310 12762341661 0017474 0 ustar 00root root 0000000 0000000 install(
FILES msg.lisp.template srv.lisp.template
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION})
catkin_install_python(
PROGRAMS gen_lisp.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION})
genlisp-0.4.16/scripts/gen_lisp.py 0000775 0000000 0000000 00000003477 12762341661 0017132 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
# Software License Agreement (BSD License)
#
# Copyright (c) 2012, Willow Garage, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of Willow Garage, Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
## ROS message source code generation for Lisp
##
## Converts ROS .msg files in a package into Lisp source files
import genlisp
import sys
if __name__ == "__main__":
genlisp.genlisp_main.genmain(sys.argv, 'gen_lisp.py')
genlisp-0.4.16/scripts/msg.lisp.template 0000664 0000000 0000000 00000001446 12762341661 0020240 0 ustar 00root root 0000000 0000000 @###############################################
@#
@# ROS message source code generation for C++
@#
@# EmPy template for generating .h files
@#
@###############################################
@# Start of Template
@#
@# Context:
@# - file_name_in (String) Source file
@# - spec (msggen.MsgSpec) Parsed specification of the .msg file
@# - md5sum (String) MD5Sum of the .msg specification
@###############################################
#include
#include <@(spec.package)/@(spec.short_name).h>
using namespace boost::python;
void export_@(spec.short_name)()
{
class_<@(spec.package)::@(spec.short_name)>("@(spec.short_name)")
@[for field in spec.parsed_fields()]@
.def_readwrite("@(field.name)", &@(spec.package)::@(spec.short_name)::@(field.name))
@[end for]@#field
;
}
genlisp-0.4.16/scripts/srv.lisp.template 0000664 0000000 0000000 00000001460 12762341661 0020260 0 ustar 00root root 0000000 0000000 @###############################################
@#
@# ROS message source code generation for C++
@#
@# EmPy template for generating .h files
@#
@###############################################
@# Start of Template
@#
@# Context:
@# - file_name_in (String) Source file
@# - spec (msggen.MsgSpec) Parsed specification of the .msg file
@# - md5sum (String) MD5Sum of the .msg specification
@###############################################
#include
#include <@(spec.package)/@(spec.short_name).h>
using namespace boost::python;
void export_@(spec.short_name)()
{
class_<@(spec.package)::@(spec.short_name)>("@(spec.short_name)")
.def_readwrite("request", &@(spec.package)::@(spec.short_name)::request)
.def_readwrite("response", &@(spec.package)::@(spec.short_name)::response);
}
genlisp-0.4.16/setup.py 0000775 0000000 0000000 00000000361 12762341661 0014770 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python
from distutils.core import setup
from catkin_pkg.python_setup import generate_distutils_setup
d = generate_distutils_setup(
packages=['genlisp'],
package_dir={'': 'src'},
requires=['genmsg']
)
setup(**d)
genlisp-0.4.16/src/ 0000775 0000000 0000000 00000000000 12762341661 0014042 5 ustar 00root root 0000000 0000000 genlisp-0.4.16/src/genlisp/ 0000775 0000000 0000000 00000000000 12762341661 0015503 5 ustar 00root root 0000000 0000000 genlisp-0.4.16/src/genlisp/__init__.py 0000664 0000000 0000000 00000003114 12762341661 0017613 0 ustar 00root root 0000000 0000000 # Software License Agreement (BSD License)
#
# Copyright (c) 2011, Willow Garage, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of Willow Garage, Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
from . genlisp_main import *
genlisp-0.4.16/src/genlisp/generate.py 0000664 0000000 0000000 00000074675 12762341661 0017672 0 ustar 00root root 0000000 0000000 # Software License Agreement (BSD License)
#
# Copyright (c) 2009, Willow Garage, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of Willow Garage, Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
## ROS message source code generation for Lisp
##
## Converts ROS .msg and .srv files in a package into Lisp source code
## t0: needed for script to work
## t1: for reference; remove once running
## t2: can be changed once we remove strict diff-compatibility requirement with old version of genmsg_lisp
import sys
import os
import traceback
import re
#import roslib.msgs
#import roslib.srvs
#import roslib.packages
#import roslib.gentools
from genmsg import SrvSpec, MsgSpec, MsgContext
from genmsg.msg_loader import load_srv_from_file, load_msg_by_type
import genmsg.gentools
try:
from cStringIO import StringIO #Python 2.x
except ImportError:
from io import StringIO #Python 3.x
############################################################
# Built in types
############################################################
def is_fixnum(t):
return t in ['int8', 'uint8', 'int16', 'uint16']
def is_integer(t):
return is_fixnum(t) or t in ['byte', 'char', 'int32', 'uint32', 'int64', 'uint64'] #t2 byte, char can be fixnum
def is_signed_int(t):
return t in ['int8', 'int16', 'int32', 'int64']
def is_unsigned_int(t):
return t in ['uint8', 'uint16', 'uint32', 'uint64']
def is_bool(t):
return t == 'bool'
def is_string(t):
return t == 'string'
def is_float(t):
return t in ['float16', 'float32', 'float64']
def is_time(t):
return t in ['time', 'duration']
def field_type(f):
if f.is_builtin:
elt_type = lisp_type(f.base_type)
else:
elt_type = msg_type(f)
if f.is_array:
return '(cl:vector %s)'%elt_type
else:
return elt_type
def parse_msg_type(f):
if f.base_type == 'Header':
return ('std_msgs', 'Header')
else:
return f.base_type.split('/')
# t2 no need for is_array
def msg_type(f):
(pkg, msg) = parse_msg_type(f)
return '%s-msg:%s'%(pkg, msg)
def lisp_type(t):
if is_fixnum(t):
return 'cl:fixnum'
elif is_integer(t):
return 'cl:integer'
elif is_bool(t):
return 'cl:boolean'
elif is_float(t):
return 'cl:float'
elif is_time(t):
return 'cl:real'
elif is_string(t):
return 'cl:string'
else:
raise ValueError('%s is not a recognized primitive type'%t)
def field_initform(f):
if f.is_builtin:
initform = lisp_initform(f.base_type)
elt_type = lisp_type(f.base_type)
else:
initform = '(cl:make-instance \'%s)'%msg_type(f)
elt_type = msg_type(f)
if f.is_array:
len = f.array_len or 0
return '(cl:make-array %s :element-type \'%s :initial-element %s)'%(len, elt_type, initform)
else:
return initform
def lisp_initform(t):
if is_integer(t):
return '0'
elif is_bool(t):
return 'cl:nil'
elif is_float(t):
return '0.0'
elif is_time(t):
return 0
elif is_string(t):
return '\"\"'
else:
raise ValueError('%s is not a recognized primitive type'%t)
NUM_BYTES = {'int8': 1, 'int16': 2, 'int32': 4, 'int64': 8,
'uint8': 1, 'uint16': 2, 'uint32': 4, 'uint64': 8}
############################################################
# Indented writer
############################################################
class IndentedWriter():
def __init__(self, s):
self.str = s
self.indentation = 0
self.block_indent = False
def write(self, s, indent=True, newline=True):
if not indent:
newline = False
if self.block_indent:
self.block_indent = False
else:
if newline:
self.str.write('\n')
if indent:
for i in range(self.indentation):
self.str.write(' ')
self.str.write(s)
def newline(self):
self.str.write('\n')
def inc_indent(self, inc=2):
self.indentation += inc
def dec_indent(self, dec=2):
self.indentation -= dec
def reset_indent(self):
self.indentation = 0
def block_next_indent(self):
self.block_indent = True
class Indent():
def __init__(self, w, inc=2, indent_first=True):
self.writer = w
self.inc = inc
self.indent_first = indent_first
def __enter__(self):
self.writer.inc_indent(self.inc)
if not self.indent_first:
self.writer.block_next_indent()
def __exit__(self, type, val, traceback):
self.writer.dec_indent(self.inc)
def write_begin(s, spec, is_service=False):
"Writes the beginning of the file: a comment saying it's auto-generated and the in-package form"
s.write('; Auto-generated. Do not edit!\n\n\n', newline=False)
suffix = 'srv' if is_service else 'msg'
s.write('(cl:in-package %s-%s)\n\n\n'%(spec.package, suffix), newline=False)
def write_html_include(s, spec, is_srv=False):
s.write(';//! \\htmlinclude %s.msg.html\n'%spec.actual_name, newline=False) # t2
def write_slot_definition(s, field):
"Write the definition of a slot corresponding to a single message field"
s.write('(%s'%field.name)
with Indent(s, 1):
s.write(':reader %s'%field.name)
s.write(':initarg :%s'%field.name)
s.write(':type %s'%field_type(field))
i = 0 if field.is_array else 1 # t2
with Indent(s, i):
s.write(':initform %s)'%field_initform(field))
def write_deprecated_readers(s, spec):
suffix = 'srv' if spec.component_type == 'service' else 'msg'
for field in spec.parsed_fields():
s.newline()
s.write('(cl:ensure-generic-function \'%s-val :lambda-list \'(m))' % field.name)
s.write('(cl:defmethod %s-val ((m %s))'%(field.name, message_class(spec)))
with Indent(s):
s.write('(roslisp-msg-protocol:msg-deprecation-warning "Using old-style slot reader %s-%s:%s-val is deprecated. Use %s-%s:%s instead.")'%(spec.package, suffix, field.name, spec.package, suffix, field.name))
s.write('(%s m))'%field.name)
def write_defclass(s, spec):
"Writes the defclass that defines the message type"
cl = message_class(spec)
new_cl = new_message_class(spec)
suffix = 'srv' if spec.component_type == 'service' else 'msg'
s.write('(cl:defclass %s (roslisp-msg-protocol:ros-message)'%cl)
with Indent(s):
s.write('(')
with Indent(s, inc=1, indent_first=False):
for field in spec.parsed_fields():
write_slot_definition(s, field)
s.write(')', indent=False)
s.write(')')
s.newline()
s.write('(cl:defclass %s (%s)'%(new_cl, cl))
with Indent(s):
s.write('())')
s.newline()
s.write('(cl:defmethod cl:initialize-instance :after ((m %s) cl:&rest args)'%cl)
with Indent(s):
s.write('(cl:declare (cl:ignorable args))')
s.write('(cl:unless (cl:typep m \'%s)'%new_cl)
with Indent(s):
s.write('(roslisp-msg-protocol:msg-deprecation-warning "using old message class name %s-%s:%s is deprecated: use %s-%s:%s instead.")))'%(spec.package, suffix, cl, spec.package, suffix, new_cl))
def message_class(spec):
"""
Return the CLOS class name for this message type
"""
return '<%s>'%spec.actual_name
def new_message_class(spec):
return spec.actual_name
def write_serialize_length(s, v, is_array=False):
#t2
var = '__ros_arr_len' if is_array else '__ros_str_len'
s.write('(cl:let ((%s (cl:length %s)))'%(var, v))
with Indent(s):
for x in range(0, 32, 8):
s.write('(cl:write-byte (cl:ldb (cl:byte 8 %s) %s) ostream)'%(x, var))
s.write(')', indent=False)
def write_serialize_bits(s, v, num_bytes):
for x in range(0, num_bytes*8, 8):
s.write('(cl:write-byte (cl:ldb (cl:byte 8 %s) %s) ostream)'%(x, v))
def write_serialize_bits_signed(s, v, num_bytes):
num_bits = num_bytes*8
s.write('(cl:let* ((signed %s) (unsigned (cl:if (cl:< signed 0) (cl:+ signed %s) signed)))'%(v, 2**num_bits))
with Indent(s):
write_serialize_bits(s, 'unsigned', num_bytes)
s.write(')')
# t2: can get rid of this lookup_slot stuff
def write_serialize_builtin(s, f, var='msg', lookup_slot=True):
v = '(cl:slot-value %s \'%s)'%(var, f.name) if lookup_slot else var
if f.base_type == 'string':
write_serialize_length(s, v)
s.write('(cl:map cl:nil #\'(cl:lambda (c) (cl:write-byte (cl:char-code c) ostream)) %s)'%v)
elif f.base_type == 'float32':
s.write('(cl:let ((bits %s))'%'(roslisp-utils:encode-single-float-bits %s)'%v)
with Indent(s):
write_serialize_bits(s, 'bits', 4)
s.write(')', False)
elif f.base_type == 'float64':
s.write('(cl:let ((bits %s))'%'(roslisp-utils:encode-double-float-bits %s)'%v)
with Indent(s):
write_serialize_bits(s, 'bits', 8)
s.write(')', False)
elif f.base_type == 'bool':
s.write('(cl:write-byte (cl:ldb (cl:byte 8 0) (cl:if %s 1 0)) ostream)'%v)
elif f.base_type in ['byte', 'char']:
s.write('(cl:write-byte (cl:ldb (cl:byte 8 0) %s) ostream)'%v)
elif f.base_type in ['duration', 'time']:
s.write('(cl:let ((__sec (cl:floor %s))'%v)
s.write(' (__nsec (cl:round (cl:* 1e9 (cl:- %s (cl:floor %s))))))'%(v,v))
with Indent(s):
write_serialize_bits(s, '__sec', 4)
write_serialize_bits(s, '__nsec', 4)
s.write(')', False)
elif is_signed_int(f.base_type):
write_serialize_bits_signed(s, v, NUM_BYTES[f.base_type])
elif is_unsigned_int(f.base_type):
write_serialize_bits(s, v, NUM_BYTES[f.base_type])
else:
raise ValueError('Unknown type: %s', f.base_type)
def write_serialize_field(s, f):
slot = '(cl:slot-value msg \'%s)'%f.name
if f.is_array:
if not f.array_len:
write_serialize_length(s, slot, True)
s.write('(cl:map cl:nil #\'(cl:lambda (ele) ')
var = 'ele'
s.block_next_indent()
lookup_slot = False
else:
var='msg'
lookup_slot = True
if f.is_builtin:
write_serialize_builtin(s, f, var, lookup_slot=lookup_slot)
else:
to_write = slot if lookup_slot else var #t2
s.write('(roslisp-msg-protocol:serialize %s ostream)'%to_write)
if f.is_array:
s.write(')', False)
s.write(' %s)'%slot)
def write_serialize(s, spec):
"""
Write the serialize method
"""
s.write('(cl:defmethod roslisp-msg-protocol:serialize ((msg %s) ostream)'%message_class(spec))
with Indent(s):
s.write('"Serializes a message object of type \'%s"'%message_class(spec))
for f in spec.parsed_fields():
write_serialize_field(s, f)
s.write(')')
# t2 can get rid of is_array
def write_deserialize_length(s, is_array=False):
var = '__ros_arr_len' if is_array else '__ros_str_len'
s.write('(cl:let ((%s 0))'%var)
with Indent(s):
for x in range(0, 32, 8):
s.write('(cl:setf (cl:ldb (cl:byte 8 %s) %s) (cl:read-byte istream))'%(x, var))
def write_deserialize_bits(s, v, num_bytes):
for x in range(0, num_bytes*8, 8):
s.write('(cl:setf (cl:ldb (cl:byte 8 %s) %s) (cl:read-byte istream))'%(x, v))
def write_deserialize_bits_signed(s, v, num_bytes):
s.write('(cl:let ((unsigned 0))')
num_bits = 8*num_bytes
with Indent(s):
write_deserialize_bits(s, 'unsigned', num_bytes)
s.write('(cl:setf %s (cl:if (cl:< unsigned %s) unsigned (cl:- unsigned %s))))'%(v, 2**(num_bits-1), 2**num_bits))
def write_deserialize_builtin(s, f, v):
if f.base_type == 'string':
write_deserialize_length(s)
with Indent(s):
s.write('(cl:setf %s (cl:make-string __ros_str_len))'%v)
s.write('(cl:dotimes (__ros_str_idx __ros_str_len msg)')
with Indent(s):
s.write('(cl:setf (cl:char %s __ros_str_idx) (cl:code-char (cl:read-byte istream)))))'%v)
elif f.base_type == 'float32':
s.write('(cl:let ((bits 0))')
with Indent(s):
write_deserialize_bits(s, 'bits', 4)
s.write('(cl:setf %s (roslisp-utils:decode-single-float-bits bits)))'%v)
elif f.base_type == 'float64':
s.write('(cl:let ((bits 0))')
with Indent(s):
write_deserialize_bits(s, 'bits', 8)
s.write('(cl:setf %s (roslisp-utils:decode-double-float-bits bits)))'%v)
elif f.base_type == 'bool':
s.write('(cl:setf %s (cl:not (cl:zerop (cl:read-byte istream))))'%v)
elif f.base_type in ['byte', 'char']:
s.write('(cl:setf (cl:ldb (cl:byte 8 0) %s) (cl:read-byte istream))'%v)
elif f.base_type in ['duration', 'time']:
s.write('(cl:let ((__sec 0) (__nsec 0))')
with Indent(s):
write_deserialize_bits(s, '__sec', 4)
write_deserialize_bits(s, '__nsec', 4)
s.write('(cl:setf %s (cl:+ (cl:coerce __sec \'cl:double-float) (cl:/ __nsec 1e9))))'%v)
elif is_signed_int(f.base_type):
write_deserialize_bits_signed(s, v, NUM_BYTES[f.base_type])
elif is_unsigned_int(f.base_type):
write_deserialize_bits(s, v, NUM_BYTES[f.base_type])
else:
raise ValueError('%s unknown'%f.base_type)
def write_deserialize_field(s, f, pkg):
slot = '(cl:slot-value msg \'%s)'%f.name
var = slot
if f.is_array:
if not f.array_len:
write_deserialize_length(s, True)
length = '__ros_arr_len'
else:
length = '%s'%f.array_len
s.write('(cl:setf %s (cl:make-array %s))'%(slot, length))
s.write('(cl:let ((vals %s))'%slot) # t2
var = '(cl:aref vals i)'
with Indent(s):
s.write('(cl:dotimes (i %s)'%length)
if f.is_builtin:
with Indent(s):
write_deserialize_builtin(s, f, var)
else:
if f.is_array:
with Indent(s):
s.write('(cl:setf %s (cl:make-instance \'%s))'%(var, msg_type(f)))
s.write('(roslisp-msg-protocol:deserialize %s istream)'%var)
if f.is_array:
s.write('))', False)
if not f.array_len:
s.write(')', False)
def write_deserialize(s, spec):
"""
Write the deserialize method
"""
s.write('(cl:defmethod roslisp-msg-protocol:deserialize ((msg %s) istream)'%message_class(spec))
with Indent(s):
s.write('"Deserializes a message object of type \'%s"'%message_class(spec))
for f in spec.parsed_fields():
write_deserialize_field(s, f, spec.package)
s.write('msg')
s.write(')')
def write_class_exports(s, msgs, pkg):
"Write the _package.lisp file"
s.write('(cl:defpackage %s-msg'%pkg, False)
with Indent(s):
s.write('(:use )')
s.write('(:export')
with Indent(s, inc=1):
for m in msgs:
msg_class = '<%s>'%m
s.write('"%s"'%msg_class.upper())
s.write('"%s"'%m.upper())
s.write('))\n\n')
def write_srv_exports(s, srvs, pkg):
"Write the _package.lisp file for a service directory"
s.write('(cl:defpackage %s-srv'%pkg, False)
with Indent(s):
s.write('(:use )')
s.write('(:export')
with Indent(s, inc=1):
for srv in srvs:
s.write('"%s"'%srv.upper())
s.write('"<%s-REQUEST>"'%srv.upper())
s.write('"%s-REQUEST"'%srv.upper())
s.write('"<%s-RESPONSE>"'%srv.upper())
s.write('"%s-RESPONSE"'%srv.upper())
s.write('))\n\n')
def write_asd_deps(s, deps, msgs):
with Indent(s):
s.write(':depends-on (:roslisp-msg-protocol :roslisp-utils ')
with Indent(s, inc=13, indent_first=False):
for d in sorted(deps):
s.write(':%s-msg'%d)
s.write(')') #t2 indentation
with Indent(s):
s.write(':components ((:file "_package")')
with Indent(s):
for name in msgs:
s.write('(:file "%s" :depends-on ("_package_%s"))'%(name, name))
s.write('(:file "_package_%s" :depends-on ("_package"))'%name)
s.write('))')
def write_srv_asd(s, pkg, srvs, context):
s.write('(cl:in-package :asdf)')
s.newline()
s.write('(defsystem "%s-srv"'%pkg)
# Figure out set of depended-upon ros packages
deps = set()
for srv in srvs:
req_spec = context.get_registered('%s/%sRequest'%(pkg, srv))
resp_spec = context.get_registered('%s/%sResponse'%(pkg, srv))
for f in req_spec.parsed_fields():
if not f.is_builtin:
(p, _) = parse_msg_type(f)
deps.add(p)
for f in resp_spec.parsed_fields():
if not f.is_builtin:
(p, _) = parse_msg_type(f)
deps.add(p)
write_asd_deps(s, deps, srvs)
def write_asd(s, pkg, msgs, context):
s.write('(cl:in-package :asdf)')
s.newline()
s.write('(defsystem "%s-msg"'%pkg)
# Figure out set of depended-upon ros packages
deps = set()
for m in msgs:
spec = context.get_registered('%s/%s'%(pkg, m))
for f in spec.parsed_fields():
if not f.is_builtin:
(p, _) = parse_msg_type(f)
deps.add(p)
if pkg in deps:
deps.remove(pkg)
write_asd_deps(s, deps, msgs)
def write_accessor_exports(s, spec):
"Write the package exports for this message/service"
is_srv = isinstance(spec, SrvSpec)
suffix = 'srv' if is_srv else 'msg'
s.write('(cl:in-package %s-%s)'%(spec.package, suffix), indent=False)
s.write('(cl:export \'(')
if is_srv:
fields = spec.request.parsed_fields()[:]
fields.extend(spec.response.parsed_fields())
else:
fields = spec.parsed_fields()
with Indent(s, inc=10, indent_first=False):
for f in fields:
accessor = '%s-val'%f.name
s.write('%s'%accessor.upper())
s.write('%s'%f.name.upper())
s.write('))')
def write_ros_datatype(s, spec):
for c in (message_class(spec), new_message_class(spec)):
s.write('(cl:defmethod roslisp-msg-protocol:ros-datatype ((msg (cl:eql \'%s)))'%c)
with Indent(s):
s.write('"Returns string type for a %s object of type \'%s"'%(spec.component_type, c))
s.write('"%s")'%spec.full_name)
def write_md5sum(s, msg_context, spec, parent=None):
md5sum = genmsg.compute_md5(msg_context, parent or spec)
for c in (message_class(spec), new_message_class(spec)):
s.write('(cl:defmethod roslisp-msg-protocol:md5sum ((type (cl:eql \'%s)))'%c)
with Indent(s):
# t2 this should print 'service' instead of 'message' if it's a service request or response
s.write('"Returns md5sum for a message object of type \'%s"'%c)
s.write('"%s")'%md5sum)
def write_message_definition(s, msg_context, spec):
for c in (message_class(spec), new_message_class(spec)):
s.write('(cl:defmethod roslisp-msg-protocol:message-definition ((type (cl:eql \'%s)))'%c)
with Indent(s):
s.write('"Returns full string definition for message of type \'%s"'%c)
s.write('(cl:format cl:nil "')
definition = genmsg.compute_full_text(msg_context, spec)
lines = definition.split('\n')
for line in lines:
l = line.replace('\\', '\\\\')
l = l.replace('"', '\\"')
l = l.replace('~', '~~')
s.write('%s~%%'%l, indent=False)
s.write('~%', indent=False)
s.write('"))', indent=False)
def write_builtin_length(s, f, var='msg'):
if f.base_type in ['int8', 'uint8']:
s.write('1')
elif f.base_type in ['int16', 'uint16']:
s.write('2')
elif f.base_type in ['int32', 'uint32', 'float32']:
s.write('4')
elif f.base_type in ['int64', 'uint64', 'float64', 'duration', 'time']:
s.write('8')
elif f.base_type == 'string':
s.write('4 (cl:length %s)'%var)
elif f.base_type in ['bool', 'byte', 'char']:
s.write('1')
else:
raise ValueError('Unknown: %s', f.base_type)
def write_serialization_length(s, spec):
c = message_class(spec)
s.write('(cl:defmethod roslisp-msg-protocol:serialization-length ((msg %s))'%c)
with Indent(s):
s.write('(cl:+ 0')
with Indent(s, 3):
for field in spec.parsed_fields():
slot = '(cl:slot-value msg \'%s)'%field.name
if field.is_array:
l = '0' if field.array_len else '4'
s.write('%s (cl:reduce #\'cl:+ %s :key #\'(cl:lambda (ele) (cl:declare (cl:ignorable ele)) (cl:+ '%(l, slot))
var = 'ele'
s.block_next_indent()
else:
var = slot
if field.is_builtin:
write_builtin_length(s, field, var)
else:
s.write('(roslisp-msg-protocol:serialization-length %s)'%var)
if field.is_array:
s.write(')))', False)
s.write('))')
def write_list_converter(s, spec):
c = message_class(spec)
s.write('(cl:defmethod roslisp-msg-protocol:ros-message-to-list ((msg %s))'%c)
with Indent(s):
s.write('"Converts a ROS message object to a list"')
s.write('(cl:list \'%s'%new_message_class(spec))
with Indent(s):
for f in spec.parsed_fields():
s.write('(cl:cons \':%s (%s msg))'%(f.name, f.name))
s.write('))')
def write_constants(s, spec):
if spec.constants:
for cls in (message_class(spec), new_message_class(spec)):
s.write('(cl:defmethod roslisp-msg-protocol:symbol-codes ((msg-type (cl:eql \'%s)))'%cls)
with Indent(s):
s.write(' "Constants for message type \'%s"'%cls)
s.write('\'(')
with Indent(s, indent_first=False):
for c in spec.constants:
s.write('(:%s . %s)'%(c.name.upper(), c.val))
s.write(')', False)
s.write(')')
def write_srv_component(s, spec, context, parent):
spec.component_type='service'
write_html_include(s, spec)
write_defclass(s, spec)
write_deprecated_readers(s, spec)
write_constants(s, spec)
write_serialize(s, spec)
write_deserialize(s, spec)
write_ros_datatype(s, spec)
write_md5sum(s, context, spec, parent=parent)
write_message_definition(s, context, spec)
write_serialization_length(s, spec)
write_list_converter(s, spec)
def write_service_specific_methods(s, spec):
spec.actual_name=spec.short_name
s.write('(cl:defmethod roslisp-msg-protocol:service-request-type ((msg (cl:eql \'%s)))'%spec.short_name)
with Indent(s):
s.write('\'%s)'%new_message_class(spec.request))
s.write('(cl:defmethod roslisp-msg-protocol:service-response-type ((msg (cl:eql \'%s)))'%spec.short_name)
with Indent(s):
s.write('\'%s)'%new_message_class(spec.response))
s.write('(cl:defmethod roslisp-msg-protocol:ros-datatype ((msg (cl:eql \'%s)))'%spec.short_name)
with Indent(s):
s.write('"Returns string type for a service object of type \'%s"'%message_class(spec))
s.write('"%s")'%spec.full_name)
def generate_msg(pkg, files, out_dir, search_path):
"""
Generate lisp code for all messages in a package
"""
msg_context = MsgContext.create_default()
for f in files:
f = os.path.abspath(f)
infile = os.path.basename(f)
full_type = genmsg.gentools.compute_full_type_name(pkg, infile)
spec = genmsg.msg_loader.load_msg_from_file(msg_context, f, full_type)
generate_msg_from_spec(msg_context, spec, search_path, out_dir, pkg)
def generate_srv(pkg, files, out_dir, search_path):
"""
Generate lisp code for all services in a package
"""
msg_context = MsgContext.create_default()
for f in files:
f = os.path.abspath(f)
infile = os.path.basename(f)
full_type = genmsg.gentools.compute_full_type_name(pkg, infile)
spec = genmsg.msg_loader.load_srv_from_file(msg_context, f, full_type)
generate_srv_from_spec(msg_context, spec, search_path, out_dir, pkg, f)
def msg_list(pkg, search_path, ext):
dir_list = search_path[pkg]
files = []
for d in dir_list:
files.extend([f for f in os.listdir(d) if f.endswith(ext)])
# sort list because listdir is filesystem specific
return sorted([f[:-len(ext)] for f in files])
def generate_msg_from_spec(msg_context, spec, search_path, output_dir, package):
"""
Generate a message
@param msg_path: The path to the .msg file
@type msg_path: str
"""
genmsg.msg_loader.load_depends(msg_context, spec, search_path)
spec.actual_name=spec.short_name
spec.component_type='message'
msgs = msg_list(package, search_path, '.msg')
for m in msgs:
genmsg.load_msg_by_type(msg_context, '%s/%s'%(package, m), search_path)
########################################
# 1. Write the .lisp file
########################################
io = StringIO()
s = IndentedWriter(io)
write_begin(s, spec)
write_html_include(s, spec)
write_defclass(s, spec)
write_deprecated_readers(s, spec)
write_constants(s, spec)
write_serialize(s, spec)
write_deserialize(s, spec)
write_ros_datatype(s, spec)
write_md5sum(s, msg_context, spec)
write_message_definition(s, msg_context, spec)
write_serialization_length(s, spec)
write_list_converter(s, spec)
if (not os.path.exists(output_dir)):
# if we're being run concurrently, the above test can report false but os.makedirs can still fail if
# another copy just created the directory
try:
os.makedirs(output_dir)
except OSError as e:
pass
with open('%s/%s.lisp'%(output_dir, spec.short_name), 'w') as f:
f.write(io.getvalue() + "\n")
io.close()
########################################
# 2. Write the _package file
# for this message
########################################
io = StringIO()
s = IndentedWriter(io)
write_accessor_exports(s, spec)
with open('%s/_package_%s.lisp'%(output_dir, spec.short_name), 'w') as f:
f.write(io.getvalue())
io.close()
########################################
# 3. Write the _package.lisp file
# This is being rewritten once per msg
# file, which is inefficient
########################################
io = StringIO()
s = IndentedWriter(io)
write_class_exports(s, msgs, package)
with open('%s/_package.lisp'%output_dir, 'w') as f:
f.write(io.getvalue())
io.close()
########################################
# 4. Write the .asd file
# This is being written once per msg
# file, which is inefficient
########################################
io = StringIO()
s = IndentedWriter(io)
write_asd(s, package, msgs, msg_context)
with open('%s/%s-msg.asd'%(output_dir, package), 'w') as f:
f.write(io.getvalue())
io.close()
# t0 most of this could probably be refactored into being shared with messages
def generate_srv_from_spec(msg_context, spec, search_path, output_dir, package, path):
"Generate code from .srv file"
genmsg.msg_loader.load_depends(msg_context, spec, search_path)
ext = '.srv'
srv_path = os.path.dirname(path)
srvs = msg_list(package, {package: [srv_path]}, ext)
for srv in srvs:
load_srv_from_file(msg_context, '%s/%s%s'%(srv_path, srv, ext), '%s/%s'%(package, srv))
########################################
# 1. Write the .lisp file
########################################
io = StringIO()
s = IndentedWriter(io)
write_begin(s, spec, True)
spec.request.actual_name='%s-request'%spec.short_name
spec.response.actual_name='%s-response'%spec.short_name
write_srv_component(s, spec.request, msg_context, spec)
s.newline()
write_srv_component(s, spec.response, msg_context, spec)
write_service_specific_methods(s, spec)
with open('%s/%s.lisp'%(output_dir, spec.short_name), 'w') as f:
f.write(io.getvalue())
io.close()
########################################
# 2. Write the _package file
# for this service
########################################
io = StringIO()
s = IndentedWriter(io)
write_accessor_exports(s, spec)
with open('%s/_package_%s.lisp'%(output_dir, spec.short_name), 'w') as f:
f.write(io.getvalue())
io.close()
########################################
# 3. Write the _package.lisp file
########################################
io = StringIO()
s = IndentedWriter(io)
write_srv_exports(s, srvs, package)
with open('%s/_package.lisp'%output_dir, 'w') as f:
f.write(io.getvalue())
io.close()
########################################
# 4. Write the .asd file
########################################
io = StringIO()
s = IndentedWriter(io)
write_srv_asd(s, package, srvs, msg_context)
with open('%s/%s-srv.asd'%(output_dir, package), 'w') as f:
f.write(io.getvalue())
io.close()
genlisp-0.4.16/src/genlisp/genlisp_main.py 0000664 0000000 0000000 00000006465 12762341661 0020535 0 ustar 00root root 0000000 0000000 # Software License Agreement (BSD License)
#
# Copyright (c) 2009, Willow Garage, Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of Willow Garage, Inc. nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
from __future__ import print_function
from optparse import OptionParser
import os
import sys
import traceback
import genmsg
import genmsg.command_line
from genmsg import MsgGenerationException
from . generate import generate_msg, generate_srv
def usage(progname):
print("%(progname)s file(s)"%vars())
def genmain(argv, progname):
parser = OptionParser("%s file"%(progname))
parser.add_option('-p', dest='package')
parser.add_option('-o', dest='outdir')
parser.add_option('-I', dest='includepath', action='append')
options, args = parser.parse_args(argv)
try:
if len(args) < 2:
parser.error("please specify args")
if not os.path.exists(options.outdir):
# This script can be run multiple times in parallel. We
# don't mind if the makedirs call fails because somebody
# else snuck in and created the directory before us.
try:
os.makedirs(options.outdir)
except OSError as e:
if not os.path.exists(options.outdir):
raise
search_path = genmsg.command_line.includepath_to_dict(options.includepath)
filename = args[1]
if filename.endswith('.msg'):
retcode = generate_msg(options.package, args[1:], options.outdir, search_path)
else:
retcode = generate_srv(options.package, args[1:], options.outdir, search_path)
except genmsg.InvalidMsgSpec as e:
print("ERROR: ", e, file=sys.stderr)
retcode = 1
except MsgGenerationException as e:
print("ERROR: ", e, file=sys.stderr)
retcode = 2
except Exception as e:
traceback.print_exc()
print("ERROR: ",e)
retcode = 3
sys.exit(retcode or 0)