UNIFDEF(1) General Commands Manual (prm) UNIFDEF(1)

unifdef, unifdefall — حذف دستورات شرطی پیش‌پردازنده از کد

unifdef [-bBcdehKkmnsStV] [-Ipath] [-[i]Dsym[=val]] [-[i]Usym] ... [-f defile] [-x {012}] [-M backext] [-o outfile] [infile ...] unifdefall [-Ipath] ... file

ابزار unifdef دستورات شرطی cpp(1) را به صورت انتخابی پردازش می‌کند. این ابزار از فایل ورودی، هم دستورات پیش‌پردازنده و هم هر متن اضافه‌ای را که این دستورات مشخص کرده‌اند باید حذف شود پاک می‌کند، در حالی که بقیه قسمت‌های فایل را بدون تغییر رها می‌سازد.

ابزار unifdef روی خطوط #if, #ifdef, #ifndef, #elif, #else, و #endif عمل می‌کند، و برای این کار از ماکروهای مشخص‌شده در گزینه‌های خط فرمان -D و -U یا در فایل‌های تعاریف -f استفاده می‌نماید. یک دستور زمانی پردازش می‌شود که مشخصات ماکروها برای تعیین یک مقدار قطعی برای عبارت کنترلی آن کافی باشد. اگر نتیجه نادرست (false) باشد، دستور پیش‌پردازنده و خطوط بعدی تحت کنترل آن حذف می‌شوند. اگر نتیجه درست (true) باشد، تنها خود دستور حذف می‌شود. یک دستور #ifdef یا #ifndef در صورتی که ماکروی کنترل‌کننده آن مشخص نشده باشد، بدون تغییر عبور داده می‌شود. هر عبارت کنترلی #if یا #elif که مقدار نامشخصی داشته باشد یا unifdef قادر به تجزیه آن نباشد، بدون تغییر عبور داده می‌شود. به‌طور پیش‌فرض، unifdef خطوط #if و #elif با عبارت‌های ثابت را نادیده می‌گیرد؛ می‌توان با مشخص کردن فلگ -k در خط فرمان، پردازش آن‌ها را درخواست کرد.

این ابزار زیرمجموعه‌ای پرکاربرد از نحو عبارت‌ها را برای خطوط #if و #elif پشتیبانی می‌کند: ثوابت عدد صحیح، مقادیر صحیح ماکروهای تعریف‌شده در خط فرمان، عملگر (), عملگرهای !, ~, - (یکانی)، *, /, %, +, -, <, <=, >, >=, ==, !=, &, ^, |, &&, ||, و عبارت‌های پرانتزبندی‌شده. تقسیم بر صفر به عنوان مقداری نامشخص در نظر گرفته می‌شود. نوعی ارزیابی “اتصال کوتاه” برای عملگر && استفاده می‌شود: اگر هر یک از عملوندها قطعاً نادرست باشد، نتیجه نادرست خواهد بود، حتی اگر مقدار عملوند دیگر نامشخص باشد. به طور مشابه، اگر هر یک از عملوندهای || قطعاً درست باشد، نتیجه درست خواهد بود.

هنگام ارزیابی یک عبارت، unifdef ابتدا ماکروها را بسط نمی‌دهد. مقدار یک ماکرو باید یک عدد ساده باشد، نه یک عبارت. شکل محدودی از ارجاع غیرمستقیم مجاز است، به گونه‌ای که مقدار یک ماکرو می‌تواند نام ماکرویی دیگر باشد.

در بیشتر موارد، unifdef تفاوتی میان ماکروهای شیء‌گونه (بدون آرگومان) و ماکروهای تابع‌گونه (دارای آرگومان) قائل نمی‌شود. فراخوانی یک ماکروی تابع‌گونه می‌تواند در عبارت‌های کنترلی #if و #elif ظاهر شود. اگر ماکرو به‌طور صریح تعریف نشده باشد، یا با فلگ -D در خط فرمان، یا با #define در یک فایل تعاریف -f تعریف شده باشد، آرگومان‌های آن نادیده گرفته می‌شوند. اگر ماکرویی به‌طور صریح در خط فرمان با فلگ -U یا با #undef در یک فایل تعاریف -f لغو تعریف (undefined) شده باشد، نمی‌تواند هیچ آرگومانی داشته باشد، زیرا این کار منجر به خطای نحوی می‌شود.

ابزار unifdef تنها به اندازه‌ای زبان C را درک می‌کند که بداند چه زمانی یکی از دستورات پیش‌پردازنده به دلیل قرار داشتن در یک کامنت غیرفعال است، یا به دلیل شکسته شدن خط با یک خط ادامه‌دار بک‌اسلش، قابل ارزیابی نیست. این ابزار دستورات پیش‌پردازنده با قالب‌بندی نامتعارف را تشخیص می‌دهد و چنانچه ساختار آن‌ها برای مدیریت بیش از حد غیرعادی باشد، آن‌ها را دست‌نخورده عبور می‌دهد. (بخش اشکالات (BUGS) در زیر را ببینید.)

اسکریپتی با نام unifdefall می‌تواند برای حذف تمام دستورات شرطی cpp(1) از یک فایل استفاده شود. این اسکریپت از unifdef -s و cpp -dM برای دریافت فهرست تمامی ماکروهای کنترل‌کننده و تعاریف آن‌ها (یا نبود آن‌ها) بهره می‌گیرد، سپس unifdef را با آرگومان‌های مناسب جهت پردازش فایل فراخوانی می‌کند.

sym=val
مشخص می‌کند که یک ماکرو با مقدار داده‌شده تعریف شده است.
sym
مشخص می‌کند که یک ماکرو با مقدار 1 تعریف شده است.
sym
مشخص می‌کند که یک ماکرو تعریف‌نشده (undefined) است.

اگر یک ماکرو در بیش از یک آرگومان ظاهر شود، آخرین مورد اولویت خواهد داشت.

sym[=val]
 
sym
رشته‌های C، کامنت‌ها و ادامه‌های خط درون بلوک‌های #ifdef و #ifndef که توسط ماکروهای ارائه‌شده با این گزینه‌ها کنترل می‌شوند، نادیده گرفته خواهند شد.
defile
فایل defile شامل دستورات پیش‌پردازنده #define و #undef است، که اثری مشابه آرگومان‌های متناظر -D و -U در خط فرمان دارند. می‌توان چندین آرگومان -f داشت و آن‌ها را با آرگومان‌های -D و -U ترکیب کرد؛ گزینه‌های بعدی بر گزینه‌های قبلی تقدم دارند.

هر دستور پیش‌پردازنده باید در یک خط منفرد باشد. تعاریف ماکروهای شیء‌گونه (بدون آرگومان) روی مقدار ارائه‌شده تنظیم می‌شوند. تعاریف ماکروهای تابع‌گونه (دارای آرگومان) به‌گونه‌ای در نظر گرفته می‌شوند که گویی روی 1 تنظیم شده‌اند.

هشدار: لیترال‌های رشته‌ای و ثوابت نویسه‌ای در فایل‌های -f به‌درستی تجزیه نمی‌شوند.

خطوط حذف‌شده را به جای پاک کردن، با خطوط خالی جایگزین می‌کند. این گزینه با گزینه -B مانعة‌الجمع است.
خطوط خالی اطراف یک بخش حذف‌شده را فشرده (یکپارچه) می‌کند. این گزینه با گزینه -b مانعة‌الجمع است.
متمم، یعنی خطوطی که در حالت عادی حذف یا خالی می‌شدند، نگه داشته می‌شوند و برعکس.
چاپ پیام‌های اشکال‌زدایی (دیباگ) را فعال می‌کند.
به‌طور پیش‌فرض، unifdef چنانچه نیاز به حذف یک دستور پیش‌پردازنده داشته باشد که بیش از یک خط گسترش یافته، خطایی را گزارش می‌دهد؛ برای نمونه هنگامی که یک کامنت چندخطی به انتهای سمت راست آن چسبیده باشد. فلگ -e باعث می‌شود به جای آن، چنین خطی نادیده گرفته شود.
راهنما را چاپ می‌کند.
path
مکانی اضافی برای جستجوی فایل‌های #include را به unifdefall معرفی می‌کند. این گزینه جهت سازگاری با cpp(1) و ساده‌سازی پیاده‌سازی unifdefall توسط unifdef نادیده گرفته می‌شود.
همیشه نتیجه عملگرهای && و || را در صورتی که هر یک از عملوندها نامشخص باشد، نامشخص تلقی می‌کند، به جای آنکه در شرایطی که عملوند نامشخص نمی‌تواند بر نتیجه اثر بگذارد، ارزیابی اتصال کوتاه انجام دهد. این گزینه برای حفظ سازگاری با نسخه‌های قدیمی‌تر unifdef فراهم شده است.
خطوط #if و #elif با عبارت‌های ثابت را پردازش می‌کند. به‌طور پیش‌فرض، بخش‌های کنترل‌شده توسط چنین خطوطی بدون تغییر عبور داده می‌شوند، زیرا معمولاً با “#if 0” شروع می‌شوند و به عنوان نوعی کامنت برای طرح‌ریزی توسعه‌های آینده یا گذشته به کار می‌روند. حذف کردن آن‌ها نادرست است، درست مانند آنچه در مورد کامنت‌های عادی صدق می‌کند.
یک یا چند فایل ورودی را درجا (in place) اصلاح می‌کند. اگر فایل ورودی نیازی به اصلاح نداشته باشد، فایل اصلی حفظ شده و با یک نسخه مشابه رونویسی نمی‌شود.
backext
فایل‌های ورودی را درجا اصلاح کرده و با الحاق پسوند backext به نام فایل‌های ورودی، نسخه‌های پشتیبان از فایل‌های اصلی نگه می‌دارد. یک پسوند backext با طول صفر، رفتاری مشابه گزینه -m خواهد داشت.
دستورات #line را پس از هر خط حذف‌شده به خروجی اضافه می‌کند، تا خطاهای تولیدشده در حین کامپایل فایل خروجی با شماره خطوط فایل ورودی همخوانی داشته باشند.
outfile
هنگام پردازش یک فایل منفرد، خروجی را به جای خروجی استاندارد در فایل outfile می‌نویسد.
به جای پردازش عادی فایل ورودی، این گزینه باعث می‌شود unifdef فهرستی از ماکروهای مورد استفاده در عبارت‌های کنترلی دستورات پیش‌پردازنده را تولید نماید.
مانند گزینه -s است، اما عمق تودرتویی هر ماکرو نیز چاپ می‌شود. این ویژگی برای پی بردن به تعداد حالت‌های ترکیبی ممکن از ماکروهای وابسته و متقابلِ تعریف‌شده/تعریف‌نشده سودمند است.
تجزیه رشته‌های C، کامنت‌ها و خطوط ادامه‌دار را غیرفعال می‌کند، که برای فایل‌های متنی ساده کاربرد دارد. این گزینه شکل فراگیری از فلگ‌های -iD و -iU است.
اطلاعات نسخه را چاپ می‌کند.
{012}
حالت وضعیت خروج را روی صفر، یک یا دو تنظیم می‌کند. برای جزئیات بیشتر به بخش وضعیت خروج (EXIT STATUS) در زیر مراجعه کنید.

ابزار unifdef در صورتی که هیچ آرگومان file داده نشود، ورودی خود را از می‌خواند. در صورت وجود چندین فایل ورودی، حتماً باید از گزینه‌های -m یا -M استفاده کنید. می‌توانید ورودی از stdin یا خروجی به stdout را با ‘-’ مشخص نمایید.

ابزار unifdef به‌خوبی با گزینه -Dsym از diff(1) همکاری می‌کند.

در استفاده عادی، وضعیت خروج ابزار unifdef به حالتی بستگی دارد که توسط گزینه -x تنظیم شده باشد.

اگر حالت خروج صفر باشد (پیش‌فرض)، unifdef در صورت تطابق کامل خروجی با ورودی، با وضعیت 0 و در صورت وجود تفاوت، با وضعیت 1 خارج می‌شود.

اگر حالت خروج یک باشد، unifdef در صورت تغییر نیافتن خروجی با وضعیت 1 و در صورت وجود تفاوت با وضعیت 0 خارج می‌شود.

اگر حالت خروج دو باشد، unifdef در هر دو مورد با وضعیت صفر خارج می‌گردد.

در تمامی حالت‌های خروج، چنانچه خطایی رخ دهد، unifdef با وضعیت 2 خارج خواهد شد.

در صورت ارائه گزینه‌های خط فرمان -h یا -V, وضعیت خروج 0 خواهد بود.

  • EOF درون کامنت
  • دستور نامناسب #elif, #else یا #endif
  • نام ماکرو در #define یا #undef جا افتاده است
  • خط کنترلی پیش‌پردازنده مبهم است
  • رسیدن زودهنگام به پایان فایل (EOF) (همراه با شماره خط مربوط به آخرین #if بسته نشده)
  • تعداد سطوح تودرتویی بیش از حد مجاز است
  • دستور پیش‌پردازنده ناشناخته است
  • لیترال نویسه‌ای یا رشته‌ای بسته نشده است

cpp(1), diff(1)

صفحه خانگی unifdef عبارت است از: http://dotat.at/prog/unifdef

دستور unifdef در 2.9BSD ارائه شد. پشتیبانی از ANSI C در FreeBSD 4.7 اضافه گردید.

پیاده‌سازی اصلی توسط Dave Yost <Dave@Yost.com> نوشته شده است. Tony Finch <dot@dotat.at> آن را برای پشتیبانی از ANSI C بازنویسی کرد.

  • ارزیابی عبارت‌ها بسیار محدود است.
  • ثوابت نویسه‌ای ارزیابی نمی‌شوند. لیترال‌های رشته‌ای و ثوابت نویسه‌ای در فایل‌های تعاریف -f به جای تجزیه به عنوان بخشی از توکن‌های جایگزین ماکرو، نادیده گرفته می‌شوند.
  • تنها فرم پایه لیترال‌های رشته خام ++C شناخته می‌شود، مانند R"(string)" بدون جداکننده‌ها همانند R"delimiter(string)delimiter".
  • فایل‌های مبدأ در هر نوبت یک خط پردازش می‌شوند، بنابراین دستورات پیش‌پردازنده‌ای که در چند خط فیزیکی پخش شده‌اند (به دلیل کامنت‌ها یا بک‌اسلش و رفتن به خط بعد) در تمامی موقعیت‌ها قابل رسیدگی نیستند.
  • سه‌نویسه‌ها (Trigraphs) پشتیبانی نمی‌شوند.
  • هیچ پشتیبانی از ماکروهایی با تعاریف مختلف در نقاط گوناگون فایل مبدأ وجود ندارد.
  • عملکرد حالت متنی و نادیده‌گیری با رفتار نسخه‌های مدرن cpp(1) همخوانی ندارد.

لطفاً گزارش اشکالات را با ایمیل به نشانی <dot@dotat.at> ارسال فرمایید.

December 3, 2015 Linux 6.12.113+deb13-amd64