MainframeSupports
tip uge 37/2002:

Jeg har tidligere skrevet et tip om, hvordan PL/1 er i stand til at læse stort set hvad som helst. Nu er tiden vist kommet til at fortælle om, hvordan man skriver hvad som helst. Nu er skrivning af hvad som helst et meget stort ord at hæfte på det følgende tip, men det kan da manipulere med både LRECL og BLKSIZE.

Følgende program kopierer fra DD-navn ANYFILE over i et FB dataset med en LRECL svarende til record-længden på den først indlæste record. Datasettet allokeres til DD-navn FBFILE:

/* PLI - copy allmost any dataset to FB */
writefb: PROC OPTIONS(MAIN);

DCL anyfile FILE RECORD SEQUENTIAL;
DCL anyfile_data CHAR(32767) VAR;
DCL anyfile_eof CHAR(1);

DCL fbfile FILE RECORD SEQUENTIAL OUTPUT
    ENV(FB RECSIZE(lrecl) BLKSIZE(blksize));
DCL fbfile_data CHAR(27998) VAR;
DCL space_data CHAR(27998) VAR;
DCL lrecl FIXED BIN(31) STATIC;
DCL blksize FIXED BIN(31) STATIC;

ON ENDFILE(anyfile) anyfile_eof = 'Y';
anyfile_eof = 'N';
lrecl = 80;
OPEN FILE(anyfile);
READ FILE(anyfile) INTO(anyfile_data);
IF anyfile_eof = 'N'
THEN DO;
  lrecl = min(length(anyfile_data), 27998);
  IF lrecl = 0
  THEN
    lrecl = 80;
END;
blksize = 27998 / lrecl;
blksize = lrecl * blksize;
space_data = repeat(' ', lrecl - 1);
OPEN FILE(fbfile);
DO WHILE(anyfile_eof = 'N');
  fbfile_data = substr(anyfile_data !! space_data, 1, lrecl);
  WRITE FILE(fbfile) FROM(fbfile_data);
  READ FILE(anyfile) INTO(anyfile_data);
END;
CLOSE FILE(fbfile);
CLOSE FILE(anyfile);

END writefb;

Så enkelt er det. Nå, men det kræver vist et par forklaringer. De to variabler lrecl og blksize skal erklæres som FIXED BIN(31) STATIC. Selve erklæringen af file variablen skal have OUTPUT med. Når filen åbnes, så skal blksize være et multiplum af lrecl. Man kan ikke benytte blksize = 0 inde fra PL/1. En vigtig detalje er, at blksize beregningen skal ske i to steps som vist. Hvis man omskriver beregningen til et statement, så virker det ikke, da 27998 / lrecl * lrecl altid giver 27998.

Jeg benytter en CHAR VAR til at skrive fbfile med og den skal pinedød have en længde, der er lig lrecl ellers fejler programmet. Jeg overvejer faktisk at erstatte fbfile_data med en CONTROLLED variabel, som jeg kan allokere med den korrekte længde, men jeg ved ikke om det virker.

Desværre kan substr i PL/1 ikke lide, når det, der substringes af er kortere end den angivne længde. Derfor sikrer jeg mig med space_data, at det aldrig kommer til at ske. Hvis længden af anyfile_data er længere end lrecl, så mister man data og sådan er det jo bare. Her kan programmet jo ændres på diverse måder, så lrecl bestemmes ud fra andre kriterier.

Når først du har set ovenstående virke bør et være en smal sag for dig at lave et program, der skriver til et VB-dataset i stedet, hvis det er det behov, du har. Så skal du kun tage højde for at længden af anyfile_data nogen gange kan være større end lrecl.

Du skal i øvrigt være opmærksom på, at når du sætter DCB-oplysningerne inde fra PL/1-programmet, så overskrives datasettets eksisterende DCB-oplysninger råt og brutalt. Omvendt kan du så nøjes med at angive DSN og SPACE på DD-kortet, når du vil allokere et nyt dataset med DISP=(NEW, CATLG).

Forrige danske tip        Last tip in english        Tip oversigten