int context_parser::handle_template(definition_scope *scope, token_t& token, unsigned inherited_flags)
{
  token = read_next_token(scope);
  if (token.type != TT_LESSTHAN) {
    token.report_error(herr, "Expected opening triangle bracket following `template' token");
    return ERROR_CODE;
  }
  token = read_next_token(scope);
  
  definition_template* temp = new definition_template("", scope, DEF_TEMPLATE | inherited_flags);
  
  for (;;) {
    string pname; // The name given to this parameter
    unsigned dtpflags = DEF_TEMPPARAM | DEF_DEPENDENT;
    
    definition_tempparam* dtn;
    if (token.type == TT_TYPENAME || token.type == TT_CLASS || token.type == TT_STRUCT) {
      token = lex->get_token(herr);
      if (token.type == TT_IDENTIFIER) {
        pname = token.content.toString();
        token = read_next_token(temp);
      }
      dtpflags |= DEF_TYPENAME;
    }
    else if (token.type == TT_DECFLAG || token.type == TT_DECLARATOR || token.type == TT_DECLTYPE) {
      full_type fts = read_fulltype(token, temp);
      pname = fts.refs.name;
    }
    else {
      if (token.type == TT_GREATERTHAN) break;
      token.report_errorf(herr, "Expected '>' token here before %s");
      FATAL_RETURN((delete temp, 1));
      break;
    }
    
    AST *ast = NULL;
    if (token.type == TT_OPERATOR) {
      if (token.content.len != 1 or *token.content.str != '=') {
        token.report_error(herr, "Unexpected operator here; value must be denoted by '='");
        FATAL_RETURN((void(delete temp),1));
      }
      token = read_next_token(temp);
      ast = new AST();
      ast->set_use_for_templates(true);
      astbuilder->parse_expression(ast, token, temp, precedence::comma+1);
    }
    dtn = new definition_tempparam(pname, temp, ast, dtpflags);
    
    temp->params.push_back(dtn);
    if (pname.empty()) {
      char nname[32];
      sprintf(nname, "<templateParam%03u>", (unsigned)temp->params.size());
    }
    else
      temp->use_general(pname, dtn);
    if (token.type == TT_GREATERTHAN)
      break;
    if (token.type != TT_COMMA)
      token.report_errorf(herr, "Expected '>' or ',' before %s");
    token = read_next_token(temp);
  }
  
  token = read_next_token(temp);
  
  // ========================================================================================================================================
  // =====: Handle template class definitions :==============================================================================================
  // ========================================================================================================================================
  
  if (token.type == TT_CLASS || token.type == TT_STRUCT)
  {
    unsigned protection = token.type == TT_CLASS? DEF_PRIVATE : 0;
    token = read_next_token(scope);
    definition_class *tclass;
    
    if (token.type == TT_IDENTIFIER) {
      regular_identifier:
      temp->name = token.content.toString();
      tclass = new definition_class(temp->name, temp, DEF_CLASS | DEF_TYPENAME);
      temp->def = tclass;
    
      scope->declare(temp->name, temp);
      
      token = read_next_token(scope);
      regular_template_class:
      
      if (token.type == TT_COLON) {
        if (handle_class_inheritance(tclass, token, tclass, protection))
          return 1;
      }
      
      if (token.type != TT_LEFTBRACE) {
        if (token.type == TT_SEMICOLON) {
          tclass->flags |= DEF_INCOMPLETE;
          return 0;
        }
        token.report_errorf(herr, "Opening brace for class body expected before %s");
        return 1;
      }
      
      if (handle_scope(tclass, token, protection))
        FATAL_RETURN(1);
      
      if (token.type != TT_RIGHTBRACE) {
        token.report_errorf(herr, "Expected closing brace to class body before %s");
        FATAL_RETURN(1);
      }
      
      return 0;
    }
    else if (token.type == TT_DEFINITION) {
      if (token.def->parent != scope)
        goto regular_identifier;
      
      if (not((token.def->flags & DEF_TEMPLATE) && (((definition_template*)token.def)->def->flags & DEF_CLASS))) {
        token.report_error(herr, "Expected class name for specialization; `" + token.def->name + "' does not name a template class");
        delete temp;
        return 1;
      }
      
      definition_template *basetemp = (definition_template*)token.def;
      
      token = read_next_token(temp);
      
      if (token.type != TT_LESSTHAN) {
        if (basetemp->def && (basetemp->def->flags & (DEF_CLASS | DEF_INCOMPLETE)) == (DEF_CLASS | DEF_INCOMPLETE)) {
          if (basetemp->params.size() != temp->params.size()) {
            token.report_error(herr, "Argument count differs from forward declaration");
            delete temp;
            return 1;
          }
          for (size_t i = 0; i < basetemp->params.size(); ++i) {
            if (basetemp->params[i]->flags != temp->params[i]->flags) {
              token.report_error(herr, "Parameter " + value((long)i).toString() + " of declaration differs from forward");
              delete temp;
              return 1;
            }
            if (!temp->params[i]->name.empty() && basetemp->params[i]->name != temp->params[i]->name) {
              definition_scope::defiter it = basetemp->using_general.find(basetemp->params[i]->name);
              if (it != basetemp->using_general.end())
                if (it->second == basetemp->params[i])
                  basetemp->using_general.erase(it);
                else token.report_warning(herr, "Template parameter `" + basetemp->params[i]->name
                                          + "' in forward declaration's using is not mapped to `" + temp->params[i]->name + "'");
              else if (!basetemp->params[i]->name.empty())
                token.report_warning(herr, "Template parameter `" + basetemp->params[i]->name
                                     + "' not found in forward declaration's using; cannot be renamed to `" + temp->params[i]->name + "'");
              
              basetemp->params[i]->name = temp->params[i]->name;
              basetemp->use_general(basetemp->params[i]->name, basetemp->params[i]);
            }
          }
          delete temp;
          temp = basetemp;
          tclass = (definition_class*)temp->def;
          goto regular_template_class;
        }
        token.report_errorf(herr, "Expected opening triangle bracket for template definition before %s");
        delete temp;
        return 1;
      }
      
      arg_key argk(basetemp->params.size());
      definition_template::specialization *spec = new definition_template::specialization(basetemp->params.size(), temp->params.size(), temp);
      argk.mirror_types(basetemp);
      size_t args_given = 0;
      for (;;++args_given)
      {
        token = read_next_token(temp);
        if (token.type == TT_GREATERTHAN)
          break;
        if (token.type == TT_SEMICOLON || token.type == TT_LEFTBRACE) {
          token.report_errorf(herr, "Expected closing triangle bracket to template parameters before %s");
          break;
        }
        
        if (token.type == TT_COMMA) continue;
        
        if (args_given >= basetemp->params.size()) {
          token.report_error(herr, "Too many parameters for template `" + basetemp->name + "'");
          delete temp; return 1;
        }
        
        if ((argk[args_given].type == arg_key::AKT_VALUE)
        and (token.type == TT_DEFINITION or token.type == TT_DECLARATOR) and (token.def->flags & DEF_TEMPPARAM))
        {
          for (size_t i = 0; i < temp->params.size(); ++i) if (temp->params[i] == token.def) {
            if (~temp->params[i]->flags & DEF_TYPENAME) {
              spec->key.arg_inds[i][++spec->key.arg_inds[i][0]] = args_given;
              argk[args_given].val() = VT_DEPENDENT;
              token = read_next_token(temp);
              goto handled_argk; // break 2;
            }
            else
              token.report_error(herr, "Type mismatch in passing parameter " + parse_bacics::visible::toString(args_given) + " to template specialization: real-valued parameter expected");
          }
        }
        
        if (read_template_parameter(argk, args_given, basetemp, token, temp)) {
          delete temp; // XXX: is this needed?
          return 1;
        }
        
        if (argk[args_given].type == arg_key::AKT_FULLTYPE) {
          definition *def = argk[args_given].ft().def;
          for (size_t i = 0; i < temp->params.size(); ++i) if (temp->params[i] == def) {
            spec->key.arg_inds[i][++spec->key.arg_inds[i][0]] = args_given;
            argk[args_given].ft().def = arg_key::abstract;
          }
        }
        
        handled_argk:
        
        if (token.type == TT_GREATERTHAN) {
          ++args_given;
          break;
        }
        if (token.type != TT_COMMA) {
          token.report_errorf(herr, "Comma or closing triangle bracket expected here before %s");
          break;
        }
      }
      if (check_read_template_parameters(argk, args_given, basetemp, token, herr)) {
        delete temp; // XXX: Needed?
        return 1;
      }
      
      // cout << "Specialization key: " << argk.toString() << endl;
      spec->filter = argk;
      definition_template::speclist &slist = basetemp->specializations;
      
      for (definition_template::speclist::iterator it = slist.begin(); it != slist.end(); ++it)
        if ((*it)->key.same_as(spec->key))
        {
          delete spec;
          spec = *it;
          
          if (~spec->spec_temp->flags & DEF_INCOMPLETE) {
            token.report_error(herr, "Cannot specialize template: specialization by this type already exists.");
            delete temp;
            return 1;
          }
          
          spec->spec_temp->using_general.clear(); // XXX: Maybe replace this with something to specifically delete template parameters, just in case? Could anything else be used? I'm thinking not.
          for (definition_template::piterator pit = temp->params.begin(); pit != temp->params.end(); ++pit)
            spec->spec_temp->use_general((*pit)->name, *pit);
          
          delete temp;
          temp = spec->spec_temp;
          break;
        }
      slist.push_back(spec);
      
      temp->name = basetemp->name + "<" + argk.toString() + ">";
      tclass = new definition_class(temp->name, temp, DEF_CLASS | DEF_TYPENAME);
      temp->def = tclass;
      tclass->instance_of = basetemp;
      
      token = read_next_token(scope);
      goto regular_template_class;
    }
    
    token.report_errorf(herr, "Expected class name here before %s");
    delete temp;
    return 1;
  }
  
  // ========================================================================================================================================
  // =====: Handle template function definitions :===========================================================================================
  // ========================================================================================================================================
  
  int funcflags = 0;
  if (token.type == TT_DECLARATOR || token.type == TT_DECFLAG || token.type == TT_DECLTYPE || token.type == TT_DEFINITION || token.type == TT_TYPENAME)
  {
    full_type funcrefs = read_fulltype(token, temp);
    if (!funcrefs.def) {
      if (token.type == TT_OPERATORKW) {
        funcflags = funcrefs.flags;
        if (!funcrefs.refs.empty()) {
          token.report_error(herr, "Program error: references attatched to typeless expression");
          return 1;
        }
        goto template_cast_operator;
      }
      token.report_error(herr, "Expected return type for template function at this point");
      delete temp;
      return 1;
    }
    
    if (funcrefs.refs.empty() || funcrefs.refs.top().type != ref_stack::RT_FUNCTION) {
      if (token.type == TT_DEFINITION && in_template(token.def)) {
        read_qualified_definition(token, scope); // We don't need to know the definition, just skip it. If we were a compiler, we'd need to know this. :P
        if (token.type == TT_OPERATOR && token.content.len == 1 && *token.content.str == '=') { // We don't need to know the value, either; we just need to skip it.
          token = read_next_token(scope);
          AST a; astbuilder->parse_expression(&a, token, scope, precedence::comma); // Read and discard; kind of a hack, but it's safe.
        }
        if (token.type != TT_SEMICOLON) {
          if (token.type == TT_LEFTPARENTH) // We're implementing a template function within a different class
          {
            read_referencers_post(funcrefs.refs, token, temp);
            if (token.type == TT_LEFTBRACE)
              delete_function_implementation(handle_function_implementation(lex, token, temp, herr));
            else
              token.report_error(herr, "I have no idea where I am.");
            delete temp;
            return 0;
          }
          token.report_errorf(herr, "Expected semicolon following template member definition before %s");
          FATAL_RETURN((void(delete temp), 1));
        }
        delete temp; // We're done with temp.
        return 0;
      }
      if (funcrefs.refs.ndef && funcrefs.refs.ndef->flags & DEF_HYPOTHETICAL) {
        // TODO: Do some error checking here to make sure whatever's being declared in that AST is a member of the template. Mark it non-extern.
      }
      else if (funcrefs.refs.ndef && (funcrefs.refs.ndef->flags & DEF_TYPED)) {
          definition_typed* dt = (definition_typed*)funcrefs.refs.ndef;
        if (dt->modifiers & builtin_flag__static)
          dt->flags &= ~DEF_INCOMPLETE; // TODO: Make structures OR static members by DEF_INCOMPLETE on creation; add error checking here
        else
          token.report_error(herr, "Definition of non-static member `" + dt->name + "'");
      }
      else
        token.report_errorf(herr, "Definition in template must be a function; `" + funcrefs.def->name + " " + funcrefs.refs.name + "' is not a function (at %s)");
      delete temp;
      return 1;
    }
    
    string funcname = funcrefs.refs.name;
    if (funcname.empty()) {
      if ((funcrefs.refs.ndef && funcrefs.refs.ndef->name == constructor_name) || is_potential_constructor(scope, funcrefs)) {
        funcname = constructor_name;
        if (token.type == TT_COLON) {
          // TODO: Actually store this. And the other one. :P
          handle_constructor_initializers(lex, token, scope, herr);
        }
      }
      else if (!funcrefs.refs.ndef) {
        token.report_error(herr, "Template functions must have names");
        delete temp;
        return 1;
      }
    }
    
    definition_function *func = NULL;
    definition *maybe = funcrefs.refs.ndef;
    if (!maybe)
      maybe = scope->find_local(funcname);
    if (maybe)
      if (!(maybe->flags & DEF_FUNCTION)) {
        token.report_error(herr, "Cannot redeclare " + maybe->kind() + " `" + funcname + "' as function in this scope");
        delete temp;
        return 1;
      }
      else func = (definition_function*)maybe;
    else {}
    
    definition_overload *tovr = new definition_overload(funcname, scope, funcrefs.def, funcrefs.refs, funcrefs.flags, DEF_FUNCTION);
    temp->def = tovr;
    
    if (!func)
      scope->declare(funcname, func = new definition_function(funcname, scope));
    func->overload(temp, herr);
    
    if (token.type == TT_COLON) {
      token.report_error(herr, "Unexpected colon; `" + funcname + "' is not a constructor");
      return 1;
    }
    
    if (token.type == TT_LEFTBRACE)
      tovr->implementation = (handle_function_implementation(lex, token, temp, herr));
    else if (token.type != TT_SEMICOLON) {
      token.report_errorf(herr, "Expected template function body or semicolon before %s");
      FATAL_RETURN(1);
    }
  }
  else if (token.type == TT_OPERATORKW) {
    template_cast_operator:
    full_type ft = read_operatorkw_cast_type(token, temp);
    definition_overload *ovr = new definition_overload("(cast)", scope, ft.def, ft.refs, ft.flags, DEF_FUNCTION | inherited_flags | funcflags);
    if (!ovr)
      return 1;
    if (token.type == TT_LEFTBRACE)
      ovr->implementation = handle_function_implementation(lex, token, scope, herr);
    else ovr->flags |= DEF_INCOMPLETE;
    temp->def = ovr;
    scope->overload_function("(cast)", temp, inherited_flags | funcflags, token, herr);
    return 0;
  }
  else if (token.type == TT_TEMPLATE) {
    // FIXME: OH MY F*****G WHAT
    // These templates are used when declaring functions which have templates as parameters,
    handle_template(temp, token, inherited_flags);
    delete temp;
    return 0;
  }
  else if (token.type == TT_FRIEND) {
    if (scope->flags & DEF_CLASS) {
      token = read_next_token(scope);
      if (token.type == TT_CLASS) {
        read_qualified_definition(token, temp);
        delete temp;
        if (token.type != TT_SEMICOLON)
          token.report_errorf(herr, "Expected semicolon to close friend statement before %s");
        return 0; // TODO: store this friend somewhere
      }
      else {
        read_fulltype(token, temp);
        delete temp;
        if (token.type != TT_SEMICOLON)
          token.report_errorf(herr, "Expected semicolon to close friend statement before %s");
        return 0; // TODO: store this friend somewhere
      }
      delete temp;
    }
    else {
      token.report_error(herr, "Unexpected `friend' statement: not in a class");
      delete temp;
      return 1;
    }
  }
  else {
    token.report_errorf(herr, "Expected class or function declaration following template clause before %s");
    delete temp;
    return ERROR_CODE;
  }
  
  
  return 0;
}