e834794f8236fd7ed2321fb174d773381d8f3f58
[sdk] / compiler / libec / src / pass3.ec
1 import "ecdefs"
2
3 #define YYLTYPE Location
4 #include "grammar.h"
5
6 extern External curExternal;
7 ///////////////// INSTANCE DECLARATION PASS ///////////////////////
8
9 // Returns true if we should add a * to the declarator
10 static bool ReplaceClassSpec(OldList specs, Specifier spec, bool param)
11 {
12    if(spec.type == templateTypeSpecifier)
13    {
14       TemplateParameter parameter = spec.templateParameter;
15       
16       if(!param && parameter.dataTypeString)
17       {
18          OldList * newSpecs = MkList();
19          Declarator decl = SpecDeclFromString(parameter.dataTypeString, newSpecs, null);
20          if(newSpecs->first)
21          {
22             Specifier newSpec = CopySpecifier(newSpecs->first);
23             *spec = *newSpec;
24             delete newSpec;
25          }
26          FreeList(newSpecs, FreeSpecifier);
27          
28          if(decl)
29          {
30             bool isPointer = decl.type == pointerDeclarator;
31             if(decl)
32                FreeDeclarator(decl);
33             if(isPointer)
34                return true;
35          }
36       }
37       else if(!param && parameter.dataType)
38       {
39          OldList * newSpecs = parameter.dataType.specifiers;
40          Declarator decl = parameter.dataType.decl;
41          if(newSpecs->first)
42          {
43             Specifier newSpec = CopySpecifier(newSpecs->first);
44             *spec = *newSpec;
45             delete newSpec;
46          }
47          
48          if(decl)
49          {
50             bool isPointer = decl.type == pointerDeclarator;
51             if(isPointer)
52                return true;
53          }
54       }
55       else
56       {
57          spec.type = nameSpecifier;
58          spec.name = CopyString("uint64");
59          spec.symbol = FindClass("uint64");
60       }
61    }
62
63    if(spec.type == nameSpecifier || spec.type == subClassSpecifier)
64    {
65       // TODO: Apply more care because nameSpecifier / subClassSpecifier use different parts of the union!
66       Symbol classSym = spec.symbol;
67       if(spec.type == subClassSpecifier)
68       {
69          classSym = FindClass("ecere::com::Class");
70       }
71
72       if(classSym)
73       {
74          Class _class = classSym.registered;
75          spec.type = nameSpecifier;
76
77          if(spec.templateArgs)
78          {
79             FreeList(spec.templateArgs, FreeTemplateArgument);
80             spec.templateArgs = null;
81          }
82
83          if(_class && _class.type == structClass)
84          {
85             //Externalexternal;
86             char name[1024];
87             name[0] = 0;
88             FullClassNameCat(name, _class.fullName, false);
89             //spec.name = CopyString(name);
90             delete spec.name;
91             spec.type = structSpecifier;
92             spec.baseSpecs = null;
93             spec.id = MkIdentifier(name);
94             spec.list = null;
95             spec.definitions = null;
96             spec.ctx = null;
97             spec.addNameSpace = false;
98          }
99          else if(_class && _class.type == noHeadClass)
100          {
101             char name[1024] = "";
102             FullClassNameCat(name, _class.fullName, false);
103             delete spec.name;
104             spec.type = structSpecifier;
105             spec.baseSpecs = null;
106             spec.id = MkIdentifier(name);
107             spec.list = null;
108             spec.definitions = null;
109             spec.ctx = null;
110             spec.addNameSpace = false;
111          }
112          else if(_class)
113          {
114             if((_class.type != systemClass ||
115                !strcmp(_class.fullName, "enum") ||
116                (_class.dataTypeString && !strcmp(_class.dataTypeString, "char *")) ||
117                //strcmp(_class.fullName, "bool") &&
118                !strcmp(_class.fullName, "uint64") ||
119                !strcmp(_class.fullName, "uint32") ||
120                !strcmp(_class.fullName, "uint16") ||
121                !strcmp(_class.fullName, "uintptr") ||
122                !strcmp(_class.fullName, "intptr") ||
123                !strcmp(_class.fullName, "uintsize") ||
124                !strcmp(_class.fullName, "intsize") ||
125                !strcmp(_class.fullName, "uint") ||
126                !strcmp(_class.fullName, "byte")))
127             {
128                delete spec.name;
129                if(_class.dataTypeString)
130                {
131                   if(!strcmp(_class.dataTypeString, "uint64") ||
132                      !strcmp(_class.dataTypeString, "uint32") ||
133                      !strcmp(_class.dataTypeString, "uint16") ||
134                      !strcmp(_class.dataTypeString, "uintptr") ||
135                      !strcmp(_class.dataTypeString, "intptr") ||
136                      !strcmp(_class.dataTypeString, "uintsize") ||
137                      !strcmp(_class.dataTypeString, "intsize") ||
138                      !strcmp(_class.dataTypeString, "uint") ||
139                      !strcmp(_class.dataTypeString, "byte"))
140                   {
141                      if(!_class.dataType)
142                         _class.dataType = ProcessTypeString(_class.dataTypeString, false);
143                      if(_class.dataType && _class.dataType.kind == classType) 
144                         classSym = _class.dataType._class;
145                      else
146                         classSym = FindClass(_class.dataTypeString);
147                      _class = classSym ? classSym.registered : null;
148                   }
149
150                   if(!strcmp(_class.dataTypeString, "char *"))
151                      spec.name = CopyString("char");
152                   else
153                      spec.name = CopyString(_class.dataTypeString);
154                   spec.symbol = null;
155                }
156                else
157                {
158                   spec.name = CopyString(null);
159                   spec.symbol = null;
160                }
161             }
162             else if(!_class.base)
163             {
164                delete spec.name;
165                spec.type = baseSpecifier;
166                spec.specifier = VOID;
167                return true;
168             }
169          }
170          else
171          {
172             delete spec.name;
173             spec.type = structSpecifier;
174             spec.id = MkIdentifier("__ecereNameSpace__ecere__com__Instance");
175             spec.list = null;
176             spec.baseSpecs = null;
177             spec.definitions = null;
178             spec.ctx = null;
179             spec.addNameSpace = false;
180          }
181
182          if(_class && _class.dataTypeString && !strcmp(_class.dataTypeString, "char *"))
183             return true; //false;
184          if(!_class || _class.type == normalClass || _class.type == noHeadClass)
185             return true;
186          else if(param && _class.type == structClass)
187             return 2;
188       }
189    }
190    else if(spec.type == baseSpecifier)
191    {
192       if(spec.specifier == ANY_OBJECT)
193       {
194          spec.specifier = VOID;
195          return true;
196       }
197    }
198    return false;
199 }
200
201 static void ReplaceByInstancePtr(Specifier spec, Declarator * declPtr, int type)
202 {
203    Declarator decl = *declPtr;
204    if(decl && decl.type == pointerDeclarator)
205    {
206       // Pointers to simple classes shouldn't be added pointers
207       if(type == 2);
208       else
209       // Add pointer
210          decl.pointer.pointer = MkPointer(null, decl.pointer.pointer);
211    }
212    else
213    {
214       Declarator newDecl { };
215       if(decl)
216       {
217          *newDecl = *decl;
218          decl.declarator = newDecl;
219       }
220       else
221          decl = newDecl;
222       decl.type = pointerDeclarator;
223       decl.pointer.pointer = MkPointer(null, null);      
224       *declPtr = decl;
225    }
226 }
227
228 static void InstDeclPassSpecifier(Specifier spec)
229 {
230    switch(spec.type)
231    {
232       case baseSpecifier:
233          if(spec.specifier == TYPED_OBJECT)
234          {
235             spec.type = extendedSpecifier;
236             spec.extDecl = MkExtDeclString(CopyString("struct __ecereNameSpace__ecere__com__Class * class, void *"));
237          }
238          break;
239       case nameSpecifier:
240          break;
241       case enumSpecifier:
242       {
243          Enumerator e;
244          if(spec.list)
245          {
246             for(e = spec.list->first; e; e = e.next)
247             {
248             
249             }
250          }
251          break;
252       }
253       case structSpecifier:
254       case unionSpecifier:
255       {
256          if(spec.definitions)
257          {
258             ClassDef def;
259             for(def = spec.definitions->first; def; def = def.next)
260                if(def.decl)
261                   InstDeclPassDeclaration(def.decl);
262          }
263          if(spec.id)
264             InstDeclPassIdentifier(spec.id);
265          break;
266       }
267       case extendedSpecifier:
268          if(spec.extDecl && spec.extDecl.type == extDeclString && spec.extDecl.s)
269          {
270             if(!strcmp(spec.extDecl.s, "dllexport"))
271             {
272                Specifier prevSpec;
273                delete spec.extDecl.s;
274                for(prevSpec = spec.prev; prevSpec; prevSpec = prevSpec.prev)
275                   if(prevSpec.type == baseSpecifier && prevSpec.specifier == EXTERN)
276                      break;
277                if(prevSpec)
278                {
279                   if(targetPlatform == win32)
280                      spec.extDecl.s = CopyString("__declspec(dllexport)");
281                   else
282                      spec.extDecl.s = CopyString("__attribute__ ((visibility(\"default\")))");
283                }
284                else
285                {
286                   if(targetPlatform == win32)
287                      spec.extDecl.s = CopyString("extern __declspec(dllexport)");
288                   else
289                      spec.extDecl.s = CopyString("extern __attribute__ ((visibility(\"default\")))");
290                }
291             }
292             else if(!strcmp(spec.extDecl.s, "stdcall") || !strcmp(spec.extDecl.s, "_stdcall") || 
293                !strcmp(spec.extDecl.s, "__stdcall") || !strcmp(spec.extDecl.s, "__stdcall__"))
294             {
295                delete spec.extDecl.s;
296                if(targetPlatform == win32)
297                   spec.extDecl.s = CopyString("__attribute__((__stdcall__))");
298                else
299                   spec.extDecl.s = CopyString("");
300             }
301          }
302          break;
303    }
304 }
305
306 static void InstDeclPassDeclarator(Declarator decl)
307 {
308    switch(decl.type)
309    {
310       case structDeclarator:
311          if(decl.declarator)
312             InstDeclPassDeclarator(decl.declarator);
313          break;
314       case identifierDeclarator:
315       {
316          if(decl.identifier)
317             InstDeclPassIdentifier(decl.identifier);
318          break;
319       }
320       case bracketsDeclarator:
321          if(decl.declarator)
322             InstDeclPassDeclarator(decl.declarator);
323          break;
324       case arrayDeclarator:
325          if(decl.declarator)
326             InstDeclPassDeclarator(decl.declarator);
327          break;
328       case functionDeclarator:
329       {
330          if(decl.declarator)
331             InstDeclPassDeclarator(decl.declarator);
332          if(decl.function.parameters)
333          {
334             TypeName type;
335             if(decl.declarator)
336                InstDeclPassDeclarator(decl.declarator);
337             for(type = decl.function.parameters->first; type; type = type.next)
338             {
339                bool typedObject = false;
340                Specifier spec = null;
341                if(type.qualifiers)
342                {
343                   spec = (Specifier)type.qualifiers->first;
344                   if(spec && spec.type == nameSpecifier && !strcmp(spec.name, "class"))
345                      typedObject = true;
346                }
347
348                InstDeclPassTypeName(type, true);
349                if(typedObject)
350                {
351                   TypeName _class
352                   {
353                      qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
354                      declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
355                   };
356                   decl.function.parameters->Insert(spec.prev, _class);
357                }
358             }
359          }
360          break;
361       }
362       case pointerDeclarator:
363       case extendedDeclarator:
364       case extendedDeclaratorEnd:
365          if((decl.type == extendedDeclarator || decl.type == extendedDeclaratorEnd) && decl.extended.extended)
366          {
367             if(decl.extended.extended.type == extDeclString && decl.extended.extended.s && !strcmp(decl.extended.extended.s, "dllexport"))
368             {
369                delete decl.extended.extended.s;
370                if(targetPlatform == win32)
371                   decl.extended.extended.s = CopyString("extern __declspec(dllexport)");
372                else
373                   decl.extended.extended.s = CopyString("extern __attribute__ ((visibility(\"default\")))");
374             }
375             else if(decl.extended.extended.type == extDeclString && decl.extended.extended.s &&
376                (!strcmp(decl.extended.extended.s, "stdcall") || !strcmp(decl.extended.extended.s, "_stdcall") || 
377                !strcmp(decl.extended.extended.s, "__stdcall") || !strcmp(decl.extended.extended.s, "__stdcall__")))
378             {
379                delete decl.extended.extended.s;
380                if(targetPlatform == win32)
381                   decl.extended.extended.s = CopyString("__attribute__((__stdcall__))");
382                else
383                   decl.extended.extended.s = CopyString("");
384             }
385          }
386          if(decl.declarator)
387             InstDeclPassDeclarator(decl.declarator);
388          break;
389    }
390 }
391
392 /*static */void InstDeclPassTypeName(TypeName type, bool param)
393 {
394    if(type.qualifiers)
395    {
396       Specifier spec;
397       for(spec = type.qualifiers->first; spec; spec = spec.next)
398       {
399          int result;
400          if((result = ReplaceClassSpec(type.qualifiers, spec, param)))
401             ReplaceByInstancePtr(spec, &type.declarator, result);
402          else
403          {
404             Symbol classSym = (spec.type == nameSpecifier) ? spec.symbol /*FindClass(spec.name)*/ : null;
405             if(type.classObjectType && (!classSym || (classSym && classSym.registered && 
406                (classSym.registered.type == enumClass || classSym.registered.type == bitClass || classSym.registered.type == unitClass))))
407                ReplaceByInstancePtr(spec, &type.declarator, 2);
408          }
409          InstDeclPassSpecifier(spec);
410       }
411    }
412    if(type.declarator)
413       InstDeclPassDeclarator(type.declarator);
414 }
415
416 static void InstDeclPassIdentifier(Identifier id)
417 {
418    if(strchr(id.string, ':'))
419    {
420       char newID[1024];
421       int c;
422       char ch;
423       int len;
424       strcpy(newID, "__ecereNameSpace__");
425       len = strlen(newID);
426
427       for(c = 0; (ch = id.string[c]); c++)
428       {
429          if(ch == ':') ch = '_';
430
431          newID[len++] = ch;
432       }
433       newID[len] = 0;
434       delete id.string;
435       id.string = CopyString(newID);
436    }
437 }
438
439 static void InstDeclPassExpression(Expression exp)
440 {
441    switch(exp.type)
442    {
443       case identifierExp:
444       {
445          if(exp.identifier)
446             InstDeclPassIdentifier(exp.identifier);
447          break;
448       }
449       case constantExp:
450          break;
451       case stringExp:
452          break;
453       case opExp:
454          if(exp.op.exp1)
455             InstDeclPassExpression(exp.op.exp1);
456          if(exp.op.exp2)
457             InstDeclPassExpression(exp.op.exp2);
458          break;
459       case extensionExpressionExp:
460       case bracketsExp:
461       {
462          Expression e;
463          for(e = exp.list->first; e; e = e.next)
464             InstDeclPassExpression(e);
465          break;
466       }
467       case indexExp:
468       {
469          Expression e;
470          InstDeclPassExpression(exp.index.exp);
471          for(e = exp.index.index->first; e; e = e.next)
472             InstDeclPassExpression(e);
473          break;
474       }
475       case callExp:
476       {
477          Expression e;
478          InstDeclPassExpression(exp.call.exp);
479          if(exp.call.arguments)
480          {
481             for(e = exp.call.arguments->first; e; e = e.next)
482                InstDeclPassExpression(e);
483          }
484          break;
485       }
486       case memberExp:
487       {
488          InstDeclPassExpression(exp.member.exp);
489          break;
490       }
491       case pointerExp:
492       {
493          InstDeclPassExpression(exp.member.exp);
494          break;
495       }
496       case typeSizeExp:
497          InstDeclPassTypeName(exp.typeName, false);
498          break;
499       case castExp:
500       {
501          Type type = exp.expType;
502          // Remove casts to simple structs... (Watch out for pointers later...)
503          if(type && type.kind == classType && type._class.registered && type._class.registered.type == structClass)
504          {
505             Expression castExp = exp.cast.exp;
506             Expression prev = exp.prev, next = exp.next;
507             exp.cast.exp = null;
508             FreeExpContents(exp);
509             FreeType(exp.expType);
510             FreeType(exp.destType);
511             *exp = *castExp;
512             delete castExp;
513             exp.prev = prev;
514             exp.next = next;
515             InstDeclPassExpression(exp);
516          }
517          else
518          {
519             InstDeclPassTypeName(exp.cast.typeName, false);
520             if(exp.cast.exp)
521                InstDeclPassExpression(exp.cast.exp);
522          }
523          break;
524       }
525       case conditionExp:
526       {
527          Expression e;
528          InstDeclPassExpression(exp.cond.cond);
529          for(e = exp.cond.exp->first; e; e = e.next)
530             InstDeclPassExpression(e);
531          InstDeclPassExpression(exp.cond.elseExp);
532          break;
533       }
534       case extensionCompoundExp:
535       {
536          InstDeclPassStatement(exp.compound);
537          break;
538       }
539       case vaArgExp:
540       {
541          InstDeclPassExpression(exp.vaArg.exp);
542          break;
543       }
544       case extensionInitializerExp:
545       {
546          InstDeclPassTypeName(exp.initializer.typeName, false);
547          InstDeclPassInitializer(exp.initializer.initializer);
548          break;
549       }
550    }
551 }
552
553 static void InstDeclPassInitializer(Initializer init)
554 {
555    switch(init.type)
556    {
557       case expInitializer:
558          InstDeclPassExpression(init.exp);
559          break;
560       case listInitializer:
561       {
562          Initializer i;
563          for(i = init.list->first; i; i = i.next)
564             InstDeclPassInitializer(i);
565          break;
566       }
567    }
568 }
569
570 static void InstDeclPassDeclaration(Declaration decl)
571 {
572    switch(decl.type)
573    {
574       case initDeclaration:
575       {
576          if(decl.specifiers)
577          {
578             Specifier spec;
579             for(spec = decl.specifiers->first; spec; spec = spec.next)
580             {
581                int type;
582                if((type = ReplaceClassSpec(decl.specifiers, spec, false)))
583                {
584                   InitDeclarator d;
585                   if(decl.declarators)
586                   {
587                      for(d = decl.declarators->first; d; d = d.next)
588                         ReplaceByInstancePtr(spec, &d.declarator, type);
589                   }
590                }
591                InstDeclPassSpecifier(spec);
592             }
593          }
594          if(decl.declarators)
595          {
596             InitDeclarator d;
597             for(d = decl.declarators->first; d; d = d.next)
598             {
599                InstDeclPassDeclarator(d.declarator);
600                if(d.initializer)
601                   InstDeclPassInitializer(d.initializer);
602             }
603          }
604          break;
605       }
606       case structDeclaration:
607       {
608          if(decl.specifiers)
609          {
610             Specifier spec;
611             for(spec = decl.specifiers->first; spec; spec = spec.next)
612             {
613                int type;
614                if((type = ReplaceClassSpec(decl.specifiers, spec, false)))
615                {
616                   if(decl.declarators)
617                   {
618                      Declarator d;
619                      for(d = decl.declarators->first; d; d = d.next)
620                         ReplaceByInstancePtr(spec, &d, type);
621                   }
622                }
623                InstDeclPassSpecifier(spec);
624             }
625          }
626
627          if(decl.declarators)
628          {
629             Declarator d;
630             for(d = decl.declarators->first; d; d = d.next)
631                InstDeclPassDeclarator(d);
632          }
633          break;
634       }
635       // This should be removed by now?
636       case instDeclaration:
637          // InstDeclPassInstantiation(decl.inst);
638          break;
639    }
640 }
641
642 static void InstDeclPassStatement(Statement stmt)
643 {
644    switch(stmt.type)
645    {
646       case badDeclarationStmt:
647          if(stmt.decl)
648             InstDeclPassDeclaration(stmt.decl);
649          break;
650       case labeledStmt:
651          InstDeclPassStatement(stmt.labeled.stmt);
652          break;
653       case caseStmt:
654          // This expression should be constant...
655          if(stmt.caseStmt.exp)
656             InstDeclPassExpression(stmt.caseStmt.exp);
657          if(stmt.caseStmt.stmt)
658             InstDeclPassStatement(stmt.caseStmt.stmt);
659          break;
660       case compoundStmt:
661       {
662          Declaration decl;
663          Statement s;
664          Context prevContext = curContext;
665
666          if(!stmt.compound.isSwitch)
667             curContext = stmt.compound.context;
668          
669          if(stmt.compound.declarations)
670          {
671             for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
672                InstDeclPassDeclaration(decl);
673          }
674          if(stmt.compound.statements)
675          {
676             for(s = stmt.compound.statements->first; s; s = s.next)
677                InstDeclPassStatement(s);
678          }
679          curContext = prevContext;
680          break;
681       }
682       case expressionStmt:
683       {
684          if(stmt.expressions)
685          {
686             Expression exp;
687             for(exp = stmt.expressions->first; exp; exp = exp.next)
688                InstDeclPassExpression(exp);
689          }
690          break;
691       }
692       case ifStmt:
693       {
694          if(stmt.ifStmt.exp)
695          {
696             Expression exp;
697             for(exp = stmt.ifStmt.exp->first; exp; exp = exp.next)
698                InstDeclPassExpression(exp);
699          }
700          if(stmt.ifStmt.stmt)
701             InstDeclPassStatement(stmt.ifStmt.stmt);
702          if(stmt.ifStmt.elseStmt)
703             InstDeclPassStatement(stmt.ifStmt.elseStmt);
704          break;
705       }
706       case switchStmt:
707       {
708          Expression exp;
709          for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
710             InstDeclPassExpression(exp);
711          InstDeclPassStatement(stmt.switchStmt.stmt);
712          break;
713       }
714       case whileStmt:
715       {
716          Expression exp;
717          for(exp = stmt.whileStmt.exp->first; exp; exp = exp.next)
718             InstDeclPassExpression(exp);
719          InstDeclPassStatement(stmt.whileStmt.stmt);
720          break;
721       }
722       case doWhileStmt:
723       {
724          if(stmt.doWhile.exp)
725          {
726             Expression exp;
727             for(exp = stmt.doWhile.exp->first; exp; exp = exp.next)
728                InstDeclPassExpression(exp);
729          }
730          if(stmt.doWhile.stmt)
731             InstDeclPassStatement(stmt.doWhile.stmt);
732          break;
733       }
734       case forStmt:
735       {
736          Expression exp;
737          if(stmt.forStmt.init)
738             InstDeclPassStatement(stmt.forStmt.init);
739          if(stmt.forStmt.check)
740             InstDeclPassStatement(stmt.forStmt.check);
741          if(stmt.forStmt.increment)
742          {
743             for(exp = stmt.forStmt.increment->first; exp; exp = exp.next)
744                InstDeclPassExpression(exp);
745          }
746          if(stmt.forStmt.stmt)
747             InstDeclPassStatement(stmt.forStmt.stmt);
748          break;
749       }
750       case gotoStmt:
751          break;
752       case continueStmt:
753          break;
754       case breakStmt:
755          break;
756       case returnStmt:
757       {
758          Expression exp;
759          if(stmt.expressions)
760          {
761             for(exp = stmt.expressions->first; exp; exp = exp.next)
762                InstDeclPassExpression(exp);
763          }
764          break;
765       }
766       case asmStmt:
767       {
768          AsmField field;
769          if(stmt.asmStmt.inputFields)
770          {
771             for(field = stmt.asmStmt.inputFields->first; field; field = field.next)
772                if(field.expression)
773                   InstDeclPassExpression(field.expression);
774          }
775          if(stmt.asmStmt.outputFields)
776          {
777             for(field = stmt.asmStmt.outputFields->first; field; field = field.next)
778                if(field.expression)
779                   InstDeclPassExpression(field.expression);
780          }
781          if(stmt.asmStmt.clobberedFields)
782          {
783             for(field = stmt.asmStmt.clobberedFields->first; field; field = field.next)
784                if(field.expression)
785                   InstDeclPassExpression(field.expression);
786          }
787          break;
788       }
789    }
790 }
791
792 public void ProcessInstanceDeclarations()
793 {
794    External external;
795    curContext = globalContext;
796    for(external = ast->first; external; external = external.next)
797    {
798       curExternal = external;
799       if(external.type == functionExternal)
800       {
801          FunctionDefinition func = external.function;
802          if(func.specifiers)
803          {
804             Specifier spec;
805             for(spec = func.specifiers->first; spec; spec = spec.next)
806             {
807                int type;
808                if((type = ReplaceClassSpec(func.specifiers, spec, false)))
809                   ReplaceByInstancePtr(spec, &func.declarator, type);
810                InstDeclPassSpecifier(spec);
811             }
812          }
813          InstDeclPassDeclarator(func.declarator);
814          if(func.body)
815             InstDeclPassStatement(func.body);
816       }
817       else if(external.type == declarationExternal)
818       {
819          if(external.declaration)
820             InstDeclPassDeclaration(external.declaration);         
821       }
822    }
823 }