| 1 | /////////////////////////////////////////////////////////////////////////////// |
| 2 | // Copyright (c) 2000-2014 Ericsson Telecom AB |
| 3 | // All rights reserved. This program and the accompanying materials |
| 4 | // are made available under the terms of the Eclipse Public License v1.0 |
| 5 | // which accompanies this distribution, and is available at |
| 6 | // http://www.eclipse.org/legal/epl-v10.html |
| 7 | /////////////////////////////////////////////////////////////////////////////// |
| 8 | #include "Valuestuff.hh" |
| 9 | #include "Identifier.hh" |
| 10 | #include "Value.hh" |
| 11 | #include "asn1/Object0.hh" |
| 12 | #include "asn1/Block.hh" |
| 13 | #include "asn1/TokenBuf.hh" |
| 14 | #include <limits.h> |
| 15 | |
| 16 | #include "ustring.hh" |
| 17 | |
| 18 | namespace Common { |
| 19 | |
| 20 | // ================================= |
| 21 | // ===== Values |
| 22 | // ================================= |
| 23 | |
| 24 | Values::Values(bool p_indexed) : Node(), indexed(p_indexed) |
| 25 | { |
| 26 | if (!p_indexed) vs = new vector<Value>(); |
| 27 | else ivs = new vector<IndexedValue>(); |
| 28 | } |
| 29 | |
| 30 | Values::~Values() |
| 31 | { |
| 32 | if (!indexed) { |
| 33 | for (size_t i = 0; i < vs->size(); i++) delete (*vs)[i]; |
| 34 | vs->clear(); |
| 35 | delete vs; |
| 36 | } else { |
| 37 | for (size_t i = 0; i < ivs->size(); i++) delete (*ivs)[i]; |
| 38 | ivs->clear(); |
| 39 | delete ivs; |
| 40 | } |
| 41 | } |
| 42 | |
| 43 | Values *Values::clone() const |
| 44 | { |
| 45 | FATAL_ERROR("Values::clone"); |
| 46 | } |
| 47 | |
| 48 | void Values::set_fullname(const string& p_fullname) |
| 49 | { |
| 50 | Node::set_fullname(p_fullname); |
| 51 | if (!indexed) { |
| 52 | for (size_t i = 0; i < vs->size(); i++) { |
| 53 | Value *v = (*vs)[i]; |
| 54 | if (v) v->set_fullname(p_fullname + "[" + Int2string(i) + "]"); |
| 55 | } |
| 56 | } else { |
| 57 | for (size_t i = 0; i < ivs->size(); i++) { |
| 58 | IndexedValue *iv = (*ivs)[i]; |
| 59 | // The order is defined by the user. The index used, doesn't really |
| 60 | // matter here. |
| 61 | if (iv) iv->set_fullname(p_fullname + "[" + Int2string(i) + "]"); |
| 62 | } |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | void Values::set_my_scope(Scope *p_scope) |
| 67 | { |
| 68 | if (!indexed) { |
| 69 | for (size_t i = 0; i < vs->size(); i++) { |
| 70 | Value *v = (*vs)[i]; |
| 71 | if (v) v->set_my_scope(p_scope); |
| 72 | } |
| 73 | } else { |
| 74 | for (size_t i = 0; i < ivs->size(); i++) { |
| 75 | IndexedValue *iv = (*ivs)[i]; |
| 76 | if (iv) iv->set_my_scope(p_scope); |
| 77 | } |
| 78 | } |
| 79 | } |
| 80 | |
| 81 | size_t Values::get_nof_vs() const |
| 82 | { |
| 83 | if (indexed) FATAL_ERROR("Values::get_nof_vs()"); |
| 84 | return vs->size(); |
| 85 | } |
| 86 | |
| 87 | size_t Values::get_nof_ivs() const |
| 88 | { |
| 89 | if (!indexed) FATAL_ERROR("Values::get_nof_ivs()"); |
| 90 | return ivs->size(); |
| 91 | } |
| 92 | |
| 93 | Value *Values::get_v_byIndex(size_t p_i) const |
| 94 | { |
| 95 | if (indexed) FATAL_ERROR("Values::get_v_byIndex"); |
| 96 | return (*vs)[p_i]; |
| 97 | } |
| 98 | |
| 99 | IndexedValue *Values::get_iv_byIndex(size_t p_i) const |
| 100 | { |
| 101 | if (!indexed) FATAL_ERROR("Values::get_iv_byIndex()"); |
| 102 | return (*ivs)[p_i]; |
| 103 | } |
| 104 | |
| 105 | void Values::add_v(Value *p_v) |
| 106 | { |
| 107 | if (!p_v) FATAL_ERROR("Values::add_v(): NULL parameter"); |
| 108 | if (indexed) FATAL_ERROR("Values::add_v()"); |
| 109 | vs->add(p_v); |
| 110 | } |
| 111 | |
| 112 | void Values::add_iv(IndexedValue *p_iv) |
| 113 | { |
| 114 | if (!p_iv) FATAL_ERROR("Values::add_iv(): NULL parameter"); |
| 115 | if (!indexed) FATAL_ERROR("Values::add_iv()"); |
| 116 | ivs->add(p_iv); |
| 117 | } |
| 118 | |
| 119 | Value *Values::steal_v_byIndex(size_t p_i) |
| 120 | { |
| 121 | if (indexed) FATAL_ERROR("Values::steal_v_byIndex()"); |
| 122 | Value *ret_val = (*vs)[p_i]; |
| 123 | if (!ret_val) FATAL_ERROR("Values::steal_v_byIndex()"); |
| 124 | (*vs)[p_i] = NULL; |
| 125 | return ret_val; |
| 126 | } |
| 127 | |
| 128 | void Values::dump(unsigned level) const |
| 129 | { |
| 130 | if (!indexed) { |
| 131 | for (size_t i = 0; i < vs->size(); i++) { |
| 132 | Value *v = (*vs)[i]; |
| 133 | if (v) v->dump(level); |
| 134 | else DEBUG(level, "Value: stolen"); |
| 135 | } |
| 136 | } else { |
| 137 | for (size_t i = 0; i < ivs->size(); i++) { |
| 138 | IndexedValue *iv = (*ivs)[i]; |
| 139 | if (iv) iv->dump(level); |
| 140 | else DEBUG(level, "Value: stolen"); |
| 141 | } |
| 142 | } |
| 143 | } |
| 144 | |
| 145 | // ================================= |
| 146 | // ===== IndexedValue |
| 147 | // ================================= |
| 148 | |
| 149 | IndexedValue::IndexedValue(Ttcn::FieldOrArrayRef *p_index, Value *p_value) |
| 150 | : Node(), Location(), index(p_index), value(p_value) |
| 151 | { |
| 152 | if (!p_index || !p_value) |
| 153 | FATAL_ERROR("NULL parameter: IndexedValue::IndexedValue()"); |
| 154 | } |
| 155 | |
| 156 | IndexedValue::~IndexedValue() |
| 157 | { |
| 158 | delete index; |
| 159 | delete value; |
| 160 | } |
| 161 | |
| 162 | IndexedValue *IndexedValue::clone() const |
| 163 | { |
| 164 | FATAL_ERROR("IndexedValue::clone"); |
| 165 | } |
| 166 | |
| 167 | void IndexedValue::set_fullname(const string& p_fullname) |
| 168 | { |
| 169 | Node::set_fullname(p_fullname); |
| 170 | if (value) value->set_fullname(p_fullname); |
| 171 | if (index) index->set_fullname(p_fullname); |
| 172 | } |
| 173 | |
| 174 | void IndexedValue::set_my_scope(Scope *p_scope) |
| 175 | { |
| 176 | if (value) value->set_my_scope(p_scope); |
| 177 | if (index) index->set_my_scope(p_scope); |
| 178 | } |
| 179 | |
| 180 | void IndexedValue::set_code_section |
| 181 | (GovernedSimple::code_section_t p_code_section) |
| 182 | { |
| 183 | // Follow the style and add ifs everywhere... |
| 184 | if (index) index->get_val()->set_code_section(p_code_section); |
| 185 | if (value) value->set_code_section(p_code_section); |
| 186 | } |
| 187 | |
| 188 | Value *IndexedValue::steal_value() |
| 189 | { |
| 190 | if (!value) FATAL_ERROR("IndexedValue::steal_value()"); |
| 191 | Value *tmp = value; |
| 192 | value = 0; |
| 193 | return tmp; |
| 194 | } |
| 195 | |
| 196 | void IndexedValue::dump(unsigned level) const |
| 197 | { |
| 198 | index->dump(level); |
| 199 | if (value) value->dump(level + 1); |
| 200 | else DEBUG(level + 1, "Value: stolen"); |
| 201 | } |
| 202 | |
| 203 | bool IndexedValue::is_unfoldable(ReferenceChain *refch, |
| 204 | Type::expected_value_t exp_val) |
| 205 | { |
| 206 | return (value->is_unfoldable(refch, exp_val) || |
| 207 | get_index()->is_unfoldable(refch, exp_val)); |
| 208 | } |
| 209 | |
| 210 | // ================================= |
| 211 | // ===== NamedValue |
| 212 | // ================================= |
| 213 | |
| 214 | NamedValue::NamedValue(Identifier *p_name, Value *p_value) |
| 215 | : Node(), Location(), name(p_name), value(p_value) |
| 216 | { |
| 217 | if (!p_name || !p_value) |
| 218 | FATAL_ERROR("NULL parameter: NamedValue::NamedValue()"); |
| 219 | } |
| 220 | |
| 221 | NamedValue::NamedValue(const NamedValue& p) |
| 222 | : Node(p), Location(p) |
| 223 | { |
| 224 | if (!p.value) FATAL_ERROR("NamedValue::NamedValue(): value is stolen"); |
| 225 | name = p.name->clone(); |
| 226 | value = p.value->clone(); |
| 227 | } |
| 228 | |
| 229 | NamedValue::~NamedValue() |
| 230 | { |
| 231 | delete name; |
| 232 | delete value; |
| 233 | } |
| 234 | |
| 235 | NamedValue *NamedValue::clone() const |
| 236 | { |
| 237 | return new NamedValue(*this); |
| 238 | } |
| 239 | |
| 240 | void NamedValue::set_fullname(const string& p_fullname) |
| 241 | { |
| 242 | Node::set_fullname(p_fullname); |
| 243 | if (value) value->set_fullname(p_fullname); |
| 244 | } |
| 245 | |
| 246 | void NamedValue::set_my_scope(Scope *p_scope) |
| 247 | { |
| 248 | if (value) value->set_my_scope(p_scope); |
| 249 | } |
| 250 | |
| 251 | Value *NamedValue::steal_value() |
| 252 | { |
| 253 | if (!value) FATAL_ERROR("NamedValue::steal_value()"); |
| 254 | Value *tmp = value; |
| 255 | value = 0; |
| 256 | return tmp; |
| 257 | } |
| 258 | |
| 259 | void NamedValue::dump(unsigned level) const |
| 260 | { |
| 261 | name->dump(level); |
| 262 | if (value) value->dump(level + 1); |
| 263 | else DEBUG(level + 1, "Value: stolen"); |
| 264 | } |
| 265 | |
| 266 | // ================================= |
| 267 | // ===== NamedValues |
| 268 | // ================================= |
| 269 | |
| 270 | NamedValues::NamedValues(const NamedValues& p) |
| 271 | : Node(p), checked(false) |
| 272 | { |
| 273 | for (size_t i = 0; i < p.nvs_v.size(); i++) |
| 274 | nvs_v.add(p.nvs_v[i]->clone()); |
| 275 | } |
| 276 | |
| 277 | NamedValues::~NamedValues() |
| 278 | { |
| 279 | for(size_t i = 0; i < nvs_v.size(); i++) delete nvs_v[i]; |
| 280 | nvs_v.clear(); |
| 281 | nvs_m.clear(); |
| 282 | } |
| 283 | |
| 284 | NamedValues *NamedValues::clone() const |
| 285 | { |
| 286 | return new NamedValues(*this); |
| 287 | } |
| 288 | |
| 289 | void NamedValues::set_fullname(const string& p_fullname) |
| 290 | { |
| 291 | Node::set_fullname(p_fullname); |
| 292 | for(size_t i = 0; i < nvs_v.size(); i++) { |
| 293 | NamedValue *nv = nvs_v[i]; |
| 294 | nv->set_fullname(p_fullname + "." + nv->get_name().get_dispname()); |
| 295 | } |
| 296 | } |
| 297 | |
| 298 | void NamedValues::set_my_scope(Scope *p_scope) |
| 299 | { |
| 300 | for (size_t i = 0; i < nvs_v.size(); i++) |
| 301 | nvs_v[i]->set_my_scope(p_scope); |
| 302 | } |
| 303 | |
| 304 | void NamedValues::add_nv(NamedValue *p_nv) |
| 305 | { |
| 306 | if (!p_nv) FATAL_ERROR("NamedValues::add_nv(): NULL parameter"); |
| 307 | nvs_v.add(p_nv); |
| 308 | if (checked) { |
| 309 | const string& name = p_nv->get_name().get_name(); |
| 310 | if (nvs_m.has_key(name)) FATAL_ERROR("NamedValues::add_nv()"); |
| 311 | nvs_m.add(name, p_nv); |
| 312 | } |
| 313 | } |
| 314 | |
| 315 | bool NamedValues::has_nv_withName(const Identifier& p_name) |
| 316 | { |
| 317 | if (!checked) chk_dupl_id(false); |
| 318 | return nvs_m.has_key(p_name.get_name()); |
| 319 | } |
| 320 | |
| 321 | NamedValue* NamedValues::get_nv_byName(const Identifier& p_name) |
| 322 | { |
| 323 | if (!checked) chk_dupl_id(false); |
| 324 | return nvs_m[p_name.get_name()]; |
| 325 | } |
| 326 | |
| 327 | void NamedValues::chk_dupl_id(bool report_errors) |
| 328 | { |
| 329 | if (checked) nvs_m.clear(); |
| 330 | for (size_t i = 0; i < nvs_v.size(); i++) { |
| 331 | NamedValue *nv = nvs_v[i]; |
| 332 | const Identifier& id = nv->get_name(); |
| 333 | const string& name = id.get_name(); |
| 334 | if (!nvs_m.has_key(name)) nvs_m.add(name, nv); |
| 335 | else if (report_errors) { |
| 336 | const char *dispname_str = id.get_dispname().c_str(); |
| 337 | nv->error("Duplicate identifier: `%s'", dispname_str); |
| 338 | nvs_m[name]->note("Previous definition of `%s' is here", dispname_str); |
| 339 | } |
| 340 | } |
| 341 | checked = true; |
| 342 | } |
| 343 | |
| 344 | void NamedValues::dump(unsigned level) const |
| 345 | { |
| 346 | for (size_t i = 0; i < nvs_v.size(); i++) |
| 347 | nvs_v[i]->dump(level); |
| 348 | } |
| 349 | |
| 350 | // ================================= |
| 351 | // ===== OID_comp |
| 352 | // ================================= |
| 353 | |
| 354 | const OID_comp::nameform_t OID_comp::names_root[] = { |
| 355 | { "itu__t", 0 }, |
| 356 | { "ccitt", 0 }, |
| 357 | { "itu__r", 0 }, |
| 358 | { "iso", 1 }, |
| 359 | { "joint__iso__itu__t", 2 }, |
| 360 | { "joint__iso__ccitt", 2 }, |
| 361 | { NULL, 0 } |
| 362 | }; |
| 363 | |
| 364 | const OID_comp::nameform_t OID_comp::names_itu[] = { |
| 365 | { "recommendation", 0 }, |
| 366 | { "question", 1 }, |
| 367 | { "administration", 2 }, |
| 368 | { "network__operator", 3 }, |
| 369 | { "identified__organization", 4 }, |
| 370 | { "r__recommendation", 5 }, |
| 371 | { NULL, 0 } |
| 372 | }; |
| 373 | |
| 374 | const OID_comp::nameform_t OID_comp::names_iso[] = { |
| 375 | { "standard", 0 }, |
| 376 | { "registration__authority", 1 }, |
| 377 | { "member__body", 2 }, |
| 378 | { "identified__organization", 3 }, |
| 379 | { NULL, 0 } |
| 380 | }; |
| 381 | |
| 382 | // taken from OID repository: http://asn1.elibel.tm.fr/oid/ |
| 383 | const OID_comp::nameform_t OID_comp::names_joint[] = { |
| 384 | { "presentation", 0 }, |
| 385 | { "asn1", 1 }, |
| 386 | { "association__control", 2 }, |
| 387 | { "reliable__transfer", 3 }, |
| 388 | { "remote__operations", 4 }, |
| 389 | { "ds", 5 }, |
| 390 | { "directory", 5 }, |
| 391 | { "mhs", 6 }, |
| 392 | { "mhs__motis", 6 }, |
| 393 | { "ccr", 7 }, |
| 394 | { "oda", 8 }, |
| 395 | { "ms", 9 }, |
| 396 | { "osi__management", 9 }, |
| 397 | { "transaction__processing", 10 }, |
| 398 | { "dor", 11 }, |
| 399 | { "distinguished__object__reference", 11 }, |
| 400 | { "reference__data__transfer", 12 }, |
| 401 | { "network__layer", 13 }, |
| 402 | { "network__layer__management", 13 }, |
| 403 | { "transport__layer", 14 }, |
| 404 | { "transport__layer__management", 14 }, |
| 405 | { "datalink__layer", 15 }, |
| 406 | { "datalink__layer__management", 15 }, |
| 407 | { "datalink__layer__management__information", 15 }, |
| 408 | { "country", 16 }, |
| 409 | { "registration__procedures", 17 }, |
| 410 | { "registration__procedure", 17 }, |
| 411 | { "physical__layer", 18 }, |
| 412 | { "physical__layer__management", 18 }, |
| 413 | { "mheg", 19 }, |
| 414 | { "genericULS", 20 }, |
| 415 | { "generic__upper__layers__security", 20 }, |
| 416 | { "guls", 20 }, |
| 417 | { "transport__layer__security__protocol", 21 }, |
| 418 | { "network__layer__security__protocol", 22 }, |
| 419 | { "international__organizations", 23 }, |
| 420 | { "internationalRA", 23 }, |
| 421 | { "sios", 24 }, |
| 422 | { "uuid", 25 }, |
| 423 | { "odp", 26 }, |
| 424 | { "upu", 40 }, |
| 425 | { NULL, 0 } |
| 426 | }; |
| 427 | |
| 428 | OID_comp::OID_comp(Identifier *p_name, Value *p_number) |
| 429 | : Node(), Location(), defdval(0), name(p_name), number(p_number), var(0) |
| 430 | { |
| 431 | if (p_name) { |
| 432 | if (p_number) formtype = NAMEANDNUMBERFORM; |
| 433 | else formtype = NAMEFORM; |
| 434 | } else { |
| 435 | if (p_number) formtype = NUMBERFORM; |
| 436 | else FATAL_ERROR("NULL parameter: Common::OID_comp::OID_comp()"); |
| 437 | } |
| 438 | } |
| 439 | |
| 440 | OID_comp::OID_comp(Value *p_defdval) |
| 441 | : Node(), Location(), formtype(DEFDVALUE), defdval(p_defdval), name(0), |
| 442 | number(0), var(0) |
| 443 | { |
| 444 | if(!p_defdval) |
| 445 | FATAL_ERROR("NULL parameter: Common::OID_comp::OID_comp()"); |
| 446 | } |
| 447 | |
| 448 | OID_comp::~OID_comp() |
| 449 | { |
| 450 | delete defdval; |
| 451 | delete name; |
| 452 | delete number; |
| 453 | delete var; |
| 454 | } |
| 455 | |
| 456 | OID_comp *OID_comp::clone() const |
| 457 | { |
| 458 | FATAL_ERROR("OID_comp::clone"); |
| 459 | } |
| 460 | |
| 461 | void OID_comp::chk_OID(ReferenceChain& refch, Value *parent, size_t index, |
| 462 | oidstate_t& state) |
| 463 | { |
| 464 | Error_Context ec(this, "In component #%lu of OBJECT IDENTIFIER value", |
| 465 | (unsigned long) (index + 1)); |
| 466 | switch (formtype) { |
| 467 | case NAMEFORM: { |
| 468 | Int v_Int = detect_nameform(state); |
| 469 | if (v_Int >= 0) { |
| 470 | // we have recognized the NameForm |
| 471 | number = new Value(Value::V_INT, v_Int); |
| 472 | number->set_fullname(get_fullname()); |
| 473 | number->set_my_scope(parent->get_my_scope()); |
| 474 | number->set_location(*this); |
| 475 | // the component is finished, jump out from switch |
| 476 | break; |
| 477 | } else { |
| 478 | // otherwise treat as a defined value and continue |
| 479 | Common::Reference *ref; |
| 480 | if (parent->is_asn1()) ref = new Asn::Ref_defd_simple(0, name); |
| 481 | else ref = new Ttcn::Reference(0, name); |
| 482 | name = 0; |
| 483 | defdval = new Value(Value::V_REFD, ref); |
| 484 | defdval->set_fullname(get_fullname()); |
| 485 | defdval->set_my_scope(parent->get_my_scope()); |
| 486 | defdval->set_location(*this); |
| 487 | formtype = DEFDVALUE; |
| 488 | } |
| 489 | } |
| 490 | // no break |
| 491 | case DEFDVALUE: |
| 492 | chk_defdvalue_OID(refch, state); |
| 493 | break; |
| 494 | case NUMBERFORM: |
| 495 | chk_numberform_OID(state); |
| 496 | break; |
| 497 | case NAMEANDNUMBERFORM: |
| 498 | chk_nameandnumberform(state); |
| 499 | break; |
| 500 | default: |
| 501 | FATAL_ERROR("OID_comp::chk_OID()"); |
| 502 | } // switch |
| 503 | } |
| 504 | |
| 505 | void OID_comp::chk_ROID(ReferenceChain& refch, size_t index) |
| 506 | { |
| 507 | Error_Context ec(this, "In component #%lu of RELATIVE-OID value", |
| 508 | (unsigned long) (index + 1)); |
| 509 | switch (formtype) { |
| 510 | case DEFDVALUE: |
| 511 | chk_defdvalue_ROID(refch); |
| 512 | break; |
| 513 | case NUMBERFORM: |
| 514 | case NAMEANDNUMBERFORM: |
| 515 | chk_numberform_ROID(); |
| 516 | break; |
| 517 | default: |
| 518 | FATAL_ERROR("OID_comp::chk_ROID()"); |
| 519 | } |
| 520 | } |
| 521 | |
| 522 | bool OID_comp::has_error() |
| 523 | { |
| 524 | if (formtype == DEFDVALUE) return defdval->has_oid_error(); |
| 525 | else return number->get_value_refd_last()->get_valuetype() != Value::V_INT; |
| 526 | } |
| 527 | |
| 528 | void OID_comp::get_comps(vector<string>& comps) |
| 529 | { |
| 530 | if (formtype == DEFDVALUE) defdval->get_oid_comps(comps); |
| 531 | else if (formtype == VARIABLE) { |
| 532 | comps.add(new string("OBJID::from_INTEGER(" + var->get_stringRepr() + ")")); |
| 533 | } |
| 534 | else comps.add(new string(number->get_stringRepr() + "u")); |
| 535 | } |
| 536 | |
| 537 | bool OID_comp::is_variable() |
| 538 | { |
| 539 | return (formtype == VARIABLE); |
| 540 | } |
| 541 | |
| 542 | Int OID_comp::detect_nameform(oidstate_t& state) |
| 543 | { |
| 544 | const string& name_str = name->get_name(); |
| 545 | Int ret_val = -1; |
| 546 | switch (state) { |
| 547 | case START: |
| 548 | if (name_str == "itu__t" || name_str == "ccitt") { |
| 549 | state = ITU; |
| 550 | ret_val = 0; |
| 551 | } else if (name_str == "itu__r") { |
| 552 | warning("Identifier `%s' should not be used as NameForm", |
| 553 | name->get_dispname().c_str()); |
| 554 | state = ITU; |
| 555 | ret_val = 0; |
| 556 | } else if (name_str == "iso") { |
| 557 | state = ISO; |
| 558 | ret_val = 1; |
| 559 | } else if (name_str == "joint__iso__itu__t" |
| 560 | || name_str == "joint__iso__ccitt") { |
| 561 | state = JOINT; |
| 562 | ret_val = 2; |
| 563 | } |
| 564 | break; |
| 565 | case ITU: |
| 566 | for (const nameform_t *nf = names_itu; nf->name != NULL; nf++) { |
| 567 | if (name_str == nf->name) { |
| 568 | ret_val = nf->value; |
| 569 | switch (nf->value) { |
| 570 | case 0: |
| 571 | state = ITU_REC; |
| 572 | break; |
| 573 | case 5: |
| 574 | warning("Identifier `%s' should not be used as NameForm", |
| 575 | name->get_dispname().c_str()); |
| 576 | // no break |
| 577 | default: |
| 578 | state = LATER; |
| 579 | } |
| 580 | break; |
| 581 | } |
| 582 | } |
| 583 | break; |
| 584 | case ISO: |
| 585 | for (const nameform_t *nf = names_iso; nf->name != NULL; nf++) { |
| 586 | if (name_str == nf->name) { |
| 587 | ret_val = nf->value; |
| 588 | state = LATER; |
| 589 | break; |
| 590 | } |
| 591 | } |
| 592 | break; |
| 593 | case JOINT: |
| 594 | for (const nameform_t *nf = names_joint; nf->name != NULL; nf++) { |
| 595 | if (name_str == nf->name) { |
| 596 | ret_val = nf->value; |
| 597 | state = LATER; |
| 598 | warning("Identifier `%s' should not be used as NameForm", |
| 599 | name->get_dispname().c_str()); |
| 600 | break; |
| 601 | } |
| 602 | } |
| 603 | break; |
| 604 | case ITU_REC: |
| 605 | if (name_str.size() == 1) { |
| 606 | char c = name_str[0]; |
| 607 | if (c >= 'a' && c <= 'z') { |
| 608 | ret_val = c - 'a' + 1; |
| 609 | state = LATER; |
| 610 | } |
| 611 | } |
| 612 | break; |
| 613 | default: |
| 614 | break; |
| 615 | } |
| 616 | return ret_val; |
| 617 | } |
| 618 | |
| 619 | void OID_comp::chk_defdvalue_OID(ReferenceChain& refch, oidstate_t& state) |
| 620 | { |
| 621 | Value *v = defdval->get_value_refd_last(); |
| 622 | switch (v->get_valuetype()) { |
| 623 | case Value::V_ERROR: |
| 624 | state = LATER; |
| 625 | break; |
| 626 | case Value::V_INT: |
| 627 | // if the component is a reference to an integer value |
| 628 | // it shall be set to number form |
| 629 | formtype = NUMBERFORM; |
| 630 | number = defdval; |
| 631 | defdval = 0; |
| 632 | chk_numberform_OID(state); |
| 633 | break; |
| 634 | case Value::V_OID: |
| 635 | if (state != START) defdval->error("INTEGER or RELATIVE-OID " |
| 636 | "value was expected"); |
| 637 | state = LATER; |
| 638 | v->chk_OID(refch); |
| 639 | break; |
| 640 | case Value::V_ROID: |
| 641 | switch (state) { |
| 642 | case ITU_REC: |
| 643 | state = LATER; |
| 644 | // no break |
| 645 | case LATER: |
| 646 | break; |
| 647 | default: |
| 648 | defdval->error("RELATIVE-OID value cannot be used as the " |
| 649 | "%s component of an OBJECT IDENTIFIER value", |
| 650 | state == START ? "first" : "second"); |
| 651 | state = LATER; |
| 652 | break; |
| 653 | } |
| 654 | break; |
| 655 | case Value::V_REFD: { |
| 656 | Common::Reference* ref = v->get_reference(); |
| 657 | Common::Assignment* as = ref->get_refd_assignment(); |
| 658 | Type* t = as->get_Type()->get_type_refd_last(); |
| 659 | if (t->get_typetype() == Type::T_INT) { |
| 660 | formtype = VARIABLE; |
| 661 | var = defdval; |
| 662 | defdval = 0; |
| 663 | } else { |
| 664 | defdval->error("INTEGER variable was expected"); |
| 665 | } |
| 666 | state = LATER; |
| 667 | break; } |
| 668 | default: |
| 669 | if (state == START) defdval->error("INTEGER or OBJECT IDENTIFIER " |
| 670 | "value was expected for the first component"); |
| 671 | else defdval->error("INTEGER or RELATIVE-OID value was expected"); |
| 672 | state = LATER; |
| 673 | break; |
| 674 | } |
| 675 | } |
| 676 | |
| 677 | void OID_comp::chk_numberform_OID(oidstate_t& state) |
| 678 | { |
| 679 | Value *v = number->get_value_refd_last(); |
| 680 | switch (v->get_valuetype()) { |
| 681 | case Value::V_INT: |
| 682 | // everything is OK, continue the checking |
| 683 | break; |
| 684 | case Value::V_ERROR: |
| 685 | state = LATER; |
| 686 | return; |
| 687 | default: |
| 688 | number->error("INTEGER value was expected in the number form"); |
| 689 | state = LATER; |
| 690 | return; |
| 691 | } |
| 692 | const int_val_t *v_Num = v->get_val_Int(); |
| 693 | if (v_Num->get_val() > (Int)UINT_MAX) { |
| 694 | number->error("An integer value less than `%u' was expected in the " |
| 695 | "number form instead of `%s'", UINT_MAX, (v_Num->t_str()).c_str()); |
| 696 | state = LATER; |
| 697 | return; |
| 698 | } |
| 699 | Int v_Int = v_Num->get_val(); |
| 700 | switch (state) { |
| 701 | case START: |
| 702 | switch (v_Int) { |
| 703 | case 0: |
| 704 | state = ITU; |
| 705 | break; |
| 706 | case 1: |
| 707 | state = ISO; |
| 708 | break; |
| 709 | case 2: |
| 710 | state = JOINT; |
| 711 | break; |
| 712 | default: |
| 713 | number->error("The value of first OBJECT IDENTIFIER component must " |
| 714 | "be between 0 and 2 instead of %s", Int2string(v_Int).c_str()); |
| 715 | state = LATER; |
| 716 | break; |
| 717 | } |
| 718 | break; |
| 719 | case ITU: |
| 720 | case ISO: |
| 721 | if (v_Int < 0 || v_Int > 39) number->error("The value of " |
| 722 | "second OBJECT IDENTIFIER component must be between 0 and 39 " |
| 723 | "instead of %s", Int2string(v_Int).c_str()); |
| 724 | if (state == ITU && v_Int == 0) state = ITU_REC; |
| 725 | else state = LATER; |
| 726 | break; |
| 727 | case JOINT: |
| 728 | default: |
| 729 | if (v_Int < 0) number->error("A non-negative integer value was " |
| 730 | "expected instead of %s", Int2string(v_Int).c_str()); |
| 731 | state = LATER; |
| 732 | break; |
| 733 | } |
| 734 | } |
| 735 | |
| 736 | void OID_comp::chk_nameandnumberform(oidstate_t& state) |
| 737 | { |
| 738 | // make a backup of state |
| 739 | oidstate_t oldstate = state; |
| 740 | chk_numberform_OID(state); |
| 741 | Value *v = number->get_value_refd_last(); |
| 742 | if (v->get_valuetype() != Value::V_INT || !v->get_val_Int()->is_native()) |
| 743 | return; |
| 744 | Int v_Int = v->get_val_Int()->get_val(); |
| 745 | const string& name_str = name->get_name(); |
| 746 | switch (oldstate) { |
| 747 | case START: |
| 748 | if (!is_valid_name_for_number(name_str, v_Int, names_root)) { |
| 749 | number->warning("Identifier %s was expected instead of `%s' for " |
| 750 | "number %s in the NameAndNumberForm as the first OBJECT IDENTIFIER " |
| 751 | "component", get_expected_name_for_number(v_Int, number->is_asn1(), |
| 752 | names_root).c_str(), name->get_dispname().c_str(), |
| 753 | Int2string(v_Int).c_str()); |
| 754 | } |
| 755 | break; |
| 756 | case ITU: |
| 757 | if (!is_valid_name_for_number(name_str, v_Int, names_itu)) { |
| 758 | number->warning("Identifier %s was expected instead of `%s' for " |
| 759 | "number %s in the NameAndNumberForm as the second OBJECT IDENTIFIER " |
| 760 | "component", get_expected_name_for_number(v_Int, number->is_asn1(), |
| 761 | names_itu).c_str(), name->get_dispname().c_str(), |
| 762 | Int2string(v_Int).c_str()); |
| 763 | } |
| 764 | break; |
| 765 | case ISO: |
| 766 | if (!is_valid_name_for_number(name_str, v_Int, names_iso)) { |
| 767 | number->warning("Identifier %s was expected instead of `%s' for " |
| 768 | "number %s in the NameAndNumberForm as the second OBJECT IDENTIFIER " |
| 769 | "component", get_expected_name_for_number(v_Int, number->is_asn1(), |
| 770 | names_iso).c_str(), name->get_dispname().c_str(), |
| 771 | Int2string(v_Int).c_str()); |
| 772 | } |
| 773 | break; |
| 774 | case JOINT: |
| 775 | if (!is_valid_name_for_number(name_str, v_Int, names_joint)) { |
| 776 | number->warning("Identifier %s was expected instead of `%s' for " |
| 777 | "number %s in the NameAndNumberForm as the second OBJECT IDENTIFIER " |
| 778 | "component", get_expected_name_for_number(v_Int, number->is_asn1(), |
| 779 | names_joint).c_str(), name->get_dispname().c_str(), |
| 780 | Int2string(v_Int).c_str()); |
| 781 | } |
| 782 | break; |
| 783 | case ITU_REC: |
| 784 | if (v_Int >= 1 && v_Int <= 26 && |
| 785 | (name_str.size() != 1 || name_str[0] != 'a' + v_Int - 1)) |
| 786 | number->warning("Identifier `%c' was expected instead of `%s' for " |
| 787 | "number %s in the NameAndNumberForm as the third OBJECT IDENTIFIER " |
| 788 | "component", (char)('a' + v_Int - 1), name->get_dispname().c_str(), |
| 789 | Int2string(v_Int).c_str()); |
| 790 | break; |
| 791 | default: |
| 792 | // no warning can be displayed in later states |
| 793 | break; |
| 794 | } |
| 795 | } |
| 796 | |
| 797 | bool OID_comp::is_valid_name_for_number(const string& p_name, |
| 798 | const Int& p_number, const nameform_t *p_names) |
| 799 | { |
| 800 | bool ret_val = true; |
| 801 | for (const nameform_t *nf = p_names; nf->name != NULL; nf++) { |
| 802 | if ((unsigned int)p_number == nf->value) { |
| 803 | if (p_name == nf->name) return true; |
| 804 | else ret_val = false; |
| 805 | } |
| 806 | } |
| 807 | return ret_val; |
| 808 | } |
| 809 | |
| 810 | string OID_comp::get_expected_name_for_number(const Int& p_number, |
| 811 | bool p_asn1, const nameform_t *p_names) |
| 812 | { |
| 813 | size_t nof_expected_names = 0; |
| 814 | for (const nameform_t *nf = p_names; nf->name != NULL; nf++) { |
| 815 | if ((unsigned int)p_number == nf->value) nof_expected_names++; |
| 816 | } |
| 817 | if (nof_expected_names <= 0) |
| 818 | FATAL_ERROR("OID_comp::get_expected_name_for_number()"); |
| 819 | string ret_val; |
| 820 | size_t i = 0; |
| 821 | for (const nameform_t *nf = p_names; nf->name != NULL; nf++) { |
| 822 | if ((unsigned int)p_number == nf->value) { |
| 823 | if (i > 0) { |
| 824 | if (i < nof_expected_names - 1) ret_val += ", "; |
| 825 | else ret_val += " or "; |
| 826 | } |
| 827 | ret_val += "`"; |
| 828 | Identifier id(Identifier::ID_NAME, string(nf->name)); |
| 829 | if (p_asn1) ret_val += id.get_asnname(); |
| 830 | else ret_val += id.get_ttcnname(); |
| 831 | ret_val += "'"; |
| 832 | i++; |
| 833 | } |
| 834 | } |
| 835 | return ret_val; |
| 836 | } |
| 837 | |
| 838 | void OID_comp::chk_defdvalue_ROID(ReferenceChain& refch) |
| 839 | { |
| 840 | Value *v = defdval->get_value_refd_last(); |
| 841 | switch (v->get_valuetype()) { |
| 842 | case Value::V_ERROR: |
| 843 | break; |
| 844 | case Value::V_INT: |
| 845 | // if the component is a reference to an integer value |
| 846 | // it shall be set to number form |
| 847 | formtype = NUMBERFORM; |
| 848 | number = defdval; |
| 849 | defdval = 0; |
| 850 | chk_numberform_ROID(); |
| 851 | break; |
| 852 | case Value::V_ROID: |
| 853 | v->chk_ROID(refch); |
| 854 | break; |
| 855 | default: |
| 856 | defdval->error("INTEGER or RELATIVE-OID value was expected"); |
| 857 | break; |
| 858 | } |
| 859 | } |
| 860 | |
| 861 | void OID_comp::chk_numberform_ROID() |
| 862 | { |
| 863 | Value *v = number->get_value_refd_last(); |
| 864 | switch (v->get_valuetype()) { |
| 865 | case Value::V_INT: { |
| 866 | const int_val_t *v_Num = v->get_val_Int(); |
| 867 | if (*v_Num > INT_MAX) { |
| 868 | number->error("An integer value less than `%d' was expected instead " |
| 869 | "of `%s'", INT_MAX, (v_Num->t_str()).c_str()); |
| 870 | return; |
| 871 | } |
| 872 | Int v_Int = v_Num->get_val(); |
| 873 | if (v_Int < 0) |
| 874 | number->error("A non-negative integer value was expected instead " |
| 875 | "of %s", Int2string(v_Int).c_str()); |
| 876 | break; } |
| 877 | case Value::V_ERROR: |
| 878 | break; |
| 879 | default: |
| 880 | number->error("INTEGER value was expected in the number form"); |
| 881 | break; |
| 882 | } |
| 883 | } |
| 884 | |
| 885 | void OID_comp::set_fullname(const string& p_fullname) |
| 886 | { |
| 887 | Node::set_fullname(p_fullname); |
| 888 | if (defdval) defdval->set_fullname(p_fullname); |
| 889 | if (number) number->set_fullname(p_fullname); |
| 890 | if (var) var->set_fullname(p_fullname); |
| 891 | } |
| 892 | |
| 893 | void OID_comp::set_my_scope(Scope *p_scope) |
| 894 | { |
| 895 | if(defdval) defdval->set_my_scope(p_scope); |
| 896 | if(number) number->set_my_scope(p_scope); |
| 897 | if(var) var->set_my_scope(p_scope); |
| 898 | } |
| 899 | |
| 900 | void OID_comp::append_stringRepr(string& str) const |
| 901 | { |
| 902 | switch (formtype) { |
| 903 | case NAMEFORM: |
| 904 | str += name->get_dispname(); |
| 905 | break; |
| 906 | case NUMBERFORM: |
| 907 | case NAMEANDNUMBERFORM: |
| 908 | str += number->get_stringRepr(); |
| 909 | break; |
| 910 | case DEFDVALUE: |
| 911 | str += defdval->get_stringRepr(); |
| 912 | break; |
| 913 | case VARIABLE: |
| 914 | str += var->get_stringRepr(); |
| 915 | break; |
| 916 | default: |
| 917 | str += "<unknown OID component>"; |
| 918 | break; |
| 919 | } |
| 920 | } |
| 921 | |
| 922 | // ================================= |
| 923 | // ===== CharsDefn |
| 924 | // ================================= |
| 925 | |
| 926 | CharsDefn::CharsDefn(string *p_str) |
| 927 | : Node(), Location(), selector(CD_CSTRING), checked(false) |
| 928 | { |
| 929 | if(!p_str) FATAL_ERROR("CharsDefn::CharsDefn()"); |
| 930 | u.str=p_str; |
| 931 | } |
| 932 | |
| 933 | CharsDefn::CharsDefn(Value *p_val) |
| 934 | : Node(), Location(), selector(CD_VALUE), checked(false) |
| 935 | { |
| 936 | if(!p_val) FATAL_ERROR("CharsDefn::CharsDefn()"); |
| 937 | u.val=p_val; |
| 938 | } |
| 939 | |
| 940 | CharsDefn::CharsDefn(Int p_g, Int p_p, Int p_r, Int p_c) |
| 941 | : Node(), Location(), selector(CD_QUADRUPLE), checked(false) |
| 942 | { |
| 943 | u.quadruple.g=p_g; |
| 944 | u.quadruple.p=p_p; |
| 945 | u.quadruple.r=p_r; |
| 946 | u.quadruple.c=p_c; |
| 947 | } |
| 948 | |
| 949 | CharsDefn::CharsDefn(Int p_c, Int p_r) |
| 950 | : Node(), Location(), selector(CD_TUPLE), checked(false) |
| 951 | { |
| 952 | u.tuple.c=p_c; |
| 953 | u.tuple.r=p_r; |
| 954 | } |
| 955 | |
| 956 | CharsDefn::CharsDefn(Block *p_block) |
| 957 | : Node(), Location(), selector(CD_BLOCK), checked(false) |
| 958 | { |
| 959 | if(!p_block) FATAL_ERROR("CharsDefn::CharsDefn()"); |
| 960 | u.block=p_block; |
| 961 | } |
| 962 | |
| 963 | CharsDefn::~CharsDefn() |
| 964 | { |
| 965 | switch(selector) { |
| 966 | case CD_CSTRING: |
| 967 | delete u.str; |
| 968 | break; |
| 969 | case CD_VALUE: |
| 970 | delete u.val; |
| 971 | break; |
| 972 | case CD_BLOCK: |
| 973 | delete u.block; |
| 974 | break; |
| 975 | default: |
| 976 | break; |
| 977 | } // switch |
| 978 | } |
| 979 | |
| 980 | CharsDefn *CharsDefn::clone() const |
| 981 | { |
| 982 | FATAL_ERROR("CharsDefn::clone"); |
| 983 | } |
| 984 | |
| 985 | void CharsDefn::set_fullname(const string& p_fullname) |
| 986 | { |
| 987 | Node::set_fullname(p_fullname); |
| 988 | switch (selector) { |
| 989 | case CD_VALUE: |
| 990 | u.val->set_fullname(p_fullname); |
| 991 | break; |
| 992 | case CD_BLOCK: |
| 993 | u.block->set_fullname(p_fullname); |
| 994 | break; |
| 995 | default: |
| 996 | break; |
| 997 | } |
| 998 | } |
| 999 | |
| 1000 | void CharsDefn::set_my_scope(Scope *p_scope) |
| 1001 | { |
| 1002 | if(selector==CD_VALUE) |
| 1003 | u.val->set_my_scope(p_scope); |
| 1004 | } |
| 1005 | |
| 1006 | void CharsDefn::parse_block() |
| 1007 | { |
| 1008 | if(selector!=CD_BLOCK) return; |
| 1009 | Block *t_block=u.block; |
| 1010 | Node *node=t_block->parse(KW_Block_QuadrupleOrTuple); |
| 1011 | CharsDefn *cd=dynamic_cast<CharsDefn*>(node); |
| 1012 | if(!cd) cd=new CharsDefn(0, 0, 0, 0); |
| 1013 | delete t_block; |
| 1014 | if(cd->selector==CD_QUADRUPLE) { |
| 1015 | u.quadruple=cd->u.quadruple; |
| 1016 | selector=CD_QUADRUPLE; |
| 1017 | } |
| 1018 | else { |
| 1019 | u.tuple=cd->u.tuple; |
| 1020 | selector=CD_TUPLE; |
| 1021 | } |
| 1022 | delete cd; |
| 1023 | } |
| 1024 | |
| 1025 | void CharsDefn::chk() |
| 1026 | { |
| 1027 | if(checked) return; |
| 1028 | checked=true; |
| 1029 | if(selector==CD_BLOCK) parse_block(); |
| 1030 | switch(selector) { |
| 1031 | case CD_QUADRUPLE: |
| 1032 | if(u.quadruple.g>127) { |
| 1033 | error("In quadruple: Group value must be in range 0..127"); |
| 1034 | u.quadruple.g=0; |
| 1035 | } |
| 1036 | if(u.quadruple.p>255) { |
| 1037 | error("In quadruple: Plane value must be in range 0..255"); |
| 1038 | u.quadruple.p=0; |
| 1039 | } |
| 1040 | if(u.quadruple.r>255) { |
| 1041 | error("In quadruple: Row value must be in range 0..255"); |
| 1042 | u.quadruple.r=0; |
| 1043 | } |
| 1044 | if(u.quadruple.c>255) { |
| 1045 | error("In quadruple: Cell value must be in range 0..255"); |
| 1046 | u.quadruple.c=0; |
| 1047 | } |
| 1048 | break; |
| 1049 | case CD_TUPLE: |
| 1050 | if(u.tuple.c>7) { |
| 1051 | error("In tuple: Column value must be in range 0..7"); |
| 1052 | u.tuple.c=0; |
| 1053 | } |
| 1054 | if(u.tuple.r>15) { |
| 1055 | error("In tuple: Row value must be in range 0..15"); |
| 1056 | u.tuple.r=0; |
| 1057 | } |
| 1058 | break; |
| 1059 | default: |
| 1060 | break; |
| 1061 | } // switch |
| 1062 | } |
| 1063 | |
| 1064 | string CharsDefn::get_string(ReferenceChain *refch) |
| 1065 | { |
| 1066 | chk(); |
| 1067 | switch(selector) { |
| 1068 | case CD_CSTRING: |
| 1069 | return *u.str; |
| 1070 | case CD_QUADRUPLE: |
| 1071 | error("Quadruple form is not allowed here."); |
| 1072 | return string("\0"); |
| 1073 | case CD_TUPLE:{ |
| 1074 | error("Tuple form is not allowed here."); |
| 1075 | char c=u.tuple.c*16+u.tuple.r; |
| 1076 | return string(1, &c); } |
| 1077 | case CD_VALUE: |
| 1078 | switch(u.val->get_value_refd_last(refch)->get_valuetype()) { |
| 1079 | case Value::V_ERROR: |
| 1080 | return string(); |
| 1081 | case Value::V_CHARSYMS: |
| 1082 | case Value::V_CSTR: |
| 1083 | return u.val->get_val_str(); |
| 1084 | case Value::V_ISO2022STR: |
| 1085 | error("Reference to string value was expected" |
| 1086 | " (instead of ISO-2022 string)."); |
| 1087 | return string(); |
| 1088 | case Value::V_USTR: |
| 1089 | error("Reference to string value was expected" |
| 1090 | " (instead of ISO-10646 string)."); |
| 1091 | return string(); |
| 1092 | default: |
| 1093 | error("Reference to character string value was expected."); |
| 1094 | return string(); |
| 1095 | } // switch valuetype |
| 1096 | break; |
| 1097 | default: |
| 1098 | FATAL_ERROR("CharsDefn::get_string()"); |
| 1099 | // to eliminate warning |
| 1100 | return string(); |
| 1101 | } |
| 1102 | } |
| 1103 | |
| 1104 | ustring CharsDefn::get_ustring(ReferenceChain *refch) |
| 1105 | { |
| 1106 | chk(); |
| 1107 | switch(selector) { |
| 1108 | case CD_CSTRING: |
| 1109 | return ustring(*u.str); |
| 1110 | break; |
| 1111 | case CD_QUADRUPLE: |
| 1112 | return ustring(u.quadruple.g, u.quadruple.p, |
| 1113 | u.quadruple.r, u.quadruple.c); |
| 1114 | break; |
| 1115 | case CD_TUPLE: |
| 1116 | error("Tuple form is not allowed here."); |
| 1117 | return ustring(0, 0, 0, u.tuple.c*16+u.tuple.r); |
| 1118 | break; |
| 1119 | case CD_VALUE: |
| 1120 | switch(u.val->get_value_refd_last(refch)->get_valuetype()) { |
| 1121 | case Value::V_ERROR: |
| 1122 | return ustring(); |
| 1123 | case Value::V_CSTR: |
| 1124 | case Value::V_USTR: |
| 1125 | case Value::V_CHARSYMS: |
| 1126 | return u.val->get_val_ustr(); |
| 1127 | case Value::V_ISO2022STR: |
| 1128 | error("Reference to ISO-10646 string value was expected" |
| 1129 | " (instead of ISO-2022 string)."); |
| 1130 | return ustring(); |
| 1131 | default: |
| 1132 | error("Reference to string value was expected."); |
| 1133 | return ustring(); |
| 1134 | } // switch valuetype |
| 1135 | break; |
| 1136 | default: |
| 1137 | FATAL_ERROR("CharsDefn::get_ustring()"); |
| 1138 | // to eliminate warning |
| 1139 | return ustring(); |
| 1140 | } |
| 1141 | } |
| 1142 | |
| 1143 | string CharsDefn::get_iso2022string(ReferenceChain *refch) |
| 1144 | { |
| 1145 | chk(); |
| 1146 | switch(selector) { |
| 1147 | case CD_CSTRING: |
| 1148 | return *u.str; |
| 1149 | case CD_QUADRUPLE: |
| 1150 | error("Quadruple form is not allowed here"); |
| 1151 | return string("\0"); |
| 1152 | case CD_TUPLE:{ |
| 1153 | char c=u.tuple.c*16+u.tuple.r; |
| 1154 | return string(1, &c); } |
| 1155 | case CD_VALUE: |
| 1156 | switch(u.val->get_value_refd_last(refch)->get_valuetype()) { |
| 1157 | case Value::V_ERROR: |
| 1158 | return string(); |
| 1159 | case Value::V_CSTR: |
| 1160 | case Value::V_ISO2022STR: |
| 1161 | case Value::V_CHARSYMS: |
| 1162 | return u.val->get_val_iso2022str(); |
| 1163 | case Value::V_USTR: |
| 1164 | error("Reference to ISO-2022 string value was expected" |
| 1165 | " (instead of ISO-10646 string)."); |
| 1166 | return string(); |
| 1167 | default: |
| 1168 | error("Reference to string value was expected."); |
| 1169 | return string(); |
| 1170 | } // switch valuetype |
| 1171 | break; |
| 1172 | default: |
| 1173 | FATAL_ERROR("CharsDefn::get_iso2022string()"); |
| 1174 | // to eliminate warning |
| 1175 | return string(); |
| 1176 | } |
| 1177 | } |
| 1178 | |
| 1179 | size_t CharsDefn::get_len(ReferenceChain *refch) |
| 1180 | { |
| 1181 | chk(); |
| 1182 | switch(selector) { |
| 1183 | case CD_CSTRING: |
| 1184 | return u.str->size(); |
| 1185 | case CD_QUADRUPLE: |
| 1186 | case CD_TUPLE: |
| 1187 | return 1; |
| 1188 | case CD_VALUE: |
| 1189 | switch(u.val->get_value_refd_last(refch)->get_valuetype()) { |
| 1190 | case Value::V_ERROR: |
| 1191 | return 0; |
| 1192 | case Value::V_CSTR: |
| 1193 | case Value::V_USTR: |
| 1194 | case Value::V_ISO2022STR: |
| 1195 | case Value::V_CHARSYMS: |
| 1196 | return u.val->get_val_strlen(); |
| 1197 | default: |
| 1198 | error("Reference to string value was expected."); |
| 1199 | return 0; |
| 1200 | } // switch valuetype |
| 1201 | break; |
| 1202 | default: |
| 1203 | FATAL_ERROR("CharsDefn::get_LEN()"); |
| 1204 | // to eliminate warning |
| 1205 | return 0; |
| 1206 | } |
| 1207 | } |
| 1208 | |
| 1209 | void CharsDefn::dump(unsigned level) const |
| 1210 | { |
| 1211 | switch (selector) { |
| 1212 | case CD_CSTRING: |
| 1213 | DEBUG(level, "\"%s\"", u.str->c_str()); |
| 1214 | break; |
| 1215 | case CD_QUADRUPLE: |
| 1216 | DEBUG(level, "{%s, %s, %s, %s}", |
| 1217 | Int2string(u.quadruple.g).c_str(), |
| 1218 | Int2string(u.quadruple.p).c_str(), |
| 1219 | Int2string(u.quadruple.r).c_str(), |
| 1220 | Int2string(u.quadruple.c).c_str()); |
| 1221 | break; |
| 1222 | case CD_TUPLE: |
| 1223 | DEBUG(level, "{%s, %s}", Int2string(u.tuple.c).c_str(), |
| 1224 | Int2string(u.tuple.r).c_str()); |
| 1225 | break; |
| 1226 | case CD_VALUE: |
| 1227 | u.val->dump(level); |
| 1228 | break; |
| 1229 | case CD_BLOCK: |
| 1230 | u.block->dump(level); |
| 1231 | break; |
| 1232 | default: |
| 1233 | break; |
| 1234 | } |
| 1235 | } |
| 1236 | |
| 1237 | // ================================= |
| 1238 | // ===== CharSyms |
| 1239 | // ================================= |
| 1240 | |
| 1241 | CharSyms::CharSyms() : Node(), Location(), selector(CS_UNDEF) |
| 1242 | { |
| 1243 | } |
| 1244 | |
| 1245 | CharSyms::~CharSyms() |
| 1246 | { |
| 1247 | for(size_t i=0; i<cds.size(); i++) delete cds[i]; |
| 1248 | cds.clear(); |
| 1249 | switch(selector) { |
| 1250 | case CS_UNDEF: |
| 1251 | break; |
| 1252 | case CS_CSTRING: |
| 1253 | case CS_ISO2022STRING: |
| 1254 | delete u.str; |
| 1255 | break; |
| 1256 | case CS_USTRING: |
| 1257 | delete u.ustr; |
| 1258 | break; |
| 1259 | default: |
| 1260 | FATAL_ERROR("CharSyms::~CharSyms()"); |
| 1261 | } // switch |
| 1262 | } |
| 1263 | |
| 1264 | CharSyms *CharSyms::clone() const |
| 1265 | { |
| 1266 | FATAL_ERROR("CharSyms::clone"); |
| 1267 | } |
| 1268 | |
| 1269 | void CharSyms::set_fullname(const string& p_fullname) |
| 1270 | { |
| 1271 | Node::set_fullname(p_fullname); |
| 1272 | for (size_t i = 0; i < cds.size(); i++) |
| 1273 | cds[i]->set_fullname(p_fullname + "." + Int2string(i)); |
| 1274 | } |
| 1275 | |
| 1276 | void CharSyms::set_my_scope(Scope *p_scope) |
| 1277 | { |
| 1278 | for(size_t i=0; i<cds.size(); i++) |
| 1279 | cds[i]->set_my_scope(p_scope); |
| 1280 | } |
| 1281 | |
| 1282 | void CharSyms::add_cd(CharsDefn *p_cd) |
| 1283 | { |
| 1284 | if(!p_cd) return; |
| 1285 | cds.add(p_cd); |
| 1286 | } |
| 1287 | |
| 1288 | string CharSyms::get_string(ReferenceChain *refch) |
| 1289 | { |
| 1290 | switch(selector) { |
| 1291 | case CS_UNDEF:{ |
| 1292 | bool destroy_refch=refch==0; |
| 1293 | if(refch) refch->mark_state(); |
| 1294 | else refch=new ReferenceChain(this, "While checking" |
| 1295 | " charstring value"); |
| 1296 | u.str=new string(); |
| 1297 | selector=CS_CHECKING; |
| 1298 | if(refch->add(get_fullname())) |
| 1299 | for(size_t i=0; i<cds.size(); i++) |
| 1300 | *u.str+=cds[i]->get_string(refch); |
| 1301 | if(destroy_refch) delete refch; |
| 1302 | else refch->prev_state(); |
| 1303 | selector=CS_CSTRING; |
| 1304 | } |
| 1305 | // no break |
| 1306 | case CS_CSTRING: |
| 1307 | return *u.str; |
| 1308 | case CS_USTRING: |
| 1309 | error("ISO-10646 charstring cannot be used in charstring context"); |
| 1310 | return string(); |
| 1311 | case CS_ISO2022STRING: |
| 1312 | error("ISO-2022 charstring cannot be used in charstring context"); |
| 1313 | return string(); |
| 1314 | case CS_CHECKING: |
| 1315 | error("Circular reference in `%s'", get_fullname().c_str()); |
| 1316 | return string(); |
| 1317 | default: |
| 1318 | FATAL_ERROR("CharSyms::get_string()"); |
| 1319 | return string(); |
| 1320 | } // switch |
| 1321 | } |
| 1322 | |
| 1323 | ustring CharSyms::get_ustring(ReferenceChain *refch) |
| 1324 | { |
| 1325 | switch(selector) { |
| 1326 | case CS_UNDEF:{ |
| 1327 | bool destroy_refch=refch==0; |
| 1328 | if(refch) refch->mark_state(); |
| 1329 | else refch=new ReferenceChain(this, "While checking" |
| 1330 | " charstring value"); |
| 1331 | u.ustr=new ustring(); |
| 1332 | selector=CS_CHECKING; |
| 1333 | if(refch->add(get_fullname())) |
| 1334 | for(size_t i=0; i<cds.size(); i++) |
| 1335 | *u.ustr+=cds[i]->get_ustring(refch); |
| 1336 | if(destroy_refch) delete refch; |
| 1337 | else refch->prev_state(); |
| 1338 | selector=CS_USTRING; |
| 1339 | } |
| 1340 | // no break |
| 1341 | case CS_USTRING: |
| 1342 | return *u.ustr; |
| 1343 | case CS_CSTRING: |
| 1344 | return ustring(*u.str); |
| 1345 | case CS_ISO2022STRING: |
| 1346 | error("ISO-2022 charstring cannot be used in ISO-10646 context"); |
| 1347 | return ustring(); |
| 1348 | case CS_CHECKING: |
| 1349 | error("Circular reference in `%s'", get_fullname().c_str()); |
| 1350 | return ustring(); |
| 1351 | default: |
| 1352 | FATAL_ERROR("CharSyms::get_ustring()"); |
| 1353 | return ustring(); |
| 1354 | } // switch |
| 1355 | } |
| 1356 | |
| 1357 | string CharSyms::get_iso2022string(ReferenceChain *refch) |
| 1358 | { |
| 1359 | switch(selector) { |
| 1360 | case CS_UNDEF:{ |
| 1361 | bool destroy_refch=refch==0; |
| 1362 | if(refch) refch->mark_state(); |
| 1363 | else refch=new ReferenceChain(this, "While checking" |
| 1364 | " charstring value"); |
| 1365 | u.str=new string(); |
| 1366 | selector=CS_CHECKING; |
| 1367 | if(refch->add(get_fullname())) |
| 1368 | for(size_t i=0; i<cds.size(); i++) |
| 1369 | *u.str+=cds[i]->get_iso2022string(refch); |
| 1370 | if(destroy_refch) delete refch; |
| 1371 | else refch->prev_state(); |
| 1372 | selector=CS_CSTRING; |
| 1373 | } |
| 1374 | // no break |
| 1375 | case CS_CSTRING: |
| 1376 | case CS_ISO2022STRING: |
| 1377 | return *u.str; |
| 1378 | case CS_USTRING: |
| 1379 | error("ISO-10646 charstring cannot be used in ISO-2022 context"); |
| 1380 | return string(); |
| 1381 | case CS_CHECKING: |
| 1382 | error("Circular reference in `%s'", get_fullname().c_str()); |
| 1383 | return string(); |
| 1384 | default: |
| 1385 | FATAL_ERROR("CharSyms::get_iso2022string()"); |
| 1386 | return string(); |
| 1387 | } // switch |
| 1388 | } |
| 1389 | |
| 1390 | size_t CharSyms::get_len(ReferenceChain *refch) |
| 1391 | { |
| 1392 | switch(selector) { |
| 1393 | case CS_UNDEF:{ |
| 1394 | bool destroy_refch=refch==0; |
| 1395 | if(refch) refch->mark_state(); |
| 1396 | else refch=new ReferenceChain(this, "While checking" |
| 1397 | " charstring value"); |
| 1398 | size_t len=0; |
| 1399 | selector=CS_CHECKING; |
| 1400 | if(refch->add(get_fullname())) |
| 1401 | for(size_t i=0; i<cds.size(); i++) |
| 1402 | len+=cds[i]->get_len(refch); |
| 1403 | if(destroy_refch) delete refch; |
| 1404 | else refch->prev_state(); |
| 1405 | selector=CS_UNDEF; |
| 1406 | } |
| 1407 | // no break |
| 1408 | case CS_CSTRING: |
| 1409 | case CS_ISO2022STRING: |
| 1410 | return u.str->size(); |
| 1411 | case CS_USTRING: |
| 1412 | return u.ustr->size(); |
| 1413 | case CS_CHECKING: |
| 1414 | error("Circular reference in `%s'", get_fullname().c_str()); |
| 1415 | return 0; |
| 1416 | default: |
| 1417 | FATAL_ERROR("CharSyms::get_len()"); |
| 1418 | return 0; |
| 1419 | } // switch |
| 1420 | } |
| 1421 | |
| 1422 | void CharSyms::dump(unsigned level) const |
| 1423 | { |
| 1424 | DEBUG(level, "CharSyms:"); |
| 1425 | level++; |
| 1426 | for (size_t i = 0; i < cds.size(); i++) |
| 1427 | cds[i]->dump(level); |
| 1428 | } |
| 1429 | |
| 1430 | } // namespace Common |