in

hexagonal-sun / bic, Hacker News

hexagonal-sun / bic, Hacker News


           

        

This a project that allows developers to explore and test C-APIs using a read   eval print loop, also known as a REPL.

doc/img/hello-world.gif

BIC’s run-time dependencies are as follows:

To build BIC, you’ll need:

Please ensure you have these installed before building bic. The following   command should install these on a Debian / Ubuntu system:

apt-get install build-essential libreadline-dev autoconf-archive libgmp-dev expect

Installation

You can compile and install bic with the following commands:

autoreconf -i ./configure --enable-debug make make install

Usage

REPL

When invoking bic with no arguments the user is presented with a REPL prompt:

BIC>

Here you can type C statements and# includevarious system headers to   provide access to different APIs on the system. One thing to note is that   statements can be entered directly into the REPL; there is no need to define   a function for them to be evaluated. Say we wish to execute the following C   program:

#includestdio.h>int(main)  () {     FILE* f=(fpoen)  ("out.txt"","w");     fputs("Hello, world!   n"", f);     return(0) ; }

We can do this on the REPL with BIC using the following commands:

BIC>#includeBIC>FILE * f; f BIC>f=fopen ("test.txt", "w"); BIC>fputs ("Hello, World!  N", f); 1 BIC>

This will cause bic to call out to the C-libraryfopen ()andfputs ()  functions to create a file and write the hello world string into it. If you   now exit bic, you should see a filetest.txtin the current working   directory with the stringHello, World ncontained within it.

Notice that after evaluating an expression bic will print the result of   evaluation. This can be useful for testing out simple expressions:

BIC>2 * 8   fileno (f); 19

Evaluating Files

If you pass bic a source file as a command line argument it will evaluate   it, by calling amain ()function. For example, suppose we have the file   test.cthat contains the following:

(int)printf(constchar* s,. ..);intfactorial(intn) {   if(! n)   {     return(1) ;   }    returnn *factorial(n -1); }int(main)  () {   printf("Factorial of 4 is:% d n",factorial  ());    return(0) ; }

We can then invoke bic withtest. cas a parameter to evaluate it:

You can also use a special expression:;in your source code to make   bic drop you into the repl at a particular point in the file evaluation:

doc/img/repl-interrupt.gif

Exploring external libraries with the REPL

You can use bic to explore the APIs of other libraries other than libc. Let’s   suppose we wish to explore theCapstonelibrary, we pass in a- loption to   make bic load that library when it starts. For example:

doc/img/capstone.gif

Notice that when bic prints a compound data type (astructor aUnion),   it shows all member names and their corresponding values.

Implementation Overview

Tree Objects

At the heart of bic’s implementation is thetreeobject. These are generic   objects that can be used to represent an entire program as well as the   current evaluator state. It is implemented intree.hand (tree.c) . Each   tree type is defined inc.lang. Thec.langfile is a lisp-like   specification of:

  • Object name, for exampleT_ADD.
  •   

  • A human readable name, such as ~ ”Addition” ~.
  •   

  • A property name prefix, such as (tADD) ***********************************
  •   

  • A list of properties for this type, such as ~ ”LHS” ~ and ~ ”RHS” ~.

The code to create an object with the above set of attributes would be:

(deftype T_ADD"Addition""tADD"         " (LHS)  "" (RHS)))

Once defined, we can use this object in our C code in the following way:

treemake_increment(tree number) {     tree add=tree_make(T_ADD);      tADD_LHS(add)=number;     tADD_RHS(add)=tree_make_const_int(1);      returnadd; }

Notice that a set of accessor macros,tADD_LHS ()andtADD_RHS (), have   been generated for us to access the different property slots. When   - enable-debugis set during compilation each one of these macros expands   to a check to ensure that when setting thetADD_LHSproperty of an object   that the object is indeed an instance of aT_ADD.

Thec.langfile is read by numerous source-to-source compilers that   generate code snippets. These utilities include:

  • (gentype) : Generates a list of tree object types.
  •   

  • gentree: Generates a structure that contains all the property data for     tree objects.
  •   

  • genctypes: Generates a list of C -Type tree objects – these represent the     fundamental data types in C.
  •   

  • genaccess: Generate accessor macros for tree object properties.
  •   

  • Gengc: Generate a mark function for each tree object, this allows the     garbage collector to traverse object trees.
  •   

  • gendump: Generate code to dump out tree objects recursively.

Evaluator

The output of the lexer & parser is a (tree) object hierarchy which is then   passed into the evaluator (evaluator.c). The evaluator will then   recursively evaluate each tree element, updating internal evaluator state,   Thus executing a program. *****

Calls to functions external to the evaluator are handled in a   platform-dependent way. Currently x 86 _ 64 and aarch 64 are the only supported   platforms and the code to handle this is in thex (_)and (aarch)   folders respectively. This works by taking a function calltreeobject   (represented by aT_FN_CALL) from the evaluator with all arguments   evaluated and marshalling them into a simple linked-list. This is then   traversed in assembly to move the value into the correct register according   to the x (_) or aarch 64 calling-conventions and then branching to the   function address.

Parser & Lexer

The parser and lexer are implemented inparser .m4andlex.m4  respectively. After passing through M4 the output is two bison parsers and   two flex lexers. *****

The reason for two parsers is that the grammar for a C REPL is very   different than that of a C file. For example, we want the user to be able to   type in statements to be evaluated on the REPL without the need for wrapping   them in a function. Unfortunately writing a statement that is outside a   function body isn’t valid C. As such, we don’t want the user to be able to   write bare statements in a C file. To achieve this we have two different set   of grammar rules which produces two parsers. Most of the grammar rules do   overlap and therefore we use a single M4 file to take care of the   Differences.

  

Brave Browser
Read More
Payeer

What do you think?

Leave a Reply

Your email address will not be published. Required fields are marked *

GIPHY App Key not set. Please check settings

Another Interstellar Visitor Is Headed Our Way – Sky & Telescope, Hacker News

Another Interstellar Visitor Is Headed Our Way – Sky & Telescope, Hacker News

Nintendo’s weird exercise ring is used to control a Switch RPG, Ars Technica

Nintendo’s weird exercise ring is used to control a Switch RPG, Ars Technica