Calling C from BinProlog: adding new builtins

New builtins are added in header.pl and after a "make realclean; make" a new version of BinProlog containing them is generated automatically.

An example of declaration in headers.pl is:

  b0(+/3,arith(1),in_body). % arity=3+1 by binarization

Notice
that arith(1) means that it is "like an arithmetic functions" which returns one value, i.e this should be used as in

  +(0,1,Result).

I would
suggest to start with the simplest form of interaction: a call of your own C-code from BinProlog. Try modifying the file c.c (provided with the C-sources of BinProlog), function new_builtin() which looks as follows:

/* 
   New builtins can be called from Prolog as:
   new_builtin(0,<INPUT_ARG>,<OUTPUT_ARG>)
   
   X(1) contains the integer `opcode' of your builtin
   X(2) contains your input arg
   regs[I] contains somthing that will be unified with what you return
      (the precise value of I depends on the register allocator).

   You are expected to `return' either 
    - a non-null object that will be unified with <OUTPUT_ARG>, or
    - NULL to signal FAILURE

   As the returned object will be in a register this
   can be used for instance to add a garbage collector
   that moves every data area around...

*/

term new_builtin(H,regs,A,P,wam)
  register term H,regs,*A;
  register instr P;
  register stack wam;
{  BP_check_call(); 
   switch(BP_op)
  { 
    /* for beginners ... */

    case 0: 
       /* this just returns your input argument (default behavior) */
    break;

    case 1: 
      BP_result=BP_integer(13); /* this example returns 13 */
    break;

    case 2: 
      BP_result=BP_atom("hello"); /* this example returns 'hello' */
    break;

    /* for experts ... */

    case 3: /* iterative list construction */
    { cell middle,last,F1,F2; int i;
      BP_make_float(F1, 77.0/2);
      BP_make_float(F2, 3.14);

      BP_begin_put_list(middle);
         BP_put_list(BP_integer(33));
         BP_put_list(F1);
         BP_put_list(BP_string("hello"));
         BP_put_list(F2);
      BP_end_put_list();
 
      BP_begin_put_list(last);
        for(i=0; i<5; i++) {
          BP_put_list(BP_integer(i));
        }
      BP_end_put_list();
      
      BP_begin_put_list(BP_result);
        BP_put_list(BP_string("first"));
        BP_put_list(middle);
        BP_put_list(last);
        BP_put_list(F1);
        BP_put_list(F2);
      BP_end_put_list(); 
    } break;

    case 4: /* cons style list construction */
      BP_begin_cons();
      BP_result=
       BP_cons(
          BP_integer(1),
          BP_cons(
               BP_integer(2),
               BP_nil
          )
       );
      BP_end_cons();
    break;

    case 5: /* for hackers only ... */ ;
      BP_result=(cell)H;

      H[0]=g.DOT;
      H[1]=X(2);

      H[2]=g.DOT;
      H[3]=BP_integer(99);

      H[4]=g.DOT;
      H[5]=(cell)(H+5); /* new var */

      H[6]=g.DOT;
      H[7]=(cell)(H+5); /* same var as previously created */

      H[8]=g.DOT;
      H[9]=BP_atom("that's it");

      H[10]=g.NIL;
      H+=11;
    break;

    case 6:
      BP_fail();
    break;

    case 7: 
      {  cell T=BP_input;
         if(BP_is_integer(T))
            {fprintf(g.tellfile,"integer: %d\n",BP_get_single_integer(T));
             BP_result=BP_integer(-1);
            }
         else
            BP_fail();         
      } 
    break;

    case 8: /* for experts: calling BinProlog from C */
      { cell L,R,Goal;
        
        BP_begin_put_list(L);
          BP_put_list(BP_string("one"));
          BP_put_list(BP_integer(2));
          BP_put_list(BP_string("three"));
          BP_put_list(BP_input); /* whatever comes as input */
        BP_end_put_list();
  
        BP_put_functor(Goal,"append",3);
        BP_put_old_var(L);
        BP_put_old_var(L);
        BP_put_new_var(R);        

        BP_prolog_call(Goal); /* this will return NULL on failure !!!*/

        BP_put_functor(Goal,"write",1);
        BP_put_old_var(R);    

        BP_prolog_call(Goal); /* calls write/1 */

        BP_put_functor(Goal,"nl",0);

        BP_prolog_call(Goal); /* calls nl/0 */

        BP_result=R; /* returns the appended list to Prolog */

      }
      break;


    /* EDIT AND ADD YOUR CODE HERE....*/

    default:
     return LOCAL_ERR(X(1),"call to unknown user_defined C function");
  }
  return H; 
}