xschem/scconfig/src/scripts/find_tcl.c

293 lines
7.6 KiB
C
Raw Normal View History

2020-08-08 15:47:34 +02:00
/*
scconfig - tcl lib detection
Copyright (C) 2009 Tibor Palinkas
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
2025-05-14 09:57:25 +02:00
Foundation, Inc., 31 Milk Street, # 960789 Boston, MA 02196 USA
2020-08-08 15:47:34 +02:00
Project page: http://repo.hu/projects/scconfig
Contact (email and IRC): http://igor2.repo.hu/contact.html
2020-08-08 15:47:34 +02:00
*/
#include "scripts.h"
#include <unistd.h>
2024-11-13 09:51:20 +01:00
static int all_vers[] = { 86, 85, 84, 90, 0, -1 };
2020-08-08 15:47:34 +02:00
int find_script_tcl_(const char *name, int logdepth, int fatal, int *vers, int fallback)
{
char *out, *temp, *temp2, *cmd, *I, *L, *end, **tclsh;
int *v;
char *tclshs[] = {
"tclsh",
"tclsh86",
"tclsh85",
"tclsh84",
"tclsh90",
2020-08-08 15:47:34 +02:00
"tclsh8.6",
"tclsh8.5",
"tclsh8.4",
"tclsh9.0",
2020-08-08 15:47:34 +02:00
NULL
};
char *test_c =
2021-01-28 23:09:37 +01:00
NL "#include <stdio.h>"
2020-08-08 15:47:34 +02:00
NL "#include <tcl.h>"
NL "int main() {"
NL " Tcl_Obj *res;"
NL " Tcl_Interp *interp;"
NL " interp = Tcl_CreateInterp();"
NL " puts(\"OK\");"
NL " return 0;"
NL "}"
NL;
char *tcl_config =
NL "proc tclConfigFile {} {"
NL " set d [info library]"
NL " set f [file join $d \"tclConfig.sh\"]"
NL " if {[file exists $f]} {return $f}"
NL ""
NL " set d [file dirname $d]"
NL " set f [file join $d \"tclConfig.sh\"]"
NL " if {[file exists $f]} {return $f}"
NL ""
NL " set d [file dirname $d]"
NL " set f [file join $d \"tclConfig.sh\"]"
NL " if {[file exists $f]} {return $f}"
NL ""
NL " set d [file dirname $d]"
NL " set f [file join $d \"tclConfig.sh\"]"
NL " if {[file exists $f]} {return $f}"
NL "}"
NL ""
NL "puts [tclConfigFile]"
NL;
/* Look at some standard places */
for(v = vers; *v != -1; v++) {
int major = *v / 10, minor = *v % 10;
char ifl[64], lfl[64];
if (*v == 0) {
report("plain... ");
if (try_icl(logdepth, "libs/script/tcl", test_c, NULL, NULL, "-ltcl")) return 0;
continue;
}
report("%d.%d... ", major, minor);
sprintf(lfl, "-ltcl%d", *v);
if (try_icl(logdepth, "libs/script/tcl", test_c, NULL, NULL, lfl)) return 0;
sprintf(lfl, "-ltcl%d.%d", major, minor);
if (try_icl(logdepth, "libs/script/tcl", test_c, NULL, NULL, lfl)) return 0;
sprintf(lfl, "-ltcl%d", *v);
sprintf(ifl, "-I/usr/include/tcl%d", *v);
if (try_icl(logdepth, "libs/script/tcl", test_c, NULL, ifl, lfl)) return 0;
sprintf(lfl, "-ltcl%d.%d", major, minor);
sprintf(ifl, "-I/usr/include/tcl%d.%d", major, minor);
if (try_icl(logdepth, "libs/script/tcl", test_c, NULL, ifl, lfl)) return 0;
}
if (!fallback)
return 1;
report(" not found by version, trying tclsh.\n");
/* Try the config script */
logprintf(logdepth, "running config tcl\n");
temp = tempfile_dump(tcl_config, ".tcl");
cmd = malloc(strlen(temp) + 16);
for(tclsh = tclshs; *tclsh != NULL; tclsh++) {
sprintf(cmd, "%s %s", *tclsh, temp);
report("Trying: %s\n", cmd);
if (run(logdepth+1, cmd, &out) == 0) {
free(cmd);
cmd = malloc(strlen(out) + 256);
sprintf(cmd, "#!/bin/sh\n. %s\necho $TCL_INCLUDE_SPEC\necho $TCL_LIB_SPEC\n", out);
temp2 = tempfile_dump(cmd, ".sh");
free(out);
out = malloc(strlen(temp2) + 32);
sprintf(out, "chmod +x %s", temp2);
system(out);
free(out);
if (run(logdepth+1, temp2, &out) == 0) {
remove(temp2);
I = out;
L = strchr(I, '\n');
if (L != NULL) {
*L = '\0';
L++;
end = strchr(L, '\n');
if (end != NULL)
*end = '\0';
}
if (try_icl(logdepth, "libs/script/tcl", test_c, NULL, I, L)) {
remove(temp);
free(cmd);
if (out != NULL)
free(out);
return 0;
}
}
remove(temp2);
}
}
remove(temp);
free(cmd);
if (out != NULL)
free(out);
return 1;
}
int find_script_tcl(const char *name, int logdepth, int fatal)
{
int res, rver[2], *vers = all_vers, fallback = 1;
const char *reqver;
require("cc/cc", logdepth, fatal);
report("Checking for tcl... ");
logprintf(logdepth, "find_tcl: trying to find tcl...\n");
logdepth++;
reqver = get("/arg/tcl-version");
if ((reqver != NULL) && (reqver[0] != '\0')) {
if (reqver[1] == '.')
rver[0] = (reqver[0] - '0') * 10 + (reqver[2] - '0');
else
rver[0] = atoi(reqver);
rver[1] = -1;
vers = rver;
fallback = 0;
}
res = find_script_tcl_(name, logdepth, fatal, vers, fallback);
if (res == 0)
return 0;
return try_fail(logdepth, "libs/script/tcl");
}
static int try_icl_tk(int logdepth, const char *prefix, const char *test_c_in, const char *includes, const char *cflags, const char *ldflags, int ver)
{
const char *XL = get("libs/gui/xopendisplay/Lflags");
const char *Xc = get("libs/gui/xopendisplay/cflags");
const char *tl, *tc;
char *tmpl, *tmpc;
int res;
tl = get("libs/script/tcl/ldflags");
tc = get("libs/script/tcl/cflags");
if (XL == NULL) XL = "";
if (Xc == NULL) Xc = "";
if (tl == NULL) tl = "";
if (tc == NULL) tc = "";
if ((*XL == '\0') && (*Xc == '\0') && (*tl == '\0') && (*tc == '\0'))
return try_icl(logdepth, prefix, test_c_in, includes, cflags, ldflags);
tmpl = str_concat(" ", tl, XL, ldflags, NULL);
tmpc = str_concat(" ", tc, Xc, cflags, NULL);
res = try_icl(logdepth, prefix, test_c_in, includes, tmpc, tmpl);
free(tmpl);
free(tmpc);
return res;
}
int find_script_tk(const char *name, int logdepth, int fatal)
{
int *v, rver[2], *vers = all_vers;
const char *reqver, *tclreqver;
char *test_c =
NL "#include <stdio.h>"
NL "#include <tk.h>"
NL "int main() {"
NL " if (Tk_GetNumMainWindows() == 0)"
NL " puts(\"OK\");"
NL " return 0;"
NL "}"
NL;
require("cc/cc", logdepth, fatal);
require("libs/gui/xopendisplay/cflags", logdepth, fatal);
require("libs/gui/xopendisplay/Lflags", logdepth, fatal);
report("Checking for tk... ");
logprintf(logdepth, "find_tk: trying to find tk...\n");
logdepth++;
reqver = get("/arg/tk-version");
if ((reqver != NULL) && (reqver[0] != '\0')) {
tclreqver = get("/arg/tcl-version");
if ((tclreqver != NULL) && (tclreqver[0] != '\0')) {
if (strcmp(tclreqver, reqver) != 0) {
report("\n\nFatal argument error: if both tcl and tk version are forced, they must match\n\n");
exit(1);
}
}
if (reqver[1] == '.')
rver[0] = (reqver[0] - '0') * 10 + (reqver[2] - '0');
else
rver[0] = atoi(reqver);
rver[1] = -1;
vers = rver;
}
/* Look at some standard places, per version */
for(v = vers; *v != -1; v++) {
int major = *v / 10, minor = *v % 10;
char lfl[64];
int tvers[2];
tvers[0] = *v;
tvers[1] = -1;
if (find_script_tcl_("libs/script/tcl", logdepth+1, 0, tvers, 0) != 0) {
report("(no tcl) ");
continue;
}
if (*v == 0) {
if (try_icl_tk(logdepth, "libs/script/tk", test_c, NULL, NULL, "-ltk", 0)) return 0;
continue;
}
sprintf(lfl, "-ltk%d", *v);
if (try_icl_tk(logdepth, "libs/script/tk", test_c, NULL, NULL, lfl, *v)) return 0;
sprintf(lfl, "-ltk%d.%d", major, minor);
if (try_icl_tk(logdepth, "libs/script/tk", test_c, NULL, NULL, lfl, *v)) return 0;
2024-11-13 09:51:20 +01:00
/* this seems to happen on some systems starting from 9.0 */
sprintf(lfl, "-ltcl%dtk%d.%d", major, major, minor);
if (try_icl_tk(logdepth, "libs/script/tk", test_c, NULL, NULL, lfl, *v)) return 0;
2020-08-08 15:47:34 +02:00
}
return try_fail(logdepth, "libs/script/tk");
}