bic : مترجم AC و API Explorerهذا المشروع الذي يسمح للمطورين باستكشاف واختبار C-Apis باستخدام حلقة قراءة almal eval ، والمعروفة أيضًا باسم REPL.

تبعيات وقت التشغيل في BIC هي كما يلي:
لبناء bic ، ستحتاج:
يرجى التأكد من تثبيت هذه قبل بناء BIC. يجب أن يقوم الأمر التالي بتثبيت هذه على نظام Debian/Ubuntu:
apt-get تثبيت build-libredline-dev autoconf-archive libgmp-dev توقع Flex Bison Automake M4 libtool pkg-config
يمكنك أيضًا استخدام الأمر التالي لتثبيت التبعيات المطلوبة عبر Homebrew على نظام MacOS.
Brew Install Bison Flex GMP Readline Autoconf-Archive
يمكنك تجميع وتثبيت BIC مع الأوامر التالية:
autoreconf -i ./configure --enable-debug يصنع اجعل التثبيت
للبناء على نظام MacOS ، تحتاج إلى تغيير خط التكوين إلى:
yacc = "$ (Brew -prefix bison)/bin/bison -y" ./configure -enable -debug
يمكنك استخدام Docker لبناء وتشغيل BIC مع الأمر التالي:
Docker Build -T BIC https://github.com/Hexagonal-sun/bic.git#master
بمجرد إنشاء الصورة ، يمكنك تشغيل BIC مع:
Docker Run -i BIC
إذا كنت تستخدم Arch Linux ، فيمكنك تثبيت BIC من AUR:
ياي -s بيك
عند استدعاء BIC بدون وسيطات ، يتم تقديم المستخدم بمطالبة Reply:
bic>
هنا يمكنك كتابة عبارات C و #include العديد من رؤوس النظام لتوفير الوصول إلى واجهات برمجة التطبيقات المختلفة على النظام. يمكن إدخال البيانات مباشرة في REPL ؛ ليست هناك حاجة لتحديد وظيفة ليتم تقييمها. لنفترض أننا نرغب في تنفيذ برنامج C التالي:
#include <stdio.h>
int main ()
{
FILE * f = fopen ( "out.txt" , "w" );
fputs ( "Hello, world!n" , f );
return 0 ;
}يمكننا القيام بذلك على REPL مع BIC باستخدام الأوامر التالية:
bic> #include <stdio.h>
bic> file *f ؛
و
bic> f = fopen ("test.txt" ، "w") ؛
bic> fputs ("مرحبا ، العالم! n" ، و) ؛
1
bic>
سيؤدي ذلك إلى استدعاء BIC إلى وظائف C-Library fopen() و fputs() لإنشاء ملف وكتابة سلسلة Hello World فيه. إذا قمت الآن بالخروج من BIC ، فيجب أن ترى test.txt file في دليل العمل الحالي مع السلسلة Hello, Worldn الموجودة داخلها.
لاحظ أنه بعد تقييم التعبير سيقوم BIC بطباعة نتيجة التقييم. يمكن أن يكون هذا مفيدًا لاختبار التعبيرات البسيطة:
BIC> 2 * 8 + fiLeno (F) ؛ 19
يمكنك استخدام BIC للحصول على معلومات حول أي متغير أو نوع تم إعلانه عن طريق بادئة اسمه باسم ? . يعمل بناء الجملة الخاص هذا فقط في REPL ولكن سيسمح لك بالحصول على خصائص مختلفة حول الأنواع والمتغيرات. على سبيل المثال:
bic> #include <stdio.h> bic>؟ stdout stdout هو مؤشر إلى بنية _io_file. قيمة stdout هي 0x7FF1325BC5C0. حجم (stdout) = 8 بايت. تم الإعلان عن stdout على: /usr/include/stdio.h:138.
عندما يبدأ الاستبدال ، سترى BIC ما إذا كان ~/.bic موجود. إذا تم تقييمه تلقائيًا ويتم استخدام البيئة الناتجة عن طريق REPL. يمكن أن يكون هذا مفيدًا لتحديد الوظائف أو المتغيرات التي يتم استخدامها بشكل شائع. على سبيل المثال ، يقول ملف ~/.bic الخاص بنا:
#include <stdio.h>
int increment ( int a )
{
return a + 1 ;
}
puts ( "Good morning, Dave." );عندما نطلق الاستبدال ، نحصل على:
$ bic صباح الخير يا ديف. BIC> الزيادة (2) ؛ 3
إذا قمت بتمرير ملف مصدر ، إلى جانب -s ، كوسيطة سطر الأوامر ، فسيقوم بتقييمه ، من خلال استدعاء وظيفة main() . على سبيل المثال ، افترض أن لدينا test.c الملف الذي يحتوي على ما يلي:
#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 ;
} يمكننا بعد ذلك استدعاء BIC مع -s test.c لتقييمه:
$ bic -s test.c عامل 4: 24
إذا كنت ترغب في نقل الحجج إلى ملف C ، فقم بإلحاقها إلى سطر أوامر BIC. بمجرد معالجة BIC حجة -s يتم التعامل مع جميع الحجج الأخرى كمعلمات لتمريرها إلى البرنامج. يتم إنشاء هذه المعلمات كمتغيرات argc و argv وتم تمريرها إلى main() . قيمة argv[0] هي اسم ملف C الذي تنفذه BIC. النظر في برنامج C التالي:
#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 ;
}إذا لم نمر أي حجج:
$ bic -s test.c Argv [0] = test.c
بينما إذا استدعينا BIC مع المزيد من الحجج ، يتم تمريرها إلى البرنامج:
$ bic -s test.c -a foo -s Bar ABC Argv [0] = test.c argv [1] = -a argv [2] = فو argv [3] = -s argv [4] = شريط Argv [5] = أ Argv [6] = ب Argv [7] = ج
يمكنك أيضًا استخدام تعبير خاص: <REPL>; في رمز المصدر الخاص بك لجعل BIC يسقطك في الاستبدال عند نقطة معينة في تقييم الملف:

يمكنك استخدام BIC لاستكشاف واجهات برمجة التطبيقات للمكتبات الأخرى غير LIBC. لنفترض أننا نرغب في استكشاف مكتبة Capstone ، نمر في خيار -l لجعل BIC تحميل تلك المكتبة عند بدء تشغيله. على سبيل المثال:

لاحظ أنه عندما تطبع BIC نوع بيانات مركب ( struct أو union ) ، فإنه يعرض جميع أسماء الأعضاء وقيمها المقابلة.
في قلب تطبيق BIC هو كائن tree . هذه كائنات عامة يمكن استخدامها لتمثيل برنامج كامل وكذلك حالة المقيِّم الحالية. يتم تنفيذه في tree.h و tree.c يتم تعريف كل نوع شجرة في c.lang . ملف c.lang هو مواصفات تشبه lisp من:
T_ADD .Addition .tADD .LHS و RHS .الرمز لإنشاء كائن مع مجموعة السمات أعلاه هو:
( deftype T_ADD " Addition " " tADD "
( " LHS " " RHS " ))بمجرد تحديدها ، يمكننا استخدام هذا الكائن في رمز C بالطريقة التالية:
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 ;
} لاحظ أنه تم إنشاء مجموعة من وحدات الماكرو للملحقات ، tADD_LHS() و tADD_RHS() ، للوصول إلى فتحات الخصائص المختلفة. عندما --enable-debug أثناء التجميع ، يتم توسيع كل واحد من وحدات الماكرو إلى فحص للتأكد من أنه عند تعيين خاصية tADD_LHS لكائن أن الكائن هو في الواقع مثيل لـ T_ADD .
تتم قراءة ملف c.lang بواسطة العديد من المترجمين إلى المصدر إلى المصدر الذي يولد قصاصات التعليمات البرمجية. وتشمل هذه المرافق:
gentype : يولد قائمة بأنواع كائنات الأشجار.gentree : يولد هيكلًا يحتوي على جميع بيانات الممتلكات لكائنات الأشجار.genctypes : ينشئ قائمة بكائنات الأشجار من النوع C - تمثل هذه أنواع البيانات الأساسية في C.genaccess : قم بإنشاء وحدات الماكرو للملحقات لخصائص كائن الشجرة.gengc : قم بإنشاء وظيفة علامة لكل كائن شجرة ، وهذا يتيح لمجمع القمامة اجتياز أشجار الكائن.gendump : إنشاء رمز لتفريغ كائنات الأشجار بشكل متكرر.gendot : قم بإنشاء ملف نقطة لتسلسل هرمي tree معين ، مما يسمح بتصوره. إن إخراج Lexer & Parser هو تسلسل هرمي للكائن tree الذي يتم تمريره بعد ذلك إلى المقيِّم ( evaluator.c ). سيقوم المقيِّم بعد ذلك بتقييم كل عنصر شجرة ، وتحديث حالة التقييم الداخلي ، وبالتالي تنفيذ برنامج.
يتم التعامل مع المكالمات إلى الوظائف الخارجية للمقيّم بطريقة تعتمد على النظام الأساسي. حاليًا X86_64 و AARCH64 هما المنصات المدعومة الوحيدة والرمز للتعامل مع هذا في مجلدات x86_64 و aarch64 على التوالي. يعمل هذا عن طريق أخذ كائن tree استدعاء دالة (يمثله T_FN_CALL ) من المقيِّم مع تقييم جميع الوسيطات وتنشطها في قائمة بسيطة. ثم يتم اجتياز ذلك في التجميع لنقل القيمة إلى السجل الصحيح وفقًا للاتصالات X86_64 أو AARCH64 ثم تتفرع إلى عنوان الوظيفة.
يتم تنفيذ المحلل و lexer في parser.m4 و lex.m4 على التوالي. بعد المرور عبر M4 ، يكون الإخراج اثنين من محلات البيسون واثنين من Lexers المرن.
السبب في اثنين من المحللين هو أن القواعد النحوية لـ C REPL تختلف تمامًا عن ملف C. على سبيل المثال ، نريد أن يكون المستخدم قادرًا على كتابة البيانات التي سيتم تقييمها على الاستبدال دون الحاجة إلى لفها في وظيفة. لسوء الحظ ، فإن كتابة بيان خارج هيئة الوظائف غير صالح C. على هذا النحو ، لا نريد أن يكون المستخدم قادرًا على كتابة عبارات عارية في ملف C. لتحقيق ذلك ، لدينا مجموعتان مختلفتان من قواعد القواعد التي تنتج محللين. تتداخل معظم قواعد القواعد ، وبالتالي نستخدم ملف M4 واحد لرعاية الاختلافات.