bic : AC Interpreter dan API ExplorerIni sebuah proyek yang memungkinkan pengembang untuk mengeksplorasi dan menguji C-APIS menggunakan loop cetak eval baca, juga dikenal sebagai repl.

Ketergantungan run-time BIC adalah sebagai berikut:
Untuk membangun BIC, Anda akan membutuhkan:
Harap pastikan Anda menginstal ini sebelum membangun BIC. Perintah berikut harus menginstal ini pada sistem Debian/Ubuntu:
install apt-get build-esensial libreadline-dev autoconf-archive libgmp-dev mengharapkan flex bison automake m4 libtool pkg-config
Anda juga dapat menggunakan perintah berikut untuk menginstal dependensi yang diperlukan melalui homebrew pada sistem macOS.
buatan menginstal bison flex gmp readline autoconf-archive
Anda dapat mengkompilasi dan menginstal BIC dengan perintah berikut:
autoreconf -i ./configure --enable-debug membuat buat instal
Untuk membangun sistem macOS, Anda perlu mengubah baris konfigurasi menjadi:
Yacc = "$ (brew --prefix bison)/bin/bison -y" ./configure --enable-debug
Anda dapat menggunakan Docker untuk membangun dan menjalankan BIC dengan perintah berikut:
Docker build -t bic https://github.com/hexagonal-sun/bic.git#master
Setelah gambar dibangun, Anda kemudian dapat menjalankan BIC dengan:
Docker run -i bic
Jika Anda menggunakan Arch Linux, Anda dapat menginstal BIC dari AUR:
yay -s bic
Saat memohon BIC tanpa argumen, pengguna disajikan dengan prompt rept:
BIC>
Di sini Anda dapat mengetikkan pernyataan C dan #include berbagai header sistem untuk menyediakan akses ke API yang berbeda pada sistem. Pernyataan dapat dimasukkan langsung ke repl; Tidak perlu mendefinisikan fungsi agar mereka dievaluasi. Katakanlah kami ingin menjalankan program C berikut:
#include <stdio.h>
int main ()
{
FILE * f = fopen ( "out.txt" , "w" );
fputs ( "Hello, world!n" , f );
return 0 ;
}Kita dapat melakukan ini pada replikan dengan BIC menggunakan perintah berikut:
BIC> #include <stdio.h>
BIC> file *f;
F
Bic> f = fopen ("test.txt", "w");
Bic> fputs ("Halo, dunia! N", f);
1
BIC>
Ini akan menyebabkan BIC memanggil fungsi C-library fopen() dan fputs() untuk membuat file dan menulis string Hello World ke dalamnya. Jika Anda sekarang keluar dari BIC, Anda akan melihat file test.txt di direktori kerja saat ini dengan string Hello, Worldn yang terkandung di dalamnya.
Perhatikan bahwa setelah mengevaluasi ekspresi BIC akan mencetak hasil evaluasi. Ini bisa berguna untuk menguji ekspresi sederhana:
BIC> 2 * 8 + fileno (f); 19
Anda dapat menggunakan BIC untuk mendapatkan informasi tentang variabel atau jenis apa pun yang telah dinyatakan dengan awalan namanya dengan A ? . Sintaks khusus ini hanya berfungsi di repl tetapi akan memungkinkan Anda untuk mendapatkan berbagai karakteristik tentang jenis dan variabel. Misalnya:
BIC> #include <stdio.h> BIC>? Stdout stdout adalah pointer ke struct _io_file. Nilai stdout adalah 0x7ff1325bc5c0. sizeof (stdout) = 8 byte. Stdout dinyatakan di: /usr/include/stdio.h:138.
Ketika rept dimulai, BIC akan melihat apakah ada ~/.bic . Jika dilakukan secara otomatis dievaluasi dan lingkungan yang dihasilkan digunakan oleh repl. Ini dapat berguna untuk mendefinisikan fungsi atau varible yang biasanya digunakan. Misalnya, katakan file ~/.bic kami berisi:
#include <stdio.h>
int increment ( int a )
{
return a + 1 ;
}
puts ( "Good morning, Dave." );Saat kami meluncurkan repl, kami mendapatkan:
$ bic Selamat pagi, Dave. BIC> Increment (2); 3
Jika Anda meneruskan file sumber BIC, bersama -s , sebagai argumen baris perintah itu akan mengevaluasinya, dengan memanggil fungsi main() . Misalnya, misalkan kita memiliki test.c file.c yang berisi yang berikut:
#include <stdio.h>
int factorial ( int n )
{
if (! n )
{
return 1 ;
}
return n * factorial ( n - 1 );
}
int main ()
{
printf ( "Factorial of 4 is: %dn" , factorial ( 4 ));
return 0 ;
} Kita kemudian dapat memohon BIC dengan -s test.c untuk mengevaluasinya:
$ bic -s test.c Faktorial 4 adalah: 24
Jika Anda ingin meneruskan argumen ke file C, tambahkannya ke baris perintah BIC. Setelah BIC memproses argumen -s semua argumen lain diperlakukan sebagai parameter untuk diteruskan ke program. Parameter ini dibuat sebagai variabel argc dan argv dan diteruskan ke main() . Nilai argv[0] adalah nama file C yang dieksekusi BIC. Pertimbangkan program C berikut:
#include <stdio.h>
int main ( int argc , char * argv [])
{
for ( int i = 0 ; i < argc ; i ++ )
printf ( "argv[%d] = %sn" , i , argv [ i ]);
return 0 ;
}Jika kami tidak lulus argumen apa pun:
$ bic -s test.c argv [0] = test.c
Sedangkan jika kita memohon BIC dengan lebih banyak argumen, mereka diteruskan ke program:
$ bic -s test.c -a foo -s bar abc argv [0] = test.c argv [1] = -a argv [2] = foo argv [3] = -s argv [4] = bar argv [5] = a argv [6] = b argv [7] = c
Anda juga dapat menggunakan ekspresi khusus: <REPL>; Dalam kode sumber Anda untuk membuat BIC menjatuhkan Anda ke repl pada titik tertentu dalam evaluasi file:

Anda dapat menggunakan BIC untuk menjelajahi API perpustakaan lain selain LIBC. Misalkan kita ingin menjelajahi Perpustakaan Capstone, kita lulus dalam opsi -l untuk membuat BIC memuat perpustakaan itu saat dimulai. Misalnya:

Perhatikan bahwa ketika BIC mencetak tipe data majemuk ( struct atau union ), itu menunjukkan semua nama anggota dan nilai yang sesuai.
Inti dari implementasi BIC adalah objek tree . Ini adalah objek generik yang dapat digunakan untuk mewakili seluruh program serta keadaan evaluator saat ini. Ini diimplementasikan di tree.h dan tree.c Setiap jenis pohon didefinisikan dalam c.lang . File c.lang adalah spesifikasi seperti LISP dari:
T_ADD .Addition .tADD .LHS dan RHS .Kode untuk membuat objek dengan set atribut di atas adalah:
( deftype T_ADD " Addition " " tADD "
( " LHS " " RHS " ))Setelah didefinisikan, kita dapat menggunakan objek ini dalam kode C kita dengan cara berikut:
tree make_increment ( tree number )
{
tree add = tree_make ( T_ADD );
tADD_LHS ( add ) = number ;
tADD_RHS ( add ) = tree_make_const_int ( 1 );
return add ;
} Perhatikan bahwa satu set makro aksesor, tADD_LHS() dan tADD_RHS() , telah dihasilkan bagi kami untuk mengakses slot properti yang berbeda. Ketika --enable-debug diatur selama kompilasi masing-masing makro ini mengembang ke cek untuk memastikan bahwa ketika mengatur properti tADD_LHS dari suatu objek yang objek memang merupakan instance dari T_ADD .
File c.lang dibaca oleh banyak kompiler sumber-ke-sumber yang menghasilkan cuplikan kode. Utilitas ini termasuk:
gentype : Menghasilkan daftar jenis objek pohon.gentree : Menghasilkan struktur yang berisi semua data properti untuk objek pohon.genctypes : Menghasilkan daftar objek pohon tipe -C - ini mewakili tipe data fundamental dalam C.genaccess : Hasilkan makro aksesor untuk properti objek pohon.gengc : Hasilkan fungsi tanda untuk setiap objek pohon, ini memungkinkan pengumpul sampah untuk melintasi pohon objek.gendump : Hasilkan kode untuk mencampakkan objek pohon secara rekursif.gendot : Hasilkan file titik untuk hierarki tree yang diberikan, memungkinkannya divisualisasikan. Output dari Lexer & Parser adalah hierarki objek tree yang kemudian diteruskan ke evaluator ( evaluator.c ). Evaluator kemudian akan secara rekursif mengevaluasi setiap elemen pohon, memperbarui status evaluator internal, sehingga melaksanakan program.
Panggilan ke fungsi eksternal ke evaluator ditangani dengan cara yang bergantung pada platform. Saat ini X86_64 dan AARCH64 adalah satu -satunya platform yang didukung dan kode untuk menangani ini masing -masing ada di folder x86_64 dan aarch64 . Ini berfungsi dengan mengambil objek tree panggilan fungsi (diwakili oleh T_FN_CALL ) dari evaluator dengan semua argumen yang dievaluasi dan mendorong mereka ke daftar tertaut sederhana. Ini kemudian dilintasi dalam perakitan untuk memindahkan nilai ke dalam register yang benar sesuai dengan konvensi panggilan x86_64 atau aarch64 dan kemudian bercabang ke alamat fungsi.
Parser dan Lexer masing -masing diimplementasikan di parser.m4 dan lex.m4 . Setelah melewati M4 output adalah dua parsers bison dan dua lexers fleksibel.
Alasan untuk dua parser adalah bahwa tata bahasa untuk c rept sangat berbeda dari file C. Misalnya, kami ingin pengguna dapat mengetikkan pernyataan untuk dievaluasi pada repl tanpa perlu membungkusnya dalam suatu fungsi. Sayangnya menulis pernyataan yang berada di luar badan fungsi tidak valid C. Karena itu, kami tidak ingin pengguna dapat menulis pernyataan telanjang dalam file C. Untuk mencapai ini, kami memiliki dua set aturan tata bahasa yang berbeda yang menghasilkan dua parser. Sebagian besar aturan tata bahasa tumpang tindih dan oleh karena itu kami menggunakan file M4 tunggal untuk mengurus perbedaan.