Commits

Zachary Anderson  committed cdebbac

Misc updates, and added tut14 on dsls

  • Participants
  • Parent commits c742ad9

Comments (0)

Files changed (20)

 # Add additional modules here. Order matters. If module x depends on module y,
 # then x has to come after y in the list.
 MODULES = tututil ciltutoptions \
-          tut0 tut1 tut2 tut3 tut4 tut5 tut6 tut7 tut8 tut9 tut10 tut11 tut12 tut13 main
+          tut0 tut1 tut2 tut3 tut4 tut5 tut6 tut7 tut8 tut9 tut10 tut11 tut12 tut13 tut14 main
 
 OCAMLFIND = @OCAMLFIND@
 CILINC = $(shell $(OCAMLFIND) query cil)

File ciltut-include/ciltut.h

 #ifndef _CILTUT_H_
 #define _CILTUT_H_
 
+#include <stdio.h>
 #include <stdint.h>
 #include <unistd.h>
 
 uint64_t perf_get_cache_miss();
 uint64_t tut_get_time();
 
+#include <getopt.h>
+size_t s;
+struct option o;
+
+#pragma cilnoremove("getoptdummy")
+static int getoptdummy()
+{
+  int i;
+  optarg = NULL;
+  sscanf(NULL,"%d",&i);
+  return getopt_long(0, NULL, NULL, NULL, NULL);
+}
+
+#define ARG_HAS_OPT 1
+
 #define argument(argtype, argname, ...) \
+argtype argname; \
+int argname##got; \
 struct ciltut_##argname { \
-  char *small; \
-  char *help; \
-  argtype def; \
-  void *req; \
-} __attribute__((ciltutarg, __VA_ARGS__)) argname =
+  char    *short_form; \
+  char    *help_text; \
+  char    *format; \
+  argtype  def; \
+  void    *requires; \
+  int      has_opt; \
+} __attribute__((ciltutarg, ##__VA_ARGS__)) _ciltut_##argname =
 
-#define arg_assert(e) (void *__attribute__((ciltut_assert((e)))))NULL
+#define arg_assert(e) (void *__attribute__((ciltut_assert((e)))))0
 
 #endif 
 

File src/ciltutoptions.ml

 let home : string ref = ref ""
 let merge : bool ref = ref false
 
-let num_tuts = 14
+let num_tuts = 15
 let enable_tut : bool ref array = Array.init num_tuts (fun i -> ref false)
 
 let prover : string ref = ref "alt-ergo"
   if !(O.enable_tut.(11)) then Tut11.tut11 cil;
   if !(O.enable_tut.(12)) then Tut12.tut12 cil;
   if !(O.enable_tut.(13)) then Tut13.tut13 cil;
+  if !(O.enable_tut.(14)) then Tut14.tut14 cil;
   outputFile cil
 ;;
 
-
-
 
 
 
-
-
-
 
 
 

File src/tut10.ml

-
-
-
-
 
 
 
 module L = List
 
 
-
 let cacheReportStr = "cache_report"
 
 let hasCacheReportAttrs : attributes -> bool = hasAttribute cacheReportStr

File src/tut11.ml

 
 
 
-
-
-
 open Cil
 open Tututil
 
 
 
 
-
 type ops = {
   iplus_op  : T.lsymbol; 
   iminus_op : T.lsymbol; 
 }
 
 
-
 type wctxt = {
 
   mutable env    : E.env;
 }
 
 
-
 let initOps (it : Th.theory) (dt : Th.theory) (mt : Th.theory) : ops =
   {iplus_op    = Th.ns_find_ls it.Th.th_export ["infix +"];
    iminus_op   = Th.ns_find_ls it.Th.th_export ["infix -"];
   }
 
 
-
 let initWhyCtxt (p : string) : wctxt = 
 
   let config  = Wc.read_config None in
 
 
 
-
 let invariantAttrStr = "invariant"
 let postAttrStr      = "post"
 let preAttrStr       = "pre"
 let tut11_attrs = [invariantAttrStr; postAttrStr; preAttrStr;]
 
 
-
 let term_of_int (i : int) : T.term   = i |> string_of_int   |> T.t_int_const
 let term_of_i64 (i : int64) : T.term = i |> Int64.to_string |> T.t_int_const
 
 
-
 let make_symbol (s : string) : T.vsymbol =
   T.create_vsymbol (W.Ident.id_fresh s) W.Ty.ty_int
 
   | _ -> Em.s(Em.error "Names only")
 
 
-
 let rec term_of_attrparam (wc : wctxt) (ap : attrparam) : T.term =
   match ap with
   | AInt i                 -> term_of_int i
   | _ -> Em.s(Em.error "Attrparam is not a term: %a" d_attrparam ap)
 
 
-
 and term_of_forall (wc : wctxt) (apl : attrparam list) : T.term =
   let fat  = apl |> L.rev |> L.hd in
   let vl   = apl |> L.rev |> L.tl |> L.map freshvar_of_ap in
   T.t_forall_close (L.map snd vl) [] t
 
 
-
 and term_of_implies (wc : wctxt) (a : attrparam) (c : attrparam) : T.term =
   let at = term_of_attrparam wc a in
   let ct = term_of_attrparam wc c in
   T.t_implies at ct
 
 
-
 and term_of_apuop (wc : wctxt) (u : unop) (ap : attrparam) : T.term =
   let te = term_of_attrparam wc ap in
   match u with
               d_attrparam ap1 d_binop b d_attrparam ap2)
 
 
-
 and term_of_star (wc : wctxt) (a : attrparam) : T.term =
   let at = term_of_attrparam wc a in
   let mt = T.t_var wc.memory in
   T.t_app_infer wc.ops.get_op [mt;at]
 
 
-
 and term_of_index (wc : wctxt) (base : attrparam) (index : attrparam) : T.term =
   let bt = term_of_attrparam wc base in
   let it = term_of_attrparam wc index in
   T.t_app_infer wc.ops.get_op [mt; addr]
 
 
-
 let oldvar_of_ap (wc : wctxt) (ap : attrparam) : T.vsymbol =
   match ap with
   | ACons(n, []) -> SM.find n wc.vars
   | _ -> Em.s(Em.error "Names only")
 
 
-
 let inv_of_attrs (wc : wctxt) (a : attributes)
                  : T.term * T.term * T.vsymbol list
   =
   | _ -> Em.s(Em.error "Malformed invariant attribute: %a" d_attrlist a)
 
 
-
 let cond_of_function (k : string) (wc : wctxt) (fd : fundec) : T.term option =
   match filterAttributes k (typeAttrs fd.svar.vtype) with
   | [Attr(_,[ap])] -> Some(term_of_attrparam wc ap)
 let pre_of_function  = cond_of_function preAttrStr
 
 
-
 let iterm_of_bterm (t : T.term) : T.term = T.t_if t (term_of_int 1) (term_of_int 0)
 let bterm_of_iterm (t : T.term) : T.term = T.t_neq t (term_of_int 0)
 
 
 
 
-
 let term_of_inst (wc : wctxt) (i : instr) : T.term -> T.term =
   match i with
   | Set((Var vi, NoOffset), e, loc) ->
   | _ -> Em.s (Em.error "term_of_inst: We can only handle assignment")
 
 
-
 let rec term_of_stmt (wc : wctxt) (s : stmt) : T.term -> T.term =
   match s.skind with
   | Instr il          -> L.fold_right (fun i t -> (term_of_inst wc i) t) il
   | _ -> Em.s(Em.error "No support for try-finally, or try-except")
 
 
-
 and term_of_if (wc : wctxt) (e : exp) (tb : block) (fb : block) : T.term -> T.term =
   let te  = e |> term_of_exp wc |> bterm_of_iterm in
   let tbf = term_of_block wc tb in
   (fun t -> T.t_if te (tbf t) (fbf t))
 
 
-
 and term_of_loop (wc : wctxt) (b : block) : T.term -> T.term =
   let test, body = L.hd b.bstmts, L.tl b.bstmts in
   let body_block = body |> L.hd |> force_block in
     |> T.t_and li)              
 
 
-
-
-
 and term_of_block (wc : wctxt) (b : block) : T.term -> T.term =
   L.fold_right (term_of_stmt wc) b.bstmts
 
   (fun t -> T.t_forall_close (vsymbols_of_function wc fd) [] (pre_impl_t wc fd pre t))
 
 
-
 let validateWhyCtxt (w : wctxt) (p : T.term) : unit = 
 
   Format.printf "@[validate:@ %a@]@." W.Pretty.print_term p;
 
 
 
-
 let processFunction (wc : wctxt) (fd : fundec) (loc : location) : unit =
   wc.vars <-
     L.fold_left (fun m vi -> SM.add vi.vname (make_symbol vi.vname) m)
 
 
 
-
 let tut11 (f : file) : unit =
   let wc = initWhyCtxt (!Ciltutoptions.prover) in
   iterGlobals f (onlyFunctions (processFunction wc));

File src/tut14.ml

+
+
+
+
+
+open Cil
+open Pretty
+open Tututil
+
+module E = Errormsg
+module L = List
+module A = Array
+module S = String
+
+
+
+type argument = {
+  mutable argName   : string;  
+  mutable argType   : typ;     
+  mutable argShort  : string;  
+  mutable argHelp   : string;  
+  mutable argFmt    : string;  
+  mutable argDef    : exp;     
+  mutable argReq    : exp;     
+  mutable argOpt    : bool;     
+  mutable argVi     : varinfo; 
+  mutable argGot    : varinfo; 
+  mutable argOption : bool;    
+}
+
+
+let dummyVar = makeVarinfo false "_tut_foo" voidType
+
+
+
+let makeArgument () =  
+
+  {argName   = "";
+   argType   = intType;
+   argShort  = "";
+   argHelp   = "";
+   argFmt    = "%d";
+   argDef    = zero;
+   argReq    = one;
+   argOpt    = true;
+   argVi     = dummyVar;
+   argGot    = dummyVar;
+   argOption = false;}
+
+
+
+
+
+let argStr       = "ciltutarg"
+let assertStr    = "ciltut_assert"
+let mandatoryStr = "mandatory"
+let attr_strings = [argStr; assertStr; mandatoryStr;]
+
+let hasArgAttr       : attributes -> bool = hasAttribute argStr
+let hasAssertAttr    : attributes -> bool = hasAttribute assertStr
+let hasMandatoryAttr : attributes -> bool = hasAttribute mandatoryStr
+
+let isArgType       (t : typ) : bool = t |> typeAttrs |> hasArgAttr
+let isMandatoryType (t : typ) : bool = t |> typeAttrs |> hasMandatoryAttr
+let getAssertAttr (t : typ) : attrparam =
+  match filterAttributes assertStr (typeAttrs t) with
+  | [Attr(_, [ap])] -> ap
+  | _ -> E.s (E.error "Malformed %s attribute: %a" assertStr d_type t)
+
+
+let rec string_of_exp (e : exp) : string =
+  match e with
+  | Const(CStr s) -> s
+  | z when z = zero -> ""
+  | CastE(_,e) -> string_of_exp e
+  | _ -> E.s (E.error "Expected string literal: %a" d_exp e)
+
+
+let name_of_argname (s : string) : string =
+  if S.length s < 8 then
+    E.s (E.error "Invalid argument name: %s" s);
+  S.sub s 8 (S.length s - 8)
+
+
+module T = Tut8
+
+let req_of_exp (c : T.ctxt) (loc : location) (e : exp) : exp =
+  match e with
+  | CastE(t, z) when z = zero ->
+    t |> getAssertAttr |> T.exp_of_ap c loc
+  | _ -> one
+
+
+let handle_field (c : T.ctxt) (loc : location) (a : argument)
+                 (off : offset) (ini : init) (t : typ) ()
+                 : unit
+  =
+  match off, ini with
+  | Field(f, NoOffset), SingleInit e -> begin
+    match f.fname with
+    | "short_form" -> a.argShort  <- string_of_exp e
+    | "help_text"  -> a.argHelp   <- string_of_exp e
+    | "def"        -> a.argDef    <- e;
+                      a.argType   <- f.ftype;
+                      a.argVi     <- makeGlobalVar a.argName a.argType
+    | "requires"   -> a.argReq    <- req_of_exp c loc e
+    | "format"     -> a.argFmt    <- string_of_exp e
+    | "has_opt"    -> a.argOption <- e = one
+    | _       -> E.s(E.bug "malformed arg struct")
+  end
+  | _ -> E.s(E.bug "Unexpected initializer in argument_of_global")
+
+
+let argument_of_global (c : T.ctxt) (g : global) : argument list =
+  match g with
+  | GVar(vi, {init = Some(CompoundInit(t,ini))}, loc)
+    when isArgType vi.vtype -> begin
+    let a = makeArgument () in
+    a.argName <- name_of_argname vi.vname;
+    a.argGot  <- makeGlobalVar (a.argName^"got") intType;
+    a.argOpt  <- not(isMandatoryType vi.vtype);
+    iterCompound ~implicit:false ~doinit:(handle_field c loc a)
+                 ~ct:vi.vtype    ~initl:ini;
+    [a]
+  end
+  | _ -> []
+
+
+let gatherArguments (f : file) : argument list =
+  let c = T.context_for_globals f in
+  f.globals
+  |> L.map (argument_of_global c)
+  |> L.concat
+
+
+let field_of_option (o : varinfo) (ot : typ) (i : int) (n : string) : lval =
+  (Var o),
+  Index(integer i, Field(fieldinfo_of_name ot n, NoOffset))
+
+
+let has_arg_of_argument (a : argument) : exp = 
+  if a.argOption then one else zero
+let int_code_of_argument (a : argument) : exp =
+  a.argShort.[0] |> int_of_char |> integer
+
+
+let initialize_options (foo : int -> string -> lval)
+                       (i : int) (a : argument)
+                       : instr list
+  =
+  [Set(foo i "name",    mkString a.argName,     locUnknown);
+   Set(foo i "has_arg", has_arg_of_argument a,  locUnknown);
+   Set(foo i "val",     int_code_of_argument a, locUnknown)]
+
+
+let create_long_options (f : file) (main : fundec) (al : argument list)
+                        : varinfo * instr * instr list
+  =
+  let malloc = findOrCreateFunc f "malloc" (mallocType f) in
+  let ot     = findType f.globals "option" in
+  let o      = makeTempVar main (TPtr(ot, [])) in
+  let foo    = field_of_option o ot in
+  let size   = integer((L.length al + 1) * ((bitsSizeOf ot)/8)) in
+  let mcall  = Call(Some(var o), v2e malloc, [size], locUnknown) in
+  let inits =
+    al
+    |> A.of_list
+    |> A.mapi (initialize_options foo)
+    |> A.to_list
+    |> L.concat
+  in
+  o, mcall, inits
+
+
+let create_short_options (al : argument list) : exp =
+  let short_arg_of_arg (a : argument) : string =
+    a.argShort^(if a.argOption then ":" else "")
+  in
+  al
+  |> L.map short_arg_of_arg
+  |> S.concat ""
+  |> mkString
+
+
+let getMainArgs (main : fundec) : varinfo * varinfo =
+  match main.sformals with
+  | argc :: argv :: _ -> argc, argv
+  | _ -> E.s (E.error "Must give main argc and argv")
+
+
+let string_of_short_arg (a : argument) : string =
+  a.argShort.[0] |> int_of_char |> string_of_int
+let string_of_arg_opt (a : argument) : string =
+  if a.argOption then "1" else "0"
+
+
+let create_def_int_string (a : argument) : string =
+  if isIntegralType a.argType && not(a.argOption)
+  then "else {%l:"^a.argVi.vname^"l = 1;}"
+  else ""
+
+
+let create_if_str (a : argument) : string =
+  "if (c == "^(string_of_short_arg a)^") {"^
+     "if ("^(string_of_arg_opt a)^") { if(%e:optarg) {"^
+       "%l:scan(%e:optarg,%e:"^a.argVi.vname^"fmt,%e:"^a.argVi.vname^"addr);"^
+     "}}"^
+    (create_def_int_string a)^
+   "%l:"^a.argGot.vname^" = 1;"^
+   "}"
+
+
+let create_opt_loop_str (al : argument list) : string =
+  "while(1) {"^
+     "int c;"^
+     "c = %l:gol(%e:argc, %e:argv, %e:sstr, %e:lopts, (void * )0);"^
+     "if (c == -1) break;"^
+     (al |> L.map create_if_str |> S.concat " else ")^
+   "}"
+
+
+let makeArgStmts (f : file) (main : fundec) (al : argument list) : stmt list =
+  let gol        = findOrCreateFunc f "getopt_long" intType in
+  let scan       = findOrCreateFunc f "sscanf" intType in
+  let optarg     = findGlobalVar f.globals "optarg" in
+  let so         = create_short_options al in
+  let o, m, i    = create_long_options f main al in
+  let argc, argv = getMainArgs main in
+  (L.map i2s (m :: i)) @
+  Formatcil.cStmts (create_opt_loop_str al)
+   (fun n t -> makeTempVar main ~name:n t) locUnknown
+   ([("argc",  Fe(v2e argc));
+     ("argv",  Fe(v2e argv));
+     ("sstr",  Fe so);
+     ("lopts", Fe (v2e o));
+     ("gol",   Fl(var gol));
+     ("scan",  Fl(var scan));
+     ("optarg",Fe(v2e optarg))]@
+     (L.map (fun a -> (a.argVi.vname^"fmt"), Fe (mkString a.argFmt)) al)@
+     (L.map (fun a -> (a.argVi.vname^"addr"),Fe (AddrOf(var a.argVi))) al)@
+     (L.map (fun a -> (a.argVi.vname^"l"),   Fl(var a.argVi)) al)@
+     (L.map (fun a -> (a.argGot.vname),      Fl(var a.argGot)) al))
+
+
+let initArgs (al : argument list) : stmt list =
+  L.map (fun a -> i2s(Set(var a.argVi, a.argDef, locUnknown))) al
+
+
+let printHelp (f : file) (al : argument list) : stmt list =
+  let print = findOrCreateFunc f "printf" intType in
+  let s s   = mkString s in
+  [i2s(Call(None,v2e print,[s "Improper arguemnts\n"],locUnknown))]@
+  (L.map (fun a ->
+    let af = if a.argFmt <> "" then a.argFmt else "%d" in
+    let fmt = if a.argOpt
+      then s ("\t-%s,--%s\t%s ("^af^")\n")
+      else s "\t-%s,--%s\t%s (mandatory)\n"
+    in
+    let args = if a.argOpt
+      then [fmt;s a.argShort;s a.argName;s a.argHelp;a.argDef]
+      else [fmt;s a.argShort;s a.argName;s a.argHelp]
+    in
+    i2s (Call(None,v2e print,args,locUnknown))
+  ) al) @
+  [mkStmt (Return(Some mone, locUnknown))]
+
+
+let makeArgChecks (f : file) (al : argument list) : stmt =
+  let got_arg a = if a.argOpt then one else v2e a.argGot in
+  let bexp, mexp =
+    L.fold_left (fun b a -> BinOp(LAnd, b, a.argReq, intType)) one al,
+    L.fold_left (fun b a -> BinOp(LAnd, b, (got_arg a), intType)) one al
+  in
+  mkStmt (If(BinOp(LOr,UnOp(LNot,mexp,intType),UnOp(LNot,bexp,intType),intType),
+             mkBlock (printHelp f al), mkBlock[],
+             locUnknown))
+
+
+let processFunction (f : file) (al : argument list)
+                    (fd : fundec) (loc : location) : unit =
+  if fd.svar.vname = "main" then
+    fd.sbody.bstmts <- (initArgs al)          @
+                       (makeArgStmts f fd al) @
+                       [makeArgChecks f al]   @
+                       fd.sbody.bstmts
+
+
+class attrEraserVisitor = object(self)
+  inherit nopCilVisitor
+
+  method vattr (a : attribute) =
+    match a with
+    | Attr(s,_) when L.mem s attr_strings -> ChangeTo []
+    | _ -> DoChildren
+
+end
+
+let eraseAttrs (f : file) : unit =
+  let vis = new attrEraserVisitor in
+  visitCilFile vis f
+
+
+
+let tut14 (f : file) : unit =
+  f
+  |> gatherArguments
+  |> processFunction f
+  |> onlyFunctions
+  |> iterGlobals f;
+  eraseAttrs f
+
+
-
-
-
 
 
 
-
-
-
 
 
 
 type varmap = int * (varinfo * oekind)
 
 
-
-
 let id_of_vm   (vm : varmap) : int     = fst vm
 let vi_of_vm   (vm : varmap) : varinfo = vm |> snd |> fst
 let kind_of_vm (vm : varmap) : oekind  = vm |> snd |> snd
 let rec oekind_of_exp (vml : varmap list) (e : exp) : oekind =
   match e with
   | Const(CInt64(i, _, _)) -> kind_of_int64 i
-  | Const _ -> Top
   | Lval(Var vi, NoOffset) -> vml |> L.assoc vi.vid |> snd
-  | Lval _ -> Top
   | SizeOf _ | SizeOfE _ | SizeOfStr _ | AlignOf _ | AlignOfE _ ->
     e |> constFold true |> oekind_of_exp vml
   | UnOp(uo, e, t) -> oekind_of_unop vml uo e
   | BinOp(bo, e1, e2, t) -> oekind_of_binop vml bo e1 e2
   | CastE(t, e) -> oekind_of_exp vml e
-  | AddrOf _ -> Top
-  | StartOf _ -> Top
+  | _ -> Top
 
 and oekind_of_unop (vml : varmap list) (u : unop) (e : exp) : oekind =
   match u with
   | LNot -> Top
 
 
-
 and oekind_of_binop (vml : varmap list) (b : binop) (e1 : exp) (e2 : exp) : oekind =
   let k1, k2 = oekind_of_exp vml e1, oekind_of_exp vml e2 in
   match b with
-
-
 
 
 
 module L = List
 
 
-
-
 type functions = {
   mutable begin_loop : varinfo;
   mutable end_loop   : varinfo;
 
 
 
-
-
 let makeInstrStmts (counter : varinfo) (loc : location)
                    : stmt * stmt * stmt * stmt =
   let f, l = mkString loc.file, integer loc.line in
 end
 
 
-
-
-
 let processFunction (fd : fundec) (loc : location) : unit =
   let vis = new loopInstrumenterClass fd in
   ignore(visitCilFunction vis fd)
-
-
-
 
 
 
   else []
 
 
-
-
 and zeroField (fd : fundec) (blv : lval) (fi : fieldinfo) : stmt list =
   zeroType fd (addOffsetLval (Field(fi,NoOffset)) blv)
 
-
-
-
 
 
 
 
 
 
-
-
-
-
 
 
 
 type colors = T.color list 
 
 
-
-
-
 let nodeStr = "Node"
 let nodeAttr (id : int) : attributes = [Attr(nodeStr,[AInt id])]
 
 
 
 
-
-
 type node = {
   mutable ncolors   : colors;
   mutable incoming  : int list;
 let graphCreate (n : int) : graph = A.init n newNode
 
 
-
-
 let graphAddEdge (g : graph) (from_node : int) (to_node : int) : unit =
   if not(L.mem to_node g.(from_node).outgoing) then
     g.(from_node).outgoing <- to_node :: g.(from_node).outgoing;
   graphAddEdge g from_id to_id
 
 
-
-
 let addEdgesForCallArgs (g : graph) (fe : exp) (aes  : exp list) : unit =
   let fts = fe |> function_elements |> snd |> L.map snd3 in
   let ats = aes |> list_take (L.length fts) |> L.map typeOf in
   g
 
 
-
-
 class nodeColorFinder (g : graph) = object(self)
   inherit nopCilVisitor
 

File src/tututil.ml

 
 let comment_compare (c1 : comment) (c2 : comment) : int =
   cabsloc_compare (fst3 c1) (fst3 c2)
+
+let rec findType (gl : global list) (typname : string) : typ =
+  match gl with
+  | [] -> E.s (E.error "Type not found: %s" typname)
+  | GType(ti,_) :: _        when ti.tname = typname -> TNamed(ti,[])
+  | GCompTag(ci,_) :: _     when ci.cname = typname -> TComp(ci,[])
+  | GCompTagDecl(ci,_) :: _ when ci.cname = typname -> TComp(ci,[])
+  | GEnumTag(ei,_) :: _     when ei.ename = typname -> TEnum(ei,[])
+  | GEnumTagDecl(ei,_) :: _ when ei.ename = typname -> TEnum(ei,[])
+  | _ :: rst -> findType rst typname
+
+let rec findGlobalVar (gl : global list) (varname : string) : varinfo =
+  match gl with
+  | [] -> E.s (E.error "Global not found: %s" varname)
+  | GVarDecl(vi, _) :: _ when vi.vname = varname -> vi
+  | GVar(vi, _, _) :: _ when vi.vname = varname -> vi
+  | _ :: rst -> findGlobalVar rst varname
+
+let mallocType (f : file) : typ =
+  let size_t = findType f.globals "size_t" in
+  TFun(voidPtrType, Some ["s",size_t,[]], false, [])
+
+let iterCompound ~(implicit : bool)
+                 ~(doinit : offset -> init -> typ -> unit -> unit)
+                 ~(ct : typ) ~(initl : (offset * init) list)
+                 : unit
+  =
+  foldLeftCompound ~implicit ~doinit ~ct ~initl ~acc:()

File test/tut10.c

 
 struct array {
   uint64_t *ptr;
-	int size;
+  int size;
 };
 
 void *thrfunc(void *a)
   int size = arr->size;
   int i,j;
 
-  printf("thread: ptr = %p, size = %d\n", ptr, size);
-  fflush(stdout);
-
   cache_report {
     for (j = 0; j < TIMES; j++) {
       ptr[0] = 0x50505050;

File test/tut14.c

+
+
+
+
+
+
+
+#include <unistd.h>
+#include <getopt.h>
+
+#include <ciltut.h> 
+
+
+
+
+
+
+
+argument(int, boolarg) {
+  .short_form = "b",
+  .help_text  = "A boolean argument",
+};
+
+
+
+
+
+
+
+
+
+
+
+argument(int, intarg, mandatory) {
+  .short_form = "i",
+  .help_text  = "An integer argument (>0)",
+  .format     = "%d",
+  .requires   = arg_assert(intarg > 0),
+  .has_opt    = ARG_HAS_OPT,
+};
+
+int main(int argc, char *argv[])
+{
+  printf("%d %d\n", boolarg, intarg);
+  return 0;
+}
+

File test/tut9b.c

+#include <ciltut.h>
+
+int red x;
+int blue y;
+int foo(int x) {
+  return x;
+}
+int main() {
+  int z;
+  z = foo(x);
+  z = foo(y);
+  return x;
+}