/* $Id: hostconst.c,v 1.2 2005/02/11 02:59:36 ken Exp $
 *
 * (c) Warren W. Gay VE3WWG ve3wwg@home.com, ve3wwg@yahoo.com
 *
 * Protected under the GNU GPL License
 *
 * Digest host specific parameters into a WC.Host package.
 */
static const char rcsid[] = "$Header: /home/cvsroot/bush/src/ADAVOX-0.51/wc/hostconst.c,v 1.2 2005/02/11 02:59:36 ken Exp $";

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>

#include "config.h"

typedef struct {
	int	key;
	char	*name;
} Key_Pair;

void
sort_keys(Key_Pair *table,int n) {
	int x, y;
	Key_Pair t;

	for ( x=0; x<n; ++x ) {	/* Simple, brute force sort */
		for ( y=x+1; y<n; ++y ) {
			if ( table[x].key > table[y].key ) {
				t = table[x];
				table[x] = table[y];
				table[y] = t;
			}
		}
	}
}

static char *
data_type(char *prefix,int bytes) {
	static char buf[64];

	switch ( bytes ) {
	case 1 :
		sprintf(buf,"%s_8",prefix);
		return buf;
	case 2 :
		sprintf(buf,"%s_16",prefix);
		return buf;
	case 4 :
		sprintf(buf,"%s_32",prefix);
		return buf;
	case 8 :
		sprintf(buf,"%s_64",prefix);
		return buf;
	default :
		return "I_GIVE_UP";
	}

	abort();        /* Should never get here */
}

static void
int_const(const char *name,int value) {
	printf("   %s: constant integer := %d;\n",name,value);
}

#if 0	/* NOT CURRENTLY USED */
static void
boolean_const(const char *name,int value) {
	printf("   %s: constant boolean := %s;\n",name,value ? "True" : "False");
}
#endif

void
have_sched() {

	puts("\n   -- Real Time Scheduling");
#if HAVE_SCHED
	puts("   Have_Real_Time : constant Boolean := True;");
#else
	puts("   Have_Real_Time : constant Boolean := False;");
#endif
	puts("   type Scheduler_Policy is (");
	puts("      SCHED_FIFO,");
	puts("      SCHED_OTHER,");
	puts("      SCHED_RR");
	puts("   );");
#if HAVE_SCHED
	puts("   for Scheduler_Policy'Size use 32;\n");
	puts("   for Scheduler_Policy use (");
	{
		static Key_Pair table[3] = {
			{ SCHED_OTHER, "SCHED_OTHER" },
			{ SCHED_FIFO, "SCHED_FIFO" },
			{ SCHED_RR,   "SCHED_RR" }
		};
		int n = 3;
		int x;
		
		sort_keys(table,n);		/* Enumerated values must be sorted for Ada */
		for ( x=0; x<n; ++x )
			printf("      %d%c  -- %s\n",
				table[x].key,
				x + 1 < n ? ',' : ' ',
				table[x].name);
	}
	puts("   );\n");
#endif	/* Else the values do not matter */

	puts("   function Set_Scheduler_Policy(Policy : Scheduler_Policy; Priority : Integer) return Errno_Type;");
	puts("   function Get_Scheduler_Priority(Policy : Scheduler_Policy; Max : Boolean := True) return Integer;\n");

	fputs("   function Set_Scheduler_Policy(Policy : Scheduler_Policy; Priority : Integer) return Errno_Type\n",stderr);
	fputs("   is\n",stderr);
#if HAVE_SCHED
	fputs("      function C_Set_Sched(Policy : Scheduler_Policy; Priority : Integer) return Errno_Type;\n",stderr);
	fputs("      pragma import(C,C_Set_Sched,\"set_sched_policy\");\n",stderr);
#endif
	fputs("   begin\n",stderr);
#if HAVE_SCHED
	fputs("      return C_Set_Sched(Policy,Priority);\n",stderr);
#else
	fputs("      return ENOERR;\n",stderr);
#endif
	fputs("   end Set_Scheduler_Policy;\n\n",stderr);

	fputs("   function Get_Scheduler_Priority(Policy : Scheduler_Policy; Max : Boolean := True) return Integer\n",stderr);
	fputs("   is\n",stderr);
	fputs("      function C_get_max(Policy : Scheduler_Policy) return Integer;\n",stderr);
	fputs("      pragma import(C,C_get_max,\"sched_get_priority_max\");\n",stderr);
	fputs("      function C_get_min(Policy : Scheduler_Policy) return Integer;\n",stderr);
	fputs("      pragma import(C,C_get_min,\"sched_get_priority_min\");\n",stderr);
	fputs("   begin\n\n",stderr);
	fputs("      if Max then\n",stderr);
	fputs("         return C_get_max(Policy);\n",stderr);
	fputs("      else\n",stderr);
	fputs("         return C_get_min(Policy);\n",stderr);
	fputs("      end if;\n",stderr);
	fputs("   end Get_Scheduler_Priority;\n",stderr);
}

int
main(int argc,char **argv) {
        union   {
            char            cc[2];
            unsigned short  u_16;
        } u16;
        union   {
            char            cc[4];
            unsigned        u_32;
        } u32;
        union   {
            char            cc[8];
            unsigned long long u_64;
        } u64;
        short x;

	/* Spec File to stdout */
	printf("-- wc-host.ads (generated by hostconst.c)\n");
	puts("--");
        puts("-- (c) Warren W. Gay VE3WWG ve3wwg@home.com, ve3wwg@yahoo.com");
        puts("--");
        puts("-- Protected under the GNU GPL License");
        puts("--");
        puts("-- WARNING: This file was generated by " __FILE__ "!\n");

	/* Body File to stderr */
	fprintf(stderr,"-- wc-host.adb (generated by hostconst.c)\n");
	fputs("--\n",stderr);
        fputs("-- (c) Warren W. Gay VE3WWG ve3wwg@home.com, ve3wwg@yahoo.com\n",stderr);
        fputs("--\n",stderr);
        fputs("-- Protected under the GNU GPL License\n",stderr);
        fputs("--\n",stderr);
        fputs("-- WARNING: This file was generated by " __FILE__ "!\n",stderr);

        puts("with Interfaces;");
        puts("use Interfaces;");
	putchar('\n');
	printf("package WC.Host is\n\n");

	fprintf(stderr,"package body WC.Host is\n\n");

	puts("   -- The UNIX errno Data Type :");
	fflush(stdout);
	fflush(stderr);

	system("./Gen_Errno");

        printf("   subtype File_Descriptor is %s;\n",data_type("Integer",sizeof(int)));
        printf("   subtype Off_T is %s;\n",data_type("Integer",sizeof(off_t)));
        printf("   subtype Ssize_T is %s;\n",data_type("Integer",sizeof(ssize_t)));

        putchar('\n');

	puts("   -- Platform :");

	printf("   Platform :          constant String := \"%s\";\n",PLATFORM);
	printf("   Platform_Release :  constant String := \"%s\";\n",RELEASE);
	printf("   Platform_Hardware : constant String := \"%s\";\n",HARDWARE);


	puts("\n   -- open(2)/creat(2)");
        int_const("O_RDONLY",O_RDONLY);
        int_const("O_WRONLY",O_WRONLY);
        int_const("O_RDWR",O_RDWR);
        int_const("O_CREAT",O_CREAT);
        int_const("O_EXCL",O_EXCL);
        int_const("O_TRUNC",O_TRUNC);
        int_const("O_APPEND",O_APPEND);

        putchar('\n');

	puts("   -- Endian Related");
        for ( x=0; x<2; ++x )
            u16.cc[x] = x + 1;
        printf("   HOST_MAP16: constant Unsigned_16 := %u; -- Host form of Big Endian 0x0102\n",u16.u_16);
        u16.u_16 = 0x0102;
        printf("   BIGE_MAP16: constant Unsigned_16 := %u; -- Net form of Big Endian 0x0102\n",u16.u_16);

        for ( x=0; x<4; ++x )
            u32.cc[x] = x + 1;
        printf("   HOST_MAP32: constant Unsigned_32 := %u; -- Host form of Big Endian 0x01020304\n",u32.u_32);
        u32.u_32 = 0x01020304;
        printf("   BIGE_MAP32: constant Unsigned_32 := %u; -- Net form of Big Endian 0x01020304\n",u32.u_32);

        for ( x=0; x<8; ++x )
            u64.cc[x] = x + 1;
        printf("   HOST_MAP64: constant Unsigned_64 := %llu; -- Host form of Big Endian 0x01020304050607\n",u64.u_64);
        u64.u_64 = 0x01020304050607;
        printf("   BIGE_MAP64: constant Unsigned_64 := %llu; -- Net form of Big Endian 0x01020304050607\n\n",u64.u_64);

        /*
         * lseek paramters :
         */
        printf("   -- lseek(2)\n");
        printf("   SEEK_SET:  constant integer := %d;\n",SEEK_SET);
        printf("   SEEK_CUR:  constant integer := %d;\n",SEEK_CUR);
        printf("   SEEK_END:  constant integer := %d;\n\n",SEEK_END);

	/*
	 * Required Constants :
	 */
	puts("   -- Sound Support: ioctl(2)");
	printf("   SNDCTL_DSP_RESET:       constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_RESET,(int)SNDCTL_DSP_RESET);
	printf("   SNDCTL_DSP_SYNC:        constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_SYNC,(int)SNDCTL_DSP_SYNC);
	printf("   SNDCTL_DSP_SPEED:       constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_SPEED,(int)SNDCTL_DSP_SPEED);
	printf("   SNDCTL_DSP_STEREO:      constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_STEREO,(int)SNDCTL_DSP_STEREO);
	printf("   SNDCTL_DSP_GETBLKSIZE:  constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_GETBLKSIZE,(int)SNDCTL_DSP_GETBLKSIZE);
	printf("   SNDCTL_DSP_SAMPLESIZE:  constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_SAMPLESIZE,(int)SNDCTL_DSP_SAMPLESIZE);

	/*
	 * The following can be enabled if required. These are disabled by default,
	 * to avoid compile errors on future versions of Linux/FreeBSD, should some
	 * of all of these become discontinued for some reason.
	 */
#if 0
	printf("   SNDCTL_DSP_CHANNELS:    constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_CHANNELS,(int)SNDCTL_DSP_CHANNELS);
	printf("   SNDCTL_DSP_POST:        constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_POST,(int)SNDCTL_DSP_POST);
	printf("   SNDCTL_DSP_SUBDIVIDE:   constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_SUBDIVIDE,(int)SNDCTL_DSP_SUBDIVIDE);
	printf("   SNDCTL_DSP_SETFRAGMENT: constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_SETFRAGMENT,(int)SNDCTL_DSP_SETFRAGMENT);
	printf("   SNDCTL_DSP_GETFMTS:     constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_GETFMTS,(int)SNDCTL_DSP_GETFMTS);
	printf("   SNDCTL_DSP_SETFMT:      constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_SETFMT,(int)SNDCTL_DSP_SETFMT);
	printf("   SNDCTL_DSP_GETOSPACE:   constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_GETOSPACE,(int)SNDCTL_DSP_GETOSPACE);
	printf("   SNDCTL_DSP_GETISPACE:   constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_GETISPACE,(int)SNDCTL_DSP_GETISPACE);
	printf("   SNDCTL_DSP_NONBLOCK:    constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_NONBLOCK,(int)SNDCTL_DSP_NONBLOCK);
	printf("   SNDCTL_DSP_GETCAPS:     constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_GETCAPS,(int)SNDCTL_DSP_GETCAPS);
	printf("   SNDCTL_DSP_GETTRIGGER:  constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_GETTRIGGER,(int)SNDCTL_DSP_GETTRIGGER);
	printf("   SNDCTL_DSP_SETTRIGGER:  constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_SETTRIGGER,(int)SNDCTL_DSP_SETTRIGGER);
	printf("   SNDCTL_DSP_GETIPTR:     constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_GETIPTR,(int)SNDCTL_DSP_GETIPTR);
	printf("   SNDCTL_DSP_GETOPTR:     constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_GETOPTR,(int)SNDCTL_DSP_GETOPTR);
	printf("   SNDCTL_DSP_MAPINBUF:    constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_MAPINBUF,(int)SNDCTL_DSP_MAPINBUF);
	printf("   SNDCTL_DSP_MAPOUTBUF:   constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_MAPOUTBUF,(int)SNDCTL_DSP_MAPOUTBUF);
	printf("   SNDCTL_DSP_SETSYNCRO:   constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_SETSYNCRO,(int)SNDCTL_DSP_SETSYNCRO);
	printf("   SNDCTL_DSP_SETDUPLEX:   constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_SETDUPLEX,(int)SNDCTL_DSP_SETDUPLEX);
	printf("   SNDCTL_DSP_GETODELAY:   constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_GETODELAY,(int)SNDCTL_DSP_GETODELAY);
	printf("   SNDCTL_DSP_PROFILE:     constant integer := %11d; -- 16#%08X#\n",(int)SNDCTL_DSP_PROFILE,(int)SNDCTL_DSP_PROFILE);
#endif

	have_sched();

	puts("   procedure Squash_Root;");
	fputs("\n"
	      "   procedure squash_root is\n",stderr);
	fputs("      procedure C_squash_root;\n",stderr);
	fputs("      pragma import(C,C_squash_root,\"squash_root\");\n",stderr);
	fputs("   begin\n",stderr);
	fputs("      C_squash_root;\n",stderr);
	fputs("   end Squash_Root;\n",stderr);
	
	printf("\nend WC.Host;\n");
	fprintf(stderr,"\nend WC.Host;\n");

	return 0;
}

/* $Source: /home/cvsroot/bush/src/ADAVOX-0.51/wc/hostconst.c,v $ */
