compiler/libec: (#402, #772) Improved reporting syntax errors
[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          if(exp.member.exp)
489             InstDeclPassExpression(exp.member.exp);
490          break;
491       }
492       case pointerExp:
493       {
494          if(exp.member.exp)
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          if(init.exp)
561             InstDeclPassExpression(init.exp);
562          break;
563       case listInitializer:
564       {
565          Initializer i;
566          for(i = init.list->first; i; i = i.next)
567             InstDeclPassInitializer(i);
568          break;
569       }
570    }
571 }
572
573 static void InstDeclPassDeclaration(Declaration decl)
574 {
575    switch(decl.type)
576    {
577       case initDeclaration:
578       {
579          if(decl.specifiers)
580          {
581             Specifier spec;
582             for(spec = decl.specifiers->first; spec; spec = spec.next)
583             {
584                int type;
585                if((type = ReplaceClassSpec(decl.specifiers, spec, false)))
586                {
587                   InitDeclarator d;
588                   if(decl.declarators)
589                   {
590                      for(d = decl.declarators->first; d; d = d.next)
591                         ReplaceByInstancePtr(spec, &d.declarator, type);
592                   }
593                }
594                InstDeclPassSpecifier(spec);
595             }
596          }
597          if(decl.declarators)
598          {
599             InitDeclarator d;
600             for(d = decl.declarators->first; d; d = d.next)
601             {
602                InstDeclPassDeclarator(d.declarator);
603                if(d.initializer)
604                   InstDeclPassInitializer(d.initializer);
605             }
606          }
607          break;
608       }
609       case structDeclaration:
610       {
611          if(decl.specifiers)
612          {
613             Specifier spec;
614             for(spec = decl.specifiers->first; spec; spec = spec.next)
615             {
616                int type;
617                if((type = ReplaceClassSpec(decl.specifiers, spec, false)))
618                {
619                   if(decl.declarators)
620                   {
621                      Declarator d;
622                      for(d = decl.declarators->first; d; d = d.next)
623                         ReplaceByInstancePtr(spec, &d, type);
624                   }
625                }
626                InstDeclPassSpecifier(spec);
627             }
628          }
629
630          if(decl.declarators)
631          {
632             Declarator d;
633             for(d = decl.declarators->first; d; d = d.next)
634                InstDeclPassDeclarator(d);
635          }
636          break;
637       }
638       // This should be removed by now?
639       case instDeclaration:
640          // InstDeclPassInstantiation(decl.inst);
641          break;
642    }
643 }
644
645 static void InstDeclPassStatement(Statement stmt)
646 {
647    switch(stmt.type)
648    {
649       case badDeclarationStmt:
650          if(stmt.decl)
651             InstDeclPassDeclaration(stmt.decl);
652          break;
653       case labeledStmt:
654          InstDeclPassStatement(stmt.labeled.stmt);
655          break;
656       case caseStmt:
657          // This expression should be constant...
658          if(stmt.caseStmt.exp)
659             InstDeclPassExpression(stmt.caseStmt.exp);
660          if(stmt.caseStmt.stmt)
661             InstDeclPassStatement(stmt.caseStmt.stmt);
662          break;
663       case compoundStmt:
664       {
665          Declaration decl;
666          Statement s;
667          Context prevContext = curContext;
668
669          if(!stmt.compound.isSwitch)
670             curContext = stmt.compound.context;
671
672          if(stmt.compound.declarations)
673          {
674             for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
675                InstDeclPassDeclaration(decl);
676          }
677          if(stmt.compound.statements)
678          {
679             for(s = stmt.compound.statements->first; s; s = s.next)
680                InstDeclPassStatement(s);
681          }
682          curContext = prevContext;
683          break;
684       }
685       case expressionStmt:
686       {
687          if(stmt.expressions)
688          {
689             Expression exp;
690             for(exp = stmt.expressions->first; exp; exp = exp.next)
691                InstDeclPassExpression(exp);
692          }
693          break;
694       }
695       case ifStmt:
696       {
697          if(stmt.ifStmt.exp)
698          {
699             Expression exp;
700             for(exp = stmt.ifStmt.exp->first; exp; exp = exp.next)
701                InstDeclPassExpression(exp);
702          }
703          if(stmt.ifStmt.stmt)
704             InstDeclPassStatement(stmt.ifStmt.stmt);
705          if(stmt.ifStmt.elseStmt)
706             InstDeclPassStatement(stmt.ifStmt.elseStmt);
707          break;
708       }
709       case switchStmt:
710       {
711          Expression exp;
712          if(stmt.switchStmt.exp)
713          {
714             for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
715                InstDeclPassExpression(exp);
716          }
717          InstDeclPassStatement(stmt.switchStmt.stmt);
718          break;
719       }
720       case whileStmt:
721       {
722          Expression exp;
723          if(stmt.whileStmt.exp)
724          {
725             for(exp = stmt.whileStmt.exp->first; exp; exp = exp.next)
726                InstDeclPassExpression(exp);
727          }
728          InstDeclPassStatement(stmt.whileStmt.stmt);
729          break;
730       }
731       case doWhileStmt:
732       {
733          if(stmt.doWhile.exp)
734          {
735             Expression exp;
736             for(exp = stmt.doWhile.exp->first; exp; exp = exp.next)
737                InstDeclPassExpression(exp);
738          }
739          if(stmt.doWhile.stmt)
740             InstDeclPassStatement(stmt.doWhile.stmt);
741          break;
742       }
743       case forStmt:
744       {
745          Expression exp;
746          if(stmt.forStmt.init)
747             InstDeclPassStatement(stmt.forStmt.init);
748          if(stmt.forStmt.check)
749             InstDeclPassStatement(stmt.forStmt.check);
750          if(stmt.forStmt.increment)
751          {
752             for(exp = stmt.forStmt.increment->first; exp; exp = exp.next)
753                InstDeclPassExpression(exp);
754          }
755          if(stmt.forStmt.stmt)
756             InstDeclPassStatement(stmt.forStmt.stmt);
757          break;
758       }
759       case gotoStmt:
760          break;
761       case continueStmt:
762          break;
763       case breakStmt:
764          break;
765       case returnStmt:
766       {
767          Expression exp;
768          if(stmt.expressions)
769          {
770             for(exp = stmt.expressions->first; exp; exp = exp.next)
771                InstDeclPassExpression(exp);
772          }
773          break;
774       }
775       case asmStmt:
776       {
777          AsmField field;
778          if(stmt.asmStmt.inputFields)
779          {
780             for(field = stmt.asmStmt.inputFields->first; field; field = field.next)
781                if(field.expression)
782                   InstDeclPassExpression(field.expression);
783          }
784          if(stmt.asmStmt.outputFields)
785          {
786             for(field = stmt.asmStmt.outputFields->first; field; field = field.next)
787                if(field.expression)
788                   InstDeclPassExpression(field.expression);
789          }
790          if(stmt.asmStmt.clobberedFields)
791          {
792             for(field = stmt.asmStmt.clobberedFields->first; field; field = field.next)
793                if(field.expression)
794                   InstDeclPassExpression(field.expression);
795          }
796          break;
797       }
798    }
799 }
800
801 public void ProcessInstanceDeclarations()
802 {
803    External external;
804    curContext = globalContext;
805    for(external = ast->first; external; external = external.next)
806    {
807       curExternal = external;
808       if(external.type == functionExternal)
809       {
810          FunctionDefinition func = external.function;
811          if(func.specifiers)
812          {
813             Specifier spec;
814             for(spec = func.specifiers->first; spec; spec = spec.next)
815             {
816                int type;
817                if((type = ReplaceClassSpec(func.specifiers, spec, false)))
818                   ReplaceByInstancePtr(spec, &func.declarator, type);
819                InstDeclPassSpecifier(spec);
820             }
821          }
822          InstDeclPassDeclarator(func.declarator);
823          if(func.body)
824             InstDeclPassStatement(func.body);
825       }
826       else if(external.type == declarationExternal)
827       {
828          if(external.declaration)
829             InstDeclPassDeclaration(external.declaration);
830       }
831    }
832 }