/*
<<<  Prolog Program Line Countor >>>
	SOFNEC CO., LTD. 1989 8 24 - 1990 8 3
  How to Compile 
   % AZPC -p count.pl /no /e count
  How to Use
   % count -p file1 file2 file3 ....
   % count -p /f FileNameFile
   % count (C/R)  == count user
   
*/

:- s_mode(_,on).

top_level:-
	e_switch(0,off,on), 
	nl,write('Prolog Line Counter ver 2.5(2012.3.5)  By AZ-Prolog Compiler V7'),nl,
	get_parameter(P),nofileerrors,prompt(_,''),
	get_allfiles(P,P1),
	e_register(0,_,0),	%% ToTal Lines
	e_register(1,_,0),	%% ToTal Clauses
	e_register(2,_,0),	%% ToTal Predicates
	   errorset(counts(P1),succ),
	e_register(0,A,A),
	e_register(1,B,B),
	e_register(2,C,C),
	write_lines('Total',A,B,C).

write_lines(Message,X,Y,Z):-	
	atom(Message,AL),Tab1 is 20-AL, (Tab1<0 -> Tab = 1; Tab = Tab1),
	nl,write(Message),tab(Tab),
	writel(X),write(' Lines'),
	writel(Y),write(' Clauses'),
	writel(Z),write(' Predicates').
	
writel(X):- name(X,L),length(L,LN),tab(10-LN),write(X).

get_allfiles([],[]):-!.
get_allfiles([ '/f',X|L],LL):- !,
	see(X),getFromFile0(L,LF,0),seen,get_allfiles(LF,LL).
get_allfiles([X|L],[X|LL]):- get_allfiles(L,LL).

getFromFile0(O,[ATM|Rest],0):- 
	get0(CC),gets(CC,CD),!,getFromFile1(CD,P,EOF),name(ATM,P),
	getFromFile0(O,Rest,EOF).
getFromFile0(O,O,_).

gets(EOF,_):- end_of_file(EOF),!,fail.
gets(A,A):- A>0'20,!.
gets(_,A):- get0(B),gets(B,A).

getFromFile1(EOF,[],1):- end_of_file(EOF),!.
getFromFile1(CD,[],0):- CD =<0'20,!.
getFromFile1(M,[M|L],EOF):- get0(CD),getFromFile1(CD,L,EOF).

end_of_file(26):- s_version(_,'OS/2',_,_),!.
end_of_file(26):- s_version(_,'MSDOS',_,_),!.
end_of_file(4).

counts([]) :- !,count(user).
counts(L) :- count(L).

count([]):-!.
count([A|L]):- count(A),!,count(L).
count(A):- 
	s_new,			%% Clear Predicate Data
	e_register(0,OldLine,OldLine),
	e_register(1,OldClause,OldClause),
	countFile(A),
	clause(data,2,Pred),
	e_register(0,NewLine,NewLine),
	e_register(1,NewClause,NewClause),
	e_register(2,OldPred,OldPred+Pred),
	Line is NewLine-OldLine,
	Clause is NewClause-OldClause,
	write_lines(A,Line,Clause,Pred).

count(A):- write('CANNOT SEE '),write(A),nl.

countFile(A):-
	see(A),repeat(Clause),read(X),do(X),seen,restore_op,
	e_register(1,OldClause,OldClause+Clause),!.

/* Clause check */

do(end_of_file).
do((X-->Y)):-lengths(Y,0,M),e_register(0,Old,Old+M+1),checkp(X),!,fail.
do((X:-Y)):- lengths(Y,0,M),e_register(0,Old,Old+M+1),checkp(X),!,fail.
do((:-ensure_loaded(X))):-  !,dolist([X]),fail.
do((:-Y)):-  list(Y),!,dolist(Y),fail.
do((:-Y)):-  op_check(Y),lengths(Y,0,M),e_register(0,Old,Old+M),!,fail.
do(A):- e_register(0,Old,Old+1),checkp(A),fail.

dolist([]):-!.
dolist([X|L]):- filename(X,X1),countFile(X1),dolist(L).

filename(-(X),X):-!.
filename(X,X).

/* body Goal volume */
 :- mode lengths(+,+,-).
lengths(X,N,M):- 	var(X),!,M is N +1.
lengths(','(X,Y),N,M):- !,lengths(X,N,N1),lengths(Y,N1,M).
lengths((X;Y),N0,M):- 	!,N is N0+1,lengths(X,N,N1),lengths(Y,N1,M).
lengths((X->Y),N0,M):-	!,N is N0+1,lengths(X,N,N1),lengths(Y,N1,M).
lengths(\+(X),N0,M):- 	!,N is N0+1,lengths(X,N,M).
lengths({}(X),N0,M):-   !,N is N0+1,lengths(X,N,M).
lengths(call(X),N0,M):- !,N is N0+1,lengths(X,N,M).
lengths(catch(_,X),N0,M):- !,N is N0+1,lengths(X,N,M).
lengths(errorset(X,_),N0,M):- !,N is N0+1,lengths(X,N,M).
lengths(_,N,M):- M is N+1.


op_check(op(X,Y,Z)):- !,save_op(X,Y,Z),op(X,Y,Z).
op_check(','(X,Y)):- !,op_check(X),op_check(Y).
op_check(_).

save_op(X,Y,Z) :- ops(_,Y,Z),!.
save_op(X,Y,Z) :- (current_op(N,Y,Z)->true;N=0),assert(ops(N,Y,Z)).

restore_op :- ops(X,Y,Z),op(X,Y,Z),fail.
restore_op.

/* predicate check */
checkp(X):- functor(X,F,A),( data(F,A) -> true;assert( data(F,A) ) ).

:- s_mode(_,off).

