1 /********************************************************************/
2 /* */
3 /* pcs_rtl.c Platform idependent process handling functions. */
4 /* Copyright (C) 1989 - 2014 Thomas Mertes */
5 /* */
6 /* This file is part of the Seed7 Runtime Library. */
7 /* */
8 /* The Seed7 Runtime Library is free software; you can */
9 /* redistribute it and/or modify it under the terms of the GNU */
10 /* Lesser General Public License as published by the Free Software */
11 /* Foundation; either version 2.1 of the License, or (at your */
12 /* option) any later version. */
13 /* */
14 /* The Seed7 Runtime Library is distributed in the hope that it */
15 /* will be useful, but WITHOUT ANY WARRANTY; without even the */
16 /* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR */
17 /* PURPOSE. See the GNU Lesser General Public License for more */
18 /* details. */
19 /* */
20 /* You should have received a copy of the GNU Lesser General */
21 /* Public License along with this program; if not, write to the */
22 /* Free Software Foundation, Inc., 51 Franklin Street, */
23 /* Fifth Floor, Boston, MA 02110-1301, USA. */
24 /* */
25 /* Module: Seed7 Runtime Library */
26 /* File: seed7/src/pcs_rtl.c */
27 /* Changes: 2014 Thomas Mertes */
28 /* Content: Platform idependent process handling functions. */
29 /* */
30 /********************************************************************/
31
32 #define LOG_FUNCTIONS 0
33 #define VERBOSE_EXCEPTIONS 0
34
35 #include "version.h"
36
37 #include "stdio.h"
38
39 #include "common.h"
40 #include "data_rtl.h"
41 #include "fil_rtl.h"
42 #include "rtl_err.h"
43 #include "pcs_drv.h"
44
45
46
47 /**
48 * Returns the error output file (stderr) of the given child process.
49 * If the standard error file of the subprocess has been redirected
50 * then this function will return NULL.
51 * @return the error output file of 'process' or
52 * CLIB_NULL_FILE, if stderr has been redirected.
53 */
pcsChildStdErr(const const_processType process)54 fileType pcsChildStdErr (const const_processType process)
55
56 {
57 fileType stdErr;
58
59 /* pcsChildStdErr */
60 if (unlikely(process == NULL)) {
61 logError(printf("pcsChildStdErr: process == NULL\n"););
62 raise_error(FILE_ERROR);
63 stdErr = NULL;
64 } else if (process->stdErr == NULL) {
65 stdErr = &nullFileRecord;
66 } else {
67 stdErr = process->stdErr;
68 stdErr->usage_count++;
69 } /* if */
70 return stdErr;
71 } /* pcsChildStdErr */
72
73
74
75 /**
76 * Returns the standard input file (stdin) of the given child process.
77 * If the standard input file of the subprocess has been redirected
78 * then this function will return NULL.
79 * @return the standard input file of 'process' or
80 * CLIB_NULL_FILE, if stdin has been redirected.
81 */
pcsChildStdIn(const const_processType process)82 fileType pcsChildStdIn (const const_processType process)
83
84 {
85 fileType stdIn;
86
87 /* pcsChildStdIn */
88 if (unlikely(process == NULL)) {
89 logError(printf("pcsChildStdIn: process == NULL\n"););
90 raise_error(FILE_ERROR);
91 stdIn = NULL;
92 } else if (process->stdIn == NULL) {
93 stdIn = &nullFileRecord;
94 } else {
95 stdIn = process->stdIn;
96 stdIn->usage_count++;
97 } /* if */
98 return stdIn;
99 } /* pcsChildStdIn */
100
101
102
103 /**
104 * Returns the standard output file (stdout) of the given child process.
105 * If the standard output file of the subprocess has been redirected
106 * then this function will return NULL.
107 * @return the standard output file of 'process' or
108 * CLIB_NULL_FILE, if stdout has been redirected.
109 */
pcsChildStdOut(const const_processType process)110 fileType pcsChildStdOut (const const_processType process)
111
112 {
113 fileType stdOut;
114
115 /* pcsChildStdOut */
116 if (unlikely(process == NULL)) {
117 logError(printf("pcsChildStdOut: process == NULL\n"););
118 raise_error(FILE_ERROR);
119 stdOut = NULL;
120 } else if (process->stdOut == NULL) {
121 stdOut = &nullFileRecord;
122 } else {
123 stdOut = process->stdOut;
124 stdOut->usage_count++;
125 } /* if */
126 return stdOut;
127 } /* pcsChildStdOut */
128
129
130
131 /**
132 * Reinterpret the generic parameters as processType and call pcsCmp.
133 * Function pointers in C programs generated by the Seed7 compiler
134 * may point to this function. This assures correct behaviour even
135 * if sizeof(genericType) != sizeof(processType).
136 * @return -1, 0 or 1 if the first argument is considered to be
137 * respectively less than, equal to, or greater than the
138 * second.
139 */
pcsCmpGeneric(const genericType value1,const genericType value2)140 intType pcsCmpGeneric (const genericType value1, const genericType value2)
141
142 { /* pcsCmpGeneric */
143 return pcsCmp(((const_rtlObjectType *) &value1)->value.processValue,
144 ((const_rtlObjectType *) &value2)->value.processValue);
145 } /* pcsCmpGeneric */
146
147
148
149 /**
150 * Assign source to *dest.
151 * A copy function assumes that *dest contains a legal value.
152 */
pcsCpy(processType * const dest,const processType source)153 void pcsCpy (processType *const dest, const processType source)
154
155 { /* pcsCpy */
156 logFunction(printf("pcsCpy(" FMT_U_MEM " (usage=" FMT_U "), "
157 FMT_U_MEM " (usage=" FMT_U "))\n",
158 (memSizeType) *dest,
159 *dest != NULL ? (*dest)->usage_count : (uintType) 0,
160 (memSizeType) source,
161 source != NULL ? source->usage_count : (uintType) 0););
162 if (source != NULL) {
163 source->usage_count++;
164 } /* if */
165 if (*dest != NULL) {
166 (*dest)->usage_count--;
167 if ((*dest)->usage_count == 0) {
168 pcsFree(*dest);
169 } /* if */
170 } /* if */
171 *dest = source;
172 logFunction(printf("pcsCpy(" FMT_U_MEM " (usage=" FMT_U "), "
173 FMT_U_MEM " (usage=" FMT_U ")) -->\n",
174 (memSizeType) *dest,
175 *dest != NULL ? (*dest)->usage_count : (uintType) 0,
176 (memSizeType) source,
177 source != NULL ? source->usage_count : (uintType) 0););
178 } /* pcsCpy */
179
180
181
182 /**
183 * Reinterpret the generic parameters as processType and call pcsCpy.
184 * Function pointers in C programs generated by the Seed7 compiler
185 * may point to this function. This assures correct behaviour even
186 * if sizeof(genericType) != sizeof(processType).
187 */
pcsCpyGeneric(genericType * const dest,const genericType source)188 void pcsCpyGeneric (genericType *const dest, const genericType source)
189
190 { /* pcsCpyGeneric */
191 pcsCpy(&((rtlObjectType *) dest)->value.processValue,
192 ((const_rtlObjectType *) &source)->value.processValue);
193 } /* pcsCpyGeneric */
194
195
196
197 /**
198 * Return a copy of source, that can be assigned to a new destination.
199 * It is assumed that the destination of the assignment is undefined.
200 * Create functions can be used to initialize Seed7 constants.
201 * @return a copy of source.
202 */
pcsCreate(const processType source)203 processType pcsCreate (const processType source)
204
205 { /* pcsCreate */
206 logFunction(printf("pcsCreate(" FMT_U_MEM ") (usage=" FMT_U ")\n",
207 (memSizeType) source,
208 source != NULL ? source->usage_count : (uintType) 0););
209 if (source != NULL) {
210 source->usage_count++;
211 } /* if */
212 logFunction(printf("pcsCreate --> " FMT_U_MEM " (usage=" FMT_U ")\n",
213 (memSizeType) source,
214 source != NULL ? source->usage_count : (uintType) 0););
215 return source;
216 } /* pcsCreate */
217
218
219
220 /**
221 * Generic Create function to be used via function pointers.
222 * Function pointers in C programs generated by the Seed7 compiler
223 * may point to this function. This assures correct behaviour even
224 * if sizeof(genericType) != sizeof(processType).
225 */
pcsCreateGeneric(const genericType from_value)226 genericType pcsCreateGeneric (const genericType from_value)
227
228 {
229 rtlObjectType result;
230
231 /* pcsCreateGeneric */
232 INIT_GENERIC_PTR(result.value.genericValue);
233 result.value.processValue =
234 pcsCreate(((const_rtlObjectType *) &from_value)->value.processValue);
235 return result.value.genericValue;
236 } /* pcsCreateGeneric */
237
238
239
240 /**
241 * Free the memory referred by 'oldProcess'.
242 * After pcsDestr is left 'oldProcess' refers to not existing memory.
243 * The memory where 'oldProcess' is stored can be freed afterwards.
244 */
pcsDestr(const processType oldProcess)245 void pcsDestr (const processType oldProcess)
246
247 { /* pcsDestr */
248 logFunction(printf("pcsDestr(" FMT_U_MEM ") (usage=" FMT_U ")\n",
249 (memSizeType) oldProcess,
250 oldProcess != NULL ? oldProcess->usage_count : (uintType) 0););
251 if (oldProcess != NULL) {
252 oldProcess->usage_count--;
253 if (oldProcess->usage_count == 0) {
254 if (oldProcess->stdIn != NULL) {
255 filClose(oldProcess->stdIn);
256 filDestr(oldProcess->stdIn);
257 } /* if */
258 if (oldProcess->stdOut != NULL) {
259 filClose(oldProcess->stdOut);
260 filDestr(oldProcess->stdOut);
261 } /* if */
262 if (oldProcess->stdErr != NULL) {
263 filClose(oldProcess->stdErr);
264 filDestr(oldProcess->stdErr);
265 } /* if */
266 pcsFree(oldProcess);
267 } /* if */
268 } /* if */
269 } /* pcsDestr */
270
271
272
273 /**
274 * Generic Destr function to be used via function pointers.
275 * Function pointers in C programs generated by the Seed7 compiler
276 * may point to this function. This assures correct behaviour even
277 * if sizeof(genericType) != sizeof(processType).
278 */
pcsDestrGeneric(const genericType old_value)279 void pcsDestrGeneric (const genericType old_value)
280
281 { /* pcsDestrGeneric */
282 pcsDestr(((const_rtlObjectType *) &old_value)->value.processValue);
283 } /* pcsDestrGeneric */
284