/*
 * Copyright (c) 2004-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "kern/linux/printk.hh"

#include <sys/types.h>

#include <algorithm>
#include <iostream>
#include <sstream>

#include "base/compiler.hh"
#include "cpu/thread_context.hh"
#include "mem/port_proxy.hh"
#include "mem/translating_port_proxy.hh"

namespace gem5
{

GEM5_DEPRECATED_NAMESPACE(Linux, linux);
namespace linux
{

int
printk(std::string &str, ThreadContext *tc, Addr format_ptr,
        PrintkVarArgs args)
{
    std::string format;
    std::ostringstream out;
    TranslatingPortProxy proxy(tc);
    proxy.readString(format, format_ptr);

    const char *p = format.c_str();

    while (*p) {
        switch (*p) {
          case '%': {
            bool more = true;
            bool islong = false;
            bool leftjustify = false;
            bool format = false;
            bool zero = false;
            int width = 0;
            while (more && *++p) {
                switch (*p) {
                  case 'l':
                  case 'L':
                    islong = true;
                    break;
                  case '-':
                    leftjustify = true;
                    break;
                  case '#':
                    format = true;
                    break;
                  case '0':
                    if (width)
                        width *= 10;
                    else
                        zero = true;
                    break;
                  default:
                    if (*p >= '1' && *p <= '9')
                        width = 10 * width + *p - '0';
                    else
                        more = false;
                    break;
                }
            }

            bool hexnum = false;
            bool octal = false;
            bool sign = false;
            switch (*p) {
              case 'X':
              case 'x':
                hexnum = true;
                break;
              case 'O':
              case 'o':
                octal = true;
                break;
              case 'D':
              case 'd':
                sign = true;
                break;
              case 'P':
                format = true;
                [[fallthrough]];
              case 'p':
                hexnum = true;
                break;
            }

            switch (*p) {
              case 'D':
              case 'd':
              case 'U':
              case 'u':
              case 'X':
              case 'x':
              case 'O':
              case 'o':
              case 'P':
              case 'p': {
                    if (hexnum)
                        out << std::hex;

                    if (octal)
                        out << std::oct;

                    if (format) {
                        if (!zero)
                            out.setf(std::ios::showbase);
                        else {
                            if (hexnum) {
                                out << "0x";
                                width -= 2;
                            } else if (octal) {
                                out << "0";
                                width -= 1;
                            }
                        }
                    }

                    if (zero)
                        out.fill('0');

                    if (width > 0)
                        out.width(width);

                    if (leftjustify && !zero)
                        out.setf(std::ios::left);

                    if (sign) {
                        if (islong)
                            out << args.get<int64_t>();
                        else
                            out << args.get<int32_t>();
                    } else {
                        if (islong)
                            out << args.get<uint64_t>();
                        else
                            out << args.get<uint32_t>();
                    }

                    if (zero)
                        out.fill(' ');

                    if (width > 0)
                        out.width(0);

                    out << std::dec;
                }
                break;

              case 's': {
                    Addr s_ptr = args.get<Addr>();
                    std::string s;
                    if (s_ptr)
                        proxy.readString(s, s_ptr);
                    else
                        s = "<NULL>";

                    if (width > 0)
                        out.width(width);
                    if (leftjustify)
                        out.setf(std::ios::left);

                    out << s;
                }
                break;
              case 'C':
              case 'c': {
                    uint64_t mask = (*p == 'C') ? 0xffL : 0x7fL;
                    uint64_t num;
                    int cwidth;

                    if (islong) {
                        num = args.get<uint64_t>();
                        cwidth = sizeof(uint64_t);
                    } else {
                        num = args.get<uint32_t>();
                        cwidth = sizeof(uint32_t);
                    }

                    while (cwidth-- > 0) {
                        char c = (char)(num & mask);
                        if (c)
                            out << c;
                        num >>= 8;
                    }
                }
                break;
              case 'b': {
                    uint64_t n = args.get<uint64_t>();
                    Addr s_ptr = args.get<Addr>();
                    std::string s;
                    proxy.readString(s, s_ptr);
                    out << s << ": " << n;
                }
                break;
              case '%':
                out << '%';
                break;
            }
            ++p;
          }
          break;
        case '\n':
          out << std::endl;
          ++p;
          break;
        case '\r':
          ++p;
          if (*p != '\n')
              out << std::endl;
          break;

        default: {
              size_t len = strcspn(p, "%\n\r\0");
              out.write(p, len);
              p += len;
            }
        }
    }

    str = out.str();
    return str.length();
}

} // namespace linux
} // namespace gem5
