كيف يمكنني تنفيذ شيء مشابه لتوجيهات برنامج التحويل البرمجي Objective-C @encode() في ANSI C؟

StackOverflow https://stackoverflow.com/questions/2255637

سؤال

يقوم التوجيه @encode بإرجاع const char * وهو واصف نوع مشفر للعناصر المختلفة لنوع البيانات الذي تم تمريره.المثال التالي:

struct test
{ int ti ;
  char tc ;
} ;

printf( "%s", @encode(struct test) ) ;
// returns "{test=ic}"

أستطيع أن أرى استخدام sizeof() لتحديد الأنواع البدائية - وإذا كان كائنًا كاملاً، فيمكنني استخدام أساليب الفصل للقيام بالاستبطان.

ومع ذلك، كيف يتم تحديد كل عنصر من عناصر البنية غير الشفافة؟

هل كانت مفيدة؟

المحلول

قد تكون إجابة @Lothars "ساخرة"، لكنها قريبة جدًا من العلامة، لسوء الحظ.من أجل تنفيذ شيء من هذا القبيل @encode(), ، أنت بحاجة إلى محلل كامل لاستخراج معلومات النوع.حسنًا، على الأقل لأي شيء آخر غير "التافه" @encode() البيانات (أي، @encode(char *)).تحتوي المترجمات الحديثة عمومًا على مكونين أو ثلاثة مكونات رئيسية:

  • الواجهة الأمامية.
  • النهاية المتوسطة (لبعض المترجمين).
  • النهاية الخلفية.

يجب أن تقوم الواجهة الأمامية بتحليل كافة التعليمات البرمجية المصدرية وتحويل نص التعليمات البرمجية المصدر بشكل أساسي إلى نموذج داخلي "قابل للاستخدام بواسطة الآلة".

تقوم النهاية الخلفية بترجمة النموذج الداخلي "القابل للاستخدام بواسطة الآلة" إلى تعليمات برمجية قابلة للتنفيذ.

عادةً ما يقوم المترجمون الذين لديهم "نهاية متوسطة" بذلك بسبب بعض الاحتياجات:إنهم يدعمون "واجهات أمامية" متعددة، ربما تتكون من لغات مختلفة تمامًا.سبب آخر هو تبسيط التحسين:تعمل جميع تمريرات التحسين على نفس التمثيل الوسيط.ال gcc تعتبر مجموعة المترجمات مثالاً على المترجمات "ثلاثية المراحل". llvm يمكن اعتباره مترجم المرحلة "المتوسطة والخلفية":"الجهاز الظاهري منخفض المستوى" هو التمثيل الوسيط، ويتم إجراء كل التحسين في هذا النموذج. llvm قادر أيضًا على الاحتفاظ به في هذا التمثيل الوسيط حتى الثانية الأخيرة - وهذا يسمح "بتحسين وقت الارتباط".ال clang المترجم هو في الحقيقة "واجهة أمامية" تقوم بالإخراج (بشكل فعال). llvm التمثيل الوسيط.

لذلك، إذا كنت ترغب في إضافة @encode() وظيفة مترجم "موجود"، ربما يتعين عليك القيام بذلك كمترجم/معالج مسبق "من مصدر إلى مصدر".كانت هذه هي الطريقة التي تمت بها كتابة مترجمي Objective-C وC++ الأصليين، حيث قاموا بتحليل نص مصدر الإدخال وتحويله إلى "C عادي" والذي تم إدخاله بعد ذلك إلى مترجم C القياسي.هناك عدة طرق للقيام بذلك:

لفة بنفسك

  • يستخدم yacc و lex لتجميع محلل ANSI-C.ستحتاج إلى قواعد النحو- قواعد ANSI C (Yacc) هي بداية جيدة.في الواقع، لأكون واضحا، عندما أقول yacc, ، أعني حقًا الثور و flex.وأيضا، بشكل فضفاض، الآخر المتنوع yacc و lex مثل الأدوات المستندة إلى C: ليمون, com.dparser, ، إلخ...
  • يستخدم perl مع ياب أو EYapp, ، وهي زائفةyacc استنساخ في perl.ربما يكون ذلك أفضل لوضع نماذج أولية سريعة للفكرة مقارنةً بالاعتماد على لغة C yacc و lex- إنه perl بعد كل ذلك:التعبيرات العادية، والمصفوفات الترابطية، وعدم وجود إدارة للذاكرة، وما إلى ذلك.
  • قم ببناء المحلل اللغوي الخاص بك باستخدام أنتلر.ليس لدي أي خبرة في سلسلة الأدوات هذه، لكنها أداة "مترجم" أخرى (يبدو) أنها موجهة أكثر نحو مطوري جافا.يبدو أن قواعد لغة C وObjective-C متاحة مجانًا.

اخترق أداة أخرى

ملحوظة: ليس لدي أي خبرة شخصية في استخدام أي من هذه الأدوات لفعل أي شيء مثل الإضافة @encode(), ، لكنني أظن أنهم سيكونون عونا كبيرا.

  • CIL - ليست هناك خبرة شخصية في استخدام هذه الأداة، ولكنها مصممة لتحليل كود مصدر لغة C ثم "القيام بالأشياء" باستخدامها.مما يمكنني استخلاصه من المستندات، يجب أن تسمح لك هذه الأداة باستخراج معلومات النوع التي تحتاجها.
  • متناثر - يستحق النظر، ولكن لست متأكدا.
  • رنة - لم أستخدمها لهذا الغرض، ولكن يُزعم أن أحد الأهداف كان جعلها "قابلة للاختراق بسهولة" لهذا النوع من الأشياء فقط.على وجه الخصوص (ومرة أخرى، لا توجد خبرة شخصية) في القيام بـ "الرفع الثقيل" لجميع عمليات التحليل، مما يتيح لك التركيز على الجزء "المثير للاهتمام"، والذي في هذه الحالة سيكون استخراج المعلومات الحساسة للسياق وبناء الجملة، ثم تحويل ذلك إلى إلى سلسلة C عادية.
  • ملحقات دول مجلس التعاون الخليجي - المكونات الإضافية هي ميزة gcc 4.5 (وهو الإصدار ألفا/بيتا الحالي للمترجم) وميزة "قد" تسمح لك بالربط بسهولة بالمترجم لاستخراج معلومات النوع التي تحتاجها.لا توجد فكرة عما إذا كانت بنية البرنامج المساعد تسمح بهذا النوع من الأشياء.

آحرون

  • العصعص - تم وضع إشارة مرجعية على هذا مؤخرًا "لإلقاء نظرة عليه لاحقًا".هذا "قد" يكون قادرًا على فعل ما تريد، و"ربما" يكون قادرًا على فعل ذلك دون بذل الكثير من الجهد.
  • ميتا سي - تم وضع إشارة مرجعية على هذا مؤخرًا أيضًا.لا فكرة عن مدى فائدة هذا.
  • com.mygcc - "قد" افعل ما تريد.إنها فكرة مثيرة للاهتمام، ولكنها لا تنطبق بشكل مباشر على ما تريد.من صفحة الويب:"يسمح Mygcc للمبرمجين بإضافة اختباراتهم الخاصة التي تأخذ في الاعتبار بناء الجملة وتدفق التحكم ومعلومات تدفق البيانات."

روابط.

تحرير رقم 1، روابط المكافأة.

@Lothar يشير إلى نقطة جيدة في تعليقه.كنت أعتزم بالفعل تضمينها lcc, ولكن يبدو أنها ضاعت على طول الطريق.

  • lcc - ال lcc مترجم C.هذا مترجم C صغير جدًا، على الأقل من حيث حجم كود المصدر.إنه أيضًا لديه كتاب, ، وهو ما أوصي به بشدة.
  • tcc - ال tcc مترجم C.ليس تماما التربوية lcc, ، ولكن بالتأكيد لا يزال يستحق النظر.
  • poc - ال poc مترجم الهدف-C.هذا هو مترجم "من المصدر إلى المصدر" Objective-C.يقوم بتحليل كود مصدر Objective-C ويصدر كود مصدر C، والذي يمرر إليه بعد ذلك gcc (حسنا، عادة gcc).يحتوي على عدد من ملحقات/ميزات Objective-C غير المتوفرة gcc.بالتأكيد تستحق النظر

نصائح أخرى

وأنت سينفذ ذلك من خلال تنفيذ مترجم ANSI C أولا ثم إضافة بعض pragmas وظائف محددة التنفيذ لذلك.

ونعم أعرف أن هذا هو الجواب ساخرة وأنا قبول downvotes.

واحد طريقة للقيام بذلك سيكون لكتابة المعالج، والذي يقرأ الكود لتعريفات نوع وأيضا محل @encode ... مع حرفي سلسلة المقابلة.

وثمة نهج آخر، إذا يتم ترجمة البرنامج مع -g، سيكون لكتابة دالة الذي يقرأ تعريف نوع من معلومات التصحيح البرنامج في وقت التشغيل، أو استخدام gdb أو برنامج آخر لقراءة ذلك لك ثم إعادة صياغة ذلك كما تريد. الأمر gdb ptype يمكن استخدامها لطباعة تعريف من نوع معين (أو إذا كان ذلك غير كاف وهناك أيضا maint print type، والتي من المؤكد لطباعة معلومات أكثر بكثير مما كنت قد ربما تريد).

إذا كنت تستخدم مترجم التي تدعم الإضافات (مثل دول مجلس التعاون الخليجي 4.5)، فإنه قد أيضا من الممكن لكتابة البرنامج المساعد مترجم لهذا الغرض. يمكن أن البرنامج المساعد الخاص بك ثم الاستفادة من المعلومات النوع الذي المترجم وتحليل بالفعل. ومن الواضح أن هذا النهج سيكون محددة مترجم للغاية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top