DBA Data[Home] [Help]

PACKAGE BODY: SYS.DIUTIL

Source


1 PACKAGE BODY     diutil IS
2 
3   defvaloption_ignore CONSTANT NUMBER := 0;
4   defvaloption_full CONSTANT NUMBER := 1;
5   defvaloption_default_comment CONSTANT NUMBER := 2;
6 
7   -----------------------
8   --  PRIVATE members
9   -----------------------
10 
11   PROCEDURE diugdn(name VARCHAR2, usr VARCHAR2, dbname VARCHAR2,
12                    dbowner VARCHAR2, status OUT ub4, nod OUT ptnod,
13                    libunit_type BINARY_INTEGER,
14                    load_source BINARY_INTEGER);
15     PRAGMA interface(c,diugdn);
16   PROCEDURE diustx(n ptnod, txt OUT VARCHAR2, status OUT ub4);
17     PRAGMA interface(c,diustx);
18 
19   assertval CONSTANT BOOLEAN := true;
20 
21   -----------------------
22   -- assert
23   -----------------------
24   PROCEDURE assert(v BOOLEAN, str VARCHAR2) IS
25     x INTEGER;
26   BEGIN
27     IF (assertval AND NOT v) THEN
28       RAISE program_error;
29     END IF;
30   END assert;
31 
32   -----------------------
33   -- assert
34   -----------------------
35   PROCEDURE assert(v BOOLEAN) IS
36   BEGIN
37     assert(v, '');
38   END;
39 
40   -----------------------
41   -- last_elt
42   -----------------------
43   FUNCTION last_elt (seq pidl.ptseqnd) RETURN pidl.ptnod IS
44     len BINARY_INTEGER;
45   BEGIN
46     len := pidl.ptslen(seq);
47     assert(len > 0);
48     RETURN pidl.ptgend(seq, len - 1);
49   END last_elt;
50 
51   -----------------------
52   -- normalname: RETURN a normalized name.  fold up IF NOT IN quotes,
53   -- ELSE strip quotes.
54   -----------------------
55   FUNCTION normalname(name VARCHAR2) RETURN VARCHAR2 IS
56     firstchar VARCHAR2(4);
57     len NUMBER;
58   BEGIN
59     IF (name IS NULL OR name = '') THEN RETURN name; END IF;
60     firstchar := substr(name, 1, 1);
61     IF (firstchar = '"') THEN
62       len := length(name);
63       IF (len > 1 AND substr(name, len, 1) = '"') THEN
64         IF (len > 33) THEN
65           len := 31;
66         ELSE
67           len := len-2;
68         END IF;
69         RETURN substr(name, 2, len);
70       END IF;
71      END IF;
72      RETURN upper(name);
73   END normalname;
74 
75   -----------------------
76   -- coatname: enquote name IF necessary
77   -----------------------
78   FUNCTION coatname(name VARCHAR2) RETURN VARCHAR2 IS
79   BEGIN
80     IF (name <> upper(name)) THEN
81       RETURN '"' || name || '"';
82     ELSIF char_for_varchar2 AND name = 'VARCHAR2' THEN
83       RETURN 'CHAR';
84     ELSE
85       RETURN name;
86     END IF;
87   END coatname;
88 
89   -----------------------
90   -- idname
91   -----------------------
92   FUNCTION idname(n ptnod) RETURN VARCHAR2 IS
93     -- RETURN the text OF an id node.  this FUNCTION IS also
94     -- used TO limit the recursion IN exprtext() below.
95     -- should have the semantics OF listtext(diana.as_list(n), ',');
96     seq pidl.ptseqnd;
97   BEGIN
98     assert(pidl.ptkin(n) = diana.ds_id);
99     seq := diana.as_list(n);
100     RETURN coatname(diana.l_symrep(last_elt(seq)));
101   END idname;
102 
103   -----------------------
104   -- exprtext: general unparsing FUNCTION
105   -----------------------
106   PROCEDURE exprtext(x ptnod, rv IN OUT VARCHAR2);
107 
108   -----------------------
109   -- genprocspec
110   --  append the spec FOR a top-LEVEL node n TO stext.
111   --  defvaloption controls whether parm DEFAULT vals should be ignored,
112   --    printed fully OR flagged IN comments AS "defaulted"
113   --  hasdefval returned true iff parm DEFAULT vals exist.
114   --  toplevel name returned IN pname.
115   --  IF FUNCTION, FUNCTION STRING returned IN returnval.
116   -----------------------
117   PROCEDURE genprocspec(n ptnod,
118                         defvaloption NUMBER,
119                         hasdefval IN OUT BOOLEAN,
120                         pname IN OUT VARCHAR2,
121                         returnval IN OUT VARCHAR2,
122                         flags VARCHAR2,
123                         stext IN OUT VARCHAR2);
124 
125 
126   -----------------------
127   -- procname
128   -----------------------
129   FUNCTION procname(k ptnod) RETURN VARCHAR2 IS
130     x ptnod; xkind pidl.ptnty;
131   BEGIN
132     IF (k IS NULL OR k = 0) THEN RETURN NULL; END IF;
133     IF (pidl.ptkin(k) <> diana.d_s_decl) THEN RETURN NULL; END IF;
134     x := diana.a_d_(k);
135     xkind := pidl.ptkin(x);
136     IF (    xkind <> diana.di_funct
137         AND xkind <> diana.di_proc
138         AND xkind <> diana.d_def_op) THEN
139       RETURN NULL;
140     END IF;
141     RETURN diana.l_symrep(x);
142   END;
143 
144 
145   -----------------------
146   --  PRIVATE members
147   -----------------------
148 
149 
150   -----------------------
151   -- get_d
152   -----------------------
153   PROCEDURE get_d (name VARCHAR2, usr VARCHAR2, dbname VARCHAR2,
154                    dbowner VARCHAR2, status IN OUT ub4, nod OUT ptnod,
155                    libunit_type NUMBER := libunit_type_spec,
156                    load_source NUMBER := load_source_no) IS
157     nname VARCHAR2(100);
158     nusr VARCHAR2(100);
159     ndbname VARCHAR2(100);
160     ndbowner VARCHAR2(100);
161   BEGIN -- get_d
162     nod := NULL;
163     BEGIN
164       nname := normalname(name);
165       nusr := normalname(usr);
166       ndbname := normalname(dbname);
167       ndbowner := normalname(dbowner);
168       IF (nname IS NULL OR nname = '') THEN
169         RAISE e_subpnotfound;
170       END IF;
171       diugdn(nname, nusr, ndbname, ndbowner, status, nod,
172              libunit_type, load_source);
173 
174       IF (status = 1) THEN
175         diugdn(nname, '', ndbname, ndbowner, status, nod,
176                libunit_type, load_source);
177       END IF;
178 
179       IF (status = 1) THEN
180         RAISE e_subpnotfound;
181       ELSIF (status = 2) THEN
182         RAISE e_nopriv;
183       ELSIF (status <> 0) THEN
184         RAISE e_other;
185       END IF;
186       status := s_ok;
187     EXCEPTION
188       WHEN e_subpnotfound THEN
189         status := s_subpnotfound;
190       WHEN e_nopriv THEN
191         status := s_subpnotfound;
192       WHEN OTHERS THEN
193         status := s_other;
194     END;
195   END get_d;
196 
197   -----------------------
198   -- get_diana
199   -----------------------
200   PROCEDURE get_diana (name VARCHAR2, usr VARCHAR2, dbname VARCHAR2,
201                        dbowner VARCHAR2,
202                        status IN OUT ub4, nod IN OUT ptnod,
203                        libunit_type NUMBER := libunit_type_spec,
204                        load_source NUMBER := load_source_no) IS
205     t ptnod;
206   BEGIN -- get_diana
207     nod := NULL;
208     BEGIN
209       get_d(name, usr, dbname, dbowner, status, nod,
210             libunit_type, load_source);
211       IF (status = s_ok) THEN
212         t := diana.a_unit_b(nod);
213         assert(pidl.ptkin(t) <> diana.q_create);
214       END IF;
215     EXCEPTION
216       WHEN program_error THEN
217         status := s_other;
218       WHEN OTHERS THEN
219         status := s_other;
220     END;
221   END get_diana;
222 
223 
224   -----------------------
225   -- subptxt
226   -----------------------
227   PROCEDURE subptxt(name VARCHAR2, subname VARCHAR2, usr VARCHAR2,
228                     dbname VARCHAR2, dbowner VARCHAR2, txt IN OUT VARCHAR2,
229                     status IN OUT ub4) IS
230     e_defaultval BOOLEAN := false;
231 
232     -----------------------
233     -- describeproc
234     -----------------------
235     PROCEDURE describeproc(n ptnod, s IN OUT VARCHAR2) IS
236       tmpval VARCHAR2(100);
237       rval VARCHAR2(500);
238     BEGIN -- describeproc
239       -- we call genprocspec here because it IS NOT
240       -- possible TO get the text reliably FOR arbitrary node
241       -- through diustx
242       --
243       tmpval := NULL;
244       genprocspec(n, defvaloption_default_comment,
245                   e_defaultval, tmpval, rval, '', s);
246       s := s || '; ';
247     END describeproc;
248 
249   BEGIN -- subptxt
250     txt := '';
251 
252     DECLARE
253       troot ptnod;
254       n ptnod;
255       nsubname VARCHAR2(100);
256     BEGIN
257       get_diana(name, usr, dbname, dbowner, status, troot,
258                 libunit_type_spec, load_source_yes);
259       IF (troot IS NULL OR troot = 0) THEN RETURN; END IF;
260 
261       nsubname := normalname(subname);
262       n := diana.a_unit_b(troot);
263 
264       IF (nsubname IS NULL OR nsubname = '') THEN
265         IF ((pidl.ptkin(n) = diana.d_p_decl) OR
266             (pidl.ptkin(n) = diana.d_library)) THEN
267           diustx(troot, txt, status);
268         ELSE
269           describeproc(n, txt);
270         END IF;
271       ELSE
272         -- search FOR subname among ALL func/proc IN the PACKAGE
273         IF (pidl.ptkin(n) <> diana.d_p_decl) THEN
274           status := s_subpnotfound;
275           RETURN;
276         END IF;
277         n := diana.a_packag(n);
278         DECLARE
279           seq pidl.ptseqnd := diana.as_list(diana.as_decl1(n));
280           len INTEGER := pidl.ptslen(seq) - 1;
281           tmp INTEGER;
282         BEGIN
283           FOR i IN 0..len LOOP --FOR each MEMBER OF the PACKAGE
284             n := pidl.ptgend(seq, i);
285             IF (procname(n) = nsubname) THEN
286               describeproc(n, txt);
287             END IF;
288           END LOOP;
289         END;
290         IF (txt IS NULL OR txt = '') THEN
291           status := s_notinpackage;
292         END IF;
293       END IF;
294 
295     EXCEPTION   -- txt reset TO NULL
296       WHEN value_error THEN
297         status := s_stubtoolong;
298       WHEN program_error THEN
299         status := s_logic;
300       WHEN e_other THEN
301         status := s_other;
302       WHEN OTHERS THEN
303         status := s_other;
304     END;
305   END subptxt;
306 
307 
308   -----------------------------------------------------------------------
309   --     PRIVATE implementations
310   -----------------------------------------------------------------------
311 
312 
313   --------------------
314   -- exprtext:
315   --  general unparsing FUNCTION
316   --------------------
317   PROCEDURE exprtext(x ptnod, rv IN OUT VARCHAR2) IS
318 
319     --------------------
320     -- etext:
321     --------------------
322     PROCEDURE etext(n ptnod);
323 
324     --------------------
325     -- listtext
326     --------------------
327     PROCEDURE listtext(seq pidl.ptseqnd, spc VARCHAR2) IS
328       len INTEGER;
329     BEGIN
330       len := pidl.ptslen(seq);
331       IF (len >= 1) THEN
332         etext(pidl.ptgend(seq, 0));
333         len := len - 1;
334         FOR i IN 1..len LOOP
335           rv := rv || spc;
336           etext(pidl.ptgend(seq, i));
337         END LOOP;
338       END IF;
339     END;
340 
341     --------------------
342     -- etext:
343     --------------------
344     PROCEDURE etext(n ptnod) IS
345       nkind pidl.ptnty;
346     BEGIN
347       IF (n IS NOT NULL) THEN
348         nkind := pidl.ptkin(n);
349         -- simple expr
350         IF (nkind = diana.di_u_nam OR nkind = diana.d_used_b
351         OR nkind = diana.di_u_blt OR nkind = diana.di_funct
352         OR nkind = diana.di_proc OR nkind = diana.di_packa
353         OR nkind = diana.di_var OR nkind = diana.di_type
354         OR nkind = diana.di_subty OR nkind = diana.di_in
355         OR nkind = diana.di_out OR nkind = diana.di_in_ou) THEN
356           rv := rv ||  coatname(diana.l_symrep(n));
357 
358         ELSIF (nkind = diana.d_s_ed) THEN
359           -- x.y
360           etext(diana.a_name(n));
361           rv := rv || '.';
362           etext(diana.a_d_char(n));
363 
364         ELSIF (nkind = diana.d_string OR nkind = diana.d_used_c
365         OR nkind = diana.d_def_op) THEN
366           rv := rv || '''' || diana.l_symrep(n) || '''';
367 
368         ELSIF (nkind = diana.d_attrib) THEN
369           -- x.y%TYPE
370           -- simply ADD the %TYPE text rather than try TO resolve
371           -- it TO get the name OF the TYPE
372           --
373           etext(diana.a_name(n));
374           rv := rv || '%';
375           etext(diana.a_id(n));
376 
377         ELSIF (nkind = diana.d_numeri) THEN
378           rv := rv ||  diana.l_numrep(n);
379 
380         ELSIF (nkind = diana.d_null_a) THEN
381           rv := rv ||  'null';
382 
383         ELSIF (nkind = diana.d_constr) THEN  -- constraint
384           etext(diana.a_name(n));
385           -- -- Function params and returns do not accept constraints directly.
389           -- END IF;
386           -- IF (diana.a_constt(n) IS NOT NULL AND diana.a_constt(n) <> 0) THEN
387           --   rv := rv || ' ';
388           --   etext(diana.a_constt(n));
390           IF (diana.a_constt(n) IS NOT NULL AND diana.a_constt(n) <> 0) THEN
391             RAISE e_notv6compat;
392           END IF;
393           IF (diana.a_cs(n) IS NOT NULL) THEN
394             IF ((diana.s_charset_form(diana.a_cs(n)) = 1) OR
395                 (diana.s_charset_form(diana.a_cs(n)) = 4)) THEN
396               -- SQLCS_IMPLICIT: don't need to mark anything.
397               -- SQLCS_FLEXIBLE: for now, don't mark anything.  If we ever
398               --   need to support v8 clients, for those we'd want marking.
399               NULL;
400             ELSE
401               -- SQLCS_NCHAR and SQLCS_EXPLICIT cases are not usable by v6
402               --   or v7 clients.  SQLCS_LIT_NULL should never occur as the
403               --   type of a formal or result.  Anything else is really bogus.
404               RAISE e_notv6compat;
405             END IF;
406           END IF;
407 
408         /*
409         -- 14jul92 =g=> many OF these remaining cases BY an work,
410         -- but aren't needed.
411 
412         -- implicit conversion
413         ELSIF (nkind = diana.d_parm_c) THEN
414           DECLARE seq pidl.ptseqnd := diana.as_list(diana.as_p_ass(n));
415           BEGIN
416             etext(last_elt(seq));
417           END;
418 
419         -- arglist
420         ELSIF (nkind = diana.ds_apply) THEN
421           DECLARE aseq ptnod := diana.as_list(n); BEGIN
422             rv := rv || '(';
423             listtext(aseq, ',');
424             rv := rv || ')';
425           END;
426 
427         -- d_f_call
428         ELSIF (nkind = diana.d_f_call) THEN
429           DECLARE args ptnod := diana.as_p_ass(n);
430           BEGIN
431             IF (pidl.ptkin(args) <> diana.ds_param) THEN
432               -- ordinary function call
433               etext(diana.a_name(n));
434               etext(args);
435             ELSE  -- operator functions, determine if unary or n-ary
436               DECLARE s pidl.ptseqnd := diana.as_list(args);
437                 namenode ptnod := diana.a_name(n);
438               BEGIN
439                 IF (pidl.ptslen(s) = 1) THEN -- unary
440                   etext(namenode);
441                   rv := rv || ' ';
442                   etext(pidl.ptgend(s, 0));
443                 ELSE exprtext(namenode, rv); listtext(s, rv);
444                 END IF;
445               END;
446             END IF;
447           END;
448 
449         -- parenthesized expr
450         -- whenever this gets uncommented, we must fully support the
451         -- D_F_CALL case as well (Usha - 6/28/95)
452         ELSIF (nkind = diana.d_parent) THEN
453           rv := rv || '(';
454           etext(diana.a_exp(n));
455           rv := rv || ')';
456 
457         -- binary logical operation
458         ELSIF (nkind = diana.d_binary) THEN
459           etext(diana.a_exp1(n));
460           rv := rv || ' ';
461           etext(diana.a_binary(n));
462           rv := rv || ' ';
463           etext(diana.a_exp2(n));
464         ELSIF (nkind = diana.d_and_th) THEN
465           rv := rv || 'and';
466         ELSIF (nkind = diana.d_or_els) THEN
467           rv := rv || 'or';
468 
469         ELSIF (nkind = diana.ds_id) THEN  -- idList
470           -- listText(diana.as_list(n), ','); causes PL/SQL Check #21037.
471           DECLARE seq pidl.ptseqnd := diana.as_list(n);
472           BEGIN
473             rv := rv || coatname(diana.l_symrep(last_elt(seq)));
474           END;
475 
476         ELSIF (nkind = diana.ds_d_ran) THEN
477           DECLARE seq pidl.ptseqnd := diana.as_list(n);
478             x ptnod;
479           BEGIN
480             x := last_elt(seq);
481             etext(diana.a_name(x));
482           END;
483 
484         -- declarations
485         ELSIF (nkind = diana.d_var OR nkind = diana.d_consta) THEN
486           -- var and const
487           etext(diana.as_id(n));
488           rv := rv || ' ';
489           IF (nkind = diana.d_consta) THEN
490             rv := rv || 'constant ';
491           END IF;
492           etext(diana.a_type_s(n));
493           IF (diana.a_object(n) IS NOT NULL AND diana.a_object(n) <> 0) THEN
494             rv := rv || ' := ';
495             etext(diana.a_object(n));
496           ELSE assert(nkind <> diana.d_consta);
497           END IF;
498 
499         ELSIF (nkind = diana.d_intege) THEN
500           etext(diana.a_range(n));
501         ELSIF (nkind = diana.d_range) THEN
502           IF (diana.a_exp1(n) IS NOT NULL AND diana.a_exp1(n) <> 0) THEN
503             -- in case of array single index;
504             rv := rv || 'range ';
505             etext(diana.a_exp1(n));
506             rv := rv || '..';
507           END IF;
508           etext(diana.a_exp2(n));
509 
510         ELSIF (nkind = diana.d_type) THEN -- type declaration
511           rv := rv || 'type ';
512           etext(diana.a_id(n));
513           IF (diana.a_type_s(n) IS NOT NULL AND diana.a_type_s(n) <> 0) THEN
514             rv := rv || ' is ';
515             etext(diana.a_type_s(n));
516           END IF;
517         ELSIF (nkind = diana.d_subtyp) THEN -- subtype declaration
518           rv := rv || 'subtype ';
519           etext(diana.a_id(n));
520           rv := rv || ' is ';
521           etext(diana.a_constd(n));
522         ELSIF (nkind = diana.d_r_) THEN -- record type
523           rv := rv || 'record (';
524           -- listText(diana.as_list(n), ','); causes PL/SQL Check #21037.
525           DECLARE seq pidl.ptseqnd := diana.as_list(n);
529           rv := rv || ')';
526           BEGIN
527             listtext(seq, ', ');
528           END;
530         ELSIF (nkind = diana.d_array) THEN
531           rv := rv || 'table of ';
532           etext(diana.a_name(diana.a_constd(n)));
533           rv := rv || '(';
534           etext(diana.a_constt(diana.a_constd(n)));
535           rv := rv || ') indexed by ';
536           etext(diana.as_dscrt(n));
537         ELSIF (nkind = diana.d_except) THEN
538           etext(diana.as_id(n));
539           rv := rv || ' exception';
540 
541         */
542 
543         ELSE
544           RAISE e_notv6compat;
545         END IF;
546 
547       END IF;
548     END etext;
549 
550   BEGIN -- exprText
551     etext(x);
552   END exprtext;
553 
554 
555   --------------------
556   -- is_v6_type
557   --
558   -- check whether given D_NAME node (from an a_NAME(parm)) names a
559   -- v6-compatible type, e.g., DATE, NUMBER, or CHAR
560   --------------------
561   FUNCTION is_v6_type (typenode ptnod) RETURN BOOLEAN IS
562     typename VARCHAR2(100);
563     percenttype BOOLEAN;
564   BEGIN
565     typename := '';
566     exprtext(typenode, typename);
567     typename := ltrim(rtrim(typename));
568     percenttype := ( length(typename) > 5 AND
569                     substr(typename, -5, 5) = '%TYPE' );
570     /* check length as else will get null as substr result */
571     IF  (typename = '' OR typename IS NULL) OR
572     NOT (   typename = 'DATE'
573          OR typename = 'NUMBER'
574          OR typename = 'BINARY_INTEGER'
575          OR typename = 'PLS_INTEGER'
576          OR typename = 'CHAR'
577          OR typename = 'VARCHAR2'
578          OR typename = 'VARCHAR'
579          OR typename = 'INTEGER'
580          OR typename = 'BOOLEAN'
581          OR percenttype
582     --   or typename = 'RAW'
583     --   or typename = 'CHARN'
584     --   or typename = 'STRING'
585     --   or typename = 'STRINGN'
586     --   or typename = 'DATEN'
587     --   or typename = 'NUMBERN'
588     --   or typename = 'PLS_INTEGERN'
589     --   or typename = 'NATURAL'
590     --   or typename = 'NATURALN'
591     --   or typename = 'POSITIVE'
592     --   or typename = 'POSITIVEN'
593     --   or typename = 'SIGNTYPE'
594     --   or typename = 'BOOLEANN'
595     --   or typename = 'REAL'
596     --   or typename = 'DECIMAL'
597     --   or typename = 'FLOAT'
598         )
599     THEN
600       RETURN false;
601     ELSE
602       RETURN true;
603     END IF;
604   END is_v6_type;
605 
606 
607   --------------------
608   -- genProcSpec:
609   --  Append the spec for a top-level node n to sText.
610   --  defValOption controls whether parm default vals should be ignored,
611   --    printed fully or flagged in comments as "DEFAULTED"
612   --  hasDefVal returned true iff parm default vals exist.
613   --  Toplevel name returned in pName.  If function, function
614   --  string returned in returnVal.
615   --------------------
616   PROCEDURE genprocspec(n ptnod,
617                         defvaloption NUMBER,
618                         hasdefval IN OUT BOOLEAN,
619                         pname IN OUT VARCHAR2,
620                         returnval IN OUT VARCHAR2,
621                         flags VARCHAR2,
622                         stext IN OUT VARCHAR2) IS
623     nodekind pidl.ptnty;
624     leftchild ptnod;
625     rightchild ptnod;
626     returntypenode ptnod;
627 
628     --------------------
629     -- genParmText
630     --------------------
631     PROCEDURE genparmtext(parmseq pidl.ptseqnd) IS
632       -- append text for param list sText
633       parmnum NATURAL;
634       k ptnod;
635       knd pidl.ptnty;
636     BEGIN
637       parmnum := pidl.ptslen(parmseq);
638       IF (parmnum > 0) THEN
639         stext := stext || ' (';
640         FOR i IN 1 .. parmnum LOOP
641           k := pidl.ptgend(parmseq, i-1);
642           assert(k IS NOT NULL);
643           stext := stext || idname(diana.as_id(k)) || ' ';
644           knd := pidl.ptkin(k);
645           IF (knd = diana.d_out) THEN
646             stext := stext || 'out ';
647           ELSIF (knd = diana.d_in_out) THEN
648             stext := stext || 'in out ';
649           ELSE
650             assert(knd = diana.d_in);
651           END IF;
652           exprtext(diana.a_name(k), stext);
653           IF 0 < instr(flags, '6') AND NOT is_v6_type(diana.a_name(k)) THEN
654             RAISE e_notv6compat;
655           END IF;
656 
657           k := diana.a_exp_vo(k);
658           IF (k IS NOT NULL AND k <> 0) THEN
659             hasdefval := true;
660             IF defvaloption = defvaloption_full THEN
661               stext := stext || ' := ';
662               exprtext(k, stext);
663             ELSIF defvaloption = defvaloption_default_comment THEN
664               stext := stext || ' /* DEFAULTED */';
665             ELSE
666               assert(defvaloption = defvaloption_ignore);
667             END IF;
668           END IF;
669 
670           IF (i < parmnum) THEN
671             stext := stext || ', ';
672           END IF;
673         END LOOP;
674 
675       stext := stext || ')';
676       END IF;
677     END genparmtext;
678 
679   BEGIN -- genProcSpec
680     -- generate a procedure declaration into sText spec
681 
682     returnval := '';
683     assert(n IS NOT NULL);
684     leftchild := diana.a_d_(n);
685     assert(leftchild IS NOT NULL);
686     nodekind := pidl.ptkin(leftchild);
687 
688     rightchild := diana.a_header(n);
689     IF (nodekind = diana.di_funct OR nodekind = diana.d_def_op) THEN
690       stext := stext || 'function ';
691       returntypenode := diana.a_name_v(rightchild);
692       exprtext(returntypenode, returnval);
693       -- ?? returnVal := substr(exprText(diana.a_name_v(rightChild)), 1, 511);
694     ELSE
695       stext := stext || 'procedure ';
696       returnval := NULL;
697       assert(nodekind = diana.di_proc);
698     END IF;
699     IF (pname IS NULL) THEN
700       exprtext(leftchild, pname);
701     END IF;
702     stext := stext || pname;
703 
704     rightchild := diana.as_p_(rightchild);
705     assert(rightchild IS NOT NULL);
706     genparmtext(diana.as_list(rightchild));
707 
708     IF (returnval IS NOT NULL) THEN
709       IF 0 < instr(flags, '6') AND NOT is_v6_type(returntypenode)
710         THEN RAISE e_notv6compat;
711       END IF;
712       stext := stext || ' return ' || returnval;
713     END IF;
714   END genprocspec;
715 
716   --------------------
717   -- bool_to_int
718   --------------------
719   FUNCTION bool_to_int(b BOOLEAN) RETURN NUMBER IS
720   BEGIN
721     IF b THEN
722       RETURN 1;
723     ELSIF NOT b THEN
724       RETURN 0;
725     ELSE
726       RETURN NULL;
727     END IF;
728   END bool_to_int;
729 
730   --------------------
731   -- int_to_bool
732   --------------------
733   FUNCTION int_to_bool(n NUMBER) RETURN BOOLEAN IS
734   BEGIN
735     IF n IS NULL THEN
736       RETURN NULL;
737     ELSIF n = 1 THEN
738       RETURN true;
739     ELSIF n = 0 THEN
740       RETURN false;
741     ELSE
742       RAISE value_error;
743     END IF;
744   END int_to_bool;
745 
746   procedure diu_node_use_statistics (libunit_node IN ptnod,
747                                      node_count out ub4,
748                                      node_limit out ub4);
749   pragma interface(c,diu_node_use_statistics);
750 
751   procedure diu_attribute_use_statistics (libunit_node IN ptnod,
752                                           attribute_count out ub4,
753                                           attribute_limit out ub4);
754   pragma interface(c,diu_attribute_use_statistics);
755 
756   -- node_use_statistics: reports libunit's node count and limit
757   --
758   -- Parameters:
759   --
760   --   libunit_node : legal ptnod, as returned by get_diana or get_d
761   --   node_count   : how many diana nodes the unit contains
762   --   node_limit   : that many diana nodes allowed to allocate
763   --
764   procedure node_use_statistics (libunit_node IN ptnod,
765                                  node_count out ub4,
766                                  node_limit out ub4)
767   IS
768   BEGIN
769      diu_node_use_statistics(libunit_node, node_count, node_limit);
770   END node_use_statistics;
771 
772   -- attribute_use_statistics: reports libunit's attribute count and limit
773   --
774   -- Parameters:
775   --
776   --   libunit_node       : legal ptnod, as returned by get_diana or get_d
777   --   attribute_count   : how many diana attributes the unit contains
778   --   attribute_limit   : that many diana attributes allowed to allocate
779   --
780   procedure attribute_use_statistics (libunit_node IN ptnod,
781                                       attribute_count out ub4,
782                                       attribute_limit out ub4)
783   IS
784   BEGIN
785     diu_attribute_use_statistics
786       (libunit_node, attribute_count, attribute_limit);
787   END attribute_use_statistics;
788 
789 end diutil;