static remset_t * create_labelled_remset_with_owner_attrib ( int tbl_entries, /* size of hash table, 0=default */ int pool_entries, /* size of remset, 0 = default */ int major_id, /* for stats */ int minor_id, /* for stats */ unsigned owner_attrib ) { word *heapptr; remset_t *rs; remset_data_t *data; pool_t *p; assert( tbl_entries >= 0 && (tbl_entries == 0 || ilog2( tbl_entries ) != -1)); assert( pool_entries >= 0 ); if (pool_entries == 0) pool_entries = DEFAULT_REMSET_POOLSIZE; if (tbl_entries == 0) tbl_entries = DEFAULT_REMSET_TBLSIZE; annoyingmsg( "Allocated remembered set\n hash=%d pool=%d", tbl_entries, pool_entries ); rs = (remset_t*)must_malloc( sizeof( remset_t ) ); data = (remset_data_t*)must_malloc( sizeof( remset_data_t ) ); while(1) { heapptr = gclib_alloc_rts( tbl_entries*sizeof(word), owner_attrib ); if (heapptr != 0) break; memfail( MF_RTS, "Can't allocate table and SSB for remembered set." ); } /* Hash table */ data->tbl_bot = heapptr; heapptr += tbl_entries; data->tbl_lim = heapptr; /* Node pool */ p = allocate_pool_segment( pool_entries, data->mem_attribute ); /* XXX */ data->first_pool = data->curr_pool = p; assert( data->curr_pool != 0 ); data->numpools = 1; /* Misc */ memset( &data->stats, 0, sizeof( data->stats )); data->pool_entries = pool_entries; data->self = stats_new_remembered_set( major_id, minor_id ); data->mem_attribute = owner_attrib; rs->live = 0; rs->has_overflowed = FALSE; rs->data = data; rs_clear( rs ); return rs; }
/* * NAME: parse_grammar() * DESCRIPTION: check the grammar, return a pre-processed version */ string *parse_grammar(string *gram) { char buffer[STRINGSZ]; hashtab *ruletab, *strtab; rschunk *rschunks; rlchunk *rlchunks; rule *rgxlist, *strlist, *estrlist, *prodlist, *tmplist, *rr, *rrl; int token, ruleno, nrgx, nstr, nestr, nprod; ssizet glen; unsigned int buflen; bool nomatch; rulesym **rs; rule *rl, **r; long size; unsigned int len; # if MAX_STRLEN > 0xffffffL if (gram->len > 0xffffffL) { error("Grammar string too large"); } # endif /* initialize */ ruletab = ht_new(PARSERULTABSZ, PARSERULHASHSZ, FALSE); strtab = ht_new(PARSERULTABSZ, PARSERULHASHSZ, FALSE); rschunks = (rschunk *) NULL; rlchunks = (rlchunk *) NULL; rgxlist = strlist = estrlist = prodlist = tmplist = (rule *) NULL; nrgx = nstr = nestr = nprod = 0; size = 17 + 8; /* size of header + start rule */ glen = gram->len; nomatch = FALSE; token = gramtok(gram, &glen, buffer, &buflen); for (ruleno = 1; ; ruleno++) { switch (token) { case TOK_TOKSYM: /* * token rule definition */ r = (rule **) ht_lookup(ruletab, buffer, TRUE); if (*r != (rule *) NULL) { if ((*r)->type == RULE_UNKNOWN) { /* replace unknown rule */ rl = *r; rl->type = RULE_REGEXP; size += 4; nrgx++; if (rl->alt != (rule *) NULL) { rl->alt->next = rl->next; } else { tmplist = rl->next; } if (rl->next != (rule *) NULL) { rl->next->alt = rl->alt; } rl->alt = (rule *) NULL; rl->next = rgxlist; rgxlist = rl; } else if ((*r)->type == RULE_REGEXP) { /* new alternative regexp */ rl = rl_new(&rlchunks, RULE_REGEXP); *((*r)->last) = rl; (*r)->last = &rl->alt; } else { sprintf(buffer, "Rule %d previously defined as production rule", ruleno); goto err; } } else { /* new rule */ rl = rl_new(&rlchunks, RULE_REGEXP); str_ref(rl->symb = str_new(buffer, (long) buflen)); rl->chain.name = rl->symb->text; rl->chain.next = (hte *) *r; *r = rl; size += 4; nrgx++; rl->next = rgxlist; rgxlist = rl; } switch (gramtok(gram, &glen, buffer, &buflen)) { case TOK_REGEXP: str_ref(rl->u.rgx = str_new(buffer, (long) buflen)); (*r)->num++; (*r)->len += buflen; size += buflen + 1; break; case TOK_BADREGEXP: sprintf(buffer, "Rule %d: malformed regular expression", ruleno); goto err; case TOK_TOOBIGRGX: sprintf(buffer, "Rule %d: regular expression too large", ruleno); goto err; case TOK_SYMBOL: if (buflen == 7 && strcmp(buffer, "nomatch") == 0) { if (nomatch) { sprintf(buffer, "Rule %d: extra nomatch rule", ruleno); goto err; } nomatch = TRUE; rl->u.rgx = (string *) NULL; break; } /* fall through */ default: sprintf(buffer, "Rule %d: regular expression expected", ruleno); goto err; } /* next token */ token = gramtok(gram, &glen, buffer, &buflen); break; case TOK_PRODSYM: /* * production rule definition */ r = (rule **) ht_lookup(ruletab, buffer, TRUE); if (*r != (rule *) NULL) { if ((*r)->type == RULE_UNKNOWN) { /* replace unknown rule */ rl = *r; rl->type = RULE_PROD; size += 4; nprod++; if (rl->alt != (rule *) NULL) { rl->alt->next = rl->next; } else { tmplist = rl->next; } if (rl->next != (rule *) NULL) { rl->next->alt = rl->alt; } rl->alt = (rule *) NULL; rl->next = prodlist; prodlist = rl; } else if ((*r)->type == RULE_PROD) { /* new alternative production */ rl = rl_new(&rlchunks, RULE_PROD); *((*r)->last) = rl; (*r)->last = &rl->alt; } else { sprintf(buffer, "Rule %d previously defined as token rule", ruleno); goto err; } } else { /* new rule */ rl = rl_new(&rlchunks, RULE_PROD); str_ref(rl->symb = str_new(buffer, (long) buflen)); rl->chain.name = rl->symb->text; rl->chain.next = (hte *) *r; *r = rl; size += 4; nprod++; rl->next = prodlist; prodlist = rl; } rr = *r; rrl = rl; rs = &rl->u.syms; len = 0; for (;;) { switch (token = gramtok(gram, &glen, buffer, &buflen)) { case TOK_SYMBOL: /* * symbol */ r = (rule **) ht_lookup(ruletab, buffer, TRUE); if (*r == (rule *) NULL) { /* new unknown rule */ rl = rl_new(&rlchunks, RULE_UNKNOWN); str_ref(rl->symb = str_new(buffer, (long) buflen)); rl->chain.name = rl->symb->text; rl->chain.next = (hte *) *r; *r = rl; rl->next = tmplist; if (tmplist != (rule *) NULL) { tmplist->alt = rl; } tmplist = rl; } else { /* previously known rule */ rl = *r; } *rs = rs_new(&rschunks, rl); rs = &(*rs)->next; len += 2; continue; case TOK_STRING: case TOK_ESTRING: /* * string */ r = (rule **) ht_lookup(strtab, buffer, FALSE); while (*r != (rule *) NULL) { if ((*r)->symb->len == buflen && memcmp((*r)->symb->text, buffer, buflen) == 0) { break; } r = (rule **) &(*r)->chain.next; } if (*r == (rule *) NULL) { /* new string rule */ rl = rl_new(&rlchunks, RULE_STRING); str_ref(rl->symb = str_new(buffer, (long) buflen)); rl->chain.name = rl->symb->text; rl->chain.next = (hte *) *r; *r = rl; if (token == TOK_STRING) { size += 4; nstr++; rl->len = gram->len - glen - buflen - 1; rl->next = strlist; strlist = rl; } else { size += 3 + buflen; nestr++; rl->next = estrlist; estrlist = rl; } } else { /* existing string rule */ rl = *r; } *rs = rs_new(&rschunks, rl); rs = &(*rs)->next; len += 2; continue; case TOK_QUEST: /* * ? function */ if (gramtok(gram, &glen, buffer, &buflen) != TOK_SYMBOL) { sprintf(buffer, "Rule %d: function name expected", ruleno); goto err; } str_ref(rrl->func = str_new(buffer, (long) buflen)); len += buflen + 1; token = gramtok(gram, &glen, buffer, &buflen); /* fall through */ default: break; } break; } if (len > 255) { sprintf(buffer, "Rule %d is too long", ruleno); goto err; } rr->num++; rr->len += len; size += len + 2; break; case TOK_NULL: /* * end of grammar */ if (tmplist != (rule *) NULL) { sprintf(buffer, "Undefined symbol %s", tmplist->symb->text); goto err; } if (rgxlist == (rule *) NULL) { strcpy(buffer, "No tokens"); goto err; } if (prodlist == (rule *) NULL) { strcpy(buffer, "No starting rule"); goto err; } if (size > (long) USHRT_MAX) { strcpy(buffer, "Grammar too large"); goto err; } gram = make_grammar(rgxlist, strlist, estrlist, prodlist, nrgx, nstr, nestr, nprod, size); rs_clear(rschunks); rl_clear(rlchunks); ht_del(strtab); ht_del(ruletab); return gram; case TOK_ERROR: sprintf(buffer, "Rule %d: bad token", ruleno); goto err; case TOK_BADREGEXP: sprintf(buffer, "Rule %d: malformed regular expression", ruleno); goto err; case TOK_TOOBIGRGX: sprintf(buffer, "Rule %d: regular expression too large", ruleno); goto err; case TOK_BADSTRING: sprintf(buffer, "Rule %d: malformed string constant", ruleno); goto err; case TOK_TOOBIGSTR: sprintf(buffer, "Rule %d: string too long", ruleno); goto err; case TOK_TOOBIGSYM: sprintf(buffer, "Rule %d: symbol too long", ruleno); goto err; default: sprintf(buffer, "Rule %d: unexpected token", ruleno); goto err; } } err: rs_clear(rschunks); rl_clear(rlchunks); ht_del(strtab); ht_del(ruletab); error(buffer); return NULL; }