From 68c21dd3e6f89976d995ffc791f3f68e13871a1e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zolt=C3=A1n=20Mizsei?= <zmizsei@extrowerk.com>
Date: Wed, 25 Jan 2017 13:45:50 +0100
Subject: [PATCH] Haiku support for ATLAS

---
 CONFIG/include/atlconf.h            |   6 +-
 CONFIG/src/Makefile                 |   8 ++
 CONFIG/src/backend/Make.ext         |   2 +
 CONFIG/src/backend/archinfo_haiku.c | 266 ++++++++++++++++++++++++++++++++++++
 CONFIG/src/probe_OS.c               |   1 +
 CONFIG/src/probe_comp.c             |   9 ++
 6 files changed, 289 insertions(+), 3 deletions(-)
 create mode 100644 CONFIG/src/backend/archinfo_haiku.c

diff --git a/CONFIG/include/atlconf.h b/CONFIG/include/atlconf.h
index e51d56d..8a5277b 100644
--- a/CONFIG/include/atlconf.h
+++ b/CONFIG/include/atlconf.h
@@ -6,12 +6,12 @@
 #include <string.h>
 #include <assert.h>
 
-#define NOS 13
+#define NOS 14
 static char *osnam[NOS] =
    {"UNKNOWN", "Linux", "SunOS", "SunOS4", "OSF1", "IRIX", "AIX",
-    "Win9x", "WinNT", "Win64", "HPUX", "FreeBSD", "OSX"};
+    "Win9x", "WinNT", "Win64", "HPUX", "FreeBSD", "OSX", "Haiku"};
 enum OSTYPE {OSOther=0, OSLinux, OSSunOS, OSSunOS4, OSOSF1, OSIRIX, OSAIX,
-             OSWin9x, OSWinNT, OSWin64, OSHPUX, OSFreeBSD, OSOSX};
+             OSWin9x, OSWinNT, OSWin64, OSHPUX, OSFreeBSD, OSOSX, OSHAIKU};
 #define OSIsWin(OS_) ( ((OS_) == OSWinNT) || ((OS_) == OSWin9x) || \
                        ((OS_) == OSWin64) )
 
diff --git a/CONFIG/src/Makefile b/CONFIG/src/Makefile
index 212b9d7..5143ee2 100644
--- a/CONFIG/src/Makefile
+++ b/CONFIG/src/Makefile
@@ -426,6 +426,11 @@ IRunArchInfo_freebsd: xarchinfo_freebsd
 	$(MAKE) $(atlrun) atldir=$(mydir) exe=xarchinfo_freebsd args="$(args)" \
                 redir=config0.out
 	- cat config0.out
+IRunArchInfo_haiku: xarchinfo_haiku
+	- rm -f config0.out
+	$(MAKE) $(atlrun) atldir=$(mydir) exe=xarchinfo_haiku args="$(args)" \
+                redir=config0.out
+	- cat config0.out
 IRunArchInfo_linux: xarchinfo_linux
 	- rm -f config0.out
 	$(MAKE) $(atlrun) atldir=$(mydir) exe=xarchinfo_linux args="$(args)" \
@@ -457,6 +462,9 @@ xarchinfo_sunos : $(SRCdir)/backend/archinfo_sunos.c atlconf_misc_BE.o
 xarchinfo_freebsd : $(SRCdir)/backend/archinfo_freebsd.c atlconf_misc_BE.o
 	$(CC) $(CCFLAGS) -o xarchinfo_freebsd $(SRCdir)/backend/archinfo_freebsd.c \
               atlconf_misc_BE.o
+xarchinfo_haiku : $(SRCdir)/backend/archinfo_haiku.c atlconf_misc_BE.o
+	$(CC) $(CCFLAGS) -o xarchinfo_haiku $(SRCdir)/backend/archinfo_haiku.c \
+              atlconf_misc_BE.o
 xarchinfo_linux : $(SRCdir)/backend/archinfo_linux.c atlconf_misc_BE.o
 	$(CC) $(CCFLAGS) -o xarchinfo_linux $(SRCdir)/backend/archinfo_linux.c \
               atlconf_misc_BE.o
diff --git a/CONFIG/src/backend/Make.ext b/CONFIG/src/backend/Make.ext
index 4743353..ecc79d9 100644
--- a/CONFIG/src/backend/Make.ext
+++ b/CONFIG/src/backend/Make.ext
@@ -163,6 +163,8 @@ archinfo_linux.c : $(basA)
 	$(extC) -b $(basA) -o archinfo_linux.c rout=archinfo_linux
 archinfo_freebsd.c : $(basA)
 	$(extC) -b $(basA) -o archinfo_freebsd.c rout=archinfo_freebsd
+archinfo_haiku.c : $(basA)
+	$(extC) -b $(basA) -o archinfo_haiku.c rout=archinfo_haiku
 archinfo_sunos.c : $(basA)
 	$(extC) -b $(basA) -o archinfo_sunos.c rout=archinfo_sunos
 archinfo_irix.c : $(basA)
diff --git a/CONFIG/src/backend/archinfo_haiku.c b/CONFIG/src/backend/archinfo_haiku.c
new file mode 100644
index 0000000..e177790
--- /dev/null
+++ b/CONFIG/src/backend/archinfo_haiku.c
@@ -0,0 +1,266 @@
+#include "atlconf.h"
+
+#include <posix/unistd.h>
+
+void PrintUsage(char *name, int i)
+{
+   fprintf(stderr, "USAGE: %s -v (verb) -b (@ bits) -a (arch) -n (ncpu) -c <ncache> -C <lvl> (cache size) -m (Mhz) -t (cpu throttling)\n", name);
+   exit(i);
+}
+
+int GetFlags(int nargs, char **args, int *CacheLevel)
+{
+   int i, flag = 0;
+
+   *CacheLevel = 0;
+   for (i=1; i < nargs; i++)
+   {
+      if (args[i][0] != '-') PrintUsage(args[0], i);
+      switch(args[i][1])
+      {
+      case 'n':
+         flag |= Pncpu;
+         break;
+      case 'c':
+         flag |= Pncache;
+         break;
+      case 'C':
+         if (++i > nargs)
+            PrintUsage(args[0], i);
+         *CacheLevel = atoi(args[i]);
+         break;
+      case 'v':
+         flag |= Pverb;
+         break;
+      case 'm':
+         flag |= PMhz;
+         break;
+      case 'a':
+         flag |= Parch;
+         break;
+      case 'b':
+         flag |= P64;
+         break;
+      case 't':
+         flag |= Pthrottle;
+         break;
+      default:
+         PrintUsage(args[0], i);
+      }
+   }
+   if (!flag)
+     flag = Parch | P64;
+   return(flag);
+}
+
+enum MACHTYPE ProbeArch()
+{
+   enum ARCHFAM fam;
+   enum MACHTYPE mach=MACHOther;
+   int ierr, i;
+   char *res;
+
+   fam = ProbeArchFam(NULL);
+   switch(fam)
+   {
+   case AFPPC: /* don't know */
+      res = atlsys_1L(NULL, "sysctl hw.model", 0, 0);
+      if (res)
+      {
+         if (strstr(res, "PowerMac"))
+         {
+            if (strstr(res,"c1,2")||strstr(res,"c3,1")||strstr(res,"c3,2")||
+                strstr(res,"c3,3")||strstr(res,"c3,4")||strstr(res,"c3,5")||
+                strstr(res,"c3,6")||strstr(res,"c4,2")||strstr(res,"c4,5")||
+                strstr(res,"c5,1")||strstr(res,"c10,1"))
+               mach = PPCG4;
+            else if (strstr(res,"c11,2")|| strstr(res,"c12,1")||
+                     strstr(res,"c7,2") || strstr(res,"c7,3") ||
+                     strstr(res,"c8,1") || strstr(res,"c8,1") ||
+                     strstr(res,"c8,2") || strstr(res,"c9,1"))
+               mach = PPCG5;
+         }
+         else if (strstr(res, "PowerBook"))
+         {
+            if (strstr(res,"k3,2") || strstr(res,"k3,3") || strstr(res,"k3,4")||
+                strstr(res,"k3,5") || strstr(res,"k5,1") || strstr(res,"k5,2")||
+                strstr(res,"k5,3") || strstr(res,"k5,4") || strstr(res,"k5,5")||
+                strstr(res,"k5,6") || strstr(res,"k5,7") || strstr(res,"k5,8")||
+                strstr(res,"k5,9") || strstr(res,"k6,1") || strstr(res,"k6,2")||
+                strstr(res,"k6,3") || strstr(res,"k6,4") || strstr(res,"k6,5")||
+                strstr(res,"k6,7") || strstr(res,"k6,8"))
+               mach = PPCG4;
+         }
+         else if (strstr(res, "RackMac"))
+         {
+            if (strstr(res, "c1,1") || strstr(res, "c1,2"))
+               mach = PPCG4;
+            else if (strstr(res, "c3,1"))
+               mach = PPCG5;
+         }
+         free(res);
+      }
+      break;
+   case AFSPARC: /* don't know */
+      break;
+   case AFALPHA:
+      #if 0
+      res = atlsys_1L(NULL, "sysctl hw.model", 0, 0);
+      if (res)
+      {
+         if (strstr(res, "433au")) mach = Dec21164;
+         else if (strstr(res, "XP1000")) mach = Dec21264;
+         free(res);
+      }
+      #endif
+      break;
+   case AFIA64: /* don't know */
+      break;
+   case AFX86:
+      res = atlsys_1L(NULL, "sysctl hw.model", 0, 0);
+      if (res)
+      {
+         if (strstr(res, "Pentium Pro")) mach = IntPPRO;
+         else if (strstr(res, "Pentium III")) mach = IntPIII;
+         else if (strstr(res, "Pentium II ")) mach = IntPII;
+         else if (strstr(res, "Athlon")) mach = AmdAthlon;
+         else if (strstr(res, "AMD-K7")) mach = AmdAthlon;
+         else if (strstr(res, "32 bit Hammer")) mach = AmdHammer;
+         else if (strstr(res, "64 bit Hammer")) mach = AmdHammer;
+         else if (strstr(res, "Pentium/P55C")) mach = IntP5MMX; /* sent by */
+         else if (strstr(res, "Pentium")) mach=IntP5;       /* Nakata Maho */
+         else if (strstr(res, "iMac4,1")) mach=IntCoreDuo;
+         free(res);
+      }
+      break;
+   default:;
+   }
+   return(mach);
+}
+int ProbeNCPU()
+{
+   int ncpu = 0;
+   ncpu = sysconf(_SC_NPROCESSORS_ONLN);
+   
+   if (ncpu < 1)
+   {
+   	   ncpu = 1;
+   }
+
+   return(ncpu);
+}
+
+int ProbePointerBits(int *sure)
+{
+   int i;
+   char *uname;
+   char *cmnd, *res;
+
+   *sure = 0;
+/*
+ * This probe should be running on backend; if its ptr length is 8, we've
+ * definitely got a 64 bit machine
+ * NOTE: getting 4 could be a result of compiler flags on a 64-bit arch,
+ * so reverse is not dispositive
+ */
+   if (sizeof(void*) == 8)
+   {
+      *sure = 1;
+      return(64);
+   }
+
+/*
+ * Note this is a weak probe, archinfo_x86 much better . . .
+ */
+   uname = FindUname(NULL);
+   i = strlen(uname) + 4;
+   cmnd = malloc(sizeof(char)*i);
+   assert(cmnd);
+   sprintf(cmnd, "%s -a", uname);
+
+   res = atlsys_1L(NULL, cmnd, 0, 0);
+   free(cmnd);
+   if (res)
+   {
+/*
+ *    If uname is a known 64-bit platform, we're sure we've got OS support
+ *    for 64bits (may not have compiler support, but that's not our fault)
+ */
+      if (strstr(res, "x86_64") || strstr(res, "ppc64") || strstr(res, "ia64"))
+      {
+         *sure = 1;
+         free(res);
+         return(64);
+      }
+      free(res);
+   }
+   return(32);
+}
+
+int ProbeMhz()
+{
+   int mhz=0;
+   char *res;
+   res = atlsys_1L(NULL, "sysinfo -cpu | fgrep MHz", 0, 0);
+   if (res)
+   {
+      mhz = GetIntBeforeWord("MHz", res);
+      if (mhz == BADINT) mhz = 0;
+      free(res);
+   }
+   if (!mhz)
+   {
+      res = atlsys_1L(NULL, "sysinfo -cpu | fgrep GHz", 0, 0);
+      if (res)
+      {
+         mhz = GetIntBeforeWord("GHz", res);
+         mhz = (mhz == BADINT) ? 0 : mhz*1000;
+         free(res);
+      }
+   }
+   return(mhz);
+}
+
+int ProbeThrottle()
+/*
+ * RETURNS: 1 if cpu throttling is detected, 0 otherwise
+ */
+{
+   int iret=0; /* Haiku d6esn't supports throttling yet */
+   return(iret);
+}
+
+main(int nargs, char **args)
+{
+   int flags, CacheLevel, ncpu, mhz, bits, sure;
+   enum MACHTYPE arch=MACHOther;
+
+   flags = GetFlags(nargs, args, &CacheLevel);
+   if (flags & Parch)
+   {
+      arch = ProbeArch();
+      if (flags & Pverb)
+         printf("Architecture detected as %s.\n", machnam[arch]);
+      printf("MACHTYPE=%d\n", arch);
+   }
+   if (flags & Pncpu)
+      printf("NCPU=%d\n", ProbeNCPU());
+   if (flags & PMhz)
+      printf("CPU MHZ=%d\n", ProbeMhz());
+   if (flags & Pthrottle)
+      printf("CPU THROTTLE=%d\n", ProbeThrottle());
+   if (flags & P64)
+   {
+      bits = ProbePointerBits(&sure);
+      printf("PTR BITS=%d, SURE=%d\n", bits, sure);
+   }
+
+/*
+ * Here for future, presently unsupported
+ */
+   if (flags & Pncache)
+      printf("NCACHES=0\n");
+   if (flags & PCacheSize)
+      printf("%d Cache size (kb) = 0\n", CacheLevel);
+   exit(0);
+}
diff --git a/CONFIG/src/probe_OS.c b/CONFIG/src/probe_OS.c
index 1bdde49..5b2a241 100644
--- a/CONFIG/src/probe_OS.c
+++ b/CONFIG/src/probe_OS.c
@@ -59,6 +59,7 @@ enum OSTYPE ProbeOS(int verb, char *targ)
          else ierr = 1;
       }
       else if (strstr(res, "HP-UX")) OS = OSHPUX;
+      else if (strstr(res, "Haiku")) OS = OSHAIKU;
       else ierr = 1;
       free(res);
    }
diff --git a/CONFIG/src/probe_comp.c b/CONFIG/src/probe_comp.c
index 1652e24..c99c194 100644
--- a/CONFIG/src/probe_comp.c
+++ b/CONFIG/src/probe_comp.c
@@ -1284,6 +1284,10 @@ char *FindGoodGcc(enum OSTYPE OS, enum MACHTYPE arch, int verb, char *targ,
    {
       OSpaths = "/sw/bin /opt/local/bin /opt/local/sbin";
    }
+   if (OS == OSHAIKU)  /* Haiku is a special snowflake */
+   {
+      OSpaths = "/system/bin /system/bin/x86 /bin /bin/x86";
+   }
 /*
  * We first look in any high-priority OS-specific spots for the right files
  */
@@ -1440,6 +1444,11 @@ char *FindGoodGfortran(enum OSTYPE OS, enum MACHTYPE arch, int verb,
    {
       OSpaths = "/sw/bin /opt/local/bin /opt/local/sbin";
    }
+
+   if (OS == OSHAIKU)  /* Haiku is a special snowflake */
+   {
+      OSpaths = "/system/bin /system/bin/x86 /bin /bin/x86";
+   }
 /*
  * We first look in any high-priority OS-specific spots for the right files
  */
-- 
2.11.0

