Synopsis - Cross-Reference
File: /Synopsis/Parsers/IDL/idlrepoId.cc1// -*- 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}