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