GTM::Perl - Documentation for the GT.M side of Perl support
s x=$ZPERLEVAL("string")
s x=$ZPERLCALL("func"|subref [,args [,args]])
s x=$ZPERLMETHOD("static-class"|objref, "methodname" [,args [,args]])
s x=$ZPERLUNREF(ref)
s x=$ZPERLSCALAR(ref)
s x=$ZPERLTYPE(ref)
s x=$ZPERLICONV("internal-charset,external-charset")
This is a short reference for using Perl within GT.M
All Perl call-out stuff is handled by functions that are named $ZPERL*.
S conversion=$ZPERLICONV("")
conversion contains internal-charset and external-charset separated by ``,''. If iconv is disabled, an empty string is returned.
To disable iconv use:
S conversion=$ZPERLICONV(",")
conversion should contain an empty string after that.
Note: The available conversions and their naming depend heavily on operating-system and/or C-library. For Linux, you can list the available charsets by invoking
iconv --list
on the shell-prompt. This is a feature of UNIX98 and SuS specification. You should not hard-code the charset-names.
You can explicitly override the charset-conversion for ``PerlArray'' I/O in the future. ``ICONV'' I/O parameter is already reserved for this but it's not activated at moment.
Here a short session:
GTM-PERL>w $ZPERLICONV("")
GTM-PERL>w $ZPERLICONV("utf-8,ucs2")
utf-8,ucs2
GTM-PERL>w $ZPERLICONV("")
utf-8,ucs2
GTM-PERL>w $ZPERLICONV(",")
GTM-PERL>
Note: character conversation is not always possible, here some reasons:
a) a character in the source string is not available in the destination character set b) a byte in the source string is invalid in source character set c) the input-byte-stream stops at in the middle of a multi-byte character d) the output-buffer is too small (we already reserve a lot)
In such cases a error like:
%GTM-E-PERLICONV, Iconv conversion error: iconv-PANIC: rc=-1 in-left=1 out-left=15 errno=22: Invalid argument
may appear (this was case b).
To be safe (if you don't know what you get and you want to drop the result) write something like:
Set tmp=$ZPERLEVAL(unknown) If $L($ZPERLSCALAR(tmp)),$ZPERLUNREF(tmp)
S res=$ZPERLCALL("Package::Function",[args...])
or you can pass a subroutine reference to $ZPERLCALL, here a complete example:
S subref=$ZPERLEVAL("sub { $_[0] + $_[1] }")
S res=$ZPERLCALL(subref,2,3)
W res,!
I $ZPERLUNREF(subref)
[this is the point where it should make click right in the center of your head If you get this, you got it! Elvis lives!! :)]
This should make the story more clear:
GTM-PERL>Set scalarref=$ZPERLEVAL("\'GT.M is cool.'") Write $ZPERLSCALAR(scalarref)
SCALAR(0x82b2d4c)
GTM-PERL>Set coderef=$ZPERLEVAL("sub{}") Write $ZPERLSCALAR(coderef)
CODE(0x82b2cec)
GTM-PERL>Set arrayref=$ZPERLEVAL("[]") Write $ZPERLSCALAR(arrayref)
ARRAY(0x81c71ec)
GTM-PERL>Set hashref=$ZPERLEVAL("{}") Write $ZPERLSCALAR(hashref)
HASH(0x81c748c)
GTM-PERL>Set refref=$ZPERLEVAL("\{}") Write $ZPERLSCALAR(refref)
REF(0x81726c0)
GTM-PERL>Set obj=$ZPERLEVAL("use Math::BigInt; new Math::BigInt(123456790 x 8) * 9") Write $ZPERLSCALAR(obj)
1111111111111111111111111111111111111111111111111111111111111111111111110
GTM-PERL>Set ref=$ZPERLEVAL("[]") S dummy=$ZPERLUNREF(ref) W $ZPERLSCALAR(ref)
DEAD PERL REFERENCE (It's dead Jim.)
GTM-PERL>Write $ZPERLSCALAR("nix da.")
GTM-PERL>
Example:
GTM-PERL>Set scalarref=$ZPERLEVAL("\'GT.M is cool.'") Write $ZPERLTYPE(scalarref)
SCALAR
GTM-PERL>Set coderef=$ZPERLEVAL("sub{}") Write $ZPERLTYPE(coderef)
CODE
GTM-PERL>Set arrayref=$ZPERLEVAL("[]") Write $ZPERLTYPE(arrayref)
ARRAY
GTM-PERL>Set hashref=$ZPERLEVAL("{}") Write $ZPERLTYPE(hashref)
HASH
GTM-PERL>Set refref=$ZPERLEVAL("\{}") Write $ZPERLTYPE(refref)
REF
GTM-PERL>Set obj=$ZPERLEVAL("use Math::BigInt; new Math::BigInt(123456790 x 8) * 9") Write $ZPERLTYPE(obj)
Math::BigInt
GTM-PERL>Set ref=$ZPERLEVAL("[]") S dummy=$ZPERLUNREF(ref) W $ZPERLTYPE(ref)
DEAD PERL REFERENCE (It's dead Jim.)
GTM-PERL>Write $ZPERLTYPE("nix da.")
GTM-PERL>
You can use Perl-Arrays for I/O. I chose the ``PERLARRAY'' I/O namespace for this. If you open an array read-only it must exists prior open.
The following OPEN-parameters are supported (you can change them also with USE):
ZPUSH (default) -> append to the array on WRITE ZUNSHIFT -> insert at array begin on WRITE ZSHIFT (default) -> shifts the array on READ ZPOP -> pops the array on READ ICONV -> to override global iconv settings (currently NOT supported/activated)
Here an example code:
S a="@array"
O a:(ZPUSH:ZSHIFT)::"PerlArray"
U a W "one" W "two" W "three",! U 0
C a
w $ZPERLEVAL("use Data::Dumper; Dumper \@array")
It writes:
$VAR1 = [
'one',
'two',
'three',
undef
];
All bugs are guaranteed hardcoded - at different levels of indirection I took care about that... :)
Hmm, ok, I confess that $ZPERLICONV(...) is overloaded. If you backup the setting by
Set oldiconv=$ZPERLICONV("")
and you want to restore it you have to use:
I $ZPERLICONV($SELECT($LENGTH(oldiconv):oldiconv,1:","))
which has the coolness-factor of american beer.
From the line below this is a kind of diary, questions that comes up when looking at GT.M code.
I basically like that code and I want to contribute. I'm just a bit sarcastic. :)
Humor, you understand - but sometimes with _very_ serious background, ok?
Syn: Wit; satire; pleasantry; temper; disposition; mood;
frame; whim; fancy; caprice. See {Wit}.
[1913 Webster]
Hi friends at Intersystems, look at GT.M source - they are getting transactions right!
Working with GT.M instead of Cache is a quality upgrade which greatly improves my productivity and the security of our products. google for ``libcacheglibcwrapper''.
------------------------------------------------------------------
First I want to greet (hello world!) the funny guy at Sanchez who is responsible for ``UNIX98 vendor extensions'' like that:
typedef enum
{
NO_XLAT = 0,
EBCDIC_TO_ASCII,
ASCII_TO_EBCDIC
} gtm_iconv_t;
#define iconv_t gtm_iconv_t
Hey, boy, I definitely want to smoke the same stuff !!
What the hell..
... that's impressive. I always thought that the iconv code in glibc written by Ulrich Drepper is heavily bloated.
If you stop playing battleship combat with ANSI/SuS/UNIX98 definitions, I can remove the first line of:
#undef iconv_t /* READ. THINK. - linus at the kernel mailinglist */ #include <iconv.h>
in my gtm_perl.h.
Hey, tell me the truth, I *know* there are two senior software engineers within Sanchez Area 51 software development center who really play ANSI/SuS battleship combat.
I can hear them:
malloc() - hit, overwritten free() - strike, overwritten stdarg.h - miss iconv_t - hit, redefined!!
These two senior software engineers - let's call them Fred and Barney - are happy now because the got the magic line:
#define MAX_STRLEN (1 * 1024 * 1024) /*maximum GT.M string size (1 MB)*/ into mdef.h.
Wow, a small step into the include file, what a big step for mankind!
Hey, Barney, I suggest to increase the magic limit to (1 * 1024 * 1024 + 42).
Why? For the same reason Fred choosed (1 * 1024 * 1024).
There is no reason for his choice. It makes simply no sense. The fun of arbitrary limits is that they are, well, arbitrary. Period.
Or did I miss something?
Your core-dump writer code is really cool. You've just forgotten to include the gdb macros that remove the unusable SIGILL-handler call-frame and restore the real call-frame of the real exception.
Is it really true that your generic I/O layer doesn't pass the filename to the device-dependent open functions? ooops? :)
Here, for reference, the full content of gcc 3.3.3 varargs.h:
#ifndef _VARARGS_H #define _VARARGS_H #error "GCC no longer implements <varargs.h>." #error "Revise your code to use <stdarg.h>." #endif
I'm going to ask the gcc steering committee (hi Marc!) to modify the error message to:
#error "Revise your (or Sanchez) code to use <stdarg.h>."
Hmm, there is one additional area which caused me pain. Pseudo security.
My notebook has 2GB RAM. I build GT.M within /dev/shm. MDEFAULT.o, Barney your cool plan? What's the idea behind:
if ((plen.p.pblk.b_dir >= sizeof("/dev/") - 1) && !MEMCMP_LIT(source_file_name, "/dev/"))
tt_so_do_once = TRUE;
What I did? Well, first I tried to break your pseudo-security stuff.
mount -obind /dev /tmp/dev
and I was able to write nicely into /dev.
You can imagine what I did next.
I try to follow tradition (not indent) of GT.M. Yes, I was really so stupid to put the perl-array I/O stuff in 13 different files. I really noted my stupidity (follow the leader) long after finishing the work on it. It's somewhat braindead.
I was faster with thinking when I wrote ``<'' instead of ``>'' when checking stringpool. I think it's really better to use:
# define SP_NEED(X) do { if (stringpool.free + (X) > stringpool.top) stp_gcol(X); \
} while(0)
the GTM manpage, the GTM::GlobalTie manpage, the GTM::Preprocessor manpage, the GTM::Preprocessor::Cache manpage
or look at my ``old'' Cac modules:
Cac, the Cac::ObjectScript manpage, the Cac::Global manpage, the Cac::Routine manpage, the Cac::Util manpage, the Cac::Bind manpage.
Stefan Traby, <stefan@hello-penguin.com> http://www.hello-penguin.com/gtm-perl
Copyright (C) 2004 by Stefan Traby <stefan@hello-penguin.com> Copyright (C) 2004 by KW-Computer Ges.m.b.H., Graz, Austria
This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License (GPL).
In addition to this license
Sanchez Computer Associates, Inc.
40 Valley Stream Parkway
Malvern, PA 19355, USA
has the non-exclusive right to do what ever they want with this code.