أسرار قديمة لتصحيح سريع: موحية شفرة المصدر

غالبًا ما تتحول مساء الجمعة إلى أمسية من الذكريات ، وليس فقط في الأسبوع الماضي ، ولكن أيضًا عن أحداث سابقة كثيرة. تذكرت يوم الجمعة هذا البرنامج المثير للإعجاب لـ MS DOS (وكذلك لنظام التشغيل Mac OS و UNIX و VAX / VMS) - مترجم Pascal و IDE Dr. باسكال. يمكن العثور على معلومات مفصلة حول الميزات والتعليقات على موقع الشركة المصنعة Visible Software (USA) المخزنة في الأرشيف ، وسأقتصر فقط على الأفكار التي أتذكرها أكثر ، وهذه الأفكار ، في رأيي ، لم تفقد أهميتها حتى اليوم. بادئ ذي بدء ، أتذكر الصورة:

الصورة

سنعود لاحقًا إلى هذه الصورة ، لكن الآن سنبدأ من البداية ، أي من القائمة الرئيسية:

الصورة

كما ترون ، القائمة شائعة جدًا لبرنامج DOS. قم بتنزيل ملف اللغز المعروف

"8 كوينز":
program EightQueens(output); { Place 8 hostile queens on a chessboard, such that none can be captured. } { From Wirth: Algorithms + Data Structures = Programs, page 146. } var i: integer; RowFree: array [1..8] of boolean; UpDiag: array [2..16] of boolean; { diagonal to upper right } DownDiag: array [-7..7] of boolean; { diagonal to lower right } QueenIn: array [1..8] of integer; procedure print; { Write out one solution } var k: integer; begin { print } for k := 1 to 8 do write(QueenIn[k]: 4); writeln; end { print }; procedure try(col: integer); { Try to place a queen in this column } var row: integer; begin { try } for row := 1 to 8 do if RowFree[row] and UpDiag[col+row] and DownDiag[col-row] then begin QueenIn[col] := row; RowFree[row] := false; UpDiag[col+row] := false; DownDiag[col-row] := false; if col < 8 then try(col+1) else print; RowFree[row] := true; UpDiag[col+row] := true; DownDiag[col-row] := true; end; end { try }; begin { EightQueens } for i := 1 to 8 do RowFree[i] := true; for i := 2 to 16 do UpDiag[i] := true; for i := -7 to 7 do DownDiag[i] := true; try(1) end { EightQueens }. 


ثم اضغط F9 (تشغيل). يتم عرض تنفيذ البرنامج على الشاشة:

الصورة

فيما يلي النتائج التي تم إخراجها بواسطة البرنامج (الإخراج) ، أعلى اليسار هو جزء الكود الخاص بالإجراء (أو الوظيفة) الذي تم تنفيذه في هذه الخطوة ، حيث يتم تمييز المشغل القابل للتنفيذ بسهم ، وقيم المتغيرات ذات الصلة الحالية على اليمين ، والشيء نفسه بالنسبة لإجراء الاستدعاء أعلاه. في الوقت نفسه ، يحدث الانتقال من المشغل إلى المشغل تلقائيًا مع تأخير يحدده المستخدم - يتوقف هذا "الفيلم" عند إيقاف البرنامج الذي تم تحميله في IDE (في حالتنا ، "8 Queens") أو عن طريق أمر التجميد ، والذي يمكن إصداره عن طريق الضغط على مفتاح الوظيفة المقابل. إذا لم ينته البرنامج ، فيمكنك الانتقال خطوة بخطوة ، كما هو الحال في برامج تصحيح الأخطاء الأخرى ، عن طريق الضغط على السهم لأسفل ، أو العودة إلى "الفيلم" بالضغط على F8 (متابعة). يعرض السطر الثاني في الجزء العلوي من الشاشة سلسلة من المكالمات الإجرائية. تجدر الإشارة إلى أن الطبيب المذكور أعلاه يختار "المتغيرات ذات الصلة حاليًا" بنفسه ، حيث يحتاج المستخدم فقط لتنزيل البرنامج والنقر فوق "تشغيل". إذا حكمنا من خلال المراجعات ، تبين أن مثل هذه الإدارة البسيطة للغاية مريحة للغاية للدورات التمهيدية للطلاب على أساسيات البرمجة ، والتي د. باسكال ، في الواقع ، هو المقصود. ومع ذلك ، يلاحظ دليل المستخدم أنه بالنسبة للمبرمج المحترف المتقدم ، قد تكون فرصة سريعة لمعرفة كيفية عمل برنامج صغير مع حركة واحدة مفيدة. هذا يثير سؤالًا مثيرًا للاهتمام: كم هو صغير؟

أخذت مترجم Wirth PascalS المكتوب بلغة Pascal. مقارنة بالملكات ، فإن هذا البرنامج ، الذي يحتوي على وحدة تخزين حوالي 2000 سطر من شفرة المصدر ، أكثر تعقيدًا بكثير. بالنسبة للطبيب ، في شكله الأصلي ، كان أكثر من اللازم لذلك ، لذا قمت بتقطيعه إلى جزأين.

الجزء الأول يعد ملفات البيانات:
 {%F- no reformatting } {%O+} program Pas1 (input,output,paskey,pasksy,spsfile,enterf,symsetf{,textf}); const nkw = 27; (*no. of key words*) alng = 10; (*no. of significant chars in identifiers*) type symbol = (intcon,realcon,charcon,string, notsy,plus,minus,times,idiv,rdiv,imod,andsy,orsy, eql,neq,gtr,geq,lss,leq, lparent,rparent,lbrack,rbrack,comma,semicolon,period, colon,becomes,constsy,typesy,varsy,functionsy, proceduresy,arraysy,recordsy,programsy,ident, beginsy,ifsy,casesy,repeatsy,whilesy,forsy, endsy,elsesy,untilsy,ofsy,dosy,tosy,downtosy,thensy); alfa = packed array [1..alng] of char; object = (konstant,variable,type1,prozedure,funktion); types = (notyp,ints,reals,bools,chars,arrays,records); keytype = array [1..nkw] of alfa; ksytype = array [1..nkw] of symbol; spstype = array [char] of symbol; symset = set of symbol; entertype = record fx0: alfa; fx1: object; fx2: types; fx3: integer; end; var key: keytype; ksy: ksytype; sps: spstype; (*special symbols*) syset : symset; pasksy : file of ksytype; paskey : file of keytype; spsfile : file of spstype; enterf : file of entertype; symsetf : file of symset; { textf : text;} procedure enter(x0: alfa; x1: object; x2: types; x3: integer); var EnterRec : EnterType; begin with EnterRec do begin fx0 := x0; fx1 := x1; fx2 := x2; fx3 := x3 end; write ( enterf, EnterRec ); end (*enter*) ; begin {main program} key[ 1] := 'and '; key[ 2] := 'array '; key[ 3] := 'begin '; key[ 4] := 'case '; key[ 5] := 'const '; key[ 6] := 'div '; key[ 7] := 'do '; key[ 8] := 'downto '; key[ 9] := 'else '; key[10] := 'end '; key[11] := 'for '; key[12] := 'function '; key[13] := 'if '; key[14] := 'mod '; key[15] := 'not '; key[16] := 'of '; key[17] := 'or '; key[18] := 'procedure '; key[19] := 'program '; key[20] := 'record '; key[21] := 'repeat '; key[22] := 'then '; key[23] := 'to '; key[24] := 'type '; key[25] := 'until '; key[26] := 'var '; key[27] := 'while '; ksy[ 1] := andsy; ksy[ 2] := arraysy; ksy[ 3] := beginsy; ksy[ 4] := casesy; ksy[ 5] := constsy; ksy[ 6] := idiv; ksy[ 7] := dosy; ksy[ 8] := downtosy; ksy[ 9] := elsesy; ksy[10] := endsy; ksy[11] := forsy; ksy[12] := functionsy; ksy[13] := ifsy; ksy[14] := imod; ksy[15] := notsy; ksy[16] := ofsy; ksy[17] := orsy; ksy[18] := proceduresy; ksy[19] := programsy; ksy[20] := recordsy; ksy[21] := repeatsy; ksy[22] := thensy; ksy[23] := tosy; ksy[24] := typesy; ksy[25] := untilsy; ksy[26] := varsy; ksy[27] := whilesy; rewrite (paskey); write (paskey, key); ksy[ 1] := andsy; ksy[ 2] := arraysy; ksy[ 3] := beginsy; ksy[ 4] := casesy; ksy[ 5] := constsy; ksy[ 6] := idiv; ksy[ 7] := dosy; ksy[ 8] := downtosy; ksy[ 9] := elsesy; ksy[10] := endsy; ksy[11] := forsy; ksy[12] := functionsy; ksy[13] := ifsy; ksy[14] := imod; ksy[15] := notsy; ksy[16] := ofsy; ksy[17] := orsy; ksy[18] := proceduresy; ksy[19] := programsy; ksy[20] := recordsy; ksy[21] := repeatsy; ksy[22] := thensy; ksy[23] := tosy; ksy[24] := typesy; ksy[25] := untilsy; ksy[26] := varsy; ksy[27] := whilesy; rewrite (pasksy); write (pasksy, ksy); sps['+'] := plus; sps['-'] := minus; sps['*'] := times; sps['/'] := rdiv; sps['('] := lparent; sps[')'] := rparent; sps['='] := eql; sps[','] := comma; sps['['] := lbrack; sps[']'] := rbrack; sps['#'] := neq; sps['&'] := andsy; sps[';'] := semicolon; rewrite (spsfile); write (spsfile, sps); rewrite (enterf); enter(' ', variable, notyp, 0); (*sentinel*) enter('false ', konstant, bools, 0); enter('true ', konstant, bools, 1); enter('real ', type1, reals, 1); enter('char ', type1, chars, 1); enter('boolean ', type1, bools, 1); enter('integer ', type1, ints , 1); enter('abs ', funktion, reals,0); enter('sqr ', funktion, reals,2); enter('odd ', funktion, bools,4); enter('chr ', funktion, chars,5); enter('ord ', funktion, ints, 6); enter('succ ', funktion, chars,7); enter('pred ', funktion, chars,8); enter('round ', funktion, ints, 9); enter('trunc ', funktion, ints, 10); enter('sin ', funktion, reals, 11); enter('cos ', funktion, reals, 12); enter('exp ', funktion, reals, 13); enter('ln ', funktion, reals, 14); enter('sqrt ', funktion, reals, 15); enter('arctan ', funktion, reals, 16); enter('eof ', funktion, bools, 17); enter('eoln ', funktion, bools, 18); enter('read ', prozedure, notyp, 1); enter('readln ', prozedure, notyp, 2); enter('write ', prozedure, notyp, 3); enter('writeln ', prozedure, notyp, 4); enter(' ', prozedure, notyp, 0); rewrite (symsetf); syset := [plus,minus,intcon,realcon,charcon,ident]; write ( symsetf, syset ); syset := [ident,arraysy,recordsy]; write ( symsetf, syset ); syset := [constsy,typesy,varsy,proceduresy,functionsy,beginsy]; write ( symsetf, syset ); syset := [intcon,realcon,charcon,ident,lparent,notsy]; write ( symsetf, syset ); syset := [beginsy,ifsy,whilesy,repeatsy,forsy,casesy]; write ( symsetf, syset ); end. 


هنا لا بد من توضيح أن الدكتور يتم وضع Pascal في أقواس التعليق وتبدأ بالحرف "٪". يتضمن التوجيه {٪ O +} اسم ملف مبسط ، حيث ، على سبيل المثال ، ملف خارجي تم تعريفه على أنه

 pasksy : file of ksytype; 

سوف يطلق عليه pasksy. مثل أي ملف خارجي ، يجب تحديده في رأس البرنامج:

 program Pas1 (input,output,paskey, 

في الجزء المتبقي من PascalS ، نحدد أيضًا ملفات البيانات:

 {%D+} {%F- no reformatting } {%O+} program Pascals(input,output,paskey,pasksy,spsfile,enterf,symsetf);{1.6.75} 

يجعل توجيه٪ D + من الممكن إيقاف رسم متحرك برمجيًا عن طريق استدعاء إجراء تجميد محدد مسبقًا.

سيبدو نص برنامج PascalS كما يلي:

 begin {main program} assign (input,'QUEENS.PAS'); reset (input); init; block(blockbegsys+statbegsys, false, 1); finish; 99: end. 

أين هي إجراءات الرهان والانتهاء:
 procedure init; {%s-} var i : integer; EnterRec : EnterType; begin writeln; reset (paskey); read (paskey, key); reset (pasksy); read (pasksy, ksy); reset (spsfile); read (spsfile, sps); reset (symsetf); read (symsetf,constbegsys,typebegsys,blockbegsys,facbegsys,statbegsys); stantyps := [notyp,ints,reals,bools,chars]; lc := 0; ll := 0; cc := 0; ch := ' '; errpos := 0; errs := []; insymbol; t := -1; a := 0; b := 1; sx := 0; c2 := 0; display[0] := 1; iflag := false; oflag := false; if sy <> programsy then freeze{3} else begin insymbol; if sy <> ident then freeze{2} else begin progname := id; insymbol; if sy <> lparent then freeze{9} else repeat insymbol; if sy <> ident then freeze{2} else begin if id = 'input ' then iflag := true else if id = 'output ' then oflag := true else freeze{0}; insymbol; end until sy <> comma; if sy = rparent then insymbol else freeze{4}; if not oflag then freeze{20}; end end ; reset (enterf); while not eof (enterf) do begin read (enterf,EnterRec ); with EnterRec do enter (fx0,fx1,fx2,fx3); end; with btab[1] do begin last := t; lastpar := 1; psize := 0; vsize := 0 end ; end {init}; procedure finish; {%s-} begin if sy <> period then freeze{22}; {emit(31)}; {halt} if btab[2].vsize > stacksize then freeze{49}; end {finish}; 


توجيه٪ s يعطل الرسوم المتحركة وعرض القيم المتغيرة داخل الإجراء الذي تم تحديده فيه.

بعد إجراء هذه التغييرات ، قمت بتنزيل وتنفيذ الجزء الأول (Pas1) ، ثم الجزء الثاني. قرأت PascalS الملكات وبدأت في بثها (انظر الصورة في البداية). كان من الصعب تتبع الرسوم المتحركة المستمرة لرمز بحجم PascalS ، لذلك اتصلت بالتجميد في النقاط الرئيسية والمكالمات المرقمة في التعليقات. بعد أن فهم الموقف ، واصل الرسوم المتحركة مع فريق Continue. أعتقد أنه في IDEs الحديثة للغات الحديثة ، سيكون هؤلاء الرسامون مفيدون.

لقد صنعت "الألعاب" الموضحة هنا لفترة طويلة على وحدة المعالجة المركزية 286 ضمن برنامج MS DOS 3.2 ، والآن أطلقت الملفات القديمة للتوصل إلى صور. في الختام ، ذكرت حقيقة مثيرة حول توزيع الدكتور. باسكال. تألفت عملية التسليم الأساسية من دليل المستخدم - كتاب يتكون من 200 صفحة تقريبًا على ورق ثقيل جيد وقرص مرن. كلفته 99.95US دولار وتم وضعه كبرنامج منخفض التكلفة. تكلف تراخيص عشرات الوظائف في الجامعات أقل بكثير من حيث نسخة واحدة. لكن إلى جانب الولايات ، وعلى سبيل المثال أستراليا ، دكتور كان باسكال مشهورًا أيضًا في الهند. حسب علمي ، بيعت الشركة المحلية رخصة توزيع في الهند ، وهذه الشركة نفسها طبعت كتبًا (أيضًا باللغة الإنجليزية 1: 1 مع الأصل) وكتبت أقراص مرنة. كانت الكتب على ورق الصحف مع نص أعمى ، ولكن كان السعر من حيث روبية حوالي 4US دولار. قامت نفس الشركة بتكرار المنتجات الشائعة الأخرى في ذلك الوقت ، مثل LOTUS 1-2-3 ، dBase-4 ، ChiWriter ، إلخ. لحوالي نفس السعر.

Source: https://habr.com/ru/post/ar432414/


All Articles