/*
 * Copyright (c) 1995, 1996 Gunther Schadow.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

:- module(mkc_cde,[mkc/0,mkc_unimesg_conf/0]).

:- style_check(+string).

:- use_module(db-inter).
:- use_module(desc-names).
:- use_module(desc-files).
:- use_module(mkc-print).
:- use_module(packages).

mgmt_table(9995).
mgmt_table(9996).
mgmt_table(9997).
mgmt_table(9998).
mgmt_table(9999).

mkc :-	format("Making code for codes:~n"),
	forall(
	(
	    implemented(M:table(I,_,_)),
 	    \+mgmt_table(I),
	    findall([Val,Des], M:value(I, Val, Des, _), TvaL),
	    TvaL \= []
	),
	(
	    file(code,code(I),Fnh),	 
	    format("[~w", [I]), flush,
	    mkc_h(I,Fnh,TvaL),	   
	    mkc_cc(I,Fnh,TvaL),
	    format("]")
	)), nl.


mkc_h(I,Fnh,TvaL) :-
	htell(Fnh,Def,code),
	format("#include <LinearCode.h>~n"),
	cdetname(I,Name),
	table(I,Des,Class),
	comment("CODE",Name,Class,Des),
	format("class ~w : public LinearCode~n", Name),
	format("{~>~n"),
	ppublic,
	format("enum Value {~>~n"),
	format("invalid     = LinearCode::invalid,~n"),
	format("not_present = LinearCode::not_present,~n"),
	format("null        = LinearCode::null,~n"),
	format("first       = LinearCode::first,~n"),

	mkc_h1(TvaL,0),

	format("~w();~n", Name),
	format("~w(Value val);~n", Name),
	format("~w(const char *s);~n~n", Name),
	format("operator Value () const;~n~n"),
	pprivate,
	format("static const char *_table[size];"),
	format("~<~n};~n~n"),
	format("inline ~w::~w()~n", [Name, Name]),
	format("         : LinearCode(_table,(size_t)size) {}~n~n"),
	format("inline ~w::~w(Value val)~n",  [Name, Name]),
	format("         : LinearCode((int)val,_table,(size_t)size) {}~n~n"),
	format("inline ~w::~w(const char *s)~n", [Name, Name]),
	format("         : LinearCode(s,_table,(size_t)size) {}~n~n"),
	format("inline ~w::operator ~w::Value () const~n", [Name, Name]),
	format("{~>~n"),
	format("return (Value)(LinearCode::operator int());"),
	format("~<~n}~n"),

	htold(Def).

mkc_h1([[Val, Des]],I) :-
	cname(Des,Name),
	valname(Val,VName),
	format("~n~w = first + ~w,", [Name, I]),
	format("~n        ~w = first + ~w,~35|//~w", [VName, I, Des]),
	format("~n~nlast = ~w,", I),
	format("~nsize = last - first + 1"),
	format("~<~n};~n").

mkc_h1([[Val, Des]|T], I) :-
	cname(Des,Name),
	valname(Val,VName),
	format("~n~w = first + ~w,", [Name, I]),
	format("~n        ~w = first + ~w,~35|//~w", [VName, I, Des]),
	In is I + 1,
	mkc_h1(T, In).

mkc_cc(I,Fnh,TvaL) :-
	cctell(Fnh,code),
	format("#include ~'LinearCode.h~'~n"),
	cdetname(I,Name),
	table(I,Des,Class),
	comment("code",Name,Class,Des),
	format("~nconst char *~w::_table[~w::size] = {~>", [Name, Name]),
	mkc_cc1(TvaL),
	format("~<~n};"),
	cctold.

mkc_cc1([]).
mkc_cc1([[Val, Des]|T]) :-
	uppercase(Val,UVal),
	format("~n~'~w~',~20|// ~w", [UVal, Des]),
	mkc_cc1(T).

%
% MANAGEMENT TABLES ARE BUILT ONLY ONCE, WHEREBY ALL PACKAGES ARE INCLUDED
%

mkc_mgmt :-
	mgmt_tables,
	format("Making code for management tables:~n"),
	forall(
	(
            mgmt_table(I),
	    file(code,code(I),Fnh),
	    findall([Val,Des], value(I, Val, Des, _), TvaLus),
            sort(TvaLus, TvaL),
	    TvaL \= []
	),
	( 
	    format("[~w", [I]),
	    mkc_h(I,Fnh,TvaL),	   
	    mkc_cc(I,Fnh,TvaL),
	    format("]")
	)), nl,
	mkc_unimesg_conf.

mgmt_tables :- 
	% include all packages from the INDEX, the first one is the main
	findall(P, package(P,_,_,_,_), [MP|PL]),
	make_package(MP),
	forall(member(P,PL), use_package(P)),
	%
	format("collect management tables~n"),
	forall(sourced_package(P),
	(
	    forall(P:message_type(M,Dm,X),
	    (
		assertz(MP:value(9995,M,Dm,X)),
		forall(P:message(M,E,De,_),
		(
		    ( ( E \= '' ) -> assertz(MP:value(9996,E,De,X)) ; true ),
		    unimesg(M,E,U),
		    assertz(MP:value(9997,U,De,X))
		))
	    )),
	    forall(P:segment(S,D,X),
	    (
		assertz(MP:value(9999,S,D,X))
	    )),	    
	    forall(P:data_type(T,D,X),
	    (
		assertz(MP:value(9998,T,D,X))
	    ))
	)).

/*
NAME
	mkc_unimesg_conf/0 -- make describing tables for mapping
				message/event to unimesg and vice versa

SYNOPSIS
	mkc_unimesg_conf()

DESCRIPTION

*/

mkc_unimesg_conf :-
	format("Writing UniMesg-conf.h~n"),
	path(code,Path),
	concat(Path,"UniMesg-conf.h",File),
	tell(File),
	main_package(P),
	format("struct unif_rec unif[MesTypeCode::size] =~>~n{~>"),
	% 9995 is the message type table
        findall(Mi,P:value(9995,Mi,_,_),MidLus),
        sort(MidLus,MidL),
	forall(member(Mid,MidL),
	(
	    message(Mid,Evc,_,_),
	    unimesg(Mid,Evc,Uni),
	    valname(Mid,MidVal),
	    ( Evc = '' ->
		EvcVal = 'EventTypeCode::not_present';
		valname(Evc,EvcVal1),
		concat('EventTypeCode::',EvcVal1,EvcVal)
	    ),
	    valname(Uni,UniVal),
	    format("~n{UniMesIdCode::~w, ~w},",
	           [UniVal,EvcVal])
	)),
        format("~<~n};~<~n~n"),
	format("struct disp_rec disp[UniMesIdCode::size] =~>~n{~>"),
	% 9997 is the unique message id table
        findall(Ui,P:value(9997,Ui,_,_),UniLus),
        sort(UniLus,UniL),
	forall(member(Uni,UniL),
	(
	    unimesg(Mid,Evc,Uni),
	    ( Evc = '' ->
		EvcVal = 'EventTypeCode::not_present';
		valname(Evc,EvcVal1),
		concat('EventTypeCode::',EvcVal1,EvcVal)
	    ),
	    valname(Mid,MidVal),
	    valname(Uni,UniVal),
	    format("~n{MesTypeCode::~w, ~w},",
	           [MidVal,EvcVal])
	)),
        format("~<~n};~<~n~n"),
        told.

