
/*
 *             Automatically Tuned Linear Algebra Software v3.2.1
 *                    (C) Copyright 1998 R. Clint Whaley                     
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions, and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *   3. The name of the University of Tennessee, the ATLAS group,
 *      or the names of its contributers may not be used to endorse
 *      or promote products derived from this software without specific
 *      written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE. 
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <ctype.h>
#include <string.h>

#define MAXL2SIZE 4194304
#define Mciswspace(C) ( (((C) > 8) && ((C) < 14)) || ((C) == 32) )
#define Mlowcase(C) ( ((C) > 64 && (C) < 91) ? (C) | 32 : (C) )


char *machnam[33] = {"21264", "21164", "21064", "HPPA8K", "HP9735", 
                     "POWER", "POWER2Thin", "POWER2Wide", "POWER3",
                     "P5", "P5MMX", "PPRO", "PII", "PIII", "P4", "ATHLON",
                     "IA64Itan",
                     "SGIIP28", "SGIIP27", "SGIIP32", "SGIIP22", "SGIIP30",
                     "SunMS", "SunSS", "SunUS1", "SunUS2", "SunUS4",
                     "SunUS5", "SunUSX", "PPC604e", "PPC604", "PPCG4", 
                     "UNKNOWN"};
enum MACHTYPE {Dec21264, Dec21164, Dec21064, HPPA8K, HP9K735,
               IbmPwr,  IbmTPwr2, IbmWPwr2, IbmPwr3,
               IntP5, IntP5MMX, IntPPRO, IntPII, IntPIII, IntP4, AmdAthlon, 
               IA64Itan,
               SgiIP28, SgiIP27, SgiIP32, SgiIP22, SgiIP30, 
               SunMS, SunSS, SunUS1, SunUS2, SunUS4, SunUS5, SunUSX, 
               PPC604e, PPC604, PPCG4, MACHOther};
char *osnam[11] = {"Linux", "SunOS", "SunOS4", "OSF1", "IRIX", "AIX", 
                  "Win9x", "WinNT", "HPUX", "FreeBSD", "Other/UNKNOWN"};
enum OSTYPE {OSLinux=0, OSSunOS, OSSunOS4, OSOSF1, OSIRIX, OSAIX, 
             OSWin9x, OSWinNT, OSHPUX, OSFreeBSD, OSOther};

enum LINUXARCH {LAPPC, LASPARC, LAALPHA, LAX86, LAIA64, LAOTHER};

enum F2CNAME {f2c_Add_=0, f2c_Add__, f2c_NoChange, f2c_UpCase, f2c_NamErr};
enum F2CINT {FintCint=0, FintClong, FintCshort, f2c_IntErr};
enum F2CSTRING {fstrSun=0, fstrCray, fstrStructVal, fstrStructPtr, f2c_StrErr};

/* NOTE on ISA extensions, order is from most preferred to least */
#define NISA 3
#define NISAp1 4
char *ISAXNAM[NISAp1] = {"SSE1", "3DNow2", "3DNow1", ""};
enum ISAEXT {ISA_SSE1=0, ISA_3DNow2, ISA_3DNow1, ISA_None};
char *usermmnam[2] = {"", "GOTO"};
enum USERGEMM {UG_None=0, UG_GOTO};

int XCOMP=0, THREADS=0, USEWINF77=0, NLINES=0, ISWIN=0;
char TARGNAM[512];
enum MACHTYPE mach=MACHOther;

#define my_join(pre, nam) pre ## nam
#define Mstr2(m) # m
#define Mstr(m) Mstr2(m)
#define OSIsWin(OS_) ( ((OS_) == OSWin9x) || ((OS_) == OSWinNT) )
#define MachIsAlpha(mach_) \
   ( ((mach_) == Dec21264) || ((mach_) == Dec21164) || ((mach_) == Dec21064) )
#define MachIsX86(mach_) \
   ( ((mach_) == IntP5) || ((mach_) == IntP5MMX) || ((mach_) == IntPPRO) || \
     ((mach_) == IntPPII) || || ((mach_) == IntPIII) || \
     ((mach_) == IntP4) || ((mach_) == AmdAthlon) || ((mach_) == IA64Itan) )
#define MachIsUS(mach_) \
   ( ((mach_) == SunUS1) || ((mach_) == SunUS2) || ((mach_) == SunUS2) || \
     ((mach_) == SunUS4) || ((mach_) == SunUS5) || ((mach_) == SunUSX) )

int QUERY=0;
FILE *fpI, *fparch;

#include <time.h>
void GetDate(int *month, int *day, int *year, int *hour, int *min)
{
   time_t tv;
   struct tm *tp;

   tv = time(NULL);
   tp = localtime(&tv);
   *month = tp->tm_mon + 1;
   *day = tp->tm_mday;
   *year = tp->tm_year + 1900;
   *hour = tp->tm_hour;
   *min = tp->tm_min;
}

long GetInt(FILE *fpin, long Default, char *spc, char *expstr)
/*
 * Gets a signed integral type from fpin.  If nothing or garbage is entered,
 * Default is returned.
 */
{
   char str[64];
   long iin;
   if (expstr) fprintf(stdout, "%sEnter %s [%d]: ", spc, expstr, Default);
   if (fgets(str, 64, fpin) == NULL) return(Default);
   if (sscanf(str, " %ld ", &iin) != 1) return(Default);
   return(iin);
}

long GetIntRange(long Default, long Min, long Max, char *spc, char *expstr)
{
   long i;
   int keepOn=0;
   do
   {
      i = GetInt(stdin, Default, spc, expstr);
      if (i > Max)
      {
         keepOn = 1;
         fprintf(stderr, "\n%d larger than max value of %d.  Try again.\n\n",
                 i, Max);
      }
      else if (i < Min)
      {
         keepOn = 1;
         fprintf(stderr, "\n%d smaller than min value of %d.  Try again.\n\n",
                 i, Min);
      }
      else keepOn = 0;
   }
   while (keepOn);
   return(i);
}

long GetIntVer(long Default, long Min, long Max, char *spc, char *expstr)
{
   long i, j;

   do 
   {
      i = GetIntRange(Default, Min, Max, spc, expstr);
      fprintf(stdout, "%s   You entered: %d\n", spc, i);
      j = GetIntRange(0, 0, 1, spc, "1 to reenter, 0 accepts");
   }
   while(j);
   return(i);
}


void GetString(FILE *fpin, char *Default, char *spc, char *expstr, 
               int len, char *str0)
/*
 * Get a string of length len, not including NULL terminator; pads
 * any extra len with NULLs
 */
{
   char str[512], *sp;
   int i;

   assert(len+1 <= 512);
   if (expstr)
   {
      if (Default) fprintf(stdout, "%sEnter %s [%s]: ", spc, expstr, Default);
      else fprintf(stdout, "%sEnter %s:", spc, expstr);
   }
   sp = fgets(str, 512, fpin);
   if ( (sp == NULL) || (str[0] == '\0') || (str[0] == '\n') )
   {
      if (Default) strcpy(str0, Default);
      else str0[0] = '\0';
      return;
   }
   str[len] = '\0';
   for (i=0; str0[i] = str[i]; i++);
   if (i) i--;
   while (Mciswspace(str0[i])) i--;
   while (++i < len) str0[i] = '\0';
   str0[i] = '\0';
}

void GetStrVer(char *def, char *spc, char *expstr, int len, char *str)
{
   int i;

   do
   {
      GetString(stdin, def, spc, expstr, len, str);
      fprintf(stdout, "%sYou have entered '%s'\n", spc, str);
      i = GetIntRange(0, 0, 1, spc, "1 to reenter, 0 to accept");
   }
   while(i);
}

int IsYes(char def, char *spc, char *expstr)
{
   char ch, ln[256];
   fprintf(stdout, "%s%s [%c]: ", spc, expstr, def);
   if (fgets(ln, 256, stdin) == NULL) ch=def;
   else if (ln[0] == '\0' || ln[0] == '\n') ch=def;
   else ch = ln[0];
   return( ((ch == 'y') || (ch == 'Y')) );
}

char GetChar(char def, char *spc, char *expstr)
{
   char ch, ln[256];
   fprintf(stdout, "%s%s [%c]: ", spc, expstr, def);
   if (fgets(ln, 256, stdin) == NULL) ch=def;
   else if (ln[0] == '\0' || ln[0] == '\n') ch=def;
   else ch = ln[0];
   return(ch);
}

int FileIsThere(char *nam)
{
   FILE *fp;

   fp = fopen(nam, "r");
   if (fp == NULL) return(0);
   fclose(fp);
   return(1);
}

#include <stdarg.h>
#define ATL_UseStringVarArgs
void ATL_mprintf(int np, ...)
/*
 * Prints same message to np output file streams
 */
{
   va_list argptr;
   FILE *fp[8];
   char *form;
   int i;
   #ifdef ATL_UseStringVarArgs
      char ln[1024];
   #endif

   if (np > 0)
   {
      va_start(argptr, np);
      assert(np <= 8);
      for (i=0; i < np; i++) fp[i] = va_arg(argptr, FILE *);
      form = va_arg(argptr, char *);
      #ifdef ATL_UseStringVarArgs
         assert(strlen(ln) < 1024);/* sanity test only, will not stop overrun */
         vsprintf(ln, form, argptr);
         va_end(argptr);
         for (i=0; i < np; i++) if (fp[i]) fprintf(fp[i], ln);
      #else
         for (i=0; i < np; i++) if (fp[i]) vfprintf(fp[i], form, argptr);
         va_end(argptr);
      #endif
   }
}

int GetFirstInt(char *ln)
{
   int i, iret=0;
   for (i=0; ln[i]; i++)
   {
      if (isdigit(ln[i]))
      {
         sscanf(ln+i, "%d", &iret);
         break;
      }
   }
   return(iret);
}

int GetLastInt(char *ln)
{
   int i, iret=0;
   for (i=0; ln[i]; i++);
   if (i > 0) for (i--; i > 0 && !isdigit(ln[i]); i--);
   if (i > 0 || (i == 0 && isdigit(ln[0])))
   {
      while(isdigit(ln[i]) && i > 0) i--;
      if (!isdigit(ln[i])) i++;
      sscanf(ln+i, "%d", &iret);
   }
   return(iret);
}

int fNumLines(char *fnam)
{
   FILE *fp;
   char ln[256];
   int i;

   fp = fopen(fnam, "r");
   assert(fp != NULL);
   for (i=0; fgets(ln, 256, fp); i++);
   return(i);
}

char *CmndResults(char *targ, char *cmnd)
{
   static char tnam[128];
   static int FirstTime=1;
   char ln[512];

   if (FirstTime)
   {
      FirstTime = 0;
      assert(tmpnam(tnam));
   }
   if (targ) sprintf(ln, "rsh %s \"%s\" > %s 2>&1 \n", targ, cmnd, tnam);
   else sprintf(ln, "%s > %s 2>&1\n", cmnd, tnam);
   if (!system(ln)) return(tnam);
   else return(NULL);
}

int CmndOneLine(char *targ, char *cmnd, char *ln)
/*
 * executes a system call with contents of cmnd, returns the output in ln;
 * Returns value returned by system call
 * if targ is set, we rsh to that machine
 */
{
   char ln2[512];
   int i;
   FILE *fp;
   char *tnam;

   ln[0] = '\0';
   tnam = CmndResults(targ, cmnd);
   if (tnam)
   {
      fp = fopen(tnam, "r");
      assert(fp);
      if (!fgets(ln, 512, fp)) ln[0] = '\0';
      fclose(fp);
      return(0);
   }
   else ln[0] = '\0';
   return(1);
}

int GetScreenHeight()
/* 
 * Returns the number of vertical lines window has
 */
{
   int i;
   for (i=160; i; i--) fprintf(stdout, "%03d\n", i);
   i = GetIntRange(0, 0, 160, "", "number at top left of screen");
   return(i);
}

void GetEnter(FILE *fpout)
{
   char ln[128];
   fprintf(fpout, "---------- PRESS ENTER TO CONTINUE ---------- ");
   fgets(ln, 128, stdin);
}

int DisplayFile(char *fnam, FILE *fpout, int nlines)
{
   FILE *fp;
   char ln[256];
   int i, GoOn=1;

   fp = fopen(fnam, "r");
   if (fp == NULL)
   {
      fprintf(stderr, "Unable to open file '%s', continuing without display.\n",
              fnam);
      return(-1);
   }
   if (nlines)
   {
      do
      {
         for (i=0; i < nlines; i++)
         {
            GoOn = (int) fgets(ln, 256, fp);
            if (!GoOn) break;
            fprintf(fpout, "%s", ln);
         }
         if (GoOn) GetEnter(stdout);
         else break;
      }
      while(GoOn);
   }
   else while (fgets(ln, 256, fp)) fprintf(fpout, "%s", ln);
   i = ferror(fp);
   fclose(fp);
   return(i);
}

int DisplayFile0(char *fnam, FILE *fpout)
{
   FILE *fp;
   char ln[256];
   int i;

   fp = fopen(fnam, "r");
   if (fp == NULL)
   {
      fprintf(stderr, "Unable to open file '%s', continuing without display.\n",
              fnam);
      return(-1);
   }
   while (fgets(ln, 256, fp)) fprintf(fpout, "%s", ln);
   i = ferror(fp);
   fclose(fp);
   return(i);
}

int FoundInFile(char *fnam, char *str)
{
   FILE *fp;
   int found=0;
   char ln[256];

   fp = fopen(fnam, "r");
   assert(fp);
   while (fgets(ln, 256, fp))
   {
      if (strstr(ln, str))
      {
         found=1;
         break;
      }
   }
   fclose(fp);
   return(found);
}

int FindFiles(char *dir, char *fnam, char ***files0)
{
   int i, j;
   FILE *fp;
   char ln[256];
   static int FirstTime=1;
   static char *fpp[32], files[32][256], tnam[128], fnd[128];

   if (FirstTime)
   {
      if (ISWIN)
      {
         if (FileIsThere("/usr/bin/find.exe")) strcpy(fnd, "/usr/bin/find");
         else if (FileIsThere("/bin/find.exe")) strcpy(fnd, "/bin/find");
         else if (FileIsThere("/usr/local/bin/find.exe"))
            strcpy(fnd, "/usr/local/bin/find");
         else strcpy(fnd, "find");
      }
      else
      {
         if (FileIsThere("/usr/bin/find")) strcpy(fnd, "/usr/bin/find");
         else if (FileIsThere("/bin/find")) strcpy(fnd, "/bin/find");
         else if (FileIsThere("/usr/local/bin/find"))
            strcpy(fnd, "/usr/local/bin/find");
         else strcpy(fnd, "find");
      }
      for (i=0; i < 32; i++) fpp[i] = files[i];
      assert(tmpnam(tnam));
      FirstTime=0;
   }
   *files0 = fpp;
   sprintf(ln, "%s %s/ -name \'%s\' 2> /dev/null > %s\n", fnd, dir, fnam, tnam);
   i = system(ln);
   fp = fopen(tnam, "r");
   if (fp)
   {
      for (i=0; i < 32; i++)
      {
         if (fgets(files[i], 256, fp) == NULL) break;
         for (j=0; files[i][j]; j++) if (files[i][j] == '\n') files[i][j] = ' ';
      }
      fclose(fp);
   }
   else
   {
      fprintf(stderr, "Find not working, error code %d\n", i);
      return(0);
   }
   remove(tnam);
   if (ISWIN && i == 0) /* for windows, search for differing file extensions */
   {
      if (!strstr(fnam, "\\.")) /* add .exe to files with no extension */
      {
         sprintf(ln, "%s\\.exe", fnam);
         i = FindFiles(dir, ln, files0);
      }
      else if (strstr(fnam, "\\.a")) /* search for .lib for libraries */
      {
         for (i=0; fnam[i] != '.'; i++) ln[i] = fnam[i];
         ln[i] = '.'; ln[i+1] = 'l'; ln[i+2] = 'i'; ln[i+3] = 'b'; 
         ln[i+4] = '\0';
         i = FindFiles(dir, ln, files0);
      }
   }
   return(i);
}

#define ISSEP(ch_) ( (ch_) == ':' )
int GetAllPaths(char ***mypaths0)
{
   char sep = ':';
   int i, j=0, np=1;
   char **mpaths, *sp;

   sp = getenv("PATH");
   for (i=0; sp[i]; i++) if (ISSEP(sp[i])) np++;
   mpaths = malloc(np * sizeof(char *));
   assert(mpaths);
   for (j=0; j < np; j++)
   {
      for (i=0; ( sp[i] && !ISSEP(sp[i]) ); i++);
      mpaths[j] = malloc((i+1)*sizeof(char));
      assert(mpaths[j]);
      strncpy(mpaths[j], sp, i);
      mpaths[j][i] = '\0';
      sp += i+1;
   }
   *mypaths0 = mpaths;
   return(np);
}

char **AddToPaths(int npaths0, char **paths0, int nnew, ...)
{
   va_list argptr;
   char **paths, *pp;
   int i, j, np = npaths0 + nnew;

   assert(npaths0 >= 0 && nnew >= 0);
   va_start(argptr, nnew);
   paths = malloc(np * sizeof(char*));
   for (i=0; i != npaths0; i++) paths[i] = paths0[i];
   free(paths0);
   for (i=0; i != nnew; i++)
   {
      pp = va_arg(argptr, char *);
      j = strlen(pp)+1;
      paths[i+npaths0] = malloc(j*sizeof(char*));
      assert(paths[i+npaths0]);
      strcpy(paths[i+npaths0], pp);
   }
   va_end(argptr);
   return(paths);
}

void KillPaths(int npaths, char **paths)
{
   int i;

   for (i=0; i < npaths; i++) free(paths[i]);
   free(paths);
}

int FindFirstInPath(char *nam, char *fnd)
/*
 * finds first instance of nam in your path, returns 0 if not found, 1 else
 */
{
   char ln[256], *sp, *cp;
   FILE *fp;

   sp = getenv("PATH");
   cp = ln;
   do
   {
      while (*sp && *sp != ':') *cp++ = *sp++;
      if (*sp) sp++;
      if (cp[-1] != '/') *cp++ = '/';
      strcpy(cp, nam);
      fp = fopen(ln, "r");
      if (ISWIN) /* for Windows, look for default file extensions */
      {
         if (!strstr(ln, "."))  /* add exe to files with no extension */
         {
            strcat(ln, ".exe");
            fp = fopen(ln, "r");
         }
      }
      if (fp != NULL)
      {
         fclose(fp);
         strcpy(fnd, ln);
         return(1);
      }
      cp = ln;
   }
   while(*sp);
   return(0);
}

int GccV278(char *GCC) /* determines if gcc is version 2.7.x or 2.8.x */
{
   char ln[256];
   char *fnam;
   int iret=0;

   sprintf(ln, "%s -v", GCC);
   fnam = CmndResults(NULL, ln);
   if (fnam)
   {
      if (FoundInFile(fnam, "version 2.8")) iret = 1;
      else if (FoundInFile(fnam, "version 2.7")) iret = 1;
   }
   return(iret);
}

void FindAllGccs(FILE *fpout, FILE *fplog, char *gcc, char *egcs, char *pgcc)
{
   char *tmpc = "CONFIG/tst.c";
   char *tnam = "CONFIG/tmp.t";
   char **files;
   char ln[256];
   char **dirs;
   int i, d, n, ND;
   FILE *fp;

   remove(tnam);
   ND = GetAllPaths(&dirs);
   dirs = AddToPaths(ND, dirs, 2, "/usr/bin", "usr/local");
   ND += 2;
   *pgcc = *egcs = *gcc = '\0';
   for (d=0; d < ND; d++)
   {
      n = FindFiles(dirs[d], "gcc", &files);
      for (i=0; i < n; i++)
      {
         sprintf(ln, "%s -v -c %s > %s 2>&1\n", files[i], tmpc, tnam);
         if (system(ln) == 0)
         {
            if (FoundInFile(tnam, "pgcc")) strcpy(pgcc, files[i]);
            else if (FoundInFile(tnam, "egcs")) strcpy(egcs, files[i]);
            else strcpy(gcc, files[i]);
         }
         remove(tnam);
         if (*gcc && *egcs && *pgcc) break;
      }
   }

   if (*gcc) ATL_mprintf(2, fplog, fpout, "   REGULAR GCC : %s\n", gcc);
   else ATL_mprintf(2, fplog, fpout, "   REGULAR GCC : not found\n");

   if (*egcs) ATL_mprintf(2, fplog, fpout, "   EGCS        : %s\n", egcs);
   else ATL_mprintf(2, fplog, fpout, "   EGCS        : not found\n");

   if (*pgcc) ATL_mprintf(2, fplog, fpout, "   PGCC        : %s\n", pgcc);
   else ATL_mprintf(2, fplog, fpout, "   PGCC        : not found\n");

   ATL_mprintf(2, fplog, fpout, "\n");
}

void FindTarZip(char *tar, char *gzip, char *gunzip)
{
   char *fw[3] = {"tar", "gzip", "gunzip"};
   char *fn[3];
   char **dirs, **files;
   int i, n, d, ND;

   fn[0] = tar; fn[1] = gzip; fn[2] = gunzip;
   ND = GetAllPaths(&dirs);
   dirs = AddToPaths(ND, dirs, 3, "/bin", "/usr/bin", "usr/local");
   ND += 3;
   *tar = *gzip = *gunzip = '\0';
   for (d=0; d < ND; d++)
   {
      for (i=0; i < 3; i++)
      {
         if (fn[i][0] == '\0')
         {
            n = FindFiles(dirs[d], fw[i], &files);
            if (n) strcpy(fn[i], files[0]);
         }
      }
      if (fn[0][0] != '\0' && fn[1][0] != '\0' && fn[2][0] != '\0') break;
   }
   if (*tar == '\0') strcpy(tar, "tar");
   if (*gzip == '\0') strcpy(gzip, "gzip");
   if (*gunzip == '\0') strcpy(gunzip, "gunzip");
}

int Wstrfndsub(char *fnd, char *sub, char *in, char *out)
/*
 * copies IN to OUT, replacing the first occurrence of FND with SUB
 * 1 if FND was found, 0 otherwise
 */
{
   char *sp;
   int i, j;

   sp = strstr(in, fnd);
   if (sp)
   {
      for (i=0; &in[i] != sp; i++) out[i] = in[i];
      for (j=i; out[j] = sub[j-i]; j++);
      for (i += strlen(fnd); out[j] = in[i]; j++, i++);
   }
   else strcpy(out, in);
   return(sp != NULL);
}

#define F2C_assert(cond_) \
{ \
   if (!(cond_)) \
   { \
      fprintf(stderr, "Assertion %s failed, line %d of %s\n", \
              Mstr(cond_), __LINE__, __FILE__); \
      fprintf(stderr, "Unable to figure F2C data\n\n"); \
      return; \
   } \
}

int findSolErr(FILE *fplog, char *redir, char *TOPdir, char *CC, char *CCFLAGS,
               char *MCC, char *MMFLAGS, char *XCC, char *XCCFLAGS)
{
   char *sp, *tnam = "CONFIG/config.tmp";
   char compdef[512], ln[640];
   int i;
   FILE *fp;

   sprintf(ln, "cd CONFIG ; make IGetSunVers %s\n", redir);
   system(ln);
   fp = fopen(tnam, "r");
   fgets(ln, 256, fp);
   fclose(fp);
   remove(tnam);
   for (i=0; !isdigit(ln[i]) && ln[i]; i++);
   if (isdigit(ln[i]))
   {
      fprintf(stdout, "   cc major version number: %c\n", ln[i]);
      if (ln[i] == '4')
      {
         sp = strstr(MMFLAGS, "-xO2");
         if (sp) sp[3] = '5';
      }
   }
   else fprintf(stdout, "   unable to find version in \'%s\'\n", ln);
   DisplayFile("CONFIG/SolErr.txt", stdout, NLINES);
   return(IsYes('y', "", "Use gcc for Level 3 BLAS compilation?"));
}

void findF2C(char *redir, char *targ, char *TOPdir, char *F77, char *F77FLAGS,
             char *FLINK0, char *FLFLAGS0, char *CC, char *CCFLAGS,
             enum F2CNAME *f2cnam, enum F2CINT *f2cint, enum F2CSTRING *f2cstr)
{
   char *namdef[4] = {"Add_", "Add__", "NoChange", "UpCase"};
   char *intdef[4]={"F77_INTEGER=int", "F77_INTEGER=long", "F77_INTEGER=short"};
   char *strdef[4] = {"SunStyle", "CrayStyle", "StructVal", "StructPtr"};
   char compdef[1024], ln[1024];
   char FLINK[512], FLFLAGS[512];
   char *tnam = "CONFIG/config.tmp";
   int i;
   FILE *fp;

   *f2cnam = f2c_NamErr;
   *f2cint = f2c_IntErr;
   *f2cstr = f2c_StrErr;
   Wstrfndsub("$(F77)", F77, FLINK0, FLINK);
   Wstrfndsub("$(F77FLAGS)", F77FLAGS, FLFLAGS0, FLFLAGS);
/*
 * Find naming strategy
 */
   if (targ)
      sprintf(compdef, "F77=%s F77FLAGS=\"%s\" FLINK=%s FLFLAGS=\"%s\" CC=%s CCFLAGS=\"%s\" mydir=%s/CONFIG tnam=%s atlrun=atlas_runX targ=%s",
              F77, F77FLAGS, FLINK, FLFLAGS, CC, CCFLAGS, TOPdir, tnam, targ);
   else
      sprintf(compdef, "F77=%s F77FLAGS=\"%s\" FLINK=%s FLFLAGS=\"%s\" CC=%s CCFLAGS=\"%s\" mydir=%s/CONFIG tnam=%s",
              F77, F77FLAGS, FLINK, FLFLAGS, CC, CCFLAGS, TOPdir, tnam);
   sprintf(ln, "cd CONFIG ; make IRunName %s %s\n", compdef, redir);
   F2C_assert(system(ln) == 0);
   fp = fopen(tnam, "r");
   F2C_assert(fp);
   fgets(ln, 256, fp);
   fclose(fp);
   remove(tnam);
   if (strstr(ln, "Add__")) *f2cnam = f2c_Add__;
   else if (strstr(ln, "Add_")) *f2cnam = f2c_Add_;
   else if (strstr(ln, "NoChange")) *f2cnam = f2c_NoChange;
   else if (strstr(ln, "UpCase")) *f2cnam = f2c_UpCase;
   else return;
/*
 * Finding integer correspondence
 */
   if (targ)
      sprintf(compdef, "F77=%s F77FLAGS=\"%s\" FLINK=%s FLFLAGS=\"%s\" CC=%s CCFLAGS=\"%s -D%s\" mydir=%s/CONFIG tnam=%s atlrun=atlas_runX targ=%s",
              F77, F77FLAGS, FLINK, FLFLAGS, CC, CCFLAGS, namdef[*f2cnam],
              TOPdir, tnam, targ);
   else
      sprintf(compdef, "F77=%s F77FLAGS=\"%s\" FLINK=%s FLFLAGS=\"%s\" CC=%s CCFLAGS=\"%s -D%s\" mydir=%s/CONFIG tnam=%s",
              F77, F77FLAGS, FLINK, FLFLAGS, CC, CCFLAGS, namdef[*f2cnam], 
              TOPdir, tnam);
   sprintf(ln, "cd CONFIG ; make IRunInt %s %s\n", compdef, redir);
   F2C_assert(system(ln) == 0);
   fp = fopen(tnam, "r");
   F2C_assert(fp);
   fgets(ln, 256, fp);
   fclose(fp);
   remove(tnam);
   if (strstr(ln, "short")) *f2cint = FintCshort;
   else if (strstr(ln, "int")) *f2cint = FintCint;
   else if (strstr(ln, "long")) *f2cint = FintClong;
   else return;
/*
 * Finding string handling
 */
   if (targ)
      sprintf(compdef, "F77=%s F77FLAGS=\"%s\" FLINK=%s FLFLAGS=\"%s\" CC=%s mydir=%s/CONFIG tnam=%s atlrun=atlas_runX targ=%s",
              F77, F77FLAGS, FLINK, FLFLAGS, CC, TOPdir, tnam, targ);
   else
      sprintf(compdef, 
"F77=%s F77FLAGS=\"%s\" FLINK=%s FLFLAGS=\"%s\" CC=%s mydir=%s/CONFIG tnam=%s",
              F77, F77FLAGS, FLINK, FLFLAGS, CC, TOPdir, tnam);
   for (i=0; i < 5; i++)
   {
      sprintf(ln, 
              "cd CONFIG ; make IRunStr %s CCFLAGS=\"%s -D%s -D%s -D%s\" %s\n", 
              compdef, CCFLAGS, strdef[i], intdef[*f2cint], namdef[*f2cnam],
              redir);
      if (system(ln) == 0)
      {
         fp = fopen(tnam, "r");
         F2C_assert(fp);
         fgets(ln, 256, fp);
         fclose(fp);
         remove(tnam);
         if (strstr(ln, strdef[i]))
         {
            *f2cstr = i;
            return;
         }
      }
   }
}

#undef F2C_assert

#define ND 3
void FindBlas(FILE *fpout, FILE *fplog, char *redir, char *F77, char *F77FLAGS,
              char *BLASlib)
{
   char **files;
   char *dirs[ND] = {"/usr/lib", "/usr/local", ""};
   char ln[256];
   int i, j, n;

   ATL_mprintf(2, fplog, fpout, "Looking for BLAS (this may take a while):\n");
   if (*BLASlib)
   {
      sprintf(ln, 
      "cd CONFIG ; make IBlasLink F77=\"%s\" F77FLAGS=\"%s\" BLASlib=\"%s\" %s\n",
              F77, F77FLAGS, BLASlib, redir);
      if (system(ln) == 0)
      {
         ATL_mprintf(2, fplog, fpout, "BLASlib set to %s.\n", BLASlib);
         return;
      }
      ATL_mprintf(2, fplog, fpout, "   Link failed, %s rejected\n", BLASlib);
   }
   dirs[ND-1] = getenv("HOME");
   for (j=0; j < ND; j++)
   {
      n = FindFiles(dirs[j], "lib.*blas.*\\.a", &files);
      if (n)
      {
         for (i=0; i < n; i++)
         {
            sprintf(ln, 
      "cd CONFIG ; make IBlasLink F77=\"%s\" F77FLAGS=\"%s\" BLASlib=\"%s\" %s\n",
                    F77, F77FLAGS, files[i], redir);
            if (system(ln) == 0)
            {
               strcpy(BLASlib, files[i]);
               ATL_mprintf(2, fplog, fpout, "BLASlib set to %s.\n", BLASlib);
               return;
            }
            ATL_mprintf(2, fplog, fpout, 
                        "   Link failed, %s rejected\n", files[i]);
         }
      }
   }
   ATL_mprintf(2, fplog, fpout, 
               "Unable to find usable BLAS, BLASlib left blank.\n");
   BLASlib[0] = '\0';
}
#undef ND

char *FindUname()
{
   static int FirstTime=1;
   static char unam[64];
   if (FirstTime)
   {
      if (FileIsThere("/bin/uname")) strcpy(unam, "/bin/uname");
      else if (FileIsThere("/usr/bin/uname")) strcpy(unam, "/usr/bin/uname");
      else strcpy(unam, "uname");
      FirstTime = 0;
   }
   return(unam);
}

enum OSTYPE GetOS(FILE *fpout, FILE *fplog, char *targ)
{
   int ierr;
   char ln[512], ln2[128];
   enum OSTYPE i, OS;
   char *unam = FindUname();

   ATL_mprintf(2, fplog, fpout, 
               "Probing to make operating system determination:\n");

   sprintf(ln2, "%s -s", unam);
   ierr = CmndOneLine(targ, ln2, ln);
   if (ierr == 0)
   {
      if(strstr(ln, "Linux")) OS = OSLinux;
      else if(strstr(ln, "FreeBSD")) OS = OSFreeBSD;
      else if(strstr(ln, "SunOS")) 
      {
         sprintf(ln2, "%s -r", unam);
         CmndOneLine(targ, ln2, ln);
         if (ln[0] == '4') OS = OSSunOS4;
         else OS = OSSunOS;
      }
      else if(strstr(ln, "OSF1")) OS = OSOSF1;
      else if(strstr(ln, "IRIX")) OS = OSIRIX;
      else if(strstr(ln, "AIX")) OS = OSAIX;
      else if(strstr(ln, "WIN"))
      {
         if (strstr(ln, "95") || strstr(ln, "98")) OS = OSWin9x;
         else if (strstr(ln, "NT")) OS = OSWinNT;  /* check this */
      }
      else if (strstr(ln, "HP-UX")) OS = OSHPUX;
      else ierr = 1;
   }
   if (ierr)
   {
      fprintf(stdout, 
         "%s -s does not appear to work.\n", unam);
      for (i=0; i <= OSOther; i++) fprintf(stdout, " %3d. %s\n", i+1, osnam[i]);
      OS = (enum OSTYPE) GetIntRange(OSOther+1, 1, OSOther+1, "", 
                                     "the number of your operating system") - 1;
   }
   ATL_mprintf(2, fplog, stdout, 
               "Operating system configured as %s\n\n", osnam[OS]);

   return(OS);
}

char *TryComp(FILE *fpout, FILE *fplog, char *redir, char lang, int np,
              char **paths, char *comp, char *flags)
{
   static char ln2[512];
   char **matches, ln[512];
   int p, n, i;

/*
 * Try user's path first
 */
   if (FindFirstInPath(comp, ln2))
   {
      sprintf(ln, "cd CONFIG ; make %cTryComp COMP=\"%s\" FLAGS=\"%s\" %s\n",
              lang, ln2, flags, redir);
      if (system(ln) == 0) return(ln2);
      ATL_mprintf(2, fplog, fpout, "   %s %s rejected\n", ln2, flags);
   }
/*
 * A separate find on each directory, in order of precedence
 */
   for (p=0 ; p < np; p++)
   {
/*
 *    Try every compiler that is found, search backwards so bigger version
 *    numbers will be tried first
 */
      n = FindFiles(paths[p], comp, &matches);
      for (i=n-1; i >= 0; i--)
      {
         sprintf(ln, "cd CONFIG ; make %cTryComp COMP=\"%s\" FLAGS=\"%s\" %s\n",
                 lang, matches[i], flags, redir);
         if (system(ln) == 0) return(matches[i]);
         ATL_mprintf(2, fplog, fpout, "   %s rejected\n", matches[i]);
      }
   }
/*
 * Try without explicit path if nothing else works
 */
   sprintf(ln, "cd CONFIG ; make %cTryComp COMP=\"%s\" FLAGS=\"%s\" %s\n",
           lang, comp, flags, redir);
   if (system(ln) == 0) return(comp);
   ATL_mprintf(2, fplog, fpout, "   %s %s rejected\n", comp, flags);

   return(NULL);
}

void GetWinF77(enum MACHTYPE mach, char *targ, char *TOPdir, char *F77, char *F77FLAGS)
{
   FILE *fp;
   int i;

   if (!F77 || !F77FLAGS) return;

   fprintf(stdout, "Which Fortran compiler would you like to use:\n");
   fprintf(stdout, "   1. Compaq Visual Fortran with /iface:cref\n");
   fprintf(stdout, 
   "   2. Compaq Visual Fortran with /iface:cref /iface=nomixed_str_len_arg\n");
   fprintf(stdout, "   3. Gnu Fortran77 (g77)\n");
   i = GetIntRange(1, 1, 3, "", "compiler number");

   if (i == 1 || i == 2)
   {
      DisplayFile("CONFIG/winf77.txt", stdout, NLINES);
      GetStrVer("c:/Program Files/Microsoft Visual Studio/DF98/BIN/DF.EXE", "",
                "full path to compaq/digital fortran", 511, F77);
      fp = fopen("CONFIG/defdf.h", "w");
      assert(fp);
      fprintf(fp, "#define DEFDF \"%s\"\n", F77);
      fclose(fp);
      sprintf(F77, "%s/CONFIG/winf77.exe", TOPdir);
      strcpy(F77FLAGS, "-fast -assume:accuracy_sensitive -fltconsistency");
      if (i == 2) strcat(F77FLAGS, " -iface=nomixed_str_len_arg");
      USEWINF77=1; 
      assert(system("cd CONFIG ; make ./winf77.exe") == 0);
   }
   else
   {
      if (F77) strcpy(F77, "g77");
      if (F77FLAGS) strcpy(F77FLAGS, "-funroll-all-loops -O3");
   }
}

void GetSyslib(enum OSTYPE OS, enum MACHTYPE mach, char *targ, char *LIBS)
{
   if (THREADS) strcpy(LIBS, "-lpthread -lm");
   else strcpy(LIBS, "-lm");

   switch(OS)
   {
   case OSFreeBSD:  /* don't know answer */
   case OSLinux:
      break;
   case OSSunOS:
      break;
   case OSSunOS4:
      assert(!THREADS);
      break;
   case OSOSF1:
      break;
   case OSIRIX:
      /* if (THREADS) strcpy(LIBS, "-lm"); */
      /* if (THREADS) strcpy(LIBS, "-lpthread -lexc -lm"); */ /* for gcc */
      break;
   case OSAIX:
      if (THREADS) strcpy(LIBS, "-lpthreads -lm");
      break;
   case OSHPUX:  /* don't know answer for threads */
      break;
   case OSWinNT:  /* don't know answer for threads */
      if (THREADS) strcpy(LIBS, "-lpthread");
      else strcpy(LIBS, "");
      break;
   case OSWin9x:
      strcpy(LIBS, "");
      assert(!THREADS);
      break;
   }
}

void GetCompDef(enum OSTYPE OS, enum MACHTYPE mach, char *targ,
                char *TOPdir, int *np0, char **paths0,
                char *F77, char *F77FLAGS, char *FLINK, char *FLFLAGS,
                char *CC, char *CCFLAGS, char *CLINK, char *CLFLAGS, 
                char *MCC, char *MMFLAGS, char *BLASlib)
/*
 * Finds the compilers, linkers and BLAS used in architectural defaults.
 * CC & CCFLAGS are required;  other options may be set * to NULL, and
 * thus not returned
 */
{
   int i, np;
   char *paths[16], *sp;
   char tline[256];
   char ln[512];
   char *unam = FindUname();
/*
 * normal defaults 
 */
   np = 2;
   paths[0] = "/usr/bin/";
   paths[1] = "/usr/local/";
   strcpy(CC, "cc");
   strcpy(CCFLAGS, "-O");
   if (CLINK) strcpy(CLINK, "$(CC)");
   if (CLFLAGS) strcpy(CLFLAGS, "$(CCFLAGS)");

   if (MCC) strcpy(MCC, CC);
   if (MMFLAGS) strcpy(MMFLAGS, CCFLAGS);

   if (F77) strcpy(F77, "f77");
   if (F77FLAGS) strcpy(F77FLAGS, "-O");
   if (FLINK) strcpy(FLINK, "$(F77)");
   if (FLFLAGS) strcpy(FLFLAGS, "$(F77FLAGS)");
   if (BLASlib) BLASlib[0] = '\0';

   switch(OS)
   {
   case OSFreeBSD:
   case OSLinux:
      if (F77) strcpy(F77, "g77");
      strcpy(CC, "gcc");
      if (F77FLAGS) strcpy(F77FLAGS, "-funroll-all-loops -O3");
      strcpy(CCFLAGS, "-fomit-frame-pointer -O3 -funroll-all-loops");
      if (MMFLAGS) strcpy(MMFLAGS, "-fomit-frame-pointer -O");
      if (mach == Dec21164 || mach == Dec21264)
      {
         if (MMFLAGS) strcpy(MMFLAGS, 
         "-O1 -fschedule-insns -fschedule-insns2 -fno-expensive-optimizations");
      }
      if (mach == PPC604 || mach == PPC604e || mach == PPCG4)
      {  /* avoid unroll loops bug */
         if (F77FLAGS) strcpy(F77FLAGS, "-O3");
         strcpy(CCFLAGS, "-fomit-frame-pointer -O3");
         if (mach == PPCG4)
         {
            if (MMFLAGS) strcpy(MMFLAGS, 
            "-fomit-frame-pointer -O2 -fschedule-insns -fno-schedule-insns2");
         }
      }
      if (MachIsUS(mach))
      {
         strcpy(CCFLAGS, 
  "-mcpu=ultrasparc -mtune=ultrasparc -fomit-frame-pointer -funroll-all-loops -O3");
/*     "-fomit-frame-pointer -O3 -funroll-all-loops -mcpu=v9 -Wa,-Av8plusa"); */
         if (MMFLAGS) 
            strcpy(MMFLAGS, 
               "-mcpu=ultrasparc -mtune=ultrasparc -fomit-frame-pointer -O");
      }
      if (OS == OSFreeBSD && F77) strcpy(F77, "f77");
      break;
   case OSSunOS:
      np = 3;
      paths[0] = "/opt/";
      paths[1] = "/usr/bin/";
      paths[2] = "/usr/local/";
      if (BLASlib) strcpy(BLASlib, "-xlic_lib=sunperf");
      if (F77) strcpy(F77, "f77");
      strcpy(CC, "cc");
      if (F77FLAGS) strcpy(F77FLAGS, "-dalign -native -xO5");
      strcpy(CCFLAGS, "-dalign -fsingle -xO5 -native");
      if (MMFLAGS) strcpy(MMFLAGS, "-dalign -fsingle -xO2 -native");
      if (MachIsUS(mach))
      {
            if (F77FLAGS) strcpy(F77FLAGS, "-dalign -native -xarch=v8plusa -xO5");
            strcpy(CCFLAGS, "-dalign -fsingle -xO5 -native -xarch=v8plusa");
            if (MMFLAGS) strcpy(MMFLAGS, 
         "-dalign -fsingle -xO2 -native -xarch=v8plusa -fsimple=1 -xsafe=mem");
      }
      if (THREADS)
      {
         strcat(CCFLAGS, " -mt");
         if (MMFLAGS) strcat(MMFLAGS, " -mt");
         if (F77FLAGS) strcat(F77FLAGS, " -mt");
      }
      break;
   case OSSunOS4:
      if (F77) strcpy(F77, "f77");
      if (F77FLAGS) strcpy(F77FLAGS, "-dalign -O4 -fast");
      strcpy(CC, "gcc");
      strcpy(CCFLAGS, "-fomit-frame-pointer -O3 -funroll-all-loops");
      if (MMFLAGS) strcpy(MMFLAGS, "-fomit-frame-pointer -O");
      break;
   case OSOSF1 :
      if (BLASlib) strcpy(BLASlib, "-lcxml");
      if (F77) strcpy(F77, "f77");
      if (F77FLAGS) strcpy(F77FLAGS, "-O5 -arch host -tune host");
      strcpy(CC, "cc");
      strcpy(CCFLAGS, "-arch host -tune host -std -O5");
      if (MCC) strcpy(MCC, "gcc");
      if (MMFLAGS) strcpy(MMFLAGS, 
         "-O1 -fschedule-insns -fschedule-insns2 -fno-expensive-optimizations");
      if (THREADS)
      {
         strcat(CCFLAGS, " -pthread");
         if (MMFLAGS) strcat(MMFLAGS, " -D_REENTRANT");
         if (F77FLAGS) strcat(F77FLAGS, " -pthread");
      }
      break;
   case OSIRIX :
      if (mach == SgiIP22) 
      {
         if (F77FLAGS) strcpy(F77FLAGS, "-O2 -mips2 -Olimit 15000");
         strcpy(CCFLAGS, "-O2 -mips2 -Olimit 15000");
      }
      else if (mach == SgiIP32)
      {
         if (F77FLAGS) sprintf(F77FLAGS, 
      "-O3 -n32 -mips4 -OPT:Olimit=15000 -TARG:platform=ip32_5k -LNO:blocking=OFF");
         sprintf(CCFLAGS, "-O2 -n32 -mips4 -OPT:Olimit=15000 -TARG:platform=ip32_5k -LNO:blocking=OFF -LOPT:aliased=typed");
      }
      else
      {
         sprintf(tline, "%s -m", unam);
         assert(CmndOneLine(targ, tline, ln) == 0);
         sp = strstr(ln, "IP");
         for (i=2; isdigit(sp[i]); i++);
         sp[i] = '\0';
         if (F77FLAGS) sprintf(F77FLAGS, 
            "-O3 -64 -OPT:Olimit=15000 -TARG:platform=%s -LNO:blocking=OFF", 
                 sp);
         sprintf(CCFLAGS, "%s -LOPT:alias=typed", F77FLAGS);
      }
      if (MMFLAGS) strcpy(MMFLAGS, CCFLAGS);
      if (BLASlib) strcpy(BLASlib, "-lblas");
      if (F77) strcpy(F77, "f77");
      strcpy(CC, "cc");
      break;
   case OSAIX  :
      if (THREADS)
      {
         strcpy(CC, "xlc_r");
         if (F77) strcpy(F77, "xlf_r");
      }
      else
      {
         strcpy(CC, "xlc");
         if (F77) strcpy(F77, "xlf");
      }
      strcpy(CCFLAGS, "-O3 -qmaxmem=-1 -qfloat=hsflt");
      if (F77FLAGS) strcpy(F77FLAGS, CCFLAGS);
      if (F77FLAGS) strcpy(CCFLAGS, F77FLAGS);
      if (MMFLAGS) MMFLAGS[0] = '\0';
      if (mach == IbmPwr)
      {
         strcpy(CCFLAGS, "-O3 -qarch=pwr -qtune=pwr -qmaxmem=-1 -qfloat=hsflt");
      }
      else if (mach == IbmTPwr2)
      {
         strcpy(CCFLAGS, 
                "-O3 -qarch=pwr2 -qtune=pwr2 -qmaxmem=-1 -qfloat=hsflt");
         if (MMFLAGS) sprintf(MMFLAGS,
  "-qarch=pwr2 -qtune=pwr2 -qmaxmem=-1 -qfloat=hsflt -qansialias -qfold -O");
         mach = IbmTPwr2;
         if (BLASlib) strcpy(BLASlib, "-lesslp2");
      }
      else if (mach == IbmPwr3)
      {
         strcpy(CCFLAGS, 
                "-qtune=pwr3 -qarch=pwr3 -O3 -qmaxmem=-1 -qfloat=hsflt");
         if (MMFLAGS) sprintf(MMFLAGS, 
         "-qtune=pwr3 -qarch=pwr3 -O3 -qmaxmem=-1 -qfloat=hsflt -qalias=allp");
         mach = IbmPwr3;
         if (BLASlib) strcpy(BLASlib, "-lessl");
      }
      else if (mach == PPC604)
      {
         strcpy(CCFLAGS, "-O3 -qarch=ppc -qtune=604 -qmaxmem=-1 -qfloat=hsflt");
         if (MMFLAGS) strcpy(MMFLAGS, 
"-O -qarch=ppc -qtune=604 -qmaxmem=-1 -qfloat=hsflt -qproto -qansialias -qfold");
      }
      else if (mach == PPC604e)
         strcpy(CCFLAGS, "-O3 -qarch=ppc -qtune=604 -qmaxmem=-1 -qfloat=hsflt");
      if (F77FLAGS) strcpy(F77FLAGS, CCFLAGS);
      if (CLFLAGS) strcpy(CLFLAGS, "$(CCFLAGS) -bmaxdata:0x70000000");
      if (FLFLAGS) strcpy(FLFLAGS, "$(F77FLAGS) -bmaxdata:0x70000000");
      if (MMFLAGS && MMFLAGS[0] == '\0')
      {
         strcpy(MMFLAGS, CCFLAGS);
         strcat(MMFLAGS, "-O");
      }
      break;
   case OSWin9x:
   case OSWinNT:
      GetWinF77(mach, targ, TOPdir, F77, F77FLAGS);
      strcpy(CC, "gcc");
      strcpy(CCFLAGS, "-fomit-frame-pointer -O3 -funroll-all-loops -DUseClock");
      if (MMFLAGS) strcpy(MMFLAGS, "-fomit-frame-pointer -O");
      break;
   case OSHPUX :
      if (F77) strcpy(F77, "f77");
      strcpy(CC, "cc");
      if (F77FLAGS) strcpy(F77FLAGS, "+O4");
      strcpy(CCFLAGS, "-D_INCLUDE_POSIX_SOURCE -DUseTimes -Aa +O4");
      if (MMFLAGS) strcpy(MMFLAGS, "-Aa +O2");
      if (mach == HPPA8K)
         if (MMFLAGS) strcpy(MMFLAGS, 
                "-Aa +O2 +Onoinitcheck +Odataprefetch +Optrs_strongly_typed");
      if (mach == HP9K735)
      {
         if (CLFLAGS) strcpy(CLFLAGS, "-Aa");
         if (FLFLAGS) strcpy(FLFLAGS, "-Aa");
      }
      break;
   case OSOther:
      break;
   }
   if (np0)
   {
      *np0 = np;
      if (paths0) for (i=0; i < np; i++) paths0[i] = paths[i];
   }
}

void GetCompInfo(FILE *fpout, FILE *fplog, enum OSTYPE OS, enum MACHTYPE mach,
                 char *targ, char *redir, char *TOPdir,
                 char *F77, char *F77FLAGS, char *FLINK, char *FLFLAGS,
                 char *CC, char *CCFLAGS, char *CLINK, char *CLFLAGS, 
                 char *MCC, char *MMFLAGS, char *BLASlib)
/*
 * Sets up good compiler flags for various OSs, and searches for the correct
 * compilers.  The compiler search should be improved so that it always takes
 * the newest release;  right now it simply takes the first compiler that
 * works with the desired flags.
 * CC & CCFLAGS are required;  other options may be set ptr to NULL, and
 * thus not probed.
 */
{
   int MCisCC=1;
   int i, np;
   char *paths[16];
   char *CCG=NULL, *MCCG=NULL, *F77G=NULL;
   char gcc[256], egcs[256], pgcc[256];

   GetCompDef(OS, mach, targ, TOPdir, &np, paths, F77, F77FLAGS, FLINK, FLFLAGS,
              CC, CCFLAGS, CLINK, CLFLAGS, MCC, MMFLAGS, BLASlib);
   if (MCC) MCisCC = !strcmp(CC, MCC);
   else MCisCC = 0;

   ATL_mprintf(2, fpout, fplog, "Looking for compilers:\n");
   if (mach == Dec21164 || mach == Dec21264 || OS == OSLinux || OS == OSFreeBSD)
   {
      FindAllGccs(fpout, fplog, gcc, egcs, pgcc);
/*
 * ATTENTION:  Need to make this guy print warnings when inferior gcc is chosen
 */
      if (mach == PPC604 || mach == PPC604e)  /* egcs best compiler for PPC */
      {
         if (*egcs) CCG = MCCG = egcs;
         else if (*gcc) CCG = MCCG = gcc;
         strcpy(CC, CCG);
         if (MCC) strcpy(MCC, MCCG);
      }
      else if (OS == OSOSF1)
      {
         if (gcc[0] == '\0' && egcs[0] == '\0') /* no gcc available */
         {
            if (MCC && strstr(MCC, "gcc")) /* no gcc to use */
            {
               strcpy(MCC, CC);
               if (MMFLAGS) strcpy(MMFLAGS, CCFLAGS);
            }
         }
         else if (MCC && strstr(MCC, "gcc"))  /* need to check for version */
         {
            if (*gcc && GccV278(gcc))
            {
               if (MCC) strcpy(MCC, gcc);
               if (MMFLAGS)
                  strcpy(MMFLAGS, "-O1 -fschedule-insns -fschedule-insns2");
            }
            else
            {
               strcpy(MCC, CC);
               if (MMFLAGS) strcpy(MMFLAGS, CCFLAGS);
            }
            if (*gcc) MCCG = gcc;
            else MCCG = egcs;
            if (MMFLAGS)
               strcpy(MMFLAGS, "-O1 -fschedule-insns -fschedule-insns2");
            if (MCCG && MCC) strcpy(MCC, MCCG);
         }
      }
      else if (mach == Dec21164 || mach == Dec21264) /* linux on evX */
      {
         if (*gcc && GccV278(gcc))
         {
            if (MCC) strcpy(MCC, gcc);
            if (MMFLAGS)
               strcpy(MMFLAGS, "-O1 -fschedule-insns -fschedule-insns2");
         }
         else
         {
            if (MCC) strcpy(MCC, CC);
            if (MMFLAGS) strcpy(MMFLAGS, CCFLAGS);
            MCisCC = 1;
         }
      }
      else
      {
         if (*gcc)  CCG = MCCG = gcc;
         else if (*pgcc) CCG = MCCG = pgcc;
         else CCG = MCCG = egcs;
         if (MCC) strcpy(MCC, MCCG);
         strcpy(CC, CCG);
      }
   }
   if (CCG == NULL)
      CCG = TryComp(fpout, fplog, redir, 'c', np, paths, CC, CCFLAGS);
   if (CCG != NULL)
   {
      strcpy(CC, CCG);
      if (MCCG == NULL && MCC)
      {
         strcpy(MCC, CCG);
         MCCG = CCG;
      }
   }
   if (!MCisCC && MCCG == NULL && MCC && MMFLAGS)
   {
      MCCG = TryComp(fpout, fplog, redir, 'c', np, paths, MCC, MMFLAGS);
   }
   if (F77G == NULL && F77)
   {
      F77G = TryComp(fpout, fplog, redir, 'f', np, paths, F77, F77FLAGS);
      if (F77G) strcpy(F77, F77G);
   }
   if (F77) ATL_mprintf(2, fplog, fpout, "F77 = %s %s\n", F77, F77FLAGS);
   ATL_mprintf(2, fplog, fpout, "CC = %s %s\n", CC, CCFLAGS);
   if (MCC) ATL_mprintf(2, fplog, fpout, "MCC = %s %s\n\n", MCC, MMFLAGS);

   if (F77 && BLASlib) FindBlas(fpout, fplog, redir, F77, F77FLAGS, BLASlib);
}

void GetArchDef(enum OSTYPE OS, enum MACHTYPE mach, char *arch, 
                char *CC, char *MCC, char *mmdef, char *def)
{
   const char *mmc=NULL, *syc=NULL;

   mmdef[0] = def[0] = '\0';
   if (strstr(MCC, "gcc")) mmc = "gcc";
   if (strstr(CC, "gcc")) syc = "gcc";
   switch(OS)
   {
   case OSSunOS:
   case OSOSF1:
   case OSIRIX:
   case OSHPUX:
      if ( (!mmc) && strstr(MCC, "cc") ) mmc = "cc";
      if ( (!syc) && strstr(CC, "cc") ) syc = "cc";
      break;
   case OSAIX:
      if (strstr(MCC, "xlc")) mmc = "xlc";
      if (strstr(CC, "xlc")) syc = "xlc";
      break;
   default:;
   }
   if (MachIsAlpha(mach) && !GccV278(MCC)) 
   { 
      if (strstr(MCC, "gcc")) mmc = "egcs"; 
      if (strstr(CC, "gcc")) syc = "egcs"; 
   }
   if (mmc) sprintf(mmdef, "$(TOPdir)/CONFIG/ARCHS/%s/%s/gemm", arch, mmc);
   if (syc) sprintf(  def, "$(TOPdir)/CONFIG/ARCHS/%s/%s/misc", arch, syc);
}

enum ISAEXT GetISAExt(char *targ, char *TOPdir)
{
   char ln[512], ln2[512];
   int i;

   fprintf(stdout, "\nProbing for supported ISA extensions:\n");
   for (i=0; i < ISA_None; i++)
   {
      if (targ)
         sprintf(ln2, "cd CONFIG ; make IRun_%s mydir=%s/CONFIG atlrun=atlas_runX targ=%s | fgrep SUCCESS",
                 ISAXNAM[i], TOPdir, targ);
      else
         sprintf(ln2, 
                 "cd CONFIG ; make IRun_%s mydir=%s/CONFIG | fgrep SUCCESS",
                 ISAXNAM[i], TOPdir);
      if(!CmndOneLine(NULL, ln2, ln))
      {
         if (strstr(ln, "SUCCESS"))
         {
            fprintf(stdout, "   %s: DETECTED!\n", ISAXNAM[i]);
            return(i);
         }
      }
      fprintf(stdout, "   %s: NO.\n", ISAXNAM[i]);
   }
   return(ISA_None);
}

int FlushMul(enum OSTYPE OS, enum MACHTYPE arch, char *targ, char *TOPdir)
/*
 * returns the multiplication factor of true cache size necessary to do
 * complete flush; this is essentially the associativity of the cache
 * if not known, returns 0
 */
{
   int imul=0;
   char ln[256], ln2[256];

   switch(OS)
   {
   case OSAIX :
      if (targ)
         sprintf(ln2, "cd CONFIG ; make IRunAixInfo mydir=%s/CONFIG atlrun=atlas_runX targ=%s | fgrep L2",
                 TOPdir, targ);
      else
         sprintf(ln2, "cd CONFIG ; make IRunAixInfo mydir=%s/CONFIG | fgrep L2",
                 TOPdir);
      if(!CmndOneLine(NULL, ln2, ln))
         imul = GetLastInt(ln);
      break;
   }
   if (imul == 0)
   {
      switch(mach)
      {
      case Dec21164:
      case AmdAthlon:
      case SunUS1:
      case SunUS2:
      case SunUS4:
      case SunUS5:
      case SunUSX:
      case IntP4:
      case PPCG4:
         imul = 2;
         break;
      case IntP5:
      case IntP5MMX:
      case IntPPRO:
      case IntPII:
      case IntPIII:
         imul = 1;
         break;
      default:
         imul = 2;
      }
   }
   return(imul);
}

int ProbeCacheSize(enum OSTYPE OS, enum MACHTYPE arch, char *targ, char *TOPdir)
/*
 * Returns size (in KB) of largest cache, returns 0 if OS cannot provide
 */
{
   int i, size=0;
   char ln[256], ln2[256], *sp, s2;

   switch(OS)
   {
   case OSLinux:
      if (mach == IntPII || mach == IntPIII || mach == IntPPRO || 
          mach == AmdAthlon)
      {
         if( !CmndOneLine(targ, "fgrep 'cache size' /proc/cpuinfo", ln) )
         {
            size = GetLastInt(ln);
            for (i=0; ln[i]; i++);
            i--;
            while (i > 0 && isspace(ln[i])) i--;
            while (i > 0 && !isspace(ln[i])) i--;
            if (i > 0)
            {
               if (ln[i+1] == 'M') size *= 1024;
               else if (ln[i+1] != 'K') size = 0;
            }
            else size = 0;
         }
      }
      else if (mach == PPCG4)
      {
         if( !CmndOneLine(targ, "fgrep 'L2 cache' /proc/cpuinfo", ln) )
         {
            size = GetLastInt(ln);
         }
         else size = 0;
      }
      break;
   case OSOSF1:
      break;
   case OSIRIX:
      if(!CmndOneLine(targ, "hinv | fgrep Secondary | fgrep 'cache size'", ln))
      {
         if (sp = strstr(ln, " Mbyte"))
         {
            s2 = 1;
            sp--;
            while(isdigit(*sp)) sp--;
            sp++;
            sscanf(sp, "%d", &size);
            size *= 1024;
         }
         else if (sp = strstr(ln, " Kbyte"))
         {
            s2 = 1;
            sp--;
            while(isdigit(*sp)) sp--;
            sp++;
            sscanf(sp, "%d", &size);
         }
      }
      break;
   case OSAIX :
      if (targ)
         sprintf(ln2, "cd CONFIG; make IRunAixInfo mydir=%s/CONFIG atlrun=atlas_runX targ=%s | fgrep L2",
                 TOPdir, targ);
      else
         sprintf(ln2, "cd CONFIG; make IRunAixInfo mydir=%s/CONFIG | fgrep L2",
                 TOPdir);
      if(!CmndOneLine(NULL, ln2, ln)) size = GetFirstInt(ln+5) / 1024;
      break;
   case OSHPUX :
   case OSSunOS:
   case OSSunOS4:
   case OSWin9x:
   case OSWinNT:
   case OSFreeBSD:
   default:
      size = 0;
   }
   return(size);
}

int GetCacheSize(enum OSTYPE OS,  enum MACHTYPE arch, char *targ, char *TOPdir,
                 int lvl, int *AmSure)
{
/*
 * Returns size of requested level of cache.  If *AmSure is 0, this is a max,
 * otherwise that machine only comes with that size of cache.  If lvl is < 0,
 * give me a safe size to flush (handling associativity and so forth)
 */
   int l1, l2, s1, s2;
   int lf1, lf2;
   char ln[512], *sp;

   if (lvl == -2)
   {
      l2 = ProbeCacheSize(OS, arch, targ, TOPdir);
      if (l2 > 0)
      {
         *AmSure = 1;
         l1 = FlushMul(OS, arch, targ, TOPdir);
         if (!l1) l1 = 2;
         return(l2*l1);
      }
   }
   switch(mach)
   {
   case MACHOther:
      l1 = l2 = s1 = s2 = 0;
      lf2 = 4096;
      break;
   case SunUS2:
   case SunUS4:
   case SunUS5:
      lf1 = l1 = 16;
      lf2 = l2 = 4096;
      s1 = 1;
      s2 = 0;
      break;
   case SunUS1:
      lf1 = l1 = 16;
      lf2 = l2 = 1024;
      s1 = 1;
      s2 = 0;
      break;
   case SunSS:
      lf1 = l1 = 32;
      lf2 = l2 = 1024;
      s1 = 1;
      s2 = 0;
      break;
   case SunMS:
      lf1 = l1 = 8;
      lf2 = l2 = l1;
      s1 = 1;
      s2 = 1;
      break;
   case SgiIP22:    /* R4600 */
      if (l2 == -1) lf2 = l2 = 128;
      lf1 = l1 = 16;
      s1 = 1;
      break;
   case SgiIP32:   /* R5K */
      if (l2 == -1) lf2 = l2 = 1024;
      l1 = 32;
      lf1 = 2*l1;
      s1 = 1;
      break;
   case SgiIP27:
   case SgiIP28:
   case SgiIP30:
      if (l2 == -1) lf2 = l2 = 4096;
      l1 = 32;
      lf1 = 2*l1;
      s1 = 1;
      break;
   case AmdAthlon:
      lf1 = l1 = 64;
      lf2 = l2 = 4096;
      s1 = 1;
      s2 = 0;
      break;
   case IA64Itan:
      lf1 = l1 = 96;  /* ignore actual L1, 'cause fpu doesn't use it */
      lf2 = l2 = 4096;
      break;
   case IntPII:
   case IntPIII:
      lf1 = l1 = 16;
      lf2 = l2 = 512;
      s1 = 1;
      s2 = 0;
      break;
   case IntP4:
      lf1 = l1 = 64;
      lf2 = l2 = 512;
      s1 = 0;
      s2 = 0;
      break;
   case IntPPRO:
      lf1 = l1 = 8;
      lf2 = l2 = 1024;
      s1 = 1;
      s2 = 0;
      break;
   case IntP5MMX:
      lf1 = l1 = 16;
      lf2 = l2 = 1024;
      s1 = 1;
      s2 = 0;
      break;
   case IntP5:
      lf1 = l1 = 8;
      lf2 = l2 = 1024;
      s1 = 1;
      s2 = 0;
      break;
   case PPCG4:
   case PPC604e:
      l1 = 32;
      lf1 = 4*l1;
      lf2 = l2 = 4096;
      s1 = 1;
      s2 = 0;
      break;
   case PPC604:
      l1 = 16;
      lf1 = 4*l1;
      lf2 = l2 = 4096;
      s1 = 1;
      s2 = 0;
      break;
   case IbmPwr:
      l1 = 64;
      l2 = 64;
      lf2 = lf1 = 4*l1;
      s1 = 0;
      s2 = 0;
      break;
   case IbmWPwr2:
      l1 = 256;
      l2 = 256;
      lf2 = lf1 = 4*l1;
      s1 = 1;
      s2 = 1;
      break;
   case IbmTPwr2:
      l1 = 128;
      l2 = 128;
      lf2 = lf1 = 4*l1;
      s1 = 1;
      s2 = 1;
      break;
   case IbmPwr3:
      l1 = 64;
      lf2 = l2 = 4096;
      s1 = 1;
      s2 = 0;
      break;
   case HP9K735:
      lf1 = l1 = 256;
      l2 = 256;
      lf2 = 4*l2;
      s1 = 1;
      s2 = 1;
      break;
   case HPPA8K:
      lf1 = l1 = 1024;
      lf2 = l2 = 1024;
      lf2 = 4*l2;
      s1 = 0;
      s2 = 0;
      break;
   case Dec21064:
      lf1 = l1 = 16;
      lf2 = l2 = 4096;
      s1 = 1;
      s2 = 0;
      break;
   case Dec21164:
      lf1 = l1 = 8;
      lf2 = l2 = 4096;
      s1 = 1;
      s2 = 0;
      break;
   default:
      l1 = l2 = s1 = s2 = 0;
      lf2 = 4096;
   }
   if (lvl == 1) 
   {
      if (AmSure) *AmSure = s1;
      return(l1);
   }
   else if (lvl == -1)
   {
      if (AmSure) *AmSure = s1;
      return(lf1);
   }
   else if (lvl == -2)
   {
      if (AmSure) *AmSure = s2;
      return(lf2);
   }
   else
   {
      if (AmSure) *AmSure = s2;
      return(l2);
   }
}

int ProbeNCPU(enum OSTYPE OS,  enum MACHTYPE mach, char *targ, char *TOPdir)
/*
 * Probes the OS for the number of CPUs.  Returns 0 if it can't
 * figure it out
 */
{
   char ln[256], ln2[256], *fnam;
   char unam;
   int ncpu=0;

   switch(OS)
   {
   case OSSunOS4: /* SunOS4 single proc, need SunOS5 for SMP, I think */
      ncpu = 1;
      break;
   case OSSunOS:
      sprintf(ln2, "%s -X | fgrep NumCPU", FindUname());
      if (!CmndOneLine(targ, ln2, ln))
         ncpu = GetFirstInt(ln);
      break;
   case OSFreeBSD:
         if ( !CmndOneLine(targ, "sysctl hw.ncpu", ln) ) ncpu = GetLastInt(ln);
         break;
   case OSLinux:
      if (mach == Dec21264 || mach == Dec21164 || mach == Dec21064)
      {
         if ( !CmndOneLine(targ, "fgrep 'cpus detected' /proc/cpuinfo", ln) )
            ncpu = GetLastInt(ln);
      }
      else
      {
         fnam = CmndResults(targ, "grep '^processor' /proc/cpuinfo");
         if (fnam) ncpu = fNumLines(fnam);
      }
      break;
   case OSOSF1:
      if (!CmndOneLine(targ, "/usr/sbin/psrinfo -n", ln))
         ncpu = GetFirstInt(ln);
      break;
   case OSIRIX:
      if (!CmndOneLine(targ, "hinv | fgrep Processor | fgrep MHZ", ln))
         ncpu = GetFirstInt(ln);
      break;
   case OSAIX :
      if (targ) sprintf(ln2, "cd CONFIG ; make IRunAixInfo mydir=%s/CONFIG atlrun=atlas_runX targ=%s | fgrep ncpus", TOPdir, targ);
      else sprintf(ln2, "cd CONFIG ; make IRunAixInfo mydir=%s/CONFIG | fgrep ncpus", TOPdir);
      if ( !CmndOneLine(NULL, ln2, ln) ) ncpu = GetLastInt(ln);
      break;
   case OSHPUX:
      if (targ) sprintf(ln2,"cd CONFIG ; make IRunHpuxInfo mydir=%s/CONFIG atlrun=atlas_runX targ=%s | fgrep ncpus", TOPdir, targ);
      else sprintf(ln2,"cd CONFIG ; make IRunHpuxInfo mydir=%s/CONFIG | fgrep ncpus", TOPdir);
      if ( !CmndOneLine(NULL, ln2 ,ln) ) ncpu = GetLastInt(ln);
      break;
   case OSWin9x:
   case OSWinNT:
   default: 
      ncpu = 0;
   }
   return(ncpu);
}

int GetNCPU(enum OSTYPE OS, enum MACHTYPE mach, char *targ, char *TOPdir)
{
   int ncpu;

   ncpu = ProbeNCPU(OS, mach, targ, TOPdir);
   if (!ncpu)
   {
      DisplayFile("CONFIG/ncpu.txt", stdout, NLINES);
      ncpu = GetIntRange(0, 0, 64, "", "the number processors in system");
   }
   return(ncpu);
}

enum LINUXARCH ProbeLinuxArch(char *targ)
{
   enum LINUXARCH la=LAOTHER;
   char ln[256], ln2[256];
   char *unam;

   unam = FindUname();

   sprintf(ln2, "%s -m", unam);
   if ( !CmndOneLine(targ, ln2, ln) )
   {
      if (strstr(ln, "ppc")) la = LAPPC;
      else if (strstr(ln, "sparc")) la = LASPARC;
      else if (strstr(ln, "alpha")) la = LAALPHA;
      else if (strstr(ln, "ia64")) la = LAIA64;
      else if ( strstr(ln, "i686") || strstr(ln, "i586") ||
                strstr(ln, "i486") || strstr(ln, "i386") ) la = LAX86;
   }
   return(la);
}

enum MACHTYPE ProbeArch(enum OSTYPE OS, char *targ, char *TOPdir)
/*
 * Probes OS for machine type, returns MACHOther on failure
 */
{
   enum MACHTYPE mach=MACHOther;
   enum LINUXARCH la;
   char *unam;
   int ierr;
   char ln[256], ln2[256];

   unam = FindUname();
   sprintf(ln2, "%s -m", unam);
   switch(OS)
   {
   case OSFreeBSD:
      la = ProbeLinuxArch(targ);
      switch(la)
      {
      case LAPPC: /* don't know */
         break;
      case LASPARC: /* don't know */
         break;
      case LAALPHA:
         if (!CmndOneLine(targ, "sysctl hw.model", ln))
         {
            if (strstr(ln, "433au")) mach = Dec21164;
            else if (strstr(ln, "XP1000")) mach = Dec21264;
         }
         break;
      case LAIA64: /* don't know */
         break;
      case LAX86:
         if (!CmndOneLine(targ, "sysctl hw.model", ln))
         {
            if (strstr(ln, "Pentium Pro")) mach = IntPPRO;
            else if (strstr(ln, "Pentium III")) mach = IntPIII;
            else if (strstr(ln, "Pentium II ")) mach = IntPII;
            else if (strstr(ln, "Athlon")) mach = AmdAthlon;
            else if (strstr(ln, "AMD-K7")) mach = AmdAthlon;
            else if (strstr(ln, "Pentium/P55C")) mach = IntP5MMX; /* sent by */
            else if (strstr(ln, "Pentium")) mach=IntP5;       /* Nagata Maho */
         }
         break;
      default:;
      }
      break;
   case OSLinux:
      la = ProbeLinuxArch(targ);
      switch(la)
      {
      case LAPPC:
         if ( !CmndOneLine(targ, "cat /proc/cpuinfo | fgrep cpu", ln2) )
         {
            if (strstr(ln2, "604e")) mach = PPC604e;
            else if (strstr(ln2, "604")) mach = PPC604;
            else if (strstr(ln2, "G4")) mach = PPCG4;
         }
         break;
      case LASPARC:  /* don't know here anymore */
         #if 0
         if ( !CmndOneLine(targ, "fgrep cpu /proc/cpuinfo", ln) )
         {
            if (strstr(ln, "UltraSparc II")) mach = SunUS2;
            else if (strstr(ln, "UltraSparc I")) mach = SunUS1;
            else if (strstr(ln, "UltraSparc")) mach = SunUSX;
         }
         #endif
         break;
      case LAALPHA:
         ln[0] = '\0';
         ierr = CmndOneLine(targ, "fgrep 'model name' /proc/cpuinfo", ln);
         if (ierr || ln[0] == '\0')
            ierr = CmndOneLine(targ, "fgrep model /proc/cpuinfo", ln);
         if (!ierr && ln[0] != '\0')
         {
            if (strstr(ln, "EV5")) mach = Dec21164;
            else if (strstr(ln, "EV4")) mach = Dec21064;
            else if (strstr(ln, "EV6")) mach = Dec21264;
         }
         break;
      case LAIA64:
         ln[0] = '\0';
         ierr = CmndOneLine(targ, "fgrep 'model name' /proc/cpuinfo", ln);
         if (ierr || ln[0] == '\0')
            ierr = CmndOneLine(targ, "fgrep model /proc/cpuinfo", ln);
         if (!ierr && ln[0] != '\0')
         {
            if (strstr(ln, "Itanium")) mach = IA64Itan;
         }
         break;
      case LAX86:
         ln[0] = '\0';
         ierr = CmndOneLine(targ, "fgrep 'model name' /proc/cpuinfo", ln);
         if (ierr || ln[0] == '\0')
            ierr = CmndOneLine(targ, "fgrep model /proc/cpuinfo", ln);
         if (!ierr && ln[0] != '\0')
         {
            if (strstr(ln, "Pentium III")) mach = IntPIII;
            else if (strstr(ln, "Pentium II")) mach = IntPII;
            else if (strstr(ln, "Pentium Pro")) mach = IntPPRO;
            else if (strstr(ln, "AMD-K7")) mach = AmdAthlon;
            else if (strstr(ln, "Athlon")) mach = AmdAthlon;
            else if (strstr(ln, "Pentium MMX")) mach = IntP5MMX;
         }
         break;
      default:;
      }
      break;
   case OSSunOS:
      sprintf(ln2, "%s -i", unam);
      if( !CmndOneLine(targ, ln2, ln) )
      {
         if (strstr(ln, "SPARCstation-5")) mach = SunMS;
         else if (strstr(ln, "Ultra-1")) mach = SunUS1;
         else if (strstr(ln, "Ultra-2")) mach = SunUS2;
         else if (strstr(ln, "Ultra-4")) mach = SunUS4;
         else if (strstr(ln, "Ultra-5_")) mach = SunUS5;
         else if (strstr(ln, "Ultra-5\n")) mach = SunUS5;
         else if (strstr(ln, "Ultra")) mach = SunUSX;
      }
      break;
   case OSSunOS4:
      if ( !CmndOneLine(targ, "sysinfo | fgrep CPU | fgrep MHz", ln) )
      {
         if (strstr(ln, "microSPARC")) mach = SunMS;
         else if (strstr(ln, "UltraSPARC"))
         {
            if( !CmndOneLine(targ, "sysinfo | fgrep Ultra", ln) )
            {
               if (strstr(ln, "Ultra-2")) mach = SunUS2;
               else if (strstr(ln, "Ultra-1")) mach = SunUS1;
               else if (strstr(ln, "Ultra")) mach = SunUSX;
            }
         }
         else if (strstr(ln, "Ultra-2")) mach = SunUS2;
         else if (strstr(ln, "Ultra-1")) mach = SunUS1;
         else if (strstr(ln, "Ultra")) mach = SunUSX;
      }
      break;
   case OSOSF1:
      if ( !CmndOneLine(targ, ln2, ln) ) 
      {
         if (strstr(ln, "alpha"))
         {
            ierr = CmndOneLine(targ, "/usr/sbin/pinfo -v | fgrep EV", ln);
            if (ierr)
            {
               ierr = CmndOneLine(targ, "/usr/sbin/psrinfo -v | fgrep EV", ln);
               if (ierr) ierr = CmndOneLine(targ, "psrinfo -v | fgrep EV", ln);
            }
            if (!ierr)
            {
               if (strstr(ln, "EV6")) mach = Dec21264;
               else if (strstr(ln, "EV5")) mach = Dec21164;
               else if (strstr(ln, "EV4")) mach = Dec21064;
            }
         }
      }
      break;
   case OSIRIX:
      if ( !CmndOneLine(targ, ln2, ln) ) 
      {
         if (strstr(ln, "IP28")) mach = SgiIP28;
         else if (strstr(ln, "IP27")) mach = SgiIP27;
         else if (strstr(ln, "IP22")) mach = SgiIP22;
         else if (strstr(ln, "IP32")) mach = SgiIP32;
         else if (strstr(ln, "IP30")) mach = SgiIP30;
      }
      break;
   case OSAIX :
      if (targ)
         sprintf(ln2, "cd CONFIG ; make IRunAixInfo mydir=%s/CONFIG atlrun=atlas_runX targ=%s | fgrep 'CPU type'", TOPdir, targ);
      else
         sprintf(ln2, 
            "cd CONFIG ; make IRunAixInfo mydir=%s/CONFIG | fgrep 'CPU type'", 
                 TOPdir);
      if ( !CmndOneLine(NULL, ln2, ln) )
      {
         if (strstr(ln, "PowerPC"))
         {
            if (strstr(ln, "604e")) mach = PPC604e;
            else if (strstr(ln, "604") && !strstr(ln, "UNKNOWN")) mach = PPC604;
            else if (strstr(ln, "PowerPC 630")) mach = IbmPwr3;
         }
         else if (strstr(ln, "Power"))
         {
            if (strstr(ln, "Power2")) mach= IbmTPwr2;
            else if (strstr(ln, "Power1")) mach = IbmPwr;
         }
      }
      break;
   case OSHPUX:
      if(!CmndOneLine(targ, ln2, ln))
      {
         if (strstr(ln, "9000/735")) mach=HP9K735;
   /*      else if (strstr(ln, "9000/715")) mach=HP9K715; */
      }
      break;
   case OSWin9x:
   case OSWinNT:
   default:;
   }
   return(mach);
}

enum MACHTYPE Getx86Arch(char *targ, char *unam)
{
   char ln[256], ln2[256];
   int i, j;
   enum MACHTYPE mach=MACHOther;

   j = 0;
   sprintf(ln2, "%s -m", unam);
   ln[0] = '\0';
   i = CmndOneLine(targ, ln2, ln);
   if (i || ln[0] == '\0' || strstr(ln, "i586") || strstr(ln, "i486") || 
            strstr(ln, "i386"))
   {
      fprintf(stdout, "Enter your machine type:\n");
      fprintf(stdout, "   1. Other/UNKNOWN\n\n");
      fprintf(stdout, "   2. AMD Athlon\n");
      fprintf(stdout, "   3. Pentium PRO\n");
      fprintf(stdout, "   4. Pentium II\n");
      fprintf(stdout, "   5. Pentium III\n");
      fprintf(stdout, "   6. Pentium 4\n");
      fprintf(stdout, "   7. Pentium \n");
      fprintf(stdout, "   8. Pentium MMX\n");
      fprintf(stdout, "   9. IA-64 Itanium\n");
      j = 9;
   }
   else if (strstr(ln, "ia64")) return(IA64Itan);
   else if (strstr(ln, "i686"))
   {
      fprintf(stdout, "Enter your machine type:\n");
      fprintf(stdout, "   1. Other/UNKNOWN\n");
      fprintf(stdout, "   2. AMD Athlon\n");
      fprintf(stdout, "   3. Pentium PRO\n");
      fprintf(stdout, "   4. Pentium II\n");
      fprintf(stdout, "   5. Pentium III\n");
      fprintf(stdout, "   6. Pentium 4\n");
      j = 6;
   }
   if (j > 0)
   {
      i = GetIntRange(1, 1, j, "", "machine number");
      if (i == 1) mach = MACHOther;
      else if (i == 2) mach = AmdAthlon;
      else if (i == 3) mach = IntPPRO;
      else if (i == 4) mach = IntPII;
      else if (i == 5) mach = IntPIII;
      else if (i == 6) mach = IntP4;
      else if (i == 7) mach = IntP5;
      else if (i == 8) mach = IntP5MMX;
      else if (i == 9) mach = IA64Itan;
      else mach = MACHOther;
   }
   return(mach);
}

enum MACHTYPE GetArch(FILE *fpout, FILE *fplog, enum OSTYPE OS, char *targ,
                      char *TOPdir)
{
   char ln[512], ln2[512];
   int i, j, ierr;
   enum MACHTYPE mach=MACHOther;
   enum LINUXARCH la;
   char *unam=FindUname();

   ATL_mprintf(2, fplog, fpout, "Probing for architecture:\n");
   mach = ProbeArch(OS, targ, TOPdir);
   if (mach != MACHOther)
   {
      ATL_mprintf(2, fplog, fpout, "Architecture is set to %s\n\n", 
                  machnam[mach]);
      return(mach);
   }

   switch(OS)
   {
   case OSFreeBSD:
   case OSLinux:
      la = ProbeLinuxArch(targ);
      switch(la)
      {
      case LAIA64:
         fprintf(stdout, "Enter your machine type:\n");
         fprintf(stdout, "   1. IA-64 Itanium\n");
         fprintf(stdout, "   2. Other/UNKNOWN\n");
         i = GetIntRange(2, 1, 2, "", "machine number");
         if (i == 1) mach = IA64Itan;
         break;
      case LAPPC:
         fprintf(stdout, "Enter your machine type:\n");
         fprintf(stdout, "   1. PowerPC 604e\n");
         fprintf(stdout, "   2. PowerPC 604\n");
         fprintf(stdout, "   3. PowerPC G4 (7400)\n");
         fprintf(stdout, "   4. Other/UNKNOWN\n");
         i = GetIntRange(4, 1, 4, "", "machine number");
         if (i == 1) mach = PPC604e;
         else if (i == 2) mach = PPC604;
         else if (i == 3) mach = PPCG4;
         break;
      case LASPARC:
         fprintf(stdout, "Enter your machine type:\n");
         fprintf(stdout, "   1. Ultra-1\n");
         fprintf(stdout, "   2. Ultra-2\n");
         fprintf(stdout, "   3. Ultra-4\n");
         fprintf(stdout, "   4. Ultra-5/10\n");
         fprintf(stdout, "   5. Other UltraSparc\n");
         fprintf(stdout, "   6. Other/UNKNOWN\n");
         i = GetIntRange(6, 1, 6, "", "machine number");
         if (i == 1) mach = SunUS1;
         else if (i == 2) mach = SunUS2;
         else if (i == 3) mach = SunUS4;
         else if (i == 4) mach = SunUS5;
         else if (i == 5) mach = SunUSX;
         break;
      case LAALPHA:
         fprintf(stdout, "Enter your machine type:\n");
         fprintf(stdout, "   1. DEC ALPHA 21064\n");
         fprintf(stdout, "   2. DEC ALPHA 21164 (ev5/ev56)\n");
         fprintf(stdout, "   3. DEC ALPHA 21264 (ev6)\n");
         fprintf(stdout, "   4. Other/UNKNOWN\n");
         i = GetIntRange(4, 1, 4, "", "machine number");
         if (i == 1) mach = Dec21064;
         else if (i == 2) mach = Dec21164;
         else if (i == 3) mach = Dec21264;
         break;
      case LAX86:
         mach = Getx86Arch(targ, unam);
      }
      break;
   case OSHPUX:
      if(CmndOneLine(targ, ln2, ln)) mach = MACHOther;
      else if (strstr(ln, "9000/735")) mach=HP9K735;
/*      else if (strstr(ln, "9000/715")) mach=HP9K715; */
      else mach = MACHOther;
      break;
   case OSSunOS4:
      fprintf(stdout, "Running trusty old SunOS 4 (hey, is that a Nehru jacket you're wearing), I see.\n");
      fprintf(stdout, 
         "Since SunOS 4 is silent on the subject, what chip do you have:\n");
      fprintf(stdout, 
"   1. UltraSparc\n   2. SuperSparc 1/2\n   3. MicroSparc\n  4. Other/UNKNOWN\n");
      i = GetIntRange(4, 1, 4, "", "chip number");
      if (i == 1) mach = SunUS2;
      else if (i == 2) mach = SunSS;
      else if (i == 3) mach = SunMS;
      break;
   case OSSunOS:
/*      assert(0); */
      break;
   case OSOSF1:
      mach = MACHOther;
         fprintf(stdout, "Looks like you are compiling OSF1/Tru64.\n");
         fprintf(stdout, "Choose model:\n");
         fprintf(stdout, "   1. Alpha 21064\n");
         fprintf(stdout, "   2. Alpha 21164 (ev5/ev56)\n");
         fprintf(stdout, "   3. Alpha 21264 (ev6)\n");
         fprintf(stdout, "   4. Other/UNKNOWN\n\n");
         i = GetIntRange(4, 1, 4, "", "machine number");
         if (i == 1) mach = Dec21064;
         else if (i == 2) mach = Dec21164;
         else if (i == 3) mach = Dec21264;
      break;
   case OSIRIX:
/*      assert(0); */
      break;
   case OSAIX:  /* don't even think about translating IBM's wild-ass uname */
      fprintf(stdout, "Here are the preconfigured ATLAS choices for AIX:\n");
      fprintf(stdout, "   1. IBM Power\n");
      fprintf(stdout, "   2. IBM Thin-node, Power2\n");
      fprintf(stdout, "   3. IBM PowerPC 604\n");
      fprintf(stdout, "   4. IBM PowerPC 604e (silver node)\n");
      fprintf(stdout, "   5. IBM Power3\n");
      fprintf(stdout, "   6. Other/UNKNOWN\n\n");
      i = GetIntRange(6, 1, 6, "", "machine number");
      if (i == 1) mach = IbmPwr;
      else if (i == 2) mach = IbmTPwr2;
      else if (i == 3) mach = PPC604;
      else if (i == 4) mach = PPC604e;
      else if (i == 5) mach = IbmPwr3;
      else mach = MACHOther;
      break;
   case OSWin9x:
   case OSWinNT:
      mach = Getx86Arch(targ, unam);
      break;
   case OSOther:
      break;
   }
   ATL_mprintf(2, fplog, fpout, "Architecture is set to %s\n\n", machnam[mach]);
   return(mach);
}

void GetPmake(enum OSTYPE OS, int ncpu, char *pmake)
{
   if (ncpu == 0) ncpu = 1;
   if (CmndResults(NULL, "make -v | fgrep GNU")) /* using gnu make */
      sprintf(pmake, "$(MAKE) -j %d", 2*ncpu);
   else
   {  /* AIX, HP-UX, SunOS make do not have parallel option */
      switch(OS)
      {
      case OSIRIX:
         strcpy(pmake, "$(MAKE) -P");
         break;
      default:
         strcpy(pmake, "$(MAKE)");
      }
   }
}

char *GetXCompTarg(FILE *fpout0, FILE *fplog, char *targnam)
{
   char *targ=NULL;
   char ln[512];
   int ierr;
   FILE *fpout;

   fprintf(stdout, "\n\nI need to know if you are using a cross-compiler (i.e., you are compiling on\n");
   fprintf(stdout, 
      "a different architecture than you want the library built for).\n\n");
   targnam[0] = '\0';
   if (IsYes('n', "", "Are you using a cross-compiler?"))
   {
      DisplayFile("CONFIG/xcomp.txt", stdout, NLINES);
      do
      {
         GetStrVer(targnam, "", "name of target machine", 511, targnam);
         fprintf(stdout, "\n\nTRYING TO rsh %s\n", targnam);
         sprintf(ln, "rsh %s \"ls\"", targnam);
         ierr = system(ln);
         if (ierr) DisplayFile("CONFIG/xcomp-err.txt", stdout, NLINES);
         else fprintf(stdout, "\n\nrsh successful!\n\n");
         ATL_mprintf(2, stdout, fplog, 
                     "Using cross compiler, spawning runs to %s.\n\n", targnam);
      }
      while (ierr);
      targ = targnam;
      fpout = fopen("CONFIG/Make.inc", "w");
      assert(fpout);
      fprintf(fpout, 
         "atlas_run:\n\trsh %s \"cd $(atldir) ; ./$(exe) $(args) > $(redir)\"\n",
              targnam);
   }
   else
   {
      fpout = fopen("CONFIG/Make.inc", "w");
      assert(fpout);
      fprintf(fpout, "atlas_run:\n\tcd $(atldir) ; ./$(exe) $(args) > $(redir)\n");
   }
   fclose(fpout);
   return(targ);
}

enum USERGEMM GetUserMM(enum OSTYPE OS, enum MACHTYPE mach,
                        char *UMMdir0, char *UMMdef0)
{
   enum USERGEMM iret=UG_None;

   strcpy(UMMdir0, "$(GMMdir)");
   UMMdef0[0] = '\0';

   switch(mach)
   {
   case Dec21164 :
   case Dec21264 :
      DisplayFile("CONFIG/gotogemm.txt", stdout, NLINES);
      if (IsYes('y', "", "Use Goto GEMM for Compaq/DEC alpha speedup?"))
      {
         strcpy(UMMdir0, "$(TOPdir)/src/blas/gemm/GOTO/$(ARCH)");
         if (mach == Dec21164) strcpy(UMMdef0, "-DEV5");
         else if (mach == Dec21264) strcpy(UMMdef0, "-DEV6");
         iret = UG_GOTO;
      }
      break;
   default:;
   }
   return(iret);
}

void GoToTown()
{
   char ARCH0[128], ARCH[128], TOPdir[256], LIBdir[256], ATLASlib[256];
   char UMMdir[256], UMMdef[256];
   char CBLASlib[256], PTCBLASlib[256];
   char F77BLASlib[256], PTF77BLASlib[256];
   int L1SIZE=(-1), L2SIZE;
   char F2CDEFS[256];
   char F77[128], CC[128], MCC[128], XCC[128];
   char F77FLAGS[512], CCFLAGS[512], MMFLAGS[512], XCCFLAGS[512];
   char FLINKER[128], CLINKER[128], ARCHIVER[128], RANLIB[128];
   char CLINKFLAGS[512], FLINKFLAGS[512], ARFLAGS[256];
   char BLASlib[256], LIBS[256];
   char TAR[256], GZIP[256], GUNZIP[256], PMAKE[128];

   char comp[64], cflg[512], ln[512], tnam[256], archdef[256], mmdef[256];
   char BC[256], BCFLAGS[256];
   int ncpu, GOGO=0, L2IsKnown=0, Use3DNow=0;
   int ierr, i, j, SOLERR=0, np=2, delay=0;
   char *paths[2] = {"/usr/bin/", "/usr/local/"};
   char *sp, *targ;
   enum OSTYPE OS=OSOther, XOS=OSOther;
   enum MACHTYPE Xmach=MACHOther;
   enum F2CNAME f2cnam;
   enum F2CINT f2cint;
   enum F2CSTRING f2cstr;
   enum ISAEXT ISAX;
   enum USERGEMM USERMM=UG_None;
   FILE *fpout, *fplog, *fps[2];
   const char *lognam="ConfSummary.log", *dmpnam="ConfDump.log";
   char redir[128];
   sprintf(redir, ">> %s 2>&1", dmpnam);

   F2CDEFS[0] = '\0';
   remove(dmpnam);
   fplog = fopen(lognam, "w");
   fps[0] = stdout;
   fps[1] = fplog;
   assert(fplog);
   assert(tmpnam(tnam));
   ATL_mprintf(2, fplog, stdout, "ATLAS configure started.\n\n");
   NLINES = GetScreenHeight();

   DisplayFile("CONFIG/errata.txt", stdout, NLINES);
   if (!IsYes('y', "", "Have you scoped the errata file?")) exit(-1);
   DisplayFile("CONFIG/init.txt", stdout, NLINES);
   if (!IsYes('y', "", "Are you ready to continue?")) exit(-1);

   targ = GetXCompTarg(stdout, fplog, TARGNAM);
   if (targ) XCOMP = 1;
/* 
 * Set up some good defaults
 */
   sp = getenv("PWD");
   if (sp) strcpy(TOPdir, sp);
   else 
   {
      i = CmndOneLine(targ, "pwd", ln);
      if (i || ln[0] == '\0') strcpy(TOPdir, "$(HOME)/ATLAS");
      else
      {
         for (i=0; TOPdir[i] = ln[i]; i++);
         i--;
         while(Mciswspace(TOPdir[i])) i--;
         TOPdir[i+1] = '\0';
      }
   }
   strcpy(LIBdir, "$(TOPdir)/lib/$(ARCH)");
   strcpy(ATLASlib, "libatlas.a");
   strcpy(F77BLASlib, "libf77blas.a");
   strcpy(CBLASlib, "libcblas.a");
   strcpy(PTCBLASlib, "libptcblas.a");
   strcpy(PTF77BLASlib, "libptf77blas.a");
   strcpy(ARCHIVER, "ar");
   strcpy(ARFLAGS, "r");
   strcpy(RANLIB, "echo");
   BLASlib[0] = '\0';
   L2SIZE = MAXL2SIZE;

   OS = GetOS(stdout, fplog, targ);
   ISWIN = OSIsWin(OS);
   mach = GetArch(stdout, fplog, OS, targ, TOPdir);
   ISAX = GetISAExt(targ, TOPdir);
   USERMM = GetUserMM(OS, mach, UMMdir, UMMdef);
   if (ISAX == ISA_3DNow1 || ISAX == ISA_3DNow2)
   {
      DisplayFile("CONFIG/3DNow.txt", stdout, NLINES);
      Use3DNow = IsYes('n', "   ", "Use 3DNow! for computation?");
      if (!Use3DNow) ISAX = ISA_None;
   }
   ncpu = ProbeNCPU(OS, mach, targ, TOPdir);
   if (ncpu != 1) /* user may want to thread */
   {
      DisplayFile("CONFIG/pthread.txt", stdout, NLINES);
      if ( IsYes('y', "   ", "enable Posix threads support?") )
      {
         THREADS=1;
         ncpu = GetNCPU(OS, mach, targ, TOPdir);
      }
      else ncpu = 1;
   }
   if (ncpu) ATL_mprintf(2, fplog, stdout, "Number of CPUs: %d\n\n", ncpu);
   else ATL_mprintf(2, fplog, stdout,
                    " Unable to determine number of CPUs.\n\n");

   strcpy(ARCH0, machnam[mach]);
   if (ISAX != ISA_None) strcat(ARCH0, ISAXNAM[ISAX]);
   if (USERMM) strcat(ARCH0, usermmnam[USERMM]);
   L1SIZE = GetCacheSize(OS,  mach, targ, TOPdir, 1, &i);
   if (!i) L1SIZE = -1;

/*
 * Linux paging may screw up L1 cache on 604e, so force detection
 */
   if (OS == OSLinux && mach == PPC604e) L1SIZE = -1;

   L2SIZE = GetCacheSize(OS,  mach, targ, TOPdir, -2, &L2IsKnown) * 1024;
   if (L2IsKnown)
      ATL_mprintf(2, fplog, stdout, 
                  "Required cache flush detected as : %d bytes\n", L2SIZE);
   GetCompInfo(stdout, fplog, OS, mach, targ, redir, TOPdir, F77, F77FLAGS, 
               FLINKER, FLINKFLAGS, CC, CCFLAGS, CLINKER, CLINKFLAGS, 
               MCC, MMFLAGS, BLASlib);
   GetSyslib(OS, mach, targ, LIBS);
   if (XCOMP)
   {
      delay = 60;
      ATL_mprintf(2, fplog, stdout, "\n\n*******************************************************************************\n");
      ATL_mprintf(2, fplog, stdout, "****************  FINDING INFO ABOUT CROSS-COMPILING MACHINE  *****************\n");
      ATL_mprintf(2, fplog, stdout, "*******************************************************************************\n");
      XOS = GetOS(stdout, fplog, NULL);
      Xmach = GetArch(stdout, fplog, XOS, NULL, TOPdir);
      GetCompInfo(stdout, fplog, XOS, Xmach, NULL, redir, TOPdir, NULL, NULL, 
                  NULL, NULL, XCC, XCCFLAGS, NULL, NULL,
                  NULL, NULL, NULL);
      ATL_mprintf(2, fplog, stdout, "\n\n*******************************************************************************\n");
      ATL_mprintf(2, fplog, stdout, "****************  DONE FINDING INFO ABOUT CROSS-COMPILING MACHINE  ************\n");
      ATL_mprintf(2, fplog, stdout, "*******************************************************************************\n");
   }
   else
   {
      strcpy(XCC, CC);
      strcpy(XCCFLAGS, CCFLAGS);
   }
   if (OS == OSSunOS4) strcpy(RANLIB, "ranlib");

   ATL_mprintf(2, fplog, stdout, "FINDING tar, gzip, AND gunzip\n");
   FindTarZip(TAR, GZIP, GUNZIP);
   ATL_mprintf(2, fplog, stdout, "   tar    : %s\n", TAR);
   ATL_mprintf(2, fplog, stdout, "   gzip   : %s\n", GZIP);
   ATL_mprintf(2, fplog, stdout, "   gunzip : %s\n", GUNZIP);
   GetPmake(OS, ncpu, PMAKE);

   if (OS != OSOther)
   {
      if (mach != MACHOther)
         fprintf(stdout, 
         "\n\nATLAS has default parameters for OS=\'%s\' and system=\'%s\'.\n",
                 osnam[OS], machnam[mach]);
      else
         fprintf(stdout, 
"\n\nAlthough your machine is not known, ATLAS has default parameters for OS=\'%s\'.\n",
                 osnam[OS]);
      fprintf(stdout,
"If you want to just trust these default values, you can use express setup,\n");
      fprintf(stdout,
"drastically reducing the amount of questions you are required to answer\n\n");
      GOGO = IsYes('y', "   ", "use express setup?");
      fprintf(stdout, "\n\n");
   }

   DisplayFile("CONFIG/arch.txt", stdout, NLINES);
   if (OS == OSOther) strcpy(ARCH, "UNKNOWN");
   else strcpy(ARCH, osnam[OS]);
   strcat(ARCH, "_");
   strcat(ARCH, ARCH0);
   if (THREADS) /* add ncpu to ARCH */
   {
      for (i=0; ARCH[i]; i++);
      sprintf(ARCH+i, "_%d", ncpu);
   }
   do
   {
      GetString(stdin, ARCH, "   ", "Architecture name (ARCH)", 127, ARCH);
      sprintf(ln, "Make.%s", ARCH);
      ierr = FileIsThere(ln);
      if (ierr)
      {
         fprintf(stderr, "File Make.%s already exists!\n", ARCH);
         ierr = !IsYes('n', "", "overwrite it?");
      }
   }
   while (ierr);
   ATL_mprintf(2, stdout, fplog, "<arch> set to \'%s\'\n\n", ARCH);

   if (!L2IsKnown)
   {
      DisplayFile("CONFIG/l2size.txt", stdout, NLINES);
      L2SIZE = GetIntRange(L2SIZE/1024, 64, 16*1024, "   ", 
                           "Maximum cache size (KB)");
      L2SIZE *= 1024;
   }
   else if (L2SIZE > MAXL2SIZE)
   {
      DisplayFile("CONFIG/l2sizemax.txt", stdout, NLINES);
      L2SIZE = GetIntRange(L2SIZE/1024, 64, 16*1024, "   ", 
                           "Maximum cache size (KB)");
      L2SIZE *= 1024;
   }
   DisplayFile("CONFIG/nfsdelay.txt", stdout, NLINES);
   delay = GetIntRange(delay, 0, 600, "   ", "File creation delay in seconds");
   if (!GOGO)
   {
      GetString(stdin, TOPdir, "   ", "Top level ATLAS directory", 255, TOPdir);
      GetString(stdin, LIBdir, "   ", 
                "Directory to build libraries in", 255, LIBdir);

      GetString(stdin, ATLASlib, "   ", 
                "Library name for ATLAS primitives", 255, ATLASlib);
      GetString(stdin, CBLASlib, "   ", 
                "Library name for the C interface to BLAS", 255, CBLASlib);
      GetString(stdin, F77BLASlib, "   ", 
                "Library name for the Fortran77 interface to BLAS", 
                255, F77BLASlib);
      if (THREADS)
      {
         GetString(stdin, PTCBLASlib, "   ", 
                   "Library name for the C interface to BLAS", 255, PTCBLASlib);
         GetString(stdin, PTF77BLASlib, "   ", 
                   "Library name for the Fortran77 interface to BLAS", 
                   255, PTF77BLASlib);
      }
   }

   ierr = !GOGO;
   if (!GOGO) DisplayFile("CONFIG/f77exp.txt", stdout, NLINES);
   do
   {
      if (ierr != 0)
      {
         if (GOGO) DisplayFile("CONFIG/f77exp.txt", stdout, NLINES);
         GetString(stdin, F77, "   ", "f77 compiler", 127, F77);
         GetString(stdin, F77FLAGS, "   ", "F77 Flags", 511, F77FLAGS);
      }
      sprintf(ln, "%s -c CONFIG/tst.f %s\n", F77, redir);
      ierr = system(ln);
      if (ierr)
      {
         if (GOGO) DisplayFile("CONFIG/f77exp.txt", stdout, NLINES);
         fprintf(stderr, "F77 = \'%s %s\' doesn't seem to work for me.\n", 
                 F77, F77FLAGS);
         ierr = GetIntRange(1, 0, 1, "   ", 
                         "1 to enter a different F77, 0 to continue with none");
      }
   }
   while (ierr);
   if (!GOGO)
   {
      GetString(stdin, FLINKER, "   ", "F77 Linker ", 127, FLINKER);
      GetString(stdin, FLINKFLAGS, "   ", "F77 Link Flags ", 511, FLINKFLAGS);
      fprintf(stdout, "\n\n");
   }
   ATL_mprintf(2, fplog, stdout, "F77 & FLAGS: %s %s\n", F77, F77FLAGS);
   ATL_mprintf(2, fplog, stdout, "FLINKER & FLAGS: %s %s\n\n", 
               FLINKER, FLINKFLAGS);

   ierr = !GOGO;
   if (!GOGO) DisplayFile("CONFIG/ccomp.txt", stdout, NLINES);
   do
   {
      if (ierr != 0)
      {
         if (GOGO) DisplayFile("CONFIG/ccomp.txt", stdout, NLINES);
         GetString(stdin, CC, "   ", "ANSI C compiler(CC)", 127, CC);
         GetString(stdin, CCFLAGS, "   ", "C Flags (CCFLAGS)", 511, CCFLAGS);
      }
      sprintf(ln, "%s %s -c CONFIG/tst.c %s\n", CC, CCFLAGS, redir);
      ierr = system(ln);
      if (ierr)
      {
         fprintf(stderr, 
                 "Compiling with = \'%s %s\' doesn't seem to work for me.\n",
                 CC, CCFLAGS);
         ierr = GetIntRange(1, 0, 1, "   ", 
                           "1 to try different CC/flags, 0 to continue anyway");
      }
   }
   while(ierr);
   ATL_mprintf(2, fplog, stdout, "CC & FLAGS: %s %s\n", CC, CCFLAGS);

   if (MachIsAlpha(mach))
   {
      if (GOGO)
      {
         ierr = 1;
         if (!strstr(MCC, "gcc"))
            DisplayFile("CONFIG/ccomp-alpha_nogcc.txt", stdout, NLINES);
         else if (!GccV278(MCC))
            DisplayFile("CONFIG/ccomp-alpha_newgcc.txt", stdout, NLINES);
         else ierr = 0;
         if (ierr) if ( !IsYes('y', "", "Continue install anyway?") ) exit(1);
      }
   }
   if (MachIsAlpha(mach)&& !GOGO)
      DisplayFile("CONFIG/ccomp-alpha.txt", stdout, NLINES);
   ierr = !GOGO;
   do
   {
      if (ierr != 0)
      {
         if (GOGO) DisplayFile("CONFIG/ccomp-alpha.txt", stdout, NLINES);
         GetString(stdin, MCC, "   ", "C compiler for generated code (MCC)", 
                   127, MCC);
         GetString(stdin, MMFLAGS, "   ", "C FLAGS (MMFLAGS)", 511, MMFLAGS);
      }
      Wstrfndsub("$(CC)", CC, MCC, comp);
      Wstrfndsub("$(CCFLAGS)", CCFLAGS, MMFLAGS, ln);
      Wstrfndsub("$(CDEFS)", "", ln, cflg);
      sprintf(ln, "%s %s -c CONFIG/tst.c %s\n", comp, cflg, redir);
      ierr = system(ln);
      if (ierr)
      {
         fprintf(stderr, 
                 "Compiling with \'%s %s\' doesn't seem to work for me.\n", 
                 MCC, MMFLAGS);
         ierr = GetIntRange(1, 0, 1, "   ", 
                            "1 to re-enter, 0 to continue anyway");
      }
   }
   while(ierr);
   if (!GOGO)
   {
      GetString(stdin, CLINKER, "   ", "C Linker ", 127, CLINKER);
      GetString(stdin, CLINKFLAGS, "   ", "C Link Flags ", 511, CLINKFLAGS);
   }
   ATL_mprintf(2, fplog, stdout, "MCC & FLAGS: %s %s\n", MCC, MMFLAGS);
   ATL_mprintf(2, fplog, stdout, "CLINKER & FLAGS: %s %s\n\n", 
               CLINKER, CLINKFLAGS);
   if (XCOMP)
   {
      ierr = !GOGO;
      do
      {
         if (ierr != 0)
         {
            GetString(stdin, XCC, "   ", 
                      "ANSI C compiler for cross-compiling machine (XCC)", 
                      127, XCC);
            GetString(stdin, XCCFLAGS, "   ", 
                      "C Flags for cross-compiling machine (XCCFLAGS)", 
                      511, XCCFLAGS);
         }
         Wstrfndsub("$(CC)", CC, XCC, comp);
         Wstrfndsub("$(CCFLAGS)", CCFLAGS, XCCFLAGS, ln);
         Wstrfndsub("$(CDEFS)", "", ln, cflg);
         sprintf(ln, "%s %s -c CONFIG/tst.c %s\n", comp, cflg, redir);
         ierr = system(ln);
         if (ierr)
         {
            fprintf(stderr, 
                    "Compiling with \'%s %s\' doesn't seem to work for me.\n", 
                    XCC, XCCFLAGS);
            ierr = GetIntRange(1, 0, 1, "   ", 
                               "1 to re-enter, 0 to continue anyway");
         }
      }
      while(ierr);
      ATL_mprintf(2, fplog, stdout, "XCC & FLAGS: %s %s\n\n", XCC, XCCFLAGS);
   }

   if (!GOGO)
   {
      GetString(stdin, ARCHIVER, "   ", "Archiver ", 127, ARCHIVER);
      GetString(stdin, ARFLAGS, "   ", "Archiver flags ", 255, ARFLAGS);
      GetString(stdin, RANLIB, "   ", "Ranlib ", 127, RANLIB);
      GetString(stdin, BLASlib, "   ", "BLAS library", 255, BLASlib);
      GetString(stdin, LIBS, "   ", "General and system libs", 255, LIBS);
   }

   fprintf(stdout, 
           "\nFinding F77 to C calling conventions (this may take a while):\n");
   findF2C(redir, targ, TOPdir, F77, F77FLAGS, FLINKER, FLINKFLAGS, CC, CCFLAGS,
           &f2cnam, &f2cint, &f2cstr);
   fprintf(stdout, "\nCalculated F77/C interoperation conventions:\n");
   sp = F2CDEFS;
   if (f2cnam == f2c_Add_)
   {
      ATL_mprintf(2, fplog, stdout, "   Suffix F77 names with _\n");
      strcpy(sp, "-DAdd_ ");
      sp += 7;
   }
   else if (f2cnam == f2c_NoChange) 
   {
      ATL_mprintf(2, fplog, stdout, "   C & F77 share the same namespace\n");
      strcpy(sp, "-DNoChange ");
      sp += 11;
   }
   else if (f2cnam == f2c_UpCase)
   {
      strcpy(sp, "-DUpCase ");
      sp += 9;
      ATL_mprintf(2, fplog, stdout, "   Make F77 names upper case\n");
   }
   else if (f2cnam == f2c_Add__)
   {
      strcpy(sp, "-DAdd__ ");
      sp += 8;
      ATL_mprintf(2, fplog, stdout, 
                  "   Suffix F77 names with underscores with __\n");
   }
   else ATL_mprintf(2, fplog, stdout, 
                    "   Unable to determine naming conventions\n");

   if (f2cint == FintCint)
      ATL_mprintf(2, fplog, stdout, "   F77 INTEGER -> C int\n");
   else if (f2cint == FintClong)
   {
      ATL_mprintf(2, fplog, stdout, "   F77 INTEGER -> C long\n");
      strcpy(sp, "-DF77_INTEGER=long ");
      sp += 19;
   }
   else if (f2cint == FintCshort)
   {
      ATL_mprintf(2, fplog, stdout,"   F77 INTEGER -> C short\n");
      strcpy(sp, "-DF77_INTEGER=short ");
      sp += 20;
   }
   else ATL_mprintf(2, fplog, stdout,
                    "   Unable to determine F77/C integer correspondence\n");

   if (f2cstr == fstrSun)
   {
      strcpy(sp, "-DStringSunStyle");  
      ATL_mprintf(2, fplog, stdout, 
                  "   F77 strings handled via standard sun style\n");
   }
   else if (f2cstr == fstrCray)
   {
      strcpy(sp, "-DCRAY");  
      ATL_mprintf(2, fplog, stdout, "   F77 strings handled using CRAY fcd\n");
   }
   else if (f2cstr == fstrStructVal)
   {
      strcpy(sp, "-DStringStructVal");  
      ATL_mprintf(2, fplog, stdout, 
                  "   F77 strings handled by passing a struct\n");
   }
   else if (f2cstr == fstrStructPtr)
   {
      strcpy(sp, "-DStringStructPtr");  
      ATL_mprintf(2, fplog, stdout,
                  "   F77 strings handled by passing a pointer to struct\n");
   }
   else ATL_mprintf(2, fplog, stdout,
                    "   Unable to determine F77/C string interoperation\n");

   mmdef[0] = archdef[0] = '\0';
   if (mach != MACHOther)
   {
      DisplayFile("CONFIG/NoSearch.txt", stdout, NLINES);
      if ( IsYes('y', "", "Use supplied default values for install?") )
      {
         ATL_mprintf(2, fplog, stdout, 
                     "\n\nUnpacking Architectural defaults . . . ");
         sprintf(ln, "cd CONFIG/ARCHS ; %s -c %s.tgz | %s xvf - %s\n", 
                 GUNZIP, ARCH0, TAR, redir);
         system(ln);
         ATL_mprintf(2, fplog, stdout, "done.\n");
         GetArchDef(OS, mach, ARCH0, CC, MCC, mmdef, archdef);
      }
   }
   if (USEWINF77) strcpy(F77, "$(BINdir)/winf77.exe");

   ATL_mprintf(2, fplog, stdout,"\nCreating make include file Make.%s\n", ARCH);
   sprintf(ln, "Make.%s", ARCH);
   fpout = fopen(ln, "w");
   assert(fpout);
   fprintf(fpout, "#  ----------------------------------\n");
   fprintf(fpout, "#  Make sure we get the correct shell\n");
   fprintf(fpout, "#  ----------------------------------\n");
   fprintf(fpout, "   SHELL = /bin/sh\n\n");

   fprintf(fpout, "#  -------------------------------------------------\n");
   fprintf(fpout, "#  Name indicating the platform to configure BLAS to\n");
   fprintf(fpout, "#  -------------------------------------------------\n");
   fprintf(fpout, "   ARCH = %s\n\n", ARCH);

   fprintf(fpout, "#  -------------------\n");
   fprintf(fpout, "#  Various directories\n");
   fprintf(fpout, "#  -------------------\n");
   fprintf(fpout, "   TOPdir = %s\n", TOPdir);
   fprintf(fpout, "   INCdir = $(TOPdir)/include/$(ARCH)\n");
   fprintf(fpout, "   SYSdir = $(TOPdir)/tune/sysinfo/$(ARCH)\n");
   fprintf(fpout, "   GMMdir = $(TOPdir)/src/blas/gemm/$(ARCH)\n");
   fprintf(fpout, "   UMMdir = %s\n", UMMdir);
   fprintf(fpout, "   GMVdir = $(TOPdir)/src/blas/gemv/$(ARCH)\n");
   fprintf(fpout, "   GR1dir = $(TOPdir)/src/blas/ger/$(ARCH)\n");
   fprintf(fpout, "   L1Bdir = $(TOPdir)/src/blas/level1/$(ARCH)\n");
   fprintf(fpout, "   L2Bdir = $(TOPdir)/src/blas/level2/$(ARCH)\n");
   fprintf(fpout, "   L3Bdir = $(TOPdir)/src/blas/level3/$(ARCH)\n");
   fprintf(fpout, "   TSTdir = $(TOPdir)/src/testing/$(ARCH)\n");
   fprintf(fpout, "   AUXdir = $(TOPdir)/src/auxil/$(ARCH)\n");
   fprintf(fpout, "   CBLdir = $(TOPdir)/interfaces/blas/C/src/$(ARCH)\n");
   fprintf(fpout, "   FBLdir = $(TOPdir)/interfaces/blas/F77/src/$(ARCH)\n");
   fprintf(fpout, "   BINdir = $(TOPdir)/bin/$(ARCH)\n");
   fprintf(fpout, "   LIBdir = %s\n", LIBdir);
   fprintf(fpout, "   PTSdir = $(TOPdir)/src/pthreads\n");
   fprintf(fpout, "   MMTdir = $(TOPdir)/tune/blas/gemm/$(ARCH)\n");
   fprintf(fpout, "   MVTdir = $(TOPdir)/tune/blas/gemv/$(ARCH)\n");
   fprintf(fpout, "   R1Tdir = $(TOPdir)/tune/blas/ger/$(ARCH)\n");
   fprintf(fpout, "   L1Tdir = $(TOPdir)/tune/blas/level1/$(ARCH)\n");
   fprintf(fpout, "   L3Tdir = $(TOPdir)/tune/blas/level3/$(ARCH)\n\n");

   fprintf(fpout,
"#  ---------------------------------------------------------------------\n");
   fprintf(fpout,
"#  Name and location of scripts for running executables during tuning\n");
   fprintf(fpout,
"#  ---------------------------------------------------------------------\n");
   fprintf(fpout, "   ATLRUN = $(BINdir)/ATLrun.sh\n");
   fprintf(fpout, "   ATLFWAIT = $(BINdir)/xatlas_waitfile\n\n");

   fprintf(fpout, "#  ---------------------\n");
   fprintf(fpout, "#  Libraries to be built\n");
   fprintf(fpout, "#  ---------------------\n");
   fprintf(fpout, "   ATLASlib = $(LIBdir)/%s\n", ATLASlib);
   fprintf(fpout, "   CBLASlib = $(LIBdir)/%s\n", CBLASlib);
   fprintf(fpout, "   F77BLASlib = $(LIBdir)/libf77blas.a\n");
   if (THREADS)
   {
      fprintf(fpout, "   PTCBLASlib = $(LIBdir)/%s\n", PTCBLASlib);
      fprintf(fpout, "   PTF77BLASlib = $(LIBdir)/%s\n", PTF77BLASlib);
   }
   fprintf(fpout, "   LAPACKlib = $(LIBdir)/liblapack.a\n\n");
   fprintf(fpout, "   TESTlib = $(LIBdir)/libtstatlas.a\n");

   fprintf(fpout, "#  -------------------------------------------\n");
   fprintf(fpout, "#  Upper bound on largest cache size, in bytes\n");
   fprintf(fpout, "#  -------------------------------------------\n");
   fprintf(fpout, "   L2SIZE = -DL2SIZE=%d\n\n", L2SIZE);

   fprintf(fpout, "#  ---------------------------------------\n");
   fprintf(fpout, "#  Command setting up correct include path\n");
   fprintf(fpout, "#  ---------------------------------------\n");
   fprintf(fpout, 
      "   INCLUDES = -I$(TOPdir)/include -I$(TOPdir)/include/$(ARCH) \\\n");
   fprintf(fpout, 
      "              -I$(TOPdir)/include/contrib \n\n");

   fprintf(fpout, "#  -------------------------------------------\n");
   fprintf(fpout, "#  Defines for setting up F77/C interoperation\n");
   fprintf(fpout, "#  -------------------------------------------\n");
   fprintf(fpout, "   F2CDEFS = %s\n\n", F2CDEFS);

   fprintf(fpout, "#  --------------------------------------\n");
   fprintf(fpout, "#  Special defines for user-supplied GEMM\n");
   fprintf(fpout, "#  --------------------------------------\n");
   fprintf(fpout, "   UMMDEFS = %s\n\n", UMMdef);

   fprintf(fpout, "#  -------------------------------\n");
   fprintf(fpout, "#  Architectural identifying flags\n");
   fprintf(fpout, "#  -------------------------------\n");
   fprintf(fpout, "   ARCHDEFS =");
   if (OS != OSOther) fprintf(fpout, " -DATL_OS_%s", osnam[OS]);
   if (mach != MACHOther) fprintf(fpout, " -DATL_ARCH_%s", machnam[mach]);
   if (USERMM) fprintf(fpout, " -DUSERGEMM");
   if (OSIsWin(OS)) fprintf(fpout, " -DGCCWIN");
   if (ISAX != ISA_None) fprintf(fpout, " -DATL_%s", ISAXNAM[ISAX]);
   if (Use3DNow) fprintf(fpout, " -DATL_3DNowFLOPS");
   if (mach == IA64Itan) fprintf(fpout, " -DATL_MAXNREG=128");
   fprintf(fpout, "\n\n");

   fprintf(fpout, 
   "#  -------------------------------------------------------------------\n");
   fprintf(fpout, 
   "#  NM is the flag required to name a compiled object/executable\n");
   fprintf(fpout, 
   "#  OJ is the flag required to compile to object rather than executable\n");
   fprintf(fpout, "#  These flags are used by all compilers.\n");
   fprintf(fpout, 
   "#  -------------------------------------------------------------------\n");
   fprintf(fpout, "   NM = -o\n");
   fprintf(fpout, "   OJ = -c\n\n");

   DisplayFile("CONFIG/f77make.txt", fpout, 0);
   fprintf(fpout, "   F77 = %s\n", F77);
   fprintf(fpout, "   F77FLAGS = %s\n", F77FLAGS);
   fprintf(fpout, "   FLINKER = %s\n", FLINKER);
   fprintf(fpout, "   FLINKFLAGS = %s\n\n", FLINKFLAGS);

   DisplayFile("CONFIG/CCmake.txt", fpout, 0);
   fprintf(fpout, "   CDEFS = $(L2SIZE) $(INCLUDES) $(F2CDEFS) $(ARCHDEFS)");
   if (THREADS)
   {
      fprintf(fpout, " -DATL_NCPU=%d", ncpu);
      if (OS == OSAIX) fprintf(fpout, " -DIBM_PT_ERROR");
      if (OS == OSIRIX) fprintf(fpout, " -D_POSIX_C_SOURCE=199506L");
   }
   if (delay) fprintf(fpout, " -DATL_FOPENDELAY");
   fprintf(fpout, "\n\n");

   fprintf(fpout, "   CC = %s\n", CC);
   fprintf(fpout, "   CCFLAGS = $(CDEFS) %s\n", CCFLAGS);
   fprintf(fpout, "   MCC = %s\n", MCC);
   fprintf(fpout, "   MMFLAGS = %s\n", MMFLAGS);
   fprintf(fpout, "   XCC = %s\n", XCC);
   if (strstr(XCCFLAGS, "CCFLAGS"))
      fprintf(fpout, "   XCCFLAGS = %s\n", XCCFLAGS);
   else fprintf(fpout, "   XCCFLAGS = $(CDEFS) %s\n", XCCFLAGS);
   fprintf(fpout, "   CLINKER = %s\n", CLINKER);
   fprintf(fpout, "   CLINKFLAGS = %s\n", CLINKFLAGS);
   if (SOLERR)
   {
      fprintf(fpout, "   BC = %s\n", BC);
      fprintf(fpout, "   BCFLAGS = $(CDEFS) %s\n", BCFLAGS);
   }
   else
   {
      fprintf(fpout, "   BC = $(CC)\n", CC);
      fprintf(fpout, "   BCFLAGS = $(CCFLAGS)\n");
   }
   fprintf(fpout, "   ARCHIVER = %s\n", ARCHIVER);
   fprintf(fpout, "   ARFLAGS  = %s\n", ARFLAGS);
   fprintf(fpout, "   RANLIB   = %s\n\n", RANLIB);

   fprintf(fpout, "#  -------------------------------------\n");
   fprintf(fpout, "#  tar, gzip, gunzip, and parallel make\n");
   fprintf(fpout, "#  -------------------------------------\n");
   fprintf(fpout, "   TAR    = %s\n", TAR);
   fprintf(fpout, "   GZIP   = %s\n", GZIP);
   fprintf(fpout, "   GUNZIP = %s\n", GUNZIP);
   fprintf(fpout, "   PMAKE  = %s\n\n", PMAKE);

   fprintf(fpout, "#  ------------------------------------\n");
   fprintf(fpout, "#  Reference and system libraries\n");
   fprintf(fpout, "#  ------------------------------------\n");
   fprintf(fpout, "   BLASlib = %s\n", BLASlib);
   fprintf(fpout, "   FBLASlib = \n");
   fprintf(fpout, "   FLAPACKlib = \n");
   fprintf(fpout, "   LIBS = %s\n\n", LIBS);

   fprintf(fpout, "#  ---------------------------------------------\n");
   fprintf(fpout, "#  Architecture default directories, if supplied\n");
   fprintf(fpout, "#  ---------------------------------------------\n");
   fprintf(fpout, "   ARCHDEF = %s\n", archdef);
   fprintf(fpout, "   MMDEF = %s\n\n", mmdef);

   fprintf(fpout, "#  ---------------------------------------\n");
   fprintf(fpout, "#  Generic targets needed by all makefiles\n");
   fprintf(fpout, "#  ---------------------------------------\n");
   if (delay)
   {
      fprintf(fpout, "   waitfile = wfdefault\n");
      fprintf(fpout, "waitfile:\n\tcd $(BINdir) ; make xatlas_waitfile\n");
      fprintf(fpout, "\t$(ATLFWAIT) -s %d -f $(waitfile)\n", delay);
   }
   else fprintf(fpout, "waitfile:\n");
   fclose(fpout);
   ATL_mprintf(2, fplog, stdout, "Make.%s successfully created.\n\n", ARCH);

   ATL_mprintf(2, fplog, stdout, "\n\nCreating ATLrun.sh\n\n", ARCH);
   sprintf(ln, "CONFIG/ATLrun.%s", ARCH);
   fpout = fopen(ln, "w");
   assert(fpout);
   fprintf(fpout, "#!/bin/sh\n");
   fprintf(fpout, "atldir=$1\nshift\n");
   if (XCOMP)
      fprintf(fpout, "exe=$1\nshift\nrsh %s \"cd $atldir ; ./$exe $*\"", 
              TARGNAM);
   else fprintf(fpout, "$atldir/$*\n");
   fclose(fpout);
   sprintf(ln, "chmod a+rx CONFIG/ATLrun.%s\n", ARCH);
   assert(system(ln) == 0);

   fprintf(stdout, "Creating subdirectories:\n");
   fprintf(stdout, "   Checking for already existing subdirectories  .....");
   fflush(stdout);
   sprintf(ln, "cd bin/%s %s", ARCH, redir);
   i = 1;
   if (system(ln) == 0)
   {
      fprintf(stdout, "...... found!\n");
      i = IsYes('y', "", "kill old subdirectories?");
   }
   else fprintf(stdout, "... no\n");
   if (i)
   {
      sprintf(ln, "make killall arch=%s %s\n", ARCH, redir);
      system(ln);
      sprintf(ln, "make startup arch=%s %s\n", ARCH, redir);
      if (system(ln))
      {
         fps[0] = stderr;
         fps[1] = fplog;
         for (i=0; i < 2; i++)
         {
            fprintf(fps[i], "UNABLE TO CREATE NECESSARY SUBDIRECTORIES:\n");
            fprintf(fps[i], 
       "  review Make.%s for accurracy, paying special attention to TOPdir.\n",
                    ARCH);
            fprintf(fps[i], "Examine %s and %s for specifics.\n", 
                    lognam, dmpnam);
            fprintf(fps[i], 
               "   for further help, see ATLAS/README/TroubleShoot.txt.\n");
            fprintf(fps[i],
                    "   when you have corrected the problem, finish the\n");
            fprintf(fps[i], "   configuration by typing :\n");
            fprintf(fps[i], "      make startup arch=%s\n", ARCH);
         }
         sprintf(ln, "make killall arch=%s %s\n", ARCH, redir);
         system(ln);
         fclose(fplog);
         exit(-1);
      }
   }
   ATL_mprintf(2, fplog, stdout, "Subdirectories successfully created.\n\n");
   if (USEWINF77)
   {
      ATL_mprintf(2, fplog, stdout, "\n\nCreating winf77.exe\n\n", ARCH);
      sprintf(ln, "cd CONFIG ; make winf77bob ARCH=%s", ARCH);
      if ( system(ln) )
      {
         ATL_mprintf(2, fplog, stderr, "Unable to create winf77, aborting.\n");
         fclose(fplog);
         exit(-1);
      }
   }
   if (L1SIZE != -1)
   {
      ATL_mprintf(2, fplog, stdout, "\nStoring L1 cache size of %dKB.\n\n", 
                  L1SIZE);
      sprintf(ln, "make -f Make.top ISetL1 arch=%s L1Size=%d %s\n", 
              ARCH, L1SIZE, redir);
      if (system(ln))
      {
         ATL_mprintf(2, fplog, stderr, 
                     "Unable to store L1CacheSize, aborting.\n");
         fclose(fplog);
         exit(-1);
      }
   }
   fprintf(fplog, "\n\nConfiguration completed successfully.\n\n");
   fclose(fplog);
   fprintf(stdout, 
           "\nMoving config logfiles %s and %s to bin/%s/INSTALL_LOG/\n",
           lognam, dmpnam, ARCH);
   sprintf(ln, "mv -f %s bin/%s/INSTALL_LOG/.\n", lognam, ARCH);
   system(ln);
   sprintf(ln, "mv -f %s bin/%s/INSTALL_LOG/.\n", dmpnam, ARCH);
   system(ln);

   fprintf(stdout, "\n\nConfiguration completed successfully.  You may want to examine the make include \n");
   fprintf(stdout, 
"file (Make.%s) for accuracy before starting the install with the command:\n",
           ARCH);
   fprintf(stdout, "   make install arch=%s\n\n", ARCH);
}

main(int nargs, char *args[])
{
   GoToTown();
   exit(0);
}
