Package: src/packages/libstruct.fdoc

Library structure

key file
std.flx share/lib/std.flx
key file
linux.flx share/lib/std/linux/linux.flx
linux_smaps.flx share/lib/std/linux/smaps.flx
key file
cstdlib.flx share/lib/std/c/cstdlib.flx
c_hack.flx share/lib/std/c/c_hack.flx
platindep.flxh share/lib/std/plat/platindep.flxh

Library structure

Specifies some of the automatic inclusion files. Others are located in other packages.

Also throw in some “don’t know where to put them” files.

Std.flx

The top level library module.

//[std.flx]
header '#include "flx_rtl_config.hpp"';
include "std/__init__";

Default includes for Standard library.

open String;

// ISO C++99 standard header tags
include "std/c/__init__";

// core type classes
include "std/algebra/__init__";

// base scalar types
include "std/scalar/__init__";

// utility
include "std/debug";

// control
include "std/control/__init__";
include "std/pthread/__init__";
include "std/program/__init__";

//memory management
include "std/gc";

// I/O
include "std/io/__init__";
include "std/time";

// codecs
include "std/codec/__init__";

// base data types
include "std/datatype/__init__";
include "std/strings/__init__";

// regexes
include "std/regex/__init__";

// database REMOVED
//include "std/db/__init__";

// Version
include "std/version";

// Platform support (implementation exposure)
include "std/osx/__init__";
include "std/posix/__init__";
include "std/win32/__init__";

// Felix (implementation exposure)
include "std/felix/__init__";

C stuff

Structure of C sublibrary.

include "std/c/c_headers";
include "std/c/cxx_headers";
include "std/c/cptr";
include "std/c/cstdlib";
include "std/c/carray";
include "std/c/c_hack";
include "std/c/shared_ptr";

Data types

Structure of datatype library.

// special
include "std/datatype/typing";
include "std/datatype/functional";
include "std/datatype/special";
include "std/datatype/unitsum";

// base data types
include "std/datatype/tuple";
include "std/datatype/option";
include "std/datatype/slice";
include "std/datatype/list";
include "std/datatype/assoc_list";
include "std/datatype/stream";
//include "std/datatype/sexpr";
//include "std/datatype/lsexpr";
//include "std/datatype/ralist";

// arrays
include "std/datatype/array_class";
include "std/datatype/array";
include "std/datatype/varray";
include "std/datatype/darray";
//include "std/datatype/sarray";
//include "std/datatype/bsarray";
include "std/datatype/judy";
include "std/datatype/sort";

// dictionaries
include "std/datatype/strdict";

// tree
//include "std/datatype/avl";

Posix

Structure of Posix support library.

struct Posix {};
include "std/posix/posix_headers";
include "std/posix/errno";
include "std/posix/signal";
include "std/posix/time";
include "std/posix/filestat";
include "std/posix/directory";
include "std/posix/filesystem";
include "std/posix/process";
include "std/posix/shell";
include "std/posix/faio_posix";
include "std/posix/mmap";

Win32

Structure of Win32 library.

struct Win32 {};

// windows services
include "std/win32/shell";
include "std/win32/filestat";
include "std/win32/directory";
include "std/win32/process";
include "std/win32/filesystem";
include "std/win32/time";
include "std/win32/signal";
include "std/win32/faio_win32";
include "std/win32/win32_headers";

Platform independent Computation enforcement

Using –import=std/plat/platindep.flxh on flxg command fails to set any of the usual platform macros like FLX_LINUX, FLX_POSIX, FLX_WIN32. Instead it sets the macro PLAT_INDEP. This should bug out any compilations requiring platform specific macros.

// Platform independent compilation enforced by
// failing to set any platform macros.
macro val PLAT_INDEP = 1;

C hackery

Hackery for mapping between Felix and C/C++.

//[c_hack.flx]

//$ This class provides access to raw C/C++ encodings.
//$ Incorrect typing is likely to pass by Felix and
//$ be trapped by the C/C++ compiler. Incorrect management
//$ of storage can lead to corruption. The use of the
//$ C_hack class is necessary for interfacing.
class C_hack
{
  //$ C void type. Incomplete, can't be instantiated.
  incomplete type void_t = "void";

  //$ Standard variable argument list pointer type.
  type va_list = "va_list";

  //$ GCC specific valist thingo: it will
  //$ be optimised away if not used (eg on MSVC).
  type __builtin_va_list = '__builtin_va_list';

  //$ Throw away result of a function call:
  //$ only useful for C functions that are mainly
  //$ called for side effects.
  proc ignore[t]:t = "(void)$t;";

  //$ C style cast.
  fun cast[dst,src]: src->dst = '(?1)($t/*cast*/)' is cast;

  //$ C++ static cast.
  fun static_cast[dst,src]: src->dst = 'static_cast<?1>($t)' is postfix;

  //$ C++ dynamic cast.
  fun dynamic_cast[dst,src]: src->dst = 'dynamic_cast<?1>($t)' is postfix;

  //$ C++ const cast.
  fun const_cast[dst,src]: src->dst = 'const_cast<?1>($t)' is postfix;

  //$ C++ reinterpret cast.
  fun reinterpret_cast[dst,src]: src->dst = 'reinterpret_cast<?1>($t)' is postfix;

  //$ Felix reinterpret cast.
  //$ More powerful than C++ reinterpret cast.
  //$ Allows casting an rvalue to an lvalue.
  fun reinterpret[dst,src]: src->dst = 'reinterpret<?1>($t)' is postfix;

  const sizeof[t]:size = 'sizeof(?1)';

  //$ Special NULL check for Felix pointers.
  //$ Should never succeed.
  fun isNULL[t]: &t -> bool = "(0==$1)";

  //$ Special NULL check for carray.
  //$ Should never succeed.
  fun isNULL[t]: +t -> bool = "(0==$1)";

  //$ Polymorphic null pointer constant
  //$ Values of this type should not exist.
  //$ This value is provided for checking.
  const null[t]:&t = "(?1*)NULL";

  //$ C++ default value for a type T.
  //$ Workaround for g++ 3.2.2 parsing bug,
  //$ it can parse T() as a default ctor call,
  //$ but screws up on (T())
  fun dflt[t]:1->t = "dflt<?1>()" requires header
    "template<class T> T dflt() { return T(); }";

  //$ Invoke C++ destructor
  proc destroy[T] : &T = "::destroy($1);/*C_hack*/"; // from flx_compiler_support_bodies
}

C stdlib Rand

Just to get random functions.

//[cstdlib.flx]

open class Cstdlib
{
  requires Cxx_headers::cstdlib;
  const RAND_MAX:long;

  //$ C89 Standard C library seed random number generator.
  proc srand: uint = '::std::srand($1);';

  //$ C89 Standard C library random number generator.
  //$ Known to be not very good. Try not to use it!
  fun rand: unit -> int = '::std::rand()';
}

OSX platform tag

struct Osx{};
include "std/posix/__init__";

Linux specifics

//[linux.flx]

module Linux {
  header '#include "plat_linux.hpp"';
  requires package "plat_linux";
  fun get_cpu_nr: 1 -> int;
}

Linux smap

Parses and totals proc/PID/smaps memory stats.

//[linux_smaps.flx]

publish """
Parses and totals proc/PID/smaps memory stats.
See smaps_total

** don't do [stack] as is last map in smaps and feof appear to be broken or
** doesnt work with /proc files

Example: (gets total smaps values for heap
 open Smaps;
  val my_smaps = smaps_total(getpid(),"[heap]");
  println("Heap Size=>"+str(my_smaps.size)+" kB");
  //Smaps for other processes
  val m = smaps_total(uint_topid(23264ui),"/usr/lib/libsqlite3.so.0.8.6");
  println("SQLite Size:RSS=>"+str((m.size))+" kB:"+ str((m.rss))+" kB");
"""

class Smaps {
  open Smaps;
  struct smaps_metric {
     size:uint;
     rss:uint;
     pss:uint;
     shared_clean:uint;
     shared_dirty:uint;
     private_clean:uint;
     private_dirty:uint;
     referenced:uint;
     anonymous:uint;
     anonhugepages:uint;
     swap:uint;
     kernelpagesize:uint;
     mmupagesize:uint;
     locked:uint;
  }

  fun getpid: ()->Process::pid_t = "getpid()";

  fun pid_touint: Process::pid_t->uint = "((unsigned int)$1)";

  fun uint_topid: uint->Process::pid_t = "((pid_t)$1)";

  fun min_whitespace(s:string) = {
    var fw = false;
    var m = "";
    for var i in 0ui upto (len s) - 1ui do
      val c = s.[int(i)];
      if  (c == char ' ' and not fw) do
        fw = true; m = m + c;
      elif not c == char ' ' do
        fw = false; m = m + c;
      done
    done
    return m;
  }

publish """
  Returns summation of blocks for each path specified for a given pid.
  Path is one of [heap] | [vdso] | [stack] | path dynamic lib (e.g /lib/libbz2.so.1.0.6)
"""
fun smaps_total(p:Process::pid_t,path:string):smaps_metric ={
  var y = pid_touint p;
  val file = fopen_input ("/proc/"+str(pid_touint p)+"/smaps");
  var at_map = false;
  var end_of_map = false;
  var nums = smaps_metric(0ui,0ui,0ui,0ui,0ui,0ui,0ui,0ui,0ui,0ui,0ui,0ui,0ui,0ui);
  var size = 0ui;
  while not (feof file) and not end_of_map do
    val ln = min_whitespace(strip(readln file));
    val cols = split(ln,' ');
    var spath = let Cons (h,_) = rev cols in h;
    if not at_map  do
      at_map = match find (ln,path) with |Some _ => true |_ => false endmatch;
    elif (at_map  and (len cols) > 5ui) and not spath == path do
      end_of_map=true;
    else
      var kv = let Cons (k,Cons (s,_)) = cols in (k,uint(s));
      match kv with
        |("Size:",e) => nums.size = nums.size + uint(e);
      |("Rss:",e) => nums.rss = nums.rss + uint(e);
      |("Pss:",e) => nums.pss = nums.pss + uint(e);
      |("Shared_Clean:",e) => nums.shared_clean = nums.shared_clean + uint(e);
      |("Shared_Dirty:",e) => nums.shared_dirty = nums.shared_dirty + uint(e);
      |("Private_Clean:",e) => nums.private_clean = nums.private_clean + uint(e);
      |("Private_Dirty:",e) => nums.private_dirty = nums.private_dirty + uint(e);
      |("Referenced:",e) => nums.referenced = nums.referenced + uint(e);
      |("Anonymous:",e) => nums.anonymous = nums.anonymous + uint(e);
      |("AnonHugePages:",e) => nums.anonhugepages = nums.anonhugepages +  uint(e);
      |("Swap:",e) => nums.swap = nums.swap +  uint(e);
      |("KernelPageSize:",e) => nums.kernelpagesize = nums.kernelpagesize + uint(e);
      |("MMUPageSize:",e) => nums.mmupagesize = nums.mmupagesize + uint(e);
      |("Locked:",e) => nums.locked = nums.locked + uint(e);
        |(k,v) => {}();
      endmatch;
    done;
  done;
  fclose file;
  return nums;
  }
}