Article 14652 of comp.lang.perl: Path: ig.co.uk!demon!uknet!EU.net!uunet!cs.utexas.edu!swrinde!ihnp4.ucsd.edu!munnari.oz.au!bunyip.cc.uq.oz.au!harbinger.cc.monash.edu.au!news.cs.su.oz.au!metro!ipso!gsms01.alcatel.oz.au!gsms01.alcatel.oz.au!not-for-mail From: jeremyp@gsms01.alcatel.oz.au (Peter Jeremy) Newsgroups: comp.lang.perl Subject: Bugs in perl, oraperl and a2p Date: 24 May 1994 16:03:16 +1000 Organization: Alcatel Australia Limited Lines: 243 Distribution: inet Message-ID: <2qn834$2fr@gsms01.alcatel.oz.au> NNTP-Posting-Host: gsms01.alcatel.oz.au Disclaimer: The views expressed herein are those of the author only In the process of converting a large awk script to perl, I have bumped into several misfeatures. I am using perl 4.034 and oraperl version 2 patchlevel 4 on SunOS 4.1.3. ---------------------------------------------------------------- 1) The perl problem is that setting $# to '%d' causes numeric output to be corrupted unless some non-numeric characters exist in the output, even if a different format is specified in a printf. gsms01% perl -ew '$# = "%d"; $a = 1; printf " %.0fx", $a; print "($a)\n";' 1x(1) gsms01% perl -ew '$# = "%d"; $a = 1; printf " %.0fx\n", $a; print "($a)\n";' 1x (1) gsms01% perl -ew '$# = "%d"; $a = 1; printf " %.0f\n", $a; print "($a)\n";' 1072693248(1) gsms01% perl -ew '$# = "%d"; $a = 1; printf " %d\n", $a; print "($a)\n";' 1072693248(1) gsms01% perl -ew '$# = "%.0f"; $a = 1; printf " %d\n", $a; print "($a)\n";' 1(1) gsms01% perl -ew '$a = 1; printf " %d\n", $a; print "($a)\n";' 1 (1) gsms01% Note that when $# is set to either '%d' or '%.0f', all whitespace is lost. With $# set to '%d', the value printed is 0x7ff00000, which is the high word of a double precision 1.0. ---------------------------------------------------------------- 2) The oraperl problem relates to LONG datatypes. oraperl internally uses shorts for the field lengths. From my reading of Oracle behaviour (and I don't have an up-to-date Pro*C manual handy to confirm), this should be an unsigned short (to allow up to 65535 bytes). This causes problems trying to read tables with LONG columns > 32K in length. I believe the following patch solves the problem, but I have not fully tested it yet. --- debug/orafns.c Wed Apr 27 15:00:44 1994 +++ orafns.c Tue May 10 15:54:39 1994 @@ -228,7 +228,7 @@ int i; struct cursor *csr; struct cursor *lda = (struct cursor *)strtoul(lda_s, (char **) NULL, 0); - short dsize; + word dsize; DBUG_ENTER("ora_open"); DBUG_PRINT("entry", ("ora_open(%s, \"%s\", %d)", lda_s, stmt, cache)); @@ -280,8 +280,8 @@ i = 0; do { - odsc(csr->csr, ++i, (short *) 0, (short *) 0, (short *) 0, - (short *) 0, (char *) 0, (short *) 0, (short *) 0); + odsc(csr->csr, ++i, (word *) 0, (word *) 0, (word *) 0, + (word *) 0, (char *) 0, (word *) 0, (word *) 0); } while (csr->csr->csrrc == 0); --i; ora_err.no = 0; @@ -317,7 +317,7 @@ i, i * sizeof(char *), (long) csr->data)); *csr->data = (char *) NULL; - if ((csr->len = (short *) malloc(i * sizeof(short))) == NULL) + if ((csr->len = (word *) malloc(i * sizeof(word))) == NULL) { DBUG_PRINT("malloc", ("insufficient memory for len")); oclose(csr->csr); @@ -327,9 +327,9 @@ DBUG_RETURN((char *) NULL); } DBUG_PRINT("malloc", ("got len array %d items %d bytes at %#lx", - i, i * sizeof(short), (long) csr->len)); + i, i * sizeof(word), (long) csr->len)); - if ((csr->rcode = (short **) malloc(i*sizeof(short *))) == NULL) + if ((csr->rcode = (word **) malloc(i*sizeof(word *))) == NULL) { DBUG_PRINT("malloc", ("insufficient memory for rcode")); oclose(csr->csr); @@ -340,9 +340,9 @@ } DBUG_PRINT("malloc", ("got rcode array %d items %d bytes at %#lx", - i, i * sizeof(short *), (long) csr->rcode)); + i, i * sizeof(word *), (long) csr->rcode)); - if ((csr->type = (short *) malloc(i * sizeof(short))) == NULL) + if ((csr->type = (word *) malloc(i * sizeof(word))) == NULL) { DBUG_PRINT("malloc", ("insufficient memory for type")); oclose(csr->csr); @@ -352,15 +352,15 @@ DBUG_RETURN((char *) NULL); } DBUG_PRINT("malloc",("got type array %d items %d bytes at %#lx", - i, i * sizeof(short), (long) csr->type)); + i, i * sizeof(word), (long) csr->type)); csr->nfields = i; for (i = 0 ; i < csr->nfields ; i++) { - odsc(csr->csr, i + 1, (short *) 0, (short *) 0, - (short *) 0, &csr->type[i], (char *) 0, - (short *) 0, &dsize); + odsc(csr->csr, i + 1, (word *) 0, (word *) 0, + (word *) 0, &csr->type[i], (char *) 0, + (word *) 0, &dsize); if ((csr->type[i] == 8) || (csr->type[i] == 24)) { @@ -386,7 +386,7 @@ i, (dsize + 1) * cache, csr->data[i])); if ((csr->rcode[i] = - (short *) malloc(sizeof(short) * cache)) == NULL) + (word *) malloc(sizeof(word) * cache)) == NULL) { DBUG_PRINT("malloc", ("insufficient memory for rcode[%d]", i)); @@ -397,10 +397,10 @@ DBUG_RETURN((char *) NULL); } DBUG_PRINT("malloc", ("got rcode %d, %d bytes at %#lx", - i, sizeof(short) * cache, csr->rcode[i])); + i, sizeof(word) * cache, csr->rcode[i])); odefin(csr->csr, i + 1, csr->data[i], dsize + 1, 5, 0, - (short *) 0, (char *) 0, 0, 0, (short *) 0, + (word *) 0, (char *) 0, 0, 0, (word *) 0, csr->rcode[i]); csr->len[i] = dsize; @@ -468,7 +468,7 @@ int truncate; { int i; - short len; + word len; struct cursor *csr = (struct cursor *)strtoul(csr_s, (char **) NULL, 0); static int n_titles = 0; @@ -533,7 +533,7 @@ for (i = 0 ; i < csr->nfields ; i++) { len = (truncate) ? csr->len[i] : 256; - oname(csr->csr, i + 1, (char *) -1, (short *) -1, + oname(csr->csr, i + 1, (char *) -1, (word *) -1, &titles[256 * i], &len); ora_result[i] = &titles[256 * i]; ora_result[i][len] = '\0'; @@ -559,7 +559,7 @@ char *csr_s; { int i; - short len; + word len; struct cursor *csr = (struct cursor *)strtoul(csr_s, (char **) NULL, 0); DBUG_ENTER("ora_lengths"); --- debug/orafns.h Wed Apr 27 15:00:44 1994 +++ orafns.h Tue May 10 15:54:36 1994 @@ -10,6 +10,8 @@ */ +typedef unsigned short word; + /* public functions to be called by Perl programs */ void ora_version(); @@ -77,7 +79,7 @@ struct csrdef *csr; char *hda, /* used if this cursor is an lda */ **data; /* used to receive database contents */ - short **rcode, /* used to receive fetch error codes */ + word **rcode, /* used to receive fetch error codes */ *type, /* used to receive data types */ *len; /* used to receive field lengths */ int cache_size, /* how many rows to cache */ ---------------------------------------------------------------- 3) a2p does not accept the following awk script: BEGIN { printf "hello\n" do { if ((getline) <= 0) exit; foo += $0 } while (1) } END { printf "%d", foo print "the end" } unless there is a semicolon following the `while (1)' (it says parse error in file /mnt/x1 at line 7 Translation aborted due to syntax errors. ). When the semicolon is added, the following script is produced, which includes a reference to an undefined label `line': #!/usr/local/bin/perl eval "exec /usr/local/bin/perl -S $0 $*" if $running_under_some_shell; # this emulates #! processing on NIH machines. # (remove #! line above if indigestible) eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_]+=)(.*)/ && shift; # process any FOO=bar switches $, = ' '; # set output field separator $\ = "\n"; # set output record separator printf "hello\n"; do { if ((($_ = &Getline0(),$getline_ok)) <= 0) { last line; } $foo += $_; } while (1); while (<>) { } # (no line actions) printf '%d', $foo; print 'the end'; sub Getline0 { if ($getline_ok = (($_ = <>) ne '')) { chop; # strip record separator } $_; } -- Peter Jeremy (VK2PJ) peter@titan.alcatel.oz.au Alcatel Australia Limited jeremyp@gsms01.alcatel.oz.au 41 Mandible St Phone: +61 2 690 5019 ALEXANDRIA NSW 2015 Fax: +61 2 690 5247 .