LCOV - code coverage report
Current view: top level - libreoffice/dmake - percent.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 80 86 93.0 %
Date: 2012-12-17 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* RCS  $Id: percent.c,v 1.1.1.1 2000-09-22 15:33:25 hr Exp $
       2             : --
       3             : -- SYNOPSIS
       4             : --      Handle building or %-rule meta-target nfa.
       5             : --
       6             : -- DESCRIPTION
       7             : --  Builds the NFA used by dmake to match targets against %-meta
       8             : --  rule constructs.  The NFA is built as a set of DFA's.
       9             : --
      10             : -- AUTHOR
      11             : --      Dennis Vadura, dvadura@dmake.wticorp.com
      12             : --
      13             : -- WWW
      14             : --      http://dmake.wticorp.com/
      15             : --
      16             : -- COPYRIGHT
      17             : --      Copyright (c) 1996,1997 by WTI Corp.  All rights reserved.
      18             : --
      19             : --      This program is NOT free software; you can redistribute it and/or
      20             : --      modify it under the terms of the Software License Agreement Provided
      21             : --      in the file <distribution-root>/readme/license.txt.
      22             : --
      23             : -- LOG
      24             : --      Use cvs log to obtain detailed change logs.
      25             : */
      26             : 
      27             : #include "extern.h"
      28             : 
      29             : static DFAPTR _build_dfa ANSI((char *));
      30             : static char   _shift_dfa ANSI((DFAPTR, char *));
      31             : 
      32             : 
      33             : #define NO_ACTION   0
      34             : #define START_PERCENT   1
      35             : #define END_PERCENT 2
      36             : #define ACCEPT      4
      37             : #define FAIL           -1
      38             : 
      39             : static  NFAPTR _nfa = NIL( NFA );
      40             : 
      41             : 
      42             : PUBLIC DFALINKPTR
      43       34255 : Match_dfa( buf )/*
      44             : ==================
      45             :    This routines runs all DFA's in parrallel and selects the one that best
      46             :    matches the string.  If no match then it returns NIL( DFA ) */
      47             : char *buf;
      48             : {
      49             :    register NFAPTR nfa;
      50             :    int         adv;
      51       34255 :    DFALINKPTR      dfa_list = NIL(DFALINK);
      52             : 
      53             :    DB_ENTER( "Match_dfa" );
      54             :    DB_PRINT( "dfa", ("Matching %s", buf) );
      55             : 
      56             :    /* Run each of the DFA's on the input string in parallel, we terminate
      57             :     * when all DFA's have either failed or ACCEPTED, if more than one DFA
      58             :     * accepts we build a list of all accepting DFA's sorted on states with
      59             :     * those matching in a higher numbered state heading the list. */
      60             : 
      61             :    do {
      62     1833714 :       adv = FALSE;
      63             : 
      64    46716212 :       for( nfa = _nfa; nfa != NIL( NFA ); nfa = nfa->next )
      65    44882498 :      if( nfa->status != (char) FAIL && nfa->status != (char) ACCEPT ) {
      66    24926580 :         adv++;
      67    24926580 :         nfa->status = _shift_dfa( nfa->dfa, buf );
      68             : 
      69             :         /* Construct the list of matching DFA's */
      70    24926580 :         if( nfa->status == (char) ACCEPT ) {
      71             :            DFALINKPTR dl;
      72             : 
      73        4760 :            TALLOC( dl, 1, DFALINK );
      74        4760 :            dl->dl_meta  = nfa->dfa->node;
      75        4760 :            dl->dl_per   = DmSubStr( nfa->dfa->pstart, nfa->dfa->pend );
      76        4760 :            dl->dl_state = nfa->dfa->states - nfa->dfa->c_state;
      77             : 
      78        4760 :            if( dfa_list == NIL(DFALINK) )
      79        4754 :               dfa_list = dl;
      80             :            else {
      81           6 :           DFALINKPTR tdli = dfa_list;
      82           6 :           DFALINKPTR tdlp = NIL(DFALINK);
      83             : 
      84           6 :           for( ; tdli != NIL(DFALINK); tdli = tdli->dl_next ) {
      85           6 :              if( dl->dl_state >= tdli->dl_state )
      86           6 :             break;
      87           0 :              tdlp = tdli;
      88             :           }
      89             : 
      90           6 :           if( tdli != NIL(DFALINK) ) {
      91           6 :              tdli->dl_prev = dl;
      92           6 :              dl->dl_next   = tdli;
      93             :           }
      94             : 
      95           6 :           if( tdlp != NIL(DFALINK) ) {
      96           0 :              tdlp->dl_next = dl;
      97           0 :              dl->dl_prev   = tdlp;
      98             :           }
      99             :           else
     100           6 :              dfa_list = dl;
     101             :            }
     102             : 
     103             :            DB_PRINT( "dfa", ("Matched [%s]", dl->dl_meta->CE_NAME) );
     104             :         }
     105             :      }
     106             : 
     107     1833714 :       buf++;
     108             :    }
     109     1833714 :    while ( adv );
     110             : 
     111      866015 :    for( nfa = _nfa; nfa != NIL( NFA ); nfa = nfa->next ) {
     112      831760 :       nfa->status = 0;
     113      831760 :       nfa->dfa->c_state = nfa->dfa->states;
     114             :    }
     115             : 
     116       34255 :    DB_RETURN( dfa_list );
     117             : }
     118             : 
     119             : 
     120             : PUBLIC void
     121         184 : Check_circle_dfa()/*
     122             : ====================
     123             :    This function is called to test for circularities in the DFA lists
     124             :    constructed from %-meta targets. */
     125             : {
     126             :    register NFAPTR nfa;
     127             : 
     128        4856 :    for( nfa = _nfa; nfa != NIL(NFA); nfa = nfa->next )
     129        4672 :       if( Test_circle( nfa->dfa->node, FALSE ) )
     130           0 :      Fatal( "Detected circular dependency in inference graph at [%s]",
     131           0 :         nfa->dfa->node->CE_NAME );
     132         184 : }
     133             : 
     134             : 
     135             : PUBLIC void
     136        4672 : Add_nfa( name )/*
     137             : =================
     138             :    Given name, build a DFA and add it to the NFA.  The NFA is maintained as
     139             :    a singly linked list of DFA's. */
     140             : char *name;
     141             : {
     142             :    NFAPTR nfa;
     143             : 
     144        4672 :    TALLOC(nfa, 1, NFA);
     145        4672 :    nfa->dfa = _build_dfa(name);
     146             : 
     147        4672 :    if( _nfa != NIL(NFA) ) nfa->next = _nfa;
     148             : 
     149        4672 :    _nfa = nfa;
     150        4672 : }
     151             : 
     152             : 
     153             : static DFAPTR
     154        4672 : _build_dfa( name )/*
     155             : ====================
     156             :    Construct a dfa for the passed in cell name.  The routine returns a struct
     157             :    that represents a finite state machine that can recognize a regular
     158             :    expression with exactly one '%' sign in it.  The '%' symbol is used as a
     159             :    wildcard character that will match anything except the character that
     160             :    immediately follows it or NUL.
     161             : 
     162             :    The Construction of DFA's is well known and can be found in Hopcroft and
     163             :    Ullman or any other book discussing formal language theory.
     164             :    A more practical treatise can be found in Compilers, Aho, Sethi and Ullman.
     165             : */
     166             : char *name;
     167             : {
     168             :    DFAPTR   dfa;
     169             :    int      nstates;
     170             :    register STATEPTR sp;
     171        4672 :    STATEPTR per_state = NIL(STATE);
     172        4672 :    int      pcount=0;
     173        4672 :    int      end_percent=FALSE;
     174             : 
     175        4672 :    nstates = strlen(name)+2;
     176             : 
     177             :    /* Allocate a DFA node and the right number of states. */
     178        4672 :    TALLOC(dfa, 1, DFA);
     179        4672 :    TALLOC(sp=dfa->c_state=dfa->states, nstates, STATE);
     180        4672 :    dfa->node = Def_cell( name );
     181             : 
     182             :    /* Now construct the state table for the DFA */
     183             :    do {
     184      172218 :       if( *name == '%' ) {
     185        4672 :      if( pcount++ > 0 )
     186           0 :         Error( "Only one %% allowed within a %%-meta target" );
     187             : 
     188        4672 :      sp->symbol   = 0;
     189        4672 :      sp->action   = START_PERCENT;
     190        4672 :      sp->no_match = sp->match = per_state = sp+1;
     191        4672 :      end_percent  = TRUE;
     192             :       }
     193             :       else {
     194      167546 :      sp->symbol   = *name;
     195      167546 :      sp->no_match = per_state;
     196             : 
     197      167546 :      if( *name == '\0' ) {
     198        4672 :         sp->action = ACCEPT;
     199        4672 :         sp->match  = dfa->states;
     200             :      }
     201             :      else {
     202      162874 :         sp->action = NO_ACTION;
     203      162874 :         sp->match  = sp+1;
     204             :      }
     205             : 
     206      167546 :      if( end_percent ) {
     207        4672 :         sp->action |= END_PERCENT;
     208        4672 :         end_percent = FALSE;
     209             :      }
     210             :       }
     211             : 
     212      172218 :       sp++;
     213             :    }
     214      172218 :    while( *name++ );
     215             : 
     216        4672 :    return(dfa);
     217             : }
     218             : 
     219             : 
     220             : static char
     221    24926580 : _shift_dfa( dfa, data )/*
     222             : =========================
     223             :    Take a given dfa and advance it based on the current state, the shift
     224             :    action in that state, and the current data value. */
     225             : DFAPTR dfa;
     226             : char   *data;
     227             : {
     228    24926580 :    register STATEPTR sp = dfa->c_state;
     229    24926580 :    char c = *data;
     230             : 
     231             :    /* Check if it is a START_PERCENT action if so then we need to save
     232             :     * a pointer to the start of the string and advance to the next state. */
     233    24926580 :    if( sp->action & START_PERCENT ) {
     234      285546 :       dfa->pstart = data;
     235      285546 :       sp++;
     236             :    }
     237             : 
     238             :    /* Now check if the current char matches the character expected in the
     239             :     * current state.  If it does then perform the specified action, otherwise
     240             :     * either shift it or fail.  We fail if the next state on no-match is
     241             :     * NIL. */
     242    24926580 :    if( sp->symbol == c ) {
     243    14112478 :       if( sp->action & END_PERCENT ) dfa->pend = data;
     244    14112478 :       if( sp->action & ACCEPT ) return(ACCEPT);
     245    14107718 :       dfa->c_state = sp->match;
     246             :    }
     247    10814102 :    else if( (dfa->c_state = sp->no_match) == NIL(STATE) || !c )
     248      827000 :       return((unsigned char) FAIL);
     249             : 
     250    24094820 :    return(NO_ACTION);
     251             : }

Generated by: LCOV version 1.10