1/* 2 * = = == === ===== ======== ============= ===================== 3 * == pt::rde (critcl) - Data Structures - PARAM architectural state. 4 */ 5 6#include <param.h> /* Public and private APIs */ 7#include <stack.h> /* Stack handling */ 8#include <tc.h> /* Token cache handling */ 9#include <util.h> /* Allocation utilities */ 10#include <string.h> 11 12/* 13 * = = == === ===== ======== ============= ===================== 14 */ 15 16typedef struct RDE_PARAM_ { 17 18 Tcl_Channel IN; 19 Tcl_Obj* readbuf; 20 char* CC; /* [TCL_UTF_MAX] */ 21 long int CC_len; 22 23 RDE_TC TC; 24 25 long int CL; 26 RDE_STACK LS; /* long int :: locations */ 27 28 ERROR_STATE* ER; 29 RDE_STACK ES; /* ERROR_STATE* :: errors */ 30 31 long int ST; 32 Tcl_Obj* SV; 33 34 Tcl_HashTable NC; 35 36 /* 37 * AS/ARS are actually intertwined. ARS is the top of 'ast' below, with 38 * the markers on 'mark' showing where ARS ends and AS with older ARS 39 * begins. 40 */ 41 42 RDE_STACK ast ; /* Tcl_Obj* :: ast (node) */ 43 RDE_STACK mark ; /* long int :: markers */ 44 45 /* Various non PARAM state needed, the only part. An array of all the 46 * strings needed by this state instance. The instruction implementations 47 * take indices into this array instead of the actual strings, where 48 * needed. This field is NOT owned by the state. 49 */ 50 51 long int numstr; /* String table (error messages), and its size */ 52 char** string; 53 54 /* 55 * A generic value for the higher layers to associate their own 56 * information with the parser's state. 57 */ 58 59 ClientData clientData; 60 61} RDE_PARAM_; 62 63typedef int (*UniCharClass) (int); 64 65typedef enum test_class_id { 66 tc_alnum, 67 tc_alpha, 68 tc_ascii, 69 tc_ddigit, 70 tc_digit, 71 tc_graph, 72 tc_lower, 73 tc_printable, 74 tc_punct, 75 tc_space, 76 tc_upper, 77 tc_wordchar, 78 tc_xdigit 79} test_class_id; 80 81/* 82 * = = == === ===== ======== ============= ===================== 83 */ 84 85static void ast_node_free (void* n); 86static void error_state_free (void* es); 87static void error_set (RDE_PARAM p, int s); 88static void nc_clear (RDE_PARAM p); 89 90static int UniCharIsAscii (int character); 91static int UniCharIsHexDigit (int character); 92static int UniCharIsDecDigit (int character); 93 94static void test_class (RDE_PARAM p, UniCharClass class, test_class_id id); 95static int er_int_compare (const void* a, const void* b); 96 97/* 98 * = = == === ===== ======== ============= ===================== 99 */ 100 101#define SV_INIT(p) \ 102 p->SV = NULL; \ 103 TRACE (("SV_INIT (%p => %p)", (p), (p)->SV)) 104 105#define SV_SET(p,newsv) \ 106 if (((p)->SV) != (newsv)) { \ 107 TRACE (("SV_CLEAR/set (%p => %p)", (p), (p)->SV)); \ 108 if ((p)->SV) { \ 109 Tcl_DecrRefCount ((p)->SV); \ 110 } \ 111 (p)->SV = (newsv); \ 112 TRACE (("SV_SET (%p => %p)", (p), (p)->SV)); \ 113 if ((p)->SV) { \ 114 Tcl_IncrRefCount ((p)->SV); \ 115 } \ 116 } 117 118#define SV_CLEAR(p) \ 119 TRACE (("SV_CLEAR (%p => %p)", (p), (p)->SV)); \ 120 if ((p)->SV) { \ 121 Tcl_DecrRefCount ((p)->SV); \ 122 } \ 123 (p)->SV = NULL 124 125#define ER_INIT(p) \ 126 p->ER = NULL; \ 127 TRACE (("ER_INIT (%p => %p)", (p), (p)->ER)) 128 129#define ER_CLEAR(p) \ 130 error_state_free ((p)->ER); \ 131 (p)->ER = NULL 132 133/* 134 * = = == === ===== ======== ============= ===================== 135 */ 136 137SCOPE RDE_PARAM 138rde_param_new (long int nstr, char** strings) 139{ 140 RDE_PARAM p; 141 142 ENTER ("rde_param_new"); 143 TRACE (("\tINT %d strings @ %p", nstr, strings)); 144 145 p = ALLOC (RDE_PARAM_); 146 p->numstr = nstr; 147 p->string = strings; 148 149 p->readbuf = Tcl_NewObj (); 150 Tcl_IncrRefCount (p->readbuf); 151 152 TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); 153 154 Tcl_InitHashTable (&p->NC, TCL_ONE_WORD_KEYS); 155 156 p->IN = NULL; 157 p->CL = -1; 158 p->ST = 0; 159 160 ER_INIT (p); 161 SV_INIT (p); 162 163 p->CC = NULL; 164 p->CC_len = 0; 165 166 p->TC = rde_tc_new (); 167 p->ES = rde_stack_new (error_state_free); 168 p->LS = rde_stack_new (NULL); 169 p->ast = rde_stack_new (ast_node_free); 170 p->mark = rde_stack_new (NULL); 171 172 RETURN ("%p", p); 173} 174 175SCOPE void 176rde_param_del (RDE_PARAM p) 177{ 178 ENTER ("rde_param_del"); 179 TRACE (("RDE_PARAM %p",p)); 180 181 ER_CLEAR (p); TRACE (("\ter_clear")); 182 SV_CLEAR (p); TRACE (("\tsv_clear")); 183 184 nc_clear (p); TRACE (("\tnc_clear")); 185 Tcl_DeleteHashTable (&p->NC); TRACE (("\tnc hashtable delete")); 186 187 rde_tc_del (p->TC); TRACE (("\ttc clear")); 188 rde_stack_del (p->ES); TRACE (("\tes clear")); 189 rde_stack_del (p->LS); TRACE (("\tls clear")); 190 rde_stack_del (p->ast); TRACE (("\tast clear")); 191 rde_stack_del (p->mark); TRACE (("\tmark clear")); 192 193 TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); 194 195 Tcl_DecrRefCount (p->readbuf); 196 ckfree ((char*) p); 197 198 RETURNVOID; 199} 200 201SCOPE void 202rde_param_reset (RDE_PARAM p, Tcl_Channel chan) 203{ 204 ENTER ("rde_param_reset"); 205 TRACE (("RDE_PARAM %p",p)); 206 TRACE (("Tcl_Channel %p",chan)); 207 208 p->IN = chan; 209 p->CL = -1; 210 p->ST = 0; 211 212 p->CC = NULL; 213 p->CC_len = 0; 214 215 ER_CLEAR (p); 216 SV_CLEAR (p); 217 nc_clear (p); 218 219 rde_tc_clear (p->TC); 220 rde_stack_trim (p->ES, 0); 221 rde_stack_trim (p->LS, 0); 222 rde_stack_trim (p->ast, 0); 223 rde_stack_trim (p->mark, 0); 224 225 TRACE (("\tTcl_Obj* readbuf %p used %d", p->readbuf,p->readbuf->refCount)); 226 227 RETURNVOID; 228} 229 230SCOPE void 231rde_param_update_strings (RDE_PARAM p, long int nstr, char** strings) 232{ 233 ENTER ("rde_param_update_strings"); 234 TRACE (("RDE_PARAM %p", p)); 235 TRACE (("INT %d strings", nstr)); 236 237 p->numstr = nstr; 238 p->string = strings; 239 240 RETURNVOID; 241} 242 243SCOPE void 244rde_param_data (RDE_PARAM p, char* buf, long int len) 245{ 246 (void) rde_tc_append (p->TC, buf, len); 247} 248 249SCOPE void 250rde_param_clientdata (RDE_PARAM p, ClientData clientData) 251{ 252 p->clientData = clientData; 253} 254 255/* 256 * = = == === ===== ======== ============= ===================== 257 */ 258 259static void 260nc_clear (RDE_PARAM p) 261{ 262 Tcl_HashSearch hs; 263 Tcl_HashEntry* he; 264 Tcl_HashTable* tablePtr; 265 266 for(he = Tcl_FirstHashEntry(&p->NC, &hs); 267 he != NULL; 268 he = Tcl_FirstHashEntry(&p->NC, &hs)) { 269 270 Tcl_HashSearch hsc; 271 Tcl_HashEntry* hec; 272 273 tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (he); 274 275 for(hec = Tcl_FirstHashEntry(tablePtr, &hsc); 276 hec != NULL; 277 hec = Tcl_NextHashEntry(&hsc)) { 278 279 NC_STATE* scs = Tcl_GetHashValue (hec); 280 error_state_free (scs->ER); 281 if (scs->SV) { Tcl_DecrRefCount (scs->SV); } 282 ckfree ((char*) scs); 283 } 284 285 Tcl_DeleteHashTable (tablePtr); 286 ckfree ((char*) tablePtr); 287 Tcl_DeleteHashEntry (he); 288 } 289} 290 291/* 292 * = = == === ===== ======== ============= ===================== 293 */ 294 295SCOPE ClientData 296rde_param_query_clientdata (RDE_PARAM p) 297{ 298 return p->clientData; 299} 300 301SCOPE void 302rde_param_query_amark (RDE_PARAM p, long int* mc, long int** mv) 303{ 304 rde_stack_get (p->mark, mc, (void***) mv); 305} 306 307SCOPE void 308rde_param_query_ast (RDE_PARAM p, long int* ac, Tcl_Obj*** av) 309{ 310 rde_stack_get (p->ast, ac, (void***) av); 311} 312 313SCOPE const char* 314rde_param_query_in (RDE_PARAM p) 315{ 316 return p->IN 317 ? Tcl_GetChannelName (p->IN) 318 : ""; 319} 320 321SCOPE const char* 322rde_param_query_cc (RDE_PARAM p, long int* len) 323{ 324 *len = p->CC_len; 325 return p->CC; 326} 327 328SCOPE int 329rde_param_query_cl (RDE_PARAM p) 330{ 331 return p->CL; 332} 333 334SCOPE const ERROR_STATE* 335rde_param_query_er (RDE_PARAM p) 336{ 337 return p->ER; 338} 339 340SCOPE Tcl_Obj* 341rde_param_query_er_tcl (RDE_PARAM p, const ERROR_STATE* er) 342{ 343 Tcl_Obj* res; 344 345 if (!er) { 346 /* 347 * Consider keeping one of these around in the main object state, for 348 * quick return. 349 */ 350 res = Tcl_NewStringObj ("", 0); 351 } else { 352 Tcl_Obj* ov [2]; 353 Tcl_Obj** mov; 354 long int mc, i, j; 355 long int* mv; 356 int lastid; 357 const char* msg; 358 359 rde_stack_get (er->msg, &mc, (void***) &mv); 360 361 /* 362 * Note: We are peeking inside the (message) stack here and are 363 * modifying it in place. This doesn't matter, we using the stack code 364 * for convenience, not for the ordering. 365 */ 366 367 qsort (mv, mc, sizeof (long int), er_int_compare); 368 369 /* 370 * Convert message ids to strings. We ignore duplicates, by comparing 371 * to the last processed id. Here the sorting (see above) comes into 372 * play, we know that duplicates are bunched together in runs, this 373 * makes it easy. 374 */ 375 376 mov = NALLOC (mc, Tcl_Obj*); 377 lastid = -1; 378 for (i=0, j=0; i < mc; i++) { 379 ASSERT_BOUNDS (i,mc); 380 381 if (mv [i] == lastid) continue; 382 lastid = mv [i]; 383 384 ASSERT_BOUNDS(mv[i],p->numstr); 385 msg = p->string [mv[i]]; /* inlined query_string */ 386 387 ASSERT_BOUNDS (j,mc); 388 mov [j] = Tcl_NewStringObj (msg, -1); 389 j++; 390 } 391 392 /* 393 * Assemble the result. 394 */ 395 396 ov [0] = Tcl_NewIntObj (er->loc); 397 ov [1] = Tcl_NewListObj (j, mov); 398 399 res = Tcl_NewListObj (2, ov); 400 401 ckfree ((char*) mov); 402 } 403 404 return res; 405} 406 407SCOPE void 408rde_param_query_es (RDE_PARAM p, long int* ec, ERROR_STATE*** ev) 409{ 410 rde_stack_get (p->ES, ec, (void***) ev); 411} 412 413SCOPE void 414rde_param_query_ls (RDE_PARAM p, long int* lc, long int** lv) 415{ 416 rde_stack_get (p->LS, lc, (void***) lv); 417} 418 419SCOPE Tcl_HashTable* 420rde_param_query_nc (RDE_PARAM p) 421{ 422 return &p->NC; 423} 424 425SCOPE int 426rde_param_query_st (RDE_PARAM p) 427{ 428 return p->ST; 429} 430 431SCOPE Tcl_Obj* 432rde_param_query_sv (RDE_PARAM p) 433{ 434 TRACE (("SV_QUERY %p => (%p)", (p), (p)->SV)); \ 435 return p->SV; 436} 437 438SCOPE long int 439rde_param_query_tc_size (RDE_PARAM p) 440{ 441 return rde_tc_size (p->TC); 442} 443 444SCOPE void 445rde_param_query_tc_get_s (RDE_PARAM p, long int at, long int last, char** ch, long int* len) 446{ 447 rde_tc_get_s (p->TC, at, last, ch, len); 448} 449 450SCOPE const char* 451rde_param_query_string (RDE_PARAM p, long int id) 452{ 453 TRACE (("rde_param_query_string (RDE_PARAM %p, %d/%d)", p, id, p->numstr)); 454 455 ASSERT_BOUNDS(id,p->numstr); 456 457 return p->string [id]; 458} 459 460/* 461 * = = == === ===== ======== ============= ===================== 462 */ 463 464SCOPE void 465rde_param_i_ast_pop_discard (RDE_PARAM p) 466{ 467 rde_stack_pop (p->mark, 1); 468} 469 470SCOPE void 471rde_param_i_ast_pop_rewind (RDE_PARAM p) 472{ 473 long int trim = (long int) rde_stack_top (p->mark); 474 475 ENTER ("rde_param_i_ast_pop_rewind"); 476 TRACE (("RDE_PARAM %p",p)); 477 478 rde_stack_pop (p->mark, 1); 479 rde_stack_trim (p->ast, (int) trim); 480 481 TRACE (("SV = (%p rc%d '%s')", 482 p->SV, 483 p->SV ? p->SV->refCount : -1, 484 p->SV ? Tcl_GetString (p->SV) : "")); 485 RETURNVOID; 486} 487 488SCOPE void 489rde_param_i_ast_rewind (RDE_PARAM p) 490{ 491 long int trim = (long int) rde_stack_top (p->mark); 492 493 ENTER ("rde_param_i_ast_rewind"); 494 TRACE (("RDE_PARAM %p",p)); 495 496 rde_stack_trim (p->ast, (int) trim); 497 498 TRACE (("SV = (%p rc%d '%s')", 499 p->SV, 500 p->SV ? p->SV->refCount : -1, 501 p->SV ? Tcl_GetString (p->SV) : "")); 502 RETURNVOID; 503} 504 505SCOPE void 506rde_param_i_ast_push (RDE_PARAM p) 507{ 508 rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); 509} 510 511SCOPE void 512rde_param_i_ast_value_push (RDE_PARAM p) 513{ 514 ENTER ("rde_param_i_ast_value_push"); 515 TRACE (("RDE_PARAM %p",p)); 516 517 ASSERT(p->SV,"Unable to push undefined semantic value"); 518 TRACE (("rde_param_i_ast_value_push %p => (%p)/%d", p, p->SV, )); 519 TRACE (("SV = (%p rc%d '%s')", p->SV, p->SV->refCount, Tcl_GetString (p->SV))); 520 521 rde_stack_push (p->ast, p->SV); 522 Tcl_IncrRefCount (p->SV); 523 524 RETURNVOID; 525} 526 527static void 528ast_node_free (void* n) 529{ 530 Tcl_DecrRefCount ((Tcl_Obj*) n); 531} 532 533/* 534 * = = == === ===== ======== ============= ===================== 535 */ 536 537SCOPE void 538rde_param_i_error_clear (RDE_PARAM p) 539{ 540 ER_CLEAR (p); 541} 542 543SCOPE void 544rde_param_i_error_nonterminal (RDE_PARAM p, int s) 545{ 546 long int pos; 547 if (!p->ER) return; 548 pos = 1 + (long int) rde_stack_top (p->LS); 549 if (p->ER->loc != pos) return; 550 error_set (p, s); 551 p->ER->loc = pos; 552} 553 554SCOPE void 555rde_param_i_error_pop_merge (RDE_PARAM p) 556{ 557 ERROR_STATE* top = (ERROR_STATE*) rde_stack_top (p->ES); 558 559 /* 560 * The states are identical. Nothing has to be done in that case. 561 */ 562 563 if (top == p->ER) { 564 rde_stack_pop (p->ES, 1); 565 return; 566 } 567 568 /* 569 * Saved state is nothing, keep current, discard top. 570 * No refCount to change. 571 */ 572 573 if (!top) { 574 rde_stack_pop (p->ES, 1); 575 return; 576 } 577 578 /* 579 * Current state is nothing, keep top, dicard current. We 'drop' as we are 580 * taking ownership of the error state in 'top' back from the stack. 581 */ 582 583 if (!p->ER) { 584 rde_stack_drop (p->ES, 1); 585 p->ER = top; 586 587 /* 588 * Note: The refCount of top is left unchanged. The reference lost 589 * through the drop is taken over by ER. 590 */ 591 return; 592 } 593 594 /* 595 * Both top and current have data. Compare their locations to determine 596 * which to keep, or discard, respectively. 597 * 598 * The current state is farther ahead in the input, keep it, and discard 599 * the saved information. 600 */ 601 602 if (top->loc < p->ER->loc) { 603 rde_stack_pop (p->ES, 1); 604 return; 605 } 606 607 /* 608 * The saved state is farther ahead than the current one, keep it, discard 609 * current. We 'drop' as we are taking ownership of the error state in 610 * 'top' back from the stack. 611 */ 612 613 if (top->loc > p->ER->loc) { 614 rde_stack_drop (p->ES, 1); 615 error_state_free (p->ER); 616 p->ER = top; 617 618 /* 619 * Note: The refCount of top is left unchanged. The reference lost 620 * through the drop is taken over by ER. 621 */ 622 return; 623 } 624 625 /* 626 * Both states describe the same location. We merge the message sets. We 627 * do not make the set unique however. This can be defered until the data 628 * is actually retrieved by the user of the PARAM. 629 */ 630 631 rde_stack_move (p->ER->msg, top->msg); 632 rde_stack_pop (p->ES, 1); 633} 634 635SCOPE void 636rde_param_i_error_push (RDE_PARAM p) 637{ 638 rde_stack_push (p->ES, p->ER); 639 if (p->ER) { p->ER->refCount ++; } 640} 641 642static void 643error_set (RDE_PARAM p, int s) 644{ 645 error_state_free (p->ER); 646 647 p->ER = ALLOC (ERROR_STATE); 648 p->ER->refCount = 1; 649 p->ER->loc = p->CL; 650 p->ER->msg = rde_stack_new (NULL); 651 652 ASSERT_BOUNDS(s,p->numstr); 653 654 rde_stack_push (p->ER->msg, (void*) s); 655} 656 657static void 658error_state_free (void* esx) 659{ 660 ERROR_STATE* es = esx; 661 662 if (!es) return; 663 664 es->refCount --; 665 if (es->refCount > 0) return; 666 667 rde_stack_del (es->msg); 668 ckfree ((char*) es); 669} 670 671/* 672 * = = == === ===== ======== ============= ===================== 673 */ 674 675SCOPE void 676rde_param_i_loc_pop_discard (RDE_PARAM p) 677{ 678 rde_stack_pop (p->LS, 1); 679} 680 681SCOPE void 682rde_param_i_loc_pop_rewind (RDE_PARAM p) 683{ 684 p->CL = (long int) rde_stack_top (p->LS); 685 rde_stack_pop (p->LS, 1); 686} 687 688SCOPE void 689rde_param_i_loc_push (RDE_PARAM p) 690{ 691 rde_stack_push (p->LS, (void*) p->CL); 692} 693 694SCOPE void 695rde_param_i_loc_rewind (RDE_PARAM p) 696{ 697 p->CL = (long int) rde_stack_top (p->LS); 698} 699 700/* 701 * = = == === ===== ======== ============= ===================== 702 */ 703 704SCOPE void 705rde_param_i_input_next (RDE_PARAM p, int m) 706{ 707 int leni; 708 char* ch; 709 710 ASSERT_BOUNDS(m,p->numstr); 711 712 p->CL ++; 713 714 if (p->CL < rde_tc_size (p->TC)) { 715 /* 716 * We are at a known position, we can and do take the associated 717 * character out of the token cache. 718 * 719 * FUTURE :: keep track of what location the data stored in CC is 720 * for. If the location is identical now extraction is required. This 721 * may help when a choice repeatedly tests the same character. 722 */ 723 724 rde_tc_get (p->TC, p->CL, &p->CC, &p->CC_len); 725 ASSERT_BOUNDS (p->CC_len, TCL_UTF_MAX); 726 727 p->ST = 1; 728 ER_CLEAR (p); 729 return; 730 } 731 732 if (!p->IN || 733 Tcl_Eof (p->IN) || 734 (Tcl_ReadChars (p->IN, p->readbuf, 1, 0) <= 0)) { 735 /* 736 * As we are outside of the known range we tried to read a character 737 * from the input, to extend the token cache with. That failed. 738 */ 739 740 p->ST = 0; 741 error_set (p, m); 742 return; 743 } 744 745 /* 746 * We got a new character, we now extend the token cache, and also make it 747 * current. 748 */ 749 750 ch = Tcl_GetStringFromObj (p->readbuf, &leni); 751 ASSERT_BOUNDS (leni, TCL_UTF_MAX); 752 753 p->CC = rde_tc_append (p->TC, ch, leni); 754 p->CC_len = leni; 755 756 p->ST = 1; 757 ER_CLEAR (p); 758} 759 760/* 761 * = = == === ===== ======== ============= ===================== 762 */ 763 764SCOPE void 765rde_param_i_status_fail (RDE_PARAM p) 766{ 767 p->ST = 0; 768} 769 770SCOPE void 771rde_param_i_status_ok (RDE_PARAM p) 772{ 773 p->ST = 1; 774} 775 776SCOPE void 777rde_param_i_status_negate (RDE_PARAM p) 778{ 779 p->ST = !p->ST; 780} 781 782/* 783 * = = == === ===== ======== ============= ===================== 784 */ 785 786SCOPE int 787rde_param_i_symbol_restore (RDE_PARAM p, int s) 788{ 789 NC_STATE* scs; 790 Tcl_HashEntry* hPtr; 791 Tcl_HashTable* tablePtr; 792 793 /* 794 * 2-level hash table keyed by location, and symbol ... 795 */ 796 797 hPtr = Tcl_FindHashEntry (&p->NC, (char*) p->CL); 798 if (!hPtr) { return 0; } 799 800 tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); 801 hPtr = Tcl_FindHashEntry (tablePtr, (char*) s); 802 if (!hPtr) { return 0; } 803 804 /* 805 * Found information, apply it to the state, restoring the cached 806 * situation. 807 */ 808 809 scs = Tcl_GetHashValue (hPtr); 810 811 p->CL = scs->CL; 812 p->ST = scs->ST; 813 814 error_state_free (p->ER); 815 p->ER = scs->ER; 816 if (p->ER) { p->ER->refCount ++; } 817 818 TRACE (("SV_RESTORE (%p) '%s'",scs->SV, scs->SV ? Tcl_GetString (scs->SV):"")); 819 820 SV_SET (p, scs->SV); 821 822 return 1; 823} 824 825SCOPE void 826rde_param_i_symbol_save (RDE_PARAM p, int s) 827{ 828 long int at = (long int) rde_stack_top (p->LS); 829 NC_STATE* scs; 830 Tcl_HashEntry* hPtr; 831 Tcl_HashTable* tablePtr; 832 int isnew; 833 834 ENTER ("rde_param_i_symbol_save"); 835 TRACE (("RDE_PARAM %p",p)); 836 TRACE (("INT %d",s)); 837 838 /* 839 * 2-level hash table keyed by location, and symbol ... 840 */ 841 842 hPtr = Tcl_CreateHashEntry (&p->NC, (char*) at, &isnew); 843 844 if (isnew) { 845 tablePtr = ALLOC (Tcl_HashTable); 846 Tcl_InitHashTable (tablePtr, TCL_ONE_WORD_KEYS); 847 Tcl_SetHashValue (hPtr, tablePtr); 848 } else { 849 tablePtr = (Tcl_HashTable*) Tcl_GetHashValue (hPtr); 850 } 851 852 hPtr = Tcl_CreateHashEntry (tablePtr, (char*) s, &isnew); 853 854 if (isnew) { 855 /* 856 * Copy state into new cache entry. 857 */ 858 859 scs = ALLOC (NC_STATE); 860 scs->CL = p->CL; 861 scs->ST = p->ST; 862 863 TRACE (("SV_CACHE (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "")); 864 865 scs->SV = p->SV; 866 if (scs->SV) { Tcl_IncrRefCount (scs->SV); } 867 868 scs->ER = p->ER; 869 if (scs->ER) { scs->ER->refCount ++; } 870 871 Tcl_SetHashValue (hPtr, scs); 872 } else { 873 /* 874 * Copy state into existing cache entry, overwriting the previous 875 * information. 876 */ 877 878 scs = (NC_STATE*) Tcl_GetHashValue (hPtr); 879 880 scs->CL = p->CL; 881 scs->ST = p->ST; 882 883 TRACE (("SV_CACHE/over (%p '%s')", p->SV, p->SV ? Tcl_GetString(p->SV) : "" )); 884 885 if (scs->SV) { Tcl_DecrRefCount (scs->SV); } 886 scs->SV = p->SV; 887 if (scs->SV) { Tcl_IncrRefCount (scs->SV); } 888 889 error_state_free (scs->ER); 890 scs->ER = p->ER; 891 if (scs->ER) { scs->ER->refCount ++; } 892 } 893 894 TRACE (("SV = (%p rc%d '%s')", 895 p->SV, 896 p->SV ? p->SV->refCount : -1, 897 p->SV ? Tcl_GetString (p->SV) : "")); 898 RETURNVOID; 899} 900 901/* 902 * = = == === ===== ======== ============= ===================== 903 */ 904 905SCOPE void 906rde_param_i_test_alnum (RDE_PARAM p) 907{ 908 test_class (p, Tcl_UniCharIsAlnum, tc_alnum); 909} 910 911SCOPE void 912rde_param_i_test_alpha (RDE_PARAM p) 913{ 914 test_class (p, Tcl_UniCharIsAlpha, tc_alpha); 915} 916 917SCOPE void 918rde_param_i_test_ascii (RDE_PARAM p) 919{ 920 test_class (p, UniCharIsAscii, tc_ascii); 921} 922 923SCOPE void 924rde_param_i_test_char (RDE_PARAM p, char* c, int msg) 925{ 926 ASSERT_BOUNDS(msg,p->numstr); 927 928 p->ST = Tcl_UtfNcmp (p->CC, c, 1) == 0; 929 930 if (p->ST) { 931 ER_CLEAR (p); 932 } else { 933 error_set (p, msg); 934 p->CL --; 935 } 936} 937 938SCOPE void 939rde_param_i_test_ddigit (RDE_PARAM p) 940{ 941 test_class (p, UniCharIsDecDigit, tc_ddigit); 942} 943 944SCOPE void 945rde_param_i_test_digit (RDE_PARAM p) 946{ 947 test_class (p, Tcl_UniCharIsDigit, tc_digit); 948} 949 950SCOPE void 951rde_param_i_test_graph (RDE_PARAM p) 952{ 953 test_class (p, Tcl_UniCharIsGraph, tc_graph); 954} 955 956SCOPE void 957rde_param_i_test_lower (RDE_PARAM p) 958{ 959 test_class (p, Tcl_UniCharIsLower, tc_lower); 960} 961 962SCOPE void 963rde_param_i_test_print (RDE_PARAM p) 964{ 965 test_class (p, Tcl_UniCharIsPrint, tc_printable); 966} 967 968SCOPE void 969rde_param_i_test_punct (RDE_PARAM p) 970{ 971 test_class (p, Tcl_UniCharIsPunct, tc_punct); 972} 973 974SCOPE void 975rde_param_i_test_range (RDE_PARAM p, char* s, char* e, int msg) 976{ 977 ASSERT_BOUNDS(msg,p->numstr); 978 979 p->ST = 980 (Tcl_UtfNcmp (s, p->CC, 1) <= 0) && 981 (Tcl_UtfNcmp (p->CC, e, 1) <= 0); 982 983 if (p->ST) { 984 ER_CLEAR (p); 985 } else { 986 error_set (p, msg); 987 p->CL --; 988 } 989} 990 991SCOPE void 992rde_param_i_test_space (RDE_PARAM p) 993{ 994 test_class (p, Tcl_UniCharIsSpace, tc_space); 995} 996 997SCOPE void 998rde_param_i_test_upper (RDE_PARAM p) 999{ 1000 test_class (p, Tcl_UniCharIsUpper, tc_upper); 1001} 1002 1003SCOPE void 1004rde_param_i_test_wordchar (RDE_PARAM p) 1005{ 1006 test_class (p, Tcl_UniCharIsWordChar, tc_wordchar); 1007} 1008 1009SCOPE void 1010rde_param_i_test_xdigit (RDE_PARAM p) 1011{ 1012 test_class (p, UniCharIsHexDigit, tc_xdigit); 1013} 1014 1015static void 1016test_class (RDE_PARAM p, UniCharClass class, test_class_id id) 1017{ 1018 Tcl_UniChar ch; 1019 Tcl_UtfToUniChar(p->CC, &ch); 1020 1021 ASSERT_BOUNDS(id,p->numstr); 1022 1023 p->ST = !!class (ch); 1024 1025 /* The double-negation normalizes the output of the class function to the 1026 * regular booleans 0 and 1. 1027 */ 1028 1029 if (p->ST) { 1030 ER_CLEAR (p); 1031 } else { 1032 error_set (p, id); 1033 p->CL --; 1034 } 1035} 1036 1037static int 1038UniCharIsAscii (int character) 1039{ 1040 return (character >= 0) && (character < 0x80); 1041} 1042 1043static int 1044UniCharIsHexDigit (int character) 1045{ 1046 return (character >= 0) && (character < 0x80) && isxdigit(character); 1047} 1048 1049static int 1050UniCharIsDecDigit (int character) 1051{ 1052 return (character >= 0) && (character < 0x80) && isdigit(character); 1053} 1054 1055/* 1056 * = = == === ===== ======== ============= ===================== 1057 */ 1058 1059SCOPE void 1060rde_param_i_value_clear (RDE_PARAM p) 1061{ 1062 SV_CLEAR (p); 1063} 1064 1065SCOPE void 1066rde_param_i_value_leaf (RDE_PARAM p, int s) 1067{ 1068 Tcl_Obj* newsv; 1069 Tcl_Obj* ov [3]; 1070 long int pos = 1 + (long int) rde_stack_top (p->LS); 1071 1072 ASSERT_BOUNDS(s,p->numstr); 1073 1074 ov [0] = Tcl_NewStringObj (p->string[s], -1); 1075 ov [1] = Tcl_NewIntObj (pos); 1076 ov [2] = Tcl_NewIntObj (p->CL); 1077 1078 newsv = Tcl_NewListObj (3, ov); 1079 1080 TRACE (("rde_param_i_value_leaf => '%s'",Tcl_GetString (newsv))); 1081 1082 SV_SET (p, newsv); 1083} 1084 1085SCOPE void 1086rde_param_i_value_reduce (RDE_PARAM p, int s) 1087{ 1088 Tcl_Obj* newsv; 1089 int oc, i, j; 1090 Tcl_Obj** ov; 1091 long int ac; 1092 Tcl_Obj** av; 1093 1094 long int pos = 1 + (long int) rde_stack_top (p->LS); 1095 long int mark = (long int) rde_stack_top (p->mark); 1096 long int asize = rde_stack_size (p->ast); 1097 long int new = asize - mark; 1098 1099 ASSERT (new >= 0, "Bad number of elements to reduce"); 1100 1101 ov = NALLOC (3+new, Tcl_Obj*); 1102 1103 ASSERT_BOUNDS(s,p->numstr); 1104 1105 ov [0] = Tcl_NewStringObj (p->string[s], -1); 1106 ov [1] = Tcl_NewIntObj (pos); 1107 ov [2] = Tcl_NewIntObj (p->CL); 1108 1109 rde_stack_get (p->ast, &ac, (void***) &av); 1110 for (i = 3, j = mark; j < asize; i++, j++) { 1111 ASSERT_BOUNDS (i, 3+new); 1112 ASSERT_BOUNDS (j, ac); 1113 ov [i] = av [j]; 1114 } 1115 1116 ASSERT (i == 3+new, "Reduction result incomplete"); 1117 newsv = Tcl_NewListObj (3+new, ov); 1118 1119 TRACE (("rde_param_i_value_reduce => '%s'",Tcl_GetString (newsv))); 1120 1121 SV_SET (p, newsv); 1122 ckfree ((char*) ov); 1123} 1124 1125/* 1126 * = = == === ===== ======== ============= ===================== 1127 */ 1128 1129static int 1130er_int_compare (const void* a, const void* b) 1131{ 1132 long int ai = *((long int*) a); 1133 long int bi = *((long int*) b); 1134 1135 if (ai < bi) { return -1; } 1136 if (ai > bi) { return 1; } 1137 return 0; 1138} 1139 1140/* 1141 * = = == === ===== ======== ============= ===================== 1142 * == Super Instructions. 1143 */ 1144 1145SCOPE int 1146rde_param_i_symbol_start (RDE_PARAM p, int s) 1147{ 1148 if (rde_param_i_symbol_restore (p, s)) { 1149 if (p->ST) { 1150 rde_stack_push (p->ast, p->SV); 1151 Tcl_IncrRefCount (p->SV); 1152 } 1153 return 1; 1154 } 1155 1156 rde_stack_push (p->LS, (void*) p->CL); 1157 return 0; 1158} 1159 1160SCOPE int 1161rde_param_i_symbol_start_d (RDE_PARAM p, int s) 1162{ 1163 if (rde_param_i_symbol_restore (p, s)) { 1164 if (p->ST) { 1165 rde_stack_push (p->ast, p->SV); 1166 Tcl_IncrRefCount (p->SV); 1167 } 1168 return 1; 1169 } 1170 1171 rde_stack_push (p->LS, (void*) p->CL); 1172 rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); 1173 return 0; 1174} 1175 1176SCOPE int 1177rde_param_i_symbol_void_start (RDE_PARAM p, int s) 1178{ 1179 if (rde_param_i_symbol_restore (p, s)) return 1; 1180 1181 rde_stack_push (p->LS, (void*) p->CL); 1182 return 0; 1183} 1184 1185SCOPE int 1186rde_param_i_symbol_void_start_d (RDE_PARAM p, int s) 1187{ 1188 if (rde_param_i_symbol_restore (p, s)) return 1; 1189 1190 rde_stack_push (p->LS, (void*) p->CL); 1191 rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); 1192 return 0; 1193} 1194 1195SCOPE void 1196rde_param_i_symbol_done_d_reduce (RDE_PARAM p, int s, int m) 1197{ 1198 if (p->ST) { 1199 rde_param_i_value_reduce (p, s); 1200 } else { 1201 SV_CLEAR (p); 1202 } 1203 1204 rde_param_i_symbol_save (p, s); 1205 rde_param_i_error_nonterminal (p, m); 1206 rde_param_i_ast_pop_rewind (p); 1207 1208 rde_stack_pop (p->LS, 1); 1209 1210 if (p->ST) { 1211 rde_stack_push (p->ast, p->SV); 1212 Tcl_IncrRefCount (p->SV); 1213 } 1214} 1215 1216SCOPE void 1217rde_param_i_symbol_done_leaf (RDE_PARAM p, int s, int m) 1218{ 1219 if (p->ST) { 1220 rde_param_i_value_leaf (p, s); 1221 } else { 1222 SV_CLEAR (p); 1223 } 1224 1225 rde_param_i_symbol_save (p, s); 1226 rde_param_i_error_nonterminal (p, m); 1227 1228 rde_stack_pop (p->LS, 1); 1229 1230 if (p->ST) { 1231 rde_stack_push (p->ast, p->SV); 1232 Tcl_IncrRefCount (p->SV); 1233 } 1234} 1235 1236SCOPE void 1237rde_param_i_symbol_done_d_leaf (RDE_PARAM p, int s, int m) 1238{ 1239 if (p->ST) { 1240 rde_param_i_value_leaf (p, s); 1241 } else { 1242 SV_CLEAR (p); 1243 } 1244 1245 rde_param_i_symbol_save (p, s); 1246 rde_param_i_error_nonterminal (p, m); 1247 rde_param_i_ast_pop_rewind (p); 1248 1249 rde_stack_pop (p->LS, 1); 1250 1251 if (p->ST) { 1252 rde_stack_push (p->ast, p->SV); 1253 Tcl_IncrRefCount (p->SV); 1254 } 1255} 1256 1257SCOPE void 1258rde_param_i_symbol_done_void (RDE_PARAM p, int s, int m) 1259{ 1260 SV_CLEAR (p); 1261 rde_param_i_symbol_save (p, s); 1262 rde_param_i_error_nonterminal (p, m); 1263 1264 rde_stack_pop (p->LS, 1); 1265} 1266 1267SCOPE void 1268rde_param_i_symbol_done_d_void (RDE_PARAM p, int s, int m) 1269{ 1270 SV_CLEAR (p); 1271 rde_param_i_symbol_save (p, s); 1272 rde_param_i_error_nonterminal (p, m); 1273 rde_param_i_ast_pop_rewind (p); 1274 1275 rde_stack_pop (p->LS, 1); 1276} 1277 1278/* 1279 * = = == === ===== ======== ============= ===================== 1280 */ 1281 1282SCOPE void 1283rde_param_i_next_char (RDE_PARAM p, char* c, int m) 1284{ 1285 rde_param_i_input_next (p, m); 1286 if (!p->ST) return; 1287 rde_param_i_test_char (p, c, m); 1288} 1289 1290SCOPE void 1291rde_param_i_next_range (RDE_PARAM p, char* s, char* e, int m) 1292{ 1293 rde_param_i_input_next (p, m); 1294 if (!p->ST) return; 1295 rde_param_i_test_range (p, s, e, m); 1296} 1297 1298SCOPE void 1299rde_param_i_next_alnum (RDE_PARAM p, int m) 1300{ 1301 rde_param_i_input_next (p, m); 1302 if (!p->ST) return; 1303 rde_param_i_test_alnum (p); 1304} 1305 1306SCOPE void 1307rde_param_i_next_alpha (RDE_PARAM p, int m) 1308{ 1309 rde_param_i_input_next (p, m); 1310 if (!p->ST) return; 1311 rde_param_i_test_alpha (p); 1312} 1313 1314SCOPE void 1315rde_param_i_next_ascii (RDE_PARAM p, int m) 1316{ 1317 rde_param_i_input_next (p, m); 1318 if (!p->ST) return; 1319 rde_param_i_test_ascii (p); 1320} 1321 1322SCOPE void 1323rde_param_i_next_ddigit (RDE_PARAM p, int m) 1324{ 1325 rde_param_i_input_next (p, m); 1326 if (!p->ST) return; 1327 rde_param_i_test_ddigit (p); 1328} 1329 1330SCOPE void 1331rde_param_i_next_digit (RDE_PARAM p, int m) 1332{ 1333 rde_param_i_input_next (p, m); 1334 if (!p->ST) return; 1335 rde_param_i_test_digit (p); 1336} 1337 1338SCOPE void 1339rde_param_i_next_graph (RDE_PARAM p, int m) 1340{ 1341 rde_param_i_input_next (p, m); 1342 if (!p->ST) return; 1343 rde_param_i_test_graph (p); 1344} 1345 1346SCOPE void 1347rde_param_i_next_lower (RDE_PARAM p, int m) 1348{ 1349 rde_param_i_input_next (p, m); 1350 if (!p->ST) return; 1351 rde_param_i_test_lower (p); 1352} 1353 1354SCOPE void 1355rde_param_i_next_print (RDE_PARAM p, int m) 1356{ 1357 rde_param_i_input_next (p, m); 1358 if (!p->ST) return; 1359 rde_param_i_test_print (p); 1360} 1361 1362SCOPE void 1363rde_param_i_next_punct (RDE_PARAM p, int m) 1364{ 1365 rde_param_i_input_next (p, m); 1366 if (!p->ST) return; 1367 rde_param_i_test_punct (p); 1368} 1369 1370SCOPE void 1371rde_param_i_next_space (RDE_PARAM p, int m) 1372{ 1373 rde_param_i_input_next (p, m); 1374 if (!p->ST) return; 1375 rde_param_i_test_space (p); 1376} 1377 1378SCOPE void 1379rde_param_i_next_upper (RDE_PARAM p, int m) 1380{ 1381 rde_param_i_input_next (p, m); 1382 if (!p->ST) return; 1383 rde_param_i_test_upper (p); 1384} 1385 1386SCOPE void 1387rde_param_i_next_wordchar (RDE_PARAM p, int m) 1388{ 1389 rde_param_i_input_next (p, m); 1390 if (!p->ST) return; 1391 rde_param_i_test_wordchar (p); 1392} 1393 1394SCOPE void 1395rde_param_i_next_xdigit (RDE_PARAM p, int m) 1396{ 1397 rde_param_i_input_next (p, m); 1398 if (!p->ST) return; 1399 rde_param_i_test_xdigit (p); 1400} 1401 1402SCOPE void 1403rde_param_i_notahead_start_d (RDE_PARAM p) 1404{ 1405 rde_stack_push (p->LS, (void*) p->CL); 1406 rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); 1407} 1408 1409SCOPE void 1410rde_param_i_notahead_exit_d (RDE_PARAM p) 1411{ 1412 if (p->ST) { 1413 rde_param_i_ast_pop_rewind (p); 1414 } else { 1415 rde_stack_pop (p->mark, 1); 1416 } 1417 p->CL = (long int) rde_stack_top (p->LS); 1418 rde_stack_pop (p->LS, 1); 1419 p->ST = !p->ST; 1420} 1421 1422SCOPE void 1423rde_param_i_notahead_exit (RDE_PARAM p) 1424{ 1425 p->CL = (long int) rde_stack_top (p->LS); 1426 rde_stack_pop (p->LS, 1); 1427 p->ST = !p->ST; 1428} 1429 1430/* 1431 * = = == === ===== ======== ============= ===================== 1432 */ 1433 1434SCOPE void 1435rde_param_i_state_push_2 (RDE_PARAM p) 1436{ 1437 /* loc_push + error_push */ 1438 rde_stack_push (p->LS, (void*) p->CL); 1439 rde_stack_push (p->ES, p->ER); 1440 if (p->ER) { p->ER->refCount ++; } 1441} 1442 1443SCOPE void 1444rde_param_i_state_push_void (RDE_PARAM p) 1445{ 1446 rde_stack_push (p->LS, (void*) p->CL); 1447 ER_CLEAR (p); 1448 rde_stack_push (p->ES, p->ER); 1449 /* if (p->ER) { p->ER->refCount ++; } */ 1450} 1451 1452SCOPE void 1453rde_param_i_state_push_value (RDE_PARAM p) 1454{ 1455 rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); 1456 rde_stack_push (p->LS, (void*) p->CL); 1457 ER_CLEAR (p); 1458 rde_stack_push (p->ES, p->ER); 1459 /* if (p->ER) { p->ER->refCount ++; } */ 1460} 1461 1462/* 1463 * = = == === ===== ======== ============= ===================== 1464 */ 1465 1466SCOPE void 1467rde_param_i_state_merge_ok (RDE_PARAM p) 1468{ 1469 rde_param_i_error_pop_merge (p); 1470 1471 if (!p->ST) { 1472 p->ST = 1; 1473 p->CL = (long int) rde_stack_top (p->LS); 1474 } 1475 rde_stack_pop (p->LS, 1); 1476} 1477 1478SCOPE void 1479rde_param_i_state_merge_void (RDE_PARAM p) 1480{ 1481 rde_param_i_error_pop_merge (p); 1482 1483 if (!p->ST) { 1484 p->CL = (long int) rde_stack_top (p->LS); 1485 } 1486 rde_stack_pop (p->LS, 1); 1487} 1488 1489SCOPE void 1490rde_param_i_state_merge_value (RDE_PARAM p) 1491{ 1492 rde_param_i_error_pop_merge (p); 1493 1494 if (!p->ST) { 1495 long int trim = (long int) rde_stack_top (p->mark); 1496 rde_stack_trim (p->ast, (int) trim); 1497 p->CL = (long int) rde_stack_top (p->LS); 1498 } 1499 rde_stack_pop (p->mark, 1); 1500 rde_stack_pop (p->LS, 1); 1501} 1502 1503/* 1504 * = = == === ===== ======== ============= ===================== 1505 */ 1506 1507SCOPE int 1508rde_param_i_kleene_close (RDE_PARAM p) 1509{ 1510 int stop = !p->ST; 1511 rde_param_i_error_pop_merge (p); 1512 1513 if (stop) { 1514 p->ST = 1; 1515 p->CL = (long int) rde_stack_top (p->LS); 1516 } 1517 1518 rde_stack_pop (p->LS, 1); 1519 return stop; 1520} 1521 1522SCOPE int 1523rde_param_i_kleene_abort (RDE_PARAM p) 1524{ 1525 int stop = !p->ST; 1526 1527 if (stop) { 1528 p->CL = (long int) rde_stack_top (p->LS); 1529 } 1530 1531 rde_stack_pop (p->LS, 1); 1532 return stop; 1533} 1534 1535/* 1536 * = = == === ===== ======== ============= ===================== 1537 */ 1538 1539SCOPE int 1540rde_param_i_seq_void2void (RDE_PARAM p) 1541{ 1542 rde_param_i_error_pop_merge (p); 1543 1544 if (p->ST) { 1545 rde_stack_push (p->ES, p->ER); 1546 if (p->ER) { p->ER->refCount ++; } 1547 return 0; 1548 } else { 1549 p->CL = (long int) rde_stack_top (p->LS); 1550 rde_stack_pop (p->LS, 1); 1551 return 1; 1552 } 1553} 1554 1555SCOPE int 1556rde_param_i_seq_void2value (RDE_PARAM p) 1557{ 1558 rde_param_i_error_pop_merge (p); 1559 1560 if (p->ST) { 1561 rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); 1562 rde_stack_push (p->ES, p->ER); 1563 if (p->ER) { p->ER->refCount ++; } 1564 return 0; 1565 } else { 1566 p->CL = (long int) rde_stack_top (p->LS); 1567 rde_stack_pop (p->LS, 1); 1568 return 1; 1569 } 1570} 1571 1572SCOPE int 1573rde_param_i_seq_value2value (RDE_PARAM p) 1574{ 1575 rde_param_i_error_pop_merge (p); 1576 1577 if (p->ST) { 1578 rde_stack_push (p->ES, p->ER); 1579 if (p->ER) { p->ER->refCount ++; } 1580 return 0; 1581 } else { 1582 long int trim = (long int) rde_stack_top (p->mark); 1583 1584 rde_stack_pop (p->mark, 1); 1585 rde_stack_trim (p->ast, (int) trim); 1586 1587 p->CL = (long int) rde_stack_top (p->LS); 1588 rde_stack_pop (p->LS, 1); 1589 return 1; 1590 } 1591} 1592 1593/* 1594 * = = == === ===== ======== ============= ===================== 1595 */ 1596 1597SCOPE int 1598rde_param_i_bra_void2void (RDE_PARAM p) 1599{ 1600 rde_param_i_error_pop_merge (p); 1601 1602 if (p->ST) { 1603 rde_stack_pop (p->LS, 1); 1604 } else { 1605 p->CL = (long int) rde_stack_top (p->LS); 1606 1607 rde_stack_push (p->ES, p->ER); 1608 if (p->ER) { p->ER->refCount ++; } 1609 } 1610 1611 return p->ST; 1612} 1613 1614SCOPE int 1615rde_param_i_bra_void2value (RDE_PARAM p) 1616{ 1617 rde_param_i_error_pop_merge (p); 1618 1619 if (p->ST) { 1620 rde_stack_pop (p->LS, 1); 1621 } else { 1622 rde_stack_push (p->mark, (void*) rde_stack_size (p->ast)); 1623 p->CL = (long int) rde_stack_top (p->LS); 1624 1625 rde_stack_push (p->ES, p->ER); 1626 if (p->ER) { p->ER->refCount ++; } 1627 } 1628 1629 return p->ST; 1630} 1631 1632SCOPE int 1633rde_param_i_bra_value2void (RDE_PARAM p) 1634{ 1635 rde_param_i_error_pop_merge (p); 1636 1637 if (p->ST) { 1638 rde_stack_pop (p->mark, 1); 1639 rde_stack_pop (p->LS, 1); 1640 } else { 1641 long int trim = (long int) rde_stack_top (p->mark); 1642 rde_stack_pop (p->mark, 1); 1643 rde_stack_trim (p->ast, (int) trim); 1644 1645 p->CL = (long int) rde_stack_top (p->LS); 1646 1647 rde_stack_push (p->ES, p->ER); 1648 if (p->ER) { p->ER->refCount ++; } 1649 } 1650 1651 return p->ST; 1652} 1653 1654SCOPE int 1655rde_param_i_bra_value2value (RDE_PARAM p) 1656{ 1657 rde_param_i_error_pop_merge (p); 1658 1659 if (p->ST) { 1660 rde_stack_pop (p->mark, 1); 1661 rde_stack_pop (p->LS, 1); 1662 } else { 1663 long int trim = (long int) rde_stack_top (p->mark); 1664 rde_stack_trim (p->ast, (int) trim); 1665 1666 p->CL = (long int) rde_stack_top (p->LS); 1667 1668 rde_stack_push (p->ES, p->ER); 1669 if (p->ER) { p->ER->refCount ++; } 1670 } 1671 1672 return p->ST; 1673} 1674 1675/* 1676 * = = == === ===== ======== ============= ===================== 1677 */ 1678 1679SCOPE void 1680rde_param_i_next_str (RDE_PARAM p, char* str, int m) 1681{ 1682 int at = p->CL; 1683 1684 while (*str) { 1685 rde_param_i_input_next (p, m); 1686 if (!p->ST) { 1687 p->CL = at; 1688 return; 1689 } 1690 1691 rde_param_i_test_char (p, str, m); 1692 if (!p->ST) { 1693 p->CL = at; 1694 return; 1695 } 1696 1697 str = Tcl_UtfNext (str); 1698 } 1699} 1700 1701SCOPE void 1702rde_param_i_next_class (RDE_PARAM p, char* class, int m) 1703{ 1704 rde_param_i_input_next (p, m); 1705 if (!p->ST) return; 1706 1707 while (*class) { 1708 p->ST = Tcl_UtfNcmp (p->CC, class, 1) == 0; 1709 1710 if (p->ST) { 1711 ER_CLEAR (p); 1712 return; 1713 } 1714 1715 class = Tcl_UtfNext (class); 1716 } 1717 1718 error_set (p, m); 1719 p->CL --; 1720} 1721 1722/* 1723 * = = == === ===== ======== ============= ===================== 1724 */ 1725 1726 1727/* 1728 * local Variables: 1729 * mode: c 1730 * c-basic-offset: 4 1731 * fill-column: 78 1732 * End: 1733 */ 1734