1 08/04/86 pascal_separate_comp.gi.info
2
3 This info file describes how to share procedures and variables between
4 Pascal programs, how to call from Pascal procedures written in other
5 languages, how to reference from Pascal Multics external variables,
6 and how to, from programs written in other languages, call procedures
7 or reference variables exported by Pascal programs.
8
9
10 Summary of compiler directives: Extensions described below are SOL
11 extensions Since the standard does not allow to reference external
12 variables or procedures i.e. variables or procedures defined in one
13 other program separately compiled, necessary extensions have been
14 implemented. They are the compiler directives $IMPORT and $EXPORT.
15
16 $import
17 identifies the procedures, functions and variables that are defined
18 outside
19 the program.
20 $export
21 identifies which of this program's procedures, functions and
22 variables are to
23 be made accessible to other programs.
24
25 These directives must appear immediately after the program header,
26 with $import first if it exists.
27
28 ONLY PROCEDURES, FUNCTIONS OR VARIABLES DECLARED AT THE MAIN LEVEL
29 GLOBALS CAN BE EXPORTED OR IMPORTED.
30
31
32 The $import directive:
33 The $import directive appears immediately after the program header
34 and identifies the procedures, functions and variables that are
35 defined outside the program. Its syntax is:
36
37 $import <imported_list> ";" <imported_list> "$"
38
39 <imported_list> = <external_description_string> ":" <pascal_id_list>
40 <pascal_id_list> = <pascal_id> "" <pascal_id>
41 <external_description_string> =
42 "'" <target_name> "" <generator_name> "descriptors" "" "'"
43 | "'external_static'"
44 <target_name> = <multics_segment_name> "$" <entry_name>
45 <generator_name> = "pl1" | "pascal" | "fortran" | "cobol" etc..
46
47 The <pascal_id> is the identifier of the procedure or function or
48 variable as it is declared in the Pascal program.
49 The <external_description_string> gives information to the compiler
50 about where is allocated the variable or in which segment is the
51 procedure. The compiler uses this information to generate a Multics
52 link in the object segment. Usually, this link consists on a segment
53 name and an entry name in this segment. The segment name is found by
54 the compiler in the <external_description_string>. If this string
55 contains an <entry_name> this entry name is used by the compiler to
56 generate the link. Otherwise, the compiler takes the internal lower
57 case name of the procedure, function or variable. The list of the
58 generated links may be obtained using the Multics "print_link_info"
59 command which analyzes the object segment. These links are used by
60 the Multics dynamic linker to locate, at execution time, the concerned
61 variable, function or procedure.
62
63
64 Examples of $import:
65
66 program example;
67 $import
68 ' pl1_program pl1' : proc1, funct1 ;
69 'fortran_program fortran' : proc3 ;
70 'external_static' : v1, v2, v3 ; * Multics external variables
71 allocated in external static standard area *
72 'hcs_ pl1 descriptors' : make_seg ;
73 'pascal_program pascal' : proc5, v4, v5 ;
74 'segment_x$procedure_y pl1' : proc_xy ;
75 'static_data cds' : v6, v7 ; * allocated in a data segment
76 created by the cds command *
77 'ioa_$ioa_ pl1 descriptors' : ioa_1, ioa_2 $
78
79 The generated links will be:
80
81 Pascal object name Multics target
82
83 proc1 pl1_program$proc1
84 funct1 pl1_program$funct1
85 proc3 fortran_program$proc3
86 v1 *system$v1
87 v2 *system$v2
88 v3 *system$v3
89 make_seg hcs_$make_seg
90 proc5 pascal_program$proc5
91 v4 pascal_program$v4*
92 v5 pascal_program$v5*
93 proc_xy segment_x$procedure_y
94 v6 static_data$v6
95 v7 static_data$v7
96 ioa_1 ioa_$ioa_
97 ioa_2 ioa_$ioa_
98
99 Imported variables must be declared in the var section in the
100 standard manner. But, since they were mentionned in the $IMPORT
101 section, they are not allocated in the object segment and will be
102 referenced through a link.
103 Imported procedures and functions are declared at the standard
104 place in the program with a standard heading including the declaration
105 of the parameters in the standard manner, but their body declarations
106 plus statement part is replaced by the reserved word "external".
107
108
109
110 The $export directive: The $export directive appears immediately after
111 the $import directive if it exists and identifies which of this
112 program's procedures, functions and variables are to be made
113 accessible to other programs. It can be used to obtain more space for
114 large global variables or arrays. Internal global variables can
115 occupy only 16383 words.
116
117
118 Its syntax is:
119
120 $export <pascal_id_list> "$"
121
122 <pascal_id_list> = <identifier> "" <identifier>
123
124 The given <identifier> is the identifier of the variable, procedure or
125 function in the Pascal program.
126
127
128 Examples of $export:
129
130 $export
131 proc6, v8, v9 $
132
133 Exported variables, procedure or functions are declared in the
134 standard manner. But the compiler makes them accessible by external
135 programs through definitions which are generated in the object
136 segment. List of generated definitions may be obtained using the
137 Multics "print_link_info" command which analyzes the object segment.
138
139
140 However, there is one difference between exported and non exported
141 variables. Non exported variables are allocated in the static section
142 of the object segment, which is limited by Pascal implementation to
143 16K machine words.
144 Exported variables are by default dynamically allocated as external
145 variables in the process_dir like PL1 external statics. So, you can
146 use $EXPORT directive to export too big variables which could not be
147 allocated in the static section of the object segment.
148 If the program is compiled using the "-private_storage" control
149 argument, which is not the default, the exported variables will be
150 allocated in a data segment named "program_name.defs". In this case
151 total size of exported variables cannot exceed one segment.
152
153
154
155 Separate Pascal compilations:
156 This part concerns only Pascal programs sharing procedures,
157 functions or variables.
158
159 Separate Pascal compilations can be used for the developpment of
160 big applications, libraries, etc..
161 Since these programs share procedures, variables, they must contain
162 the declarations of these objects, and these declarations must be
163 identical in the different programs.
164 It is highly recommended to use include files $INCLUDE extension
165 to include in the different sources the useful constant declarations,
166 type declarations, variable declarations and procedure or function
167 headings.
168
169
170 The pascal_cref command can be used to improve, after compilation,
171 the validity of the separate compilations by checking the conformity
172 of types of objects shared by different Pascal object segments. This
173 command scans the symbol tables of the object segments.
174
175 Example of separate Pascal compilations:
176
177 PROGRAM caller output ;
178 $IMPORT
179 'called pascal' : open, n_lines, close ;
180 'called$out_nl pascal' : write_line $
181 TYPE
182 output_type = discard terminal ;
183 VAR
184 n_lines : integer ;
185 PROCEDURE open
186 file_type : output_type ; EXTERNAL ;
187 PROCEDURE write_line
188 str : PACKED ARRAY a..b : integer OF char ; EXTERNAL ;
189
190
191 PROCEDURE close ; EXTERNAL ;
192 BEGIN
193 open terminal ;
194 ....
195 write_line 'This is a line.' ;
196 ....
197 write_line 'This is one other line.' ;
198 ....
199 close ;
200 writeln 'Number of lines written : ' n_lines ;
201 END.
202
203
204 PROGRAM called ;
205 $EXPORT
206 open, out_nl, close, n_lines $
207 TYPE
208 output_type = discard terminal ;
209 VAR
210 output_file : text ;
211 n_lines : integer ;
212
213
214 PROCEDURE open
215 file_type : output_type ;
216 BEGIN
217 CASE file_type OF
218 discard :
219 fconnect output_file 'discard_' ;
220 terminal :
221 fconnect output_file 'syn_ user_output' ;
222 END ;
223 n_lines := 0 ;
224 rewrite output_file
225 END ;
226
227
228 PROCEDURE out_nl
229 str : PACKED ARRAY a..b : integer OF char ;
230 BEGIN
231 writeln output_file str ;
232 n_lines := n_lines + 1
233 END ;
234 PROCEDURE close ;
235 BEGIN
236 fclose output_file
237 END ;
238 BEGIN
239 END.
240
241
242 Note that "called" is a kind of library. His main procedure is
243 empty and never used.
244 Such are most of the Pascal applications using separate
245 compilations. There is only one significant main procedure, which is
246 first called when the program is executed.
247
248
249 Call from Pascal to other languages:
250 This part describes the rules which must be observed when a Pascal
251 program calls a procedure written in one other language.
252
253
254 Multics Pascal allows a Pascal program to "import" external
255 procedures written in other languages and compiled by other
256 translators.
257 Since these procedures are somewhere else, they dont have any body
258 in your source program. This body is replaced by the reserved word
259 "external":
260
261
262 Examples:
263
264 PROCEDURE arg_count VAR arg_count error_code : integer ; EXTERNAL;
265
266 The "$import" directive, which takes place immediately after the
267 program header, contains informations usefull to the compiler for the
268 generation of a link to the external procedure: the name of the
269 segment containing this procedure, and the name of this procedure in
270 this segment. It contains also the name of the language in which this
271 procedure was compiled. This name can be followed by the word
272 "descriptors" meaning that this procedure is expecting for parameter
273 descriptors.
274
275
276 Examples:
277
278 $IMPORT 'cu_ pl1' : arg_count $
279
280 This program imports the PL/I procedure arg_count from the segment
281 cu_.
282
283 $IMPORT
284 'cu_ pl1' : arg_count, arg_ptr $
285 ...
286 PROCEDURE arg_count VAR arg_count error_code : integer ; EXTERNAL ;
287 PROCEDURE arg_ptr arg_no : integer ; VAR arg_addr : arg_ptr ;
288 VAR arg_len err_code : integer ; EXTERNAL ;
289
290 This program imports from the segment cu_ the procedures arg_count
291 and arg_ptr.
292
293 In the two previous examples, the name of the entry point is the
294 same than the internal Pascal name of the procedure. But this
295 internal name can be different:
296
297
298 Examples:
299
300 $IMPORT
301 'cu_$arg_countpl1' : argument_count ;
302 'cu_$arg_ptr pl1' : argument_pointer $
303 ...
304 TYPE
305 argument = PACKED ARRAY 1..256 OF CHAR ;
306 arg_ptr = ^argument ;
307 ...
308 PROCEDURE argument_count VAR arg_count error_code : integer ;
309 EXTERNAL ;
310 PROCEDURE argument_pointer arg_no : integer ; VAR arg_addr : arg_ptr ;
311 VAR arg_len err_code : integer ; EXTERNAL ;
312
313
314 Note that the following "import" specifications are equivalent:
315
316 $IMPORT 'cu_$arg_count pl1' : arg_count $
317
318 $IMPORT 'cu_ pl1' : arg_count $
319
320
321 When you want to use a procedure which was written in one other
322 language, you know this language if you wrote yourself this procedure,
323 or you can determine what is the language used looking at the
324 declaration of the procedure You probably found this declaration in a
325 manual or an info segment... It does not matter if the procedure
326 was not really written in this language, the only one thing you have
327 to know is in which language the declaration is given. For instance
328 the entry point cu_$arg_count is described using a PL/I declaration.
329 In reality it is an ALM program. It does not matter. Since this
330 program is described in the documentation with a PL/I declaration he
331 conforms to the PL/I call standards and for your Pascal program it
332 will be a PL/I program.
333
334
335 Now, you have to determine if this entry point needs descriptors.
336 This point is very important.
337 A descriptor is a data structure which is passed to the called
338 procedure and describes the type and dimensions of a parameter. This
339 descriptor is used by the generated code of the called procedure if
340 the parameter may have different sizes or dimensions. It is the only
341 whay for this procedure to find out what are the actual size or
342 dimensions of the passed parameter.
343
344
345 Descriptors are used by PL/I and FORTRAN.
346 A PL/I procedure needs descriptors when type description of at
347 least one of his parameters contains stars "*" or when it is
348 declared "options variable".
349 A FORTRAN procedure needs descriptors when type description of at
350 least one of his parameters contains stars "*".
351
352
353 If the external procedure needs descriptors, you must add the word
354 "descriptors" after the name of the language, between the parentheses.
355
356 Examples:
357
358 $IMPORT 'hcs_ pl1 descriptors' : make_seg $
359 ...
360 TYPE
361 data = ...
362 dir_name = PACKED ARRAY 1..168 OF char ;
363 entry_name, ref_name = PACKED ARRAY 1..32 OF char ;
364 data_ptr = ^data ;
365 ...
366
367
368 PROCEDURE make_seg dir : dir_name ; entry : entry_name ;
369 ref : ref_name ; mode : integer ; VAR seg_ptr : data_ptr ;
370 VAR err_code : integer ;
371 ...
372 BEGIN
373 ....
374 make_seg '>udd>PROJECT>Me>this_dir' 'this_segment' ' '
375 read_write seg_ptr error_code ;
376 IF error_code <> 0 THEN
377 BEGIN
378 ...
379
380
381 Pascal only accepts declaration of procedures which have a definite
382 -and fixed- number of parameters, which types can't change.
383 But for PL/I or FORTRAN procedures which may receive different
384 numbers of parameters, or parameters which type may change, Pascal
385 allows to declare more than one Pascal procedure, each Pascal
386 procedure corresponding to a different use of this procedure.
387
388 Examples:
389
390 $IMPORT 'ioa_$ioa_ pl1 descriptors' : ioa_1, ioa_2 $
391 ....
392 TYPE
393 char_18: PACKED ARRAY 1..18 OF char
394 ...
395 ...
396
397
398 PROCEDURE ioa_1 control_string : char_18 ; EXTERNAL ;
399 PROCEDURE ioa_2 control_string : char_18; number : integer; EXTERNAL;
400 ....
401 BEGIN
402 ....
403 IF result = 0 THEN
404 ioa_1 'The result is null'
405 ELSE
406 ioa_2 'The result is : ^d' number ;
407
408 The procedures ioa_1 and ioa_2 have the same target : the Multics
409 subroutine ioa_ which is declared "options variable". They
410 correspond to different uses of this procedure. ioa_ uses the
411 descriptors to know the number of parameters and their types.
412
413
414 Now you have to determine if the parameter has to be passed by
415 address i.e. declared with the reserved word "VAR" or by value
416 i.e. without the reserved word "VAR".
417 If the parameter is an input-output parameter or an output
418 parameter, it MUST be passed by address. If it is an input parameter,
419 it is more secure to pass it by value. But since this way of passing
420 parameters is less efficient a copy of the value is made in the stack
421 frame of the calling procedure, and is sometimes impossible if the
422 value is too big, you can pass it by address. Let's hope that the
423 called procedure works as it is supposed to and doesn't modify it!
424 Normally, even if you did not write this procedure, you must be
425 able to know which parameters are input, output or input-output
426 parameters A good documentation must say these things.
427 If you have some doubt, pass the parameter by address.
428
429
430 Now you have to give your parameters the right type which
431 corresponds to the type of the parameter the procedure is waiting for.
432
433 If the procedure does not need descriptors, declare parameter types
434 which conform to the data types equivalences given at the end of this
435 segment.
436
437
438 If the procedure needs descriptors, during the compilation, the
439 compiler looks at the types of the parameters and generates if
440 possible otherwise there is one error the descriptor for the
441 concerned language corresponding to the Pascal type of this parameter.
442
443
444 If the Pascal type is: The generated PL/I descriptor will be:
445
446 boolean fixed bin 35 aligned
447 value transmitted is the internal
448 code 1=true 0=false
449 integer fixed bin 35 aligned
450 real float bin 63 aligned
451 any typed pointer ptr aligned
452 any enumerated type fixed bin 35 aligned
453 value transmitted is the internal
454 code
455 SET OF boolean bit 2 unal
456 SET OF char bit 128 unal
457 SET OF a..b bit b+1 unal
458 string n char n varying unaligned
459
460
461 RECORD see NOTE * below
462 length : 0..n ;
463 string : PACKED ARRAY 1..n of char
464 END; char n varying unaligned
465 RECORD
466 a : any type of this
467 list excepted sets
468 ...
469 No variant part
470 END 1 aligned,
471 2 the corresponding type ,
472 ...
473
474
475 ARRAY ... OF any type of this
476 list excepted sets
477 ... the corresponding type
478 Subscripts:
479 Pascal type element.
480 Subscripts:
481 boolean 0:1
482 char 0:127
483 enumerated of n elements 0:n-1
484 numeric a..b a:b
485
486
487 * NOTE : This way of passing charn varying parameters was useful
488 in Pascal 8.02, when dynamic-strings did not exist.
489 If you want continue to use it, BE CAREFUL: The Multics PL/1
490 implementation supposes that, for these parameters, the address passed
491 is not the address of the beginning of the variable length integer
492 word but the address of the string itself. So, for these parameters,
493 pass ALWAYS BY ADDRESS the "string" field of the corresponding Pascal
494 record. This is done automatically for "string n" Pascal
495 parameters transmitted to PL1
496
497
498 Reference from Pascal to non Pascal variables:
499 Non Pascal variables can be external variables or variables
500 allocated in a data segment.
501 Pascal declarations must conform to the data type equivalences
502 given at the end of this info file.
503
504 External variables can have been created by Multics like
505 pl1_severity_ or pascal_severity_ after a compilation or may be
506 FORTRAN commons or variables declared "external static" in a PL/I
507 program. The given <external_description_string> must be
508 'external_static':
509
510
511 Examples:
512
513 $IMPORT 'external_static' : pascal_severity, common_a $
514 ....
515 VAR
516 pascal_severity_ : integer ;
517 common_a : ARRAY 1..10000 OF real ;
518
519 Variables allocated in a data segment must be referenced using the
520 name of the segment followed by the name of the variable. Data
521 segments can be generated using the Multics "create_data_segment"
522 command.
523
524
525 Examples:
526
527 $IMPORT 'common_data cds' : nbr_of_calls, last_caller$
528 ....
529 VAR
530 nbr_of_calls : integer ;
531 last_caller : RECORD
532 user : PACKED ARRAY 1..22 OF char;
533 project : PACKED ARRAY 1..9 OF char
534 END;
535
536
537 Call from PL/I to a Pascal main procedure:
538 Pascal main procedures accept arguments which can be read from
539 inside the program using ARGC and ARGV extensions. Multics PL/I
540 subroutines cu_$arg_count cu_$arg_ptr etc... can also be used.
541 These arguments must be non varying character strings. The Pascal
542 main procedure must be declared "options variables" PL/I or
543 "descriptors" FORTRAN because it needs descriptors.
544 The last argument can optionnally be an integer or fixed bin 35.
545 If this argument exists, it will be affected by the STOP Pascal
546 predefined procedure extension and can be used to contain a return
547 code if necessary It is set to zero by default if it is transmitted
548 and not affected by a STOP in the Pascal program.
549
550
551 Examples:
552
553 In a PL/I program:
554 dcl pascal_program entry optionsvariable ;
555 dcl code fixed bin 35 ;
556 dcl name char 32 ;
557 dcl string char 168 ;
558
559 call pascal_program "-arg1" "-arg2" name string ;
560
561 Or:
562
563 call pascal_program "-arg1" "-arg2" code ;
564 if code ^= 0 then
565 .....
566
567
568 For the Pascal program :
569
570 PROGRAM pascal_program ;
571 ...
572 VAR
573 error_code : integer ;
574 ....
575 BEGIN
576 ...
577 * process args etc... *
578 ...
579 IF error THEN stop error_code
580 ELSE stop 0
581 END.
582
583
584 Call from PL/I to a Pascal exported procedure or function:
585 In your PL/I program, give your procedure a name of the form:
586
587 <pascal_program_name>$<lower_case_procedure_name>
588
589 If the name of the exported procedure was added to the Pascal
590 program, you can only use the procedure name.
591 The number of parameters must be equal to the number of parameters
592 the procedure is waiting for.
593 The types of the parameters must conform to the data type
594 equivalences given at the end of this segment.
595
596 If the Pascal procedure is waiting for one conformant array, the
597 PL/I description of the corresponding array must contain star array
598 bounds for the variable dimensions. Descriptors will be passed to
599 the Pascal procedure.
600
601
602 Examples:
603
604 For the Pascal declarations:
605
606 PROGRAM pascal_program ;
607 ....
608 $EXPORT foo, get_ptr $
609 ....
610 TYPE
611 char_32 = PACKED ARRAY 1..32 OF char ;
612 data = RECORD
613 ....
614 END ;
615 data_ptr = ^data ;
616 ....
617
618
619 PROCEDURE foo VAR index : integer ;
620 VAR matrix ARRAY a..b : integer; c..d : integer OF real ;
621 string : char_32 ;
622 ....
623 BEGIN
624 .....
625 END * foo * ;
626 ....
627 FUNCTION get_ptr VAR seg_name : char_32 : data_ptr ;
628 ....
629 BEGIN
630 ....
631 END *get_ptr * ;
632
633
634 You will declare, for instance, in your PL/I program:
635
636 dcl pascal_program$foo entry fixed bin 35
637 ** float bin 63 char 32 ;
638 dcl pascal_program$get_ptr entry char 32 returns ptr ;
639
640 Note that if the Pascal program was compiled with the control
641 argument "-add_exportable_names", the names of the exported procedures
642 have been added by the compiler to the object segment, and that you
643 can, in the PL/I program, call the procedures "foo" and "get_ptr",
644 without giving the segment name.
645
646
647 Reference from PL/I to a Pascal exported variable:
648 The following example illustrates how to access a Pascal exported variable.
649
650 dcl pascalprogram$a ptr external;
651 dcl a fixed bin 35 based pascalprogram$a;
652
653 for:
654
655 program pascalprogram ;
656 ...
657 $export a $
658 var
659 a : integer ;
660
661 This convoluted method is used because a Pascal exported variable is
662 not necessarily the same as a PL/I external variable with the same
663 name. If the Pascal program above has been compiled with the
664 -private_storage -ps option, the variable "a" will be allocated in a
665 segment named "pascalprogram.defs" as pascalprogram.defs$a instead of
666 in the user free area as the *system variable a.
667
668
669 Data types equivalences:
670
671 Simple data:
672
673 PASCAL
674 PL/I alignment between brackets
675 is the default
676
677 FORTRAN integer
678 PL/I fixed bin 35 aligned
679 PL/I fixed bin 35 unaligned integer
680 PL/I fixed bin n aligned 0<n<36 numeric -2**n .. +2**n - 1
681 PL/I fixed bin aligned numeric -2**17 .. +2**17 -1
682
683 FORTRAN logical true integer = -1
684 FORTRAN logical false integer = 0
685
686 FORTRAN integer = 0
687 PL/I fixed bin 35 = 0 boolean false
688 FORTRAN integer = 1
689 PL/I fixed bin 35 = 1 boolean true
690
691 FORTRAN double precision
692 PL/I float bin 63 aligned
693 PL/I float bin 63 unaligned real
694
695 PL/I char aligned
696 PL/I char unaligned packed array 1..1 of char
697 FORTRAN character*n
698 PL/I char n unaligned
699 PL/I char n aligned packed array 1..n of char
700
701 PL/I ptr aligned any typed pointer
702 PL/I null value nil value
703
704 PL/I bit n unaligned
705 PL/I bit n aligned SET OF a .. x enumerated base type
706 with ord a = 0 and ord x = n-1
707 SET OF 0..n-1 numeric base type
708
709 PL/I char n varying aligned
710 PL/I char n varying unaligned string n
711 or : still possible. See NOTE above..
712 RECORD
713 length : 0..n ;
714 string : PACKED ARRAY 1..n OF CHAR
715 END ;
716 PL/I n char unaligned PACKED ARRAY 1..n OF char
717
718 PL/I char unal
719 PL/I char aligned PACKED ARRAY 1..1 OF char
720
721 Agregates
722
723 PL/I aligned structure which members are
724 type of any aligned type of this list
725 excepted bit strings
726 Unpacked unvariant record which fields
727 have the corresponding Pascal type.
728
729 PL/I array of aligned elements which type
730 if any type of this list excepted
731 bit strings
732 Unpacked array of corresponding
733 Pascal type element.
734
735 Fortran ONE DIMENSION array of
736 integer, or double precision Unpacked array of corresponding
737 Pascal type element.
738
739 Subscripts:
740 0:1 boolean
741 0:127 char
742 0:n-1 enumerated of n elements
743 a:b numeric a..b