void AMXStackFramePrinter::PrintArgument(const AMXStackFrame &frame,
                                         const AMXDebugSymbol &arg,
                                         int index) {
  if (arg.IsReference()) {
    *stream_ << "&";
  }

  PrintTag(arg);
  *stream_ << arg.GetName();

  if (!arg.IsVariable()) {
    std::vector<AMXDebugSymbolDim> dims = arg.GetDims();

    if (arg.IsArray() || arg.IsArrayRef()) {
      for (std::size_t i = 0; i < dims.size(); ++i) {
        if (dims[i].GetSize() == 0) {
          *stream_ << "[]";
        } else {
          std::string tag = debug_info_->GetTagName(dims[i].GetTag()) + ":";
          if (tag == "_:") tag.clear();
          *stream_ << "[" << tag << dims[i].GetSize() << "]";
        }
      }
    }
  }

  *stream_ << "=";
  PrintArgumentValue(frame, arg, index);
}
void AMXStackFramePrinter::PrintCallerName(const AMXStackFrame &frame) {
  if (IsMain(frame.amx(), frame.caller_address())) {
    stream_ << "main";
    return;
  }

  if (debug_info_.IsLoaded()) {
    AMXDebugSymbol caller =
      debug_info_.GetExactFunction(frame.caller_address());
    if (caller) {
      if (IsPublicFunction(frame.amx(), caller.GetCodeStart())
          && !IsMain(frame.amx(), caller.GetCodeStart())) {
        stream_ << "public ";
      }
      PrintTag(caller);
      stream_ << caller.GetName();
      return;
    }
  }

  const char *name = 0;
  if (frame.caller_address() != 0) {
    name = frame.amx().FindPublic(frame.caller_address());
  }
  if (name != 0) {
    stream_ << "public " << name;
  } else {
    stream_ << "??";
  }
}
void AMXStackFramePrinter::PrintCallerName(const AMXStackFrame &frame,
                                           const AMXDebugSymbol &caller) {
  bool is_public = IsPublicFunction(frame.amx(),
                                    caller.GetCodeStart());
  bool is_main = IsMain(frame.amx(), caller.GetCodeStart());
  if (is_public && !is_main) {
    *stream_ << "public ";
  }
  PrintTag(caller);
  *stream_ << caller.GetName();
}