/* util.c
*
- * Copyright (c) 1991-2001, Larry Wall
+ * Copyright (c) 1991-2002, Larry Wall
*
* You may distribute under the terms of either the GNU General Public
* License or the Artistic License, as specified in the README file.
# include <sys/wait.h>
#endif
+#ifdef HAS_SELECT
+# ifdef I_SYS_SELECT
+# include <sys/select.h>
+# endif
+#endif
+
#define FLUSH
#ifdef LEAKTEST
If FBMcf_TAIL, the table is created as if the string has a trailing \n. */
/*
+=head1 Miscellaneous Functions
+
=for apidoc fbm_compile
Analyses the string in order to make fast searches on it using fbm_instr()
/* copy a string to a safe spot */
/*
+=head1 Memory Management
+
=for apidoc savepv
Copy a string to a safe spot. This does not use an SV.
char *
Perl_savepv(pTHX_ const char *sv)
{
- register char *newaddr;
-
- New(902,newaddr,strlen(sv)+1,char);
- (void)strcpy(newaddr,sv);
+ register char *newaddr = Nullch;
+ if (sv) {
+ New(902,newaddr,strlen(sv)+1,char);
+ (void)strcpy(newaddr,sv);
+ }
return newaddr;
}
=for apidoc savepvn
Copy a string to a safe spot. The C<len> indicates number of bytes to
-copy. This does not use an SV.
+copy. If pointer is NULL allocate space for a string of size specified.
+This does not use an SV.
=cut
*/
register char *newaddr;
New(903,newaddr,len+1,char);
- Copy(sv,newaddr,len,char); /* might not be null terminated */
- newaddr[len] = '\0'; /* is now */
+ /* Give a meaning to NULL pointer mainly for the use in sv_magic() */
+ if (sv) {
+ Copy(sv,newaddr,len,char); /* might not be null terminated */
+ newaddr[len] = '\0'; /* is now */
+ }
+ else {
+ Zero(newaddr,len+1,char);
+ }
return newaddr;
}
+/*
+=for apidoc savesharedpv
+
+Copy a string to a safe spot in memory shared between threads.
+This does not use an SV.
+
+=cut
+*/
+char *
+Perl_savesharedpv(pTHX_ const char *sv)
+{
+ register char *newaddr = Nullch;
+ if (sv) {
+ newaddr = PerlMemShared_malloc(strlen(sv)+1);
+ (void)strcpy(newaddr,sv);
+ }
+ return newaddr;
+}
+
+
+
/* the SV for Perl_form() and mess() is not kept in an arena */
STATIC SV *
#endif /* PERL_IMPLICIT_CONTEXT */
/*
+=head1 Miscellaneous Functions
=for apidoc form
Takes a sprintf-style format pattern and conventional
if (CopLINE(cop))
Perl_sv_catpvf(aTHX_ sv, " at %s line %"IVdf,
- CopFILE(cop), (IV)CopLINE(cop));
+ OutCopFILE(cop), (IV)CopLINE(cop));
if (GvIO(PL_last_in_gv) && IoLINES(GvIOp(PL_last_in_gv))) {
bool line_mode = (RsSIMPLE(PL_rs) &&
SvCUR(PL_rs) == 1 && *SvPVX(PL_rs) == '\n');
#endif /* PERL_IMPLICIT_CONTEXT */
/*
+=head1 Warning and Dieing
+
=for apidoc croak
This is the XSUB-writer's interface to Perl's C<die> function.
CV *cv;
SV *msv;
STRLEN msglen;
+ IO *io;
+ MAGIC *mg;
msv = vmess(pat, args);
message = SvPV(msv, msglen);
return;
}
}
+
+ /* if STDERR is tied, use it instead */
+ if (PL_stderrgv && (io = GvIOp(PL_stderrgv))
+ && (mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar))) {
+ dSP; ENTER;
+ PUSHMARK(SP);
+ XPUSHs(SvTIED_obj((SV*)io, mg));
+ XPUSHs(sv_2mortal(newSVpvn(message, msglen)));
+ PUTBACK;
+ call_method("PRINT", G_SCALAR);
+ LEAVE;
+ return;
+ }
+
{
PerlIO *serr = Perl_error_log;
(dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
/*
+=head1 Miscellaneous Functions
+
=for apidoc getcwd_sv
Fill the sv with current working directory
}
/*
+=head1 SV Manipulation Functions
+
=for apidoc new_vstring
Returns a pointer to the next character after the parsed
vstring, as well as updating the passed in sv.
- *
+
Function must be called like
-
+
sv = NEWSV(92,5);
s = new_vstring(s,sv);
for (;;) {
rev = 0;
{
- /* this is atoi() that tolerates underscores */
- char *end = pos;
- UV mult = 1;
- if ( *(s-1) == '_') {
- mult = 10;
- }
- while (--end >= s) {
- UV orev;
- orev = rev;
- rev += (*end - '0') * mult;
- mult *= 10;
- if (orev > rev && ckWARN_d(WARN_OVERFLOW))
- Perl_warner(aTHX_ WARN_OVERFLOW,
- "Integer overflow in decimal number");
- }
+ /* this is atoi() that tolerates underscores */
+ char *end = pos;
+ UV mult = 1;
+ if ( *(s-1) == '_') {
+ mult = 10;
+ }
+ while (--end >= s) {
+ UV orev;
+ orev = rev;
+ rev += (*end - '0') * mult;
+ mult *= 10;
+ if (orev > rev && ckWARN_d(WARN_OVERFLOW))
+ Perl_warner(aTHX_ WARN_OVERFLOW,
+ "Integer overflow in decimal number");
+ }
}
+#ifdef EBCDIC
+ if (rev > 0x7FFFFFFF)
+ Perl_croak(aTHX "In EBCDIC the v-string components cannot exceed 2147483647");
+#endif
/* Append native character for the rev point */
tmpend = uvchr_to_utf8(tmpbuf, rev);
sv_catpvn(sv, (const char*)tmpbuf, tmpend - tmpbuf);
if (!UNI_IS_INVARIANT(NATIVE_TO_UNI(rev)))
- SvUTF8_on(sv);
+ SvUTF8_on(sv);
if ( (*pos == '.' || *pos == '_') && isDIGIT(pos[1]))
- s = ++pos;
+ s = ++pos;
else {
- s = pos;
- break;
+ s = pos;
+ break;
}
while (isDIGIT(*pos) )
- pos++;
+ pos++;
}
SvPOK_on(sv);
SvREADONLY_on(sv);
return s;
}
-#if !defined(HAS_SOCKETPAIR) && defined(HAS_SOCKET)
+#if !defined(HAS_SOCKETPAIR) && defined(HAS_SOCKET) && defined(AF_INET) && defined(PF_INET) && defined(SOCK_DGRAM)
+# define EMULATE_SOCKETPAIR_UDP
+#endif
+
+#ifdef EMULATE_SOCKETPAIR_UDP
static int
S_socketpair_udp (int fd[2]) {
+ dTHX;
/* Fake a datagram socketpair using UDP to localhost. */
int sockets[2] = {-1, -1};
struct sockaddr_in addresses[2];
memset (&addresses, 0, sizeof (addresses));
i = 1;
do {
- sockets[i] = socket (AF_INET, SOCK_DGRAM, 0);
+ sockets[i] = PerlSock_socket (AF_INET, SOCK_DGRAM, PF_INET);
if (sockets[i] == -1)
goto tidy_up_and_fail;
addresses[i].sin_family = AF_INET;
addresses[i].sin_addr.s_addr = htonl (INADDR_LOOPBACK);
addresses[i].sin_port = 0; /* kernel choses port. */
- if (bind (sockets[i], (struct sockaddr *) &addresses[i],
+ if (PerlSock_bind (sockets[i], (struct sockaddr *) &addresses[i],
sizeof (struct sockaddr_in))
== -1)
goto tidy_up_and_fail;
for each connect the other socket to it. */
i = 1;
do {
- if (getsockname (sockets[i], (struct sockaddr *) &addresses[i], &size)
+ if (PerlSock_getsockname (sockets[i], (struct sockaddr *) &addresses[i], &size)
== -1)
goto tidy_up_and_fail;
if (size != sizeof (struct sockaddr_in))
goto abort_tidy_up_and_fail;
/* !1 is 0, !0 is 1 */
- if (connect(sockets[!i], (struct sockaddr *) &addresses[i],
+ if (PerlSock_connect(sockets[!i], (struct sockaddr *) &addresses[i],
sizeof (struct sockaddr_in)) == -1)
goto tidy_up_and_fail;
} while (i--);
(Who knows if someone somewhere has sin_port as a bitfield and needs
this routine. (I'm assuming crays have socketpair)) */
port = addresses[i].sin_port;
- got = write (sockets[i], &port, sizeof(port));
+ got = PerlLIO_write (sockets[i], &port, sizeof(port));
if (got != sizeof(port)) {
if (got == -1)
goto tidy_up_and_fail;
FD_SET (sockets[0], &rset);
FD_SET (sockets[1], &rset);
- got = select (max + 1, &rset, NULL, NULL, &waitfor);
+ got = PerlSock_select (max + 1, &rset, NULL, NULL, &waitfor);
if (got != 2 || !FD_ISSET (sockets[0], &rset)
|| !FD_ISSET (sockets[1], &rset)) {
/* I hope this is portable and appropriate. */
i = 1;
do {
- got = recvfrom (sockets[i], (char *) &buffer, sizeof(buffer),
#ifdef MSG_DONTWAIT
+ got = PerlSock_recvfrom (sockets[i], (char *) &buffer, sizeof(buffer),
MSG_DONTWAIT,
+ (struct sockaddr *) &readfrom, &size);
#else
+ got = PerlSock_recvfrom (sockets[i], (char *) &buffer, sizeof(buffer),
0,
-#endif
(struct sockaddr *) &readfrom, &size);
+#endif
if (got == -1)
goto tidy_up_and_fail;
{
int save_errno = errno;
if (sockets[0] != -1)
- close (sockets[0]);
+ PerlLIO_close (sockets[0]);
if (sockets[1] != -1)
- close (sockets[1]);
+ PerlLIO_close (sockets[1]);
errno = save_errno;
return -1;
}
int
Perl_my_socketpair (int family, int type, int protocol, int fd[2]) {
/* Stevens says that family must be AF_LOCAL, protocol 0.
- I'm going to enforce that, then ignore it, and use TCP. */
+ I'm going to enforce that, then ignore it, and use TCP (or UDP). */
+ dTHX;
int listener = -1;
int connector = -1;
int acceptor = -1;
errno = EAFNOSUPPORT;
return -1;
}
- if (!fd)
- return EINVAL;
+ if (!fd) {
+ errno = EINVAL;
+ return -1;
+ }
+#ifdef EMULATE_SOCKETPAIR_UDP
if (type == SOCK_DGRAM)
return S_socketpair_udp (fd);
+#endif
- listener = socket (AF_INET, type, 0);
+ listener = PerlSock_socket (AF_INET, type, 0);
if (listener == -1)
return -1;
memset (&listen_addr, 0, sizeof (listen_addr));
listen_addr.sin_family = AF_INET;
listen_addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
listen_addr.sin_port = 0; /* kernel choses port. */
- if (bind (listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr))
+ if (PerlSock_bind (listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr))
== -1)
goto tidy_up_and_fail;
- if (listen(listener, 1) == -1)
+ if (PerlSock_listen(listener, 1) == -1)
goto tidy_up_and_fail;
- connector = socket (AF_INET, type, 0);
+ connector = PerlSock_socket (AF_INET, type, 0);
if (connector == -1)
goto tidy_up_and_fail;
/* We want to find out the port number to connect to. */
size = sizeof (connect_addr);
- if (getsockname (listener, (struct sockaddr *) &connect_addr, &size) == -1)
+ if (PerlSock_getsockname (listener, (struct sockaddr *) &connect_addr, &size) == -1)
goto tidy_up_and_fail;
if (size != sizeof (connect_addr))
goto abort_tidy_up_and_fail;
- if (connect(connector, (struct sockaddr *) &connect_addr,
+ if (PerlSock_connect(connector, (struct sockaddr *) &connect_addr,
sizeof (connect_addr)) == -1)
goto tidy_up_and_fail;
size = sizeof (listen_addr);
- acceptor = accept (listener, (struct sockaddr *) &listen_addr, &size);
+ acceptor = PerlSock_accept (listener, (struct sockaddr *) &listen_addr, &size);
if (acceptor == -1)
goto tidy_up_and_fail;
if (size != sizeof (listen_addr))
goto abort_tidy_up_and_fail;
- close (listener);
+ PerlLIO_close (listener);
/* Now check we are talking to ourself by matching port and host on the
two sockets. */
- if (getsockname (connector, (struct sockaddr *) &connect_addr, &size) == -1)
+ if (PerlSock_getsockname (connector, (struct sockaddr *) &connect_addr, &size) == -1)
goto tidy_up_and_fail;
if (size != sizeof (connect_addr)
|| listen_addr.sin_family != connect_addr.sin_family
{
int save_errno = errno;
if (listener != -1)
- close (listener);
+ PerlLIO_close (listener);
if (connector != -1)
- close (connector);
+ PerlLIO_close (connector);
if (acceptor != -1)
- close (acceptor);
+ PerlLIO_close (acceptor);
errno = save_errno;
return -1;
}
}
#endif /* !defined(HAS_SOCKETPAIR) && defined(HAS_SOCKET) */
+#ifdef HAS_SOCKETPAIR
+/* In any case have a stub so that there's code corresponding
+ * to the my_socketpair in global.sym. */
+int
+Perl_my_socketpair (int family, int type, int protocol, int fd[2]) {
+ return socketpair(family, type, protocol, fd);
+}
+#endif
+
+/*
+
+=for apidoc sv_nosharing
+
+Dummy routine which "shares" an SV when there is no sharing module present.
+Exists to avoid test for a NULL function pointer and because it could potentially warn under
+some level of strict-ness.
+
+=cut
+*/
+
+void
+Perl_sv_nosharing(pTHX_ SV *sv)
+{
+}
+
+/*
+=for apidoc sv_nolocking
+
+Dummy routine which "locks" an SV when there is no locking module present.
+Exists to avoid test for a NULL function pointer and because it could potentially warn under
+some level of strict-ness.
+
+=cut
+*/
+
+void
+Perl_sv_nolocking(pTHX_ SV *sv)
+{
+}
+
+
+/*
+=for apidoc sv_nounlocking
+
+Dummy routine which "unlocks" an SV when there is no locking module present.
+Exists to avoid test for a NULL function pointer and because it could potentially warn under
+some level of strict-ness.
+
+=cut
+*/
+
+void
+Perl_sv_nounlocking(pTHX_ SV *sv)
+{
+}
+
+/*
+=for apidoc memcmp_byte_utf8
+
+Similar to memcmp(), but the first string is with bytes, the second
+with utf8. Takes into account that the lengths may be different.
+
+=cut
+*/
+
+int
+Perl_memcmp_byte_utf8(pTHX_ char *sb, STRLEN lbyte, char *su, STRLEN lutf)
+{
+ U8 *sbyte = (U8*)sb;
+ U8 *sutf = (U8*)su;
+ U8 *ebyte = sbyte + lbyte;
+ U8 *eutf = sutf + lutf;
+
+ while (sbyte < ebyte) {
+ if (sutf >= eutf)
+ return 1; /* utf one shorter */
+ if (NATIVE_IS_INVARIANT(*sbyte)) {
+ if (*sbyte != *sutf)
+ return *sbyte - *sutf;
+ sbyte++; sutf++; /* CONTINUE */
+ } else if ((*sutf & UTF_CONTINUATION_MASK) ==
+ (*sbyte >> UTF_ACCUMULATION_SHIFT)) {
+ if ((sutf[1] & UTF_CONTINUATION_MASK) !=
+ (*sbyte & UTF_CONTINUATION_MASK))
+ return (*sbyte & UTF_CONTINUATION_MASK) -
+ (*sutf & UTF_CONTINUATION_MASK);
+ sbyte++, sutf += 2; /* CONTINUE */
+ } else
+ return (*sbyte >> UTF_ACCUMULATION_SHIFT) -
+ (*sutf & UTF_CONTINUATION_MASK);
+ }
+ if (sutf >= eutf)
+ return 0;
+ return -1; /* byte one shorter */
+}