1 /* pvm.h - Poke Virtual Machine.  */
2 
3 /* Copyright (C) 2019, 2020, 2021 Jose E. Marchesi */
4 
5 /* This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 /* This is the public interface of the Poke Virtual Machine (PVM)
20    services as provided by libpoke.  */
21 
22 #ifndef PVM_H
23 #define PVM_H
24 
25 #include <config.h>
26 #include <stdarg.h>
27 
28 #include "ios.h"
29 
30 /* **************** Status Codes **************** */
31 
32 /* The following status codes are used in the several APIs defined
33    below in the file.  */
34 
35 #define PVM_OK      0 /* The operation was performed to completion, in
36                          the expected way.  */
37 #define PVM_ERROR  -1 /* An unspecified error condition happened.  */
38 #define PVM_EINVAL -3 /* Invalid argument.  */
39 #define PVM_EINSN  -4 /* Malformed instruction.  */
40 
41 /* **************** PVM Values **************** */
42 
43 /* The pvm_val type implements values that are native to the poke
44    virtual machine.
45 
46    It is fundamental for pvm_val values to fit in 64 bits, in order to
47    avoid expensive allocations and to also improve the performance of
48    the virtual machine.  */
49 
50 typedef uint64_t pvm_val;
51 
52 /* PVM_NULL is an invalid pvm_val.  */
53 
54 #define PVM_NULL 0x7ULL
55 
56 /* **************** PVM Programs ****************  */
57 
58 /* PVM programs are sequences of instructions, labels and directives,
59    that can be run in the virtual machine.  */
60 
61 typedef struct pvm_program *pvm_program;
62 
63 /* Each PVM program can contain zero or more labels.  Labels are used
64    as targets of branch instructions.  */
65 
66 typedef int pvm_program_label;
67 
68 /* The PVM features a set of registers.
69    XXX  */
70 
71 typedef unsigned int pvm_register;
72 
73 /* Create a new PVM program.
74 
75    The created program is returned.  If there is a problem creating
76    the program then this function returns NULL.  */
77 
78 pvm_program pvm_program_new (void);
79 
80 /* Destroy the given PVM program.  */
81 
82 void pvm_destroy_program (pvm_program program);
83 
84 /* Make the given PVM program executable so it can be run in the PVM.
85 
86    This function returns a status code indicating whether the
87    operation was successful or not.  */
88 
89 int pvm_program_make_executable (pvm_program program);
90 
91 /* Print a native disassembly of the given program in the standard
92    output.  */
93 
94 void pvm_disassemble_program_nat (pvm_program program);
95 
96 /* Print a disassembly of the given program in the standard
97    output.  */
98 
99 void pvm_disassemble_program (pvm_program program);
100 
101 /* **************** Assembling PVM Programs ****************  */
102 
103 /* Assembling a PVM program involves starting with an empty program
104    and then appending its components, like labels and instructions.
105 
106    For each instruction, you need to append its parameters before
107    appending the instruction itself.  For example, in order to build
108    an instruction `foo 1, 2', you would need to:
109 
110      append parameter 1
111      append parameter 2
112      append instruction foo
113 
114    All the append functions below return a status code.  */
115 
116 /* Create a fresh label for the given program and return it.  This
117    label should be eventually appended to the program.  */
118 
119 pvm_program_label pvm_program_fresh_label (pvm_program program);
120 
121 /* Append a PVM value instruction parameter to a PVM program.
122 
123    PROGRAM is the program in which to append the parameter.
124    VAL is the PVM value to use as the instruction parameter.  */
125 
126 int pvm_program_append_val_parameter (pvm_program program,
127                                       pvm_val val);
128 
129 /* Append an unsigned integer literal instruction parameter to a PVM
130    program.
131 
132    PROGRAM is the program in which to append the parameter.
133    N is the literal to use as the instruction parameter.  */
134 
135 int pvm_program_append_unsigned_parameter (pvm_program program,
136                                            unsigned int n);
137 
138 /* Append a PVM register instruction parameter to a PVM program.
139 
140    PROGRAM is the program in which to append the parameter.
141    REG is the PVM register to use as the instruction parameter.
142 
143    If REG is not a valid register this function returns
144    PVM_EINVAL.  */
145 
146 int pvm_program_append_register_parameter (pvm_program program,
147                                            pvm_register reg);
148 
149 /* Appenda PVM label instruction parameter to a PVM program.
150 
151    PROGRAM is the program in which to append the parameter.
152    LABEL is the PVM label to use as the instruction parameter.
153 
154    If LABEL is not a label in PROGRAM, this function returns
155    PVM_EINVAL.  */
156 
157 int pvm_program_append_label_parameter (pvm_program program,
158                                         pvm_program_label label);
159 
160 /* Append an instruction to a PVM program.
161 
162    PROGRAM is the program in which to append the instruction.
163    INSN_NAME is the name of the instruction to append.
164 
165    If there is no instruction named INSN_NAME, this function returns
166    PVM_EINVAL.
167 
168    If not all the parameters required by the instruction have been
169    already appended, this function returns PVM_EINSN.  */
170 
171 int pvm_program_append_instruction (pvm_program program,
172                                     const char *insn_name);
173 
174 /* Append a `push' instruction to a PVM program.
175 
176    Due to a limitation of Jitter, we can't build push instructions the
177    usual way.  This function should be used instead.
178 
179    PROGRAM is the program in which to append the instruction.
180    VAL is the PVM value that will be pushed by the instruction.  */
181 
182 int pvm_program_append_push_instruction (pvm_program program,
183                                          pvm_val val);
184 
185 /* Append a PVM label to a PVM program.
186 
187    PROGRAM is the program in which to append the label.
188    LABEL is the PVM label to append.
189 
190    If LABEL doesn't exist in PROGRAM this function return
191    PVM_EINVAL.  */
192 
193 int pvm_program_append_label (pvm_program program,
194                               pvm_program_label label);
195 
196 /* **************** Building PVM Values **************** */
197 
198 /* Make signed and unsigned integer PVM values.
199    SIZE is measured in bits and should be in the range 1 to 32.  */
200 
201 pvm_val pvm_make_int (int32_t value, int size);
202 
203 pvm_val pvm_make_uint (uint32_t value, int size);
204 
205 /* Make signed and unsigned long PVM values.
206    SIZE is measured in bits and should be in the range 1 to 64.  */
207 
208 pvm_val pvm_make_long (int64_t value, int size);
209 
210 pvm_val pvm_make_ulong (uint64_t value, int size);
211 
212 /* Make a string PVM value.  */
213 
214 pvm_val pvm_make_string (const char *value);
215 
216 /* Make an offset PVM value.
217 
218    MAGNITUDE is a PVM integral value.
219 
220    UNIT is an ulong<64> PVM value specifying the unit of the offset,
221    in terms of the basic unit which is the bit.  */
222 
223 pvm_val pvm_make_offset (pvm_val magnitude, pvm_val unit);
224 
225 /* Make an array PVM value.
226 
227    NELEM is an ulong<64> PVM value specifying the number of elements
228    in the array.
229 
230    TYPE is a type PVM value specifying the type of the array.
231 
232    The elements in the created array are initialized to PVM_NULL.  */
233 
234 pvm_val pvm_make_array (pvm_val nelem, pvm_val type);
235 
236 /* Make a struct PVM value.
237 
238    NFIELDS is an ulong<64> PVM value specifying the number of fields
239    in the struct.  This can be ulong<64>0 for an empty struct.
240 
241    NMETHODS is an ulong<64> PVM vlaue specifying the number of methods
242    in the struct.
243 
244    TYPE is a type PVM value specifying the type of the struct.
245 
246    The fields and methods in the created struct are initialized to
247    PVM_NULL.  */
248 
249 pvm_val pvm_make_struct (pvm_val nfields, pvm_val nmethods, pvm_val type);
250 
251 /* Make a closure PVM value.
252    PROGRAM is a PVM program that conforms the body of the closure.  */
253 
254 pvm_val pvm_make_cls (pvm_program program);
255 
256 /* Compare two PVM values.
257 
258    Returns 1 if they match, 0 otherwise.  */
259 
260 int pvm_val_equal_p (pvm_val val1, pvm_val val2);
261 
262 /*** PVM values.  ***/
263 
264 void pvm_print_string (pvm_val string);
265 
266 pvm_val pvm_ref_struct (pvm_val sct, pvm_val name);
267 pvm_val pvm_ref_struct_cstr (pvm_val sct, const char *name);
268 
269 /* Given a struct value SCT and the name of a field in NAME, return
270    the bit-offset of the referred field in BOFF.
271 
272    If the referred field doesn't exist in the given struct, or if it
273    is an absent field, then this function returns PVM_NULL.  */
274 pvm_val pvm_refo_struct (pvm_val sct, pvm_val name);
275 
276 int pvm_set_struct (pvm_val sct, pvm_val name, pvm_val val);
277 
278 pvm_val pvm_get_struct_method (pvm_val sct, const char *name);
279 
280 pvm_val pvm_make_integral_type (pvm_val size, pvm_val signed_p);
281 
282 pvm_val pvm_make_string_type (void);
283 
284 pvm_val pvm_make_void_type (void);
285 
286 pvm_val pvm_make_any_type (void);
287 
288 pvm_val pvm_make_array_type (pvm_val type, pvm_val bound);
289 
290 pvm_val pvm_make_struct_type (pvm_val nfields, pvm_val name,
291                               pvm_val *fnames, pvm_val *ftypes);
292 
293 pvm_val pvm_make_offset_type (pvm_val base_type, pvm_val unit);
294 pvm_val pvm_make_closure_type (pvm_val rtype, pvm_val nargs,
295                                pvm_val *atypes);
296 
297 pvm_val pvm_dup_type (pvm_val type);
298 
299 pvm_val pvm_typeof (pvm_val val);
300 
301 int pvm_type_equal_p (pvm_val type1, pvm_val type2);
302 
303 pvm_program pvm_val_cls_program (pvm_val cls);
304 
305 /* Insert the value VAL in the array ARR past to the last element.
306    IDX is an ulong<64> denoting the index of the new element.
307 
308    More than one element may be created, depending on the provided
309    index.  In that case, all the new elements contain a copy of VAL.
310 
311    If the index corresponds to an existing element, then return 0.
312    Otherwise return 1.  */
313 
314 int pvm_array_insert (pvm_val arr, pvm_val idx, pvm_val val);
315 
316 /* Set VAL as the value of the element occupying the position IDX in
317    the array ARR.
318 
319    If IDX is not within the boundaries of the array, return 0.
320    Otherwise return 1.  */
321 
322 int pvm_array_set (pvm_val arr, pvm_val idx, pvm_val val);
323 
324 /* Remove the element at position IDX from the array ARR.
325 
326    If IDX is not within the boundaries of the array, return 0.
327    Otherwise return 1.  */
328 
329 int pvm_array_rem (pvm_val arr, pvm_val idx);
330 
331 /* Return the size of VAL, in bits.  */
332 
333 uint64_t pvm_sizeof (pvm_val val);
334 
335 /* For strings, arrays and structs, return the number of
336    elements/fields stored, as an unsigned 64-bits long.  Return 1
337    otherwise.  */
338 
339 pvm_val pvm_elemsof (pvm_val val);
340 
341 /* Return the mapper function for the given value, and the writer
342    function.  If the value is not mapped, return PVM_NULL.  */
343 
344 pvm_val pvm_val_mapper (pvm_val val);
345 
346 pvm_val pvm_val_writer (pvm_val val);
347 
348 /* Relocate the given value to the given bit-offset.  If the value is
349    not map-able then this is a no-operation.  */
350 
351 void pvm_val_reloc (pvm_val val, pvm_val ios, pvm_val boffset);
352 
353 /* Undo the last relocation performed on the given value.  If the
354    value is not map-able then this is a no-operation.  */
355 
356 void pvm_val_ureloc (pvm_val val);
357 
358 /* Recursively unmap the given value.  If the given value is not
359    map-able then this is a no-operation.  */
360 void pvm_val_unmap (pvm_val val);
361 
362 /* Return a PVM value for an exception with the given CODE, MESSAGE
363    and EXIT_STATUS.  */
364 
365 pvm_val pvm_make_exception (int code, char *message, int exit_status);
366 
367 
368 /* **************** The Run-Time Environment ****************  */
369 
370 /* The poke virtual machine (PVM) maintains a data structure called
371    the run-time environment.  This structure contains run-time frames,
372    which in turn store the variables of PVM routines.
373 
374    A set of PVM instructions are provided to allow programs to
375    manipulate the run-time environment.  These are implemented in
376    pvm.jitter in the "Environment instructions" section, and
377    summarized here:
378 
379    `pushf' pushes a new frame to the run-time environment.  This is
380    used when entering a new environment, such as a function.
381 
382    `popf' pops a frame from the run-time environment.  After this
383    happens, if no references are left to the popped frame, both the
384    frame and the variables stored in the frame are eventually
385    garbage-collected.
386 
387    `popvar' pops the value at the top of the main stack and creates a
388    new variable in the run-time environment to hold that value.
389 
390    `pushvar BACK, OVER' retrieves the value of a variable from the
391    run-time environment and pushes it in the main stack.  BACK is the
392    number of frames to traverse and OVER is the order of the variable
393    in its containing frame.  The BACK,OVER pairs (also known as
394    lexical addresses) are produced by the compiler; see `pkl-env.h'
395    for a description of the compile-time environment.
396 
397    This header file provides the prototypes for the functions used to
398    implement the above-mentioned PVM instructions.  */
399 
400 typedef struct pvm_env *pvm_env;  /* Struct defined in pvm-env.c */
401 
402 /* Create a new run-time environment, containing an empty top-level
403    frame, and return it.
404 
405    HINT specifies the expected number of variables that will be
406    registered in this environment.  If HINT is 0 it indicates that we
407    can't provide an estimation.  */
408 
409 pvm_env pvm_env_new (int hint);
410 
411 /* Push a new empty frame to ENV and return the modified run-time
412    environment.
413 
414    HINT provides a hint on the number of entries that will be stored
415    in the frame.  If HINT is 0, it indicates the number can't be
416    estimated at all.  */
417 
418 pvm_env pvm_env_push_frame (pvm_env env, int hint);
419 
420 /* Pop a frame from ENV and return the modified run-time environment.
421    The popped frame will eventually be garbage-collected if there are
422    no more references to it.  Trying to pop the top-level frame is an
423    error.  */
424 
425 pvm_env pvm_env_pop_frame (pvm_env env);
426 
427 /* Create a new variable in the current frame of ENV, whose value is
428    VAL.  */
429 
430 void pvm_env_register (pvm_env env, pvm_val val);
431 
432 /* Return the value for the variable occupying the position BACK, OVER
433    in the run-time environment ENV.  Return PVM_NULL if the variable
434    is not found.  */
435 
436 pvm_val pvm_env_lookup (pvm_env env, int back, int over);
437 
438 /* Set the value of the variable occupying the position BACK, OVER in
439    the run-time environment ENV to VAL.  */
440 
441 void pvm_env_set_var (pvm_env env, int back, int over, pvm_val val);
442 
443 /* Return 1 if the given run-time environment ENV contains only one
444    frame.  Return 0 otherwise.  */
445 
446 int pvm_env_toplevel_p (pvm_env env);
447 
448 /* Return the toplevel frame of the given environment.  */
449 
450 pvm_env pvm_env_toplevel (pvm_env env);
451 
452 /*** Other Definitions.  ***/
453 
454 enum pvm_omode
455   {
456     PVM_PRINT_FLAT,
457     PVM_PRINT_TREE,
458   };
459 
460 /* The following enumeration contains every possible exit code
461    resulting from the execution of a routine in the PVM.
462 
463    PVM_EXIT_OK is returned if the routine was executed successfully,
464    and every raised exception was properly handled.
465 
466    PVM_EXIT_ERROR is returned in case of an unhandled exception.  */
467 
468 enum pvm_exit_code
469   {
470     PVM_EXIT_OK = 0,
471     PVM_EXIT_ERROR = 1
472   };
473 
474 /* Exceptions.  These should be in sync with the exception code
475    variables, and the exception messages, declared in pkl-rt.pkl */
476 
477 #define PVM_E_GENERIC       0
478 #define PVM_E_GENERIC_MSG "generic"
479 #define PVM_E_GENERIC_ESTATUS 1
480 
481 #define PVM_E_DIV_BY_ZERO   1
482 #define PVM_E_DIV_BY_ZERO_MSG "division by zero"
483 #define PVM_E_DIV_BY_ZERO_ESTATUS 1
484 
485 #define PVM_E_NO_IOS        2
486 #define PVM_E_NO_IOS_MSG "no IOS"
487 #define PVM_E_NO_IOS_ESTATUS 1
488 
489 #define PVM_E_NO_RETURN     3
490 #define PVM_E_NO_RETURN_MSG "no return"
491 #define PVM_E_NO_RETURN_ESTATUS 1
492 
493 #define PVM_E_OUT_OF_BOUNDS 4
494 #define PVM_E_OUT_OF_BOUNDS_MSG "out of bounds"
495 #define PVM_E_OUT_OF_BOUNDS_ESTATUS 1
496 
497 #define PVM_E_MAP_BOUNDS    5
498 #define PVM_E_MAP_BOUNDS_MSG "out of map bounds"
499 #define PVM_E_MAP_BOUNDS_ESTATUS 1
500 
501 #define PVM_E_EOF           6
502 #define PVM_E_EOF_MSG "EOF"
503 #define PVM_E_EOF_ESTATUS 1
504 
505 #define PVM_E_MAP           7
506 #define PVM_E_MAP_MSG "no map"
507 #define PVM_E_MAP_ESTATUS 1
508 
509 #define PVM_E_CONV          8
510 #define PVM_E_CONV_MSG "conversion error"
511 #define PVM_E_CONV_ESTATUS 1
512 
513 #define PVM_E_ELEM          9
514 #define PVM_E_ELEM_MSG "invalid element"
515 #define PVM_E_ELEM_ESTATUS 1
516 
517 #define PVM_E_CONSTRAINT   10
518 #define PVM_E_CONSTRAINT_MSG "constraint violation"
519 #define PVM_E_CONSTRAINT_ESTATUS 1
520 
521 #define PVM_E_IO           11
522 #define PVM_E_IO_MSG "generic IO"
523 #define PVM_E_IO_ESTATUS 1
524 
525 #define PVM_E_SIGNAL       12
526 #define PVM_E_SIGNAL_MSG ""
527 #define PVM_E_SIGNAL_ESTATUS 1
528 
529 #define PVM_E_IOFLAGS      13
530 #define PVM_E_IOFLAGS_MSG "invalid IO flags"
531 #define PVM_E_IOFLAGS_ESTATUS 1
532 
533 #define PVM_E_INVAL        14
534 #define PVM_E_INVAL_MSG "invalid argument"
535 #define PVM_E_INVAL_ESTATUS 1
536 
537 #define PVM_E_EXIT         15
538 #define PVM_E_EXIT_MSG ""
539 #define PVM_E_EXIT_ESTATUS 0
540 
541 #define PVM_E_ASSERT       16
542 #define PVM_E_ASSERT_MSG "assertion failure"
543 #define PVM_E_ASSERT_ESTATUS 1
544 
545 #define PVM_E_OVERFLOW     17
546 #define PVM_E_OVERFLOW_MSG "overflow"
547 #define PVM_E_OVERFLOW_ESTATUS 1
548 
549 typedef struct pvm *pvm;
550 
551 /* Initialize a new Poke Virtual Machine and return it.  */
552 
553 pvm pvm_init (void);
554 
555 /* Finalize a Poke Virtual Machine, freeing all used resources.  */
556 
557 void pvm_shutdown (pvm pvm);
558 
559 /* Get the current run-time environment of PVM.  */
560 
561 pvm_env pvm_get_env (pvm pvm);
562 
563 /* Print a profiling summary corresponding to the currrent state of
564    the PVM.  */
565 
566 void pvm_print_profile (pvm pvm);
567 
568 /* Reset profiling counters in the given PVM.  */
569 
570 void pvm_reset_profile (pvm pvm);
571 
572 /* Run a PVM program in a virtual machine.
573 
574    If the execution of PROGRAM generates a result value, it is put in
575    RES.
576 
577    This function returns an exit code, indicating whether the
578    execution was successful or not.  */
579 
580 enum pvm_exit_code pvm_run (pvm vm,
581                             pvm_program program,
582                             pvm_val *res);
583 
584 /* Given a PVM and a closure value, call the closure.
585 
586    A list of pvm_val arguments terminated with PVM_NULL are passed as
587    arguments to the closure.  Note that this function doesn't allow
588    pass nulls as arguments.  */
589 
590 void pvm_call_closure (pvm vm, pvm_val cls, ...);
591 
592 /* Get/set the current byte endianness of a virtual machine.
593 
594    The current endianness is used by certain VM instructions that
595    perform IO.
596 
597    ENDIAN should be one of IOS_ENDIAN_LSB (for little-endian) or
598    IOS_ENDIAN_MSB (for big-endian).  */
599 
600 enum ios_endian pvm_endian (pvm pvm);
601 
602 void pvm_set_endian (pvm pvm, enum ios_endian endian);
603 
604 /* Get/set the current negative encoding of a virtual machine.
605 
606    The current negative encoding is used by certain VM instructions
607    that perform IO.
608 
609    NENC should be one of the IOS_NENC_* values defined in ios.h */
610 
611 enum ios_nenc pvm_nenc (pvm pvm);
612 
613 void pvm_set_nenc (pvm pvm, enum ios_nenc nenc);
614 
615 /* Get/set the pretty-print flag in a virtual machine.
616 
617    PRETTY_PRINT_P is a boolean indicating whether to use pretty print
618    methods when printing struct PVM values.  This requires the
619    presence of a compiler associated with the VM.  */
620 
621 int pvm_pretty_print (pvm pvm);
622 
623 void pvm_set_pretty_print (pvm pvm, int pretty_print_p);
624 
625 /* Get/set the output parameters configured in a virtual machine.
626 
627    OBASE is the numeration based to be used when printing PVM values.
628    Valid values are 2, 8, 10 and 16.
629 
630    OMAPS is a boolean indicating whether to show mapping information
631    when printing PVM values.
632 
633    OINDENT is a number indicating the indentation step used when
634    printing composite PVM values, measured in number of whitespace
635    characters.
636 
637    ODEPTH is the maximum depth to use when printing composite PVM
638    values.  A value of 0 indicates to not use a maximum depth, i.e. to
639    print the whole structure.
640 
641    OACUTOFF is the maximum number of elements to show when printing
642    array PVM values.  A value of 0 indicates to print all the elements
643    of arrays.  */
644 
645 int pvm_obase (pvm vm);
646 
647 void pvm_set_obase (pvm vm, int obase);
648 
649 enum pvm_omode pvm_omode (pvm vm);
650 
651 void pvm_set_omode (pvm vm, enum pvm_omode omode);
652 
653 int pvm_omaps (pvm vm);
654 
655 void pvm_set_omaps (pvm vm, int omaps);
656 
657 unsigned int pvm_oindent (pvm vm);
658 
659 void pvm_set_oindent (pvm vm, unsigned int oindent);
660 
661 unsigned int pvm_odepth (pvm vm);
662 
663 void pvm_set_odepth (pvm vm, unsigned int odepth);
664 
665 unsigned int pvm_oacutoff (pvm vm);
666 void pvm_set_oacutoff (pvm vm, unsigned int cutoff);
667 
668 /* Get/set the compiler associated to a virtual machine.
669 
670    This compiler is used when the VM needs to build programs and
671    execute them.
672 
673    It there is no compiler associated with VM, pvm_compiler returns
674    NULL.  */
675 
676 typedef struct pkl_compiler *pkl_compiler;
677 
678 pkl_compiler pvm_compiler (pvm vm);
679 
680 void pvm_set_compiler (pvm vm, pkl_compiler compiler);
681 
682 /* The following function is to be used in pvm.jitter, because the
683    system `assert' may expand to a macro and is therefore
684    non-wrappeable.  */
685 
686 void pvm_assert (int expression);
687 
688 /* This is defined in the late-c block in pvm.jitter.  */
689 
690 void pvm_handle_signal (int signal_number);
691 
692 /* Call the pretty printer of the given value VAL.  */
693 
694 int pvm_call_pretty_printer (pvm vm, pvm_val val);
695 
696 /* Print a PVM value.
697 
698    DEPTH is a number that specifies the maximum depth used when
699    printing composite values, i.e. arrays and structs.  If it is 0
700    then it means there is no maximum depth.
701 
702    MODE is one of the PVM_PRINT_* values defined in pvm_omode, and
703    specifies the output mode to use when printing the value.
704 
705    BASE is the numeration base to use when printing numbers.  It may
706    be one of 2, 8, 10 or 16.
707 
708    INDENT is the step value to use when indenting nested structured
709    when printin in tree mode.
710 
711    ACUTOFF is the maximum number of elements of arrays to print.
712    Elements beyond are not printed.
713 
714    FLAGS is a 32-bit unsigned integer, that encodes certain properties
715    to be used while printing:
716 
717    If PVM_PRINT_F_MAPS is specified then the attributes of mapped
718    values (notably their offsets) are also printed out.  When
719    PVM_PRINT_F_MAPS is not specified, mapped values are printed
720    exactly the same way than non-mapped values.
721 
722    If PVM_PRINT_F_PPRINT is specified then pretty-printers are used to
723    print struct values, if they are defined.  */
724 
725 #define PVM_PRINT_F_MAPS   1
726 #define PVM_PRINT_F_PPRINT 2
727 
728 void pvm_print_val (pvm vm, pvm_val val);
729 
730 void pvm_print_val_with_params (pvm vm, pvm_val val,
731                                 int depth,int mode, int base,
732                                 int indent, int acutoff,
733                                 uint32_t flags);
734 
735 #endif /* ! PVM_H */
736