Commit fb1caba6 authored by Andre Maroneze's avatar Andre Maroneze 💬

Merge branch 'doc/slicing-pdg' into 'master'

Doc/slicing pdg

See merge request frama-c/frama-c!2940
parents 59d0bcdb a1ace968
......@@ -19,6 +19,7 @@ prefix=framacbook@,
\DeclareVoidOption{web}{\PassOptionsToPackage{colorlinks,urlcolor=blue}{hyperref}}
\DeclareVoidOption{paper}{\PassOptionsToPackage{pdfborder=0 0 0}{hyperref}}
\DeclareStringOption[{version=4.0,modifier=by-sa}]{license}
\DeclareStringOption[english]{lang}
\DeclareDefaultOption{\PassOptionsToClass{\CurrentOption}{report}}
\PassOptionsToClass{a4paper,11pt,twoside,openright}{report}
......@@ -26,10 +27,13 @@ prefix=framacbook@,
\LoadClass{report}
\PassOptionsToPackage{\framacbook@lang}{babel}
\ifthenelse{\equal{\framacbook@license}{no}}{\useccfalse}{}
\ifusecc
\PassOptionsToPackage{\framacbook@license}{doclicense}
\fi
\RequirePackage{babel}
\RequirePackage{fullpage}
\RequirePackage{lmodern}
\RequirePackage[T1]{fontenc}
......
biblio.bib
frama-c-book.cls
frama-c-cover.pdf
frama-c-left.pdf
frama-c-right.pdf
main.pdf
.PHONY: all clean
all: main.pdf
GENERATED=biblio.bib
GENERATED+=frama-c-book.cls frama-c-cover.pdf frama-c-left.pdf frama-c-right.pdf
include ../MakeLaTeXModern
DWNLDDIR=../manuals
DOCNAME=pdg-documentation-fr.pdf
TEST_DIR=../../tests/pdg/
BIB_FILE = ../slicing/bib-slicing.bib
main.bbl : $(BIB_FILE)
@echo "=== Fichier .bib plus récent -> effacement du .bbl"
rm -f $(SRC).bbl
main.pdf: $(FRAMAC_MODERN) $(BIB_FILE) \
main.tex pdg.tex macros_pdg.tex \
intro.tex conclusion.tex \
data.tex ctrl.tex calls.tex utilisation.tex mark.tex impact.tex \
../images/cealistlogo.jpg \
exple-call.c call-f.pdf call-g.pdf \
ctrl-dpds.pdf ex-goto.pdf goto.pdf pdg-call.pdf
###############################################################################
GENERATED+=call-f.fig call-g.fig
%.fig : %.dot
dot -Tfig $< > $@
GENERATED+=call-f.pdf call-g.pdf
%.pdf : %.fig
fig2dev -L pdf $< $@
GENERATED+=call-f.dot call-g.dot
call-%.dot : $(TEST_DIR)/call.%.dot
cp $< $@
call-%.dot :
@echo
@echo "ERROR : $@ not found : you should run PDG tests to have it"
@echo " Run : cd ../.. ; make pdg_tests ; cd - "
@echo
exit 1
GENERATED+=exple-call.c
exple-%.c : $(TEST_DIR)/%.c
sed "1,/BDOC/d" $< > $@
###############################################################################
%.pdf: %.tex
pdflatex $*
bibtex $*
pdflatex $*
pdflatex $*
install: main.pdf
@echo "copying main.pdf in $(DWNLDDIR)/$(DOCNAME)"
@rm -f "$(DWNLDDIR)/$(DOCNAME)"
@cp main.pdf "$(DWNLDDIR)/$(DOCNAME)"
clean:
rm -rf *~ *.aux *.log *.nav *.out *.snm *.toc *.lof *.pp *.bnf \
*.haux *.hbbl *.htoc \
*.cb *.cb2 *.cm? *.bbl *.blg *.idx *.ind *.ilg \
$(GENERATED)
###############################################################################
\chapter{Dépendances interprocédurales}\label{sec-intro-call}
On a vu qu'un PDG est associé à une fonction.
La question se pose donc de savoir
comment calculer des dépendances interprocédurales, c'est-à-dire comment mettre
en relation les appels de fonctions et les dépendances des fonctions appelées.
Nous allons tout d'abord voir qu'un appel de fonction
est représenté par plusieurs éléments dans le PDG (\S\ref{sec-call}).
Puis, nous allons voir que pour mettre en relation des appels et les fonctions
appelées, ils faut ajouter d'autres éléments à chaque fonction
(\S\ref{sec-fct-inout}).
\section{Appels de fonction}\label{sec-call}
L'instruction contenant l'appel est représentée par plusieurs
éléments dans le graphe de dépendances
afin de pouvoir plus précisément mettre en relation les appels aux
fonctions appelées.
Les éléments créés sont les suivants~:
\begin{itemize}
\item un élément pour chaque paramètre de la fonction appelée;
les dépendances sont crées par une simulation
de l'affectation des arguments d'appel dans les paramètres formels,
\item un élément représentant le contrôle du point d'entrée de la fonction
appelée (un peu comme si l'appel était dans un bloc et que ce noeud
représentait ce bloc),
\item un élément pour chaque sortie, dépendant des entrées correspondantes.
\end{itemize}
Pour ne pas avoir à calculer les flots de données de toutes les fonctions de
l'application, il a été décidé d'utiliser les dépendances ({\it from})
calculées indépendamment par \ppc.
La liste des entrées et des sorties, ainsi que les dépendances entre les unes et
les autres sont extraites des spécifications des fonctions appelées, et non de
leur PDG\footnote{c'est peut-être un problème
si on fait de la coupure de branche, car les dépendances peuvent être réduites
par une telle spécialisation.}.
Ceci est vrai également pour les
fonctions dont le code est absent de l'application étudiée
car cela permet d'être cohérent avec les autres analyses.
Cela permettra en particulier, d'utiliser d'éventuelles propriétés
fournies par la suite par l'utilisateur.
\begin{exemple}
\begin{tabular}{m{0.35\textwidth} m{0.6\textwidth}}
\begin{verbatim}
struct {int a;
int b; } G;
/*@ assigns \result {a},
G.a {G, a} */
int g (int a);
int f (int x, int y) {
G.b = x;
x = g (x+y);
return x + G.b;
}
\end{verbatim}
&
Ici, pour représenter l'appel à \verbtt{g} dans \verbtt{f} dans le PDG,
on va avoir~:
\begin{itemize}
\item un élément représentant le point d'entrée dans \verbtt{g},
\item un élément $e_1$ pour représenter \verbtt{a = x+y},
c'est-à-dire l'affectation de l'argument de l'appel
dans le paramètre formel de \verbtt{g},
\item un élément $e_2$ pour calculer la valeur de retour de \verbtt{g},
qui dépend de la valeur de $e_1$
(utilisation de la spécification de $g$),
\item et enfin, un élément $e_3$ qui représente la seconde sortie de \verbtt{g}~:
\verbtt{G.a} qui dépend du paramètre \verbtt{a} et donc de $e_1$
et de des éléments $\{ e_G \}$
correspondant à
la valeur de $G$ avant l'appel
(selon la spécification de $g$).
\end{itemize}
\end{tabular}
\end{exemple}
On note que, contrairement à ce qui était fait dans la version précédente,
on ne crée par d'élément pour l'entrée implicite $G$ de $g$ dans $f$.
Cela permet d'améliorer la précision des dépendances lorsque
l'ajout d'un tel noeud conduisait au regroupement de plusieurs données.
Ainsi, dans l'exemple précédent, on ne crée pas d'élément pour
représenter la valeur de $G$ avant l'appel, même si l'élément $e_3$ en dépend,
et on conserve donc l'information que $G.b$ ne dépend que de l'affectation
précédent l'appel.
\section{Entrées/sorties d'une fonction}\label{sec-fct-inout}
Pour relier un appel de fonction au PDG de la fonction appelée,
il faut ajouter des éléments représentant ses entrées/sorties,
c'est-à-dire~:
\begin{itemize}
\item un élément correspondant au point de contrôle d'entrée
dans la fonction,
\item deux éléments pour chaque paramètre (cf. \S\ref{sec-decl-param}),
\item un élément pour les entrées implicites (cf. \S\ref{sec-impl-in}),
\item un élément pour la sortie de la fonction si celle-ci retourne
quelque chose.
\end{itemize}
On note que, contrairement à ce qui était fait dans la version précédente,
on ne crée par d'élément pour les sorties implicites de la fonction.
Cela permet d'améliorer la précision des dépendances lorsque
l'ajout d'un tel noeud conduisait au regroupement de plusieurs données.
C'est par exemple le cas lorsqu'une fonction calcule $G.a$,
puis $G.a.x$ car un élément de sortie regrouperait les deux alors que
si par la suite on s'intéresse juste à $G.a.x$ à la sortie de la fonction,
le fait de ne pas avoir créé cet élément permet de retrouver l'information plus
précise.
\subsection{Entrées implicites}\label{sec-impl-in}
Au cours du calcul du PDG, on mémorise l'utilisation des données
qui ne sont pas préalablement définies.
Cela permet par la suite que créer des éléments pour ces entrées dites
implicites. On ne crée pas d'élément pour les variables locales non
initialisées, mais un message d'avertissement est émis.
Il est possible que ce soit une fausse alerte dans le cas où l'initialisation
est faite dans une branche dont la condition est forcement vrai à chaque
exécution où l'on passe par la suite par l'utilisation.
Diverses stratégies de regroupement de ces entrées peuvent être utilisées.
A ce jour, l'outil construit tous les éléments lui permettant d'avoir une
meilleure précision. C'est-à-dire que deux éléments peuvent représenter les
données qui ont une intersection.
\subsection{Déclaration des paramètres formels}\label{sec-decl-param}
En plus de l'élément représentant la valeur des paramètres,
on crée un second élément qui représente sa déclaration,
le premier dépendant du second.
Cette représentation peut permettre d'avoir une meilleure précision
dans le cas où certains calcul ne dépendent pas de la valeur du
paramètre, mais uniquement de sa déclaration.
\begin{exemple}
\begin{tabular}{m{5cm} m{\linewidth - 6cm}}
\begin{verbatim}
int g (int a) {
G = 2 * a;
a = calcul_a ();
return a;
}
int f (void) {
int x = calcul_x ();
return g (x);
}
\end{verbatim}
&
On voit que la valeur de retour de \verbtt{g} ne nécessite pas la valeur initiale
de \verbtt{a}, mais seulement sa déclaration. La valeur de retour de \verbtt{f}
ne dépend donc pas de l'appel à \verbtt{calcul\_x}.
\end{tabular}
\end{exemple}
Ce point n'est pas encore implémenté dans la version actuelle,
car dans des cas plus complexe, il est délicat de savoir ce qu'il faut
garder dans la fonction appelante. Le plus simple serait sans doute
de transformer le paramètre formel en une variable locale,
mais le filtrage permet à l'heure actuelle de garder ou d'effacer des
éléments existants, mais pas d'effectuer des transformations de code...
\section{Fonctions à nombre d'arguments variable}
Pour l'instant, on ne calcule pas le PDG des fonctions à nombre
d'arguments variable, c'est-à-dire que pour le reste de l'application,
tout se passe comme si on n'avait pas le code source de ces fonctions.\\
En revanche, les appels à de telles fonctions sont gérées de manière semblable à
ce qui est fait pour les autres appels, c'est-à-dire~:
\begin{itemize}
\item création d'un noeud d'entrée pour chaque argument d'appel,
(il y en a donc éventuellement plus que que paramètres formels dans le
déclaration de la fonction appelée)
\item utilisation des informations {\it from} pour créer les éventuelles
entrées implicites, les sorties, et les liens de dépendance.
\end{itemize}
\section{Exemple}
\begin{exemple}
\lstinputlisting[language=c]{exple-call.c}
\end{exemple}
Graphe de la fonction \verbtt{f}: \\
\includegraphics[width=0.6\textwidth]{call-f}
\\
\clearpage
Graphe de la fonction \verbtt{g}: \\
\includegraphics[width=1\textwidth]{call-g}
\\
Les graphes sont ceux qui sont effectivement produits par l'outil.
\chapter{Conclusion}
La version actuelle de ce greffon semble fonctionner.
Elle est utilisée par les greffons {\sc Security}, {\sc Sparecode} et
{\sc Slicing}. Ces résultats peuvent également être visualisés
graphiquement en utilisant la fonction d'exportation
au format {\tt .dot}.\\
D'autres information relatives au développement peuvent être trouvées dans la documentation du code dont un point d'entrée
est~:
\centerline{\tt doc/code/pdg/index.html}
\section{Limitations}
Les fonctions ayant un nombre d'arguments variable
ne sont pas traitées (mais les appels à de telles fonctions sont gérés).
Par ailleurs, les calculs se basant sur l'analyse de valeur,
et sur le calcul des dépendances fonctionnelles (\from)
il hérite des limitations de ces modules.
#FIG 3.2
Portrait
Center
Metric
A4
100.00
Single
-2
1200 2
0 32 #ffffff
6 4410 2610 5355 3195
2 3 0 1 32 32 0 -1 20 0.000 0 0 0 0 0 5
4417 2645 5314 2645 5314 3165 4417 3165 4417 2645
2 3 0 1 0 0 0 0 -1 0.000 0 0 0 0 0 5
4417 2645 5314 2645 5314 3165 4417 3165 4417 2645
4 1 0 0 0 16 17 0.0000 6 180 810 4866 2976 START\001
-6
6 5715 6210 6120 6795
2 3 0 1 32 32 0 -1 20 0.000 0 0 0 0 0 5
5728 6236 6082 6236 6082 6755 5728 6755 5728 6236
2 3 0 1 0 0 0 0 -1 0.000 0 0 0 0 0 5
5728 6236 6082 6236 6082 6755 5728 6755 5728 6236
4 1 0 0 0 16 17 0.0000 6 180 165 5905 6566 B\001
-6
6 7470 4860 7965 5445
2 3 0 1 32 32 0 -1 20 0.000 0 0 0 0 0 5
7488 4889 7960 4889 7960 5409 7488 5409 7488 4889
2 3 0 1 0 0 0 0 -1 0.000 0 0 0 0 0 5
7488 4889 7960 4889 7960 5409 7488 5409 7488 4889
4 1 0 0 0 16 17 0.0000 6 180 300 7724 5220 S2\001
-6
6 5715 4860 6120 5445
2 3 0 1 32 32 0 -1 20 0.000 0 0 0 0 0 5
5740 4889 6094 4889 6094 5409 5740 5409 5740 4889
2 3 0 1 0 0 0 0 -1 0.000 0 0 0 0 0 5
5740 4889 6094 4889 6094 5409 5740 5409 5740 4889
4 1 0 0 0 16 17 0.0000 6 180 150 5917 5220 Z\001
-6
6 4725 5715 5220 6255
2 3 0 1 32 32 0 -1 20 0.000 0 0 0 0 0 5
4748 5716 5220 5716 5220 6236 4748 6236 4748 5716
2 3 0 1 0 0 0 0 -1 0.000 0 0 0 0 0 5
4748 5716 5220 5716 5220 6236 4748 6236 4748 5716
4 1 0 0 0 16 17 0.0000 6 180 285 4984 6047 Z1\001
-6
6 6435 5715 6975 6255
2 3 0 1 32 32 0 -1 20 0.000 0 0 0 0 0 5
6472 5716 6968 5716 6968 6236 6472 6236 6472 5716
2 3 0 1 0 0 0 0 -1 0.000 0 0 0 0 0 5
6472 5716 6968 5716 6968 6236 6472 6236 6472 5716
4 1 0 0 0 16 17 0.0000 6 180 285 6720 6047 Z2\001
-6
6 4455 7155 5220 7740
2 3 0 1 32 32 0 -1 20 0.000 0 0 0 0 0 5
4464 7181 5196 7181 5196 7700 4464 7700 4464 7181
2 3 0 1 0 0 0 0 -1 0.000 0 0 0 0 0 5
4464 7181 5196 7181 5196 7700 4464 7700 4464 7181
4 1 0 0 0 16 17 0.0000 6 180 675 4830 7511 STOP\001
-6
6 6480 3375 6885 3960
2 3 0 1 32 32 0 -1 20 0.000 0 0 0 0 0 5
6519 3401 6874 3401 6874 3921 6519 3921 6519 3401
2 3 0 1 0 0 0 0 -1 0.000 0 0 0 0 0 5
6519 3401 6874 3401 6874 3921 6519 3921 6519 3401
4 1 0 0 0 16 17 0.0000 6 180 165 6696 3732 A\001
-6
6 4725 4185 5220 4725
2 3 0 1 32 32 0 -1 20 0.000 0 0 0 0 0 5
4745 4204 5194 4204 5194 4724 4745 4724 4745 4204
2 3 0 1 0 0 0 0 -1 0.000 0 0 0 0 0 5
4745 4204 5194 4204 5194 4724 4745 4724 4745 4204
4 1 0 0 0 16 17 0.0000 6 180 300 4970 4535 S1\001
-6
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 3
2 1 1.00 60.00 120.00
5310 2925 6345 2925 6705 3420
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 3
2 1 1.00 60.00 120.00
4500 3150 4275 5445 4680 7200
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 3
2 1 1.00 60.00 120.00
6525 3600 5175 3600 4950 4185
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 3
2 1 1.00 60.00 120.00
6885 3600 7245 3600 7650 4905
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 3
2 1 1.00 60.00 120.00
5175 4455 5625 4455 5895 4905
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 3
2 1 1.00 60.00 120.00
5760 5175 5310 5175 4950 5715
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 3
2 1 1.00 60.00 120.00
6075 5175 6480 5175 6750 5715
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 3
2 1 1.00 60.00 120.00
4950 6210 4995 6390 5715 6615
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 3
2 1 1.00 60.00 120.00
6750 6210 6705 6390 6075 6615
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 3
2 1 1.00 60.00 120.00
7650 5400 7650 6300 5175 7425
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 3
2 1 1.00 60.00 120.00
5850 6750 5850 6975 5175 7290
This diff is collapsed.
\chapter{Dépendances liées aux données}
Le calcul de dépendances de données et d'adresse consiste principalement
à retrouver les éléments de flot correspondant aux données utilisées dans les
expressions.
Mais comme les données peuvent être incluses les unes dans les
autres, il ne suffit pas de retrouver les éléments de flot qui calculent
exactement ces données, mais aussi ceux qui ont une intersection possible.
Par exemple, dans la séquence~:\\
\centerline{\verbtt{d = d0; x = d.a;}}
il faut être capable de voir que \verbtt{x} dépend de \verbtt{d0}.
Autre exemple~: dans la séquence~:\\
\centerline{\verbtt{d0.a = a; d0.b = b; d = d0;}}
il faut voir que \verbtt{d} dépend éventuellement de la valeur initiale de \verbtt{d0}
(si \verbtt{d0} contient d'autres champs que \verbtt{.a} et \verbtt{.b}), mais aussi
de \verbtt{a}, et de \verbtt{b}.\\
\section{Recherche arrière}
Le premier calcul mis en {\oe}uvre procédait par recherche en arrière
des éléments de la table ayant une intersection avec les données présentes en
partie droite de l'instruction. Mais cette recherche était compliquée en cas de
dépendances partielles comme dans le second exemple ci-dessus. Cette solution a
donc été abandonnée.
\section{Propagation avant d'un état}\label{sec-propagation-etat}
La méthode finalement choisie pour calculer ces dépendances
consiste à propager en avant, par une analyse du type flot de données,
un \indexdef{état des données}
qui contient pour chaque donnée, une liste de liens vers les éléments
du graphe qui ont permis de déterminer sa valeur en ce point.
Cet état doit avoir les propriétés suivantes~:
\begin{itemize}
\item on veut pouvoir associer un nouveau noeud à une donnée
en précisant s'il faut faire l'union avec l'ensemble précédemment stocké.
Par exemple~;
\begin{itemize}
\item pour l'instruction \verbtt{x = 3;} on construit un nouvel élément
dans le PDG, et on mémorise dans l'état que \verbtt{x} est maintenant associé
à cet élément. L'ancienne association est perdue.
\item pour l'instruction \verbtt{*p = 3;} si \verbtt{p} peut pointer sur \verbtt{x},
il faut mémoriser que \verbtt{x} peut être défini par l'élément du PDG
correspondant, mais comme ce n'est pas sûr, il faut faire l'union avec
ce qui était précédemment stocké pour \verbtt{x}.
\end{itemize}
\item lorsque l'on demande l'ensemble associé à une donnée,
le résultat doit contenir au moins ce qu'on a stocké
(il peut contenir plus d'élément en cas de perte de précision),
\item la consultation ne doit pas modifier l'état,
\item il faut savoir faire l'union de deux états.
\end{itemize}
La structure de donnée du module \verbtt{Lmap} de \ppc correspond à ces critères,
et peut donc être utilisée pour ce calcul.\\
\section{Propagation arrière d'un état}
Une autre solution aurait pu être de propager en arrière
un état contenant les utilisations
de variables, et mettre à jour le graphe en rencontrant la définition.
Le coût de ce calcul semble être le même que le précèdent,
mais la propagation avant nous permet d'avoir, à chaque point de programme,
un état donnant la correspondance entre une donnée et les éléments du graphe,
même si cette donnée n'est pas utilisée à ce point.
Cette information nous permet par la suite de définir des critères
de \slicing moins restrictifs.
\section{Traitement de l'affectation}
Le principe de l'algorithme du traitement d'une affectation
\verbtt{lval = exp;} est donc le suivant~:
\begin{itemize}
\item recherche des données $\{d_v\}$
utilisées dans \verbtt{exp} à l'aide des résultats de l'analyse d'alias préalable,
\item calcul de {\it dpdv},
c'est-à-dire l'union des ensembles associées à ces données $d_v$ dans l'état,
\item recherche des données $\{d_a\}$
utilisées pour calculer l'adresse de {\it lval},
\item calcul de {\it dpda}
c'est-à-dire l'union des ensembles associées à ces données $d_a$ dans l'état,
\item recherche de l'élément $e$
correspondant à cette instruction dans le graphe,
et création de cet élément s'il n'existe pas,
\item ajout des dépendances {\it dpdv} et {\it dpda} à $e$,
\item recherche des données $\{d_x\}$
potentiellement modifiées par cette affectation,
\item calcul du nouvel état (après l'instruction)
en ajoutant dans l'ancien état un lien entre les $\{d_x\}$ et $e$.
\end{itemize}
\section{Déclarations}
Les déclarations de variable doivent être traitées séparément
des valeurs, car on peut parfois dépendre de l'adresse d'une variable
sans dépendre de ce qu'elle contient.
C'est par exemple le cas lorsque la variable apparaît à gauche
d'une affectation (\verbtt{x = 3;})
ou encore quand on n'utilise que son adresse (\verbtt{p = \&x;}).
On garde donc une table qui permet de retrouver les éléments
du graphe de dépendances qui correspondent aux déclarations.
\section{Calcul de conditions}
Les noeuds du graphe de dépendances représentant
les calculs de condition des \verbtt{if} ou \verbtt{switch}
ont des dépendances de donnée sur les données utilisées.
\section{Dépendances de donnée dans les boucles}
Pour les boucles {\it explicites}, il suffirait d'effectuer deux tours
de la boucle pour obtenir toutes les dépendances de donnée car le premier
capture les dépendances avec les données provenant d'avant la boucle,
ou interne à un tour, et le second capture les dépendances entre un tour et le
suivant.
Mais comme les boucles peuvent être introduites par la présence de sauts
quelconques,
le plus simple est dans un premier temps d'itérer jusqu'à obtenir un point fixe
sur l'état des données. Il faut noter que les noeuds ne sont créés que lors de la
première itération, les suivantes n'ajoutant que de nouvelles dépendances entre
ces noeuds. Le nombre de noeuds étant fini (de l'ordre de grandeur du nombre
d'instruction de la fonction), l'atteignabilité du point fixe est
garantie.
\section{Appels de fonction}
Le traitement des appels de fonction est présenté
dans le chapitre \ref{sec-intro-call}
#FIG 3.2
Landscape
Center
Metric
A4
100.00
Single
-2
1200 2
6 3195 2160 8010 5130
6 3195 2385 4950 4950
6 3195 2385 3780 2790
1 1 0 1 0 7 50 -1 -1 0.000 1 0.0000 3465 2565 270 180 3465 2565 3735 2745
4 1 0 50 -1 0 12 0.0000 4 150 390 3465 2610 entry\001
-6
6 3195 3105 3780 3510
1 1 0 1 0 7 50 -1 -1 0.000 1 0.0000 3465 3285 270 180 3465 3285 3735 3465
4 1 0 50 -1 0 12 0.0000 4 135 90 3465 3330 2\001
-6
6 3195 3825 3780 4230
1 1 0 1 0 7 50 -1 -1 0.000 1 0.0000 3465 4005 270 180 3465 4005 3735 4185
4 1 0 50 -1 0 12 0.0000 4 135 90 3465 4050 5\001
-6
6 4365 3105 4950 3510
1 1 0 1 0 7 50 -1 -1 0.000 1 0.0000 4635 3285 270 180 4635 3285 4905 3465
4 1 0 50 -1 0 12 0.0000 4 135 90 4635 3330 3\001
-6
6 4365 3825 4950 4230
6 4590 3915 4680 4050
4 1 0 50 -1 0 12 0.0000 4 135 90 4635 4050 4\001
-6
1 1 0 1 0 7 50 -1 -1 0.000 1 0.0000 4635 4005 270 180 4635 4005 4905 4185
-6
6 3195 4545 3780 4950
1 1 0 1 0 7 50 -1 -1 0.000 1 0.0000 3465 4725 270 180 3465 4725 3735 4905
4 1 0 50 -1 0 12 0.0000 4 135 90 3465 4770 6\001
-6
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
2 1 1.00 60.00 120.00
3465 2745 3465 3105
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
2 1 1.00 60.00 120.00
3465 3465 3465 3825
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2
2 1 1.00 60.00 120.00
3465 4185 3465 4545
2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 1 0 2