Пример #1
0
/* Create a list of parameters from the type t, using the file_line_node Node for 
 * file and line numbering for the parameters */
ParmList *SwigType_function_parms(const SwigType *t, Node *file_line_node) {
  List *l = SwigType_parmlist(t);
  Hash *p, *pp = 0, *firstp = 0;
  Iterator o;

  for (o = First(l); o.item; o = Next(o)) {
    p = file_line_node ? NewParm(o.item, 0, file_line_node) : NewParmWithoutFileLineInfo(o.item, 0);
    if (!firstp)
      firstp = p;
    if (pp) {
      set_nextSibling(pp, p);
      Delete(p);
    }
    pp = p;
  }
  Delete(l);
  return firstp;
}
Пример #2
0
int
Swig_DestructorToFunction(Node *n, String *classname, int cplus, int flags)
{
  SwigType *type;
  Parm     *p;
 
  type  = NewString(classname);
  SwigType_add_pointer(type);
  p = NewParm(type,"self");
  Delete(type);
  type = NewString("void");

  if (flags & CWRAP_EXTEND) {
    String *membername, *mangled, *code;
    membername = Swig_name_destroy(classname);
    mangled = Swig_name_mangle(membername);
    code = Getattr(n,"code");
    if (code) {
      String *s = NewStringf("void %s(%s)", mangled, ParmList_str(p));
      Printv(s,code,"\n",NIL);
      Setattr(n,"wrap:code",s);
      Delete(s);
    }
    Setattr(n,"wrap:action", NewStringf("%s;\n", Swig_cfunction_call(mangled,p)));
    Delete(membername);
    Delete(mangled);
  } else {
    if (cplus) {
      String* action = NewString("");
      Printf(action, "%s;\n", Swig_cppdestructor_call());
      Setattr(n,"wrap:action", action);
    } else {
      Setattr(n,"wrap:action", NewStringf("%s;\n", Swig_cdestructor_call()));
    }
  }
  Setattr(n,"type",type);
  Setattr(n,"parms", p);
  Delete(type);
  Delete(p);
  return SWIG_OK;
}
Пример #3
0
int
Swig_VarsetToFunction(Node *n) {
  String   *name,*nname;
  ParmList *parms;
  SwigType *type, *ty;

  name = Getattr(n,"name");
  type = Getattr(n,"type");

  nname = SwigType_namestr(name);

  ty = Swig_wrapped_var_type(type);
  parms = NewParm(ty,"value");
  Delete(ty);
  
  Setattr(n,"wrap:action", NewStringf("%s = %s;\n", nname, Swig_wrapped_var_deref(type,Swig_cparm_name(0,0))));
  Setattr(n,"type","void");
  Setattr(n,"parms",parms);
  Delete(parms);
  Delete(nname);
  return SWIG_OK;
}
int Swig_VarsetToFunction(Node *n, int flags) {
  String *name, *nname;
  ParmList *parms;
  SwigType *type, *ty;

  int varcref = flags & CWRAP_NATURAL_VAR;

  name = Getattr(n, k_name);
  type = Getattr(n, k_type);

  nname = SwigType_namestr(name);

  ty = Swig_wrapped_var_type(type, varcref);
  parms = NewParm(ty, name);
  Delete(ty);

  if (!Strstr(type, "enum $unnamed")) {
    String *pname = Swig_cparm_name(0, 0);
    String *dref = Swig_wrapped_var_deref(type, pname, varcref);
    String *call = NewStringf("%s = %s;\n", nname, dref);
    Setattr(n, k_wrapaction, call);
    Delete(call);
    Delete(dref);
    Delete(pname);
  } else {
    String *pname = Swig_cparm_name(0, 0);
    String *call = NewStringf("if (sizeof(int) == sizeof(%s)) *(int*)(void*)&(%s) = %s;\n", nname, nname, pname);
    Setattr(n, k_wrapaction, call);
    Delete(call);
  }
  Setattr(n, k_type, "void");
  Setattr(n, k_parms, parms);
  Delete(parms);
  Delete(nname);
  return SWIG_OK;
}
int Swig_MethodToFunction(Node *n, String *classname, int flags, SwigType *director_type, int is_director) {
  String *name, *qualifier;
  ParmList *parms;
  SwigType *type;
  Parm *p;
  String *self = 0;

  /* If smart pointer, change self dereferencing */
  if (flags & CWRAP_SMART_POINTER) {
    self = NewString("(*this)->");
  }

  /* If node is a member template expansion, we don't allow added code */
  if (Getattr(n, k_templatetype))
    flags &= ~(CWRAP_EXTEND);

  name = Getattr(n, k_name);
  qualifier = Getattr(n, k_qualifier);
  parms = CopyParmList(nonvoid_parms(Getattr(n, k_parms)));

  type = NewString(classname);
  if (qualifier) {
    SwigType_push(type, qualifier);
  }
  SwigType_add_pointer(type);
  p = NewParm(type, k_self);
  Setattr(p, k_self, "1");
  Setattr(p, k_hidden, "1");
  /*
     Disable the 'this' ownership in 'self' to manage inplace
     operations like:

     A& A::operator+=(int i) { ...; return *this;}

     Here the 'self' parameter ownership needs to be disabled since
     there could be two objects sharing the same 'this' pointer: the
     input and the result one. And worse, the pointer could be deleted
     in one of the objects (input), leaving the other (output) with
     just a seg. fault to happen.

     To avoid the previous problem, use

     %feature("self:disown") *::operator+=;
     %feature("new") *::operator+=;

     These two lines just transfer the ownership of the 'this' pointer
     from the input to the output wrapping object.

     This happens in python, but may also happens in other target
     languages.
   */
  if (GetFlag(n, "feature:self:disown")) {
    Setattr(p, k_wrapdisown, "1");
  }
  set_nextSibling(p, parms);
  Delete(type);

  /* Generate action code for the access */
  if (!(flags & CWRAP_EXTEND)) {
    String *explicit_qualifier = 0;
    String *call = 0;
    String *cres = 0;
    String *explicitcall_name = 0;
    int pure_virtual = !(Cmp(Getattr(n, k_storage), "virtual")) && !(Cmp(Getattr(n, k_value), "0"));

    /* Call the explicit method rather than allow for a polymorphic call */
    if ((flags & CWRAP_DIRECTOR_TWO_CALLS) || (flags & CWRAP_DIRECTOR_ONE_CALL)) {
      String *access = Getattr(n, "access");
      if (access && (Cmp(access, "protected") == 0)) {
	/* If protected access (can only be if a director method) then call the extra public accessor method (language module must provide this) */
	String *explicit_qualifier_tmp = SwigType_namestr(Getattr(Getattr(parentNode(n), "typescope"), k_qname));
	explicitcall_name = NewStringf("%sSwigPublic", name);
	explicit_qualifier = NewStringf("SwigDirector_%s", explicit_qualifier_tmp);
	Delete(explicit_qualifier_tmp);
      } else {
	explicit_qualifier = SwigType_namestr(Getattr(Getattr(parentNode(n), "typescope"), k_qname));
      }
    }

    call = Swig_cmethod_call(explicitcall_name ? explicitcall_name : name, p, self, explicit_qualifier, director_type);
    cres = Swig_cresult(Getattr(n, k_type), k_result, call);

    if (pure_virtual && is_director && (flags & CWRAP_DIRECTOR_TWO_CALLS)) {
      String *qualifier = SwigType_namestr(Getattr(Getattr(parentNode(n), "typescope"), k_qname));
      Delete(cres);
      cres = NewStringf("Swig::DirectorPureVirtualException::raise(\"%s::%s\");", qualifier, name);
      Delete(qualifier);
    }

    if (flags & CWRAP_DIRECTOR_TWO_CALLS) {
      /* Create two method calls, one to call the explicit method, the other a normal polymorphic function call */
      String *cres_both_calls = NewStringf("");
      String *call_extra = Swig_cmethod_call(name, p, self, 0, director_type);
      String *cres_extra = Swig_cresult(Getattr(n, k_type), k_result, call_extra);
      Printv(cres_both_calls, "if (upcall) {\n", cres, "\n", "} else {", cres_extra, "\n}", NIL);
      Setattr(n, k_wrapaction, cres_both_calls);
      Delete(cres_extra);
      Delete(call_extra);
      Delete(cres_both_calls);
    } else {
      Setattr(n, k_wrapaction, cres);
    }

    Delete(explicitcall_name);
    Delete(call);
    Delete(cres);
    Delete(explicit_qualifier);
  } else {
    /* Methods with default arguments are wrapped with additional methods for each default argument,
     * however, only one extra %extend method is generated. */

    String *defaultargs = Getattr(n, k_defaultargs);
    String *code = Getattr(n, k_code);
    String *cname = Getattr(n, k_classname) ? Getattr(n, k_classname) : classname;
    String *membername = Swig_name_member(cname, name);
    String *mangled = Swig_name_mangle(membername);
    int is_smart_pointer = flags & CWRAP_SMART_POINTER;

    type = Getattr(n, k_type);

    /* Check if the method is overloaded.   If so, and it has code attached, we append an extra suffix
       to avoid a name-clash in the generated wrappers.  This allows overloaded methods to be defined
       in C. */
    if (Getattr(n, k_symoverloaded) && code) {
      Append(mangled, Getattr(defaultargs ? defaultargs : n, k_symovername));
    }

    /* See if there is any code that we need to emit */
    if (!defaultargs && code && !is_smart_pointer) {
      Swig_add_extension_code(n, mangled, p, type, code, cparse_cplusplus, k_self);
    }
    if (is_smart_pointer) {
      int i = 0;
      Parm *pp = p;
      String *func = NewStringf("%s(", mangled);
      String *cres;

      if (Cmp(Getattr(n, k_storage), k_static) != 0) {
	String *pname = Swig_cparm_name(pp, i);
        String *ctname = SwigType_namestr(cname);
	String *fadd = NewStringf("(%s*)(%s)->operator ->()", ctname, pname);
	Append(func, fadd);
        Delete(ctname);
	Delete(fadd);
	Delete(pname);
	pp = nextSibling(pp);
	if (pp)
	  Append(func, ",");
      } else {
	pp = nextSibling(pp);
      }
      ++i;
      while (pp) {
	SwigType *pt = Getattr(pp, k_type);
	if ((SwigType_type(pt) != T_VOID)) {
	  String *pname = Swig_cparm_name(pp, i++);
	  String *rcaststr = SwigType_rcaststr(pt, pname);
	  Append(func, rcaststr);
	  Delete(rcaststr);
	  Delete(pname);
	  pp = nextSibling(pp);
	  if (pp)
	    Append(func, ",");
	}
      }
      Append(func, ")");
      cres = Swig_cresult(Getattr(n, k_type), k_result, func);
      Setattr(n, k_wrapaction, cres);
      Delete(cres);
    } else {
      String *call = Swig_cfunction_call(mangled, p);
      String *cres = Swig_cresult(Getattr(n, k_type), k_result, call);
      Setattr(n, k_wrapaction, cres);
      Delete(call);
      Delete(cres);
    }

    Delete(membername);
    Delete(mangled);
  }
  Setattr(n, k_parms, p);
  Delete(p);
  Delete(self);
  Delete(parms);
  return SWIG_OK;
}
int Swig_MembergetToFunction(Node *n, String *classname, int flags) {
  String *name;
  ParmList *parms;
  SwigType *t;
  SwigType *ty;
  SwigType *type;
  String *membername;
  String *mangled;
  String *self = 0;
  String *gname;

  int varcref = flags & CWRAP_NATURAL_VAR;

  if (flags & CWRAP_SMART_POINTER) {
    if (checkAttribute(n, k_storage, k_static)) {
      Node *sn = Getattr(n, k_cplusstaticbase);
      String *base = Getattr(sn, k_name);
      self = NewStringf("%s::", base);
    } else {
      self = NewString("(*this)->");
    }
  }

  name = Getattr(n, k_name);
  type = Getattr(n, k_type);

  gname = Swig_name_get(name);
  membername = Swig_name_member(classname, gname);
  mangled = Swig_name_mangle(membername);

  t = NewString(classname);
  SwigType_add_pointer(t);
  parms = NewParm(t, k_self);
  Setattr(parms, k_self, "1");
  Setattr(parms, k_hidden, "1");
  Delete(t);

  ty = Swig_wrapped_member_var_type(type, varcref);
  if (flags & CWRAP_EXTEND) {
    String *call;
    String *cres;

    String *code = Getattr(n, k_code);
    if (code) {
      Swig_add_extension_code(n, mangled, parms, ty, code, cparse_cplusplus, k_self);
    }
    call = Swig_cfunction_call(mangled, parms);
    cres = Swig_cresult(ty, k_result, call);
    Setattr(n, k_wrapaction, cres);
    Delete(cres);
    Delete(call);
  } else {
    String *call = Swig_cmemberget_call(name, type, self, varcref);
    String *cres = Swig_cresult(ty, k_result, call);
    Setattr(n, k_wrapaction, cres);
    Delete(call);
    Delete(cres);
  }
  Setattr(n, k_type, ty);
  Setattr(n, k_parms, parms);
  Delete(parms);
  Delete(ty);
  Delete(membername);
  Delete(gname);
  Delete(mangled);

  return SWIG_OK;
}
int Swig_MembersetToFunction(Node *n, String *classname, int flags) {
  String *name;
  ParmList *parms;
  Parm *p;
  SwigType *t;
  SwigType *ty;
  SwigType *type;
  SwigType *void_type = NewString("void");
  String *membername;
  String *mangled;
  String *self = 0;
  String *sname;

  int varcref = flags & CWRAP_NATURAL_VAR;

  if (flags & CWRAP_SMART_POINTER) {
    self = NewString("(*this)->");
  }

  name = Getattr(n, k_name);
  type = Getattr(n, k_type);

  sname = Swig_name_set(name);
  membername = Swig_name_member(classname, sname);
  mangled = Swig_name_mangle(membername);

  t = NewString(classname);
  SwigType_add_pointer(t);
  parms = NewParm(t, k_self);
  Setattr(parms, k_self, "1");
  Setattr(parms, k_hidden, "1");
  Delete(t);

  ty = Swig_wrapped_member_var_type(type, varcref);
  p = NewParm(ty, name);
  Setattr(parms, k_hidden, "1");
  set_nextSibling(parms, p);

  /* If the type is a pointer or reference.  We mark it with a special wrap:disown attribute */
  if (SwigType_check_decl(type, "p.")) {
    Setattr(p, k_wrapdisown, "1");
  }
  Delete(p);

  if (flags & CWRAP_EXTEND) {
    String *call;
    String *cres;
    String *code = Getattr(n, k_code);
    if (code) {
      Swig_add_extension_code(n, mangled, parms, void_type, code, cparse_cplusplus, k_self);
    }
    call = Swig_cfunction_call(mangled, parms);
    cres = NewStringf("%s;\n", call);
    Setattr(n, k_wrapaction, cres);
    Delete(call);
    Delete(cres);
  } else {
    String *call = Swig_cmemberset_call(name, type, self, varcref);
    String *cres = NewStringf("%s;\n", call);
    Setattr(n, k_wrapaction, cres);
    Delete(call);
    Delete(cres);
  }
  Setattr(n, k_type, void_type);
  Setattr(n, k_parms, parms);
  Delete(parms);
  Delete(ty);
  Delete(void_type);
  Delete(membername);
  Delete(sname);
  Delete(mangled);
  Delete(self);
  return SWIG_OK;
}
Пример #8
0
int Swig_MembergetToFunction(Node *n, String *classname, int flags) {
    String *name;
    ParmList *parms;
    SwigType *t;
    SwigType *ty;
    SwigType *type;
    String *membername;
    String *mangled;
    String *self = 0;
    String *gname;

    int varcref = flags & CWRAP_NATURAL_VAR;

    if (flags & CWRAP_SMART_POINTER) {
        if (checkAttribute(n, "storage", "static")) {
            Node *sn = Getattr(n, "cplus:staticbase");
            String *base = Getattr(sn, "name");
            self = NewStringf("%s::", base);
        } else {
            self = NewString("(*this)->");
        }
    }
    if (flags & CWRAP_ALL_PROTECTED_ACCESS) {
        self = NewStringf("darg->");
    }

    name = Getattr(n, "name");
    type = Getattr(n, "type");

    gname = Swig_name_get(name);
    membername = Swig_name_member(classname, gname);
    mangled = Swig_name_mangle(membername);

    t = NewString(classname);
    SwigType_add_pointer(t);
    parms = NewParm(t, "self");
    Setattr(parms, "self", "1");
    Setattr(parms, "hidden","1");
    Delete(t);

    ty = Swig_wrapped_member_var_type(type, varcref);
    if (flags & CWRAP_EXTEND) {
        String *call;
        String *cres;

        String *code = Getattr(n, "code");
        if (code) {
            /* I don't think this ever gets run - WSF */
            Swig_add_extension_code(n, mangled, parms, ty, code, cparse_cplusplus, "self");
        }
        call = Swig_cfunction_call(mangled, parms);
        cres = Swig_cresult(ty, "result", call);
        Setattr(n, "wrap:action", cres);
        Delete(cres);
        Delete(call);
    } else {
        String *call = Swig_cmemberget_call(name, type, self, varcref);
        String *cres = Swig_cresult(ty, "result", call);
        Setattr(n, "wrap:action", cres);
        Delete(call);
        Delete(cres);
    }
    Setattr(n, "type", ty);
    Setattr(n, "parms", parms);
    Delete(parms);
    Delete(ty);
    Delete(membername);
    Delete(gname);
    Delete(mangled);

    return SWIG_OK;
}
Пример #9
0
int Swig_MembersetToFunction(Node *n, String *classname, int flags, String **call) {
    String *name;
    ParmList *parms;
    Parm *p;
    SwigType *t;
    SwigType *ty;
    SwigType *type;
    SwigType *void_type = NewString("void");
    String *membername;
    String *mangled;
    String *self = 0;
    String *sname;

    int varcref = flags & CWRAP_NATURAL_VAR;

    if (flags & CWRAP_SMART_POINTER) {
        self = NewString("(*this)->");
    }
    if (flags & CWRAP_ALL_PROTECTED_ACCESS) {
        self = NewStringf("darg->");
    }

    name = Getattr(n, "name");
    type = Getattr(n, "type");

    sname = Swig_name_set(name);
    membername = Swig_name_member(classname, sname);
    mangled = Swig_name_mangle(membername);

    t = NewString(classname);
    SwigType_add_pointer(t);
    parms = NewParm(t, "self");
    Setattr(parms, "self", "1");
    Setattr(parms, "hidden","1");
    Delete(t);

    ty = Swig_wrapped_member_var_type(type, varcref);
    p = NewParm(ty, name);
    Setattr(parms, "hidden", "1");
    set_nextSibling(parms, p);

    /* If the type is a pointer or reference.  We mark it with a special wrap:disown attribute */
    if (SwigType_check_decl(type, "p.")) {
        Setattr(p, "wrap:disown", "1");
    }
    Delete(p);

    if (flags & CWRAP_EXTEND) {
        String *cres;
        String *code = Getattr(n, "code");
        if (code) {
            /* I don't think this ever gets run - WSF */
            Swig_add_extension_code(n, mangled, parms, void_type, code, cparse_cplusplus, "self");
        }
        *call = Swig_cfunction_call(mangled, parms);
        cres = NewStringf("%s;", *call);
        Setattr(n, "wrap:action", cres);
        Delete(cres);
    } else {
        String *cres;
        *call = Swig_cmemberset_call(name, type, self, varcref);
        cres = NewStringf("%s;", *call);
        Setattr(n, "wrap:action", cres);
        Delete(cres);
    }
    Setattr(n, "type", void_type);
    Setattr(n, "parms", parms);
    Delete(parms);
    Delete(ty);
    Delete(void_type);
    Delete(membername);
    Delete(sname);
    Delete(mangled);
    Delete(self);
    return SWIG_OK;
}
Пример #10
0
int
Swig_MethodToFunction(Node *n, String *classname, int flags) {
  String   *name, *qualifier;
  ParmList *parms;
  SwigType *type;
  Parm     *p;
  String   *self = 0;

  /* If smart pointer, change self derefencing */
  if (flags & CWRAP_SMART_POINTER) {
    self = NewString("(*this)->");
  }
  /* If node is a member template expansion, we don't allow added code */

  if (Getattr(n,"templatetype")) flags &= ~(CWRAP_EXTEND);

  name      = Getattr(n,"name");
  qualifier = Getattr(n,"qualifier");
  parms     = CopyParmList(nonvoid_parms(Getattr(n,"parms")));
 
  type = NewString(classname);
  if (qualifier) {
    SwigType_push(type,qualifier);
  }
  SwigType_add_pointer(type);
  p = NewParm(type,"self");
  Setattr(p,"hidden","1");
  set_nextSibling(p,parms);
  Delete(type);
  
  /* Generate action code for the access */
  if (!(flags & CWRAP_EXTEND)) {
    Setattr(n,"wrap:action", Swig_cresult(Getattr(n,"type"),"result", Swig_cmethod_call(name,p,self)));
  } else {
    String *code;
    String *mangled;
    String *membername = Swig_name_member(classname, name);
    mangled = Swig_name_mangle(membername);

    code = Getattr(n,"code");
    type = Getattr(n,"type");

    /* Check if the method is overloaded.   If so, and it has code attached, we append an extra suffix
       to avoid a name-clash in the generated wrappers.  This allows overloaded methods to be defined
       in C. */

    if (Getattr(n,"sym:overloaded") && code) {
      Append(mangled,Getattr(n,"sym:overname"));
    }

    Setattr(n,"wrap:action", Swig_cresult(Getattr(n,"type"),"result", Swig_cfunction_call(mangled,p)));

    /* See if there is any code that we need to emit */
    if (code) {
      String *body;
      String *tmp = NewStringf("%s(%s)", mangled, ParmList_str(p));
      body = SwigType_str(type,tmp);
      Delete(tmp);
      Printv(body,code,"\n",NIL);
      Setattr(n,"wrap:code",body);
    }
    Delete(membername);
    Delete(mangled);
  }
  Setattr(n,"parms",p);
  Delete(p);
  Delete(self);
  return SWIG_OK;
}
Пример #11
0
Parm *NewParmNode(SwigType *type, Node *from_node) {
  Parm *p = NewParm(type, Getattr(from_node, "name"), from_node);
  Setattr(p, "sym:symtab", Getattr(from_node, "sym:symtab"));
  return p;
}
Пример #12
0
static void AddParms( void )
{
    PARMPTR             parm;
    PARMPTR             prev_parm;
    SYM_HANDLE          sym_handle;
    SYM_HANDLE          prev_sym_handle;
    SYM_HANDLE          new_sym_handle;
    TYPEPTR             typ = NULL;
    int                 parm_count;
    id_hash_idx         h;
    parm_list           *parmlist;
    SYM_ENTRY           new_sym;

    CurFunc->u.func.locals = SYM_NULL;
    CurFunc->u.func.parms = SYM_NULL;
    parmlist = NULL;
    prev_sym_handle = SYM_NULL;
    parm_count = 0;
    prev_parm = NULL;
    for( parm = ParmList; parm != NULL; parm = parm->next_parm ) {
        new_sym_handle = SYM_NULL;
        parm->sym.flags |= SYM_DEFINED | SYM_ASSIGNED;
        parm->sym.attribs.is_parm = true;
        h = parm->sym.info.hash;
        if( parm->sym.name[0] == '\0' ) {
            /* no name ==> ... */
            parm->sym.sym_type = GetType( TYPE_DOT_DOT_DOT );
            parm->sym.attribs.stg_class = SC_AUTO;
        } else if( parm->sym.sym_type == NULL ) {
            parm->sym.sym_type = TypeDefault();
            parm->sym.attribs.stg_class = SC_AUTO;
        } else {
            /*
                    go through ParmList again, looking for FLOAT parms
                    change the name to ".P" and duplicate the symbol with type
                    float and generate an assignment statement.
            */
            typ = parm->sym.sym_type;
            SKIP_TYPEDEFS( typ );

            switch( typ->decl_type ) {
            case TYPE_CHAR:
            case TYPE_UCHAR:
            case TYPE_SHORT:
                if( CompFlags.strict_ANSI ) {
                    parm->sym.sym_type = GetType( TYPE_INT );
                }
                break;

            case TYPE_USHORT:
                if( CompFlags.strict_ANSI ) {
#if TARGET_SHORT == TARGET_INT
                    parm->sym.sym_type = GetType( TYPE_UINT );
#else
                    parm->sym.sym_type = GetType( TYPE_INT );
#endif
                }
                break;

            case TYPE_FLOAT:
                memcpy( &new_sym, &parm->sym, sizeof( SYM_ENTRY ) );
                new_sym.handle = CurFunc->u.func.locals;
                new_sym_handle = SymAdd( h, &new_sym );
                CurFunc->u.func.locals = new_sym_handle;
                SymReplace( &new_sym, new_sym_handle );
                parm->sym.name = ".P";
                parm->sym.flags |= SYM_REFERENCED;
                parm->sym.sym_type = GetType( TYPE_DOUBLE );
                break;

            default:
                break;
            }
        }
        sym_handle = SymAdd( h, &parm->sym );
        if( new_sym_handle != SYM_NULL ) {
            TREEPTR         tree;

            tree = ExprNode( VarLeaf( &new_sym, new_sym_handle ),
                             OPR_EQUALS, RValue( VarLeaf( &parm->sym, sym_handle ) ) );
            tree->op.u2.result_type = typ;
            tree->u.expr_type = typ;
            AddStmt( tree );
        }

        if( prev_parm == NULL ) {
            CurFunc->u.func.parms = sym_handle;
        } else {
            prev_parm->sym.handle = sym_handle;
            SymReplace( &prev_parm->sym, prev_sym_handle );
            CMemFree( prev_parm );
        }
        prev_parm = parm;
        prev_sym_handle = sym_handle;
        ++parm_count;
        parmlist = NewParm( parm->sym.sym_type, parmlist );
    }
    if( prev_parm != NULL ) {
        prev_parm->sym.handle = SYM_NULL;
        SymReplace( &prev_parm->sym, prev_sym_handle );
        CMemFree( prev_parm );
    }
    typ = CurFunc->sym_type;
    // TODO not following my scheme
    CurFunc->sym_type = FuncNode( typ->object, FLAG_NONE,
                                  MakeParmList( parmlist, ParmsToBeReversed( CurFunc->mods, NULL ) ) );

    if( PrevProtoType != NULL ) {
        ChkProtoType();
    }
}