scriplib.cpp
1 /* 2 * scriplib.c 3 * MACT library Script file parsing and writing 4 * 5 * by Jonathon Fowler 6 * 7 * Since we weren't given the source for MACT386.LIB so I've had to do some 8 * creative interpolation here. 9 * 10 * This all should be rewritten in a much much cleaner fashion. 11 * 12 */ 13 //------------------------------------------------------------------------- 14 /* 15 Duke Nukem Copyright (C) 1996, 2003 3D Realms Entertainment 16 17 This file is part of Duke Nukem 3D version 1.5 - Atomic Edition 18 19 Duke Nukem 3D is free software; you can redistribute it and/or 20 modify it under the terms of the GNU General Public License 21 as published by the Free Software Foundation; either version 2 22 of the License, or (at your option) any later version. 23 24 This program is distributed in the hope that it will be useful, 25 but WITHOUT ANY WARRANTY; without even the implied warranty of 26 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 27 28 See the GNU General Public License for more details. 29 30 You should have received a copy of the GNU General Public License 31 along with this program; if not, write to the Free Software 32 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 33 */ 34 //------------------------------------------------------------------------- 35 36 #include "scriplib.h" 37 38 #include "_scrplib.h" 39 #include "compat.h" 40 #include "log.h" 41 #include "vfs.h" 42 43 static script_t *scriptfiles[MAXSCRIPTFILES]; 44 45 46 #define SC(s) scriptfiles[s] 47 48 49 int32_t SCRIPT_New(void) 50 { 51 int32_t i; 52 53 for (i=0; i<MAXSCRIPTFILES; i++) 54 { 55 if (!SC(i)) 56 { 57 SC(i) = (script_t *)Xmalloc(sizeof(script_t)); 58 memset(SC(i), 0, sizeof(script_t)); 59 return i; 60 } 61 } 62 63 return -1; 64 } 65 66 void SCRIPT_Delete(int32_t scripthandle) 67 { 68 ScriptSectionType *s; 69 70 if (scripthandle < 0 || scripthandle >= MAXSCRIPTFILES) return; 71 72 if (!SC(scripthandle)) return; 73 74 if (SCRIPT(scripthandle,apScript)) 75 { 76 while (SCRIPT(scripthandle,apScript)->nextsection != SCRIPT(scripthandle,apScript)) 77 { 78 s = SCRIPT(scripthandle,apScript)->nextsection; 79 SCRIPT_FreeSection(SCRIPT(scripthandle,apScript)); 80 Xfree(SCRIPT(scripthandle,apScript)); 81 SCRIPT(scripthandle,apScript) = s; 82 } 83 84 SCRIPT_FreeSection(SCRIPT(scripthandle, apScript)); 85 Xfree(SCRIPT(scripthandle,apScript)); 86 } 87 88 Xfree(SC(scripthandle)); 89 SC(scripthandle) = 0; 90 } 91 92 void SCRIPT_FreeSection(ScriptSectionType * section) 93 { 94 ScriptEntryType *e; 95 96 if (!section) return; 97 if (!section->entries) return; 98 99 while (section->entries->nextentry != section->entries) 100 { 101 e = section->entries->nextentry; 102 103 Xfree(section->entries->name); 104 Xfree(section->entries->value); 105 Xfree(section->entries); 106 section->entries = e; 107 } 108 109 Xfree(section->entries->name); 110 Xfree(section->entries->value); 111 Xfree(section->entries); 112 Xfree(section->name); 113 } 114 115 #define AllocSection(s) \ 116 { \ 117 (s) = (ScriptSectionType *)Xmalloc(sizeof(ScriptSectionType)); \ 118 (s)->name = NULL; \ 119 (s)->entries = NULL; \ 120 (s)->lastline = NULL; \ 121 (s)->nextsection = (s); \ 122 (s)->prevsection = (s); \ 123 } 124 #define AllocEntry(e) \ 125 { \ 126 (e) = (ScriptEntryType *)Xmalloc(sizeof(ScriptEntryType)); \ 127 (e)->name = NULL; \ 128 (e)->value = NULL; \ 129 (e)->nextentry = (e); \ 130 (e)->preventry = (e); \ 131 } 132 133 ScriptSectionType * SCRIPT_SectionExists(int32_t scripthandle, const char * sectionname) 134 { 135 ScriptSectionType *s, *ls=NULL; 136 137 if (scripthandle < 0 || scripthandle >= MAXSCRIPTFILES) return NULL; 138 if (!sectionname) return NULL; 139 if (!SC(scripthandle)) return NULL; 140 if (!SCRIPT(scripthandle,apScript)) return NULL; 141 142 for (s = SCRIPT(scripthandle,apScript); ls != s; ls=s,s=s->nextsection) 143 if (!Bstrcasecmp(s->name, sectionname)) return s; 144 145 return NULL; 146 } 147 148 ScriptSectionType * SCRIPT_AddSection(int32_t scripthandle, const char * sectionname) 149 { 150 ScriptSectionType *s,*s2; 151 152 if (scripthandle < 0 || scripthandle >= MAXSCRIPTFILES) return NULL; 153 if (!sectionname) return NULL; 154 if (!SC(scripthandle)) return NULL; 155 156 s = SCRIPT_SectionExists(scripthandle, sectionname); 157 if (s) return s; 158 159 AllocSection(s); 160 s->name = Xstrdup(sectionname); 161 if (!SCRIPT(scripthandle,apScript)) 162 { 163 SCRIPT(scripthandle,apScript) = s; 164 } 165 else 166 { 167 s2 = SCRIPT(scripthandle,apScript); 168 while (s2->nextsection != s2) s2=s2->nextsection; 169 s2->nextsection = s; 170 s->prevsection = s2; 171 } 172 173 return s; 174 } 175 176 ScriptEntryType * SCRIPT_EntryExists(ScriptSectionType * section, const char * entryname) 177 { 178 ScriptEntryType *e,*le=NULL; 179 180 if (!section) return NULL; 181 if (!entryname) return NULL; 182 if (!section->entries) return NULL; 183 184 for (e = section->entries; le != e; le=e,e=e->nextentry) 185 if (!Bstrcasecmp(e->name, entryname)) return e; 186 187 return NULL; 188 } 189 190 void SCRIPT_AddEntry(int32_t scripthandle, const char * sectionname, const char * entryname, const char * entryvalue) 191 { 192 ScriptSectionType *s; 193 ScriptEntryType *e,*e2; 194 195 if (scripthandle < 0 || scripthandle >= MAXSCRIPTFILES) return; 196 if (!sectionname || !entryname || !entryvalue) return; 197 if (!SC(scripthandle)) return; 198 199 // s = SCRIPT_SectionExists(scripthandle, sectionname); 200 // if (!s) { 201 s = SCRIPT_AddSection(scripthandle, sectionname); 202 if (!s) return; 203 // } 204 205 e = SCRIPT_EntryExists(s, entryname); 206 if (!e) 207 { 208 AllocEntry(e); 209 e->name = Xstrdup(entryname); 210 if (!s->entries) 211 { 212 s->entries = e; 213 } 214 else 215 { 216 e2 = s->entries; 217 while (e2->nextentry != e2) e2=e2->nextentry; 218 e2->nextentry = e; 219 e->preventry = e2; 220 } 221 } 222 223 Xfree(e->value); 224 e->value = Xstrdup(entryvalue); 225 } 226 227 228 int32_t SCRIPT_ParseBuffer(int32_t scripthandle, char *data, int32_t length) 229 { 230 if (!data || length < 0) return 1; 231 232 char const *currentsection = ""; 233 char const *currententry = NULL; 234 char const *currentvalue = NULL; 235 236 char *fence = data + length; 237 char ch = 0; 238 char lastch = 0; 239 240 enum 241 { 242 ParsingIdle, 243 ParsingSectionBegin, 244 ParsingSectionName, 245 ParsingEntry, 246 ParsingValueBegin, 247 ParsingValue 248 }; 249 250 enum 251 { 252 ExpectingSection = 1, 253 ExpectingEntry = 2, 254 ExpectingAssignment = 4, 255 ExpectingValue = 8, 256 ExpectingComment = 16 257 }; 258 259 260 #define SETERR(v) do { if (v>errlevel||errlevel==0) errlevel=v; } while (0) 261 262 char *sp = data; 263 char *dp = data; 264 265 int state = ParsingIdle; 266 int expect = ExpectingSection | ExpectingEntry; 267 int linenum = 1; 268 int errlevel = 0; 269 270 #define EATLINE(p) while (length > 0 && *p != '\n' && *p != '\r') { p++; length--; } 271 #define LETTER() { lastch = ch; ch = *(sp++); length--; } 272 273 while (length > 0) 274 { 275 switch (state) 276 { 277 case ParsingIdle: 278 LETTER(); 279 switch (ch) 280 { 281 // whitespace 282 case ' ': 283 case '\t': continue; 284 case '\n': if (lastch == '\r') continue; linenum++; continue; 285 case '\r': linenum++; continue; 286 287 case ';': 288 /*case '#':*/ 289 EATLINE(sp); 290 continue; 291 292 case '[': if (!(expect & ExpectingSection)) 293 { 294 // Unexpected section start 295 DLOG_F(WARNING, "Unexpected start of section on line %d.", linenum); 296 SETERR(-1); 297 EATLINE(sp); 298 continue; 299 } 300 else 301 { 302 state = ParsingSectionBegin; 303 continue; 304 } 305 306 default: if (isalpha(ch)) 307 { 308 if (!(expect & ExpectingEntry)) 309 { 310 // Unexpected name start 311 DLOG_F(WARNING, "Unexpected entry LabelText on line %d.", linenum); 312 SETERR(-1); 313 EATLINE(sp); 314 continue; 315 } 316 else 317 { 318 currententry = dp = sp-1; 319 state = ParsingEntry; 320 continue; 321 } 322 } 323 else 324 { 325 // Unexpected character 326 DLOG_F(WARNING, "Illegal character (ASCII %d) on line %d.", ch, linenum); 327 SETERR(-1); 328 EATLINE(sp); 329 continue; 330 } 331 } 332 333 case ParsingSectionBegin: 334 currentsection = dp = sp; 335 state = ParsingSectionName; 336 fallthrough__; 337 case ParsingSectionName: 338 LETTER(); 339 switch (ch) 340 { 341 case '\n': 342 case '\r': // Unexpected newline 343 DLOG_F(WARNING, "Unexpected newline on line %d.", linenum); 344 SETERR(-1); 345 state = ParsingIdle; 346 linenum++; 347 continue; 348 349 case ']': 350 *(dp) = 0; // Add new section 351 expect = ExpectingSection | ExpectingEntry; 352 state = ParsingIdle; 353 EATLINE(sp); 354 continue; 355 356 default: 357 dp++; 358 continue; 359 } 360 361 case ParsingEntry: 362 LETTER(); 363 switch (ch) 364 { 365 case ';': 366 /*case '#':*/ 367 // unexpected comment 368 EATLINE(sp); 369 DLOG_F(WARNING, "Unexpected comment on line %d.", linenum); 370 SETERR(-1); 371 fallthrough__; 372 case '\n': 373 case '\r': 374 // Unexpected newline 375 DLOG_F(WARNING, "Unexpected newline on line %d.", linenum); 376 SETERR(-1); 377 expect = ExpectingSection | ExpectingEntry; 378 state = ParsingIdle; 379 linenum++; 380 continue; 381 382 case '=': 383 // Entry name finished, now for the value 384 while (*dp == ' ' || *dp == '\t') dp--; 385 *(++dp) = 0; 386 state = ParsingValueBegin; 387 continue; 388 389 default: 390 dp++; 391 continue; 392 } 393 394 case ParsingValueBegin: 395 currentvalue = dp = sp; 396 state = ParsingValue; 397 fallthrough__; 398 case ParsingValue: 399 LETTER(); 400 switch (ch) 401 { 402 case '\n': 403 case '\r': 404 // value complete, add it using parsed name 405 while (*dp == ' ' || *dp == '\t') dp--; 406 *(dp) = 0; 407 while (*currentvalue == ' ' || *currentvalue == '\t') currentvalue++; 408 state = ParsingIdle; 409 linenum++; 410 411 SCRIPT_AddSection(scripthandle,currentsection); 412 SCRIPT_AddEntry(scripthandle,currentsection,currententry,currentvalue); 413 continue; 414 415 default: 416 dp++; 417 continue; 418 } 419 420 default: length=0; 421 continue; 422 } 423 } 424 425 if (sp > fence) DLOG_F(ERROR, "Stepped outside the fence!"); 426 427 return errlevel; 428 } 429 430 431 //--- 432 433 int32_t SCRIPT_Init(char const * name) 434 { 435 int32_t h = SCRIPT_New(); 436 437 if (h >= 0) Bstrncpy(SCRIPT(h,scriptfilename), name, 127); 438 439 return h; 440 } 441 442 void SCRIPT_Free(int32_t scripthandle) 443 { 444 SCRIPT_Delete(scripthandle); 445 } 446 447 int32_t SCRIPT_Load(char const * filename) 448 { 449 int32_t s,l; 450 char *b; 451 buildvfs_fd h; 452 453 h = buildvfs_open_read(filename); 454 l = (int32_t)buildvfs_length(h)+1; 455 b = (char *)Xmalloc(l); 456 buildvfs_read(h,b,l-1); 457 b[l-1] = '\n'; // JBF 20040111: evil nasty hack to trick my evil nasty parser 458 buildvfs_close(h); 459 460 s = SCRIPT_Init(filename); 461 if (s<0) 462 { 463 Xfree(b); 464 return -1; 465 } 466 467 SCRIPT_ParseBuffer(s,b,l); 468 469 Xfree(b); 470 471 return s; 472 } 473 474 void SCRIPT_Save(int32_t scripthandle, char const * filename) 475 { 476 char const *section, *entry, *value; 477 int32_t sec, ent, numsect, nument; 478 buildvfs_FILE fp; 479 480 481 if (!filename) return; 482 if (!SC(scripthandle)) return; 483 484 fp = buildvfs_fopen_write_text(filename); 485 if (!fp) return; 486 487 numsect = SCRIPT_NumberSections(scripthandle); 488 for (sec=0; sec<numsect; sec++) 489 { 490 section = SCRIPT_Section(scripthandle, sec); 491 if (sec>0) 492 buildvfs_fputc('\n', fp); 493 if (section[0] != 0) 494 { 495 buildvfs_fputc('[', fp); 496 buildvfs_fputstrptr(fp, section); 497 buildvfs_fputstr(fp, "]\n"); 498 } 499 500 nument = SCRIPT_NumberEntries(scripthandle,section); 501 for (ent=0; ent<nument; ent++) 502 { 503 entry = SCRIPT_Entry(scripthandle,section,ent); 504 value = SCRIPT_GetRaw(scripthandle,section,entry); 505 506 buildvfs_fputstrptr(fp, entry); 507 buildvfs_fputstr(fp, " = "); 508 buildvfs_fputstrptr(fp, value); 509 buildvfs_fputc('\n', fp); 510 } 511 } 512 513 buildvfs_fclose(fp); 514 } 515 516 int32_t SCRIPT_NumberSections(int32_t scripthandle) 517 { 518 int32_t c=0; 519 ScriptSectionType *s,*ls=NULL; 520 521 if (!SC(scripthandle)) return 0; 522 if (!SCRIPT(scripthandle,apScript)) return 0; 523 524 for (s = SCRIPT(scripthandle,apScript); ls != s; ls=s,s=s->nextsection) c++; 525 526 return c; 527 } 528 529 char const * SCRIPT_Section(int32_t scripthandle, int32_t which) 530 { 531 ScriptSectionType *s,*ls=NULL; 532 533 if (!SC(scripthandle)) return ""; 534 if (!SCRIPT(scripthandle,apScript)) return ""; 535 536 for (s = SCRIPT(scripthandle,apScript); which>0 && ls != s; ls=s, s=s->nextsection, which--) ; 537 538 return s->name; 539 } 540 541 int32_t SCRIPT_NumberEntries(int32_t scripthandle, char const * sectionname) 542 { 543 ScriptSectionType *s; 544 ScriptEntryType *e,*le=NULL; 545 int32_t c=0; 546 547 if (!SC(scripthandle)) return 0; 548 if (!SCRIPT(scripthandle,apScript)) return 0; 549 550 s = SCRIPT_SectionExists(scripthandle, sectionname); 551 if (!s) return 0; 552 553 for (e = s->entries; le != e; le=e,e=e->nextentry) c++; 554 return c; 555 } 556 557 char const * SCRIPT_Entry(int32_t scripthandle, char const * sectionname, int32_t which) 558 { 559 ScriptSectionType *s; 560 ScriptEntryType *e,*le=NULL; 561 562 if (!SC(scripthandle)) return 0; 563 if (!SCRIPT(scripthandle,apScript)) return 0; 564 565 s = SCRIPT_SectionExists(scripthandle, sectionname); 566 if (!s) return ""; 567 568 for (e = s->entries; which>0 && le != e; le=e, e=e->nextentry, which--) ; 569 return e->name; 570 } 571 572 char const * SCRIPT_GetRaw(int32_t scripthandle, char const * sectionname, char const * entryname) 573 { 574 ScriptSectionType *s; 575 ScriptEntryType *e; 576 577 if (!SC(scripthandle)) return 0; 578 if (!SCRIPT(scripthandle,apScript)) return 0; 579 580 s = SCRIPT_SectionExists(scripthandle, sectionname); 581 e = SCRIPT_EntryExists(s, entryname); 582 583 if (!e) return ""; 584 return e->value; 585 } 586 587 static char * SCRIPT_ParseString(char ** dest, char * p) 588 { 589 int32_t c = 0; 590 char ch; 591 592 if (!(*dest)) 593 { 594 // find length 595 char *q = p; 596 597 if (*q == '\"') 598 { 599 // quoted string 600 q++; 601 while ((ch = *(q++)) && ch != '\"') 602 { 603 if (ch == '\\') 604 { 605 ch = *(q++); 606 607 if (!ch) 608 break; 609 } 610 611 c++; 612 } 613 } 614 else 615 { 616 while ((ch = *(q++)) && ch != ' ' && ch != '\t') 617 c++; 618 } 619 620 // allocate 621 *dest = (char*)Xcalloc(c+1,sizeof(char)); 622 c = 0; 623 } 624 625 if (*p == '\"') 626 { 627 // quoted string 628 p++; 629 while ((ch = *(p++))) 630 { 631 switch (ch) 632 { 633 case '\\': 634 ch = *(p++); 635 switch (ch) 636 { 637 case 0: return p; 638 case 'n': (*dest)[c++] = '\n'; break; 639 case 'r': (*dest)[c++] = '\r'; break; 640 case 't': (*dest)[c++] = '\t'; break; 641 default: (*dest)[c++] = ch; break; 642 } 643 break; 644 case '\"': 645 (*dest)[c] = 0; 646 return p; 647 default: 648 (*dest)[c++] = ch; 649 break; 650 } 651 } 652 return p; 653 } 654 else 655 { 656 while ((ch = *(p++))) 657 { 658 if (ch == ' ' || ch == '\t') { (*dest)[c] = 0; break; } 659 else (*dest)[c++] = ch; 660 } 661 } 662 663 return p; 664 } 665 666 int32_t SCRIPT_GetStringPtr(int32_t scripthandle, char const * sectionname, char const * entryname, char ** dest) 667 { 668 ScriptSectionType *s; 669 ScriptEntryType *e; 670 char *p; 671 672 if (!SC(scripthandle)) return 1; 673 if (!SCRIPT(scripthandle,apScript)) return 1; 674 675 s = SCRIPT_SectionExists(scripthandle, sectionname); 676 e = SCRIPT_EntryExists(s, entryname); 677 678 //dest[0] = 0; 679 if (!e) return 1; 680 681 p = e->value; 682 683 SCRIPT_ParseString(dest, p); 684 685 return 0; 686 } 687 688 int32_t SCRIPT_GetString(int32_t scripthandle, char const * sectionname, char const * entryname, char * dest) 689 { 690 return SCRIPT_GetStringPtr(scripthandle, sectionname, entryname, &dest); 691 } 692 693 int32_t SCRIPT_GetDoubleString(int32_t scripthandle, const char * sectionname, const char * entryname, char * dest1, char * dest2) 694 { 695 ScriptSectionType *s; 696 ScriptEntryType *e; 697 char *p; 698 699 if (!SC(scripthandle)) return 1; 700 if (!SCRIPT(scripthandle,apScript)) return 1; 701 702 s = SCRIPT_SectionExists(scripthandle, sectionname); 703 e = SCRIPT_EntryExists(s, entryname); 704 705 //dest1[0] = 0; 706 //dest2[0] = 0; 707 if (!e) return 1; 708 709 p = e->value; 710 711 p = SCRIPT_ParseString(&dest1, p); 712 713 if (*(p-1) != '\"') 714 return 0; 715 716 while (*p == ' ' || *p == '\t') p++; 717 if (*p == 0) return 0; 718 719 SCRIPT_ParseString(&dest2, p); 720 721 return 0; 722 } 723 724 int32_t SCRIPT_GetNumber(int32_t scripthandle, const char * sectionname, const char * entryname, int32_t * number) 725 { 726 ScriptSectionType *s; 727 ScriptEntryType *e; 728 char *p; 729 730 if (!SC(scripthandle)) return 1; 731 if (!SCRIPT(scripthandle,apScript)) return 1; 732 733 s = SCRIPT_SectionExists(scripthandle, sectionname); 734 e = SCRIPT_EntryExists(s, entryname); 735 736 if (!e) return 1;// *number = 0; 737 else 738 { 739 if (e->value[0] == '0' && e->value[1] == 'x') 740 { 741 // hex 742 *number = strtol(e->value+2, &p, 16); 743 if (p == e->value+2 || (*p != 0 && *p != ' ' && *p != '\t')) return 1; 744 } 745 else 746 { 747 // decimal 748 *number = strtol(e->value, &p, 10); 749 if (p == e->value || (*p != 0 && *p != ' ' && *p != '\t')) return 1; 750 } 751 } 752 753 return 0; 754 } 755 756 int32_t SCRIPT_GetBoolean(int32_t scripthandle, char const * sectionname, char const * entryname, int32_t * boole) 757 { 758 ScriptSectionType *s; 759 ScriptEntryType *e; 760 761 if (!SC(scripthandle)) return 1; 762 if (!SCRIPT(scripthandle,apScript)) return 1; 763 764 s = SCRIPT_SectionExists(scripthandle, sectionname); 765 e = SCRIPT_EntryExists(s, entryname); 766 767 if (!e) return 1;// *boole = 0; 768 else 769 { 770 if (!Bstrncasecmp(e->value, "true", 4)) *boole = 1; 771 else if (!Bstrncasecmp(e->value, "false", 5)) *boole = 0; 772 else if (e->value[0] == '1' && (e->value[1] == ' ' || e->value[1] == '\t' || e->value[1] == 0)) *boole = 1; 773 else if (e->value[0] == '0' && (e->value[1] == ' ' || e->value[1] == '\t' || e->value[1] == 0)) *boole = 0; 774 } 775 776 return 0; 777 } 778 779 int32_t SCRIPT_GetDouble(int32_t scripthandle, const char * sectionname, const char * entryname, double * number) 780 { 781 ScriptSectionType *s; 782 ScriptEntryType *e; 783 char *p; 784 785 if (!SC(scripthandle)) return 1; 786 if (!SCRIPT(scripthandle,apScript)) return 1; 787 788 s = SCRIPT_SectionExists(scripthandle, sectionname); 789 e = SCRIPT_EntryExists(s, entryname); 790 791 if (!e) return 1;// *number = 0; 792 else 793 { 794 // decimal 795 *number = strtod(e->value, &p); 796 if (p == e->value || (*p != 0 && *p != ' ' && *p != '\t')) return 1; 797 } 798 799 return 0; 800 } 801 802 void SCRIPT_PutSection(int32_t scripthandle, char const * sectionname) 803 { 804 SCRIPT_AddSection(scripthandle, sectionname); 805 } 806 void SCRIPT_PutRaw(int32_t scripthandle, char const *sectionname, char const *entryname, char const *raw) 807 { 808 SCRIPT_AddEntry(scripthandle, sectionname, entryname, raw); 809 } 810 811 void SCRIPT_PutString(int32_t scripthandle, char const *sectionname, char const *entryname, const char *string) 812 { 813 const char *q; 814 char *raw,*p; 815 int32_t len = 3; 816 if (!string) string = ""; 817 818 for (q=string; *q; q++) 819 { 820 if (*q == '\r' || *q == '\n' || *q == '\t' || *q == '\\' || *q == '"') len+=2; 821 else if (*q >= ' ') len++; 822 } 823 p = raw = (char *)Xmalloc(len); 824 *(p++) = '"'; 825 for (q=string; *q; q++) 826 { 827 if (*q == '\r') { *(p++) = '\\'; *(p++) = 'r'; } 828 else if (*q == '\n') { *(p++) = '\\'; *(p++) = 'n'; } 829 else if (*q == '\t') { *(p++) = '\\'; *(p++) = 't'; } 830 else if (*q == '\\' || *q == '"') { *(p++) = '\\'; *(p++) = *q; } 831 else if (*q >= ' ') *(p++) = *q; 832 } 833 *(p++) = '"'; 834 *p=0; 835 836 SCRIPT_AddEntry(scripthandle, sectionname, entryname, raw); 837 Xfree(raw); 838 } 839 840 void SCRIPT_PutDoubleString 841 ( 842 int32_t scripthandle, 843 const char * sectionname, 844 const char * entryname, 845 const char * string1, 846 const char * string2 847 ) 848 { 849 const char *q; 850 char *raw,*p; 851 int32_t len = 6; 852 if (!string1) string1 = ""; 853 if (!string2) string2 = ""; 854 855 for (q=string1; *q; q++) 856 { 857 if (*q == '\r' || *q == '\n' || *q == '\t' || *q == '\\' || *q == '"') len+=2; 858 else if (*q >= ' ') len++; 859 } 860 for (q=string2; *q; q++) 861 { 862 if (*q == '\r' || *q == '\n' || *q == '\t' || *q == '\\' || *q == '"') len+=2; 863 else if (*q >= ' ') len++; 864 } 865 p = raw = (char *)Xmalloc(len); 866 *(p++) = '"'; 867 for (q=string1; *q; q++) 868 { 869 if (*q == '\r') { *(p++) = '\\'; *(p++) = 'r'; } 870 else if (*q == '\n') { *(p++) = '\\'; *(p++) = 'n'; } 871 else if (*q == '\t') { *(p++) = '\\'; *(p++) = 't'; } 872 else if (*q == '\\' || *q == '"') { *(p++) = '\\'; *(p++) = *q; } 873 else if (*q >= ' ') *(p++) = *q; 874 } 875 *(p++) = '"'; 876 *(p++) = ' '; 877 *(p++) = '"'; 878 for (q=string2; *q; q++) 879 { 880 if (*q == '\r') { *(p++) = '\\'; *(p++) = 'r'; } 881 else if (*q == '\n') { *(p++) = '\\'; *(p++) = 'n'; } 882 else if (*q == '\t') { *(p++) = '\\'; *(p++) = 't'; } 883 else if (*q == '\\' || *q == '"') { *(p++) = '\\'; *(p++) = *q; } 884 else if (*q >= ' ') *(p++) = *q; 885 } 886 *(p++) = '"'; 887 *p=0; 888 889 SCRIPT_AddEntry(scripthandle, sectionname, entryname, raw); 890 Xfree(raw); 891 } 892 893 void SCRIPT_PutNumber 894 ( 895 int32_t scripthandle, 896 const char * sectionname, 897 const char * entryname, 898 int32_t number, 899 int32_t hexadecimal, 900 int32_t defaultvalue 901 ) 902 { 903 char raw[64]; 904 905 UNREFERENCED_PARAMETER(defaultvalue); 906 if (hexadecimal) Bsprintf(raw, "0x%X", number); 907 else Bsprintf(raw, "%d", number); 908 909 SCRIPT_AddEntry(scripthandle, sectionname, entryname, raw); 910 } 911 912 void SCRIPT_PutBoolean 913 ( 914 int32_t scripthandle, 915 char const * sectionname, 916 char const * entryname, 917 int32_t boole 918 ) 919 { 920 char raw[2] = "0"; 921 922 if (boole) raw[0] = '1'; 923 924 SCRIPT_AddEntry(scripthandle, sectionname, entryname, raw); 925 } 926 927 void SCRIPT_PutDouble 928 ( 929 int32_t scripthandle, 930 char const * sectionname, 931 char const * entryname, 932 double number, 933 int32_t defaultvalue 934 ) 935 { 936 char raw[64]; 937 938 UNREFERENCED_PARAMETER(defaultvalue); 939 Bsprintf(raw, "%g", number); 940 941 SCRIPT_AddEntry(scripthandle, sectionname, entryname, raw); 942 }