' Copyright (c) 2021-2022 Thomas Hugo Williams
' License MIT <https://opensource.org/licenses/MIT>
' For MMBasic 5.07

Option Base 0
Option Default None
Option Explicit On

#Include "../sptools/src/splib/system.inc"
#Include "../sptools/src/splib/string.inc"

Const LF$ = Chr$(10)

Dim max_page_name_len% = 0

main()
End

Sub main()
  read_csv_file(Mm.Info$(Path) + "../resources/mmb4l_codepages.csv")
  write_c_file(Mm.Info$(Path) + "../linux-src/common/codepage.c")
  write_h_file(Mm.Info$(Path) + "../linux-src/common/codepage.h")
  Print "Done"
End Sub

Sub read_csv_file(f$)
  Local i%, j%, s$

  Print "Reading " f$ " ..."
  Open f$ For Input As #1

  Line Input #1, s$
  Dim num_codepages% = Val(Field$(s$, 1, ","))

  Dim page_names$(num_codepages%)
  For i% = 1 To num_codepages%
    page_names$(i%) = Field$(s$, 2 + (i% - 1) * 4, ",")
    max_page_name_len% = Max(max_page_name_len%, Len(page_names$(i%)))
'    Print page_names$(i%)
  Next

  Dim code_points%(128 * num_codepages%)

  ' Skip two lines.
  Line Input #1, s$
  Line Input #1, s$

  ' Read code points.
  For i% = 1 To 128
    Line Input #1, s$
    For j% = 1 To num_codepages%
      code_points%(128 * (j% - 1) + i%) = Val("&h" + Field$(s$, 2 + (j% - 1) * 4, ","))
    Next
  Next

  Close #1
End Sub

Sub write_c_file(f$)
  Local i%, j%, k%, utf8$

  Print "Writing " f$ " ..."
  Open f$ For Output As #1

  Print #1, "// This file is autogenerated from 'resources/mmb4l_codepages.csv'" LF$;
  Print #1, LF$;

  Print #1, "#include <stddef.h>" LF$;
  Print #1, LF$;
  Print #1, "#include " str.quote$("codepage.h") LF$;
  Print #1, LF$;

  For i% = 1 To num_codepages%
    Print #1, "static char CODEPAGE_" page_names$(i%) "_UTF8[] = {" LF$;
    For j% = 1 To 128
      utf8$ = Chr$(UTF8 code_points%(128 * (i% - 1) + j%))
      Print #1, "    ";
      For k% = 1 To 4
        If k% > Len(utf8$) Then
          Print #1, "0x00";
        Else
          Print #1, "0x" Hex$(Peek(Byte Peek(VarAddr utf8$) + k%), 2);
        EndIf
        Print #1, Choice(k% = 4, ",", ", ");
      Next
      Print #1, LF$;
    Next
    Print #1, "};" LF$;
    Print #1, LF$;
  Next

  Print #1, "const NameOrdinalPair codepage_name_to_ordinal_map[] = {" LF$;
  Print #1, "    { " str.rpad$(str.quote$("None") + ",", max_page_name_len% + 3);
  Print #1, " kCodepageNone }," LF$;
  For i% = 1 To num_codepages%
    Print #1, "    { " str.rpad$(str.quote$(page_names$(i%)) + ",", max_page_name_len% + 3);
    Print #1, " kCodepage" page_names$(i%) " }," LF$;
  Next
  Print #1, "    { NULL, -1 }" LF$;
  Print #1, "};" LF$;
  Print #1, LF$;

  Print #1, "const NameOrdinalPair codepage_data_to_ordinal_map[] = {" LF$;
  Print #1, "    { " str.rpad$("NULL,", max_page_name_len% + 15) " kCodepageNone }," LF$;
  For i% = 1 To num_codepages%
    Print #1, "    { " str.rpad$("CODEPAGE_" + page_names$(i%) + "_UTF8,", max_page_name_len% + 15);
    Print #1, " kCodepage" page_names$(i%) " }," LF$;
  Next
  Print #1, "    { NULL, -1 }" LF$;
  Print #1, "};" LF$;

  Close #1
End Sub

Sub write_h_file(f$)
  Local i%, j%, k%, utf8$

  Print "Writing " f$ " ..."
  Open f$ For Output As #1

  Print #1, "// This file is autogenerated from 'resources/mmb4l_codepages.csv'" LF$;
  Print #1, LF$;

  Print #1, "#if !defined(MMB4L_CODEPAGE_H)" LF$;
  Print #1, "#define MMB4L_CODEPAGE_H" LF$;
  Print #1, LF$;
  Print #1, "#include " str.quote$("options.h") LF$;
  Print #1, LF$;

  Print #1, "typedef enum {" LF$;
  Print #1, "    kCodepageNone," LF$;
  For i% = 1 To num_codepages%
    Print #1, "    kCodepage" page_names$(i%);
    If i% < num_codepages% Then Print #1, "," LF$;
  Next
  Print #1, " } CodepageEnum;" LF$;
  Print #1, LF$;

  Print #1, "extern const NameOrdinalPair codepage_name_to_ordinal_map[];" LF$;
  Print #1, LF$;
  Print #1, "// Note that codepage data is (const char *) so we can reuse NameOrdinalPair." LF$;
  Print #1, "extern const NameOrdinalPair codepage_data_to_ordinal_map[];" LF$;
  Print #1, LF$;
  Print #1, "#endif" LF$;

  Close #1
End Sub
