EP1200894A1 - Verfahren und anordnung zur ermittlung einer gesamtfehlerbeschreibung zumindest eines teils eines computerprogramms sowie computerprogramm-erzeugnis und computerlesbares speichermedium - Google Patents
Verfahren und anordnung zur ermittlung einer gesamtfehlerbeschreibung zumindest eines teils eines computerprogramms sowie computerprogramm-erzeugnis und computerlesbares speichermediumInfo
- Publication number
- EP1200894A1 EP1200894A1 EP00929272A EP00929272A EP1200894A1 EP 1200894 A1 EP1200894 A1 EP 1200894A1 EP 00929272 A EP00929272 A EP 00929272A EP 00929272 A EP00929272 A EP 00929272A EP 1200894 A1 EP1200894 A1 EP 1200894A1
- Authority
- EP
- European Patent Office
- Prior art keywords
- int
- error
- description
- slicec
- iterator
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Withdrawn
Links
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F11/00—Error detection; Error correction; Monitoring
- G06F11/36—Preventing errors by testing or debugging software
- G06F11/3604—Software analysis for verifying properties of programs
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F11/00—Error detection; Error correction; Monitoring
- G06F11/008—Reliability or availability analysis
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F11/00—Error detection; Error correction; Monitoring
- G06F11/07—Responding to the occurrence of a fault, e.g. fault tolerance
- G06F11/0796—Safety measures, i.e. ensuring safe condition in the event of error, e.g. for controlling element
Definitions
- the invention relates to a method and an arrangement for determining an overall error description of at least part of a computer program as well as a computer product and a computer-readable storage medium.
- a control flow description in the form of a control flow graph is determined for the computer program.
- an element error description is determined using a stored error description, which is assigned to a stored reference element.
- the error description of a reference element describes possible errors of the respective reference element.
- the overall error description is determined from the element error descriptions in the form of element error trees, taking into account the control flow graph for the computer program.
- the method and the arrangement from [1] have the following disadvantages in particular.
- the overall fault tree determined is incomplete with regard to the faults examined and their causes and is therefore unreliable. Thus, this procedure cannot be used sensibly for safety-critical applications in the context of fault tree generation for a computer program.
- Slicing corresponds to the analysis that is carried out when searching for the cause of a malfunction of a computer program. This procedure checks whether the misconduct was caused by an instruction that is currently being viewed. If this is not the case, the statements that supply data for the statement or control its execution are checked. This process continues until no more processes exist, that is, input data of the computer program are reached. So-called slices are determined during slicing. A slice is used to show which instructions are influenced in which way by a value under consideration. In the following, the term slicing is always understood to mean backward slicing.
- the invention is based on the problem of determining an overall fault description which is more reliable than a determination of an overall fault tree known according to the method from [1].
- a method for determining an overall error description of at least part of a computer program by a computer at least the part of the computer program is stored.
- a control flow description and a data flow description for the part of the computer program are determined and program elements are selected from the part of the computer program.
- An element error description is determined for each selected program element using a stored error description.
- the error description is assigned to a reference element.
- the element error description describes possible errors of the respective program element.
- An error description of a reference element describes possible errors of the respective reference element.
- the overall error description is determined from the element error descriptions taking into account the control flow description and the data flow description.
- An arrangement for determining an overall fault description of at least part of a computer program has a processor which is set up in such a way that the following method steps can be carried out: at least the part of the computer program is stored,
- control flow description and a data flow description are determined for the part of the computer program
- an element error description is determined using a stored error description, which is assigned to a reference element, with which possible errors of the respective program element are described,
- the total error description is determined from the element error descriptions taking into account the control flow description and the data flow description.
- a computer program product comprises a computer readable storage medium on which a program is stored that enables a computer after it has been stored in a memory of the
- At least the part of the computer program is stored, a control flow description and a data flow description for the part of the computer program are determined,
- Program elements are selected from the part of the computer program, - For each selected program element, an element error is used using a stored error description, which is assigned to a reference element. ler description determined with which possible errors of the respective program element are described,
- an error description of a reference element describes possible errors of the respective reference element
- the overall error description is determined taking into account the control flow description and the data flow description.
- a program is stored on a computer-readable storage medium, which enables a computer, after it has been loaded into a memory of the computer, to carry out the following steps to determine an overall error description of at least part of a computer program: At least the part of the computer program is stored,
- control flow description and a data flow description are determined for the part of the computer program
- an element error description is determined using a stored error description, which is assigned to a reference element, with which possible errors of the respective program element are described,
- the total error description is determined from the element error descriptions taking into account the control flow description and the data flow description.
- the invention now makes it possible to determine a reliable overall error description for a computer program or a part thereof, taking into account the peculiarities of a computer program. Since the determined overall fault description is much more reliable than that according to The method can be determined from [1] overall error description, the invention is also suitable for security-critical applications, ie in particular for determining an overall error description of a security-critical computer program.
- control flow description and / or the data flow description can be in the form of a control flow graph or a data flow graph.
- the error description can be in the form of a stored error tree and the element error description can be determined as an element error tree.
- the overall error description can be determined as an overall error tree.
- the overall error description can be used in a further development for error analysis of the part of the computer program.
- the overall error description is determined as an overall error tree and the overall error tree is changed with regard to predefinable framework conditions.
- the change can be made by adding a supplementary fault tree.
- FIG. 1 shows a computer with which the method according to the embodiment is carried out;
- FIG. 2 shows a flow chart in which the individual method steps of the method according to the exemplary embodiment are shown;
- FIG. 3 shows a general fault tree, as it is principally formed for a reference element; 4a to 4c a control flow graph (FIG. 4a), a slice (FIG. 4b) and a fault tree (FIG. 4c) for an instruction sequence as a reference element of a computer program;
- FIG. 5a to 5c a control flow graph (FIG. 5a), a slice (FIG. 5b) and an error tree (FIG. 5c) for a selection sequence as a reference element of a computer program; 6a to 6c a control flow graph (FIG. 6a), a slice (FIG. 6b) and an error tree (FIG. 6c) for a loop as a reference element of a computer program;
- FIG. 7 shows a control flow graph with a data flow graph for a computer program according to the exemplary embodiment
- Figures 8a and 8b a slice of the output of the variable max
- FIG. 8a or a slice for the variable avr (FIG. 8b) for the program according to the exemplary embodiment
- FIG. 9 shows the slice for the variable avr, in which a structure of the loop is highlighted from the program of the exemplary embodiment
- FIG. 10 shows an error tree for the assumption that the variable avr is incorrect
- FIG. 11 shows the overall fault construction according to FIG. 10, redundant events from the overall fault tree according to FIG. 10 having been combined into one event.
- Fig.l shows a computer 100 with which the method described below is carried out.
- the computer 100 has a processor 101 which is connected to a memory 102 via a bus 103.
- An input / output interface 106 is also connected to the bus 103.
- a computer program 104 is stored in the memory 102, for which an overall error description is determined in the manner described below.
- a program 105 is also stored in the memory 102, by means of which the method described below is implemented.
- error descriptions 115 are different in the memory
- Reference elements of a computer program saved.
- An error description of a reference element describes possible errors of the respective reference element.
- Various reference elements and error descriptions assigned to the reference elements are explained in detail below.
- a keyboard 108 is connected to the input / output interface 106 via a first connection 107.
- the input / output interface 106 is connected to a computer mouse 110 via a second connection 109, and the input / output interface 106 is connected to a screen 112 via a third connection 111, on which the determined overall error description of the computer program 104 is displayed.
- Output cut parts 106 connected to an external storage medium 114. 2 shows in a block diagram the procedure according to the exemplary embodiment described below.
- a control flow graph 201 and a data flow graph 202 for the computer program 104 are determined from the stored computer program 104.
- Individual program elements are selected from the computer program (step 203). For each selected program element, an element error description is determined using a stored error description that is assigned to a reference element corresponding to the selected program element (step 204). The element error description describes possible errors of the selected program element.
- an overall error description of the computer program for the error case to be examined is determined from the element error descriptions, taking into account the control flow graph and the data flow graph .
- the determined overall fault tree is displayed to the user on the screen 112.
- FIG 3 shows the basic procedure for creating an error tree, as was used in the context of the starting example, to form the error trees described below for the reference elements.
- an erroneous output of a variable can be a selected erroneous event (undesirable event) 301 are caused by a control flow error 303 and / or a data error 304 (INCLUSIVE-OR link 302).
- a control flow error 303 is to be understood as an incorrect control of the processing of the respective variables.
- the data flow error 304 is to be understood as an error that arises from incorrect data during processing.
- the data flow error 304 can arise again in the processing step currently under consideration (block 306) and / or it can already have been present and can only be retained by error propagation (block 307) (INCLUSIVE-OR link 305).
- the fault tree 420 shown in FIG. C results for the following predetermined undesired event 421:
- the faulty event 421 may have been generated by an error in the considered third instruction 404 even with data correct up to this instruction step (element 422 in FIG. 4c).
- the erroneous event 421 can also be caused by corrupted input data of the third instruction, i.e. by INCLUSIVE-ORing 424 the events that the second variable k after the second
- FIGS. 5 a to 5 c there is a control flow graph 501 (see FIG. 5 a), a slice 520 (see FIG. 5 b) and an error tree 540 (see Fig. 5c) for an If-Then-Else statement as a selection element.
- a third instruction 504 in which it is checked whether the second variable k has a value greater than 0; if the value of the second variable is greater than 0, the instruction branches to a fourth instruction 505, otherwise to a fifth instruction 506,
- the control flow graph 501 shown in FIG. 5 a results in the slice 520 shown in FIG. 5 b for the selection element.
- Solid edges in the slice 520 represent a data dependency of the different instructions from one another.
- Control dependencies of the corresponding instructions from one another are indicated with dashed edges.
- control edges are directed from instructions which contain a predictive reference (failure constructs, loop control) to the instructions which are directly controlled, ie to those instructions which are only executed if the predicate has a certain value.
- Control edges are only drawn between the control instruction and immediately nested instructions. If another control level is nested in a controlled block, no control edges are drawn that cover more than one level. Since a control relationship is transitive, this indirect control can be inferred from the slice by using transitivity.
- - Solid edges hereinafter referred to as data flow edges, are directed from instructions in which a variable is defined to instructions in which this variable is referenced. The considered variable must not be redefined between the definition and the reference. This is known as the path free of definition with regard to the variables under consideration.
- the slice is determined by searching the control flow graph against the edge direction for the definition of the variables under consideration, based on the instruction with the variables under consideration, for which the undesired event is specified. If there are computational references to the definition, the process continues recursively until no additional nodes are found.
- the dependencies between statements found in this way are data dependencies. If a node under consideration is in a block, the execution of which is directly controlled by a decision, this represents a control dependency. For the predictive references of the variables involved in the decision, nodes with corresponding definitions - that is, data flow dependencies - are recursively searched for have further control dependencies.
- 5b shows the slice 520 belonging to the failure element with corresponding control edges and data flow edges.
- 5c shows the error tree 540 for the specified event "the third variable i is faulty before the 6th instruction" 541.
- a multiple selection element as a reference element can be treated according to the above-described scheme by breaking the multiple selection into a cascade of two-sided selection elements which are processed in accordance with the above procedure, in order thus to determine an error tree for a multiple selection element.
- FIGS. 6 a to 6 c show an error tree 601 (see FIG. 6 a), the corresponding slice 620 (see FIG. 6 b) and the associated error tree 640 (see FIG. 6 c) for the reference element of a loop.
- the control flow graph 601 for a loop element has the following seven instructions:
- a fourth instruction 605 which specifies as a loop instruction a condition that a fifth instruction and a sixth instruction are carried out as long as the value of the second variable is j> 0 (WHILE j> 0 DO),
- FIG. 6b shows the corresponding slice 620 for the control flow graph 601 shown in FIG. 6a with associated control flow edges and data flow edges.
- the fault tree 640 shown in FIG. 6c is formed for the predetermined event 641 that the "first variable i before the seventh instruction is faulty".
- the error tree 640 results from the INCLUSIVE-OR link 642 of the following four events:
- Loop body has been run through at least twice (element 645) and the event that the sixth instruction 607 is incorrect (646),
- error trees described above which are assigned to the individual reference elements, are stored in the memory 102 as error trees 115.
- 7 shows a control flow graph 700 for the following computer program:
- FIG. 8a shows the associated slice 800 for the variable max
- FIG. 8b shows the associated slice 810 for the variable avr .
- the numbering of the individual instructions in the slices corresponds to the numbering of the individual instructions in the control flow graph 700 from FIG. 7.
- FIG. 9 shows the slice 900 for the variable avr, as shown in FIG. 8b.
- the structure of the loop element contained in the program shown above is highlighted in bold. This structure corresponds to the slice shown in FIG. 6b for a loop element.
- An overall fault tree 1000 for the computer program shown above is shown in FIG.
- the overall fault tree for the computer program is generated by instantiating the corresponding fault tree that is assigned to the reference element that corresponds to the selected program element. By proceeding backwards starting from the predetermined undesired event, the overall error tree 1000 is thus determined using the error trees assigned to the reference elements.
- the fault tree 1000 is related to the event that "the variable avr is faulty before the thirteenth instruction" (element 1001).
- the variable avr may be incorrect before the thirteenth instruction 13 due to at least one of the following three events, as is also shown in the slice 900 for the variable avr shown in FIG. 9 (INCLUSIVE-OR operation 1002):
- variable sum is faulty before the eleventh instruction 11 (element 1005) if at least one of the following events is fulfilled (INCLUSIVE-OR link 1006):
- variable sum is incorrect after the fourth statement 4 (element 1007)
- the error tree 1000 from FIG. 10 is changed so that events that are shown several times in the error tree 1000 are combined to form a node of a cause and effect graph 1100 (see FIG. 11).
- a fault tree analysis method as described in [5] is applied to the fault tree 1000 shown in FIG. 10, as a result of which an analysis of the computer program with regard to a predetermined undesired event is analyzed.
- the overall fault tree generated with the method described above can be used for various purposes:
- KFGListNode.h "usmg namespace std; class GraphNodeC: public
- KFGListC SL 2 void sliceForLoops (KFGListC SL 2 , KFGListC:: iterator LOOPIT); KFGListC:: iterator defineVariableToSlice (KFGListC SL 2 );
- KFGListC:: iterator findUpperLimit KFGListC s Ll, KFGListC:: iterator ITER, KFGP UseListC:: iterator PUSEIT);
- KFGListC:: iterator fmdLowerLimit (KFGListC & Ll, KFGListC:: iterator ITER, KFGListC :: iterator UPPERLIMIT);
- KFGListC:: iterator findLowerLimitFromCUse KFGListC S Ll, KFGListC: -.iterator ITER, KFGListC:: iterator UPPERLIMIT
- KFGListC:: iterator findUpperLimitFromCUse KFGListC S Ll, KFGListC:: iterator ITER
- KFGUseListC iterator USEIT); int checkForNodes (int NodeNumber); void KFKPUseToCUse (KFGListC:: ⁇ terator PUSEIT, int LoopEnd); void fmdDefToCUse (KFGListC S Ll, KFGListC:: iterator ITER); void deflnLooplKFGListC S Ll, KFGListC:: iterator ITER); void startBuildSlice (KFGListC S Ll); void sliceExpendl); );
- template ⁇ class corner type, class edge type> void graph ⁇ corner type, edge type>:: verbindeEcken (int posl, int pos2, const edge type value) (
- MILES.DAT (128 knots).
- the stack depth corresponds to the number of edges
- KFGListC public l ⁇ st ⁇ KFGL ⁇ stNodeC> (int number_defs, number_Uses, number_P_Uses, number of declarations; int loop decisions, decisions, counting loop decisions; int instructions; publlc: KFGListC () ( ⁇ ; void TokenL ⁇ st2KFn); node (S) void node identifier (KFGListC:: iterator KFG); void list output!); void addLmelnToList (); void addL ⁇ neToKFG (KFGProgL ⁇ stC S LP); int count declarations (KFGTokenL ⁇ stC S TL); void base size file ();
- class KFGDefListC public list ⁇ KFGDefC> ( ⁇ ; class KFGUseListC: public reads ⁇ KFGUseC> ( ⁇ ; class KFGP_UseL ⁇ stC: public reads ⁇ KFGUseC> ( ⁇ ;
- KFGListNodeCO (strcpy (Statement, "- unknown -");
- NodeNr Dummy myNodeNr ++
- KFGL ⁇ stNodeC (char _Statement [], KFGNodeTypeT _KFGNodeType) strcpy (statement, _Statement);
- NodeNr Dummy myNodeNr ++
- KFGL ⁇ stNodeC (char _Statement [], KFGNodeTypeT _KFGNodeType, int _Level)
- NodeNr Dummy myNodeNr ++
- Node number 0; Node identifier - NONE;
- NodeNr Dummy myNodeNr ++
- LineNr LineNr; strcpy (CodeLine, "—unknown—”); ⁇ ; from the setStatement (char _Statement []) strcpy (Statement, _Statement); ⁇ ; void setCodeL e (char _CodeL ⁇ ne []) strcpy (CodeLine, _CodeL ⁇ ne); ⁇ ; void setKFGKnoten endeavor (int _KnotenNr)
- Node ID _ node ID; ⁇ ; int getNodeNumber () (return NodeNumber; ⁇ ; char * getStatement!) (return Statement; ⁇ ; char * getCodeL e () (return CodeLme; ⁇ ; int getLevel () (return Level; ⁇ ; int getNodeNrl) (return NodeNr; ⁇ ; int getL ⁇ neNr () (return LineNr; ⁇ ;
- NodeC creates " « endl; * / ⁇ ;
- ScopeLevel 0; ); KFGNodeCIchar _Name [], int _ScopeLevel)
- NodeC creates " « endl; * / ⁇ ;
- KFGLlstNodeC (char _Name []) (strcpy (Name, _Name);
- ScopeLevel 0; ⁇ ; KFGLlstNodeC (char _Name [], int _ScopeLevel)
- NodeC creates " « endl; * / ⁇ ;
- ScopeLevel 0; ); KFGLlstNodeC (char _Name [], int _ScopeLevel)
- KFGListeC inherits all properties // from the list created with STL ⁇ KFGNodeC>.
- «Lfdef _KFGProgL ⁇ stHeader (quietly « define _KFGProgListHeader ffinclude ⁇ str ⁇ ng> ffinclude ⁇ ostream> ffinclude ⁇ std ⁇ o.h> flinclude ⁇ l ⁇ st> ffinclude ⁇ fstream> ffinclude ⁇ terator> namfinespodehsting using KFNclodGlist using the class; using the FinNodeGlist; KFNclingGlist using the name; using the FinNodeGlead; KFNclodGlist using the "; KFGL ⁇ neNodeC> (public:
- KFGProgListC (); // void KFGListeAusgabel);
- KFGTokenListC public reads ⁇ KFGTokenNodeC> (public:
- KFGTokenListC ( ⁇ ; Void KFGListeAusgabel);
- KFGTokenNodeC (char _Name [], int _ScopeLevel, TokenNodeTypeT TokenNodeType)
- ScopeLevel _ScopeLevel
- KFGTokenNodeC (char _Name [], t _ScopeLevel, TokenNodeTypeT _TokenNodeType, int LineNumber)
- KFGUseC (strcpy (Use, "- unknown -");
- ScopeLevelU 0; );
- KFGUseC (char _Use [], int _ScopeLevelU) (strcpy (Use, _Use);
- H include "AS Slice. H” using namespace std; class uwggraphC: public graph ⁇ uwgknotenC, uwgkanteC> (public:
- SliceC iterator definelterator (SliceC S Sl, mt SliceNr); void addFirstNodesToFTISliceC s Sl, int NodeNo, int Posl);
- SliceC iterator returnCondNode (SliceC S Sl, mt SliceNr); mt checkUWGNode ( ⁇ nt SliceNr); void Slice SliceC S Sl) t void startBuildFT (SliceC S Sl); void buildInLoopTree (SliceC S Sl, int Posl, SliceC:: iterator SLPUSE, SliceC:: iterator SLNODE); void bu ⁇ ldIn_Dl_Part (SliceC S Sl, int posOR_Dl, SliceC:: iterator SLPUSE, SliceC:: iterator SLNODE, int D2_RefNr); SliceC:: ⁇ terator f dOutmostPUse (SliceC S Sl, SliceC:: iterator SLPUSE); int checkPUsesl (SliceC Sl, SliceC:: iterator SLPUSE, SliceC:: iterator SLPUSEREF);
- SliceC:: iterator f ⁇ nd_Dl_Node (SliceC S Sl, SliceC:: iterator SLPUSE, SliceC:: ⁇ terator SLNODE); void addAllDlNodes (SliceC S Sl, SliceC:: iterator SLNODE, int posGatter, int D2_RefNr);
- SliceC :: ⁇ terator findLastPUse (SliceC S Sl, int SliceNr);
- SliceC:: iterator fmdLastPUse2 (SliceC S Sl, int SliceNr, mt RefNr); void checkLoopOrCondl SliceC S Sl, SliceC:: ⁇ terator SLl, SliceC:: ⁇ terator SLORIG, int Posil); void buildIn_D2_Part (SliceC S Sl, int posOR_D2, SliceC:: iterator SLl, SliceC:: iterator SLPUSE, int nodeNoD2); int f ⁇ ndD2Node (SliceC S Sl, SliceC:: iterator PUSE); t buildlnlfTree (SliceC s Sl, SliceC:: ⁇ terator SLIF, SliceC:: iterator SLORIG, int posl);
- SliceC:: iterator lookForNextPUse (SliceC S Sl, SliceC:: ⁇ terator SNODE, SliceC:: iterator SLPUSE); void bu ⁇ ld_IFKF_Part (SliceC Sl, t posKFOR, SliceC:: iterator SLPUSE); void build_Al_Part (SliceC Sl, int posIFDFOR, SliceC:: iterator SLIF, SliceC:: iterator SLORIG); void bu ⁇ ldD2_IFKF_Part (SliceC Sl, int posKFOR, SliceC:: iterator SLPUSE); void bu ⁇ ldD2_Al_Part (SliceC Sl, int posIFDFOR, SliceC:: iterator SLIF, SliceC:: ⁇ terator SLNODE); int bu ⁇ ldD2InIfTree (SliceC S Sl, SliceC:::: it
- Gatterldent DummyNr ++; ⁇ ; uwgknotenC (NodeldentT _NodeIdent)
- Gatterldent DummyNr ++; ); uwgknotenC (NodeldentT _NodeIdent, t _CauseNr / *, char _gattertext [] * / )
- CauseNr CauseNr; strepyl gate text, "- unknown -”); strepyl gate remark, "—none—”); / * strcpy (gattertext, _gattertext); * /
- VARDEFI L2.beginl
- HLevel LOOPIT-> getLevel ();
- (HELPLOOP-> getLevel ⁇ )! Akt- Level)) ⁇
- HELPIT HELPLOOP
- (HELPLOOP-> getLevel () ' HELPIF-> getLevel ())) (
- KFGListC :: iterator HELPDEF ITER
- KFGListC :: iterator HELPLOOP ITER
- HELPLOOP HELPIT; if (HELPIT-> getLevel ()> 2) (
- HELPIT ⁇ HELPLOOP
- KFGListC:: iterator HELPIT ITER;
- KFGListC:: iterator HELPLOOP ITER;
- KFGListC:: iterator LOWERLIMIT ITER;
- HELPLOOP HELPIT; if (HELPIT-> getLevel ()> 2) (
- AktLevel UPPERLIMIT-> getLevel (); while
- LOWERLIMIT HELPLOOP; ⁇ return LOWERLIMIT;
- KFGUseLi ⁇ tC iterator USEIT
- KFGPJJseListC iterator PUSEIT2
- KFGUseListC iterator CUSEIT2; int node level; int node number;
- UPPERLIMIT findUpperLimitFromCUse (Ll, ITER, USEIT1); HELPIT - findLowerLimitFromCUse (Ll, ITER, UPPERLIMIT); UPPERLIMIT—;
- KFGListC :: iterator HELPIT ITER;
- KFGListC :: iterator HELPLOOP ITER;
- KFGListC:: iterator LOWERLIMIT ITER;
- HELPIT HELPLOOP; // iterator points to the end of the outermost
- HELPIT—; ⁇ if (HELPIT-> getNodeNr () ⁇ UPPERLIMIT-> getNodeNr ()) (LOWERLIMIT HELPLOOP; // upper limit outside the outermost loop;
- LOWERLIMIT HELPLOOP; // upper limit in the same outer loop, but ⁇ // inside a different loop before the c-use; ice (
- LOWERLIMIT HELPLOOP; // upper limit in a lower loop than the c-use; ⁇
- KFGListC:: iterator HELPDEF ITERl
- KFGListC:: iterator HELPLOOP ITERl
- KFGListC:: iterator HELPIT ITERl
- KFGListC:: iterator HELPIF ITERl
- KFGDefListC iterator DEFIT
- AktLevel ITERl-> getLevel ();
- HELPDEF HELPDEFRETURN
- HELPDEFRETURN HELPDEF
- KFGListC TokenL ⁇ st2KFGL ⁇ st (KFGTokenListC S Ll) (int dummy;
- KFGP_UseL ⁇ stC iterator P_USEI
- KFGUseC hUsel (TLI-> getName (), TLI-> getScopeLevel ());
- P_USEI f ⁇ nd (HNl. P_Uses.beginl), hNl. P_Uses.end (), hUsel);
- push_front (hNl); ⁇ break; case DO: push_front (KFGL ⁇ stNodeC ("DOWHILELOOP", DOWL, TLI-> getScopeLevel ())); TLI -;
- HLevel TLI-> getScopeLevel (); push_front (KFGLlstNodeC ("ENDLOOP", EL, LI-> getScopeLevel ()));
- KFGLlstNodeC hNl ("NORMAL", NO, TLI-> getScopeLevel (), TLI-> getLmeNumber ()); hNl.Defs.push_back (KFGDefC (TLI-> getName (), TLI-> getScopeLevel ()));
- Number_defs ++ if (TLI-> getTokenNodeType () - N) (helpNodel.Defs.pop_front (); number_defs—; // in this case it is an array and
- KFGUseC hUse2 (TLI-> getName (), TLI-> getScopeLevel ());
- helpNodel Defs .push_back (KFGDefC (TLI-> getName (), TLI-> getScopeLevel ())); push_front (helpNodel);
- helpNodel > getL ⁇ neNumber ()); helpNodel .Uses. push_back (KFGUseC (TLI-> getName (), TLI-> getScopeLevel ())); push_front (helpNodel);
- PROG1—; dummy 1; ) else ⁇ PROG1—;
- Target «" STOP " « endl «endl; Target «" BASIC SIZES: “« endl; Target «" Number of empty branches: “ « “0” «endl; Target «" Number of decisions: “ « Decisions «final;
- Target « Number of atomic predicates, which are arithmetic relations: " « “0” «endl; Target «" Number of loop decisions: " « Loop decisions «endl;
- Target «" Number of non-nested loop decisions: “« “0” «endl; Target «" number of counting loop decisions: “ « counting loop decisions «endl;
- Target «" Number of declarations of structured data types: “ « “0” «endl; Target «" Number of declarations: “« Number_declarations «endl;
- Target «" Number of real element declarations: “ « “0” «endl; Target «" number of base type declarations: “« number_declarations «endl; Target «" number of defs: “« number_defs «endl; Target «" Number of Uses: “ « Number_Uses «endl; Target «" Number of P-Uses: “ « Number_P_Uses «endl» endl; base size file (); ⁇ void KFGListC:: bas ⁇ sgroessenIn voyage () (ofstream file ("Basisgroessen.bgd”, ⁇ os :: out); file «" 0 "« endl; file «decisions « endl; file «instructions « endl; file «decisions « endl; file «decisions« endl; file «" 0 "« endl; file «loop decisions « endl; file «" 0 " « endl; file «counting loop decisions « endl; file «" 0 " « endl; file «number_declarations
- KFGTokenList.h D void KFGTokenListC:: KFGL ⁇ steAusgabe () (D ofstream destination ("CFGTokenList”); D ostream_ ⁇ terator ⁇ KFGTokenNodeC> oPos (Z ⁇ el, " ⁇ n");
- KFGTokenNode.h include ⁇ ostream> ostreamS Operator «(ostreamS os, const KFGTokenNodeCS Node) (os « Node.Name «" "« Node. ScopeLevel «” "« Node. TokenNodeType «” «Node. IneNumber « endl; return os;
- KFGProgList .h " include ⁇ ostream> static void usagelchar * progname); int maindnt arge, char * argv
Landscapes
- Engineering & Computer Science (AREA)
- Theoretical Computer Science (AREA)
- Quality & Reliability (AREA)
- Physics & Mathematics (AREA)
- General Engineering & Computer Science (AREA)
- General Physics & Mathematics (AREA)
- Software Systems (AREA)
- Computer Hardware Design (AREA)
- Stored Programmes (AREA)
- Debugging And Monitoring (AREA)
Abstract
Aus dem Teil des Computerprogramms werden eine Kontrollflussbeschreibung und eine Datenflussbeschreibung ermittelt und es werden Programmelemente aus dem Teil des Computerprogramms ausgewählt. Für jedes ausgewählte Programmelement wird unter Verwendung einer gespeicherten Fehlerbeschreibung, die jeweils einem Referenzelement zugeordnet ist, eine Elementenfehlerbeschreibung ermittelt, mit der mögliche Fehler des jeweiligen Programmelements beschrieben werden. Aus den Elementenfehlerbeschreibungen wird die Gesamtfehlerbeschreibung unter Berücksichtigung der Kontrollflussbeschreibung und der Datenflussbeschreibung ermittelt.
Description
Beschreibung
Verfahren und Anordnung zur Ermittlung einer Gesamtfehlerbe- Schreibung zumindest eines Teils eines Computerprogramms so- wie Computerprogramm-Erzeugnis und computerlesbares Speichermedium
Die Erfindung betrifft ein Verfahren und eine Anordnung zur Ermittlung einer Gesamtfehlerbeschreibung zumindest eines Teils eines Computerprogramms sowie ein Computer-Erzeugnis und ein computerlesbares Speichermedium.
Ein solches Verfahren und eine solche Anordnung ist aus [1] bekannt.
Aus [1] ist bekannt, eine Gesamtfehlerbeschreibung in Form eines Gesamtfehlerbaums für ein Computerprogramm rechnergestützt zu ermitteln. Für das Computerprogramm wird eine Kontrollflußbeschreibung in Form eines Kontrollflußgraphen er- mittelt. Für verschiedene Programmelemente des Computerprogramms wird unter Verwendung einer gespeicherten Fehlerbeschreibung, die jeweils einem gespeicherten Referenzelement zugeordnet ist, eine Elementenfehlerbeschreibung ermittelt. Mit der Fehlerbeschreibung eines Referenzelements werden mög- liehe Fehler des jeweiligen Referenzelements beschrieben. Aus den Elementenfehlerbeschreibungen in Form von Elementenfeh- lerbäumen wird die Gesamtfehlerbeschreibung unter Berücksichtigung des Kontrollflußgraphen zu den Computerprogramm ermittelt.
Das Verfahren und die Anordnung aus [1] weisen insbesondere folgende Nachteile auf. Der ermittelte Gesamtfehlerbaum ist hinsichtlich der untersuchten Fehler und deren Ursachen unvollständig und damit unzuverlässig. Somit ist diese Vorge- hensweise für sicherheitskritische Anwendungen im Rahmen der Fehlerbaumgenerierung für ein Computerprogramm nicht sinnvoll einsetzbar. Auch sind die einzelnen Fehlerbäume, die den Re-
ferenzelementen zugeordnet sind, unvollständig und damit unzuverlässig.
In [2] ist eine Übersicht über ein sogenanntes Slicing zu finden. Slicing entspricht der Analyse, die bei der Ursachensuche für ein Fehlverhalten eines Computerprogramm.es durchgeführt wird. Im Rahmen dieses Vorgehens wird geprüft, ob das Fehlverhalten durch eine aktuell betrachtete Anweisung verursacht wurde. Ist dies nicht der Fall, so werden die Anweisun- gen überprüft, die für die Anweisung Daten liefern oder ihre Ausführung steuern. Dieses Verfahren wird fortgesetzt, bis keine Vorgänge mehr existieren, also Eingabedaten des Computerprogramms erreicht werden. Beim Slicing werden sogenannte Slices ermittelt. Mit einem Slice wird dargestellt, welche Anweisungen auf welche Weise von einem betrachteten Wert beeinflußt werden. Im weiteren wird unter dem Begriff Slicing stets ein rückwärts gerichtetes Slicing verstanden.
Aus [3] ist es bekannt, zu einem Computerprogramm eine Kon- trollflußbeschreibung und eine Datenflußbeschreibung zu ermitteln. In [3] wird diese Darstellung als Ausgangsbasis für sogenanntes datenflußorientiertes Testen des Computerprogramms eingesetzt. Den Anweisungen (Knoten) des Kontrollflußgraphen werden Datenflußattribute (Datenflußbeschreibung) zu- geordnet, die die Art der in den Anweisungen des Computerpro- grammes enthaltenen Datenzugriffe beschreibt. Es werden schreibende Zugriffe und lesende Zugriffe unterschieden. Schreibzugriffe werden als Definitionen (def) bezeichnet. Lesende Zugriffe werden als Referenz bezeichnet. Erfolgt ein lesender Zugriff in einer Entscheidung, so wird dieser Zugriff als prädikative Referenz (p-use, predicate use) bezeichnet. Ein lesender Zugriff in einer Berechnung eines Wertes wird als berechnende Referenz bezeichnet (c-use, computa- tional use) .
Aus [4] sind Grundlagen über einen Fehlerbaum bekannt. Unter einem Fehlerbaum ist, wie in [4] beschrieben, eine Struktur
zu verstehen, die logische Zusammenhänge zwischen Eingangsgrößen des Fehlerbaums beschreibt, welche Eingangsgrößen zu einem vorgegebenen unerwünschten Ereignis führen.
Ferner sind aus [5] verschiedene Verfahren zur Fehlerbaumanalyse bekannt.
Der Erfindung liegt das Problem zugrunde, eine Gesamtfehlerbeschreibung zu ermitteln, die gegenüber einer gemäß dem Ver- fahren aus [1] bekannten Ermittlung eines Gesamtfehlerbaums zuverlässiger ist.
Das Problem wird durch das Verfahren sowie durch die Anordnung mit den Merkmalen gemäß den unabhängigen Ansprüchen so- wie durch das Computer-Erzeugnis und das computerlesbare
Speichermedium mit den Merkmalen gemäß den unabhängigen Ansprüchen gelöst.
Bei einem Verfahren zur Ermittlung einer Gesamtfehlerbe- Schreibung zumindest eines Teils eines Computerprogrammes, durch einen Computer, ist zumindest der Teil des Computerprogrammes gespeichert. Es wird eine Kontrollflußbeschreibung und eine Datenflußbeschreibung zu dem Teil des Computerprogrammes ermittelt und es werden Programmelemente aus dem Teil des Computerprogrammes ausgewählt. Für jedes ausgewählte Programmelement wird unter Verwendung einer gespeicherten Fehlerbeschreibung eine Elementenfehlerbeschreibung ermittelt. Die Fehlerbeschreibung ist jeweils einem Referenzelement zugeordnet. Mit der Elementenfehlerbeschreibung werden mögliche Fehler des jeweiligen Programmelementes beschrieben. Mit einer Fehlerbeschreibung eines Referenzelements werden mögliche Fehler des jeweiligen Referenzelements beschrieben. Aus den Elementenfehlerbeschreibungen wird unter Berücksichtigung der Kontrollflußbeschreibung und der Datenflußbeschreibung die Gesamtfehlerbeschreibung ermittelt.
Eine Anordnung zur Ermittlung einer Gesamtfehlerbeschreibung zumindest eines Teils eines Computerprogrammes weist einen Prozessor auf, der derart eingerichtet ist, daß folgende Verfahrensschritte durchführbar sind: - Zumindest der Teil des Computerprogramms ist gespeichert,
- es werden eine Kontrollflußbeschreibung und eine Datenflußbeschreibung für den Teil des Computerprogramms ermittelt,
- aus dem Teil des Computerprogrammes werden Programmelemen- te ausgewählt,
- für jedes ausgewählte Programmelement wird unter Verwendung einer gespeicherten Fehlerbeschreibung, die jeweils einem Referenzelement zugeordnet ist, eine Elementenfehlerbeschreibung ermittelt, mit der mögliche Fehler des je- weiligen Programmelements beschrieben werden,
- mit einer Fehlerbeschreibung eines Referenzelements werden mögliche Fehler des jeweiligen Referenzelements beschrieben,
- aus den Elementenfehlerbeschreibungen wird die Gesamtfeh- lerbeschreibung unter Berücksichtigung der Kontrollflußbeschreibung und der Datenflußbeschreibung ermittelt.
Ein Computerprogramm-Erzeugnis umfaßt ein computerlesbares Speichermedium, auf dem ein Programm gespeichert ist, daß es einem Computer ermöglicht, nachdem es in einen Speicher des
Computers geladen worden ist, folgende Schritte durchzuführen zur Ermittlung einer Gesamtfehlerbeschreibung zumindest eines Teils eines Computerprogramms:
- Zumindest der Teil des Computerprogramms ist gespeichert, - es werden eine Kontrollflußbeschreibung und eine Datenflußbeschreibung für den Teil des Computerprogramms ermittelt,
- aus dem Teil des Computerprogrammes werden Programmelemente ausgewählt, - für jedes ausgewählte Programmelement wird unter Verwendung einer gespeicherten Fehlerbeschreibung, die jeweils einem Referenzelement zugeordnet ist, eine Elementenfeh-
lerbeschreibung ermittelt, mit der mögliche Fehler des jeweiligen Programmelements beschrieben werden,
- mit einer Fehlerbeschreibung eines Referenzelements werden mögliche Fehler des jeweiligen Referenzelements beschrie- ben,
- aus den Elementenfehlerbeschreibungen wird die Gesamtfehlerbeschreibung unter Berücksichtigung der Kontrollflußbeschreibung und der Datenflußbeschreibung ermittelt.
Auf einem computerlesbaren Speichermedium ist ein Programm gespeichert, daß es einem Computer ermöglicht, nachdem es in einen Speicher des Computers geladen worden ist, folgende Schritte durchzuführen zur Ermittlung einer Gesamtfehlerbeschreibung zumindest eines Teils eines Computerprogramms: - Zumindest der Teil des Computerprogramms ist gespeichert,
- es werden eine Kontrollflußbeschreibung und eine Datenflußbeschreibung für den Teil des Computerprogramms ermittelt,
- aus dem Teil des Computerprogrammes werden Programmelemen- te ausgewählt,
- für jedes ausgewählte Programmelement wird unter Verwendung einer gespeicherten Fehlerbeschreibung, die jeweils einem Referenzelement zugeordnet ist, eine Elementenfehlerbeschreibung ermittelt, mit der mögliche Fehler des je- weiligen Programmelements beschrieben werden,
- mit einer Fehlerbeschreibung eines Referenzelements werden mögliche Fehler des jeweiligen Referenzelements beschrieben,
- aus den Elementenfehlerbeschreibungen wird die Gesamtfeh- lerbeschreibung unter Berücksichtigung der Kontrollflußbeschreibung und der Datenflußbeschreibung ermittelt.
Durch die Erfindung ist es nunmehr möglich, eine zuverlässige, die Eigenheiten eines Computerprogramms berücksichtigende Gesamtfehlerbeschreibung für ein Computerprogramm oder einen Teil desselben zu ermitteln. Da die ermittelte Gesamtfehlerbeschreibung wesentlich zuverlässiger ist als die gemäß dem
Verfahren aus [1] ermittelbare Gesamtfehlerbeschreibung, ist die Erfindung auch für sicherheitskritische Anwendungen, d.h. insbesondere für die Ermittlung einer Gesamtfehlerbeschreibung eines sicherheitskritischen Computerprogramms geeignet.
Bevorzugte Weiterbildungen der Erfindung ergeben sich aus den abhängigen Ansprüchen.
Die Kontrollflußbeschreibung und/oder die Datenflußbeschrei- bung kann/können in Form eines Kontrollflußgraphen bzw. eines Datenflußgraphen vorliegen.
Die Fehlerbeschreibung kann in Form eines gespeicherten Fehlerbaums vorliegen und die Elementenfehlerbeschreibung kann als Elementenfehlerbaum ermittelt werden. In diesem Fall kann die Gesamtfehlerbeschreibung als Gesamtfehlerbaum ermittelt werden.
Durch diese Weiterbildung ist eine standardisierte Darstel- lung einer Fehlerbeschreibung möglich, was es einem Benutzer der Fehlerbeschreibung erheblich vereinfacht, diese zu analysieren.
Die Gesamtfehlerbeschreibung kann in einer Weiterbildung ein- gesetzt werden zur Fehleranalyse des Teils des Computerprogramms .
Diese Weiterbildung weist insbesondere den Vorteil auf, daß eine automatisierte, zuverlässige Fehleranalyse, bei Vorlie- gen der Fehlerbeschreibungen in Form von Fehlerbäumen sogar eine gemäß den Fehlerbaumanalyseverfahren "normierte" Analyse der Fehlerbeschreibung möglich wird.
In einer weiteren Ausgestaltung wird die Gesamtfehlerbe- Schreibung als Gesamtfehlerbaum ermittelt und der Gesamtfehlerbaum wird hinsichtlich vorgebbarer Rahmenbedingungen verändert.
Die Veränderung kann durch Hinzufügen eines Ergänzungsfehlerbaums erfolgen.
Ein Ausführungsbeispiel der Erfindung ist in den Figuren dargestellt und wird im weiteren näher erläutert:
Es zeigen
Figur 1 einen Computer, mit dem das Verfahren gemäß dem Ausführungsbeispiel durchgeführt wird; Figur 2 ein Ablaufdiagramm, in dem die einzelnen Verfahrensschritte des Verfahrens gemäß dem Ausführungsbeispiel dargestellt sind; Figur 3 eine Darstellung eines allgemeinen Fehlerbaums, wie er für ein Referenzelement prinzipiell gebildet wird; Figuren 4a bis 4c einen Kontrollflußgraphen (Figur 4a) , einen Slice (Figur 4b) und einen Fehlerbaum (Figur 4c) für eine Anweisungssequenz als Referenzelement eines Com- puterprogramms;
Figuren 5a bis 5c einen Kontrollflußgraphen (Figur 5a), einen Slice (Figur 5b) und einen Fehlerbaum (Figur 5c) für eine Auswahlsequenz als Referenzelement eines Computerprogramms; Figur 6a bis 6c einen Kontrollflußgraphen (Figur 6a), einen Slice (Figur 6b) und einen Fehlerbaum (Figur 6c) für eine Schleife als Referenzelement eines Computerprogramms; Figur 7 ein Kontrollflußgraph mit Datenflußgraph zu einem Computerprogramm gemäß dem Ausführungsbeispiel;
Figuren 8a und 8b einen Slice der Ausgabe der Variable max
(Figur 8a) bzw. einen Slice zu der Variable avr (Figur 8b) zu dem Programm gemäß dem Ausführungsbei- spiel; Figur 9 den Slice für die Variable avr, in dem eine Struktur der Schleife aus dem Programm des Ausführungsbei- spiels hervorgehoben ist;
Figur 10 einen Fehlerbaum für die Annahme, daß die Variable avr fehlerhaft ist; Figur 11 den Gesamtfehlerbau gemäß Figur 10, wobei redundante Ereignisse aus dem Gesamtfehlerbaum gemäß Figur 10 zu einem Ereignis zusammengefaßt worden sind.
Fig.l zeigt einen Computer 100 mit dem das im weiteren beschriebene Verfahren durchgeführt wird.
Der Computer 100 weist einen Prozessor 101 auf, der über einen Bus 103 mit einem Speicher 102 verbunden ist. Mit dem Bus 103 ist ferner eine Eingangs-/Ausgangsschnittstelle 106 verbunden.
In dem Speicher 102 ist ein Computerprogramm 104 gespeichert, für das auf die im folgenden beschriebene Weise eine Gesamtfehlerbeschreibung ermittelt wird. Ferner ist in dem Speicher 102 ein Programm 105 gespeichert, durch das das im weiteren beschriebene Verfahren realisiert ist. Ferner sind in dem Speicher Fehlerbeschreibungen 115 unterschiedlicher
Referenzelemente eines Computerprogramms gespeichert. Mit einer Fehlerbeschreibung eines Referenzelements werden mögliche Fehler des jeweiligen Referenzelements beschrieben. Verschiedene Referenzelemente und den Referenzelementen zugeordnete Fehlerbeschreibungen werden im weiteren detailliert erläutert.
Mit der Eingangs-/Ausgangsschnittstelle 106 ist über eine erste Verbindung 107 eine Tastatur 108 verbunden. Über eine zweite Verbindung 109 ist die Eingangs-/Ausgangsschnittstelle 106 mit einer Computermaus 110 und über eine dritte Verbindung 111 ist die Eingangs-ΛAusgangsschnittstelle 106 mit einem Bildschirm 112 verbunden, auf dem die ermittelte Gesamtfehlerbeschreibung des Computerprogramms 104 dargestellt wird. Über eine vierte Verbindung 113 ist die Eingangs-
/Ausgangsschnittsteile 106 mit einem externen Speichermedium 114 verbunden.
Fig.2 zeigt in einem Blockschaltbild die Vorgehensweise gemäß dem im weiteren beschriebenen Ausführungsbeispiel.
Aus dem gespeicherten Computerprogramm 104 werden ein Kontrollflußgraph 201 und ein Datenflußgraph 202 für das Computerprogramm 104 ermittelt.
Aus dem Computerprogramm werden einzelne Programmelemente ausgewählt (Schritt 203) . Für jedes ausgewählte Programmelement wird unter Verwendung einer gespeicherten Fehlerbeschreibung, die einen zu dem ausgewählten Programmelement korrespondierenden Referenzelement zugeordnet ist, eine Elementenfehlerbeschreibung ermittelt (Schritt 204) . Mit der Elementenfehlerbeschreibung werden mögliche Fehler des jeweiligen ausgewählten Programmelements beschrieben.
Ausgehend von einem von einem Benutzer vorgegebenen zu untersuchenden Fehlerereignis in dem Computerprogramm (unerwünsch- tes Ereignis) wird in einem letzten Schritt (Schritt 205) eine Gesamtfehlerbeschreibung des Computerprogrammes für den zu untersuchenden Fehlerfall ermittelt aus den Elementenfehlerbeschreibungen, wobei der Kontrollflußgraph und der Datenflußgraph berücksichtigt werden.
Der ermittelte Gesamtfehlerbaum wird dem Benutzer auf dem Bildschirm 112 dargestellt.
Fig.3 zeigt die grundlegende Vorgehensweise bei der Erstel- lung eines Fehlerbaums, wie sie im Rahmen des Ausgangsbeispiels verwendet worden ist zur Bildung der im weiteren beschriebenen Fehlerbäume zu den Referenzelementen.
Zu einem von einem Benutzer ausgewählten Ereignis 301 ist zu ermitteln, wie das ausgewählte fehlerhafte Ereignis entstehen kann. Bei einem Computerprogramm kann eine fehlerhafte Ausgabe einer Variablen als ausgewähltes fehlerhaftes Ereignis
(unerwünschtes Ereignis) 301 verursacht werden durch einen Kontrollflußfehler 303 und/oder einen Datenfehler 304 (INKLUSIV-ODER-Verknüpfung 302) .
Unter einem Kontrollflußfehler 303 ist eine fehlerhafte An- steuerung der Verarbeitung der jeweiligen Variablen zu verstehen.
Unter dem Datenflußfehler 304 ist ein Fehler zu verstehen, der durch fehlerhafte Daten bei der Verarbeitung entsteht.
Der Datenflußfehler 304 kann in dem aktuell betrachteten Verarbeitungsschritt neu entstehen (Block 306) und/oder er kann schon vorhanden gewesen sein und lediglich durch Fehlerpropa- gation erhalten bleiben Block 307) (INKLUSIV-ODER-Verknüpfung 305) .
Ausgehend von diesen Überlegungen werden im weiteren für folgende Elemente eines Computerprogrammes jeweils der entspre- chende Fehlerbaum, ein die Anweisung beschreibender Slice sowie ein Kontrollflußgraph dargelegt:
- eine Anweisungssequenz,
- ein Auswahlelement,
- ein Schleifenelement.
Anweisungssequenz
Die Anweisungssequenz 401 weist die in Fig.4a dargestellten drei Anweisungen auf. In einer ersten Anweisung 402 wird einer ersten Variable j der Wert 3 zugewiesen (j := 3) . Durch eine zweite Anweisung 403 wird einer zweiten Variable k der Wert 2 zugeordnet (k := 2) . Durch eine dritte Anweisung 404 wird eine Summe über die erste Variable und die zweite Varia- ble gebildet (i := j + k) .
Es wird gemäß der Vorgehensweise aus [2] zu dieser Anweisungssequenz 401 ein Slice 410 gebildet, wie er in Fig. b dargestellt ist. Die erste Anweisung 402 und die zweite Anweisung 403 haben beide Auswirkungen auf die dritte Anweisung 404, was durch zwei Pfeile 411, 412 in dem Slice 410 dargestellt ist.
Zu dem Kontrollflußgraph 401 ergibt sich der in Fig. c dargestellte Fehlerbaum 420 für folgendes vorgegebenes unerwünsch- tes Ereignis 421:
"Variable i ist nach der dritten Anweisung fehlerhaft".
Das fehlerhafte Ereignis 421 kann durch einen Fehler bei der betrachteten dritten Anweisung 404 selbst bei bis zu diesem Anweisungsschritt korrekten Daten erzeugt worden sein (Element 422 in Fig.4c) . Das fehlerhafte Ereignis 421 kann jedoch auch durch verfälschte Eingabedaten der dritten Anweisung verursacht werden, d.h. durch INKLUSIV-ODER-Verknüpfung 424 der Ereignisse, daß die zweite Variable k nach der zweiten
Anweisung fehlerhaft war (Element 425) und/oder daß die erste Variable j nach der ersten Anweisung 402 fehlerhaft war (Element 426) . Das Ergebnis der ersten INKLUSIV-ODER-Verknüpfung 424 wird inklusiv-oder verknüpft mit dem Ereignis, daß die dritte Anweisung fehlerhaft ist (INKLUSIV-ODER-Verknüpfung 423) .
Auswahlelement
Bei einem Auswahlelement als Referenzelement müssen Fehlermöglichkeiten der Datenflüsse und der Kontrollflüsse innerhalb des Computerprogramms beachtet werden.
In den Fig.5a bis Fig.5c ist ein Kontrollflußgraph 501 (vgl. Fig.5a), ein Slice 520 (vgl. Fig.5b) sowie ein Fehlerbaum 540
(vgl. Fig.5c) für eine If-Then-Else-Anweisung als Auswahlelement dargestellt.
Der Kontrollflußgraph 501 umfaßt folgende sechs Anweisungen: - Eine erste Anweisung 502, mit der einer ersten Variable j der Wert 3 zugeordnet wird (j := 3),
- eine zweite Anweisung 503, mit der einer zweiten Variable k ein vorgebbarer Wert zugeordnet wird (k := ...),
- eine dritte Anweisung 504, in der überprüft wird, ob die zweite Variable k einen Wert größer als 0 aufweist; ist der Wert der zweiten Variable größer 0, dann verzweigt die Anweisung zu einer vierten Anweisung 505, sonst zu einer fünften Anweisung 506,
- die vierte Anweisung 505, in der einer dritten Variable i der Wert der zweiten Variable k zugeordnet wird (i := k) ,
- eine fünfte Anweisung 506, in der der dritten Variable i der Wert der zweiten Variable k mit negativem Vorzeichen zugeordnet wird (i:=-k),
- eine sechste Anweisung 507, in der die dritte Variable i in beliebiger Weise weiterverarbeitet wird.
Zu dem in Fig.5a dargestellten Kontrollflußgraphen 501 ergibt sich für das Auswahlelement der in Fig.5b dargestellte Slice 520.
Durchgezogene Kanten in dem Slice 520 stellen eine Datenabhängigkeit der unterschiedlichen Anweisungen voneinander dar.
Mit gestrichelten Kanten werden Kontrollabhängigkeiten der entsprechenden Anweisungen voneinander angegeben.
Für die beiden Kantentypen gelten die folgenden Definitionen:
- gestrichelte Kanten, im weiteren als Kontrollkanten bezeichnet, sind von Anweisungen, die eine prädikative Refe- renz enthalten (Ausfallkonstrukte, Schleifensteuerung) , auf die unmittelbar kontrollierten Anweisungen gerichtet, d.h. auf jene Anweisungen, die nur ausgeführt werden, wenn
das Prädikat einen bestimmten Wert hat. Kontrollkanten werden nur zwischen der kontrollierenden Anweisung und unmittelbar eingeschachtelten Anweisungen gezogen. Ist in einem kontrollierten Block eine weitere Kontrollebene ein- geschachtelt, so werden keine Kontrollkanten gezogen, die mehr als eine Ebene überstreichen. Da eine Kontrollbeziehung transitiv ist, kann diese mittelbare Kontrolle aus dem Slice durch Ausnutzung der Transitivität geschlossen werden. - durchgezogene Kanten, im weiteren als Datenflußkanten bezeichnet, sind von Anweisungen, in denen eine Variable definiert wird, auf Anweisungen gerichtet, in denen diese Variable referenziert wird. Die betrachtete Variable darf zwischen der Definition und der Referenz nicht erneut de- finiert werden. Man bezeichnet dies als definitionsfreien Pfad bezüglich der betrachteten Variablen.
Der Slice wird ermittelt, indem ausgehend von der Anweisung mit der betrachteten Variablen, für die das unerwünschte Er- eignis vorgegeben wird, der Kontrollflußgraph gegen die Kantenrichtung nach Definition der betrachteten Variablen durchsucht wird. Existieren zu der Definition berechnende Referenzen, so wird das Verfahren rekursiv fortgesetzt, bis keine zusätzlichen Knoten mehr gefunden werden. Die auf diese Weise gefundenen Abhängigkeiten zwischen Anweisungen sind Datenabhängigkeiten. Befindet sich ein betrachteter Knoten in einem Block, dessen Ausführung von einer Entscheidung direkt gesteuert wird, so stellt dies eine Kontrollabhängigkeit dar. Für die prädikativen Referenzen der in der Entscheidung be- teiligten Variablen werden Knoten mit entsprechenden Definitionen - also Datenflußabhängigkeiten - rekursiv gesucht, die weitere Kontrollabhängigkeiten besitzen.
Fig.5b zeigt den zu dem Ausfallelement gehörenden Slice 520 mit entsprechenden Kontrollkanten und Datenflußkanten.
Fig.5c zeigt den Fehlerbaum 540 für das vorgegebene Ereignis "die dritte Variable i ist vor der 6. Anweisung fehlerhaft" 541.
Folgende Ereignisse führen in INKLUSIV-ODER-Verknüpfung 542 zu dem fehlerhaften Ereignis 541:
- eine UND-Ver nüpfung 543 der Ereignisse, daß die Entscheidung gemäß der dritten Anweisung 504 wahr ist (Element 544) und einem Ergebnis einer INKLUSIV-ODER-Verknüpfung 545 der Ereignisse, daß die vierte Anweisung 505 fehlerhaft ist (Element 546) und/oder die erste Variable j nach der ersten Anweisung 502 fehlerhaft ist (Element 547);
- eine UND-Verknüpfung 550 der Ereignisse, daß die Entscheidung gemäß der dritten Anweisung 504 falsch ist (Element 551) mit einem Ergebnis einer INKLUSIV-ODER-Verknüpfung 552 der Ereignisse, daß die fünfte Anweisung fehlerhaft ist (Element 553) und/oder daß die erste Variable j nach der ersten Anweisung 502 fehlerhaft ist (Element 554);
- eine INKLUSIV-ODER-Verknüpfung 560 der Ereignisse: Die Entscheidung gemäß der dritten Anweisung 504 ist fehlerhaft (Element 561) und/oder die zweite Variable k ist nach der zweiten Anweisung 503 fehlerhaft (Element 562) .
Mehrfach-Auswahlelement
Ein Mehrfach-Auswahlelement als Referenzelement kann nach dem oben beschriebenen Schema durch Aufbrechen der Mehrfachauswahl in eine Kaskade von zweiseitigen Auswahlelementen, die gemäß dem oberen Vorgehen bearbeitet werden, behandelt werden, um somit einen Fehlerbaum für ein Mehrfach- Auswahlelement zu ermitteln.
Schleife
Die Fig.6a bis Fig.6c zeigen für das Referenzelement einer Schleife einen Fehlerbaum 601 (vgl. Fig.6a), den entsprechenden Slice 620 (vgl. Fig.6b) sowie den zugehörigen Fehlerbaum 640 (vgl. Fig.6c) .
Der Kontrollflußgraph 601 für ein Schleifenelement weist folgende sieben Anweisungen auf:
- Eine erste Anweisung 602, mit der einer erste Variable i der Wert 0 zugeordnet wird (i := 0), - eine zweite Anweisung 603, mit der einer zweiten Variable j ein Wert frei zugeordnet wird (j := ...),
- eine dritte Anweisung 604, durch die einer dritten Variable k ein weiterer Wert frei vorgegeben wird (k := ...),
- eine vierte Anweisung 605, die als Schleifenanweisung eine Bedingung angibt, daß eine fünfte Anweisung sowie eine sechste Anweisung solange durchgeführt werden, solange der Wert der zweiten Variablen j > 0 ist (WHILE j > 0 DO) ,
- eine fünfte Anweisung 606, in der der ersten Variable i ein Wert zugeordnet wird, der sich ergibt aus der Summe des bisherigen Werts der ersten Variable sowie dem Produkt aus der zweiten Variable und der dritten Variable (i := i + k * j),
- eine sechste Anweisung 607, durch die der zweiten Variable j ein Wert zugewiesen wird, der sich ergibt durch Vermin- derung des ursprünglichen Werts der zweiten Variable j um den Wert 1 (j := j - 1) ,
- eine siebte Anweisung 608, in der die erste Variable i in vorgebbarer Weise weiterbearbeitet wird (... := i ...).
Fig.6b zeigt den entsprechenden Slice 620 zu dem in Fig.6a dargestellten Kontrollflußgraphen 601 mit zugehörigen Kontrollflußkanten und Datenflußkanten.
Der in Fig.6c dargestellte Fehlerbaum 640 wird gebildet für das vorgegebene Ereignis 641, daß die "erste Variable i vor der siebten Anweisung fehlerhaft" ist.
Der Fehlerbaum 640 ergibt sich durch INKLUSIV-ODER- Verknüpfung 642 folgender vier Ereignisse:
- Ein erstes Ereignis 643, das beschreibt, daß die erste Variable i nach der ersten Anweisung 602 fehlerhaft ist, - eine UND-Verknüpfung 644 aus den Ereignissen, daß der
Schleifenrumpf der Schleife mindestens zweimal durchlaufen worden ist (Element 645) und dem Ereignis, daß die sechste Anweisung 607 fehlerhaft ist (646),
- eine UND-Verknüpfung 650 des Ereignisses, daß der Schlei- fenrumpf mindestens einmal ausgeführt wurde (Element 651) und einer IΝKLUSIV-ODER-Verknüpfung 652 folgende vier Ereignisse: a) die fünfte Anweisung 606 ist fehlerhaft (Element 653), b) die erste Variable i ist nach der ersten Anweisung feh- lerhaft (Element 654) c) die zweite Variable j ist nach der zweiten Anweisung fehlerhaft (Element 655), d) die dritte Variable k ist nach der dritten Anweisung fehlerhaft (Element 656), - eine IΝKLUSIV-ODER-Verknüpfung 660 folgender drei Ereignisse: e) die Entscheidung gemäß der vierten Anweisung 605 ist fehlerhaft (Element 661), f) die zweite Variable j ist nach der zweiten Anweisung 603 fehlerhaft (Element 662), g) eine UND-Verknüpfung 663 der Ereignisse, daß die sechste Anweisung fehlerhaft ist (Element 664) mit dem Ereignis, daß der Schleifenrumpf mindestens einmal durchlaufen worden ist (Element 665) .
Die oben beschriebenen Fehlerbäume, die den einzelnen Referenzelementen zugeordnet sind, sind in dem Speicher 102 als Fehlerbäume 115 gespeichert.
Fig.7 zeigt einen Kontrollflußgraphen 700 zu folgendem Computerprogramm:
input (n) ; input (a) ; max:=0; sum:=0; i : =2 ;
WHILE i =n DO IF max < a[i]
THEN max:= a[i] sum:= sum + a[i] i:= i + 1 avr:= sum/n; output (max) ; Output (avr) ;
Zu dem in Fig.7 dargestellten Kontrollflußgraphen 700 mit 13 Anweisungen (Bezugszeichen 1, 2, 3, ..., 13) zeigt Fig.8a den zugehörigen Slice 800 zu der Variablen max und Fig.8b den zugehörigen Slice 810 zu der Variablen avr. Die Numerierung der einzelnen Anweisungen in den Slices entspricht der Numerierung der einzelnen Anweisungen in dem Kontrollflußgraphen 700 aus Fig.7.
Fig.9 zeigt den Slice 900 für die Variable avr, wie er in Fig.8b dargestellt ist. Die Struktur des in dem oben dargestellten Programm enthaltenen Schleifenelements ist durch Fettdruck hervorgehoben. Diese Struktur entspricht dem in Fig.6b dargestellten Slice für ein Schleifenelement.
Ein Gesamtfehlerbaum 1000 für das oben dargestellte Computerprogramm ist in Fig.10 dargestellt. Der Gesamtfehlerbaum für das Computerprogramm wird durch Instantiieren des entspre- chenden Fehlerbaums, der dem Referenzelement zugeordnet ist, das dem ausgewählten Programmelement entspricht, erzeugt.
Durch rückwärts gerichtetes Vorgehen ausgehend von dem vorgegebenen unerwünschten Ereignis wird somit unter Verwendung der den Referenzelementen zugeordneten Fehlerbäume der Gesamtfehlerbaum 1000 ermittelt.
In Fig.10 ist der Fehlerbaum 1000 zu dem Ereignis, daß "die Variable avr vor der dreizehnten Anweisung fehlerhaft" ist (Element 1001) . Die Variable avr kann vor der dreizehnten Anweisung 13 fehlerhaft sein aufgrund mindestens eines der fol- genden drei Ereignisse, wie dies auch in dem in Fig.9 dargestellten Slice 900 für die Variable avr dargestellt ist (INKLUSIV-ODER-Verknüpfung 1002) :
- Eine Eingangsvariable n ist nach der ersten Anweisung 1 fehlerhaft (Element 1003), - die elfte Anweisung 11 ist fehlerhaft (Element 1004),
- der Wert der Variablen sum vor der elften Anweisung 11 ist fehlerhaft (Element 1005) .
Die Variable sum ist vor der elften Anweisung 11 fehlerhaft (Element 1005), wenn mindestens eines der folgenden Ereignisse erfüllt ist (INKLUSIV-ODER-Verknüpfung 1006) :
- Die Variable sum ist nach der vierten Anweisung 4 fehlerhaft (Element 1007) ,
- eine UND-Verknüpfung 1008 des Ereignisses, daß mindestens zweimal der Schleifenrumpf ausgeführt worden ist (Element
1009) mit dem Ereignis, daß die zehnte Anweisung 10 fehlerhaft ist (Element 1010),
- eine UND-Verknüpfung 1011 des Ereignisses, daß mindestens einmal der Schleifenrumpf ausgeführt worden ist (Element 1012) mit dem Ergebnis einer INKLUSIV-ODER-Verknüpfung 1013 folgender vier Ereignisse: a) die neunte Anweisung 9 ist fehlerhaft (Element 1014), b) die Variable sum ist nach der vierten Anweisung 4 fehlerhaft (Element 1015) , c) die Variable i ist nach der fünften Anweisung 5 fehlerhaft (Element 1016) ,
d) die Variable a ist nach der zweiten Anweisung 2 fehlerhaft (Element 1017) ,
- eine INKLUSIV-ODER-Verknüpfung 1018 folgender Ereignisse: e) die Entscheidung gemäß der sechsten Anweisung ist feh- lerhaft (Element 1019), f) die Variable i ist nach der fünften Anweisung fehlerhaft (Element 1020) , g) die Variable n ist nach der ersten Anweisung fehlerhaft (Element 1021) , h) eine UND-Verknüpfung 1022 des Ereignisses, daß die 10. Anweisung fehlerhaft ist (Element 1023) mit dem Ereignis, daß mindestens einmal der Schleifenrumpf ausgeführt worden ist (Element 1024) .
Der Fehlerbaum 1000 aus Fig.10 wird zur anschaulicheren Darstellung dahingehend verändert, daß Ereignisse, die in dem Fehlerbaum 1000 mehrfach dargestellt sind, zu einem Knoten eines Ursache-Wirkungs-Graphen 1100 (vgl. Fig.11) zusammengefaßt werden.
Auf den in Fig.10 dargestellten Fehlerbaum 1000 wird ein Fehlerbaumanalyseverfahren, wie in [5] beschrieben, angewendet, wodurch eine Analyse des Computerprogramms hinsichtlich eines vorgegebenen unerwünschten Ereignisses analysiert wird.
Im weiteren werden Alternativen und weitere Anwendungsmöglichkeiten des oben beschriebenen Ausführungsbeispiels dargestellt.
Der mit dem oben beschriebenen Verfahren erzeugte Gesamtfehlerbaum kann zu verschiedenen Zwecken eingesetzt werden:
- Beschreibung der Fehlererzeugung bzw. Fehlverhaltenspropa- gation durch einen Teil eines Computerprogramms im Rahmen einer Sicherheitsanalyse oder eine Zuverlässigkeitsanalyse des Computerprogramms,
- Analyse von Softwarefehlermechanismen, beispielsweise im Rahmen einer Testfallgenerierung.
Im weiteren ist ein Computerprogramm in der Programmiersprache C++ angegeben, mit dem das Verfahren gemäß dem Ausführungsbeispiel realisiert ist :
#ιnclude "AS_GraphKante.h"
D dinclude <ιostream>
D
0 ostreamS Operator « ( ostreamS os, const GraphKanteC & Kante) 0 os « Kan e.KantenTyp; o return os;
0 } π π/π/i/i π ππ/ππ/π/π/ππ/ππ/ππ/π/iπi/ππ/ii in/// /////////////////////
I / Klasse zur Erzeugung von Kanten im Slice-Graph. // Es gibt zwei Arten von Kanten: // 1. Kontroll luß-Kanten KFK // 2. Datenfluß-Kanten DFK
// Auch diese Klasse erfüllt die nice-Anforderungen für die STL.
// //ππ/ππiππiππi/πiππ/π/π in π /ππi/π/πi/ππ///////// ///////// //////
II 1997-09-12 Andreas Steinhorst ππmiiimmiπiππimmmiπimmmiiiiπm nimm m mπiiππiiiim Olfndef _GraphNodeHeader Kdefine _GraphNodeHeader
Kmclude <ιostream> «include "KFGListNode.h" usmg namespace std; class GraphNodeC : public KFGListNodeC { public:
//GraphNodeC! ) {); friend ostreamS Operator « ( ostreamS os, const GraphNodeCS Node); );
#endιf /////////////////////// iπ/iπ/i/π in ππ/π/iimπ in // in π π ////////// /////////// o
// Klasse zur Erstellung eines Slice. Dieser Klasse wird ein leeres Objekt
D
// der Klasse Graph vererbt. o
// Die Ecken des Graphen/Slice haben dieselbe Struktur wie die Listen im KFG. // Die Kanten sind von Typ KantenTypT; eine Klasse GraphKanteC ließ sich aus // für mich unersichtlichen Gründen nicht in die Klasse Graph einbinden. // // III l/ll 1/ 1/ 1/ 1/1 /Hl/// HIIIIH II 1997-09-12 Andreas Steinhorst ππmimπimπimmimmmmmmmπiπimimπim/mπimimiim flifdef _SlιceHeader #else #defιne _SlιceHeader
#ιnclude "graph.h" Kinclude "AS_GraphKante.h" //»lnclude "AS GraphNode.h" Hinclude "KFGListNode.h" (fmclude "KFGList.h"
//using namespace std;
//typedef enum (DFK, KFK} KantenTypT;
class SliceC : public Graph<KFGLιstNodeC,GraphKanteC> { public:
SliceC () {}; void sliceForLoops (KFGListC S L2, KFGListC: : iterator LOOPIT); KFGListC: : iterator defineVariableToSlice (KFGListC S L2);
//void buildTestGraph (KFGListC s L2); void fmdAllDefs (KFGListC S Ll, KFGListC: : iterator ITER);
KFGListC: : iterator findUpperLimit (KFGListC s Ll, KFGListC: : iterator ITER, KFGP UseListC: : iterator PUSEIT);
KFGListC: : iterator fmdLowerLimit (KFGListC & Ll, KFGListC: : iterator ITER, KFGListC:: iterator UPPERLIMIT);
KFGListC: : iterator findLowerLimitFromCUse (KFGListC S Ll, KFGListC: -.iterator ITER, KFGListC: : iterator UPPERLIMIT); KFGListC: : iterator findUpperLimitFromCUse (KFGListC S Ll, KFGListC: : iterator ITER,
KFGUseListC: : iterator USEIT); int checkForNodes (int NodeNumber); void KFKPUseToCUse (KFGListC: :ιterator PUSEIT, int SchleifenEnde) ; void fmdDefToCUse (KFGListC S Ll, KFGListC: : iterator ITER); void deflnLooplKFGListC S Ll, KFGListC: : iterator ITER); void startBuildSlice (KFGListC S Ll ) ; void sliceAusgebenl ) ; );
«endif πiiiimi miiπimiii mm im m mmmi/i/mi m um
II Mit einigen Änderungen übernommen aus "Die C++ Standard Template Library".
//
// Template-Klasse Graph zur Erstellung von gerichteten oder ungeπchteten
// Graphen. Der Graph besteht aus einem Vektor E für alle Ecken. Jedes // Vektorelement besteht wiederum aus einem Paar: der Ecke und der Menge der
// Nachfolger.
// Die Menge der Nachfolger wird durch den STL Datentyp map dargestellt; der
// Schlüssel zu einem Kantentyp/Kantenwert ist die Nummer einer nachfolgenden
// Ecke. // III
#ιfndef _graphHeader
#defιne _graphHeader
#ιnclude <assert.h> (tinclude <map> flinclude <stack>
#ιnclude <vector> iinclude "checkvec.h"
(finclude <ιostream> «include "AS_GraphNode.h" using namespace std;
// Leere Parameterklasse mit Mindestsatz von Operationen, // falls keine Kantengewichte benötigt werden. struct Empty { public:
Empty(mt=0) () bool operator< (const Empty ) const { return true; )
// Empty-Operationen, damit Ein-Ausgabe allgemein formuliert
// werden kann
//ostreamS operator«(ostreamS os, const Emptys) { return os; )
//istream Operator» (istream is, Emptys ) { return ιs;( template<class Eckentyp, class Kantentyp> class Graph ( public: typedef map<ιnt, Kantentyp, less<int> > Nachfolger; typedef paιr<Eckentyp, Nachfolger> Ecke; typedef checkedVector<Ecke> Graphtyp;
//typedef vector<Ecke> Graphtyp; typedef Graphtyp: : iterator iterator; typedef Graphtyp: :const_ιterator const_ιterator; Graph (bool g, ostreamS os = cerr)
: gerichte (g) , pOut(Soε) {}
Graph ( ) { } sιze_t sιze() const { return C.sιze(); } bool istGerichtet ( ) const { return gerichtet;} iterator beginl) { return C.beginf);} iterator end ( ) { return C.endO;} Eckes Operator [] (int l) { return C[ι);} sιze_t AnzahlKanten ( ) ; int ιnsert( const Eckentyps e); void ιnsert( const Eckentyps el, const Eckentyps e2, const Kantentyps Wert); void verbmdeEckendnt el, int e2, // über Eckennummern const Kantentyps Wert); void setgerichtet (bool wert); // neue Methode für gerichtete/ungerichtete Graphen,
// die aber nicht ver- wendet wird. void check (ostreamS = cout); void ZyklusUndZusammenhang (ostreamS = cout); private: bool gerichtet;
Graphtyp C; // Container ostream* pOut;
};
//Funktion, die überprüft, ob es sich um einen gerichteten oder ungerichteten //Graphen handelt, und die Anzahl der Ecken und Kanten ausgibt. template<class Eckentyp, class Kantentyp> void Graph<Eckentyp,Kantentyp>: : check (ostream os) { os « "Der Graph ist "; //if (' istGerichtet () ) // os « "un"; os « "gerichtet und hat " « sιze() « " Knoten und "
« AnzahlKanten () « " KantenNn"; //ZyklusUndZusammenhang ( os ) ;
//Methode, die einen Wert setzt, ob der Graph gerichtet oder ungerichtet ist. template<class Eckentyp, class Kantentyp> void Graph<Eckentyp,Kantentyp>: : setgerichtet (bool wert) gerichtet = wert;
//Funktion berechnet die Anzahl der Kanten in Graph template<class Eckentyp, class Kantentyp> sιze_t Graph<Eckentyp,Kantentyp>: :AnzahlKanten ( ) { sιze_t Kanten = 0; iterator temp « begm(); whιle(temp '= end ( ) )
Kanten += (*temp++) . second.size ( ) ; Hi t ('gerichtet) // Kanten /= 2;
return Kanten; } //Einfügen einer Ecke in den Graphen, falls diese noch nicht vorhanden ist. template<class Eckentyp, class Kantentyp> int Graph<Eckentyp,Kantentyp>: :ιnsert( const Eckentyps e) f fordnt i = 0; l < sιze(); ++ι) if (e == C[ι) .first) return i;
// falls nicht gefunden, einfuegen: C.push_back(Ecke le, Nachfolger! ) ) ) ; return sιze()-l;
//Einfügen einer Kante in den Graphen, indem zuerst die Ecken eingefügt werden. template<class Eckentyp, class Kantentyp> void Graph<Eckentyp,Kantentyp>: : insert (const Eckentyps el, const Eckentyp e2, const Kantentyps Wert)
{ int posl = insert (el); int pos2 = insert ( e2 ); verbmdeEckenlposl, pos2, Wert);
//Verbinden der beiden neu eingefügten Ecken durch eine Kante. template<class Eckentyp, class Kantentyp> void Graph<Eckentyp,Kantentyp>: : verbindeEcken ( int posl, int pos2, const Kantentyps Wert) (
(Clposl) .second) [pos2] « Wert;
//if ( Igenchtet) // automatisch auch Gegenrichtung eintragen
// (C(pos2] .second) [posl] = Wert;
/* ZyklusUndZusammenhang!) arbeitet mit der Tiefensuche. Im Gegensatz zu CLR S. 47S wurde nicht mit der Rekursion gearbeitet, weil bei dieser Stack-Overflow bei großen Graphen (zB. MILES.DAT bei mehr als 40 Knoten) auftrat.
Die Nachbildung der Rekursion durch eigenen Stack ermöglicht die Verarbeitung der gesamten Datei
MILES.DAT (128 Knoten). Die Stacktiefe entspricht der Kantenanzahl
+ 1 bei ungerichteten Graphen. */ template-class Eckentyp, class Kantentyp> void Graph<Eckentyp, Kantentyp>: : ZyklusUndZusammenhang (ostreamS os) int Zyklen - 0; int Komponentenanzahl = 0; stack<ιnt, ector<ιnt> > EckenStack; // zu besuchende Ecken
// allen Ecken den Zustand nichtBesucht zuordnen enum EckStatus (nichtBesucht, besucht, bearbeitet); vector<EckStatus> Eckenzustand (size () , nichtBesucht);
// alle Ecken besuchen fordnt l = 0; l < sιze(); ++i) if (Eckenzustand d] == nichtBesucht)
<
Komponentenanzahl++;
// auf dem Stack zwecks Bearbeitung ablegen
EckenStack.pushd ) ;
// Stack abarbeiten while ( ' EckenStack. empty ( ) int dieEcke = EckenStack. top () ; EckenStack. pop( ) ; if (Eckenzustand [dieEcke] »= besucht)
Eckenzustand[dιeEcke] = bearbeitet; eise
if (Eckenzustand[dιeEcke] == nichtBesucht)
(
Eckenzustand [dieEcke] = besucht; // neue Ecke, für bearbeitet-Kennung vormerken EckenStack.push (dieEcke ) ;
// Nachfolger vormerken:
Graph<Eckentyp, Kantentyp>: :Nachfolger: -.iterator Start = Operator [) (dieEcke) .second.beginf ) , ende = Operator [] (dieEcke) .second. end () ; while (start != ende) ( int Nachf «= (*start) . first; if (Eckenzustand [Nachf] == besucht) (
++Zyklen; // hier war schon jemand! (*pOut) « "mindestens Ecke " « Operator [] (Nachf ). first « " ist in einem ZyklusNn"; } if (Eckenzustand [Nachf] == nichtBesucht)
EckenStack.pus (Nachf) ; ++start; } }
} // Stack Empty? } // for ( ) ... i (Eckenzustand... if (gerichtet) ( if (Komponentenanzahl == 1) os « "Der Graph ist stark zusammenhangend. \n"; eise os « "Der Graph ist nicht oder schwach " "zusammenhangend . \n" ; eise os « "Der Graph hat "
« Komponentenanzahl
« " Komponente (n) . " « endl; os « "Der Graph hat "; if (Zyklen == 0) os « "keine "; os « "Zyklen." « endl;
//Ausgabe des Graphen. template<class Eckentyp, class Kantentyp> ostream Operator« (ostreamS os,
Graph<Eckentyp,Kantentyp>s G)
< ofstream Ziel ("FaultTree.uwg" ) ; ostream_ιterator<uwgknotenC> POSIT(Zιel) ; ostream_ιterator<uwgknotenC> POSIT2 (Ziel ) ;
// Anzeige der Ecken mit Nachfolgern
Ziel « "%%UWG" « endl « "\"V0. l\"~\"Fehlerbaum\"-\"A.Steιnhorst\"" « endl « "%%BEGIN" « endl; fordnt l = 0; l < G.sizeO; ++ι) (
POΞIT++ = G[ι ]. first; /*os « G[ι]. first « " <"; Graph<Eckentyp,Kantentyp>: :Nachfolger: :ιterator startN = G[ι] .second.begin () , endeN = G[ι ] .second. end ( ) ; while (startN != endeN) ( os « G[ (*startN) .first) .first « ' ' // Ecke « (»startN) .second « ' '; // Kantenwert *POSIT2++ = G[ (*startN) .first] .first;
//*KANTEIT++ = (*startN) .second; ++startN; } os « ">\n";*/ «POSIT++;
) fordnt u = 0; u < G.sizef); ++u) (
Graph<Eckentyp,Kantentyp>: :Nachfolger: :ιterator
startN = G[u] .second.begin! ) , endeN - G[u] .second. end( ) ; while (startN != endeN) (
Ziel « "%%EDGE:" « G[u] . fitst.getGatterldent ( ) « ","
« G[ (*startN) .first] .first.getGatterldent ( ) « "/0;" « endl;
++startN;
Ziel « "%%PROBSLIST" « endl « "%%END" « endl; return os;
«endif
(dfdef _KFGDefHeader
G
#else
O
«define _KFGDefHeader
D
„include <strιng> D
#include <ιostream> D using namespace std;
D
D typedef char StringT [256]; 0 D class KFGDefC .( D private: O D
StringT Def; D int ScopeLevelD; public:
KFGDefC ( ) strcpy (Def, "— unknown —"); ScopeLevelD = 0; } ;
KFGDefC(char _Def [], int _ScopeLevelD) strcpy (Def, _Def); ScopeLevelD =
_ScopeLevelD; ) ; void setDeffchar _Def []) ( strcpy (Def, _Def); } char* getDefO ( return Def; } int getScopeLevelD( ) ( return ScopeLevelD; } bool Operator == (const KFGDefCS other) const
( return ( (strcmp(Def, other. Def) ~ 0) s (Scope-
LevelD == other .ScopeLevelD) ) ; }; bool Operator '= (const KFGDefCS other) const
( return ' (*thιs == other) ; }; bool Operator < (const KFGDefCS other) const
{ return (strcmp(Def, other. Def ) < 0) ; }; bool Operator > (const KFGDefCS other) const
( return (strcmpfDef, other.Def) > 0); ); friend ostreamS Operator « ( ostreamS os, const KFGDefCS Node); };
„endi iπ/π/πiπ π iπ/π π ππ/i////////// //////////////////////////////// //////////////// o
II Klasse für Hilfsliste, um daraus einen KFG zu erstellen.
// Diese Klasse erfüllt die nice-Anforderungen für die STL;
// d.h. für eine Klasse T gilt // 0. Sie unterstützt den Copy-Konstruktor T (const T ),
// 1. den Zuweisungsoperator TS operator= (const TS),
// 2. den Vergleichsoperator bool operator== (const T, Sconst TS) und
// 3. den Ungleichoperator !■=
// in einer Weise so daß gilt: // (a) ( TRUE } T a(b) (a -= b}
// (b) ( TRUE } a = b (a — b}
// (c) { a == a}
// (d) { a == b <==> b == a }
// (e) ( (a == b) AND ( b == c ) ==> (a == c) } // (f) ( a != b <==> NOT ( a— b) };
//
// Außerdem sind alle Funktionen, insbesondere getName equality preservmg, d.h.
// (g) { a == b == > a. getName () == b. getName () }
// // (C) 1997 Siemens AG
//
// iimiii mmiπimiim m mπiimmimmimπimiimiπ
II 1997-08-25 Andreas Steinhorst mmπiiiiimmmmimπimiiiimi ππ /ii/imiiiiiiiiiii »lfdef _KFGLιneNodeHeader
«eise «def ine _KFGLmeNodeHeader
(f include <string> ftinclude <ιostream> using namespace std; typedef char StringL [ 1000] ; class KFGLmeNodeC private:
StringL Name; int LineNumber; publlc:
KFGLmeNodeC ( ) ( strcpy (Name, "— unknown —
LineNumber = 0;
KFGLmeNodeC (char _Name []) ( strcpy (Name, _Name); LineNumber
0; } ;
KFGLmeNodeC (char _Name [], int _LmeNumber)
( strcpy (Name, _Name); LineNumber =
LineNumber; void setName(char _Name []) ( strcpy (Name, _Name); }; char* getName() ( return Name; }; int getLineNumber ( ) ( return LineNumber; }; bool Operator == (const KFGLineNodeCS other) const
( return (strcmp (Name, other.Name) == 0)
S (LineNumber == other.LineNumber)) ; }; bool Operator ' = (const KFGL eNodeCS other) const ( return ' (*thιs
== other) ; } ; bool Operator < (const KFGLmeNodeCS other) const
( return (strcmp(Name, other.Name) < 0); }; bool Operator > (const KFGLmeNodeCS other) const
( return (strcmp(Name, other.Name) > 0); }; friend ostreamS Operator « ( ostreamS os, const KFGLmeNodeCS Node);
};
#endif π/ππiππiπ/ππ/ππiππ/ππ/ππiππiππ/ππ/ππiπ/ππ/πi/ππi/π/ππ
II Klasse für die Liste, die den KFG darstellt.
// Diese Klasse erfüllt die nice-Anforderungen für die STL; // d.h. für eine Klasse T gilt
// 0. Sie unterstützt den Copy-Konstruktor T (const TS),
// 1. den Zuweisungsoperator TS operator= (const TS),
// 2. den Vergleichsoperator bool operator== (const T, sconst T ) und
// 3. den Ungleichoperator '= // in einer Weise so daß gilt:
// (a) ( TRUE } T a(b) (a == b}
// (b) ( TRUE } a = b (a == b}
// (c) ( a == a}
// (.d). (. a == b <==> b — a } // ((ee)) (( ((aa ==== bb)) AANNDD (( bb ==== cc )) ====>> (a == c)
// (f) { a '= b <==> NOT ( a-== b) };
//
// Außerdem sind alle Funktionen, insbesondere getStatement equality preservmg, d.
// (g) ( a == b == > a. getStatement ( ) == b. getStatement ( ) } //
// im mimimii mim /nimm mm ιι ιι 11 ιι im ι im in ιι ι / in ι ιι ιι ι / ιι /
II 1997-09-01 Andreas Steinhorst ππiπmimπiπimπimiπmiiii ιι min/im m im ιι in mmiiimπi ffifdef _KFGLιstHeader #else
(fdefine _KFGLιstHeader dinclude <strιng> tdnclude <ιostream> linclude <stdιo.h> ftinclude <list>
(linclude <fstream> ftinclude <ιterator> (fmclude "KFGListNode.h"
„include "KFGTokenList.h"
#ιnclude "KFGProgList.h" using namespace std; class KFGListC : public lιst<KFGLιstNodeC> ( int Anzahl_Defs, Anzahl_Uses, Anzahl_P_Uses, Anzahl Deklarationen; int Schleifenentscheidungen, Entscheidungen, Zaehlschleifenentscheidungen; int Anweisungen; publlc : KFGListC () (}; void TokenLιst2KFGLιst (KFGTokenListC S Ll ) ; void KnotenNummern ( ) ; void Knotenldentifizierer (KFGListC: : iterator KFG); void ListeAusgeben! ) ;
void addLmelnToList ( ) ; void addLιneToKFG(KFGProgLιstC S LP); int zaehleDeklaratιonen(KFGTokenLιstC S TL); void basisgroessenlnDatei ( ) ;
}; class KFGDefListC : public list<KFGDefC> (}; class KFGUseListC : public lιst<KFGUseC> (}; class KFGP_UseLιstC : public lιst<KFGUseC> (};
#endιf ffinclude <stπng> D
Oinclude <ιostream> «mclude <lιst> ffinclude "KFGNode.h" us g namespace std; typedef lιst<KFGNodeC> KFGListeT; extern void KFGListeAusgeben (KFGListeT ) ; /////////// ////ι iππ in ππ π/π n/n ι n/n // ιι / // in / ιι π // π // iπ/ππ /////////////
0
// Klasse für die Knoten im Kontrollflußgraph.
// Diese Klasse erfüllt die nice-Anforderungen für die STL;
// d.h. für eine Klasse T gilt 1/ 0. Sie unterstützt den Copy-Konstruktor T (const TS),
// 1. den Zuweisungsoperator TS operator= (const TS),
// 2. den Vergleichsoperator bool operator== (const T, Sconst Ts ) und
// 3. den Ungleichoperator !=
// in einer Weise so daß gilt: // (a) ( TRUE } T a(b) (a == b}
// (b) ( TRUE } a = b (a == b}
// (c) ( a == a}
// (d) ( a == b <==> b == a }
// (e) ( (a == b) AND ( b == c ) ==> (a == c) } // (f) ( a != b <==> NOT ( a== b) };
//
// Außerdem sind alle Funktionen, insbesondere getStatement equality preservmg, d.h.
// (g) ( a == b == > a. getStatement ( ) == b. getStatement ( ) }
// // II llll/IIIIHIIII Hl
II 1997-08-25 Andreas Steinhorst iπ/π/π/π/π/iπ iππ IΠΠI/ΠΠ ι in / π ι // π/π/π///////////// ////// ////////////// difdef _KFGNodeLιstHeader „eise (fdefme _KFGNodeLιstHeader finclude <strιng> dinclude <ιostream>
(finclude <list> (finclude "KFGUse.h" ftmclude "KFGDef.h" using namespace std; typedef char StringT [256]; typedef char CodeLineT [256] ; typedef enum (NO, LC,BL, EL, IFC,BTh,ETh, BEI, EE1, OP, DOWL, DOWLC, SWITCH, CASE, ENDCASE, BDEFA, ENDDEFA, RETURN, BRE AK) KFGNodeTypeT; typedef enum (LOOP, THEN, ELSE, NONE} KnotenldentT; class KFGListNodeC (
protected: //private: static int DummyNodeNr; int NodeNr; int Level; int KnotenNr; int LineNr; StringT Statement; CodeLineT CodeLine; KFGNodeTypeT KFGNodeType; KnotenldentT Knotenldent ; public: lιst<KFGUseC> Uses; lιst<KFGDefC> Defs; lιst<KFGUseC> P_Uses;
KFGListNodeCO ( strcpy (Statement, "— unknown —" ) ;
Level = 0; KFGNodeType =
NO;
NodeNr = Dum- myNodeNr++;
KnotenNr = 0; Knotenldent =
NONE;
LineNr ■= 0; strcpy (CodeLi- ne, "—unknown—"); };
KFGLιstNodeC(char _Statement [ ] , KFGNodeTypeT _KFGNodeType ) strcpy (State- ment, _Statement);
Level = 0;
KFGNodeType =
_KFGNodeType;
NodeNr = Dum- myNodeNr++;
KnotenNr = 0; Knotenldent =
NONE;
LineNr = 0; strcpy (CodeLi- ne, "—unknown—"); };
KFGLιstNodeC(char _Statement [], KFGNodeTypeT _KFGNodeType, int _Level )
( strcpy (State- ment, _Statement ) ; Level = _Level; KFGNodeType =
_KFGNodeType;
NodeNr = Dum- myNodeNr++;
KnotenNr = 0; Knotenldent - NONE;
LineNr = 0; strcpy (CodeLi- ne, "—unknown—"); };
KFGListNodeCIchar _Statement KFGNodeTypeT _KFGNodeType, int _Level, int _LmeNr)
( strcpy (State- ment, _Statement); Level = _Level; KFGNodeType =
_KFGNodeType;
NodeNr = Dum- myNodeNr++;
KnotenNr = 0; Knotenldent =
NONE;
LineNr = LineNr;
strcpy ( CodeLi- ne, "—unknown—"); }; vo d setStatement (char _Statement []) strcpy (State- ment, _Statement); }; void setCodeL e (char _CodeLιne []) strcpy (CodeLi- ne, _CodeLιne); }; void setKFGKnotenNummer (int _KnotenNr)
( KnotenNr _KnotenNr; ) ; void setKnotenldent (KnotenldentT _KnotenIdent )
Knotenldent _KnotenIdent; }; int getKnotenNummer ( ) ( return KnotenNr; }; char* getStatement!) ( return Statement; }; char* getCodeL e ( ) ( return CodeLme; }; int getLevel ( ) ( return Level; }; int getNodeNrl) ( return NodeNr; }; int getLιneNr() ( return LineNr; };
KnotenldentT getKnotenlden ( ) ( return Knotenldent; };
KFGNodeTypeT getKFGNodeType ( ) ( return KFGNodeType; }; bool Operator == (const KFGListNodeCS other) const
( return ( (strcm tStatement, other .Statement ) == 0)
S (Level — other. Level ) S (KFGNodeType == other. KFGNodeType) s (NodeNr == other. NodeNr) ); }; bool Operator '= (const KFGListNodeCS other) const
( return ! (*thιs == other) ; } ; bool Operator < (const KFGListNodeCS other) const (strcm l Statement, other. Statement) < 0); }; bool Operator > (const KFGListNodeCS other) const return (strcmpIStatement, other. Statement ) > 0); }; friend ostreamS Operator « ( ostreamS os, const KFGListNodeCS Node);
jfendif
//ftinclude <strιng> //fl clude <ιostream> //«include "KFGList.h"
//us g namespace std;
//class KFGListOpC : public KFGListeC (
//public:
// void KFGListOut (KFGListeT S L)
// (
// KFGListeT: : iterator I = L.beginO;
// while (I '•= L.end! ) )
// cout « *I++ « ' ' ;
// cout « " sιze ( ) = " « L. size O « endl;
// } //);
IIII II IIII 111 Uli III I I Hill II lllll 1111 III I II
D
// Klasse für Hilfsliste, um daraus einen KFG zu erstellen. Q
// Diese Klasse erfüllt die nice-Anforderungen für die STL;
// d.h. für eine Klasse T gilt
// 0. Sie unterstützt den Copy-Konstruktor T (const TS),
// 1. den Zuweisungsoperator Ts operator= (const Ts), // 2. den Vergleichsoperator bool operator== (const T, Sconst T ) und
// 3. den Ungleichoperator !=
// in einer Weise so daß gilt:
// (a) { TRUE } T a(b) (a — b)
// (b) ( TRUE } a = b (a == b} // (c) ( a — a}
// (d) ( a == b <==> b == a }
// (e) ( (a == b) AND ( b — c ) —> (a == c) }
// (f) { a '= b <==> NOT ( a== b) };
// // Außerdem sind alle Funktionen, insbesondere getName equality preservmg, d.h.
// (g) ( a = b == > a.getName!) == b. getName!) }
//
// (C) 1997 Siemens AG
// // II II llll III III II 1997-08-25 Andreas Steinhorst
HIHI 111 ιι m um um ιι ι in ι IIII 11 m 11 ιι ι ιι ι m IIII um m ffifdef _KFGNodeHeader «eise ffdef e _KFGNodeHeader ff clude <stπng> ffinclude <ιostream> using namespace std; typedef char StringT [256]; class KFGNodeC ( private:
StringT Name; int ScopeLevel; public:
KFGNodeCO ( strcpy (Name, "— unknown —"); ScopeLevel = 0;
/* cout « "NodeC erzeugt" « endl ; */};
KFGNodeCIchar _Name [] ) ( strcpy (Name, _Name);
ScopeLevel = 0; ); KFGNodeCIchar _Name [], int _ScopeLevel)
( strcpy (Name,
_Name ) ;
ScopeLevel = ScopeLevel; } ; void setName(char _Name []) ( strcpy (Name, _Name); }; char* getName!) { return Name; }; int getScopeLevel ( ) ( return ScopeLevel; }; bool Operator == (const KFGNodeCS other) const
{ return ( (strcmplName, other. Name) == 0) S (ScopeLevel
== other. ScopeLevel) ) ; }; bool Operator '= (const KFGNodeCS other) const
return ! (*thιs
== other) bool Operator < (const KFGNodeCS other) const { return (strcm lName, other.Name) < 0); }; bool Operator > (const KFGNodeCS other) const return (strcmplName, other.Name) > 0); }; friend ostreamS Operator « ( ostreamS os, const KFGNodeCS Node);
}; ftendif ff ifdef _KFGNodelHeader D ffelse
D ππiππ/ππ/ππiππ/ππ/ππi/π/ππ/π/ππii/ππ/π/π/π π in// ////////////
I I Klasse für Hilfsliste, um daraus einen KFG zu erstellen.
// Diese Klasse erfüllt die nice-Anforderungen für die STL; // d.h. für eine Klasse T gilt
// 0. Sie unterstützt den Copy-Konstruktor T (const Ts),
// 1. den Zuweisungsoperator TS operator= (const TS),
// 2. den Vergleichsoperator bool operator== (const T, const TS) und
// 3. den Ungleichoperator '= // in einer Weise so daß gilt:
// (a) < TRUE } T a(b) (a == b}
// (b) ( TRUE } a = b (a == b}
// (c) ( a == a}
// (d) ( a == b <==> b == a ) // (e) ( (a == b) AND ( b == c ) ==> (a == c) }
// (f) ( a != b <==> NOT ( a== b) };
//
// Außerdem sind alle Funktionen, insbesondere getName equality preservmg, d.h.
// (g) ( a == b == > a. getName!) == b. getName!) } //
// (C) 1997 Siemens AG
//
// 1111111111111111111111111111 lll/1/llll / 1 Hill I um 111/ /
II 1997-08-25 Andreas Steinhorst ππππmmiπmiπmm mim// im/m IIII ιι m in ιι ff ifdef _KFGNodelHeader ffelse ftdefine _KFGNodelHeader ffinclude <stnng> ffinclude <ιostream> us g namespace std; typedef char StringT [256]; class KFGLlstNodeC ( private: StringT Name; int ScopeLevel; list <KFGUseC> Uses; list <KFGDefC> Defs; public:
KFGLlstNodeC() ( strcpy (Name, "— unknown —"); ScopeLevel = 0;
/* cout « "NodeC erzeugt" « endl ; */};
KFGLlstNodeC (char _Name [] ) ( strcpy (Name, _Name);
ScopeLevel = 0; }; KFGLlstNodeC (char _Name [], int _ScopeLevel)
( strcpy (Name, Name ) ;
ScopeLevel ■
ScopeLevel; } ; void setName(char _Name []) strcpy (Name, _Name); }; char* getName!) ( return Name; ) ; int getScopeLevel ( ) ( return ScopeLevel; }; bool Operator == (const KFGListNodeCS other) const
( return ((strcmplName, other. ame) == 0)
S (ScopeLevel =« other. ScopeLevel) ); }; bool Operator != (const KFGListNodeCS other) const
( return ' (*thιs == other) ; } ; bool Operator < (const KFGListNodeCS other) const return (strcmplName, other.Name) < 0); }; bool Operator > (const KFGListNodeCS other) const return (strcmplName, other.Name) > 0); ); friend ostreamS Operator « ( ostreamS os, const KFGListNodeCS Node);
ffendlf flifdef KFGNodelHeader 0
»eise
D
III lllll III 11 lllll III II I II III 11 lllll 11 II I III 111 III I II I II IIII II II I II
0 // Klasse für Hilfsliste, um daraus einen KFG zu erstellen.
D
// Diese Klasse erfüllt die nice-Anforderungen für die STL;
// d.h. für eme Klasse T gilt
// 0. Sie unterstützt den Copy-Konstruktor T (const TS), II I . den Zuweisungsoperator Ts operator= (const TS),
// 2. den Vergleichsoperator bool operator== (const T, Sconst TS) und
// 3. den Ungleichoperator !=
// in einer Weise so daß gilt:
// (a) ( TRUE ) T a(b) (a — b) // (b) ( TRUE } a = b (a == b}
// (c) { a — a)
// (d) ( a == b <==> b == a }
// (e) ( (a =- b) AND ( b == c ) ==> (a == c) }
// (f) ( a '= b <==> NOT ( a— b) }; //
// Außerdem sind alle Funktionen, insbesondere getName equality preservmg, d.h.
// (g) ( a ~ b — > a. getName () == b. getName!) }
//
// (C) 1997 Siemens AG //
// ππiππ/ππiππiππiππiiπ/π/iiiiπ IIII π/π iiiiππ ////// ////////
II 1997-08-25 Andreas Steinhorst mimiiiπmiiπiiππmimiiiii πimmm ππ m ////////////im im ff ifdef _KFGNodelHeader »eise ffdefine KFGNodelHeader ffinclude <strmg> ffinclude <ιostream> using namespace std; typedef char StringT [256]; class KFGLlstNodeC { private:
StringT Name;
int ScopeLevel; list <KFGUseC> Uses; list <KFGDefC> Defs; public:
KFGLlstNodeC! ) ( strcpy (Name, known ScopeLevel = 0;
/* cout « "NodeC erzeugt" « endl ; */};
KFGLlstNodeC (char _Name [) ) ( strcpy (Name, _Name);
ScopeLevel = 0; ) ; KFGLlstNodeC (char _Name [], int _ScopeLevel)
( strcpy (Name, _Name ) ;
ScopeLevel = ScopeLevel; ); - void setNamelchar _Name []) ( strcpy (Name, _Name); }; char* getName!) ( return Name; ) ,- int getScopeLevel ( ) ( return ScopeLevel; ); bool Operator == (const KFGListNodeCS other) const
( return ((strcmplName, other.Name) == 0) S (ScopeLevel
== other. ScopeLevel) ) ; }; bool Operator != (const KFGListNodeCS other) const
( return ! (*thιs == other); ); bool Operator < (const KFGListNodeCS other) const
( return (strcmplName, other.Name) < 0); }; bool Operator > (const KFGListNodeCS other) const
{ return (strcmp(Name, other.Name) > 0); ); friend ostreamS Operator « ( ostreamS os, const KFGListNodeCS Node);
); ffendif
//Klasse für eine Liste aus STL. KFGListeC erbt dabei alle Eigenschaften //von der mit STL erstellten Liste lιst<KFGNodeC>. «lfdef _KFGProgLιstHeader (leise «define _KFGProgListHeader ffinclude <strιng> ffinclude <ιostream> ffinclude <stdιo.h> flinclude <lιst> ffinclude <fstream> ffinclude <ιterator> ffinclude "KFGLineNode.h" using namespace std; class KFGProgListC : public lιst<KFGLιneNodeC> ( public:
KFGProgListC!) (); //void KFGListeAusgebenl ) ;
//void KFGTokenListToKFGList ();
) ; ffendif
//Klasse für eine Liste aus STL. KFGListeC erbt dabei alle Eigenschaften D
//von der mit STL erstellten Liste lιst<KFGNodeC>. D difdef _KFGTokenListHeader D
»eise D ffdefine KFGTokenListHeader ü
D
D ffinclude <stnng>
D ffinclude <ιostream>
O ffinclude <stdιo.h> ffinclude <lιst> ffinclude <fstream> ffinclude <ιterator>
#ιnclude "KFGTokenNode.h" usmg namespace std; class KFGTokenListC : public lιst<KFGTokenNodeC> ( public:
KFGTokenListC!) (}; void KFGListeAusgebenl ) ;
//void KFGTokenListToKFGList ();
}; ffendif
III 11 III IIII II 111 II IIII III II II III 11111 II II 11 III 1111111111 II III III I III I lllll IIII
D // Klasse für Hilfsliste, um daraus einen KFG zu erstellen.
D
// Diese Klasse erfüllt die nice-Anforderungen für die STL;
D
// d.h. für eine Klasse T gilt // 0. Sie unterstützt den Copy-Konstruktor T (const T ) ,
// 1. den Zuweisungsoperator TS operator= (const Ts),
// 2. den Vergleichsoperator bool operator== (const T, Sconst TS) und
// 3. den Ungleichoperator '=
// in einer Weise so daß gilt: // (a) ( TRUE } T a(b) (a -= b)
// (b) < TRUE } a = b (a == b)
// (c) ( a == a)
// (d) { a == b <==> b == a }
// (e) ( (a == b) AND ( b == c ) ==> (a == c) ) // (f) ( a '= b <==> NOT ( a== b) };
//
// Außerdem sind alle Funktionen, insbesondere getName equality preservmg, d.h.
// (g) ( a == b == > a.getNameO == b. getName!) )
// // (C) 1997 Siemens AG
//
// lllll I I II II II II I I II II II II II I I I I I III I I I I I I I I I I I I I I II I I I I I I III I II II I I I III I /
II 1997-08-25 Andreas Stemhorst
/ / ιι ιι IIIII im m mπiπiimπm mm/1 ii / 11 m ι ιι 11 mπimiiim ffifdef _KFGTokenNodeHeader ffelse (fdefme KFGTokenNodeHeader
ffinclude <strιng> ffinclude <ιostream> usmg namespace std; typedef char StringT [256); typedef enum (N,PL,IF,BT,ET,BE,EE,FOR,BF,EF,WHILE,BW,EW,SW,CA,ECA,BRK,RET,DEFA,EDEFA, DO, BDOW, DOWS,NL, DEF , BFUNC, EFUNC, TD, OUT, FOR_D, PF) TokenNodeTypeT; class KFGTokenNodeC ( private:
StringT Name;
TokenNodeTypeT TokenNodeType; int ScopeLevel; int LineNumber; public:
KFGTokenNodeC ( ) { strcpy (Name, "— un- known —" )
ScopeLevel = 0; TokenNodeType =
N;
LineNumber = 0; );
KFGTokenNodeC (char _Name [], TokenNodeTypeT _TokenNodeType )
( strcpy (Name,
_Name ) ;
ScopeLevel - 0; TokenNodeType
_TokenNodeType;
LineNumber = 0;);
KFGTokenNodeC (char _Name [], int _ScopeLevel, TokenNodeTypeT TokenNodeType)
( strcpy (Name,
_Name) ; ScopeLevel = _ScopeLevel;
TokenNodeType = TokenNodeType; LineNumber = 0;
KFGTokenNodeC (char _Name [], t _ScopeLevel, TokenNodeTypeT _TokenNodeType, int LineNumber)
( strcpy (Name,
_Name ) ; ScopeLevel = _ScopeLevel;
TokenNodeType _TokenNodeType; LineNumber = LineNumber; ); void setNamelchar _Name []) ( strcpy (Name, _Name); ); char* getName ( ) ( return Name; }; int getScopeLevel ( ) ( return ScopeLevel; ); mt getLineNumber ( ) ( return LineNumber; ); TokenNodeTypeT getTokenNodeType ( ) ( return TokenNodeType; }; bool Operator == (const KFGTokenNodeCS other) const return ((strcmplName, other. Name) == 0)
S (ScopeLevel == other. ScopeLevel )
S (TokenNode- Type == other. TokenNodeType) ) ; }; bool Operator '= (const KFGTokenNodeCS other) const
( return ' (*thιs -= other); ); bool Operator < (const KFGTokenNodeCS other) const ( return
(strcmplName, other.Name) < 0); }; bool Operator > (const KFGTokenNodeCS other) const
( return (strcmplName, other.Name) > 0); ); friend ostreamS Operator « ( ostreamS os, const KFGTokenNodeCS Node); ); ffendif ff ifdef _KFGUseHeader D »eise
D
»define _KFGUseHeader D D
»include <stπng>
D
»include <ιostream>
O o usmg namespace std; D
G typedef char StringT [256]; D
D class KFGUseC ( α private:
D D
StringT Use;
D int ScopeLevelU; D
D public: D
KFGUseC () ( strcpy (Use, "— unknown --" ) ;
ScopeLevelU = 0; );
KFGUseC(char _Use [], int _ScopeLevelU) ( strcpy (Use, _Use);
ScopeLevelU = _ScopeLevelU; } ; void setUse(char _Use []) ( strcpy (Use, _Use); ) char* getUse I ) ( return Use; ) int getScopeLevelU ( ) ( return ScopeLevelU; } bool Operator == (const KFGUseCS other) const
( return ( (strcmp (Use, other. Use) — 0) s (ScopeLevelU == other. ScopeLevelU) ) ; ); bool Operator '= (const KFGUseCS other) const
( return ' (*thιs == other) ; };
bool Operator < (const KFGUseCS other) const
( return (strcmplUse, other.Use) < 0); ); bool Operator > (const KFGUseCS other) const f return (strcmplUse, other.Use) > 0); ); friend ostreamS Operator « I ostreamS os, const KFGUseCS Node);
};
»endif
»ifndef _uwggraphC D
»def e uwggraphC D
0
»mclude <Graph. h> D »include "uwgknoten . h" D
»include "uwgkante . h" 0 »include "AS Slice . h" using namespace std; class uwggraphC : public Graph < uwgknotenC, uwgkanteC > ( public:
Short mt eingefaltet; uwggraphC! ) { } ; SliceC: : iterator findOutputNode (SliceC s Sl ) ;
SliceC: : iterator definelterator (SliceC S Sl, mt SliceNr); void addFirstNodesToFTISliceC s Sl, int KnotenNr, int Posl);
SliceC: : iterator returnCondNode (SliceC S Sl, mt SliceNr); mt checkUWGNode(ιnt SliceNr); void SliceAusgeben! SliceC S Sl ) t void startBuildFT (SliceC S Sl ) ; void buildInLoopTree (SliceC S Sl, int Posl, SliceC: : iterator SLPUSE, Sli- ceC: : iterator SLNODE); void buιldIn_Dl_Part (SliceC S Sl, int posOR_Dl, SliceC: : iterator SLPUSE, SliceC: : iterator SLNODE, int D2_RefNr); SliceC: :ιterator f dOutmostPUse (SliceC S Sl, SliceC: : iterator SLPUSE); int checkPUsesl (SliceC S Sl, SliceC: : iterator SLPUSE, SliceC: : iterator SLPUSEREF) ; mt checkPUses2 (SliceC S Sl, SliceC: :ιterator SLPUSE, SliceC: :ιterator
SLPUSEREF) ;
SliceC: : iterator fιnd_Dl_Node (SliceC S Sl, SliceC: : iterator SLPUSE, SliceC: :ιterator SLNODE); void addAllDlNodes (SliceC S Sl, SliceC: : iterator SLNODE, int posGatter, int D2_RefNr);
SliceC: :ιterator findLastPUse (SliceC S Sl, int SliceNr);
SliceC: : iterator fmdLastPUse2 (SliceC S Sl, int SliceNr, mt RefNr);
void checkLoopOrCondl SliceC S Sl, SliceC: :ιterator SLl, SliceC: :ιterator SLORIG, int Posil ) ; void buildIn_D2_Part (SliceC S Sl, int posOR_D2, SliceC: : iterator SLl, SliceC: : iterator SLPUSE, int KnotenNrD2); int fιndD2Node(SliceC S Sl, SliceC: : iterator PUSE); t buildlnlfTree (SliceC s Sl, SliceC: :ιterator SLIF, SliceC: : iterator SLORIG, int posl ) ;
SliceC: : iterator lookForNextPUse (SliceC S Sl, SliceC: :ιterator SNODE, SliceC: : iterator SLPUSE); void buιld_IFKF_Part( SliceC S Sl, t posKFOR, SliceC: : iterator SLPUSE); void build_Al_Part (SliceC S Sl, int posIFDFOR, SliceC: :iterator SLIF, SliceC: : iterator SLORIG); void buιldD2_IFKF_Part (SliceC S Sl, int posKFOR, SliceC: : iterator SLPUSE); void buιldD2_Al_Part (SliceC S Sl, int posIFDFOR, SliceC: : iterator SLIF, SliceC: :ιterator SLNODE) ; int buιldD2InIfTree (SliceC S Sl, SliceC: :ιterator SLIF, SliceC: : iterator SLORIG, int posl); void buιldLoopKF_Part (SliceC S Sl, mt posAND_KF, int posLOOP_KF, int posD2, SliceC: : iterator SLOOP); mt buιldIn_LoopKF_ANDPart (SliceC S Sl, int posAND_KF, SliceC: :ιterator
SLPUSE ) ; void buildIn_LoopKF_ORPart (SliceC S Sl, int posAND_KF, SliceC: : iterator SLl, int KnotenNrD2);
};
»endi
»lfndef _uwgkanteC »def e _uwgkanteC
»include <ιostream using namespace std; class uwgkanteC ( public:
Short int eingefaltet; int Number; uwgkanteC () {}; uwgkanteC (mt _Number) { Number = _Number; bool Operator == (const uwgkanteCS other) const
( return (Number — other. Number ) ; }; bool Operator '= (const uwgkanteCS other) const
( return ' (*thιs == other); ); bool Operator < (const uwgkanteCS other) const
( return (Number == other. umber ) ; }; bool Operator > (const uwgkanteCS other) const
( return (Number == other.Number ) ; ); friend ostreamS Operator « ( ostreamS os, const uwgkanteCS Node);
»endif
»lfndef _uwgknotenC
D
»define _uwgknotenC
D
D ffinclude <iostream> const int maxKnotentextLength=128; const mt maxBemerkLength=1000; const mt maxWahrVarLength=16; typedef struct ww (
Short mt Wert; struct ww *next; } TMCSWert; typedef struct el ( struct ftgatter* unabElement; struct ww *next; struct el *nextel; ) TMinSet; typedef enum (AND, OR, CAUSE, EFFECT, NOT] NodeldentT; usmg namespace std; class uwgknotenC ( public: static int DummyNr; t Gatterldent; t outof; int CauseNr; char gattertext [maxKnotentextLength] ; char gatterbemerkung [maxBemerkLength] ; double wahrseh; char wahrvar [maxWahrVarLength] ;
NodeldentT Nodeldent; uwgknotenC () ( Nodeldent = EFFECT;
CauseNr = 0; strcpy (gattertext, "— unknown —"); strcpy (gatterbemerkung, "—keine—");
Gatterldent = DummyNr++; }; uwgknotenC (NodeldentT _NodeIdent )
( Nodeldent = _NodeIdent;
CauseNr = 0; strepylgattertext, "— unknown —"); strepylgatterbemerkung, "—keine—");
Gatterldent = DummyNr++; ); uwgknotenC (NodeldentT _NodeIdent, t _CauseNr/*, char _gattertext [ ] */ )
( Nodeldent = _NodeIdent;
CauseNr = CauseNr; strepylgattertext, "— unknown —"); strepylgatterbemerkung, "—keine—") ; /*strcpy(gattertext, _gattertext ) ;*/
Gatterldent
DummyNr++; };
uwgknotenC (NodeldentT _NodeIdent, t _CauseNr, char _gattertex [ ] , char _gatterbemerkung[ ] )
( Nodeldent = _NodeIdent; CauseNr =
_CauseNr; strepylgattertext, "— unknown —"); strepylgattertext, _gattertext ) ; strepylgatterbemerkung, _gatterbemerkung) ;
Gatterldent DummyNr++; }; uwgknotenC(NodeldentT _NodeIdent, int _CauseNr, char _gattertext ( ] )
( Nodeldent = _NodeIdent;
CauseNr = _CauseNr;
/*strcpy (gattertext, "— unknown —");*/ strepylgattertext, _gattertext) ; strepylgatterbemerkung, "—keine—" ) ;
Gatterldent DummyNr++; ); uwgknotenC (NodeldentT _NodeIdent, ehar _gattertext [ ] , char
_gatterbemerkung[] )
( Nodeldent =
Nodeldent; CauseNr = 0; strepylgattertext, _gattertext) ; strepylgatterbemerkung, _gatterbemerkung) ;
Gatterldent DummyNr++; ) ; uwgknotenC (NodeldentT _NodeIdent, char _gattertext [ ] )
( Nodeldent = _NodeIdent; CauseNr = 0; strepylgattertext, _gattertext) ; strepylgatterbemerkung, "—keine—" ) ; Gatterldent «
DummyNr++; }; int getCauseNrl) ( return CauseNr; }; mt getGatterldent ( ) ( return Gatterldent; );
NodeldentT getNodeldent I ) const ( return Nodeldent; ); bool Operator == (const uwgknotenCS other) eonst
( return ( (Cau- seNr == other. CauseNr) S (Nodeldent == other . Nodeldent ) s
(strcmplgattertext, other. gattertext) == 0) /*S (Gatterl- dent == other.Gatterldent)*/) ; ); bool Operator '= (const uwgknotenCS other) const
( return ! (*thιs
== other) ; ); bool Operator < (const uwgknotenCS other) const ( return (Gatterldent < other.Gatterldent); ); bool Operator > (const uwgknotenCS other) const
( return (Gatterldent > other.Gatterldent); }; friend ostreamS Operator « ( ostreamS os, const uwgknotenCS Node);
»endif
»include "AS_GraphKante.h"
D
»include <ιostream> ostreamS Operator « ( ostreamS os, const GraphKanteC S Kante)) os « Kante. KantenTyp; return os; }
»include "AS_GraphNode.h"
D
»include <ιostream>
0
D ostreamS Operator « ( ostreamS os, const GraphNodeCS Node)( 0 os « endl « Node.NodeNr; return os;
}
»include "AS Slice. h" D
»include <ιostream>
0
»include <ιterator>
0 »include <algoπthm>
D
»include "uwggraph.h"
D o using namespace std; D
D
D
IIFO : Funktion zur Auswahl der Variable, für die ein Fehlerbaum erstellt werden soll. D
// Zurückgegeben wird em Zeiger auf den ausgewählten Knoten. KFGListC: : iterator SliceC: :defιneVarιableToSlιce (KFGListC S L2 ) ( int Number = 0;
KFGListC: : iterator KFGI = L2.begin(); KFGListC: : iterator VARDEFI = L2.begιn(); KFGUseListC: : iterator USEIT; while ( KFGI != L2.end()) (
USEIT = KFGI->Uses.begιn(); if ( KFGI->getKFGNodeType ( ) == OP ) ( cout « KFGI->getKnotenNummer ( ) « ": " « USEIT->getUse( ) « endl ; ; )
KFGI++; } cout « "Geben Sie die Knotennummer em und drücken Sie RETURN: "; cm » Number; while ( KFGI '= L2.begιn()) ( if (KFGI->getKnotenNummer ( ) == Number) (
VARDEFI = KFGI, } KFGI--; if (VARDEFI->getKFGNodeType() == OP) ( cout « "Ausgewählt wurde Knoten Nr.: " « VARDEFI->getKnotenNummer ( ) « endl ;
return VARDEFI; eise
VARDEFI = L2.beginl); eout « "Dieser Knoten ist kein Ausgabeknoten, das Programm wird beendet."
« endl; exιt(l); return VARDEFI; )
//Fl: Sucht P-Use Knoten, fügt ihn dem Slice hinzu und zieht eine KFK. // input: Iterator auf den C-Use oder D-Use, KFG-Liste; void SliceC: :slιceForLoops (KFGListC S L2, KFGListC: : iterator LOOPIT) ( int HLevel; int check = 0; int KnotenNummer = 0; KFGListC: : iterator HELPIT = LOOPIT; while ( ( LOOPIT->getKFGNodeType ( ) != LC SS LOOPIT->getKFGNodeType ( ) != IFC) ||
(LOOPIT->getLevel( ) != HELPIT->getLevel ( ) ) ) { LOOPIT—;
}
KnotenNummer = LOOPIT->getNodeNr ( ) ; check = checkForNodes (KnotenNummer ) ;
//insert (*LOOPIT,*HELPIT, KFK); insert («HELPIT, *LOOPIT, KFK); //umgekehrte Richtung der Kante, damit ]eder Knoten seine Vorgänger kennt.
//cout « "eingefügterKnotenFla: " « LOOPIT->getNodeNr ( ) « endl; //cout « "eingefügterKnotenFla: " « HELPIT->getNodeNr ( ) « endl « endl; if (check == 0) { fιndAHDefs ( L2 , LOOPIT ) ;
}
HLevel = LOOPIT->getLevel ( ) ; while (LOOPIT->getLevel() > 2) ( check = 0;
HELPIT = LOOPIT; whil e ( ( LOOPIT->getKFGNodeType ( ) ' = LC S S LOOPIT->getKFGNodeType ( ) ' = IFC ) I I ( LOOPIT->getLevel ( ) >= HELPIT->getLevel ( ) ) ) ( LOOPIT—;
}
KnotenNummer = LOOPIT->getNodeNr ( ) ; check = checkForNodes (KnotenNummer) ;
//insert (*LOOPIT, *HELPIT,KFK) ; insert (»HELPIT, »LOOPIT, KFK) ; //umgekehrte Richtung der Kante, damit 3eder
Knoten seine Vorgänger kennt.
//cout « "eingefügterKnotenFlb: " « LOOPIT->getNodeNr ( ) « endl;
//cout « "eingefügterKnotenFlb: " « HELPIT->getNodeNr ( ) « endl « endl; if (check == 0) ( fmdAHDefs(L2, LOOPIT);
}
HLevel = LOOPIT->getLevel ( ) ;
//F2: Sucht alle D-Uses zu einem P-Use, fügt diese dem Slice hinzu und zieht DFK. // input: Iterator auf den Knoten mit der P-Use Liste, KFG-Liste; void SliceC: : findAHDefs (KFGListC S Ll, KFGListC: : iterator ITER) { int AktLevel; int dummylf = 0; int KnotenNummerEnde = 0; AktLevel = ITER->getLevel ( ) ; KFGListC: : iterator HELPIT = ITER; KFGListC: : iterator HELPIF = ITER;
KFGListC: : iterator HELPLOOP = ITER; KFGListC: : iterator UPPERLIMIT = ITER; KFGPJJseListC: : iterator PUSEIT; PUSEIT = ITER->P_Uses.begιn( ); KFGDefListC: : iterator DEFIT1; if (ITER->getKFGNodeType() == LC) < while ( (HELPLOOP->getKFGNodeType( ) >= EL) || (HELPLOOP->getLevel { ) != Akt- Level ) ) {
HELPLOOP++; }
HELPIT = HELPLOOP;
KnotenNummerEnde = HELPLOOP->getNodeNr ( ) ;
while (PUSEIT '= ITER->P_Uses.end( ) ) (
UPPERLIMIT = fmdUpperLimit (Ll, ITER, PUSEIT); HELPLOOP = fιndLowerLιmit(Ll, ITER, UPPERLIMIT); //insert (»UPPERLIMIT, *ITER, DFK) ; insert (»ITER, »UPPERLIMIT, DFK) ; //umgekehrte Richtung der Kante, damit 3eder
Knoten seine Vorgänger kennt.
//cout « "eιngefügterKnotenF2a: " « UPPERLIMIT->getNodeNr ( ) « endl; //cout « "eιngefügterKnotenF2a: " « ITER->getNodeNr ( ) « endl; while (HELPLOOP ι= UPPERLIMIT) ( HELPLOOP--; if (HELPLOOP->getKFGNodeType( ) — EE1 ) { dummylf = 1; } if ( (HELPLOOP->getKFGNodeType( ) == ETh) SS (HELPLOOP->getLevel I ) < ITER->getLevel I ) ) SS Idummylf == 0)) (
HELPIF = HELPLOOP; while ( (HELPLOOP->getKFGNodeType() != IFC) || (HELPLOOP- >getLevel() '= HELPIF->getLevel ( ) ) ) (
HELPLOOP--; } dummylf = 0; } if (HELPLOOP->getKFGNodeType( ) == NO) ( DEFIT1 = HELPLOOP->Defs.begιn(); while (DEFIT1 '= HELPLOOP->Defs.end ( ) ) { if (strcmp(PUSEIT->getUse( ) , DEFITl->getDef ( ) ) == 0) ( //insert ( »HELPLOOP, *ITER, DFK) ; msert(*ITER,*HELPLOOP,DFK); //umgekehrte Richtung der Kante, damit jeder Knoten seine Vorgänger kennt. defInLoopILl, HELPLOOP);
//cout « "eιngefügterKnotenF2b: " « HELPLOOP- >getNodeNr() « endl;
//cout « "eιngefügterKnotenF2b: " « ITER-
>getNodeNr() « endl « endl; if CHEL JPPLLOOOOPP-->>UUsseess.. eemmppttyy II )) )) (( fmdDefToCUselLl, HELPLOOP);
} }
DEFIT1++;
}
PUSEIT++; } KFKPUseToCUse (ITER, KnotenNummerEnde ) ;
//F5: Funktion sucht den ersten def oberhalb eines p-uses oder c-uses und
// liefert einen Iterator auf diese obere Grenze bei der Suche aller defs // zurück.
KFGListC: : iterator SliceC: : findUpperLimit (KFGListC S Ll, KFGListC: : iterator ITER, KFGP_UseLιstC: : iterator PUSEIT) ( int dummy = 0; mt dummyl = 0; mt dummylf = 0; int AktLevel = 0;
KFGListC:: iterator HELPDEF = ITER; KFGListC:: iterator HELPLOOP = ITER;
KFGListC:: iterator HELPIF = ITER; KFGListC:: iterator HELPIT = ITER; KFGListC:: iterator HELPDEFRETURN = ITER; KFGDefListC: : iterator DEFIT; AktLevel = ITER->getLevel ( ) ;
//finden des ersten defs oberhalb des p-use. while ((HELPDEF != Ll.beginO) SS (dummy '= 1)) ( HELPDEF--; if (HELPLOOP->getKFGNodeType( ) == EE1) ( dummyl f = 1 ;
) if I (HELPDEF->getKFGNodeType( ) == ETh) S (HELPDEF->getLevel ( ) < ITER- >getLevel()) SS (dummylf == 0)) (
HELPIF = HELPDEF; while ( (HELPDEF->getKFGNodeType( ) '= IFC) II (HELPDEF->getLevel ( ) ' =
HELPIF->getLevel( ) ) ) (
HELPDEF—;
dummylf = 0;
} if (HELPDEF->getKFGNodeType( ) == NO) ( DEFIT = HELPDEF->Defs.begιn(); if (strcmp(DEFIT->getDef ( ) , PUSEIT->getUse ( ) ) == 0) (
HELPDEFRETURN = HELPDEF; dummy = 1; ) } } if ((HELPDEF == Ll.begmO) SS (HELPDEF->getKFGNodeType ( ) == NO)) ( DEFIT = HELPDEF->Defs.begm(); if (strcmp(DEFIT->getDef ( ) , PUSEIT->getUse ( ) ) ~ 0) ( HELPDEFRETURN = HELPDEF; dummy = 1;
} }
//finden der äußersten Schleife, falls diese überhaupt existiert, if (ITER->getLevel() > 2) ( while ((HELPIT '= Ll.endO) SS (dummyl '= 1)) {
HELPIT++; if ( (HELPIT->getKFGNodeType( ) == EL) SS (HELPIT->getLevel ( ) < Akt- Level ) ) (
HELPLOOP = HELPIT; if (HELPIT->getLevel() > 2) (
AktLevel = HELPIT->getLevel ( ]
} eise dummyl = 1; }
) }
HELPIT ■= HELPLOOP;
//gehe zum Anfang der äußersten Schleife: while I (HELPIT->getKFGNodeType() '= LC) II (HELPIT->getLevel ( ) '= HELPLOOP-
>getLevel I ) ) ) (
HELPIT—; )
//wenn der gefundene def-Koten außerhalb der äußersten Schleife liegt, und //sein ScopeLevel großer ist als das der äußersten Schleife, suche, ob es
//noch einen weiteren def-Knoten weiter oben gibt, if (HELPDEF->getNodeNr( ) > HELPIT->getNodeNr ( ) ) ( if (HELPDEF->getLevel( ) >= HELPIT->getLevel ( ) ) ( dummy = 0; while ((HELPDEF '= Ll.begmO) SS (dummy '= 1)) (
HELPDEF—;
DEFIT = HELPDEF->Defs.begιn( ); if (strcmplDEFIT->getDe (),PUSEIT->getUse( ) ) == 0) ( HELPDEFRETURN = HELPDEF; dummy = 1;
) ) } ) } return HELPDEFRETURN;
//F6: Funktion sucht, abhängig vom oberen Ende, das untere Ende des Bereichs, indem // die defs gesucht werden müssen.
// Zurückgeliefert wird ein Iterator auf die untere Grenze.
KFGListC: : iterator SliceC: : findLowerLimit (KFGListC S Ll, KFGListC: : iterator ITER, KFGListC: :ιterator UPPERLIMIT) ( int dummyl = 0; int AktLevel « 0;
KFGListC: : iterator HELPIT = ITER; KFGListC: : iterator HELPLOOP = ITER; KFGListC: : iterator LOWERLIMIT = ITER;
AktLevel = ITER->getLevel I ) ; if (ITER->getKFGNodeType( ) == LC) ( while ( (HELPLOOP->getKFGNodeType( ) >= EL) || (HELPLOOP->getLevel ( ) ^ Akt- Level)) ( HELPLOOP++;
} } //finden des Endes der äußersten Schleife.
if (ITER->getLevel() > 2) ( while I (HELPIT != Ll.end(l) SS (dummyl != 1)) ( HELPIT++; if ( (HELPIT->getKFGNodeType() == EL) SS (HELPIT->getLevel ( ) < Akt- Level)) {
HELPLOOP = HELPIT; if (HELPIT->getLevel() > 2) (
AktLevel = HELPIT->getLevel ( ) ; ) eise < dummyl = 1; } } } HELPIT = HELPLOOP; //HELPLOOP zeigt auf das Ende der äußersten Schleife, ansonsten auf den p-use. while ( (HELPIT->getKFGNodeType() >= LC) || (HELPIT->getLevel ( ) != HELPLOOP- >getLevel ( ) ) ) (
HELPIT—; } //HELPIT zeigt auf den
Anfang der äußersten Schleife. if (HELPIT->getNodeNr() < UPPERLIMIT->getNodeNr ( ) ) (
LOWERLIMIT = HELPLOOP; //falls die obere Grenze außerhalb der Schlei- fen liegt. eise
AktLevel = UPPERLIMIT->getLevel ( ) ; while | (HELPLOOP->getKFGNodeType() ι= EL) II (HELPLOOP->getLevel ( ) <=
AktLevel ) ) ( HELPLOOP—;
LOWERLIMIT = HELPLOOP; //falls die obere Grenze innerhalb der Schleife liegt. eise (
LOWERLIMIT = HELPLOOP; } return LOWERLIMIT;
//F3: Funktion zieht eine KFK vom P-Use zu allen C-Uses, die sich in derselben // Schleifen- bzw. Verzweigungsebene befinden. // input: Iterator auf P-Use Knoten. void SliceC: :KFKPUseToCUse (KFGListC: : iterator PUSEIT, t SchielfenEnde) ( SliceC: : iterator SLl = begιn(); SliceC: : iterator SLHELP = beginl); KFGListC:: iterator ITER = PUSEIT;
KFGUseLiεtC: : iterator USEIT; KFGPJJseListC: : iterator PUSEIT2; KFGUseListC:: iterator CUSEIT2; int KnotenLevel; int KnotenNummer;
KnotenNummer = PUSEIT->getNodeNr ( ) ; KnotenLevel = PUSEIT->getLevel ( ) ; while I (*SL1) . first. getNodeNr ( ) != KnotenNummer) SL1++; SLHELP - SLl;
SLl - begin ( ) ; while (SLl '= end() ) { if ((KnotenNummer > (*SL1 ). first. getNodeNr () ) SS (SchleifenEnde < (*SL1) .first. getNodeNr!) ) ) ( if (( (*SL1) .first. getKFGNodeType! ) == NO) SS ( (*SL1 ). first. getLevel ( )
== KnotenLevel ) ) (
//insert ( («SLHELP) .first, (*SL1) .first, KFK) ; insert ! ( *SL1 ) . first, ( *SLHELP) . first, KFK) ; //umgekehrte Richtung der Kante, damit j eder Knoten seine Vorgänger kennt . //cout « "emgefügterKnotenF3 : " «
( *SL1 ) . first . getNodeNr ! ) « endl ;
//cout « "eιngefügterKnotenF3 : " « ( *SLHELP ) . first . getNodeNr ! ) « endl ; , '
SL1++;
) }
//F4: Funktion sucht, wenn der Knoten neben den defs noch c-uses enthält, zu diesen // c-uses alle defs und zieht DFK vom gefundenem def zum c-use. void SliceC: : indDefToCUse (KFGListC S Ll, KFGListC: : iterator ITER) { t HLevel; mt check = 0; t dummy = 0; int dummylf = 0; int KnotenNummer = 0;
KFGListC: : iterator HELPIT «= ITER; KFGListC: : Iterator HELPLOOP = ITER; KFGListC: : iterator HELPIF = ITER; KFGListC: : iterator LOWERLIMIT = ITER; KFGListC: : iterator UPPERLIMIT = ITER;
KFGDefListC: : iterator DEFIT1; KFGUseListC: : iterator USEIT1; USEIT1 = ITER->Uses.begin(); HLevel = ITER->getLevel ( ) ; while (USEIT1 != ITER->Uses.end ( ) ) (
UPPERLIMIT = findUpperLimitFromCUse (Ll, ITER, USEIT1 ) ; HELPIT - findLowerLimitFromCUse (Ll, ITER, UPPERLIMIT); UPPERLIMIT—;
//cout « "eιngefügterKnotenF4a: " « UPPERLIMIT->getNodeNr ( ) « endl; //cout « "eιngefügterKnotenF4a: " « ITER->getNodeNr ( ) « endl; while (HELPIT != UPPERLIMIT) ( if (HELPLOOP->getKFGNodeType() == EE1) ( dummylf = 1; } lf ( (HELPIT->getKFGNodeType( ) == ETh) SS (HELPIT->getLevel ( ) <= ITER-
>getLevel()) SS (dummylf == 0)) (
HELPIF = HELPIT; while ( (HELPIT->getKFGNodeType() '= IFC) II (HELPIT- >getLevel() != HELPIF->getLevel ( ) ) ) ( HELPIT—;
) dummylf » 0;
} lf (HELPIT->getKFGNodeType( ) == NO) ( DEFIT1 = HELPIT->Defs.beginl ); lf (strcmp(DEFITl->getDef I ) ,USEITl->getUse ( ) ) == 0) ( lf (!HELPIT->Uses. emptyI) ) (
KnotenNummer = HELPIT->getNodeNr I ) ; check = checkForNodes (KnotenNummer) ; }
//insert ( *HELPIT, *ITER, DFK) ; insert (»ITER, «HELPIT, DFK); //umgekehrte Richtung der Kante, damit jeder Knoten seine Vorgänger kennt. defInLoop ( Ll , HELPIT ) ; //cout « "emgefügterKnotenF4b: " « HELPIT-
>getNodeNr() « endl;
//cout « "eingefügterKnotenF b: " « ITER- >getNodeNr() « endl « endl; if (check == 0) ( findDefToCUse |L1, HELPIT);
) } } HELPIT—; }
USEIT1++;
}
//F8: Funktion sucht die untere Grenze, von der an die defs zu einem c-use gesucht // werden dürfen.
KFGListC: : iterator SliceC: : findLowerLimitFromCUse (KFGListC S Ll, KFGListC: : iterator ITER, KFGListC: :ιterator UPPERLIMIT) ( int HLevel; int dummy = 0;
KFGListC:: iterator HELPIT = ITER; KFGListC:: iterator HELPLOOP = ITER; KFGListC: : iterator LOWERLIMIT = ITER;
KFGDefListC: : iterator DEFIT1; KFGUseListC: : iterator USEIT1; USEIT1 = ITER->Uses. beginl ) ;
HLevel = ITER->getLevel ( ) ;
/ /Ist der c-use Knoten in einer Schleife? if ( ITER->getLevel ( ) >= 2 ) ( while ((HELPIT != Ll.endO) SS (dummy !«= 1)) ( HELPIT++; if ( (HELPIT->getKFGNodeType() == EL) SS (HELPIT->getLevel ( ) <- HLevel)) {
HELPLOOP = HELPIT; lf IHELPIT->getLevel( ) > 2) ( HLevel—; eise ( dummy = 1; ) } }
}
//Der Iterator HELPLOOP zeigt jetzt auf das Ende der äußersten, den Knoten umgebenden //Schleife, falls es diese gibt, ansonsten zeigt der Iterator auf den c-use-Knoten selbst. lf (HELPLOOP '= ITER) {
HELPIT = HELPLOOP; //Iterator zeigt auf das Ende der äußersten
Schleife. while ( (HELPIT->getKFGNodeType() != LC) || (HELPIT->getLevel ( ) != HELPLOOP-
>getLevel ( ) ) ) (
HELPIT—; } if (HELPIT->getNodeNr( ) < UPPERLIMIT->getNodeNr ( ) ) ( LOWERLIMIT = HELPLOOP; //obere Grenze außerhalb der äußersten Schleife;
} eise if (ITER->getLevel( ) == UPPERLIMIT->getLevel ( ) ) (
LOWERLIMIT = ITER; //obere Grenze mit dem c-use in dersel- ben Schleife;
) eise lf (ITER->getLevel( ) < UPPERLIMIT->getLevel ( ) ) (
LOWERLIMIT = HELPLOOP; //obere Grenze in derselben äußeren Schleife, aber } //innerhalb in einer anderen, vor dem c-use liegenden Schleife; eise (
HLevel = UPPERLIMIT->getLevel ( ) ; while ( (HELPLOOP->getKFGNodeType( ) !- EL) II (HELPLOOP->getLevel ( ) <= HLevel)) (
HELPLOOP—; }
LOWERLIMIT = HELPLOOP; //obere Grenze in einer niedrigeren Schleife als der c-use; }
} eise {
LOWERLIMIT = ITER; //keine äußere Schleife vorhanden.
} return LOWERLIMIT;
)
//F7: Funktion sucht die obere Grenze, bis zu der defs zu einem c-use gesucht werden // dürfen. Die Funktionsweise ist ähnlich entsprechenden Funktion für p-uses.
KFGListC: : iterator SliceC: : findUpperLimitFromCUse (KFGListC S Ll, KFGListC: : iterator ITERl, KFGUseListC:: iterator USEIT) ( int dummy = 0; t dummyl = 0; int dummylf = 0; int AktLevel = 0;
KFGListC: : iterator HELPDEF = ITERl; KFGListC: : iterator HELPLOOP = ITERl; KFGListC: : iterator HELPIT = ITERl; KFGListC: : iterator HELPIF = ITERl;
KFGListC: : iterator HELPDEFRETURN = ITER1; KFGDefListC: : iterator DEFIT; AktLevel = ITERl->getLevel () ;
//cout « "bearbeitender Knoten: " « ITERl->getNodeNr ( ) « endl; //finden des ersten defs oberhalb des use. do ( lf (HELPLOOP->getKFGNodeType() -= EE1 ) ( dummylf = 1;
} lf ( (HELPDEF->getKFGNodeType() == ETh) SS (HELPDEF->getLevel ( ) <= ITERl- >getLevel ( ) ) &S (dummylf == 0)) f
HELPIF = HELPDEF; while ( (HELPDEF->getKFGNodeType() != IFC) II (HELPDEF->getLevel I ) !=
HELPIF->getLevel I ) ) ) {
HELPDEF—; } dummylf = 0; l)f (HELPDEF->getKFGNodeType() -= NO) ( DEFIT = HELPDEF->Defs.beginl ); lf (strcmp(DEFIT->getDef ( ) ,USEIT->getUse I ) ) == 0) ( HELPDEFRETURN = HELPDEF; if (HELPDEF != ITERl) ( dummy = 1; } ) } HELPDEF—;
) while ((HELPDEF != Ll.begmO) SS (dummy != 1 ) ) ; if ( (HELPDEF == Ll.beginl ) ) SS (HELPDEF->getKFGNodeType ( ) == NO) ) ( DEFIT = HELPDEF->Defs.begin ( ) ; lf (stremp(DEFIT->getDef (),USEIT->getUse() ) == 0) { HELPDEFRETURN = HELPDEF;
}
}
HELPDEF = HELPDEFRETURN;
//cout « "erster def: " « HELPDEFRETURN->getNodeNr ( ) « endl; //finden der äußersten Schleife, falls diese überhaupt existiert, if (ITERl->getLevel() >= 2) ( while ((HELPIT != Ll . end ( ) ) SS (dummyl != 1)) ( HELPIT++; lf ( (HELPIT->getKFGNodeType() == EL) SS (HELPIT->getLevel ( ) <= Akt- Level))
HELPLOOP = HELPIT; lf (HELPIT->getLevel( ) > 2) ( AktLevel—; eise { dummyl = 1; ) } ) HELPIT - HELPLOOP;
//cout « "Ende der äußersten Schleife: " « HELPIT->getNodeNr ( ) « endl; //gehe zum Anfang der äußersten Schleife, wenn es diese gibt; if (HELPLOOP->getKFGNodeType( ) == EL) { while ( (HELPIT->getKFGNodeType() != LC) || (HELPIT->getLevel ( ) != HELPLOOP->getLevel ( ) ) ) (
HELPIT—; )
//cout « "Anfang der äußeren Schleife: " « HELPIT->getNodeNr ( ) « endl; //wenn der gefundene def-Koten außerhalb der äußersten Schleife liegt, und
//sein ScopeLevel größer ist als das der äußersten Schleife, suche. ob es
//noch einen weiteren def-Knoten weiter oben gibt. lf (HELPDEF->getNodeNr() > HELPIT->getNodeNr I ) ) ( lf (HELPDEF->getLevel( 1 >= HELPIT->getLevel ( ) ) ( dummy = 0; while ((HELPDEF != Ll.begmO) SS (dummy != 1)) ( HELPDEF—; DEFIT = HELPDEF->Defs.begιn(); if (strcmp(DEFIT->getDe () ,USEIT->getUse ( ) )
0)
HELPDEFRETURN = HELPDEF; dummy = 1;
//c-use innerhalb der äußersten Schleife; eise ( if (HELPDEF->getLevel( ) > ITERl->getLevel ( ) ) ( dummy = 0; while IHELPDEF >= HELPIT) (
HELPDEF—;
DEFIT = HELPDEF->Def s . egin l ) ; l f | strcmp ( DEFIT->getDef ( ) , USEIT->getUse ( ) ]
0 ) <
HELPDEFRETURN = HELPDEF;
} } )
//c-use in keiner Schleife, aber in einer Verzweigung; eise ( lf (HELPDEF->getLevel|) > ITERl->getLevel () ) ( dummy = 0; while ((HELPDEF '= Ll.beginO) SS (dummy '= 1)) {
HELPDEF—;
DEFIT = HELPDEF->Defs.beginl ); lf (strcmp(DEFIT->getDef () ,USEIT->getUse( ) ) == 0) { HELPDEFRETURN = HELPDEF; dummy = 1;
}
) }
//c-use in keiner Schleife; eise ( lf (HELPDEF->getLevel( ) > ITERl->getLevel () ) ( dummy = 0; while ((HELPDEF '= Ll.begmO) SS (dummy '= 1)) (
HELPDEF—;
DEFIT = HELPDEF->Defs.beginl ); if (strcmp(DEFIT->getDef ( ) ,UΞEIT->getUse ( ) ) == 0) ( HELPDEFRETURN = HELPDEF; dummy = 1;
) } } //cout « "UpperLimitFunktion: " « HELPDEFRETURN->getNodeNr ( ) « endl; return HELPDEFRETURN;
//F9: Funktion überprüft, ob ein Knoten bereits im Slice vorhanden ist. Wenn ja, // wird eine eins zurückgeliefert, andernfalls eine null. // input: Knotennummer des gesuchten Knotens; // Output: Integerwert 0 oder 1; int SliceC: : checkForNodes (int NodeNumber) ( mt dummy = 0;
SliceC: : iterator SLl = beginl); while ((SLl '= end()) SS (dummy '= 1)) ( lf ( (*SL1) .first. getNodeNrO == NodeNumber) ( dummy = 1;
SL1++;
) lf (dummy == 1 ) ( return 1; } eise ( return 0; }
//FlO: Funktion untersucht, ob em def in einer Schleife ist; wenn ja, wird die // Funktion Fl, die den p-use sucht, aufgerufen. Dort wird als erstes nach- // gesehen, ob der gefundene p-use bereits im Slice vorhanden ist. void SliceC: :defInLoop (KFGListC S Ll, KFGListC: : iterator ITER) ( int dummyLoop = 0; KFGListC:: iterator HELPIT = ITER; while ((HELPIT '= Ll.beginO) SS (dummyLoop '= 1)) { HELPIT—; lf ( ( (HELPIT->getKFGNodeType() == LC) II (HELPIT->getKFGNodeType ( ) == IFC)) SS (HELPIT->getLevel() == ITER->getLevel ( ) ) ) ( sliceForLoops (Ll, ITER) ;
dummyLoop = 1;
//Fll: Funktion bekommt den ausgewählten Startknoten für den Slice übermmittelt, // untersucht, ob dieser Knoten in einer Schleife ist; wenn ja, wird zuerst // die Funktion "sliceForLoops" aufgerufen, ansonsten sofort "findDefToCUse"'. void SliceC: :startBuιldSlιce (KFGListC S Ll/*, KFGListC: : iterator OUTPUTIT*/) ( mt dummyNode = 0;
KFGListC: : iterator STARTVARI = defineVariableToSlice (Ll ) ; KFGListC:: iterator HELPOUT = STARTVARI; while ((HELPOUT '= Ll.beginO) SS (dummyNode != 1)) (
HELPOUT--; lf ( I (HELPOUT->getKFGNodeType() == LC) II (HELPOUT->getKFGNodeType | ) IFC)) SS (HELPOUT->getLevel() == STARTVARI->getLevel I) ) ) ( SliceForLoops ( Ll , STARTVARI ) ; dummyNode = 1 ;
} )
//cout « "Fll" « OUTPUTIT->getNodeNr ( ) « endl; findDefToCUse ( Ll , STARTVARI ) ; }
void SliceC: :slιceAusgeben( ) ( ofstream Ziel ("Slιce2. sie" ) ; ostream_lterator<KFGLιstNodeC> POSITIZiel, "\n"); //ostream_ιterator<KFGLιstNodeC> POSIT2(Zιel, "\n"); SliceC: : iterator SLC = beginl); while (SLC !-= end() ) ( *POSIT++ = (*SLC) .first;
SliceC: :Nachfolger: :ιterator IT = («SLC) .second. begm( ) ; SliceC: :Nachfolger: :ιterator ITEND = (*SLC) .second. end( ) ; while (IT != ITEND) (
//a = (*IT) .first; »POSIT++ = SLC[ («IT) .first] .first;
»IT++; ) ++SLC;
«include "KFGDef.h"
D
»include <ιostream>
D
G ostreamS Operator « ( ostreamS os, const KFGDefCS Node)( G os « "DEF: " « Node. Def « " " « Node. ScopeLevelD; α return os; α
»include "KFGLineNode.h"
G
»include <ιostream> ostreamS Operator « ( ostreamS os, const KFGLmeNodeCS Node)( os « Node.Name « " " « Node. LineNumber « endl; return os; }
//Funktion, die aus KFGTokenList einen KFG baut. D
»include <ιoεtream>
D
»include "KFGList.h"
D
»include "KFGTokenList.h"
»include "KFGUse.h"
»include "KFGDef.h"
»include "KFGProgList.h"
»include <algoπthm> void KFGListC: :TokenLιst2KFGLιst (KFGTokenListC S Ll ) ( int dummy;
KFGTokenListC: : iterator TLI = Ll.endO; KFGP_UseLιstC: : iterator P_USEI;
KFGUseListC: : iterator USEI; dummy = 0;
//while (strcmp(TLI->getName( ) , "main") '= 0) { while ((TLI != Ll.beginO) SS (dummy != 1)) ( l (TLI->getTokenNodeType( ) -= N) { lf (strcmp(TLI->getName(),"maιn") == 0) { dummy = 1; ) } //TLI++; switch (TLI->getTokenNodeType( ) ) ( case PL: (
TLI--; KFGLlstNodeC hNl ("NORMAL", NO, TLI->getScopeLevel ( ) ,TLI-
>getLιneNumber () ) ; hNl . Defs .push_bac (KFGDefC (TLI->getName ( ) , TLI- >getScopeLevel ( ) ) ) ; push_front (hNl ) ; TLI—;
} break; /«case IF: push_front ( KFGLιstNodeC ( "IF" , IFC, TLI->getScopeLevel ( ) ) ) ; TLI--; break; */ case BT :
//push_front (KFGLlstNodeC ("BT",BTh,TLI->getScopeLevel ( ) ) ) ; ( TLI—;
//KFGP_UseLιstC: : iterator P_USEI;
KFGLlstNodeC hNl ("IFCOND", IFC, TLI->getScopeLevel ( ) ,TLI- >getLιneNumber ( ) ) ; while (TLI->getTokenNodeType( ) '= IF) ( KFGUseC hUsel (TLI->getName( ) ,TLI->getScopeLevel () ) ;
P JSEI = f dlhNl. P_Uses.beginl ) ,hNl . P_Uses.end( ) ,hUsel) ; if I P_USEI == hNl . P_Uses . end () ) { hNl.P_Uses.push_back(hUsel) ; Anzahl_P_Uses++;
)
//hNl . P_Uses .push_back (KFGUseC (TLI ->getName ( ) ,TLI- >getScopeLevel ( ) ) ) ;
TLI — ; } push_front (hNl ) ; Entscheιdungen++; } break; case ET: push_front (KFGLlstNodeC ("ENDTHEN",ETh,TLI->getScopeLevel ( ) ) ) ; TLI--; break; case BE: push_front (KFGLlstNodeC ("BEGINELSE", BEI, TLI->getScopeLevel( ) ) ) ;
TLI--; break; case EE: push_front (KFGLlstNodeC ( "ENDELSE", EE1, TLI->getScopeLevel () ) ) ; TLI—; break; /•case WHILE: push_front (KFGLlstNodeC ("WHILE", LC, TLI->getScopeLevel ( ) ) );
TLI--; break;*/ case BW:
//push front(KFGLιstNodeC("BW",BL,TLI->getScopeLevel() ) ); {
TLI—;
//KFGP_UseLιstC: :ιterator PJJSEI;
KFGLlstNodeC hNl ("LOOPCOND",LC,TLI->getSeopeLevel ( ) ,TLI- >getLιneNumber ( ) ) ; while (TLI->getTokenNodeType() '= WHILE) (
KFGUseC hUsel (TLI->getName ( ) ,TLI->getScopeLevel ( ) ) ; PJJSEI = find (hNl.P Uses. beginl ) , hNl . P_Uses . end ( ) ,hUsel) ; if (P_USEI == hNl.P_Uses.end() ) { hNl.P_Uses.push_back(hUsel);
Anzahl_P_Uses++; }
//hNl. P_Uses.push_back(KFGUseC (TLI->getName () ,TLI- >getScopeLevel ( ) ) ) ; TLI--;
} push_front (hNl) ; Schieifenentscheιdungen++; } break; case EW: push_front (KFGLlstNodeC ("ENDLOOP", EL, TLI->getScopeLevel () ) ); TLI—; break; case BDOW:
(
TLI—;
KFGLlstNodeC hNl ("DOWHILELOOPCOND", DOWLC.TLI- >getScopeLevel ( ) ,TLI->getLιneNumber ( ) ) ; while (TLI->getTokenNodeType() '= DOWS) (
KFGUseC hUsel (TLI->getName ( ) , TLI->getScopeLevel ( ) ) ; P_USEI = fιnd( hNl. P_Uses.beginl ) ,hNl. P_Uses.end( ) ,hUsel) ; lf (PJJSEI == hNl.P_Uses.end()) ( hNl. PJJses.pushJ>ack!hUsel);
Anzahl_P_Uses++; } hNl. PJJses.pushJ-ack(KFGUseC (TLI->getName ( ),TLI- >getScopeLevel I ) ) ) ; TLI—;
) push_front(hNl) ; } break; case DO: push_front (KFGLιstNodeC("DOWHILELOOP",DOWL,TLI->getScopeLevel ( ) ) ) ; TLI — ;
Schle f enentscheιdungen++ ; break; case EF:
(
//TLI—; int HLevel;
HLevel = TLI->getScopeLevel ( ) ; push_front (KFGLlstNodeC ("ENDLOOP", EL, LI->getScopeLevel() ) );
//while (TLI->getTokenNodeType() != BF) ( while ( (TLI->getTokenNodeType() >= BF) II (TLI- >getScopeLevel I ) != HLevel)) (
TLI—; }
TLI—; if (TLI->getTokenNodeType( ) == PF)
TLI--; KFGLlstNodeC hNl ( "NORMAL",NO,TLI->getScopeLevel ( ) ,TLI- >getLmeNumber () ) ; hNl.Defs.push_back(KFGDefC(TLI->getName( ),TLI- >getScopeLevel () ) ) ;
AnzahlJ3efs++; hNl.Uses.push_back( KFGUseC (TLI->getName ( ) , TLI- >getScopeLevel I ) ) ) ;
Anzahl_Uses++; push_front(hNl);
//while (TLI->getTokenNodeType() '= EF) (
while ( (TLI->getTokenNodeType() != EF) II (TLI-
>getScopeLevel( ) '= HLevel)) {
TLI++;
}
TLI—;
Zaehlschleιfenentscheιdungen++; Schleifenentscheιdungen++; break; case FOR_D: (
TLI—;
KFGLlstNodeC hNl ( "LOOPCOND", LC,TLI->getScopeLevel ( ) ,TLI- >getLιneNumber ( ) ) ; while (TLI->getTokenNodeType() != DEF) {
KFGUseC hUsel (TLI->getName ( ) ,TLI->getScopeLevel () ) ; PJJSEI -= find (hNl. PJJses.beginl ) , hNl . PJJses. endl ) ,hUsel) ; lf (PJJSEI — hNl.P_Uses.end()) ( hNl . PJJses .push_back (hUsel ) ; Anzahl_P_Uses++; } //hNl . PJJses.push_back (KFGUseC (TLI->getName ( ) ,TLI-
>getScopeLevel ( ) ) ) ;
TLI—; } push_front (hNl) ;
TLI--;
KFGLlstNodeC hN2 ( "NORMAL", NO, (TLI->getScopeLevel ( ) -1 ) ,TLI-
>getLιneNumber ( ) ) ; hN2.Defs.push_back(KFGDefC(TLI->getName( ) , (TLI- >getScopeLevel ()-!)));
Anzahl_Defs++; push_front (hN2) ; TLI--; break; case RET:
//Nur eine vorläufige Implementierung; muß noch erweitert werden
//für den Fall, daß nach dem RETURN eine Ausgabe folgt. push_front( KFGLlstNodeC ("RETURN", RETURN, LI->getScopeLevel ( ) ) ) ;
TLI—; break; case NL:
TLI--;
//Knoten erzeugen, der Defs und Uses enthält; lf (TLI->getTokenNodeType() —= N) (
KFGLlstNodeC helpNodel ( "NORMAL", NO, TLI->getScopeLevel ( ) ,TLI- >getLιneNumber ( ) ) ;
TLI--; lf (TLI->getTokenNodeType() == NL) (
TLI++; helpNodel. Defs.push_back(KFGDefC (TLI->getName ( ) ,TLI-
>getScopeLevel ( ) ) I ;
Anzahl_Defs++; helpNodel .Uses .pushjoack (KFGUseC (TLI->getName ( ) ,TLI- >getScopeLevel ( ) ) ) ;
Anzahl_Uses++; TLI—;
} eise (
TLI++; while (TLI->getTokenNodeType( ) ' = DEF) { KFGUseC hUsel (TLI->getName ( ) ,TLI- >getScopeLevel ( ) ) ;
USEI = find (helpNodel.Uses. beginl ) , helpNodel .Uses. end ( ) ,hUsel ) ; lf (USEI == helpNodel. Uses. endl ) ) { helpNodel .Uses.push_back (hUsel ) ; Anzahl_Uses++ ; }
//helpNodel. Uses.push_back(KFGUseC (TLI-
>getName( ) ,TLI->getScopeLevel O ) ) ; TLI—; } TLI--;
helpNodel. Defs.push_bac (KFGDefC (TLI->getName ( ) ,TLI- >getScopeLevel ( ) ) ) ;
TLI—;
Anzahl_Defs++; if (TLI->getTokenNodeType() — N) ( helpNodel.Defs.pop_front ( ) ; Anzahl_Defs—; //in diesem Fall handelt es sich um ein Array und
//daher muß der letzte Knoten wieder gelöscht werden.
TLI++; //Dafür muß der gelöschte Knoten in die Use-Liste eingetragen werden.
KFGUseC hUse2 (TLI->getName ( ) ,TLI- >getScopeLevel ( ) ) ;
USEI - find (helpNodel.Uses. begm( ) , helpNodel. Uses. end ( ) ,hUse2) ; lf (USEI == helpNodel.Uses. en () ) ( helpNodel.Uses. ush_back(hUse2) ; Anzahl Uses++;
TLI--; helpNodel.Defs.pushJ-ack (KFGDefC(TLI-
>getName ( ) , TLI->getScopeLevel ( ) ) ) ; helpNodel.Uses.push_bac (KFGUseC (TLI- >getName ( ) , TLI->getScopeLevel () ) ) ;
Anzahl_Defs++; AnzahlJJses++; TLI--;
} push fron (helpNodel) ; }
//Knoten erzeugen, der nur Defs enthält; eise if (TLI->getTokenNodeType() == DEF) (
TLI—;
KFGLlstNodeC helpNodel ("NORMAL",NO, TLI->getScopeLevel ( ) ,TLI-
>getLιneNumber ( ) ) ; helpNodel . Defs .push_back (KFGDefC (TLI->getName ( ) , TLI- >getScopeLevel ( ) ) ) ; push_front (helpNodel ) ;
Anzahl_Defs++;
TLI--; ) eise if (TLI->getTokenNodeType( ) == PF) (
TLI—;
KFGLlstNodeC hNl ( "NORMAL", NO, TLI->getScopeLevel ( ) ,TLI-
>getLιneNumber ( ) ) ; hNl.Defs.push_back(KFGDefC(TLI->getName( ) ,TLI- >getScopeLevel ( ) ) ) ; hNl.Uses.push_back(KFGUseC(TLI->getName( ) ,TLI- >getScopeLevel ( ) ) ) ; push_front(hNl);
Anzahl_Defs++;
Anzahl_Uses++; }
//Knoten erzeugen, der Output-Variablen enthält; eise (
TLI—;
KFGLlstNodeC helpNodel ("OUTPUT", OP,TLI->getScopeLevel ( ) ,TLI-
>getLιneNumber ( ) ) ; helpNodel .Uses . push_back ( KFGUseC (TLI->getName ( ) , TLI- >getScopeLevel ( ) ) ) ; push_front (helpNodel ) ;
Anzahl_Uses++;
TLI—;
Anweιsungen++; break; default:
TLI—;
}
KnotenNummern ( ) ;
KFGListC:: iterator KFG = beginl);
Knotenldentifizierer (KFG) ; addL elnToList ( ) ;
Anzahl Deklarationen = zaehleDeklaratιonen(Ll ) ;
void KFGListC: : KnotenNummern ( ) ( mt KnotenNr = 1;
KFGListC: : iterator KFGI = beginl); while (KFGI '= end()) ( lf ( (KFGl->getKFGNodeType() == EL) II (KFGl->getKFGNodeType ( ) == ETh) II (KFGl->getKFGNodeType( ) == BE1) II (KFGl->getKFGNodeType( ) == EE1 ) ) ( KFG1++;
) eise (
KFGI->setKFGKnotenNummer (KnotenNr) ; KnotenNr++; KFG1++;
void KFGListC: :KnotenIdentιflzierer (KFGListC: :iterator KFG) int LOOPLevel = 0 int THENLevel = 0 int ELSELevel = 0 KFGListC: : iterator KFGI KFG; KFGListC: : iterator LOOPIT = KFG; KFGListC: : iterator IFIT KFG; KFGListC: : iterator ELSEIT = KFG; while (KFGI != end() ) ( switch (KFGl->getKFGNodeType ( ) ) case LC:
LOOPLevel = KFGl->getLevel ( ) ;
KFG1++;
LOOPIT = KFGI; while ( (KFGl->getKFGNodeType ( ) != EL) II (KFGl->getLevel()
LOOPLevel ) ) {
KFGl->setKnotenIdent (LOOP) ; KFG1++; }
Knotenldentifizierer (LOOPIT) ; } break; case IFC: <
THENLevel = KFGl->getLevel ( ) ;
KFG1++;
IFIT = KFGI; while ( (KFGl->getKFGNodeType() >= ETh) II (KFGl->getLevel () != THENLevel) )
KFGl->setKnotenIdent (THEN) ;
KFG1++; } Knotenldentifizierer (IFIT) ; } break; case BEI: (
ELSELevel = KFGl->getLevel ( ) ; KFG1++;
ELSEIT = KFGI; while ( (KFGl->getKFGNodeType() != EE1) || (KFGl->getLevel (
!= ELSELevel) )
KFGI->setKnotenIdent (ELSE) ; KFG1++;
Knotenldentifizierer (ELSEIT) ;
} break; default:
//cout « "Autsch" « endl;
KFG1++; ) //KFG1++;
voiα KFGListC: :addLιneInToLιst ( ) ( mt zahl; char lιne[256]; KFGProgListC LP; lfstream datei ("CodeLine.dat") ; if (!dateι) ( cout « "ERROR: Cannot open file 'CodeLine.dat'." « endl;
) eise ( while ( idatei.eof ( ) ) ( datei.getlmelline, 255, '\n'); for (int ι=0; Kstrlen(line) ; ι++) ( lf (line(ι) == •"' ) ( lιne[ι] = '\"; ) if (lineli) — '(') ( lιne(i] = ';'; ) } zahl = atoι(lιne);
KFGLmeNodeC hknotendine, zahl ) ;
LP.push_back (hknoten) ;
//cout « line « " " « zahl « endl;
} } addLιneToKFG(LP);
void KFGListC: :addLιneToKFG (KFGProgListC S LP) { int dummy = 0; char help(256];
KFGListC: : iterator KFGI = end(); KFGProgListC: : iterator PROG1 = LP.endO; //KFGI—; while (KFGI != begιn()) ( KFGI—; lf ( (KFGl->getKFGNodeType() == EL) || (KFGl->getKFGNodeType () == ETh) II (KFGl->getKFGNodeType() == BEI ) || (KFGl->getKFGNodeType ( ) == EE1 ) ) ( KFGI—;
} while ((PROG1 '= LP.beginO) SS (dummy '= 1)) ( lf (KFGl->getLmeNr() == PROGl->getLmeNumber I ) ) ( strcpy (help,PROGl->getName () ) ; KFGl->setCodeLιne(help);
PROG1—; dummy = 1; ) else{ PROG1—;
PROG1 = LP. en l ); dummy = 0;
int KFGListC: :zaehleDeklaratιonen (KFGTokenListC S TL) ( int zaehler = 0;
KFGTokenListC: : iterator TListI = TL.endO; while (strcmp(TLιstI->getName( ) ,"maιn") '= 0) ( lf (TLιstI->getTokenNodeType() == TD) f zaehler++; }
TListI—; return zaehler;
//Funktion zur Ausgabe der KFGList auf den Bildschirm und in eine Datei "CFGList". void KFGListC: :LιsteAusgeben( ) { ofstream Ziell ("CFGLis . cfg" ) ; ostream_ιterator<KFGLιstNodeC> Pos(Zιell, "\n"); ostream_ιterator<KFGDefC> PosDIZiell, "\n") ostream_ιterator<KFGUseC> PosUIZiell, "\n"); ostream_ιterator<KFGUseC> PosPIZiell, "\n");
KFGListC: : iterator KLI = beginl ); KFGDefListC: : iterator DEF; KFGUseListC: : iterator USE; KFGPJJseListC: : iterator PJJSE; Ziell « "START" « endl « endl; while (KLI '= endO ) (
Ziell « "Line " « KLI->getLιneNr ( ) « endl; Ziell « "Zeile " « KLI->getCodeLιne ( ) « endl; Ziell « "Knoten " « KLI->getKnotenNummer ( ) « endl; Ziell « "KnotenTyp " « KLI->getKnotenIdent O « endl;
Ziell « KLI->getStatement () « " " « KLI->getLevel () « endl; //*Pos++ - »KLI; DEF - KLI->Defs.begin(); USE = KLI->Uses.begin(); P_USE - KLI->P_Uses.beginl ); while (DEF !»= KLI->Defs.end( ) ) ( //*PosD++ = »DEF;
Ziell « "DEF: " « DEF->getDef ( ) « " " « DEF- >getScopeLevelD( ) « endl; DEF++;
) while (USE != KLI->Uses.end() ) ( //*PosU++ = »USE;
Ziell « "USE: " « USE->getUse ( ) « " " « USE- >getScopeLevelU( ) « endl;
USE++; } while (PJJSE '= KLI->P_Uses.end() ) ( //*PosP++ = «P_USE; Ziell « "P_USE: " « P_USE->getUse ( ) « " " «
P_USE->getScopeLevelU 0 « endl; PJJSE++; )
Ziell « endl; KLI++;
)
Ziell « "STOP" « endl « endl; Ziell « "BASISGROESSEN:" « endl; Ziell « "Anzahl leerer Zweige: " « "0" « endl; Ziell « "Anzahl Entscheidungen: " « Entscheidungen « endl;
Ziell « "Anzahl Anweisungen: " « Anweisungen « endl; Ziell « "Anzahl atomarer Prädikate: " « Entscheidungen « endl; Ziell « "Anzahl Prädikate: " « Entscheidungen « endl;
Ziell « "Anzahl atomarer Prädikate, die arithm. Relationen sind: " « "0" « endl; Ziell « "Anzahl Schleifenentscheidungen: " « Schleifenentscheidungen « endl;
Ziell « "Anzahl nicht eingeschachtelter Schleifenentscheidungen: " « "0" « endl; Ziell « "Anzahl Zählschleifenentscheidungen: " « Zaehlschleifenentscheidungen « endl;
Ziell « "Anzahl Deklarationen von strukturierten Datentypen: " « "0" « endl; Ziell « "Anzahl Deklarationen: " « Anzahl_Deklaratιonen « endl;
Ziell « "Anzahl Realelement-Deklarationen: " « "0" « endl; Ziell « "Anzahl Basistyp-Deklarationen: " « Anzahl_Deklaratιonen « endl; Ziell « "Anzahl Defs: " « Anzahl_Defs « endl; Ziell « "Anzahl Uses: " « Anzahl_Uses « endl; Ziell « "Anzahl P-Uses: " « Anzahl_P_Uses « endl « endl; basisgroessenlnDatei ( ) ; } void KFGListC: :basιsgroessenInDatei ( ) ( ofstream datei ("Basisgroessen.bgd", ιos::out); datei « "0" « endl; datei « Entscheidungen « endl; datei « Anweisungen « endl; datei « Entscheidungen « endl; datei « Entscheidungen « endl; datei « "0" « endl; datei « Schleifenentscheidungen « endl; datei « "0" « endl; datei « Zaehlschleifenentscheidungen « endl; datei « "0" « endl; datei « Anzahl_Deklaratιonen « endl; datei « "0" « endl; datei « Anzahl_Deklaratιonen « endl; datei « "0" « endl; datei « Anzahl_Defs « endl; datei « AnzahlJJses « endl; datei « Anzahl_P_Uses « endl;
datei « "0" « endl; datei « "0" « endl; datei « "0" « endl; datei « "0" « endl; datei « "0" « endl; datei « "0" « endl; datei « "0" « endl; datei « "0" « endl;
»include "KFGListe .h" D
D
KFGListeT KFGListe;
D α void KFGListeAusgebenlKFGListeT S L) { 0
KFGListeT: : iterator I = L.beginO; D whiled '= L.endl) ) cout « »I++ « ' '; cout « " sιze() = " « L.sizeO « endl; }
»include "KFGListNode.h"
□
»include <ιostream>
0
D ostreamS Operator « ( ostreamS os, const KFGListNodeCS Node)( □ os « endl « "KnotenNr:" « Node. KnotenNr « " Typ:" « Node. Knotenldent « endl « Node. Statement « " Level:" « Node. Level; return os; int KFGLlstNodeC: :DummyNodeNr=l;
0
»include "KFGNode.h" 0
»include <ιostream> D
□ ostreamS Operator « ( ostreamS os, const KFGNodeCS Node)
D os « Node. Name « " " « Node. ScopeLevel; return os; }
»include "KFGTokenList.h" D
void KFGTokenListC: :KFGLιsteAusgeben( ) ( D ofstream Ziel ("CFGTokenList") ; D ostream_ιterator<KFGTokenNodeC> oPos(Zιel, "\n");
D
KFGTokenListC: : iterator I = beginl); 0 while (I != endl ) ) { //»oPos++ - I->getName();
*oPos++ = »I;
//cout « I->getName() « " " « I->getScopeLevel ( ) « " " « I- >getTokenNodeType ( ) « endl; I++; ) cout « " sizel) = " « sizeO « endl;
»mclude "KFGTokenNode.h" »include <ιostream> ostreamS Operator « ( ostreamS os, const KFGTokenNodeCS Node)( os « Node.Name « " " « Node. ScopeLevel « " " « Node. TokenNodeType « " « Node. ineNumber « endl; return os;
»include "KFGUse.h"
0
»include <ιostream> ostreamS Operator « ( ostreamS os, const KFGUseCS Node)( os « "USE: " « Node. Use « " " « Node. ScopeLevelU; return os;
/* D * Main program to test C++ grammar and preprocessor D
*/ π o »include "JLStr.h"
D
»include "tokens.h"
0
»include "DLGLexer.h" »include "BufferedCPreParser.h"
»include "CPreToCPPBuffer.h"
»include "JLTokenBuffer.h"
»include "CPPParserSym.h"
»mclude "KFGTokenList.h" «include "KFGList. h"
» clude "graph.h"
»mclude "AS_Slιce.h"
»include "uwggraph.h"
« clude "KFGProgList .h" »include <ιostream> static void usagelchar* progname); int maindnt arge, char *argv|]) {
// For reporting memory usage char *p = new char [ 100000) ; long heapl = (long) (void* )p;
delete [ ] p;
// Parse command-line options JLStr includePath; JLStr definitions;
FILE «lnputFile = stdin; bool doTraceParse = false; bool doTraeelnclude = false; bool doDump = false; char «progname = «argv; arge—; argv++; ofstream datei ("CodeLme.dat", ιos::trunc); while (arge > 0)
( if (argv[0] [0] == •-•) ( switch (argv(0] [1] ) ( case ' I" : lf (argv[0] [2] != 0) (
// argument is part of "-I" includePath += ' ; ' ; includePath += Sargv[0][2); } eise lf (arge > 1) arge—; argv++; includePath += ' ; ' ; includePath - «argv; ) eise ( usage (progname ) ; } break; case 'd' : lf (strcmp|argv[0], "-dump") == 0)
( doDump = true; ) break; case 'D': lf (argv[0] [2] '= 0) (
// argument is part of "-D" definitions += ';'; definitions += sargv|0][2);
} eise lf (arge > 1) (
// argument follows "-D" arge—; argv++; definitions += ';'; definitions = *argv; } eise ( usage (progname ) ; } break; case ' t ' : lf (strcmp(*argv, "-traceParse" ) == 0) { doTraceParse = true;
) eise lf (stremp (*argv, "-tracelnclude" ) == 0) ( doTraeelnclude = true; ) eise { usage (progname) ;
} break; default: usage (progname ) ; break;
) ) eise (
// must be the input filename
if (mputFile != stdin)
(
// already have one usage (progname) ; )
FILE *fp = fopen(*argv, "r"); lf (fp — NULL)
( fpnntf ( stderr, "%s : cannot open %s for ιnput\n" , progname, *argv) ; exιt ( O ) ;
) putFile = fp;
} arge—; argv++; }
//printf ("*s\n%s\n%s\n", includePath, definitions, mputFile) ; // Create input stream, lexer DLGFllelnput mput ( putFile) ; DLGLexer Scanner (Sinput) ; FastToken tok; Scanner. setToken(stok) ;
// Create preprocessor parser. Note that the preprocessor parser has // a built- token buffer in the form of an put Stack.
Buf eredCPreParser preprocessor (Sscanner) ; preprocessor . mit ( ) ;
// set include path and defines directly for debugging if ( includePath. lengthO ~ 0)
( includePath = "c: \\devstudιo\\vc\\ιnclude; \\msdev\\devstudιo\\vc\\mfc\\ιnclude" ; if (defimt ons . length l ) == 0 )
< definitions =
" cplusplus; " " DATE =\"date\";"
" FILE =\"fιlename\";"
" LINE =1 ; "
" TIME =\"tιme\";"
" TIMESTAMP =\"tιmestamp\";' "_M_IX86=400;"
"_MSC_VER=1100;" "_WIN32;"
"_INTEGRAL_MAX_BITS=64" ; }
// Set preprocessor options preprocessor. SetIncludePath ( includePath ) ; preprocessor. SetDefinitions (definitions) ; // Set options in parser to make it act Standard with MS Extensions preprocessor. SetOption(CPreParserImp: :OptMSExtensιons, true) ; preprocessor. SetOption (CPreParserlmp: :OptBool, true) ; preprocessor. SetOption (CPreParserlmp: :OptWCharT, true) ; preprocessor. SetOption (CPreParserlmp: :OptPragmas, true) ; preprocessor. SetOption!CPreParserlmp: :OptExpandPragmas, true); preprocessor. SetOption (CPreParserlmp: :OptTrackInclude, doTraeelnclude) ;
// Buffer to störe tokens Output by preprocessor CPreToCPPBu fer pιpe2 ( Spreprocessor ) ;
// Connect preprocessor to second token buffer so that the
// preprocessor can unilaterally squirt new tokens into the buffer preprocessor. SetBu er ( pιpe2) ; // Token buffer for the usual backtrack ng, etc.
JLTokenBuffer pιpe3 (Spιpe2, CPPParserSym: :ConstLLK) ;
// Create the C++ parser CPPParserSym parser ( pιpe3) ;
// Set parser options to look like MSVC++ parser. SetOption (CPPParserSym: :OptPragmaMSPackιng, true) parser. SetOption (CPPParserSym: :OptMSTypedefHack, true);
//preprocessor.doTrace (doTraceParse) ; parser . doTrace (doTraceParse ) ;
// Process top-level rule parser. mit ( ) ;
KFGTokenListC Ll; parser. translatιon_unit (Ll ) ;
// Close the input file stream if (mputFile '= stdin)
{ fclose ( mputFile ) ; }
// For reporting memory usage // For reporting memory usage p = new char[100000]; long heap2 = (long) (void* )p; delete [] p; cout « "Approx heap usage before dump: " « (heap2 - heapl ) « endl; if (doDump)
(
// Dump the scope hierarchy cout « "Dump of scope hierarchy" « endl; parser. DumpScopes ( ) ; cout « endl;
// For reporting memory usage // For reporting memory usage p = new char[100000] ; long heap3 = (long) (void* )p; delete [] p; cout « "Approx heap usage after dump: " « (heap3 - heapl) « endl; Ll .KFGListeAusgeben ( ) ; //Ll .KFGTokenListToKFGList ( ) ;
KFGListC L2;
//KFGListC: : iterator Iter; L2. TokenLιst2KFGLιst ( Ll ) ; L2. ListeAusgeben ( ) ;
SliceC Slice;
Slice . startBuildSlice (L2 ) ; //Slice. uιldTestGraph(L2); //cout « Slice; uwggraphC uwggraph; //uwggraph.buildlfTree (Slice) ; uwggraph. startBuildFT ( Slice) ; cout << uwggraph; return 0;
) static void usage ( char* progname ) ( fprintf ( stderr,
"usage: %s [-1 directories] [-D definitions] (-traceParse] [ -tracelnclude ] [-o ofile] |ιfιle]\n" " -I directories- semicolon-separated list of include dιrectoπes\n"
-D definitions: semicolon-separated list of definitions, lιke:\n" symbol1; symbol2=value2\n" -traceParse: output debugging ιnformatιon\n" -tracelnclude: Output trace of include stack\n" " -dump: dump type and scope hιerarchy\n"
" ifile: name of mput file (otherwise it uses stdιn)\n", progname ); exιt(l); )
«include <ιostream>
»include <ιterator> «include <algorιthm> «include <fstream> «include "uwggraph. h" using namespace std;
SliceC: : iterator uwggraphC: : fmdOutputNode (SliceC s Sl) { t dummy - 0; SliceC: : iterator SLl - Sl.begmO;
SliceC: : iterator HELP = Sl.beginO; while ((SLl != Sl.endO) SS (dummy != 1)) ( if I (*SL1) .first. getKFGNodeType!) ~ OP ) HELP = SLl; dummy = 1;
}
SLl ++; } return HELP; }
void uwggraphC: :startBuιldFT (SliceC S Sl) ( t posl - 0; int Posil = 0; mt SliceNr = 0; t LineNr = 0; int inLoop = 0; SlιceAusgeben(Sl) ; char NodeText (128] ; char BemerkungllOOO] ;
SliceC: : iterator SLl = f dOutputNode ( Sl ) ; SliceNr = (»SLl ) . first. getKnotenNummer ( ) ; LineNr = (»SLl ). first. getLineN O ; sprintf (NodeText, "Op%d", SliceNr); strcpy(Bemerkung, SLl->fιrst.getCodeLιne( ) ) ; //sprintf (Bemerkung, "Line %d", LineNr) ;
SliceC: :Nachfolger: :ιterator BEGIN = (»SLl ) .second.beginl ) ; SliceC: :Nachfolger: :ιterator END » («SLl ) .second. end () ; while (BEGIN '= END) ( lf (BEGIN->second == KFK) ( uwgknotenC hknotenl (EFFECT, SliceNr, NodeText, Bemerkung) ; Posil = insert (hknotenl ) ; SliceC: :ιterator SLPUSE = findLastPUse (Sl, SliceNr);
CheekLoopOrCondlSl, SLPUSE, SLl, Posil); mLoop = 1; BEGIN++; } eise (
BEGIN++; ) } if (inLoop == 0) { uwgknotenC hknotenl (EFFECT, SliceNr,NodeText, Bemerkung) ; uwgknotenC hknoten2 (OR, "OR" ) ; insert (hknotenl, hknoten2, 0) ; n3 (CAUSE, SliceNr, NodeText, Bemerkung) ; knoten3, 0) ;
ISl, SliceNr, posl); } check ( ) ; ' void uwggraphC: : checkLoopOrCond (SliceC S Sl, SliceC: : iterator SLPUSE, SliceC: : iterator SLORIG, t Posl) { int PosRet = 0; switch ( SLPUSE->fιrst. getKFGNodeType! ) ) ( case IFC:
PosRet = buildlnIfTreelSl, SLPUSE, SLORIG, Posl); //cout « "Testla: " « SLHELP->fιrst .getKnotenNummer ( ) « endl; break; case LC: buildInLoopTree (Sl, Posl, SLPUSE, SLORIG);
//cout « "Testlb: " « SLHELP->fιrst .getKnotenNummer ( ) « endl;
break; default: cout « "Ups" « endl;
}
void uwggraphC: :addFιrstNodesToFT(ΞlιceC S Sl, t KnotenNr, mt Posl) ( int helpNr = 0; t ret - 0; mt pos - 0; int KnotenNrl = 0; int LineNrl = 0; char NodeText [128] ; char Bemerkung [1000];
SliceC: : iterator NODE ■> definelterator (Sl, KnotenNr); SliceC: :Naehfolger: :iterator BEGIN = NODE->second.begιn( ) ; SliceC: :Nachfolger: : iterator END = NODE->second.end ( ) ; while (BEGIN != END) { helpNr = BEGIN->fιrst;
KnotenNrl = Sl [helpNr] . first. getKnotenNummer () ; SliceC: : iterator N0DE1 = definelterator (Sl, KnotenNrl ) ; lf (NODEl->fιrst.getLevel() > 1) (
SliceC: :ιterator PUSE = findLastPUse (Sl, KnotenNrl); switch ( PUSE->fιrst. getKFGNodeType () ) ( case IFC: ret = buildlnIfTreelSl, PUSE, NODE1, Posl); break; case LC: buildInLoopTree (Sl, Posl, PUSE, NODE1 ) ; break; default: cout « "Something is wrong'" « endl; } ) eise (
LineNrl = Sl [helpNr] . first. getLineNr () ; sprintf (NodeText, "Op%d", KnotenNrl ) ; //sprintf (Bemerkung, "Line %d", LineNrl) ; strcpy!Bemerkung, Sl (helpNr) . first. getCodeLine ( ) ) ; uwgknotenC hknotenl (CAUSE, KnotenNrl, NodeText, Bemerkung) ; pos = insert (hknotenl ) ; verbmdeEcken (Posl,pos, 0) ; addFirstNodesToFTISl, KnotenNrl, Posl); }
BEGIN++;
SliceC: :ιterator uwggraphC: : findLastPUse (SliceC S Sl, int SliceNr) ( int helpNrl = 0; int SliceNrl = 0; SliceC: :ιterator SLl = definelterator (Sl, SliceNr);
SliceC: :ιterator SLHELP = SLl;
SliceC: :Nachfolger: : iterator BEGIN = («SLl ) .second. eginl ) ; SliceC: :Nachfolger: :ιterator END = («SLl ) .second. endl ) ; while (BEGIN '= END) ( if (BEGIN->second == KFK) ( helpNrl = BEGIN->fιrst;
SliceNrl = Sl [helpNrl ]. first .getKnotenNummer () ;
SLHELP = defιneIterator(Sl, SliceNrl); SLHELP = findLastPUse (Sl, SliceNrl);
BEGIN++; } return SLHELP;
SliceC: :ιterator uwggraphC: : fιndLastPUse2 (SliceC S Sl, int SliceNr, int RefNr) ( mt helpNrl = 0; lnt SliceNrl = 0; SliceC: :ιterator SLRETURN = definelterator (Sl, SliceNr);
SliceC: :ιterator SLHELP = SLRETURN;
SliceC: :Nachfolger: : iterator BEGIN = SLRETURN->second.begιn ( ) ; SliceC: :Nachfolger: .iterator END = SLRETURN->second. end ( ) ;
while (BEGIN != END) ( lf (BEGIN->second == KFK) ( helpNrl = BEGIN->fιrst;
SliceNrl = Sl [helpNrl] .first. getKnotenNummer () ; SLHELP = definelterator (Sl, SliceNrl);
SLHELP = fιndLastPUse2(Sl, SliceNrl, RefNr); lf ( SLHELP->fιrst. getKnotenNummer ( ) '= RefNr) (
SLRETURN = SLHELP; } }
BEGIN++;
} return SLRETURN;
}
SliceC: : iterator uwggraphC: :lookForNextPUse (SliceC S Sl, SliceC: : iterator SNODE, SliceC: :ιterator SLPUSE) ( int helpNrl - 0; int helpNr2 = 0; int helpNr3 = 0; int dummy = 0; int dummyl = 0; int KnotenNrl = 0; int KnotenNr2 = 0; int RefNr = SLPUSE->flrst. getKnotenNummer () ; SliceC: : iterator HELP = SNODE; SliceC: : iterator RETURN = SNODE; SliceC: :Nachfolger: :ιterator BEGIN1 « SNODE->second.beginl ) ;
SliceC: :Nachfolger: :ιterator END1 = SNODE->second.end() ; while I (BEGIN1 '= END1 ) SS (dummy != 1))( helpNrl = BEGINl->first;
SliceC: :Nachfolger: :ιterator BEGIN2 = Sl [helpNrl] .second. beginl ) ; SliceC: :Nachfolger: :ιterator END2 = Sl [helpNrl] -second. end () ; while ((BEGIN2 '= END2 ) SS (dummyl '= 1)1 ( if (BEGIN2->second == KFK) ( helpNr2 = BEGIN2->flrst; if (Sl [helpNr2] .first. etKnotenNummer ( ) '= RefNr) ( KnotenNrl = Sl |helpNr2] . first. getKnotenNummer () ;
RETURN = definelterator (Sl, KnotenNrl); SliceC: :Nachfolger: :ιterator BEGIN3 = RETURN-
>second.begιn ( ) ;
SliceC: :Nachfolger: :ιterator END3 = RETURN- >second . end ( ) ; whlle (BEGIN3 '= END3) ( lf (BEGIN3->second == KFK) ( helpNr3 = BEGIN3->flrst; lf (Sl [helpNr3] . first. getKnotenNummer ( ) •- RefNr) {
KnotenNr2 =
Sl [helpNr3] . first .getKnotenNummer ( ) ;
RETURN = fιndLastPUse2(Sl, Kno- tenNr2, RefNr);
BEGIN3++; } dummyl = 1 ; dummy = 1;
) eise {
KnotenNrl = Sl [helpNrl ]. first. getKnotenNummer () ; HELP = definelterator (Sl, KnotenNrl); RETURN = lookForNextPUse(Ξl, HELP, SLPUSE);
BEGIN2++; BEGIN1++;
} return RETURN;
SliceC: : iterator uwggraphC: : returnCondNode (SliceC S Sl, int SliceNr) int helpNr = 0;
mt dummy = 0; mt dummy2 = 0; int SlιceNr2 = 0;
SliceC: : iterator SLl = definelterator |S1, SliceNr); SliceC: : iterator HELP = SLl;
SliceC: :Nachfolger:: iterator BEGIN = (*SL1) .second.beginl ) ; SliceC: :Nachfolger: : iterator END = (»SLl ) .second. end( ); while ((BEGIN ι= END) SS (dummy != 1)) { helpNr = BEGIN->first; SliceNr = Sl [helpNr] . first. getKnotenNummer () ;
HELP = definelteratorlSl, SliceNr);
SliceC: :Nachfolger: :ιterator BEGIN2 = (»HELP) .second. beginl ) ; SliceC: :Nachfolger: :ιterator END2 = (»HELP) .second. endl ) ; while ( (BEGIN2 != END2 ) SS (dummy2 != D) ( if ( (»BEGIN2) .second == KFK) ( helpNr = (»BEGIN) . first;
SlιceNr2 = Sl [helpNr] . first .getKnotenNummer () ; HELP = definelteratorlSl, SlιceNr2); dummy2 = 1; dummy = 1;
}
BEGIN2++; } BEGIN++; return HELP;
//Funktion untersucht, ob zwei Kontrollstrukturen geschachtelt sind oder nicht. int uwggraphC: :checkPUsesl (SliceC S Sl, SliceC: : iterator SLPUSEREF, SliceC: : iterator SLPUSE) ( int helpreturn ■= 0; int KnotenNummerRef - 0; int helpNrl = 0; int KnotenNrl = 0;
KnotenNummerRef = SLPUSE->first. getKnotenNummer () ; SliceC: :Nachfolger: :ιterator BEGIN1 = SLPUSEREF->second.beginl ) ; SliceC: :Nachfolger: .-iterator END1 = SLPUSEREF->second.end() ; while (BEGIN1 != END1 ) ( lf (BEGINl->second == KFK) ( helpNrl = BEGINl->fιrst;
KnotenNrl = Sl [helpNrl] . first. getKnotenNummer () ; if (KnotenNrl == KnotenNummerRef) ( helpreturn = 1;
} eise (
SLPUSEREF = de inelterator ( Sl, KnotenNrl ) ; helpreturn = checkPUsesl (Sl, SLPUSEREF, SLPUSE) ;
)
BEGIN1++; } return helpreturn;
t uwggraphC: :checkPUses2 (SliceC S Sl, SliceC: : iterator SLPUSEREF, SliceC: :ιterator SLPUSE) { mt helpreturn = 0; mt KnotenNummerRef = 0; int helpNrl = 0; int KnotenNrl = 0; KnotenNummerRef = SLPUSEREF->first. getKnotenNummer () ;
SliceC: :Nachfolger: : iterator BEGIN1 = SLPUSE->second.begιn ( ) ; SliceC: :Nachfolger: : iterator END1 = SLPUΞE->second.end() ; while (BEGIN1 '= END1 ) ( if (BEGINl->second == KFK) { helpNrl = BEGINl->first;
KnotenNrl = Sl [helpNrl] . first .getKnotenNummer I ) ; lf (KnotenNrl == KnotenNummerRef) ( helpreturn = 1; } eise (
SLPUSE = definelterator (Sl, KnotenNrl); helpreturn = checkPUses2 (Sl, SLPUSEREF, SLPUSE ) ;
}
BEGIN1++; } return helpreturn;
int uwggraphC: :buιldInIfTree (SliceC S Sl, SliceC: : iterator SLIF, SliceC: : iterator SLORIG, int posl) ( int pos2 = 0; int posIFOR = 0; int posIFDFOR - 0; int posIFKFOR - 0; int posIFDFORA2 - 0; char NodeText [128]; char Bemerkun [ 1000] ; int KnotenNr = SLIF->fιrst. getKnotenNummer () ; int LineNr = SLIF->fιrst.getLιneNr ( ) ; sprintf (Bemerkung, "Verzweigung (%d)", LineNr) ; strcpy (NodeText, SLIF->fιrst.getCodeLιne ( ) ) ; uwgknotenC hknotenl (OR,NodeText, Bemerkung) ; pos2 = insert (hknotenl ) ; posIFOR = sizel) - 1; verbmdeEckenlposl, pos2,0); sprintf (NodeText, "Verzweιgung_KF(%d) ", LineNr) ; uwgknotenC hknotenδ (OR,NodeText) ; posIFKFOR = inser (hknotenδ) ; verbιndeEcken(pos2, posIFKFOR, 0) ; buιld_IFKF_Part(Sl, posIFKFOR, SLIF); switch (SLORIG->flrst.getKnotenIdent( ) ) ( case THEN: { sprintf (NodeText, "Verzweιgung_DF_Alt.l (%d) ", LineNr) ; uwgknotenC hknoten2 (AND, NodeText ) ; insert (hknotenl , hknoten2, 0) ; sprint (Bemerkung, "Alt.1 (%d) ", LineNr) ; sprintf (NodeText, "Alt .1 ( %d ) " , LineNr ) ; uwgknotenC hknoten3 (CAUSE, NodeText, Bemerkung) ; insert Ihknoten2,hknoten3,0) ; sprintf (NodeText, "Alt. l(%d)", LineNr) ; uwgknotenC hknoten<J (OR,NodeText ) ; insert (hknoten2,hknoten4, 0) ; posIFDFOR « sιze() - 1; buιld_Al_Part(Ξl, posIFDFOR, SLIF, SLORIG);
} break; case ELSE: sprintf (NodeText, "Verzweιgung_DF_Alt .2 (%d) ", LineNr) ; uwgknotenC hknoten2 (AND, NodeText ) ; insert (hknotenl, hknoten2, 0) ; sprintf (Bemerkung, "Alt.2 (%d) ", LineNr) ; sprintf (NodeText, "Alt .2 ( *d) " , LineNr ) ; uwgknotenC hknoten3(CAUSE,NodeText, Bemerkung) ; insert (hknoten2,hknoten3, 0) ; sprintf (NodeText, "Alt.2 (%d) ", LineNr) ; uwgknotenC hknoten4 (OR, NodeText ) ; insert (hknoten2,hknoten4, 0) ; posIFDFORA2 = sizeO - 1; build_Al_Part (Sl, posIFDFORA2, SLIF, SLORIG);
} break; default: cout « "Autsch1'1" « endl; return posIFDFOR;
void uwggraphC: :buιld_Al_Part (SliceC s Sl, int posIFDFOR, SliceC: : iterator SLIF, SliceC: : iterator SLNODE) ( int posO = 0;
int dummy = 0; int checkNr = 1;
int checkPUse = 1; int helpNrl = 0; int helpNr2 = 0; mt KnotenNrO = 0; t KnotenNrl = 0; t KnotenNr2 = 0; int LineNrO » 0; int LineNrl = 0; char NodeTextO [128]; char BemerkungO [ 1000] ;
KnotenNrO = SLNODE->first. getKnotenNummer () ;
LineNrO = SLNODE->fιrst.getLineNr() ; sprintf (NodeTextO, "Op%d", KnotenNrO);
//sprintf (BemerkungO, "Line %d", LineNrO) ; strcpy(Bemerkung0,SLNODE->fιrst.getCodeLιne( ) ) ; uwgknotenC hknotenO (CAUSE, KnotenNrO, NodeTextO, BemerkungO) ; posO = insert (hknotenO) ; verb deEcken (posIFDFOR,posO, 0) ;
SliceC: :Nachfolger: : iterator BEGIN0 = SLNODE->second.begιn() ;
SliceC: :Nachfolger: : iterator END0 = SLNODE->second.end( ) ; while (BEGINO != END0) ( lf (BEGIN0->second == DFK) ( helpNrl = BEGIN0->first;
KnotenNrl = Sl [helpNrl] . first. getKnotenNummer () ;
SLNODE = definelterator (Sl, KnotenNrl ) ; lf (KnotenNrl < KnotenNrO) (
SliceC: :Nachfolger: : iterator BEGIN1 = SLNODE->second.begιn( ) ; SliceC: :Nachfolger: : iterator END1 = SLNODE->second.end() ; while (BEGIN1 ' = END1) ( lf (BEGINl->second == KFK) ( helpNr2 = BEGINl->first; KnotenNr2 =
Sl [helpNr2] . first. getKnotenNummer ( ) ;
SliceC: : iterator HELPPUSE = defmeltera- tor(Sl,KnotenNr2); checkNr = checkUWGNode (KnotenNr2) ; lf (SLIF->fιrst.getKnotenNummer() > KnotenNr2)
( checkPUse checkPU- sesl ( Sl , SLIF, HELPPUSE) ; else ( checkPUse = checkPU- ses2 ( Sl, SLIF, HELPPUSE ) ;
} lf (KnotenNr2 != SLIF-> irst. getKnotenNummer () ) if (checkPUse == 0) ( dummy = 1; HELPPUSE = fmdOutmostPU- se ( Sl , HELPPUSE) ; switch (HELPPUSE-
>first. getKFGNodeType () ) ( case LC: buildInLoopTree (Sl, po- sIFDFOR, HELPPUSE, SLNODE) ; break; case IFC: ret = buιldInIfTree(Sl, HELPPUSE, SLNODE, posIFDFOR); break; default: cout « "Falscher Weg in AI' " « endl;
) eise ( lf (checkNr == 0) ( dummy = 1; HELPPUSE = findOutmost-
PUse (Sl, HELPPUSE ) ; switch (HELPPUSE-
>first. getKFGNodeType () ) ( case LC: buildInLoopTree (Sl, posIFDFOR, HELPPUΞE, SLNODE) break; case IFC:
ret = buildlnlf-
Tree ( Ξl , HELPPUSE, SLNODE, posIFDFOR) ; break; default: cout « "Falscher
Weg! " « endl;
}
BEGIN1++;
} lf (dummy == 0) (
LineNrl = Sl [helpNrl] . first. getLineNrl ) ; sprintf (NodeTextO, "Op%d" , KnotenNrl ) ;
//sprintf (BemerkungO, "Line %d", LineNrl) ; strcpy(Bemer ungO, Sl [helpNrl ] .first. etCodeLine () ) ; uwgknotenC hknotenl (CAUSE, KnotenNrl,NodeTextO,BemerkungO) ; posl = insert (hknotenl ) ; verbindeEcken (posIFDFOR, posl, 0) ; buιld_Al_Part(Sl, posIFDFOR, SLIF, SLNODE); }
)
BEGIN0++; dummy = 0;
void uwggraphC: :buιld_IFKF_Part (SliceC S Sl, int posKFOR, SliceC: : iterator SLPUSE) ( int posl = 0; int ret = 0; int dummy = 0; int checkNr = 1; int checkPUse = 1; int helpNrl = 0; int helpNr2 - 0; int KnotenNrO = 0; mt KnotenNrl = 0; int KnotenNr2 = 0; mt LineNrO = 0; int LineNrl = 0; char NodeText [ 128 ] ; char BemerkungllOOO] ;
KnotenNrO = SLPUSE->fιrst. getKnotenNummer () ; LineNrO = SLPUSE-> ιrst.getLineNr () ; sprintf (NodeText, "Op%d", KnotenNrO ) ;
//sprintf (Bemerkung, "Line %d", LineNrO) ; strcpy!Bemerkung, SLPUSE->flrst. getCodeLine! ) ) ; uwgknotenC hknotenl (CAUSE, KnotenNrO, NodeText, Bemerkung) ; posl = insert (hknotenl ) ; verbindeEcken (posKFOR, pos1,0) ;
SliceC: :Nachfolger: :ιterator BEGIN0 = SLPUSE->second.begιn( ) ; SliceC: :Nachfolger: :ιterator END0 = SLPUSE->second.end ( ) ; while (BEGIN0 '= ENDO) { lf (BEGIN0->second -» DFK) ( helpNrl = BEGIN0->fιrst;
KnotenNrl = Sl [helpNrl] . first .getKnotenNummer () ; SliceC: :ιterator SLNODE = definelterator (Sl, KnotenNrl ) ; lf (KnotenNrl < KnotenNrO) (
SliceC: :Nachfolger: : iterator BEGIN1 = SLNODE->second.begin ( ) ; SliceC: :Nachfolger: :ιterator END1 = SLNODE->second. endl) ; while (BEGIN1 '= END1 ) ( lf (BEGINl->second == KFK) ( helpNr2 = BEGINl->first; KnotenNr2 = Sl[helpNr2] . first .getKnotenNummer I ) ;
SliceC: :ιterator HELPPUSE = defineltera- tor (Sl,KnotenNr2) ; checkNr = checkUWGNode (KnotenNr2) ; if (SLPUSE->fιrst. getKnotenNummer! ) > Kno- tenNr2) ( checkPUse = checkPU- sesl (Sl, SLPUSE, HELPPUSE ) ;
eise ( checkPUse = checkPU- ses2 (Sl, SLPUSE, HELPPUSE) ; lf (KnotenNr2 '= SLPUSE- >fιrst. getKnotenNumme () ) ( if (checkPUse == 0) ( dummy = 1; HELPPUSE = findOutmostPU- se (Sl, HELPPUSE ) ; switch (HELPPUSE-
>first. getKFGNodeType! ) ) ( case LC: buildInLoopTree (Sl, posKFOR, HELPPUSE, SLNODE); break; case IFC: ret = buildlnIfTreelSl,
HELPPUΞE, SLNODE, posKFOR); break; default: cout « "Falscher Weg in
AI! " « endl; eise ( lf (checkNr == 0) ( dummy = 1; HELPPUSE = findOutmost-
PUse (Sl, HELPPUSE ) ; switch (HELPPUSE-
>first. getKFGNodeType! ) ) ( case LC: buildInLoopTree (Sl, posKFOR, HELPPUSE, SLNODE); break; case IFC: ret = buildlnlf- Tree(Sl, HELPPUSE, SLNODE, posKFOR); break; default: cout « "Falscher Weg' " « endl;
BEGIN1++; l f (dummy == 0 ) (
LineNrl = Sl [helpNrl] . first. getLmeNr () ; sprintf (NodeText, "Op%d" , KnotenNrl ) ; //sprintf (Bemerkung, "Line %d", LineNrl ) ; strcpy)Bemerkung, Sl [helpNrl] . first. getCodeLine ( ) ) ; uwgknotenC hknotenl (CAUSE, KnotenNrl,NodeText, Bemerkung) ; posl = insert (hknotenl ) ; verbindeEcken (posKFOR, posl, 0) ; buιld_IFKF_Part(Sl, posKFOR, SLNODE);
BEGIN0++; dummy = 0;
void uwggraphC: :buιldInLoopTree (SliceC s Sl, int Posl, SliceC: : iterator SLPUSE, SliceC: :ιterator SLNODE) ( mt posil = 0; int pos3 = 0; int posLOOPJCF = 0; int posOR_Dl = 0; t posOR_D2 - 0; t posANDJCF = 0; mt SliceNr = 0;
int NodeNrD2 = 0; t KnotenNr = 0; t LineNr = 0;
KnotenNr = SLPUSE->first. getKnotenNummer () ; LineNr = SLPUSE->fιrst.getLιneNr I ) ; char NodeText[128] ; char Bemerkung[1000] ; sprintf (Bemerkung, "Schleife (%d) ", KnotenNr) ; strcpy(NodeText,SLPUSE->fιrst. getCodeLine! ) ) ; uwgknotenC hknotenl (OR,NodeText, Bemerkung) ; posil = insert (hknotenl) ; verbindeEcken (Posl,posil, 0) ; sprintf (NodeText, "Schlei fe_DF_Durchl .1 ( %d)", LineNr) ; uwgknotenC hknoten2 (AND,NodeText) ; sprintf (NodeText, "Schleife_DF_Durchl . + ( %d) " , LineNr ) ; uwgknotenC hknoten3 (AND, NodeText ) ; pos3 = insert (hknoten3) ; verbindeEcken!posil,pos3,0) ; sprintf (NodeText, "Schleife_KF (%d )", LineNr ) ; uwgknotenC hknoten4 (OR, NodeText ) ; insert (hknotenl, hknoten2, 0) ; insert (hknotenl,hknoten4, 0) ; posLOOPJCF = sizel) - 1; sprintf (Bemerkung, "Durchl.l (%d) ", LineNr) ; sprintf (NodeText, "Durchl .1 ( %d ) " , LineNr ) ; uwgknotenC hknoten5 (CAUSE,NodeText, Bemerkung) ; sprintf (NodeText, "Durchl .1 ( %d ) " , LineNr ) ; uwgknotenC hknoten6 (OR, NodeText) ; insert (hknoten2,hknoten5, 0) ; insert (hknoten2,hknoten6, 0) ; posOR_Dl = size!) - 1; sprintf (Bemerkung, "Durchl . + ( *d ) " , LineNr ) ; sprintf (NodeText, "Durchl . + ( %d ) ", LineNr ) ; uwgknotenC hknoten7 (CAUSE, NodeText, Bemerkung) ; sprintf (NodeText, "Durchl. + (%d)", LineNr) ; uwgknotenC hknotenδ (OR,NodeText) ; insert (hknoten3,hknoten"7, 0) ; posOR_D2 = insert (hknotenβ) ; verbindeEcken (pos3, posOR_D2,0); sprintf (NodeText, "KF ( %d) " , LineNr ) ; uwgknotenC hknoten9 (AND, NodeText ) ; insert (hknoten4,hknoten9, 0) ; insert (hknoten3,hknoten5, 0) ; posANDJCF = sizeO - 1; msert (hknoten9,hknoten5,0) ;
NodeNrD2 = buιldIn_LoopKF_ANDPart (Sl, posANDJCF, SLPUSE); buιldIn_LoopKF_ORPart (Sl, posLOOFJCF, SLPUSE, NodeNrD2);
//buιldIn_D2_Part (Sl, posOR_D2, SLPUSE, SLNODE, NodeNrD2); buιldIn_Dl_Part (Sl, posOR_Dl, SLPUSE, SLNODE, NodeNrD2); buιldIn_D2_Part(Sl, posOR_D2, SLPUSE, SLNODE, NodeNrD2);
void uwggraphC: :buιldIn_Dl_Part (SliceC S Sl, int posOR_Dl, SliceC: : iterator SLPUSE, Sli¬ ceC: :ιterator SLNODE, int D2_RefNr) ( int posl ■= 0; int ret = 0; int KnotenNrl = 0; int LineNrl = 0;
SliceC: : iterator ITERl = fmd_Dl_Node (Sl, SLPUSE, SLNODE); SliceC: :ιterator HELP = ITERl; swιtch(ITERl->fιrst. getKFGNodeType! ) ) ( case IFC: HELP = fιnd_Dl_Node(Sl, ITERl, SLNODE); ret = buildlnIfTreelSl, ITERl, HELP,posOR_Dl); break; case LC:
HELP = fιnd_Dl_Node(Ξl, ITERl, SLNODE); buildInLoopTree (Sl,posOR_Dl, ITERl, SLNODE) ; break; default: addAllDlNodes ( Sl , ITERl ,posOR_Dl , D2_Ref r ) ; ,
SliceC: :ιterator uwggraphC: : fιnd_Dl_Node (SliceC S Sl, SliceC: : iterator SLPUSE, SliceC: : iterator SLNODE) ( int helpNrl = 0; int helpNr2 = 0; mt dummyl = 0; int dummy∑ = 0; int KnotenNrRet = 0; int KnotenNrRetl = 0; int PUseNr = SLPUSE->fιrst. getKnotenNummer () ; int PUseLevel = SLPUSE->first.getLevel () ;
SliceC:: iterator RETURNITER = SLNODE; KnotenNrRetl = SLNODE->first. getKnotenNummer () ; lf (KnotenNrRetl -== (PUseNr + 1)) (
RETURNITER = definelterator (Sl, KnotenNrRetl ) ; dummyl « 1; dummy2 = 1;
}
SliceC: :Nachfolger:: iterator BEGIN1 = ΞLNODE->second.beginl ) ; SliceC: :Nachfolger: :ιterator END1 = SLNODE->second.end( ) ; while ((BEGIN1 != END1 ) SS (dummyl != 1)) ( helpNrl = BEGINl->fιrst; lf ( (Sl[helpNrl) .first. getKnotenNummer ( ) > PUseNr) SS (SlfhelpNrl] .first. getLevel ( ) >= PUseLevel ) ) ( lf (Sl [helpNrl] . first. etLevel ( ) > PUseLevel) ( KnotenNrRetl = Sl [helpNrl ]. first .getKnotenNummer () ; lf (KnotenNrRetl == (PUseNr + 1)) {
RETURNITER = definelterator ( Sl, KnotenNrRetl ) ; dummyl = 1; dummy2 = 1 ; }
SliceC: :Nachfolger: : iterator BEGIN2 = Sl [helpNrl] .second.beginl ) ;
SliceC: :Nachfolger: :ιterator END2 = Sl (helpNrl] .second. end( ) while ( (BEGIN2 '= END2 ) SS (dummy2 != 1)) ( lf (BEGIN2->second == KFK) ( helpNr2 = BEGIN2->first; KnotenNrRet = Sl [helpNr2] . first. getKnotenNummer ( ) ; if (KnotenNrRet != PUseNr) ( RETURNITER = definelterator ( Sl , KnotenNrRet ) ; dummyl = 1; dummy∑ = 1 ; } }
BEGIN2++; } } eise ( KnotenNrRet = Sl [helpNrl] . first .getKnotenNummer () ;
RETURNITER = definelterator (Sl, KnotenNrRet ) ; dummyl = 1 ; } BEGIN1++;
) lf ((RETURNITER == SLNODE) SS (dummyl == 0)) { BEGIN1 = SLNODE->second.beginl ); while (BEGIN1 '= END1 ) ( helpNrl = BEGINl->fιrst;
KnotenNrRet = Sl [helpNrl] . first .getKnotenNummer () ; SliceC: : iterator SLNODE = definelterator (Sl, KnotenNrRet ) ; RETURNITER = fιnd_Dl_Node (Sl, SLPUSE, SLNODE); BEGIN1++; )
} return RETURNITER; }
void uwggraphC: :buιldIn_D2_Part (SliceC S Sl, int posOR_D2, SliceC: : iterator SLPUSE, SliceC: : iterator SLNODE, mt KnotenNrD2) (
int helpNrl = 0; int helpNr2 = 0;
int KnotenNrl = 0; t LineNrl = 0; t KnotenNrD2Ret - 0; int USEinD2KnotenNr ■= 0; char Bemerkungl [1000] ; char NodeTextl [128];
SliceC: :ιterator D2_NODE = definelteratorlSl, KnotenNrD2); KnotenNrl = D2_NODE->first. getKnotenNummer I ) ; LineNrl - D2_N0DE->fιrst.getLιneNr I ) ; sprintf (NodeTextl , "Op%d" , KnotenNrl ) ;
//sprintf (Bemerkungl, "Line %d", LineNrl) ; strcpy(Bemerkungl,D2_N0DE->first. getCodeLine! ) ) ; uwgknotenC hknotenl (CAUSE, KnotenNrl,NodeTextl, Bemerkungl ) ; posl = insert (hknotenl) ; verbindeEcken (posOR_D2,posl, 0) ;
SliceC: :Nachfolger: :ιterator BEGIN1 = D2_NODE->second.begιn( ) ; SliceC: :Nachfolger: : iterator END1 = D2_NODE->second.end () ; while (BEGIN1 '= END1) ( lf (BEGINl->second == DFK) ( helpNrl = BEGINl->fιrst;
KnotenNrl = Sl [helpNrl] . first .getKnotenNummer () ; LineNrl = Sl [helpNrl] . first .getLineNr () ; sprintf (NodeTextl, "Op%d", KnotenNrl) ; //sprintf (Bemerkungl, "Line %d", LineNrl) ; strcpy(Bemerkungl, Sl (helpNrl] . first. getCodeLine ( ) ) ; uwgknotenC hknoten2 (CAUSE, KnotenNrl, NodeTextl, Bemerkungl ) ; pos2 = insert (hknoten2) ; verbιndeEcken(posOR_D2,pos2,0) ;
SliceC: :Nachfolger: :ιterator BEGIN2 = Sl [helpNrl] .second.beginl ) ; SliceC: :Nachfolger: : iterator END2 = Sl [helpNrl] .second. end () ; while (BEGIN2 != END2 ) ( helpNr2 = BEGIN2->first; if ( (BEGIN2->second -= DFK) SS (Sl [helpNr2] .first. getKnotenNummer ( ) '= KnotenNrD2)) ( //SliceC: :ιterator SLNODE1 = definelterator (Sl, KnotenNrl ) ;
//buιldIn_D2_Part ( Sl ,posOR, SLPUSE, SLNODE1 , KnotenNrD2 ) ;
}
BEGIN2++;
} BEGIN1++;
}
SliceC: :ιterator USEmD2 = fmd_Dl_Node (Sl, SLPUSE, SLNODE); SliceC: :ιterator HELP = USEιnD2; if (USEιnD2->fιrst. getLevel! ) > SLPUSE->fιrst. getLevel () ) ( USEιnD2KnotenNr = USEmD2->fιrst. getKnotenNummer () ; KnotenNrD2Ret = fmdD2Node (Sl, USEιnD2); if (KnotenNrD2Ret == USEιnD2KnotenNr) ( switch (USEιnD2->first. getKFGNodeType! ) ) ( case IFC:
HELP = fιnd_Dl_Node(Sl,USEιnD2, SLNODE); //ret = buildlnIfTreelSl, UΞEιnD2, HELP, posOR); ret = buιldD2InIfTree (Ξl,USEιnD2,HELP,posOR_D2) ; break; case LC:
HELP = f ιnd_Dl_Node ( Sl , USEιnD2 , SLNODE ) ; buildInLoopTree ( Sl , posOR_D2 , USEιnD2 , SLNODE ) ; break; default : cout « "Uups ! ! ' " « endl ; } )
}
int uwggraphC: :fιndD2Node (SliceC S Sl, SliceC: :ιterator PUSE) ( int dummy = 0; int helpNrl = 0; int helpNr2 = 0; int KnotenNrReturn - PUSE->first. getKnotenNummer () ; mt PUSEKnotenNr = PUSE->first .getKnotenNummer I) ; SliceC: :Nachfolger: :ιterator BEGIN1 = PUSE->second.begιn ( ) ; SliceC: :Nachfolger: :ιterator END1 = PUSE->second. end ( ) ; while ( (BEGIN1 '= END1 ) SS (dummy '= 1)1 ( lf (BEGINl->second == DFK) { helpNrl = BEGINl->first;
SliceC: :Nachfolger: :ιterator BEGIN2 = Sl [helpNrl] .second.begin! ) ; SliceC: :Nachfolger: : iterator END2 = Sl [helpNrl] . second. end( ) ; while ( (BEGIN2 != END2) SS (dummy != 1)){ if (BEGIN2->second == KFK) ( helpNr2 = BEGIN2->fιrst; lf (Sl[helpNr2) .first. getKnotenNummer ( ) — PUSEKno- tenNr) (
KnotenNrReturn = Sl lhelpNr2] . first. getKnotenNummer I ) ; dummy - 1 ;
} } BEGIN2++;
}
)
BEGIN1++; ) return KnotenNrReturn;
int uwggraphC: :buildIn_LoopKF_ANDPart (SliceC S Sl, int posANDJCF, SliceC: :ιterator SLPUSE) t pos = 0; int helpNrl = 0; int helpNr2 = 0; int RefPUse = 0; int KnotenNr = O.mt LineNr = 0; t dummy = 0; int dummyl = 0; char Bemerkung [1000] ; char NodeText [128); RefPUse = SLPUSE->first. getKnotenNummer () ;
SliceC: :Nachfolger: :ιterator BEGIN « SLPUSE->second.begιn() ; SliceC: :Nachfolger:: iterator END = SLPUSE->second.end ( ) ; while ((BEGIN != END) SS (dummyl != 1)) ( if (BEGIN->second == DFK) ( helpNrl = BEGIN->first;
ΞliceC: :Nachfolger: : iterator BEGIN2 = Sl [helpNrl ] .second. beginl) ; ΞliceC: :Nachfolger: :ιterator END2 = Sl [helpNrl ] .second. end () ; while ((BEGIN2 != END2 ) SS (dummy != 1)) ( if (BEGIN2->second «« KFK) ( helpNr2 = BEGIN2->first; lf (Sl [helpNr2] .first. getKnotenNummer ( ) == RefPUse) ( KnotenNr = Sl [helpNrl] . firs .getKnotenNummer () ; LineNr = Sl [helpNrl] . first .getLineNr () ; sprintf (NodeText, "Op%d", KnotenNr) ; //sprintf (Bemerkung, "Line %d", LineNr) ; strcpylBemerkung, Sl [helpNrl] . first. getCodeLine ( ) ) ; uwgknotenC hkno- ten |CAUSE, KnotenNr, NodeText, Bemerkung) ; pos = insert (hknoten) ; verbindeEcken (posAND_KF, pos, 0) ; dummy = 1; dummyl = 1;
BEGIN2++;
}
BEGIN++; return KnotenNr;
void uwggraphC: :buιldIn_LoopKF_ORPart (SliceC S Sl, t po≤LOOPJCF, ΞliceC: : iterator SLl, t KnotenNrD2) { int posl = 0; int pos2 = 0; int helpNrl = 0; t helpNr2 = 0; int KnotenNr = 0; int KnotenNrl = 0; int LineNr = 0;
int LineNrl = 0; char NodeText [128] ; char Bemerkung [ 1000] ;
KnotenNr = SLl->fιrst. getKnotenNummer I ) ; LineNr = SLl->first .getLineNr I ) ; sprintf (NodeText, "Op%d", KnotenNr) ; //sprintf (Bemerkung, "Line %d", LineNr) ; strcpylBemerkung, SLl->first. getCodeLine! ) ) ; uwgknotenC hknotenl (CAUSE, KnotenNr, NodeText, Bemerkung) ; posl » insert (hknotenl ) ; verbindeEcken (posLOOPJCF,posl, 0) ;
SliceC: :Nachfolger:: iterator BEGIN = SLl->second.begin() ; SliceC: :Nachfolger: : iterator END - SLl->second.end ( ) ; while (BEGIN '= END) ( lf (BEGIN->second == DFK) ( helpNrl = BEGIN->fιrst;
KnotenNrl = Sl [helpNrl] . first. getKnotenNummer () ; lf (KnotenNrl '= KnotenNrD2) (
LineNrl = Sl [helpNrl] . first. getLineNr I ) ; sprintf (NodeText, "Op%d" , KnotenNrl ) ;
//sprintf (Bemerkung, "Line %d", ineNrl) ; strcpy(Bemerkung,SLl->fιrst. getCodeLine ( ) ) ; uwgknotenC hknotenl (CAUSE, KnotenNrl, NodeText, Bemerkung) ; posl = insert (hknotenl ) ; verbindeEcken (posLOOPJCF,posl, 0) ; j
SliceC: : iterator NEXTNODE = definelterator (Sl, KnotenNrl ) ; SliceC: :Nachfolger: : iterator BEGIN2 = NEXTNODE->second.begιn () ; ΞliceC: :Nachfolger: : iterator END2 = NEXTNODE->second.end( ) ; while (BEGIN2 '= END2) ( lf (BEGIN2->second == DFK) ( helpNr2 = BEGIN2->first; if (NEXTNODE->first. getKnotenNummer! ) '= KnotenNrD2) ( buιldIn_LoopKF_ORPart(Sl, posLOOPJCF, NEXTNODE, KnotenNrD2);
BEGIN2++;
BEGIN++;
void uwggraphC: : addAllDlNodes (SliceC s Sl, SliceC: : iterator SLNODE, t posGatter, int D2_RefNr) (
int checkNr = 1; int helpNrl = 0; mt helpNr2 = 0; int SlιceNr2 = 0; int KnotenNrO = 0; int KnotenNrl = 0; int KnotenNr2 = 0; int LineNrl = 0; int LineNrO = 0; char Bemerkungl [1000] ; char NodeTextl [128];
KnotenNrO = SLNODE->flrst .getKnotenNummer () ; LineNrO = SLNODE->fιrst. getLineNr () ; sprintf (NodeTextl , "Op%d" , KnotenNrO ) ; //sprintf (Bemerkungl, "Line %d", LineNrO) ; strcpy(Bemerkungl,SLNODE->fιrst. etCodeLine ( ) ) ; uwgknotenC hknotenl (CAUSE, KnotenNrO, NodeTextl, Bemerkungl ) ; posl = insert (hknotenl ) ; verbindeEcken (posGatter, posl, 0) ;
SliceC: .-Nachfolger: :ιterator BEGIN1 = SLNODE->second. beginl ) ; ΞliceC: :Nachfolger: :ιterator END1 = SLNODE->second.end ( ) ; while (BEGIN1 '= END1 ) ( lf (BEGINl->second == DFK) ( helpNrl = BEGINl->first;
KnotenNrl = Ξl [helpNrl ]. firs .getKnotenNummer I ) ; SLNODE = definelterator (Ξl, KnotenNrl ) ; lf ((KnotenNrl '= D2_RefNr) SS (KnotenNrl '= KnotenNrO)) { ΞliceC: :Nachfolger: : iterator BEGIN2 = Ξl [helpNrl ] . second.begin ( ) ;
SliceC: :Nachfolger: :ιterator END2 = Sl (helpNrl] .second. end () ; hile (BEGIN2 != END2 ) ( lf (BEGIN2->second == KFK) { helpNr2 = BEGIN2->fιrst;
SlιceNr2 = Sl [helpNr2] . first .getKnotenNummer () ;
SliceC: : iterator HELPPUSE = definelteratorlSl,
SlιceNr2) ; checkNr = checkUWGNode (SlιceNr2) ; if (checkNr == 0) ( ΞliceC: : iterator HELP1 = findOutmostPU- se(Sl, HELPPUSE); switch (HELPl->fιrst. getKFGNodeType! ) 1 case LC: buildInLoopTree (Sl, posGatter,
HELPPUSE, SLNODE) ; break; case IFC: ret = buildlnlf-
Tree l Ξl, HELPPUSE, SLNODE, posGatter ) ; break; default: cout « "Falscher Weg' " « endl; }
} )
BEGIN2++; } if (checkNr == 1 ) (
LineNrl = Sl [helpNrl] . first. getLineNr O ; sprintf (NodeTextl, "Op%d", KnotenNrl) ;
//sprintf (Bemerkungl, "Line %d", LineNrl) ; strcpylBemerkungl, Sl [helpNrl] . first .getCodeLine! ) ) ; uwgknotenC hkno- ten2 (CAUSE, KnotenNrl, NodeTextl, Bemerkungl) ; posl = insert (hknoten2) ; verbindeEcken (posGatter, posl, 0) ; addAllDlNodes (Sl, SLNODE,posGatter, D2 RefNr) ; }
} }
BEGIN1++; , ' mt uwggraphC: :buιldD2InIfTree (ΞliceC S Ξl, ΞliceC: : iterator SLIF, ΞliceC: : iterator SLORIG, int posl) ( mt pos2 = 0; int posIFOR = 0; int posIFDFOR = 0; int posIFKFOR = 0; mt posIFDFORAΣ = 0; char NodeText [128]; char Bemerkung [ 1000] ; int KnotenNr = SLIF->first. getKnotenNummer () ; int LineNr = SLIF->first .getLineNr () ; sprintf (NodeText, "Verzweιgung_D+ (%d) "»KnotenNr) ; strcpy(Bemerkung,SLIF->flrst. getCodeLine ( ) ) ; uwgknotenC hknotenl (OR, NodeText, Bemerkung) ; pos2 = insert (hknotenl ) ; posIFOR = sizeO - 1; verbindeEcken (posl, pos2,0); sprintf (NodeText, "Verzweιgung_KF_D+ (%d) ", LineNr) ; uwgknotenC hknotenδ ( OR, NodeText ) ; posIFKFOR = insert (hknotenδ) ; verbindeEcken (pos2, posIFKFOR, 0) ; buιldD2_IFKF_Part(Sl, posIFKFOR, SLIF); switch (ΞLORIG->fιrst.getKnotenIdent( ) ) ( case THEN: ( sprintf (NodeText, "Verzweιgung_DF_Alt .1_D+ ( %d ) " , LineNr ) ; uwgknotenC hknoten2 (AND, NodeTex ) ; insert (hknotenl,hknoten2, 0) ; sprintf ( Bemerkung, "Al .1_D+ ( %d ) " , LineNr ) ; sprintf (NodeText, "Alt .1_D+ I %d ) " , LineNr ) ; uwgknotenC hknoten3 (CAUΞE, NodeText, Bemerkung) ;
insert (hknoten2,hknoten3, 0) ; sprintf (NodeText, "Alt .1_D+ ( % ) " , LineNr ) ; uwgknotenC hknoten4 ( OR, NodeText ) ; insert (hknoten2,hknoten , 0) ; posIFDFOR - sizeO - 1; buildD2_Al_Part(Sl, posIFDFOR, SLIF, SLORIG);
} break; case ELSE: sprintf (NodeText, "Verzweιgung_DF_Alt.2_D+ (%d) ", LineNr) ; uwgknotenC hknoten2 (AND, NodeText) ; insert (hknotenl, hknoten2,0) ; sprintf (Bemerkung, "Alt .2_D+ ( %d) " , ineNrl ; sprintf (NodeText, "AIt .2_D+ ( %d ) " , LineNr ) ; uwgknotenC hknoten3(CAUSE,NodeText, Bemerkung) ; insert (hknoten2,hknoten3, 0) ; sprintf (NodeText, "Alt .2_D+ ( %d ) " , LineNr ) ; uwgknotenC hknoten4 (OR, NodeText ) ; insert (hknoten2,hknoten4, 0) ; posIFDFORA2 = sizeO - 1; buildD2_Al_Part(Sl, posIFDFORA2, SLIF, SLORIG);
} break; default: cout « "Autsch'!'" « endl; return posIFDFOR;
void uwggraphC: :buιldD2_Al_Part( SliceC S Sl, int posIFDFOR_D2, SliceC: : iterator SLIF, SliceC: : iterator SLNODE) (~ mt pos0_Al = 0 int posl_Al = 0 int helpNrO = 0 int helpNrl = 0 int KnotenNrO » 0 int KnotenNrl = 0 int KnotenNr2 = 0 int LineNrO = 0; int LineNrl = 0; char NodeTextO[128] ; char BemerkungO [ 1000] ; KnotenNrO = SLNODE->first. getKnotenNummer () ;
LineNrO - SLNODE->first. getLineNr () ; sprintf (NodeTextO, "Op%d" , KnotenNrO ) ; //sprintf (BemerkungO, "Line %d", LineNrO) ; strcpy(Bemerkung0,ΞLNODE->fιrst. getCodeLine! ) ) ; uwgknotenC hknotenO (CAUΞE, KnotenNrO, NodeTextO, BemerkungO) ; pos0_Al = insert (hknotenO) ; verbmdeEcken(posIFDFOR_D2,posO_Al, 0) ;
SliceC: :Nachfolger: :ιterator BEGIN0 = SLNODE->second.beginl ) ; SliceC: :Nachfolger: :ιterator END0 = SLNODE->second.end( ) ; while (BEGIN0 != END0) ( helpNrO = BEGIN0->fιrst;
KnotenNrl = Sl [helpNrO] . first. getKnotenNummer () ; if (KnotenNrl > KnotenNrO) (
LineNrl = Sl [helpNrO] . first .getLineNr () ; sprintf (NodeTextO, "Op%d", KnotenNrl) ;
//sprintf (BemerkungO, "Line %d", LineNrl ) ; strcpy (BemerkungO, Sl [helpNr0] .first .getCodeLine ( ) ) ; uwgknotenC hknotenl (CAUSE, KnotenNrl, NodeTextO, BemerkungO) ; posl_Al = insert (hknotenl ) ; verbmdeEcken(posIFDFOR_D2,posl_Al,0) ;
SliceC: :Nachfolger: :ιterator BEGIN1 = Sl [helpNrO] .second.beginl ) ; ΞliceC: :Nachfolger: :ιterator END1 = Ξl [helpNrO] .second. endl ) ; while (BEGIN1 != END1 ) ( if (BEGINl->second == DFK) ( helpNrl = BEGINl->first;
KnotenNr2 = Sl [helpNrl ). first .getKnotenNummer () ; if (KnotenNrl '= KnotenNr2) (
ΞliceC: : iterator SLNODE = definelterattoorrl(SSll,.KKnnootteennNNrr22)) : buιldD2_Al_Part (Ξl, posIFDFOR_D2, SLIF,
SLNODE ) ;
BEGIN1++;
} BEGIN0++;
void uwggraphC: :buιldD2_IFKF_Part (ΞliceC S Sl, int posKFOR_D2, SliceC: : iterator ΞLPUSE) ( int posO_D2 = 0; int posl_D2 = 0; int ret - 0; mt dummy = 0; int helpNrO = 0; int helpNrl = int helpNr2 -= int checkPUse = 0 mt checkNode = 0 int KnotenNrO = 0 int KnotenNrl = 0 int KnotenNr2 = 0 int KnotenNr3 = 0 int LineNrO = 0; int LineNrl = 0; char NodeTextO [128]; char BemerkungO(lOOO) ;
KnotenNrO = ΞLPUSE->fιrst .getKnotenNummer () ; LineNrO = SLPUSE->fιrst. getLineNr () ; sprintf (NodeTextO, "Op%d", KnotenNrO) ; //sprintf (BemerkungO, "Line %d", LineNrO) ; strcpy(BemerkungO,SLPUSE->fιrst. getCodeLine) ) ) ; uwgknotenC hknotenO (CAUSE, KnotenNrO, NodeTextO, BemerkungO) ; posO_D2 = insert (hknotenO) ; verbindeEcken (posKFOR_D2,posO_D2, 0) ;
SliceC: :Nachfolger: :ιterator BEGIN0 = SLPUΞE->second.begιn ( ) ; ΞliceC: :Nachfolger: : iterator END0 = SLPUSE->second.end ( ) ; while (BEGIN0 '= END0) ( helpNrO = BEGIN0->fιrst;
KnotenNrl = Sl (helpNrO] . first .getKnotenNummer I ) ; SliceC: :ιterator SLNODE = definelterator (Sl, KnotenNrl ) ; lf (KnotenNrl > KnotenNrO) (
LineNrl = Ξl [helpNrO] . first. getLineNr () ; sprintf (NodeTextO, "Op%d" , KnotenNrl ) ;
//sprintf (BemerkungO, "Line %d", LineNrl) ; strcpy(BemerkungO,Ξl IhelpNrO] . first. getCodeLine ( ) ) ; uwgknotenC hknotenl (CAUΞE, KnotenNrl, NodeTextO, BemerkungO) ; posl_D2 = insert (hknotenl ) ; verbindeEcken (posKFOR_D2,posl_D2, 0) ;
ΞliceC: :Nachfolger: :ιterator BEGIN1 = SLNODE->second.begm ( ) ;
SliceC: :Nachfolger: :ιterator END1 ΞLNODE->second. end ( ) ; while (BEGIN1 != END1 ) { lf (BEGINl->second «= DFK) ( helpNrl = BEGINl->fιrst;
KnotenNrΣ = Sl [helpNrl] . first. getKnotenNummer O ; lf (KnotenNr2 '= KnotenNrl) (
SliceC: : iterator SLNODE = defmeltera- tor (Sl,KnotenNr2);
ΞliceC: :Nachfolger: :ιterator BEGIN2 =
Sl [helpNrl] . second.beginl ) ;
ΞliceC: :Nachfolger: :ιterator END2 =
Sl [helpNrl] .second. end ( ) ; while (BEGIN2 '= END2) ( lf (BEGIN2->second == KFK) ( helpNr2 = BEGIN2->first; KnotenNr3 =
Sl [helpNr2] . first .getKnotenNummer ( ) ;
SliceC: : iterator HELPPUSE = definelterator (Sl,KnotenNr3) ; if (SLPUSE- >first. getKnotenNumme ( ) > KnotenNr3) checkPUse = checkPU- sesl ( Ξl , ΞLPUSE, HELPPUSE ) ; eise { checkPUse = checkPU- ses2 (Sl, ΞLPUSE, HELPPUSE ) ;
checkNode = checkU-
WGNode I KnotenNr2 ) ; lf (checkNode == 0) { if (checkPUse == 0) (
//HELPPUSE = fin- dOutmostPUse (Ξl, HELPPUSE ) ; switch (HELPPUSE- >first. getKFGNodeType () ) ( case LC: buildInLoopTree (Sl, posKFOR_D2, HELPPUΞE, ΞLNODE); dummy - 1; break; case IFC: ret - buildlnIfTreelSl, HELPPUSE, SLNODE, posKFOR D2 ) ; dummy = 1; break; default:
"Falscher Weg in AI ! " « endl; eise (
LineNrl =
Ξl[helpNr2] . first. getLineNr () ; sprintf (NodeTextO, "Op%d", KnotenNr2 ) ;
//sprintf (BemerkungO, "Line %d", LineNrl ) ; strcpy!BemerkungO, l [helpNr2] . first .getCodeLine ( ) ) ; uwgknotenC hkno- tenl (CAUSE, KnotenNr2, NodeTextO, BemerkungO) ; posl D2 = insert (hknotenl ) ; verbindeEcken (posKFOR D2,posl D2,0);
BEGIN2++;
) BEGIN1++;
BEGIN0++ ;
SliceC: : iterator uwggraphC: : findOutmostPUse (SliceC s Sl, ΞliceC: : iterator ΞLPUΞE) ( int dummy = 0; int helpNrl = 0; mt checkNr = 0; int KnotenNrl = 0; SliceC:: iterator RETURN = SLPUSE;
SliceC: :Nachfolger: :ιterator BEGIN1 = SLPUΞE->second.beginl ) ; ΞliceC: :Nachfolger: :ιterator END1 = SLPUSE->second.end ( ) ; while ÜBEGIN1 != END1 ) SS (dummy '= 1))( lf (BEGINl->second == KFK) ( helpNrl = BEGINl->first;
KnotenNrl = Ξl [helpNrl ]. first .getKnotenNummer () ; checkNr = checkUWGNode (KnotenNrl ) ; lf (checkNr == 0) (
ΞLPUSE = definelterator (Ξl, KnotenNrl); RETURN = findOutmostPUse (Ξl, ΞLPUΞE); dummy = 1; eise
RETURN = ΞLPUΞE; dummy = 1;
BEGINH
return RETURN;
int uwggraphC: : checkUWGNode(int SliceNr) ( int dummy = 0; uwggraphC: : iterator ITER = beginl); while (ITER '= endO) ( if ( (»ITER) .first. getCauseNrl ) == SliceNr) ( dummy = 1;
) ITER++;
} lf (dummy ■== 1 ) return 1; eise return 0; )
ΞliceC: :ιterator uwggraphC: :definelterator (ΞliceC S Ξl, mt SliceNr) ( int dummy = 0;
SliceC: : iterator ITER = Sl.beginO; SliceC: :ιterator HELP = Sl.beginO; while ((ITER '= Sl.endO) SS (dummy != 1)) ( lf ( («ITER) .first.getKnotenNummer ( ) == SliceNr) ( HELP = ITER; dummy = 1; } ITER++;
} return HELP; }
void S Ξl ) (
ostream_ιterator<KFGLιstNodeC> POSITIZiel, "Knoten\n"); ostream_ιterator<KFGLιstNodeC> POSIT2(Zιel, " Nachfolger: "); ostream_ιterator<GraphKanteC> KANTEIT (Ziel, "\n"); Ziel « "SLICE:" « endl « endl; for (int l = 0; l < Sl.sizeO; ++ι) ( Ziel « Sl[ι]. first « " <";
SliceC: :Nachfolger: :ιterator IT = Sl [l] .second. beginl ) ; SliceC: :Nachfolger: :ιterator ITEND = Sl [l ] .second. end () ; while (IT != ITEND) (
Ziel « Ξl[ («IT) .first] .first « ' ' // Ecke « endl « "Kante:" « («IT). second « ' '; // Kantenwert
++IT;
Ziel « ">\n";
„ include "uwgkante . h" D ffinclude <ιostream> D
D ostreamS Operator << ( ostreamS os, const uwgkanteCS Node)| D os « Node.Number << endl ; return os;
ffinclude "uwgknoten.h"
D ftmclude <iostream>
D
D ostreamS Operator « ( ostreamS os, eonst uwgknotenCS Node)(
//os « Node. Gatterldent « " " « Node. CauseNr « " " « Node. gattertext « endl //return os; lf (Node.getNodeldentl ) == EFFECT) ( os « "%%EFFECT:\"" « Node .gatterbemerkung « »\» :\»» « Node. gattertext « "\"," « Node.Gatterldent « " , , 10; " « endl; return os; ) eise lf (Node.getNodeldentl) == OR) ( os « "%%OR:l:\"" « Node. gattertext << "\": \"keme\", " « Node. Gatterldent « ", , 10; " « endl; return os; } eise lf (Node.getNodeldentl) == AND) ( os « "%%AND:\"" « Node. gattertext « "\":\"keine\", " « Node. Gatterldent « " , , 10; " « endl; return os; } eise lf (Node.getNodeldentl) == NOT) ( os « "%%NOT:\"" « Node. gattertext « "\" : \"keιne\", " « Node. Gatterldent « " , , 10; " « endl; return os; }
/«eise if (Node.getNodeldentl) == CAUΞE) ( os « "%%CAUSE:\"" « Node. gattertext « "\":\"keme\", " « Node. Gatterldent « ", , 10; " « endl; return os; }«/ eise lf (Node.getNodeldentl) == CAUSE) { os « "%%CAUSE:\"" « Node. gatterbemerkung « "\» :\»» « Node. gattertext « "\"," « Node. Gatterldent « " , , 10; " « endl; return os; } eise ( os « Node.Gatterldent « " " « Node. CauseNr « " " « Node. attertext « endl ; return os; }
} int uwgknotenC: : DummyNr = 1;
In diesem Dokument sind folgende Veröffentlichungen zitiert:
[1] N. Leveson, Safety Verification of ADA Programs using Software fault trees, IEEE Software, Seite 48 bis 59, Juli 1991
[2] Weiser M., Program Slicing, in: IEEE Transaction on Software Engineering, Vol. 10, No. 4 , July 1984, pp. 352-357
[3] Liggesmeyer P., Modultest und ModulVerifikation - State of the Art, Mannheim, Wien, Zürich: BI Wissenschaftsverlag 1990
[4] DIN 25424-1: Fehlerbaumanalysen; Methoden und Bildzei- chen, September 1981
[5] DIN 25424-2: Fehlerbaumanalyse; Handrechenverfahren zur Auswertung eines Fehlerbaums, Berlin, Beuth Verlag GmbH, April 1990
Claims
1. Verfahren zur Ermittlung einer Gesamtfehlerbeschreibung zumindest eines Teils eines Computerprogramms, durch einen Computer,
• bei dem zumindest der Teil des Computerprogramms gespeichert ist,
• bei dem eine Kontrollflußbeschreibung und eine Datenflußbeschreibung für den Teil des Computerprogramms ermittelt werden,
• bei dem Programmelemente aus dem Teil des Computerprogramms ausgewählt werden,
• bei dem für jedes ausgewählte Programmelement unter Verwendung einer gespeicherten Fehlerbeschreibung, die jeweils einem Referenzelement zugeordnet ist, eine Elementenfehlerbeschreibung ermittelt wird, mit der mögliche Fehler des jeweiligen Programmelements beschrieben werden,
• bei dem mit einer Fehlerbeschreibung eines Referenzelements mögliche Fehler des jeweiligen Referenzelements beschrieben werden, und
• bei dem aus den Elementenfehlerbeschreibungen die Gesamtfehlerbeschreibung unter Berücksichtigung der Kontrollflußbeschreibung und der Datenflußbeschreibung ermittelt wird.
2. Verfahren nach Anspruch 1, bei dem die Kontrollflußbeschreibung in Form eines Kontrollflußgraphen vorliegt.
3. Verfahren nach Anspruch 1 oder 2, bei dem die Datenflußbeschreibung in Form eines Datenflußgra- phen vorliegt.
4. Verfahren nach einem der vorangegangenen Ansprüche, • bei dem die Fehlerbeschreibung in Form eines gespeicherten Fehlerbaums vorliegt, • bei dem die Elementenfehlerbeschreibung als Elementenfehlerbaum ermittelt wird, und
• bei dem die Gesamtfehlerbeschreibung als Gesamtfehlerbaum ermittelt wird.
5. Verfahren nach einem der vorangegangenen Ansprüche, eingesetzt zur Fehleranalyse des Teils des Computerprogramms.
6. Verfahren nach einem der vorangegangenen Ansprüche, • bei dem die Gesamtfehlerbeschreibung als Gesamtfehlerbaum ermittelt wird,
• bei dem der Gesamtfehlerbaum verändert wird hinsichtlich vorgebbarer Rahmenbedingungen.
7. Verfahren nach Anspruch 6, bei dem die Veränderung durch Hinzufügen eines Ergänzungsfehlerbaums erfolgt.
8. Anordnung zur Ermittlung einer Gesamtfehlerbeschreibung zumindest eines Teils eines Computerprogramms, durch einen Computer, mit einem Prozessor, der derart eingerichtet ist, daß folgende Schritte durchführbar sind:
• zumindest der Teil des Computerprogramms ist gespeichert, • eine Kontrollflußbeschreibung und eine Datenflußbeschreibung werden für den Teil des Computerprogramms ermittelt,
• Programmelemente werden aus dem Teil des Computerprogramms ausgewählt,
• für jedes ausgewählte Programmelement wird unter Verwendung einer gespeicherten Fehlerbeschreibung, die jeweils einem
Referenzelement zugeordnet ist, eine Elementenfehlerbeschreibung ermittelt, mit der mögliche Fehler des jeweiligen Programmelements beschrieben werden,
• mit einer Fehlerbeschreibung eines Referenzelements werden mögliche Fehler des jeweiligen Referenzelements beschrieben, und • aus den Elementenfehlerbeschreibungen wird die Gesamtfehlerbeschreibung unter Berücksichtigung der Kontrollflußbeschreibung und der Datenflußbeschreibung ermittelt.
9. Anordnung nach Anspruch 8, bei der der Prozessor derart eingerichtet ist, daß die Kontrollflußbeschreibung in Form eines Kontrollflußgraphen vorliegt.
10. Anordnung nach Anspruch 8 oder 9, bei der der Prozessor derart eingerichtet ist, daß die Datenflußbeschreibung in Form eines Datenflußgraphen vorliegt.
11. Anordnung nach einem der Ansprüche 8 bis 10, bei der der Prozessor derart eingerichtet ist, daß
• die Fehlerbeschreibung in Form eines gespeicherten Fehlerbaums vorliegt,
• die Elementenfehlerbeschreibung als Elementenfehlerbaum ermittelt wird, und • die Gesamtfehlerbeschreibung als Gesamtfehlerbaum ermittelt wird.
12. Anordnung nach einem der Ansprüche 8 bis 11, eingesetzt zur Fehleranalyse des Teils des Computerprogramms.
13. Anordnung nach einem der Ansprüche 8 bis 12, bei der der Prozessor derart eingerichtet ist, daß
• die Gesamtfehlerbeschreibung als Gesamtfehlerbaum ermittelt wird, • der Gesamtfehlerbaum verändert wird hinsichtlich vorgebbarer Rahmenbedingungen.
14. Anordnung nach Anspruch 13, bei der der Prozessor derart eingerichtet ist, daß die Verän- derung durch Hinzufügen eines Ergänzungsfehlerbaums erfolgt.
15. Computerprogramm-Erzeugnis, das ein computerlesbares Speichermedium umfaßt, auf dem ein Programm gespeichert ist, das es einem Computer ermöglicht, nachdem es in einen Speicher des Computers geladen worden ist, folgende Schritte durchzuführen zur Ermittlung einer Gesamtfehlerbeschreibung zumindest eines Teils eines Computerprogramms:
• zumindest der Teil des Computerprogramms ist gespeichert,
• eine Kontrollflußbeschreibung und eine Datenflußbeschreibung werden für den Teil des Computerprogramms ermittelt, • Programmelemente werden aus dem Teil des Computerprogramms ausgewählt,
• für jedes ausgewählte Programmelement wird unter Verwendung einer gespeicherten Fehlerbeschreibung, die jeweils einem Referenzelement zugeordnet ist, eine Elementenfehlerbe- Schreibung ermittelt, mit der mögliche Fehler des jeweiligen Programmelements beschrieben werden,
• mit einer Fehlerbeschreibung eines Referenzelements werden mögliche Fehler des jeweiligen Referenzelements beschrieben, und • aus den Elementenfehlerbeschreibungen wird die Gesamtfehlerbeschreibung unter Berücksichtigung der Kontrollflußbeschreibung und der Datenflußbeschreibung ermittelt.
16. Computerlesbares Speichermedium, auf dem ein Programm ge- speichert ist, das es einem Computer ermöglicht, nachdem es in einen Speicher des Computers geladen worden ist, folgende Schritte durchzuführen zur Ermittlung einer Gesamtfehlerbeschreibung zumindest eines Teils eines Computerprogramms:
• zumindest der Teil des Computerprogramms ist gespeichert, • eine Kontrollflußbeschreibung und eine Datenflußbeschreibung werden für den Teil des Computerprogramms ermittelt,
• Programmelemente werden aus dem Teil des Computerprogramms ausgewählt,
• für jedes ausgewählte Programmelement wird unter Verwendung einer gespeicherten Fehlerbeschreibung, die jeweils einem
Referenzelement zugeordnet ist, eine Elementenfehlerbe- Schreibung ermittelt, mit der mögliche Fehler des jeweiligen Programmelements beschrieben werden, mit einer Fehlerbeschreibung eines Referenzelements werden mögliche Fehler des jeweiligen Referenzelements beschrieben, und aus den Elementenfehlerbeschreibungen wird die Gesamtfehlerbeschreibung unter Berücksichtigung der Kontrollflußbeschreibung und der Datenflußbeschreibung ermittelt.
Applications Claiming Priority (3)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
DE19925239 | 1999-06-02 | ||
DE19925239 | 1999-06-02 | ||
PCT/DE2000/001001 WO2000075780A1 (de) | 1999-06-02 | 2000-04-03 | Verfahren und anordnung zur ermittlung einer gesamtfehlerbeschreibung zumindest eines teils eines computerprogramms sowie computerprogramm-erzeugnis und computerlesbares speichermedium |
Publications (1)
Publication Number | Publication Date |
---|---|
EP1200894A1 true EP1200894A1 (de) | 2002-05-02 |
Family
ID=7909989
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
EP00929272A Withdrawn EP1200894A1 (de) | 1999-06-02 | 2000-04-03 | Verfahren und anordnung zur ermittlung einer gesamtfehlerbeschreibung zumindest eines teils eines computerprogramms sowie computerprogramm-erzeugnis und computerlesbares speichermedium |
Country Status (3)
Country | Link |
---|---|
US (1) | US7047523B1 (de) |
EP (1) | EP1200894A1 (de) |
WO (1) | WO2000075780A1 (de) |
Families Citing this family (7)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
DE50213782D1 (de) * | 2001-02-20 | 2009-10-01 | Siemens Ag | Verfahren und anordnung zur ermittlung einer gesamtfehlerbeschreibung zumindest eines teils eines technischen systems, computer programm-element und computerlesbares speichermedium |
JP2006113934A (ja) * | 2004-10-18 | 2006-04-27 | Hitachi Ltd | プログラム開発支援装置、プログラム開発支援方法およびプログラム |
US7563542B2 (en) * | 2005-10-05 | 2009-07-21 | California Institute Of Technology | Subfluorinated graphite fluorides as electrode materials |
US7685471B2 (en) * | 2007-02-01 | 2010-03-23 | Fujitsu Limited | System and method for detecting software defects |
CN100461132C (zh) * | 2007-03-02 | 2009-02-11 | 北京邮电大学 | 基于源代码静态分析的软件安全代码分析器及其检测方法 |
US9189318B2 (en) * | 2013-05-15 | 2015-11-17 | Oracle International Corporation | Path-sensitive analysis framework for bug checking |
US11036866B2 (en) | 2018-10-18 | 2021-06-15 | Denso Corporation | Systems and methods for optimizing control flow graphs for functional safety using fault tree analysis |
Family Cites Families (5)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
US5740357A (en) * | 1990-04-26 | 1998-04-14 | Digital Equipment Corporation | Generic fault management of a computer system |
US5586252A (en) * | 1994-05-24 | 1996-12-17 | International Business Machines Corporation | System for failure mode and effects analysis |
US5500941A (en) * | 1994-07-06 | 1996-03-19 | Ericsson, S.A. | Optimum functional test method to determine the quality of a software system embedded in a large electronic system |
US5903453A (en) * | 1996-01-19 | 1999-05-11 | Texas Instruments Incorporated | Method for estimating software operation and performance using a goal-question-metric paradigm |
US6012152A (en) * | 1996-11-27 | 2000-01-04 | Telefonaktiebolaget Lm Ericsson (Publ) | Software fault management system |
-
2000
- 2000-04-03 WO PCT/DE2000/001001 patent/WO2000075780A1/de active Application Filing
- 2000-04-03 US US09/980,489 patent/US7047523B1/en not_active Expired - Fee Related
- 2000-04-03 EP EP00929272A patent/EP1200894A1/de not_active Withdrawn
Non-Patent Citations (1)
Title |
---|
See references of WO0075780A1 * |
Also Published As
Publication number | Publication date |
---|---|
WO2000075780A1 (de) | 2000-12-14 |
US7047523B1 (en) | 2006-05-16 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
DE69622219T2 (de) | Optimierungsgerät zum Entfernen von Gefahren durch Arrangierung der Befehlsreihenfolge | |
Sivaramakrishnan et al. | Declarative programming over eventually consistent data stores | |
Georgakopoulos et al. | Specification and management of extended transactions in a programmable transaction environment | |
DE69503065T2 (de) | Objektorientierte vorrichtung für konfigurationsverlaufsverwaltung | |
EP1764715B1 (de) | Verfahren zur Bestimmung der Güte einer Menge von Eigenschaften, verwendbar zur Verifikation and zur Spezifikation von Schaltungen | |
DE69626377T2 (de) | Vorrichtung, Verfahren, Speichermedium und computerlesbare Module zur raumeffizienten Objektverriegelung | |
Back et al. | Superposition refinement of reactive systems | |
DE112005002402T5 (de) | Hybride Hardware-/Software-Implementierung eines Transaktionsspeicherzugriffs | |
DE19926116A1 (de) | Mehr-Teilprozeß-Protokollierung in einer Konfigurationsdatenbank | |
DE69421346T2 (de) | Verklemmungsanalyseverfahren in einem Betriebssystem | |
DE102004058288A1 (de) | Vorrichtung und Verfahren zur Behebung von Fehlern bei einem Prozessor mit zwei Ausführungseinheiten | |
Dong et al. | Ensuring structure and behavior correctness in design composition | |
DE112013007083B4 (de) | Programmanalysevorrichtung, Programmanalyseverfahren und Programmanalyseprogramm | |
Aggarwal et al. | Software Design Metrics for Object-Oriented Software. | |
EP1200894A1 (de) | Verfahren und anordnung zur ermittlung einer gesamtfehlerbeschreibung zumindest eines teils eines computerprogramms sowie computerprogramm-erzeugnis und computerlesbares speichermedium | |
DE69128908T2 (de) | Verfahren zum Durchführen von erlässlichen Befehlen in einem Rechner | |
Frühwirth | Parallelizing union-find in Constraint Handling Rules using confluence analysis | |
DE112004002576T5 (de) | Management externer Speicheraktualisierung zur Fehlererfassung in redundanten Multithreading-Systemen unter Verwendung einer spekulativen Speicherunterstützung | |
Xu et al. | JMLAutoTest: A novel automated testing framework based on JML and JUnit | |
DE10038499A1 (de) | Verfahren und System für die verbesserte Entwicklungsprüfung mittels angepasster Ablaufverfolgung | |
DE69328664T2 (de) | Verfahren und Anordnung zur Zusammenbindung von Objekten | |
Lyu et al. | Software diversity metrics and measurements | |
DE102015102034A1 (de) | Verfahren zum Analysieren von Ergebnissen in einem Entwurfsautomatisierungsablauf für elektronische Systeme, Computersystem und Computerprogrammprodukt | |
Georgakopoulos et al. | An environment for the specification and management of extended transactions in DOMS | |
WO2005109196A1 (de) | Verfahren zur bestimmung von verklemmungen in nebenläufigen prozessen |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
PUAI | Public reference made under article 153(3) epc to a published international application that has entered the european phase |
Free format text: ORIGINAL CODE: 0009012 |
|
17P | Request for examination filed |
Effective date: 20011106 |
|
AK | Designated contracting states |
Kind code of ref document: A1 Designated state(s): AT BE CH CY DE DK ES FI FR GB GR IE IT LI LU MC NL PT SE |
|
RBV | Designated contracting states (corrected) |
Designated state(s): DE FR GB |
|
17Q | First examination report despatched |
Effective date: 20060627 |
|
GRAP | Despatch of communication of intention to grant a patent |
Free format text: ORIGINAL CODE: EPIDOSNIGR1 |
|
STAA | Information on the status of an ep patent application or granted ep patent |
Free format text: STATUS: THE APPLICATION IS DEEMED TO BE WITHDRAWN |
|
18D | Application deemed to be withdrawn |
Effective date: 20100817 |