home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume39 / sybperl / part02 < prev    next >
Encoding:
Text File  |  1993-09-25  |  61.4 KB  |  2,359 lines

  1. Newsgroups: comp.sources.misc
  2. From: mpeppler@itf.ch (Michael Peppler)
  3. Subject: v39i102:  sybperl - Sybase DB-library extensions to Perl, v1.8, Part02/03
  4. Message-ID: <1993Sep25.182643.13406@sparky.sterling.com>
  5. X-Md4-Signature: 8f6c6b86ed41cf7a499641a9deccac21
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Sterling Software
  8. Date: Sat, 25 Sep 1993 18:26:43 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: mpeppler@itf.ch (Michael Peppler)
  12. Posting-number: Volume 39, Issue 102
  13. Archive-name: sybperl/part02
  14. Environment: UNIX, Perl, Sybase
  15. Supersedes: sybperl: Volume 37, Issue 33-34
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then feed it
  19. # into a shell via "sh file" or similar.  To overwrite existing files,
  20. # type "sh file -c".
  21. # Contents:  eg/dbschema.pl eg/report.pl sybperl.1 sybperl.c.B
  22. # Wrapped by kent@sparky on Sat Sep 25 13:16:00 1993
  23. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 2 (of 3)."'
  26. if test -f 'eg/dbschema.pl' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'eg/dbschema.pl'\"
  28. else
  29.   echo shar: Extracting \"'eg/dbschema.pl'\" \(9359 characters\)
  30.   sed "s/^X//" >'eg/dbschema.pl' <<'END_OF_FILE'
  31. X#! /usr/local/bin/sybperl
  32. X#
  33. X#    @(#)dbschema.pl    1.5    9/10/93
  34. X#
  35. X#
  36. X#    dbschema.pl    A script to extract a database structure from
  37. X#            a Sybase database
  38. X#
  39. X#    Written by:    Michael Peppler (mpeppler@itf.ch)
  40. X#    Last Modified:  24 June 1992
  41. X#
  42. X#    Usage:        dbschema.pl -d database -o script.name -t pattern -v
  43. X#                where   database is self-explanatory (default: master)
  44. X#                                   script.name is the output file (default: script.isql)
  45. X#                                   pattern is the pattern of object names (in sysobjects)
  46. X#                                           that we will look at (default: %)
  47. X#
  48. X#                -v turns on a verbose switch.
  49. X#
  50. X
  51. X
  52. Xrequire 'sybperl.pl';
  53. Xrequire 'getopts.pl';
  54. Xrequire 'ctime.pl';
  55. X
  56. X@nul = ('not null','null');
  57. X
  58. Xselect(STDOUT); $| = 1;        # make unbuffered
  59. X
  60. Xdo Getopts('d:t:o:v');
  61. X
  62. X$opt_d = 'master' unless $opt_d;
  63. X$opt_o = 'script.isql' unless $opt_o;
  64. X$opt_t = '%' unless $opt_t;
  65. X
  66. Xopen(SCRIPT, "> $opt_o") || die "Can't open $opt_o: $!\n";
  67. Xopen(LOG, "> $opt_o.log") || die "Can't open $opt_o.log: $!\n";
  68. X
  69. X#
  70. X# NOTE: We login to Sybase with the default (Unix) user id.
  71. X#       We should probably login as 'SA', and get the passwd
  72. X#       from the user at run time.
  73. X#
  74. X$dbproc = &dblogin;
  75. X&dbuse($dbproc, $opt_d);
  76. X
  77. Xchop($date = &ctime(time));
  78. X
  79. X
  80. Xprint "dbschema.pl on Database $opt_d\n";
  81. X
  82. Xprint LOG "Error log from dbschema.pl on Database $opt_d on $date\n\n";
  83. Xprint LOG "The following objects cannot be reliably created from the script in $opt_o.
  84. XPlease correct the script to remove any inconsistencies.\n\n";
  85. X
  86. Xprint SCRIPT
  87. X    "/* This Isql script was generated by dbschema.pl on $date.
  88. X** The indexes need to be checked: column names & index names
  89. X** might be truncated!
  90. X*/\n";
  91. X
  92. Xprint SCRIPT "\nuse $opt_d\ngo\n"; # Change to the appropriate database
  93. X
  94. X
  95. X# first, Add the appropriate user data types:
  96. X#
  97. X
  98. Xprint "Add user-defined data types...";
  99. Xprint SCRIPT
  100. X    "/* Add user-defined data types: */\n\n";
  101. X
  102. X&dbcmd($dbproc, "select s.length, s.name, st.name,\n");
  103. X&dbcmd($dbproc, "       object_name(s.tdefault),\n");
  104. X&dbcmd($dbproc, "       object_name(s.domain)\n");
  105. X&dbcmd($dbproc, "from   $opt_d.dbo.systypes s, $opt_d.dbo.systypes st\n");
  106. X&dbcmd($dbproc, "where  st.type = s.type\n");
  107. X&dbcmd($dbproc, "and s.usertype > 100 and st.usertype < 100 and st.usertype != 18\n");
  108. X&dbsqlexec($dbproc);
  109. X&dbresults($dbproc);
  110. X
  111. X
  112. Xwhile((@dat = &dbnextrow($dbproc)))
  113. X{
  114. X    print SCRIPT "sp_addtype $dat[1],";
  115. X    if ($dat[2] =~ /char|binary/)
  116. X    {
  117. X        print SCRIPT "'$dat[2]($dat[0])'";
  118. X    }
  119. X    else
  120. X    {
  121. X        print SCRIPT "$dat[2]";
  122. X    }
  123. X    print SCRIPT "\ngo\n";
  124. X                # Now remeber the default & rule for later.
  125. X    $urule{$dat[1]} = $dat[4] if $dat[4] !~ /NULL/;
  126. X    $udflt{$dat[1]} = $dat[3] if $dat[3] !~ /NULL/;
  127. X}
  128. X
  129. Xprint "Done\n";
  130. X
  131. Xprint "Create rules...";
  132. Xprint SCRIPT
  133. X    "\n/* Now we add the rules... */\n\n";
  134. X
  135. X&getObj('Rule', 'R');
  136. Xprint "Done\n";
  137. X
  138. Xprint "Create defaults...";
  139. Xprint SCRIPT
  140. X    "\n/* Now we add the defaults... */\n\n";
  141. X
  142. X&getObj('Default', 'D');
  143. Xprint "Done\n";
  144. X
  145. Xprint "Bind rules & defaults to user data types...";
  146. Xprint SCRIPT "/* Bind rules & defaults to user data types... */\n\n";
  147. X
  148. Xwhile(($dat, $dflt)=each(%udflt))
  149. X{
  150. X    print SCRIPT "sp_bindefault $dflt, $dat\ngo\n";
  151. X}
  152. Xwhile(($dat, $rule) = each(%urule))
  153. X{
  154. X    print SCRIPT "sp_bindrule $rule, $dat\ngo\n";
  155. X}
  156. Xprint "Done\n";
  157. X
  158. Xprint "Create Tables & Indices...";
  159. Xprint "\n" if $opt_v;
  160. X
  161. X&dbcmd($dbproc, "select o.name,u.name, o.id\n");
  162. X&dbcmd($dbproc, "from $opt_d.dbo.sysobjects o, $opt_d.dbo.sysusers u\n");
  163. X&dbcmd($dbproc, "where o.type = 'U' and o.name like '$opt_t' and u.uid = o.uid\n");
  164. X&dbcmd($dbproc, "order by o.name\n");
  165. X
  166. X&dbsqlexec($dbproc);
  167. X&dbresults($dbproc);
  168. X
  169. Xwhile((@dat = &dbnextrow($dbproc)))
  170. X{
  171. X    $_ = join('@', @dat);    # join the data together on a line
  172. X    push(@tables,$_);        # and save it in a list
  173. X}
  174. X
  175. X
  176. Xforeach (@tables)        # For each line in the list
  177. X{
  178. X    @tab = split(/@/, $_);
  179. X
  180. X    print "Creating table $tab[0], owner $tab[1]\n" if $opt_v;
  181. X
  182. X    print SCRIPT "/* Start of description of table $tab[1].$tab[0] */\n\n";
  183. X
  184. X    &dbcmd($dbproc, "select Column_name = c.name, \n");
  185. X    &dbcmd($dbproc, "       Type = t.name, \n");
  186. X    &dbcmd($dbproc, "       Length = c.length, \n");
  187. X    &dbcmd($dbproc, "       Nulls = convert(bit, (c.status & 8)),\n");
  188. X    &dbcmd($dbproc, "       Default_name = object_name(c.cdefault),\n");
  189. X    &dbcmd($dbproc, "       Rule_name = object_name(c.domain)\n");
  190. X    &dbcmd($dbproc, "from   $opt_d.dbo.syscolumns c, $opt_d.dbo.systypes t\n");
  191. X    &dbcmd($dbproc, "where  c.id = $tab[2]\n");
  192. X    &dbcmd($dbproc, "and    c.usertype *= t.usertype\n");
  193. X
  194. X    &dbsqlexec($dbproc);
  195. X    &dbresults($dbproc);
  196. X
  197. X    undef(%rule);
  198. X    undef(%dflt);
  199. X
  200. X    print SCRIPT "\n\nCREATE TABLE $opt_d.$tab[1].$tab[0]\n ("; 
  201. X    $first = 1;
  202. X    while((@field = &dbnextrow($dbproc)))
  203. X    {
  204. X        print SCRIPT ",\n" if !$first;        # add a , and a \n if not first field in table
  205. X        
  206. X        print SCRIPT "\t$field[0] \t$field[1]";
  207. X        print SCRIPT "($field[2])" if $field[1] =~ /char|bin/;
  208. X        print SCRIPT " $nul[$field[3]]";
  209. X    
  210. X    $rule{"$tab[0].$field[0]"} = $field[5] if ($field[5] !~ /NULL/ && $urule{$field[1]} ne $field[5]);
  211. X    $dflt{"$tab[0].$field[0]"} = $field[4] if ($field[4] !~ /NULL/ && $udflt{$field[1]} ne $field[4]);;
  212. X        $first = 0 if $first;
  213. X        
  214. X    }
  215. X    print SCRIPT " )\n";
  216. X
  217. X# now get the indexes...
  218. X#
  219. X
  220. X    print "Indexes for table $tab[1].$tab[0]\n" if $opt_v;
  221. X    
  222. X    &dbcmd($dbproc, "sp_helpindex '$tab[1].$tab[0]'\n");
  223. X
  224. X    &dbsqlexec($dbproc);
  225. X    &dbresults($dbproc);
  226. X
  227. X    while((@field = &dbnextrow($dbproc)))
  228. X    {
  229. X        print SCRIPT "\nCREATE ";
  230. X        print SCRIPT "unique " if $field[1] =~ /unique/;
  231. X        print SCRIPT "clustered " if $field[1] =~ /^clust/;
  232. X        print SCRIPT "index $field[0]\n";
  233. X        @col = split(/,/,$field[2]);
  234. X        print SCRIPT "on $opt_d.$tab[1].$tab[0] (";
  235. X        $first = 1;
  236. X        foreach (@col)
  237. X        {
  238. X            print SCRIPT ", " if !$first;
  239. X            $first = 0;
  240. X            print SCRIPT "$_";
  241. X        }
  242. X        print SCRIPT ")\n";
  243. X    }
  244. X
  245. X    &getPerms("$tab[1].$tab[0]");
  246. X
  247. X    print SCRIPT "go\n";
  248. X
  249. X    print "Bind rules & defaults to columns...\n" if $opt_v;
  250. X    print SCRIPT "/* Bind rules & defaults to columns... */\n\n";
  251. X
  252. X    if($tab[1] ne 'dbo' && (keys(%dflt) || keys(%rules)))
  253. X    {
  254. X    print SCRIPT "/* The owner of the table is $tab[1].
  255. X** I can't bind the rules/defaults to a table of which I am not the owner.
  256. X** The procedures below will have to be run manualy by user $tab[1].
  257. X*/";
  258. X    print LOG "Defaults/Rules for $tab[1].$tab[0] could not be bound\n";
  259. X    }
  260. X
  261. X    while(($dat, $dflt)=each(%dflt))
  262. X    {
  263. X    print SCRIPT "/* " if $tab[1] ne 'dbo';
  264. X    print SCRIPT "sp_bindefault $dflt, '$dat'";
  265. X    if($tab[1] ne 'dbo')
  266. X    {
  267. X        print SCRIPT " */\n";
  268. X    }
  269. X    else
  270. X    {
  271. X        print SCRIPT "\ngo\n";
  272. X    }
  273. X    }
  274. X    while(($dat, $rule) = each(%rule))
  275. X    {
  276. X    print SCRIPT "/* " if $tab[1] ne 'dbo';
  277. X    print SCRIPT "sp_bindrule $rule, '$dat'";
  278. X    if($tab[1] ne 'dbo')
  279. X    {
  280. X        print SCRIPT " */\n";
  281. X    }
  282. X    else
  283. X    {
  284. X        print SCRIPT "\ngo\n";
  285. X    }
  286. X    }
  287. X    print SCRIPT "\n/* End of description of table $tab[1].$tab[0] */\n";
  288. X
  289. X}
  290. X
  291. Xprint "Done\n";
  292. X
  293. X
  294. X#
  295. X# Now create any views that might exist
  296. X#
  297. X
  298. Xprint "Create views...";
  299. Xprint SCRIPT
  300. X    "\n/* Now we add the views... */\n\n";
  301. X
  302. X&getObj('View', 'V');
  303. X
  304. Xprint "Done\n";
  305. X
  306. X#
  307. X# Now create any stored procs that might exist
  308. X#
  309. X
  310. Xprint "Create stored procs...";
  311. Xprint SCRIPT
  312. X    "\n/* Now we add the stored procedures... */\n\n";
  313. X&getObj('Stored Proc', 'P');
  314. X
  315. Xprint "Done\n";
  316. X
  317. X#
  318. X# Now create the triggers
  319. X#
  320. X
  321. Xprint "Create triggers...";
  322. Xprint SCRIPT
  323. X    "\n/* Now we add the triggers... */\n\n";
  324. X
  325. X&getObj('Trigger', 'TR');
  326. X
  327. X
  328. Xprint "Done\n";
  329. X
  330. Xprint "\nLooks like I'm all done!\n";
  331. Xclose(SCRIPT);
  332. Xclose(LOG);
  333. X
  334. X&dbexit;
  335. X
  336. X
  337. Xsub getPerms
  338. X{
  339. X    local($obj) = $_[0];
  340. X    local($ret, @dat, $act, $cnt);
  341. X
  342. X    &dbcmd($dbproc, "sp_helprotect '$obj'\n");
  343. X    &dbsqlexec;
  344. X
  345. X    $cnt = 0;
  346. X    while(($ret = &dbresults) != $NO_MORE_RESULTS && $ret != $FAIL)
  347. X    {
  348. X    while(@dat = &dbnextrow)
  349. X    {
  350. X        $act = 'to';
  351. X        $act = 'from' if $dat[0] =~ /Revoke/;
  352. X        print SCRIPT "$dat[0] $dat[1] on $obj $act $dat[2]\n";
  353. X        ++$cnt;
  354. X    }
  355. X    }
  356. X    $cnt;
  357. X}
  358. X
  359. Xsub getObj
  360. X{
  361. X    local($objname, $obj) = @_;
  362. X    local(@dat, @items, @vi, $found);
  363. X    
  364. X    &dbcmd($dbproc, "select o.name, u.name, o.id\n");
  365. X    &dbcmd($dbproc, "from $opt_d.dbo.sysobjects o, $opt_d.dbo.sysusers u\n");
  366. X    &dbcmd($dbproc, "where o.type = '$obj' and o.name like '$opt_t' and u.uid = o.uid\n");
  367. X    &dbcmd($dbproc, "order by o.name\n");
  368. X
  369. X    &dbsqlexec($dbproc);
  370. X    &dbresults($dbproc);
  371. X
  372. X    while((@dat = &dbnextrow($dbproc)))
  373. X    {                # 
  374. X    $_ = join('@', @dat);    # join the data together on a line
  375. X    push(@items, $_);    # and save it in a list
  376. X    }
  377. X
  378. X    foreach (@items)
  379. X    {
  380. X    @vi = split(/@/, $_);
  381. X    $found = 0;
  382. X
  383. X    &dbcmd($dbproc, "select text from syscomments where id = $vi[2]");
  384. X    &dbsqlexec;
  385. X    &dbresults;
  386. X    
  387. X    print SCRIPT
  388. X        "/* $objname $vi[0], owner $vi[1] */\n";
  389. X
  390. X    while(($text) = &dbnextrow)
  391. X    {
  392. X        if(!$found && $vi[1] ne 'dbo')
  393. X        {
  394. X        ++$found if($text =~ /$vi[1]/);
  395. X        }
  396. X        print SCRIPT $text;
  397. X    }
  398. X    print SCRIPT "\ngo\n";
  399. X    if(!$found && $vi[1] ne 'dbo')
  400. X    {
  401. X        print "**Warning**\n$objname $vi[0] has owner $vi[1]\nbut this is not mentioned in the CREATE PROC statement!!\n";
  402. X        print LOG "$objname $vi[0] (owner $vi[1])\n";
  403. X    }
  404. X    }
  405. X}
  406. X
  407. X
  408. END_OF_FILE
  409.   if test 9359 -ne `wc -c <'eg/dbschema.pl'`; then
  410.     echo shar: \"'eg/dbschema.pl'\" unpacked with wrong size!
  411.   fi
  412.   # end of 'eg/dbschema.pl'
  413. fi
  414. if test -f 'eg/report.pl' -a "${1}" != "-c" ; then 
  415.   echo shar: Will not clobber existing file \"'eg/report.pl'\"
  416. else
  417.   echo shar: Extracting \"'eg/report.pl'\" \(753 characters\)
  418.   sed "s/^X//" >'eg/report.pl' <<'END_OF_FILE'
  419. X#! /usr/local/bin/sybperl
  420. X
  421. X#
  422. X#    @(#)report.pl    1.1    6/24/92
  423. X#
  424. X
  425. Xrequire "sybperl.pl";
  426. Xrequire "sql.pl";
  427. X
  428. X#
  429. X# Log us in to Sybase.
  430. X#
  431. X$d = &dblogin;
  432. X
  433. X#
  434. X# define the format
  435. X#
  436. Xformat top=
  437. X             PASSWORD FILE
  438. XLogin      Uid Group      Shell                   Home directory
  439. X-------- ----- ---------- ----------------------- ----------------------
  440. X. 
  441. Xformat stdout=
  442. X@<<<<<<< @>>>> @<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<
  443. X$n,      $u,   $gn,       $s,                     $d
  444. X. 
  445. X
  446. X#
  447. X# See if everything is there.
  448. X#
  449. X@results = &sql($d, '
  450. X    select username, uid, isnull(groupname,convert(char,p.gid)), shell, home
  451. X    from password p, groups g
  452. X    where    p.gid *= g.gid
  453. X    order by uid
  454. X    ');
  455. Xforeach $x (@results) {
  456. X    ($n,$u,$gn,$s,$d) = split("~",$x);
  457. X    write;
  458. X}
  459. X
  460. END_OF_FILE
  461.   if test 753 -ne `wc -c <'eg/report.pl'`; then
  462.     echo shar: \"'eg/report.pl'\" unpacked with wrong size!
  463.   fi
  464.   chmod +x 'eg/report.pl'
  465.   # end of 'eg/report.pl'
  466. fi
  467. if test -f 'sybperl.1' -a "${1}" != "-c" ; then 
  468.   echo shar: Will not clobber existing file \"'sybperl.1'\"
  469. else
  470.   echo shar: Extracting \"'sybperl.1'\" \(10929 characters\)
  471.   sed "s/^X//" >'sybperl.1' <<'END_OF_FILE'
  472. X.\".po 4
  473. X.\"    @(#)sybperl.1    1.4    9/7/93
  474. X.TH SYBPERL 1 "31 Aug 1993"
  475. X.ad
  476. X.nh
  477. X.SH NAME
  478. Xsybperl \- Perl access to Sybase databases
  479. X.SH SYNOPSIS
  480. X.nf
  481. X$dbproc  = &dblogin([$user[, $pwd[, $server]]])
  482. X$dbproc1 = &dbopen([$server])
  483. X       &dbclose($dbproc)
  484. X$ret     = &dbcmd($dbproc, $sql_cmd)
  485. X$ret     = &dbsqlexec($dbproc)
  486. X$ret     = &dbresults($dbproc)
  487. X@data    = &dbnextrow($dbproc [, $doAssoc])
  488. X@data    = &dbretdata($dbproc [, $doAssoc])
  489. X$ret     = &dbuse($dbproc, $database)
  490. X$ret     = &dbcancel($dbproc)
  491. X$ret     = &dbcanquery($dbproc)
  492. X$ret     = &dbexit($dbproc)
  493. X$string  = &dbstrcpy($dbproc)
  494. X$string  = &dbsafestr($dbproc,$instring[,$quote_char])
  495. X$status  = &dbwritetext($dbproc_1, $col_name, $dbproc_2, $select_col, $text)
  496. X$count   = &dbnumcol($dbproc)
  497. X$type    = &dbcoltype($dbproc, $colid)
  498. X$name    = &dbcolname($dbproc, $colid)
  499. X$len     = &dbcollen($dbproc, $colid)
  500. X$status  = &dbhasretstat($dbproc)
  501. X$status  = &dbretstatus($dbproc)
  502. X$ret     = &dberrhandle($handler)
  503. X$ret     = &dbmsghandle($handler)
  504. X$ret     = &DBCURCMD($dbproc)
  505. X$status  = &DBMORECMD($dbproc)
  506. X$status  = &DBCMDROW($dbproc)
  507. X$status  = $DBROWS($dbproc)
  508. X$ret     = $DBCOUNT($dbproc)
  509. X($status, $sum)    = &dbmny4add($dbproc,$m1,$m2)
  510. X$status        = &dbmny4cmp($dbproc,$m1,$m2)
  511. X($status, $quotient)    = &dbmny4divide($dbproc,$m1,$m2)
  512. X($status, $dest)    = &dbmny4minus($dbproc,$source)
  513. X($status, $product)    = &dbmny4mul($dbproc,$m1,$m2)
  514. X($status, $difference)    = &dbmny4sub($dbproc,$m1,$m2)
  515. X($status, $ret)    = &dbmny4zero($dbproc)
  516. X($status, $sum)    = &dbmnyadd($dbproc,$m1,$m2)
  517. X$status        = &dbmnycmp($dbproc,$m1,$m2)
  518. X($status, $ret)    = &dbmnydec($dbproc, $m1)
  519. X($status, $quotient)    = &dbmnydivide($dbproc,$m1,$m2)
  520. X($status, $ret, $remainder) = &dbmnydown($dbproc,$m1, $divisor)
  521. X($status, $ret)    = &dbmnyinc($dbproc, $m1)
  522. X($status, $ret, $remain)    = &dbmnyinit($dbproc, $m1,$trim)
  523. X($status, $ret)        = &dbmnymaxneg($dbproc)
  524. X($status, $ret)        = &dbmnymaxpos($dbproc)
  525. X($status, $dest) = &dbmnyminus($dbproc,$source)
  526. X($status, $product)    = &dbmnymul($dbproc,$m1,$m2)
  527. X($status, $m1, $digits, $remain)    = &dbmnyndigit($dbproc,$m1)
  528. X($status, $ret)        = &dbmnyscale($dbproc,$m1,$multiplier,
  529. X                $addend)
  530. X($status, $difference)    = &dbmnysub($dbproc,$m1,$m2)
  531. X($status, $ret)    = &dbmnyzero($dbproc)
  532. X
  533. X$status    = &BCP_SETL($state)
  534. X$status = &bcp_getl;
  535. X$status = &bcp_init($dbproc, $tblname, $hostfile, $errfile, $dir)
  536. X$status = &bcp_meminit($dbproc, $numcols)
  537. X$status = &bcp_sendrow($dbproc, $col1, $col2, ...)
  538. X$status = &bcp_batch($dbproc)
  539. X$status = &bcp_done($dbproc)
  540. X$status = &bcp_control($dbproc, $field, $value)
  541. X$status = &bcp_columns($dbproc, $host_columns)
  542. X$status = &bcp_colfmt($dbproc, $host_column, $host_type,
  543. X              $host_prefixlen, $host_collen, $host_term,
  544. X              $host_termlen, $table_colnum)
  545. X($status, $rows_copied) = &bcp_exec($dbproc)
  546. X$status = &bcp_readfmt($dbproc, $filename)
  547. X$status = &bcp_writefmt($dbproc, $filename)
  548. X
  549. X$SUCCEED        $MORE_ROWS            $EXCEPTION    $EXPROGRAM
  550. X$FAIL            $REG_ROW            $EXSIGNAL    $EXSERVER
  551. X$NO_MORE_ROWS    $BUF_FULL            $EXINFO    $EXCOMM
  552. X$NO_MORE_RESULTS    $NO_MORE_PARAMS        $EXDBLIB    $EXTIME
  553. X$ComputeId        $DBSAVE            $EXFORMS    $EXFATAL
  554. X$DBstatus        $DBNOSAVE            $EXUSER
  555. X$SybperlVer        $DBNOERR            $EXLOOKUP
  556. X$STDEXIT        $DB_PASSTHRU_MORE    $EXSCREENIO
  557. X$ERREXIT        $DB_PASSTHRU_EOM        $EXCLIPBOARD
  558. X$INT_EXIT        $DBNOPROC            $EXNONFATAL
  559. X$INT_CONTINUE                    $EXCONVERSION
  560. X$INT_CANCEL                        $EXRESOURCE
  561. X$INT_TIMEOUT                        $EXCONSISTENCY
  562. X$DB_IN        $DB_OUT
  563. X$BCPMAXERRS    $BCPFIRST    $BCPLAST    $BCPBATCH
  564. X$DBTRUE        $DBFALSE
  565. X$SybPackageBug
  566. X$dbNullIsUndef    $dbKeepNumeric    $dbBin0x
  567. X.fi
  568. X.SH DESCRIPTION
  569. X\fBSybperl\fP is a version of \fIPerl\fP which has been extended (via
  570. Xthe \fIusersubs\fP feature) to allow access to \fISybase\fP databases.
  571. X
  572. X\fBSybperl\fP maps a subset of the \fISybase
  573. XDB-Library\fP API to \fIPerl\fP. The usage of these functions is the same
  574. Xas in \fIDB-Library\fP, unless specifically noted.
  575. X
  576. X\fBDifferences with DB-Library:\fP
  577. X
  578. X\fB&dblogin\fP takes 3 optional arguements (the userid, the
  579. Xpassword and the server to connect to). These default to the Unix
  580. Xuserid, the null password and the default server (from the DSQUERY
  581. Xenvironment variable).
  582. X
  583. X\fB&dblogin\fP returns a \fBDBPROCESS\fP, not a \fBLOGINREC\fP. This
  584. Xsimplifies the call to open a connection to a Sybase dataserver
  585. Xsomewhat. If the login fails for any reason \fB&dblogin\fP returns -1.
  586. X\fB&dblogin\fP can be called multiple times to login to different
  587. Xservers, or to login as several users simultaneously.
  588. X
  589. XFurther \fBDBPROCESSes\fP can be opened using
  590. X\fB&dbopen([$server])\fP, using the login information from the
  591. Xlast call to \fB&dblogin()\fP. The number of simultaneous DBPROCESSes
  592. Xis limited to 25 (This can be changed by altering a #define in sybperl.c).
  593. X
  594. XThe \fB$dbproc\fP parameter used by most subroutines is optional,
  595. Xand defaults to the DBPROCESS returned
  596. Xby the first call to \fB&dblogin\fP (exceptions: \fB&dbsafestr()\fP,
  597. X\fB&dbwritetext()\fP and \fB&bcp_sendrow()\fP require explicit \fB$dbproc\fP parameters.)
  598. X
  599. X\fB&dbnextrow\fP returns an array of formatted data, based on the
  600. Xdatatype of the corresponding columns. \fB&dbnextrow\fP sets the
  601. Xvariable \fB$ComputeId\fP when the result row is a computed row (the
  602. Xresult of a \fIcompute by\fP clause). If the optional \fB$doAssoc\fP
  603. Xparameter is non-zero \fB&dbnextrow\fP returns an
  604. Xassociative array keyed on the column name of each returned field. If
  605. Xthe column name is null (as for example in the case of an aggregate),
  606. Xthen \fB&dbnextrow\fP assigns a column name based on the column number.
  607. X
  608. X\fB&dbretdata\fP returns an array of the parameters
  609. Xdeclared as \fBOUTput\fP in an \fBEXEC\fP stored procedure statement.
  610. XIf the ooptional \fB$doAssoc\fP parameter is non-zero, then an
  611. Xassociative array keyed on the name of the parameters is returned
  612. X(again, if the parameters are unnamed, the key is based on the
  613. Xparamter number). A single call will
  614. Xreturn all the parameters for the last \fBEXEC\fP statement.
  615. X
  616. X\fB&dbsafestr\fP takes a string literal ' or " as the third [optional] argument
  617. Xand means \fBDBSINGLE\fP or \fBDBDOUBLE\fP, respectively.
  618. XOmission of the third argument means \fBDBBOTH\fP.
  619. X
  620. XIn order to simplify its use somewhat, the calling sequence of
  621. X\fB&dbwritetext\fP has been changed. \fI$select_proc\fP and
  622. X\fI$select_col\fP are the dbproc and column number of a currently
  623. Xactive query. Logging is always off.
  624. X
  625. XNote that all DBMONEY routines which in the C version take pointers to
  626. Xarguments (in order to return values) return these values in an array
  627. Xinstead (eg: status = dbmnyadd(dbproc, m1, m2, result) becomes
  628. X($status, $result) = &dbmnyadd($dbproc, $m1, $m2))
  629. X
  630. XCopying data from program variables into a Sybase table using BCP has
  631. Xbeen implemented in a slightly different manner. Instead of using
  632. Xbcp_bind(), you need to call &bcp_meminit() to determine the number of
  633. Xcolumns that will be sent to the server, and the call &bcp_sendrow()
  634. Xwith the data for each row (see \fBEXAMPLES\fP, below). Passing
  635. X\fBundef\fP as one of the data
  636. Xvalues will result in a \fBNULL\fP value being sent to the server for
  637. Xthat column.
  638. X
  639. X\fBVariables:\fP
  640. X
  641. X\fBSybperl\fP defines a number of Read-Only variables, and three
  642. XRead-Write variables. Most of the variables correspond to #define's in
  643. Xthe \fIOpenClient\fP include files (see the Sybase documentation for
  644. Xmore information).
  645. X
  646. XThe \fBSybperl\fP specific variables are:
  647. X
  648. X\fB$ComputeId\fP \- Set by \fB&dbnextrow\fP when it processes a
  649. X\fIcompute row\fP as opposed to a normal results row.
  650. X.br
  651. X\fB$DBstatus\fP \- The status returned by the last call to
  652. X\fBdbnextrow()\fP.
  653. X.br
  654. X\fB$SybperlVer\fP \- The Sybperl release version.
  655. X.br
  656. X\fB$SybPackageBug\fP \- Set to TRUE if \fBSybperl\fP was compiled with
  657. Xthe option to circumvent a bug in \fBPerl's\fP implementation of
  658. Xpackages. This variable is undefined otherwise.
  659. X.br
  660. X\fB$dbNullIsUndef\fP \- This variable controls whether NULL values
  661. Xreturned from a query will be returned as the string '\fINULL\fP' (the
  662. Xdefault) or as the \fBPerl\fP \fIundef\fP value.
  663. X.br
  664. X\fB$dbKeepNumeric\fP \- This variable controls whether numeric
  665. Xdatatypes returned by queries are converted to strings (the default)
  666. Xor left in native format.
  667. X.br
  668. X\fB$dbBin0x\fP \- This variable controls whether variables of type
  669. X\fBSYBBINARY\fP are returned with a leading \fB0x\fP or not (the
  670. Xdefault).
  671. X
  672. XThese last three variables are all boolean.
  673. X
  674. X.SH "UNIMPLEMENTED FEATURES"
  675. X
  676. X\fB&dbfcmd\fP is not implemented, but can be emulated by using
  677. X\fIsprintf\fP as in \fI&dbcmd($dbproc, sprintf("%d", $num_val))\;\fP
  678. X
  679. X.SH EXAMPLES
  680. X
  681. XUsing &dbretdata():
  682. X
  683. X.nf
  684. X    &dbcmd($dbproc, "declare @data int\n");
  685. X    &dbcmd($dbproc, "exec my_stored_proc @data out\n");
  686. X    &dbsqlexec($dbproc);
  687. X    &dbresults($dbproc);
  688. X    while(&dbnextrow($dbproc))
  689. X    {
  690. X        ;    # empty loop...
  691. X    }
  692. X    ($ret) = &dbretdata($dbproc);
  693. X.fi
  694. X
  695. XDoing a Bulk Copy from program variables into a Sybase table:
  696. X
  697. X.nf
  698. X    &BCP_SETL($DBTRUE);
  699. X    $dbproc = &dbopen;
  700. X    &bcp_init($dbproc, "test.dbo.t2", '', 'bcp.err', $DB_IN);
  701. X    &bcp_meminit($dbproc, 3);   # we wish to copy three columns into
  702. X                    # the 't2' table
  703. X    while(<>)
  704. X    {
  705. X        chop;
  706. X        @dat = split(' ', $_);
  707. X        &bcp_sendrow($dbproc, @dat);
  708. X    }
  709. X    $ret = &bcp_done($dbproc);
  710. X.fi
  711. X
  712. X
  713. X
  714. X.SH OPTIONS
  715. X
  716. XSee the \fIPerl(1)\fP manual page.
  717. X
  718. X.SH BUGS
  719. X
  720. XMemory usage can become very large in certain conditions when
  721. Xusing a version of Perl prior to 4.035. This
  722. Xcan be circumvented - see the BUGS file in the Sybperl distribution.
  723. X
  724. XIf \fB&dbnextrow\fP encounters a datatype that it does not know about,
  725. Xit tries to convert it to SYBCHAR, and to store it in a 256 byte
  726. Xbuffer - without checking for overflow.
  727. X
  728. XThe handling of multiple logins isn't really clean. A call to
  729. X\fB&dblogin\fP sets the values for the User name and Password. These
  730. Xvalues are remembered - and used in calls to \fB&dbopen\fP - until
  731. Xthey are changed in a new call to \fB&dblogin()\fP. It is possible to
  732. Xavoid the use of \fB&dbopen\fP alltogether, and simply call
  733. X\fB&dblogin\fP each time a new \fBDBPROCESS\fP is required.
  734. X
  735. XIt is not possible to call \fB&BCP_SETL\fP for the first
  736. X\fBDBPROCESS\fP. You have to call \fB&dblogin\fP, then
  737. X\fB&BCP_SETL\fP, then \fB&dbopen\fP to get a \fBDBPROCESS\fP with
  738. X\fBBCP_IN\fP enabled.
  739. X
  740. X.SH FILES
  741. X
  742. X\fI$PERLLIB/sybperl.pl\fP should be called in all \fBsybperl\fP
  743. Xscripts to set the correct environment variables used by DB-Library.
  744. XA sample \fI$PERLLIB/sybdb.ph\fP is provided with sybperl. You may
  745. Xwant to use \fBh2ph\fP to add definitions to this file.
  746. X
  747. X.SH "SEE ALSO"
  748. X
  749. X\fIPerl(1L), Sybase Open Client DB Library Reference Manual, h2ph(1L).\fP
  750. X
  751. X.SH AUTHOR
  752. X
  753. X.nf
  754. XMichael Peppler, ITF Management SA \- mpeppler@itf.ch
  755. X.fi
  756. XBrent Milnor (brent@oceania.com) contributed &dbwritetext().
  757. XEric Fifer (egf@sbi.com) contributed corrections to the
  758. X&dblogin()/&dbopen() sequence.
  759. XMark Lawrence (mark@drd.com) contributed &dbsafestr().
  760. XMichael Bloom (mb@tti.com) contributed code to handle SYBIMAGE data.
  761. XDon Preuss (donp@niaid.nih.gov) contributed the &dbcolXXX() calls.
  762. XJeffrey Wong (jtw@comdyn.cdsyd.oz.au) contributed the
  763. XOpenClient R4.6.1 DBMONEY routines
  764. X
  765. END_OF_FILE
  766.   if test 10929 -ne `wc -c <'sybperl.1'`; then
  767.     echo shar: \"'sybperl.1'\" unpacked with wrong size!
  768.   fi
  769.   # end of 'sybperl.1'
  770. fi
  771. if test -f 'sybperl.c.B' -a "${1}" != "-c" ; then 
  772.   echo shar: Will not clobber existing file \"'sybperl.c.B'\"
  773. else
  774.   echo shar: Extracting \"'sybperl.c.B'\" \(36266 characters\)
  775.   sed "s/^X//" >'sybperl.c.B' <<'END_OF_FILE'
  776. X      case US_dbmnycmp:
  777. X    if ((items > 3) || (items < 2 ))
  778. X        {
  779. X        fatal("Usage: &dbmnycmp($dbproc, $m1, $m2)");
  780. X        }
  781. X    else
  782. X    {
  783. X        int     retval, off1, off2;
  784. X        DBMONEY m1, m2;
  785. X
  786. X        if(items == 3)
  787. X        {
  788. X        inx  = getDbProc(STACK(sp)[1]);
  789. X        off1 = 2;
  790. X        off2 = 3;
  791. X        }
  792. X        else
  793. X        {
  794. X        inx  = 0;
  795. X        off1 = 1;
  796. X        off2 = 2;
  797. X            }
  798. X
  799. X        if (dbconvert(dbProc[inx].dbproc, SYBCHAR,
  800. X              (char *)str_get(STACK(sp)[off1]), (DBINT)-1,
  801. X              SYBMONEY, (BYTE*)&m1, (DBINT)-1) == -1)
  802. X            {
  803. X           fatal("Invalid dbconvert() for &dbmnycmp $m1 parameter");
  804. X            }
  805. X
  806. X        if (dbconvert(dbProc[inx].dbproc, SYBCHAR,
  807. X              (char *)str_get(STACK(sp)[off2]), (DBINT)-1,
  808. X              SYBMONEY, (BYTE*)&m2, (DBINT)-1) == -1)
  809. X            {
  810. X           fatal("Invalid dbconvert() for &dbmnycmp $m2 parameter");
  811. X            }
  812. X
  813. X        retval = dbmnycmp(dbProc[inx].dbproc, &m1, &m2);
  814. X
  815. X        str_numset(STACK(sp)[0], (double)retval);
  816. X    }
  817. X    break;
  818. X      case US_dbmnydivide:
  819. X    if ((items > 3) || (items < 2 ))
  820. X        {
  821. X        fatal("Usage: @arr = &dbmnydivide($dbproc, $m1, $m2)");
  822. X        }
  823. X    else
  824. X    {
  825. X        int     retval, off1, off2;
  826. X        DBMONEY m1, m2, mresult;
  827. X            DBCHAR  mnybuf[40];
  828. X
  829. X        if(items == 3)
  830. X        {
  831. X        inx  = getDbProc(STACK(sp)[1]);
  832. X        off1 = 2;
  833. X        off2 = 3;
  834. X        }
  835. X        else
  836. X        {
  837. X        inx  = 0;
  838. X        off1 = 1;
  839. X        off2 = 2;
  840. X            }
  841. X
  842. X        if (dbconvert(dbProc[inx].dbproc, SYBCHAR,
  843. X              (char *)str_get(STACK(sp)[off1]), (DBINT)-1,
  844. X              SYBMONEY, (BYTE*)&m1, (DBINT)-1) == -1)
  845. X            {
  846. X           fatal("Invalid dbconvert() for &dbmnydivide $m1 parameter");
  847. X            }
  848. X
  849. X        if (dbconvert(dbProc[inx].dbproc, SYBCHAR,
  850. X              (char *)str_get(STACK(sp)[off2]), (DBINT)-1,
  851. X              SYBMONEY, (BYTE*)&m2, (DBINT)-1) == -1)
  852. X            {
  853. X           fatal("Invalid dbconvert() for &dbmnydivide $m2 parameter");
  854. X            }
  855. X
  856. X        retval = dbmnydivide(dbProc[inx].dbproc, &m1, &m2, &mresult);
  857. X
  858. X            new_mnytochar(dbProc[inx].dbproc, &mresult, mnybuf);
  859. X
  860. X            --sp;  /* readjust to get rid of space preallocation */
  861. X
  862. X            (void)astore(ary,++sp,str_2mortal(str_nmake((double)retval)));
  863. X        (void)astore(ary,++sp,str_2mortal(str_make(mnybuf, 0)));
  864. X    }
  865. X    break;
  866. X      case US_dbmnyminus:
  867. X    if ((items > 2) || (items < 1 ))
  868. X        {
  869. X        fatal("Usage: @arr = &dbmnyminus($dbproc, $m1)");
  870. X        }
  871. X    else
  872. X    {
  873. X        int     retval, off1;
  874. X        DBMONEY m1, mresult;
  875. X            DBCHAR  mnybuf[40];
  876. X
  877. X        if(items == 2)
  878. X        {
  879. X        inx  = getDbProc(STACK(sp)[1]);
  880. X        off1 = 2;
  881. X        }
  882. X        else
  883. X        {
  884. X        inx  = 0;
  885. X        off1 = 1;
  886. X            }
  887. X
  888. X        if (dbconvert(dbProc[inx].dbproc, SYBCHAR,
  889. X              (char *)str_get(STACK(sp)[off1]), (DBINT)-1,
  890. X              SYBMONEY, (BYTE*)&m1, (DBINT)-1) == -1)
  891. X            {
  892. X           fatal("Invalid dbconvert() for &dbmnyminus $m1 parameter");
  893. X            }
  894. X
  895. X        retval = dbmnyminus(dbProc[inx].dbproc, &m1, &mresult);
  896. X
  897. X            new_mnytochar(dbProc[inx].dbproc, &mresult, mnybuf);
  898. X
  899. X            --sp;  /* readjust to get rid of space preallocation */
  900. X
  901. X            (void)astore(ary,++sp,str_2mortal(str_nmake((double)retval)));
  902. X        (void)astore(ary,++sp,str_2mortal(str_make(mnybuf, 0)));
  903. X    }
  904. X    break;
  905. X      case US_dbmnymul:
  906. X    if ((items > 3) || (items < 2 ))
  907. X        {
  908. X        fatal("Usage: @arr = &dbmnymul($dbproc, $m1, $m2)");
  909. X        }
  910. X    else
  911. X    {
  912. X        int     retval, off1, off2;
  913. X        DBMONEY m1, m2, mresult;
  914. X            DBCHAR  mnybuf[40];
  915. X
  916. X        if(items == 3)
  917. X        {
  918. X        inx  = getDbProc(STACK(sp)[1]);
  919. X        off1 = 2;
  920. X        off2 = 3;
  921. X        }
  922. X        else
  923. X        {
  924. X        inx  = 0;
  925. X        off1 = 1;
  926. X        off2 = 2;
  927. X            }
  928. X
  929. X        if (dbconvert(dbProc[inx].dbproc, SYBCHAR,
  930. X              (char *)str_get(STACK(sp)[off1]), (DBINT)-1,
  931. X              SYBMONEY, (BYTE*)&m1, (DBINT)-1) == -1)
  932. X            {
  933. X           fatal("Invalid dbconvert() for &dbmnymul $m1 parameter");
  934. X            }
  935. X
  936. X        if (dbconvert(dbProc[inx].dbproc, SYBCHAR,
  937. X              (char *)str_get(STACK(sp)[off2]), (DBINT)-1,
  938. X              SYBMONEY, (BYTE*)&m2, (DBINT)-1) == -1)
  939. X            {
  940. X           fatal("Invalid dbconvert() for &dbmnymul $m2 parameter");
  941. X            }
  942. X
  943. X        retval = dbmnymul(dbProc[inx].dbproc, &m1, &m2, &mresult);
  944. X
  945. X            new_mnytochar(dbProc[inx].dbproc, &mresult, mnybuf);
  946. X
  947. X            --sp;  /* readjust to get rid of space preallocation */
  948. X
  949. X            (void)astore(ary,++sp,str_2mortal(str_nmake((double)retval)));
  950. X        (void)astore(ary,++sp,str_2mortal(str_make(mnybuf, 0)));
  951. X    }
  952. X    break;
  953. X      case US_dbmnysub:
  954. X    if ((items > 3) || (items < 2 ))
  955. X        {
  956. X        fatal("Usage: @arr = &dbmnysub($dbproc, $m1, $m2)");
  957. X        }
  958. X    else
  959. X    {
  960. X        int     retval, off1, off2;
  961. X        DBMONEY m1, m2, mresult;
  962. X            DBCHAR  mnybuf[40];
  963. X
  964. X        if(items == 3)
  965. X        {
  966. X        inx  = getDbProc(STACK(sp)[1]);
  967. X        off1 = 2;
  968. X        off2 = 3;
  969. X        }
  970. X        else
  971. X        {
  972. X        inx  = 0;
  973. X        off1 = 1;
  974. X        off2 = 2;
  975. X            }
  976. X
  977. X        if (dbconvert(dbProc[inx].dbproc, SYBCHAR,
  978. X              (char *)str_get(STACK(sp)[off1]), (DBINT)-1,
  979. X              SYBMONEY, (BYTE*)&m1, (DBINT)-1) == -1)
  980. X            {
  981. X           fatal("Invalid dbconvert() for &dbmnysub $m1 parameter");
  982. X            }
  983. X
  984. X        if (dbconvert(dbProc[inx].dbproc, SYBCHAR,
  985. X              (char *)str_get(STACK(sp)[off2]), (DBINT)-1,
  986. X              SYBMONEY, (BYTE*)&m2, (DBINT)-1) == -1)
  987. X            {
  988. X           fatal("Invalid dbconvert() for &dbmnysub $m2 parameter");
  989. X            }
  990. X
  991. X        retval = dbmnysub(dbProc[inx].dbproc, &m1, &m2, &mresult);
  992. X
  993. X            new_mnytochar(dbProc[inx].dbproc, &mresult, mnybuf);
  994. X
  995. X            --sp;  /* readjust to get rid of space preallocation */
  996. X
  997. X            (void)astore(ary,++sp,str_2mortal(str_nmake((double)retval)));
  998. X        (void)astore(ary,++sp,str_2mortal(str_make(mnybuf, 0)));
  999. X    }
  1000. X    break;
  1001. X      case US_dbmnyzero:
  1002. X    if (items > 1)
  1003. X        {
  1004. X        fatal("Usage: @arr = &dbmnyzero($dbproc)");
  1005. X        }
  1006. X    else
  1007. X    {
  1008. X        int     retval;
  1009. X        DBMONEY mresult;
  1010. X            DBCHAR  mnybuf[40];
  1011. X
  1012. X        if(items == 1)
  1013. X        {
  1014. X        inx = getDbProc(STACK(sp)[1]);
  1015. X        }
  1016. X        else
  1017. X        {
  1018. X        inx = 0;
  1019. X            }
  1020. X
  1021. X        retval = dbmnyzero(dbProc[inx].dbproc, &mresult);
  1022. X
  1023. X            new_mnytochar(dbProc[inx].dbproc, &mresult, mnybuf);
  1024. X
  1025. X            --sp;  /* readjust to get rid of space preallocation */
  1026. X
  1027. X            (void)astore(ary,++sp,str_2mortal(str_nmake((double)retval)));
  1028. X        (void)astore(ary,++sp,str_2mortal(str_make(mnybuf, 0)));
  1029. X    }
  1030. X    break;
  1031. X      case US_dbmnydec:
  1032. X    if ((items > 2) || (items < 1 ))
  1033. X        {
  1034. X        fatal("Usage: @arr = &dbmnydec($dbproc, $m1)");
  1035. X        }
  1036. X    else
  1037. X    {
  1038. X        int     retval, off1;
  1039. X        DBMONEY mresult;
  1040. X            DBCHAR  mnybuf[40];
  1041. X
  1042. X        if(items == 2)
  1043. X        {
  1044. X        inx  = getDbProc(STACK(sp)[1]);
  1045. X        off1 = 2;
  1046. X        }
  1047. X        else
  1048. X        {
  1049. X        inx  = 0;
  1050. X        off1 = 1;
  1051. X            }
  1052. X
  1053. X        if (dbconvert(dbProc[inx].dbproc, SYBCHAR,
  1054. X              (char *)str_get(STACK(sp)[off1]), (DBINT)-1,
  1055. X              SYBMONEY, (BYTE *)&mresult, (DBINT)-1) == -1)
  1056. X            {
  1057. X           fatal("Invalid dbconvert() for &dbmnydec $m1 parameter");
  1058. X            }
  1059. X
  1060. X        retval = dbmnydec(dbProc[inx].dbproc, &mresult);
  1061. X
  1062. X            new_mnytochar(dbProc[inx].dbproc, &mresult, mnybuf);
  1063. X
  1064. X            --sp;  /* readjust to get rid of space preallocation */
  1065. X
  1066. X            (void)astore(ary,++sp,str_2mortal(str_nmake((double)retval)));
  1067. X        (void)astore(ary,++sp,str_2mortal(str_make(mnybuf, 0)));
  1068. X    }
  1069. X    break;
  1070. X      case US_dbmnydown:
  1071. X    if ((items > 3) || (items < 2 ))
  1072. X        {
  1073. X        fatal("Usage: @arr = &dbmnydown($dbproc, $m1, $i1)");
  1074. X        }
  1075. X    else
  1076. X    {
  1077. X        int     retval, off1, off2;
  1078. X        int   i1, iresult = 0;
  1079. X        DBMONEY mresult;
  1080. X            DBCHAR  mnybuf[40];
  1081. X
  1082. X        if(items == 3)
  1083. X        {
  1084. X        inx  = getDbProc(STACK(sp)[1]);
  1085. X        off1 = 2;
  1086. X        off2 = 3;
  1087. X        }
  1088. X        else
  1089. X        {
  1090. X        inx  = 0;
  1091. X        off1 = 1;
  1092. X        off2 = 2;
  1093. X            }
  1094. X
  1095. X        if (dbconvert(dbProc[inx].dbproc, SYBCHAR,
  1096. X              (char *)str_get(STACK(sp)[off1]), (DBINT)-1,
  1097. X              SYBMONEY, (BYTE*)&mresult, (DBINT)-1) == -1)
  1098. X            {
  1099. X           fatal("Invalid dbconvert() for &dbmnydown $m1 parameter");
  1100. X            }
  1101. X
  1102. X        if (dbconvert(dbProc[inx].dbproc, SYBCHAR,
  1103. X              (char *)str_get(STACK(sp)[off2]), (DBINT)-1,
  1104. X              SYBINT4, (BYTE*)&i1, (DBINT)-1) == -1)
  1105. X            {
  1106. X           fatal("Invalid dbconvert() for &dbmnydown $i1 parameter");
  1107. X            }
  1108. X
  1109. X        retval = dbmnydown(dbProc[inx].dbproc, &mresult, i1, &iresult);
  1110. X
  1111. X            new_mnytochar(dbProc[inx].dbproc, &mresult, mnybuf);
  1112. X
  1113. X            --sp;  /* readjust to get rid of space preallocation */
  1114. X
  1115. X            (void)astore(ary,++sp,str_2mortal(str_nmake((double)retval)));
  1116. X        (void)astore(ary,++sp,str_2mortal(str_make(mnybuf, 0)));
  1117. X            (void)astore(ary,++sp,str_2mortal(str_nmake((double)iresult)));
  1118. X    }
  1119. X    break;
  1120. X      case US_dbmnyinc:
  1121. X    if ((items > 2) || (items < 1 ))
  1122. X        {
  1123. X        fatal("Usage: @arr = &dbmnyinc($dbproc, $m1)");
  1124. X        }
  1125. X    else
  1126. X    {
  1127. X        int     retval, off1;
  1128. X        DBMONEY mresult;
  1129. X            DBCHAR  mnybuf[40];
  1130. X
  1131. X        if(items == 2)
  1132. X        {
  1133. X        inx  = getDbProc(STACK(sp)[1]);
  1134. X        off1 = 2;
  1135. X        }
  1136. X        else
  1137. X        {
  1138. X        inx  = 0;
  1139. X        off1 = 1;
  1140. X            }
  1141. X
  1142. X        if (dbconvert(dbProc[inx].dbproc, SYBCHAR,
  1143. X              (char *)str_get(STACK(sp)[off1]), (DBINT)-1,
  1144. X              SYBMONEY, (BYTE*)&mresult, (DBINT)-1) == -1)
  1145. X            {
  1146. X           fatal("Invalid dbconvert() for &dbmnyinc $m1 parameter");
  1147. X            }
  1148. X
  1149. X        retval = dbmnyinc(dbProc[inx].dbproc, &mresult);
  1150. X
  1151. X            new_mnytochar(dbProc[inx].dbproc, &mresult, mnybuf);
  1152. X
  1153. X            --sp;  /* readjust to get rid of space preallocation */
  1154. X
  1155. X            (void)astore(ary,++sp,str_2mortal(str_nmake((double)retval)));
  1156. X        (void)astore(ary,++sp,str_2mortal(str_make(mnybuf, 0)));
  1157. X    }
  1158. X    break;
  1159. X      case US_dbmnyinit:
  1160. X    if ((items > 3) || (items < 2 ))
  1161. X        {
  1162. X        fatal("Usage: @arr = &dbmnyinit($dbproc, $m1, $i1)");
  1163. X        }
  1164. X    else
  1165. X    {
  1166. X        int     retval, off1, off2;
  1167. X        DBINT   i1, iresult;
  1168. X        DBMONEY mresult;
  1169. X        DBBOOL  bresult = (DBBOOL)FALSE;
  1170. X            DBCHAR  mnybuf[40];
  1171. X
  1172. X        if(items == 3)
  1173. X        {
  1174. X        inx  = getDbProc(STACK(sp)[1]);
  1175. X        off1 = 2;
  1176. X        off2 = 3;
  1177. X        }
  1178. X        else
  1179. X        {
  1180. X        inx  = 0;
  1181. X        off1 = 1;
  1182. X        off2 = 2;
  1183. X            }
  1184. X
  1185. X        if (dbconvert(dbProc[inx].dbproc, SYBCHAR,
  1186. X              (char *)str_get(STACK(sp)[off1]), (DBINT)-1,
  1187. X              SYBMONEY, (BYTE*)&mresult, (DBINT)-1) == -1)
  1188. X            {
  1189. X           fatal("Invalid dbconvert() for &dbmnyinit $m1 parameter");
  1190. X            }
  1191. X
  1192. X        if (dbconvert(dbProc[inx].dbproc, SYBCHAR,
  1193. X              (char *)str_get(STACK(sp)[off2]), (DBINT)-1,
  1194. X              SYBINT4, (BYTE*)&i1, (DBINT)-1) == -1)
  1195. X            {
  1196. X           fatal("Invalid dbconvert() for &dbmnyinit $i1 parameter");
  1197. X            }
  1198. X
  1199. X        retval = dbmnyinit(dbProc[inx].dbproc, &mresult, i1, &bresult);
  1200. X
  1201. X            new_mnytochar(dbProc[inx].dbproc, &mresult, mnybuf);
  1202. X
  1203. X        iresult = (DBINT)bresult;
  1204. X
  1205. X            --sp;  /* readjust to get rid of space preallocation */
  1206. X
  1207. X            (void)astore(ary,++sp,str_2mortal(str_nmake((double)retval)));
  1208. X        (void)astore(ary,++sp,str_2mortal(str_make(mnybuf, 0)));
  1209. X            (void)astore(ary,++sp,str_2mortal(str_nmake((double)iresult)));
  1210. X    }
  1211. X    break;
  1212. X      case US_dbmnymaxneg:
  1213. X    if (items > 1)
  1214. X        {
  1215. X        fatal("Usage: @arr = &dbmnymaxneg($dbproc)");
  1216. X        }
  1217. X    else
  1218. X    {
  1219. X        int     retval;
  1220. X        DBMONEY mresult;
  1221. X            DBCHAR  mnybuf[40];
  1222. X
  1223. X        if(items == 1)
  1224. X        {
  1225. X        inx = getDbProc(STACK(sp)[1]);
  1226. X        }
  1227. X        else
  1228. X        {
  1229. X        inx = 0;
  1230. X            }
  1231. X
  1232. X        retval = dbmnymaxneg(dbProc[inx].dbproc, &mresult);
  1233. X
  1234. X            new_mnytochar(dbProc[inx].dbproc, &mresult, mnybuf);
  1235. X
  1236. X            --sp;  /* readjust to get rid of space preallocation */
  1237. X
  1238. X            (void)astore(ary,++sp,str_2mortal(str_nmake((double)retval)));
  1239. X        (void)astore(ary,++sp,str_2mortal(str_make(mnybuf, 0)));
  1240. X    }
  1241. X    break;
  1242. X      case US_dbmnymaxpos:
  1243. X    if (items > 1)
  1244. X        {
  1245. X        fatal("Usage: @arr = &dbmnymaxpos($dbproc)");
  1246. X        }
  1247. X    else
  1248. X    {
  1249. X        int     retval;
  1250. X        DBMONEY mresult;
  1251. X            DBCHAR  mnybuf[40];
  1252. X
  1253. X        if(items == 1)
  1254. X        {
  1255. X        inx = getDbProc(STACK(sp)[1]);
  1256. X        }
  1257. X        else
  1258. X        {
  1259. X        inx = 0;
  1260. X            }
  1261. X
  1262. X        retval = dbmnymaxpos(dbProc[inx].dbproc, &mresult);
  1263. X
  1264. X            new_mnytochar(dbProc[inx].dbproc, &mresult, mnybuf);
  1265. X
  1266. X            --sp;  /* readjust to get rid of space preallocation */
  1267. X
  1268. X            (void)astore(ary,++sp,str_2mortal(str_nmake((double)retval)));
  1269. X        (void)astore(ary,++sp,str_2mortal(str_make(mnybuf, 0)));
  1270. X    }
  1271. X    break;
  1272. X      case US_dbmnyndigit:
  1273. X    if ((items > 2) || (items < 1 ))
  1274. X        {
  1275. X        fatal("Usage: @arr = &dbmnyndigit($dbproc, $m1)");
  1276. X        }
  1277. X    else
  1278. X    {
  1279. X        int     retval, off1;
  1280. X        DBMONEY mresult;
  1281. X        DBINT   iresult;
  1282. X        DBBOOL  bresult = (DBBOOL)FALSE;
  1283. X            DBCHAR  mnybuf[40], dgtbuf[ 10 ];
  1284. X
  1285. X        if(items == 2)
  1286. X        {
  1287. X        inx  = getDbProc(STACK(sp)[1]);
  1288. X        off1 = 2;
  1289. X        }
  1290. X        else
  1291. X        {
  1292. X        inx  = 0;
  1293. X        off1 = 1;
  1294. X            }
  1295. X
  1296. X        if (dbconvert(dbProc[inx].dbproc, SYBCHAR,
  1297. X              (char *)str_get(STACK(sp)[off1]), (DBINT)-1,
  1298. X              SYBMONEY, (BYTE*)&mresult, (DBINT)-1) == -1)
  1299. X            {
  1300. X           fatal("Invalid dbconvert() for &dbmnyndigit $m1 parameter");
  1301. X            }
  1302. X
  1303. X        retval = dbmnyndigit(dbProc[inx].dbproc, &mresult, dgtbuf, &bresult);
  1304. X
  1305. X            new_mnytochar(dbProc[inx].dbproc, &mresult, mnybuf);
  1306. X
  1307. X        iresult = (DBINT)bresult;
  1308. X
  1309. X            --sp;  /* readjust to get rid of space preallocation */
  1310. X
  1311. X            (void)astore(ary,++sp,str_2mortal(str_nmake((double)retval)));
  1312. X        (void)astore(ary,++sp,str_2mortal(str_make(mnybuf, 0)));
  1313. X        (void)astore(ary,++sp,str_2mortal(str_make(dgtbuf, 0)));
  1314. X            (void)astore(ary,++sp,str_2mortal(str_nmake((double)iresult)));
  1315. X    }
  1316. X    break;
  1317. X      case US_dbmnyscale:
  1318. X    if ((items > 4) || (items < 3 ))
  1319. X        {
  1320. X        fatal("Usage: @arr = &dbmnyscale($dbproc, $m1, $i1, $i2)");
  1321. X        }
  1322. X    else
  1323. X    {
  1324. X        int     retval, off1, off2, off3;
  1325. X        DBINT   i1, i2;
  1326. X        DBMONEY mresult;
  1327. X            DBCHAR  mnybuf[40];
  1328. X
  1329. X        if(items == 4)
  1330. X        {
  1331. X        inx  = getDbProc(STACK(sp)[1]);
  1332. X        off1 = 2;
  1333. X        off2 = 3;
  1334. X        off3 = 4;
  1335. X        }
  1336. X        else
  1337. X        {
  1338. X        inx  = 0;
  1339. X        off1 = 1;
  1340. X        off2 = 2;
  1341. X        off3 = 3;
  1342. X            }
  1343. X
  1344. X        if (dbconvert(dbProc[inx].dbproc, SYBCHAR,
  1345. X              (char *)str_get(STACK(sp)[off1]), (DBINT)-1,
  1346. X              SYBMONEY, (BYTE*)&mresult, (DBINT)-1) == -1)
  1347. X            {
  1348. X           fatal("Invalid dbconvert() for &dbmnyscale $m1 parameter");
  1349. X            }
  1350. X
  1351. X        if (dbconvert(dbProc[inx].dbproc, SYBCHAR,
  1352. X              (char *)str_get(STACK(sp)[off2]), (DBINT)-1,
  1353. X              SYBINT4, (BYTE*)&i1, (DBINT)-1) == -1)
  1354. X            {
  1355. X           fatal("Invalid dbconvert() for &dbmnyscale $i1 parameter");
  1356. X            }
  1357. X
  1358. X        if (dbconvert(dbProc[inx].dbproc, SYBCHAR,
  1359. X              (char *)str_get(STACK(sp)[off3]), (DBINT)-1,
  1360. X              SYBINT4, (BYTE*)&i2, (DBINT)-1) == -1)
  1361. X            {
  1362. X           fatal("Invalid dbconvert() for &dbmnyscale $i2 parameter");
  1363. X            }
  1364. X
  1365. X        retval = dbmnyscale(dbProc[inx].dbproc, &mresult, i1, i2);
  1366. X
  1367. X            new_mnytochar(dbProc[inx].dbproc, &mresult, mnybuf);
  1368. X
  1369. X            --sp;  /* readjust to get rid of space preallocation */
  1370. X
  1371. X            (void)astore(ary,++sp,str_2mortal(str_nmake((double)retval)));
  1372. X        (void)astore(ary,++sp,str_2mortal(str_make(mnybuf, 0)));
  1373. X    }
  1374. X    break;
  1375. X#endif
  1376. X      case US_dbwritetext:
  1377. X        if (items != 5)
  1378. X            fatal ("Usage: dbwritetext($dbproc1,$column,$dbproc2,$col,$text");
  1379. X    else
  1380. X    {
  1381. X        int inx2, wcolnum;
  1382. X        char *wcolname, *wtext;
  1383. X        int ret;
  1384. X        
  1385. X        inx = getDbProc(STACK(sp)[1]);
  1386. X        wcolname = str_get(STACK(sp)[2]);
  1387. X        inx2 = getDbProc(STACK(sp)[3]);
  1388. X        wcolnum = (int)str_gnum(STACK(sp)[4]);
  1389. X        wtext = str_get(STACK(sp)[5]);
  1390. X        ret = dbwritetext (dbProc[inx].dbproc, wcolname, dbtxptr(dbProc[inx2].dbproc, wcolnum),
  1391. X                   DBTXPLEN, dbtxtimestamp(dbProc[inx2].dbproc, wcolnum), 0,
  1392. X                   strlen(wtext), wtext);
  1393. X        str_numset(STACK(sp)[0], (double) ret);
  1394. X    }
  1395. X        break;
  1396. X      case US_dbnumcols:
  1397. X    if (items > 1)
  1398. X        fatal("Usage: $dbnumcols = &dbnumcols($dbproc);");
  1399. X    else
  1400. X    {
  1401. X        int j;
  1402. X
  1403. X        if(items)
  1404. X        inx = getDbProc(STACK(sp)[1]);
  1405. X        else
  1406. X        inx = 0;
  1407. X        
  1408. X        j = dbnumcols(dbProc[inx].dbproc);
  1409. X        str_numset(STACK(sp)[0], (double) j);
  1410. X    }
  1411. X    break;
  1412. X      case US_dbcoltype:
  1413. X    if (items > 2 || items < 1)
  1414. X        fatal("Usage: $dbcoltype = &dbcoltype($dbproc, columnid);");
  1415. X    else
  1416. X    {
  1417. X        int j, off;
  1418. X        
  1419. X        if(items)
  1420. X        {
  1421. X        inx = getDbProc(STACK(sp)[1]);
  1422. X        off = 2;
  1423. X        }
  1424. X        else
  1425. X        inx = 0, off = 1;
  1426. X        
  1427. X        
  1428. X        j = dbcoltype(dbProc[inx].dbproc, (int)str_gnum(STACK(sp)[off]));
  1429. X        str_numset(STACK(sp)[0], (double) j);
  1430. X    }
  1431. X    break;
  1432. X      case US_dbcolname:
  1433. X    if (items > 2 || items < 1)
  1434. X        fatal("Usage: $dbcolname = &dbcolname($dbproc, columnid);");
  1435. X    else
  1436. X    {
  1437. X        int j, off;
  1438. X        char *colname;
  1439. X        
  1440. X        if(items)
  1441. X        {
  1442. X        inx = getDbProc(STACK(sp)[1]);
  1443. X        off = 2;
  1444. X        }
  1445. X        else
  1446. X        inx = 0, off = 1;
  1447. X        
  1448. X        
  1449. X        colname = dbcolname(dbProc[inx].dbproc, (int)str_gnum(STACK(sp)[off]));
  1450. X        str_set (STACK (sp)[0], colname);
  1451. X    }
  1452. X    break;
  1453. X      case US_dbcollen:
  1454. X    if (items > 2)
  1455. X        fatal("Usage: $dbcollen = &dbcollen($dbproc, columnid);");
  1456. X    else
  1457. X    {
  1458. X        int j, off;
  1459. X        
  1460. X        if(items)
  1461. X        {
  1462. X        inx = getDbProc(STACK(sp)[1]);
  1463. X        off = 2;
  1464. X        }
  1465. X        else
  1466. X        inx = 0, off = 1;
  1467. X        
  1468. X        
  1469. X        j = dbcollen(dbProc[inx].dbproc, (int)str_gnum(STACK(sp)[off]));
  1470. X        str_numset(STACK(sp)[0], (double) j);
  1471. X    }
  1472. X    break;
  1473. X      case US_dbrecftos:
  1474. X    if (items != 1)
  1475. X        fatal("Usage: &dbrecftos($filename);");
  1476. X    else
  1477. X    {
  1478. X        dbrecftos((char *)str_get(STACK(sp)[1]));
  1479. X        
  1480. X        str_numset(STACK(sp)[0], (double) 0);
  1481. X    }
  1482. X    break;
  1483. X
  1484. X      case US_BCP_SETL:
  1485. X    if (items != 1)
  1486. X        fatal("Usage: &BCP_SETL($state);");
  1487. X    else
  1488. X    {
  1489. X        BCP_SETL(login, (int)str_gnum(STACK(sp)[1]));
  1490. X        str_numset(STACK(sp)[0], (double) 0);
  1491. X    }
  1492. X    break;
  1493. X
  1494. X      case US_bcp_getl:
  1495. X    if (items)
  1496. X        fatal("Usage: $state = &bcp_getl();");
  1497. X    else
  1498. X    {
  1499. X        int ret;
  1500. X        ret = bcp_getl(login);
  1501. X        str_numset(STACK(sp)[0], (double) ret);
  1502. X    }
  1503. X    break;
  1504. X
  1505. X      case US_bcp_init:
  1506. X    if (items < 4 || items > 5)
  1507. X        fatal("Usage: &bcp_init($dbproc, $tblname, $hfile, $errfile, $dir);");
  1508. X    else
  1509. X    {
  1510. X        int j, off;
  1511. X        char *hfile;
  1512. X        
  1513. X        if(items == 5)
  1514. X        {
  1515. X        inx = getDbProc(STACK(sp)[1]);
  1516. X        off = 2;
  1517. X        }
  1518. X        else
  1519. X        inx = 0, off = 1;
  1520. X
  1521. X        hfile = str_get(STACK(sp)[off+1]);
  1522. X        if((Str = STACK(sp)[off+1]) == &str_undef ||
  1523. X           ((hfile = str_get(Str)) && strlen(hfile) == 0))
  1524. X        hfile = NULL;
  1525. X        j = bcp_init(dbProc[inx].dbproc, str_get(STACK(sp)[off]),
  1526. X             hfile,
  1527. X             str_get(STACK(sp)[off+2]),
  1528. X             (int)str_gnum(STACK(sp)[off+3]));
  1529. X        str_numset(STACK(sp)[0], (double) j);
  1530. X    }
  1531. X    break;
  1532. X
  1533. X      case US_bcp_meminit:
  1534. X    if (items < 1 || items > 2)
  1535. X        fatal("Usage: &bcp_meminit($dbproc, $num_cols);");
  1536. X    else
  1537. X    {
  1538. X        int j, off, numcols;
  1539. X        BYTE dummy;
  1540. X        
  1541. X        if(items == 2)
  1542. X        {
  1543. X        inx = getDbProc(STACK(sp)[1]);
  1544. X        off = 2;
  1545. X        }
  1546. X        else
  1547. X        inx = 0, off = 1;
  1548. X        numcols = str_gnum(STACK(sp)[off]);
  1549. X        for(j = 1; j <= numcols; ++j)
  1550. X        bcp_bind(dbProc[inx].dbproc, &dummy, 0, -1, "", 1, SYBCHAR, j);
  1551. X
  1552. X        if(dbProc[inx].colPtr) /* avoid a potential memory leak */
  1553. X        Safefree(dbProc[inx].colPtr);
  1554. X        New (902, dbProc[inx].colPtr, numcols, BYTE *);
  1555. X        
  1556. X        str_numset(STACK(sp)[0], (double) j);
  1557. X    }
  1558. X    break;
  1559. X    
  1560. X      case US_bcp_sendrow:    /* WARNING: the dbproc param is NOT */
  1561. X                /* optional for this call!!! */
  1562. X    if (items < 2)
  1563. X        fatal("Usage: &bcp_sendrow($dbproc, LIST);");
  1564. X    else
  1565. X    {
  1566. X        int j, off;
  1567. X
  1568. X        inx = getDbProc(STACK(sp)[1]);
  1569. X        for(j = 1; j < items; ++j)
  1570. X        {
  1571. X        Str = STACK(sp)[j+1];
  1572. X        if(Str == &str_undef) /* it's a NULL data value */
  1573. X            bcp_collen(dbProc[inx].dbproc, 0, j);
  1574. X        else
  1575. X            bcp_collen(dbProc[inx].dbproc, -1, j);
  1576. X        dbProc[inx].colPtr[j] = (BYTE *)str_get(Str);
  1577. X        bcp_colptr(dbProc[inx].dbproc, dbProc[inx].colPtr[j], j);
  1578. X        }
  1579. X        j = bcp_sendrow(dbProc[inx].dbproc);
  1580. X        str_numset(STACK(sp)[0], (double) j);
  1581. X    }
  1582. X    break;
  1583. X    
  1584. X      case US_bcp_batch:
  1585. X    if (items > 1)
  1586. X        fatal("Usage: $ret = &bcp_batch($dbproc);");
  1587. X    else
  1588. X    {
  1589. X        int j;
  1590. X        
  1591. X        if(items)
  1592. X        inx = getDbProc(STACK(sp)[1]);
  1593. X        else
  1594. X        inx = 0;
  1595. X        
  1596. X        j = bcp_batch(dbProc[inx].dbproc);
  1597. X        str_numset(STACK(sp)[0], (double) j);
  1598. X    }
  1599. X    break;
  1600. X        
  1601. X      case US_bcp_done:
  1602. X    if (items > 1)
  1603. X        fatal("Usage: $ret = &bcp_done($dbproc);");
  1604. X    else
  1605. X    {
  1606. X        int j;
  1607. X        
  1608. X        if(items)
  1609. X        inx = getDbProc(STACK(sp)[1]);
  1610. X        else
  1611. X        inx = 0;
  1612. X        if(dbProc[inx].colPtr)
  1613. X        {
  1614. X        Safefree(dbProc[inx].colPtr);
  1615. X        dbProc[inx].colPtr = NULL;
  1616. X        }
  1617. X        j = bcp_done(dbProc[inx].dbproc);
  1618. X        str_numset(STACK(sp)[0], (double) j);
  1619. X    }
  1620. X    break;
  1621. X
  1622. X      case US_bcp_control:
  1623. X    if (items < 2 || items > 3)
  1624. X        fatal("Usage: $ret = &bcp_control($dbproc, $field, $value);");
  1625. X    else
  1626. X    {
  1627. X        int j, off;
  1628. X
  1629. X        if(items == 3)
  1630. X        {
  1631. X        inx = getDbProc(STACK(sp)[1]);
  1632. X        off = 2;
  1633. X        }
  1634. X        else
  1635. X        inx = 0, off = 1;
  1636. X        j = bcp_control(dbProc[inx].dbproc, (int)str_gnum(STACK(sp)[off]),
  1637. X                (int)str_gnum(STACK(sp)[off+1]));
  1638. X        str_numset(STACK(sp)[0], (double) j);
  1639. X    }
  1640. X    break;
  1641. X        
  1642. X      case US_bcp_columns:
  1643. X    if (items < 1 || items > 2)
  1644. X        fatal("Usage: $ret = &bcp_columns($dbproc, $host_colcount);");
  1645. X    else
  1646. X    {
  1647. X        int j, off;
  1648. X
  1649. X        if(items == 2)
  1650. X        {
  1651. X        inx = getDbProc(STACK(sp)[1]);
  1652. X        off = 2;
  1653. X        }
  1654. X        else
  1655. X        inx = 0, off = 1;
  1656. X        j = bcp_columns(dbProc[inx].dbproc, (int)str_gnum(STACK(sp)[off]));
  1657. X        str_numset(STACK(sp)[0], (double) j);
  1658. X    }
  1659. X    break;
  1660. X        
  1661. X      case US_bcp_colfmt:
  1662. X    if (items < 7 || items > 8)
  1663. X        fatal("Usage: $ret = &bcp_colfmt($dbproc, $host_colnum, $host_type, $host_prefixlen, $host_collen, $host_term, $host_termlen, $table_colnum);");
  1664. X    else
  1665. X    {
  1666. X        int j, off;
  1667. X        char *host_term;
  1668. X
  1669. X        if(items == 8)
  1670. X        {
  1671. X        inx = getDbProc(STACK(sp)[1]);
  1672. X        off = 2;
  1673. X        }
  1674. X        else
  1675. X        inx = 0, off = 1;
  1676. X
  1677. X        if(STACK(sp)[off+4] == &str_undef)
  1678. X        host_term = NULL;
  1679. X        else
  1680. X        host_term = str_get(STACK(sp)[off+4]);
  1681. X        
  1682. X        j = bcp_colfmt(dbProc[inx].dbproc, (int)str_gnum(STACK(sp)[off]),
  1683. X               (int)str_gnum(STACK(sp)[off+1]),
  1684. X               (int)str_gnum(STACK(sp)[off+2]),
  1685. X               (int)str_gnum(STACK(sp)[off+3]),
  1686. X               host_term,
  1687. X               (int)str_gnum(STACK(sp)[off+5]),
  1688. X               (int)str_gnum(STACK(sp)[off+6]));
  1689. X        str_numset(STACK(sp)[0], (double) j);
  1690. X    }
  1691. X    break;
  1692. X        
  1693. X      case US_bcp_collen:
  1694. X    if (items < 2 || items > 3)
  1695. X        fatal("Usage: $ret = &bcp_collen($dbproc, $varlen, $table_column);");
  1696. X    else
  1697. X    {
  1698. X        int j, off;
  1699. X
  1700. X        if(items == 3)
  1701. X        {
  1702. X        inx = getDbProc(STACK(sp)[1]);
  1703. X        off = 2;
  1704. X        }
  1705. X        else
  1706. X        inx = 0, off = 1;
  1707. X        j = bcp_collen(dbProc[inx].dbproc, (int)str_gnum(STACK(sp)[off]),
  1708. X               (int)str_gnum(STACK(sp)[off+1]));
  1709. X        str_numset(STACK(sp)[0], (double) j);
  1710. X    }
  1711. X    break;
  1712. X    
  1713. X      case US_bcp_exec:
  1714. X    if (items > 1)
  1715. X        fatal("Usage: ($ret, $rows_copied) = &bcp_exec($dbproc);");
  1716. X    else
  1717. X    {
  1718. X        int j;
  1719. X        DBINT rows;
  1720. X
  1721. X        if(items == 1)
  1722. X        inx = getDbProc(STACK(sp)[1]);
  1723. X        else
  1724. X        inx = 0;
  1725. X        j = bcp_exec(dbProc[inx].dbproc, &rows);
  1726. X        
  1727. X            --sp;  /* readjust to get rid of space preallocation */
  1728. X
  1729. X            (void)astore(ary,++sp,str_2mortal(str_nmake((double)j)));
  1730. X        (void)astore(ary,++sp,str_2mortal(str_nmake((double)rows)));
  1731. X    }
  1732. X    break;
  1733. X        
  1734. X      case US_bcp_readfmt:
  1735. X    if (items < 1 || items > 2)
  1736. X        fatal("Usage: $ret = &bcp_readfmt($dbproc, $filename);");
  1737. X    else
  1738. X    {
  1739. X        int j, off;
  1740. X
  1741. X        if(items == 2)
  1742. X        {
  1743. X        inx = getDbProc(STACK(sp)[1]);
  1744. X        off = 2;
  1745. X        }
  1746. X        else
  1747. X        inx = 0, off = 1;
  1748. X        j = bcp_readfmt(dbProc[inx].dbproc, str_get(STACK(sp)[off]));
  1749. X        str_numset(STACK(sp)[0], (double) j);
  1750. X    }
  1751. X    break;
  1752. X    
  1753. X      case US_bcp_writefmt:
  1754. X    if (items < 1 || items > 2)
  1755. X        fatal("Usage: $ret = &bcp_writefmt($dbproc, $filename);");
  1756. X    else
  1757. X    {
  1758. X        int j, off;
  1759. X
  1760. X        if(items == 2)
  1761. X        {
  1762. X        inx = getDbProc(STACK(sp)[1]);
  1763. X        off = 2;
  1764. X        }
  1765. X        else
  1766. X        inx = 0, off = 1;
  1767. X        j = bcp_writefmt(dbProc[inx].dbproc, str_get(STACK(sp)[off]));
  1768. X        str_numset(STACK(sp)[0], (double) j);
  1769. X    }
  1770. X    break;
  1771. X    
  1772. X      default:
  1773. X    fatal("Unimplemented user-defined subroutine");
  1774. X    }
  1775. X    return sp;
  1776. X}
  1777. X
  1778. X/* 
  1779. X * Return the value of a userdefined variable. These variables are nearly all
  1780. X * READ-ONLY.
  1781. X */
  1782. Xstatic int
  1783. Xuserval(ix, str)
  1784. Xint ix;
  1785. XSTR *str;
  1786. X{
  1787. X    char buff[24];
  1788. X    
  1789. X    switch (ix)
  1790. X    {
  1791. X      case UV_SUCCEED:
  1792. X    str_numset(str, (double)SUCCEED);
  1793. X    break;
  1794. X      case UV_FAIL:
  1795. X    str_numset(str, (double)FAIL);
  1796. X    break;
  1797. X      case UV_NO_MORE_ROWS:
  1798. X    str_numset(str, (double)NO_MORE_ROWS);
  1799. X    break;
  1800. X      case UV_NO_MORE_RESULTS:
  1801. X    str_numset(str, (double)NO_MORE_RESULTS);
  1802. X    break;
  1803. X      case UV_ComputeId:
  1804. X    str_numset(str, (double)ComputeId);
  1805. X    break;
  1806. X      case UV_SybperlVer:
  1807. X    sprintf(buff, "%d.%3.3d", VERSION, PATCHLEVEL);
  1808. X    str_set(str, buff);
  1809. X    break;
  1810. X      case UV_DBstatus:
  1811. X    str_numset(str, (double)DBstatus);
  1812. X    break;
  1813. X#if defined(DBLIB461)
  1814. X      case UV_STDEXIT:
  1815. X    str_numset(str, (double)STDEXIT);
  1816. X    break;
  1817. X      case UV_ERREXIT:
  1818. X    str_numset(str, (double)ERREXIT);
  1819. X    break;
  1820. X      case UV_INT_EXIT:
  1821. X    str_numset(str, (double)INT_EXIT);
  1822. X    break;
  1823. X      case UV_INT_CONTINUE:
  1824. X    str_numset(str, (double)INT_CONTINUE);
  1825. X    break;
  1826. X      case UV_INT_CANCEL:
  1827. X    str_numset(str, (double)INT_CANCEL);
  1828. X    break;
  1829. X      case UV_INT_TIMEOUT:
  1830. X    str_numset(str, (double)INT_TIMEOUT);
  1831. X    break;
  1832. X      case UV_MORE_ROWS:
  1833. X    str_numset(str, (double)MORE_ROWS);
  1834. X    break;
  1835. X      case UV_REG_ROW:
  1836. X    str_numset(str, (double)REG_ROW);
  1837. X    break;
  1838. X      case UV_BUF_FULL:
  1839. X    str_numset(str, (double)BUF_FULL);
  1840. X    break;
  1841. X      case UV_NO_MORE_PARAMS:
  1842. X    str_numset(str, (double)NO_MORE_PARAMS);
  1843. X    break;
  1844. X      case UV_DBSAVE:
  1845. X    str_numset(str, (double)DBSAVE);
  1846. X    break;
  1847. X      case UV_DBNOSAVE:
  1848. X    str_numset(str, (double)DBNOSAVE);
  1849. X    break;
  1850. X      case UV_DBNOERR:
  1851. X    str_numset(str, (double)DBNOERR);
  1852. X    break;
  1853. X      case UV_DB_PASSTHRU_MORE:
  1854. X    str_numset(str, (double)DB_PASSTHRU_MORE);
  1855. X    break;
  1856. X      case UV_DB_PASSTHRU_EOM:
  1857. X    str_numset(str, (double)DB_PASSTHRU_EOM);
  1858. X    break;
  1859. X      case UV_DBNOPROC:
  1860. X    str_numset(str, (double)DBNOPROC);
  1861. X    break;
  1862. X      case UV_EXCEPTION:
  1863. X    str_numset(str, (double)EXCEPTION);
  1864. X    break;
  1865. X      case UV_EXSIGNAL:
  1866. X    str_numset(str, (double)EXSIGNAL);
  1867. X    break;
  1868. X      case UV_EXSCREENIO:
  1869. X    str_numset(str, (double)EXSCREENIO);
  1870. X    break;
  1871. X      case UV_EXDBLIB:
  1872. X    str_numset(str, (double)EXDBLIB);
  1873. X    break;
  1874. X      case UV_EXFORMS:
  1875. X    str_numset(str, (double)EXFORMS);
  1876. X    break;
  1877. X      case UV_EXCLIPBOARD:
  1878. X    str_numset(str, (double)EXCLIPBOARD);
  1879. X    break;
  1880. X      case UV_EXLOOKUP:
  1881. X    str_numset(str, (double)EXLOOKUP);
  1882. X    break;
  1883. X      case UV_EXINFO:
  1884. X    str_numset(str, (double)EXINFO);
  1885. X    break;
  1886. X      case UV_EXUSER:
  1887. X    str_numset(str, (double)EXUSER);
  1888. X    break;
  1889. X      case UV_EXNONFATAL:
  1890. X    str_numset(str, (double)EXNONFATAL);
  1891. X    break;
  1892. X      case UV_EXCONVERSION:
  1893. X    str_numset(str, (double)EXCONVERSION);
  1894. X    break;
  1895. X      case UV_EXSERVER:
  1896. X    str_numset(str, (double)EXSERVER);
  1897. X    break;
  1898. X      case UV_EXTIME:
  1899. X    str_numset(str, (double)EXTIME);
  1900. X    break;
  1901. X      case UV_EXPROGRAM:
  1902. X    str_numset(str, (double)EXPROGRAM);
  1903. X    break;
  1904. X      case UV_EXRESOURCE:
  1905. X    str_numset(str, (double)EXRESOURCE);
  1906. X    break;
  1907. X      case UV_EXCOMM:
  1908. X    str_numset(str, (double)EXCOMM);
  1909. X    break;
  1910. X      case UV_EXFATAL:
  1911. X    str_numset(str, (double)EXFATAL);
  1912. X    break;
  1913. X      case UV_EXCONSISTENCY:
  1914. X    str_numset(str, (double)EXCONSISTENCY);
  1915. X    break;
  1916. X#endif
  1917. X      case UV_DB_IN:
  1918. X    str_numset(str, (double)DB_IN);
  1919. X    break;
  1920. X      case UV_DB_OUT:
  1921. X    str_numset(str, (double)DB_OUT);
  1922. X    break;
  1923. X      case UV_BCPMAXERRS:
  1924. X    str_numset(str, (double)BCPMAXERRS);
  1925. X    break;
  1926. X      case UV_BCPFIRST:
  1927. X    str_numset(str, (double)BCPFIRST);
  1928. X    break;
  1929. X      case UV_BCPLAST:
  1930. X    str_numset(str, (double)BCPLAST);
  1931. X    break;
  1932. X      case UV_BCPBATCH:
  1933. X    str_numset(str, (double)BCPBATCH);
  1934. X    break;
  1935. X      case UV_DBTRUE:
  1936. X    str_numset(str, (double)TRUE);
  1937. X    break;
  1938. X      case UV_DBFALSE:
  1939. X    str_numset(str, (double)FALSE);
  1940. X    break;
  1941. X#if defined(PACKAGE_BUG)
  1942. X      case UV_PACKAGE_BUG:
  1943. X    str_numset(str, 1.0);
  1944. X    break;
  1945. X#endif
  1946. X      case UV_dbNullIsUndef:
  1947. X    str_numset(str, (double)dbNullIsUndef);
  1948. X    break;
  1949. X      case UV_dbKeepNumeric:
  1950. X    str_numset(str, (double)dbKeepNumeric);
  1951. X    break;
  1952. X      case UV_dbBin0x:
  1953. X    str_numset(str, (double)dbBin0x);
  1954. X    break;
  1955. X     }
  1956. X    return 0;
  1957. X}
  1958. X
  1959. Xstatic int
  1960. Xuserset(ix, str)
  1961. Xint ix;
  1962. XSTR *str;
  1963. X{
  1964. X    switch (ix)
  1965. X    {
  1966. X      case UV_dbNullIsUndef:
  1967. X    dbNullIsUndef = str_gnum(str);
  1968. X    break;
  1969. X      case UV_dbKeepNumeric:
  1970. X    dbKeepNumeric = str_gnum(str);
  1971. X    break;
  1972. X      case UV_dbBin0x:
  1973. X    dbBin0x = str_gnum(str);
  1974. X    break;
  1975. X      default:
  1976. X#if defined(USERVAL_SET_FATAL)
  1977. X    fatal("sybperl: trying to write to a read-only variable.");
  1978. X#else
  1979. X    warn("sybperl: trying to write to a read-only variable.");
  1980. X#endif
  1981. X    break;
  1982. X    }
  1983. X    return 0;
  1984. X}
  1985. X
  1986. X
  1987. X/*ARGSUSED*/
  1988. Xstatic int err_handler(db, severity, dberr, oserr, dberrstring, oserrstr)
  1989. X    DBPROCESS *db;
  1990. X    int severity;
  1991. X    int dberr;
  1992. X    int oserr;
  1993. X    char *dberrstring;
  1994. X    char *oserrstr;
  1995. X{
  1996. X#ifdef HAS_CALLBACK
  1997. X    /* If we have error handler subroutine, use it. */
  1998. X    if (err_handler_sub)
  1999. X    {
  2000. X    int sp = perl_sp;
  2001. X    int j;
  2002. X
  2003. X    for(j = 0; j < MAX_DBPROCS; ++j)
  2004. X        if(db == dbProc[j].dbproc)
  2005. X        break;
  2006. X    if(j == MAX_DBPROCS)
  2007. X        j = 0;
  2008. X    
  2009. X    /* Reserve spot for return value. */
  2010. X    astore (stack, ++ sp, Nullstr);
  2011. X    
  2012. X    /* Set up arguments. */
  2013. X    astore (stack, ++ sp,
  2014. X        str_2mortal (str_nmake ((double) j)));
  2015. X    astore (stack, ++ sp, str_2mortal (str_nmake ((double) severity)));
  2016. X    astore (stack, ++ sp, str_2mortal (str_nmake ((double) dberr)));
  2017. X    astore (stack, ++ sp, str_2mortal (str_nmake ((double) oserr)));
  2018. X    if (dberrstring && *dberrstring)
  2019. X        astore (stack, ++ sp, str_2mortal (str_make (dberrstring, 0)));
  2020. X    else
  2021. X        astore (stack, ++ sp, &str_undef);
  2022. X    if (oserrstr && *oserrstr)
  2023. X        astore (stack, ++ sp, str_2mortal (str_make (oserrstr, 0)));
  2024. X    else
  2025. X        astore (stack, ++ sp, &str_undef);
  2026. X    
  2027. X    /* Call it. */
  2028. X    sp = callback (err_handler_sub, sp, 0, 1, 6);
  2029. X    
  2030. X    /* Return whatever it returned. */
  2031. X    return (int) str_gnum (STACK (sp)[0]);
  2032. X    }
  2033. X#endif                /* HAS_CALLBACK */
  2034. X    if ((db == NULL) || (DBDEAD(db)))
  2035. X    return(INT_EXIT);
  2036. X    else 
  2037. X    {
  2038. X    fprintf(stderr,"DB-Library error:\n\t%s\n", dberrstring);
  2039. X    
  2040. X    if (oserr != DBNOERR)
  2041. X        fprintf(stderr,"Operating-system error:\n\t%s\n", oserrstr);
  2042. X    
  2043. X    return(INT_CANCEL);
  2044. X    }
  2045. X}
  2046. X
  2047. X/*ARGSUSED*/
  2048. X
  2049. Xstatic int msg_handler(db, msgno, msgstate, severity, msgtext, srvname, procname, line)
  2050. X    DBPROCESS *db;
  2051. X    DBINT msgno;
  2052. X    int msgstate;
  2053. X    int severity;
  2054. X    char *msgtext;
  2055. X    char *srvname;
  2056. X    char *procname;
  2057. X    DBUSMALLINT line;
  2058. X{
  2059. X#ifdef HAS_CALLBACK
  2060. X    /* If we have message handler subroutine, use it. */
  2061. X    if (msg_handler_sub)
  2062. X    {
  2063. X    int sp = perl_sp;
  2064. X    int j;
  2065. X
  2066. X    for(j = 0; j < MAX_DBPROCS; ++j)
  2067. X        if(db == dbProc[j].dbproc)
  2068. X        break;
  2069. X    if(j == MAX_DBPROCS)
  2070. X        j = 0;
  2071. X    
  2072. X    /* Reserve spot for return value. */
  2073. X    astore (stack, ++ sp, Nullstr);
  2074. X    
  2075. X    /* Set up arguments. */
  2076. X    astore (stack, ++ sp,
  2077. X        str_2mortal (str_nmake ((double) j)));
  2078. X    astore (stack, ++ sp, str_2mortal (str_nmake ((double) msgno)));
  2079. X    astore (stack, ++ sp, str_2mortal (str_nmake ((double) msgstate)));
  2080. X    astore (stack, ++ sp, str_2mortal (str_nmake ((double) severity)));
  2081. X    if (msgtext && *msgtext)
  2082. X        astore (stack, ++ sp, str_2mortal (str_make (msgtext, 0)));
  2083. X    else
  2084. X        astore (stack, ++ sp, &str_undef);
  2085. X    if (srvname && *srvname)
  2086. X        astore (stack, ++ sp, str_2mortal (str_make (srvname, 0)));
  2087. X    else
  2088. X        astore (stack, ++ sp, &str_undef);
  2089. X    if (procname && *procname)
  2090. X        astore (stack, ++ sp, str_2mortal (str_make (procname, 0)));
  2091. X    else
  2092. X        astore (stack, ++ sp, &str_undef);
  2093. X    astore (stack, ++ sp, str_2mortal (str_nmake ((double) line)));
  2094. X    
  2095. X    /* Call it. */
  2096. X    sp = callback (msg_handler_sub, sp, 0, 1, 8);
  2097. X    
  2098. X    /* Return whatever it returned. */
  2099. X    return (int) str_gnum (STACK (sp)[0]);
  2100. X    }
  2101. X#endif                /* HAS_CALLBACK */
  2102. X#ifdef OLD_SYBPERL
  2103. X    if(!severity)
  2104. X    return 0;
  2105. X#endif
  2106. X    fprintf (stderr,"Msg %ld, Level %d, State %d\n", 
  2107. X         msgno, severity, msgstate);
  2108. X    if (strlen(srvname) > 0)
  2109. X    fprintf (stderr,"Server '%s', ", srvname);
  2110. X    if (strlen(procname) > 0)
  2111. X    fprintf (stderr,"Procedure '%s', ", procname);
  2112. X    if (line > 0)
  2113. X    fprintf (stderr,"Line %d", line);
  2114. X    
  2115. X    fprintf(stderr,"\n\t%s\n", msgtext);
  2116. X    
  2117. X    return(0);
  2118. X}
  2119. X
  2120. X/* 
  2121. X * Get the index into the dbproc[] array from a Perl STR datatype. 
  2122. X * Check that the index is reasonably valid...
  2123. X */
  2124. Xstatic int
  2125. XgetDbProc(Str)
  2126. X    STR *Str;
  2127. X{
  2128. X    int ix;
  2129. X
  2130. X    if (Str == &str_undef || !Str->str_nok) /* This may be getting a bit too */
  2131. X                        /* close with the internals of */
  2132. X                        /* the 'str' workings... */
  2133. X    warn("The $dbproc parameter has not been properly initialized - it defaults to 0");
  2134. X
  2135. X    ix = (int)str_gnum(Str);
  2136. X
  2137. X    if(ix < 0 || ix >= MAX_DBPROCS)
  2138. X    fatal("$dbproc parameter is out of range");
  2139. X    if(dbProc[ix].dbproc == NULL || DBDEAD(dbProc[ix].dbproc))
  2140. X    fatal("$dbproc parameter is NULL or the connection to the server has been closed");
  2141. X    return ix;
  2142. X}
  2143. X
  2144. X
  2145. X#ifdef HAS_CALLBACK
  2146. X
  2147. X/* Taken from Perl 4.018 usub/usersub.c. mp. */
  2148. X
  2149. X/* Be sure to refetch the stack pointer after calling these routines. */
  2150. X
  2151. Xint
  2152. Xcallback(subname, sp, gimme, hasargs, numargs)
  2153. Xchar *subname;
  2154. Xint sp;            /* stack pointer after args are pushed */
  2155. Xint gimme;        /* called in array or scalar context */
  2156. Xint hasargs;        /* whether to create a @_ array for routine */
  2157. Xint numargs;        /* how many args are pushed on the stack */
  2158. X{
  2159. X    static ARG myarg[3];    /* fake syntax tree node */
  2160. X    int arglast[3];
  2161. X    
  2162. X    arglast[2] = sp;
  2163. X    sp -= numargs;
  2164. X    arglast[1] = sp--;
  2165. X    arglast[0] = sp;
  2166. X
  2167. X    if (!myarg[0].arg_ptr.arg_str)
  2168. X    myarg[0].arg_ptr.arg_str = str_make("",0);
  2169. X
  2170. X    myarg[1].arg_type = A_WORD;
  2171. X    myarg[1].arg_ptr.arg_stab = stabent(subname, FALSE);
  2172. X
  2173. X    myarg[2].arg_type = hasargs ? A_EXPR : A_NULL;
  2174. X
  2175. X    return do_subr(myarg, gimme, arglast);
  2176. X}
  2177. X
  2178. X#endif                /* HAS_CALLBACK */
  2179. X
  2180. X
  2181. X#if defined(DBLIB461)
  2182. X
  2183. X/* The following routines originate from the OpenClient R4.6.1 reference  */
  2184. X/* manual, pages 2-165 to 2-168 both inclusive.  It has been subsequently */
  2185. X/* modified (slightly) to suit local conditions.                          */
  2186. X
  2187. X#define PRECISION 4
  2188. X
  2189. Xstatic void new_mny4tochar(dbproc, mny4ptr, buf_ptr)
  2190. XDBPROCESS *dbproc;
  2191. XDBMONEY4  *mny4ptr;
  2192. XDBCHAR    *buf_ptr;
  2193. X{
  2194. X   DBMONEY local_mny;
  2195. X   DBCHAR  value;
  2196. X   char    temp_buf[40];
  2197. X
  2198. X   int     bytes_written = 0;
  2199. X   int     i             = 0;
  2200. X   DBBOOL  negative      = (DBBOOL)FALSE;
  2201. X   DBBOOL  zero          = (DBBOOL)FALSE;
  2202. X
  2203. X   if (dbconvert(dbproc, SYBMONEY4, (BYTE*)mny4ptr, (DBINT)-1,
  2204. X                 SYBMONEY, (BYTE*)&local_mny, (DBINT)-1) == -1)
  2205. X   {
  2206. X      fatal("dbconvert() failed in routine new_mny4tochar()");
  2207. X   }
  2208. X
  2209. X   if (dbmnyinit(dbproc, &local_mny, 4 - PRECISION, &negative) == FAIL)
  2210. X   {
  2211. X      fatal("dbmnyinit() failed in routine new_mny4tochar()");
  2212. X   }
  2213. X
  2214. X   while (zero == FALSE)
  2215. X   {
  2216. X      if (dbmnyndigit(dbproc, &local_mny, &value, &zero) == FAIL)
  2217. X      {
  2218. X         fatal("dbmnyndigit() failed in routine new_mny4tochar()");
  2219. X      }
  2220. X
  2221. X      temp_buf[bytes_written++] = value;
  2222. X
  2223. X      if (zero == FALSE)
  2224. X      {
  2225. X         if (bytes_written == PRECISION)
  2226. X         {
  2227. X            temp_buf[bytes_written++] = '.';
  2228. X         }
  2229. X      }
  2230. X   }
  2231. X
  2232. X   while (bytes_written < PRECISION)
  2233. X   {
  2234. X      temp_buf[bytes_written++] = '0';
  2235. X   }
  2236. X
  2237. X   if (bytes_written == PRECISION)
  2238. X   {
  2239. X      temp_buf[bytes_written++] = '.';
  2240. X      temp_buf[bytes_written++] = '0';
  2241. X   }
  2242. X
  2243. X   if (negative == TRUE)
  2244. X   {
  2245. X      buf_ptr[i++] = '-';
  2246. X   }
  2247. X
  2248. X   while (bytes_written--)
  2249. X   {
  2250. X      buf_ptr[i++] = temp_buf[bytes_written];
  2251. X   }
  2252. X
  2253. X   buf_ptr[i] = '\0';
  2254. X
  2255. X   return;
  2256. X}
  2257. X
  2258. Xstatic void new_mnytochar(dbproc, mnyptr, buf_ptr)
  2259. XDBPROCESS *dbproc;
  2260. XDBMONEY   *mnyptr;
  2261. XDBCHAR    *buf_ptr;
  2262. X{
  2263. X   DBMONEY local_mny;
  2264. X   DBCHAR  value;
  2265. X   char    temp_buf[40];
  2266. X
  2267. X   int     bytes_written = 0;
  2268. X   int     i             = 0;
  2269. X   DBBOOL  negative      = (DBBOOL)FALSE;
  2270. X   DBBOOL  zero          = (DBBOOL)FALSE;
  2271. X
  2272. X   if (dbmnycopy(dbproc, mnyptr, &local_mny) == FAIL)
  2273. X   {
  2274. X      fatal("dbmnycopy() failed in routine new_mnytochar()");
  2275. X   }
  2276. X
  2277. X   if (dbmnyinit(dbproc, &local_mny, 4 - PRECISION, &negative) == FAIL)
  2278. X   {
  2279. X      fatal("dbmnyinit() failed in routine new_mnytochar()");
  2280. X   }
  2281. X
  2282. X   while (zero == FALSE)
  2283. X   {
  2284. X      if (dbmnyndigit(dbproc, &local_mny, &value, &zero) == FAIL)
  2285. X      {
  2286. X         fatal("dbmnyndigit() failed in routine new_mnytochar()");
  2287. X      }
  2288. X
  2289. X      temp_buf[bytes_written++] = value;
  2290. X
  2291. X      if (zero == FALSE)
  2292. X      {
  2293. X         if (bytes_written == PRECISION)
  2294. X         {
  2295. X            temp_buf[bytes_written++] = '.';
  2296. X         }
  2297. X      }
  2298. X   }
  2299. X
  2300. X   while (bytes_written < PRECISION)
  2301. X   {
  2302. X      temp_buf[bytes_written++] = '0';
  2303. X   }
  2304. X
  2305. X   if (bytes_written == PRECISION)
  2306. X   {
  2307. X      temp_buf[bytes_written++] = '.';
  2308. X      temp_buf[bytes_written++] = '0';
  2309. X   }
  2310. X
  2311. X   if (negative == TRUE)
  2312. X   {
  2313. X      buf_ptr[i++] = '-';
  2314. X   }
  2315. X
  2316. X   while (bytes_written--)
  2317. X   {
  2318. X      buf_ptr[i++] = temp_buf[bytes_written];
  2319. X   }
  2320. X
  2321. X   buf_ptr[i] = '\0';
  2322. X
  2323. X   return;
  2324. X}
  2325. X
  2326. X#endif  /* DBLIB461 */
  2327. X
  2328. END_OF_FILE
  2329.   if test 36266 -ne `wc -c <'sybperl.c.B'`; then
  2330.     echo shar: \"'sybperl.c.B'\" unpacked with wrong size!
  2331.   elif test -f 'sybperl.c.A' ; then
  2332.     echo shar: Combining  \"'sybperl.c'\" \(84305 characters\)
  2333.     cat 'sybperl.c.A' 'sybperl.c.B' > 'sybperl.c'
  2334.     if test 84305 -ne `wc -c <'sybperl.c'`; then
  2335.       echo shar: \"'sybperl.c'\" combined with wrong size!
  2336.     else 
  2337.       rm sybperl.c.A sybperl.c.B
  2338.     fi 
  2339.   fi
  2340.   # end of 'sybperl.c.B'
  2341. fi
  2342. echo shar: End of archive 2 \(of 3\).
  2343. cp /dev/null ark2isdone
  2344. MISSING=""
  2345. for I in 1 2 3 ; do
  2346.     if test ! -f ark${I}isdone ; then
  2347.     MISSING="${MISSING} ${I}"
  2348.     fi
  2349. done
  2350. if test "${MISSING}" = "" ; then
  2351.     echo You have unpacked all 3 archives.
  2352.     rm -f ark[1-9]isdone
  2353. else
  2354.     echo You still must unpack the following archives:
  2355.     echo "        " ${MISSING}
  2356. fi
  2357. exit 0
  2358. exit 0 # Just in case...
  2359.