Technical specifications

From Webhuis wiki
Revision as of 16:44, 25 March 2026 by Martin (talk | contribs) (Created page with "<span id="technical-specification"></span> = Technical Specification = '''Project:''' pgcobol — Prime Numbers Application<br /> '''Version:''' 1.0 (reverse-engineered)<br /> '''Date:''' 2026-03-17 ----- <span id="technology-stack"></span> == 1. Technology Stack == {| !width="50%"| Component !width="50%"| Technology |- | Runtime | GnuCOBOL 4.0, Linux |- | SQL pre-processor | GixSQL (translates EXEC SQL … END-EXEC to GIXSQLExec calls) |- | Database server | Postgr...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Technical Specification[edit]

Project: pgcobol — Prime Numbers Application
Version: 1.0 (reverse-engineered)
Date: 2026-03-17



1. Technology Stack[edit]

Component Technology
Runtime GnuCOBOL 4.0, Linux
SQL pre-processor GixSQL (translates EXEC SQL … END-EXEC to GIXSQLExec calls)
Database server PostgreSQL 11.22, localhost:5432
Database schema primes
Credentials user primes_user, password pr1mes_user (hard-coded)
Output file primes.prt — line-sequential, 132 chars/record, linage 56
Console GnuCOBOL special-name scherm mapped to system console



2. Component Architecture[edit]

┌─────────────────────────────────────────────────────┐
│                   primesmain                        │  ← Entry point / orchestrator
│  WORKING-STORAGE: commandline-args                  │
│  COPY: primes-session, primes-ui                    │
└────────────┬────────────────────────────────────────┘
             │ CALL "primesgen" USING primes-session
             ▼
┌─────────────────────────────────────────────────────┐
│                   primesgen                         │  ← Business logic / sieve engine
│  WORKING-STORAGE: primes (local), printer           │
│  COPY (linkage): primes-session                     │
│  COPY (local):   primes-ui, primes-dal              │
└────────┬──────────────────────┬─────────────────────┘
         │ CALL "primes"        │ CALL "primesui"
         │ USING primes-dal     │ USING primes-ui
         ▼                      ▼
┌──────────────────┐   ┌──────────────────────────────┐
│     primes       │   │          primesui             │  ← Presentation / output
│  (DAL + SQL)     │   │  FILE: fprinter → primes.prt  │
│  EXEC SQL via    │   │  WORKING-STORAGE: primes-table│
│  GixSQL          │   │  COPY (linkage): primes-ui    │
└──────────────────┘   └──────────────────────────────┘
         │
         ▼
┌──────────────────┐
│   PostgreSQL     │
│  schema: primes  │
│  table:  primes  │
└──────────────────┘

3. Inter-Tier Interface Contracts[edit]

All communication between tiers uses method-dispatch over shared copybook control blocks. A caller sets a verb string in the methods field, invokes the subprogram, and reads the result code on return.

3.1 Session tier — primes-session[edit]

primes-session
  methods          PIC X(32)          verb sent by caller
    88 report-primes   "report"
    88 generate-primes "generate"
    88 start-primes    "start"
    88 stop-primes     "stop"
    88 invalid-method  "bad"
  session-result   PIC 9(2)           set by callee
    88 session-method-ok   0
    88 session-method-nok  1
    88 session-method-eof  9

3.2 DAL tier — primes-dal[edit]

primes-dal
  dal-methods      PIC X(32)          verb sent by caller
    88 next-prime      "next-prime"
    88 next-divider    "next-divider"
    88 write-prime     "write"
    88 db-cursor       "cursor"
    88 db-connect      "connect"
    88 db-disconnect   "disconnect"
  primes-data                         data payload (one row)
    primes-sequence  PIC 9(9)         ident from DB
    prime-number     PIC 9(9)         prime value from DB
  dal-result       PIC 9(2)           set by callee
    88 dal-method-ok   0
    88 dal-method-nok  1
    88 dal-method-eof  99

3.3 UI tier — primes-ui[edit]

primes-ui
  ui-methods       PIC X(32)          verb sent by caller
    88 start-ui        "start"
    88 write-ui        "write"
    88 message-ui      "log-message"
    88 stop-ui         "stop"
  process-message                     structured console message
    program-name     PIC X(20)
    program-paragraph PIC X(20)
    program-message  PIC X(92)
  u-primes                            one prime row for print output
    u-sequence       PIC 9(9)
    u-number         PIC 9(9)
  ui-method-result PIC 9(2)           set by callee
    88 ui-method-ok    0
    88 ui-method-nok   1

4. Pseudocode[edit]

4.1 primesmain[edit]

PROGRAM primesmain
  INPUT: command-line argument → commandline-args

  CALL primesui("start")
  IF ui-method-ok THEN
    LOG "UI initialisation succeeded."
    LOG commandline-args
  ELSE
    DISPLAY emergency message on console
    STOP

  CASE commandline-args OF

    "report":
      LOG "Primes report generation starts."
      SET methods = "report"
      CALL primesgen(primes-session)       -- report flow

    "generate":
      LOG "Primes generation starts."
      SET methods = "generate"
      -- NOTE: CALL primesgen commented out in current source

    OTHER:
      LOG "Bad parameter, program initialisation failed."
      CALL primesui("stop")
      STOP

  END CASE

  LOG "Primes run complete, program stops."
  CALL primesui("stop")
  STOP
END PROGRAM

4.2 primesgen — report path[edit]

PROCEDURE report-path
  CALL primes-dal("connect")
  IF dal-method-ok THEN
    LOG "Database initialisation succeeded."
  ELSE
    LOG "Database initialisation failed."
    SET session-result = 1
    RETURN

  CALL primes-dal("cursor")           -- START TRANSACTION + OPEN primescursor
  IF dal-method-ok THEN
    LOG "Cursor initialisation succeeded."
  ELSE
    LOG "Cursor initialisation failed."
    SET session-result = 1
    RETURN

  FETCH first row via primes-dal("next-prime")
  IF fetch fails THEN
    LOG "Fetch first row nok."
    SET dal-result = 1

  LOOP UNTIL session-method-eof
    SET u-sequence = primes-sequence
    SET u-number   = prime-number
    CALL primesui("write")            -- accumulate into print buffer
    CALL primes-dal("next-prime")     -- advance cursor
  END LOOP
END PROCEDURE

4.3 primesgen — generate path[edit]

PROCEDURE generate-path
  CALL primes-dal("connect")
  IF dal-method-ok THEN
    SET test-divider   = 2
    SET old-ident      = 1
    SET test-number    = 3
    SET test-number-sqr = SQRT(3)
    LOG "Database initialisation succeeded."
  ELSE
    LOG "Database initialisation failed."
    SET session-result = 1
    RETURN

  LOOP UNTIL test-number = 999,999,999

    DIVIDE test-number BY test-divider → test-quot REMAINDER test-rest

    CASE OF
      test-rest = 0:
        -- test-number is composite; move to next candidate
        ADD 2 TO test-number
        SET test-number-sqr = SQRT(test-number)
        SET old-ident = 1
        FETCH divider[old-ident+1] via primes-dal("next-divider")

      test-divider > test-number-sqr:
        -- no factor found up to sqrt; test-number is prime
        CALL primes-dal("write")      -- INSERT INTO primes
        CALL primesui("write")        -- add to print buffer
        ADD 2 TO test-number
        SET test-number-sqr = SQRT(test-number)
        SET old-ident = 1
        FETCH divider[old-ident+1] via primes-dal("next-divider")

      OTHERWISE:
        -- try next divider from DB
        FETCH divider[old-ident+1] via primes-dal("next-divider")
    END CASE

  END LOOP
END PROCEDURE

4.4 primes (DAL)[edit]

PROGRAM primes
  LINKAGE: primes-dal

  CASE dal-methods OF
    "connect":
      EXEC SQL CONNECT TO datasrc AS primes USER dbusr USING dbpwd
      IF SQLCODE = 0 THEN dal-result = 0 ELSE dal-result = 1

    "cursor":
      EXEC SQL AT primes START TRANSACTION
      IF SQLCODE = 0 THEN
        EXEC SQL OPEN primescursor
        IF SQLCODE = 0 THEN dal-result = 0 ELSE dal-result = 1
      ELSE dal-result = 1

    "next-prime":
      EXEC SQL FETCH primescursor INTO :primes-row
      IF SQLCODE = 0 THEN
        primes-sequence = r-ident
        prime-number    = r-prime
        dal-result = 0
      ELSE dal-result = 1

    "next-divider":
      new-ident = old-ident + 1
      EXEC SQL SELECT prime INTO :test-divider
               FROM primes WHERE ident = :new-ident
      old-ident = new-ident

    "write":
      EXEC SQL INSERT INTO primes (prime) VALUES (:prime)

    "disconnect":
      EXEC SQL CONNECT RESET primes
      IF SQLCODE = 0 THEN dal-result = 0 ELSE dal-result = 1

    OTHER:
      dal-result = 1
  END CASE
  EXIT PROGRAM
END PROGRAM

4.5 primesui[edit]

PROGRAM primesui
  LINKAGE: primes-ui

  CASE ui-methods OF
    "start":
      OPEN OUTPUT fprinter (primes.prt)
      IF file-status = "00" THEN
        ui-method-result = 0
        primes-idx = 1
      ELSE
        ui-method-result = 1

    "write":
      t-ident(primes-idx) = u-sequence
      t-prime(primes-idx) = u-number
      primes-idx = primes-idx + 1
      IF new-page THEN write heading + column header
      IF primes-idx = 7 THEN
        WRITE primes-table line to fprinter
        primes-idx = 1
      IF linage-counter = 53 THEN write footing, increment page

    "log-message":
      DISPLAY process-message ON CONSOLE

    "stop":
      LOOP writing zero rows UNTIL new-page   -- flush partial line
      CLOSE fprinter

  END CASE
  EXIT PROGRAM
END PROGRAM

5. Database Interface Specification[edit]

5.1 Connection[edit]

Parameter Value
Driver GixSQL pgsql
Host localhost
Port 5432
Database primes
Schema search path primes
Connection alias primes
User primes_user
Password pr1mes_user

5.2 SQL Statements[edit]

ID Statement Called from
S-01 CONNECT TO :DATASRC AS primes USER :DBUSR USING :DBPWD s00-connect
S-02 START TRANSACTION s01-cursor
S-03 DECLARE primescursor CURSOR FOR SELECT * FROM primes compile-time
S-04 OPEN primescursor s01-cursor
S-05 FETCH primescursor INTO :primes-row s02-fetch
S-06 SELECT prime INTO :test-divider FROM primes WHERE ident = :new-ident r81-get-next-divider
S-07 INSERT INTO primes (prime) VALUES (:prime) r83-write-prime
S-08 CONNECT RESET primes s99-disconnect

5.3 Error Handling[edit]

  • All SQL paths test SQLCODE = 0 for success.
  • On failure, a diagnostic string is moved to program-message and logged via primesui.
  • dal-result is set to 1 (nok) on SQL errors; callers check dal-method-ok before continuing.
  • No retry logic is implemented; errors cause the current operation to be skipped or the session to terminate.



6. Output File Specification[edit]

Property Value
Filename primes.prt
Organisation Line-sequential
Record length 132 characters
Linage 56 lines per page
Footing area 2 lines from bottom
Bottom margin 2 lines
Records per data line 6 primes (sequence + value pairs)
Page heading "primes overview" (col 1)
Column header "Sequence Prime" × 6 across
Page footing Spaces + "page: ZZZZ9" (right side)
EOP trigger linage-counter = 53



7. Known Defects and Limitations[edit]

ID Severity Description
D-01 High Generate loop (PERFORM r80-test-number) is commented out in primesmain; generation mode does not execute the sieve.
D-02 Medium Prime 2 is never seeded; generation starts at 3 with first divider = 2 retrieved from DB, but DB is empty at start of a fresh run.
D-03 Medium primes_cbsql.out shows disconnect using alias primesdb; primes.cbl uses alias primes — alias mismatch will cause runtime SQL error.
D-04 Low Database credentials are hard-coded in WORKING-STORAGE of primes.cbl.
D-05 Low No COMMIT after INSERT in r83-write-prime (statement is commented out); relies on PostgreSQL auto-commit or session-level transaction semantics.
D-06 Low Two almost-identical host-variable copybooks (primes-table.cpy vs primes_table.cpy) suggest unresolved refactoring.

Terug naar: Primes_programs_specifications | Cobol and PostgreSQL