הידע המינימלי הנדרש לפני קריאת קוד COBOL

· עודכן בתאריך: · · COBOL, טכנולוגיה ישנה, מערכות עסקיות, תחזוקה, Mainframe

העברת אחריות, טיפול בתקלה, תחזוקת חבילה של ספק. במצבים כאלה, יכול לקרות שיום אחד פתאום מגיע אליכם קוד COBOL.

  • שם הקובץ .cbl או .cpy
  • שמות המשתנים כולם באותיות גדולות
  • 01,‏ 05,‏ 77,‏ 88 מסודרים בשורה
  • מופיע רישום כמו PIC S9(7)V99 COMP-3, משהו בין לחש קסמים לתוכנת הנהלת חשבונות
  • ובנוסף, הכול מלא ב-COPY, ורק מהקובץ הפתוח לא רואים את התמונה השלמה

בשלב הזה, רוב האנשים עוצרים לרגע.

עם זאת, המפה הדרושה לקריאה לא כל כך גדולה. יש הבדלים בין מערכות ומוצרי COBOL שונים, אבל השלד שכדאי לתפוס קודם כשקוראים מערכת עסקית קיימת די משותף. המאמר הזה מסדר, על בסיס COBOL ממשפחת IBM וקוד COBOL עסקי אופייני, סט מינימלי עבור מי שפתאום נאלץ לקרוא קוד.

הסיבה שעוצרים והגודל של המפהתרשים שמראה ששמות משתנים באותיות גדולות, מספרי רמה, רישום כמו PIC S9(7)V99 COMP-3, וריבוי COPY שלא מראה את התמונה השלמה גורמים לעצור, אבל השלד שצריך לתפוס בקריאת מערכת עסקית קיימת די משותף, והמפה לא כל כך גדולה.רישום לא מוכר גורם לעצוראבל השלד משותף בין מערכותמחזיקים קודם רק את המפה המינימליתהרבה COPY, לא רואים את התמונה השלמה

איור 1: הזהות של הרישום שנראה כמו לחש קסמים מתרכזת בכמה מושגים משותפים.

1. קודם כל - המסקנה (בקצרה)

אם אומרים את זה בגסות, אך שימושי בפועל:

  • COBOL היא, לפני שהיא שפת לוגיקה, שפה שמתמקדת חזק מאוד בהגדרת רשומות
  • קריאה של PROCEDURE DIVISION בלבד נותנת רק חצי מהתמונה. קודם כל בודקים את DATA DIVISION
  • PIC מייצג את צורת הפריט, ו-USAGE מייצג באיזה ייצוג הוא נשמר
  • COMP-3 הוא packed decimal. מופיע הרבה בעולם הסכומים ומספרי הפריטים
  • 88 הוא לא ממש משתנה נפרד, אלא שם תנאי שניתן לערך של הפריט שקדם לו ישירות
  • REDEFINES הוא מנגנון שמסתכל על אותו זיכרון בצורה אחרת. זו לא העתקה
  • אם יש COPY, הקובץ הפתוח כרגע עדיין לא שלם. בלי לראות את ה-copybook, אי אפשר לראות את התמונה השלמה
  • אם עוקבים אחרי PERFORM,‏ IF,‏ EVALUATE,‏ READ,‏ WRITE,‏ CALL, אפשר לתפוס פחות או יותר את הזרימה
  • קוד ישן הוא פורמט קבוע שבו למיקום העמודה יש משמעות. הרווח שנראה עיצוב גרידא הוא לא רק קישוט1

בקיצור, DIVISION,‏ PIC,‏ USAGE,‏ COMP-3,‏ REDEFINES,‏ OCCURS,‏ 88,‏ COPY,‏ PERFORM. אם יודעים לקרוא את אלה, שיעור ההיאבדות יורד משמעותית.

מפת הידע של המאמר

COBOL היא, לפני שהיא שפת סדר פעולות דרך PROCEDURE DIVISION, שפה שמגדירה ב-DATA DIVISION את צורת הרשומה, כשכל פריט נתונים מציין את הצורה שלו עם סעיף PICTURE ואת הייצוג הפנימי כמו COMP-3 עם סעיף USAGE. COMP-3 הוא packed decimal שדוחס ספרה עשרונית שתיים לבייט, ונראה כרצף בייטים חסר משמעות אם פותחים אותו כטקסט. REDEFINES מפרש מחדש את אותו שטח בצורה אחרת, OCCURS מייצג מערך, ורמה 88 מייצגת תנאי ששמו ניתן לערך של הפריט שקדם לו ישירות. משפט COPY מכניס copybook חיצוני בזמן קומפילציה, ולכן הקובץ הפתוח כשלעצמו לא מראה את התמונה השלמה, ויש צורך לעקוב אחרי זרימת העיבוד עם משפט PERFORM ו-scope terminator, ולתפוס את הגבול החיצוני עם FILE STATUS,‏ EXEC SQL ו-EXEC CICS.

מפת הידע של קריאת COBOLתרשים שמראה ש-COBOL, לפני שהיא שפת סדר פעולות דרך PROCEDURE DIVISION, היא שפה שמגדירה את צורת הרשומה ב-DATA DIVISION, ואת הקשרים בין סעיף PICTURE,‏ USAGE,‏ COMP-3,‏ REDEFINES,‏ OCCURS, רמה 88, משפט COPY, משפט PERFORM ו-scope terminator, ואת גבולות החוץ כמו EBCDIC,‏ FILE STATUS,‏ EXEC SQL ו-EXEC CICS.משתמש במשתמש במשתמש במשתמש במשתמש במשתמש במשתמש במשתמש במשתמש במשתמש במשתמש במשתמש במשתמש במשתמש במשתמש במשתמש במשתמש במשתמש במשתמש במשתמש במשתמש בCOBOLDATA DIVISIONCOMP-3(packed decimal)PROCEDURE DIVISIONסעיף PICTURE‏ (PIC)סעיף USAGECOMP-5סעיף REDEFINESסעיף OCCURSOCCURS DEPENDING ONרמה 88 (שם תנאי)משפט COPYcopybookמשפט PERFORMמסיים תחום (scope terminator)משפט MOVEפורמט קבוע (פורמט ייחוס)IBM Enterprise COBOLEBCDICסעיף FILE STATUSEXEC SQLEXEC CICS

בתרשים, קו מלא מציין קשר שמתקיים תמיד וקו מקווקו מציין קשר מותנה (תנאי ההתקיימות מפורטים בהסבר של כל קשר בעמוד המפורט). רשימת כל הקשרים (סך הכול 21, עם אסמכתה ורמת ודאות) והגדרות המושגים המרכזיים מרוכזות בעמוד המפורט של מפת הידע (ביפנית). נתונים: JSON-LD / Turtle

2. חושבים על COBOL קודם כשפת “צורת הנתונים”

אם קוראים בתחושה של C# או Java, בהתחלה רוצים לעקוב אחרי if,‏ for וקריאות לפונקציות. אבל ב-COBOL, לפני זה, מהיר יותר לתפוס “איזו רשומה התכנית הזו מקבלת, איזו רשומה היא יוצרת, ואיזה buffer היא מחזיקה”.

קוד COBOL עסקי אופייני הולך בערך בזרימה הזו.

  1. קוראים רשומה מקובץ או מ-DB
  2. מכניסים לפריט ב-WORKING-STORAGE
  3. מסתעפים בתנאי
  4. ממלאים לתוך רשומה אחרת
  5. כותבים החוצה

כלומר, הפריסה נוטה להקדים את האלגוריתם.

הזרימה האופיינית ל-COBOL עסקיתרשים שמראה שקוד COBOL עסקי אופייני קורא רשומה מקובץ או DB, מכניס אותה לפריט ב-WORKING-STORAGE, מסתעף בתנאי, ממלא לתוך רשומה אחרת וכותב אותה החוצה.קוראים רשומהמכניסים ל-WORKING-STORAGEמסתעפים בתנאיממלאים לרשומה אחרתכותבים החוצה

איור 2: הכוכב הוא זרימת הרשומה, והאלגוריתם נכנס ביניים.

לדוגמה, שלד כזה.

       IDENTIFICATION DIVISION.
       PROGRAM-ID. SAMPLE01.

       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT SALES-FILE ASSIGN TO ...

       DATA DIVISION.
       FILE SECTION.
       FD  SALES-FILE.
       01  SALES-REC.
           05  SALE-ID       PIC 9(8).
           05  SALE-AMOUNT   PIC S9(7)V99 COMP-3.

       WORKING-STORAGE SECTION.
       01  WS-EOF            PIC X VALUE 'N'.
           88  EOF           VALUE 'Y'.

       PROCEDURE DIVISION.
           PERFORM UNTIL EOF
               READ SALES-FILE
                   AT END
                       SET EOF TO TRUE
                   NOT AT END
                       PERFORM PROCESS-SALE
               END-READ
           END-PERFORM
           STOP RUN.

כשקוראים את הקוד הזה, מה שכדאי לבדוק ראשית הוא לא PERFORM, אלא הטיפוס של SALE-AMOUNT והמשמעות של EOF. COBOL נעשית פתאום שקטה אם קוראים בסדר הזה.

3. קודם מסתכלים על 4 ה-DIVISION

קוד COBOL מתחלק תחילה, בגדול, ל-4 DIVISION.

DIVISION מה בודקים תחילה
IDENTIFICATION DIVISION שם התכנית, הערות ישנות, מקור
ENVIRONMENT DIVISION קבצים, משאבים חיצוניים, הנחות קלט/פלט
DATA DIVISION הגדרת רשומות, שטח עבודה, ארגומנטים
PROCEDURE DIVISION הליך העיבוד עצמו

בפרט חשובים אלה.

  • FILE SECTION יש הגדרת רשומה של קבצי קלט/פלט
  • WORKING-STORAGE SECTION יש משתנים, דגלים, מונים, buffer עבודה בשימוש רגיל
  • LOCAL-STORAGE SECTION לפעמים יש שטח שמאותחל בכל קריאה
  • LINKAGE SECTION לפעמים יש ארגומנט שמתקבל מבחוץ, או כניסה לתת-תכנית

אם רואים LINKAGE SECTION ו-PROCEDURE DIVISION USING ..., יש סיכוי גבוה שהתכנית הזו לא שלמה בפני עצמה, אלא מקבלת נתונים מבחוץ ופועלת.

מה LINKAGE SECTION מראהתרשים שמראה שאם רואים LINKAGE SECTION ו-PROCEDURE DIVISION USING, יש סיכוי גבוה שהתכנית לא שלמה בפני עצמה, אלא מקבלת נתונים מבחוץ ופועלת.יש LINKAGE SECTIONסיכוי שמקבלת נתונים מבחוץיש PROCEDURE DIVISION USINGלא תכנית שלמה בפני עצמה

איור 3: אם רואים הגדרת כניסה, קוראים בהנחה שיש קורא חיצוני.

4. לא להיבהל ממראה הפורמט הקבוע

ב-COBOL ישנה, למיקום העמודה עצמו בשורת הקוד יש משמעות. בלי לדעת את זה, “למה יש רווח מוזר בצד שמאל” נשאר תעלומה לנצח.1

בפורמט קבוע, בגסות זה כך.

  • עמודות 1-6: מספר סידורי
  • עמודה 7: indicator
  • עמודות 8-11: Area A
  • עמודות 12-72: Area B

עמודה 7 חשובה במיוחד.

  • * או /: שורת הערה
  • -: שורת המשך
  • D: שורת debugging
  • *>: הערה שאפשר לכתוב גם באמצע השורה

ההתאמה בין עמודות לתוכן, עם סרגל, נראית כך. שורה ראשונה - ספרת העשרות, שורה שנייה - ספרת האחדות.

         1         2         3         4         5         6         7         8
12345678901234567890123456789012345678901234567890123456789012345678901234567890
SSSSSSIAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB........
  • S = מספר סידורי (עמודות 1-6)
  • I = indicator (עמודה 7)
  • A = Area A (עמודות 8-11)
  • B = Area B (עמודות 12-72)
  • . = מעמודה 73 ואילך. בחלק מהמערכות משמש כשדה זיהוי, אבל לא משפיע על משמעות התכנית

אם מיישמים על קוד אמיתי, זה נראה כך.

000100* שורה זו היא הערה כי בעמודה 7 יש *
000200 IDENTIFICATION DIVISION.
000300 PROGRAM-ID. SAMPLE01.
000400 DATA DIVISION.
000500 WORKING-STORAGE SECTION.
000600 01  WS-ORDER.
000700     05  WS-ORDER-ID    PIC 9(8).
000800     05  WS-LONG-NAME   PIC X(30) VALUE 'ABCDEFGHIJKLMNOPQRST
000900-    'UVWXYZ0123'.

ארבע נקודות שכדאי לשים לב אליהן בקריאה.

  • עמודות 1-6 הן מספר סידורי. בדוגמה למעלה, 000100 וכדומה, וזה לא משפיע על התנהגות התכנית. לפעמים גם ריק.
  • עמודה 7 היא ה-indicator. אם *, זו הערה; אם -, שורת המשך. שורה 000900 בדוגמה למעלה היא המשך של הליטרל המחרוזתי מהשורה הקודמת.
  • עמודות 8-11 הן Area A.DIVISION,‏ SECTION, שם פסקה, FD, ומספרי הרמה 01 ו-77 מתחילים כאן. בדוגמה למעלה, IDENTIFICATION DIVISION. ו-01 WS-ORDER. מתחילים ב-Area A.
  • עמודות 12-72 הן Area B. משפט רגיל, ורמות משנה כמו 05, נכתבים כאן. בדוגמה למעלה, 05 WS-ORDER-ID מתחיל ב-Area B.

הרווח כאן הוא לא “עיצוב” במובן המודרני, אלא בחלקו תחביר. אם עורכים בעורך, ממירים tab, מיישרים שמאלה, או מדביקים ברשלנות, זה בדרך כלל נשבר. כשמסתכלים על קוד ישן, כדאי לחשוד קודם אם הקובץ הוא fixed format או free format. אם מפעילים עיצוב אוטומטי מודרני על קוד בפורמט fixed, הגבול בין Area A ל-Area B נשבר וזה מפסיק להתקמפל.

לפני שנוגעים בקוד בפורמט קבועתרשים שמראה שבקוד ישן קודם בודקים אם זה fixed format או free format, ואם מפעילים עיצוב אוטומטי מודרני או המרת tab על קוד בפורמט fixed, הגבול בין Area A ל-Area B נשבר וזה מפסיק להתקמפל.פורמט fixedפורמט freeפותחים קוד ישןfixed או freeמיקום העמודה עצמו הוא תחבירעיצוב אוטומטי או המרת tab שובריםהמגבלה על העמודה רופפת

איור 4: לפני עיצוב, קובעים תחילה את הפורמט של הקובץ.

5. המינימום ב-DATA DIVISION

5.1 מספר רמה

הגדרת הנתונים ב-COBOL בונה היררכיה לא עם הזחה, אלא עם מספר רמה.2

       01  WS-ORDER.
           05  WS-ORDER-ID    PIC 9(8).
           05  WS-AMOUNT      PIC S9(7)V99 COMP-3.
           05  WS-STATUS      PIC X.
               88  WS-OK      VALUE '0'.
               88  WS-ERROR   VALUE '9'.

       77  WS-COUNT           PIC 9(4).

מספיק לזכור לפחות את אלה.

  • 01: רשומה עליונה אחת, קבוצה
  • 02-49: הרמה שמתחתיה
  • 77: פריט בודד עצמאי
  • 88: ‏condition-name. נותן שם לערך של הפריט שקדם לו ישירות3
  • 66: לשימוש RENAMES. לא נפוץ מאוד, אבל קיים

חשוב לא לחשוב על 88 כמשתנה בוליאני נפרד. זה לא ששטח בשם WS-OK קיים בנפרד, אלא שכש-WS-STATUS הוא '0', אפשר לקרוא לזה בשם WS-OK.

הזהות של רמה 88תרשים שמראה שרמה 88 היא לא משתנה בוליאני עצמאי, אלא שם תנאי שניתן לערך של הפריט שקדם לו ישירות, וכש-WS-STATUS מקבל ערך מסוים אפשר לקרוא לזה בשם WS-OK.09פריט הבסיס WS-STATUSמה הערךנכון תחת השם WS-OKנכון תחת השם WS-ERRORאין שטח נפרד אחר

איור 5: 88 הוא לא משתנה, אלא כינוי קריא שניתן לערך.

עוד דבר חשוב: מה שקובע את ההיררכיה הוא לא הרווח, אלא מספר הרמה. ההזחה החזותית עוזרת להתמצאות, אבל מה שסופו-של-דבר צריך להאמין לו הוא 01 / 05 / 10 / 88.2

5.2 PICTURE

PIC מייצג את צורת הפריט. הנפוצים ביותר הם אלה.

רישום משמעות בגסות
X תו
9 ספרה
S עם סימן
V נקודה עשרונית לוגית בלבד
X(10) 10 תווים
9(5) מספר בן 5 ספרות
S9(7)V99 עם סימן, 7 ספרות שלמות + 2 ספרות עשרוניות

לדוגמה,

  • PIC X(10) -> 10 תווים
  • PIC 9(5)V99 -> מספר שלם בן 5 ספרות + 2 ספרות עשרוניות
  • PIC S9(7)V99 -> עם סימן, 7 ספרות שלמות + 2 ספרות עשרוניות

זה החלוקה.

מה שחשוב במיוחד כאן הוא V. ל-V אין תו . ממשי. ‏PIC 9(5)V99 מטופל “כמספר עם 2 ספרות אחרי הנקודה”, אבל בנתונים עצמם אין תו נקודה. לכן, אם קוראים קובץ או dump כ”מחרוזת שנראית”, לרוב זה נכשל.

V היא נקודה עשרונית לוגיתתרשים שמראה של-V ב-PIC 9(5)V99 אין תו נקודה ממשי, זה מטופל כמספר עם 2 ספרות אחרי הנקודה אבל אין נקודה בנתונים, ולכן אם קוראים קובץ או dump כמחרוזת שנראית, זה נכשל.PIC 9(5)V99מטופל כמספר עם 2 ספרות עשרוניותאין תו נקודה בנתוניםפרשנות כמחרוזת שנראית נכשלת

איור 6: הנקודה קיימת רק בהגדרה, ולא בנתונים.

5.3 USAGE /‏ DISPLAY /‏ COMP /‏ COMP-3

אם PIC הוא הצורה, USAGE הוא באיזה ייצוג נשמר. מספיק לתפוס לפחות את אלה כדי לקרוא ברוב המקרים.45

רישום משמעות בגסות הערה בקריאה
DISPLAY עשרוני חיצוני שנראה כתו ב-mainframe לפעמים מניח EBCDIC6
COMP /‏ BINARY בינארי מספר הספרות במראה וייצוג הפנימי נפרדים
COMP-3 /‏ PACKED-DECIMAL packed decimal נראה שבור אם קוראים כתו

לדוגמה,

       01  WS-AMOUNT-DISP   PIC S9(7)V99.
       01  WS-AMOUNT-BIN    PIC S9(7) COMP.
       01  WS-AMOUNT-PACK   PIC S9(7)V99 COMP-3.

שלושת אלה כולם “מספרים”, אבל הצורה הפנימית שלהם שונה.

אותו מספר, החזקה שונהתרשים שמראה שגם עם צורה זהה, ל-DISPLAY יש ייצוג עשרוני חיצוני שנראה כתו, ל-COMP יש ייצוג בינארי, ול-COMP-3 יש ייצוג packed decimal, כשה-USAGE משנה את צורת ההחזקה בפנים.פריט מספרי באותה צורהDISPLAY (נראה כתו)COMP (בינארי)COMP-3 (packed decimal)נראה שבור אם קוראים כתו

איור 7: גם אם ה-PIC זהה, אם ה-USAGE שונה, רצף הבייטים שונה לגמרי.

מה שהכי משפיע בפועל הוא התגובה הראשונית ברגע שרואים COMP-3.

  • זה packed decimal
  • כנראה סכום, מס, מספר פריטים, או תעריף
  • טבעי לגמרי שזה נראה שבור כטקסט
  • אם מסתכלים בתחושת CSV או UTF-8, זו תקלה

אם מחזיקים הבנה כזו, אפשר להימנע מלהיבהל סתם מהמראה של dump או קובץ בינארי.

התגובה ברגע שרואים COMP-3תרשים שמראה שכשרואים COMP-3, מבינים שזה packed decimal, כנראה שדה של סכום, מס, מספר פריטים או תעריף, שטבעי לגמרי שנראה שבור כטקסט, ולא נבהלים כשמסתכלים בתחושת CSV או UTF-8.מוצאים COMP-3מבינים שזה packed decimalחושדים בשדה כספי או מספר פריטיםלא נבהלים גם אם נראה שבור כטקסט

איור 8: רק הרפלקס הזה מקטין את מספר הפעמים שנבהלים מול dump.

איך COMP-3 נראה בפועל כרצף בייטים

שווה לעבור על זה פעם אחת ידנית, וזה משנה את המראה מכאן ואילך.

לחוקי ה-packed decimal יש רק שני כללים.45

  1. ספרה עשרונית נדחסת שתיים בכל בייט
  2. אבל, רק הבייט הימני ביותר משתמש לספרה התחתונה ולסימן

הסימן מיוצג בערך בן 4 סיביות, C חיובי, D שלילי, F ללא סימן.

בודקים בדוגמה מהמדריך הרשמי של IBM.4

הגדרה ערך רצף בייטים
PIC S9(4) PACKED-DECIMAL +1234 01 23 4C
PIC S9(4) PACKED-DECIMAL -1234 01 23 4D
PIC 9(4) PACKED-DECIMAL 1234 01 23 4F

1234 הוא בן 4 ספרות, ולכן לפי כלל 2 נוצר רווח בגובה ספרה אחת בהתחלה. זה ה-0 שבתחילה.

באותה שיטה, בואו נעקוב אחר PIC S9(7)V99 COMP-3 שהופיע כמה פעמים במאמר הזה.

  • S9(7)V99 הוא 7 ספרות שלמות + 2 ספרות עשרוניות = 9 ספרות
  • V רק מציין את מיקום הנקודה העשרונית, ולכן הוא לא צורך אף בייט
  • אם דוחסים 9 ספרות שתיים לבייט, זה 4 בייטים, והספרה שנותרת + הסימן הם עוד בייט. סך הכול 5 בייטים

אם הערך הוא +12345.67, כשמיישרים ל-9 ספרות מקבלים 001234567, וזה נראה כך.

ערך        : +12345.67
ייצוג ב-9 ספרות : 0 0 1 2 3 4 5 6 7  וסימן
בייט       : 00 12 34 56 7C
                            ^ סימן C = חיובי

עבור ערך שלילי -12345.67, רק הבייט האחרון הופך ל-7D.

בייט       : 00 12 34 56 7D

איך זה נראה אם פותחים את זה כטקסט זה הנקודה המרכזית. אם מנסים בכוח להתאים 00 12 34 56 7C לתו ASCII אחד לכל בייט,

  • 00 הוא NUL, ו-12 הוא תו בקרה, ולכן בכלל לא ניתנים להצגה כתו
  • 34 הוא 4, ‏56 הוא V, ‏7C הוא |

התוצאה. כלומר, על המסך זה נראה כמו “כמה תווים לא ניתנים להצגה, ואז 4V|”. הרצף 12345.67 לא מופיע בשום מקום.

זו הזהות של “נראה כמו מוג’יבאקה אבל לא שבור”. אם פותחים dump ונתקלים ברצף לא מובן, כדאי לחשוד קודם שה-USAGE של הפריט הזה הוא COMP-3.

איך רצף הבייטים של COMP-3 נבנהתרשים שמראה שב-packed decimal דוחסים ספרה עשרונית שתיים לבייט, רק הבייט האחרון משמש לספרה התחתונה ולסימן, ולכן מספר בן 9 ספרות הופך ל-5 בייטים, ואם פותחים את זה כ-ASCII הרצף המקורי לא מופיע בשום מקום.דוחסים ספרה עשרונית שתיים לבייטהבייט האחרון הוא ספרה תחתונה + סימן9 ספרות הופכות ל-5 בייטיםפתיחה כ-ASCII לא מראה את המספר המקורינראה כמו מוג'יבאקה אבל לא שבור

איור 9: אם יודעים את שני כללי הדחיסה, dump לא מובן הופך לרצף שאפשר לקרוא.

בנוסף, הנה גם טבלת עזר מהירה שממירה בין מספר ספרות למספר בייטים. מספר הבייטים מתקבל לפי “מחלקים את מספר ה-9 בשתיים, מעגלים כלפי מטה, ומוסיפים 1”.

מספר ה-9 ב-PICTURE מספר בייטים ב-COMP-3
1 1
2-3 2
4-5 3
6-7 4
8-9 5
10-11 6
12-13 7

הסיבה שאותו מספר בייטים מתקבל משני מספרי ספרות היא שכשמספר ה-9 זוגי, נוצר רווח של ספרה אחת בתחילה. זו הסיבה ש-S9(4) הופך ל-3 בייטים כמו 01 23 4C, וגם S9(5) נכנס לאותם 3 בייטים.

בהתאמת פריסה מול קובץ חיצוני, בלי הטבלה הזו, ההיסט זז בייט אחד בכל פעם.

עוד הערה קטנה: זה שמדובר ב-DISPLAY לא בהכרח אומר מחרוזת ASCII. במערכות מסוג z/OS, מניחים EBCDIC, ולכן גם אם ספרות נראות כתו, ערך הבייט שונה מ-'0'-'9' של ASCII.6

5.4 REDEFINES /‏ OCCURS /‏ COPY /‏ FILLER

ארבעת אלה הם המקומות שהכי קל להיתקע בהם בקריאה.

REDEFINES

REDEFINES הוא מנגנון שמסתכל על אותו שטח בצורה אחרת. זו לא העתקה.7

       01  REC-BUF.
           05  REC-TYPE      PIC X.
           05  REC-DATA      PIC X(99).

       01  HEADER-REC REDEFINES REC-BUF.
           05  HDR-TYPE      PIC X.
           05  HDR-DATE      PIC 9(8).
           05  FILLER        PIC X(91).

זה קרוב לתחושה של union בשפות מסוג C. מופיע הרבה בכתיבה מהסוג “מזהים 100 בייט אחד כסוגי רשומה שונים”.

REDEFINES היא פרשנות אחרת לאותו שטחתרשים שמראה ש-REDEFINES היא לא העתקה אלא מנגנון שרואה את אותו שטח זיכרון בצורה אחרת, כשאותו buffer נראה גם כרשומה כללית וגם כרשומת header, וכתיבה בצד אחד משנה את המראה בצד השני.שטח זיכרון אחדנראה כ-REC-BUFנראה כ-HEADER-RECכתיבה בצד אחד משנה את שני המראות

איור 10: גם אם יש שתי הגדרות, יש רק רצף בייטים אחד בפועל.

OCCURS

OCCURS הוא מערך. ב-COBOL נוטים לקרוא לזה table.

       05  WS-ITEM OCCURS 12 TIMES.
           10  WS-PRICE    PIC 9(5).

ואם מופיע גם OCCURS DEPENDING ON, זו טבלה באורך משתנה. במקרה כזה, זה עשוי להשפיע גם על המיקום של הפריטים הבאים, ולכן אם עוקבים בתחושת אורך קבוע, מפספסים.8

תשומת לב ל-OCCURS DEPENDING ONתרשים שמראה ש-OCCURS הוא מערך, ואם מופיע DEPENDING ON זו הופכת לטבלה באורך משתנה שהמיקום של הפריטים הבאים עשוי לזוז בהתאם לערך, ולכן עקיבה בתחושת אורך קבוע מפספסת.איןישמוצאים OCCURSיש DEPENDING ON?טבלה במספר קבועטבלה באורך משתנההמיקום של הפריטים הבאים עשוי לזוז

איור 11: שלוש המילים DEPENDING ON משנות את הנחת חישוב ההיסט.

COPY

COPY הוא include בזמן קומפילציה. כלומר, הקובץ הפתוח כרגע עשוי עדיין לא להיות הצורה המלאה.9

       COPY CUSTOMER-REC.
       COPY ERROR-MAP.

די רגיל שהגדרת רשומה, דגלים משותפים, host variable ל-SQL, וממשק חיצוני דחוסים בתוך ה-copybook.

כשיש הרבה COPY וקשה לקרוא, מהיר יותר לבדוק אם אפשר לראות את המקור אחרי הרחבה או את ה-compiler listing. ל-IBM Enterprise COBOL יש גם אפשרות בשם MDECK, שמוציאה את מקור הקלט אחרי עיבוד הספרייה.10

איך קוראים קוד עם COPYתרשים שמראה ש-COPY הוא include בזמן קומפילציה ולכן הקובץ הפתוח עשוי להיות לא שלם, ולכן פותחים את ה-copybook לבדיקה, ואם קשה לקרוא, מחפשים את המקור אחרי הרחבה, listing או פלט של אפשרות MDECK.כשקשה לקרואמוצאים COPYהקובץ הפתוח עשוי להיות לא שלםפותחים את ה-copybook לבדיקהמחפשים מקור אחרי הרחבה או listing

איור 12: מספר השורות שרואים כרגע לא בהכרח כל התכנית.

FILLER

FILLER הוא פריט בלי שם. אבל, “לא מפנים אליו אז אין לו משמעות” - זה לא נכון.

  • שטח שמור
  • חור לתאימות עם מפרט ישן
  • התאמת אורך רשומה
  • רווח ל-REDEFINES

זה תפקידו הרגיל.

ל-FILLER אין שם, אבל כמות בייטים הוא בהחלט קיים. אם שוכחים את זה, במיפוי מול קובץ חיצוני העולם זז בייט אחר בייט.

מה קורה אם שוכחים לספור FILLERתרשים שמראה של-FILLER אין שם אבל כמות בייטים בהחלט קיימת, וזה משמש כשטח שמור או להתאמת אורך רשומה, ואם שוכחים לספור אותו, המיפוי מול קובץ חיצוני זז בייט אחר בייט.נכללנשכחFILLER הוא פריט בלי שםכמות הבייטים בהחלט קיימתנכלל בחישוב הפריסה?תואם לקובץ החיצוניזז בייט אחר בייט

איור 13: גם לפריט שלא מפנים אליו יש תפקיד - אורך.

6. המינימום ב-PROCEDURE DIVISION

אם DATA DIVISION היא המפה, PROCEDURE DIVISION הוא מסלול התנועה.

6.1 PERFORM

PERFORM היא תזוזת הבקרה הבסיסית ב-COBOL. בגסות, זה קורא לעיבוד וחוזר.11

הצורה הנפוצה היא:

       PERFORM INIT-PROC
       PERFORM UNTIL EOF
           PERFORM READ-PROC
           IF NOT EOF
               PERFORM EDIT-PROC
               PERFORM WRITE-PROC
           END-IF
       END-PERFORM

ל-PERFORM יש בגדול שתי משפחות.

  • ‏out-of-line PERFORM שמציין פסקה או section
  • ‏inline PERFORM ... END-PERFORM שכותב את הבלוק במקום

בקוד ישן עוד יותר, מופיע גם ציון טווח רגיל כמו PERFORM A-100 THRU A-199. זה נוח, אבל אם מוסיפים פסקה באמצע, קל שזה יגרור תקלה נלווית, ולכן בקריאה בודקים היטב את סוף הטווח.

שלוש הצורות של PERFORMתרשים שמראה של-PERFORM יש out-of-line שקורא פסקה או section וחוזר, inline שכותב בלוק במקום, ובקוד ישן גם ציון טווח עם THRU שבו תוספת פסקה באמצע עלולה לגרור תקלה נלווית.מוצאים PERFORMout-of-line שקורא פסקהinline שכתוב במקוםציון טווח עם THRUחובה לבדוק את סוף הטווח

איור 14: לפי צורת ה-PERFORM, יעד החזרה והטווח שצריך לעקוב אחריהם משתנים.

6.2 IF /‏ EVALUATE / תחום

הסתעפות בתנאי מבוססת בעיקר על IF. ‏EVALUATE דומה מאוד לתחושה של switch/case.

מה שצריך לשים לב אליו הוא איך התחום נגמר.12

  • END-IF
  • END-PERFORM
  • END-READ

קוד עם סיום מפורש כאלה עדיין קל יחסית לקריאה.

הבעיה היא קוד ישן. ב-COBOL, . פועל כ-scope terminator משתמע, וסוגר בבת אחת את כל המשפטים שעוד לא נסגרו.12

כלומר, עם נקודה אחת בלבד,

  • עד איפה IF
  • עד איפה PERFORM
  • איפה עוברים ל-sentence הבא

הכול משתנה.

בנוסף, NEXT SENTENCE הוא לא זהה ל-CONTINUE. ‏NEXT SENTENCE מתקדם אל אחרי הנקודה הבאה, ולכן לפי מיקום ה-. שבא אחריה, יעד הקפיצה משתנה.12

כשקוראים COBOL ישנה, נכון בערך לא להסתכל על סוף שורה, אלא על הנקודה.

המשקל של הנקודהתרשים שמראה שקוד עם סיום מפורש כמו END-IF קל יותר לקריאה, אבל בקוד ישן הנקודה פועלת כ-scope terminator משתמע שסוגר בבת אחת משפטים שעוד לא נסגרו, ולכן מיקום נקודה אחת משנה את הטווח של IF או PERFORM.יש END-IF וכדומהקוד ישן בלי זהיש סיום מפורש?הטווח קל לקריאההנקודה היא סיום משתמעמיקום אחד משנה את הטווחמסתכלים על הנקודה ולא על סוף השורה

איור 15: זרימת הבקרה בקוד ישן נמצאת בשליטת מיקום הנקודות.

6.3 READ /‏ WRITE /‏ CALL

אלה הנפוצים ב-COBOL עסקי.

  • READ
  • WRITE
  • REWRITE
  • START
  • CALL

בפרט READ ... AT END ... הוא הדרך המלכותית.

       READ IN-FILE
           AT END
               SET EOF TO TRUE
           NOT AT END
               PERFORM PROCESS-REC
       END-READ

אם יש CALL 'SUBPGM' USING ..., זה קופץ לתכנית אחרת. במקרה כזה, אם מסתכלים על LINKAGE SECTION ועל PROCEDURE DIVISION USING של הצד הנקרא, רואים די ברור את צורת ההעברה.

איך עוקבים כשמוצאים CALLתרשים שמראה שאם יש CALL, זה קופץ לתכנית אחרת, ואם מסתכלים על ה-LINKAGE SECTION של הצד הנקרא ועל ה-USING שלו, רואים את צורת העברת הארגומנטים.מוצאים CALLקופץ לתכנית אחרתמסתכלים על LINKAGE SECTION של הנקראה-USING מראה את צורת ההעברה

איור 16: משמעות הקריאה נקראת יחד עם כניסת הצד הנקרא.

7. מה שנמצא מחוץ ל-COBOL

יש הרבה מקרים שבהם ה-COBOL עצמו לא מכיל את כל העולם.

  • הגדרת קובץ
  • סביבת הרצה
  • חיבור ל-DB
  • הקשר טרנזקציה
  • בקרת job

כי אלה מחולקים החוצה.

לפחות אלה כדאי לתפוס כדי שהקריאה תהיה קלה יותר.

קובץ ו-FILE STATUS

קוראים יחד את FILE-CONTROL ב-ENVIRONMENT DIVISION ואת FILE SECTION /‏ FD ב-DATA DIVISION.13

       SELECT IN-FILE ASSIGN TO ...
           FILE STATUS IS WS-FS.

       FD  IN-FILE.
       01  IN-REC.
           05 ...

אם יש FILE STATUS, נכנס לשם קוד תוצאה אחרי כל קלט/פלט. בקריאת תקלות קובץ או בדיקת EOF, בלי להסתכל על זה לא מתחילים בכלל.14

הגדרת קובץ נקראת יחדתרשים שמראה ש-SELECT תחת FILE-CONTROL ו-FD תחת FILE SECTION נקראים יחד כהגדרת קובץ אחת, ואם יש FILE STATUS נכנס לשם קוד תוצאה אחרי כל קלט/פלט, שמשמש נקודת מוצא לקריאת תקלה ובדיקת EOF.SELECT תחת FILE-CONTROLיחד - הגדרת קובץ אחתFD תחת FILE SECTIONFILE STATUS מקבל קוד תוצאהנקודת מוצא לקריאת תקלה ו-EOF

איור 17: צורת הקובץ מחולקת לכתיבה בשני DIVISION.

EXEC SQL

אם זה מופיע, זה SQL משובץ.

       EXEC SQL
           SELECT ...
       END-EXEC.

במקרה כזה, ה-COBOL הוא “כלי קיבול למשתני host”, ותנאי השליפה או יעד העדכון האמיתיים נמצאים בצד ה-SQL. לכן, לקרוא את תוכן ה-EXEC SQL כ-SQL רגיל זו הדרך הקצרה.

EXEC CICS

אם זה מופיע, זה הקשר טרנזקציה של CICS.15

       EXEC CICS
           RECEIVE MAP(...)
       END-EXEC.

ברגע הזה, זה כבר לא סתם קריאת batch. נדרש לקרוא כולל הקשר חיצוני - מסך, טרנזקציה, קוד תגובה, COMMAREA.

JCL או הגדרות הרצה

ב-mainframe batch, לא נדיר שאיזה dataset בפועל מוקצה או באיזה סדר ה-job זורם נמצא מחוץ לקוד ה-COBOL. כשמסתכלים רק על הקוד ולא רואים “איפה הקובץ הזה נמצא”, זה לא בהכרח בעיה בקוד, אלא לעיתים סתם שהטווח שרואים עדיין לא מספיק.

העולם שמחוץ לקודתרשים שמראה שאם מופיע EXEC SQL, תנאי השליפה בפועל נמצאים בצד ה-SQL, אם מופיע EXEC CICS, ההקשר החיצוני כולל מסך וטרנזקציה, וב-mainframe batch הקצאת dataset וזרימת job נמצאים ב-JCL - כלומר יש עולם מחוץ לקוד ה-COBOL.EXEC SQLמסתכלים גם מחוץ לקודEXEC CICSJCL או הגדרות הרצהתנאי SQL, הקשר מסך, זרימת job

איור 18: לפעמים אי-ההבנה היא לא באשמת הקוד, אלא רק כי הטווח שרואים צר מדי.

הבדל בין מערכות (מהדרים)

המאמר הזה נכתב מתוך התייחסות למשפחת IBM, אבל בפועל אפשר להיתקל גם ב-Micro Focus, או COBOL על Linux / Windows. השלד משותף, ולכן אופן הקריאה לא משתנה, אבל יש נקודות קבועות שבהן “אותה כתיבה, תוצאה שונה”, ולכן כדאי לתפוס אותן מראש כדי לא להיכשל.

מה בודקים משפחת z/OS (‏IBM Enterprise COBOL) משפחת open (‏Micro Focus, גרסת Linux / Windows וכדומה)
קידוד תווים מניח EBCDIC6 מניח ASCII6
פורמט ייחוס פורמט fixed הוא ברירת המחדל המסורתית. אפשר לבחור גם free1 יש גם fixed וגם free, מה ברירת המחדל תלוי בהגדרת הבנייה1
איך מחפשים copybook ציון ספרייה ציון נתיב חיפוש דרך אפשרות מהדר
דיאלקט יש אפשרות שמחליפה “לאיזו מערכת להתאים”

מה שמשפיע במיוחד הוא קידוד התווים. גם באותו PIC X(10), אם קובץ שנכתב ב-z/OS נקרא ישירות בצד Windows, אפילו הספרות הופכות לערכי בייט שונים. הרבה מהמקרים שבהם “אחרי ההעברה הכול הפך לג’יבריש” נובעים מזה, וזו בעיה נפרדת מהנושא של COMP-3.

עוד מקום שנוטה להבדל הוא הייצוג הפנימי של מספרים. ב-IBM Enterprise COBOL, ב-BINARY /‏ COMP-4 הקיטום מתבצע לפי מספר הספרות שכתוב ב-PICTURE, לעומת COMP-5 שבו הערך נשמר עד קיבולת בינארית טבעית של 2 /‏ 4 /‏ 8 בייטים, וגם הקיטום מתבצע לפי גודל הבינארי.16 כלומר PIC S9(4) COMP ו-PIC S9(4) COMP-5 נראים דומים, אבל התקרה של הערך שנכנס שונה. אם COMP-5 מופיע בקוד שמחליף ערכים בינאריים ישירות עם מערכת אחרת, כדאי לקרוא את זה ככתוב בכוונה.

הצעדים הקצרים ביותר להשוואה מול הסביבה שלכם הם אלה.

  1. פותחים קודם את הגדרת הבנייה (makefile,‏ JCL, הגדרות פרויקט). לפני הקוד, אפשר לדעת באיזו מערכת ובאילו אפשרויות זה מקומפל.
  2. קובעים את פורמט הייחוס (fixed / free). אם טועים כאן ומעצבים בעורך, זה נשבר.
  3. קובעים את קידוד התווים. לפי EBCDIC או ASCII, אופן קריאת ה-dump משתנה.
  4. מסמנים פריטים ממשפחת COMP. כמעט תמיד כאן מופיעים הבדלי מערכת.
הצעדים הקצרים ביותר להשוואה מול הסביבה שלכםתרשים שמראה שקודם פותחים את הגדרת הבנייה כדי לדעת באיזו מערכת ובאילו אפשרויות מקומפלים, קובעים את פורמט הייחוס fixed או free, קובעים את קידוד התווים EBCDIC או ASCII, ומסמנים פריטים ממשפחת COMP שבהם נוטים להופיע הבדלי מערכת.פותחים קודם הגדרת בנייהקובעים פורמט ייחוסקובעים קידוד תוויםמסמנים פריטים ממשפחת COMP

איור 19: ב-4 הצעדים האלה לפני קריאת הקוד, נמנעים מתקלות הבדלי מערכת.

8. סדר הקריאה המינימלי

כשפתאום נאלצים לקרוא COBOL, הסדר הבא בטוח.

  1. עוברים על כל ה-COPY אם אפשר לפתוח copybook, פותחים. אם לא, מחפשים listing או מקור אחרי הרחבה
  2. אוספים הגדרות רשומה ברמת 01 מרכזים רשימה של הרמה העליונה של FILE SECTION,‏ WORKING-STORAGE,‏ LINKAGE SECTION
  3. קוראים PIC ו-USAGE מזהים סכום, תאריך, מספר פריטים, קוד, דגל
  4. מחפשים READ /‏ WRITE /‏ REWRITE /‏ CALL /‏ EXEC SQL /‏ EXEC CICS תופסים קודם קלט/פלט וגבול חיצוני
  5. עוקבים רק אחרי המסלול הראשי הראשון עוקבים אחרי שרשרת ה-PERFORM מתחילת PROCEDURE DIVISION
  6. מסתכלים על 88 ופריטי status המשמעות של EOF, תקין/לא תקין, קוד סוג נעשית קלה יותר לקריאה
  7. מסמנים REDEFINES /‏ OCCURS DEPENDING ON /‏ COMP-3 אלה תמיד ישפיעו בהמשך, ולכן מסמנים אותם מראש כחומר מסוכן
  8. בקובץ, מסתכלים על FILE STATUS זה מקטין משמעותית טעויות קריאה בתחום שגיאות קלט/פלט

בסדר הזה, לא צריך לקרוא בעיון את כל הטקסט מיד. עדיף לתפוס קודם את שלוש הנקודות רשומה, גבול חיצוני, מסלול ראשי, ורק אז לרדת לפרטים - זה הרבה יותר קל מלנסות להבין 100% מההתחלה.

סדר קריאה בטוחתרשים שמראה שעוברים על ה-COPY ובודקים את ה-copybook, מרכזים רשימת הגדרות רשומה ברמת 01, קוראים את צורת הפריטים דרך PIC ו-USAGE, מחפשים קלט/פלט וגבול חיצוני, עוקבים אחרי שרשרת PERFORM ראשית מ-PROCEDURE DIVISION, ומסמנים חומר מסוכן.עוברים על כל ה-COPYמרכזים רשימת הגדרות ברמת 01קוראים צורה דרך PIC ו-USAGEמחפשים קלט/פלט וגבול חיצוניעוקבים אחרי שרשרת PERFORM ראשיתמסמנים חומר מסוכן

איור 20: לא קריאה מלאה בעיון, אלא מילוי מבחוץ פנימה בסדר הזה.

8.1 תרגול: קוראים הגדרת רשומה זו

הסבר על אופן הקריאה בלבד לא נטמע, ולכן נכניס רשומה קטנה אחת. קודם ענו בעצמכם, ואז הסתכלו על הפתרון למטה.

       01  CUST-REC.
           05  CUST-ID          PIC X(8).
           05  CUST-NAME        PIC X(20).
           05  CUST-KBN         PIC X.
               88  CUST-NORMAL  VALUE '0'.
               88  CUST-VIP     VALUE '1'.
           05  CUST-BALANCE     PIC S9(7)V99 COMP-3.
           05  CUST-HIST OCCURS 3 TIMES.
               10  HIST-DATE    PIC 9(8).
               10  HIST-AMOUNT  PIC S9(5)V99 COMP-3.
           05  FILLER           PIC X(4).

שאלות

  1. כמה בייטים CUST-REC בסך הכול?
  2. מאיזה בייט, נספר מתחילת הרשומה, מתחיל CUST-BALANCE?
  3. מאיזה בייט מתחיל HIST-AMOUNT של הרשומה השנייה, נספר מתחילת הרשומה?
  4. כש-CUST-KBN מכיל '1', איזה שם תנאי הופך לנכון?
  5. אם פותחים את הקובץ הזה בעורך טקסט, איזה פריט נראה שבור?
  6. ציינו שני דברים שאי אפשר לדעת רק מההגדרה הזו.

פתרונות

  1. 74 בייטים. הפירוט הוא כך.

    פריט חישוב מספר בייטים
    CUST-ID X(8) 8
    CUST-NAME X(20) 20
    CUST-KBN X 1
    CUST-BALANCE 9 ספרות ב-COMP-3 5
    CUST-HIST (8 + 4) × 3 פעמים 36
    FILLER X(4) 4
    סך הכול   74

    רמת 88 היא שם תנאי, ולכן לא צורכת בייט. זו טעות נפוצה לספור אותה בטעות. ל-FILLER אין שם, אבל 4 הבייטים בהחלט קיימים.

  2. מהבייט ה-30. לפניו יש 8 + 20 + 1 = 29 בייטים, והוא מתחיל מיד אחריהם.

  3. מהבייט ה-55. CUST-HIST מתחיל בבייט ה-35, ופריט אחד הוא 12 בייט. פריט 1 הוא בייטים 35-46, פריט 2 הוא בייטים 47-58. מתוכם 8 הבייטים הראשונים הם HIST-DATE, ולכן HIST-AMOUNT מתחיל בבייט ה-55.

  4. CUST-VIP. אין שטח נפרד בשם CUST-VIP, אלא רק שכש-CUST-KBN הוא '1', אפשר לקרוא לו בשם הזה.

  5. CUST-BALANCE ו-HIST-AMOUNT. שניהם COMP-3, ולכן קריאה כתו נותנת רצף חסר משמעות. ‏HIST-DATE הוא PIC 9(8) מסוג DISPLAY, ולכן בסביבת ASCII אפשר לקרוא אותו כספרות כמו 20260317. עם זאת, בסביבת EBCDIC, גם אם זה נראה כספרות, ערך הבייט שונה מ-ASCII.

  6. לדוגמה, דברים כמו אלה.

    • האם ההגדרה הזו עצמה מוכנסת דרך COPY. בלי לבדוק את ה-copybook, אי אפשר לדעת אם זו הגרסה שבאמת בשימוש.
    • האם קידוד הקובץ הוא EBCDIC או ASCII. המראה של PIC X ו-PIC 9 DISPLAY משתנה.
    • האם יש תפעול שבו CUST-KBN מקבל ערך שאינו '0' או '1'. מוגדרים רק שני שמות תנאי, אבל זה לא מבטיח שלא יגיע ערך אחר.
    • תכונות הקובץ עצמו (אורך רשומה, האם משתנה אורך, FILE STATUS). את זה אי אפשר לדעת בלי לבדוק את ENVIRONMENT DIVISION ואת FD.

אם טעיתם בשאלות 1 ו-3, חזרו לטבלה במספר ספרות מול מספר בייטים בסעיף 5.3. טעויות קריאה ב-COBOL, ברוב המקרים, מתחילות בדיוק שם.

9. מוקשים נפוצים

לסיום, נרכז את המקומות שמתחילים כמעט תמיד נתקעים בהם בסבירות גבוהה.

חושבים על REDEFINES כ”משתנה אחר”

לא נכון. זה קורא לאותו שטח בצורה אחרת. אם משנים צד אחד, גם המראה של הצד השני משתנה.7

חושבים על 88 כ-bool עצמאי

לא נכון. זה רק שם שניתן לערך של הפריט שקדם לו ישירות. SET WS-OK TO TRUE מכניס מאחורי הקלעים את הערך המתאים לפריט הבסיס.3

מתעלמים מ-COPY וקוראים רק את הגוף

הקובץ הפתוח הוא עדיין רק חצי מהתמונה. זה רגיל שהגדרת שדות, דגלים משותפים, ו-host variable נמצאים בכמות גדולה מבחוץ.9

חושבים על MOVE כהשמה פשוטה

MOVE הוא לא סתם memcpy. בהתאם לטיפוס הצד המקבל, יכולים להתרחש המרה, יישור ספרות, מילוי אפסים, קיטום, עריכה או ביטול עריכה.17

מזלזלים בהשפעה של ה-.

ה-. ב-COBOL כבד יותר משנדמה. בקוד ישן בלי סיום מפורש, אם טועים בעד איפה הנקודה הזו סוגרת, קוראים לא נכון את זרימת הבקרה.12

חושבים ש-packed decimal או EBCDIC הם “מוג’יבאקה”

זה לא בהכרח שבור. לפעמים זה פשוט לא מחרוזת מלכתחילה, או שזה לא ASCII.46

חושבים שמה שאחרי OCCURS DEPENDING ON הוא מיקום קבוע

הפריטים שאחרי טבלה באורך משתנה עשויים לזוז במיקום לפי הערך. אם קוראים בראש של אורך קבוע, כל חישוב ההיסט זז.8

10. טבלת עזר מהירה ראשונה

מילה שנמצאה מה בודקים תחילה
01 הרמה העליונה של רשומה או קבוצה. תופסים מכאן את התמונה הכללית
88 שם משמעות של דגל או קוד מצב. מפתח לקריאת הסתעפות
PIC X(...) פריט תווים
PIC 9(...) /‏ S9(...)V... פריט מספרי. בודקים מספר ספרות ומיקום העשרוני
COMP binary
COMP-3 packed decimal. סיכוי גבוה לסכום או מספר פריטים
REDEFINES פרשנות אחרת לאותו שטח
OCCURS מערך / table
OCCURS DEPENDING ON אורך משתנה. שימו לב גם למיקום הבא
FILLER אין שם, אבל יש אורך
COPY בלי לראות את ה-copybook, לא רואים את הצורה המלאה
PERFORM שלד המסלול הראשי
READ /‏ WRITE /‏ REWRITE קלט/פלט לקובץ
EXEC SQL עיבוד DB
EXEC CICS עיבוד טרנזקציה
FILE STATUS קוד תוצאה של קלט/פלט

11. סיכום

‏COBOL לא קשה כי היא ישנה. הגדרת נתונים, קובץ חיצוני, והקשר הרצה קשורים חזק זה בזה, ולכן רק הכניסה הראשונה קשה לראייה.

אם מסכמים שוב את הסט המינימלי לקריאה, זה כך.

  • תופסים את המפה עם DIVISION
  • קוראים קודם את DATA DIVISION
  • קוראים את צורת הפריט עם PIC ו-USAGE
  • מסמנים COMP-3,‏ REDEFINES,‏ OCCURS,‏ 88,‏ COPY
  • עוקבים אחרי PERFORM,‏ READ,‏ WRITE,‏ CALL
  • תופסים גבול חיצוני עם FILE STATUS,‏ EXEC SQL,‏ EXEC CICS
  • לא מזלזלים באיך ה-. פועל

ברגע שזה נראה, COBOL הופכת מ”קסם עתיק מסתורי” ל”שפת עיבוד רשומות”. טכנולוגיה ישנה לא מפחידה כי השם ישן, אלא רק אם טועים בקנה המידה הראשוני שבו מסתכלים, זה פתאום נעשה קשה להבנה. אם קנה המידה של המפה מתאים, זה נקרא באופן מפתיע רגיל.

קוראים בהתאמת קנה מידהתרשים שמראה שאם תופסים את המפה עם DIVISION, קוראים קודם את DATA DIVISION ותופסים צורה, עוקבים אחרי הזרימה עם PERFORM וקלט/פלט, ותופסים את הגבול החיצוני עם FILE STATUS ו-EXEC SQL ו-EXEC CICS, COBOL הופכת לשפת עיבוד רשומות רגילה.תופסים מפה עם DIVISIONקוראים צורה עם DATA DIVISIONעוקבים אחרי הזרימה עם PERFORM וקלט/פלטתופסים גבול חיצוניהקסם העתיק הופך לשפת עיבוד רשומות

איור 21: זהות הקושי היא לא גיל השפה, אלא בחירת קנה המידה הראשוני.

12. מקורות

אלה המקורות העיקריים שהוזכרו בגוף המאמר. המספרים המוגבהים בגוף המאמר הם קישורים לרשימה הזו, ומהחץ בסוף כל פריט אפשר לחזור למקום המקורי.

מאמרים עדכניים עם אותן תגיות, להעמקה בנושאים קרובים.

העמודים האלה ממקמים את הנושא בהקשר רחב יותר של שירותים והחלטות.

המאמר קשור ישירות לשירותים הבאים.

שאלות נפוצות

שאלות נפוצות בפניות בנושא המאמר.

מאיפה כדאי להתחיל לקרוא קוד COBOL?
קריאה של PROCEDURE DIVISION בלבד נותנת רק חצי מהתמונה. COBOL היא, לפני שהיא שפת לוגיקה, שפה שמתמקדת חזק מאוד בהגדרת רשומות, ולכן קודם כל בודקים את DATA DIVISION. סדר קריאה בטוח: לעבור על כל ה-COPY ולבדוק את ה-copybook, לרכז רשימה של הגדרות הרשומה ברמה 01, לקרוא את צורת הפריטים דרך PIC ו-USAGE, לחפש READ,‏ WRITE,‏ CALL,‏ EXEC SQL,‏ EXEC CICS כדי לתפוס קלט/פלט וגבול חיצוני, ורק אז לעקוב אחרי שרשרת ה-PERFORM בתחילת PROCEDURE DIVISION כדי לתפוס את המסלול הראשי.
מה המשמעות של PIC S9(7)V99 COMP-3?
PIC מציין את צורת הפריט, ו-USAGE מציין באיזה ייצוג הוא נשמר. S9(7)V99 הוא מספר עם סימן, 7 ספרות שלמות + 2 ספרות עשרוניות, אבל ה-V הוא נקודה עשרונית לוגית בלבד - אין תו נקודה ממשי בנתונים. COMP-3 הוא packed decimal, ומופיע הרבה בפריטים של סכומים, מסים, מספר פריטים, ותעריפים. כשמסתכלים על זה כטקסט זה נראה שבור, וזה טבעי לגמרי, ולכן אסור להסתכל על dump בתחושה של CSV או UTF-8.
איך מבינים את רמת 88 ו-REDEFINES ב-COBOL?
רמה 88 היא לא משתנה בוליאני עצמאי, אלא שם תנאי (condition-name) שנותנים לערך של הפריט שקדם לו ישירות. SET WS-OK TO TRUE מכניס מאחורי הקלעים את הערך המתאים לפריט הבסיס. REDEFINES הוא מנגנון שמסתכל על אותו שטח זיכרון בצורה אחרת - זה לא העתקה, אלא תחושה קרובה ל-union בשפות מסוג C. אם משנים צד אחד, גם המראה של הצד השני משתנה, ולכן זה מופיע הרבה בכתיבה שמזהה את אותו שטח לפי סוג הרשומה.
מה עושים כשיש הרבה משפטי COPY ולא רואים את התמונה השלמה?
COPY הוא include בזמן קומפילציה, ולכן ייתכן שהקובץ הפתוח כרגע עדיין לא הצורה המלאה. די נפוץ שהגדרות רשומה, דגלים משותפים, host variable ל-SQL, וממשקים חיצוניים דחוסים בתוך ה-copybook. כשקשה לקרוא, מהיר יותר לבדוק אם אפשר לראות את המקור אחרי הרחבה, או את ה-compiler listing, ול-IBM Enterprise COBOL יש גם אפשרות בשם MDECK שמוציאה את מקור הקלט אחרי עיבוד הספרייה.

פרופיל הכותב

עמוד היכרות עם כותב המאמר.

Go Komura

מנהל KomuraSoft LLC

מתמחה בפיתוח תוכנה עבור Windows, ייעוץ טכני וחקירת תקלות, בעיקר בפרויקטים עם מערכות קיימות ובאגים שקשה לשחזר.

קישורים ציבוריים

חזרה לבלוג