home *** CD-ROM | disk | FTP | other *** search
/ Winzipper / Winzipper_ISO.iso / programming / oracle7 7.2 / DB / UTIL72 / DIUTIL.SQL < prev    next >
Encoding:
Text File  |  1995-05-18  |  44.0 KB  |  1,344 lines

  1. Rem
  2. Rem $Header: diutil.sql 7020200.1 95/02/15 18:19:20 cli Generic<base> $ 
  3. Rem
  4. Rem Copyright (c) 1992 by Oracle Corporation
  5. Rem   NAME
  6. Rem     diutil.pls - package DIUTIL
  7. Rem   DESCRIPTION
  8. Rem Diana application routines
  9. Rem
  10. Rem   RETURNS
  11. Rem
  12. Rem   NOTES
  13. Rem     <other useful comments, qualifications, etc.>
  14. Rem   MODIFIED   (MM/DD/YY)
  15. Rem     usundara   10/01/94 -  merge from 1.20.710.5: PSTUBI,PSTUBQ,PSTUBR
  16. Rem     usundara   06/07/94 -  merge 1.20.710.3 and 1.20.710.4 (bug #196374);
  17. Rem                            also, don't pass in PUBLIC cos kgl does this.
  18. Rem     usundara   04/08/94 -  merge changes from branch 1.20.710.2
  19. Rem                            fix traversals (161306,147036) add libunit_type
  20. Rem     usundara   01/06/94 -  fix #190597; deal with %type; reindent (merge)
  21. Rem     smuench    05/26/93 -  fix problems w/ boolean support
  22. Rem     pshaw      10/21/92 -  modify script for bug 131187 
  23. Rem     gclossma   09/28/92 -  sanitize 
  24. Rem     gclossma   09/07/92 -  logic error (as if there's some other kind?) 
  25. Rem     gclossma   09/04/92 -  no more to-varchar2 
  26. Rem     gclossma   08/05/92 -  source-control Steve M's changes for booleans 
  27. Rem     smuench    07/17/92 -  add boolean param supt, int_to_bool/bool_to_int
  28. Rem     gclossma   07/14/92 -  pstubT: add constraints to CHARs; bigger pkgs 
  29. Rem     gclossma   05/08/92 -  simplify; check buffer lengths 
  30. Rem     gclossma   04/10/92 -  gen CHAR stead of VARCHAR2 for sqlforms3 for v6 
  31. Rem     ahong      03/25/92 -  fix synonym expansion for pstub
  32. Rem     ahong      03/20/92 -  add s_notInPackage
  33. Rem     ahong      03/12/92 -  synonym
  34. Rem     ahong      03/10/92 -  no s_noPriv
  35. Rem     ahong      03/03/92 -  return empty instead of null
  36. Rem     ahong      02/21/92 -  upper names
  37. Rem     ahong      02/11/92 -  Creation
  38.  
  39.  
  40. Rem  NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
  41. Rem  NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
  42. Rem  NOTE: you must be connected "internal" (i.e. as user SYS) to run this
  43. Rem  script.
  44. Rem  NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
  45. Rem  NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE
  46.  
  47.  
  48. drop table sys.pstubtbl;
  49.  
  50. create table sys.pstubtbl (
  51.   username varchar2(30),
  52.   dbname   varchar2(128),
  53.   lun      varchar2(30),
  54.   lutype   varchar2(3),
  55.   lineno   number,
  56.   line     varchar2(1800) 
  57. );
  58.  
  59. grant select,delete on sys.pstubtbl to public;
  60.  
  61. drop package body sys.diutil;
  62. drop package sys.diutil;
  63.  
  64.  
  65.  
  66. create or replace package sys.diutil is
  67.  
  68.   e_subpNotFound exception;
  69.   e_notInPackage exception;
  70.   e_noPriv exception;
  71.   e_stubTooLong exception;
  72.   e_notv6compat exception;
  73.   e_other exception;
  74.  
  75.   subtype ptnod is pidl.ptnod;
  76.   subtype ub4 is pidl.ub4;
  77.  
  78.   --   Return code from diutil functions
  79.   --
  80.   s_ok constant number := 0;            -- successful
  81.   s_notInPackage constant number := 6;  -- package found, proc not found
  82.   s_subpNotFound constant number := 1;  -- subprogram not found
  83.   s_stubTooLong constant number := 3;   -- text to be returned is too long
  84.   s_logic constant number := 4;         -- logic error
  85.   s_other constant number := 5;         -- other error
  86.   s_defaultVal constant number := 8;    -- true iff parameters have default
  87.                                         --   values.  Applicable to pstub
  88.   s_notv6compat constant number := 7;   -- found non v6 type or construct
  89.  
  90.   char_for_varchar2 boolean;            -- set from flags for v6 compatibility
  91.  
  92.   libunit_type_spec constant number := 1; 
  93.   libunit_type_body constant number := 2;
  94.  
  95.   -- get_d: returns the root of the diana of a libunit, given name and usr.
  96.   --    name will be first folded to upper case if not in quotes, else stripped
  97.   --    of quotes.
  98.   --    In:  name = subprogram name
  99.   --         usr  = user name
  100.   --         dbname = database name, null for current
  101.   --         dbowner = null for current
  102.   --         libunit_type = libunit_type_spec for spec,
  103.   --                      = libunit_type_body for body
  104.   --    Out: status = s_ok(0): diana root returned in nod
  105.   --                  s_subpNotFound:  nod null
  106.   --                  s_other:   other error, nod null
  107.   --
  108.   procedure get_d(name varchar2, usr varchar2, dbname varchar2,
  109.          dbowner varchar2, status in out ub4, nod OUT ptnod, 
  110.          libunit_type number := libunit_type_spec);
  111.  
  112.   -- get_diana: returns the root of the diana of a libunit, given name and usr.
  113.   --    name will be first folded to upper case if not in quotes, else stripped
  114.   --    of quotes.  Will trace synonym links.
  115.   --    In:  name = subprogram name
  116.   --         usr  = user name
  117.   --         dbname = database name, null for current
  118.   --         dbowner = null for current
  119.   --         libunit_type = libunit_type_spec for spec,
  120.   --                      = libunit_type_body for body
  121.   --    Out: status = s_ok(0): diana root returned in nod
  122.   --                  s_subpNotFound:  nod null
  123.   --                  s_other:   other error, nod null
  124.   --
  125.   procedure get_diana(name varchar2, usr varchar2, dbname varchar2,
  126.          dbowner varchar2, status in out ub4, nod in out ptnod,
  127.          libunit_type number := libunit_type_spec);
  128.  
  129.   -- subptxt: returns the text of a subprogram source (DESCRIBE).
  130.   --    In:  name - package or toplevel proc/func name;
  131.   --         subname - non-null to specify proc/func in package <name>.
  132.   --         dbname - database name
  133.   --         dbowner - dbase owner
  134.   --    Out:  status = s_ok (0): text returned in txt
  135.   --                   s_subpNotFound: txt empty
  136.   --                   s_notInPackagte: txt empty
  137.   --                   s_stubTooLong: txt len too small; txt empty
  138.   --                   s_logic: logic error; txt empty
  139.   --                   s_other: other failure; txt empty
  140.   --
  141.   procedure subptxt(name varchar2, subname varchar2, usr varchar2, 
  142.                     dbname varchar2, dbowner varchar2, txt in out varchar2,
  143.                     status in out ub4);
  144.  
  145.   -- pstub:  procedure returning stub text of a subprogram
  146.   --         In:  pname - subprogram name
  147.   --              subname - NULL or member name (if pname is a package
  148.   --                        spec)
  149.   --              uname - user name, NULL or '' to mean current user
  150.   --              dbname - database name
  151.   --              dbowner - dbase owner
  152.   --         Out: status - s_ok (0): stub text in return val
  153.   --                       s_subpNotFound: stubSpec, stubText empty
  154.   --                       s_stubTooLong: stub text too long; stubSpec, 
  155.   --                                                    stubText empty
  156.   --                       s_logic: logic error; stubSpec, stubText empty
  157.   --                       s_other failure; stubSpec, stubText empty
  158.   --                       s_defaultVal: proc/func default parm values; 
  159.   --                            stubSpec,  stubText partial
  160.   --              stubSpec - empty if subprogram is a top level proc/func
  161.   --                         or if subname is specified for package pname,
  162.   --                         else contain package spec
  163.   --              stubText - contains stub body
  164.   --
  165.   procedure pstub(pname varchar2, subname varchar2, 
  166.                   uname varchar2, dabaname varchar2, dbowner varchar2,
  167.                   status in out ub4, flags varchar2, stubtype in out varchar2);
  168.  
  169.   -- bool_to_int:  Translates 3-valued boolean to NUMBER for use
  170.   --               in sending boolean parameter / return values
  171.   --               between PLS v1 (client) and PLS v2. Since SQLNET
  172.   --               has no boolean bind variable type, we encode 
  173.   --               booleans as FALSE = 0, TRUE = 1, NULL = NULL for
  174.   --               network transfer as NUMBER
  175.   --
  176.   function bool_to_int( b BOOLEAN) return number;
  177.  
  178.   -- int_to_bool:  Translates 3-valued NUMBER encoding to BOOLEAN for use
  179.   --               in sending boolean parameter / return values
  180.   --               between PLS v1 (client) and PLS v2. Since SQLNET
  181.   --               has no boolean bind variable type, we encode 
  182.   --               booleans as FALSE = 0, TRUE = 1, NULL = NULL for
  183.   --               network transfer as NUMBER
  184.   --
  185.   function int_to_bool( n NUMBER) return boolean;
  186.  
  187. end diutil;
  188. /
  189.  
  190.  
  191.  
  192. Rem
  193. Rem  Package body DIUTIL:
  194. Rem
  195. Rem
  196. create or replace package body sys.diutil is
  197.  
  198.  
  199.   -----------------------
  200.   --  Private members
  201.   -----------------------
  202.  
  203.   procedure diugdn(name varchar2, usr varchar2, dbname varchar2,
  204.                    dbowner varchar2, status out ub4, nod OUT ptnod,
  205.                    libunit_type binary_integer := libunit_type_spec);
  206.     pragma interface(c,diugdn);
  207.   procedure diustx(n ptnod, txt out varchar2, status out ub4);
  208.     pragma interface(c,diustx);
  209.  
  210.   assertVal constant boolean := TRUE;
  211.  
  212.   -----------------------
  213.   -- assert
  214.   -----------------------
  215.   procedure assert(v boolean, str varchar2) is
  216.     x integer;
  217.   begin
  218.     if (assertVal and not v) then
  219.       raise program_error;
  220.     end if;
  221.   end assert;
  222.  
  223.   -----------------------
  224.   -- assert
  225.   -----------------------
  226.   procedure assert(v boolean) is
  227.   begin
  228.     assert(v, '');
  229.   end;
  230.  
  231.   -----------------------
  232.   -- last_elt
  233.   -----------------------
  234.   function last_elt (seq pidl.ptseqnd) return pidl.ptnod is
  235.     len binary_integer;
  236.   begin
  237.     len := pidl.ptslen(seq);
  238.     assert(len > 0);
  239.     return pidl.ptgend(seq, len - 1);
  240.   end last_elt;
  241.  
  242.   -----------------------
  243.   -- normalName: return a normalized name.  Fold up if not in quotes,
  244.   -- else strip quotes.
  245.   -----------------------
  246.   function normalName(name varchar2) return varchar2 is
  247.     firstChar varchar2(1);
  248.     len number;
  249.   begin
  250.     if (name is null or name = '') then return name; end if;
  251.     firstChar := substr(name, 1, 1);
  252.     if (firstChar = '"') then
  253.       len := length(name);
  254.       if (len > 1 and substr(name, len, 1) = '"') then
  255.         if (len > 33) then
  256.           len := 31;
  257.         else
  258.           len := len-2;
  259.         end if;
  260.         return substr(name, 2, len);
  261.       end if;
  262.      end if;
  263.      return upper(name);
  264.   end normalName;
  265.  
  266.   -----------------------
  267.   -- coatName: Enquote name if necessary
  268.   -----------------------
  269.   function coatName(name varchar2) return varchar2 is
  270.   begin
  271.     if (name <> upper(name)) then
  272.       return '"' || name || '"';
  273.     elsif char_for_varchar2 and name = 'VARCHAR2' then
  274.       return 'CHAR';
  275.     else
  276.       return name;
  277.     end if;
  278.   end coatName;
  279.  
  280.   -----------------------
  281.   -- idName
  282.   -----------------------
  283.   function idName(n ptnod) return varchar2 is
  284.     -- return the text of an ID node.  This function is also
  285.     -- used to limit the recursion in exprText() below.
  286.     -- Should have the semantics of listText(diana.as_list(n), ',');
  287.     seq pidl.ptseqnd;
  288.   begin
  289.     assert(pidl.ptkin(n) = diana.DS_ID);
  290.     seq := diana.as_list(n);
  291.     return coatName(diana.l_symrep(last_elt(seq)));
  292.   end idName;
  293.  
  294.   -----------------------
  295.   -- exprText: General unparsing function
  296.   -----------------------
  297.   procedure exprText(x ptnod, rv in out varchar2);
  298.  
  299.   -----------------------
  300.   -- genProcSpec
  301.   --  Append the spec for a top-level node n to sText.
  302.   --  ignoreDefVal controls whether parm default vals should be ignored.
  303.   --  hasDefVal returned true iff parm default vals exist.
  304.   --  Toplevel name returned in pName.  
  305.   --  If function, function string returned in returnVal.
  306.   -----------------------
  307.   procedure genProcSpec(n ptnod, 
  308.                         ignoreDefVal boolean,
  309.                         hasDefVal in out boolean,
  310.                         pName in out varchar2, 
  311.                         returnVal in out varchar2, 
  312.                         flags varchar2,
  313.                         sText in out varchar2);
  314.  
  315.  
  316.   -----------------------
  317.   -- procName
  318.   -----------------------
  319.   function procName(k ptnod) return varchar2 is
  320.     x ptnod; xKind pidl.ptnty;
  321.   begin
  322.     if (k is null or k = 0) then return null; end if;
  323.     if (pidl.ptkin(k) <> diana.D_S_DECL) then return null; end if;
  324.     x := diana.a_d_(k);
  325.     xKind := pidl.ptkin(x);
  326.     if (    xKind <> diana.DI_FUNCT
  327.         and xKind <> diana.DI_PROC
  328.         and xKind <> diana.D_DEF_OP) then
  329.       return null;
  330.     end if;
  331.     return diana.l_symrep(x);
  332.   end;
  333.  
  334.  
  335.   -----------------------
  336.   --  Private members
  337.   -----------------------
  338.  
  339.  
  340.   -----------------------
  341.   -- get_d
  342.   -----------------------
  343.   procedure get_d (name varchar2, usr varchar2, dbname varchar2,
  344.                    dbowner varchar2, status in out ub4, nod OUT ptnod,
  345.                    libunit_type number := libunit_type_spec) is
  346.     nName varchar2(100);
  347.     nUsr varchar2(100);
  348.     nDbname varchar2(100);
  349.     nDbowner varchar2(100);
  350.   begin -- get_d
  351.     nod := null;
  352.     begin
  353.       nName := normalName(name);
  354.       nUsr := normalName(usr);
  355.       nDbname := normalName(dbname);
  356.       nDbowner := normalName(dbowner);
  357.       if (nName is null or nName = '') then
  358.         raise e_subpNotFound;
  359.       end if;
  360.       diugdn(nName, nUsr, nDbname, nDbowner, status, nod, libunit_type);
  361.  
  362.       if (status = 1) then
  363.         diugdn(nName, '', nDbname, nDbowner, status, nod, libunit_type);
  364.       end if;
  365.  
  366.       if (status = 1) then
  367.         raise e_subpNotFound;
  368.       elsif (status = 2) then
  369.         raise e_noPriv;
  370.       elsif (status <> 0) then
  371.         raise e_other;
  372.       end if;
  373.       status := s_ok;
  374.     exception
  375.       when e_subpNotFound then
  376.         status := s_subpNotFound;
  377.       when e_noPriv then
  378.         status := s_subpNotFound;
  379.       when others then
  380.         status := s_other;
  381.     end;
  382.   end get_d;
  383.  
  384.   -----------------------
  385.   -- get_diana
  386.   -----------------------
  387.   procedure get_diana (name varchar2, usr varchar2, dbname varchar2,
  388.                        dbowner varchar2,
  389.                        status in out ub4, nod in out ptnod,
  390.                        libunit_type number := libunit_type_spec) is
  391.     t ptnod;
  392.   begin -- get_diana
  393.     nod := null;
  394.     begin
  395.       get_d(name, usr, dbname, dbowner, status, nod, libunit_type);
  396.       if (status = s_ok) then
  397.         t := diana.a_unit_b(nod);
  398.         assert(pidl.ptkin(t) <> diana.Q_CREATE);
  399.       end if;
  400.     exception
  401.       when program_error then
  402.     status := s_other;
  403.       when others then
  404.     status := s_other;
  405.     end;
  406.   end get_diana;
  407.  
  408.  
  409.   -----------------------
  410.   -- subptxt
  411.   -----------------------
  412.   procedure subptxt(name varchar2, subname varchar2, usr varchar2,
  413.                     dbname varchar2, dbowner varchar2, txt in out varchar2, 
  414.                     status in out ub4) is
  415.     e_defaultVal boolean := FALSE;
  416.  
  417.     -----------------------
  418.     -- describeProc
  419.     -----------------------
  420.     procedure describeProc(n ptnod, s in out varchar2) is
  421.       tmpVal varchar2(100);
  422.       rVal varchar2(500);
  423.     begin -- describeProc
  424.       -- We call genProcSpec here because it is not
  425.       -- possible to get the text reliably for arbitrary node
  426.       -- through diustx
  427.       --
  428.       tmpVal := null;
  429.       genProcSpec(n, FALSE, e_defaultVal, tmpVal, rVal, '', s);
  430.       s := s || '; ';
  431.     end describeProc;
  432.  
  433.   begin -- subptxt
  434.     txt := '';
  435.  
  436.     declare
  437.       troot ptnod;
  438.       n ptnod;
  439.       nSubName varchar2(100);
  440.     begin
  441.       get_diana(name, usr, dbname, dbowner, status, troot);
  442.       if (troot is null or troot = 0) then return; end if;
  443.  
  444.       nSubname := normalName(subname);
  445.       n := diana.a_unit_b(troot);
  446.  
  447.       if (nSubname is null or nSubname = '') then
  448.         if (pidl.ptkin(n) = diana.D_P_DECL) then
  449.           diustx(troot, txt, status);
  450.         else
  451.           describeProc(n, txt);
  452.         end if;
  453.       else
  454.         -- search for subname among all func/proc in the package
  455.         if (pidl.ptkin(n) <> diana.D_P_DECL) then
  456.           status := s_subpNotFound;
  457.           return;
  458.         end if;
  459.         n := diana.a_packag(n);
  460.         declare
  461.           seq pidl.ptseqnd := diana.as_list(diana.as_decl1(n));
  462.           len integer := pidl.ptslen(seq) - 1;
  463.           tmp integer;
  464.         begin
  465.           for i in 0..len loop --for each member of the package
  466.             n := pidl.ptgend(seq, i);
  467.             if (procName(n) = nSubname) then
  468.               describeProc(n, txt);
  469.             end if;
  470.           end loop;
  471.         end;
  472.         if (txt is null or txt = '') then
  473.           status := s_notInPackage;
  474.         end if;
  475.       end if;
  476.  
  477.     exception   -- txt reset to null
  478.       when value_error then
  479.         status := s_stubTooLong;
  480.       when program_error then
  481.         status := s_logic;
  482.       when e_other then
  483.         status := s_other;
  484.       when others then
  485.         status := s_other;
  486.     end;
  487.   end subptxt;
  488.  
  489.  
  490.   --------------------
  491.   -- pstub
  492.   --------------------
  493.   procedure pstub(pname varchar2, subname varchar2, uname varchar2,
  494.                   dabaname varchar2, dbowner varchar2, status in out ub4,
  495.                   flags varchar2, stubtype in out varchar2) is
  496.  
  497.     ignoreParmVal constant boolean := TRUE;
  498.  
  499.     subtype ptnod is pidl.ptnod;
  500.     lubptr ptnod;
  501.     e_defaultVal boolean := FALSE;
  502.     tsubName varchar2(100);
  503.  
  504.     stubSpec varchar2(32700);
  505.     stubText varchar2(32700);
  506.     specLine binary_integer := 1;
  507.     textLine binary_integer := 1;
  508.  
  509.     --------------------
  510.     -- flushStubs
  511.     --------------------
  512.     procedure flushStubs (partial_lines_ok boolean) is
  513.       len binary_integer;
  514.       pos binary_integer;
  515.       luty varchar2(3);
  516.       rowbuf varchar2(1820);
  517.     begin
  518.       pos := 1;
  519.       len := length(stubSpec);
  520.       if len > 0 then
  521.         -- we have a package spec
  522.         assert(stubtype = 'PKG');
  523.         luty := 'PKS'; 
  524.       end if;
  525.       while (len - pos > 1800 or 
  526.              (partial_lines_ok and pos <= len)) loop
  527.         rowbuf := substr(stubSpec, pos, 1800);
  528.         insert into sys.pstubtbl (username, dbname, lun, lutype, lineno, line)
  529.           values (uname, dabaname, pname, luty, specLine, rowbuf);
  530.         pos := pos + 1800;
  531.         specLine := specLine + 1;
  532.       end loop;
  533.       if pos > 1 then stubSpec := substr(stubSpec, pos); end if;
  534.  
  535.       pos := 1;
  536.       len := length(stubText);
  537.       if len > 0 then
  538.         -- a subprogram or package body
  539.         if stubtype = 'PKG' then luty := 'PKB'; else luty := 'SUB'; end if;
  540.       end if;
  541.       while (len - pos > 1800 or 
  542.              (partial_lines_ok and pos <= len)) loop
  543.         rowbuf := substr(stubText, pos, 1800);
  544.         insert into sys.pstubtbl (username, dbname, lun, lutype, lineno, line)
  545.             values (uname, dabaname, pname, luty, textLine, rowbuf);
  546.         pos := pos + 1800;
  547.         textLine := textLine + 1;
  548.       end loop;
  549.       if pos > 1 then stubText := substr(stubText, pos); end if;
  550.     end flushStubs;
  551.  
  552.     --------------------
  553.     -- genStubBody
  554.     --------------------
  555.     procedure genStubBody(x ptnod, pName varchar2, returnVal varchar2) is
  556.       -------------------------------------------------------
  557.       -- append the text for the stub body to stubText buffer
  558.       -------------------------------------------------------
  559.       MAXVCSLEN  varchar2(4) := '2000';
  560.       Type bindArr is Table of varchar2(30) index by binary_integer;
  561.       parmSeq    pidl.ptseqnd;
  562.       parmNum    natural;
  563.       k          ptnod;
  564.       knd        pidl.ptnty;
  565.       uniq_id    varchar2(80);              
  566.       parmname   varchar2(80);
  567.       digit      integer;
  568.       BoolPrm    Boolean := FALSE;
  569.       bindVarLst BindArr;
  570.       bindVarTyp BindArr;
  571.       lstptr     integer  := 0;
  572.  
  573.       -- push_bindvar
  574.       --
  575.       procedure push_bindvar( v_name varchar2, v_type varchar2 ) is
  576.       begin
  577.         lstptr := lstptr + 1;
  578.         bindVarLst(lstptr) := v_name;
  579.         bindVarTyp(lstptr) := UPPER(v_type);
  580.       end push_bindvar;
  581.  
  582.       -- get_bindvar
  583.       --
  584.       procedure get_bindvar( i integer, 
  585.                              v_name OUT varchar2, 
  586.                              v_type OUT varchar2) is
  587.       begin
  588.         v_name := bindVarLst(i);
  589.         v_type := bindVarTyp(i);
  590.       end get_bindvar;
  591.  
  592.       -- is_boolean
  593.       --
  594.       function is_boolean( typenode ptnod ) return boolean is
  595.         typename varchar2(100);
  596.       begin
  597.         typename := '';
  598.         exprText(typenode,typename);
  599.         return( ltrim(rtrim(typename))='BOOLEAN');
  600.       end is_boolean;
  601.  
  602.     begin -- genStubBody
  603.  
  604.       assert(x is not null);
  605.       k := diana.a_header(x); assert(k is not null);
  606.       parmSeq := diana.as_list(diana.as_p_(k));
  607.       assert(parmSeq is not null);
  608.       parmNum := pidl.ptslen(parmSeq);
  609.  
  610.       uniq_id := '';
  611.       digit := 0;
  612.       if returnVal is not null then
  613.         -- gen a unique id, dift from any parm id, for the return-value
  614.         -- variable
  615.         loop
  616.           uniq_id := 'X'||to_char(digit);
  617.           for i in 1 .. parmNum loop
  618.             k := pidl.ptgend(parmSeq, i-1);
  619.             parmname := idName(diana.as_id(k));
  620.             if parmname = uniq_id then exit; end if;
  621.           end loop;
  622.           if parmNum = 0 or parmname <> uniq_id then exit; end if;
  623.           digit := digit + 1;
  624.         end loop;
  625.       end if;
  626.  
  627.       stubText := stubText || ' is ';
  628.       if (returnVal is not null) then
  629.         stubText := stubText || uniq_id || ' ';
  630.         if (returnVal = 'CHAR' or
  631.             returnVal = 'VARCHAR2' or
  632.             returnVal = 'VARCHAR' or
  633.             returnVal = 'RAW') then
  634.           stubText := stubText || returnVal || '('||MAXVCSLEN||'); ';
  635.         else
  636.           stubText := stubText || returnVal || '; ';
  637.         end if;
  638.       end if;
  639.       stubText  := stubText || 'begin stproc.init(''';
  640.  
  641.       If (returnVal = 'BOOLEAN') then
  642.         stubText := stubText || 'declare '||uniq_id||'rv BOOLEAN; ';
  643.         BoolPrm := TRUE;
  644.       End If;
  645.  
  646.       -- Local BOOL
  647.       if (parmNum > 0) then
  648.         for i in 1..parmNum loop
  649.           k := pidl.ptgend(parmSeq, i-1);
  650.           if ( is_boolean(diana.a_name(k)) ) then
  651.             if (NOT BoolPrm) then
  652.               stubText := stubText || 'declare ';
  653.               BoolPrm := TRUE;
  654.             end if;
  655.             stubText := stubText||uniq_id||
  656.                  idName(diana.as_id(k))||' BOOLEAN; ';
  657.           end if;
  658.         end loop;
  659.       end if;
  660.  
  661.       stubText := stubText || 'begin ';
  662.  
  663.       -- Init all BOOL params
  664.       if (parmNum > 0) then
  665.         for i in 1..parmNum loop
  666.           k := pidl.ptgend(parmSeq, i-1);
  667.           if ( is_boolean(diana.a_name(k)) ) then
  668.             stubText := stubText||uniq_id||idName(diana.as_id(k))||
  669.                 ' := sys.diutil.int_to_bool(:'||
  670.                 idName(diana.as_id(k))||'); ';
  671.           end if;
  672.         end loop;
  673.       end if;
  674.  
  675.       -- Non-BOOL Return Val
  676.       if (returnVal is not null) then
  677.         if (returnVal = 'BOOLEAN') then
  678.           stubText := stubText || uniq_id ||'rv := ' || pName;
  679.         else
  680.           stubText := stubText || ':'||uniq_id||' := ' || pName;
  681.         end if;
  682.       else
  683.         stubText := stubText ||  pName;
  684.       end if;
  685.  
  686.       if (parmNum > 0) then
  687.         k := pidl.ptgend(parmSeq, 0);
  688.         -- Pass local BOOL, non-BOOL binds
  689.         if ( is_boolean(diana.a_name(k)) ) then
  690.           stubText := stubText || '(' || uniq_id||idName(diana.as_id(k));
  691.         else
  692.           stubText := stubText || '(:' || idName(diana.as_id(k));
  693.         end if;
  694.  
  695.         for i in 2..parmNum loop
  696.           k := pidl.ptgend(parmSeq, i-1);
  697.           if ( is_boolean(diana.a_name(k)) ) then
  698.             stubText := stubText || ', ' || uniq_id||idName(diana.as_id(k));
  699.           else
  700.             stubText := stubText || ', :' || idName(diana.as_id(k));
  701.           end if;
  702.         end loop;
  703.         stubText := stubText || ')';
  704.       end if;
  705.       stubText := stubText || '; ';
  706.  
  707.       -- Convert OUT booleans (including return value)
  708.       if (returnVal is not null and returnVal = 'BOOLEAN' ) then
  709.         stubText := stubText ||':'||uniq_id||
  710.              ' := sys.diutil.bool_to_int('||uniq_id||'rv); ';
  711.       end if;
  712.       if (parmNum > 0) then
  713.         for i in 1..parmNum loop
  714.           k := pidl.ptgend(parmSeq, i-1);
  715.           if ( is_boolean(diana.a_name(k)) ) then
  716.             knd := pidl.ptkin(k);
  717.             if (knd = diana.D_OUT or knd = diana.D_IN_OUT) then
  718.               stubText := stubText||':'||idName(diana.as_id(k))||
  719.                     ' := sys.diutil.bool_to_int('||
  720.                     uniq_id||idName(diana.as_id(k))||'); ';
  721.             end if;
  722.           end if;
  723.         end loop;
  724.       end if;
  725.  
  726.       stubText := stubText || 'end;''); ';
  727.  
  728.       -- Bind order according to bind var appearance in stub
  729.       for i in 1..parmNum loop
  730.         k := pidl.ptgend(parmSeq, i-1);
  731.         if ( is_boolean(diana.a_name(k))) then
  732.           knd := pidl.ptkin(k);
  733.           declare
  734.             tmp varchar2(100);
  735.           begin
  736.             if (knd = diana.D_IN) then
  737.               tmp := 'bind_i';
  738.               push_bindvar(IdName(diana.as_id(k)),'IN');
  739.             elsif (knd = diana.D_OUT) then
  740.               tmp := 'bind_o';
  741.               push_bindvar(IdName(diana.as_id(k)),'OUT');
  742.             else tmp := 'bind_io';
  743.               push_bindvar(IdName(diana.as_id(k)),'IN OUT');
  744.             end if;
  745.             stubText := stubText || 'stproc.' || tmp || '('
  746.               || idName(diana.as_id(k)) || '); ';
  747.           end;
  748.         end if;
  749.       end loop;
  750.       if (returnVal is not null and returnVal <> 'BOOLEAN') then
  751.         stubText := stubText || 'stproc.bind_o(' || uniq_id || '); ';
  752.             push_bindvar(uniq_id,'OUT');
  753.       end if;
  754.       for i in 1..parmNum loop
  755.         k := pidl.ptgend(parmSeq, i-1);
  756.         if ( NOT is_boolean(diana.a_name(k))) then
  757.           knd := pidl.ptkin(k);
  758.           declare
  759.             tmp varchar2(100);
  760.           begin
  761.             if (knd = diana.D_IN) then
  762.               tmp := 'bind_i';
  763.               push_bindvar(IdName(diana.as_id(k)),'IN');
  764.             elsif (knd = diana.D_OUT) then
  765.               tmp := 'bind_o';
  766.               push_bindvar(IdName(diana.as_id(k)),'OUT');
  767.             else tmp := 'bind_io';
  768.               push_bindvar(IdName(diana.as_id(k)),'IN OUT');
  769.             end if;
  770.             stubText := stubText || 'stproc.' || tmp || '('
  771.                  || idName(diana.as_id(k)) || '); ';
  772.           end;
  773.         end if;
  774.       end loop;
  775.       if (returnVal is not null and returnVal = 'BOOLEAN') then
  776.         stubText := stubText || 'stproc.bind_o(' || uniq_id || '); ';
  777.         push_bindvar(uniq_id,'OUT');
  778.       end if;
  779.  
  780.       stubText := stubText || 'stproc.execute; ';
  781.  
  782.       -- Retrieve all out bind variables
  783.       declare
  784.         bvarname varchar2(30);
  785.         bvartype varchar2(30);
  786.       begin
  787.         for i in 1..lstptr loop
  788.           get_bindvar(i,bvarname,bvartype);
  789.           if (bvartype in ('OUT','IN OUT')) then
  790.             stubText := stubText || 'stproc.retrieve(' || to_char(i)
  791.                         || ', ' || bvarname || '); ';
  792.           end if;
  793.         end loop;
  794.       end;        
  795.  
  796.       if (returnVal is not null) then
  797.         stubText := stubText || 'return '|| uniq_id || '; ';
  798.       end if;
  799.  
  800.       stubText := stubText || 'end; ';
  801.     end genStubBody;
  802.  
  803.     --------------------
  804.     -- genStub
  805.     --------------------
  806.     procedure genStub(x ptnod) is
  807.       -- generate the stub for a subprogram
  808.       -- if a Proc/Func, generate the stub into stubText
  809.       -- if a Package, stuff the spec into stubSpec,
  810.       -- the body into stubText
  811.       n ptnod;
  812.       nKind pidl.ptnty; 
  813.       tKind  pidl.ptnty;
  814.       subpName varchar2(100);
  815.       returnVal varchar2(500);
  816.       isPackage boolean;
  817.       saverow varchar2(1800);
  818.     begin
  819.       assert(x is not null);
  820.       n := diana.a_unit_b(x); assert(n is not null);
  821.       tKind := pidl.ptkin(n);
  822.       subpName := pName;  -- assume top-level synonym
  823.       isPackage := false;  stubType := 'SUB'; -- assume subprg, not pkg
  824.  
  825.       if (tKind = diana.D_P_DECL) then   --package
  826.         -- stubSpec := 'package ' || exprText(diana.a_id(n)) || ' is ';
  827.         -- stubText := 'package body ' || exprText(diana.a_id(n)) || ' is ';
  828.         isPackage := true; stubType := 'PKG';
  829.  
  830.         if (tsubName is null or tsubName = '') then
  831.           stubSpec := 'package ' || pName || ' is ';
  832.           stubText := 'package body ' || pName || ' is ';
  833.         end if;
  834.  
  835.         n := diana.a_packag(n);
  836.  
  837.         declare
  838.           seq pidl.ptseqnd := diana.as_list(diana.as_decl1(n));
  839.           len integer := pidl.ptslen(seq) - 1;
  840.           tmp integer; 
  841.         begin   -- this loop should be factored out with the Describe loop
  842.           for i in 0..len loop -- for each member of the package
  843.             saverow := stubSpec; -- save in case of rollback
  844.             begin
  845.               n := pidl.ptgend(seq, i); assert(n is not null);
  846.               nKind := pidl.ptkin(n);
  847.  
  848.               if (nKind = diana.D_S_DECL) then  --proc/func
  849.                 if (tsubName is null or tsubName = '') then
  850.                   tmp := length(stubText);
  851.                   subpName := null;
  852.                   genProcSpec(n, ignoreParmVal, e_defaultVal,
  853.                               subpName, returnVal, flags, stubText);
  854.                   stubSpec := stubSpec || substr(stubText, tmp+1) 
  855.                                         || '; ';
  856.                   genStubBody(n, pName || '.' || subpName, returnVal);
  857.                 else
  858.                   if (procName(n) = tsubName) then
  859.                     subpName := null;
  860.                     exit;
  861.                   end if;
  862.                 end if;
  863.               --else
  864.               --  if (tsubName is null or tsubName = '') then
  865.               --    exprText(n, stubSpec);
  866.               --    stubSpec := stubSpec || '; ';
  867.               --  end if;
  868.               end if;
  869.               n := null;
  870.               flushstubs(false);
  871.             exception
  872.               when e_notv6compat 
  873.                 then stubSpec := saverow; -- rollback
  874.             end;
  875.           end loop;
  876.         end;
  877.  
  878.         if (tsubName is null or tsubName = '') then
  879.           stubSpec := stubSpec || ' end;';
  880.           stubText := stubText || 'end;';
  881.         end if;
  882.       end if;
  883.  
  884.       if (stubSpec is null or stubSpec = '') then
  885.         if (n is null) then
  886.           raise e_notInPackage;
  887.         end if;
  888.         genProcSpec(n, ignoreParmVal, e_defaultVal,
  889.                     subpName, returnVal, flags, stubText);
  890.         if (isPackage) then
  891.           genStubBody(n, pName || '.' || subpName, returnVal);
  892.         else
  893.           genStubBody(n, subpName, returnVal);
  894.         end if;
  895.       end if;
  896.     end genstub;
  897.  
  898.   begin -- pstub
  899.     status := s_ok;
  900.     stubText := '';
  901.     stubSpec := '';
  902.  
  903.     char_for_varchar2 := 0 < instr(flags, '6');
  904.     begin
  905.       get_diana(pname, uname, dabaname, dbowner, status, lubptr);
  906.       if (lubptr is null or lubptr = 0) then return; end if;
  907.       tSubName := normalName(subname);
  908.       genStub(lubptr);
  909.       if (e_defaultVal) then
  910.         status := s_defaultVal;
  911.       end if;
  912.  
  913.     exception   -- stubText, stubSpec reset to null
  914.       when value_error then
  915.         status := s_stubTooLong;
  916.       when e_other then
  917.         status := s_other;
  918.       when program_error then
  919.         status := s_logic;
  920.       when e_notInPackage then
  921.         status := s_notInPackage;
  922.       when e_notv6compat then
  923.         status := s_notv6Compat;
  924.       when others then
  925.         status := s_other;
  926.     end;
  927.  
  928.     flushstubs(true);
  929.  
  930.   end pstub;
  931.  
  932.  
  933.   -----------------------------------------------------------------------
  934.   --     Private implementations
  935.   -----------------------------------------------------------------------
  936.  
  937.  
  938.   --------------------
  939.   -- exprText:
  940.   --  General unparsing function
  941.   --------------------
  942.   procedure exprText(x ptnod, rv IN OUT varchar2) is
  943.  
  944.     --------------------
  945.     -- eText:
  946.     --------------------
  947.     procedure eText(n ptnod);
  948.  
  949.     --------------------
  950.     -- listText
  951.     --------------------
  952.     procedure listText(seq pidl.ptseqnd, spc varchar2) is
  953.       len integer;
  954.     begin
  955.       len := pidl.ptslen(seq);
  956.       if (len >= 1) then
  957.         eText(pidl.ptgend(seq, 0));
  958.         len := len - 1;
  959.         for i in 1..len loop
  960.           rv := rv || spc;
  961.           eText(pidl.ptgend(seq, i));
  962.         end loop;
  963.       end if;
  964.     end;
  965.  
  966.     --------------------
  967.     -- eText:
  968.     --------------------
  969.     procedure eText(n ptnod) is
  970.       nKind pidl.ptnty;
  971.     begin
  972.       if (n is not null) then
  973.         nKind := pidl.ptkin(n);
  974.  
  975.         -- simple expr
  976.         if (nKind = diana.DI_U_NAM or nKind = diana.D_USED_B
  977.         or nKind = diana.DI_U_BLT or nKind = diana.DI_FUNCT
  978.         or nKind = diana.DI_PROC or nKind = diana.DI_PACKA
  979.         or nKind = diana.DI_VAR or nKind = diana.DI_TYPE
  980.         or nKind = diana.DI_SUBTY or nKind = diana.DI_IN
  981.         or nKind = diana.DI_OUT or nKind = diana.DI_IN_OU) then
  982.           rv := rv ||  coatName(diana.l_symrep(n));
  983.         elsif (nKind = diana.D_S_ED) then
  984.           -- x.y
  985.           eText(diana.a_name(n));
  986.           rv := rv || '.';
  987.           eText(diana.a_d_char(n));
  988.         elsif (nKind = diana.D_STRING or nKind = diana.D_USED_C 
  989.         or nKind = diana.D_DEF_OP) then
  990.           rv := rv || '''' || diana.l_symrep(n) || '''';
  991.         elsif (nKind = diana.D_ATTRIB) then
  992.           -- x.y%type
  993.           -- simply add the %type text rather than try to resolve
  994.           -- it to get the name of the type
  995.           --
  996.           eText(diana.a_name(n));
  997.           rv := rv || '%';
  998.           eText(diana.a_id(n));
  999.  
  1000.         /*
  1001.         -- 14jul92 =G=> Many of these remaining cases by An work,
  1002.         -- but aren't needed.
  1003.  
  1004.         elsif (nKind = diana.D_NUMERI) then
  1005.           rv := rv ||  diana.l_numrep(n);
  1006.         elsif (nKind = diana.D_NULL_A) then
  1007.           rv := rv ||  'null';
  1008.  
  1009.         -- implicit conversion
  1010.         elsif (nKind = diana.D_PARM_C) then
  1011.           declare seq pidl.ptseqnd := diana.as_list(diana.as_p_ass(n));
  1012.           begin
  1013.             eText(last_elt(seq));
  1014.           end; 
  1015.  
  1016.           -- arglist
  1017.           elsif (nKind = diana.DS_APPLY) then
  1018.             declare aseq ptnod := diana.as_list(n); begin
  1019.               rv := rv || '(';
  1020.               listText(aseq, ',');
  1021.               rv := rv || ')';
  1022.             end;
  1023.  
  1024.           -- d_f_call
  1025.           elsif (nKind = diana.D_F_CALL) then
  1026.             declare args ptnod := diana.as_p_ass(n);
  1027.             begin
  1028.               if (pidl.ptkin(args) <> diana.DS_PARAM) then
  1029.                 -- ordinary function call
  1030.                 eText(diana.a_name(n));
  1031.                 eText(args);
  1032.               else  -- operator functions, determine if unary or n-ary
  1033.                 declare s pidl.ptseqnd := diana.as_list(args);
  1034.                   nameNode ptnod := diana.a_name(n);
  1035.                 begin
  1036.                   if (pidl.ptslen(s) = 1) then -- unary
  1037.                     eText(nameNode);
  1038.                     rv := rv || ' ';
  1039.                     eText(pidl.ptgend(s, 0));
  1040.                   else exprText(nameNode, rv); listText(s, rv);
  1041.                   end if;
  1042.                 end;
  1043.               end if;
  1044.             end;
  1045.  
  1046.           -- parenthesized expr
  1047.           elsif (nKind = diana.D_PARENT) then
  1048.             rv := rv || '(';
  1049.             eText(diana.a_exp(n));
  1050.             rv := rv || ')';
  1051.  
  1052.           -- binary logical operation
  1053.           elsif (nKind = diana.D_BINARY) then
  1054.             eText(diana.a_exp1(n));
  1055.             rv := rv || ' '; 
  1056.             eText(diana.a_binary(n));
  1057.             rv := rv || ' '; 
  1058.             eText(diana.a_exp2(n));
  1059.           elsif (nKind = diana.D_AND_TH) then
  1060.             rv := rv || 'and';
  1061.           elsif (nKind = diana.D_OR_ELS) then
  1062.             rv := rv || 'or';
  1063.  
  1064.           elsif (nKind = diana.DS_ID) then  -- idList
  1065.             -- listText(diana.as_list(n), ','); causes PL/SQL Check #21037.
  1066.             declare seq pidl.ptseqnd := diana.as_list(n);
  1067.             begin       
  1068.               rv := rv || coatName(diana.l_symrep(last_elt(seq)));
  1069.             end;
  1070.  
  1071.           elsif (nKind = diana.DS_D_RAN) then
  1072.             declare seq pidl.ptseqnd := diana.as_list(n);
  1073.               x ptnod;
  1074.             begin
  1075.               x := last_elt(seq);
  1076.               eText(diana.a_name(x));
  1077.             end;
  1078.  
  1079.           -- declarations
  1080.           elsif (nKind = diana.D_VAR or nKind = diana.D_CONSTA) then 
  1081.             -- var and const
  1082.             eText(diana.as_id(n));
  1083.             rv := rv || ' ';
  1084.             if (nKind = diana.D_CONSTA) then
  1085.               rv := rv || 'constant ';
  1086.             end if;
  1087.             eText(diana.a_type_s(n));
  1088.             if (diana.a_object(n) is not null and diana.a_object(n) <> 0) then
  1089.               rv := rv || ' := ';
  1090.               eText(diana.a_object(n));
  1091.             else assert(nKind <> diana.D_CONSTA);
  1092.             end if;
  1093.  
  1094.           elsif (nKind = diana.D_CONSTR) then  -- constraint
  1095.             eText(diana.a_name(n));
  1096.             if (diana.a_constt(n) is not null and diana.a_constt(n) <> 0) then
  1097.               rv := rv || ' ';
  1098.               eText(diana.a_constt(n));
  1099.             end if;
  1100.           elsif (nKind = diana.D_INTEGE) then
  1101.             eText(diana.a_range(n));
  1102.           elsif (nKind = diana.D_RANGE) then
  1103.             if (diana.a_exp1(n) is not null and diana.a_exp1(n) <> 0) then
  1104.               -- in case of array single index;
  1105.               rv := rv || 'range ';
  1106.               eText(diana.a_exp1(n));
  1107.               rv := rv || '..';
  1108.             end if;
  1109.             eText(diana.a_exp2(n));
  1110.  
  1111.           elsif (nKind = diana.D_TYPE) then -- type declaration
  1112.             rv := rv || 'type ';
  1113.             eText(diana.a_id(n));
  1114.             if (diana.a_type_s(n) is not null and diana.a_type_s(n) <> 0) then
  1115.               rv := rv || ' is ';
  1116.               eText(diana.a_type_s(n));
  1117.             end if;
  1118.           elsif (nKind = diana.D_SUBTYP) then -- subtype declaration
  1119.             rv := rv || 'subtype ';
  1120.             eText(diana.a_id(n));
  1121.             rv := rv || ' is ';
  1122.             eText(diana.a_constd(n));
  1123.           elsif (nKind = diana.D_R_) then -- record type
  1124.             rv := rv || 'record (';
  1125.             -- listText(diana.as_list(n), ','); causes PL/SQL Check #21037.
  1126.             declare seq pidl.ptseqnd := diana.as_list(n);
  1127.             begin
  1128.               listText(seq, ', ');
  1129.             end;
  1130.             rv := rv || ')';
  1131.           elsif (nKind = diana.D_ARRAY) then
  1132.             rv := rv || 'table of ';
  1133.             eText(diana.a_name(diana.a_constd(n)));
  1134.             rv := rv || '(';
  1135.             eText(diana.a_constt(diana.a_constd(n)));
  1136.             rv := rv || ') indexed by ';
  1137.             eText(diana.as_dscrt(n));
  1138.           elsif (nKind = diana.D_EXCEPT) then
  1139.             eText(diana.as_id(n));
  1140.             rv := rv || ' exception';
  1141.  
  1142.           */
  1143.  
  1144.           else
  1145.             raise e_notv6compat;
  1146.         end if;
  1147.  
  1148.       end if;
  1149.     end eText;
  1150.  
  1151.   begin -- exprText
  1152.     eText(x);
  1153.   end exprText;
  1154.  
  1155.  
  1156.   --------------------
  1157.   -- is_v6_type
  1158.   --
  1159.   -- check whether given D_NAME node (from an a_NAME(parm)) names a
  1160.   -- v6-compatible type, e.g., DATE, NUMBER, or CHAR
  1161.   --------------------
  1162.   function is_v6_type (typenode ptnod) return boolean is
  1163.     typename varchar2(100);
  1164.   begin
  1165.     typename := '';
  1166.     exprText(typenode, typename);
  1167.     typename := ltrim(rtrim(typename));
  1168.     if  (typename = '' or typename is null) or
  1169.     not (   typename = 'DATE'
  1170.          or typename = 'NUMBER'
  1171.          or typename = 'BINARY_INTEGER'
  1172.          or typename = 'PLS_INTEGER'
  1173.          or typename = 'CHAR'
  1174.          or typename = 'VARCHAR2'
  1175.          or typename = 'VARCHAR'
  1176.          or typename = 'INTEGER'
  1177.          or typename = 'BOOLEAN'
  1178.          or substr(typename, -5, 5) = '%TYPE'
  1179.  
  1180.     --   or typename = 'RAW'
  1181.     --   or typename = 'CHARN'
  1182.     --   or typename = 'STRING'
  1183.     --   or typename = 'STRINGN'
  1184.     --   or typename = 'DATEN'
  1185.     --   or typename = 'NUMBERN'
  1186.     --   or typename = 'PLS_INTEGERN'
  1187.     --   or typename = 'NATURAL'
  1188.     --   or typename = 'NATURALN'
  1189.     --   or typename = 'POSITIVE'
  1190.     --   or typename = 'POSITIVEN'
  1191.     --   or typename = 'SIGNTYPE'
  1192.     --   or typename = 'BOOLEANN'
  1193.     --   or typename = 'REAL'
  1194.     --   or typename = 'DECIMAL'
  1195.     --   or typename = 'FLOAT'
  1196.         )
  1197.     then
  1198.       return false;
  1199.     else
  1200.       return true;
  1201.     end if;
  1202.   end is_v6_type;
  1203.  
  1204.  
  1205.   --------------------
  1206.   -- genProcSpec:
  1207.   --  Append the spec for a top-level node n to sText.
  1208.   --  ignoreDefVal controls whether parm default vals should be ignored.
  1209.   --  hasDefVal returned true iff parm default vals exist.
  1210.   --  Toplevel name returned in pName.  If function, function
  1211.   --  string returned in returnVal.
  1212.   --------------------
  1213.   procedure genProcSpec(n ptnod,
  1214.                         ignoreDefVal boolean,
  1215.                         hasDefVal in out boolean,
  1216.                         pName in out varchar2, 
  1217.                         returnVal in out varchar2,
  1218.                         flags varchar2,
  1219.                         sText in out varchar2) is
  1220.     nodeKind pidl.ptnty;
  1221.     leftChild ptnod;
  1222.     rightChild ptnod;
  1223.     returnTypeNode ptnod;
  1224.  
  1225.     --------------------
  1226.     -- genParmText
  1227.     --------------------
  1228.     procedure genParmText(parmSeq pidl.ptseqnd) is
  1229.       -- append text for param list sText
  1230.       parmNum natural;
  1231.       k ptnod;
  1232.       knd pidl.ptnty;
  1233.     begin
  1234.       parmNum := pidl.ptslen(parmSeq);
  1235.       if (parmNum > 0) then
  1236.         sText := sText || ' (';
  1237.         for i in 1 .. parmNum loop
  1238.           k := pidl.ptgend(parmSeq, i-1);
  1239.           assert(k is not null);
  1240.           sText := sText || idName(diana.as_id(k)) || ' ';
  1241.           knd := pidl.ptkin(k);
  1242.           if (knd = diana.D_OUT) then
  1243.             sText := sText || 'out ';
  1244.           elsif (knd = diana.D_IN_OUT) then
  1245.             sText := sText || 'in out ';
  1246.           else
  1247.             assert(knd = diana.D_IN);
  1248.           end if;
  1249.           exprText(diana.a_name(k), sText);
  1250.  
  1251.           if 0 < instr(flags, '6') and not is_v6_type(diana.a_name(k)) then
  1252.             raise e_notv6compat;
  1253.           end if;
  1254.  
  1255.           k := diana.a_exp_vo(k);
  1256.           if (k is not null and k <> 0) then
  1257.             hasDefVal := TRUE;
  1258.             if (not ignoreDefVal) then
  1259.               sText := sText || ' := ';
  1260.               exprText(k, sText);
  1261.             end if;
  1262.           end if;
  1263.  
  1264.           if (i < parmNum) then
  1265.             sText := sText || ', ';
  1266.           end if;
  1267.         end loop;
  1268.  
  1269.       sText := sText || ')';
  1270.       end if;
  1271.     end genParmText;
  1272.  
  1273.   begin -- genProcSpec
  1274.     -- generate a procedure declaration into sText spec
  1275.  
  1276.     returnVal := '';
  1277.     assert(n is not null);
  1278.     leftChild := diana.a_d_(n);
  1279.     assert(leftChild is not null);
  1280.     nodeKind := pidl.ptkin(leftChild);
  1281.  
  1282.     rightChild := diana.a_header(n);
  1283.     if (nodeKind = diana.DI_FUNCT or nodeKind = diana.D_DEF_OP) then
  1284.       sText := sText || 'function ';
  1285.       returnTypeNode := diana.a_name_v(rightChild);
  1286.       exprText(returnTypeNode, returnVal);
  1287.       -- ?? returnVal := substr(exprText(diana.a_name_v(rightChild)), 1, 511);
  1288.     else
  1289.       sText := sText || 'procedure ';
  1290.       returnVal := null;
  1291.       assert(nodeKind = diana.DI_PROC);
  1292.     end if;
  1293.     if (pName is null) then
  1294.       exprText(leftChild, pName);
  1295.     end if;
  1296.     sText := sText || pName;
  1297.  
  1298.     rightChild := diana.as_p_(rightChild);
  1299.     assert(rightChild is not null);
  1300.     genParmText(diana.as_list(rightChild));
  1301.  
  1302.     if (returnVal is not null) then
  1303.       if 0 < instr(flags, '6') and not is_v6_type(returnTypeNode) 
  1304.         then raise e_notv6compat;
  1305.       end if;
  1306.       sText := sText || ' return ' || returnVal;
  1307.     end if;
  1308.   end genProcSpec;
  1309.  
  1310.   --------------------
  1311.   -- bool_to_int
  1312.   --------------------
  1313.   function bool_to_int(b BOOLEAN) return number is
  1314.   begin
  1315.     if b then
  1316.       return 1;
  1317.     elsif not b then
  1318.       return 0;
  1319.     else
  1320.       return NULL;
  1321.     end if;
  1322.   end bool_to_int;
  1323.  
  1324.   --------------------
  1325.   -- int_to_bool
  1326.   --------------------
  1327.   function int_to_bool(n NUMBER) return boolean is
  1328.   begin
  1329.     if n is null then
  1330.       return NULL;
  1331.     elsif n = 1 then
  1332.       return TRUE;
  1333.     elsif n = 0 then
  1334.       return FALSE;
  1335.     else
  1336.       raise VALUE_ERROR;
  1337.     end if;
  1338.   end int_to_bool;
  1339.  
  1340. end diutil;
  1341. /
  1342.  
  1343. grant execute on diutil to public;
  1344.