DEB_DIR = Debug
-!ifndef MAKE_TYPE
!ifndef NLMSDKBASE
!message "Run bat\SetNWBld.bat to set the NetWare SDK before continuing.\n"
!error
BS_CFLAGS = -opt off -inline off -sym on -sym codeview4 -sym internal -DDEBUGGING -DDKFBPON
BLDMESG = $(BLDMESG) Using /d2 option
!ifdef NLM_NAME8
-LDFLAGS = $(LDFLAGS) -sym on -sym codeview4 -sym internal -osym $(NLM_NAME8).sym
+LDFLAGS = $(LDFLAGS) -sym on -sym codeview4 -sym internal -osym $(MAKE_TYPE)\$(NLM_NAME8).sym
!else # !ifdef NLM_NAME8
-LDFLAGS = $(LDFLAGS) -sym on -sym codeview4 -sym internal -osym $(NLM_NAME).sym
+LDFLAGS = $(LDFLAGS) -sym on -sym codeview4 -sym internal -osym $(MAKE_TYPE)\$(NLM_NAME).sym
!endif # !ifdef NLM_NAME8
!else # !ifdef USE_D2
BS_CFLAGS = -opt off -inline off -sym on -sym codeview4 -sym internal -DDEBUGGING -DDKFBPON
BLDMESG = $(BLDMESG) Using /d1 option
!ifdef NLM_NAME8
-LDFLAGS = $(LDFLAGS) -sym on -sym codeview4 -sym internal -osym $(NLM_NAME8).sym
+LDFLAGS = $(LDFLAGS) -sym on -sym codeview4 -sym internal -osym $(MAKE_TYPE)\$(NLM_NAME8).sym
!else # !ifdef NLM_NAME8
-LDFLAGS = $(LDFLAGS) -sym on -sym codeview4 -sym internal -osym $(NLM_NAME).sym
+LDFLAGS = $(LDFLAGS) -sym on -sym codeview4 -sym internal -osym $(MAKE_TYPE)\$(NLM_NAME).sym
!endif # !ifdef NLM_NAME8
!endif # !ifdef USE_D2
!else # !if "$(MAKE_TYPE)"=="Debug"
@echo $(MPKMESSAGE)...$(BLDMESG)...$@
$(C_COMPILER) $(COMPLER_FLAGS) $(NLM_INCLUDES) -I..\x2p $(ADD_LOCDEFS) $(ERROR_FLAG) $*.c -o $@
@echo Built $(@)
-
+
..\x2p\hash$(o) : ..\x2p\hash.c
@echo $(MPKMESSAGE)...$(BLDMESG)...$@
$(C_COMPILER) $(COMPLER_FLAGS) $(NLM_INCLUDES) -I..\x2p $(ADD_LOCDEFS) $(ERROR_FLAG) $*.c -o $@
$(MINIPERL) -I..\lib ..\splittree.pl "../LIB" $(AUTODIR)
@echo ========Linked $@ ==========
-!if "$(MAKE_TYPE)"=="Debug"
-!ifdef NLM_NAME8
- .\bat\cvpack $(BLDDIR)\$(NLM_NAME8).sym
-!else
- .\bat\cvpack $(BLDDIR)\$(NLM_NAME).sym
-!endif
-!endif
-
@echo======= Finished building $(BUILT).
# Create the debug or release directory if not existing
@if exist .\config.h del /f /q .\config.h
@if exist .\config.nw5 del /f /q .\config.nw5
@if exist .\perl.imp del /f /q .\perl.imp
- -del /f /q *.obj *.lib *.def *.sym *.map *.xdc *.err
+ -del /f /q *.obj *.lib *.def *.sym *.map *.xdc *.err *.nlm
cd testnlm\echo
- -del /f /q *.obj *.map *.link *.options *.nlm *.sym *.xdc *.err
+ -del /f /q *.obj *.map *.link *.options *.nlm *.sym *.xdc *.err *.lib *.def *.pdb *.bs
cd ..\type
- -del /f /q *.obj *.map *.link *.options *.nlm *.sym *.xdc *.err
+ -del /f /q *.obj *.map *.link *.options *.nlm *.sym *.xdc *.err *.lib *.def *.pdb *.bs
cd ..\..\
utils: $(BLDDIR)\$(NLM_NAME8).$(NLM_EXT) $(X2P)
-del /f /q $(CONFIGPM)
-del /f /q bin\*.bat
cd $(EXTDIR)
- -del /s /f /q *.lib *.def *.map *.pdb *.bs Makefile *$(o) pm_to_blib *.xdc *.err
+ -del /s /q /f *.lib *.def *.map *.pdb *.bs Makefile *$(o) pm_to_blib *.xdc *.err *.obj *.sym
cd ..\netware
!if "$(NW_EXTNS)"=="yes"
cd cgi2perl
- -del /f /q *.obj *.bs Makefile *$(o) *.c pm_to_blib *.xdc *.err *.sym *.map
+ -del /f /q *.obj *.bs Makefile *$(o) *.c pm_to_blib *.xdc *.err *.sym *.map *.def *.lib *.pdb
cd ..
cd $(EXTDIR)\Perl2UCS
- -del /f /q *.obj *.bs Makefile *$(o) *.c pm_to_blib *.xdc *.err *.sym *.map *.c
+ -del /f /q *.obj *.bs Makefile *$(o) *.c pm_to_blib *.xdc *.err *.sym *.map *.def *.lib *.pdb
cd ..\..\netware
cd $(EXTDIR)\UCSExt
-del /f /q *.obj *.bs Makefile *$(o) *.c pm_to_blib *.xdc *.err *.sym *.map *.c
strcpy(pclp->m_argv[pclp->m_argc], new_arg); // Appended the new argument.
pclp->m_argc++; // Increment the number of parameters appended.
- // The char array is emptied for all elements upto the end so that there are no junk characters.
- // If this is not done, then the issue is like this:
+ // The char array is emptied for all elements upto the end so that there are no
+ // junk characters. If this is not done, then the issue is like this:
// - Simple perl command like "perl" on the system console works fine for the first time.
- // - When it is given the second time, a new blank screen should come up which also
- // allows for editing. This was not consistently working well.
- // More so when the command was like, "perl ", that is the name "perl"
- // followed by a few blank spaces. It used to give error in opening file and
- // would give some junk as the filename unable to open.
- // Once the below fix was done, it is working fine.
+ // - When "perl" is executed the second time, a new blank screen should come up
+ // which allows for editing also. This was not consistently working well.
+ // More so when the command was like, "perl ", that is the name "perl" followed
+ // by a few blank spaces, it used to give error in opening file:
+ // "unable to open the file" since the filename would have some junk characters.
+ //
+ // These issues are fixed through the code below.
for(i=pclp->m_argc; i<pclp->m_argv_len; i++)
strncpy(pclp->m_argv[i], "", (MAX_DN_BYTES * sizeof(char))); // MAX_DN_BYTES is the size of pclp->m_argv[].
if "%1" == "d" goto set_type_dbg
if "%1" == "D" goto set_type_dbg
-Rem Invalid input, display help message
+Rem Invalid input and so display the help message
goto Usage
:set_type_rel
:now
if "%MAKE_TYPE%" == "" echo MAKE_TYPE is not set, hence it defaults to Release build
-if not "%MAKE_TYPE%" == "" echo Current build type is - %MAKE_TYPE%
+if not "%MAKE_TYPE%" == "" echo Current build type is - %MAKE_TYPE%
call ToggleD2 /now
goto exit
:Usage
@echo on
@echo "Usage: buildtype r/R|d/D [on/off]"
- @echo on/off - Toggling D2 flag for debug build
+ @echo on/off - Toggling only for D2 flag during debug build
@echo "Usage: buildtype /now" - To display current setting
@echo Ex. buildtype d on
@echo Ex. setCodeWar d:\CodeWar
:exit
-@echo off\r
-@rem AUTHOR: sgp & apc\r
-@rem CREATED: 24th July 2000\r
-@rem LAST REVISED: 6th April 2001\r
-@rem LAST REVISED: 22nd May 2002\r
-@rem AUTHOR: apc\r
-@rem Batch file to set the path to CodeWarrior directories\r
-@rem This file is called from SetNWBld.bat.\r
-\r
-if "%1" == "/now" goto now\r
-if "%1" == "" goto Usage\r
-if "%1" == "/?" goto usage\r
-if "%1" == "/h" goto usage\r
-\r
-set CODEWAR=%1\r
-ECHO CODEWAR=%1\r
-\r
-call buildtype r\r
-@echo Buildtype set to Release type\r
-\r
-set MWCIncludes=%1\include\r
-@echo MWCIncludes=%1\include\r
-set MWLibraries=%1\lib\r
-@echo MWLibraries=%1\lib\r
-set MWLibraryFiles=%1\lib\nwpre.obj;%1\lib\mwcrtld.lib\r
-@echo MWLibraryFiles=%1\lib\nwpre.obj;%1\lib\mwcrtld.lib\r
-\r
-set PATH=%PATH%;%1\bin;\r
-@echo PATH=%PATH%;%1\bin;\r
-\r
-goto exit\r
-\r
-:now\r
-@echo CODEWAR=%CODEWAR%\r
-goto exit\r
-\r
-:Usage\r
- @echo on\r
- @echo "Usage: setCodeWar <Path to CodeWarrior binaries>"\r
- @echo "Usage: setCodeWar /now" - To display current setting\r
- @echo Ex. setCodeWar d:\CodeWar\r
-\r
-:exit\r
@echo off
-@rem AUTHOR: sgp
+@rem AUTHOR: apc
@rem CREATED: Thu 18th Jan 2001 09:18:08
@rem LAST REVISED: 6th April 2001
-@rem Batch file to set the path to NetWare SDK, Watcom directories & MPK SDK
-@rem This file calls setnlmsdk.bat, setwatcom.bat & setmpksdk.bat
+@rem LAST REVISED: 22nd May 2002
+@rem Batch file to set the path to Default Buildtype,NetWare SDK, CodeWarrior directories
+@rem This file calls buildtype with release as defualt,setnlmsdk.bat, setCodeWar.bat & setmpksdk.bat and MpkBuild with off as default
REM If no parameters are passed, display usage
if "%1" == "" goto Usage
REM If na is passed, don't set that parameter
if "%1" == "na" goto skip_nlmsdk_msg
+
:setnwsdk
call setnlmsdk %1
goto skip_nlmsdk_nomsg
:skip_nlmsdk_msg
@echo Retaining NLMSDKBASE=%NLMSDKBASE%
-:skip_nlmsdk_nomsg
-if "%2" == "" goto exit
-if "%2" == "na" goto skip_watcom_msg
-:setwatcom
-call setwatcom %2
-goto skip_watcom_nomsg
-
-:skip_watcom_msg
-@echo Retaining WATCOM=%WATCOM%
-:skip_watcom_nomsg
+:skip_nlmsdk_nomsg
+if "%2" == "" goto err_exit
+if "%2" == "na" goto skip_cw_msg
-if "%3" == "" goto exit
-if "%3" == "na" goto skip_mpksdk_msg
-:setmpk
-call setmpksdk %3
-goto skip_mpksdk_nomsg
+:setcodewar
+call setcodewar %2
+goto skip_cw_nomsg
-:skip_mpksdk_msg
-@echo Retaining MPKBASE=%MPKBASE%
-:skip_mpksdk_nomsg
+:skip_cw_msg
+@echo Retaining CODEWAR=%CODEWAR%
+goto exit
+:skip_cw_nomsg
goto exit
+:err_exit
+@echo Not Enough Parameters
+goto Usage
+
:now
@echo NLMSDKBASE=%NLMSDKBASE%
-@echo WATCOM=%WATCOM%
-@echo MPKBASE=%MPKBASE%
+@echo CODEWAR=%CODEWAR%
goto exit
-goto exit
:Usage
@echo on
- @echo "Usage: setnwbld <path to NetWare SDK> [<path to Watcom dir>] [<path to MPK SDK>]"
- @echo "Usage: setnwbld /now" - To display current setting
+ @echo "Usage: setnwdef <path to NetWare SDK> <path to CodeWarrior dir>"
+ @echo "Usage: setnwdef /now" - To display current setting
@echo Pass na if you don't want to change a setting
- @echo Ex. setnwbld d:\ndk\nwsdk na p:\mpk
- @echo Ex. setnwbld d:\ndk\
+ @echo Ex. setnwbld d:\ndk\nwsdk na
+ @echo Ex. setnwbld na d:\codewar
+
:exit
@echo "Usage: setnlmsdk <path to NetWare sdk>"
@echo "Usage: setnlmsdk /now" - To display current setting
@echo Ex. setnlmsdk e:\sdkcd14\nwsdk
-:exit
+:exit
if "%1" == "off" goto no
if "%1" == "/?" goto usage
if "%1" == "/h" goto usage
-goto dontknow
+
+Rem Invalid input and so display the help message
+goto Usage
:now
if "%USE_D2%" == "" echo USE_D2 is removed, uses /d1
echo ....USE_D2 is removed. uses /d1
goto exit
-:dontknow
-goto Usage
-
:Usage
@echo on
@echo "Usage: ToggleD2 [on|off]"
@echo "Usage: ToggleD2 /now" - To display current setting
+
:exit
# These scripts have problems (either abend or hang) as of now (11 May 2001).
# So, they are commented out in the corresponding auto scripts, io.pl and lib.pl
-@ScriptsNotUsed = ("t/io/openpid.t", "t/lib/filehandle.t", "t/lib/memoize/t/expire_module_t.t", "t/lib/NEXT/t/next.t", "t/lib/Math/BigInt/t/require.t", "t/ext/B/t/debug.t","t/lib/IPC/Open3.t", "t/ext/B/t/showlex.t", "t/op/subst_wamp.t", "t/uni/upper.t", "t/lib/Net/t/ftp.t");
+@ScriptsNotUsed = ("t/io/openpid.t", "t/lib/filehandle.t", "t/lib/memoize/t/expire_module_t.t", "t/lib/NEXT/t/next.t", "t/lib/Math/BigInt/t/require.t", "t/ext/B/t/debug.t","t/lib/IPC/Open3.t", "t/ext/B/t/showlex.t", "t/op/subst_wamp.t", "t/uni/upper.t", "t/lib/Net/t/ftp.t", "t/op/sort.t, ", "t/ext/POSIX/t/posix.t");
opendir(DIR, $DirName);
@Dirs = readdir(DIR);
BEGIN {
if ($ithreads) {
- @EXPORT = qw(cond_wait cond_broadcast cond_signal unlock)
+ @EXPORT = qw(cond_wait cond_broadcast cond_signal)
} elsif ($othreads) {
@EXPORT_OK = qw(cond_signal cond_broadcast cond_wait);
}
my @list = Thread->list; # not available with ithreads
- unlock(...); # not available with the 5.005 threads
-
use Thread 'async';
=head1 DESCRIPTION
=item lock VARIABLE
-C<lock> places a lock on a variable until the lock goes out of scope
-(with ithreads you can also explicitly unlock()).
+C<lock> places a lock on a variable until the lock goes out of scope.
If the variable is locked by another thread, the C<lock> call will
block until it's available. C<lock> is recursive, so multiple calls
*{"Thread::$m"} = \&{"threads::$m"};
}
require 'threads/shared.pm';
- for my $m (qw(cond_signal cond_broadcast cond_wait unlock)) {
+ for my $m (qw(cond_signal cond_broadcast cond_wait)) {
no strict 'refs';
*{"Thread::$m"} = \&{"threads::shared::${m}_enabled"};
}
unimplement(qw(done flags));
} elsif ($othreads) {
XSLoader::load 'Thread';
- unimplement(qw(unlock));
} else {
require Carp;
Carp::croak("This Perl has neither ithreads nor 5005threads");
the 5.005 threading implementation. These are not new failures--Perl
5.005_0x has the same bugs, but didn't have these tests.
+ ../ext/B/t/xref.t 255 65280 14 12 85.71% 3-14
../ext/List/Util/t/first.t 255 65280 7 4 57.14% 2 5-7
../lib/English.t 2 512 54 2 3.70% 2-3
+ ../lib/ExtUtils/t/basic.t 1 256 17 1 5.88% 14
+ ../lib/FileCache.t 5 1 20.00% 5
../lib/Filter/Simple/t/data.t 6 3 50.00% 1-3
- ../lib/Filter/Simple/t/filter_only 9 3 33.33% 1-2 5
+ ../lib/Filter/Simple/t/filter_onl 9 3 33.33% 1-2 5
+ ../lib/Tie/File/t/31_autodefer.t 255 65280 65 32 49.23% 34-65
../lib/autouse.t 10 1 10.00% 4
op/flip.t 15 1 6.67% 15
functioning as a class, but that package doesn't define that particular
method, nor does any of its base classes. See L<perlobj>.
+=item Can't locate PerlIO%s
+
+(F) You tried to use in open() a PerlIO layer that does not exist,
+e.g. open(FH, ">:nosuchlayer", "somefile").
+
=item (perhaps you forgot to load "%s"?)
(F) This is an educated guess made in conjunction with the message
Perl also uses two special typedefs, I32 and I16, which will always be at
least 32-bits and 16-bits long, respectively. (Again, there are U32 and U16,
-as well.)
+as well.) They will usually be exactly 32 and 16 bits long, but on Crays
+they will both be 64 bits.
=head2 Working with SVs
-An SV can be created and loaded with one command. There are four types of
-values that can be loaded: an integer value (IV), a double (NV),
-a string (PV), and another scalar (SV).
+An SV can be created and loaded with one command. There are five types of
+values that can be loaded: an integer value (IV), an unsigned integer
+value (UV), a double (NV), a string (PV), and another scalar (SV).
-The six routines are:
+The seven routines are:
SV* newSViv(IV);
+ SV* newSVuv(UV);
SV* newSVnv(double);
SV* newSVpv(const char*, int);
SV* newSVpvn(const char*, int);
SV* newSVpvf(const char*, ...);
SV* newSVsv(SV*);
-To change the value of an *already-existing* SV, there are seven routines:
+If you require more complex initialisation you can create an empty SV with
+newSV(len). If C<len> is 0 an empty SV of type NULL is returned, else an
+SV of type PV is returned with len + 1 (for the NUL) bytes of storage
+allocated, accessible via SvPVX. In both cases the SV has value undef.
+
+ SV* newSV(0); /* no storage allocated */
+ SV* newSV(10); /* 10 (+1) bytes of uninitialised storage allocated */
+
+To change the value of an *already-existing* SV, there are eight routines:
void sv_setiv(SV*, IV);
void sv_setuv(SV*, UV);
module. In our example above, that's what MyMod_threaded is, and it's
only imported if we're running on a threaded Perl.
+=head2 A Note about the Examples
+
+Although thread support is considered to be stable, there are still a number
+of quirks that may startle you when you try out any of the examples below.
+In a real situation, care should be taken that all threads are finished
+executing before the program exits. That care has B<not> been taken in these
+examples in the interest of simplicity. Running these examples "as is" will
+produce error messages, usually caused by the fact that there are still
+threads running when the program exits. You should not be alarmed by this.
+Future versions of Perl may fix this problem.
+
=head2 Creating Threads
The L<threads> package provides the tools you need to create new
$Param3 = "foo";
$thr = threads->new(\&sub1, "Param 1", "Param 2", $Param3);
$thr = threads->new(\&sub1, @ParamList);
- $thr = threads->new(\&sub1, qw(Param1 Param2 $Param3));
+ $thr = threads->new(\&sub1, qw(Param1 Param2 Param3));
sub sub1 {
my @InboundParameters = @_;
my $thread = shift;
my $foo = 50;
while($foo--) { print "in thread $thread\n" }
- threads->yield();
+ threads->yield;
$foo = 50;
while($foo--) { print "in thread $thread\n" }
}
my $c : shared;
my $thr1 = threads->create(sub { $b = $a; $a = $b + 1; });
my $thr2 = threads->create(sub { $c = $a; $a = $c + 1; });
- $thr1->join();
- $thr2->join();
+ $thr1->join;
+ $thr2->join;
Two threads both access $a. Each thread can potentially be interrupted
at any point, or be executed in any order. At the end, $a could be 3
The lock() function takes a shared variable and puts a lock on it.
No other thread may lock the variable until the the variable is unlocked
by the thread holding the lock. Unlocking happens automatically
-when the locking thread exists the outermost block that contains
+when the locking thread exits the outermost block that contains
C<lock()> function. Using lock() is straightforward: this example has
several threads doing some calculations in parallel, and occasionally
updating a running total:
# (... do some calculations and set $result ...)
{
lock($total); # block until we obtain the lock
- $total += $result
+ $total += $result;
} # lock implicitly released at end of scope
last if $result == 0;
}
{
{
lock($x); # wait for lock
- lock($x): # NOOP - we already have the lock
+ lock($x); # NOOP - we already have the lock
{
lock($x); # NOOP
{
use threads;
use threads::shared::queue;
- my $DataQueue = threads::shared::queue->new();
+ my $DataQueue = threads::shared::queue->new;
$thr = threads->new(sub {
while ($DataElement = $DataQueue->dequeue) {
print "Popped $DataElement off the queue\n";
$DataQueue->enqueue(\$thr);
sleep 10;
$DataQueue->enqueue(undef);
- $thr->join();
+ $thr->join;
You create the queue with C<new threads::shared::queue>. Then you can
add lists of scalars onto the end with enqueue(), and pop scalars off
}
}
- $thr1->join();
- $thr2->join();
- $thr3->join();
+ $thr1->join;
+ $thr2->join;
+ $thr3->join;
The three invocations of the subroutine all operate in sync. The
semaphore, though, makes sure that only one thread is accessing the
$semaphore->up(5); # Increment the counter by five
}
- $thr1->detach();
- $thr2->detach();
+ $thr1->detach;
+ $thr2->detach;
If down() attempts to decrement the counter below zero, it blocks until
the counter is large enough. Note that while a semaphore can be created
14 }
15
16 $stream->enqueue(undef);
- 17 $kid->join();
+ 17 $kid->join;
18
19 sub check_num {
20 my ($upstream, $cur_prime) = @_;
30 }
31 }
32 $downstream->enqueue(undef) if $kid;
- 33 $kid->join() if $kid;
+ 33 $kid->join if $kid;
34 }
This program uses the pipeline model to generate prime numbers. Each
use Config;
use File::Basename qw(&basename &dirname);
use Cwd;
+use subs qw(link);
+
+sub link { # This is a cutdown vesion of installperl:link().
+ my($from,$to) = @_;
+ my($success) = 0;
+
+ eval {
+ CORE::link($from, $to)
+ ? $success++
+ : ($from =~ m#^/afs/# || $to =~ m#^/afs/#)
+ ? die "AFS" # okay inside eval {}
+ : die "Couldn't link $from to $to: $!\n";
+ };
+ if ($@) {
+ warn $@;
+ require File::Copy;
+ File::Copy::copy($from, $to)
+ ? $success++
+ : warn "Couldn't copy $from to $to: $!\n";
+ }
+ $success;
+}
# List explicitly here the variables you want Configure to
# generate. Metaconfig only looks for shell variables, so you
#ifdef VMS
# include "config.h"
+#elif defined(NETWARE)
+# include "../NetWare/config.h"
#else
# include "../config.h"
#endif
use Config;
use File::Basename qw(&basename &dirname);
use Cwd;
+use subs qw(link);
+
+sub link { # This is a cutdown vesion of installperl:link().
+ my($from,$to) = @_;
+ my($success) = 0;
+
+ eval {
+ CORE::link($from, $to)
+ ? $success++
+ : ($from =~ m#^/afs/# || $to =~ m#^/afs/#)
+ ? die "AFS" # okay inside eval {}
+ : die "Couldn't link $from to $to: $!\n";
+ };
+ if ($@) {
+ warn $@;
+ require File::Copy;
+ File::Copy::copy($from, $to)
+ ? $success++
+ : warn "Couldn't copy $from to $to: $!\n";
+ }
+ $success;
+}
# List explicitly here the variables you want Configure to
# generate. Metaconfig only looks for shell variables, so you