06-13-2011، 01:11 PM
PL/I (زبان برنامهنویسی اول) یک زبان برنامهنویسی دستوری با قابلیتهای علمی، مهندسی، تجاری است. این زبان جز زبانهای دارای قابلیتهای بسیار زیاد است و یکی از اولین زبانهایی است که در رده زبانهای دارای ویژگی زیاد محسوب میگردد. این زبان بطور گسترده توسط دانشگاهیان، بازرگانی، و صنعتی از ابتدای معرفی این زبان در اوایل دهه ۱۹۶۰ به کار میرفته است و هماکنون نیز این زبان فعال است.
محدوده اصلی عملکرد PL/I پردازش داده است. این زبان از مفهوم برنامهنویسی بازگشتی و برنامهنویسی ساختیافته نیز پشتیبانی مینماید. دستور زبان آن مشابه انگلیسی است و با استفاده از دستورات آن میتوان بیشتر ساختارهای پیچیده داده را بیان نمود و با استفاده از توابع بسیار زیاد آن براحتی آنها را تغییر داد.
تاریخچه PL/I
زبان PL/I توسط IBM در آزمایشگاه هارسلی در انگلستان به عنوان بخشی از توسعه سیستم/۳۶۰ ایجاد گردید. پیش از تولید سیستم/۳۶۰ IBM چندین مدل از کامپیوترهای بزرگ خود تولید کرده بود که با یکدیگر منطبق نیودند و بعضی برای کابردهای تجاری به کار میذرفتند در حالی که بعضی دیگر برای کابرد علمی منایب بودند. این مشکل IBM را بر آن داشت تا با تولید سیستم/۳۶۰ تمامی این مدلها را با یک مدل یکسان جایگزین نموده که برای کاربردهای علمی و تجاری بصورت یکسان مناسب باشد.
نه تنها سیستم مورد استفاده توسط دانشگاهیان و بازرگانان متفاوت بود زبان مورد استفاده آنها نیز با یکدیگر یکی نبود در کاربردهای تجاری زبان کوبول بکار میرفت اما در کاربردهای علمی فرترن مورد نظر بود. هدف از تولید این زبان بوجود آوردن یک زبان واحد برای کاربردهای علمی و تجاری بوده است و هدف دیگر این بوده است که بتوانند ویژگی ساختیافته را به کاربردهای این زبان با توجه به زبان الگول اضافه نمایند که در هیچ یک از زبانهای فرتن و کوبول مورد پشتیبانی قرار نمیگرفتند(در زبان تولید این زبان). طراحی PL/I توسط یک کمیته ایجاد شده توسط IBM و کاربران در سراسر آمریکا انجام شد. هدف اولیه استفاده از این زبان در سیستم/۳۶۰ بود اما متاسفانه این هدف با توجه به زمان قابل دستیابی نبود.
در ابتدا این زبان NPL(زبان برنامهنویسی جدید) نامیده شد اما این نام قابل استفاده نبود زیرا که همنام موسسه ملی فیزیک در انگلستان بود. این نام از ۱ مارس تا ۳۰ نوامبر سال ۱۹۶۴ بکار برده میشد. نامها MPL و MMPL نیز پیش از PL/I در نظر گرفته شد(این نامگذاری همزمان با زبان دسترسی به پایگاه داده Data Language/1 بود).
کامپایلرهای مناسب توسط گروههای مختلف پیاده شدند. پروژه مالتیکس در MIT از زبان پیال/آی اولیه (EPL) برای ساخت یک سیستمعامل در یک زبان سطح بالا در سال ۱۹۶۴ استفاده نمود. EPL توسط آزمایشگاههای بل و MIT داگلاس موری و رابرت موریس و دیگران ایجاد شد.
با وجود عدم موفقیت گسترده این زبان در تمام سیستمهای معمول در سال ۱۹۷۰ نمیتوان از موفقیت آن در جزایر جداگانه تشکیل شده توسط سیستمهای گوناگون گذشت نمود. این زبان کابردهای مهمی در پردازش دادههای تجاری و کاربردهای معمولتر همانند نوشتن سیستم عاملهای جدید داشت و PL/M که توسط اینتل ایجاد شد برای نوشتن سیستم عامل CP/M به کار رفت و این زبان به عنوان زبان اصلی تولید برنامههای اجرا شده در سیستم عاملهای CP/M و MP/M به کار میرفت. دیجیتال ریسرچ کامپایلری که خود توسط PL/M نوشته شده بود برای زبان PL/I ارائه نمود. در سالهای ۱۹۷۰ این زبان برای نوشتن بیشتر برنامههای اجرا شده بر ۸۰۸۰، ۸۰۸۵ ,Z80 به کار میرفت. سیستم SAS توسط PL/I نوشته شد و هماکنون دادههای SAS توسط دستوراتی همانند PL/I نوشته میشود. XPL که زیرمجموعهای از PL/I است برای نوشتن HAL/S در شاتلهای فضایی مورد استفاده قرار گرفت. PL/P زیرمجموعه دیرگ این زبان برای نوشتن بخشهای جدید پریموس در تمامی حلقههای دفاعی این به کار رفت. کامپایلر CORC که توسط دانشگاه کرنل نوشته شده بود و زیرمجموعه دیگری به نام PL/C را با استفاده از آن تدریس مینمودن قابلیت جالبی در کامپایل تمام برنامهها بدون شکست داشت. این کامپایلر تمام اشکالات معمول را اصلاح مینمود و بقیه خطاها را نیز به عنوان خروجیهایی نمایش میداد.
نوع دیگری از این زبان PL/S است که زبان سیستمهای IBM بوده و MVS توسط آن در سالهای ۱۹۷۰ نوشته شد. IBM زبان PL/S را تغییر داده و برای نوشتن سیستم عامل OS/390 و هماکنون z/OS به کار میبرد.
PL8 یا PL/8 نسخه ساده شده از زبان PL/I است در IBM برای نوشتن برنامههای AS/400 و S/390 توسعه یافت.
اولین سیستم رزرواسیون بلیط هواپیما به نام sabre اولین بار توسط اسمبلی ۷۰۹۰ نوشته شده بود در ادامه از زبان PL/I برای نوشتن سایر بخشهای سطح بالا استفاده نمود.
با توجه به استفاده گسترده در کامپیوترهای بزرگ زبان PL/I برای ویندوز، یونیکس، داس، AJX، و openVMS نیز موجود است.
بازنگری
این زبان به دلایل گوناگون موفقیت زیادی بدست نساورد در حالی که این ادعا وجود دارد که بدون زبان PL/I پروژه آپولو قادر نبود انسانها را بر ماه قرار دهد.
مشکلات طراحی و پیاده سازی
یکی از مشکلات در مورد زبان PL/I با وجود یادگیری و بکارگیری آسان نوشتن کامپایلر برای این زبان بسیار پیچیده و زمانبر بود. و دلیل این امر نیز توسعه این زبان توسط یک کمیته و برای پاسخگویی به نیازهای متفاوت ایجاد شد. علاوه بر این استاندارد برخلاف زبانهای دیگر مانند کوبول و زبانهای سطح بالا دیگر هیچ زیرمجموعهای از این زبان تعریف ننمود در نتیجه تمام ویژگیها باید با استاندارد تطبیق میداشت. (البته این زیرمجموعه نیز تعریف شد که ۱۵ سال بعد انجام شد.):
انتخابهای گوناگونی در دستورات این زبان وجود داشت که تحلیل آن را مشکل مینمود:
کامپایلر نمیتوانست تا زمان رسیدن به ; تعیین نماید که یک عبارت یک اعلام بوده یا دستور اجرایی.
این زبان کلمات کلیدی و رزرو شده نداشت در نتیجه کامپایلر باید تعیین مینمود که آیا این کلمه متغیر است یا کلمه کلیدی که چون دارای تصحیح خودکار بود باید آن را یک متغیر در نظر میگرفت که در نتیجه اشکالات بعدی زیادی را ایجاد مینمود و پیامهای خطای بسیار عجیب و گیجکننده نمایش میدهد.
استفاده از ساختار پیچیده ماکرو کامپایلر را مجبور مینمو که یک مفسر داخلی PL/I داشته و به این دلیل اندازه آن دو برابر شده و چندین گذر به کامپایلر اضافه نموده و این روند را کند میسازد.
این کامپایلرها ۴ برابر حجیمتر از کامپایلرهای مشابه برای کوبول و فرترن بوده و به همان اندازه نیز کندتر بود و این در زمان حافظههای کامپیوترهای بزرگ با حافظهای معادل ۲۵۶ KB بوده و زمان CPU بسیار با ارزش بود. البته این ضعف با توجه به میزان تولید برنامهنویس قابل چشمپوشی است.
پیچیدگی مشکل دیگر گریبانگیر PL/I بوده است. بهینهسازی مورد نیاز (با توجه به کارایی کم برخلاف زبانهای مشابه کوبول و فرترن) برای تغییر متغیرها بصورت غیرهمزمان (به عنوان مثال در حالت خطا در پردازش استثنا) پیشبینی تغییرات اعمال شده بر متغیرها در زمان اجرا غیر قابل پیشبینی مینمود.
مشکل بعدی سیاسی بود:زبانی که تماما توسط IBM نوشته شده بود واقعیت بسیار وحشتناکی برای رقیبان IBM بوده و آنها علاقهای به سرمایهگذاری بر این محصول نداشتند و ارائه خدمات برای این زبان را تا زمانی که مشتری صریحا آن را درخواست نماید به تعویق انداختند و انها را تشویق مینمودند تا با محصولات مطمئن در زبانهای کوبول و فرترن باقی بمانند.
مشکلات اولویتهای برنامهنویسان
مشکلات ذکر شده در بالا اعم از پیچیدگی و کیفیت پایین کامپایلرهای تولید شده توسط IBM برنامهنویسان را از تغییر زبان خود از کوبول و فرترن باز میداشت. این زبان دارای ویژگیهایی بود که بندرت مورد استفاده قرار میگرفتند مانند پشتیبانی از چندرشتهای که هزینه متناسب را به کامپایلر تحمیل نمود و نیاز به پشتیبانی محیط برنامهنویسی چندگانه توسط پردازنده و پشتیبانی از رشتههای غیرمسدودکننده توسط سیستم عامل داشت.
مشکل دیگر دستهبندی میان برنامهنویسان به عنوان علمی و تجاری بوده است. این دو گروه حتی از یکدیگر منزجر بودند. PL/I از ویژگیهای هر دو زبان فرترن و کوبول استفاده مینمود در نتیجه کاربران فرترن بدیلی وجود دستورات کوبول از آن استفاده نمیکردند و کابران کوبول نیز بدلیل مشابه آن را نمیپسندیدند. و هردو دسته کاربران آن را نمونه بزرگتر زبان خود میدانستند و از کاربرد آن هراس داشتند.
مشکل دیگری که بوجود آمد شباهت بعضی از دستورات PL/I به الگول یا کوبول یا فرترن و عملکرد متفاوت آن در این زبان بود. به عنوان مثال MOVE در کوبول تمام اعضا را به یک گروه از itemها کپی مینماید اما نمونه همین دستور در PL/I فقط یکی را کپی میکند. این چنین مشکلاتی ممکن است موجی خطاهای منطقی بسیار ریزی شود که برنامهنویسان کوبول متوجه آن نگردند. این مشکلات مانع از بکارگیری این زبان توسط برنامهنویسان حرفهای شد. ساختار ماکرو در PL/I منحصربفرد بود چرا که از معنا و دستورات زبان مقصد استفاده مینمود (برخلاف پیشپردازنده در سی++).
ویژگیهای بهبود یافته
با پشتیبانی کامل از اشارهگرها حتی برای ساختارها، بازگشتی، پردازشگر کمکی، توابه پیشساخته بسیار زیاد، و ویژگیهای دیگر PL/I را یک قدم بزرگ به جلو برخلاف زبانهای مشابه زمان خود نموده بود. با این حال این ویژگیها برای متقاعد نمودن همه کافی نبودند.
برنامههای نمونه
برنامه hello world
Hello2: proc options(main);
put list ('Hello, world!');
end Hello2;
جستجوی یک رشته
FINDSTRINGS: PROCEDURE OPTIONS(MAIN)
/* READ A STRING, THEN PRINT EVERY */
/* SUBSEQUENT LINE WITH A MATCH */
DECLARE PAT VARYING CHARACTER(100),
LINEBUF VARYING CHARACTER(100),
(LINENO, NDFILE, IX) FIXED BINARY;
NDFILE = 0; ON ENDFILE(SYSIN) NDFILE=1;
GET EDIT(PAT) (A);
LINENO = 1;
DO WHILE (NDFILE=0);
GET EDIT(LINEBUF) (A);
IF LENGTH(LINEBUF) > 0 THEN DO;
IX = INDEX(LINEBUF, PAT);
IF IX > 0 THEN DO;
PUT SKIP EDIT (LINENO,LINEBUF)(F(2),A)
END;
END;
LINENO = LINENO + 1;
END;
END FINDSTRINGS;
محدوده اصلی عملکرد PL/I پردازش داده است. این زبان از مفهوم برنامهنویسی بازگشتی و برنامهنویسی ساختیافته نیز پشتیبانی مینماید. دستور زبان آن مشابه انگلیسی است و با استفاده از دستورات آن میتوان بیشتر ساختارهای پیچیده داده را بیان نمود و با استفاده از توابع بسیار زیاد آن براحتی آنها را تغییر داد.
تاریخچه PL/I
زبان PL/I توسط IBM در آزمایشگاه هارسلی در انگلستان به عنوان بخشی از توسعه سیستم/۳۶۰ ایجاد گردید. پیش از تولید سیستم/۳۶۰ IBM چندین مدل از کامپیوترهای بزرگ خود تولید کرده بود که با یکدیگر منطبق نیودند و بعضی برای کابردهای تجاری به کار میذرفتند در حالی که بعضی دیگر برای کابرد علمی منایب بودند. این مشکل IBM را بر آن داشت تا با تولید سیستم/۳۶۰ تمامی این مدلها را با یک مدل یکسان جایگزین نموده که برای کاربردهای علمی و تجاری بصورت یکسان مناسب باشد.
نه تنها سیستم مورد استفاده توسط دانشگاهیان و بازرگانان متفاوت بود زبان مورد استفاده آنها نیز با یکدیگر یکی نبود در کاربردهای تجاری زبان کوبول بکار میرفت اما در کاربردهای علمی فرترن مورد نظر بود. هدف از تولید این زبان بوجود آوردن یک زبان واحد برای کاربردهای علمی و تجاری بوده است و هدف دیگر این بوده است که بتوانند ویژگی ساختیافته را به کاربردهای این زبان با توجه به زبان الگول اضافه نمایند که در هیچ یک از زبانهای فرتن و کوبول مورد پشتیبانی قرار نمیگرفتند(در زبان تولید این زبان). طراحی PL/I توسط یک کمیته ایجاد شده توسط IBM و کاربران در سراسر آمریکا انجام شد. هدف اولیه استفاده از این زبان در سیستم/۳۶۰ بود اما متاسفانه این هدف با توجه به زمان قابل دستیابی نبود.
در ابتدا این زبان NPL(زبان برنامهنویسی جدید) نامیده شد اما این نام قابل استفاده نبود زیرا که همنام موسسه ملی فیزیک در انگلستان بود. این نام از ۱ مارس تا ۳۰ نوامبر سال ۱۹۶۴ بکار برده میشد. نامها MPL و MMPL نیز پیش از PL/I در نظر گرفته شد(این نامگذاری همزمان با زبان دسترسی به پایگاه داده Data Language/1 بود).
کامپایلرهای مناسب توسط گروههای مختلف پیاده شدند. پروژه مالتیکس در MIT از زبان پیال/آی اولیه (EPL) برای ساخت یک سیستمعامل در یک زبان سطح بالا در سال ۱۹۶۴ استفاده نمود. EPL توسط آزمایشگاههای بل و MIT داگلاس موری و رابرت موریس و دیگران ایجاد شد.
با وجود عدم موفقیت گسترده این زبان در تمام سیستمهای معمول در سال ۱۹۷۰ نمیتوان از موفقیت آن در جزایر جداگانه تشکیل شده توسط سیستمهای گوناگون گذشت نمود. این زبان کابردهای مهمی در پردازش دادههای تجاری و کاربردهای معمولتر همانند نوشتن سیستم عاملهای جدید داشت و PL/M که توسط اینتل ایجاد شد برای نوشتن سیستم عامل CP/M به کار رفت و این زبان به عنوان زبان اصلی تولید برنامههای اجرا شده در سیستم عاملهای CP/M و MP/M به کار میرفت. دیجیتال ریسرچ کامپایلری که خود توسط PL/M نوشته شده بود برای زبان PL/I ارائه نمود. در سالهای ۱۹۷۰ این زبان برای نوشتن بیشتر برنامههای اجرا شده بر ۸۰۸۰، ۸۰۸۵ ,Z80 به کار میرفت. سیستم SAS توسط PL/I نوشته شد و هماکنون دادههای SAS توسط دستوراتی همانند PL/I نوشته میشود. XPL که زیرمجموعهای از PL/I است برای نوشتن HAL/S در شاتلهای فضایی مورد استفاده قرار گرفت. PL/P زیرمجموعه دیرگ این زبان برای نوشتن بخشهای جدید پریموس در تمامی حلقههای دفاعی این به کار رفت. کامپایلر CORC که توسط دانشگاه کرنل نوشته شده بود و زیرمجموعه دیگری به نام PL/C را با استفاده از آن تدریس مینمودن قابلیت جالبی در کامپایل تمام برنامهها بدون شکست داشت. این کامپایلر تمام اشکالات معمول را اصلاح مینمود و بقیه خطاها را نیز به عنوان خروجیهایی نمایش میداد.
نوع دیگری از این زبان PL/S است که زبان سیستمهای IBM بوده و MVS توسط آن در سالهای ۱۹۷۰ نوشته شد. IBM زبان PL/S را تغییر داده و برای نوشتن سیستم عامل OS/390 و هماکنون z/OS به کار میبرد.
PL8 یا PL/8 نسخه ساده شده از زبان PL/I است در IBM برای نوشتن برنامههای AS/400 و S/390 توسعه یافت.
اولین سیستم رزرواسیون بلیط هواپیما به نام sabre اولین بار توسط اسمبلی ۷۰۹۰ نوشته شده بود در ادامه از زبان PL/I برای نوشتن سایر بخشهای سطح بالا استفاده نمود.
با توجه به استفاده گسترده در کامپیوترهای بزرگ زبان PL/I برای ویندوز، یونیکس، داس، AJX، و openVMS نیز موجود است.
بازنگری
این زبان به دلایل گوناگون موفقیت زیادی بدست نساورد در حالی که این ادعا وجود دارد که بدون زبان PL/I پروژه آپولو قادر نبود انسانها را بر ماه قرار دهد.
مشکلات طراحی و پیاده سازی
یکی از مشکلات در مورد زبان PL/I با وجود یادگیری و بکارگیری آسان نوشتن کامپایلر برای این زبان بسیار پیچیده و زمانبر بود. و دلیل این امر نیز توسعه این زبان توسط یک کمیته و برای پاسخگویی به نیازهای متفاوت ایجاد شد. علاوه بر این استاندارد برخلاف زبانهای دیگر مانند کوبول و زبانهای سطح بالا دیگر هیچ زیرمجموعهای از این زبان تعریف ننمود در نتیجه تمام ویژگیها باید با استاندارد تطبیق میداشت. (البته این زیرمجموعه نیز تعریف شد که ۱۵ سال بعد انجام شد.):
انتخابهای گوناگونی در دستورات این زبان وجود داشت که تحلیل آن را مشکل مینمود:
کامپایلر نمیتوانست تا زمان رسیدن به ; تعیین نماید که یک عبارت یک اعلام بوده یا دستور اجرایی.
این زبان کلمات کلیدی و رزرو شده نداشت در نتیجه کامپایلر باید تعیین مینمود که آیا این کلمه متغیر است یا کلمه کلیدی که چون دارای تصحیح خودکار بود باید آن را یک متغیر در نظر میگرفت که در نتیجه اشکالات بعدی زیادی را ایجاد مینمود و پیامهای خطای بسیار عجیب و گیجکننده نمایش میدهد.
استفاده از ساختار پیچیده ماکرو کامپایلر را مجبور مینمو که یک مفسر داخلی PL/I داشته و به این دلیل اندازه آن دو برابر شده و چندین گذر به کامپایلر اضافه نموده و این روند را کند میسازد.
این کامپایلرها ۴ برابر حجیمتر از کامپایلرهای مشابه برای کوبول و فرترن بوده و به همان اندازه نیز کندتر بود و این در زمان حافظههای کامپیوترهای بزرگ با حافظهای معادل ۲۵۶ KB بوده و زمان CPU بسیار با ارزش بود. البته این ضعف با توجه به میزان تولید برنامهنویس قابل چشمپوشی است.
پیچیدگی مشکل دیگر گریبانگیر PL/I بوده است. بهینهسازی مورد نیاز (با توجه به کارایی کم برخلاف زبانهای مشابه کوبول و فرترن) برای تغییر متغیرها بصورت غیرهمزمان (به عنوان مثال در حالت خطا در پردازش استثنا) پیشبینی تغییرات اعمال شده بر متغیرها در زمان اجرا غیر قابل پیشبینی مینمود.
مشکل بعدی سیاسی بود:زبانی که تماما توسط IBM نوشته شده بود واقعیت بسیار وحشتناکی برای رقیبان IBM بوده و آنها علاقهای به سرمایهگذاری بر این محصول نداشتند و ارائه خدمات برای این زبان را تا زمانی که مشتری صریحا آن را درخواست نماید به تعویق انداختند و انها را تشویق مینمودند تا با محصولات مطمئن در زبانهای کوبول و فرترن باقی بمانند.
مشکلات اولویتهای برنامهنویسان
مشکلات ذکر شده در بالا اعم از پیچیدگی و کیفیت پایین کامپایلرهای تولید شده توسط IBM برنامهنویسان را از تغییر زبان خود از کوبول و فرترن باز میداشت. این زبان دارای ویژگیهایی بود که بندرت مورد استفاده قرار میگرفتند مانند پشتیبانی از چندرشتهای که هزینه متناسب را به کامپایلر تحمیل نمود و نیاز به پشتیبانی محیط برنامهنویسی چندگانه توسط پردازنده و پشتیبانی از رشتههای غیرمسدودکننده توسط سیستم عامل داشت.
مشکل دیگر دستهبندی میان برنامهنویسان به عنوان علمی و تجاری بوده است. این دو گروه حتی از یکدیگر منزجر بودند. PL/I از ویژگیهای هر دو زبان فرترن و کوبول استفاده مینمود در نتیجه کاربران فرترن بدیلی وجود دستورات کوبول از آن استفاده نمیکردند و کابران کوبول نیز بدلیل مشابه آن را نمیپسندیدند. و هردو دسته کاربران آن را نمونه بزرگتر زبان خود میدانستند و از کاربرد آن هراس داشتند.
مشکل دیگری که بوجود آمد شباهت بعضی از دستورات PL/I به الگول یا کوبول یا فرترن و عملکرد متفاوت آن در این زبان بود. به عنوان مثال MOVE در کوبول تمام اعضا را به یک گروه از itemها کپی مینماید اما نمونه همین دستور در PL/I فقط یکی را کپی میکند. این چنین مشکلاتی ممکن است موجی خطاهای منطقی بسیار ریزی شود که برنامهنویسان کوبول متوجه آن نگردند. این مشکلات مانع از بکارگیری این زبان توسط برنامهنویسان حرفهای شد. ساختار ماکرو در PL/I منحصربفرد بود چرا که از معنا و دستورات زبان مقصد استفاده مینمود (برخلاف پیشپردازنده در سی++).
ویژگیهای بهبود یافته
با پشتیبانی کامل از اشارهگرها حتی برای ساختارها، بازگشتی، پردازشگر کمکی، توابه پیشساخته بسیار زیاد، و ویژگیهای دیگر PL/I را یک قدم بزرگ به جلو برخلاف زبانهای مشابه زمان خود نموده بود. با این حال این ویژگیها برای متقاعد نمودن همه کافی نبودند.
برنامههای نمونه
برنامه hello world
Hello2: proc options(main);
put list ('Hello, world!');
end Hello2;
جستجوی یک رشته
FINDSTRINGS: PROCEDURE OPTIONS(MAIN)
/* READ A STRING, THEN PRINT EVERY */
/* SUBSEQUENT LINE WITH A MATCH */
DECLARE PAT VARYING CHARACTER(100),
LINEBUF VARYING CHARACTER(100),
(LINENO, NDFILE, IX) FIXED BINARY;
NDFILE = 0; ON ENDFILE(SYSIN) NDFILE=1;
GET EDIT(PAT) (A);
LINENO = 1;
DO WHILE (NDFILE=0);
GET EDIT(LINEBUF) (A);
IF LENGTH(LINEBUF) > 0 THEN DO;
IX = INDEX(LINEBUF, PAT);
IF IX > 0 THEN DO;
PUT SKIP EDIT (LINENO,LINEBUF)(F(2),A)
END;
END;
LINENO = LINENO + 1;
END;
END FINDSTRINGS;
گروه دور همی پارسی کدرز
https://t.me/joinchat/GxVRww3ykLynHFsdCvb7eg
https://t.me/joinchat/GxVRww3ykLynHFsdCvb7eg