#include <os2.h>
#include "dlfcn.h"
#include <emx/syscalls.h>
+#include <sys/emxload.h>
#include <sys/uflags.h>
#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)
{
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; */
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 */
#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 *);
Renew(thread_join_data, thread_join_count, thread_join_t);
Zero(thread_join_data + oc, thread_join_count - oc, thread_join_t);
} else {
- Newz(1323, thread_join_data, thread_join_count, thread_join_t);
+ Newxz(thread_join_data, thread_join_count, thread_join_t);
}
}
if (thread_join_data[tid].state != pthreads_st_none) {
int rc;
STRLEN n_a;
if ((rc = DosResetEventSem(*c,&n_a)) && (rc != ERROR_ALREADY_RESET))
- Perl_rc = rc, croak_with_os2error("panic: COND_WAIT-reset");
+ Perl_rc = CheckOSError(rc), croak_with_os2error("panic: COND_WAIT-reset");
if (m) MUTEX_UNLOCK(m);
if (CheckOSError(DosWaitEventSem(*c,SEM_INDEFINITE_WAIT))
&& (rc != ERROR_INTERRUPT))
return 0;
}
}
- New(1322, pbuffer, buf_len, char);
+ Newx(pbuffer, buf_len, char);
/* QSS_PROCESS | QSS_MODULE | QSS_SEMAPHORES | QSS_SHARED */
rc = QuerySysState(flags, pid, pbuffer, buf_len);
while (rc == ERROR_BUFFER_OVERFLOW) {
{
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", };
if (strnEQ(cmd,"/bin/sh",7) && isSPACE(cmd[7])) {
STRLEN l = strlen(PL_sh_path);
- New(1302, news, strlen(cmd) - 7 + l + 1, char);
+ Newx(news, strlen(cmd) - 7 + l + 1, char);
strcpy(news, PL_sh_path);
strcpy(news + l, cmd + 7);
cmd = news;
}
/* cmd="a" may lead to "sh", "-c", "\"$@\"", "a", "a.cmd", NULL */
- New(1303,PL_Argv, (s - cmd + 11) / 2, char*);
+ Newx(PL_Argv, (s - cmd + 11) / 2, char*);
PL_Cmd = savepvn(cmd, s-cmd);
a = PL_Argv;
for (s = PL_Cmd; *s;) {
return rc;
}
+#define ASPAWN_WAIT 0
+#define ASPAWN_EXEC 1
+#define ASPAWN_NOWAIT 2
+
/* Array spawn/exec. */
int
-os2_aspawn4(pTHX_ SV *really, register SV **vmark, register SV **vsp, int execing)
+os2_aspawn_4(pTHX_ SV *really, register SV **args, I32 cnt, int execing)
{
- register SV **mark = (SV **)vmark;
- register SV **sp = (SV **)vsp;
+ register SV **argp = (SV **)args;
+ register SV **last = argp + cnt;
register char **a;
int rc;
int flag = P_WAIT, flag_set = 0;
STRLEN n_a;
- if (sp > mark) {
- New(1301,PL_Argv, sp - mark + 3, char*);
+ if (cnt) {
+ Newx(PL_Argv, cnt + 3, char*); /* 3 extra to expand #! */
a = PL_Argv;
- if (mark < sp && SvNIOKp(*(mark+1)) && !SvPOKp(*(mark+1))) {
- ++mark;
- flag = SvIVx(*mark);
- flag_set = 1;
-
- }
+ if (cnt > 1 && SvNIOKp(*argp) && !SvPOKp(*argp)) {
+ flag = SvIVx(*argp);
+ flag_set = 1;
+ } else
+ --argp;
- while (++mark <= sp) {
- if (*mark)
- *a++ = SvPVx(*mark, n_a);
+ while (++argp < last) {
+ if (*argp)
+ *a++ = SvPVx(*argp, n_a);
else
*a++ = "";
}
*a = Nullch;
if ( flag_set && (a == PL_Argv + 1)
- && !really && !execing ) { /* One arg? */
+ && !really && execing == ASPAWN_WAIT ) { /* One arg? */
rc = do_spawn3(aTHX_ a[-1], EXECF_SPAWN_BYFLAG, flag);
- } else
- rc = do_spawn_ve(aTHX_ really, flag,
- (execing ? EXECF_EXEC : EXECF_SPAWN), NULL, 0);
+ } else {
+ const int execf[3] = {EXECF_SPAWN, EXECF_EXEC, EXECF_SPAWN_NOWAIT};
+
+ rc = do_spawn_ve(aTHX_ really, flag, execf[execing], NULL, 0);
+ }
} else
rc = -1;
do_execfree();
int
os2_do_aspawn(pTHX_ SV *really, register SV **vmark, register SV **vsp)
{
- return os2_aspawn4(aTHX_ really, vmark, vsp, 0);
+ return os2_aspawn_4(aTHX_ really, vmark + 1, vsp - vmark, ASPAWN_WAIT);
}
/* Array exec. */
bool
Perl_do_aexec(pTHX_ SV* really, SV** vmark, SV** vsp)
{
- return os2_aspawn4(aTHX_ really, vmark, vsp, 1);
+ return os2_aspawn_4(aTHX_ really, vmark + 1, vsp - vmark, ASPAWN_EXEC);
}
int
}
bool
-Perl_do_exec(pTHX_ char *cmd)
+Perl_do_exec(pTHX_ const char *cmd)
{
do_spawn3(aTHX_ cmd, EXECF_EXEC, 0);
return FALSE;
}
PerlIO *
-my_syspopen(pTHX_ char *cmd, char *mode)
+my_syspopen4(pTHX_ char *cmd, char *mode, I32 cnt, SV** args)
{
#ifndef USE_POPEN
int p[2];
fcntl(p[this], F_SETFD, FD_CLOEXEC);
if (newfd != -1)
fcntl(newfd, F_SETFD, FD_CLOEXEC);
- pid = do_spawn_nowait(aTHX_ cmd);
+ if (cnt) { /* Args: "Real cmd", before first arg, the last, execing */
+ pid = os2_aspawn_4(aTHX_ Nullsv, args, cnt, ASPAWN_NOWAIT);
+ } else
+ pid = do_spawn_nowait(aTHX_ cmd);
if (newfd == -1)
close(*mode == 'r'); /* It was closed initially */
else if (newfd != (*mode == 'r')) { /* Probably this check is not needed */
PerlIO *res;
SV *sv;
+ if (cnt)
+ Perl_croak(aTHX_ "List form of piped open not implemented");
+
# ifdef TRYSHELL
res = popen(cmd, mode);
# else
}
+PerlIO *
+my_syspopen(pTHX_ char *cmd, char *mode)
+{
+ return my_syspopen4(aTHX_ cmd, mode, 0, NULL);
+}
+
/******************************************************************/
#ifndef HAS_FORK
if (!replaceModule(target, source, backup))
croak_with_os2error("replaceModule() error");
}
- XSRETURN_EMPTY;
+ XSRETURN_YES;
}
/* APIRET APIENTRY DosPerfSysCall(ULONG ulCommand, ULONG ulParm1,
RETVAL = perfSysCall(ulCommand, ulParm1, ulParm2, ulParm3);
if (!RETVAL)
croak_with_os2error("perfSysCall() error");
+ XSprePUSH;
if (total) {
int i,j;
PUSHn(u[0][0]); /* Total ticks on the first processor */
XSRETURN(1);
}
+ EXTEND(SP, 4*total);
for (i=0; i < total; i++)
for (j=0; j < 4; j++)
PUSHs(sv_2mortal(newSVnv(u[i][j])));
case PMERR_NOT_IN_A_PM_SESSION:
name = "PMERR_NOT_IN_A_PM_SESSION";
break;
+ case PMERR_INVALID_ATOM:
+ name = "PMERR_INVALID_ATOM";
+ break;
+ case PMERR_INVALID_HATOMTBL:
+ name = "PMERR_INVALID_HATOMTMB";
+ break;
+ case PMERR_INVALID_INTEGER_ATOM:
+ name = "PMERR_INVALID_INTEGER_ATOM";
+ break;
+ case PMERR_INVALID_ATOM_NAME:
+ name = "PMERR_INVALID_ATOM_NAME";
+ break;
+ case PMERR_ATOM_NAME_NOT_FOUND:
+ name = "PMERR_ATOM_NAME_NOT_FOUND";
+ break;
}
sprintf(s, "%s%s[No description found in OSO001.MSG]",
name, (*name ? "=" : ""));
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 == '\\')
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;
}
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_YES;
+}
+
ULONG (*pDosTmrQueryFreq) (PULONG);
ULONG (*pDosTmrQueryTime) (unsigned long long *);
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",
- CAPS_FAMILY + 1,
si)))
rc1 = Perl_rc;
+ else {
+ EXTEND(SP,2*(CAPS_DEVICE_POLYSET_POINTS - CAPS_FAMILY + 1));
+ while (i < CAPS_DEVICE_POLYSET_POINTS - CAPS_FAMILY + 1) {
+ ST(j) = sv_newmortal();
+ sv_setpv(ST(j++), dc_fields[i]);
+ ST(j) = sv_newmortal();
+ sv_setiv(ST(j++), si[i]);
+ i++;
+ }
+ i = CAPS_DEVICE_POLYSET_POINTS + 1;
+ while (i < CAPS_DEVICE_POLYSET_POINTS + 11) { /* Just in case... */
+ LONG l;
+
+ if (CheckWinError(pDevQueryCaps(hScreenDC, i, 1, &l)))
+ break;
+ EXTEND(SP, j + 2);
+ ST(j) = sv_newmortal();
+ sv_setiv(ST(j++), i);
+ ST(j) = sv_newmortal();
+ sv_setiv(ST(j++), l);
+ i++;
+ }
+ }
if (!items && CheckWinError(pDevCloseDC(hScreenDC)))
Perl_warn_nocontext("DevCloseDC() failed: %s", os2error(Perl_rc));
if (rc1)
Perl_rc = rc1, croak_with_os2error("DevQueryCaps() failed");
- EXTEND(SP,2*(CAPS_DEVICE_POLYSET_POINTS - CAPS_FAMILY + 1));
- while (i < CAPS_DEVICE_POLYSET_POINTS - CAPS_FAMILY + 1) {
- ST(j) = sv_newmortal();
- sv_setpv(ST(j++), dc_fields[i]);
- ST(j) = sv_newmortal();
- sv_setiv(ST(j++), si[i]);
- i++;
- }
+ XSRETURN(j);
}
- XSRETURN(2 * (CAPS_DEVICE_POLYSET_POINTS - CAPS_FAMILY + 1));
}
LONG (*pWinQuerySysValue) (HWND hwndDesktop, LONG iSysValue);
if (CheckWinError(pWinSetSysValue(hwnd, which, val)))
croak_with_os2error("SysValues_set()");
}
- XSRETURN_EMPTY;
+ XSRETURN_YES;
}
#define QSV_MAX_WARP3 QSV_MAX_COMP_LENGTH
(PVOID)si,
sizeof(si))))
croak_with_os2error("DosQuerySysInfo() failed");
- while (last++ <= C_ARRAY_LENGTH(si)) {
+ while (++last <= C_ARRAY_LENGTH(si)) {
if (CheckOSError(DosQuerySysInfo(last, last, /* One entry only */
(PVOID)(si+last-1),
sizeof(*si)))) {
break;
}
}
- last--;
+ last--; /* Count of successfully processed offsets */
EXTEND(SP,2*last);
while (i < last) {
ST(j) = sv_newmortal();
- sv_setpv(ST(j++), si_fields[i]);
+ if (i < C_ARRAY_LENGTH(si_fields))
+ sv_setpv(ST(j++), si_fields[i]);
+ else
+ sv_setiv(ST(j++), i + 1);
ST(j) = sv_newmortal();
- sv_setiv(ST(j++), si[i]);
+ sv_setuv(ST(j++), si[i]);
i++;
}
XSRETURN(2 * last);
if (CheckOSError(DosBeep(freq, ms)))
croak_with_os2error("SysValues_set()");
}
- XSRETURN_EMPTY;
+ XSRETURN_YES;
}
#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)
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) \
- (!CheckOSError(ExtLIBPATH(ORD_DosSetExtLibpath, (p), (type))))
+#define extLibpath_set(p,type, fatal) \
+ (!CheckOSError(ExtLIBPATH(ORD_DosSetExtLibpath, (p), (type), fatal)))
+
+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;
}
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;
}
{
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);
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,
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)
{
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;
else
Perl_croak(aTHX_ "Usage: OS2::mytype_set(type)");
my_type_set(type);
- XSRETURN_EMPTY;
+ XSRETURN_YES;
}
XSRETURN(1);
}
+/* wait>0: force wait, wait<0: force nowait;
+ if restore, save/restore flags; otherwise flags are in oflags.
+
+ Returns 1 if connected, 0 if not (due to nowait); croaks on error. */
+static ULONG
+connectNPipe(ULONG hpipe, int wait, ULONG restore, ULONG oflags)
+{
+ ULONG ret = ERROR_INTERRUPT, rc, flags;
+
+ if (restore && wait)
+ os2cp_croak(DosQueryNPHState(hpipe, &oflags), "DosQueryNPHState()");
+ /* DosSetNPHState fails if more bits than NP_NOWAIT|NP_READMODE_MESSAGE */
+ oflags &= (NP_NOWAIT | NP_READMODE_MESSAGE);
+ flags = (oflags & ~NP_NOWAIT) | (wait > 0 ? NP_WAIT : NP_NOWAIT);
+ /* We know (o)flags unless wait == 0 && restore */
+ if (wait && (flags != oflags))
+ os2cp_croak(DosSetNPHState(hpipe, flags), "DosSetNPHState()");
+ while (ret == ERROR_INTERRUPT)
+ ret = DosConnectNPipe(hpipe);
+ (void)CheckOSError(ret);
+ if (restore && wait && (flags != oflags))
+ os2cp_croak(DosSetNPHState(hpipe, oflags), "DosSetNPHState() back");
+ /* We know flags unless wait == 0 && restore */
+ if ( ((wait || restore) ? (flags & NP_NOWAIT) : 1)
+ && (ret == ERROR_PIPE_NOT_CONNECTED) )
+ return 0; /* normal return value */
+ if (ret == NO_ERROR)
+ return 1;
+ croak_with_os2error("DosConnectNPipe()");
+}
+
+/* With a lot of manual editing:
+NO_OUTPUT ULONG
+DosCreateNPipe(PCSZ pszName, OUTLIST HPIPE hpipe, ULONG ulOpenMode, int connect = 1, int count = 1, ULONG ulInbufLength = 8192, ULONG ulOutbufLength = ulInbufLength, ULONG ulPipeMode = count | NP_NOWAIT | NP_TYPE_BYTE | NP_READMODE_BYTE, ULONG ulTimeout = 0)
+ PREINIT:
+ ULONG rc;
+ C_ARGS:
+ pszName, &hpipe, ulOpenMode, ulPipeMode, ulInbufLength, ulOutbufLength, ulTimeout
+ POSTCALL:
+ if (CheckOSError(RETVAL))
+ croak_with_os2error("OS2::mkpipe() error");
+*/
+XS(XS_OS2_pipe); /* prototype to pass -Wmissing-prototypes */
+XS(XS_OS2_pipe)
+{
+ dXSARGS;
+ if (items < 2 || items > 8)
+ Perl_croak(aTHX_ "Usage: OS2::pipe(pszName, ulOpenMode, connect= 1, count= 1, ulInbufLength= 8192, ulOutbufLength= ulInbufLength, ulPipeMode= count | NP_NOWAIT | NP_TYPE_BYTE | NP_READMODE_BYTE, ulTimeout= 0)");
+ {
+ ULONG RETVAL;
+ PCSZ pszName = ( SvOK(ST(0)) ? (PCSZ)SvPV(ST(0),PL_na) : NULL );
+ HPIPE hpipe;
+ SV *OpenMode = ST(1);
+ ULONG ulOpenMode;
+ int connect = 0, count, message_r = 0, message = 0, b = 0;
+ ULONG ulInbufLength, ulOutbufLength, ulPipeMode, ulTimeout, rc;
+ STRLEN len;
+ char *s, buf[10], *s1, *perltype = Nullch;
+ PerlIO *perlio;
+ double timeout;
+
+ if (!pszName || !*pszName)
+ Perl_croak(aTHX_ "OS2::pipe(): empty pipe name");
+ s = SvPV(OpenMode, len);
+ if (len == 4 && strEQ(s, "wait")) { /* DosWaitNPipe() */
+ ULONG ms = 0xFFFFFFFF, ret = ERROR_INTERRUPT; /* Indefinite */
+
+ if (items == 3) {
+ timeout = (double)SvNV(ST(2));
+ ms = timeout * 1000;
+ if (timeout < 0)
+ ms = 0xFFFFFFFF; /* Indefinite */
+ else if (timeout && !ms)
+ ms = 1;
+ } else if (items > 3)
+ Perl_croak(aTHX_ "OS2::pipe(): too many arguments for wait-for-connect: %ld", (long)items);
+
+ while (ret == ERROR_INTERRUPT)
+ ret = DosWaitNPipe(pszName, ms); /* XXXX Update ms? */
+ os2cp_croak(ret, "DosWaitNPipe()");
+ XSRETURN_YES;
+ }
+ if (len == 4 && strEQ(s, "call")) { /* DosCallNPipe() */
+ ULONG ms = 0xFFFFFFFF, got; /* Indefinite */
+ STRLEN l;
+ char *s;
+ char buf[8192];
+ STRLEN ll = sizeof(buf);
+ char *b = buf;
+
+ if (items < 3 || items > 5)
+ Perl_croak(aTHX_ "usage: OS2::pipe(pszName, 'call', write [, timeout= 0xFFFFFFFF, buffsize = 8192])");
+ s = SvPV(ST(2), l);
+ if (items >= 4) {
+ timeout = (double)SvNV(ST(3));
+ ms = timeout * 1000;
+ if (timeout < 0)
+ ms = 0xFFFFFFFF; /* Indefinite */
+ else if (timeout && !ms)
+ ms = 1;
+ }
+ if (items >= 5) {
+ STRLEN lll = SvUV(ST(4));
+ SV *sv = NEWSV(914, lll);
+
+ sv_2mortal(sv);
+ ll = lll;
+ b = SvPVX(sv);
+ }
+
+ os2cp_croak(DosCallNPipe(pszName, s, l, b, ll, &got, ms),
+ "DosCallNPipe()");
+ XSRETURN_PVN(b, got);
+ }
+ s1 = buf;
+ if (len && len <= 3 && !(*s >= '0' && *s <= '9')) {
+ int r, w, R, W;
+
+ r = strchr(s, 'r') != 0;
+ w = strchr(s, 'w') != 0;
+ R = strchr(s, 'R') != 0;
+ W = strchr(s, 'W') != 0;
+ b = strchr(s, 'b') != 0;
+ if (r + w + R + W + b != len || (r && R) || (w && W))
+ Perl_croak(aTHX_ "OS2::pipe(): unknown OpenMode argument: `%s'", s);
+ if ((r || R) && (w || W))
+ ulOpenMode = NP_INHERIT | NP_NOWRITEBEHIND | NP_ACCESS_DUPLEX;
+ else if (r || R)
+ ulOpenMode = NP_INHERIT | NP_NOWRITEBEHIND | NP_ACCESS_INBOUND;
+ else
+ ulOpenMode = NP_INHERIT | NP_NOWRITEBEHIND | NP_ACCESS_OUTBOUND;
+ if (R)
+ message = message_r = 1;
+ if (W)
+ message = 1;
+ else if (w && R)
+ Perl_croak(aTHX_ "OS2::pipe(): can't have message read mode for non-message pipes");
+ } else
+ ulOpenMode = (ULONG)SvUV(OpenMode); /* ST(1) */
+
+ if ( (ulOpenMode & 0x3) == NP_ACCESS_DUPLEX
+ || (ulOpenMode & 0x3) == NP_ACCESS_INBOUND )
+ *s1++ = 'r';
+ if ( (ulOpenMode & 0x3) == NP_ACCESS_DUPLEX )
+ *s1++ = '+';
+ if ( (ulOpenMode & 0x3) == NP_ACCESS_OUTBOUND )
+ *s1++ = 'w';
+ if (b)
+ *s1++ = 'b';
+ *s1 = 0;
+ if ( (ulOpenMode & 0x3) == NP_ACCESS_DUPLEX )
+ perltype = "+<&";
+ else if ( (ulOpenMode & 0x3) == NP_ACCESS_OUTBOUND )
+ perltype = ">&";
+ else
+ perltype = "<&";
+
+ if (items < 3)
+ connect = -1; /* no wait */
+ else if (SvTRUE(ST(2))) {
+ s = SvPV(ST(2), len);
+ if (len == 6 && strEQ(s, "nowait"))
+ connect = -1; /* no wait */
+ else if (len == 4 && strEQ(s, "wait"))
+ connect = 1; /* wait */
+ else
+ Perl_croak(aTHX_ "OS2::pipe(): unknown connect argument: `%s'", s);
+ }
+
+ if (items < 4)
+ count = 1;
+ else
+ count = (int)SvIV(ST(3));
+
+ if (items < 5)
+ ulInbufLength = 8192;
+ else
+ ulInbufLength = (ULONG)SvUV(ST(4));
+
+ if (items < 6)
+ ulOutbufLength = ulInbufLength;
+ else
+ ulOutbufLength = (ULONG)SvUV(ST(5));
+
+ if (count < -1 || count == 0 || count >= 255)
+ Perl_croak(aTHX_ "OS2::pipe(): count should be -1 or between 1 and 254: %ld", (long)count);
+ if (count < 0 )
+ count = 255; /* Unlimited */
+
+ ulPipeMode = count;
+ if (items < 7)
+ ulPipeMode |= (NP_WAIT
+ | (message ? NP_TYPE_MESSAGE : NP_TYPE_BYTE)
+ | (message_r ? NP_READMODE_MESSAGE : NP_READMODE_BYTE));
+ else
+ ulPipeMode |= (ULONG)SvUV(ST(6));
+
+ if (items < 8)
+ timeout = 0;
+ else
+ timeout = (double)SvNV(ST(7));
+ ulTimeout = timeout * 1000;
+ if (timeout < 0)
+ ulTimeout = 0xFFFFFFFF; /* Indefinite */
+ else if (timeout && !ulTimeout)
+ ulTimeout = 1;
+
+ RETVAL = DosCreateNPipe(pszName, &hpipe, ulOpenMode, ulPipeMode, ulInbufLength, ulOutbufLength, ulTimeout);
+ if (CheckOSError(RETVAL))
+ croak_with_os2error("OS2::pipe(): DosCreateNPipe() error");
+
+ if (connect)
+ connectNPipe(hpipe, connect, 1, 0); /* XXXX wait, retval */
+ hpipe = __imphandle(hpipe);
+
+ perlio = PerlIO_fdopen(hpipe, buf);
+ ST(0) = sv_newmortal();
+ {
+ GV *gv = newGVgen("OS2::pipe");
+ if ( do_open(gv, perltype, strlen(perltype), FALSE, 0, 0, perlio) )
+ sv_setsv(ST(0), sv_bless(newRV((SV*)gv), gv_stashpv("IO::Handle",1)));
+ else
+ ST(0) = &PL_sv_undef;
+ }
+ }
+ XSRETURN(1);
+}
+
+XS(XS_OS2_pipeCntl); /* prototype to pass -Wmissing-prototypes */
+XS(XS_OS2_pipeCntl)
+{
+ dXSARGS;
+ if (items < 2 || items > 3)
+ Perl_croak(aTHX_ "Usage: OS2::pipeCntl(pipe, op [, wait])");
+ {
+ ULONG rc;
+ PerlIO *perlio = IoIFP(sv_2io(ST(0)));
+ IV fn = PerlIO_fileno(perlio);
+ HPIPE hpipe = (HPIPE)fn;
+ STRLEN len;
+ char *s = SvPV(ST(1), len);
+ int wait = 0, disconnect = 0, connect = 0, message = -1, query = 0;
+ int peek = 0, state = 0, info = 0;
+
+ if (fn < 0)
+ Perl_croak(aTHX_ "OS2::pipeCntl(): not a pipe");
+ if (items == 3)
+ wait = (SvTRUE(ST(2)) ? 1 : -1);
+
+ switch (len) {
+ case 4:
+ if (strEQ(s, "byte"))
+ message = 0;
+ else if (strEQ(s, "peek"))
+ peek = 1;
+ else if (strEQ(s, "info"))
+ info = 1;
+ else
+ goto unknown;
+ break;
+ case 5:
+ if (strEQ(s, "reset"))
+ disconnect = connect = 1;
+ else if (strEQ(s, "state"))
+ query = 1;
+ else
+ goto unknown;
+ break;
+ case 7:
+ if (strEQ(s, "connect"))
+ connect = 1;
+ else if (strEQ(s, "message"))
+ message = 1;
+ else
+ goto unknown;
+ break;
+ case 9:
+ if (!strEQ(s, "readstate"))
+ goto unknown;
+ state = 1;
+ break;
+ case 10:
+ if (!strEQ(s, "disconnect"))
+ goto unknown;
+ disconnect = 1;
+ break;
+ default:
+ unknown:
+ Perl_croak(aTHX_ "OS2::pipeCntl(): unknown argument: `%s'", s);
+ break;
+ }
+
+ if (items == 3 && !connect)
+ Perl_croak(aTHX_ "OS2::pipeCntl(): no wait argument for `%s'", s);
+
+ XSprePUSH; /* Do not need arguments any more */
+ if (disconnect) {
+ os2cp_croak(DosDisConnectNPipe(hpipe), "OS2::pipeCntl(): DosDisConnectNPipe()");
+ PerlIO_clearerr(perlio);
+ }
+ if (connect) {
+ if (!connectNPipe(hpipe, wait , 1, 0))
+ XSRETURN_IV(-1);
+ }
+ if (query) {
+ ULONG flags;
+
+ os2cp_croak(DosQueryNPHState(hpipe, &flags), "DosQueryNPHState()");
+ XSRETURN_UV(flags);
+ }
+ if (peek || state || info) {
+ ULONG BytesRead, PipeState;
+ AVAILDATA BytesAvail;
+
+ os2cp_croak( DosPeekNPipe(hpipe, NULL, 0, &BytesRead, &BytesAvail,
+ &PipeState), "DosPeekNPipe() for state");
+ if (state) {
+ EXTEND(SP, 3);
+ PUSHs(newSVuv(PipeState));
+ /* Bytes (available/in-message) */
+ PUSHs(newSViv(BytesAvail.cbpipe));
+ PUSHs(newSViv(BytesAvail.cbmessage));
+ XSRETURN(3);
+ } else if (info) {
+ /* L S S C C C/Z*
+ ID of the (remote) computer
+ buffers (out/in)
+ instances (max/actual)
+ */
+ struct pipe_info_t {
+ ULONG id; /* char id[4]; */
+ PIPEINFO pInfo;
+ char buf[512];
+ } b;
+ int size;
+
+ os2cp_croak( DosQueryNPipeInfo(hpipe, 1, &b.pInfo, sizeof(b) - STRUCT_OFFSET(struct pipe_info_t, pInfo)),
+ "DosQueryNPipeInfo(1)");
+ os2cp_croak( DosQueryNPipeInfo(hpipe, 2, &b.id, sizeof(b.id)),
+ "DosQueryNPipeInfo(2)");
+ size = b.pInfo.cbName;
+ /* Trailing 0 is included in cbName - undocumented; so
+ one should always extract with Z* */
+ if (size) /* name length 254 or less */
+ size--;
+ else
+ size = strlen(b.pInfo.szName);
+ EXTEND(SP, 6);
+ PUSHs(newSVpvn(b.pInfo.szName, size));
+ PUSHs(newSVuv(b.id));
+ PUSHs(newSViv(b.pInfo.cbOut));
+ PUSHs(newSViv(b.pInfo.cbIn));
+ PUSHs(newSViv(b.pInfo.cbMaxInst));
+ PUSHs(newSViv(b.pInfo.cbCurInst));
+ XSRETURN(6);
+ } else if (BytesAvail.cbpipe == 0) {
+ XSRETURN_NO;
+ } else {
+ SV *tmp = NEWSV(914, BytesAvail.cbpipe);
+ char *s = SvPVX(tmp);
+
+ sv_2mortal(tmp);
+ os2cp_croak( DosPeekNPipe(hpipe, s, BytesAvail.cbpipe, &BytesRead,
+ &BytesAvail, &PipeState), "DosPeekNPipe()");
+ SvCUR_set(tmp, BytesRead);
+ *SvEND(tmp) = 0;
+ SvPOK_on(tmp);
+ XSprePUSH; PUSHs(tmp);
+ XSRETURN(1);
+ }
+ }
+ if (message > -1) {
+ ULONG oflags, flags;
+
+ os2cp_croak(DosQueryNPHState(hpipe, &oflags), "DosQueryNPHState()");
+ /* DosSetNPHState fails if more bits than NP_NOWAIT|NP_READMODE_MESSAGE */
+ oflags &= (NP_NOWAIT | NP_READMODE_MESSAGE);
+ flags = (oflags & NP_NOWAIT)
+ | (message ? NP_READMODE_MESSAGE : NP_READMODE_BYTE);
+ if (flags != oflags)
+ os2cp_croak(DosSetNPHState(hpipe, flags), "DosSetNPHState()");
+ }
+ }
+ XSRETURN_YES;
+}
+
+/*
+NO_OUTPUT ULONG
+DosOpen(PCSZ pszFileName, OUTLIST HFILE hFile, OUTLIST ULONG ulAction, ULONG ulOpenFlags, ULONG ulOpenMode = OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW, ULONG ulAttribute = FILE_NORMAL, ULONG ulFileSize = 0, PEAOP2 pEABuf = NULL);
+ PREINIT:
+ ULONG rc;
+ C_ARGS:
+ pszFileName, &hFile, &ulAction, ulFileSize, ulAttribute, ulOpenFlags, ulOpenMode, pEABuf
+ POSTCALL:
+ if (CheckOSError(RETVAL))
+ croak_with_os2error("OS2::open() error");
+*/
+XS(XS_OS2_open); /* prototype to pass -Wmissing-prototypes */
+XS(XS_OS2_open)
+{
+ dXSARGS;
+ if (items < 2 || items > 6)
+ Perl_croak(aTHX_ "Usage: OS2::open(pszFileName, ulOpenMode, ulOpenFlags= OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW, ulAttribute= FILE_NORMAL, ulFileSize= 0, pEABuf= NULL)");
+ {
+#line 39 "pipe.xs"
+ ULONG rc;
+#line 113 "pipe.c"
+ ULONG RETVAL;
+ PCSZ pszFileName = ( SvOK(ST(0)) ? (PCSZ)SvPV(ST(0),PL_na) : NULL );
+ HFILE hFile;
+ ULONG ulAction;
+ ULONG ulOpenMode = (ULONG)SvUV(ST(1));
+ ULONG ulOpenFlags;
+ ULONG ulAttribute;
+ ULONG ulFileSize;
+ PEAOP2 pEABuf;
+
+ if (items < 3)
+ ulOpenFlags = OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW;
+ else {
+ ulOpenFlags = (ULONG)SvUV(ST(2));
+ }
+
+ if (items < 4)
+ ulAttribute = FILE_NORMAL;
+ else {
+ ulAttribute = (ULONG)SvUV(ST(3));
+ }
+
+ if (items < 5)
+ ulFileSize = 0;
+ else {
+ ulFileSize = (ULONG)SvUV(ST(4));
+ }
+
+ if (items < 6)
+ pEABuf = NULL;
+ else {
+ pEABuf = (PEAOP2)SvUV(ST(5));
+ }
+
+ RETVAL = DosOpen(pszFileName, &hFile, &ulAction, ulFileSize, ulAttribute, ulOpenFlags, ulOpenMode, pEABuf);
+ if (CheckOSError(RETVAL))
+ croak_with_os2error("OS2::open() error");
+ XSprePUSH; EXTEND(SP,2);
+ PUSHs(sv_newmortal());
+ sv_setuv(ST(0), (UV)hFile);
+ PUSHs(sv_newmortal());
+ sv_setuv(ST(1), (UV)ulAction);
+ }
+ XSRETURN(2);
+}
+
int
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);
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, "$$;$");
newXSproto("OS2::Beep", XS_OS2_Beep, file, ";$$");
+ newXSproto("OS2::pipe", XS_OS2_pipe, file, "$$;$$$$$$");
+ newXSproto("OS2::pipeCntl", XS_OS2_pipeCntl, file, "$$;$");
+ newXSproto("OS2::open", XS_OS2_open, file, "$$;$$$$");
gv = gv_fetchpv("OS2::is_aout", TRUE, SVt_PV);
GvMULTI_on(gv);
#ifdef PERL_IS_AOUT
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 */
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;
c++;
e = e + strlen(e) + 1;
}
- New(1307, env, c + 1, char*);
+ Newx(env, c + 1, char*);
ep = env;
e = pib->pib_pchenv;
while (c--) {
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;
settmppath();
OS2_Perl_data.xs_init = &Xs_OS2_init;
- if ( (shell = getenv("PERL_SH_DRIVE")) ) {
- New(1304, PL_sh_path, strlen(SH_PATH) + 1, char);
+ if (perl_sh_installed) {
+ int l = strlen(perl_sh_installed);
+
+ Newx(PL_sh_path, l + 1, char);
+ memcpy(PL_sh_path, perl_sh_installed, l + 1);
+ } else if ( (shell = getenv("PERL_SH_DRIVE")) ) {
+ Newx(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);
+ Newx(PL_sh_path, l + 8, char);
strncpy(PL_sh_path, shell, l);
strcpy(PL_sh_path + l, "/sh.exe");
for (i = 0; i < l; i++) {
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);
}
if (s[l-1] == '/' || s[l-1] == '\\') { /* EMX mkdir fails... */
if (l >= sizeof b)
- New(1305, buf, l + 1, char);
+ Newx(buf, l + 1, char);
strcpy(buf,s);
while (l > 1 && (s[l-1] == '/' || s[l-1] == '\\'))
l--;
if (s[l-1] == '/' || s[l-1] == '\\') { /* EMX mkdir fails... */
if (l >= sizeof b)
- New(1305, buf, l + 1, char);
+ Newx(buf, l + 1, char);
strcpy(buf,s);
while (l > 1 && (s[l-1] == '/' || s[l-1] == '\\'))
l--;
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;
+}