Line data Source code
1 : /* do not edit automatically generated by mc from M2Preprocess. */
2 : /* M2Preprocess.mod provides a mechanism to invoke the C preprocessor.
3 :
4 : Copyright (C) 2001-2026 Free Software Foundation, Inc.
5 : Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>.
6 :
7 : This file is part of GNU Modula-2.
8 :
9 : GNU Modula-2 is free software; you can redistribute it and/or modify
10 : it under the terms of the GNU General Public License as published by
11 : the Free Software Foundation; either version 3, or (at your option)
12 : any later version.
13 :
14 : GNU Modula-2 is distributed in the hope that it will be useful, but
15 : WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 : General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with GNU Modula-2; see the file COPYING3. If not see
21 : <http://www.gnu.org/licenses/>. */
22 :
23 : #include "config.h"
24 : #include "system.h"
25 : #include "gcc-consolidation.h"
26 :
27 : #include <stdbool.h>
28 : # if !defined (PROC_D)
29 : # define PROC_D
30 : typedef void (*PROC_t) (void);
31 : typedef struct { PROC_t proc; } PROC;
32 : # endif
33 :
34 : # if !defined (FALSE)
35 : # define FALSE (1==0)
36 : # endif
37 :
38 : #if defined(__cplusplus)
39 : # undef NULL
40 : # define NULL 0
41 : #endif
42 : #define _M2Preprocess_C
43 :
44 : #include "GM2Preprocess.h"
45 : # include "GSYSTEM.h"
46 : # include "GDynamicStrings.h"
47 : # include "Gchoosetemp.h"
48 : # include "Gpexecute.h"
49 : # include "Glibc.h"
50 : # include "GLists.h"
51 : # include "GFIO.h"
52 : # include "GM2Printf.h"
53 : # include "GM2Options.h"
54 : # include "GNameKey.h"
55 : # include "GM2RTS.h"
56 :
57 : # define Debugging false
58 : static Lists_List ListOfFiles;
59 :
60 : /*
61 : PreprocessModule - preprocess a file, filename, returning the new filename
62 : of the preprocessed file.
63 : Preprocessing will only occur if requested by the user.
64 : If no preprocessing was requested then filename is returned.
65 : If preprocessing occurs then a temporary file is created
66 : and its name is returned.
67 : All temporary files will be deleted when the compiler exits.
68 : outputdep is the filename which will contain the dependency
69 : info if -M, -MM is provided. outputdep can be NIL in which case
70 : it is ignored.
71 : */
72 :
73 : extern "C" DynamicStrings_String M2Preprocess_PreprocessModule (DynamicStrings_String filename, bool topSource, bool deleteDep, DynamicStrings_String outputDep);
74 :
75 : /*
76 : MakeSaveTempsFileNameExt - creates and return the temporary filename.ext.
77 : in the current working directory unless
78 : SaveTempsDir = obj, when we put it in the dumpdir
79 : if that is specified (or fallback to '.' if not).
80 : */
81 :
82 : extern "C" DynamicStrings_String M2Preprocess_MakeSaveTempsFileNameExt (DynamicStrings_String filename, DynamicStrings_String ext);
83 :
84 : /*
85 : OnExitDelete - when the application finishes delete filename.
86 : */
87 :
88 : extern "C" DynamicStrings_String M2Preprocess_OnExitDelete (DynamicStrings_String filename);
89 :
90 : /*
91 : RemoveFile - removes a single file, s.
92 : */
93 :
94 : static void RemoveFile (unsigned int w);
95 :
96 : /*
97 : RemoveFiles -
98 : */
99 :
100 : static int RemoveFiles (void);
101 : static DynamicStrings_String GetFileName (DynamicStrings_String Path);
102 :
103 : /*
104 : MakeSaveTempsFileName - return a temporary file like
105 : "./filename.{def,mod}.m2i" in the current working directory unless
106 : SaveTempsDir = obj, when we put it in the dumpdir if that is specified
107 : (or fallback to '.' if not).
108 : We have to keep the original extension because that disambiguates .def
109 : and .mod files (otherwise, we'd need two 'preprocessed' extensions).
110 : */
111 :
112 : static DynamicStrings_String MakeSaveTempsFileName (DynamicStrings_String filename);
113 :
114 : /*
115 : BuildCommandLineExecute - build the cpp command line and execute the command and return
116 : the tempfile containing the preprocessed source.
117 : */
118 :
119 : static DynamicStrings_String BuildCommandLineExecute (DynamicStrings_String filename, bool topSource, bool deleteDep, DynamicStrings_String command, DynamicStrings_String outputdep);
120 :
121 :
122 : /*
123 : RemoveFile - removes a single file, s.
124 : */
125 :
126 17820 : static void RemoveFile (unsigned int w)
127 : {
128 17820 : NameKey_Name n;
129 :
130 17820 : n = static_cast<NameKey_Name> (w);
131 17820 : if (Debugging)
132 : {
133 : libc_printf ((const char *) "removing: %s\\n", 14, NameKey_KeyToCharStar (n));
134 : }
135 17820 : if ((libc_unlink (NameKey_KeyToCharStar (n))) != 0)
136 : {} /* empty. */
137 17820 : }
138 :
139 :
140 : /*
141 : RemoveFiles -
142 : */
143 :
144 14952 : static int RemoveFiles (void)
145 : {
146 14952 : Lists_ForeachItemInListDo (ListOfFiles, (SymbolKey_PerformOperation) {(SymbolKey_PerformOperation_t) RemoveFile});
147 14952 : return 0;
148 : /* static analysis guarentees a RETURN statement will be used before here. */
149 : __builtin_unreachable ();
150 : }
151 :
152 244920 : static DynamicStrings_String GetFileName (DynamicStrings_String Path)
153 : {
154 244920 : int fstart;
155 :
156 : /*
157 : Return the filename with no path.
158 : */
159 244920 : fstart = DynamicStrings_RIndex (Path, '/', 0);
160 244920 : if (fstart == -1)
161 : {
162 : fstart = 0;
163 : }
164 : else
165 : {
166 14952 : fstart = fstart+1;
167 : }
168 244920 : return DynamicStrings_Dup (DynamicStrings_Slice (Path, fstart, static_cast<int> (DynamicStrings_Length (Path))));
169 : /* static analysis guarentees a RETURN statement will be used before here. */
170 : __builtin_unreachable ();
171 : }
172 :
173 :
174 : /*
175 : MakeSaveTempsFileName - return a temporary file like
176 : "./filename.{def,mod}.m2i" in the current working directory unless
177 : SaveTempsDir = obj, when we put it in the dumpdir if that is specified
178 : (or fallback to '.' if not).
179 : We have to keep the original extension because that disambiguates .def
180 : and .mod files (otherwise, we'd need two 'preprocessed' extensions).
181 : */
182 :
183 0 : static DynamicStrings_String MakeSaveTempsFileName (DynamicStrings_String filename)
184 : {
185 0 : return M2Preprocess_MakeSaveTempsFileNameExt (filename, DynamicStrings_InitString ((const char *) ".m2i", 4));
186 : /* static analysis guarentees a RETURN statement will be used before here. */
187 : __builtin_unreachable ();
188 : }
189 :
190 :
191 : /*
192 : BuildCommandLineExecute - build the cpp command line and execute the command and return
193 : the tempfile containing the preprocessed source.
194 : */
195 :
196 2868 : static DynamicStrings_String BuildCommandLineExecute (DynamicStrings_String filename, bool topSource, bool deleteDep, DynamicStrings_String command, DynamicStrings_String outputdep)
197 : {
198 2868 : DynamicStrings_String tempfile;
199 2868 : DynamicStrings_String commandLine;
200 :
201 2868 : commandLine = DynamicStrings_Dup (command);
202 2868 : tempfile = static_cast<DynamicStrings_String> (NULL);
203 : /* We support MD and MMD for the main file only, at present. */
204 2868 : if (topSource || M2Options_PPonly)
205 : {
206 528 : if (M2Options_GetMD ())
207 : {
208 0 : tempfile = DynamicStrings_ConCat (DynamicStrings_InitString ((const char *) " -MD ", 5), outputdep);
209 : }
210 528 : else if (M2Options_GetMMD ())
211 : {
212 : /* avoid dangling else. */
213 0 : tempfile = DynamicStrings_ConCat (DynamicStrings_InitString ((const char *) " -MMD ", 6), outputdep);
214 : }
215 0 : if (tempfile != NULL)
216 : {
217 0 : commandLine = DynamicStrings_ConCat (DynamicStrings_Dup (commandLine), DynamicStrings_Dup (tempfile));
218 : /* We can only add MQ if we already have an MD/MMD. */
219 0 : if ((M2Options_GetMQ ()) != NULL)
220 : {
221 0 : tempfile = DynamicStrings_InitStringCharStar (M2Options_GetMQ ());
222 0 : commandLine = DynamicStrings_ConCat (DynamicStrings_Dup (commandLine), DynamicStrings_Dup (tempfile));
223 : }
224 : }
225 : }
226 : /* The output file depends on whether we are in stand-alone PP mode, and
227 : if an output file is specified. */
228 2868 : tempfile = static_cast<DynamicStrings_String> (NULL);
229 2868 : if (M2Options_PPonly)
230 : {
231 : /* avoid dangling else. */
232 0 : if ((M2Options_GetObj ()) != NULL)
233 : {
234 0 : tempfile = DynamicStrings_InitStringCharStar (M2Options_GetObj ());
235 : }
236 : }
237 2868 : else if (M2Options_SaveTemps)
238 : {
239 : /* avoid dangling else. */
240 0 : tempfile = MakeSaveTempsFileName (filename);
241 : }
242 : else
243 : {
244 : /* avoid dangling else. */
245 2868 : tempfile = DynamicStrings_InitStringCharStar (choosetemp_make_temp_file (NameKey_KeyToCharStar (NameKey_MakeKey ((const char *) ".m2i", 4))));
246 : }
247 2868 : commandLine = DynamicStrings_ConCat (DynamicStrings_ConCatChar (DynamicStrings_Dup (commandLine), ' '), filename);
248 2868 : if (tempfile != NULL)
249 : {
250 2868 : commandLine = DynamicStrings_ConCat (DynamicStrings_ConCat (DynamicStrings_Dup (commandLine), DynamicStrings_Mark (DynamicStrings_InitString ((const char *) " -o ", 4))), tempfile);
251 : }
252 2868 : if (((outputdep != NULL) && ((DynamicStrings_Length (outputdep)) > 0)) && ((M2Options_GetM ()) || (M2Options_GetMM ())))
253 : {
254 0 : commandLine = DynamicStrings_ConCat (commandLine, DynamicStrings_ConCat (DynamicStrings_Mark (DynamicStrings_InitString ((const char *) " -MF ", 5)), outputdep));
255 0 : if (deleteDep && ! M2Options_SaveTemps)
256 : {
257 0 : outputdep = M2Preprocess_OnExitDelete (outputdep);
258 : }
259 : }
260 : /* for now we'll use system */
261 2868 : if (M2Options_Verbose)
262 : {
263 0 : M2Printf_fprintf1 (FIO_StdOut, (const char *) "preprocess: %s\\n", 16, (const unsigned char *) &commandLine, (sizeof (commandLine)-1));
264 : }
265 2868 : if ((libc_system (DynamicStrings_string (commandLine))) != 0)
266 : {
267 0 : M2Printf_fprintf1 (FIO_StdErr, (const char *) "C preprocessor failed when preprocessing %s\\n", 45, (const unsigned char *) &filename, (sizeof (filename)-1));
268 0 : libc_exit (1);
269 : }
270 2868 : commandLine = DynamicStrings_KillString (commandLine);
271 2868 : if (M2Options_SaveTemps)
272 : {
273 : return tempfile;
274 : }
275 : else
276 : {
277 2868 : return M2Preprocess_OnExitDelete (tempfile);
278 : }
279 : /* static analysis guarentees a RETURN statement will be used before here. */
280 : __builtin_unreachable ();
281 : }
282 :
283 :
284 : /*
285 : PreprocessModule - preprocess a file, filename, returning the new filename
286 : of the preprocessed file.
287 : Preprocessing will only occur if requested by the user.
288 : If no preprocessing was requested then filename is returned.
289 : If preprocessing occurs then a temporary file is created
290 : and its name is returned.
291 : All temporary files will be deleted when the compiler exits.
292 : outputdep is the filename which will contain the dependency
293 : info if -M, -MM is provided. outputdep can be NIL in which case
294 : it is ignored.
295 : */
296 :
297 244920 : extern "C" DynamicStrings_String M2Preprocess_PreprocessModule (DynamicStrings_String filename, bool topSource, bool deleteDep, DynamicStrings_String outputDep)
298 : {
299 244920 : DynamicStrings_String command;
300 :
301 244920 : if (M2Options_GetCpp ())
302 : {
303 2868 : command = M2Options_CppCommandLine ();
304 2868 : if ((command == NULL) || (DynamicStrings_EqualArray (command, (const char *) "", 0)))
305 : {
306 0 : return DynamicStrings_Dup (filename);
307 : }
308 2868 : command = BuildCommandLineExecute (filename, topSource, deleteDep, command, outputDep);
309 2868 : if (command == NULL)
310 : {
311 : return filename;
312 : }
313 : else
314 : {
315 2868 : return command;
316 : }
317 : }
318 : else
319 : {
320 242052 : return DynamicStrings_Dup (filename);
321 : }
322 : /* static analysis guarentees a RETURN statement will be used before here. */
323 : __builtin_unreachable ();
324 : }
325 :
326 :
327 : /*
328 : MakeSaveTempsFileNameExt - creates and return the temporary filename.ext.
329 : in the current working directory unless
330 : SaveTempsDir = obj, when we put it in the dumpdir
331 : if that is specified (or fallback to '.' if not).
332 : */
333 :
334 244920 : extern "C" DynamicStrings_String M2Preprocess_MakeSaveTempsFileNameExt (DynamicStrings_String filename, DynamicStrings_String ext)
335 : {
336 244920 : DynamicStrings_String NewName;
337 244920 : DynamicStrings_String DumpDir;
338 244920 : DynamicStrings_String NewDir;
339 :
340 244920 : NewName = DynamicStrings_ConCat (DynamicStrings_Dup (GetFileName (filename)), ext);
341 244920 : NewDir = DynamicStrings_Dup (M2Options_GetSaveTempsDir ());
342 244920 : DumpDir = DynamicStrings_Dup (M2Options_GetDumpDir ());
343 244920 : if (Debugging)
344 : {
345 : M2Printf_fprintf1 (FIO_StdOut, (const char *) "newname: %s", 11, (const unsigned char *) &NewName, (sizeof (NewName)-1));
346 : M2Printf_fprintf1 (FIO_StdOut, (const char *) " NewDir: %s", 11, (const unsigned char *) &NewDir, (sizeof (NewDir)-1));
347 : M2Printf_fprintf1 (FIO_StdOut, (const char *) " DumpDir: %s\\n", 14, (const unsigned char *) &DumpDir, (sizeof (DumpDir)-1));
348 : }
349 244920 : if (((NewDir != NULL) && (DynamicStrings_EqualArray (NewDir, (const char *) "obj", 3))) && (DumpDir != NULL))
350 : {
351 0 : return DynamicStrings_ConCat (DumpDir, NewName);
352 : }
353 : else
354 : {
355 244920 : return DynamicStrings_ConCat (DynamicStrings_InitString ((const char *) "./", 2), NewName);
356 : }
357 : /* static analysis guarentees a RETURN statement will be used before here. */
358 : __builtin_unreachable ();
359 : }
360 :
361 :
362 : /*
363 : OnExitDelete - when the application finishes delete filename.
364 : */
365 :
366 17820 : extern "C" DynamicStrings_String M2Preprocess_OnExitDelete (DynamicStrings_String filename)
367 : {
368 17820 : if (filename != NULL)
369 : {
370 17820 : if (Debugging)
371 : {
372 : libc_printf ((const char *) "scheduling removal: %s\\n", 24, DynamicStrings_string (filename));
373 : }
374 17820 : Lists_IncludeItemIntoList (ListOfFiles, NameKey_makekey (DynamicStrings_string (filename)));
375 : }
376 17820 : return filename;
377 : /* static analysis guarentees a RETURN statement will be used before here. */
378 : __builtin_unreachable ();
379 : }
380 :
381 14952 : extern "C" void _M2_M2Preprocess_init (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[])
382 : {
383 14952 : Lists_InitList (&ListOfFiles);
384 14952 : if ((libc_atexit ((libc_exitP_C) RemoveFiles)) != 0)
385 : {
386 0 : M2RTS_HALT (-1);
387 : __builtin_unreachable ();
388 : }
389 14952 : }
390 :
391 0 : extern "C" void _M2_M2Preprocess_fini (__attribute__((unused)) int argc, __attribute__((unused)) char *argv[], __attribute__((unused)) char *envp[])
392 : {
393 0 : }
|