cint_variables.c (11074B)
1 /* 2 * 3 * 4 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 5 * 6 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 7 * 8 * File: cint_variables.c 9 * Purpose: CINT variable functions 10 */ 11 12 #include "cint_config.h" 13 #include "cint_variables.h" 14 #include "cint_porting.h" 15 #include "cint_debug.h" 16 #include "cint_interpreter.h" 17 18 /******************************************************************************* 19 * 20 * Global Static Data Variables 21 */ 22 23 typedef struct lscope_list_s { 24 struct lscope_list_s* next; 25 cint_variable_t* vlist; 26 cint_variable_t* autolist; 27 } lscope_list_t; 28 29 typedef struct vscope_list_s { 30 struct vscope_list_s* next; 31 lscope_list_t* lscopes; 32 } vscope_list_t; 33 34 /* 35 * Global variable scope. 36 * 37 * This scope is available at all times. 38 */ 39 static vscope_list_t _global_scope = { NULL, NULL }; 40 41 42 /* 43 * This is the list of all variable scopes. 44 */ 45 static vscope_list_t* _scopes = NULL; 46 47 /* 48 * Mutex to protect all list operations 49 */ 50 sal_mutex_t cint_variables_mutex = NULL; 51 52 static void 53 __cint_variables_mutex_create(void) 54 { 55 if (!cint_variables_mutex) { 56 57 SAL_GLOBAL_LOCK; 58 59 if (!cint_variables_mutex) { 60 61 cint_variables_mutex = sal_mutex_create("cint_variables_mutex"); 62 if (!cint_variables_mutex) { 63 /* should probably just assert here */ 64 cint_internal_error(__FILE__, __LINE__, "Failed to create cint_variables_mutex"); 65 } 66 } 67 68 SAL_GLOBAL_UNLOCK; 69 } 70 } 71 72 int 73 cint_variable_init(void) 74 { 75 __cint_variables_mutex_create(); 76 77 /* Destroy any previous scopes */ 78 while(cint_variable_scope_pop("") != CINT_E_NOT_FOUND); 79 80 /* Initialize the global scope */ 81 _scopes = &_global_scope; 82 cint_variable_lscope_push("global"); 83 return 0; 84 } 85 86 static int 87 __destroy_vlist(cint_variable_t* vlist, int force) 88 { 89 cint_variable_t* v; 90 for(v = vlist; v;) { 91 cint_variable_t* next = v->next; 92 if (force) { 93 v->flags &= ~CINT_VARIABLE_F_NODESTROY; 94 } 95 cint_variable_free(v); 96 v = next; 97 } 98 99 return CINT_E_NONE; 100 } 101 102 103 int 104 cint_variable_scope_push(const char* msg) 105 { 106 vscope_list_t* vscope = CINT_MALLOC(sizeof(*vscope)); 107 108 if(vscope == NULL) { 109 return CINT_E_MEMORY; 110 } 111 112 CINT_VARIABLES_LOCK; 113 114 vscope->lscopes = NULL; 115 vscope->next = _scopes; 116 _scopes = vscope; 117 118 CINT_VARIABLES_UNLOCK; 119 120 CINT_DTRACE(("scope_push(%s)=%p", msg, (void *)vscope)); 121 return cint_variable_lscope_push(msg); 122 } 123 124 int 125 cint_variable_scope_pop(const char* msg) 126 { 127 vscope_list_t* vscope; 128 129 CINT_VARIABLES_LOCK; 130 131 vscope = _scopes; 132 133 if(vscope) { 134 while(cint_variable_lscope_pop(msg) != CINT_E_NOT_FOUND); 135 _scopes = vscope->next; 136 CINT_DTRACE(("scope_pop(%s)=%p", msg, (void *)vscope)); 137 if (vscope != &_global_scope) { 138 CINT_FREE(vscope); 139 } 140 141 CINT_VARIABLES_UNLOCK; 142 143 return CINT_E_NONE; 144 } 145 else { 146 147 CINT_VARIABLES_UNLOCK; 148 149 return CINT_E_NOT_FOUND; 150 } 151 } 152 153 void * 154 cint_variable_scope_global_set(const char *msg) 155 { 156 vscope_list_t *vscope; 157 158 CINT_VARIABLES_LOCK; 159 160 vscope = _scopes; 161 _scopes = &_global_scope; 162 163 CINT_VARIABLES_UNLOCK; 164 165 CINT_DTRACE(("scope_global_set(%s)=%p (prev %p)", msg, _scopes, vscope)); 166 167 return vscope; 168 } 169 170 void * 171 cint_variable_scope_set(const char *msg, void *vscope) 172 { 173 vscope_list_t *c_scope; 174 175 CINT_VARIABLES_LOCK; 176 177 c_scope = _scopes; 178 _scopes = vscope; 179 180 CINT_VARIABLES_UNLOCK; 181 182 CINT_DTRACE(("scope_set(%s)=%p (prev %p)", msg, _scopes, c_scope)); 183 184 return c_scope; 185 } 186 187 188 int 189 cint_variable_lscope_push(const char* msg) 190 { 191 lscope_list_t* lscope; 192 193 if (!_scopes) { 194 CINT_DTRACE(("lscope_push(%s) no scope", msg)); 195 return CINT_E_NONE; 196 } 197 198 lscope = CINT_MALLOC(sizeof(*lscope)); 199 200 if(lscope == NULL) { 201 return CINT_E_MEMORY; 202 } 203 204 lscope->vlist = NULL; 205 lscope->autolist = NULL; 206 207 CINT_VARIABLES_LOCK; 208 209 lscope->next = _scopes->lscopes; 210 _scopes->lscopes = lscope; 211 212 CINT_VARIABLES_UNLOCK; 213 214 CINT_DTRACE(("lscope_push(%s)", msg)); 215 return CINT_E_NONE; 216 } 217 218 int 219 cint_variable_lscope_pop(const char* msg) 220 { 221 lscope_list_t* lscope; 222 223 CINT_VARIABLES_LOCK; 224 225 lscope = _scopes->lscopes; 226 if (!lscope) { 227 CINT_VARIABLES_UNLOCK; 228 return CINT_E_NOT_FOUND; 229 } 230 231 _scopes->lscopes = lscope->next; 232 __destroy_vlist(lscope->vlist, 0); 233 __destroy_vlist(lscope->autolist, 0); 234 235 CINT_VARIABLES_UNLOCK; 236 237 CINT_FREE(lscope); 238 CINT_DTRACE(("lscope_pop(%s)", msg)); 239 return CINT_E_NONE; 240 } 241 242 243 cint_variable_t* 244 cint_variable_alloc(void) 245 { 246 cint_variable_t* v = (cint_variable_t*)CINT_MALLOC(sizeof(cint_variable_t)); 247 if (v) { 248 CINT_MEMSET(v, 0, sizeof(*v)); 249 } 250 return v; 251 } 252 253 int 254 cint_variable_free(cint_variable_t* v) 255 { 256 if(v) { 257 258 if(v->flags & CINT_VARIABLE_F_NODESTROY){ 259 return 0; 260 } 261 /*CINT_PRINTF("free variable '%s' flags=0x%x name=%p data=%p\n", 262 v->name, v->flags, v->name, v->data);*/ 263 if(v->name && !(v->flags & CINT_VARIABLE_F_SNAME)) { 264 CINT_FREE(v->name); 265 } 266 if(v->data && !(v->flags & CINT_VARIABLE_F_SDATA)) { 267 if(v->flags & CINT_VARIABLE_F_CSTRING) { 268 char **sptr = (char **)v->data; 269 if (sptr) { 270 CINT_FREE(*sptr); 271 } 272 } 273 CINT_FREE(v->data); 274 } 275 CINT_FREE(v); 276 } 277 return 0; 278 } 279 280 /* Find a variable on a variable list */ 281 static cint_variable_t* 282 _variable_find_list(cint_variable_t* vlist, const char* name) 283 { 284 cint_variable_t* v; 285 for(v = vlist; v; v = v->next) { 286 if(!CINT_STRCMP(v->name, name)) { 287 return v; 288 } 289 } 290 return NULL; 291 } 292 293 /* Find a variable within a scope on manual and auto lists */ 294 static cint_variable_t* 295 _variable_find_scope(lscope_list_t* lscope, const char* name) 296 { 297 cint_variable_t* rv = NULL; 298 299 rv = _variable_find_list(lscope->vlist, name); 300 301 if (rv == NULL) { 302 rv = _variable_find_list(lscope->autolist, name); 303 } 304 305 return rv; 306 } 307 308 /* Find a variable within a set of scopes on manual and auto lists */ 309 static cint_variable_t* 310 _variable_find_scopes(lscope_list_t* lscope, const char* name) 311 { 312 lscope_list_t* s; 313 cint_variable_t* rv = NULL; 314 315 for (s = lscope; s; s = s->next) { 316 if ((rv = _variable_find_scope(s, name)) != NULL) { 317 break; 318 } 319 } 320 321 return rv; 322 } 323 324 cint_variable_t* 325 cint_variable_find(const char* name, int current_scope_only) 326 { 327 cint_variable_t* rv = NULL; 328 329 CINT_VARIABLES_LOCK; 330 331 if(_scopes && _scopes->lscopes) { 332 if(current_scope_only) { 333 rv = _variable_find_scope(_scopes->lscopes, name); 334 CINT_VARIABLES_UNLOCK; 335 return rv; 336 } else { 337 rv = _variable_find_scopes(_scopes->lscopes, name); 338 } 339 } 340 341 if(rv == NULL) { 342 rv = _variable_find_scopes(_global_scope.lscopes, name); 343 } 344 345 CINT_VARIABLES_UNLOCK; 346 347 return rv; 348 } 349 350 int 351 cint_variable_add(cint_variable_t* v) 352 { 353 int is_global = 0; 354 v->prev = NULL; 355 356 CINT_VARIABLES_LOCK; 357 358 if(v->flags & CINT_VARIABLE_F_AUTO) { 359 v->next = _scopes->lscopes->autolist; 360 _scopes->lscopes->autolist = v; 361 } 362 else { 363 v->next = _scopes->lscopes->vlist; 364 _scopes->lscopes->vlist = v; 365 if (_scopes == &_global_scope) { 366 is_global = 1; 367 } 368 } 369 370 if(v->next) { 371 v->next->prev = v; 372 } 373 374 CINT_VARIABLES_UNLOCK; 375 376 if (is_global) { 377 cint_interpreter_event(cintEventGlobalVariableAdded); 378 } 379 380 return CINT_E_NONE; 381 } 382 383 int 384 cint_variable_rename(cint_variable_t* v, const char *name) 385 { 386 if (name) { 387 if (v->name) { 388 CINT_FREE(v->name); 389 } 390 v->name = CINT_STRDUP(name); 391 } 392 393 return CINT_E_NONE; 394 } 395 396 int 397 cint_variable_list_remove(cint_variable_t* v) 398 { 399 if(v == NULL) { 400 return 0; 401 } 402 403 CINT_VARIABLES_LOCK; 404 405 if(v->prev) { 406 v->prev->next = v->next; 407 } 408 409 if (v->next) { 410 v->next->prev = v->prev; 411 } 412 413 if(v == _scopes->lscopes->autolist) { 414 _scopes->lscopes->autolist = v->next; 415 } 416 else if(v == _scopes->lscopes->vlist) { 417 _scopes->lscopes->vlist = v->next; 418 } 419 420 CINT_VARIABLES_UNLOCK; 421 422 return 0; 423 } 424 425 426 int 427 cint_variable_auto_clear(void) 428 { 429 CINT_VARIABLES_LOCK; 430 431 /* Clear all autovars from the current scope */ 432 __destroy_vlist(_scopes->lscopes->autolist, 0); 433 _scopes->lscopes->autolist = NULL; 434 435 CINT_VARIABLES_UNLOCK; 436 return 0; 437 } 438 439 int 440 cint_variable_auto_save(cint_variable_t* v) 441 { 442 /* 443 * Move this autovar from the auto list to variable list 444 */ 445 if(v && (v->flags & CINT_VARIABLE_F_AUTO)) { 446 447 /* Remove it from it's auto list */ 448 cint_variable_list_remove(v); 449 450 v->flags &= ~CINT_VARIABLE_F_AUTO; 451 cint_variable_add(v); 452 } 453 return 0; 454 } 455 456 457 458 459 int 460 cint_variable_delete(const char* name) 461 { 462 cint_variable_t* v = cint_variable_find(name, 1); 463 if(v) { 464 cint_variable_list_remove(v); 465 cint_variable_free(v); 466 } 467 return 0; 468 } 469 470 471 int 472 cint_variable_show(const char* var) 473 { 474 return CINT_E_NONE; 475 } 476 477 478 int 479 cint_variable_dump(void) 480 { 481 int l, v; 482 cint_variable_t* var; 483 484 CINT_VARIABLES_LOCK; 485 486 if(_scopes) { 487 vscope_list_t* vscopes; 488 for(v = 0, vscopes = _scopes; vscopes; vscopes = vscopes->next, v++) { 489 lscope_list_t* lscopes; 490 for(l = 0, lscopes = vscopes->lscopes; lscopes; lscopes = lscopes->next, l++) { 491 for(var = lscopes->vlist; var; var = var->next) { 492 if(!CINT_STRCMP(var->name, "NULL")) continue; 493 CINT_PRINTF("V %d L %d: %s\n", v, l, var->name); 494 } 495 for(var = lscopes->autolist; var; var = var->next) { 496 CINT_PRINTF("A %d L %d: %s\n", v, l, var->name); 497 } 498 } 499 } 500 } 501 502 CINT_VARIABLES_UNLOCK; 503 504 return CINT_E_NONE; 505 } 506 507 508 509 int 510 cint_variable_clear(void) 511 { 512 vscope_list_t* vscopes; 513 514 __cint_variables_mutex_create(); 515 516 CINT_VARIABLES_LOCK; 517 518 for (vscopes = _scopes; vscopes; vscopes = vscopes->next) { 519 lscope_list_t* lscopes; 520 for (lscopes = vscopes->lscopes; lscopes; lscopes = lscopes->next) { 521 __destroy_vlist(lscopes->vlist, 1); 522 __destroy_vlist(lscopes->autolist, 1); 523 lscopes->vlist = NULL; 524 lscopes->autolist = NULL; 525 } 526 } 527 _scopes = NULL; 528 529 CINT_VARIABLES_UNLOCK; 530 531 return CINT_E_NONE; 532 }