[project @ 2000-01-10 17:19:32 by sewardj]
[ghc-hetmet.git] / ghc / interpreter / link.c
1
2 /* --------------------------------------------------------------------------
3  * Load symbols required from the Prelude
4  *
5  * The Hugs 98 system is Copyright (c) Mark P Jones, Alastair Reid, the
6  * Yale Haskell Group, and the Oregon Graduate Institute of Science and
7  * Technology, 1994-1999, All rights reserved.  It is distributed as
8  * free software under the license in the file "License", which is
9  * included in the distribution.
10  *
11  * $RCSfile: link.c,v $
12  * $Revision: 1.31 $
13  * $Date: 2000/01/10 17:19:33 $
14  * ------------------------------------------------------------------------*/
15
16 #include "prelude.h"
17 #include "storage.h"
18 #include "backend.h"
19 #include "connect.h"
20 #include "errors.h"
21 #include "Assembler.h" /* for asmPrimOps and AsmReps */
22
23 #include "link.h"
24
25
26 Type typeArrow;                         /* Function spaces                 */
27
28 Type typeChar;
29 Type typeInt;
30 Type typeInteger;
31 Type typeWord;
32 Type typeAddr;
33 Type typePrimArray;            
34 Type typePrimByteArray;
35 Type typeRef;                  
36 Type typePrimMutableArray;     
37 Type typePrimMutableByteArray; 
38 Type typeFloat;
39 Type typeDouble;
40 Type typeStable;
41 Type typeThreadId;
42 Type typeMVar;
43 #ifdef PROVIDE_WEAK
44 Type typeWeak;
45 #endif
46 #ifdef PROVIDE_FOREIGN
47 Type typeForeign;
48 #endif
49
50 Type typeList;
51 Type typeUnit;
52 Type typeString;
53 Type typeBool;
54 Type typeST;
55 Type typeIO;
56 Type typeException;
57
58 Class classEq;                          /* `standard' classes              */
59 Class classOrd;
60 Class classShow;
61 Class classRead;
62 Class classIx;
63 Class classEnum;
64 Class classBounded;
65
66 Class classReal;                        /* `numeric' classes               */
67 Class classIntegral;
68 Class classRealFrac;
69 Class classRealFloat;
70 Class classFractional;
71 Class classFloating;
72 Class classNum;
73 Class classMonad;                       /* Monads and monads with a zero   */
74
75 List stdDefaults;                       /* standard default values         */
76
77 Name nameTrue;    
78 Name nameFalse;            /* primitive boolean constructors  */
79 Name nameNil;     
80 Name nameCons;             /* primitive list constructors     */
81 Name nameUnit;                          /* primitive Unit type constructor */
82
83 Name nameEq;    
84 Name nameFromInt;
85 Name nameFromDouble;       /* coercion of numerics            */
86 Name nameFromInteger;
87 Name nameReturn;  
88 Name nameBind;             /* for translating monad comps     */
89 Name nameZero;                          /* for monads with a zero          */
90
91 Name nameId;
92 Name nameRunIO_toplevel;
93 Name namePrint;
94
95 Name nameOtherwise;
96 Name nameUndefined;                     /* generic undefined value         */
97 #if NPLUSK
98 Name namePmSub; 
99 #endif
100 Name namePMFail;
101 Name nameEqChar;
102 Name namePmInt;
103 Name namePmInteger;
104 Name namePmDouble;
105 Name namePmLe;
106 Name namePmSubtract;
107 Name namePmFromInteger;
108 Name nameMkIO;
109 Name nameUnpackString;
110 Name nameError;
111 Name nameInd;
112 Name nameCreateAdjThunk;
113
114 Name nameAnd;
115 Name nameCompAux;
116 Name nameRangeSize;
117 Name nameComp;
118 Name nameShowField;
119 Name nameApp;
120 Name nameShowParen;
121 Name nameReadParen;
122 Name nameLex;
123 Name nameReadField;
124 Name nameFlip;
125
126 Name namePrimSeq;
127 Name namePrimCatch;
128 Name namePrimRaise;
129 Name namePrimTakeMVar;
130
131 Name nameFromTo;
132 Name nameFromThen;
133 Name nameFrom;
134 Name nameFromThenTo;
135 Name nameNegate;
136
137 /* these names are required before we've had a chance to do the right thing */
138 Name nameSel;
139 Name nameUnsafeUnpackCString;
140
141 /* constructors used during translation and codegen */
142 Name nameMkC;                           /* Char#        -> Char           */
143 Name nameMkI;                           /* Int#         -> Int            */
144 Name nameMkInteger;                     /* Integer#     -> Integer        */
145 Name nameMkW;                           /* Word#        -> Word           */
146 Name nameMkA;                           /* Addr#        -> Addr            */
147 Name nameMkF;                           /* Float#       -> Float           */
148 Name nameMkD;                           /* Double#      -> Double          */
149 Name nameMkPrimArray;            
150 Name nameMkPrimByteArray;
151 Name nameMkRef;                  
152 Name nameMkPrimMutableArray;     
153 Name nameMkPrimMutableByteArray; 
154 Name nameMkStable;                      /* StablePtr# a -> StablePtr a     */
155 Name nameMkThreadId;                    /* ThreadId#    -> ThreadId        */
156 Name nameMkPrimMVar;                    /* MVar# a      -> MVar a          */
157 #ifdef PROVIDE_WEAK
158 Name nameMkWeak;                        /* Weak# a      -> Weak a          */
159 #endif
160 #ifdef PROVIDE_FOREIGN
161 Name nameMkForeign;                     /* ForeignObj#  -> ForeignObj      */
162 #endif
163
164
165
166 Name nameMinBnd;
167 Name nameMaxBnd;
168 Name nameCompare;
169 Name nameShowsPrec;
170 Name nameIndex;
171 Name nameReadsPrec; 
172 Name nameRange;
173 Name nameEQ;
174 Name nameInRange;
175 Name nameGt;
176 Name nameLe;
177 Name namePlus;
178 Name nameMult;
179 Name nameMFail;
180 Type typeOrdering;
181 Module modulePrelude;
182 Name nameMap;
183 Name nameMinus;
184
185
186 /* --------------------------------------------------------------------------
187  * Frequently used type skeletons:
188  * ------------------------------------------------------------------------*/
189
190 Type  arrow;                     /* mkOffset(0) -> mkOffset(1)      */
191 Type  boundPair;                 /* (mkOffset(0),mkOffset(0))       */
192 Type  listof;                    /* [ mkOffset(0) ]                 */
193 Type  typeVarToVar;              /* mkOffset(0) -> mkOffset(0)      */
194
195 Cell  predNum;                   /* Num (mkOffset(0))               */
196 Cell  predFractional;            /* Fractional (mkOffset(0))        */
197 Cell  predIntegral;              /* Integral (mkOffset(0))          */
198 Kind  starToStar;                /* Type -> Type                    */
199 Cell  predMonad;                 /* Monad (mkOffset(0))             */
200 Type  typeProgIO;                /* IO a                            */
201
202
203 /* --------------------------------------------------------------------------
204  * 
205  * ------------------------------------------------------------------------*/
206
207 static Tycon linkTycon ( String s );
208 static Tycon linkClass ( String s );
209 static Name  linkName  ( String s );
210 static Name  predefinePrim ( String s );
211
212
213 static Tycon linkTycon( String s )
214 {
215     Tycon tc = findTycon(findText(s));
216     if (nonNull(tc)) return tc;
217     if (combined) {
218        tc = findTyconInAnyModule(findText(s));
219        if (nonNull(tc)) return tc;
220     }
221 fprintf(stderr, "frambozenvla!  unknown tycon %s\n", s );
222 return NIL;
223     ERRMSG(0) "Prelude does not define standard type \"%s\"", s
224     EEND;
225 }
226
227 static Class linkClass( String s )
228 {
229     Class cc = findClass(findText(s));
230     if (nonNull(cc)) return cc;
231     if (combined) {
232        cc = findClassInAnyModule(findText(s));
233        if (nonNull(cc)) return cc;
234     }   
235 fprintf(stderr, "frambozenvla!  unknown class %s\n", s );
236 return NIL;
237     ERRMSG(0) "Prelude does not define standard class \"%s\"", s
238     EEND;
239 }
240
241 static Name linkName( String s )
242 {
243     Name n = findName(findText(s));
244     if (nonNull(n)) return n;
245     if (combined) {
246        n = findNameInAnyModule(findText(s));
247        if (nonNull(n)) return n;
248     }   
249 fprintf(stderr, "frambozenvla!  unknown  name %s\n", s );
250 return NIL;
251     ERRMSG(0) "Prelude does not define standard name \"%s\"", s
252     EEND;
253 }
254
255 static Name predefinePrim ( String s )
256 {
257     Name nm;
258     Text t = findText(s);
259     nm = findName(t);
260     if (nonNull(nm)) {
261        //fprintf(stderr, "predefinePrim: %s already exists\n", s );
262     } else {
263        nm = newName(t,NIL);
264        name(nm).defn=PREDEFINED;
265     }
266     return nm;
267 }
268
269
270 /* --------------------------------------------------------------------------
271  * 
272  * ------------------------------------------------------------------------*/
273
274 /* In standalone mode, linkPreludeTC, linkPreludeCM and linkPreludeNames
275    are called, in that order, during static analysis of Prelude.hs.
276    In combined mode such an analysis does not happen.  Instead these
277    calls will be made as a result of a call link(POSTPREL).
278
279    linkPreludeTC, linkPreludeCM and linkPreludeNames are needed in both
280    standalone and combined modes.
281 */
282
283
284 Void linkPreludeTC(void) {              /* Hook to tycons and classes in   */
285     static Bool initialised = FALSE;    /* prelude when first loaded       */
286     if (!initialised) {
287         Int i;
288         initialised = TRUE;
289         setCurrModule(modulePrelude);
290
291         typeChar                 = linkTycon("Char");
292         typeInt                  = linkTycon("Int");
293         typeInteger              = linkTycon("Integer");
294         typeWord                 = linkTycon("Word");
295         typeAddr                 = linkTycon("Addr");
296         typePrimArray            = linkTycon("PrimArray");
297         typePrimByteArray        = linkTycon("PrimByteArray");
298         typeRef                  = linkTycon("STRef");
299         typePrimMutableArray     = linkTycon("PrimMutableArray");
300         typePrimMutableByteArray = linkTycon("PrimMutableByteArray");
301         typeFloat                = linkTycon("Float");
302         typeDouble               = linkTycon("Double");
303         typeStable               = linkTycon("StablePtr");
304 #       ifdef PROVIDE_WEAK
305         typeWeak                 = linkTycon("Weak");
306 #       endif
307 #       ifdef PROVIDE_FOREIGN
308         typeForeign              = linkTycon("ForeignObj");
309 #       endif
310         typeThreadId             = linkTycon("ThreadId");
311         typeMVar                 = linkTycon("MVar");
312         typeBool                 = linkTycon("Bool");
313         typeST                   = linkTycon("ST");
314         typeIO                   = linkTycon("IO");
315         typeException            = linkTycon("Exception");
316         typeString               = linkTycon("String");
317         typeOrdering             = linkTycon("Ordering");
318
319         classEq                  = linkClass("Eq");
320         classOrd                 = linkClass("Ord");
321         classIx                  = linkClass("Ix");
322         classEnum                = linkClass("Enum");
323         classShow                = linkClass("Show");
324         classRead                = linkClass("Read");
325         classBounded             = linkClass("Bounded");
326         classReal                = linkClass("Real");
327         classIntegral            = linkClass("Integral");
328         classRealFrac            = linkClass("RealFrac");
329         classRealFloat           = linkClass("RealFloat");
330         classFractional          = linkClass("Fractional");
331         classFloating            = linkClass("Floating");
332         classNum                 = linkClass("Num");
333         classMonad               = linkClass("Monad");
334
335         stdDefaults              = NIL;
336         stdDefaults              = cons(typeDouble,stdDefaults);
337 #       if DEFAULT_BIGNUM
338         stdDefaults              = cons(typeInteger,stdDefaults);
339 #       else
340         stdDefaults              = cons(typeInt,stdDefaults);
341 #       endif
342
343         predNum                  = ap(classNum,aVar);
344         predFractional           = ap(classFractional,aVar);
345         predIntegral             = ap(classIntegral,aVar);
346         predMonad                = ap(classMonad,aVar);
347         typeProgIO               = ap(typeIO,aVar);
348
349         nameMkC                  = addPrimCfunREP(findText("C#"),1,0,CHAR_REP);
350         nameMkI                  = addPrimCfunREP(findText("I#"),1,0,INT_REP);
351         nameMkW                  = addPrimCfunREP(findText("W#"),1,0,WORD_REP);
352         nameMkA                  = addPrimCfunREP(findText("A#"),1,0,ADDR_REP);
353         nameMkF                  = addPrimCfunREP(findText("F#"),1,0,FLOAT_REP);
354         nameMkD                  = addPrimCfunREP(findText("D#"),1,0,DOUBLE_REP);
355         nameMkStable             = addPrimCfunREP(findText("Stable#"),1,0,STABLE_REP);
356         nameMkThreadId           = addPrimCfunREP(findText("ThreadId#"),1,0,THREADID_REP);
357
358 #       ifdef PROVIDE_FOREIGN
359         nameMkForeign            = addPrimCfunREP(findText("Foreign#"),1,0,0);
360 #       endif
361 #       ifdef PROVIDE_WEAK
362         nameMkWeak               = addPrimCfunREP(findText("Weak#"),1,0,0);
363 #       endif
364         nameMkPrimArray          = addPrimCfunREP(findText("PrimArray#"),1,0,0);
365         nameMkPrimByteArray      = addPrimCfunREP(findText("PrimByteArray#"),1,0,0);
366         nameMkRef                = addPrimCfunREP(findText("STRef#"),1,0,0);
367         nameMkPrimMutableArray   = addPrimCfunREP(findText("PrimMutableArray#"),1,0,0);
368         nameMkPrimMutableByteArray = addPrimCfunREP(findText("PrimMutableByteArray#"),1,0,0);
369         nameMkPrimMVar           = addPrimCfunREP(findText("MVar#"),1,0,0);
370         nameMkInteger            = addPrimCfunREP(findText("Integer#"),1,0,0);
371
372         name(namePrimSeq).type   = primType(MONAD_Id, "ab", "b");
373         name(namePrimCatch).type = primType(MONAD_Id, "aH", "a");
374         name(namePrimRaise).type = primType(MONAD_Id, "E", "a");
375
376         /* This is a lie.  For a more accurate type of primTakeMVar
377            see ghc/interpreter/lib/Prelude.hs.
378         */
379         name(namePrimTakeMVar).type = primType(MONAD_Id, "rbc", "d");
380
381         for (i=2; i<=NUM_DTUPLES; i++) {/* Add derived instances of tuples */
382             addTupInst(classEq,i);
383             addTupInst(classOrd,i);
384             addTupInst(classIx,i);
385             addTupInst(classShow,i);
386             addTupInst(classRead,i);
387             addTupInst(classBounded,i);
388         }
389     }
390 }
391
392 Void linkPreludeCM(void) {              /* Hook to cfuns and mfuns in      */
393     static Bool initialised = FALSE;    /* prelude when first loaded       */
394     if (!initialised) {
395         Int i;
396         initialised = TRUE;
397
398         setCurrModule(modulePrelude);
399
400         /* constructors */
401         nameFalse        = linkName("False");
402         nameTrue         = linkName("True");
403
404         /* members */
405         nameEq           = linkName("==");
406         nameFromInt      = linkName("fromInt");
407         nameFromInteger  = linkName("fromInteger");
408         nameFromDouble   = linkName("fromDouble");
409         nameReturn       = linkName("return");
410         nameBind         = linkName(">>=");
411         nameLe           = linkName("<=");
412         nameGt           = linkName(">");
413         nameShowsPrec    = linkName("showsPrec");
414         nameReadsPrec    = linkName("readsPrec");
415         nameEQ           = linkName("EQ");
416         nameCompare      = linkName("compare");
417         nameMinBnd       = linkName("minBound");
418         nameMaxBnd       = linkName("maxBound");
419         nameRange        = linkName("range");
420         nameIndex        = linkName("index");
421         namePlus         = linkName("+");
422         nameMult         = linkName("*");
423         nameRangeSize    = linkName("rangeSize");
424         nameInRange      = linkName("inRange");
425         nameMinus        = linkName("-");
426         /* These come before calls to implementPrim */
427         for(i=0; i<NUM_TUPLES; ++i) {
428             implementTuple(i);
429         }
430     }
431 }
432
433 Void linkPreludeNames(void) {           /* Hook to names defined in Prelude */
434     static Bool initialised = FALSE;
435     if (!initialised) {
436         Int i;
437         initialised = TRUE;
438
439         setCurrModule(modulePrelude);
440
441         /* primops */
442         nameMkIO           = linkName("hugsprimMkIO");
443         for (i=0; asmPrimOps[i].name; ++i) {
444             Text t = findText(asmPrimOps[i].name);
445             Name n = findName(t);
446             if (isNull(n)) {
447                 n = newName(t,NIL);
448             }
449             name(n).line   = 0;
450             name(n).defn   = NIL;
451             name(n).type   = primType(asmPrimOps[i].monad,
452                                       asmPrimOps[i].args,
453                                       asmPrimOps[i].results);
454             name(n).arity  = strlen(asmPrimOps[i].args);
455             name(n).primop = &(asmPrimOps[i]);
456             implementPrim(n);
457         }
458
459         /* static(tidyInfix)                        */
460         nameNegate         = linkName("negate");
461         /* user interface                           */
462         nameRunIO_toplevel = linkName("hugsprimRunIO_toplevel");
463         namePrint          = linkName("print");
464         /* desugar                                  */
465         nameOtherwise      = linkName("otherwise");
466         nameUndefined      = linkName("undefined");
467         /* pmc                                      */
468 #       if NPLUSK                      
469         namePmSub          = linkName("hugsprimPmSub");
470 #       endif                          
471         /* translator                               */
472         nameEqChar         = linkName("primEqChar");
473         nameCreateAdjThunk = linkName("hugsprimCreateAdjThunk");
474         namePmInt          = linkName("hugsprimPmInt");
475         namePmInteger      = linkName("hugsprimPmInteger");
476         namePmDouble       = linkName("primPmDouble");
477  
478         namePmFromInteger = linkName("hugsprimPmFromInteger");
479         namePmSubtract    = linkName("hugsprimPmSubtract");
480         namePmLe          = linkName("hugsprimPmLe");
481
482         implementCfun ( nameCons, NIL );
483         implementCfun ( nameNil, NIL );
484         implementCfun ( nameUnit, NIL );
485     }
486 }
487
488
489 /* --------------------------------------------------------------------------
490  * 
491  * ------------------------------------------------------------------------*/
492
493 /* ToDo: fix pFun (or eliminate its use) */
494 #define pFun(n,s) n = predefinePrim(s)
495
496 Void linkControl(what)
497 Int what; {
498     Int i;
499     switch (what) {
500         case RESET   :
501         case MARK    : 
502                        break;
503
504         case POSTPREL: 
505 #if 1
506           fprintf(stderr, "linkControl(POSTPREL)\n");
507 #if 1
508           setCurrModule(modulePrelude);
509           linkPreludeTC();
510           linkPreludeCM();
511           linkPreludeNames();
512 #endif
513 #endif
514           break;
515
516         case PREPREL : 
517
518            if (combined) {
519
520                modulePrelude = findFakeModule(textPrelude);
521                module(modulePrelude).objectExtraNames 
522                   = singleton(findText("libHS_cbits"));
523
524                nameMkC = addWiredInBoxingTycon("PrelBase","Char",  "C#",1,0,CHAR_REP  );
525                nameMkI = addWiredInBoxingTycon("PrelBase","Int",   "I#",1,0,INT_REP   );
526                nameMkW = addWiredInBoxingTycon("PrelAddr","Word",  "W#",1,0,WORD_REP  );
527                nameMkA = addWiredInBoxingTycon("PrelAddr","Addr",  "A#",1,0,ADDR_REP  );
528                nameMkF = addWiredInBoxingTycon("PrelFloat","Float", "F#",1,0,FLOAT_REP );
529                nameMkD = addWiredInBoxingTycon("PrelFloat","Double","D#",1,0,DOUBLE_REP);
530                nameMkInteger            
531                        = addWiredInBoxingTycon("PrelNum","Integer","Integer#",1,0,0);
532                nameMkPrimByteArray      
533                        = addWiredInBoxingTycon("PrelGHC","ByteArray","PrimByteArray#",1,0,0);
534
535                for (i=0; i<NUM_TUPLES; ++i) {
536                    addTupleTycon(i);
537                }
538                addWiredInEnumTycon("PrelBase","Bool",
539                                    doubleton(findText("False"),findText("True")));
540
541                //nameMkThreadId
542                //        = addWiredInBoxingTycon("PrelConc","ThreadId","ThreadId#"
543                //                                ,1,0,THREADID_REP);
544
545                setCurrModule(modulePrelude);
546
547                typeArrow = addPrimTycon(findText("(->)"),
548                                         pair(STAR,pair(STAR,STAR)),
549                                         2,DATATYPE,NIL);
550            } else {
551
552                modulePrelude = newModule(textPrelude);
553                setCurrModule(modulePrelude);
554         
555                for (i=0; i<NUM_TUPLES; ++i) {
556                    addTupleTycon(i);
557                }
558                setCurrModule(modulePrelude);
559
560                typeArrow = addPrimTycon(findText("(->)"),
561                                         pair(STAR,pair(STAR,STAR)),
562                                         2,DATATYPE,NIL);
563
564                /* newtype and USE_NEWTYPE_FOR_DICTS     */
565                pFun(nameId,             "id");
566
567                /* desugaring                            */
568                pFun(nameInd,            "_indirect");
569                name(nameInd).number = DFUNNAME;
570
571                /* pmc                                   */
572                pFun(nameSel,            "_SEL");
573
574                /* strict constructors                   */
575                pFun(nameFlip,           "flip"     );
576
577                /* parser                                */
578                pFun(nameFromTo,         "enumFromTo");
579                pFun(nameFromThenTo,     "enumFromThenTo");
580                pFun(nameFrom,           "enumFrom");
581                pFun(nameFromThen,       "enumFromThen");
582
583                /* deriving                              */
584                pFun(nameApp,            "++");
585                pFun(nameReadField,      "readField");
586                pFun(nameReadParen,      "readParen");
587                pFun(nameShowField,      "showField");
588                pFun(nameShowParen,      "showParen");
589                pFun(nameLex,            "lex");
590                pFun(nameComp,           ".");
591                pFun(nameAnd,            "&&");
592                pFun(nameCompAux,        "primCompAux");
593                pFun(nameMap,            "map");
594
595                /* implementTagToCon                     */
596                pFun(namePMFail,         "primPmFail");
597                pFun(nameError,          "error");
598                pFun(nameUnpackString,   "primUnpackString");
599
600                /* hooks for handwritten bytecode */
601                pFun(namePrimSeq,        "primSeq");
602                pFun(namePrimCatch,      "primCatch");
603                pFun(namePrimRaise,      "primRaise");
604                pFun(namePrimTakeMVar,   "primTakeMVar");
605                {
606                   StgVar vv = mkStgVar(NIL,NIL);
607                   Name n = namePrimSeq;
608                   name(n).line = 0;
609                   name(n).arity = 1;
610                   name(n).type = NIL;
611                   vv = mkStgVar(NIL,NIL);
612                   stgVarInfo(vv) = mkPtr ( asm_BCO_seq() );
613                   name(n).stgVar = vv;
614                   stgGlobals=cons(pair(n,vv),stgGlobals);
615                   namePrimSeq = n;
616                }
617                {
618                   StgVar vv = mkStgVar(NIL,NIL);
619                   Name n = namePrimCatch;
620                   name(n).line = 0;
621                   name(n).arity = 2;
622                   name(n).type = NIL;
623                   stgVarInfo(vv) = mkPtr ( asm_BCO_catch() );
624                   name(n).stgVar = vv;
625                   stgGlobals=cons(pair(n,vv),stgGlobals);
626                }
627                {
628                   StgVar vv = mkStgVar(NIL,NIL);
629                   Name n = namePrimRaise;
630                   name(n).line = 0;
631                   name(n).arity = 1;
632                   name(n).type = NIL;
633                   stgVarInfo(vv) = mkPtr ( asm_BCO_raise() );
634                   name(n).stgVar = vv;
635                   stgGlobals=cons(pair(n,vv),stgGlobals);
636                }
637                {
638                   StgVar vv = mkStgVar(NIL,NIL);
639                   Name n = namePrimTakeMVar;
640                   name(n).line = 0;
641                   name(n).arity = 2;
642                   name(n).type = NIL;
643                   stgVarInfo(vv) = mkPtr ( asm_BCO_takeMVar() );
644                   name(n).stgVar = vv;
645                   stgGlobals=cons(pair(n,vv),stgGlobals);
646                }
647            }
648            break;
649     }
650 }
651 #undef pFun
652
653
654 /*-------------------------------------------------------------------------*/