fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
at master 688 lines 11 kB view raw
1/***************************************************************************** 2 * libini * 3 *****************************************************************************/ 4 5/***************************************************************************** 6 * File name: src/libini/section.c * 7 * Created: 2001-08-24 by Hampa Hug <hampa@hampa.ch> * 8 * Copyright: (C) 2001-2010 Hampa Hug <hampa@hampa.ch> * 9 *****************************************************************************/ 10 11/***************************************************************************** 12 * This program is free software. You can redistribute it and / or modify it * 13 * under the terms of the GNU General Public License version 2 as published * 14 * by the Free Software Foundation. * 15 * * 16 * This program is distributed in the hope that it will be useful, but * 17 * WITHOUT ANY WARRANTY, without even the implied warranty of * 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * 19 * Public License for more details. * 20 *****************************************************************************/ 21 22 23#include <config.h> 24 25#include <stdlib.h> 26#include <string.h> 27 28#include <libini/libini.h> 29 30 31/* 32 * Check if c is a letter, a digit or both. 33 */ 34static 35int ini_check_char (char c, int alpha, int num) 36{ 37 if (alpha) { 38 if ((c >= 'a') && (c <= 'z')) { 39 return (1); 40 } 41 42 if ((c >= 'A') && (c <= 'Z')) { 43 return (1); 44 } 45 46 if (c == '_') { 47 return (1); 48 } 49 } 50 51 if (num) { 52 if ((c >= '0') && (c <= '9')) { 53 return (1); 54 } 55 } 56 57 return (0); 58} 59 60/* 61 * Extract the first name and index from a longer section name. 62 */ 63static 64int ini_get_name_and_index (const char **str, char *name, unsigned max, 65 unsigned *idx, int *noidx, int *addnew, int *last) 66{ 67 unsigned i; 68 const char *s; 69 70 s = *str; 71 72 *idx = 0; 73 *noidx = 1; 74 *addnew = 0; 75 *last = 0; 76 77 if (ini_check_char (*s, 1, 0) == 0) { 78 return (1); 79 } 80 81 name[0] = *(s++); 82 i = 1; 83 84 while ((*s != 0) && (i < max)) { 85 if (ini_check_char (*s, 1, 1) == 0) { 86 break; 87 } 88 89 name[i++] = *(s++); 90 } 91 92 if (i >= max) { 93 return (1); 94 } 95 96 name[i] = 0; 97 98 if (*s == 0) { 99 *str = s; 100 return (0); 101 } 102 103 if (*s == '.') { 104 *str = s + 1; 105 return (0); 106 } 107 108 if (*s != '[') { 109 return (1); 110 } 111 112 s += 1; 113 114 if (*s == '+') { 115 *addnew = 1; 116 s += 1; 117 } 118 else if (*s == '-') { 119 *last = 1; 120 s += 1; 121 } 122 else { 123 if (ini_check_char (*s, 0, 1) == 0) { 124 return (1); 125 } 126 127 while (ini_check_char (*s, 0, 1)) { 128 *idx = 10 * *idx + (*s - '0'); 129 s += 1; 130 } 131 } 132 133 if (*s != ']') { 134 return (1); 135 } 136 137 s += 1 ; 138 139 if (*s == '.') { 140 s += 1 ; 141 } 142 143 *str = s; 144 *noidx = 0; 145 146 return (0); 147} 148 149ini_sct_t *ini_sct_new (const char *name) 150{ 151 ini_sct_t *sct; 152 153 sct = malloc (sizeof (ini_sct_t)); 154 155 if (sct == NULL) { 156 return (NULL); 157 } 158 159 sct->next = NULL; 160 sct->parent = NULL; 161 162 if (name == NULL) { 163 name = ""; 164 } 165 166 if (name != NULL) { 167 sct->name = strdup (name); 168 } 169 else { 170 sct->name = NULL; 171 } 172 173 sct->sub_head = NULL; 174 sct->sub_tail = NULL; 175 176 sct->val_head = NULL; 177 sct->val_tail = NULL; 178 179 return (sct); 180} 181 182void ini_sct_del (ini_sct_t *sct) 183{ 184 ini_sct_t *tmp; 185 186 while (sct != NULL) { 187 tmp = sct; 188 sct = sct->next; 189 190 ini_val_del (tmp->val_head); 191 ini_sct_del (tmp->sub_head); 192 193 free (tmp->name); 194 free (tmp); 195 } 196} 197 198static 199ini_sct_t *ini_new_sct (ini_sct_t *sct, const char *name) 200{ 201 ini_sct_t *sub; 202 203 sub = ini_sct_new (name); 204 205 if (sub == NULL) { 206 return (NULL); 207 } 208 209 if (sct != NULL) { 210 sub->parent = sct; 211 212 if (sct->sub_head == NULL) { 213 sct->sub_head = sub; 214 } 215 else { 216 sct->sub_tail->next = sub; 217 } 218 219 sct->sub_tail = sub; 220 } 221 222 return (sub); 223} 224 225static 226ini_val_t *ini_new_val (ini_sct_t *sct, const char *name) 227{ 228 ini_val_t *val; 229 230 val = ini_val_new (name); 231 232 if (val == NULL) { 233 return (NULL); 234 } 235 236 if (sct != NULL) { 237 if (sct->val_head == NULL) { 238 sct->val_head = val; 239 } 240 else { 241 sct->val_tail->next = val; 242 } 243 244 sct->val_tail = val; 245 } 246 247 return (val); 248} 249 250ini_sct_t *ini_next_sct (ini_sct_t *sct, ini_sct_t *val, const char *name) 251{ 252 if (val == NULL) { 253 if (sct == NULL) { 254 return (NULL); 255 } 256 257 val = sct->sub_head; 258 } 259 else { 260 val = val->next; 261 } 262 263 if (val == NULL) { 264 return (NULL); 265 } 266 267 if (name == NULL) { 268 return (val); 269 } 270 271 while (val != NULL) { 272 if (strcmp (val->name, name) == 0) { 273 return (val); 274 } 275 276 val = val->next; 277 } 278 279 return (NULL); 280} 281 282ini_val_t *ini_next_val (ini_sct_t *sct, ini_val_t *val, const char *name) 283{ 284 if (val == NULL) { 285 if (sct == NULL) { 286 return (NULL); 287 } 288 289 val = sct->val_head; 290 } 291 else { 292 val = val->next; 293 } 294 295 if (val == NULL) { 296 return (NULL); 297 } 298 299 if (name == NULL) { 300 return (NULL); 301 } 302 303 while (val != NULL) { 304 if (strcmp (val->name, name) == 0) { 305 return (val); 306 } 307 308 val = val->next; 309 } 310 311 return (NULL); 312} 313 314/* 315 * Get the last subsection of sct with name name. If there is no such 316 * subsection and add is true, add a new subsection and return it. 317 */ 318static 319ini_sct_t *ini_get_last_sct (ini_sct_t *sct, const char *name, int add) 320{ 321 ini_sct_t *sub, *ret; 322 323 sub = sct->sub_head; 324 ret = NULL; 325 326 while (sub != NULL) { 327 if (strcmp (sub->name, name) == 0) { 328 ret = sub; 329 } 330 331 sub = sub->next; 332 } 333 334 if ((add == 0) || (ret != NULL)) { 335 return (ret); 336 } 337 338 return (ini_new_sct (sct, name)); 339} 340 341static 342ini_sct_t *ini_get_indexed_sct (ini_sct_t *sct, const char *name, 343 unsigned index, int add) 344{ 345 ini_sct_t *sub; 346 347 sub = sct->sub_head; 348 349 while (sub != NULL) { 350 if (strcmp (sub->name, name) == 0) { 351 if (index == 0) { 352 return (sub); 353 } 354 355 index -= 1; 356 } 357 358 sub = sub->next; 359 } 360 361 if (add == 0) { 362 return (NULL); 363 } 364 365 while (index > 0) { 366 if (ini_new_sct (sct, name) == NULL) { 367 return (NULL); 368 } 369 370 index -= 1; 371 } 372 373 return (ini_new_sct (sct, name)); 374} 375 376/* 377 * Get the last value of sct with name name. If there is no such value 378 * and add is true, add a new value and return it. 379 */ 380static 381ini_val_t *ini_get_last_val (ini_sct_t *sct, const char *name, int add) 382{ 383 ini_val_t *val, *ret; 384 385 val = sct->val_head; 386 ret = NULL; 387 388 while (val != NULL) { 389 if (strcmp (val->name, name) == 0) { 390 ret = val; 391 } 392 393 val = val->next; 394 } 395 396 if ((add == 0) || (ret != NULL)) { 397 return (ret); 398 } 399 400 return (ini_new_val (sct, name)); 401} 402 403static 404ini_val_t *ini_get_indexed_val (ini_sct_t *sct, const char *name, 405 unsigned index, int add) 406{ 407 ini_val_t *val; 408 409 val = sct->val_head; 410 411 while (val != NULL) { 412 if (strcmp (val->name, name) == 0) { 413 if (index == 0) { 414 return (val); 415 } 416 417 index -= 1; 418 } 419 420 val = val->next; 421 } 422 423 if (add == 0) { 424 return (NULL); 425 } 426 427 while (index > 0) { 428 if (ini_new_val (sct, name) == NULL) { 429 return (NULL); 430 } 431 432 index -= 1; 433 } 434 435 return (ini_new_val (sct, name)); 436} 437 438ini_sct_t *ini_get_sct (ini_sct_t *sct, const char *name, int add) 439{ 440 int simple, noidx, addnew, last; 441 unsigned index; 442 char name2[256]; 443 444 if (sct == NULL) { 445 return (NULL); 446 } 447 448 simple = 1; 449 450 while (*name != 0) { 451 if (ini_get_name_and_index (&name, name2, 256, &index, &noidx, &addnew, &last)) { 452 return (NULL); 453 } 454 455 if (*name != 0) { 456 simple = 0; 457 } 458 459 if (addnew || (simple && add && noidx)) { 460 sct = ini_new_sct (sct, name2); 461 } 462 else if (last) { 463 sct = ini_get_last_sct (sct, name2, add); 464 } 465 else { 466 sct = ini_get_indexed_sct (sct, name2, index, add); 467 468 } 469 470 if (sct == NULL) { 471 return (NULL); 472 } 473 } 474 475 return (sct); 476} 477 478ini_val_t *ini_get_val (ini_sct_t *sct, const char *name, int add) 479{ 480 int simple, noidx, addnew, last; 481 unsigned index; 482 char name2[256]; 483 484 if (sct == NULL) { 485 return (NULL); 486 } 487 488 simple = 1; 489 490 while (*name != 0) { 491 if (ini_get_name_and_index (&name, name2, 256, &index, &noidx, &addnew, &last)) { 492 return (NULL); 493 } 494 495 if (*name == 0) { 496 if (addnew || (simple && add && noidx)) { 497 return (ini_new_val (sct, name2)); 498 } 499 else if (last) { 500 return (ini_get_last_val (sct, name2, add)); 501 } 502 503 return (ini_get_indexed_val (sct, name2, index, add)); 504 } 505 else { 506 simple = 0; 507 } 508 509 if (addnew || (simple && add && noidx)) { 510 sct = ini_new_sct (sct, name2); 511 } 512 else if (last) { 513 sct = ini_get_last_sct (sct, name2, add); 514 } 515 else { 516 sct = ini_get_indexed_sct (sct, name2, index, add); 517 } 518 519 if (sct == NULL) { 520 return (NULL); 521 } 522 } 523 524 return (NULL); 525} 526 527 528int ini_set_uint32 (ini_sct_t *sct, const char *name, unsigned long v) 529{ 530 ini_val_t *val; 531 532 val = ini_get_val (sct, name, 1); 533 534 if (val == NULL) { 535 return (1); 536 } 537 538 ini_val_set_uint32 (val, v); 539 540 return (0); 541} 542 543int ini_set_sint32 (ini_sct_t *sct, const char *name, long v) 544{ 545 ini_val_t *val; 546 547 val = ini_get_val (sct, name, 1); 548 549 if (val == NULL) { 550 return (1); 551 } 552 553 ini_val_set_sint32 (val, v); 554 555 return (0); 556} 557 558int ini_set_str (ini_sct_t *sct, const char *name, const char *v) 559{ 560 ini_val_t *val; 561 562 val = ini_get_val (sct, name, 1); 563 564 if (val == NULL) { 565 return (1); 566 } 567 568 ini_val_set_str (val, v); 569 570 return (0); 571} 572 573int ini_get_uint32 (const ini_sct_t *sct, const char *name, unsigned long *ret, unsigned long def) 574{ 575 ini_val_t *val; 576 577 *ret = def; 578 579 val = ini_get_val ((ini_sct_t *) sct, name, 0); 580 581 if (val == NULL) { 582 return (1); 583 } 584 585 if (ini_val_get_uint32 (val, ret)) { 586 return (1); 587 } 588 589 return (0); 590} 591 592int ini_get_sint32 (const ini_sct_t *sct, const char *name, long *ret, long def) 593{ 594 ini_val_t *val; 595 596 *ret = def; 597 598 val = ini_get_val ((ini_sct_t *) sct, name, 0); 599 600 if (val == NULL) { 601 return (1); 602 } 603 604 if (ini_val_get_sint32 (val, ret)) { 605 return (1); 606 } 607 608 return (0); 609} 610 611int ini_get_uint16 (const ini_sct_t *sct, const char *name, unsigned *ret, unsigned def) 612{ 613 ini_val_t *val; 614 615 *ret = def; 616 617 val = ini_get_val ((ini_sct_t *) sct, name, 0); 618 619 if (val == NULL) { 620 return (1); 621 } 622 623 if (ini_val_get_uint16 (val, ret)) { 624 return (1); 625 } 626 627 return (0); 628} 629 630int ini_get_sint16 (const ini_sct_t *sct, const char *name, int *ret, int def) 631{ 632 ini_val_t *val; 633 634 *ret = def; 635 636 val = ini_get_val ((ini_sct_t *) sct, name, 0); 637 638 if (val == NULL) { 639 return (1); 640 } 641 642 if (ini_val_get_sint16 (val, ret)) { 643 return (1); 644 } 645 646 return (0); 647} 648 649int ini_get_bool (const ini_sct_t *sct, const char *name, int *ret, int def) 650{ 651 ini_val_t *val; 652 653 *ret = (def != 0); 654 655 val = ini_get_val ((ini_sct_t *) sct, name, 0); 656 657 if (val == NULL) { 658 return (1); 659 } 660 661 if (ini_val_get_bool (val, ret)) { 662 return (1); 663 } 664 665 return (0); 666} 667 668int ini_get_string (const ini_sct_t *sct, const char *name, const char **ret, const char *def) 669{ 670 const char *tmp; 671 ini_val_t *val; 672 673 *ret = def; 674 675 val = ini_get_val ((ini_sct_t *) sct, name, 0); 676 677 if (val == NULL) { 678 return (1); 679 } 680 681 tmp = ini_val_get_str (val); 682 683 if (tmp != NULL) { 684 *ret = tmp; 685 } 686 687 return (0); 688}