Commit | Line | Data |
---|---|---|
78bc553a WJ |
1 | /* Copyright (C) 1989, 1992 Aladdin Enterprises. All rights reserved. |
2 | Distributed by Free Software Foundation, Inc. | |
3 | ||
4 | This file is part of Ghostscript. | |
5 | ||
6 | Ghostscript is distributed in the hope that it will be useful, but | |
7 | WITHOUT ANY WARRANTY. No author or distributor accepts responsibility | |
8 | to anyone for the consequences of using it or for whether it serves any | |
9 | particular purpose or works at all, unless he says so in writing. Refer | |
10 | to the Ghostscript General Public License for full details. | |
11 | ||
12 | Everyone is granted permission to copy, modify and redistribute | |
13 | Ghostscript, but only under the conditions described in the Ghostscript | |
14 | General Public License. A copy of this license is supposed to have been | |
15 | given to you along with Ghostscript so you can know your rights and | |
16 | responsibilities. It should be in a file named COPYING. Among other | |
17 | things, the copyright notice and this notice must be preserved on all | |
18 | copies. */ | |
19 | ||
20 | /* oper.h */ | |
21 | /* Definitions for Ghostscript operators */ | |
22 | #include "ostack.h" | |
23 | #include "opdef.h" | |
24 | #include "gsutil.h" | |
25 | #include "iutil.h" | |
26 | ||
27 | /* Structure for initializing variables that hold name constants. */ | |
28 | typedef struct { | |
29 | const char _ds *vname; | |
30 | ref _ds *pvref; | |
31 | } names_def; | |
32 | #define names_def_end {(char _ds *)0, (ref _ds *)0} | |
33 | extern void init_names(P1(const names_def _ds *)); | |
34 | ||
35 | /* Operand stack manipulation */ | |
36 | /* The most efficient code is different depending on the compiler.... */ | |
37 | #ifdef __MSDOS__ /* stupid compilers */ | |
38 | #define push(n)\ | |
39 | if ( (op += (n)) > ostop ) return (e_stackoverflow); else osp += (n) | |
40 | #else /* reasonable compiler */ | |
41 | #define push(n)\ | |
42 | if ( (osp = op += (n)) > ostop ) return (osp -= (n), e_stackoverflow) | |
43 | #endif | |
44 | /* | |
45 | * Note that the pop macro only decrements osp, not op. For this reason, | |
46 | * | |
47 | * >>> pop should only be used just before returning, <<< | |
48 | * >>> or else op must be decremented explicitly. <<< | |
49 | */ | |
50 | #define pop(n) (osp -= (n)) | |
51 | /* | |
52 | * Note that the interpreter does not check for operand stack underflow | |
53 | * before calling the operator procedure. There are "guard" entries | |
54 | * with invalid types and attributes just below the bottom of the | |
55 | * operand stack: if the operator returns with a typecheck error, | |
56 | * the interpreter checks for underflow at that time. | |
57 | * Operators that don't typecheck their arguments must check for | |
58 | * operand stack underflow explicitly. | |
59 | */ | |
60 | #define os_max_nargs 6 | |
61 | extern os_ptr osp_nargs[os_max_nargs]; | |
62 | #define op_nargs_check(nargs) osp_nargs[(nargs) - 1] | |
63 | #define check_op(nargs)\ | |
64 | if ( op < op_nargs_check(nargs) ) return e_stackunderflow | |
65 | ||
66 | /* Check type */ | |
67 | #define check_type(rf,typ)\ | |
68 | if ( !r_has_type(&rf,typ) ) return e_typecheck | |
69 | /* Check for array */ | |
70 | #define check_array_else(rf,err)\ | |
71 | if ( !r_has_type(&rf, t_array) ) return err | |
72 | #define check_array(rf) check_array_else(rf, e_typecheck) | |
73 | /* Check for procedure */ | |
74 | #define check_proc(rf)\ | |
75 | switch ( r_type_xe(&rf) )\ | |
76 | { default:\ | |
77 | return(r_has_attrs(&rf, a_execute + a_executable) ? e_typecheck :\ | |
78 | e_invalidaccess);\ | |
79 | case type_xe_value(t_array, a_execute + a_executable):\ | |
80 | case type_xe_value(t_mixedarray, a_execute + a_executable):\ | |
81 | case type_xe_value(t_shortarray, a_execute + a_executable): ;\ | |
82 | } | |
83 | ||
84 | /* Check for read, write, or execute access. */ | |
85 | #define check_access(rf,acc1)\ | |
86 | if ( !r_has_attr(&rf,acc1) ) return e_invalidaccess | |
87 | #define check_read(rf) check_access(rf,a_read) | |
88 | #define check_type_access(rf,typ,acc1)\ | |
89 | if ( !r_has_type_attrs(&rf,typ,acc1) )\ | |
90 | return (r_has_attr(&rf,acc1) ? e_typecheck : e_invalidaccess) | |
91 | #define check_read_type(rf,typ) check_type_access(rf,typ,a_read) | |
92 | #define check_write(rf) check_access(rf,a_write) | |
93 | #define check_write_type(rf,typ) check_type_access(rf,typ,a_write) | |
94 | #define check_execute(rf) check_access(rf,a_execute) | |
95 | ||
96 | /* Macro for as yet unimplemented operators. */ | |
97 | /* The if ( 1 ) is to prevent the compiler from complaining about */ | |
98 | /* unreachable code. */ | |
99 | #define NYI(msg) if ( 1 ) return e_undefined | |
100 | ||
101 | /* | |
102 | * If an operator has popped or pushed something on the control stack, | |
103 | * it must return o_pop_estack or o_push_estack respectively, | |
104 | * rather than 0, to indicate success. | |
105 | * It is OK to return o_pop_estack if nothing has been popped, | |
106 | * but it is not OK to return o_push_estack if nothing has been pushed. | |
107 | * | |
108 | * If an operator has suspended the current context and wants the | |
109 | * interpreter to call the scheduler, it must return o_reschedule. | |
110 | * It may also have pushed or popped elements on the control stack. | |
111 | * (This is only used when the Display PostScript option is included.) | |
112 | * | |
113 | * These values must be positive, and far enough apart from zero and | |
114 | * from each other not to tempt a compiler into implementing a 'switch' | |
115 | * on them using indexing rather than testing. | |
116 | */ | |
117 | #define o_push_estack 3 | |
118 | #define o_pop_estack 8 | |
119 | #define o_reschedule 14 |