*DECK DB$COPN 
USETEXT UTMPTTX 
USETEXT UTCITTX 
USETEXT UTCDFTX 
USETEXT CUGBATX 
      PROC DB$COPN(LFNSUBSC,LFNSCHEM,DATSCHEM,TIMSCHEM);
 #
  *   DB$COPN - OPEN SUBSCHEMA AND SCHEMA FILES  PAGE  1
  *   STEVEN P. LEVIN                            DATE  09/08/75 
  
  DC  PURPOSE 
  
      CALL DIRECTORY ACCESS ROUTINES TO OPEN THE SUBSCHEMA AND SCHEMA 
      DIRECTORY FILES AND TO SET DIRECTORY INFORMATION TABLE FIELDS.
  
  DC  ENTRY CONDITIONS
  
      THE PARAMETER LFNSUBSC IS THE SUBSCHEMA LOGICAL FILE NAME (LFN).
      THE PARAMETER LFNSCHEM IS THE SCHEMA LOGICAL FILE NAME (LFN). 
      THE PARAMETER DATSCHEM IS THE MD DATE OF CREATION OF THE SCHEMA.
      THE PARAMETER TIMSCHEM IS THE MD TIME OF CREATION OF THE SCHEMA.
      THE FOLLOWING COMMON ITEMS SHOULD HAVE BEEN GIVEN VALID VALUES: 
      DBPTADDR - DB PROC TABLE BLOCK ADDRESS OF WORD AFTER HEADER WORD
      NAMESCHE - BLANK-FILLED SCHEMA NAME 
      NAMESUBS - BLANK-FILLED SUBSCHEMA NAME
      THE SUBSCHEMA AND SCHEMA DIRECTORY FILES SHOULD BE AVAILABLE, 
      AND THE DATA BASE PROC BLOCK SHOULD CONTAIN AN MD DB PROC TABLE.
  
  DC  EXIT CONDITIONS 
  
      ON NORMAL RETURN, SUBSCHEMA AND SCHEMA DIRECTORY FILES WILL BE
      OPEN.  ARRAY SCCWDDIT (SBCWDDIT) WILL CONTAIN SCHEMA (SUBSCHEMA)
      CONTROL WORDS.  COMMON ITEMS WILL CONTAIN CONTROL WORD FIELDS.
      IF AN ERROR IS FOUND DURING DB$COPN PROCESSING, THE CST BUILDER 
      (AT LEAST) WILL BE ABORTED THROUGH A CALL TO THE MODULE DB$CERR.
  
  DC  CALLING ROUTINES
  
      DB$CBLD - CONDENSED SCHEMA/SUBSCHEMA TABLE BUILDER MAIN MODULE
  
  DC  CALLED ROUTINES 
  
      DE$OPSB - DIRECTORY ACCESS ROUTINE TO OPEN THE SUBSCHEMA FILE 
      DE$OPSC - DIRECTORY ACCESS ROUTINE TO OPEN THE SCHEMA FILE
      DB$CERR - ERROR MESSAGE AND RETURN HANDLER FOR FATAL ERRORS 
      DB$CESB - SUBSCHEMA FILE CYBER RECORD MANAGER ERROR HANDLER 
      DB$CESC - SCHEMA FILE CYBER RECORD MANAGER (CRM) ERROR HANDLER
      DB$CFIL - FUNCTION TO BLANK OR BINARY ZERO CHARACTER FILL STRING
      DB$UADR - UPDATE MANAGED MEMORY BLOCK FIRST-USABLE-ADDRESS WORDS
  
  DC  NON-LOCAL VARIABLES 
  
      CURSCRAT - CURRENT SCRATCH NAME (USED AS A TEMPORARY AT TIMES)
      OUTWARN  - TRUE IFF WARNING FOR SCHEMA DATES OR TIMES DIFFERENT 
      SBCHKSUM - SUBSCHEMA DIRECTORY CHECKSUM DERIVED BY DDL ALGORITHM
      SBCKSMWA - SUBSCHEMA CHECKSUM LIST FIRST WORD ADDRESS 
      SBDATASV - SUBSCHEMA DATA NAME SAVE BUFFER LENGTH IN WORDS
      SBFIRARE - SUBSCHEMA FIRST AREA ENTRY WORD ADDRESS
      SBFIRCAP - SUBSCHEMA FIRST MAPPING CAPSULE WORD ADDRESS 
      SBFIRREC - SUBSCHEMA FIRST RECORD ENTRY WORD ADDRESS
      SBFIRREL - SUBSCHEMA FIRST RELATION ENTRY WORD ADDRESS
      SBFWADDR - SUBSCHEMA FIRST WORD ADDRESS IN FILE 
      SBJULIAN - SUBSCHEMA JULIAN DATE OF CREATION (FORMAT IS YYDDD)
      SBMAXCAP - SUBSCHEMA MAXIMUM MAPPING CAPSULE LENGTH IN WORDS
      SBMAXENT - SUBSCHEMA MAXIMUM SUBENTRY LENGTH IN WORDS 
      SBMAXREC - SUBSCHEMA MAXIMUM RECORD LENGTH IN CHARACTERS
      SBNUMARE - SUBSCHEMA TOTAL NUMBER OF AREA ENTRIES 
      SBNUMREC - SUBSCHEMA TOTAL NUMBER OF RECORD ENTRIES 
      SBNUMREL - SUBSCHEMA TOTAL NUMBER OF RELATION ENTRIES 
      SBTIME   - SUBSCHEMA TIME OF CREATION (FORMAT IS HH.MM DISPLAY) 
      SCCKSMWA - SCHEMA CHECKSUM LIST FIRST WORD ADDRESS
      SCMAXENT - SCHEMA MAXIMUM SUBENTRY LENGTH IN WORDS
      SCNUMARE - SCHEMA TOTAL NUMBER OF AREA ENTRIES
      SCNUMCON - SCHEMA TOTAL NUMBER OF CONSTRAINT ENTRIES
      SCNUMDBP - SCHEMA TOTAL NUMBER OF DATA BASE PROCEDURES
      SCNUMREL - SCHEMA TOTAL NUMBER OF RELATION ENTRIES
      STATSCHE - SCHEMA DIRECTORY FILE STATUS 
      STATSUBS - SUBSCHEMA DIRECTORY FILE STATUS
      SBCWDDIT AND SCCWDDIT ARRAYS WILL CONTAIN DIRECTORY CONTROL WDS.
  
  DC  DESCRIPTION 
  
      CALL DE$OPSB TO OPEN THE SUBSCHEMA FILE AND TO SET UP THE DIT.
      IF THERE ARE SUBSCHEMA OPEN OR CONTROL WORD FIELD ERRORS, ABORT.
      MOVE FIELDS FROM THE SUBSCHEMA CONTROL WORDS TO ITEMS IN COMMON.
      CALL DE$OPSC TO OPEN THE SCHEMA FILE AND TO SET UP THE DIT. 
      IF THERE ARE SCHEMA OPEN OR CONTROL WORD FIELD ERRORS, ABORT. 
      MOVE MORE FIELDS FROM THE SCHEMA CONTROL WORDS TO COMMON ITEMS. 
      RETURN WITH THE SUBSCHEMA AND SCHEMA DIRECTORY FILES NOW OPEN.
 #
        CONTROL EJECT;
  
        BEGIN                # DB$COPN #
  
# THE FOLLOWING ARE FORMAL PARAMETERS IN THE ORDER THEY ARE PASSED #
  
        ITEM LFNSUBSC C(7);  # LOGICAL FILE NAME (LFN) OF SUBSCHEMA # 
        ITEM LFNSCHEM C(7);  # LOGICAL FILE NAME (LFN) OF THE SCHEMA #
        ITEM DATSCHEM U;     # MD FILE DATE OF CREATION OF THE SCHEMA#
        ITEM TIMSCHEM U;     # MD FILE TIME OF CREATION OF THE SCHEMA#
  
# THE FOLLOWING ARE EXTERNALLY REFERENCED PROCEDURES AND FUNCTIONS #
  
        XREF PROC DE$OPSB;   # DIRECTORY ACCESS OPEN SUBSCHEMA PROC # 
        XREF PROC DE$OPSC;   # DIRECTORY ACCESS OPEN SCHEMA PROCEDURE#
        XREF PROC DB$CERR;   # ERROR HANDLER FOR FATAL ERRORS # 
        XREF PROC DB$CESB;   # SUBSCHEMA FILE CRM ERROR HANDLER # 
        XREF PROC DB$CESC;   # SCHEMA FILE CRM ERROR HANDLER #
        XREF FUNC DB$CFIL C(30);       # BLANK OR ZERO CHARACTER FILL#
        XREF PROC DB$UADR;   # UPDATE MANAGED MEMORY USABLE ADDRESSES#
  
        CONTROL NOLIST;      # DCLS: UTCDF UTCIT UTMPT UTCAS CUGBA #
*CALL UTCASDCLS 
        CONTROL LIST;        # RESUME THE LISTING OF THE SOURCE CODE #
  
# THE FOLLOWING ITEMS ARE LOCAL TO DB$COPN #
  
        ITEM FILENAME C(10);           # ZERO-FILLED FILE NAME (LFN) #
        ITEM INDEX I;        # A GENERAL INDEX AND INDUCTION VARIABLE#
  
# THE FOLLOWING LOCAL BASED ARRAY IS FOR MD DATA BASE PROC DIRECTORY #
  
        BASED ARRAY MDDPROC[0:0] P(DFMDDPCW);   # MD DBP DIRECTORY #
  
          BEGIN              # MDDPROC BASED ARRAY #
*CALL MDDPDDCLS 
          END                # MDDPROC BASED ARRAY #
        CONTROL EJECT;
  
# CALL DE$OPSB TO OPEN THE SUBSCHEMA FILE AND TO SET UP THE DIT # 
  
        CURSCRAT = DB$CFIL(NAMESUBS,DFNAMECH,0); # 0-FILL SUBSCH MAME#
        FILENAME = DB$CFIL(LFNSUBSC,7,0);        # 0-FILL SUBSCH LFN #
        P<PUTENTRY> = LOC(SBCWDDIT) - 1;         # LOC(SUBSCHEMA DIT)#
        FOR INDEX = 1 THRU DFDITLEN DO PUTUNSIG[INDEX] = 0; 
        STATSUBS = 2;        # SUBSCHEMA STATUS - OPEN BEING TRIED #
        XCALL DE$OPSB(FILENAME,CURSCRAT,SBCWDDIT,SBBUFFER,DFSBBUFF);
  
# IF THERE ARE SUBSCHEMA OPEN OR CONTROL WORD FIELD ERRORS, ABORT # 
  
        P<DIRACCES> = LOC(SBCWDDIT);   # POINT TO SUBSCHEMA DIT ARRAY#
        IF DASTATE[0] NQ 0 AND DASTATE[0] NQ 1 THEN XCALL DB$CESB;
        STATSUBS = 3;        # SUBSCHEMA FILE STATUS - OPEN WAS TRIED#
        IF DASTATE[0] EQ 1 THEN XCALL DB$CERR("7001COPN",FILENAME); 
        CURSCRAT = DB$CFIL(NAMESCHE,DFNAMECH,0); # 0-FILL SCHEMA NAME#
        IF SBCWSCHNAM30[0] NQ CURSCRAT           # IF DIFFERENT NAMES#
          THEN               # CALL DB$CERR FOR A SUBSCHEMA ABORT # 
            BEGIN 
              CURSCRAT = SBCWSCHNAM30[0];        # OTHER SCHEMA NAME #
              XCALL DB$CERR("7002COPN",DFNAMECH);          # ABORT #
            END 
        IF SBCWVERSION[0] NQ DFDDLVEROL  # IF BAD DDL VERSION NUMBER   #
          AND SBCWVERSION[0] NQ DFDDLVER
          THEN XCALL DB$CERR("7003COPN",FILENAME);         # ABORT #
        IF SBCWNUMAREAS[0] GR DFORDMAX           # IF GREATER, ABORT #
          THEN XCALL DB$CERR("7004COPN",SBCWNUMAREAS[0] - DFORDMAX);
        IF SBCWNUMBERCS[0] GR DFORDMAX           # IF GREATER, ABORT #
          THEN XCALL DB$CERR("7005COPN",SBCWNUMBERCS[0] - DFORDMAX);
        IF SBCWNUMRELS[0] GR DFORDMAX            # IF GREATER, ABORT #
          THEN XCALL DB$CERR("7006COPN",SBCWNUMRELS[0] - DFORDMAX); 
        STATSUBS = 4;        # SUBSCHEMA STATUS - OPEN OK AND IN USE #
  
# MOVE FIELDS FROM THE SUBSCHEMA CONTROL WORDS TO ITEMS IN COMMON # 
  
        SBCHKSUM = SBCWCHECKSUM[0];    # SUBSCHEMA DIRECTORY CHECKSUM#
        SBCKSMWA = SBCWCKSUMWA[0];     # SUBSCHEMA CHECKSUM LIST ADDR#
        SBDATASV = SBCWDNSBUFSZ[0];    # DATA NAME SAVE BUFFER LENGTH#
        SBFIRARE = SBCWFRSTAREA[0];    # SUBSCHEMA FIRST AREA ADDRESS#
        SBFIRCAP = SBCWFRSTCAPA[0];    # SUBSCHEMA FIRST CAPSULE ADDR#
        SBFIRREC = SBCWFRSTRECA[0];    # SUBSCHEMA FIRST RECORD ADDRS#
        SBFIRREL = SBCWFRSTRELA[0];    # SUBSCHEMA FIRST RELATION ADD#
        SBFWADDR = SBCWSBADDR[0];      # SUBSCHEMA FIRST WORD ADDRESS#
        SBJULIAN = SBCWSBSCHDTE[0];    # SUBSCHEMA CREATE JULIAN DATE#
        SBMAXCAP = SBCWMAXCAPL[0];     # MAXIMUM CAPSULE WORD LENGTH #
        SBMAXENT = SBCWMAXSELEN[0];    # MAXIMUM SUBENTRY WORD LENGTH#
        SBMAXREC = SBCWMAXRECS[0];     # MAXIMUM RECORD CHARAC LENGTH#
        SBNUMARE = SBCWNUMAREAS[0];    # SUBSCHEMA NUMBER OF AREAS #
        SBNUMREC = SBCWNUMBERCS[0];    # SUBSCHEMA NUMBER OF RECORDS #
        SBNUMREL = SBCWNUMRELS[0];     # SUBSCHEMA NUMBER OF RELATION#
        SBTIME = SBCWSBSCHTME[0];      # SUBSCHEMA TIME OF CREATION # 
        CONTROL EJECT;
  
# CALL DE$OPSC TO OPEN THE SCHEMA FILE AND TO SET UP THE SCHEMA DIT # 
  
        FILENAME = DB$CFIL(LFNSCHEM,7,0);        # 0-FILL SCHEMA LFN #
        P<PUTENTRY> = LOC(SCCWDDIT) - 1;         # LOC(SCHEMA DIT) #
        FOR INDEX = 1 THRU DFDITLEN DO PUTUNSIG[INDEX] = 0; 
        STATSCHE = 2;        # SCHEMA FILE STATUS - OPEN BEING TRIED #
        XCALL DE$OPSC(FILENAME,SCCWDDIT,SCBUFFER,DFSCBUFF); 
  
# IF THERE ARE SCHEMA OPEN OR CONTROL WORD FIELD ERRORS, ABORT #
  
        P<DIRACCES> = LOC(SCCWDDIT);   # POINT TO SCHEMA DIT ARRAY #
        IF DASTATE[0] NQ 0 AND DASTATE[0] NQ 1 THEN XCALL DB$CESC;
        STATSCHE = 3;        # SCHEMA FILE STATUS - OPEN WAS TRIED #
        IF DASTATE[0] EQ 1 THEN XCALL DB$CERR("7007COPN",FILENAME); 
        IF SCCWSCHNAM30[0] NQ CURSCRAT           # IF DIFFERENT NAMES#
          THEN               # CALL DB$CERR FOR A SCHEMA-LEVEL ABORT #
            BEGIN 
              CURSCRAT = SCCWSCHNAM30[0];        # OTHER SCHEMA NAME #
              XCALL DB$CERR("7008COPN",DFNAMECH);          # ABORT #
            END 
        IF SCCWVERSION[0] NQ DFDDLVEROL  # IF BAD DDL VERSION NUMBER   #
          AND SCCWVERSION[0] NQ DFDDLVER
          THEN XCALL DB$CERR("7009COPN",FILENAME);         # ABORT #
        IF SCCWMAXITEMS[0] GR DFORDMAX           # IF GREATER, ABORT #
          THEN XCALL DB$CERR("7010COPN",SCCWMAXITEMS[0] - DFORDMAX);
        XCALL DB$UADR;       # UPDATE MANAGED MEMORY USABLE ADDRESSES#
        P<MDDPROC> = DBPTADDR;         # POINT TO DB PROCEDURE TABLE #
        IF SCCWDBPLENG[0] GR  0        # IF THERE ARE SCHEMA DB PROCS#
          THEN SCNUMDBP = SCCWDBPLENG[0] - 1;    # -1 FOR DBPT HEADER#
          ELSE SCNUMDBP = SCCWDBPLENG[0];        # NO SCHEMA DB PROCS#
        IF MDDPNBEN[0] NQ SCNUMDBP     # IF NUMBER OF DBPS IS UNEQUAL#
          THEN XCALL DB$CERR("7011COPN",SCNUMDBP);         # ABORT #
        STATSCHE = 4;        # SCHEMA STATUS - OPENED OK AND IN USE # 
  
# MOVE MORE FIELDS FROM THE SCHEMA CONTROL WORDS TO ITEMS IN COMMON # 
  
        OUTWARN = SCCWSCHDATE[0] NQ SBCWSCHDATE[0]         # T=SCHEMA#
               OR SCCWSCHTIME[0] NQ SBCWSCHTIME[0]         # DATES OR#
               OR SCCWSCHDATE[0] NQ DATSCHEM               # TIMES #
               OR SCCWSCHTIME[0] NQ TIMSCHEM;              # DIFFER # 
        SCCKSMWA = SCCWCKSUMWA[0];     # SCHEMA CHECKSUM LIST WD ADDR#
        SCMAXENT = SCCWMAXSELEN[0];    # SCHEMA MAX SUBENTRY WORD LEN#
        SCNUMARE = SCCWNUMAREAS[0];    # SCHEMA NUMBER OF AREAS # 
        SCNUMCON = SCCWCSNUM[0];       # SCHEMA NUMBER OF CONSTRAINTS#
        SCNUMREL = SCCWNUMRELTN[0];    # SCHEMA NUMBER OF RELATIONS # 
  
# RETURN WITH THE SUBSCHEMA AND SCHEMA DIRECTORY FILES NOW OPEN # 
  
        RETURN;              # SUBSCHEMA AND SCHEMA FILES NOW OPEN #
  
        END                  # DB$COPN #
  
      TERM
