Date: Tue, 12 Jun 2001 11:36:46 -0400
Reply-To: Bernard Tremblay <imaginasys@HOTMAIL.COM>
Sender: "SAS(r) Discussion" <SAS-L@LISTSERV.UGA.EDU>
From: Bernard Tremblay <imaginasys@HOTMAIL.COM>
Subject: Re: SAS code analysis
Content-Type: text/plain; charset=ISO-8859-1
Hi SAS-L'ers,
I just want to give a follow up of my previous posts of last week. I
have writen some SAS code to analyse a set of SAS program and give some
statistics about each program. Right now, it's a work in progress but I
just want others to be able to give some feedback.
The program is at the end of this message.
The input is a SAS file (pgms) that contains a variable (pgm) with the
name of a program. All the pmg are in the same directory, I build back the
physical name and then analyse the program. The output will be an
observation with some statistics on:
* pmg : Name of program
* nb_lig : Number of lines
* nb_ins : Number of SAS instructions (total
* nb_c : Number of comments
* nb_iml : Number of PROC
* nb_data : number of DATA steps
* nb_proc : Number of PROC autre que IML
* ni_iml : Number of SAS instructions with PROC IML
* ni_data : Number of SAS instructions in DATA steps
* ni_proc : Number of SAS instructions with other PROC
* nb_inc : Number of INCLUDE
* nb_file : Number of FILENAME
* nb_lib : Number of LIBNAME
I don't have sufficient time to translate everything in the program, so
comments are in french for now, sorry.
I know that it is not perfect right now. It doesn't go into the INCLUDE
code and it doesn't take MACRO into account. But it is sufficient for the
task I had to do here.
If anybody has comments or improvements, I'm open to suggestions !
Regards,
\\\|///
\\ - - //
( @ @ )
+-----oOOo-(_)-oOOo--+-----------------------------------+
| Bernard Tremblay | |
+----------------------------+---------------------------+
| Imaginasys enr | Res: (418) 658-1411 |
| | Int: bertrem@videotron.ca |
| | Hot: imaginasys@hotmail.com |
| | http://pages.infinit.net/bertrem/ |
+--------------Oooo--+-----------------------------------+
oooO ( )
( ) ) /
\ ( (_/
\_)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*;
*******************************************************************;
* CodeAnalysis.v3.sas *;
*-----------------------------------------------------------------*;
* Donne des statistiques des sources codés en SAS *;
* 2001-06-12 Bernard Tremblay, Imaginasys enr. *;
* Écriture du programme *;
*******************************************************************;
* Input *;
* PGM : Un fichiers SAS, noms de programmes dans la variable pgm *;
* macro variable REP : Le répertoire où sont situés les sources *;
* NB: aucune validations n*est faite, les fichiers doivent être *;
* présent dans le répertoire *;
*-----------------------------------------------------------------*;
* Output *;
* stats : Un fichier SAS avec des statistiques *;
* *;
* pmg : Nom du programme *;
* nb_lig : Nombre de lignes du programme *;
* nb_ins : Nombre d'instructions SAS (total) *;
* nb_c : Nombre de commentaires *;
* nb_iml : Nombre de PROC IML *;
* nb_data : Nombre de DATA steps *;
* nb_proc : Nombre de PROC autre que IML *;
* ni_iml : Nombre d*instructions SAS sous PROC IML *;
* ni_data : Nombre d'instructions SAS dans les DATA steps *;
* ni_proc : Nombre d'instructions SAS dans les PROC autres *;
* nb_inc : Nombre de INCLUDE *;
* nb_file : Nombre de FILENAME *;
* nb_lib : Nombre de LIBNAME *;
*******************************************************************;
*;
*;
%let rep = S:\prod\TSU\PROD\EXEC ; /* Le répertoire où sont les
programmes */
*;
proc sort data=sasuser.struct5(keep=pgm act_sas menu src
where=(act_sas & pgm like 'TSU%'))
out=pgms nodupkey;
by pgm;
run;
*;
data stats(keep=pgm nb_lig nb_ins nb_c nb_iml nb_data nb_proc
ni_iml ni_data ni_proc nb_inc nb_file
nb_lib)
/*debug /**/;
format pgm $30. fname ligne mot $200.
nb_lig nb_ins nb_c nb_iml nb_data nb_proc
ni_iml ni_data ni_proc nb_inc nb_file nb_lib
6. ;
/* Prendre un PGM SAS pour analyser et trouver son nom
physique */
set pgms(keep=pgm);
fname= "&rep\"||trim(pgm)||".SAS";
infile pgmsas filevar=fname end=eof truncover lrecl=200 pad;
/* Les compteurs */
nb_lig=0;nb_ins=0;nb_c=0;
nb_iml=0;nb_data=0;nb_proc=0;
ni_iml=0;ni_data=0;ni_proc=0;
nb_inc=0;nb_file=0;nb_lib=0;
comm=0;eof=0;
/* Les indicateurs */
flag_c1=0; flag_c2=0;
data=0;proc=0;iml=0;first=1;
/* Lire mot par mot le pgm */
do while (not eof);
link lire;
do while (mot>' ');
if ^(flag_c1|flag_c2)
then do;
if ^(data|proc|iml)
then do;
select;
when(mot=:'/*')
do;flag_c2=1;nb_c+1;end;
when(first & mot=:'*')
do;flag_c1=1;nb_c+1;first=0;end;
when(first & mot="DATA")do;
data=1;nb_data+1;first=0;
end;
when(first & mot="PROC")
do;first=0;
link scan;
do while (mot=' ' & ^eof);
link lire;
end;
if mot='IML'
then do;
iml=1;
nb_iml+1;
end;
else do;
proc=1;
nb_proc+1;
end;
end;
when(first &
mot='FILENAME') do;nb_file+1;first=0;end;
when(first &
mot='LIBNAME') do;nb_lib+1;first=0;end;
when(first & mot='%
INCLUDE') do;nb_inc+1;first=0;end;
when(mot=';')
do;first=1;nb_ins+1;end; /*Fin d*une instruction*/
otherwise
first=0; /* On continue a scanner */
end;
end;
else do; /* détecter la fin d*une
instruction */
if mot = ';'
then do;
select;
when(data)
ni_data+1;
when(proc)
ni_proc+1;
when(iml) ni_iml+1;
otherwise;
end;
nb_ins+1;
end;
else do;
if mot in
('RUN','QUIT')
then do;
select;
when(data)
ni_data+1;
when(proc)
ni_proc+1;
when(iml)
ni_iml+1;
otherwise;
end;
link scan;
if mot
= ';'
then do;
nb_ins+1;first=1;
data=0;proc=0;iml=0;
end;
end;
else
if mot in
('DATA','PROC') & i=1 /*1er mot seulement*/
then do;
data=0;proc=0;iml=0;first=1;
goto encore;
end;
else ; /*
un mot qcq dans une instruction */
end;
end;
end;
else do; /* On cherche la fin d*un commentaire*/
select;
when(flag_c1)do;
if mot=';'
then do;
flag_c1=0;
if ^(iml|proc|data) then first=1;
end;
end;
when(flag_c2)do;
if left
(reverse(mot))=:'/*'
then do;
flag_c2=0;
if ^
(iml|proc|data) then first=1;
end;
end;
otherwise;
end;
end;
link scan;
encore: end;
end;
output;
return;
lire:
input @1 ligne $UPCASE200.;
/* Espacer les fins de lignes et commentaires pour le scan
*/
ligne=tranwrd(ligne,';',' ; ');
ligne=tranwrd(ligne,'/*',' /* ');
ligne=tranwrd(ligne,'*/',' */ ');
ligne=left(ligne);
nb_lig+1;
i=0;
scan: i+1;
mot=scan(ligne,i,' ');
return;
run;
*;
options ls=208 ps=82 pageno=1;
proc print data=stats;
title 'Statistiques sur les traitements';
run;
********************* END OF PROGRAM **********************;