summaryrefslogtreecommitdiff
path: root/os2
diff options
context:
space:
mode:
authorIlya Zakharevich <ilya@math.berkeley.edu>2003-12-18 06:10:29 -0800
committerRafael Garcia-Suarez <rgarciasuarez@gmail.com>2004-01-01 17:29:21 +0000
commit1933e12cd0d32c774bd7f483285802de52dc8cbc (patch)
treea2cdc2316a1e9964350869b0754cf42977a94088 /os2
parentb08eb2a88581a6164b7fe182bf291c86bfb3c690 (diff)
downloadperl-1933e12cd0d32c774bd7f483285802de52dc8cbc.tar.gz
OS/2 update
Message-ID: <20031218221029.GA7898@math.berkeley.edu> p4raw-id: //depot/perl@22032
Diffstat (limited to 'os2')
-rw-r--r--os2/Changes40
-rw-r--r--os2/OS2/REXX/DLL/Changes2
-rw-r--r--os2/OS2/REXX/DLL/DLL.pm57
-rw-r--r--os2/os2.c641
-rw-r--r--os2/os2ish.h222
-rw-r--r--os2/perl2cmd.pl18
6 files changed, 905 insertions, 75 deletions
diff --git a/os2/Changes b/os2/Changes
index bcd970d745..3bd33a56c5 100644
--- a/os2/Changes
+++ b/os2/Changes
@@ -779,3 +779,43 @@ After @21574:
is void.
New executables perl___<number> generated with decreased stack size
(good when virtual memory is low; e.g. floppy boot).
+
+After 5.8.2 (@21668):
+ Fixes to installperl scripts to avoid junk output, allow overwrite
+ of existing files (File::Copy::copy is mapped to DosCopy()
+ with flags which would not overwrite).
+ Disable DynaLoading of Perl modules with AOUT build (will core anyway).
+ For AOUT build: Quick hack to construct directories necessary for
+ /*/% stuff [maybe better do it from hints/os2.sh?].
+ AOUT build: do -D__ST_MT_ERRNO__ to simplify linking with -Zmtd
+ (e.g., to test GD: gd.dll linked with -Zmtd).
+ MANIFEST.SKIP was read without a drive part of the filename.
+ Rename Cwd::extLibpath*() to OS2::... (old names still preserved).
+ Install perl.lib and perl.a too.
+ New methods libPath_find(),has_f32(),handle(),fullname() for OS2::DLL.
+ Enable quad support using long long.
+ New C exported functions os2_execname(), async_mssleep(), msCounter(),
+ InfoTable(), dir_subst(), Perl_OS2_handler_install(),
+ fill_extLibpath().
+ async_mssleep() uses some undocumented features which allow usage of
+ highest possible resolution of sleep() while preserving low
+ priority (raise of resolution may be not available before
+ Warp3fp40; resolution is 8ms/CLOCK_SCALE).
+ usleep() and select(undef,undef,undef,$t) are using this
+ interface for time up to 0.5sec.
+ New convenience macros os2win_croak_0OK(rc,msg), os2win_croak(rc,msg),
+ os2cp_croak(rc,msg).
+ Supports ~installprefix, ~exe, ~dll in PERLLIB_PREFIX etc (actual
+ directories are substituted).
+ New functions OS2::msCounter(), OS2::ms_sleep(), OS2::_InfoTable().
+ Checks stack when fixing EMX being under-initialized (-Zomf -Zsys
+ produces 32K stack???).
+ New environment variables PERL_BEGINLIBPATH, PERL_PRE_BEGINLIBPATH,
+ PERL_POST_BEGINLIBPATH, PERL_ENDLIBPATH,
+ PERL_PRE_ENDLIBPATH PERL_POST_ENDLIBPATH (~-enabled);
+ PERL_EMXLOAD_SECS.
+ Better handling of FIRST_MAKEFILE (propagate to subdirs during test,
+ do not require Makefile.PL present).
+ perl2cmd converter: do not rewrite if no change.
+ README.os2 updated with info on building binary distributions and
+ custom perl executables (but not much else).
diff --git a/os2/OS2/REXX/DLL/Changes b/os2/OS2/REXX/DLL/Changes
index 874f7fab4a..e2c656dd90 100644
--- a/os2/OS2/REXX/DLL/Changes
+++ b/os2/OS2/REXX/DLL/Changes
@@ -1,2 +1,4 @@
0.01:
Split out of OS2::REXX
+0.02:
+ New methods libPath_find(), has_f32(), handle() and fullname().
diff --git a/os2/OS2/REXX/DLL/DLL.pm b/os2/OS2/REXX/DLL/DLL.pm
index 537a2107fc..5d8a24ea7b 100644
--- a/os2/OS2/REXX/DLL/DLL.pm
+++ b/os2/OS2/REXX/DLL/DLL.pm
@@ -1,6 +1,6 @@
package OS2::DLL;
-our $VERSION = '1.01';
+our $VERSION = '1.02';
use Carp;
use XSLoader;
@@ -58,6 +58,20 @@ sub load {
$load_with_dirs->(@_, @libs);
}
+sub libPath_find {
+ my ($name, $flags, @path) = (shift, shift);
+ $flags = 0x7 unless defined $flags;
+ push @path, split /;/, OS2::extLibpath if $flags & 0x1; # BEGIN
+ push @path, split /;/, OS2::libPath if $flags & 0x2;
+ push @path, split /;/, OS2::extLibpath(1) if $flags & 0x4; # END
+ s,(?![/\\])$,/, for @path;
+ s,\\,/,g for @path;
+ $name .= ".dll" unless $name =~ /\.[^\\\/]*$/;
+ $_ .= $name for @path;
+ -f $_ and return $_ for @path;
+ return;
+}
+
package OS2::DLL::dll;
use Carp;
@ISA = 'OS2::DLL';
@@ -102,6 +116,16 @@ sub find
return 1;
}
+sub handle { shift->{Handle} }
+sub fullname { OS2::DLLname(0x202, shift->handle) }
+#sub modname { OS2::DLLname(0x201, shift->handle) }
+
+sub has_f32 {
+ my $handle = shift->handle;
+ my $name = shift;
+ DynaLoader::dl_find_symbol($handle, $name);
+}
+
XSLoader::load 'OS2::DLL';
1;
@@ -186,6 +210,37 @@ Unless used inside REXX environment (see L<OS2::REXX>), the REXX runtime
environment (variable pool, queue etc.) is not available to the called
function.
+=head1 Inspecting the module
+
+=over
+
+=item $module->handle
+
+=item $module->fullname
+
+Return the (integer) handle and full path name of a loaded DLL.
+
+TODO: the module name (whatever is specified in the C<LIBRARY> statement
+of F<.def> file when linking) via OS2::Proc.
+
+=item $module->has_f32($name)
+
+Returns the address of a 32-bit entry point with name $name, or 0 if none
+found. (Keep in mind that some entry points may be 16-bit, and some may have
+capitalized names comparing to callable-from-C counterparts.) Name of the
+form C<#197> will find entry point with ordinal 197.
+
+=item libPath_find($name [, $flags])
+
+Looks for the DLL $name on C<BEGINLIBPATH>, C<LIBPATH>, C<ENDLIBPATH> if
+bits 0x1, 0x2, 0x4 of $flags are set correspondingly. If called with no
+arguments, looks on all 3 locations. Returns the full name of the found
+file. B<DLL is not loaded.>
+
+$name has F<.dll> appended unless it already has an extension.
+
+=back
+
=head1 Low-level API
=over
diff --git a/os2/os2.c b/os2/os2.c
index e8e10d97b7..776031d17b 100644
--- a/os2/os2.c
+++ b/os2/os2.c
@@ -12,6 +12,7 @@
#include <os2.h>
#include "dlfcn.h"
#include <emx/syscalls.h>
+#include <sys/emxload.h>
#include <sys/uflags.h>
@@ -32,6 +33,14 @@
#include "EXTERN.h"
#include "perl.h"
+enum module_name_how { mod_name_handle, mod_name_shortname, mod_name_full,
+ mod_name_C_function = 0x100, mod_name_HMODULE = 0x200};
+
+/* Find module name to which *this* subroutine is compiled */
+#define module_name(how) module_name_at(&module_name_at, how)
+
+static SV* module_name_at(void *pp, enum module_name_how how);
+
void
croak_with_os2error(char *s)
{
@@ -118,6 +127,7 @@ static struct perlos2_state_t {
int po2__my_pwent; /* = -1; */
int po2_DOS_harderr_state; /* = -1; */
signed char po2_DOS_suppression_state; /* = -1; */
+
PFN po2_ExtFCN[ORD_NENTRIES]; /* Labeled by ord ORD_*. */
/* struct PMWIN_entries_t po2_PMWIN_entries; */
@@ -153,7 +163,10 @@ static struct perlos2_state_t {
int po2_emx_runtime_init; /* If 1, we need to manually init it */
int po2_emx_exception_init; /* If 1, we need to manually set it */
int po2_emx_runtime_secondary;
-
+ char* (*po2_perllib_mangle_installed)(char *s, unsigned int l);
+ char* po2_perl_sh_installed;
+ PGINFOSEG po2_gTable;
+ PLINFOSEG po2_lTable;
} perlos2_state = {
-1, /* po2__my_pwent */
-1, /* po2_DOS_harderr_state */
@@ -195,10 +208,13 @@ static struct perlos2_state_t {
#define emx_runtime_init (Perl_po2()->po2_emx_runtime_init)
#define emx_exception_init (Perl_po2()->po2_emx_exception_init)
#define emx_runtime_secondary (Perl_po2()->po2_emx_runtime_secondary)
+#define perllib_mangle_installed (Perl_po2()->po2_perllib_mangle_installed)
+#define perl_sh_installed (Perl_po2()->po2_perl_sh_installed)
+#define gTable (Perl_po2()->po2_gTable)
+#define lTable (Perl_po2()->po2_lTable)
const Perl_PFN * const pExtFCN = (Perl_po2()->po2_ExtFCN);
-
#if defined(USE_5005THREADS) || defined(USE_ITHREADS)
typedef void (*emx_startroutine)(void *);
@@ -966,7 +982,7 @@ do_spawn_ve(pTHX_ SV *really, U32 flag, U32 execf, char *inicmd, U32 addflag)
{
int trueflag = flag;
int rc, pass = 1;
- char *real_name;
+ char *real_name = NULL; /* Shut down the warning */
char const * args[4];
static const char * const fargs[4]
= { "/bin/sh", "-c", "\"$@\"", "spawn-via-shell", };
@@ -2100,34 +2116,50 @@ void
CroakWinError(int die, char *name)
{
FillWinError;
- if (die && Perl_rc) {
- dTHX;
+ if (die && Perl_rc)
+ croak_with_os2error(name ? name : "Win* API call");
+}
- Perl_croak(aTHX_ "%s: %s", (name ? name : "Win* API call"), os2error(Perl_rc));
- }
+static char *
+dllname2buffer(pTHX_ char *buf, STRLEN l)
+{
+ char *o;
+ STRLEN ll;
+ SV *dll = Nullsv;
+
+ dll = module_name(mod_name_full);
+ o = SvPV(dll, ll);
+ if (ll < l)
+ memcpy(buf,o,ll);
+ SvREFCNT_dec(dll);
+ return (ll >= l ? "???" : buf);
}
-char *
-os2_execname(pTHX)
+static char *
+execname2buffer(char *buf, STRLEN l, char *oname)
{
- char buf[300], *p, *o = PL_origargv[0], ok = 1;
+ char *p, *orig = oname, ok = oname != NULL;
- if (_execname(buf, sizeof buf) != 0)
- return o;
+ if (_execname(buf, l) != 0) {
+ if (!oname || strlen(oname) >= l)
+ return oname;
+ strcpy(buf, oname);
+ ok = 0;
+ }
p = buf;
while (*p) {
if (*p == '\\')
*p = '/';
if (*p == '/') {
- if (ok && *o != '/' && *o != '\\')
+ if (ok && *oname != '/' && *oname != '\\')
ok = 0;
- } else if (ok && tolower(*o) != tolower(*p))
+ } else if (ok && tolower(*oname) != tolower(*p))
ok = 0;
p++;
- o++;
+ oname++;
}
- if (ok) { /* PL_origargv[0] matches the real name. Use PL_origargv[0]: */
- strcpy(buf, PL_origargv[0]); /* _execname() is always uppercased */
+ if (ok) { /* orig matches the real name. Use orig: */
+ strcpy(buf, orig); /* _execname() is always uppercased */
p = buf;
while (*p) {
if (*p == '\\')
@@ -2135,61 +2167,238 @@ os2_execname(pTHX)
p++;
}
}
- p = savepv(buf);
+ return buf;
+}
+
+char *
+os2_execname(pTHX)
+{
+ char buf[300], *p = execname2buffer(buf, sizeof buf, PL_origargv[0]);
+
+ p = savepv(p);
SAVEFREEPV(p);
return p;
}
+int
+Perl_OS2_handler_install(void *handler, enum Perlos2_handler how)
+{
+ char *s, b[300];
+
+ switch (how) {
+ case Perlos2_handler_mangle:
+ perllib_mangle_installed = (char *(*)(char *s, unsigned int l))handler;
+ return 1;
+ case Perlos2_handler_perl_sh:
+ s = (char *)handler;
+ s = dir_subst(s, strlen(s), b, sizeof b, 0, "handler_perl_sh");
+ perl_sh_installed = savepv(s);
+ return 1;
+ case Perlos2_handler_perllib_from:
+ s = (char *)handler;
+ s = dir_subst(s, strlen(s), b, sizeof b, 0, "handler_perllib_from");
+ oldl = strlen(s);
+ oldp = savepv(s);
+ return 1;
+ case Perlos2_handler_perllib_to:
+ s = (char *)handler;
+ s = dir_subst(s, strlen(s), b, sizeof b, 0, "handler_perllib_to");
+ newl = strlen(s);
+ newp = savepv(s);
+ strcpy(mangle_ret, newp);
+ s = mangle_ret - 1;
+ while (*++s)
+ if (*s == '\\')
+ *s = '/';
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+/* Returns a malloc()ed copy */
+char *
+dir_subst(char *s, unsigned int l, char *b, unsigned int bl, enum dir_subst_e flags, char *msg)
+{
+ char *from, *to = b, *e = b; /* `to' assignment: shut down the warning */
+ STRLEN froml = 0, tol = 0, rest = 0; /* froml: likewise */
+
+ if (l >= 2 && s[0] == '~') {
+ switch (s[1]) {
+ case 'i': case 'I':
+ from = "installprefix"; break;
+ case 'd': case 'D':
+ from = "dll"; break;
+ case 'e': case 'E':
+ from = "exe"; break;
+ default:
+ from = NULL;
+ froml = l + 1; /* Will not match */
+ break;
+ }
+ if (from)
+ froml = strlen(from) + 1;
+ if (l >= froml && strnicmp(s + 2, from + 1, froml - 2) == 0) {
+ int strip = 1;
+
+ switch (s[1]) {
+ case 'i': case 'I':
+ strip = 0;
+ tol = strlen(INSTALL_PREFIX);
+ if (tol >= bl) {
+ if (flags & dir_subst_fatal)
+ Perl_croak_nocontext("INSTALL_PREFIX too long: `%s'", INSTALL_PREFIX);
+ else
+ return NULL;
+ }
+ memcpy(b, INSTALL_PREFIX, tol + 1);
+ to = b;
+ e = b + tol;
+ break;
+ case 'd': case 'D':
+ if (flags & dir_subst_fatal) {
+ dTHX;
+
+ to = dllname2buffer(aTHX_ b, bl);
+ } else { /* No Perl present yet */
+ HMODULE self = find_myself();
+ APIRET rc = DosQueryModuleName(self, bl, b);
+
+ if (rc)
+ return 0;
+ to = b - 1;
+ while (*++to)
+ if (*to == '\\')
+ *to = '/';
+ to = b;
+ }
+ break;
+ case 'e': case 'E':
+ if (flags & dir_subst_fatal) {
+ dTHX;
+
+ to = execname2buffer(b, bl, PL_origargv[0]);
+ } else
+ to = execname2buffer(b, bl, NULL);
+ break;
+ }
+ if (!to)
+ return NULL;
+ if (strip) {
+ e = strrchr(to, '/');
+ if (!e && (flags & dir_subst_fatal))
+ Perl_croak_nocontext("%s: Can't parse EXE/DLL name: '%s'", msg, to);
+ else if (!e)
+ return NULL;
+ *e = 0;
+ }
+ s += froml; l -= froml;
+ if (!l)
+ return to;
+ if (!tol)
+ tol = strlen(to);
+
+ while (l >= 3 && (s[0] == '/' || s[0] == '\\')
+ && s[1] == '.' && s[2] == '.'
+ && (l == 3 || s[3] == '/' || s[3] == '\\' || s[3] == ';')) {
+ e = strrchr(b, '/');
+ if (!e && (flags & dir_subst_fatal))
+ Perl_croak_nocontext("%s: Error stripping dirs from EXE/DLL/INSTALLDIR name", msg);
+ else if (!e)
+ return NULL;
+ *e = 0;
+ l -= 3; s += 3;
+ }
+ if (l && s[0] != '/' && s[0] != '\\' && s[0] != ';')
+ *e++ = '/';
+ }
+ } /* Else: copy as is */
+ if (l && (flags & dir_subst_pathlike)) {
+ STRLEN i = 0;
+
+ while ( i < l - 2 && s[i] != ';') /* May have ~char after `;' */
+ i++;
+ if (i < l - 2) { /* Found */
+ rest = l - i - 1;
+ l = i + 1;
+ }
+ }
+ if (e + l >= b + bl) {
+ if (flags & dir_subst_fatal)
+ Perl_croak_nocontext("%s: name `%s%s' too long", msg, b, s);
+ else
+ return NULL;
+ }
+ memcpy(e, s, l);
+ if (rest) {
+ e = dir_subst(s + l, rest, e + l, bl - (e + l - b), flags, msg);
+ return e ? b : e;
+ }
+ e[l] = 0;
+ return b;
+}
+
+char *
+perllib_mangle_with(char *s, unsigned int l, char *from, unsigned int froml, char *to, unsigned int tol)
+{
+ if (!to)
+ return s;
+ if (l == 0)
+ l = strlen(s);
+ if (l < froml || strnicmp(from, s, froml) != 0)
+ return s;
+ if (l + tol - froml > STATIC_FILE_LENGTH || tol > STATIC_FILE_LENGTH)
+ Perl_croak_nocontext("Malformed PERLLIB_PREFIX");
+ if (to && to != mangle_ret)
+ memcpy(mangle_ret, to, tol);
+ strcpy(mangle_ret + tol, s + froml);
+ return mangle_ret;
+}
+
char *
perllib_mangle(char *s, unsigned int l)
{
+ char *name;
+
+ if (perllib_mangle_installed && (name = perllib_mangle_installed(s,l)))
+ return name;
if (!newp && !notfound) {
- newp = getenv("PERLLIB_" STRINGIFY(PERL_REVISION)
+ newp = getenv(name = "PERLLIB_" STRINGIFY(PERL_REVISION)
STRINGIFY(PERL_VERSION) STRINGIFY(PERL_SUBVERSION)
"_PREFIX");
if (!newp)
- newp = getenv("PERLLIB_" STRINGIFY(PERL_REVISION)
+ newp = getenv(name = "PERLLIB_" STRINGIFY(PERL_REVISION)
STRINGIFY(PERL_VERSION) "_PREFIX");
if (!newp)
- newp = getenv("PERLLIB_" STRINGIFY(PERL_REVISION) "_PREFIX");
+ newp = getenv(name = "PERLLIB_" STRINGIFY(PERL_REVISION) "_PREFIX");
if (!newp)
- newp = getenv("PERLLIB_PREFIX");
+ newp = getenv(name = "PERLLIB_PREFIX");
if (newp) {
- char *s;
+ char *s, b[300];
oldp = newp;
- while (*newp && !isSPACE(*newp) && *newp != ';') {
- newp++; oldl++; /* Skip digits. */
- }
- while (*newp && (isSPACE(*newp) || *newp == ';')) {
+ while (*newp && !isSPACE(*newp) && *newp != ';')
+ newp++; /* Skip old name. */
+ oldl = newp - oldp;
+ s = dir_subst(oldp, oldl, b, sizeof b, dir_subst_fatal, name);
+ oldp = savepv(s);
+ oldl = strlen(s);
+ while (*newp && (isSPACE(*newp) || *newp == ';'))
newp++; /* Skip whitespace. */
- }
- newl = strlen(newp);
- if (newl == 0 || oldl == 0) {
- Perl_croak_nocontext("Malformed PERLLIB_PREFIX");
- }
- strcpy(mangle_ret, newp);
- s = mangle_ret;
- while (*s) {
- if (*s == '\\') *s = '/';
- s++;
- }
- } else {
+ Perl_OS2_handler_install((void *)newp, Perlos2_handler_perllib_to);
+ if (newl == 0 || oldl == 0)
+ Perl_croak_nocontext("Malformed %s", name);
+ } else
notfound = 1;
- }
}
- if (!newp) {
+ if (!newp)
return s;
- }
- if (l == 0) {
+ if (l == 0)
l = strlen(s);
- }
- if (l < oldl || strnicmp(oldp, s, oldl) != 0) {
+ if (l < oldl || strnicmp(oldp, s, oldl) != 0)
return s;
- }
- if (l + newl - oldl > STATIC_FILE_LENGTH || newl > STATIC_FILE_LENGTH) {
+ if (l + newl - oldl > STATIC_FILE_LENGTH || newl > STATIC_FILE_LENGTH)
Perl_croak_nocontext("Malformed PERLLIB_PREFIX");
- }
strcpy(mangle_ret + newl, s + oldl);
return mangle_ret;
}
@@ -2394,6 +2603,105 @@ XS(XS_OS2_Errors2Drive)
XSRETURN(1);
}
+int
+async_mssleep(ULONG ms, int switch_priority) {
+ /* This is similar to DosSleep(), but has 8ms granularity in time-critical
+ threads even on Warp3. */
+ HEV hevEvent1 = 0; /* Event semaphore handle */
+ HTIMER htimerEvent1 = 0; /* Timer handle */
+ APIRET rc = NO_ERROR; /* Return code */
+ int ret = 1;
+ ULONG priority = 0, nesting; /* Shut down the warnings */
+ PPIB pib;
+ PTIB tib;
+ char *e = NULL;
+ APIRET badrc;
+
+ if (!(_emx_env & 0x200)) /* DOS */
+ return !_sleep2(ms);
+
+ os2cp_croak(DosCreateEventSem(NULL, /* Unnamed */
+ &hevEvent1, /* Handle of semaphore returned */
+ DC_SEM_SHARED, /* Shared needed for DosAsyncTimer */
+ FALSE), /* Semaphore is in RESET state */
+ "DosCreateEventSem");
+
+ if (ms >= switch_priority)
+ switch_priority = 0;
+ if (switch_priority) {
+ if (CheckOSError(DosGetInfoBlocks(&tib, &pib)))
+ switch_priority = 0;
+ else {
+ /* In Warp3, to switch scheduling to 8ms step, one needs to do
+ DosAsyncTimer() in time-critical thread. On laters versions,
+ more and more cases of wait-for-something are covered.
+
+ It turns out that on Warp3fp42 it is the priority at the time
+ of DosAsyncTimer() which matters. Let's hope that this works
+ with later versions too... XXXX
+ */
+ priority = (tib->tib_ptib2->tib2_ulpri);
+ if ((priority & 0xFF00) == 0x0300) /* already time-critical */
+ switch_priority = 0;
+ /* Make us time-critical. Just modifying TIB is not enough... */
+ /* tib->tib_ptib2->tib2_ulpri = 0x0300;*/
+ /* We do not want to run at high priority if a signal causes us
+ to longjmp() out of this section... */
+ if (DosEnterMustComplete(&nesting))
+ switch_priority = 0;
+ else
+ DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0);
+ }
+ }
+
+ if ((badrc = DosAsyncTimer(ms,
+ (HSEM) hevEvent1, /* Semaphore to post */
+ &htimerEvent1))) /* Timer handler (returned) */
+ e = "DosAsyncTimer";
+
+ if (switch_priority && tib->tib_ptib2->tib2_ulpri == 0x0300) {
+ /* Nobody switched priority while we slept... Ignore errors... */
+ /* tib->tib_ptib2->tib2_ulpri = priority; */ /* Get back... */
+ if (!(rc = DosSetPriority(PRTYS_THREAD, (priority>>8) & 0xFF, 0, 0)))
+ rc = DosSetPriority(PRTYS_THREAD, 0, priority & 0xFF, 0);
+ }
+ if (switch_priority)
+ rc = DosExitMustComplete(&nesting); /* Ignore errors */
+
+ /* The actual blocking call is made with "normal" priority. This way we
+ should not bother with DosSleep(0) etc. to compensate for us interrupting
+ higher-priority threads. The goal is to prohibit the system spending too
+ much time halt()ing, not to run us "no matter what". */
+ if (!e) /* Wait for AsyncTimer event */
+ badrc = DosWaitEventSem(hevEvent1, SEM_INDEFINITE_WAIT);
+
+ if (e) ; /* Do nothing */
+ else if (badrc == ERROR_INTERRUPT)
+ ret = 0;
+ else if (badrc)
+ e = "DosWaitEventSem";
+ if ((rc = DosCloseEventSem(hevEvent1)) && !e) { /* Get rid of semaphore */
+ e = "DosCloseEventSem";
+ badrc = rc;
+ }
+ if (e)
+ os2cp_croak(badrc, e);
+ return ret;
+}
+
+XS(XS_OS2_ms_sleep) /* for testing only... */
+{
+ dXSARGS;
+ ULONG ms, lim;
+
+ if (items > 2 || items < 1)
+ Perl_croak_nocontext("Usage: OS2::ms_sleep(wait_ms [, high_priority_limit])");
+ ms = SvUV(ST(0));
+ lim = items > 1 ? SvUV(ST(1)) : ms + 1;
+ async_mssleep(ms, lim);
+ XSRETURN_EMPTY;
+}
+
ULONG (*pDosTmrQueryFreq) (PULONG);
ULONG (*pDosTmrQueryTime) (unsigned long long *);
@@ -2425,6 +2733,37 @@ XS(XS_OS2_Timer)
XSRETURN(1);
}
+XS(XS_OS2_msCounter)
+{
+ dXSARGS;
+
+ if (items != 0)
+ Perl_croak_nocontext("Usage: OS2::msCounter()");
+ {
+ dXSTARG;
+
+ XSprePUSH; PUSHu(msCounter());
+ }
+ XSRETURN(1);
+}
+
+XS(XS_OS2__InfoTable)
+{
+ dXSARGS;
+ int is_local = 0;
+
+ if (items > 1)
+ Perl_croak_nocontext("Usage: OS2::_infoTable([isLocal])");
+ if (items == 1)
+ is_local = (int)SvIV(ST(0));
+ {
+ dXSTARG;
+
+ XSprePUSH; PUSHu(InfoTable(is_local));
+ }
+ XSRETURN(1);
+}
+
static const char * const dc_fields[] = {
"FAMILY",
"IO_CAPS",
@@ -3219,11 +3558,13 @@ typedef APIRET (*PELP)(PSZ path, ULONG type);
#endif
APIRET
-ExtLIBPATH(ULONG ord, PSZ path, IV type)
+ExtLIBPATH(ULONG ord, PSZ path, IV type, int fatal)
{
ULONG what;
- PFN f = loadByOrdinal(ord, 1); /* Guarantied to load or die! */
+ PFN f = loadByOrdinal(ord, fatal); /* if fatal: load or die! */
+ if (!f) /* Impossible with fatal */
+ return Perl_rc;
if (type > 0)
what = END_LIBPATH;
else if (type == 0)
@@ -3233,23 +3574,35 @@ ExtLIBPATH(ULONG ord, PSZ path, IV type)
return (*(PELP)f)(path, what);
}
-#define extLibpath(to,type) \
- (CheckOSError(ExtLIBPATH(ORD_DosQueryExtLibpath, (to), (type))) ? NULL : (to) )
+#define extLibpath(to,type, fatal) \
+ (CheckOSError(ExtLIBPATH(ORD_DosQueryExtLibpath, (to), (type), fatal)) ? NULL : (to) )
+
+#define extLibpath_set(p,type, fatal) \
+ (!CheckOSError(ExtLIBPATH(ORD_DosSetExtLibpath, (p), (type), fatal)))
-#define extLibpath_set(p,type) \
- (!CheckOSError(ExtLIBPATH(ORD_DosSetExtLibpath, (p), (type))))
+static void
+early_error(char *msg1, char *msg2, char *msg3)
+{ /* Buffer overflow detected; there is very little we can do... */
+ ULONG rc;
+
+ DosWrite(2, msg1, strlen(msg1), &rc);
+ DosWrite(2, msg2, strlen(msg2), &rc);
+ DosWrite(2, msg3, strlen(msg3), &rc);
+ DosExit(EXIT_PROCESS, 2);
+}
XS(XS_Cwd_extLibpath)
{
dXSARGS;
if (items < 0 || items > 1)
- Perl_croak_nocontext("Usage: Cwd::extLibpath(type = 0)");
+ Perl_croak_nocontext("Usage: OS2::extLibpath(type = 0)");
{
IV type;
char to[1024];
U32 rc;
char * RETVAL;
dXSTARG;
+ STRLEN l;
if (items < 1)
type = 0;
@@ -3258,9 +3611,13 @@ XS(XS_Cwd_extLibpath)
}
to[0] = 1; to[1] = 0; /* Sometimes no error reported */
- RETVAL = extLibpath(to, type);
+ RETVAL = extLibpath(to, type, 1); /* Make errors fatal */
if (RETVAL && RETVAL[0] == 1 && RETVAL[1] == 0)
- Perl_croak_nocontext("panic Cwd::extLibpath parameter");
+ Perl_croak_nocontext("panic OS2::extLibpath parameter");
+ l = strlen(to);
+ if (l >= sizeof(to))
+ early_error("Buffer overflow while getting BEGIN/ENDLIBPATH: `",
+ to, "'\r\n"); /* Will not return */
sv_setpv(TARG, RETVAL);
XSprePUSH; PUSHTARG;
}
@@ -3271,7 +3628,7 @@ XS(XS_Cwd_extLibpath_set)
{
dXSARGS;
if (items < 1 || items > 2)
- Perl_croak_nocontext("Usage: Cwd::extLibpath_set(s, type = 0)");
+ Perl_croak_nocontext("Usage: OS2::extLibpath_set(s, type = 0)");
{
STRLEN n_a;
char * s = (char *)SvPV(ST(0),n_a);
@@ -3285,13 +3642,74 @@ XS(XS_Cwd_extLibpath_set)
type = SvIV(ST(1));
}
- RETVAL = extLibpath_set(s, type);
+ RETVAL = extLibpath_set(s, type, 1); /* Make errors fatal */
ST(0) = boolSV(RETVAL);
if (SvREFCNT(ST(0))) sv_2mortal(ST(0));
}
XSRETURN(1);
}
+ULONG
+fill_extLibpath(int type, char *pre, char *post, int replace, char *msg)
+{
+ char buf[2048], *to = buf, buf1[300], *s;
+ STRLEN l;
+ ULONG rc;
+
+ if (!pre && !post)
+ return 0;
+ if (pre) {
+ pre = dir_subst(pre, strlen(pre), buf1, sizeof buf1, dir_subst_pathlike, msg);
+ if (!pre)
+ return ERROR_INVALID_PARAMETER;
+ l = strlen(pre);
+ if (l >= sizeof(buf)/2)
+ return ERROR_BUFFER_OVERFLOW;
+ s = pre - 1;
+ while (*++s)
+ if (*s == '/')
+ *s = '\\'; /* Be extra causious */
+ memcpy(to, pre, l);
+ if (!l || to[l-1] != ';')
+ to[l++] = ';';
+ to += l;
+ }
+
+ if (!replace) {
+ to[0] = 1; to[1] = 0; /* Sometimes no error reported */
+ rc = ExtLIBPATH(ORD_DosQueryExtLibpath, to, type, 0); /* Do not croak */
+ if (rc)
+ return rc;
+ if (to[0] == 1 && to[1] == 0)
+ return ERROR_INVALID_PARAMETER;
+ to += strlen(to);
+ if (buf + sizeof(buf) - 1 <= to) /* Buffer overflow */
+ early_error("Buffer overflow while getting BEGIN/ENDLIBPATH: `",
+ buf, "'\r\n"); /* Will not return */
+ if (to > buf && to[-1] != ';')
+ *to++ = ';';
+ }
+ if (post) {
+ post = dir_subst(post, strlen(post), buf1, sizeof buf1, dir_subst_pathlike, msg);
+ if (!post)
+ return ERROR_INVALID_PARAMETER;
+ l = strlen(post);
+ if (l + to - buf >= sizeof(buf) - 1)
+ return ERROR_BUFFER_OVERFLOW;
+ s = post - 1;
+ while (*++s)
+ if (*s == '/')
+ *s = '\\'; /* Be extra causious */
+ memcpy(to, post, l);
+ if (!l || to[l-1] != ';')
+ to[l++] = ';';
+ to += l;
+ }
+ *to = 0;
+ rc = ExtLIBPATH(ORD_DosSetExtLibpath, buf, type, 0); /* Do not croak */
+ return rc;
+}
+
/* Input: Address, BufLen
APIRET APIENTRY
DosQueryModFromEIP (HMODULE * hmod, ULONG * obj, ULONG BufLen, PCHAR Buf,
@@ -3303,9 +3721,6 @@ DeclOSFuncByORD(APIRET, _DosQueryModFromEIP,ORD_DosQueryModFromEIP,
ULONG * Offset, ULONG Address),
(hmod, obj, BufLen, Buf, Offset, Address))
-enum module_name_how { mod_name_handle, mod_name_shortname, mod_name_full,
- mod_name_C_function = 0x100, mod_name_HMODULE = 0x200};
-
static SV*
module_name_at(void *pp, enum module_name_how how)
{
@@ -3351,9 +3766,6 @@ module_name_of_cv(SV *cv, enum module_name_how how)
return module_name_at(CvXSUB(SvRV(cv)), how);
}
-/* Find module name to which *this* subroutine is compiled */
-#define module_name(how) module_name_at(&module_name_at, how)
-
XS(XS_OS2_DLLname)
{
dXSARGS;
@@ -3589,6 +4001,8 @@ Xs_OS2_init(pTHX)
newXS("File::Copy::syscopy", XS_File__Copy_syscopy, file);
newXS("Cwd::extLibpath", XS_Cwd_extLibpath, file);
newXS("Cwd::extLibpath_set", XS_Cwd_extLibpath_set, file);
+ newXS("OS2::extLibpath", XS_Cwd_extLibpath, file);
+ newXS("OS2::extLibpath_set", XS_Cwd_extLibpath_set, file);
}
newXS("OS2::Error", XS_OS2_Error, file);
newXS("OS2::Errors2Drive", XS_OS2_Errors2Drive, file);
@@ -3620,6 +4034,9 @@ Xs_OS2_init(pTHX)
newXSproto("OS2::_headerInfo", XS_OS2__headerInfo, file, "$$;$$");
newXSproto("OS2::libPath", XS_OS2_libPath, file, "");
newXSproto("OS2::Timer", XS_OS2_Timer, file, "");
+ newXSproto("OS2::msCounter", XS_OS2_msCounter, file, "");
+ newXSproto("OS2::ms_sleep", XS_OS2_ms_sleep, file, "$;$");
+ newXSproto("OS2::_InfoTable", XS_OS2__InfoTable, file, ";$");
newXSproto("OS2::incrMaxFHandles", XS_OS2_incrMaxFHandles, file, ";$");
newXSproto("OS2::SysValues", XS_OS2_SysValues, file, ";$$");
newXSproto("OS2::SysValues_set", XS_OS2_SysValues_set, file, "$$;$");
@@ -3741,6 +4158,12 @@ force_init_emx_runtime(EXCEPTIONREGISTRATIONRECORD *preg, ULONG flags)
oldstack = tib->tib_pstack;
oldstackend = tib->tib_pstacklimit;
+ if ( (char*)&s < (char*)oldstack + 4*1024
+ || (char *)oldstackend < (char*)oldstack + 52*1024 )
+ early_error("It is a lunacy to try to run EMX Perl ",
+ "with less than 64K of stack;\r\n",
+ " at least with non-EMX starter...\r\n");
+
/* Minimize the damage to the stack via reducing the size of argv. */
if (flags & FORCE_EMX_INIT_CONTRACT_ARGV) {
pib->pib_pchcmd = "\0\0"; /* Need 3 concatenated strings */
@@ -3863,7 +4286,7 @@ extern ULONG __os_version(); /* See system.doc */
void
check_emx_runtime(char **env, EXCEPTIONREGISTRATIONRECORD *preg)
{
- ULONG v_crt, v_emx, count = 0, rc, rc1, maybe_inited = 0;
+ ULONG v_crt, v_emx, count = 0, rc = NO_ERROR, rc1, maybe_inited = 0;
static HMTX hmtx_emx_init = NULLHANDLE;
static int emx_init_done = 0;
@@ -4000,7 +4423,8 @@ Perl_OS2_init(char **env)
void
Perl_OS2_init3(char **env, void **preg, int flags)
{
- char *shell;
+ char *shell, *s;
+ ULONG rc;
_uflags (_UF_SBRK_MODEL, _UF_SBRK_ARBITRARY);
MALLOC_INIT;
@@ -4009,15 +4433,20 @@ Perl_OS2_init3(char **env, void **preg, int flags)
settmppath();
OS2_Perl_data.xs_init = &Xs_OS2_init;
- if ( (shell = getenv("PERL_SH_DRIVE")) ) {
+ if (perl_sh_installed) {
+ int l = strlen(perl_sh_installed);
+
+ New(1304, PL_sh_path, l + 1, char);
+ memcpy(PL_sh_path, perl_sh_installed, l + 1);
+ } else if ( (shell = getenv("PERL_SH_DRIVE")) ) {
New(1304, PL_sh_path, strlen(SH_PATH) + 1, char);
strcpy(PL_sh_path, SH_PATH);
PL_sh_path[0] = shell[0];
} else if ( (shell = getenv("PERL_SH_DIR")) ) {
int l = strlen(shell), i;
- if (shell[l-1] == '/' || shell[l-1] == '\\') {
+
+ while (l && (shell[l-1] == '/' || shell[l-1] == '\\'))
l--;
- }
New(1304, PL_sh_path, l + 8, char);
strncpy(PL_sh_path, shell, l);
strcpy(PL_sh_path + l, "/sh.exe");
@@ -4032,6 +4461,29 @@ Perl_OS2_init3(char **env, void **preg, int flags)
os2_mytype = my_type(); /* Do it before morphing. Needed? */
os2_mytype_ini = os2_mytype;
Perl_os2_initial_mode = -1; /* Uninit */
+
+ s = getenv("PERL_BEGINLIBPATH");
+ if (s)
+ rc = fill_extLibpath(0, s, NULL, 1, "PERL_BEGINLIBPATH");
+ else
+ rc = fill_extLibpath(0, getenv("PERL_PRE_BEGINLIBPATH"), getenv("PERL_POST_BEGINLIBPATH"), 0, "PERL_(PRE/POST)_BEGINLIBPATH");
+ if (!rc) {
+ s = getenv("PERL_ENDLIBPATH");
+ if (s)
+ rc = fill_extLibpath(1, s, NULL, 1, "PERL_ENDLIBPATH");
+ else
+ rc = fill_extLibpath(1, getenv("PERL_PRE_ENDLIBPATH"), getenv("PERL_POST_ENDLIBPATH"), 0, "PERL_(PRE/POST)_ENDLIBPATH");
+ }
+ if (rc) {
+ char buf[1024];
+
+ snprintf(buf, sizeof buf, "Error setting BEGIN/ENDLIBPATH: %s\n",
+ os2error(rc));
+ DosWrite(2, buf, strlen(buf), &rc);
+ exit(2);
+ }
+
+ _emxload_env("PERL_EMXLOAD_SECS");
/* Some DLLs reset FP flags on load. We may have been linked with them */
_control87(MCW_EM, MCW_EM);
}
@@ -4460,3 +4912,52 @@ int fork_with_resources()
return rc;
}
+/* APIRET APIENTRY DosGetInfoSeg(PSEL pselGlobal, PSEL pselLocal); */
+
+ULONG _THUNK_FUNCTION(Dos16GetInfoSeg)(USHORT *pGlobal, USHORT *pLocal);
+
+APIRET APIENTRY
+myDosGetInfoSeg(PGINFOSEG *pGlobal, PLINFOSEG *pLocal)
+{
+ APIRET rc;
+ USHORT gSel, lSel; /* Will not cross 64K boundary */
+
+ rc = ((USHORT)
+ (_THUNK_PROLOG (4+4);
+ _THUNK_FLAT (&gSel);
+ _THUNK_FLAT (&lSel);
+ _THUNK_CALL (Dos16GetInfoSeg)));
+ if (rc)
+ return rc;
+ *pGlobal = MAKEPGINFOSEG(gSel);
+ *pLocal = MAKEPLINFOSEG(lSel);
+ return rc;
+}
+
+static void
+GetInfoTables(void)
+{
+ ULONG rc = 0;
+
+ MUTEX_LOCK(&perlos2_state_mutex);
+ if (!gTable)
+ rc = myDosGetInfoSeg(&gTable, &lTable);
+ MUTEX_UNLOCK(&perlos2_state_mutex);
+ os2cp_croak(rc, "Dos16GetInfoSeg");
+}
+
+ULONG
+msCounter(void)
+{ /* XXXX Is not lTable thread-specific? */
+ if (!gTable)
+ GetInfoTables();
+ return gTable->SIS_MsCount;
+}
+
+ULONG
+InfoTable(int local)
+{
+ if (!gTable)
+ GetInfoTables();
+ return local ? (ULONG)lTable : (ULONG)gTable;
+}
diff --git a/os2/os2ish.h b/os2/os2ish.h
index accba2a0c9..b3b3ed0c14 100644
--- a/os2/os2ish.h
+++ b/os2/os2ish.h
@@ -318,6 +318,11 @@ void my_setpwent (void);
void my_endpwent (void);
char *gcvt_os2(double value, int digits, char *buffer);
+extern int async_mssleep(unsigned long ms, int switch_priority);
+extern unsigned long msCounter(void);
+extern unsigned long InfoTable(int local);
+extern unsigned long find_myself(void);
+
#define MAX_SLEEP (((1<30) / (1000/4))-1) /* 1<32 msec */
static __inline__ unsigned
@@ -358,7 +363,7 @@ struct passwd *my_getpwnam (__const__ char *);
#define strtoll _strtoll
#define strtoull _strtoull
-#define usleep(usec) ((void)_sleep2(((usec)+500)/1000))
+#define usleep(usec) ((void)async_mssleep(((usec)+500)/1000, 500))
/*
@@ -749,6 +754,21 @@ enum entries_ordinals {
void ResetWinError(void);
void CroakWinError(int die, char *name);
+enum Perlos2_handler {
+ Perlos2_handler_mangle = 1,
+ Perlos2_handler_perl_sh,
+ Perlos2_handler_perllib_from,
+ Perlos2_handler_perllib_to,
+};
+enum dir_subst_e {
+ dir_subst_fatal = 1,
+ dir_subst_pathlike = 2
+};
+
+extern int Perl_OS2_handler_install(void *handler, enum Perlos2_handler how);
+extern char *dir_subst(char *s, unsigned int l, char *b, unsigned int bl, enum dir_subst_e flags, char *msg);
+extern unsigned long fill_extLibpath(int type, char *pre, char *post, int replace, char *msg);
+
#define PERLLIB_MANGLE(s, n) perllib_mangle((s), (n))
char *perllib_mangle(char *, unsigned int);
@@ -759,7 +779,7 @@ static __inline__ int
my_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
{
if (nfds == 0 && timeout && (_emx_env & 0x200)) {
- if (DosSleep(1000 * timeout->tv_sec + (timeout->tv_usec + 500)/1000) == 0)
+ if (async_mssleep(1000 * timeout->tv_sec + (timeout->tv_usec + 500)/1000, 500))
return 0;
errno = EINTR;
return -1;
@@ -782,6 +802,18 @@ int getpriority(int which /* ignored */, int pid);
void croak_with_os2error(char *s) __attribute__((noreturn));
+/* void return value */
+#define os2cp_croak(rc,msg) (CheckOSError(rc) && (croak_with_os2error(msg),0))
+
+/* propagates rc */
+#define os2win_croak(rc,msg) \
+ SaveCroakWinError((expr), 1 /* die */, /* no prefix */, (msg))
+
+/* propagates rc; use with functions which may return 0 on success */
+#define os2win_croak_0OK(rc,msg) \
+ SaveCroakWinError((ResetWinError, (expr)), \
+ 1 /* die */, /* no prefix */, (msg))
+
#ifdef PERL_CORE
int os2_do_spawn(pTHX_ char *cmd);
int os2_do_aspawn(pTHX_ SV *really, SV **vmark, SV **vsp);
@@ -851,6 +883,192 @@ int os2_do_aspawn(pTHX_ SV *really, SV **vmark, SV **vsp);
#endif
+/* ************************************************* */
+#ifndef MAKEPLINFOSEG
+
+/* From $DDK\base32\rel\os2c\include\base\os2\16bit\infoseg.h + typedefs */
+
+/*
+ * The structure below defines the content and organization of the system
+ * information segment (InfoSeg). The actual table is statically defined in
+ * SDATA.ASM. Ring 0, read/write access is obtained by the clock device
+ * driver using the DevHlp GetDOSVar function. (GetDOSVar returns a ring 0,
+ * read-only selector to all other requestors.)
+ *
+ * In order to prevent an errant process from destroying the infoseg, two
+ * identical global infosegs are maintained. One is in the tiled shared
+ * arena and is accessible in user mode (and therefore can potentially be
+ * overwritten from ring 2), and the other is in the system arena and is
+ * accessible only in kernel mode. All kernel code (except the clock driver)
+ * is responsible for updating BOTH copies of the infoseg. The copy kept
+ * in the system arena is addressable as DOSGROUP:SISData, and the copy
+ * in the shared arena is addressable via a system arena alias. 16:16 and
+ * 0:32 pointers to the alias are stored in _Sis2.
+ */
+
+typedef struct InfoSegGDT {
+
+/* Time (offset 0x00) */
+
+unsigned long SIS_BigTime; /* Time from 1-1-1970 in seconds */
+unsigned long SIS_MsCount; /* Freerunning milliseconds counter */
+unsigned char SIS_HrsTime; /* Hours */
+unsigned char SIS_MinTime; /* Minutes */
+unsigned char SIS_SecTime; /* Seconds */
+unsigned char SIS_HunTime; /* Hundredths of seconds */
+unsigned short SIS_TimeZone; /* Timezone in min from GMT (Set to EST) */
+unsigned short SIS_ClkIntrvl; /* Timer interval (units=0.0001 secs) */
+
+/* Date (offset 0x10) */
+
+unsigned char SIS_DayDate; /* Day-of-month (1-31) */
+unsigned char SIS_MonDate; /* Month (1-12) */
+unsigned short SIS_YrsDate; /* Year (>= 1980) */
+unsigned char SIS_DOWDate; /* Day-of-week (1-1-80 = Tues = 3) */
+
+/* Version (offset 0x15) */
+
+unsigned char SIS_VerMajor; /* Major version number */
+unsigned char SIS_VerMinor; /* Minor version number */
+unsigned char SIS_RevLettr; /* Revision letter */
+
+/* System Status (offset 0x18) */
+
+unsigned char SIS_CurScrnGrp; /* Fgnd screen group # */
+unsigned char SIS_MaxScrnGrp; /* Maximum number of screen groups */
+unsigned char SIS_HugeShfCnt; /* Shift count for huge segments */
+unsigned char SIS_ProtMdOnly; /* Protect-mode-only indicator */
+unsigned short SIS_FgndPID; /* Foreground process ID */
+
+/* Scheduler Parms (offset 0x1E) */
+
+unsigned char SIS_Dynamic; /* Dynamic variation flag (1=enabled) */
+unsigned char SIS_MaxWait; /* Maxwait (seconds) */
+unsigned short SIS_MinSlice; /* Minimum timeslice (milliseconds) */
+unsigned short SIS_MaxSlice; /* Maximum timeslice (milliseconds) */
+
+/* Boot Drive (offset 0x24) */
+
+unsigned short SIS_BootDrv; /* Drive from which system was booted */
+
+/* RAS Major Event Code Table (offset 0x26) */
+
+unsigned char SIS_mec_table[32]; /* Table of RAS Major Event Codes (MECs) */
+
+/* Additional Session Data (offset 0x46) */
+
+unsigned char SIS_MaxVioWinSG; /* Max. no. of VIO windowable SG's */
+unsigned char SIS_MaxPresMgrSG; /* Max. no. of Presentation Manager SG's */
+
+/* Error logging Information (offset 0x48) */
+
+unsigned short SIS_SysLog; /* Error Logging Status */
+
+/* Additional RAS Information (offset 0x4A) */
+
+unsigned short SIS_MMIOBase; /* Memory mapped I/O selector */
+unsigned long SIS_MMIOAddr; /* Memory mapped I/O address */
+
+/* Additional 2.0 Data (offset 0x50) */
+
+unsigned char SIS_MaxVDMs; /* Max. no. of Virtual DOS machines */
+unsigned char SIS_Reserved;
+
+unsigned char SIS_perf_mec_table[32]; /* varga 6/5/97 Table of Perfomance Major Event Codes (MECS) varga*/
+} GINFOSEG, *PGINFOSEG;
+
+#define SIS_LEN sizeof(struct InfoSegGDT)
+
+/*
+ * InfoSeg LDT Data Segment Structure
+ *
+ * The structure below defines the content and organization of the system
+ * information in a special per-process segment to be accessible by the
+ * process through the LDT (read-only).
+ *
+ * As in the global infoseg, two copies of the current processes local
+ * infoseg exist, one accessible in both user and kernel mode, the other
+ * only in kernel mode. Kernel code is responsible for updating BOTH copies.
+ * Pointers to the local infoseg copy are stored in _Lis2.
+ *
+ * Note that only the currently running process has an extra copy of the
+ * local infoseg. The copy is done at context switch time.
+ */
+
+typedef struct InfoSegLDT {
+unsigned short LIS_CurProcID; /* Current process ID */
+unsigned short LIS_ParProcID; /* Process ID of parent */
+unsigned short LIS_CurThrdPri; /* Current thread priority */
+unsigned short LIS_CurThrdID; /* Current thread ID */
+unsigned short LIS_CurScrnGrp; /* Screengroup */
+unsigned char LIS_ProcStatus; /* Process status bits */
+unsigned char LIS_fillbyte1; /* filler byte */
+unsigned short LIS_Fgnd; /* Current process is in foreground */
+unsigned char LIS_ProcType; /* Current process type */
+unsigned char LIS_fillbyte2; /* filler byte */
+
+unsigned short LIS_AX; /* @@V1 Environment selector */
+unsigned short LIS_BX; /* @@V1 Offset of command line start */
+unsigned short LIS_CX; /* @@V1 Length of Data Segment */
+unsigned short LIS_DX; /* @@V1 STACKSIZE from the .EXE file */
+unsigned short LIS_SI; /* @@V1 HEAPSIZE from the .EXE file */
+unsigned short LIS_DI; /* @@V1 Module handle of the application */
+unsigned short LIS_DS; /* @@V1 Data Segment Handle of application */
+
+unsigned short LIS_PackSel; /* First tiled selector in this EXE */
+unsigned short LIS_PackShrSel; /* First selector above shared arena */
+unsigned short LIS_PackPckSel; /* First selector above packed arena */
+/* #ifdef SMP */
+unsigned long LIS_pTIB; /* Pointer to TIB */
+unsigned long LIS_pPIB; /* Pointer to PIB */
+/* #endif */
+} LINFOSEG, *PLINFOSEG;
+
+#define LIS_LEN sizeof(struct InfoSegLDT)
+
+
+/*
+ * Process Type codes
+ *
+ * These are the definitons for the codes stored
+ * in the LIS_ProcType field in the local infoseg.
+ */
+
+#define LIS_PT_FULLSCRN 0 /* Full screen app. */
+#define LIS_PT_REALMODE 1 /* Real mode process */
+#define LIS_PT_VIOWIN 2 /* VIO windowable app. */
+#define LIS_PT_PRESMGR 3 /* Presentation Manager app. */
+#define LIS_PT_DETACHED 4 /* Detached app. */
+
+
+/*
+ *
+ * Process Status Bit Definitions
+ *
+ */
+
+#define LIS_PS_EXITLIST 0x01 /* In exitlist handler */
+
+
+/*
+ * Flags equates for the Global Info Segment
+ * SIS_SysLog WORD in Global Info Segment
+ *
+ * xxxx xxxx xxxx xxx0 Error Logging Disabled
+ * xxxx xxxx xxxx xxx1 Error Logging Enabled
+ *
+ * xxxx xxxx xxxx xx0x Error Logging not available
+ * xxxx xxxx xxxx xx1x Error Logging available
+ */
+
+#define LF_LOGENABLE 0x0001 /* Logging enabled */
+#define LF_LOGAVAILABLE 0x0002 /* Logging available */
+
+#define MAKEPGINFOSEG(sel) ((PGINFOSEG)MAKEP(sel, 0))
+#define MAKEPLINFOSEG(sel) ((PLINFOSEG)MAKEP(sel, 0))
+
+#endif /* ndef(MAKEPLINFOSEG) */
+
/* ************************************************************ */
#define Dos32QuerySysState DosQuerySysState
#define QuerySysState(flags, pid, buf, bufsz) \
diff --git a/os2/perl2cmd.pl b/os2/perl2cmd.pl
index 4db40a0a31..07529ad8e8 100644
--- a/os2/perl2cmd.pl
+++ b/os2/perl2cmd.pl
@@ -2,6 +2,7 @@
# Note that we cannot put hashbang to be extproc to make Configure work.
use Config;
+use File::Compare;
$dir = shift;
$dir =~ s|/|\\|g ;
@@ -26,9 +27,11 @@ foreach $file (<$idir/*>) {
$base =~ s|\.pl$||;
#$file =~ s|/|\\|g ;
warn "Clashing output name for $file, skipping" if $seen{$base}++;
- print "Processing $file => $dir\\$base.cmd\n";
+ my $new = (-f "$dir/$base.cmd" ? '' : ' (new file)');
+ print "Processing $file => $dir/$base.cmd$new\n";
+ my $ext = ($new ? '.cmd' : '.tcm');
open IN, '<', $file or warn, next;
- open OUT, '>', "$dir/$base.cmd" or warn, next;
+ open OUT, '>', "$dir/$base$ext" or warn, next;
my $firstline = <IN>;
my $flags = '';
$flags = $2 if $firstline =~ /^#!\s*(\S+)\s+-([^#]+?)\s*(#|$)/;
@@ -36,5 +39,16 @@ foreach $file (<$idir/*>) {
print OUT $_ while <IN>;
close IN or warn, next;
close OUT or warn, next;
+ chmod 0444, "$dir/$base$ext";
+ next if $new;
+ if (compare "$dir/$base$ext", "$dir/$base.cmd") { # different
+ chmod 0666, "$dir/$base.cmd";
+ unlink "$dir/$base.cmd";
+ rename "$dir/$base$ext", "$dir/$base.cmd";
+ } else {
+ chmod 0666, "$dir/$base$ext";
+ unlink "$dir/$base$ext";
+ print "...unchanged...\n";
+ }
}