/* Copyright (c) 1990 The Regents of the University of California. */ /* All rights reserved. */
/* This code is derived from software contributed to Berkeley by */ /* Vern Paxson. */
/* The United States Government has rights in this work pursuant */ /* to contract no. DE-AC03-76SF00098 between the United States */ /* Department of Energy and the University of California. */
/* This file is part of flex. */
/* Redistribution and use in source and binary forms, with or without */ /* modification, are permitted provided that the following conditions */ /* are met: */
/* 1. Redistributions of source code must retain the above copyright */ /* notice, this list of conditions and the following disclaimer. */ /* 2. Redistributions in binary form must reproduce the above copyright */ /* notice, this list of conditions and the following disclaimer in the */ /* documentation and/or other materials provided with the distribution. */
/* Neither the name of the University nor the names of its contributors */ /* may be used to endorse or promote products derived from this software */ /* without specific prior written permission. */
/* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */ /* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */ /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ /* PURPOSE. */
#include"flexdef.h"
/* declarations for functions that have forward references */
void mkentry PROTO ((int *, int, int, int, int)); void mkprot PROTO ((int[], int, int)); void mktemplate PROTO ((int[], int, int)); void mv2front PROTO ((int)); int tbldiff PROTO ((int[], int, int[]));
void bldtbl (state, statenum, totaltrans, comstate, comfreq) int state[], statenum, totaltrans, comstate, comfreq;
{ int extptr, extrct[2][CSIZE + 1]; int mindiff, minprot, i, d;
/* If extptr is 0 then the first array of extrct holds the result *ofthe"bestdifference"todate,whichisthosetransitions *whichoccurin"state"butnotintheprotowhich,todate, *hasthefewestdifferencesbetweenitselfand"state".If *extptris1thenthesecondarrayofextrctholdthebest *difference.Thetwoarraysaretoggledbetweensothatthe *bestdifferencetodatecanbekeptaroundandalsoadifference *justcreatedbycheckingagainstacandidate"best"proto.
*/
extptr = 0;
/* If the state has too few out-transitions, don't bother trying to *compactitstables.
*/
if (checkcom) { /* Find first proto which has the same "comstate". */ for (i = firstprot; i != NIL; i = protnext[i]) if (protcomst[i] == comstate) {
minprot = i;
mindiff = tbldiff (state, minprot,
extrct[extptr]); break;
}
}
else { /* Since we've decided that the most common destination *outof"state"doesnotoccurwithahighenough *frequency,wesetthe"comstate"tozero,assuring *thatifthisstateisenteredintotheprotolist, *itwillnotbeconsideredatemplate.
*/
comstate = 0;
/* We now have the first interesting proto in "minprot". If *itmatcheswithinthetolerancessetforthefirstproto, *wedon'twanttobotherscanningtherestoftheprotolist *toseeifwehaveanyotherreasonablematches.
*/
if (mindiff * 100 >
totaltrans * FIRST_MATCH_DIFF_PERCENTAGE) { /* Not a good enough match. Scan the rest of the *protos.
*/ for (i = minprot; i != NIL; i = protnext[i]) {
d = tbldiff (state, i, extrct[1 - extptr]); if (d < mindiff) {
extptr = 1 - extptr;
mindiff = d;
minprot = i;
}
}
}
/* Check if the proto we've decided on as our best bet is close *enoughtothestatewewanttomatchtobeusable.
*/
if (mindiff * 100 >
totaltrans * ACCEPTABLE_DIFF_PERCENTAGE) { /* No good. If the state is homogeneous enough, *wemakeatemplateoutofit.Otherwise,we *makeaproto.
*/
/* Since mkprot added a new proto to the proto queue, *it'spossiblethat"minprot"isnolongeronthe *protoqueue(ifithappenedtohavebeenthelast *entry,itwouldhavebeenbumpedoff).Ifit's *notthere,thenthenewprototookitsphysical *place(thoughlogicallythenewprotoisatthe *beginningofthequeue),sointhatcasethe *followingcallwilldonothing.
*/
void cmptmps ()
{ int tmpstorage[CSIZE + 1]; int *tmp = tmpstorage, i, j; int totaltrans, trans;
peakpairs = numtemps * numecs + tblend;
if (usemecs) { /* Create equivalence classes based on data gathered on *templatetransitions.
*/
nummecs = cre8ecs (tecfwd, tecbck, numecs);
}
else
nummecs = numecs;
while (lastdfa + numtemps + 1 >= current_max_dfas)
increase_max_dfas ();
/* Loop through each template. */
for (i = 1; i <= numtemps; ++i) { /* Number of non-jam transitions out of this template. */
totaltrans = 0;
for (j = 1; j <= numecs; ++j) {
trans = tnxt[numecs * i + j];
if (usemecs) { /* The absolute value of tecbck is the *meta-equivalenceclassofagiven *equivalenceclass,assetupbycre8ecs().
*/ if (tecbck[j] > 0) {
tmp[tecbck[j]] = trans;
if (trans > 0)
++totaltrans;
}
}
else {
tmp[j] = trans;
if (trans > 0)
++totaltrans;
}
}
/* It is assumed (in a rather subtle way) in the skeleton *thatifwe'reusingmeta-equivalenceclasses,thedef[] *entryforalltemplatesisthejamtemplate,i.e., *templatesneverdefaulttoothernon-jamtableentries *(e.g.,anothertemplate)
*/
/* Leave room for the jam-state after the last real state. */
mkentry (tmp, nummecs, lastdfa + i + 1, JAMSTATE,
totaltrans);
}
}
/* expand_nxt_chk - expand the next check arrays */
void expand_nxt_chk ()
{ int old_max = current_max_xpairs;
/* find_table_space - finds a space in the table for a state to be placed * *synopsis *int*state,numtrans,block_start; *intfind_table_space(); * *block_start=find_table_space(state,numtrans); * *Stateisthestatetobeaddedtothefullspeedtransitiontable. *Numtransisthenumberofout-transitionsforthestate. * *find_table_space()returnsthepositionofthestartofthefirstblock(in *chk)abletoaccommodatethestate * *Indeterminingifastatewillorwillnotfit,find_table_space()musttake *intoaccountthefactthatanend-of-bufferstatewillbeaddedat[0], *andanactionnumberwillbeaddedin[-1].
*/
int find_table_space (state, numtrans) int *state, numtrans;
{ /* Firstfree is the position of the first possible occurrence of two *consecutiveunusedrecordsinthechkandnxtarrays.
*/ int i; int *state_ptr, *chk_ptr; int *ptr_to_last_entry_in_state;
/* If there are too many out-transitions, put the state at the end of *nxtandchk.
*/ if (numtrans > MAX_XTIONS_FULL_INTERIOR_FIT) { /* If table is empty, return the first available spot in *chk/nxt,whichshouldbe1.
*/ if (tblend < 2) return1;
/* Start searching for table space near the end of *chk/nxtarrays.
*/
i = tblend - numecs;
}
else /* Start searching for table space from the beginning *(skippingonlytheelementswhichwilldefinitelynot *holdthenewstate).
*/
i = firstfree;
while (1) { /* loops until a space is found */ while (i + numecs >= current_max_xpairs)
expand_nxt_chk ();
/* Loops until space for end-of-buffer and action number *arefound.
*/ while (1) { /* Check for action number space. */ if (chk[i - 1] == 0) { /* Check for end-of-buffer space. */ if (chk[i] == 0) break;
else /* Since i != 0, there is no use *checkingtoseeif(++i)-1==0, *becausethat'sthesameasi==0, *soweskipaspace.
*/
i += 2;
}
else
++i;
while (i + numecs >= current_max_xpairs)
expand_nxt_chk ();
}
/* If we started search from the beginning, store the new *firstfreeforthenextcalloffind_table_space().
*/ if (numtrans <= MAX_XTIONS_FULL_INTERIOR_FIT)
firstfree = i + 1;
/* Check to see if all elements in chk (and therefore nxt) *thatareneededforthenewstatehavenotyetbeentaken.
*/
if (usemecs) { /* Set up doubly-linked meta-equivalence classes; these *aresetsofequivalenceclasseswhichallhaveidentical *transitionsoutofTEMPLATES.
*/
tecbck[1] = NIL;
for (i = 2; i <= numecs; ++i) {
tecbck[i] = i - 1;
tecfwd[i - 1] = i;
}
tecfwd[numecs] = NIL;
}
}
/* mkdeftbl - make the default, "jam" table entries */
void mkdeftbl ()
{ int i;
jamstate = lastdfa + 1;
++tblend; /* room for transition on end-of-buffer character */
while (tblend + numecs >= current_max_xpairs)
expand_nxt_chk ();
void mkentry (state, numchars, statenum, deflink, totaltrans) int *state; int numchars, statenum, deflink, totaltrans;
{ int minec, maxec, i, baseaddr; int tblbase, tbllast;
if (totaltrans == 0) { /* there are no out-transitions */ if (deflink == JAMSTATE)
base[statenum] = JAMSTATE; else
base[statenum] = 0;
def[statenum] = deflink; return;
}
for (minec = 1; minec <= numchars; ++minec) { if (state[minec] != SAME_TRANS) if (state[minec] != 0 || deflink != JAMSTATE) break;
}
if (totaltrans == 1) { /* There's only one out-transition. Save it for later to fill *inholesinthetables.
*/
stack1 (statenum, minec, state[minec], deflink); return;
}
for (maxec = numchars; maxec > 0; --maxec) { if (state[maxec] != SAME_TRANS) if (state[maxec] != 0 || deflink != JAMSTATE) break;
}
/* Whether we try to fit the state table in the middle of the table *entrieswehavealreadygenerated,orifwejusttakethestate *tableattheendofthenxt/chktables,wemustmakesurethatwe *haveavalidbaseaddress(i.e.,non-negative).Notethat *negativebaseaddressesdangerousatrun-time(becauseindexing *thenxtarraywithoneandalow-valuedcharacterwillaccess *memorybeforethestartofthearray.
*/
/* Find the first transition of state that we need to worry about. */ if (totaltrans * 100 <= numchars * INTERIOR_FIT_PERCENTAGE) { /* Attempt to squeeze it into the middle of the tables. */
baseaddr = firstfree;
while (baseaddr < minec) { /* Using baseaddr would result in a negative base *addressbelow;findthenextfreeslot.
*/ for (++baseaddr; chk[baseaddr] != 0; ++baseaddr) ;
}
if (firstfree >= current_max_xpairs)
expand_nxt_chk ();
}
}
/* mkprot - create new proto entry */
void mkprot (state, statenum, comstate) int state[], statenum, comstate;
{ int i, slot, tblbase;
if (++numprots >= MSP || numecs * numprots >= PROT_SAVE_SIZE) { /* Gotta make room for the new proto by dropping last entry in *thequeue.
*/
slot = lastprot;
lastprot = protprev[lastprot];
protnext[lastprot] = NIL;
}
/* place_state - place a state into full speed transition table * *Stateisthestatenum'thstate.Itisindexedbyequivalenceclassand *givesthenumberofthestatetoenterforagivenequivalenceclass. *Transnumisthenumberofout-transitionsforthestate.
*/
void place_state (state, statenum, transnum) int *state, statenum, transnum;
{ int i; int *state_ptr; int position = find_table_space (state, transnum);
/* "base" is the table of start positions. */
base[statenum] = position;
/* Put in action number marker; this non-zero number makes sure that *find_table_space()knowsthatthispositioninchk/nxtistaken *andshouldnotbeusedforanotheracceptingnumberinanother *state.
*/
chk[position - 1] = 1;
/* Put in end-of-buffer marker; this is for the same purposes as *above.
*/
chk[position] = 1;
/* Place the state into chk and nxt. */
state_ptr = &state[1];
for (i = 1; i <= numecs; ++i, ++state_ptr) if (*state_ptr != 0) {
chk[position + i] = i;
nxt[position + i] = *state_ptr;
}
if (position + numecs > tblend)
tblend = position + numecs;
}
/* stack1 - save states with only one out-transition to be processed later * *Ifthere'sroomforanotherstateonthe"one-transition"stack,the *stateispushedontoit,tobeprocessedlaterbymk1tbl.Ifthere's *noroom,weprocessthesuckerrightnow.
*/
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.