home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1996 February / PCWK0296.iso / po7_win / db / rdbms71 / diutil.sql < prev    next >
Encoding:
Text File  |  1994-08-04  |  42.5 KB  |  1,342 lines

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