-
Notifications
You must be signed in to change notification settings - Fork 2
/
cmssys.assemble
1313 lines (1313 loc) · 65.1 KB
/
cmssys.assemble
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
*********************************************************************** 00010000
* CMSSYS contains C interfaces to CMS system services: * 00020000
* @@DEBUG A dummy routine callable from C (set breakpoint here). * 00030000
* @@ATTN Place a line on the CMS console stack. * 00040000
* @@SVC202 Invoke a CMS system service or command. * 00050000
* @@DMSFRE Allocate free memory. * 00060000
* @@DMSFRT Release allocated memory. * 00070000
* @@FSCLOS Close an open file and save it to disk. * 00080000
* @@FSERAS Delete a CMS file. * 00090000
* @@FSOPEN Open a CMS file for reading or writing. * 00100000
* @@FSPOIN Set the next item in a file to be read or written. * 00110000
* @@FSREAD Read a record from an open file. * 00120000
* @@FSSTAT Determine whether a file exists. *
* @@FSWRIT Write a record to an open file. *
* @@GETCLK Get the system clock time. *
* @@PRINTL Write a line to the virtual printer. *
* @@PUNCHC Write a line to the virtual card punch. *
* @@RDCARD Read a line from the virtual card reader. *
* @@RDDRCT Read a line from the virtual console, bypassing stack. *
* # @@RDTAPE Read a record from a virtual tape drive. *
* @@RDTERM Read a line from the stack or, if empty, the console. *
* @@RENAME Rename a CMS file. *
* @@STACKN Return number of lines in the CMS console stack. *
* # @@TAPCTL Position the tape on a virtual tape drive. *
* # @@WAITD Wait for the next interrupt on a device. *
* @@WAITT Wait for terminal I/O to complete. *
* # @@WRTAPE Write a record to a virtual tape drive. *
* @@WRTERM Display a line on the terminal. *
* # not yet implemented. *
* *
* This version will run in 24-bit mode only. Support for 31-bit *
* addressing is a future objective. *
* *
* TODO: Detect if we are in resident memory, and if so, BALR to the *
* system functions instead of using SVC 202... *
* *
* This code is not yet reentrant, but it is reuseable. *
* *
* Robert O'Hara, Redmond Washington, July 2010. *
* Released to the public domain. *
***********************************************************************
CMSSYS CSECT
USING CMSSYS,R12
USING CMSCRAB,R13 map the save area
USING FSCBD,R8 CMS File System Control Block
SPACE 3
***********************************************************************
* @@DEBUG Entry Point *
* Return to caller. This is a place to set a breakpoint. *
* *
* Syntax is: *
* int __DEBUG(int retcode) *
* where: *
* retcode is a number to be returned to the caller. *
* returns: *
* (int) The number passed to this function. *
***********************************************************************
ENTRY @@DEBUG
@@DEBUG DS 0H
L R15,0(R1) get the desired return code
BR R14 return to our caller
EJECT
***********************************************************************
* CMSSetNU *
* void CMSSetNUCON(void *address, int value) *
* *
* Set memory in NUCON *
***********************************************************************
ENTRY CMSSETNU
CMSSETNU DS 0H
STM R14,R12,12(R13)
LR R12,R15
LA R15,CMSSETNU-CMSSYS
SLR R12,R15
USING NUCON,0
L R5,0(R1) get Address
L R3,4(R1) get Value
IPK ,
SPKA 0
SSM *+1
ST R3,0(R5) Save Value
SPKA 0(R2)
SSM =X'FF'
L R14,12(R13) restore our return address
LM R0,R12,20(R13) restore the registers
BR R14 return to our caller
EJECT
***********************************************************************
* void CMSSetFlag(int flag, int value) - thanks to Bob Bolch *
* *
* Set the value of the CMS Flag (TRACEFLAG or HALTFLAG) *
* Args flag and value (0 or 1) *
***********************************************************************
ENTRY CMSSETFL
CMSSETFL DS 0H
STM R14,R12,12(R13)
LR R12,R15
LA R15,CMSSETFL-CMSSYS
SLR R12,R15
USING NUCON,0
L R5,0(R1) get Flag
L R3,4(R1) get Value
LTR R3,R3
BZ SETFOFF branch to reset flag
IPK ,
SPKA 0
SSM *+1
IC R4,EXECFLAG Get Flag
OR R4,R5 Set Flag On
STC R4,EXECFLAG Save Flag
B SETFDONE
SETFOFF DS 0H
IPK ,
SPKA 0
SSM *+1
LA R6,X'FF' For Anding the Flag
SR R6,R5
IC R4,EXECFLAG Get Flag
NR R4,R6 Set Flag Off
STC R4,EXECFLAG Save Flag
SETFDONE DS 0H
SPKA 0(R2)
SSM =X'FF'
L R14,12(R13) restore our return address
LM R0,R12,20(R13) restore the registers
BR R14 return to our caller
EJECT
***********************************************************************
* @@ATTN Entry Point *
* Place a line on the CMS console stack. *
* *
* Syntax is: *
* int __ATTN(char * line, int order) *
* where: *
* line is a pointer to the line to be stacked. It must be no *
* more than 130 on VM/370, no more than 256 on VM/SP or *
* z/VM. *
* order is 0 if the line is to be stacked 'LIFO', anything *
* else if it is to be stacked 'FIFO'. *
* returns: *
* (int) Return code from the ATTN function, always 0. *
***********************************************************************
@@ATTN PDPPRLG CINDEX=0,FRAME=CMSSVALN,BASER=12,ENTRY=YES
LA R15,@@ATTN-CMSSYS
SLR R12,R15
USING CMSSYS,R12
MVC ATTNPL,=CL8'ATTN'
L R6,0(R1) R6 is start of line to stack
LA R3,LINELEN(R6) last possible char to stack
LA R2,1 loop increment
LR R4,R6 start of line to stack
ATTN1 DS 0H determine the length of the line
CLI 0(R4),X'00' look for end of the C string
BE ATTN2 found it
BXLE R4,R2,ATTN1 keep looping if not
ATTN2 DS 0H we have the end of the line
SR R4,R6 length of line to stack
ST R6,ATTNLN put line addr in ATTN plist
STC R4,ATTNLN put line length in ATTN plist
* Now check for FIFO or LIFO.
L R2,4(R1) get 'order'
LTR R2,R2 FIFO or LIFO?
BZ ATTN3 LIFO it is
MVC ATTNOD(4),=C'FIFO'
B ATTN4
ATTN3 DS 0H
MVC ATTNOD(4),=C'LIFO'
ATTN4 DS 0H
* Use the ATTN function to stack the line.
LA R1,ATTNPL
SVC 202 stack the line
DC AL4(ATTNRT) go here if an error
ATTNRT DS 0H
SR R15,R15 zero return code
PDPEPIL
EJECT
***********************************************************************
* @@SVC202 Entry Point *
* Invoke a CMS system service or command. Both a standard and *
* extended parameter list are passed to the command. *
* *
* Syntax is: *
* int __SVC202(void *plist , void* eplist, int calltype) *
* where: *
* plistr, eplist pointers to the parameters in both formats *
* calltype specifies the type of call: *
* 0 indicates the command is to be invoked as a *
* function. (REALLY? CHECK!) *
* 1 indicates the command is invoked as if from a CMS *
* EXEC. For example, if you want to invoke ABC *
* EXEC you must *
* code 'EXEC ABC'. *
* 11 indicates the command is invoked as if typed by *
* the user at the terminal. *
* returns: *
* (int) Return code from the invoked service or command. *
***********************************************************************
ENTRY @@SVC202
@@SVC202 DS 0H
STM R14,R12,12(R13)
LR R12,R15
LA R15,@@SVC202-CMSSYS
SLR R12,R15
LR R2,R1 save C parameter list
L R1,0(R2) plist
L R0,4(R2) eplist
ICM R1,8,11(R2) CALLTYPE flag byte
SVC 202 call the command
DC AL4(*+4) error address
L R14,12(R13) restore our return address
LM R0,R12,20(R13) restore the registers
BR R14 return to our caller
EJECT
***********************************************************************
* @DMSFREE *
* DMSFREE Stub *
* Allocate free memory. *
* *
* Syntax is: *
* _DMSFREE(int doublewords) *
* returns: *
* (int) Address of the allocated memory, or 0 if the memory *
* could not be allocated. *
***********************************************************************
ENTRY @DMSFREE
@DMSFREE DS 0H
STM R14,R12,12(R13)
LR R12,R15
LA R15,@DMSFREE-CMSSYS
SLR R12,R15
L R0,0(R1) get number of dounlewords to allocate
* Use DMSFREE to allocate the memory.
DMSFREE DWORDS=(0),TYPE=USER,ERR=DMSFREE2
LTR R15,R15 did we get the memory?
BNZ DMSFREE2 no, quit now
LR R15,R1
DMSFREE1 DS 0H
L R14,12(R13) restore our return address
LM R0,R12,20(R13) restore the registers
BR R14 return to our caller
DMSFREE2 DS 0H no memory
SR R15,R15 indicate no memory allocated
B DMSFREE1
EJECT
***********************************************************************
* @DMSFRET *
* DMSFRET Stub *
* Release allocated memory. *
* *
* Syntax is: *
* int _DMSFRET(void *address, int doublewords) *
* where: *
* memory is a pointer to the memory to be freed. *
* returns: *
* 0 Success. *
* 1 Error. *
***********************************************************************
ENTRY @DMSFRET
@DMSFRET DS 0H
STM R14,R12,12(R13)
LR R12,R15
LA R15,@DMSFRET-CMSSYS
SLR R12,R15
L R0,4(R1) get doublewords to return
L R1,0(R1) get address of memory to return
* Use DMSFRET to return the memory.
DMSFRET DWORDS=(0),LOC=(1),ERR=DMSFRET2
SR R15,R15 indicate all OK
DMSFRET1 DS 0H
L R14,12(R13) restore our return address
LM R0,R12,20(R13) restore the registers
BR R14 return to our caller
DMSFRET2 DS 0H no memory
LA R15,1 indicate error
B DMSFRET1
EJECT
***********************************************************************
* @@DMSFRE Entry Point *
* Allocate free memory. *
* *
* Syntax is: *
* __DMSFRE(int bytes, int type) *
* where: *
* bytes is the number of bytes to be allocated. *
* type is the type of memory: 0 for NUCLEUS, 1 for USER. *
* returns: *
* (int) Address of the allocated memory, or 0 if the memory *
* could not be allocated. *
* Notes: *
* 1. Since CMS allocates memory in doublewords, we divide the bytes *
* requested by 8 then add 2 to effectively round up, and add an *
* additional doubleword which we use in note 2. *
* 2. The first word is used to store the number of doublewords *
* allocated, needed in @@DMSFRT. The next word is 'GCC' followed *
* by a 0 byte. This helps detect memory overruns, I hope. *
* 3. Memory returned to the caller starts 8 bytes after the memory *
* allocated to us by CMS. *
* 4. If you allocate NUCLEUS memory, your program must be generated *
* with the SYSTEM option. Note that if such a program abnormally *
* terminates, CMS does not release this memory. *
***********************************************************************
@@DMSFRE PDPPRLG CINDEX=0,FRAME=CMSSVALN,BASER=12,ENTRY=YES
LA R15,@@DMSFRE-CMSSYS
SLR R12,R15
USING CMSSYS,R12
L R2,0(R1) get number of bytes to allocate
SRL R2,3 convert to doublewords
LA R0,2(R2) round up plus 1 for housekeeping
L R2,4(R1) get type parameter
* ---------------------------------------------------------------------
* For debugging...
L R3,0(R1) get number of bytes to allocate
L R4,=F'1000000'
SR R4,R3
BP OKAY
MVC LINEDITL(LINEDISZ),LINEDITP Set pattern
MVI OUTBUF,255 Set buffer size in byte 1
LINEDIT TEXT='Attempting to allocate ........ bytes', X
SUB=(DEC,(3)),COMP=NO,BUFFA=OUTBUF, X
MF=(E,LINEDITL)
SR R0,R0
SR R1,R1
B NOMEMORY
OKAY DS 0H
* End of debugging...
* ---------------------------------------------------------------------
LTR R2,R2
BZ NUCMEM get nucleus memory
* Use DMSFREE to allocate the memory.
DMSFREE DWORDS=(0),TYPE=USER,ERR=NOMEMORY
B POSTMEM
NUCMEM DS 0H
DMSFREE DWORDS=(0),TYPE=NUCLEUS,ERR=NOMEMORY
POSTMEM DS 0H
LTR R15,R15 did we get the memory?
BNZ NOMEMORY no, quit now
ST R0,0(R1) store number of doublewords allocated
MVC 4(4,R1),=X'C7C3C300' store marker: "GCC" C string
LA R15,8(R1) here is where user memory starts
B FREERET remove this for debugging message
* ---------------------------------------------------------------------
* For debugging...
LR R2,R15
LR R3,R0
LR R4,R1
MVC LINEDITL(LINEDISZ),LINEDITP Set pattern
MVI OUTBUF,255 Set buffer size in byte 1
LINEDIT TEXT='Allocated ...... dwords of memory at ......', X
SUB=(DEC,(3),HEX,(4)),COMP=NO, X
MF=(E,LINEDITL)
LR R15,R2
* End of debugging...
* ---------------------------------------------------------------------
FREERET DS 0H
PDPEPIL
NOMEMORY DS 0H
SR R15,R15 indicate no memory allocated
B FREERET
EJECT
***********************************************************************
* @@DMSFRT Entry Point *
* Release allocated memory. *
* *
* Syntax is: *
* int __DMSFRT(void * memory) *
* where: *
* memory is a pointer to the memory to be freed. *
* returns: *
* 0 Success. *
* 5 Returned size not positive (no doubt memory was *
* overwritten. *
* 6 Memory block overlaps other memory. *
* 7 Returned block is not double-word aligned. *
* 8 Illegal code or argument. *
***********************************************************************
@@DMSFRT PDPPRLG CINDEX=0,FRAME=CMSSVALN,BASER=12,ENTRY=YES
LA R15,@@DMSFRT-CMSSYS
SLR R12,R15
USING CMSSYS,R12
L R1,0(R1) get address of memory to return
LTR R1,R1 check the address
BP FRTOK
MVC LINEDITL(LINEDISZ),LINEDITP Set pattern
MVI OUTBUF,255 Set buffer size in byte 1
LINEDIT TEXT='Invalid address passed to __DMSFRT', X
MF=(E,LINEDITL)
LA R15,8 indicate bad pointer
B FRTEND
FRTOK DS 0H
S R1,=F'8' get to real start of memory
* Complain if our label has been overwritten.
CLC 4(4,R1),=X'C7C3C300'
BE ALLSWELL looks good
LR R2,R1
MVC LINEDITL(LINEDISZ),LINEDITP Set pattern
MVI OUTBUF,255 Set buffer size in byte 1
LINEDIT TEXT='Memory overwrite detected by __DMSFRT at ......'X
,SUB=(HEX,(2)), X
MF=(E,LINEDITL)
LA R15,5 indicate memory overwrite
B FRTEND
ALLSWELL DS 0H
L R0,0(R1) get doublewords to return
* Use DMSFRET to return the memory.
DMSFRET DWORDS=(0),LOC=(1)
B FRTEND
* ---------------------------------------------------------------------
* For debugging...
LR R2,R15
LR R3,R0
LR R4,R1
MVC LINEDITL(LINEDISZ),LINEDITP Set pattern
MVI OUTBUF,255 Set buffer size in byte 1
LINEDIT TEXT='Freed ...... dwords of memory at ......', X
SUB=(DEC,(3),HEX,(4)),COMP=NO, X
MF=(E,LINEDITL)
LR R15,R2
* End of debugging...
* ---------------------------------------------------------------------
FRTEND DS 0H
PDPEPIL
EJECT
***********************************************************************
* @@FSCLOS Entry Point *
* Close an open file and save it to disk. *
* *
* Syntax is: *
* int __FSCLOS(FSCB * fscb) *
* where: *
* fscb is a pointer to the FSCB returned from __FSOPEN. *
* returns: *
* 0 Success. *
* 6 The file is not open. *
***********************************************************************
ENTRY @@FSCLOS
@@FSCLOS DS 0H
STM R14,R12,12(R13)
LR R12,R15
LA R15,@@FSCLOS-CMSSYS
SLR R12,R15
L R8,0(R1) get FSCB
* Use FSCLOSE to close the file.
FSCLOSE FSCB=(R8)
L R14,12(R13) restore our return address
LM R0,R12,20(R13) restore the registers
BR R14 return to our caller
EJECT
***********************************************************************
* @@FSERAS Entry Point *
* Delete a CMS file. *
* *
* Syntax is: *
* int __FSERAS(char * fileid) *
* where: *
* fileid is a pointer to the CMS fileid, an 18 character field. *
* The first 8 characters are the filename, the next 8 *
* are the filetype, and the last 2 are the filemode. *
* This string is not NULL terminated. *
* returns: *
* 0 Success. *
* 24 Parameter list error (invalid character in fileid). *
* 28 The file was not found. *
* 36 Disk not accessed. *
***********************************************************************
@@FSERAS PDPPRLG CINDEX=0,FRAME=CMSSVALN,BASER=12,ENTRY=YES
LA R15,@@FSERAS-CMSSYS
SLR R12,R15
USING CMSSYS,R12
L R2,0(R1) get address of fileid
LA R8,WORKFSCB FSCB is built here
XC 0(FSCBLEN,R8),0(R8)
MVI FSCBFN,C' '
MVC FSCBFN+1(18-1),FSCBFN blank out fileid
OC FSCBFN(18),0(R2) copy FILEID and uppercase
* Use FSERASE to delete the file.
FSERASE FSCB=WORKFSCB
PDPEPIL
EJECT
***********************************************************************
* @@FSOPEN Entry Point *
* Open a CMS file for reading or writing. *
* *
* Syntax is: *
* int __FSOPEN(char * fileid, void * buffer, int bsize, *
* char recfm, int numrec, int recnum, FSCB * fscb) *
* where: *
* fileid is a pointer to the CMS fileid, an 18 character field. *
* The first 8 characters are the filename, the next 8 *
* are the filetype, and the last 2 are the filemode. *
* This string is not NULL terminated. *
* buffer is a pointer to the buffer from which records are read *
* from or written to. *
* bsize is the size of the buffer. *
* recfm is 'F' if you are writing a file of fixed-length *
* records, 'V' if you are writing a file of variable- *
* length records. This parameter is ignored if you are *
* reading from the file. *
* numrec is the number of records to be read or written at a *
* time. This parameter can be greater than 1 only when *
* reading or writing fixed-length records. *
* recnum is the record number at which to begin reading or *
* writing. *
* fscb is a pointer to an FSCB. It is updated by FSOPEN. *
* Pass this as an argument to other file I/O functions. *
* returns: *
* 0 Success. *
* 20 The fileid is invalid. *
* 28 The file was not found. *
***********************************************************************
ENTRY @@FSOPEN
@@FSOPEN DS 0H
STM R14,R12,12(R13)
LR R12,R15
LA R15,@@FSOPEN-CMSSYS
SLR R12,R15
LM R2,R8,0(R1) get address of parameters
* R2 address of fileid
* R3 buffer address
* R4 buffer length
* R5 record format
* R6 number of records to read or write
* R7 record number
* R8 FSCB is built here
XC 0(FSCBLEN,R8),0(R8)
MVI FSCBFN,C' '
MVC FSCBFN+1(18-1),FSCBFN blank out fileid
OC FSCBFN(18),0(R2) copy FILEID and uppercase
* Use FSOPEN to open the file.
FSOPEN BUFFER=(R3),BSIZE=(R4),RECFM=(R5), *
NOREC=(R6),RECNO=(R7), *
FSCB=(R8)
L R14,12(R13) restore our return address
LM R0,R12,20(R13) restore the registers
BR R14 return to our caller
EJECT
ENTRY @@FSPOIN
***********************************************************************
* @@FSPOIN Entry Point *
* Set the next item number (record) to read or write from a CMS file. *
* *
* Syntax is: *
* int __FSPOIN(FSCB * fscb, int recnum, int rw) *
* where: *
* fscb is a pointer to an FSCB. It is updated by FSPOINT. *
* Pass this as an argument to other file I/O functions. *
* recnum is the record number at which to begin reading or *
* writing. *
* rw is 0 to set the read pointer, 1 to set the write *
* pointer. *
* returns: *
* 0 Success. *
* 1 The file was not found. *
* 2 Parameter list error. *
* Notes: *
* 1. Pointing to an record number greater than the number of records *
* in the file yields unpredictable results. *
***********************************************************************
@@FSPOIN DS 0H
STM R14,R12,12(R13)
LR R12,R15
LA R15,@@FSPOIN-CMSSYS
SLR R12,R15
L R8,0(,R1) FSCB
LM R3,R4,0(R1)
* R3 record number
* R4 read or write flag
LTR R4,R4
BZ POINTRD set the read pointer
* Use FSPOINT to set the write pointer
FSPOINT FSCB=(R8),WRPNT=(R3)
B POINTED
POINTRD DS 0H
* Use FSPOINT to set the read pointer
FSPOINT FSCB=(R8),RDPNT=(R3)
POINTED DS 0H
L R14,12(R13) restore our return address
LM R0,R12,20(R13) restore the registers
BR R14 return to our caller
EJECT
***********************************************************************
* @@FSREAD Entry Point *
* Read a record from an open file. *
* *
* Syntax is: *
* int __FSREAD(FSCB * fscb, int RECNUM, int * bytesread) *
* where: *
* fscb is a pointer to the FSCB of the open file. *
* recnum is the record number at which to begin reading. To *
* read sequential records, specify 1 on the first call *
* to __FSREAD, 0 on subsequent calls. Alternately, *
* specify 1 as the 'recnum' parameter in __FSOPEN, and *
* set 'recnum' to 0 on all __FSREAD calls. To use the *
* record number currently set in the FSCB, specify -1. *
* bytesread (returned) is a pointer to the number of bytes *
* actually read. *
* returns: *
* 0 Success. *
* 1 The file was not found. *
* 2 Invalid buffer address. *
* 3 Permanent I/O error. *
* 5 Number of records is less than 1, or greater than *
* 32,768. *
* 7 Invalid record format (only checked when file is first *
* opened for reading). *
* 8 Incorrect length. *
* 9 File open for output. *
* 11 Number of records greater than 1 for variable-length *
* file. *
* 12 End of file reached. *
* 13 Variable-length file has invalid displacement in the *
* active file table. *
* 14 Invalid character in filename. *
* 15 Invalid character in filetype. *
* Notes: *
* 1. The bytes placed into the FSCB buffer are NOT terminated with a *
* null character. *
***********************************************************************
ENTRY @@FSREAD
@@FSREAD DS 0H
STM R14,R12,12(R13)
LR R12,R15
LA R15,@@FSREAD-CMSSYS
SLR R12,R15
LR R2,R1 save our plist pointer
L R8,0(,R1) FSCB
LM R4,R5,4(R1)
* R4 record number
* R5 where to store number of bytes read
LTR R4,R4
BH READREC if record number > 0, use it
BL READNREC if record number < 0, use FSCB recnum
* The caller specified 0 as the record number to read. If the FSCB is
* set to read record 1, read that, then set the FSCB record number to 0
* after the FSREAD has completed.
LH R1,FSCBITNO get the record number from the FSCB
C R1,=F'1'
BH READREC it was >1, so read next record instead
READNREC DS 0H
* Use FSREAD to read from the file, using the recnum in the FSCB
FSREAD FSCB=(R8)
LTR R4,R4 did the user specify recnum of 0?
BNZ DONEREAD no, so we are done
STH R4,FSCBITNO yes, set the FSCB record number to 0
B DONEREAD
READREC DS 0H
* Use FSREAD to read from the file, specifying the recnum
FSREAD FSCB=(R8),RECNO=(R4)
DONEREAD DS 0H
ST R0,0(R5) return number of bytes read
L R14,12(R13) restore our return address
LM R0,R12,20(R13) restore the registers
BR R14 return to our caller
EJECT
***********************************************************************
* @@FSSTAT Entry Point *
* Determine whether a file exists. *
* *
* Syntax is: *
* int __FSSTAT(char * fileid, FST ** fst) *
* where: *
* fileid is a pointer to the CMS fileid, an 18 character field. *
* The first 8 characters are the filename, the next 8 *
* are the filetype, and the last 2 are the filemode. *
* The filename, filetype, and filemode may each be *
* specified as *, in which case the first file *
* satisfying the rest of the fileid is used. This *
* string is not NULL terminated. *
* fst is a handle to a copy of the CMS file state table *
* (FST) for this file. It provides details of the *
* specified file. *
* returns: *
* 0 Success. *
* 20 The fileid is invalid. *
* 24 Invalid filemode. *
* 28 The file was not found. *
* 36 Disk not accessed. *
***********************************************************************
@@FSSTAT PDPPRLG CINDEX=0,FRAME=CMSSVALN,BASER=12,ENTRY=YES
LA R15,@@FSSTAT-CMSSYS
SLR R12,R15
USING CMSSYS,R12
LM R2,R3,0(R1)
* R2 address of fileid
* R3 address to receive FST ptr
LA R8,WORKFSCB FSCB is built here
XC 0(FSCBLEN,R8),0(R8)
MVI FSCBFN,C' '
MVC FSCBFN+1(18-1),FSCBFN Blank out FILEID
OC FSCBFN(18),0(R2) copy fileid and uppercase
* Use FSSTATE to determine if the file exists.
FSSTATE FSCB=WORKFSCB
ST R1,0(,R3) store FST
PDPEPIL
EJECT
ENTRY @@FSWRIT
***********************************************************************
* @@FSWRIT Entry Point *
* Write a record to an open file. *
* *
* Syntax is: *
* int __FSWRIT(FSCB fscb, int recnum, int reclen) *
* where: *
* fscb is a pointer to the FSCB of the open file. *
* recnum is the record number at which to begin writing. To *
* write sequential records, specify 1 on the first call *
* to __FSWRIT, 0 on subsequent calls. To use the record *
* number currently set in the FSCB, specify -1. *
* reclen is the length of the record to be written. *
* returns: *
* 0 Success. *
* 2 Invalid buffer address. *
* 4 First character of filemode is illegal. *
* 5 Second character of filemode is illegal. *
* 6 Record number too large. *
* 7 Attempt to skip over unwritten variable-length record. *
* 8 Buffer size not specified. *
* 9 File open for input. *
* 10 Maximum number of files reached. *
* 11 Record format not F or V. *
* 12 Attempt to write on read-only disk. *
* 13 Disk is full. *
* 14 Number of bytes written is not integrally divisible by *
* the number of records to be written. *
* 15 Length of fixed-length recod not the same as previous *
* record. *
* 16 Record format specified is not the same as that of the *
* file. *
* 17 Variable-length record is greater than 65K bytes. *
* 18 Number of records to write is greater than 1 for a *
* variable length file. *
* 19 Maximum number of data blocks per file (16060) has *
* been reached. *
* 20 Invalid character detected in filename. *
* 21 Invalid character detected in filetype. *
* 22 Virtual storage capacity exceeded. *
* 25 Insufficent free storage available for file directory *
* buffers. *
* Notes: *
* 1. It is possible to overwrite a record within a file. However, *
* care must be taken that the record being written is the same *
* length as the one it is replacing. Failing to do this can *
* result in corruption of the file and possibly the entire *
* mini-disk. *
* 2. To overwrite an existing file with new records, call *
* @@FSERAS to first erase the file, then open the file and begin *
* writing from record 1. *
***********************************************************************
@@FSWRIT DS 0H
STM R14,R12,12(R13)
LR R12,R15
LA R15,@@FSWRIT-CMSSYS
SLR R12,R15
LM R2,R4,0(R1)
* R2 FSCB
* R3 record number
* R4 record length
* Use FSWRITE to write to the file.
LTR R3,R3
BNL WRECNO if record number is 0 or higher, use it
FSWRITE FSCB=(R2),BSIZE=(R4)
B DONEWRIT
WRECNO DS 0H
FSWRITE FSCB=(R2),RECNO=(R3),BSIZE=(R4)
DONEWRIT DS 0H
L R14,12(R13) restore our return address
LM R0,R12,20(R13) restore the registers
BR R14 return to our caller
EJECT
***********************************************************************
* @@GETCLK Entry Point *
* Get the system clock time. *
* *
* Syntax is: *
* int __GETCLK(clock) *
* where: *
* clock is an 8-byte variable into which the clock will be *
* stored. *
* returns: *
* (int) The number of seconds since 1/1/1970. *
***********************************************************************
ENTRY @@GETCLK
@@GETCLK DS 0H
STM R14,R12,12(R13)
LR R12,R15
LA R15,@@GETCLK-CMSSYS
SLR R12,R15
L R2,0(R1) get address of 'clock'
STCK 0(R2) store the clock there
L R4,0(R2) calculate seconds since 1/1/1970
L R5,4(R2)
SRDL R4,12
SL R4,=X'0007D910'
D R4,=F'1000000'
SL R5,=F'1220'
LR R15,R5 and return it
L R14,12(R13) restore our return address
LM R0,R12,20(R13) restore the registers
BR R14 return to our caller
EJECT
***********************************************************************
* @@PRINTL Entry Point *
* Write a line to the virtual printer. *
* *
* Syntax is: *
* int __PRINTL(char * line) *
* where: *
* line is a pointer to the line to be printed. The first *
* character of the line must be a carriage control *
* character (a blank skips to a new line). The string *
* must be NULL terminated. The maximum length of the *
* line is 133 characters for a virtual 1403 printer (the *
* default), 151 characters for a virtual 3211 printer; a *
* line longer than this results in an error. *
* returns: *
* 0 Success. *
* 1 Line too long. *
* 2 Channel 12 punch sensed (virtual 3211 only). *
* 3 Channel 9 punch sensed (virtual 3211 only). *
* 4 Intervention required. *
* 5 Unknown error. *
* 100 Printer not attached. *
* Notes: *
* 1. Use the CP CLOSE command to close the virtual printer. You can *
* issue this via the @@CMSCMD entry point. *
***********************************************************************
@@PRINTL PDPPRLG CINDEX=0,FRAME=CMSSVALN,BASER=12,ENTRY=YES
LA R15,@@PRINTL-CMSSYS
SLR R12,R15
USING CMSSYS,R12
L R6,0(R1) R6 is start of line to display
LA R3,151(R6) last possible char to display
LA R2,1 loop increment
LR R4,R6 start of line to display
PRINTL1 DS 0H
* Loop to determine the length of the line to display.
CLI 0(R4),X'00' look for end of the C string
BE PRINTL2 found it
BXLE R4,R2,PRINTL1 keep looping if not
PRINTL2 DS 0H
SR R4,R6 length of line to display
* Use PRINTL to display the line.
* PRINTL (R6),(R4)
MVC PRINTLE(PRINTLPL),PRINTLP SET PATTERN
LA R9,PRINTLE BRANCH THERE TO CALL IT
BR R9
PRINTLND DS 0H IT RETURNS HERE
*
PDPEPIL
*
DS 0D ALIGN TO AVOID GENERATED CNOP
USING PRINTLP,R9
PRINTLP PRINTL (R6),(R4)
DROP R9
B PRINTLND
PRINTLPL EQU *-PRINTLP
EJECT
***********************************************************************
* @@PUNCHC Entry Point *
* Write a line to the virtual card punch. *
* *
* Syntax is: *
* int __PUNCHC(char * line) *
* where: *
* line is a pointer to the line to be written to the punch. *
* The line must be 80 bytes long. *
* returns: *
* 0 Success. *
* 2 Unit check. *
* 3 Unknown error. *
* 100 Punch not attached. *
* Notes: *
* 1. Use the CP CLOSE command to close the virtual card punch. You *
* can issue this via the @@CMSCMD entry point. *
***********************************************************************
@@PUNCHC PDPPRLG CINDEX=0,FRAME=CMSSVALN,BASER=12,ENTRY=YES
LA R15,@@PUNCHC-CMSSYS
SLR R12,R15
USING CMSSYS,R12
L R6,0(R1) R6 is start of line to punch
* Use PUNCHC to punch the card.
* PUNCHC (6)
MVC PUNCHCE(PUNCHCPL),PUNCHCP set pattern
LA R9,PUNCHCE branch there to call it
BR R9
PUNCHCND DS 0H it returns here
*
PDPEPIL
*
DS 0D align to avoid generated CNOP
USING PUNCHCP,R9
PUNCHCP PUNCHC (6)
DROP R9
B PUNCHCND
PUNCHCPL EQU *-PUNCHCP
EJECT
***********************************************************************
* @@RDCARD Entry Point *
* Read a line from the virtual card reader. *
* *
* Syntax is: *
* int __RDCARD(char * line, int * len) *
* where: *
* line is a pointer to the buffer into which the line is *
* read. As it is possible to read printer output files, *
* the buffer must be at least 133 bytes in size. The *
* incoming line is terminated with a null character, *
* forming a C string. *
* len is a pointer to a variable that on: *
* input - holds the line lenght expected *
* output - the line the number of characters read *
* returns: *
* 0 Success. *
* 1 End-of-file. *
* 2 Unit check. *
* 3 Unknown error. *
* 5 Length not equal to requested length. *
* 100 Punch not attached. *
***********************************************************************
@@RDCARD PDPPRLG CINDEX=0,FRAME=CMSSVALN,BASER=12,ENTRY=YES
LA R15,@@RDCARD-CMSSYS
SLR R12,R15
USING CMSSYS,R12
L R2,0(R1) get buffer address
L R4,4(R1) get address of length variable
L R3,0(R4) length of line to read
* Use RDCARD to read the line.
* RDCARD (R2),(R3)
MVC RDCARDE(RDCARDPL),RDCARDP set pattern
LA R9,RDCARDE branch there to call it
BR R9
RDCARDND DS 0H it returns here
*
ST R0,0(R4) return number of bytes read in 'len'
SR R1,R1
STC R1,0(R3,R2) place null character at end of line
PDPEPIL
*
DS 0D align to avoid generated CNOP
USING RDCARDP,R9
RDCARDP RDCARD (R2),(R3)
DROP R9
B RDCARDND
RDCARDPL EQU *-RDCARDP
EJECT
***********************************************************************
* @@RDTERM Entry Point *
* Read a line from the stack, or if empty, the virtual console. *
* *
* Syntax is: *
* int __RDTERM(char * line) *
* where: *
* line is a pointer to the 131-character buffer into which *
* the line is read. This line will be terminated with a *
* null character, forming a C string. *
* returns: *
* (int) Length of the string placed in the buffer. *
***********************************************************************
@@RDTERM PDPPRLG CINDEX=0,FRAME=CMSSVALN,BASER=12,ENTRY=YES
LA R15,@@RDTERM-CMSSYS
SLR R12,R15
USING CMSSYS,R12
L R2,0(R1) get buffer address
* Use RDTERM to read the line.
* RDTERM (2),EDIT=NO
MVC RDTERME(RDTERMPL),RDTERMP set pattern
LA R9,RDTERME branch there to call it
BR R9
RDTERMND DS 0H it returns here
LH R0,14(,R1) Length returned here
*
LR R15,R0 get number of bytes read as return code
SR R1,R1
STC R1,0(R15,R2) place null character at end of line
PDPEPIL
*
DS 0D align to avoid generated CNOP
USING RDTERMP,R9
RDTERMP RDTERM (2),EDIT=NO
DROP R9
B RDTERMND
RDTERMPL EQU *-RDTERMP
EJECT
***********************************************************************
* @@RDDRCT Entry Point *
* Read a line from the virtual console, bypassing the stack *
* *
* Syntax is: *
* int __RDDRCT(char * line) *
* where: *
* line is a pointer to the 131-character buffer into which *
* the line is read. This line will be terminated with a *
* null character, forming a C string. *
* returns: *
* (int) Length of the string placed in the buffer. *
***********************************************************************
@@RDDRCT PDPPRLG CINDEX=0,FRAME=CMSSVALN,BASER=12,ENTRY=YES
LA R15,@@RDDRCT-CMSSYS
SLR R12,R15
USING CMSSYS,R12
L R2,0(R1) get buffer address