Subject: V2 series

From: unmush <[email-masked]>
Date: Fri, 20 Dec 2024 05:12:29 +0000

Efraim writes:

> It turns out the first 2 patches didn't apply cleanly, so I fixed that
> up and I'm sending them back to the list.

It turns out that git wants to do a full 3-way merge when applying patches, and
I formatted the patches from my local repository which has a bunch of extra
commits in it that touch gnu/local.mk, so the generated patch referenced a file
hash that didn't exist upstream.

> A couple of things that I noticed:
> 
> * mono-5.something doesn't have its patches apply cleanly

mono-5.10's patches didn't apply cleanly because some of the mono sources being
patched used CRLF line endings, and git normalized those in the
patch-containing-the-patch.  This time around I've tried first running "git
config core.autocrlf false", hopefully that fixes it.  Note that you'll need to
pass '--keep-cr' to 'git am'.

> * I was only able to build to mono-3.12 before I got a build failure on
> x86_64

After some discussion in #guix we discovered that the cause for this was that
parallel builds weren't properly supported.  I didn't encounter these failures
very much on my own system because I used --keep-failed, which disabled
offloading so that they were built on my rather weak 4-core system.  I
have since tested without --keep-failed and found consistent built failures with
'#:parallel-build? #t' all the way up to and including mono-5.10.0, so I've
passed '#:parallel-build? #f' to all of those.

I have, however, added `"-j" (number->string (parallel-job-count))' to the
build-reference-assemblies phase, since that phase takes quite a long time and
doesn't seem to have any trouble with parallel builds.

> * mono-1.2.6 doesn't have support for aarch64 or riscv64, and will
> probably need some patches (later) to add support.

Old versions of mono do technically have an interpreter, but by mono-1.2.6 it's
already bitrotted to the point of not working (it's not only missing several
includes, it also refers to nonexistent fields and procedures that seem to have
been since renamed).  They eventually fully deleted the interpreter in 2014 in
commit 6bee6a7b18978aa6ce977b8b0f9ce19cf962f36b, only to later revive it in 2017
(https://www.mono-project.com/news/2017/11/13/mono-interpreter/).  So even if we
fixed up mono 1.2.6's interpreter, we'd need to also get it working for each
version up to 2017 in order to achieve a fully portable bootstrap path.

One alternative option could be some variety of frankenmono: either trying to
backport 2017's interpreter to older versions of mono, or trying to run an old
mono compiler / class library with a newer mono runtime.  Mono's class library
depends on runtime-specific icalls, which may have changed over time in a
non-backwards-compatible way, which could hinder the latter attempt.  The
implementation of those icalls, additionally, is probably going to depend on
code that is also depended on by the interpreter, so replacing runtime internals
to more easily suit the backported interpreter may also require updating those,
which could hinder the former attempt.

Another possibility would be trying to use pnet's ilrun for mono versions up to
2017, but this would run in to the same issues with runtime-specific icalls, so
either mono's class library would need to be adjusted to be able to use pnet's
icalls, or mono's icalls would have to be ported to pnet's ilrun, or mcs would
have to be adjusted to not depend on anything mono-specific (if it doesn't
already).

That last possibility may be one of the most interesting, as compilers usually
don't need many fancy runtime features (they are after all a very basic batch
input-output process that usually solely touches files), and this would
effectively strip every intermediate mono build down to just building
mcs. Additionally, if the build could be stripped down to just building mcs, we
wouldn't need to support the new features used by the class library, which would
allow us to make much bigger jumps between versions.  The sheer amount of work
saved may end up more than making up for ilrun's lower performance.

> * libjit FTBFS on powerpc64le. I tried working around it but wasn't
> successful in when it came to using libjit.
> * The assembly included in libjit targets a too-early version of arm, so
> it is just broken completely on armhf and would probably do best with it
> being ripped out.

libjit is the one component of Portable.NET that outlived its parent project,
and it's been updated as recently as 2020.  It's supposed to fall back to
interpreting on architectures it doesn't support, so it could be that the only
changes that need to be made are to refine its detection process.  In the
meantime, I've adjusted pnet-git to not use libjit on all non-x86 platforms,
instead using pnet's own Converted Virtual Machine (CVM) interpreter.  This was
buggy when using its "unroller" functionality, which requires a small amount of
platform-specific code anyway, so I disabled that.  This also caused a subtle
change in pnetlib-git's test suite, so that a test that previously failed is now
properly reported as failing, so I disabled that (it failed due to requiring
libx11 and an X server, and due to no provision being made for it to find a .so
produced by pnetlib that interfaces with libx11).

A V2 series is attached.  Note: the full series in one message was rejected by debbugs moderators, but presumably made it through to the other CC'ed recipients.  I'm splitting it across some more messages in the hope that it will go through that way.  There should be 21 patches in total.

From f8b05606513f2df1a3d085f90bdd953c8e202ae9 Mon Sep 17 00:00:00 2001
From: unmush <[email-masked]>
Date: Tue, 26 Nov 2024 12:13:32
Subject: [PATCH v2 01/21] gnu: add treecc.

* gnu/packages/dotnet.scm: new module.
  (treecc): new package.
* gnu/local.mk (GNU_SYSTEM_MODULES): add new module.
---
 gnu/local.mk            |  1 +
 gnu/packages/dotnet.scm | 62 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+)
 create mode 100644 gnu/packages/dotnet.scm

diff --git a/gnu/local.mk b/gnu/local.mk
index fbe9dfbb0ef..9ebe49ca864 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -243,6 +243,7 @@ GNU_SYSTEM_MODULES =				\
   %D%/packages/dhall.scm			\
   %D%/packages/dico.scm				\
   %D%/packages/dictd.scm			\
+  %D%/packages/dotnet.scm			\
   %D%/packages/dictionaries.scm			\
   %D%/packages/diffoscope.scm			\
   %D%/packages/digest.scm			\
diff --git a/gnu/packages/dotnet.scm b/gnu/packages/dotnet.scm
new file mode 100644
index 00000000000..3084e1cf3a5
--- /dev/null
+++ b/gnu/packages/dotnet.scm
@@ -0,0 +1,62 @@
+(define-module (gnu packages dotnet)
+  #:use-module ((guix licenses) #:prefix license:)
+  #:use-module (gnu packages assembly)
+  #:use-module (gnu packages bison)
+  #:use-module (gnu packages check)
+  #:use-module (gnu packages cmake)
+  #:use-module (gnu packages compression)
+  #:use-module (gnu packages curl)
+  #:use-module (gnu packages flex)
+  #:use-module (gnu packages gettext)
+  #:use-module (gnu packages pkg-config)
+  #:use-module (gnu packages base)
+  #:use-module (gnu packages autotools)
+  #:use-module (gnu packages bdw-gc)
+  #:use-module (gnu packages fontutils)
+  #:use-module (gnu packages glib)
+  #:use-module (gnu packages icu4c)
+  #:use-module (gnu packages instrumentation)
+  #:use-module (gnu packages kerberos)
+  #:use-module (gnu packages libffi)
+  #:use-module (gnu packages linux)
+  #:use-module (gnu packages llvm)
+  #:use-module (gnu packages perl)
+  #:use-module (gnu packages photo)
+  #:use-module (gnu packages texinfo)
+  #:use-module (gnu packages tls)
+  #:use-module (gnu packages image)
+  #:use-module (gnu packages gtk)
+  #:use-module (gnu packages python)
+  #:use-module (gnu packages xml)
+  #:use-module (gnu packages xorg)
+  #:use-module (gnu packages version-control)
+  #:use-module (gnu packages)
+  #:use-module (guix modules)
+  #:use-module (guix packages)
+  #:use-module (guix download)
+  #:use-module (guix git-download)
+  #:use-module (guix gexp)
+  #:use-module (guix utils)
+  #:use-module (guix build-system gnu)
+  #:use-module (guix build-system python)
+  #:use-module (ice-9 match))
+
+(define-public treecc
+  (package
+    (name "treecc")
+    (version "0.3.10")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append
+                    "https://download.savannah.gnu.org/releases/dotgnu-pnet/treecc-"
+                    version ".tar.gz"))
+              (sha256
+               (base32
+                "1rzgnspg2xccdq3qsx0vi3j28h4qkrzbrjnhzvnny34fjfk217ay"))))
+    (build-system gnu-build-system)
+    (home-page "https://www.gnu.org/software/dotgnu")
+    (synopsis "Tree Compiler-Compiler.")
+    (description "The treecc program is designed to assist in the development
+of compilers and other language-based tools.  It manages the generation of
+code to handle abstract syntax trees and operations upon the trees.")
+    (license license:gpl2+)))
-- 
2.45.2

From 7fd3eb19130d60075e24c1c2b0bd0367386d50ba Mon Sep 17 00:00:00 2001
From: unmush <[email-masked]>
Date: Tue, 26 Nov 2024 12:53:23
Subject: [PATCH v2 03/21] gnu: Add pnetlib-git.

* gnu/packages/dotnet.scm (pnetlib-git): New variable.

---
 gnu/packages/dotnet.scm | 81 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)

diff --git a/gnu/packages/dotnet.scm b/gnu/packages/dotnet.scm
index fd0d71bfe69..9d9cc5421b0 100644
--- a/gnu/packages/dotnet.scm
+++ b/gnu/packages/dotnet.scm
@@ -184,3 +184,84 @@ (define-public pnet-git
 to build and execute .NET applications, including a C# compiler,
 assembler, disassembler, and runtime engine.")
       (license license:gpl2+))))
+
+(define-public pnetlib-git
+  (let ((version "0.8.0")
+        (commit "c3c12b8b0c65f5482d03d6a4865f7670e98baf4c")
+        (revision "0"))
+    (package
+      (name "pnetlib-git")
+      (version (git-version version revision commit))
+      (source (origin
+                (method git-fetch)
+                (uri (git-reference
+                      (url
+                       "https://git.savannah.gnu.org/git/dotgnu-pnet/pnetlib.git")
+                      (commit commit)))
+                (file-name (git-file-name name version))
+                (sha256
+                 (base32
+                  "04dikki3lr3m1cacirld90rpi95656b2y2mc5rkycb7s0yfdz1nk"))
+                (modules '((guix build utils)))
+                (snippet
+                 #~(begin
+                     (for-each delete-file (filter file-exists?
+                                                   '("configure"
+                                                     "config.guess"
+                                                     "config.sub"
+                                                     "install-sh"
+                                                     "ltmain.sh")))
+                     (for-each delete-file (find-files "." "Makefile(\\.in)?$"))
+                     (substitute* (find-files "tests" "^Makefile\\.am$")
+                       (("TESTS_ENVIRONMENT.*")
+                        (string-append
+                         "LOG_COMPILER = $(SHELL)\n"
+                         "AM_LOG_FLAGS = $(top_builddir)/tools/run_test.sh"
+                         " $(top_builddir)")))
+                     (substitute* "tools/run_test.sh.in"
+                       (("en_US") "en_US.utf8"))
+                     (substitute* "tools/wrapper.sh.in"
+                       (("exec .LN_S clrwrap ..1." all)
+                        (string-append
+                         "echo '#!@SHELL@' >> $1\n"
+                         "echo exec $CLRWRAP"
+                         " $(dirname $(dirname $1))"
+                         "/lib/cscc/lib/$(basename $1).exe >> $1\n"
+                         "chmod +x $1")))))))
+      (build-system gnu-build-system)
+      (arguments
+       (list
+        #:make-flags #~(list "CFLAGS+=-Wno-pointer-to-int-cast")
+        #:phases
+        #~(modify-phases %standard-phases
+            (add-after 'unpack 'disable-x11-tests
+              (lambda _
+                (substitute* "tests/Makefile.am"
+                  ;; This actually always fails, for a number of
+                  ;; reasons:
+                  ;; 1. We have no libx11 present, nor do we have an X display
+                  ;;    present.  This will cause libXsharpSupport.so to be
+                  ;;    built with only shims that fail at runtime.
+                  ;; 2. No mechanism is provided for
+                  ;;    tests/System.Windows.Forms/TestForms.dll to find
+                  ;;    libXsharpSupport.so, which seems to sit at
+                  ;;    Xsharp/.libs/libXsharpSupport.so.
+                  ;; With a libjit pnet,
+                  ;; System.Drawing.Toolkit.ToolkitHandler.CreateDefaultToolkit
+                  ;; throws ArgumentNullException when invoking Assembly.Load,
+                  ;; while a cvm pnet instead succeeds temporarily, but then
+                  ;; fails when invoking
+                  ;; System.Drawing.Toolkit.DrawingToolkit..ctor.  For some
+                  ;; reason this results in csunit passing the former and
+                  ;; failing the latter.
+                  (("System\\.Windows\\.Forms") "")))))))
+      (native-inputs
+       (list autoconf automake libtool treecc))
+      (inputs
+       (list pnet-git))
+      (home-page "http://www.gnu.org/software/dotgnu/html2.0/pnet.html")
+      (synopsis "Libraries for the C# programming language")
+      (description
+       "DotGNU Portable.NET Library contains an implementation of the C# library,
+for use with .NET-capable runtime engines and applications.")
+      (license license:gpl2+))))
-- 
2.45.2

From 2954360a9a1d797a72168181ac372d0c3d5c389f Mon Sep 17 00:00:00 2001
From: unmush <[email-masked]>
Date: Tue, 26 Nov 2024 12:44:56
Subject: [PATCH v2 02/21] gnu: Add pnet-git.

* gnu/packages/dotnet.scm (pnet-git): New variable.
* gnu/packages/patches/pnet-fix-line-number-info.patch: new patch.
* gnu/packages/patches/pnet-fix-off-by-one.patch: new patch.
* gnu/packages/patches/pnet-newer-libgc-fix.patch: new patch.
* gnu/packages/patches/pnet-newer-texinfo-fix.patch: new patch.
* gnu/local.mk (dist_patch_DATA): register new patches.

---
 gnu/local.mk                                  |   4 +
 gnu/packages/dotnet.scm                       | 124 ++++++++++++++++++
 .../patches/pnet-fix-line-number-info.patch   |  13 ++
 .../patches/pnet-fix-off-by-one.patch         |  13 ++
 .../patches/pnet-newer-libgc-fix.patch        |  45 +++++++
 .../patches/pnet-newer-texinfo-fix.patch      |  13 ++
 6 files changed, 212 insertions(+)
 create mode 100644 gnu/packages/patches/pnet-fix-line-number-info.patch
 create mode 100644 gnu/packages/patches/pnet-fix-off-by-one.patch
 create mode 100644 gnu/packages/patches/pnet-newer-libgc-fix.patch
 create mode 100644 gnu/packages/patches/pnet-newer-texinfo-fix.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index 9ebe49ca864..0e2d7bfa137 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1923,6 +1923,10 @@ dist_patch_DATA =						\
   %D%/packages/patches/owncloud-disable-updatecheck.patch	\
   %D%/packages/patches/p7zip-CVE-2016-9296.patch		\
   %D%/packages/patches/p7zip-CVE-2017-17969.patch		\
+  %D%/packages/patches/pnet-fix-line-number-info.patch		\
+  %D%/packages/patches/pnet-fix-off-by-one.patch		\
+  %D%/packages/patches/pnet-newer-libgc-fix.patch		\
+  %D%/packages/patches/pnet-newer-texinfo-fix.patch		\
   %D%/packages/patches/p7zip-fix-build-with-gcc-11.patch	\
   %D%/packages/patches/p7zip-remove-unused-code.patch		\
   %D%/packages/patches/pam-krb5-CVE-2020-10595.patch		\
diff --git a/gnu/packages/dotnet.scm b/gnu/packages/dotnet.scm
index 3084e1cf3a5..fd0d71bfe69 100644
--- a/gnu/packages/dotnet.scm
+++ b/gnu/packages/dotnet.scm
@@ -60,3 +60,127 @@ (define-public treecc
 of compilers and other language-based tools.  It manages the generation of
 code to handle abstract syntax trees and operations upon the trees.")
     (license license:gpl2+)))
+
+;; several improvements occurred past the 0.8.0 release that make it easier to
+;; bootstrap mono
+(define-public pnet-git
+  (let ((commit "3baf94734d8dc3fdabba68a8891e67a43ed6c4bd")
+        (version "0.8.0")
+        (revision "0")
+        (libjit-supported?
+         (lambda ()
+           ;; TODO: accurately determine which platforms are
+           ;; and aren't supported by libjit, then use:
+           ;;
+           ;; (supported-package? libjit
+           ;;                     (or (%current-target-system)
+           ;;                         (%current-system)))
+           (target-x86?))))
+    (package
+      (name "pnet-git")
+      (version (git-version version revision commit))
+      (source (origin
+                (method git-fetch)
+                (uri (git-reference
+                      (url "https://git.savannah.gnu.org/git/dotgnu-pnet/pnet.git")
+                      (commit commit)))
+                (file-name (git-file-name name version))
+                (sha256
+                 (base32
+                  "0vznvrgz8l0mpib1rz5v3clr7cn570vyp80f7f1jvzivnc1imzn6"))
+                (modules '((guix build utils)))
+                (snippet
+                 #~(begin
+                     (for-each delete-file-recursively '("libffi" "libgc"))
+                     (for-each delete-file (filter file-exists?
+                                                   '("compile"
+                                                     "configure"
+                                                     "config.guess"
+                                                     "config.sub"
+                                                     "depcomp"
+                                                     "install-sh"
+                                                     "ltconfig"
+                                                     "ltcf-c.sh"
+                                                     "ltmain.sh")))
+                     (for-each delete-file (find-files "." "Makefile(\\.in)?$"))
+                     (for-each delete-file (find-files "." "_grammar\\.(c|h)$"))
+                     (for-each delete-file (find-files "." "_scanner\\.(c|h)$"))
+                     ;; Fix to not require bundled dependencies
+                     (substitute* "configure.in"
+                       (("GCLIBS='.*libgc.a'") "GCLIBS='-lgc'")
+                       ;; AC_SEARCH_LIBJIT checks hardcoded header locations
+                       (("search_libjit=true")
+                        (string-append "search_libjit=false\n"
+                                       "JIT_LIBS=-ljit")))
+                     (substitute* "Makefile.am"
+                       (("OPT_SUBDIRS \\+= lib.*") ""))
+                     (substitute* "support/hb_gc.c"
+                       (("#include .*/libgc/include/gc.h.")
+                        "#include <gc.h>")
+                       (("#include .*/libgc/include/gc_typed.h.")
+                        "#include <gc/gc_typed.h>"))
+                     (substitute* (list "codegen/Makefile.am"
+                                        "cscc/bf/Makefile.am"
+                                        "cscc/csharp/Makefile.am"
+                                        "cscc/c/Makefile.am"
+                                        "cscc/java/Makefile.am")
+                       ;; Generated files aren't prerequisites
+                       (("TREECC_OUTPUT =.*") ""))
+                     (substitute* "cscc/csharp/cs_grammar.y"
+                       (("YYLEX") "yylex()"))
+                     (substitute* "cscc/common/cc_main.h"
+                       (("CCPreProc CCPreProcessorStream;" all)
+                        (string-append "extern " all)))
+                     (substitute* "csdoc/scanner.c"
+                       (("int\ttoken;" all)
+                        (string-append "extern " all)))
+                     (substitute* "doc/cvmdoc.py"
+                       (("python1.5")
+                        "python3"))
+                     (substitute* "profiles/full"
+                       ;; If this is left unmodified, it causes a segfault in
+                       ;; pnetlib's tests.  Unrollers are somewhat
+                       ;; architecture-specific anyway, and it will fall back
+                       ;; to using GNU C's labels-as-values feature (it can be
+                       ;; made to further fall back to fully
+                       ;; standards-portable interpreter implementations).
+                       (("IL_CONFIG_UNROLL=y")
+                        "IL_CONFIG_UNROLL=n"))))
+                (patches
+                 (search-patches "pnet-newer-libgc-fix.patch"
+                                 "pnet-newer-texinfo-fix.patch"
+                                 "pnet-fix-line-number-info.patch"
+                                 "pnet-fix-off-by-one.patch"))))
+      (build-system gnu-build-system)
+      (native-inputs
+       (list autoconf
+             automake
+             bison
+             flex
+             libtool
+             libatomic-ops
+             (default-python) ;; for cvmdoc.py
+             texinfo
+             treecc))
+      (inputs
+       (cons* libgc
+              libffi
+              (if (libjit-supported?)
+                  (list libjit)
+                  '())))
+      (arguments
+       (append (if (libjit-supported?)
+                   (list #:configure-flags #~(list "--with-jit"))
+                   '())
+               (list #:make-flags #~(list "CFLAGS+=-Wno-pointer-to-int-cast"))))
+      (native-search-paths
+       (list (search-path-specification
+              (variable "CSCC_LIB_PATH")
+              (files (list "lib/cscc/lib")))))
+      (home-page "http://www.gnu.org/software/dotgnu/html2.0/pnet.html")
+      (synopsis "Compiler for the C# programming language")
+      (description
+       "The goal of this project is to build a suite of free software tools
+to build and execute .NET applications, including a C# compiler,
+assembler, disassembler, and runtime engine.")
+      (license license:gpl2+))))
diff --git a/gnu/packages/patches/pnet-fix-line-number-info.patch b/gnu/packages/patches/pnet-fix-line-number-info.patch
new file mode 100644
index 00000000000..9e5af849413
--- /dev/null
+++ b/gnu/packages/patches/pnet-fix-line-number-info.patch
@@ -0,0 +1,13 @@
+diff --git a/codegen/cg_coerce.c b/codegen/cg_coerce.c
+index 92d2f59a..c90ad5e2 100644
+--- a/codegen/cg_coerce.c
++++ b/codegen/cg_coerce.c
+@@ -1203,6 +1203,8 @@ int ILCoerce(ILGenInfo *info, ILNode *node, ILNode **parent,
+ 					!= ILMachineType_Void)
+ 	{
+ 		*parent = ILNode_CastSimple_create(node, constType);
++                yysetfilename(*parent, yygetfilename(node));
++		yysetlinenum(*parent, yygetlinenum(node));
+ 		return 1;
+ 	}
+ 	else if(indirect && GetIndirectConvertRules(info,fromType,toType,0, 
diff --git a/gnu/packages/patches/pnet-fix-off-by-one.patch b/gnu/packages/patches/pnet-fix-off-by-one.patch
new file mode 100644
index 00000000000..858d2266976
--- /dev/null
+++ b/gnu/packages/patches/pnet-fix-off-by-one.patch
@@ -0,0 +1,13 @@
+diff --git a/codegen/cg_genattr.c b/codegen/cg_genattr.c
+index 535852da..c3acc0dc 100644
+--- a/codegen/cg_genattr.c
++++ b/codegen/cg_genattr.c
+@@ -1532,7 +1532,7 @@ static int MarshalAsAttribute(ILGenInfo *info,
+ 			else
+ 			{
+ 				sizeParamIndex = attributeInfo->namedArgs[currentNamedArg].evalValue.un.i4Value;
+-				if(sizeParamIndex <= 0)
++				if(sizeParamIndex < 0)
+ 				{
+ 					CGErrorForNode(info, attributeInfo->namedArgs[currentNamedArg].node,
+ 						_("The size parameter index must be >= 0"));
diff --git a/gnu/packages/patches/pnet-newer-libgc-fix.patch b/gnu/packages/patches/pnet-newer-libgc-fix.patch
new file mode 100644
index 00000000000..1084b5a5bec
--- /dev/null
+++ b/gnu/packages/patches/pnet-newer-libgc-fix.patch
@@ -0,0 +1,45 @@
+diff --git a/support/hb_gc.c b/support/hb_gc.c
+index a5addb2d..41126963 100644
+--- a/support/hb_gc.c
++++ b/support/hb_gc.c
+@@ -104,12 +104,6 @@ static volatile int _FinalizersRunningSynchronously = 0;
+ 	#define GC_TRACE(a, b)
+ #endif
+ 
+-/*
+- * This is a internal global variable with the number of reclaimed bytes
+- * after a garbage collection.
+- */
+-extern GC_signed_word GC_bytes_found;
+-
+ /*
+  *	Main entry point for the finalizer thread.
+  */
+@@ -432,6 +426,7 @@ int ILGCFullCollection(int timeout)
+ {
+ 	int lastFinalizingCount;
+ 	int hasThreads;
++       struct GC_prof_stats_s stats;
+ 
+ 	hasThreads = _ILHasThreads();
+ 
+@@ -462,7 +457,8 @@ int ILGCFullCollection(int timeout)
+ 			GC_TRACE("Last finalizingCount = %i\n", lastFinalizingCount);
+ 
+ 			GC_gcollect();
+-			bytesCollected = GC_bytes_found;
++                       GC_get_prof_stats(&stats, sizeof(stats));
++			bytesCollected = stats.bytes_reclaimed_since_gc;
+ 
+ 			GC_TRACE("GC: bytes collected =  %i\n", bytesCollected);
+ 
+@@ -516,7 +512,8 @@ int ILGCFullCollection(int timeout)
+ 			GC_TRACE("Last finalizingCount = %i\n", lastFinalizingCount);
+ 
+ 			GC_gcollect();
+-			bytesCollected = GC_bytes_found;
++                       GC_get_prof_stats(&stats, sizeof(stats));
++			bytesCollected = stats.bytes_reclaimed_since_gc;
+ 
+ 			GC_TRACE("GC: bytes collected =  %i\n", bytesCollected);
+ 
diff --git a/gnu/packages/patches/pnet-newer-texinfo-fix.patch b/gnu/packages/patches/pnet-newer-texinfo-fix.patch
new file mode 100644
index 00000000000..b57052eeeaa
--- /dev/null
+++ b/gnu/packages/patches/pnet-newer-texinfo-fix.patch
@@ -0,0 +1,13 @@
+diff --git a/doc/pnettools.texi b/doc/pnettools.texi
+index 916d90bb..cdbe05cf 100644
+--- a/doc/pnettools.texi
++++ b/doc/pnettools.texi
+@@ -59,7 +59,7 @@ Copyright @copyright{} 2001, 2002, 2003 Southern Storm Software, Pty Ltd
+ @center @titlefont{Portable.NET Development Tools}
+ 
+ @vskip 0pt plus 1fill
+-@center{Copyright @copyright{} 2001, 2002, 2003 Southern Storm Software, Pty Ltd}
++@center Copyright @copyright{} 2001, 2002, 2003 Southern Storm Software, Pty Ltd
+ @end titlepage
+ 
+ @c -----------------------------------------------------------------------
-- 
2.45.2

From f13ff502f887d3167c2f482c2b851881c17547e4 Mon Sep 17 00:00:00 2001
From: unmush <[email-masked]>
Date: Tue, 26 Nov 2024 13:04:13
Subject: [PATCH v2 07/21] gnu: Add mono-2.6.4.

* gnu/dotnet.scm (mono-2.6.4): New variable.
* gnu/packages/patches/mono-2.6.4-fixes.patch: New patch.
* gnu/local.mk (dist_patch_DATA): Register it.

---
 gnu/local.mk                                |  1 +
 gnu/packages/dotnet.scm                     | 23 ++++++++++
 gnu/packages/patches/mono-2.6.4-fixes.patch | 49 +++++++++++++++++++++
 3 files changed, 73 insertions(+)
 create mode 100644 gnu/packages/patches/mono-2.6.4-fixes.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index fa99696e338..99e106df8fc 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1827,6 +1827,7 @@ dist_patch_DATA =						\
   %D%/packages/patches/mono-1.9.1-add-MONO_CREATE_IMAGE_VERSION.patch		\
   %D%/packages/patches/mono-1.9.1-fixes.patch			\
   %D%/packages/patches/mono-2.4.2.3-fixes.patch			\
+  %D%/packages/patches/mono-2.6.4-fixes.patch			\
   %D%/packages/patches/mosaicatcher-unbundle-htslib.patch	\
   %D%/packages/patches/mrrescue-support-love-11.patch		\
   %D%/packages/patches/mtools-mformat-uninitialized.patch	\
diff --git a/gnu/packages/dotnet.scm b/gnu/packages/dotnet.scm
index ac4dfb67c4c..82bee55aa90 100644
--- a/gnu/packages/dotnet.scm
+++ b/gnu/packages/dotnet.scm
@@ -522,3 +522,26 @@ (define-public mono-2.4.2
               license:lgpl2.0+ ;; note: ./mcs/LICENSE.LGPL specifies no version
               ;; mcs/jay
               license:bsd-4))))
+
+(define-public mono-2.6.4
+  (package
+    (inherit mono-2.4.2)
+    (version "2.6.4")
+    (name "mono")
+    (source (origin
+              (method git-fetch)
+              (uri
+               (git-reference
+                (url "https://gitlab.winehq.org/mono/mono.git")
+                (commit (string-append "mono-" "2.6.4"))))
+              (file-name (git-file-name name version))
+              (sha256
+               (base32
+                "17977w45qh8jmfsl4bhi83si4fxd8s3x8b0pxnwdzjv3bqr54c85"))
+              (modules '((guix build utils)
+                         (ice-9 string-fun)))
+              (snippet prepare-mono-source)
+              (patches
+               (search-patches "mono-2.6.4-fixes.patch"))))
+    (native-inputs (modify-inputs (package-native-inputs mono-2.4.2)
+                     (replace "mono" mono-2.4.2)))))
diff --git a/gnu/packages/patches/mono-2.6.4-fixes.patch b/gnu/packages/patches/mono-2.6.4-fixes.patch
new file mode 100644
index 00000000000..e802c8bb7e4
--- /dev/null
+++ b/gnu/packages/patches/mono-2.6.4-fixes.patch
@@ -0,0 +1,49 @@
+diff --git a/data/mono.pc.in b/data/mono.pc.in
+index 01e0a9e5d41..d43bb187218 100644
+--- a/data/mono.pc.in
++++ b/data/mono.pc.in
+@@ -7,8 +7,6 @@ sysconfdir=@sysconfdir@
+ Name: Mono
+ Description: Mono Runtime
+ Version: @VERSION@
+-## Commented out because SLE hides devel files in the SLE SDK,
+-## which not all customers will have.
+-#Requires: glib-2.0 gthread-2.0
++Requires: glib-2.0 gthread-2.0 bdw-gc
+ Libs: -L${libdir} @export_ldflags@ -lmono @libmono_ldflags@
+ Cflags: -I${includedir} @libmono_cflags@
+diff --git a/mono-uninstalled.pc.in b/mono-uninstalled.pc.in
+index 7fa3f12dc91..2a0734362fd 100644
+--- a/mono-uninstalled.pc.in
++++ b/mono-uninstalled.pc.in
+@@ -1,6 +1,6 @@
+ Name: Mono
+ Description: Mono Runtime
+ Version: @VERSION@
+-Requires: glib-2.0 gthread-2.0
++Requires: glib-2.0 gthread-2.0 bdw-gc
+ Libs: -L@mono_build_root@/mono/mini/.libs @export_ldflags@ -lmono @libmono_ldflags@
+ Cflags: -I@abs_top_srcdir@ -I@abs_top_srcdir@/mono @libmono_cflags@
+diff --git a/mono/mini/driver.c b/mono/mini/driver.c
+index c4e7f4ccdb3..bb705c0d1fc 100644
+--- a/mono/mini/driver.c
++++ b/mono/mini/driver.c
+@@ -1302,6 +1302,7 @@ mono_main (int argc, char* argv[])
+ #endif
+ 	if (!g_thread_supported ())
+ 		g_thread_init (NULL);
++        GC_allow_register_threads();
+ 
+ 	if (mono_running_on_valgrind () && getenv ("MONO_VALGRIND_LEAK_CHECK")) {
+ 		GMemVTable mem_vtable;
+diff --git a/runtime/Makefile.am b/runtime/Makefile.am
+index da0c0e8671d..9d0deaf182f 100644
+--- a/runtime/Makefile.am
++++ b/runtime/Makefile.am
+@@ -1,6 +1,3 @@
+-# hack to prevent 'check' from depending on 'all'
+-AUTOMAKE_OPTIONS = cygnus
+-
+ tmpinst = _tmpinst
+ 
+ noinst_SCRIPTS = mono-wrapper monodis-wrapper
-- 
2.45.2

From fa1feb5147b85c17be0f6b3652eec3f4667425e4 Mon Sep 17 00:00:00 2001
From: unmush <[email-masked]>
Date: Tue, 26 Nov 2024 12:55:57
Subject: [PATCH v2 04/21] gnu: Add mono-1.2.6.

* gnu/packages/dotnet.scm (mono-1.2.6): New variable.
* gnu/packages/patches/mono-1.2.6-bootstrap.patch: New patch.
* gnu/local.mk (dist_patch_DATA): register it.

---
 gnu/local.mk                                  |   1 +
 gnu/packages/dotnet.scm                       | 145 +++++
 .../patches/mono-1.2.6-bootstrap.patch        | 585 ++++++++++++++++++
 3 files changed, 731 insertions(+)
 create mode 100644 gnu/packages/patches/mono-1.2.6-bootstrap.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index 0e2d7bfa137..54f01ba05a9 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1823,6 +1823,7 @@ dist_patch_DATA =						\
   %D%/packages/patches/mpg321-gcc-10.patch			\
   %D%/packages/patches/module-init-tools-moduledir.patch	\
   %D%/packages/patches/monero-use-system-miniupnpc.patch			\
+  %D%/packages/patches/mono-1.2.6-bootstrap.patch		\
   %D%/packages/patches/mosaicatcher-unbundle-htslib.patch	\
   %D%/packages/patches/mrrescue-support-love-11.patch		\
   %D%/packages/patches/mtools-mformat-uninitialized.patch	\
diff --git a/gnu/packages/dotnet.scm b/gnu/packages/dotnet.scm
index 9d9cc5421b0..093865080bb 100644
--- a/gnu/packages/dotnet.scm
+++ b/gnu/packages/dotnet.scm
@@ -265,3 +265,148 @@ (define-public pnetlib-git
        "DotGNU Portable.NET Library contains an implementation of the C# library,
 for use with .NET-capable runtime engines and applications.")
       (license license:gpl2+))))
+
+(define prepare-mono-source-0
+  #~((false-if-exception
+      (delete-file "./configure"))
+     (false-if-exception
+      (delete-file-recursively "./libgc"))
+     ;; just to be sure
+     (for-each delete-file
+               (find-files "."
+                           "\\.(dll|exe|DLL|EXE|so)$"))
+     ;; We deleted docs/AgilityPack.dll earlier (if it existed), and it's
+     ;; required for building the documentation, so skip building the
+     ;; documentation.  According to docs/README, "the sources to this DLL
+     ;; live in GNOME CVS module beagle/Filters/AgilityPack".
+     (substitute* "./Makefile.am"
+       (("^(|DIST_|MOONLIGHT_|MONOTOUCH_)SUBDIRS =.*" all)
+        (string-replace-substring
+         (string-replace-substring
+          (string-replace-substring all " docs" "")
+          " $(libgc_dir)" "")
+         " libgc" "")))))
+
+;; A lot of the fixes are shared between many versions, and it doesn't hurt to
+;; apply them to versions before or after they are necessary, so just include
+;; them all.
+(define prepare-mono-source
+  #~(begin
+      #$@prepare-mono-source-0
+      (substitute* (filter file-exists?
+                           '("./configure.in"
+                             "./configure.ac"))
+        (("int f = isinf \\(1\\);")
+         "int f = isinf (1.0);"))
+      ;; makedev is in <sys/sysmacros.h> now.  Include
+      ;; it.
+      (substitute* "mono/io-layer/processes.c"
+        (("#ifdef HAVE_SYS_MKDEV_H") "#if 1")
+        (("sys/mkdev.h") "sys/sysmacros.h"))
+      (substitute* (filter file-exists? '("./mono/metadata/boehm-gc.c"))
+        (("GC_set_finalizer_notify_proc")
+         "GC_set_await_finalize_proc")
+        (("GC_toggleref_register_callback")
+         "GC_set_toggleref_func"))
+      (substitute* (filter file-exists? '("./mono/utils/mono-compiler.h"))
+        (("static __thread gpointer x MONO_TLS_FAST")
+         (string-append
+          "static __thread gpointer x"
+          " __attribute__((used))")))
+      ;; Since the time the old mono versions were written at, gcc has started
+      ;; removing more things it thinks are unused (for example because they
+      ;; are only referenced in inline assembly of some sort).
+      (substitute* (filter file-exists? '("./mono/metadata/sgen-alloc.c"))
+        (("static __thread char \\*\\*tlab_next_addr")
+         (string-append
+          "static __thread char **tlab_next_addr"
+          " __attribute__((used))")))
+      (substitute* (filter file-exists? '("mono/utils/mono-compiler.h"))
+        (("#define MONO_TLS_FAST ")
+         "#define MONO_TLS_FAST __attribute__((used)) "))))
+
+(define-public mono-1.2.6
+  (package
+    (version "1.2.6")
+    (name "mono")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append
+                    "http://download.mono-project.com/sources/mono/"
+                    "mono" "-" version ".tar.bz2"))
+              (sha256
+               (base32 "03sn7wyvrjkkkbrqajpmqifxfn83p30qprizpb3m6c5cdhwlzk14"))
+              (modules '((guix build utils)
+                         (ice-9 string-fun)))
+              (snippet #~(begin
+                           #$prepare-mono-source
+                           (delete-file
+                            "./mcs/class/System/System.Text.RegularExpressions/BaseMachine.cs")
+                           ;; Can't patch a file with different line endings,
+                           ;; so the patch creates a new one, and we overwrite
+                           ;; the old one here.
+                           (rename-file
+                            "./mcs/class/System/System.Text.RegularExpressions/BaseMachine.cs-2"
+                            "./mcs/class/System/System.Text.RegularExpressions/BaseMachine.cs")))
+              (patches
+               (search-patches "mono-1.2.6-bootstrap.patch"))))
+    (build-system gnu-build-system)
+    (native-inputs
+     (list autoconf
+           automake
+           bison
+           libtool
+           pnet-git
+           pnetlib-git
+           pkg-config))
+    (inputs
+     (list glib
+           libgc
+           libx11
+           zlib))
+    (arguments
+     (list
+      #:configure-flags #~(list "--with-gc=boehm")
+      #:make-flags #~(list (string-append "EXTERNAL_MCS="
+                                          #+(this-package-native-input "pnet-git")
+                                          "/bin/cscc")
+                           (string-append "EXTERNAL_RUNTIME="
+                                          #+(this-package-native-input "pnet-git")
+                                          "/bin/ilrun")
+                           "CFLAGS+=-DARG_MAX=500"
+                           "CC=gcc"
+                           "V=1")
+      ;; build fails nondeterministically without this
+      #:parallel-build? #f
+      #:phases
+      #~(modify-phases %standard-phases
+          (add-after 'unpack 'set-env
+            (lambda _ ;;* (#:key inputs #:allow-other-keys)
+              ;; all tests under mcs/class fail trying to access $HOME
+              (setenv "HOME" "/tmp")
+              ;; ZIP files have "DOS time" which starts in Jan 1980.
+              (setenv "SOURCE_DATE_EPOCH" "315532800"))))
+      ;; System.Object isn't marked as serializable because it causes issues
+      ;; with compiling with pnet (circular class reference between Object and
+      ;; SerializableAttribute), and this causes tests to fail
+      #:tests? #f))
+    (native-search-paths
+     (list (search-path-specification
+            (variable "MONO_PATH")
+            (files (list "lib/mono")))))
+    (synopsis "Compiler and libraries for the C# programming language")
+    (description "Mono is a compiler, vm, debugger and set of libraries for
+C#, a C-style programming language from Microsoft that is very similar to
+Java.")
+    (home-page "https://www.mono-project.com/")
+    ;; See ./LICENSE
+    (license (list
+              ;; most of mcs/tools, mono/man, most of mcs/class, tests by
+              ;; default, mono/eglib
+              license:x11
+              ;; mcs/mcs, mcs/gmcs, some of mcs/tools
+              license:gpl1+ ;; note: ./mcs/LICENSE.GPL specifies no version
+              ;; mono/mono (the mono VM, I think they meant mono/mini)
+              license:lgpl2.0+ ;; note: ./mcs/LICENSE.LGPL specifies no version
+              ;; mcs/jay
+              license:bsd-4))))
diff --git a/gnu/packages/patches/mono-1.2.6-bootstrap.patch b/gnu/packages/patches/mono-1.2.6-bootstrap.patch
new file mode 100644
index 00000000000..0f6efd4a034
--- /dev/null
+++ b/gnu/packages/patches/mono-1.2.6-bootstrap.patch
@@ -0,0 +1,585 @@
+diff --git a/mcs/class/System/System.Diagnostics/ICollectData.cs b/mcs/class/System/System.Diagnostics/ICollectData.cs
+index c52f9871589..c66c1936d3d 100644
+--- a/mcs/class/System/System.Diagnostics/ICollectData.cs
++++ b/mcs/class/System/System.Diagnostics/ICollectData.cs
+@@ -41,7 +41,7 @@ namespace System.Diagnostics
+ #endif
+ 	public interface ICollectData {
+ 		void CloseData ();
+-		[return: MarshalAs(UnmanagedType.I4)]
++		//[return: MarshalAs(UnmanagedType.I4)]
+ 		void CollectData (
+ 			[In] [MarshalAs(UnmanagedType.I4)] int id, 
+ 			[In] [MarshalAs(UnmanagedType.SysInt)] IntPtr valueName, 
+diff --git a/mcs/class/System/System.Diagnostics/LocalFileEventLog.cs b/mcs/class/System/System.Diagnostics/LocalFileEventLog.cs
+index 280e6a97227..c41816dca24 100644
+--- a/mcs/class/System/System.Diagnostics/LocalFileEventLog.cs
++++ b/mcs/class/System/System.Diagnostics/LocalFileEventLog.cs
+@@ -140,6 +140,30 @@ namespace System.Diagnostics
+ 			file_watcher.EnableRaisingEvents = false;
+ 		}
+ 
++        void FileCreationWatcher(object o, FileSystemEventArgs e)
++        {
++            lock (this) {
++                if (_notifying)
++                    return;
++                _notifying = true;
++            }
++
++            // Process every new entry in one notification event.
++            try {
++                while (GetLatestIndex () > last_notification_index) {
++                    try {
++                        CoreEventLog.OnEntryWritten (GetEntry (last_notification_index++));
++                    } catch (Exception ex) {
++                        // FIXME: find some proper way to output this error
++                        Debug.WriteLine (ex);
++                    }
++                }
++                } finally {
++                lock (this)
++                    _notifying = false;
++            }
++        }
++
+ 		public override void EnableNotification ()
+ 		{
+ 			if (file_watcher == null) {
+@@ -149,28 +173,7 @@ namespace System.Diagnostics
+ 
+ 				file_watcher = new FileSystemWatcher ();
+ 				file_watcher.Path = logDir;
+-				file_watcher.Created += delegate (object o, FileSystemEventArgs e) {
+-					lock (this) {
+-						if (_notifying)
+-							return;
+-						_notifying = true;
+-					}
+-
+-					// Process every new entry in one notification event.
+-					try {
+-						while (GetLatestIndex () > last_notification_index) {
+-							try {
+-								CoreEventLog.OnEntryWritten (GetEntry (last_notification_index++));
+-							} catch (Exception ex) {
+-								// FIXME: find some proper way to output this error
+-								Debug.WriteLine (ex);
+-							}
+-						}
+-					} finally {
+-						lock (this)
+-							_notifying = false;
+-					}
+-				};
++				file_watcher.Created += new FileSystemEventHandler(FileCreationWatcher);
+ 			}
+ 			last_notification_index = GetLatestIndex ();
+ 			file_watcher.EnableRaisingEvents = true;
+diff --git a/mcs/class/System/System.IO/InotifyWatcher.cs b/mcs/class/System/System.IO/InotifyWatcher.cs
+index d8e7acce3a7..7b0907eebc1 100644
+--- a/mcs/class/System/System.IO/InotifyWatcher.cs
++++ b/mcs/class/System/System.IO/InotifyWatcher.cs
+@@ -423,19 +423,36 @@ namespace System.IO {
+ 			return 16 + len;
+ 		}
+ 
++        class ThingEnumerator : IEnumerator, IEnumerable
++        {
++            object thing;
++            int j;
++            public ThingEnumerator(object thing)
++            { this.thing = thing; j = -1; }
++
++            public IEnumerator GetEnumerator() { return this; }
++            public bool MoveNext()
++            {
++                if(thing == null) { return false; }
++                if(thing is ArrayList)
++                {
++                    ArrayList list = (ArrayList) thing;
++                    if(j+1 >= list.Count) { return false; }
++                    j++;
++                    return true;
++                }
++                if(j == -1) { j = 0; return true; }
++                return false;
++            }
++            public void Reset() { j = -1; }
++            public object Current
++            { get { if(thing is ArrayList) return ((ArrayList)thing)[j];
++                    return thing; }}
++        }
++
+ 		static IEnumerable GetEnumerator (object source)
+ 		{
+-			if (source == null)
+-				yield break;
+-
+-			if (source is InotifyData)
+-				yield return source;
+-
+-			if (source is ArrayList) {
+-				ArrayList list = (ArrayList) source;
+-				for (int i = 0; i < list.Count; i++)
+-					yield return list [i];
+-			}
++			return new ThingEnumerator(source);
+ 		}
+ 
+ 		/* Interesting events:
+diff --git a/mcs/class/System/System.Net/ServicePoint.cs b/mcs/class/System/System.Net/ServicePoint.cs
+index a884d90f507..e1c73b098c2 100644
+--- a/mcs/class/System/System.Net/ServicePoint.cs
++++ b/mcs/class/System/System.Net/ServicePoint.cs
+@@ -137,7 +137,7 @@ namespace System.Net
+ 			get {
+ 				return idleSince;
+ 			}
+-			internal set {
++			set {
+ 				lock (locker)
+ 					idleSince = value;
+ 			}
+diff --git a/mcs/class/System/System.Text.RegularExpressions/BaseMachine.cs-2 b/mcs/class/System/System.Text.RegularExpressions/BaseMachine.cs-2
+new file mode 100644
+index 00000000000..a685e2679b7
+--- /dev/null
++++ b/mcs/class/System/System.Text.RegularExpressions/BaseMachine.cs-2
+@@ -0,0 +1,168 @@
++//
++// BaseMachine.jvm.cs
++//
++// Author:
++// author:	Dan Lewis ([email-masked])
++//		(c) 2002
++// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
++//
++
++//
++// Permission is hereby granted, free of charge, to any person obtaining
++// a copy of this software and associated documentation files (the
++// "Software"), to deal in the Software without restriction, including
++// without limitation the rights to use, copy, modify, merge, publish,
++// distribute, sublicense, and/or sell copies of the Software, and to
++// permit persons to whom the Software is furnished to do so, subject to
++// the following conditions:
++//
++// The above copyright notice and this permission notice shall be
++// included in all copies or substantial portions of the Software.
++//
++// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
++// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
++// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
++// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
++//
++
++using System;
++using System.Collections;
++using System.Collections.Specialized;
++
++namespace System.Text.RegularExpressions
++{
++	abstract class BaseMachine : IMachine
++	{
++		internal delegate void MatchAppendEvaluator (Match match, StringBuilder sb);
++
++		public virtual string Replace (Regex regex, string input, string replacement, int count, int startat)
++		{
++			ReplacementEvaluator ev = new ReplacementEvaluator (regex, replacement);
++			if (regex.RightToLeft)
++				return RTLReplace (regex, input, new MatchEvaluator (ev.Evaluate), count, startat);
++			else
++				return LTRReplace (regex, input, new MatchAppendEvaluator (ev.EvaluateAppend), count, startat);
++		}
++
++		virtual public string [] Split (Regex regex, string input, int count, int startat)
++		{
++			ArrayList splits = new ArrayList ();
++			if (count == 0)
++				count = Int32.MaxValue;
++
++			int ptr = startat;
++			Match m = null;
++			while (--count > 0) {
++				if (m != null)
++					m = m.NextMatch ();
++				else
++					m = regex.Match (input, ptr);
++
++				if (!m.Success)
++					break;
++
++				if (regex.RightToLeft)
++					splits.Add (input.Substring (m.Index + m.Length, ptr - m.Index - m.Length));
++				else
++					splits.Add (input.Substring (ptr, m.Index - ptr));
++
++				int gcount = m.Groups.Count;
++				for (int gindex = 1; gindex < gcount; gindex++) {
++					Group grp = m.Groups [gindex];
++					splits.Add (input.Substring (grp.Index, grp.Length));
++				}
++
++				if (regex.RightToLeft)
++					ptr = m.Index;
++				else
++					ptr = m.Index + m.Length;
++
++			}
++
++			if (regex.RightToLeft && ptr >= 0)
++				splits.Add (input.Substring (0, ptr));
++			if (!regex.RightToLeft && ptr <= input.Length)
++				splits.Add (input.Substring (ptr));
++
++			return (string []) splits.ToArray (typeof (string));
++		}
++
++		virtual public Match Scan (Regex regex, string text, int start, int end)
++		{
++			throw new NotImplementedException ("Scan method must be implemented in derived classes");
++		}
++
++		virtual public string Result (string replacement, Match match)
++		{
++			return ReplacementEvaluator.Evaluate (replacement, match);
++		}
++
++		internal static string LTRReplace (Regex regex, string input, MatchAppendEvaluator evaluator, int count, int startat)
++		{
++			Match m = regex.Match (input, startat);
++			if (!m.Success)
++				return input;
++
++			StringBuilder result = new StringBuilder ();
++			int ptr = startat;
++			int counter = count;
++
++			result.Append (input, 0, ptr);
++
++			do {
++				if (count != -1)
++					if (counter-- <= 0)
++						break;
++				if (m.Index < ptr)
++					throw new SystemException ("how");
++				result.Append (input, ptr, m.Index - ptr);
++				evaluator (m, result);
++
++				ptr = m.Index + m.Length;
++				m = m.NextMatch ();
++			} while (m.Success);
++
++			result.Append (input, ptr, input.Length - ptr);
++
++			return result.ToString ();
++		}
++
++		internal static string RTLReplace (Regex regex, string input, MatchEvaluator evaluator, int count, int startat)
++		{
++			Match m = regex.Match (input, startat);
++			if (!m.Success)
++				return input;
++
++			int ptr = startat;
++			int counter = count;
++			StringCollection pieces = new StringCollection ();
++			pieces.Add (input.Substring (ptr));
++
++			do {
++				if (count != -1)
++					if (counter-- <= 0)
++						break;
++				if (m.Index + m.Length > ptr)
++					throw new SystemException ("how");
++				pieces.Add (input.Substring (m.Index + m.Length, ptr - m.Index - m.Length));
++				pieces.Add (evaluator (m));
++
++				ptr = m.Index;
++				m = m.NextMatch ();
++			} while (m.Success);
++
++			StringBuilder result = new StringBuilder ();
++
++			result.Append (input, 0, ptr);
++			for (int i = pieces.Count; i > 0; )
++				result.Append (pieces [--i]);
++
++			pieces.Clear ();
++
++			return result.ToString ();
++		}
++	}
++}
+diff --git a/mcs/class/corlib/System.Runtime.Remoting.Messaging/MethodCall.cs b/mcs/class/corlib/System.Runtime.Remoting.Messaging/MethodCall.cs
+index 94069d1727e..042574178fa 100644
+--- a/mcs/class/corlib/System.Runtime.Remoting.Messaging/MethodCall.cs
++++ b/mcs/class/corlib/System.Runtime.Remoting.Messaging/MethodCall.cs
+@@ -272,6 +272,10 @@ namespace System.Runtime.Remoting.Messaging {
+ 			set { _uri = value; }
+ 		}
+ 
++        string IMethodMessage.Uri {
++			get { return Uri; }
++		}
++
+ 		string IInternalMessage.Uri {
+ 			get { return Uri; }
+ 			set { Uri = value; }
+diff --git a/mcs/class/corlib/System.Runtime.Remoting.Messaging/MethodResponse.cs b/mcs/class/corlib/System.Runtime.Remoting.Messaging/MethodResponse.cs
+index 1b1eab014b3..575e7e37dee 100644
+--- a/mcs/class/corlib/System.Runtime.Remoting.Messaging/MethodResponse.cs
++++ b/mcs/class/corlib/System.Runtime.Remoting.Messaging/MethodResponse.cs
+@@ -272,6 +272,10 @@ namespace System.Runtime.Remoting.Messaging {
+ 			}
+ 		}
+ 
++        string IMethodMessage.Uri {
++			get { return Uri; }
++		}
++
+ 		string IInternalMessage.Uri {
+ 			get { return Uri; }
+ 			set { Uri = value; }
+diff --git a/mcs/class/corlib/System.Runtime.Remoting.Messaging/ReturnMessage.cs b/mcs/class/corlib/System.Runtime.Remoting.Messaging/ReturnMessage.cs
+index aee39f5bb81..ec09b73c15d 100644
+--- a/mcs/class/corlib/System.Runtime.Remoting.Messaging/ReturnMessage.cs
++++ b/mcs/class/corlib/System.Runtime.Remoting.Messaging/ReturnMessage.cs
+@@ -166,6 +166,10 @@ namespace System.Runtime.Remoting.Messaging
+ 			}
+ 		}
+ 
++        string IMethodMessage.Uri {
++			get { return Uri; }
++		}
++
+ 		string IInternalMessage.Uri {
+ 			get { return Uri; }
+ 			set { Uri = value; }
+diff --git a/mcs/class/corlib/System/MulticastDelegate.cs b/mcs/class/corlib/System/MulticastDelegate.cs
+index b36aff33492..cf9134a33b3 100644
+--- a/mcs/class/corlib/System/MulticastDelegate.cs
++++ b/mcs/class/corlib/System/MulticastDelegate.cs
+@@ -262,16 +262,16 @@ namespace System
+ 
+ 		public static bool operator == (MulticastDelegate a, MulticastDelegate b)
+ 		{
+-			if (a == null)
+-		    		return b == null;
++			if ((object)a == null)
++                return (object)b == null;
+ 		    		
+ 			return a.Equals (b);
+ 		}
+ 		
+ 		public static bool operator != (MulticastDelegate a, MulticastDelegate b)
+ 		{
+-			if (a == null)
+-				return b != null;
++			if ((object)a == null)
++				return (object)b != null;
+ 		    	
+ 			return !a.Equals (b);
+ 		}
+diff --git a/mcs/class/corlib/System/Object.cs b/mcs/class/corlib/System/Object.cs
+index 6b0a03d2a31..694cbd454e1 100644
+--- a/mcs/class/corlib/System/Object.cs
++++ b/mcs/class/corlib/System/Object.cs
+@@ -40,7 +40,7 @@ using System.Runtime.ConstrainedExecution;
+ 
+ namespace System {
+ 
+-	[Serializable]
++	//[Serializable]
+ 	[ClassInterface (ClassInterfaceType.AutoDual)]
+ #if NET_2_0
+ 	[ComVisible (true)]
+@@ -47,6 +47,12 @@
+ #endif
+ 	public class Object {
+ 
++        // Default definition of the object finalizer.
++        #if NET_2_0
++		[ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
++        #endif
++        protected virtual void Finalize() {}
++
+ 		// <summary>
+ 		//   Compares this object to the specified object.
+ 		//   Returns true if they are equal, false otherwise.
+@@ -80,16 +86,6 @@ namespace System {
+ 		{
+ 		}
+ 
+-		// <summary>
+-		//   Object destructor. 
+-		// </summary>
+-#if NET_2_0
+-		[ReliabilityContractAttribute (Consistency.WillNotCorruptState, Cer.Success)]
+-#endif
+-		~Object ()
+-		{
+-		}
+-
+ 		// <summary>
+ 		//   Returns a hashcode for this object.  Each derived
+ 		//   class should return a hash code that makes sense
+diff --git a/mcs/mcs/codegen.cs b/mcs/mcs/codegen.cs
+index c94a61772f4..8546d671ec6 100644
+--- a/mcs/mcs/codegen.cs
++++ b/mcs/mcs/codegen.cs
+@@ -498,7 +498,7 @@ namespace Mono.CSharp {
+ 
+ 		// utility helper for CheckExpr, UnCheckExpr, Checked and Unchecked statements
+ 		// it's public so that we can use a struct at the callsite
+-		public struct FlagsHandle : IDisposable
++		public class FlagsHandle : IDisposable
+ 		{
+ 			EmitContext ec;
+ 			readonly Flags invmask, oldval;
+diff --git a/mcs/mcs/typemanager.cs b/mcs/mcs/typemanager.cs
+index 1e173de89d2..58477af41a3 100644
+--- a/mcs/mcs/typemanager.cs
++++ b/mcs/mcs/typemanager.cs
+@@ -629,18 +629,42 @@ namespace Mono.CSharp {
+ 		return CSharpName (GetFullName (t));
+     }
+ 
++    static bool StartsWithWord(string haystack, string check)
++    {
++        if(String.Compare(haystack, 0, check, 0, check.Length, false) != 0)
++        { return false; }
++        if(check.Length == haystack.Length) { return true; }
++        char c = haystack[check.Length];
++        return !(Char.IsLetter(c) || Char.IsDigit(c));
++    }
++        
+ 	public static string CSharpName (string name)
+ 	{
+ 		if (name.StartsWith (AnonymousTypeClass.ClassNamePrefix))
+ 				return AnonymousTypeClass.SignatureForError;
+-			
+-		return Regex.Replace (name,
+-			@"^System\." +
+-			@"(Int32|UInt32|Int16|UInt16|Int64|UInt64|" +
+-			@"Single|Double|Char|Decimal|Byte|SByte|Object|" +
+-			@"Boolean|String|Void|Null)" +
+-			@"(\W+|\b)",
+-			new MatchEvaluator (CSharpNameMatch)).Replace ('+', '.');
++
++        int l = "System.".Length;
++        if(name.StartsWith("System.") && name.Length > l)
++        {
++            string s2 = name.Substring(l).ToLower();
++            if(StartsWithWord(s2, "int32"))
++                return "int";
++            if(StartsWithWord(s2, "uint32"))
++                return "uint";
++            if(StartsWithWord(s2, "int16"))
++                return "short";
++            if(StartsWithWord(s2, "uint16"))
++                return "ushort";
++            if(StartsWithWord(s2, "int64"))
++                return "long";
++            if(StartsWithWord(s2, "uint64"))
++                return "ulong";
++            if(StartsWithWord(s2, "single"))
++                return "float";
++            if(StartsWithWord(s2, "boolean"))
++                return "bool";
++        }
++        return name;
+ 	}
+ 
+ 	static public string CSharpName (Type[] types)
+@@ -654,21 +678,6 @@ namespace Mono.CSharp {
+ 		return sb.ToString ();
+ 	}
+ 	
+-	static String CSharpNameMatch (Match match) 
+-	{
+-		string s = match.Groups [1].Captures [0].Value;
+-		return s.ToLower ().
+-		Replace ("int32", "int").
+-		Replace ("uint32", "uint").
+-		Replace ("int16", "short").
+-		Replace ("uint16", "ushort").
+-		Replace ("int64", "long").
+-		Replace ("uint64", "ulong").
+-		Replace ("single", "float").
+-		Replace ("boolean", "bool")
+-		+ match.Groups [2].Captures [0].Value;
+-	}
+-
+ 	// Used for error reporting to show symbolic name instead of underlying value
+ 	public static string CSharpEnumValue (Type t, object value)
+ 	{
+diff --git a/mono/io-layer/processes.c b/mono/io-layer/processes.c
+index cd6176cdda2..486087d3a1b 100644
+--- a/mono/io-layer/processes.c
++++ b/mono/io-layer/processes.c
+@@ -15,6 +15,7 @@
+ #include <sys/time.h>
+ #include <errno.h>
+ #include <sys/types.h>
++#include <sys/sysmacros.h>
+ #include <unistd.h>
+ #include <signal.h>
+ #include <sys/wait.h>
+diff --git a/mono/metadata/Makefile.am b/mono/metadata/Makefile.am
+index 6ff2368895b..b8ba66e8756 100644
+--- a/mono/metadata/Makefile.am
++++ b/mono/metadata/Makefile.am
+@@ -154,7 +154,6 @@ libmonoruntimeinclude_HEADERS = \
+ 	object.h	\
+ 	exception.h	\
+ 	profiler.h	\
+-	appdomain.h	\
+ 	mono-config.h	\
+ 	debug-helpers.h	\
+ 	mempool.h
+diff --git a/mono/metadata/class.c b/mono/metadata/class.c
+index f13f37632fe..128710337f4 100644
+--- a/mono/metadata/class.c
++++ b/mono/metadata/class.c
+@@ -2695,10 +2695,10 @@ initialize_object_slots (MonoClass *class)
+ 				finalize_slot = i;
+ 		}
+ 
+-		g_assert (ghc_slot > 0);
++		g_assert (ghc_slot >= 0);
+ 		default_ghc = class->vtable [ghc_slot];
+ 
+-		g_assert (finalize_slot > 0);
++		g_assert (finalize_slot >= 0);
+ 		default_finalize = class->vtable [finalize_slot];
+ 	}
+ }
+diff --git a/mono/metadata/object.c b/mono/metadata/object.c
+index 2b6f4909b34..ef4c8fd8b44 100644
+--- a/mono/metadata/object.c
++++ b/mono/metadata/object.c
+@@ -861,7 +861,7 @@ mono_class_compute_gc_descriptor (MonoClass *class)
+ 		mono_register_jit_icall (GC_local_gcj_fast_malloc, "GC_local_gcj_fast_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
+ #endif
+ 		mono_register_jit_icall (GC_gcj_malloc, "GC_gcj_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
+-		mono_register_jit_icall (GC_gcj_fast_malloc, "GC_gcj_fast_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
++		mono_register_jit_icall (GC_gcj_malloc, "GC_gcj_fast_malloc", mono_create_icall_signature ("object int ptr"), FALSE);
+ #endif
+ 		gcj_inited = TRUE;
+ 		mono_loader_unlock ();
+diff --git a/runtime/Makefile.am b/runtime/Makefile.am
+index 779787b3ce3..b67957dcf16 100644
+--- a/runtime/Makefile.am
++++ b/runtime/Makefile.am
+@@ -1,6 +1,3 @@
+-# hack to prevent 'check' from depending on 'all'
+-AUTOMAKE_OPTIONS = cygnus
+-
+ tmpinst = _tmpinst
+ 
+ noinst_SCRIPTS = mono-wrapper monodis-wrapper semdel-wrapper
-- 
2.45.2

From 484801000bbeb798116d87923dba543a24bf4b06 Mon Sep 17 00:00:00 2001
From: unmush <[email-masked]>
Date: Tue, 26 Nov 2024 13:02:31
Subject: [PATCH v2 06/21] gnu: Add mono-2.4.2.

* gnu/packages/dotnet.scm (mono-2.4.2): New variable.
* gnu/packages/patches/mono-2.4.2.3-fixes.patch: New patch.
* gnu/local.mk (dist_patch_DATA): Register it.

---
 gnu/local.mk                                  |  1 +
 gnu/packages/dotnet.scm                       | 52 ++++++++++++++++
 gnu/packages/patches/mono-2.4.2.3-fixes.patch | 59 +++++++++++++++++++
 3 files changed, 112 insertions(+)
 create mode 100644 gnu/packages/patches/mono-2.4.2.3-fixes.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index b7fa68bd677..fa99696e338 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1826,6 +1826,7 @@ dist_patch_DATA =						\
   %D%/packages/patches/mono-1.2.6-bootstrap.patch		\
   %D%/packages/patches/mono-1.9.1-add-MONO_CREATE_IMAGE_VERSION.patch		\
   %D%/packages/patches/mono-1.9.1-fixes.patch			\
+  %D%/packages/patches/mono-2.4.2.3-fixes.patch			\
   %D%/packages/patches/mosaicatcher-unbundle-htslib.patch	\
   %D%/packages/patches/mrrescue-support-love-11.patch		\
   %D%/packages/patches/mtools-mformat-uninitialized.patch	\
diff --git a/gnu/packages/dotnet.scm b/gnu/packages/dotnet.scm
index 99511a07a99..ac4dfb67c4c 100644
--- a/gnu/packages/dotnet.scm
+++ b/gnu/packages/dotnet.scm
@@ -470,3 +470,55 @@ (define-public mono-1.9.1
                 (patch-shebang "mono/tests/test-driver")))))
        ((#:tests? _ #f) #f)
        ((#:parallel-tests? _ #f) #f)))))
+
+(define-public mono-2.4.2
+  (package
+    (inherit mono-1.9.1)
+    (version "2.4.2.3")
+    (name "mono")
+    (source (origin
+              (method git-fetch)
+              (uri
+               (git-reference
+                (url "https://gitlab.winehq.org/mono/mono.git")
+                (commit (string-append "mono-" "2-4-2-3"))))
+              (file-name (git-file-name name version))
+              (sha256
+               (base32
+                "0mnrk17rd9c5rh30dh82a39c9ak1ns998b41ivprvy7m068skpda"))
+              (modules '((guix build utils)
+                         (ice-9 string-fun)))
+              (snippet prepare-mono-source)
+              (patches
+               (search-patches "mono-2.4.2.3-fixes.patch"))))
+    (native-inputs (modify-inputs (package-native-inputs mono-1.9.1)
+                     (replace "mono" mono-1.9.1)))
+    (inputs (modify-inputs (package-inputs mono-1.9.1)
+              (append gettext-minimal)))
+    (arguments
+     (substitute-keyword-arguments (package-arguments mono-1.9.1)
+       ((#:tests? _ #f)
+        ;; When it tries building iltests.il in mono/mini, it gets: error
+        ;; CS0006: cannot find metadata file `TestDriver.dll'.  It builds fine
+        ;; outside of the build environment, but later tests fail, and I can't
+        ;; be bothered to figure out what's causing ilasm to not find
+        ;; TestDriver.dll.
+        #f)
+       ((#:phases phases #~%standard-phases)
+        #~(modify-phases #$phases
+            (add-before 'bootstrap 'patch-sub-autogen.sh-shebang
+              (lambda _
+                (patch-shebang "./eglib/autogen.sh")))))))
+    (license (list
+              ;; most of mcs/tools, mono/man, most of mcs/class, tests by
+              ;; default, mono/eglib
+              ;; mcs/mcs, mcs/gmcs (dual-licensed GPL)
+              ;; samples
+              license:x11
+              ;; mcs/mcs, mcs/gmcs (dual-licensed X11)
+              ;; some of mcs/tools
+              license:gpl1+ ;; note: ./mcs/LICENSE.GPL specifies no version
+              ;; mono/mono (the mono VM, I think they meant mono/mini)
+              license:lgpl2.0+ ;; note: ./mcs/LICENSE.LGPL specifies no version
+              ;; mcs/jay
+              license:bsd-4))))
diff --git a/gnu/packages/patches/mono-2.4.2.3-fixes.patch b/gnu/packages/patches/mono-2.4.2.3-fixes.patch
new file mode 100644
index 00000000000..13cff774506
--- /dev/null
+++ b/gnu/packages/patches/mono-2.4.2.3-fixes.patch
@@ -0,0 +1,59 @@
+diff --git a/data/mono.pc.in b/data/mono.pc.in
+index 6da0960db2d..d43bb187218 100644
+--- a/data/mono.pc.in
++++ b/data/mono.pc.in
+@@ -7,6 +7,6 @@ sysconfdir=@sysconfdir@
+ Name: Mono
+ Description: Mono Runtime
+ Version: @VERSION@
+-Requires: glib-2.0 gthread-2.0
++Requires: glib-2.0 gthread-2.0 bdw-gc
+ Libs: -L${libdir} @export_ldflags@ -lmono @libmono_ldflags@
+ Cflags: -I${includedir} @libmono_cflags@
+diff --git a/mono-uninstalled.pc.in b/mono-uninstalled.pc.in
+index 7fa3f12dc91..2a0734362fd 100644
+--- a/mono-uninstalled.pc.in
++++ b/mono-uninstalled.pc.in
+@@ -1,6 +1,6 @@
+ Name: Mono
+ Description: Mono Runtime
+ Version: @VERSION@
+-Requires: glib-2.0 gthread-2.0
++Requires: glib-2.0 gthread-2.0 bdw-gc
+ Libs: -L@mono_build_root@/mono/mini/.libs @export_ldflags@ -lmono @libmono_ldflags@
+ Cflags: -I@abs_top_srcdir@ -I@abs_top_srcdir@/mono @libmono_cflags@
+diff --git a/mono/metadata/Makefile.am b/mono/metadata/Makefile.am
+index 83f8532369b..3fca7fc13b9 100644
+--- a/mono/metadata/Makefile.am
++++ b/mono/metadata/Makefile.am
+@@ -171,7 +171,6 @@ libmonoruntimeinclude_HEADERS = \
+ 	object.h	\
+ 	exception.h	\
+ 	profiler.h	\
+-	appdomain.h	\
+ 	mono-config.h	\
+ 	debug-helpers.h	\
+ 	mempool.h
+diff --git a/mono/mini/driver.c b/mono/mini/driver.c
+index 48ca2d96899..9fb3512200b 100644
+--- a/mono/mini/driver.c
++++ b/mono/mini/driver.c
+@@ -1236,6 +1236,7 @@ mono_main (int argc, char* argv[])
+ #endif
+ 	if (!g_thread_supported ())
+ 		g_thread_init (NULL);
++        GC_allow_register_threads();
+ 
+ 	if (mono_running_on_valgrind () && getenv ("MONO_VALGRIND_LEAK_CHECK")) {
+ 		GMemVTable mem_vtable;
+diff --git a/runtime/Makefile.am b/runtime/Makefile.am
+index 0e876e2a491..b9cd0a99d9e 100644
+--- a/runtime/Makefile.am
++++ b/runtime/Makefile.am
+@@ -1,6 +1,3 @@
+-# hack to prevent 'check' from depending on 'all'
+-AUTOMAKE_OPTIONS = cygnus
+-
+ tmpinst = _tmpinst
+ 
+ noinst_SCRIPTS = mono-wrapper monodis-wrapper
-- 
2.45.2

From 2441ce2c3889c031da9699af18dee6648a063aff Mon Sep 17 00:00:00 2001
From: unmush <[email-masked]>
Date: Tue, 26 Nov 2024 12:59:49
Subject: [PATCH v2 05/21] gnu: Add mono-1.9.1.

* gnu/packages/dotnet.scm (mono-1.9.1): New variable.
* gnu/packages/patches/mono-1.9.1-add-MONO_CREATE_IMAGE_VERSION.patch:
  New patch.
* gnu/packages/patches/mono-1.9.1-fixes.patch: New patch.
* gnu/local.mk (dist_patch_DATA): register new patches.

---
 gnu/local.mk                                  |  2 +
 gnu/packages/dotnet.scm                       | 60 +++++++++++++++++++
 ...-1.9.1-add-MONO_CREATE_IMAGE_VERSION.patch | 14 +++++
 gnu/packages/patches/mono-1.9.1-fixes.patch   | 59 ++++++++++++++++++
 4 files changed, 135 insertions(+)
 create mode 100644 gnu/packages/patches/mono-1.9.1-add-MONO_CREATE_IMAGE_VERSION.patch
 create mode 100644 gnu/packages/patches/mono-1.9.1-fixes.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index 54f01ba05a9..b7fa68bd677 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1824,6 +1824,8 @@ dist_patch_DATA =						\
   %D%/packages/patches/module-init-tools-moduledir.patch	\
   %D%/packages/patches/monero-use-system-miniupnpc.patch			\
   %D%/packages/patches/mono-1.2.6-bootstrap.patch		\
+  %D%/packages/patches/mono-1.9.1-add-MONO_CREATE_IMAGE_VERSION.patch		\
+  %D%/packages/patches/mono-1.9.1-fixes.patch			\
   %D%/packages/patches/mosaicatcher-unbundle-htslib.patch	\
   %D%/packages/patches/mrrescue-support-love-11.patch		\
   %D%/packages/patches/mtools-mformat-uninitialized.patch	\
diff --git a/gnu/packages/dotnet.scm b/gnu/packages/dotnet.scm
index 093865080bb..99511a07a99 100644
--- a/gnu/packages/dotnet.scm
+++ b/gnu/packages/dotnet.scm
@@ -410,3 +410,63 @@ (define-public mono-1.2.6
               license:lgpl2.0+ ;; note: ./mcs/LICENSE.LGPL specifies no version
               ;; mcs/jay
               license:bsd-4))))
+
+(define-public mono-1.9.1
+  (package
+    (inherit mono-1.2.6)
+    (version "1.9.1")
+    (name "mono")
+    (source (origin
+              (method git-fetch)
+              (uri
+               (git-reference
+                (url "https://gitlab.winehq.org/mono/mono.git")
+                (commit (string-append "mono-" "1.9.1.1"))))
+              (file-name (git-file-name name version))
+              (sha256
+               (base32
+                "0s1n3zdhc2alk9smxfdl1kjz7lz2p19gs0ks4hgr864jlmf13bws"))
+              (modules '((guix build utils)
+                         (ice-9 string-fun)))
+              (snippet prepare-mono-source)
+              (patches
+               (search-patches
+                "mono-1.9.1-fixes.patch"
+                "mono-1.9.1-add-MONO_CREATE_IMAGE_VERSION.patch"))))
+    (native-inputs
+     (modify-inputs (package-native-inputs mono-1.2.6)
+       (delete "pnet-git")
+       (delete "pnetlib-git")
+       (prepend mono-1.2.6)
+       (append which)
+       ;; needed for tests
+       (append perl)))
+    (arguments
+     (substitute-keyword-arguments (package-arguments mono-1.2.6)
+       ((#:make-flags _ #f)
+        #~(list "CC=gcc" "V=1"))
+       ((#:phases phases #~%standard-phases)
+        #~(modify-phases #$phases
+            (add-before 'configure 'set-cflags
+              (lambda _
+                ;; apparently can't be set via make flags in this version
+                (let ((original (getenv "CFLAGS")))
+                  (setenv "CFLAGS" (string-append (or original "")
+                                                  (if original " " "")
+                                                  "-DARG_MAX=500")))))
+            (add-before 'configure 'set-create-image-version
+              (lambda _
+                ;; pnet produces v2.x assemblies.  Mono does this weird thing
+                ;; where it always produces assemblies of the same version as
+                ;; the runtime that is running it, which is based on the
+                ;; version of the assembly that it loaded, which is based on
+                ;; what it decided for the previous compiler... on and on all
+                ;; the way back to pnet.  This breaks that chain, because
+                ;; otherwise it ends up compiling the initial mcs against .NET
+                ;; 2.0 libraries and then running with .NET 1.0 libraries.
+                (setenv "MONO_CREATE_IMAGE_VERSION" "v1.1.4322")))
+            (add-after 'unpack 'patch-test-driver-shebang
+              (lambda _
+                (patch-shebang "mono/tests/test-driver")))))
+       ((#:tests? _ #f) #f)
+       ((#:parallel-tests? _ #f) #f)))))
diff --git a/gnu/packages/patches/mono-1.9.1-add-MONO_CREATE_IMAGE_VERSION.patch b/gnu/packages/patches/mono-1.9.1-add-MONO_CREATE_IMAGE_VERSION.patch
new file mode 100644
index 00000000000..1eef0548ca1
--- /dev/null
+++ b/gnu/packages/patches/mono-1.9.1-add-MONO_CREATE_IMAGE_VERSION.patch
@@ -0,0 +1,14 @@
+diff --git a/mono/metadata/reflection.c b/mono/metadata/reflection.c
+index ce053b0ef49..7c51f20c4cf 100644
+--- a/mono/metadata/reflection.c
++++ b/mono/metadata/reflection.c
+@@ -4336,6 +4336,9 @@ create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, c
+ 
+ 	const char *version = mono_get_runtime_info ()->runtime_version;
+ 
++        char *env_ver = getenv("MONO_CREATE_IMAGE_VERSION");
++        if (env_ver) version = env_ver;
++
+ #if HAVE_BOEHM_GC
+ 	image = GC_MALLOC (sizeof (MonoDynamicImage));
+ #else
diff --git a/gnu/packages/patches/mono-1.9.1-fixes.patch b/gnu/packages/patches/mono-1.9.1-fixes.patch
new file mode 100644
index 00000000000..16353ea741e
--- /dev/null
+++ b/gnu/packages/patches/mono-1.9.1-fixes.patch
@@ -0,0 +1,59 @@
+diff --git a/data/mono.pc.in b/data/mono.pc.in
+index 6da0960db2d..d43bb187218 100644
+--- a/data/mono.pc.in
++++ b/data/mono.pc.in
+@@ -7,6 +7,6 @@ sysconfdir=@sysconfdir@
+ Name: Mono
+ Description: Mono Runtime
+ Version: @VERSION@
+-Requires: glib-2.0 gthread-2.0
++Requires: glib-2.0 gthread-2.0 bdw-gc
+ Libs: -L${libdir} @export_ldflags@ -lmono @libmono_ldflags@
+ Cflags: -I${includedir} @libmono_cflags@
+diff --git a/mono-uninstalled.pc.in b/mono-uninstalled.pc.in
+index 7fa3f12dc91..2a0734362fd 100644
+--- a/mono-uninstalled.pc.in
++++ b/mono-uninstalled.pc.in
+@@ -1,6 +1,6 @@
+ Name: Mono
+ Description: Mono Runtime
+ Version: @VERSION@
+-Requires: glib-2.0 gthread-2.0
++Requires: glib-2.0 gthread-2.0 bdw-gc
+ Libs: -L@mono_build_root@/mono/mini/.libs @export_ldflags@ -lmono @libmono_ldflags@
+ Cflags: -I@abs_top_srcdir@ -I@abs_top_srcdir@/mono @libmono_cflags@
+diff --git a/mono/metadata/Makefile.am b/mono/metadata/Makefile.am
+index 2e480190c8c..90d0f619959 100644
+--- a/mono/metadata/Makefile.am
++++ b/mono/metadata/Makefile.am
+@@ -157,7 +157,6 @@ libmonoruntimeinclude_HEADERS = \
+ 	object.h	\
+ 	exception.h	\
+ 	profiler.h	\
+-	appdomain.h	\
+ 	mono-config.h	\
+ 	debug-helpers.h	\
+ 	mempool.h
+diff --git a/mono/mini/driver.c b/mono/mini/driver.c
+index ffa4b5e5e69..85a954960eb 100644
+--- a/mono/mini/driver.c
++++ b/mono/mini/driver.c
+@@ -1033,6 +1033,7 @@ mono_main (int argc, char* argv[])
+ #endif
+ 	if (!g_thread_supported ())
+ 		g_thread_init (NULL);
++        GC_allow_register_threads();
+ 
+ 	if (mono_running_on_valgrind () && getenv ("MONO_VALGRIND_LEAK_CHECK")) {
+ 		GMemVTable mem_vtable;
+diff --git a/runtime/Makefile.am b/runtime/Makefile.am
+index e3a8a21e9e2..587b9f4aa79 100644
+--- a/runtime/Makefile.am
++++ b/runtime/Makefile.am
+@@ -1,6 +1,3 @@
+-# hack to prevent 'check' from depending on 'all'
+-AUTOMAKE_OPTIONS = cygnus
+-
+ tmpinst = _tmpinst
+ 
+ noinst_SCRIPTS = mono-wrapper monodis-wrapper semdel-wrapper
-- 
2.45.2

From 4017125ae45aeaf4388944c41192d1989e7d25ac Mon Sep 17 00:00:00 2001
From: unmush <[email-masked]>
Date: Tue, 26 Nov 2024 13:13:40
Subject: [PATCH v2 09/21] gnu: Add mono-3.0.

* gnu/packages/dotnet.scm
  (mono-3.0.12-external-repo-specs, mono-3.0): New variables.

---
 gnu/packages/dotnet.scm | 63 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/gnu/packages/dotnet.scm b/gnu/packages/dotnet.scm
index f97567dc29f..1dd82703b91 100644
--- a/gnu/packages/dotnet.scm
+++ b/gnu/packages/dotnet.scm
@@ -640,3 +640,66 @@ (define-public mono-2.11.4
               license:bsd-4
               ;; mcs/class/System.Core/System/TimeZoneInfo.Android.cs
               license:asl2.0))))
+
+(define mono-3.0.12-external-repo-specs
+  ;; format: ({reponame OR (reponame dir-name)} commit sha256) ...
+  ;; if reponame starts with https:// it is treated as the repository url,
+  ;; otherwise the name of a repository under https://github.com/mono/
+  '(("aspnetwebstack"               "e77b12e6cc5ed260a98447f609e887337e44e299"
+     "0rks344qr4fmp3fs1264d2qkmm348m8d1kjd7z4l94iiirwn1fq1")
+    ("cecil"                        "54e0a50464edbc254b39ea3c885ee91ada730705"
+     "007szbf5a14q838695lwdp7ap6rwzz3kzllgjfnibzlqipw3x2yk")
+    ("entityframework"              "a5faddeca2bee08636f1b7b3af8389bd4119f4cd"
+     "0b05pzf6qwdd92pbzym32nfmw8rq36820vdzakq1kykfmddjr9a7")
+    (("ikvm-fork" "ikvm")           "10b8312c8024111780ee382688cd4c8754b1f1ac"
+     "025wf9gjgfvrq42vgw91ahy3cmzcw094vx783dsp7gjdyd8q09nm")
+    ("Lucene.Net"                   "88fb67b07621dfed054d8d75fd50672fb26349df"
+     "1rfxqfz7hkp9rg5anvxlv6fna0xi0bnv1y8qbhf8x48l08yjb38k")
+    ("Newtonsoft.Json"              "471c3e0803a9f40a0acc8aeceb31de6ff93a52c4"
+     "0dgngd5hqk6yhlg40kabn6qdnknm32zcx9q6bm2w31csnsk5978s")
+    ("rx"                           "17e8477b2cb8dd018d49a567526fe99fd2897857"
+     "0fyyy4jf0mma6kff6fvbvdcs5ra1bz4s063nvjjva9xlnv7sjvh4")))
+
+(define-public mono-3.0
+  (package
+    (inherit mono-2.11.4)
+    (version "3.0.12")
+    (name "mono")
+    (source (origin
+              (method git-fetch)
+              (uri
+               (git-reference
+                (url "https://gitlab.winehq.org/mono/mono.git")
+                (commit (string-append "mono-" "3.0.12"))))
+              (file-name (git-file-name name version))
+              (sha256
+               (base32
+                "110f3hcfikk6bxbrgjas5dqldci9f24gvm3vdgn4j9j7xhlcx1lj"))
+              (modules '((guix build utils)
+                         (ice-9 string-fun)))
+              (snippet #~(begin
+                           #$(add-external-repos
+                              mono-3.0.12-external-repo-specs)
+                           #$prepare-mono-source))))
+    (native-inputs (modify-inputs (package-native-inputs mono-2.11.4)
+                     (replace "mono" mono-2.11.4)))
+    (license (list
+              ;; most of mcs/tools, mono/man, most of mcs/class, tests by
+              ;; default, mono/eglib, mono/metadata/sgen*,
+              ;; mono/arch/*/XXX-codegen.h
+              ;; mcs/mcs, mcs/gmcs (dual-licensed GPL)
+              ;; samples
+              license:x11
+              ;; mcs/mcs, mcs/gmcs (dual-licensed X11)
+              ;; some of mcs/tools
+              license:gpl1+ ;; note: ./mcs/LICENSE.GPL specifies no version
+              ;; mono/mono (the mono VM, I think they meant mono/mini)
+              ;; mono/support (note: directory doesn't exist, probably meant
+              ;; ./support, but that contains a copy of zlib?)
+              license:lgpl2.0+ ;; note: ./mcs/LICENSE.LGPL specifies no version
+              ;; mcs/jay
+              license:bsd-4
+              ;; mcs/class/System.Core/System/TimeZoneInfo.Android.cs
+              license:asl2.0
+              ;; ./support, contains a copy of zlib
+              license:zlib))))
-- 
2.45.2

From e6f255c9e1199a69ec780ef28e987db88d117320 Mon Sep 17 00:00:00 2001
From: unmush <[email-masked]>
Date: Tue, 26 Nov 2024 13:14:35
Subject: [PATCH v2 10/21] gnu: Add mono-3.12.1.

* gnu/packages/dotnet.scm
  (mono-3.12.1-external-repo-specs, mono-3.12.1): New variables.

---
 gnu/packages/dotnet.scm | 52 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/gnu/packages/dotnet.scm b/gnu/packages/dotnet.scm
index 1dd82703b91..5375ec412e3 100644
--- a/gnu/packages/dotnet.scm
+++ b/gnu/packages/dotnet.scm
@@ -703,3 +703,55 @@ (define-public mono-3.0
               license:asl2.0
               ;; ./support, contains a copy of zlib
               license:zlib))))
+
+(define mono-3.12.1-external-repo-specs
+  ;; format: ({reponame OR (reponame dir-name)} commit sha256) ...
+  '(("aspnetwebstack"               "e77b12e6cc5ed260a98447f609e887337e44e299"
+     "0rks344qr4fmp3fs1264d2qkmm348m8d1kjd7z4l94iiirwn1fq1")
+    ("cecil"                        "33d50b874fd527118bc361d83de3d494e8bb55e1"
+     "1p4hl1796ib26ykyf5snl6cj0lx0v7mjh0xqhjw6qdh753nsjyhb")
+    ("entityframework"              "a5faddeca2bee08636f1b7b3af8389bd4119f4cd"
+     "0b05pzf6qwdd92pbzym32nfmw8rq36820vdzakq1kykfmddjr9a7")
+    ("ikdasm"                       "7ded4decb9c39446be634d42a575fda9bc3d945c"
+     "0f3mbfizxmvr5njj123w0wn7sz85v5q2mzwijjql8w1095i0916l")
+    (("ikvm-fork" "ikvm")           "22534de2098acbcf208f6b06836d122dab799e4b"
+     "1ivywy5sc594sl3bs9xrkna1dbhkp7v1mv79n96ydgq6zcs0698l")
+    ("Lucene.Net"                   "88fb67b07621dfed054d8d75fd50672fb26349df"
+     "1rfxqfz7hkp9rg5anvxlv6fna0xi0bnv1y8qbhf8x48l08yjb38k")
+    ("Newtonsoft.Json"              "471c3e0803a9f40a0acc8aeceb31de6ff93a52c4"
+     "0dgngd5hqk6yhlg40kabn6qdnknm32zcx9q6bm2w31csnsk5978s")
+    ("rx"                           "00c1aadf149334c694d2a5096983a84cf46221b8"
+     "0ndam0qrnkb4gj21lapqgcy0mqw7s18viswsjyjyaaa4fgqw8kmq")))
+
+(define-public mono-3.12.1
+  (package
+    (inherit mono-3.0)
+    (version "3.12.1")
+    (name "mono")
+    (source (origin
+              (method git-fetch)
+              (uri
+               (git-reference
+                (url "https://gitlab.winehq.org/mono/mono.git")
+                (commit (string-append "mono-" "3.12.1"))))
+              (file-name (git-file-name name version))
+              (sha256
+               (base32
+                "01sxrnfch61k8v7av7ccbmy3v37ky8yp8460j6ycnbyfa3305y0f"))
+              (modules '((guix build utils)
+                         (ice-9 string-fun)))
+              (snippet #~(begin
+                           #$(add-external-repos
+                              mono-3.12.1-external-repo-specs)
+                           #$prepare-mono-source))))
+    (native-inputs (modify-inputs (package-native-inputs mono-3.0)
+                     (replace "mono" mono-3.0)))
+    (arguments
+     (substitute-keyword-arguments (package-arguments mono-3.0)
+       ((#:phases phases #~%standard-phases)
+        #~(modify-phases #$phases
+            (add-after 'unpack 'set-TZ
+              (lambda _
+                ;; for some reason a default is only used if this is empty, not
+                ;; if it is unset.
+                (setenv "TZ" "")))))))))
-- 
2.45.2

From 47964f7d6d1ac45fc301b15b7eebfd338196a3fa Mon Sep 17 00:00:00 2001
From: unmush <[email-masked]>
Date: Tue, 26 Nov 2024 13:12:11
Subject: [PATCH v2 08/21] gnu: Add mono-2.11.4.

* gnu/packages/dotnet.scm
  (mono-2.11.4-external-repo-specs, mono-2.11.4): New variables.
  (add-external-repos): New procedure.
* gnu/packages/patches/mono-2.11.4-fixes.patch: New patch.
* gnu/local.mk (dist_patch_DATA): Register it.

---
 gnu/local.mk                                 |  1 +
 gnu/packages/dotnet.scm                      | 95 ++++++++++++++++++++
 gnu/packages/patches/mono-2.11.4-fixes.patch | 36 ++++++++
 3 files changed, 132 insertions(+)
 create mode 100644 gnu/packages/patches/mono-2.11.4-fixes.patch

diff --git a/gnu/local.mk b/gnu/local.mk
index 99e106df8fc..8aeb4536f51 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1828,6 +1828,7 @@ dist_patch_DATA =						\
   %D%/packages/patches/mono-1.9.1-fixes.patch			\
   %D%/packages/patches/mono-2.4.2.3-fixes.patch			\
   %D%/packages/patches/mono-2.6.4-fixes.patch			\
+  %D%/packages/patches/mono-2.11.4-fixes.patch			\
   %D%/packages/patches/mosaicatcher-unbundle-htslib.patch	\
   %D%/packages/patches/mrrescue-support-love-11.patch		\
   %D%/packages/patches/mtools-mformat-uninitialized.patch	\
diff --git a/gnu/packages/dotnet.scm b/gnu/packages/dotnet.scm
index 82bee55aa90..f97567dc29f 100644
--- a/gnu/packages/dotnet.scm
+++ b/gnu/packages/dotnet.scm
@@ -545,3 +545,98 @@ (define-public mono-2.6.4
                (search-patches "mono-2.6.4-fixes.patch"))))
     (native-inputs (modify-inputs (package-native-inputs mono-2.4.2)
                      (replace "mono" mono-2.4.2)))))
+
+;; submodule checkouts use git://, which isn't supported by github anymore, so
+;; we need to manually provide them instead of being able to use (recursive?
+;; #t).  Also try not to think too hard about the fact that some of these
+;; submodules in later versions contain binary compiler blobs which mono
+;; maintainers presumably used when creating the bootstrap binaries they
+;; published.  All fetched and updated over unauthenticated git://.
+
+(define mono-2.11.4-external-repo-specs
+  ;; format: ({reponame OR (reponame dir-name)} commit-hash origin-sha256) ...
+  ;; if reponame starts with https:// it is treated as the repository url,
+  ;; otherwise the name of a repository under https://github.com/mono/
+  '(("aspnetwebstack"               "1836deff6a2683b8a5b7dd78f2b591a10b47573e"
+     "0vqq45i8k6jylljarr09hqqiwjs8wn0lgjrl6bz72vxqpp0j344k")
+    ("cecil"                        "54e0a50464edbc254b39ea3c885ee91ada730705"
+     "007szbf5a14q838695lwdp7ap6rwzz3kzllgjfnibzlqipw3x2yk")
+    ("entityframework"              "9baca562ee3a747a41870f45e749e4436b6aca26"
+     "0l8k04bykbrbk5q2pz8hzh8xy8y4ayz7j97fw0kyk3lrai89v5da")
+    ("Newtonsoft.Json"              "471c3e0803a9f40a0acc8aeceb31de6ff93a52c4"
+     "0dgngd5hqk6yhlg40kabn6qdnknm32zcx9q6bm2w31csnsk5978s")))
+
+(define (add-external-repos specs)
+  (define (reponame->url reponame)
+    (if (string-prefix? "https://" reponame)
+        reponame
+        (string-append "https://github.com/mono/" reponame)))
+
+  (define* (external-repo-gexp reponame commit hash
+                               #:key recursive? (patches '()))
+    (let ((short-commit (string-take commit 6))
+          (reponame (if (pair? reponame) (car reponame)
+                        reponame))
+          (dir-name (if (pair? reponame) (cadr reponame)
+                        reponame)))
+      #~(copy-recursively #+(origin
+                              (method git-fetch)
+                              (uri (git-reference
+                                    (url (reponame->url reponame))
+                                    (commit commit)
+                                    (recursive? recursive?)))
+                              (file-name
+                               (git-file-name dir-name
+                                              short-commit))
+                              (sha256 (base32 hash))
+                              (patches (map search-patch patches)))
+                          #$(string-append "./external/" dir-name))))
+
+  (define (spec->gexp spec)
+    (apply external-repo-gexp spec))
+
+  #~(begin
+      #+@(map spec->gexp specs)))
+
+(define-public mono-2.11.4
+  (package
+    (inherit mono-2.6.4)
+    (version "2.11.4")
+    (name "mono")
+    (source (origin
+              (method git-fetch)
+              (uri
+               (git-reference
+                (url "https://gitlab.winehq.org/mono/mono.git")
+                (commit (string-append "mono-" "2.11.4"))))
+              (file-name (git-file-name name version))
+              (sha256
+               (base32
+                "0y2bifi2avbjmfp80hjga2dyqip4b46zkvx6yfr9pa2hhm940rpx"))
+              (modules '((guix build utils)
+                         (ice-9 string-fun)))
+              (snippet #~(begin
+                           #$(add-external-repos
+                              mono-2.11.4-external-repo-specs)
+                           #$prepare-mono-source))
+              (patches
+               (search-patches "mono-2.11.4-fixes.patch"))))
+    (build-system gnu-build-system)
+    (native-inputs (modify-inputs (package-native-inputs mono-2.6.4)
+                     (replace "mono" mono-2.6.4)))
+    (license (list
+              ;; most of mcs/tools, mono/man, most of mcs/class, tests by
+              ;; default, mono/eglib, mono/metadata/sgen*,
+              ;; mono/arch/*/XXX-codegen.h
+              ;; mcs/mcs, mcs/gmcs (dual-licensed GPL)
+              ;; samples
+              license:x11
+              ;; mcs/mcs, mcs/gmcs (dual-licensed X11)
+              ;; some of mcs/tools
+              license:gpl1+ ;; note: ./mcs/LICENSE.GPL specifies no version
+              ;; mono/mono (the mono VM, I think they meant mono/mini)
+              license:lgpl2.0+ ;; note: ./mcs/LICENSE.LGPL specifies no version
+              ;; mcs/jay
+              license:bsd-4
+              ;; mcs/class/System.Core/System/TimeZoneInfo.Android.cs
+              license:asl2.0))))
diff --git a/gnu/packages/patches/mono-2.11.4-fixes.patch b/gnu/packages/patches/mono-2.11.4-fixes.patch
new file mode 100644
index 00000000000..02a05f7977a
--- /dev/null
+++ b/gnu/packages/patches/mono-2.11.4-fixes.patch
@@ -0,0 +1,36 @@
+diff --git a/configure.in b/configure.in
+index 38cc6dc2925..4c608eb150f 100644
+--- a/configure.in
++++ b/configure.in
+@@ -470,7 +470,7 @@ AC_CHECK_HEADERS(wchar.h)
+ AC_CHECK_HEADERS(ieeefp.h)
+ AC_MSG_CHECKING(for isinf)
+ AC_TRY_LINK([#include <math.h>], [
+-	int f = isinf (1);
++	int f = isinf (1.0);
+ ], [
+ 	AC_MSG_RESULT(yes)
+ 	AC_DEFINE(HAVE_ISINF, 1, [isinf available])
+diff --git a/mono/io-layer/processes.c b/mono/io-layer/processes.c
+index 586b54715db..d27857aa092 100644
+--- a/mono/io-layer/processes.c
++++ b/mono/io-layer/processes.c
+@@ -18,6 +18,7 @@
+ #include <errno.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
++#include <sys/sysmacros.h>
+ #include <unistd.h>
+ #include <signal.h>
+ #include <sys/wait.h>
+diff --git a/runtime/Makefile.am b/runtime/Makefile.am
+index 6957a287d38..2d071230a84 100644
+--- a/runtime/Makefile.am
++++ b/runtime/Makefile.am
+@@ -1,6 +1,3 @@
+-# hack to prevent 'check' from depending on 'all'
+-AUTOMAKE_OPTIONS = cygnus
+-
+ tmpinst = _tmpinst
+ 
+ noinst_SCRIPTS = mono-wrapper monodis-wrapper
-- 
2.45.2