Synopsis - Cross-Reference

File: /Synopsis/Parsers/IDL/idlrepoId.cc
  1// -*- c++ -*-
  2//                          Package   : omniidl
  3// idlrepoId.cc             Created on: 1999/10/11
  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//   Implementation of repoId management
 28
 29// $Id: idlrepoId.cc,v 1.9.2.4 2005/07/22 17:18:36 dgrisby Exp $
 30// $Log: idlrepoId.cc,v $
 31// Revision 1.9.2.4  2005/07/22 17:18:36  dgrisby
 32// Another merge from omni4_0_develop.
 33//
 34// Revision 1.9.2.3  2005/05/10 22:07:31  dgrisby
 35// Merge again.
 36//
 37// Revision 1.9.2.2  2005/01/06 23:11:14  dgrisby
 38// Big merge from omni4_0_develop.
 39//
 40// Revision 1.9.2.1  2003/03/23 21:01:45  dgrisby
 41// Start of omniORB 4.1.x development branch.
 42//
 43// Revision 1.5.2.6  2001/11/13 14:11:46  dpg1
 44// Tweaks for CORBA 2.5 compliance.
 45//
 46// Revision 1.5.2.5  2001/10/17 16:48:33  dpg1
 47// Minor error message tweaks
 48//
 49// Revision 1.5.2.4  2000/11/03 12:20:58  dpg1
 50// #pragma ID can now be declared more than once for a type, as long as
 51// the id is the same.
 52//
 53// Revision 1.5.2.3  2000/10/27 16:31:09  dpg1
 54// Clean up of omniidl dependencies and types, from omni3_develop.
 55//
 56// Revision 1.5.2.2  2000/10/10 10:18:51  dpg1
 57// Update omniidl front-end from omni3_develop.
 58//
 59// Revision 1.3.2.1  2000/08/29 10:20:27  dpg1
 60// Operations and attributes now have repository ids.
 61//
 62// Revision 1.3  1999/11/08 10:50:47  dpg1
 63// Change to behaviour when files end inside a scope.
 64//
 65// Revision 1.2  1999/11/02 17:07:25  dpg1
 66// Changes to compile on Solaris.
 67//
 68// Revision 1.1  1999/10/27 14:05:56  dpg1
 69// *** empty log message ***
 70//
 71
 72#include <idlrepoId.h>
 73#include <idlast.h>
 74#include <idlutil.h>
 75#include <idlerr.h>
 76#include <idlvisitor.h>
 77
 78#include <string.h>
 79#include <stdio.h>
 80#include <ctype.h>
 81
 82// Globals from lexer/parser
 83extern int   yylineno;
 84extern char* currentFile;
 85
 86Prefix* Prefix::current_ = 0;
 87
 88Prefix::
 89Prefix(char* str, IDL_Boolean isfile) :
 90  str_(str), parent_(current_), isfile_(isfile)
 91{
 92  current_ = this;
 93}
 94
 95Prefix::
 96~Prefix()
 97{
 98  current_ = parent_;
 99  delete [] str_;
100}
101
102const char*
103Prefix::
104current()
105{
106  return current_->get();
107}
108
109void
110Prefix::
111newScope(const char* name)
112{
113  if (name[0] == '_') ++name;
114  int len   = strlen(current()) + strlen(name) + 2;
115  char* str = new char[len];
116
117  strcpy(str, current());
118  if (str[0] != '\0') strcat(str, "/");
119  strcat(str, name);
120
121  new Prefix(str, 0);
122}
123
124void
125Prefix::
126newFile()
127{
128  char* str = new char[1];
129  str[0]    = '\0';
130  new Prefix(str, 1);
131}
132
133void
134Prefix::
135setPrefix(const char* prefix)
136{
137  current_->set(prefix);
138}
139
140void
141Prefix::
142endScope()
143{
144  if (current_->parent_)
145    delete current_;
146  else
147    IdlWarning(currentFile, yylineno,
148	       "Confused by pre-processor line directives");
149}
150
151void
152Prefix::
153endFile()
154{
155  if (!current_->isfile()) {
156    IdlWarning(currentFile, yylineno,
157	       "File ended inside a declaration. "
158	       "Repository identifiers may be incorrect");
159  }
160  if (current_->parent_)
161    delete current_;
162  else
163    IdlWarning(currentFile, yylineno,
164	       "Confused by pre-processor line directives");
165}
166
167void
168Prefix::
169endOuterFile()
170{
171  if (current_->parent_)
172    IdlWarning(currentFile, yylineno,
173	       "Confused by pre-processor line directives");
174  else
175    delete current_;
176}
177
178const char*
179Prefix::
180get()
181{
182  return str_;
183}
184
185void
186Prefix::
187set(const char* setTo)
188{
189  char* str;
190  delete [] str_;
191  if (setTo[0] == '\0') {
192    str    = new char[1];
193    str[0] = '\0';
194  }
195  else
196    str = idl_strdup(setTo);
197
198  str_ = str;
199}
200
201IDL_Boolean
202Prefix::
203isfile()
204{
205  return isfile_;
206}
207
208
209// Implementation of DeclRepoId
210
211DeclRepoId::
212DeclRepoId(const char* identifier)
213
214  : eidentifier_(idl_strdup(identifier)),
215    prefix_(idl_strdup(Prefix::current())),
216    set_(0), maj_(1), min_(0)
217{
218  if (identifier[0] == '_')
219    identifier_ = idl_strdup(++identifier);
220  else
221    identifier_ = eidentifier_;
222
223  const ScopedName* psn = Scope::current()->scopedName();
224  if (psn) {
225    scopedName_ = new ScopedName(psn);
226    scopedName_->append(identifier);
227  }
228  else
229    scopedName_ = new ScopedName(identifier, 1);
230
231  genRepoId();
232}
233
234DeclRepoId::
235~DeclRepoId()
236{
237  if (identifier_ != eidentifier_) delete [] identifier_;
238  delete [] eidentifier_;
239  delete [] repoId_;
240  delete [] prefix_;
241  if (set_) delete [] rifile_;
242}
243
244void
245DeclRepoId::
246setRepoId(const char* repoId, const char* file, int line)
247{
248  if (set_) {
249    if (strcmp(repoId, repoId_)) {
250      IdlError(file, line, "Cannot set repository id of '%s' to '%s'",
251	       identifier_, repoId);
252      IdlErrorCont(rifile_, riline_,
253		   "Repository id previously set to '%s' here", repoId_);
254    }
255  }
256  else {
257    delete [] repoId_;
258    repoId_ = idl_strdup(repoId);
259    set_    = 1;
260    rifile_ = idl_strdup(file);
261    riline_ = line;
262
263    for (; *repoId && *repoId != ':'; ++repoId);
264    if (*repoId == '\0') goto invalid;
265
266    // If the repoId set is in OMG IDL format, we must figure out the
267    // version number, so a future #pragma version can succeed if the
268    // same version is given. Evil spec.
269
270    if (!strncmp(repoId_, "IDL:", 4)) {
271      const char* c;
272      for (c=repoId_ + 4; *c && *c != ':'; ++c);
273      if (*c++ == '\0') goto invalid;
274
275      // c should now point to a string of the form maj.min
276      if (sscanf(c, "%hd.%hd", &maj_, &min_) != 2)
277	goto invalid;
278
279      // Check there's no trailing garbage
280      for (; *c && isdigit(*c); ++c);
281      if (*c++ != '.') goto invalid;
282      for (; *c && isdigit(*c); ++c);
283      if (*c != '\0') goto invalid;
284    }
285    else {
286      maj_ = -1; // Make sure a future #pragma version complains
287    }
288  }
289  return;
290
291 invalid:
292  IdlWarning(file, line,
293	     "Repository id of '%s' set to invalid string '%s'",
294	     identifier_, repoId_);
295  maj_ = -1;
296}
297
298void
299DeclRepoId::
300setVersion(IDL_Short maj, IDL_Short min, const char* file, int line)
301{
302  if (set_) {
303    if (maj_ != maj || min_ != min) {
304      IdlError(file, line, "Cannot set version of '%s' to '%d.%d'",
305	       identifier_, maj, min);
306      IdlErrorCont(rifile_, riline_,
307		   "Repository id previously set to '%s' here", repoId_);
308    }
309  }
310  else {
311    delete [] repoId_;
312    maj_    = maj;
313    min_    = min;
314    set_    = 1;
315    rifile_ = idl_strdup(file);
316    riline_ = line;
317    genRepoId();
318  }
319}
320
321void
322DeclRepoId::
323genRepoId()
324{
325  char* id;
326  int   len;
327
328  // RepoId length = IDL: + prefix + "/" + identifier + : + maj + . + min + \0
329  len = 4 + strlen(prefix_) + 1 + strlen(identifier_) + 1 + 5 + 1 + 5 + 1;
330
331  char* repoId = new char[len];
332
333  sprintf(repoId, "IDL:%s%s%s:%hd.%hd", prefix_,
334	  prefix_[0] == '\0' ? "" : "/", identifier_, maj_, min_);
335  repoId_ = repoId;
336}
337
338
339// Static set functions
340
341class SetRepoIdVisitor : public AstVisitor {
342public:
343
344  SetRepoIdVisitor(const char* repoId, const char* file, int line)
345    : r_(repoId), f_(file), l_(line) {}
346  virtual ~SetRepoIdVisitor() {}
347
348  void visitModule       (Module* d)       { d->setRepoId(r_, f_, l_); }
349  void visitInterface    (Interface* d)    { d->setRepoId(r_, f_, l_); }
350  void visitForward      (Forward* d)      { d->setRepoId(r_, f_, l_); }
351  void visitConst        (Const* d)        { d->setRepoId(r_, f_, l_); }
352  void visitDeclarator   (Declarator* d)   { d->setRepoId(r_, f_, l_); }
353  void visitStruct       (Struct* d)       { d->setRepoId(r_, f_, l_); }
354  void visitException    (Exception* d)    { d->setRepoId(r_, f_, l_); }
355  void visitUnion        (Union* d)        { d->setRepoId(r_, f_, l_); }
356  void visitEnum         (Enum* d)         { d->setRepoId(r_, f_, l_); }
357  void visitNative       (Native* d)       { d->setRepoId(r_, f_, l_); }
358  void visitValueForward (ValueForward* d) { d->setRepoId(r_, f_, l_); }
359  void visitValueBox     (ValueBox* d)     { d->setRepoId(r_, f_, l_); }
360  void visitValueAbs     (ValueAbs* d)     { d->setRepoId(r_, f_, l_); }
361  void visitValue        (Value* d)        { d->setRepoId(r_, f_, l_); }
362  void visitMember       (Member* d)       { error(d); }
363  void visitUnionCase    (UnionCase* d)    { error(d); }
364  void visitEnumerator   (Enumerator* d)   { error(d); }
365  void visitAttribute    (Attribute* d)    { error(d); }
366  void visitOperation    (Operation* d)    { d->setRepoId(r_, f_, l_); }
367  void visitStateMember  (StateMember* d)  { error(d); }
368  void visitFactory      (Factory* d)      { error(d); }
369
370private:
371  const char* r_;
372  const char* f_;
373  int         l_;
374  void error(Decl* d) {
375    IdlError(f_, l_, "Cannot set repository id of %s", d->kindAsString());
376  }
377};
378
379void
380DeclRepoId::
381setRepoId(Decl* d, const char* repoId, const char* file, int line)
382{
383  SetRepoIdVisitor v(repoId, file, line);
384  d->accept(v);
385}
386
387
388class SetVersionVisitor : public AstVisitor {
389public:
390
391  SetVersionVisitor(IDL_Short maj, IDL_Short min,
392		    const char* file, int line)
393    : a_(maj), i_(min), f_(file), l_(line) {}
394  virtual ~SetVersionVisitor() {}
395
396  void visitModule       (Module* d)       { d->setVersion(a_, i_, f_, l_); }
397  void visitInterface    (Interface* d)    { d->setVersion(a_, i_, f_, l_); }
398  void visitForward      (Forward* d)      { d->setVersion(a_, i_, f_, l_); }
399  void visitConst        (Const* d)        { d->setVersion(a_, i_, f_, l_); }
400  void visitDeclarator   (Declarator* d)   { d->setVersion(a_, i_, f_, l_); }
401  void visitStruct       (Struct* d)       { d->setVersion(a_, i_, f_, l_); }
402  void visitException    (Exception* d)    { d->setVersion(a_, i_, f_, l_); }
403  void visitUnion        (Union* d)        { d->setVersion(a_, i_, f_, l_); }
404  void visitEnum         (Enum* d)         { d->setVersion(a_, i_, f_, l_); }
405  void visitNative       (Native* d)       { d->setVersion(a_, i_, f_, l_); }
406  void visitValueForward (ValueForward* d) { d->setVersion(a_, i_, f_, l_); }
407  void visitValueBox     (ValueBox* d)     { d->setVersion(a_, i_, f_, l_); }
408  void visitValueAbs     (ValueAbs* d)     { d->setVersion(a_, i_, f_, l_); }
409  void visitValue        (Value* d)        { d->setVersion(a_, i_, f_, l_); }
410  void visitMember       (Member* d)       { error(d); }
411  void visitUnionCase    (UnionCase* d)    { error(d); }
412  void visitEnumerator   (Enumerator* d)   { error(d); }
413  void visitAttribute    (Attribute* d)    { error(d); }
414  void visitOperation    (Operation* d)    { d->setVersion(a_, i_, f_, l_); }
415  void visitStateMember  (StateMember* d)  { error(d); }
416  void visitFactory      (Factory* d)      { error(d); }
417
418private:
419  IDL_Short a_;
420  IDL_Short i_;
421  const char*  f_;
422  int          l_;
423  void error(Decl* d) {
424    IdlError(f_, l_, "Cannot set version of %s", d->kindAsString());
425  }
426};
427
428void
429DeclRepoId::
430setVersion(Decl* d, IDL_Short maj, IDL_Short min,
431	   const char* file, int line)
432{
433  SetVersionVisitor v(maj, min, file, line);
434  d->accept(v);
435}