.\" -*- mode: troff; coding: utf-8 -*- .\" Automatically generated by Pod::Man v6.0.2 (Pod::Simple 3.45) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>. .ie n \{\ . ds C` "" . ds C' "" 'br\} .el\{\ . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Required to disable full justification in groff 1.23.0. .if n .ds AD l .\" ======================================================================== .\" .IX Title "BT_POSTPROCESS 1" .TH BT_POSTPROCESS 1 2025-07-14 "btparse, version 0.91" btparse .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "نام (NAME)" bt_postprocess \- پس‌پردازش ورودی‌ها و متغیرها در btparse .SH "خلاصه دستور (SYNOPSIS)" .IX Header "SYNOPSIS" .Vb 2 \& void bt_postprocess_string (char * s, \& btshort options) \& \& char * bt_postprocess_value (AST * value, \& btshort options, \& boolean replace); \& \& char * bt_postprocess_field (AST * field, \& btshort options, \& boolean replace); \& \& void bt_postprocess_entry (AST * entry, \& btshort options); .Ve .SH "توضیحات (DESCRIPTION)" .IX Header "DESCRIPTION" هنگامی که .B btparse یک مدخل BibTeX را تجزیه می‌کند، نتایج را در ابتدا در یک درخت نحو انتزاعی (AST) دقیقاً به همان شکلی که داده‌ها تجزیه شده‌اند ذخیره می‌نماید. برای مثال، مدخل: .PP .Vb 7 \& @Article{Jones:1997a, \& AuThOr = "Bob Jones" # and # "Jim Smith ", \& TITLE = "Feeding Habits of \& the Common Cockroach", \& JoUrNaL = j_ent, \& YEAR = 1997 \& } .Ve .PP به یک AST تجزیه می‌شود که می‌توان آن را به شکل زیر نمایش داد: .PP .Vb 12 \& (entry,"Article") \& (key,"Jones:1997a") \& (field,"AuThOr") \& (string,"Bob Jones") \& (macro,"and") \& (string,"Jim Smith ") \& (field,"TITLE") \& (string,"Feeding Habits of the Common Cockroach") \& (field,"JoUrNaL") \& (macro,"j_ent") \& (field,"YEAR") \& (number,"1997") .Ve .PP مزیت این ساختار این است که تمام اطلاعات مهم مدخل با پیمایش درخت از طریق توابع شرح‌داده‌شده در .B bt_traversal به‌آسانی در دسترس هستند. مشکل آشکار این است که داده‌ها کمی خام‌تر از آن هستند که مستقیماً قابل استفاده باشند: انواع مدخل‌ها و نام فیلدها با بزرگی و کوچکی نامنظم حروف ذخیره شده‌اند، رشته‌ها پر از فاصله‌های خالی ناخواسته هستند، مقادیر فیلدها به رشته‌های منفرد تبدیل نشده‌اند و مواردی از این دست. .PP تمام این مشکلات توسط توابع پس‌پردازش .B btparse که در اینجا توضیح داده شده‌اند برطرف می‌شوند. معمولاً نیازی به فراخوانی دستی این توابع نخواهید داشت؛ کتابخانه پس از تجزیه هر مدخل به‌طور خودکار کار درست را برای شما انجام می‌دهد و می‌توانید نحوه پردازش را متناسب با برنامه خود سفارشی‌سازی کنید (برای مثال، می‌توانید تعیین کنید که ماکروها باز شوند اما زیررشته‌ها به یکدیگر متصل نشوند). با این حال، ممکن است بخواهید کنترل پس‌پردازش را مستقیماً به کد خود منتقل کنید و آن را از اختیار کتابخانه خارج سازید. یا محتمل‌تر اینکه رشته‌هایی از منابعی غیر از فایل‌های BibTeX داشته باشید و بخواهید با آن‌ها مانند رشته‌های BibTeX رفتار شود؛ در این شرایط توابع پس‌پردازش ضروری خواهند بود. در نهایت، شاید فقط کنجکاو باشید که دقیقاً چه بلایی بر سر داده‌ها پس از تجزیه می‌آید. در این صورت، برای مطالعه توضیحات بسیار دقیق به جای درستی آمده‌اید. .SH "توابع (FUNCTIONS)" .IX Header "FUNCTIONS" کتابخانه .B btparse چهار نقطه ورود برای کد پس‌پردازش خود ارائه می‌دهد. از میان این‌ها، احتمالاً تنها اولی و آخری \- یعنی پردازش رشته‌های منفرد و کل مدخل‌ها \- کاربرد رایج خواهند داشت. .SS "نقاط ورودی پس‌پردازش (Post-processing entry points)" .IX Subsection "Post-processing entry points" برای درک دلیل ارائه چهار نقطه ورود، توضیح نمونه AST ارائه‌شده در بالا کمک خواهد کرد. نخست اینکه کل مدخل با گره \f(CW\*(C`(entry,"Article")\*(C'\fR نمایش داده می‌شود؛ این گره کلید مدخل و تمام جفت‌های فیلد/مقدار را به عنوان فرزندان خود دارد. گره‌های مدخل توسط توابع \f(CWbt_parse_entry()\fR و \f(CWbt_parse_entry_s()\fR (به .B bt_input مراجعه کنید) و همچنین \f(CWbt_next_entry()\fR (که فهرستی از مدخل‌های برگشتی از \f(CWbt_parse_file()\fR را می‌پیماید \- به .B bt_traversal مراجعه کنید) بازگردانده می‌شوند. کل مدخل‌ها را می‌توان با تابع \f(CWbt_postprocess_entry()\fR پس‌پردازش کرد. .PP همچنین ممکن است نیاز داشته باشید یک فیلد منفرد یا فقط مقدار مرتبط با آن را پس‌پردازش کنید (تفاوت در این است که پردازش فیلد علاوه بر مقدار فیلد می‌تواند نام فیلد را نیز تغییر دهد \- مثلاً تبدیل آن به حروف کوچک). گره \f(CW\*(C`(field,"AuThOr")\*(C'\fR در بالا نمونه‌ای از یک زیردرخت فیلد است، و گره \f(CW\*(C`(string,"Bob Jones")\*(C'\fR نخستین گره در فهرست مقادیر ساده است که مقدار آن فیلد را نشان می‌دهد (به یاد داشته باشید که مقدار یک فیلد به‌طور کلی فهرستی از مقادیر ساده است). گره‌های فیلد توسط \f(CWbt_next_field()\fR و گره‌های مقدار توسط \f(CWbt_next_value()\fR بازگردانده می‌شوند. اولی را می‌توان برای پس‌پردازش به \f(CWbt_postprocess_field()\fR و دومی را به \f(CWbt_postprocess_value()\fR ارسال کرد. .PP در نهایت، ممکن است رشته‌های منفرد از منابعی غیر از AST کتابخانه .B btparse وارد برنامه شما شوند. به همین دلیل، تابع \f(CWbt_postprocess_string()\fR برای پس‌پردازش رشته‌های دلخواه در دسترس قرار دارد. .SS "گزینه‌های پس‌پردازش (Post-processing options)" .IX Subsection "Post-processing options" تمامی توابع پس‌پردازش دارای پارامتر \f(CW\*(C`options\*(C'\fR هستند که می‌توانید از آن برای تنظیم دقیق فرایند پس‌پردازش استفاده کنید (این پارامتر دقیقاً مانند گزینه‌های پردازش رشته بر اساس متاتایپ است که پیش از تجزیه مدخل‌ها تنظیم می‌کنید؛ به \f(CWbt_set_stringopts()\fR در .B bt_input مراجعه کنید). همانند سایر بخش‌های کتابخانه، \f(CW\*(C`options\*(C'\fR یک نگاشت بیتی (bitmap) است که از طریق ترکیب بیتی (OR منطقی) ثابت‌های از پیش تعریف‌شده مختلف ساخته می‌شود. این ثابت‌ها و اثرات آن‌ها در بخش "String processing option macros" از مستندات .B btparse شرح داده شده‌اند. .IP "bt_postprocess_string ()" 4 .IX Item "bt_postprocess_string ()" .Vb 2 \& void bt_postprocess_string (char * s, \& btshort options) .Ve .Sp یک رشته منفرد \f(CW\*(C`s\*(C'\fR را پس‌پردازش می‌کند که درجا تغییر می‌یابد. تنها گزینه پس‌پردازش که برای رشته‌های منفرد معنادار است، فشرده‌سازی فاصله‌های خالی مطابق قوانین BibTeX است؛ بنابراین، اگر عبارت \f(CW\*(C`options & BTO_COLLAPSE\*(C'\fR نادرست (false) باشد، این تابع هیچ اثری نخواهد داشت (هرچند در هر حال یک پیمایش کامل روی رشته انجام می‌دهد که برای توسعه‌های آینده در نظر گرفته شده است). .Sp قوانین دقیق فشرده‌سازی فاصله‌های خالی ساده هستند: نویسه‌های فاصله خالی غیر از فاصله معمولی (عمدتاً تب‌ها و خطوط جدید) به فاصله تبدیل می‌شوند، هر دنباله‌ای از بیش از یک فاصله متوالی به یک تک‌فاصله فشرده می‌شود و فاصله‌های ابتدا و انتهای رشته حذف می‌گردند (اطمینان از اینکه تمام فاصله‌ها به نویسه فاصله معمولی تبدیل شوند در واقع توسط پویشگر واژگانی .B btparse انجام می‌شود، بنابراین رشته‌ها در AST کتابخانه .B btparse هرگز فاصله‌ای جز فاصله معمولی نخواهند داشت. به همین ترتیب، هر رشته‌ای که به \f(CWbt_postprocess_string()\fR ارسال می‌شود نباید حاوی نویسه‌های فاصله غیر از فاصله معمولی باشد). .IP "bt_postprocess_value ()" 4 .IX Item "bt_postprocess_value ()" .Vb 3 \& char * bt_postprocess_value (AST * value, \& btshort options, \& boolean replace); .Ve .Sp یک مقدار فیلد منفرد را پس‌پردازش می‌کند که سرلیستِ فهرستی از مقادیر ساده بازگردانده‌شده توسط \f(CWbt_next_value()\fR است. تمام گزینه‌های مربوط به پردازش رشته در اینجا وارد عمل می‌شوند: تبدیل اعداد به رشته (\f(CW\*(C`BTO_CONVERT\*(C'\fR)، گسترش ماکروها (\f(CW\*(C`BTO_EXPAND\*(C'\fR)، فشرده‌سازی فاصله‌های خالی (\f(CW\*(C`BTO_COLLAPSE\*(C'\fR) و چسباندن رشته‌ها به یکدیگر (\f(CW\*(C`BTO_PASTE\*(C'\fR). از آنجا که چسباندن زیررشته‌ها به یکدیگر بدون گسترش ماکروها و تبدیل اعداد بی‌معنی خواهد بود، تلاش برای انجام چنین کاری یک خطای مهلک (fatal error) محسوب می‌شود. .Sp اگر \f(CW\*(C`replace\*(C'\fR درست (true) باشد، فهرست با سرلیست \f(CW\*(C`value\*(C'\fR با فهرستی که مقدار پردازش‌شده را نشان می‌دهد جایگزین خواهد شد. یعنی اگر چسباندن رشته‌ها فعال باشد (\f(CW\*(C`options & BTO_PASTE\*(C'\fR درست باشد)، این فهرست به یک گره منفرد کاهش می‌یابد که حاوی رشته یکتای حاصل از پیوند همه زیررشته‌ها است. اگر چسباندن رشته‌ها فعال نباشد، هر گره در فهرست دست‌نخورده باقی می‌ماند اما متن آن با متن پردازش‌شده جایگزین می‌شود. .Sp اگر \f(CW\*(C`replace\*(C'\fR نادرست (false) باشد، یک رشته جدید در لحظه ساخته شده و توسط تابع بازگردانده می‌شود. توجه داشته باشید که اگر در این حالت چسباندن فعال نباشد، فقط آخرین رشته موجود در فهرست را دریافت خواهید کرد (هرچند پس‌پردازش مقدار بدون چسباندن، مگر در حالتی که آن را با مقدار جدید جایگزین کنید، چندان معنادار نیست). .Sp رشته حاصل از پردازش کل مقدار را بازمی‌گرداند؛ این مقدار تنها زمانی معنا دارد که چسباندن فعال بوده باشد یا تنها یک مقدار در فهرست وجود داشته باشد. اگر یک فهرست چندمقداری بدون چسباندن پردازش شود، آخرین رشته فهرست (پس از پردازش) بازگردانده می‌شود. .Sp عملیاتی را در نظر بگیرید که می‌توان روی مقدار فیلد \f(CW\*(C`author\*(C'\fR در مثال بالا انجام داد، که ترکیبی از یک رشته، یک ماکرو و یک رشته دیگر است. فرض کنید ماکروی \f(CW\*(C`and\*(C'\fR به \f(CW" and "\fR بسط می‌یابد، و متغیر \f(CW\*(C`value\*(C'\fR به زیردرخت AST برای این مقدار اشاره می‌کند. زیردرخت AST اصلی متناظر با این مقدار عبارت است از: .Sp .Vb 3 \& (string,"Bob Jones") \& (macro,"and") \& (string,"Jim Smith ") .Ve .Sp برای پردازش کامل این مقدار به‌صورت درجا (in-place)، این تابع را به شکل زیر فراخوانی می‌کنید: .Sp .Vb 1 \& bt_postprocess_value (value, BTO_FULL, TRUE); .Ve .Sp این فراخوانی مقدار را به یک فهرست تک‌عضوی تبدیل می‌کند: .Sp .Vb 1 \& (string,"Bob Jones and Jim Smith") .Ve .Sp و رشته کاملاً پردازش‌شده \f(CW"Bob Jones and Jim Smith"\fR را بازمی‌گرداند. توجه داشته باشید که ماکروی \f(CW\*(C`and\*(C'\fR بسط یافته، میان دو رشته لفظی قرار گرفته، همه‌چیز به هم چسبانده شده و در نهایت فاصله‌های خالی فشرده شده‌اند (فشرده‌سازی فاصله‌های خالی پیش از اتصال رشته‌ها کار اشتباهی خواهد بود). .Sp (به‌طور ضمنی، \f(CW\*(C`BTO_FULL\*(C'\fR صرفاً ماکرویی برای ترکیب تمام گزینه‌های ممکن پردازش رشته است، در حال حاضر شامل: .Sp .Vb 1 \& BTO_CONVERT | BTO_EXPAND | BTO_PASTE | BTO_COLLAPSE .Ve .Sp دو ماکروی میان‌بر مشابه دیگر نیز وجود دارند: \f(CW\*(C`BTO_MACRO\*(C'\fR برای اعمال پردازش ویژه روی مقادیر ماکرو، که دقیقاً همانند \f(CW\*(C`BTO_FULL\*(C'\fR است با این تفاوت که \f(CW\*(C`BTO_COLLAPSE\*(C'\fR در آن وجود ندارد؛ و \f(CW\*(C`BTO_MINIMAL\*(C'\fR که به معنای عدم انجام هرگونه پردازش رشته است). .Sp فرض کنید ترجیح می‌دهید ماهیت فهرستی مقدار را حفظ کنید، در حالی که ماکروها بسط داده شوند و هر عددی به رشته تبدیل شود (این تبدیل ساده است: صرفاً نوع گره را از \f(CW\*(C`BTAST_NUMBER\*(C'\fR به \f(CW\*(C`BTAST_STRING\*(C'\fR تغییر می‌دهد. مقادیر عددی همواره به صورت رشته‌ای از ارقام ذخیره می‌شوند، دقیقاً همان‌طور که در فایل آمده‌اند). این کار با فراخوانی زیر انجام می‌شود: .Sp .Vb 2 \& bt_postprocess_value \& (value, BTO_CONVERT|BTO_EXPAND|BTO_COLLAPSE,TRUE); .Ve .Sp که فهرست را به این صورت تغییر می‌دهد: .Sp .Vb 3 \& (string,"Bob Jones") \& (string,"and") \& (string,"Jim Smith") .Ve .Sp توجه داشته باشید که در اینجا فاصله‌های خالی \fIپیش از\fR هرگونه اتصالی فشرده شده‌اند؛ این کار احتمالاً ایده مناسبی نیست، اما در صورت تمایل می‌توانید آن را انجام دهید (اگر ایده‌ای به سرتان زده که طرح پس‌پردازش مقادیر اختصاصی خود را با انجام گام‌های کوچک این‌چنینی پیاده‌سازی کنید، نگاهی به کد منبع \f(CWbt_postprocess_value()\fR بیندازید؛ احتمالاً شما را از چنین کاری منصرف خواهد کرد). .IP "bt_postprocess_field ()" 4 .IX Item "bt_postprocess_field ()" .Vb 3 \& char * bt_postprocess_field (AST * field, \& btshort options, \& boolean replace); .Ve .Sp این تابع چیزی بیش از یک رابط فرانت‌اند برای \f(CWbt_postprocess_value()\fR نیست؛ تنها تفاوت این است که یک گره AST از نوع "فیلد" (مانند \f(CW\*(C`(field,"AuThOr")\*(C'\fR در مثال بالا) به آن ارسال می‌کنید، و اینکه علاوه بر مقدار فیلد، نام فیلد را نیز دگرگون می‌سازد. به‌ویژه اینکه نام فیلد به حروف کوچک تبدیل می‌شود؛ این رفتار (در حال حاضر) اختیاری نیست. .Sp رشته بازگردانده‌شده توسط \f(CWbt_postprocess_value()\fR را برمی‌گرداند. .IP "bt_postprocess_entry ()" 4 .IX Item "bt_postprocess_entry ()" .Vb 2 \& void bt_postprocess_entry (AST * entry, \& btshort options); .Ve .Sp تمام مقادیر موجود در یک مدخل را پس‌پردازش می‌کند. اگر \f(CW\*(C`entry\*(C'\fR به AST یک مدخل "معمولی" (regular) یا "تعریف ماکرو" (macro definition) اشاره کند، مقادیر دقیقاً همان چیزی خواهند بود که انتظار دارید: هر آنچه در سمت راست یک فیلد یا "انتساب" ماکرو قرار دارد. همچنین می‌توانید مدخل‌های کامنت (comment) و پیش‌دیباچه (preamble) را نیز پس‌پردازش کنید. مدخل‌های کامنت اساساً یک رشته بزرگ هستند، بنابراین تنها فشرده‌سازی فاصله‌های خالی برای آن‌ها معنا دارد. مدخل‌های دیباچه ممکن است چندین رشته متصل به هم داشته باشند، بنابراین تمام گزینه‌های پردازش رشته روی آن‌ها اعمال می‌شوند (و هیچ مانعی برای استفاده از ماکروها در یک دیباچه وجود ندارد). .SH "همچنین ببینید (SEE ALSO)" .IX Header "SEE ALSO" btparse, bt_input, bt_traversal .SH "نویسنده (AUTHOR)" .IX Header "AUTHOR" Greg Ward