Merge 5b66163a4d into c7530dbcc1
This commit is contained in:
commit
e16b5c0d55
12
Makefile.in
12
Makefile.in
|
|
@ -59,6 +59,8 @@ SUBDIRS += driver-vpi
|
|||
# rebuild the lexor_keyword.cc file. If we do, then we want to use the
|
||||
# local version instead of the one is $(srcdir).
|
||||
vpath lexor_keyword.cc .
|
||||
vpath %.c $(srcdir)/libmisc
|
||||
vpath %.c $(srcdir)
|
||||
vpath %.cc $(srcdir)/libmisc
|
||||
vpath %.cc $(srcdir)
|
||||
|
||||
|
|
@ -109,7 +111,8 @@ M = LineInfo.o StringHeap.o
|
|||
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o t-dll-analog.o
|
||||
FF = cprop.o exposenodes.o nodangle.o synth.o synth2.o syn-rules.o
|
||||
|
||||
O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
|
||||
C_OBJ = CmdExec.o
|
||||
CXX_OBJ = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
|
||||
elab_expr.o elaborate_analog.o elab_lval.o elab_net.o \
|
||||
elab_scope.o elab_sig.o elab_sig_analog.o elab_type.o \
|
||||
emit.o eval_attrib.o \
|
||||
|
|
@ -128,6 +131,7 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
|
|||
Attrib.o HName.o Module.o PClass.o PDelays.o PEvent.o PExpr.o PFunction.o \
|
||||
PGate.o PGenerate.o PModport.o PNamedItem.o PPackage.o PScope.o PSpec.o PTimingCheck.o \
|
||||
PTask.o PUdp.o PWire.o Statement.o AStatement.o $M $(FF) $(TT)
|
||||
O = $(C_OBJ) $(CXX_OBJ)
|
||||
|
||||
all: dep config.h _pli_types.h version_tag.h version_base.h ivl@EXEEXT@
|
||||
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
|
||||
|
|
@ -174,7 +178,7 @@ ifneq (@srcdir@,.)
|
|||
endif
|
||||
rm -rf autom4te.cache
|
||||
|
||||
cppcheck: $(O:.o=.cc) $(srcdir)/dosify.c
|
||||
cppcheck: $(C_OBJ:.o=.c) $(CXX_OBJ:.o=.cc) $(srcdir)/dosify.c
|
||||
cppcheck --enable=all --std=c99 --std=c++11 -f \
|
||||
--check-level=exhaustive \
|
||||
--suppressions-list=$(srcdir)/cppcheck-global.sup \
|
||||
|
|
@ -232,6 +236,10 @@ endif
|
|||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o
|
||||
mv $*.d dep/$*.d
|
||||
|
||||
%.o: %.c config.h | dep
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o
|
||||
mv $*.d dep/$*.d
|
||||
|
||||
# Here are some explicit dependencies needed to get things going.
|
||||
main.o: main.cc version_tag.h
|
||||
|
||||
|
|
|
|||
|
|
@ -93,6 +93,10 @@ unusedFunction:vpi_modules.cc:90
|
|||
// vpi_sim_control()
|
||||
unusedFunction:vpi_modules.cc:110
|
||||
|
||||
// CmdExec.c is shared by multiple executables, so each cppcheck target sees
|
||||
// some exported helpers that are used only by another target.
|
||||
unusedFunction:libmisc/CmdExec.c
|
||||
|
||||
// These are the functions that the compiler exports to the targets.
|
||||
//ivl_branch_island()
|
||||
unusedFunction:t-dll-api.cc:39
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ builddir=@builddir@
|
|||
top_builddir=@top_builddir@
|
||||
|
||||
VPATH = $(srcdir)
|
||||
vpath %.c $(srcdir)/../libmisc
|
||||
|
||||
bindir = $(exec_prefix)/bin
|
||||
libdir = $(exec_prefix)/lib
|
||||
|
|
@ -50,16 +51,16 @@ MAN = @MAN@
|
|||
PS2PDF = @PS2PDF@
|
||||
|
||||
ifeq (@srcdir@,.)
|
||||
INCLUDE_PATH = -I. -I..
|
||||
INCLUDE_PATH = -I. -I.. -I../libmisc
|
||||
else
|
||||
INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/..
|
||||
INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../libmisc
|
||||
endif
|
||||
|
||||
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
O = main.o substit.o cflexor.o cfparse.o
|
||||
O = main.o substit.o cflexor.o cfparse.o CmdExec.o
|
||||
|
||||
all: dep iverilog@EXEEXT@ iverilog.man
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@ memleakOnRealloc
|
|||
nullPointerArithmeticOutOfMemory
|
||||
nullPointerOutOfMemory
|
||||
|
||||
// CmdExec.c is shared by multiple executables, so this target sees helpers
|
||||
// that are used only by another target.
|
||||
unusedFunction:../libmisc/CmdExec.c
|
||||
|
||||
// Errors/limitations in the generated yacc and lex files
|
||||
duplicateBreak:cflexor.lex
|
||||
constVariablePointer:cfparse.y
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ extern const char*optarg;
|
|||
#endif
|
||||
|
||||
# include "globals.h"
|
||||
# include "CmdExec.h"
|
||||
#include "cfparse_misc.h" /* cfparse() */
|
||||
#include "ivl_alloc.h"
|
||||
|
||||
|
|
@ -335,16 +336,16 @@ static int t_version_only(void)
|
|||
free(source_path);
|
||||
|
||||
fflush(0);
|
||||
snprintf(tmp, sizeof tmp, "%s%civlpp -V", ivlpp_dir, sep);
|
||||
rc = system(tmp);
|
||||
snprintf(tmp, sizeof tmp, "\"%s%civlpp\" -V", ivlpp_dir, sep);
|
||||
rc = ivl_run_cmd(tmp, verbose_flag);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "Unable to get version from \"%s\"\n", tmp);
|
||||
}
|
||||
|
||||
fflush(0);
|
||||
snprintf(tmp, sizeof tmp, "%s%civl -V -C\"%s\" -C\"%s\"", ivl_dir, sep,
|
||||
snprintf(tmp, sizeof tmp, "\"%s%civl\" -V -C\"%s\" -C\"%s\"", ivl_dir, sep,
|
||||
iconfig_path, iconfig_common_path);
|
||||
rc = system(tmp);
|
||||
rc = ivl_run_cmd(tmp, verbose_flag);
|
||||
if (rc != 0) {
|
||||
fprintf(stderr, "Unable to get version from \"%s\"\n", tmp);
|
||||
}
|
||||
|
|
@ -363,7 +364,7 @@ static int t_version_only(void)
|
|||
|
||||
static void build_preprocess_command(int e_flag)
|
||||
{
|
||||
snprintf(tmp, sizeof tmp, "%s%civlpp%s%s%s -F\"%s\" -f\"%s\" -p\"%s\"%s",
|
||||
snprintf(tmp, sizeof tmp, "\"%s%civlpp\"%s%s%s -F\"%s\" -f\"%s\" -p\"%s\"%s",
|
||||
ivlpp_dir, sep,
|
||||
verbose_flag ? " -v" : "",
|
||||
e_flag ? "" : " -L",
|
||||
|
|
@ -395,7 +396,7 @@ static int t_preprocess_only(void)
|
|||
if (verbose_flag)
|
||||
printf("preprocess: %s\n", cmd);
|
||||
|
||||
rc = system(cmd);
|
||||
rc = ivl_run_cmd(cmd, verbose_flag);
|
||||
remove(source_path);
|
||||
free(source_path);
|
||||
|
||||
|
|
@ -449,7 +450,7 @@ static int t_compile(void)
|
|||
#endif
|
||||
|
||||
/* Build the ivl command. */
|
||||
snprintf(tmp, sizeof tmp, "%s%civl", ivl_dir, sep);
|
||||
snprintf(tmp, sizeof tmp, "\"%s%civl\"", ivl_dir, sep);
|
||||
rc = strlen(tmp);
|
||||
cmd = realloc(cmd, ncmd+rc+1);
|
||||
strcpy(cmd+ncmd, tmp);
|
||||
|
|
@ -496,7 +497,7 @@ static int t_compile(void)
|
|||
printf("translate: %s\n", cmd);
|
||||
|
||||
|
||||
rc = system(cmd);
|
||||
rc = ivl_run_cmd(cmd, verbose_flag);
|
||||
if ( ! getenv("IVERILOG_ICONFIG")) {
|
||||
remove(source_path);
|
||||
free(source_path);
|
||||
|
|
@ -1484,7 +1485,7 @@ int main(int argc, char **argv)
|
|||
|
||||
if (vhdlpp_work == 0)
|
||||
vhdlpp_work = "ivl_vhdl_work";
|
||||
fprintf(defines_file, "vhdlpp:%s%cvhdlpp\n", vhdlpp_dir, sep);
|
||||
fprintf(defines_file, "vhdlpp:\"%s%cvhdlpp\"\n", vhdlpp_dir, sep);
|
||||
fprintf(defines_file, "vhdlpp-work:%s\n", vhdlpp_work);
|
||||
for (unsigned idx = 0 ; idx < vhdlpp_libdir_cnt ; idx += 1)
|
||||
fprintf(defines_file, "vhdlpp-libdir:%s\n", vhdlpp_libdir[idx]);
|
||||
|
|
@ -1547,7 +1548,7 @@ int main(int argc, char **argv)
|
|||
/* Write the preprocessor command needed to preprocess a
|
||||
single file. This may be used to preprocess library
|
||||
files. */
|
||||
fprintf(iconfig_file, "ivlpp:%s%civlpp %s -L -F\"%s\" -P\"%s\"\n",
|
||||
fprintf(iconfig_file, "ivlpp:\"%s%civlpp\" %s -L -F\"%s\" -P\"%s\"\n",
|
||||
ivlpp_dir, sep,
|
||||
strchr(warning_flags, 'r') ? "-Wredef-all" :
|
||||
strchr(warning_flags, 'R') ? "-Wredef-chg" : "",
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ exec_prefix = @exec_prefix@
|
|||
srcdir = @srcdir@
|
||||
|
||||
VPATH = $(srcdir)
|
||||
vpath %.c $(srcdir)/../libmisc
|
||||
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
|
|
@ -38,16 +39,16 @@ INSTALL_DATA = @INSTALL_DATA@
|
|||
LEX = @LEX@
|
||||
|
||||
ifeq (@srcdir@,.)
|
||||
INCLUDE_PATH = -I. -I..
|
||||
INCLUDE_PATH = -I. -I.. -I../libmisc
|
||||
else
|
||||
INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/..
|
||||
INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../libmisc
|
||||
endif
|
||||
|
||||
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
O = main.o lexor.o
|
||||
O = main.o lexor.o CmdExec.o
|
||||
|
||||
all: ivlpp@EXEEXT@
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@ memleakOnRealloc
|
|||
nullPointerArithmeticOutOfMemory
|
||||
nullPointerOutOfMemory
|
||||
|
||||
// CmdExec.c is shared by multiple executables, so this target sees helpers
|
||||
// that are used only by another target.
|
||||
unusedFunction:../libmisc/CmdExec.c
|
||||
|
||||
// Errors/limitations in the generated yacc and lex files
|
||||
ctunullpointerOutOfMemory:lexor.lex
|
||||
memleakOnRealloc:lexor.lex
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
# include <ctype.h>
|
||||
# include <assert.h>
|
||||
|
||||
# include "CmdExec.h"
|
||||
# include "globals.h"
|
||||
# include "ivl_alloc.h"
|
||||
|
||||
|
|
@ -2128,12 +2129,12 @@ static void open_input_file(struct include_stack_t*isp)
|
|||
cmdlen += liblen;
|
||||
|
||||
char*cmd = malloc(cmdlen);
|
||||
snprintf(cmd, cmdlen, "%s -w\"%s\"%s %s", vhdlpp_path, vhdlpp_work, libs, isp->path);
|
||||
snprintf(cmd, cmdlen, "%s -w\"%s\"%s \"%s\"", vhdlpp_path, vhdlpp_work, libs, isp->path);
|
||||
|
||||
if (verbose_flag) fprintf(stderr, "Invoke vhdlpp: %s\n", cmd);
|
||||
|
||||
isp->file = popen(cmd, "r");
|
||||
isp->file_close = pclose;
|
||||
isp->file = ivl_run_cmd_pipe(cmd);
|
||||
isp->file_close = ivl_close_cmd_pipe;
|
||||
|
||||
free(libs);
|
||||
free(cmd);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,302 @@
|
|||
/*
|
||||
* Copyright (c) 2026 Lars-Peter Clausen <lars@metafoo.de>
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
# include "CmdExec.h"
|
||||
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
|
||||
#ifdef __MINGW32__
|
||||
# if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600
|
||||
# undef _WIN32_WINNT
|
||||
# define _WIN32_WINNT 0x0600
|
||||
# endif
|
||||
# if !defined(WINVER) || WINVER < 0x0600
|
||||
# undef WINVER
|
||||
# define WINVER 0x0600
|
||||
# endif
|
||||
# include <fcntl.h>
|
||||
# include <io.h>
|
||||
# include <stdint.h>
|
||||
# include <windows.h>
|
||||
|
||||
static char *get_cmd_exe(void)
|
||||
{
|
||||
DWORD n = GetEnvironmentVariableA("COMSPEC", NULL, 0);
|
||||
char *buf;
|
||||
|
||||
if (n > 0) {
|
||||
buf = (char *)malloc(n);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
DWORD len = GetEnvironmentVariableA("COMSPEC", buf, n);
|
||||
|
||||
if (len > 0 && len < n)
|
||||
return buf;
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
/* Fallback. This avoids searching PATH for cmd.exe. */
|
||||
{
|
||||
char sysdir[MAX_PATH];
|
||||
UINT len = GetSystemDirectoryA(sysdir, sizeof(sysdir));
|
||||
|
||||
if (len > 0 && len < sizeof(sysdir)) {
|
||||
static const char suffix[] = "\\cmd.exe";
|
||||
size_t need = strlen(sysdir) + sizeof(suffix);
|
||||
|
||||
buf = (char *)malloc(need);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
|
||||
strcpy(buf, sysdir);
|
||||
strcat(buf, suffix);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
return _strdup("cmd.exe");
|
||||
}
|
||||
|
||||
/*
|
||||
* On Windows `system()` runs the string as cmd.exe /C <command>.
|
||||
* `popen()` similarly runs the string through CMD.exe and attaches one side of
|
||||
* a pipe.
|
||||
*
|
||||
* cmd.exe has special quote handling for /C. Quote characters are preserved
|
||||
* only if all of the following are true:
|
||||
* - there is no /S switch;
|
||||
* - there are exactly two quote characters;
|
||||
* - there are no special characters between them, where special is one
|
||||
* of &<>()@^|;
|
||||
* - there is whitespace between them;
|
||||
* - the string between them is the name of an executable file.
|
||||
*
|
||||
* For an input like "C:\Program Files\...\ivlpp" -F"...\defs" "input file.v"
|
||||
* the quotes at the beginning and the end get stripped, which results in
|
||||
* incorrect behavior.
|
||||
*
|
||||
* Below are versions of `system()` and `popen()` that call cmd.exe with /C /S,
|
||||
* which will preserve the quotes. Select cmd.exe from COMSPEC, with a fallback
|
||||
* to the system directory, and pass it as the application name so PATH is not
|
||||
* searched.
|
||||
*
|
||||
* Also pass /D to suppress AutoRun commands so a registry setting cannot
|
||||
* modify this parsing path.
|
||||
*/
|
||||
static int start_cmd_process(const char *cmd, HANDLE stdout_handle,
|
||||
PROCESS_INFORMATION *pi,
|
||||
DWORD *last_error)
|
||||
{
|
||||
STARTUPINFOEX siex;
|
||||
STARTUPINFO si;
|
||||
STARTUPINFO *startup_info;
|
||||
HANDLE child_stdout = NULL;
|
||||
HANDLE inherit_handles[3];
|
||||
DWORD creation_flags = 0;
|
||||
BOOL inherit = FALSE;
|
||||
SIZE_T attr_size = 0;
|
||||
unsigned inherit_count = 0;
|
||||
char *cmd_exe = get_cmd_exe();
|
||||
size_t cmd2len;
|
||||
char *cmd2;
|
||||
LPPROC_THREAD_ATTRIBUTE_LIST attr_list = NULL;
|
||||
int attr_list_initialized = 0;
|
||||
int rc = -1;
|
||||
|
||||
if (last_error != NULL)
|
||||
*last_error = 0;
|
||||
|
||||
if (cmd_exe == NULL)
|
||||
return -1;
|
||||
|
||||
cmd2len = strlen(cmd_exe) + strlen(cmd) + 16;
|
||||
cmd2 = (char *)malloc(cmd2len);
|
||||
if (cmd2 == NULL)
|
||||
goto out;
|
||||
|
||||
snprintf(cmd2, cmd2len, "\"%s\" /D /S /C \"%s\"", cmd_exe, cmd);
|
||||
|
||||
memset(&si, 0x00, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
startup_info = &si;
|
||||
|
||||
if (stdout_handle != NULL) {
|
||||
HANDLE std_input = GetStdHandle(STD_INPUT_HANDLE);
|
||||
HANDLE std_error = GetStdHandle(STD_ERROR_HANDLE);
|
||||
|
||||
memset(&siex, 0x00, sizeof(siex));
|
||||
siex.StartupInfo.cb = sizeof(siex);
|
||||
siex.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
|
||||
|
||||
if (!DuplicateHandle(GetCurrentProcess(), stdout_handle, GetCurrentProcess(),
|
||||
&child_stdout, 0, TRUE, DUPLICATE_SAME_ACCESS))
|
||||
goto out;
|
||||
|
||||
/* The normal system()/popen() path already relies on standard
|
||||
* handles being inheritable. Only the pipe writer is duplicated.
|
||||
*/
|
||||
if (std_input != NULL && std_input != INVALID_HANDLE_VALUE)
|
||||
inherit_handles[inherit_count++] = std_input;
|
||||
inherit_handles[inherit_count++] = child_stdout;
|
||||
if (std_error != NULL && std_error != INVALID_HANDLE_VALUE)
|
||||
inherit_handles[inherit_count++] = std_error;
|
||||
|
||||
siex.StartupInfo.hStdInput = std_input;
|
||||
siex.StartupInfo.hStdOutput = child_stdout;
|
||||
siex.StartupInfo.hStdError = std_error;
|
||||
|
||||
InitializeProcThreadAttributeList(NULL, 1, 0, &attr_size);
|
||||
attr_list = (LPPROC_THREAD_ATTRIBUTE_LIST)malloc(attr_size);
|
||||
if (attr_list == NULL)
|
||||
goto out;
|
||||
if (!InitializeProcThreadAttributeList(attr_list, 1, 0, &attr_size))
|
||||
goto out;
|
||||
attr_list_initialized = 1;
|
||||
if (!UpdateProcThreadAttribute(attr_list, 0,
|
||||
PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
|
||||
inherit_handles,
|
||||
inherit_count * sizeof(inherit_handles[0]),
|
||||
NULL, NULL))
|
||||
goto out;
|
||||
|
||||
siex.lpAttributeList = attr_list;
|
||||
startup_info = &siex.StartupInfo;
|
||||
creation_flags = EXTENDED_STARTUPINFO_PRESENT;
|
||||
inherit = TRUE;
|
||||
}
|
||||
memset(pi, 0x00, sizeof(*pi));
|
||||
|
||||
if (!CreateProcess(cmd_exe, cmd2, NULL, NULL, inherit,
|
||||
creation_flags, NULL, NULL, startup_info, pi)) {
|
||||
if (last_error != NULL)
|
||||
*last_error = GetLastError();
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
|
||||
out:
|
||||
if (attr_list_initialized)
|
||||
DeleteProcThreadAttributeList(attr_list);
|
||||
if (attr_list != NULL)
|
||||
free(attr_list);
|
||||
if (child_stdout != NULL)
|
||||
CloseHandle(child_stdout);
|
||||
free(cmd2);
|
||||
free(cmd_exe);
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
int ivl_run_cmd(const char *cmd, int verbose)
|
||||
{
|
||||
if (verbose)
|
||||
fprintf(stderr, "Executing: %s", cmd);
|
||||
|
||||
#ifdef __MINGW32__
|
||||
DWORD exit_code = 1;
|
||||
DWORD last_error;
|
||||
PROCESS_INFORMATION pi;
|
||||
|
||||
if (start_cmd_process(cmd, NULL, &pi, &last_error) != 0) {
|
||||
if (last_error != 0)
|
||||
fprintf(stderr, "CreateProcess failed (%lu).\n", last_error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
GetExitCodeProcess(pi.hProcess, &exit_code);
|
||||
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
|
||||
return exit_code;
|
||||
#else
|
||||
return system(cmd);
|
||||
#endif
|
||||
}
|
||||
|
||||
FILE *ivl_run_cmd_pipe(const char *cmd)
|
||||
{
|
||||
#ifdef __MINGW32__
|
||||
SECURITY_ATTRIBUTES sa;
|
||||
HANDLE read_pipe = NULL;
|
||||
HANDLE write_pipe = NULL;
|
||||
PROCESS_INFORMATION pi;
|
||||
int fd;
|
||||
FILE *fp;
|
||||
|
||||
memset(&sa, 0x00, sizeof(sa));
|
||||
sa.nLength = sizeof(sa);
|
||||
sa.bInheritHandle = FALSE;
|
||||
|
||||
if (!CreatePipe(&read_pipe, &write_pipe, &sa, 0))
|
||||
return NULL;
|
||||
|
||||
if (start_cmd_process(cmd, write_pipe, &pi, NULL) != 0) {
|
||||
CloseHandle(read_pipe);
|
||||
CloseHandle(write_pipe);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CloseHandle(write_pipe);
|
||||
CloseHandle(pi.hThread);
|
||||
|
||||
/* Match popen("r") text-mode semantics. The lexer expects CRLF from
|
||||
* Windows command output to be normalized before it sees `line directives.
|
||||
*/
|
||||
fd = _open_osfhandle((intptr_t)read_pipe, _O_RDONLY | _O_TEXT);
|
||||
if (fd < 0) {
|
||||
CloseHandle(read_pipe);
|
||||
TerminateProcess(pi.hProcess, 1);
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
CloseHandle(pi.hProcess);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fp = _fdopen(fd, "rt");
|
||||
if (fp == NULL) {
|
||||
_close(fd);
|
||||
TerminateProcess(pi.hProcess, 1);
|
||||
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||
CloseHandle(pi.hProcess);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* The child owns the pipe writer. We do not need the process handle
|
||||
* unless we want pclose() style exit status.
|
||||
*/
|
||||
CloseHandle(pi.hProcess);
|
||||
return fp;
|
||||
#else
|
||||
return popen(cmd, "r");
|
||||
#endif
|
||||
}
|
||||
|
||||
int ivl_close_cmd_pipe(FILE *fp)
|
||||
{
|
||||
#ifdef __MINGW32__
|
||||
return fclose(fp);
|
||||
#else
|
||||
return pclose(fp);
|
||||
#endif
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
#ifndef IVL_CmdExec_H
|
||||
#define IVL_CmdExec_H
|
||||
/*
|
||||
* Copyright (c) 2026 Lars-Peter Clausen <lars@metafoo.de>
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
# include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int ivl_run_cmd(const char *cmd, int verbose);
|
||||
FILE *ivl_run_cmd_pipe(const char *cmd);
|
||||
int ivl_close_cmd_pipe(FILE *fp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* IVL_CmdExec_H */
|
||||
14
pform.cc
14
pform.cc
|
|
@ -44,6 +44,7 @@
|
|||
# include <cstdlib>
|
||||
# include <cctype>
|
||||
|
||||
# include "CmdExec.h"
|
||||
# include "ivl_assert.h"
|
||||
# include "ivl_alloc.h"
|
||||
|
||||
|
|
@ -3466,17 +3467,14 @@ int pform_parse(const char*path)
|
|||
if (strcmp(path, "-") == 0) {
|
||||
vl_input = stdin;
|
||||
} else if (ivlpp_string) {
|
||||
char*cmdline = static_cast<char*>(malloc(strlen(ivlpp_string) +
|
||||
strlen(path) + 4));
|
||||
strcpy(cmdline, ivlpp_string);
|
||||
strcat(cmdline, " \"");
|
||||
strcat(cmdline, path);
|
||||
strcat(cmdline, "\"");
|
||||
size_t cmdlen = strlen(ivlpp_string) + strlen(path) + 4;
|
||||
char*cmdline = static_cast<char*>(malloc(cmdlen));
|
||||
snprintf(cmdline, cmdlen, "%s \"%s\"", ivlpp_string, path);
|
||||
|
||||
if (verbose_flag)
|
||||
cerr << "Executing: " << cmdline << endl<< flush;
|
||||
|
||||
vl_input = popen(cmdline, "r");
|
||||
vl_input = ivl_run_cmd_pipe(cmdline);
|
||||
if (vl_input == 0) {
|
||||
cerr << "Unable to preprocess " << path << "." << endl;
|
||||
return 1;
|
||||
|
|
@ -3526,7 +3524,7 @@ int pform_parse(const char*path)
|
|||
|
||||
if (vl_input != stdin) {
|
||||
if (ivlpp_string)
|
||||
pclose(vl_input);
|
||||
ivl_close_cmd_pipe(vl_input);
|
||||
else
|
||||
fclose(vl_input);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue