File: Synopsis/Parsers/IDL/idlutil.py
  1# -*- python -*-
  2#                           Package   : omniidl
  3# idlutil.py                Created on: 1999/10/27
  4#			    Author    : Duncan Grisby (dpg1)
  5#
  6#    Copyright (C) 1999 AT&T Laboratories Cambridge
  7#
  8#  This file is part of omniidl.
  9#
 10#  omniidl is free software; you can redistribute it and/or modify it
 11#  under the terms of the GNU General Public License as published by
 12#  the Free Software Foundation; either version 2 of the License, or
 13#  (at your option) any later version.
 14#
 15#  This program is distributed in the hope that it will be useful,
 16#  but WITHOUT ANY WARRANTY; without even the implied warranty of
 17#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 18#  General Public License for more details.
 19#
 20#  You should have received a copy of the GNU General Public License
 21#  along with this program; if not, write to the Free Software
 22#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 23#  02111-1307, USA.
 24#
 25# Description:
 26#   
 27#   Utility functions
 28
 29# $Id: idlutil.py,v 1.9.2.4 2006/01/10 12:24:03 dgrisby Exp $
 30# $Log: idlutil.py,v $
 31# Revision 1.9.2.4  2006/01/10 12:24:03  dgrisby
 32# Merge from omni4_0_develop pre 4.0.7 release.
 33#
 34# Revision 1.9.2.3  2005/07/21 09:54:59  dgrisby
 35# Typo in docstring.
 36#
 37# Revision 1.9.2.2  2005/04/08 00:35:45  dgrisby
 38# Merging again.
 39#
 40# Revision 1.9.2.1  2003/03/23 21:01:38  dgrisby
 41# Start of omniORB 4.1.x development branch.
 42#
 43# Revision 1.5.2.6  2001/08/29 11:54:22  dpg1
 44# Clean up const handling in IDL compiler.
 45#
 46# Revision 1.5.2.5  2001/08/15 10:31:23  dpg1
 47# Minor tweaks and fixes.
 48#
 49# Revision 1.5.2.4  2001/06/13 11:28:22  dpg1
 50# Proper omniidl support for wchar/wstring constants.
 51#
 52# Revision 1.5.2.3  2001/03/13 10:34:01  dpg1
 53# Minor Python clean-ups
 54#
 55# Revision 1.5.2.2  2000/10/10 10:18:54  dpg1
 56# Update omniidl front-end from omni3_develop.
 57#
 58# Revision 1.3.2.1  2000/08/29 15:20:29  dpg1
 59# New relativeScope() function. New -i flag to enter interactive loop
 60# after parsing
 61#
 62# Revision 1.3  1999/11/15 15:49:23  dpg1
 63# Documentation strings.
 64#
 65# Revision 1.2  1999/11/01 20:18:30  dpg1
 66# Added string escaping
 67#
 68# Revision 1.1  1999/10/29 15:47:07  dpg1
 69# First revision.
 70#
 71
 72"""Utility functions for IDL compilers
 73
 74escapifyString()  -- return a string with non-printing characters escaped.
 75escapifyWString() -- return a wstring with non-printing characters escaped.
 76reprFloat()       -- return a string represenation of an IDL float type.
 77slashName()       -- format a scoped name with '/' separating components.
 78dotName()         -- format a scoped name with '.' separating components.
 79ccolonName()      -- format a scoped name with '::' separating components.
 80pruneScope()      -- remove common prefix from a scoped name.
 81relativeScope()   -- give a minimal name for one scope relative to another."""
 82
 83import string
 84
 85def slashName(scopedName, our_scope=[]):
 86    """slashName(list, [list]) -> string
 87
 88Return a scoped name given as a list of strings as a single string
 89with the components separated by '/' characters. If a second list is
 90given, remove a common prefix using pruneScope()."""
 91
 92    pscope = pruneScope(scopedName, our_scope)
 93    return string.join(pscope, "/")
 94
 95def dotName(scopedName, our_scope=[]):
 96    """dotName(list, [list]) -> string
 97
 98Return a scoped name given as a list of strings as a single string
 99with the components separated by '.' characters. If a second list is
100given, remove a common prefix using pruneScope()."""
101
102    pscope = pruneScope(scopedName, our_scope)
103    return string.join(pscope, ".")
104
105def ccolonName(scopedName, our_scope=[]):
106    """ccolonName(list, [list]) -> string
107
108Return a scoped name given as a list of strings as a single string
109with the components separated by '::' strings. If a second list is
110given, remove a common prefix using pruneScope()."""
111
112    pscope = pruneScope(scopedName, our_scope)
113    return string.join(pscope, "::")
114
115def pruneScope(target_scope, our_scope):
116    """pruneScope(list A, list B) -> list
117
118Given two lists of strings (scoped names), return a copy of list A
119with any prefix it shares with B removed.
120
121  e.g. pruneScope(['A', 'B', 'C', 'D'], ['A', 'B', 'D']) -> ['C', 'D']"""
122
123    tscope = target_scope[:]
124    i = 0
125    while len(tscope) > 0 andi < len(our_scope) andtscope[0] == our_scope[i]:
126        del tscope[0]
127        i = i + 1
128    return tscope
129
130_valid_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"" 0123456789_!$%^&*()-=+[]{};#:@~,./<>?|`"
131
132_valid_unichars = map(ord, list(_valid_chars))
133
134def escapifyString(s):
135    """escapifyString(string) -> string
136
137Return the given string with any non-printing characters escaped."""
138
139    global _valid_chars
140    l = list(s)
141    for i in range(len(l)):
142        if l[i] not in _valid_chars:
143            l[i] = "\\%03o" % ord(l[i])
144    return string.join(l, "")
145
146
147def escapifyWString(l, escchar="u"):
148    """escapifyWString(int list) -> string
149
150Take a list of integers representing Unicode characters and return an
151ASCII string with all characters outside that range replaced with \\u
152escapes."""
153
154    global _valid_unichars
155    m = [None] * len(l)
156    for i in range(len(l)):
157        assert(l[i] <= 0xffff)
158        if l[i] in _valid_unichars:
159            m[i] = chr(l[i])
160        else:
161            m[i] = "\\%s%04x" % (escchar, l[i])
162    return string.join(m, "")
163
164
165def reprFloat(f):
166    """reprFloat(float) -> string
167
168Return the string representation of an IDL float type (float, double,
169long double), with enough precision to completely reconstruct the bit
170pattern."""
171    # *** Deal with long double
172
173    s = "%.17g" % f
174    if string.find(s, ".") == -1:
175        s = s + ".0"
176    return s
177
178
179def relativeScope(fromScope, destScope):
180    """relativeScope(fromScope, destScope) -> list
181
182Given two globally-scoped names, return a minimal scoped name list
183which identifies the destination scope, without clashing with another
184identifier. For example, given IDL:
185
186  module M {
187    typedef short A;
188    typedef long  B;
189
190    module N {
191      typedef string B;
192      interface I {
193        void op(in ::M::A x, in ::M::B y);
194      };
195    };
196  };
197
198relativeScope(["M", "N", "I"], ["M", "A"]) -> ["A"]
199relativeScope(["M", "N", "I"], ["M", "B"]) -> ["M", "B"]
200
201If the only valid result is a globally-scoped name, the result list is
202prefixed with None:
203
204  module O {
205    typedef short C;
206  };
207  module P {
208    module O {
209      interface J {
210        void op(in ::O::C z);
211      };
212    };
213  };
214
215relativeScope(["P", "O", "J"], ["O", "C"]) -> [None, "O", "C"]
216
217If either scoped name does not exist, returns None."""
218
219    import _omniidl
220    return _omniidl.relativeScopedName(fromScope, destScope)
221