text: #include "atlconf.h"
  
  void PrintUsage(char *name, int i)
  {
     fprintf(stderr, "USAGE: %s -v (verb) -b (@ bits) -a (arch) -n (ncpu) -c <ncache> -C <lvl> (cache size) -m (Mhz) -t (cpu throttling)\n", name);
     exit(i);
  }
  
  int GetFlags(int nargs, char **args, int *CacheLevel)
  {
     int i, flag = 0;
  
     *CacheLevel = 0;
     for (i=1; i < nargs; i++)
     {
        if (args[i][0] != '-') PrintUsage(args[0], i);
        switch(args[i][1])
        {
        case 'n':
           flag |= Pncpu;
           break;
        case 'c':
           flag |= Pncache;
           break;
        case 'C':
           if (++i > nargs)
              PrintUsage(args[0], i);
           *CacheLevel = atoi(args[i]);
           break;
        case 'v':
           flag |= Pverb;
           break;
        case 'm':
           flag |= PMhz;
           break;
        case 'a':
           flag |= Parch;
           break;
        case 'b':
           flag |= P64;
           break;
        case 't':
           flag |= Pthrottle;
           break;
        default:
           PrintUsage(args[0], i);
        }
     }
     if (!flag)
       flag = Parch | P64;
     return(flag);
  }
  
  enum MACHTYPE ProbeArch()
  {
     enum ARCHFAM fam;
     enum MACHTYPE mach=MACHOther;
     int ierr, i;
     char *res;
  
     fam = ProbeArchFam(NULL);
     switch(fam)
     {
     case AFPPC:
        res = atlsys_1L(NULL, "cat /proc/cpuinfo | fgrep cpu", 0, 0);
        if (res)
        {
  #if 0
           if (strstr(res, "604e")) mach = PPC604e;
           else if (strstr(res, "604")) mach = PPC604;
           else
  #endif
           if (strstr(res, "G4")) mach = PPCG4;
           else if (strstr(res, "7400")) mach = PPCG4;
           else if (strstr(res, "7410")) mach = PPCG4;
           else if (strstr(res, "7447")) mach = PPCG4;
           else if (strstr(res, "7455")) mach = PPCG4;
           else if (strstr(res, "PPC970FX")) mach = PPCG5;
           else if (strstr(res, "PPC970MP")) mach = PPCG5;
           else if (strstr(res, "POWER8")) mach = IbmPwr8;
           else if (strstr(res, "POWER7")) mach = IbmPwr7;
           else if (strstr(res, "POWER6")) mach = IbmPwr6;
           else if (strstr(res, "POWER5")) mach = IbmPwr5;
           else if (strstr(res, "POWER4")) mach = IbmPwr4;
           else if (strstr(res, "e6500")) mach = Pwre6500;
           free(res);
        }
        break;
     case AFMIPS:
        res = atlsys_1L(NULL, "fgrep 'cpu model' /proc/cpuinfo", 0, 0);
        if (res)
        {
           if (res[0] != '\0')
           {
              if (strstr(res, "ICE9"))
                 mach = MIPSICE9;
  /*
   *          I have no access to what cpuinfo on Linux does for this procs,
   *          so this is a WAG as to what it would say
   */
              else if (strstr(res, "R10000") || strstr(res, "R12000") ||
                       strstr(res, "R12000") || strstr(res, "R14000"))
                 mach = MIPSR1xK;
           }
           free(res);
        }
        break;
     case AFARM:
        res = atlsys_1L(NULL, "fgrep 'Processor' /proc/cpuinfo", 0, 0);
        if (!res)
           res = atlsys_1L(NULL, "fgrep cpu /proc/cpuinfo", 0, 0);
        if (!res)
           res = atlsys_1L(NULL, "uname -a", 0, 0);
        if (res)
        {
           if (strstr(res, "ARMv7") || strstr(res,"v7l"))
           {
              free(res);
              res = atlsys_1L(NULL, "fgrep 'CPU part' /proc/cpuinfo", 0, 0);
              if (res)
              {
                 char *sp;
                 sp = strstr(res, "0x");
                 if (sp)
                 {
                    int i;
                    if (sscanf(sp, "%x", &i) == 1)
                    {
                       i &= 0xFF;
                       switch(i)
                       {
                       case 7:
                          mach = ARM7;
                          break;
                       case 9:
                          mach = ARM9;
                          break;
                       case 15:
                          mach = ARM15;
                          break;
                       case 17:
                          mach = ARM17;
                          break;
                       default:;
                       }
                    }
                 }
              }
           }
           else if (strstr(res, "AArch64") || strstr(res, "aarch64"))
           {
              free(res);
              res = atlsys_1L(NULL, "fgrep 'Hardware' /proc/cpuinfo", 0, 0);
              if (res && strstr(res, "X-Gene "))
                 mach = ARM64xg;
              else
              {
                 if(res)
                    free(res);
                 res = atlsys_1L(NULL, "fgrep 'CPU part' /proc/cpuinfo", 0, 0);
                 if (res)
                 {
                    char *sp;
                    sp = strstr(res, "0x");
                    if (sp)
                    {
                       int i;
                       if (sscanf(sp, "%x", &i) == 1)
                       {
                          i &= 0xFF;
                          switch(i)
                          {
                          case 3:
                             mach = ARM64a53;
                             break;
                          case 7:
                             mach = ARM64a57;
                             break;
                          default:;
                          }
                       }
                    }
                 }
              }
           }
           free(res);
        }
        break;
     case AFIA64:
        res = atlsys_1L(NULL, "fgrep 'Itanium' /proc/cpuinfo", 0, 0);
        if (res && res[0] == '\0')
        {
           free(res);
           res = NULL;
        }
        if (!res)
        {
           res = atlsys_1L(NULL, "fgrep 'IA-64' /proc/cpuinfo", 0, 0);
           if (res && res[0] == '\0')
           {
              free(res);
              res = NULL;
           }
        }
        if (!res)
           res = atlsys_1L(NULL, "fgrep \"model name\" /proc/cpuinfo", 0, 0);
        if (res)
        {
           if (res[0] != '\0')
           {
              if (strstr(res, "Itanium 2") || strstr(res, "McKinley"))
                 mach = IA64Itan2;
              else if (strstr(res, "Itanium")) mach = IA64Itan;
           }
           free(res);
        }
        break;
     case AFX86:
        res = atlsys_1L(NULL, "fgrep 'model name' /proc/cpuinfo", 0, 0);
        if (res && res[0] == '\0')
        {
           free(res);
           res = NULL;
        }
        if (!res)
           res = atlsys_1L(NULL, "fgrep model /proc/cpuinfo", 0, 0);
        if (res && res[0] == '\0')
        {
           free(res);
           res = NULL;
        }
        if (res)
        {
           if (strstr(res, "Pentium"))
           { /* Pentium of some flavor */
              if (strstr(res, " III ")) mach = IntPIII;
              else if (strstr(res, " II ")) mach = IntPII;
              else if (strstr(res, "Pro")) mach = IntPPRO;
              else if (strstr(res, "MMX")) mach = IntP5MMX;
              else if (strstr(res, " 4 "))
              {
                 char *rs2;
                 rs2 = atlsys_1L(NULL,
                        "fgrep 'model' /proc/cpuinfo | fgrep -v 'name'", 0, 0);
                 if (rs2)
                 {
                    i = GetLastInt(res);
                    if (i < 3) mach = IntP4;
                    else if (i == 3) mach = IntP4E;
                    free(rs2);
                 }
              }
           }
           else if (strstr(res, "Atom"))
              mach = IntAtom;
           else if (strstr(res, "Core"))
           {
              if (strstr(res, "i7"))
              {
                 if (strstr(res, "4770") || strstr(res, "4765"))
                    mach = IntCorei3;
                 else if (strstr(res, "2600") || strstr(res, "3770"))
                    mach = IntCorei2;
                 else if (strstr(res, "6700"))
                    mach = IntCorei4;
                 else
                    mach = IntCorei1;
              }
              if (strstr(res, "i5"))
              {
                 if (strstr(res, "4670") || strstr(res, "4570") ||
                     strstr(res, "4430"))
                    mach = IntCorei3;
                 else if (strstr(res, "i5-2500") || strstr(res, "i5-2400") ||
  	           strstr(res, "i5-2390") || strstr(res, "i5-2300"))
                    mach = IntCorei2;
                 else
                    mach = IntCorei1;
              }
           }
           else if (strstr(res, "Xeon")) /* dreaded Xeon-is-anything */
           {
              if (strstr(res, "E5420")) mach = IntCore2;
              else if (strstr(res, "X7560")) mach = IntCorei1;
           }
           else if (strstr(res, "A8-3850"))
              mach = AmdLlano;
           else if (strstr(res, "Efficeon")) mach = TMEff;
           else if (strstr(res, "Athlon HX")) mach = AmdHammer;
           else if (strstr(res, "Opteron") || strstr(res, "Hammer") ||
                    strstr(res, "Athlon(tm) 64"))
              mach = AmdHammer;
           else if (strstr(res, "Athlon")) mach = AmdAthlon;
           else if (strstr(res, "AMD-K7")) mach = AmdAthlon;
           free(res);
        }
        break;
  /*
   *    Add these back if we get machine access and can test
   */
     case AFSPARC:  /* don't know here anymore */
        res = atlsys_1L(NULL, "fgrep cpu /proc/cpuinfo", 0, 0);
        if (res)
        {
           if (strstr(res, "UltraSparc T2")) mach = SunUST2;
           else if (strstr(res, "UltraSparc T1")) mach = SunUST1;
           else if (strstr(res, "UltraSparc IV")) mach = SunUSIV;
           else if (strstr(res, "UltraSparc III")) mach = SunUSIII;
           else if (strstr(res, "UltraSparc II")) mach = SunUSII;
           else if (strstr(res, "UltraSparc I")) mach = SunUSI;
           else if (strstr(res, "UltraSparc")) mach = SunUSX;
           free(res);
        }
        break;
     case AFALPHA:
        #if 0
        res[0] = '\0';
        ierr = CmndOneLine(NULL, "fgrep 'model name' /proc/cpuinfo", res);
        if (ierr || res[0] == '\0')
           ierr = CmndOneLine(NULL, "fgrep model /proc/cpuinfo", res);
        if (!ierr && res[0] != '\0')
        {
           if (strstr(res, "EV5")) mach = Dec21164;
           else if (strstr(res, "EV4")) mach = Dec21064;
           else if (strstr(res, "EV6")) mach = Dec21264;
        }
        #endif
        break;
     case AFS390:
        res = atlsys_1L(NULL, "cat /proc/cpuinfo | fgrep \"processor \"", 0, 0);
        if (res)
        {
           if (strstr(res, "2094") || strstr(res, "2096")) mach = IbmZ9;
           else if (strstr(res, "2097") || strstr(res, "2098")) mach = IbmZ10;
           /* we consider anything else to be a z196 or later */
           else if (strstr(res, "2817") || strstr(res, "2818")) mach = IbmZ196;
           else if (strstr(res, "2827") || strstr(res, "2828")) mach = IbmZ12;
           else if (strstr(res, "2964") || strstr(res, "2965")) mach = IbmZ13;
           else mach = IbmZ13;  /* looks risky to me, but IBM folks did it */
           free(res);
        }
        break;
     default:
  #if 0
        if (!CmndOneLine(NULL, "fgrep 'cpu family' /proc/cpuinfo", res))
           if (strstr(res, "PA-RISC 2.0")) mach = HPPA20;
  #else
       ;
  #endif
     }
     return(mach);
  }
  int ProbeNCPU()
  {
     int ncpu = 0;
     char *res;
  
     #if 0
     if (mach == Dec21264 || mach == Dec21164 || mach == Dec21064)
     {
        if ( !CmndOneLine(NULL, "fgrep 'cpus detected' /proc/cpuinfo", res) )
           ncpu = GetLastInt(res);
     }
     #endif
     if (!ncpu)
     {
        FILE *fpres;
        int len=0;
        fpres = atlsys(NULL, "grep '^processor' /proc/cpuinfo", 0, 0);
        if (fpres)
        {
           for (ncpu=0; res = ATL_fgets(res, &len, fpres); ncpu++);
           fclose(fpres);
        }
     }
     if (!ncpu)
     {
        res = atlsys_1L(NULL, "grep 'ncpus active' /proc/cpuinfo", 0, 0);
        if (res)
        {
           ncpu = GetFirstInt(res);
           free(res);
        }
     }
     return(ncpu);
  }
  
  int ProbePointerBits(int *sure)
  {
     int i;
     char *uname;
     char *cmnd, *res;
  
     *sure = 0;
  /*
   * This probe should be running on backend; if its ptr length is 8, we've
   * definitely got a 64 bit machine
   * NOTE: getting 4 could be a result of compiler flags on a 64-bit arch,
   * so reverse is not dispositive
   */
     if (sizeof(void*) == 8)
     {
        *sure = 1;
        return(64);
     }
  
  /*
   * Note this is a weak probe, archinfo_x86 much better . . .
   */
     uname = FindUname(NULL);
     i = strlen(uname) + 4;
     cmnd = malloc(sizeof(char)*i);
     assert(cmnd);
     sprintf(cmnd, "%s -a", uname);
  
     res = atlsys_1L(NULL, cmnd, 0, 0);
     free(cmnd);
     if (res)
     {
  /*
   *    If uname is a known 64-bit platform, we're sure we've got OS support
   *    for 64bits (may not have compiler support, but that's not our fault)
   */
        if (strstr(res, "x86_64") || strstr(res, "ppc64") || strstr(res, "ia64"))
        {
           *sure = 1;
           free(res);
           return(64);
        }
        free(res);
     }
     return(32);
  }
  
  int ProbeMhz()
  {
     int mhz=0;
     char *res;
     res = atlsys_1L(NULL, "fgrep 'cpu MHz' /proc/cpuinfo", 0, 0);
     if (res)
     {
        mhz = GetFirstDouble(res) + 0.5;
        free(res);
     }
     if (!mhz)
     {
        res = atlsys_1L(NULL, "cat /proc/cpuinfo | fgrep clock | fgrep MHz",0,0);
        if (res)
        {
           mhz = GetLastLongWithRound(res);
           free(res);
        }
     }
  /*
   * Try Linux/SPARC lookup
   */
     if (!mhz)
     {
        res = atlsys_1L(NULL, "fgrep 'ClkTck' /proc/cpuinfo", 0, 0);
        if (res)
        {
           mhz = GetLastHex(res) / 1000000;
           free(res);
        }
     }
     if (!mhz)
     {
        res = atlsys_1L(NULL, "cpufreq-info -f -m", 0, 0);
        if (res)
        {
           char *sp;
           sp = strstr(res, "Hz");
           if (sp)
           {
             double dmhz;
              dmhz = GetFirstDouble(res);
              if (dmhz != 0.0)
              {
                 switch(sp[-1])
                 {
                 case 'G':
                    mhz = dmhz / 1000;
                    break;
                 case ' ':
                    mhz = dmhz / 1000000;
                    break;
                 case 'K':
                    mhz = dmhz / 1000;
                    break;
                 case 'M':
                 default:
                    mhz = dmhz;
                    break;
                 }
              }
           }
           free(res);
        }
     }
     if (!mhz)
     {
        res = atlsys_1L(NULL, "cpufreq-info -f", 0, 0);
        if (res)
        {
           mhz = GetLastInt(res);  /* assumes clock speed given in KHz */
           free(res);
           if (mhz)
              mhz = mhz / 1000;
        }
     }
  /*
   * RCW: Patch supplied by IBM.  I have no idea why it is written this way.
   * S390 CPU speed is in bogomips rather than mhz
   */
     if (!mhz)
     {
        res = atlsys_1L(NULL, "cat /proc/cpuinfo | fgrep bogomips",0,0);
        if (res)
        {
           double result = GetFirstDouble(res);
           result = (result*100.0)/88.0;  /* RCW: WTF? */
           /*if (result > 5000) result = 5000;*/
           mhz = result;
           free(res);
        }
     }
     return(mhz);
  }
  
  int ProbeThrottle()
  /*
   * RETURNS: 1 if cpu throttling is detected, 0 otherwise
   */
  {
     int iret=0;
     int imax=0, imin=0, icur=0;
     char *res;
  
  /*
   * If cpufreq directory doesn't exist, guess no throttling.  If
   * cpufreq exists, and cur Mhz < max, throttling is enabled,
   * throttling also enabled if governer is not "performance", and min freq
   * is less than max
   */
     res = atlsys_1L(NULL,
                     "cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq",
                     0, 0);
     if (res)
     {
        imax = GetFirstInt(res);
        free(res);
        res = atlsys_1L(NULL,
              "cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq", 0, 0);
        assert(res);
        imin = GetFirstInt(res);
        free(res);
        res = atlsys_1L(NULL,
              "cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq", 0, 0);
        assert(res);
        icur = GetFirstInt(res);
        free(res);
        res = atlsys_1L(NULL,
              "cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", 0, 0);
        assert(res);
        if (icur < imax)
           iret = 1;
        else if (!strstr(res, "performance") && imin < imax)
           iret = 1;
        free(res);
     }
     return(iret);
  }
  
  main(int nargs, char **args)
  {
     int flags, CacheLevel, ncpu, mhz, bits, sure;
     enum MACHTYPE arch=MACHOther;
  
     flags = GetFlags(nargs, args, &CacheLevel);
     if (flags & Parch)
     {
        arch = ProbeArch();
        if (flags & Pverb)
           printf("Architecture detected as %s.\n", machnam[arch]);
        printf("MACHTYPE=%d\n", arch);
     }
     if (flags & Pncpu)
        printf("NCPU=%d\n", ProbeNCPU());
     if (flags & PMhz)
        printf("CPU MHZ=%d\n", ProbeMhz());
     if (flags & Pthrottle)
        printf("CPU THROTTLE=%d\n", ProbeThrottle());
     if (flags & P64)
     {
        bits = ProbePointerBits(&sure);
        printf("PTR BITS=%d, SURE=%d\n", bits, sure);
     }
  
  /*
   * Here for future, presently unsupported
   */
     if (flags & Pncache)
        printf("NCACHES=0\n");
     if (flags & PCacheSize)
        printf("%d Cache size (kb) = 0\n", CacheLevel);
     exit(0);
  }
  