<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://freem-wiki.coherent-logic.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Smw</id>
	<title>FreeM Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://freem-wiki.coherent-logic.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Smw"/>
	<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php/Special:Contributions/Smw"/>
	<updated>2026-04-18T10:10:16Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.34.4</generator>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Main_Page&amp;diff=408</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Main_Page&amp;diff=408"/>
		<updated>2025-05-16T13:05:16Z</updated>

		<summary type="html">&lt;p&gt;Smw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki contains documentation not included in the [https://freem.coherent-logic.com/docs FreeM Manual], including platform-specific installation and configuration notes, project policies, technical deep-dives, and release notes.&lt;br /&gt;
&lt;br /&gt;
== Release Notes ==&lt;br /&gt;
* [[Conformance Clause]]&lt;br /&gt;
* [[FreeM 0.62.3]]&lt;br /&gt;
* [[FreeM 0.62.2]]&lt;br /&gt;
* [[FreeM 0.62.1]]&lt;br /&gt;
* [[FreeM Lite]]&lt;br /&gt;
* [[FreeM 0.59.2]]&lt;br /&gt;
&lt;br /&gt;
== Project Policies and Procedures ==&lt;br /&gt;
* [[General Policies]]&lt;br /&gt;
* [[Code of Conduct]]&lt;br /&gt;
&lt;br /&gt;
== Hacking FreeM Code ==&lt;br /&gt;
* [[Contributor Guide]]&lt;br /&gt;
* [[Release Procedure]]&lt;br /&gt;
&lt;br /&gt;
== Port Tiers ==&lt;br /&gt;
* [[Port Tiers]]&lt;br /&gt;
* [[:Category:Tier 1 Ports|Tier 1 Ports]]&lt;br /&gt;
* [[:Category:Tier 2 Ports|Tier 2 Ports]]&lt;br /&gt;
* [[:Category:Tier 3 Ports|Tier 3 Ports]]&lt;br /&gt;
&lt;br /&gt;
== Platform Notes ==&lt;br /&gt;
=== Tier 1 Ports ===&lt;br /&gt;
* [[Platform Notes (Solaris/Illumos)]]&lt;br /&gt;
* [[Platform Notes (NetBSD)]]&lt;br /&gt;
* [[Platform Notes (FreeBSD)]]&lt;br /&gt;
* [[Platform Notes (GNU/Linux)]]&lt;br /&gt;
* [[Platform Notes (OpenBSD)]]&lt;br /&gt;
&lt;br /&gt;
=== Tier 2 Ports ===&lt;br /&gt;
* [[Platform Notes (OS/2)]]&lt;br /&gt;
* [[Platform Notes (SCO OpenServer)]]&lt;br /&gt;
* [[Platform Notes (Compaq Tru64 UNIX)]]&lt;br /&gt;
* [[Platform Notes (IBM AIX)]]&lt;br /&gt;
* [[Platform Notes (Mac OS X)]]&lt;br /&gt;
&lt;br /&gt;
=== Tier 3 Ports ===&lt;br /&gt;
* [[Platform Notes (GNU HURD)]]&lt;br /&gt;
* [[Platform Notes (SGI IRIX)]]&lt;br /&gt;
* [[Platform Notes (HP-UX)]]&lt;br /&gt;
* [[Platform Notes (Minix 3+)]]&lt;br /&gt;
&lt;br /&gt;
== Tips and Tricks ==&lt;br /&gt;
* [[Subscript Rules (Local and Global)]]&lt;br /&gt;
* [[Object-Oriented Programming in FreeM]]&lt;br /&gt;
&lt;br /&gt;
== Technical Deep-Dives ==&lt;br /&gt;
* [[FreeM System Architecture]]&lt;br /&gt;
* [[Event Handling in FreeM]]&lt;br /&gt;
* [[FreeM Transaction Processing Architecture]]&lt;br /&gt;
* [[What is the GUMP?]]&lt;br /&gt;
* [[Namespace Rules]]&lt;br /&gt;
* [[Routine and Global Search Path Internals]]&lt;br /&gt;
&lt;br /&gt;
== History ==&lt;br /&gt;
* [[FreeM History]]&lt;br /&gt;
* [[Original README from Shalom ha-Ashkenaz]]&lt;br /&gt;
&lt;br /&gt;
== Status of Popular M Applications in FreeM ==&lt;br /&gt;
&lt;br /&gt;
* [[Applications: VA VistA]]&lt;br /&gt;
* [[Applications: VA FileMan]]&lt;br /&gt;
* [[Applications: VPE (Victory Programming Environment)]]&lt;br /&gt;
* [[Applications: M Web Server]]&lt;br /&gt;
* [[Applications: GDS/JDS]]&lt;br /&gt;
* [[Applications: MVTS (M Validation and Test Suite)]]&lt;br /&gt;
&lt;br /&gt;
== General M Topics ==&lt;br /&gt;
* [[M User's Group]]&lt;br /&gt;
* [[M Technology Association]]&lt;br /&gt;
* [[M Development Committee]]&lt;br /&gt;
* [[Cache and M Technology Association UK]]&lt;br /&gt;
* [[M User's Group-Deutschland]]&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(Mac_OS_X)&amp;diff=407</id>
		<title>Platform Notes (Mac OS X)</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(Mac_OS_X)&amp;diff=407"/>
		<updated>2025-05-16T13:02:19Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Port Challenges */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Port Status ==&lt;br /&gt;
&lt;br /&gt;
The Mac OS X port is a [[Tier 2 Port]].&lt;br /&gt;
The main branch will compile on macOS Monterey (12.6.8) on Intel, and it can run if the &amp;lt;code&amp;gt;kern.sysv.shmmax&amp;lt;/code&amp;gt; parameter is correct (see below).&lt;br /&gt;
&lt;br /&gt;
== Verified Releases ==&lt;br /&gt;
* [[FreeM Lite]]&lt;br /&gt;
* FreeM 0.65.1-rc0&lt;br /&gt;
&lt;br /&gt;
== Build Notes ==&lt;br /&gt;
&lt;br /&gt;
In order to build FreeM on macOS, you will need to install the following:&lt;br /&gt;
&lt;br /&gt;
* Apple XCode command-line tools&lt;br /&gt;
* Homebrew&lt;br /&gt;
&lt;br /&gt;
Then, install the following with the brew package manager:&lt;br /&gt;
&lt;br /&gt;
* automake&lt;br /&gt;
* autoconf&lt;br /&gt;
* gcc&lt;br /&gt;
* libtool&lt;br /&gt;
* texinfo&lt;br /&gt;
* texi2html&lt;br /&gt;
* git&lt;br /&gt;
&lt;br /&gt;
== Testing Details ==&lt;br /&gt;
&lt;br /&gt;
We build the macOS port on the following hardware:&lt;br /&gt;
&lt;br /&gt;
* MacBook Air (Early 2015) running macOS Monterey (12.6.8)&lt;br /&gt;
* M1 Mac Mini running macOS Sequoia&lt;br /&gt;
&lt;br /&gt;
== Required Kernel Tuning ==&lt;br /&gt;
&lt;br /&gt;
You will need to set the &amp;lt;code&amp;gt;kern.sysv.shmmax&amp;lt;/code&amp;gt; sysctl parameter to at least 17002496 (the value must be a multiple of the system page size; generally 4096).&lt;br /&gt;
&lt;br /&gt;
To determine the current setting, see below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo sysctl -a | grep shmmax&lt;br /&gt;
kern.sysv.shmmax: 4194304&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above example, the &amp;lt;code&amp;gt;shmmax&amp;lt;/code&amp;gt; value is &amp;lt;code&amp;gt;4194304&amp;lt;/code&amp;gt;, and thus insufficient for proper FreeM operation.&lt;br /&gt;
&lt;br /&gt;
See your macOS version below for instructions on modifying this value.&lt;br /&gt;
&lt;br /&gt;
=== All Versions ===&lt;br /&gt;
&lt;br /&gt;
* Find the file &amp;lt;code&amp;gt;com.startup.sysctl.plist&amp;lt;/code&amp;gt; file in the &amp;lt;code&amp;gt;scripts&amp;lt;/code&amp;gt; subdirectory of the FreeM distribution&lt;br /&gt;
* Copy it to &amp;lt;code&amp;gt;/Library/LaunchDaemons&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change the ownership of &amp;lt;code&amp;gt;/Library/LaunchDaemons/com.startup.sysctl.plist&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;root:wheel&amp;lt;/code&amp;gt;&lt;br /&gt;
* Run &amp;lt;code&amp;gt;sudo launchctl load /Library/LaunchDaemons/com.startup.sysctl.plist&amp;lt;/code&amp;gt;&lt;br /&gt;
* Reboot&lt;br /&gt;
&lt;br /&gt;
See the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo cp scripts/com.startup.sysctl.plist /Library/LaunchDaemons/&lt;br /&gt;
$ sudo chown root:wheel /Library/LaunchDaemons/com.startup.sysctl.plist&lt;br /&gt;
$ sudo launchctl load /Library/LaunchDaemons/com.startup.sysctl.plist&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Starting the FreeM Daemon Automatically ==&lt;br /&gt;
Coming soon.&lt;br /&gt;
&lt;br /&gt;
== Port Challenges ==&lt;br /&gt;
The shared memory architecture of FreeM had to be rewritten to support Apple's System V IPC changes for their Unified Memory Architecture.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Platform Notes]]&lt;br /&gt;
[[Category:Tier 2 Ports]]&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(Mac_OS_X)&amp;diff=406</id>
		<title>Platform Notes (Mac OS X)</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(Mac_OS_X)&amp;diff=406"/>
		<updated>2025-05-16T13:01:38Z</updated>

		<summary type="html">&lt;p&gt;Smw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Port Status ==&lt;br /&gt;
&lt;br /&gt;
The Mac OS X port is a [[Tier 2 Port]].&lt;br /&gt;
The main branch will compile on macOS Monterey (12.6.8) on Intel, and it can run if the &amp;lt;code&amp;gt;kern.sysv.shmmax&amp;lt;/code&amp;gt; parameter is correct (see below).&lt;br /&gt;
&lt;br /&gt;
== Verified Releases ==&lt;br /&gt;
* [[FreeM Lite]]&lt;br /&gt;
* FreeM 0.65.1-rc0&lt;br /&gt;
&lt;br /&gt;
== Build Notes ==&lt;br /&gt;
&lt;br /&gt;
In order to build FreeM on macOS, you will need to install the following:&lt;br /&gt;
&lt;br /&gt;
* Apple XCode command-line tools&lt;br /&gt;
* Homebrew&lt;br /&gt;
&lt;br /&gt;
Then, install the following with the brew package manager:&lt;br /&gt;
&lt;br /&gt;
* automake&lt;br /&gt;
* autoconf&lt;br /&gt;
* gcc&lt;br /&gt;
* libtool&lt;br /&gt;
* texinfo&lt;br /&gt;
* texi2html&lt;br /&gt;
* git&lt;br /&gt;
&lt;br /&gt;
== Testing Details ==&lt;br /&gt;
&lt;br /&gt;
We build the macOS port on the following hardware:&lt;br /&gt;
&lt;br /&gt;
* MacBook Air (Early 2015) running macOS Monterey (12.6.8)&lt;br /&gt;
* M1 Mac Mini running macOS Sequoia&lt;br /&gt;
&lt;br /&gt;
== Required Kernel Tuning ==&lt;br /&gt;
&lt;br /&gt;
You will need to set the &amp;lt;code&amp;gt;kern.sysv.shmmax&amp;lt;/code&amp;gt; sysctl parameter to at least 17002496 (the value must be a multiple of the system page size; generally 4096).&lt;br /&gt;
&lt;br /&gt;
To determine the current setting, see below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo sysctl -a | grep shmmax&lt;br /&gt;
kern.sysv.shmmax: 4194304&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In the above example, the &amp;lt;code&amp;gt;shmmax&amp;lt;/code&amp;gt; value is &amp;lt;code&amp;gt;4194304&amp;lt;/code&amp;gt;, and thus insufficient for proper FreeM operation.&lt;br /&gt;
&lt;br /&gt;
See your macOS version below for instructions on modifying this value.&lt;br /&gt;
&lt;br /&gt;
=== All Versions ===&lt;br /&gt;
&lt;br /&gt;
* Find the file &amp;lt;code&amp;gt;com.startup.sysctl.plist&amp;lt;/code&amp;gt; file in the &amp;lt;code&amp;gt;scripts&amp;lt;/code&amp;gt; subdirectory of the FreeM distribution&lt;br /&gt;
* Copy it to &amp;lt;code&amp;gt;/Library/LaunchDaemons&amp;lt;/code&amp;gt;&lt;br /&gt;
* Change the ownership of &amp;lt;code&amp;gt;/Library/LaunchDaemons/com.startup.sysctl.plist&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;root:wheel&amp;lt;/code&amp;gt;&lt;br /&gt;
* Run &amp;lt;code&amp;gt;sudo launchctl load /Library/LaunchDaemons/com.startup.sysctl.plist&amp;lt;/code&amp;gt;&lt;br /&gt;
* Reboot&lt;br /&gt;
&lt;br /&gt;
See the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo cp scripts/com.startup.sysctl.plist /Library/LaunchDaemons/&lt;br /&gt;
$ sudo chown root:wheel /Library/LaunchDaemons/com.startup.sysctl.plist&lt;br /&gt;
$ sudo launchctl load /Library/LaunchDaemons/com.startup.sysctl.plist&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Starting the FreeM Daemon Automatically ==&lt;br /&gt;
Coming soon.&lt;br /&gt;
&lt;br /&gt;
== Port Challenges ==&lt;br /&gt;
Apple makes it extremely difficult to build traditional UNIX software, in the name of &amp;quot;security&amp;quot;. Also, Apple silicon (M1 and descendants) cannot likely be supported with the current shared memory architecture.&lt;br /&gt;
&lt;br /&gt;
We will most likely support only PowerPC and Intel Macs.&lt;br /&gt;
&lt;br /&gt;
[[Category:Platform Notes]]&lt;br /&gt;
[[Category:Tier 2 Ports]]&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Conformance_Clause&amp;diff=405</id>
		<title>Conformance Clause</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Conformance_Clause&amp;diff=405"/>
		<updated>2025-05-05T04:50:19Z</updated>

		<summary type="html">&lt;p&gt;Smw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Conformance Policy ==&lt;br /&gt;
&lt;br /&gt;
FreeM attempts to comply with ANSI X11.1-1995 and the unpublished Millennium Draft Standard (MDS) from the [[M Development Committee]], in routine buffers where the dialect setting is set to a particular version of the standard.&lt;br /&gt;
&lt;br /&gt;
Routine buffers in &amp;lt;code&amp;gt;FREEM&amp;lt;/code&amp;gt; dialect enable all nonstandard extensions.&lt;br /&gt;
&lt;br /&gt;
This article has been superseded by &amp;lt;code&amp;gt;freem_conformance(1)&amp;lt;/code&amp;gt; in the UNIX manual.&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=404</id>
		<title>Contributor Guide</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=404"/>
		<updated>2025-04-29T22:30:49Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Building FreeM */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
This article describes the facilities, methods, and commands used to contribute to the FreeM project.&lt;br /&gt;
&lt;br /&gt;
=For All Developers=&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
In order to contribute to FreeM, you must agree to abide by both the [[Code of Conduct]] and the [[General Policies]]. Your code must also conform to the style standards laid out in Appendix F of [https://freem.coherent-logic.com/docs/0.61.2/freem.html The FreeM Manual].&lt;br /&gt;
&lt;br /&gt;
You will also need to have &amp;lt;code&amp;gt;cvs&amp;lt;/code&amp;gt; installed on your machine. This is available in the package repositories of all popular Linux and UNIX operating systems.&lt;br /&gt;
&lt;br /&gt;
==Language==&lt;br /&gt;
All contributions to FreeM proper must be written in C. Bourne shell scripts are permissible where appropriate, and of course M code for the &amp;lt;code&amp;gt;mlib&amp;lt;/code&amp;gt; routines.&lt;br /&gt;
&lt;br /&gt;
===C Standard===&lt;br /&gt;
* FreeM contributions must not use language features unavailable in C89&lt;br /&gt;
* Vendor extensions in C compilers (like GNU extensions) are only permitted if guarded by preprocessor macros, and should be avoided if possible&lt;br /&gt;
* Contributions should be backwards compatible with gcc 2.95.3 (the oldest compiler we support)&lt;br /&gt;
* Contributions should not break compiles on Sun &amp;lt;code&amp;gt;cc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;clang&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the last two guidelines, FreeM core developers will test your contributions and work with you to address any incompatibilities with these older compilers. We do not require every contributor to have access to every compiler.&lt;br /&gt;
&lt;br /&gt;
===Autotools===&lt;br /&gt;
* Contributions to &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; configuration must not use &amp;lt;code&amp;gt;pkg-config&amp;lt;/code&amp;gt;, as it is unavailable on some of our target platforms&lt;br /&gt;
* Target &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; 2.54 and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; 1.7.1 for compatibility&lt;br /&gt;
&lt;br /&gt;
=Anonymous CVS Access=&lt;br /&gt;
&lt;br /&gt;
==Getting Source Code from CVS==&lt;br /&gt;
To fetch the latest FreeM source code from CVS, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
To update a previously-fetched copy of FreeM source code, go into the directory in which FreeM is located, and run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Submitting Changes Without CVS Write Access==&lt;br /&gt;
To submit a change to FreeM as an anonymous user (i.e., a user without writer access to the FreeM CVS repository), generate a &amp;lt;code&amp;gt;.patch&amp;lt;/code&amp;gt; file using the &amp;lt;code&amp;gt;diff&amp;lt;/code&amp;gt; utility, and send it to &amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt; (you must be subscribed to the mailing list), along with a description containing the following information:&lt;br /&gt;
&lt;br /&gt;
* What bug your patch fixes, or feature it implements&lt;br /&gt;
* Your full preferred name (this will be used in order to credit you for your work)&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
&lt;br /&gt;
Each patch should address no more than one bug fix or feature addition. Patches that do not comply with this requirement will be kicked back to the developer for revision.&lt;br /&gt;
&lt;br /&gt;
=CVS Writer Access=&lt;br /&gt;
&lt;br /&gt;
==Requesting Writer Access==&lt;br /&gt;
&lt;br /&gt;
In order to get CVS writer access, you will need to have either a track record of submitting good patches, or be an existing member of the core team. If you meet this criteria, please send a request to &lt;br /&gt;
&amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt;, including the following information:&lt;br /&gt;
&lt;br /&gt;
* Your full preferred name&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
* The username you would like to use for access to our CVS server (we will do our best to accommodate, but you may be required to choose a different username if your preferred username is already taken)&lt;br /&gt;
&lt;br /&gt;
==Configuring CVS==&lt;br /&gt;
&lt;br /&gt;
Once the below changes are made, you will need to log out and log back in to make them take effect.&lt;br /&gt;
&lt;br /&gt;
===Bourne-Again Shell (bash)===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.bashrc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;~/.bash_profile&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export CVS_RSH=/usr/bin/ssh&lt;br /&gt;
export CVSROOT=:ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also need to change the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; value to the correct absolute path to your &amp;lt;code&amp;gt;ssh&amp;lt;/code&amp;gt; binary. You can find this information using &amp;lt;code&amp;gt;which ssh&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===C Shell===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.cshrc&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setenv CVS_RSH /usr/bin/ssh&lt;br /&gt;
setenv CVSROOT :ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Fetching FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
To fetch the latest FreeM source code for the first time, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this fails, make sure you have the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CVSROOT&amp;lt;/code&amp;gt; environment variables correctly configured.&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
In the directory containing the FreeM source code, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Adding Files to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands from the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory, substituting the path and filename (relative to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory) for &amp;lt;code&amp;gt;&amp;amp;lt;filename&amp;amp;gt;&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs add &amp;lt;filename&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Committing Changes and Pushing to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands ''from the parent directory of the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory'', replacing &amp;lt;code&amp;gt;commit-message&amp;lt;/code&amp;gt; with a message describing the change:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs ci -m &amp;quot;commit-message&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Building FreeM=&lt;br /&gt;
&lt;br /&gt;
Please see [[:Category:Platform Notes]] for any additional notes unique to your platform.&lt;br /&gt;
&lt;br /&gt;
Note that the autotools &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; will place FreeM in &amp;lt;code&amp;gt;/usr/local&amp;lt;/code&amp;gt; by default on most platforms. This conflicts with binary packages on Solaris.&lt;br /&gt;
&lt;br /&gt;
You can override the default installation location in the &amp;lt;code&amp;gt;configure&amp;lt;/code&amp;gt; step with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./configure --prefix=/path/to/desired/location&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Build==&lt;br /&gt;
This applies to the first build after you've obtained the FreeM source code.&lt;br /&gt;
&lt;br /&gt;
Follow these steps for the initial build:&lt;br /&gt;
&lt;br /&gt;
# Change directories to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; repository&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./autogen.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./configure&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;sudo make install&amp;lt;/code&amp;gt;&lt;br /&gt;
# Create a &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; group&lt;br /&gt;
# Create a &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; user&lt;br /&gt;
# Run &amp;lt;code&amp;gt;sudo fmadm configure&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will need to add any users who will use FreeM to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; group, and log out and back in.&lt;br /&gt;
&lt;br /&gt;
Once this is done, check the [[:Category:Platform Notes]] for your platform for further instructions about configuring your environment.&lt;br /&gt;
&lt;br /&gt;
Once you have done the initial build, most changes shouldn't require more than a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Subsequent Builds==&lt;br /&gt;
Most subsequent builds will just need a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;. See the following paragraphs for caveats.&lt;br /&gt;
&lt;br /&gt;
===When to run autogen.sh===&lt;br /&gt;
The &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; script is currently a shorthand for &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
We recommend that FreeM hackers get used to using &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; instead of running &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt; directly, as &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; may eventually contain other auto-generated items in future.&lt;br /&gt;
&lt;br /&gt;
You will need to run &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; only if you change any &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; files. Even then, a fresh &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; will generally check to see if your generated autoconf/automake files are older than &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; and do this step for you automatically.&lt;br /&gt;
&lt;br /&gt;
===When to run make install===&lt;br /&gt;
You should only need to run &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; in the following scenarios:&lt;br /&gt;
&lt;br /&gt;
* You've changed the way the environment catalog (&amp;lt;code&amp;gt;env.conf&amp;lt;/code&amp;gt;) or environment configuration files (&amp;lt;code&amp;gt;freem.conf&amp;lt;/code&amp;gt;) work&lt;br /&gt;
* You've modified a vendor routine in the &amp;lt;code&amp;gt;mlib/&amp;lt;/code&amp;gt; directory&lt;br /&gt;
* You've modified &amp;lt;code&amp;gt;libfreem&amp;lt;/code&amp;gt; and want to test it from a standard system location&lt;br /&gt;
&lt;br /&gt;
Other than these scenarios, you should be able to run the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;fmadm&amp;lt;/code&amp;gt; binaries out of the repository directory hierarchy.&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=403</id>
		<title>Contributor Guide</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=403"/>
		<updated>2025-04-29T22:24:56Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Initial Build */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
This article describes the facilities, methods, and commands used to contribute to the FreeM project.&lt;br /&gt;
&lt;br /&gt;
=For All Developers=&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
In order to contribute to FreeM, you must agree to abide by both the [[Code of Conduct]] and the [[General Policies]]. Your code must also conform to the style standards laid out in Appendix F of [https://freem.coherent-logic.com/docs/0.61.2/freem.html The FreeM Manual].&lt;br /&gt;
&lt;br /&gt;
You will also need to have &amp;lt;code&amp;gt;cvs&amp;lt;/code&amp;gt; installed on your machine. This is available in the package repositories of all popular Linux and UNIX operating systems.&lt;br /&gt;
&lt;br /&gt;
==Language==&lt;br /&gt;
All contributions to FreeM proper must be written in C. Bourne shell scripts are permissible where appropriate, and of course M code for the &amp;lt;code&amp;gt;mlib&amp;lt;/code&amp;gt; routines.&lt;br /&gt;
&lt;br /&gt;
===C Standard===&lt;br /&gt;
* FreeM contributions must not use language features unavailable in C89&lt;br /&gt;
* Vendor extensions in C compilers (like GNU extensions) are only permitted if guarded by preprocessor macros, and should be avoided if possible&lt;br /&gt;
* Contributions should be backwards compatible with gcc 2.95.3 (the oldest compiler we support)&lt;br /&gt;
* Contributions should not break compiles on Sun &amp;lt;code&amp;gt;cc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;clang&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the last two guidelines, FreeM core developers will test your contributions and work with you to address any incompatibilities with these older compilers. We do not require every contributor to have access to every compiler.&lt;br /&gt;
&lt;br /&gt;
===Autotools===&lt;br /&gt;
* Contributions to &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; configuration must not use &amp;lt;code&amp;gt;pkg-config&amp;lt;/code&amp;gt;, as it is unavailable on some of our target platforms&lt;br /&gt;
* Target &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; 2.54 and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; 1.7.1 for compatibility&lt;br /&gt;
&lt;br /&gt;
=Anonymous CVS Access=&lt;br /&gt;
&lt;br /&gt;
==Getting Source Code from CVS==&lt;br /&gt;
To fetch the latest FreeM source code from CVS, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
To update a previously-fetched copy of FreeM source code, go into the directory in which FreeM is located, and run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Submitting Changes Without CVS Write Access==&lt;br /&gt;
To submit a change to FreeM as an anonymous user (i.e., a user without writer access to the FreeM CVS repository), generate a &amp;lt;code&amp;gt;.patch&amp;lt;/code&amp;gt; file using the &amp;lt;code&amp;gt;diff&amp;lt;/code&amp;gt; utility, and send it to &amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt; (you must be subscribed to the mailing list), along with a description containing the following information:&lt;br /&gt;
&lt;br /&gt;
* What bug your patch fixes, or feature it implements&lt;br /&gt;
* Your full preferred name (this will be used in order to credit you for your work)&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
&lt;br /&gt;
Each patch should address no more than one bug fix or feature addition. Patches that do not comply with this requirement will be kicked back to the developer for revision.&lt;br /&gt;
&lt;br /&gt;
=CVS Writer Access=&lt;br /&gt;
&lt;br /&gt;
==Requesting Writer Access==&lt;br /&gt;
&lt;br /&gt;
In order to get CVS writer access, you will need to have either a track record of submitting good patches, or be an existing member of the core team. If you meet this criteria, please send a request to &lt;br /&gt;
&amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt;, including the following information:&lt;br /&gt;
&lt;br /&gt;
* Your full preferred name&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
* The username you would like to use for access to our CVS server (we will do our best to accommodate, but you may be required to choose a different username if your preferred username is already taken)&lt;br /&gt;
&lt;br /&gt;
==Configuring CVS==&lt;br /&gt;
&lt;br /&gt;
Once the below changes are made, you will need to log out and log back in to make them take effect.&lt;br /&gt;
&lt;br /&gt;
===Bourne-Again Shell (bash)===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.bashrc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;~/.bash_profile&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export CVS_RSH=/usr/bin/ssh&lt;br /&gt;
export CVSROOT=:ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also need to change the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; value to the correct absolute path to your &amp;lt;code&amp;gt;ssh&amp;lt;/code&amp;gt; binary. You can find this information using &amp;lt;code&amp;gt;which ssh&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===C Shell===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.cshrc&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setenv CVS_RSH /usr/bin/ssh&lt;br /&gt;
setenv CVSROOT :ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Fetching FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
To fetch the latest FreeM source code for the first time, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this fails, make sure you have the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CVSROOT&amp;lt;/code&amp;gt; environment variables correctly configured.&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
In the directory containing the FreeM source code, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Adding Files to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands from the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory, substituting the path and filename (relative to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory) for &amp;lt;code&amp;gt;&amp;amp;lt;filename&amp;amp;gt;&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs add &amp;lt;filename&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Committing Changes and Pushing to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands ''from the parent directory of the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory'', replacing &amp;lt;code&amp;gt;commit-message&amp;lt;/code&amp;gt; with a message describing the change:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs ci -m &amp;quot;commit-message&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Building FreeM=&lt;br /&gt;
&lt;br /&gt;
Please see [[:Category:Platform Notes]] for any additional notes unique to your platform.&lt;br /&gt;
&lt;br /&gt;
Note that the autotools &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; will place FreeM in &amp;lt;code&amp;gt;/usr/local&amp;lt;/code&amp;gt; by default on most platforms. This conflicts with binary packages on Solaris.&lt;br /&gt;
&lt;br /&gt;
You can override the default installation location in the &amp;lt;code&amp;gt;configure&amp;lt;/code&amp;gt; step with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./configure --prefix=/path/to/desired/location&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Build==&lt;br /&gt;
This applies to the first build after you've obtained the FreeM source code.&lt;br /&gt;
&lt;br /&gt;
Follow these steps for the initial build:&lt;br /&gt;
&lt;br /&gt;
# Change directories to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; repository&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./autogen.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./configure&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;sudo make install&amp;lt;/code&amp;gt;&lt;br /&gt;
# Create a &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; group&lt;br /&gt;
# Create a &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; user&lt;br /&gt;
# Run &amp;lt;code&amp;gt;sudo fmadm configure&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will need to add any users who will use FreeM to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; group, and log out and back in.&lt;br /&gt;
&lt;br /&gt;
Once you have done the initial build, most changes shouldn't require more than a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Subsequent Builds==&lt;br /&gt;
Most subsequent builds will just need a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;. See the following paragraphs for caveats.&lt;br /&gt;
&lt;br /&gt;
===When to run autogen.sh===&lt;br /&gt;
The &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; script is currently a shorthand for &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
We recommend that FreeM hackers get used to using &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; instead of running &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt; directly, as &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; may eventually contain other auto-generated items in future.&lt;br /&gt;
&lt;br /&gt;
You will need to run &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; only if you change any &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; files. Even then, a fresh &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; will generally check to see if your generated autoconf/automake files are older than &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; and do this step for you automatically.&lt;br /&gt;
&lt;br /&gt;
===When to run make install===&lt;br /&gt;
You should only need to run &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; in the following scenarios:&lt;br /&gt;
&lt;br /&gt;
* You've changed the way the environment catalog (&amp;lt;code&amp;gt;env.conf&amp;lt;/code&amp;gt;) or environment configuration files (&amp;lt;code&amp;gt;freem.conf&amp;lt;/code&amp;gt;) work&lt;br /&gt;
* You've modified a vendor routine in the &amp;lt;code&amp;gt;mlib/&amp;lt;/code&amp;gt; directory&lt;br /&gt;
* You've modified &amp;lt;code&amp;gt;libfreem&amp;lt;/code&amp;gt; and want to test it from a standard system location&lt;br /&gt;
&lt;br /&gt;
Other than these scenarios, you should be able to run the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;fmadm&amp;lt;/code&amp;gt; binaries out of the repository directory hierarchy.&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=402</id>
		<title>Contributor Guide</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=402"/>
		<updated>2025-04-29T22:23:14Z</updated>

		<summary type="html">&lt;p&gt;Smw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
This article describes the facilities, methods, and commands used to contribute to the FreeM project.&lt;br /&gt;
&lt;br /&gt;
=For All Developers=&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
In order to contribute to FreeM, you must agree to abide by both the [[Code of Conduct]] and the [[General Policies]]. Your code must also conform to the style standards laid out in Appendix F of [https://freem.coherent-logic.com/docs/0.61.2/freem.html The FreeM Manual].&lt;br /&gt;
&lt;br /&gt;
You will also need to have &amp;lt;code&amp;gt;cvs&amp;lt;/code&amp;gt; installed on your machine. This is available in the package repositories of all popular Linux and UNIX operating systems.&lt;br /&gt;
&lt;br /&gt;
==Language==&lt;br /&gt;
All contributions to FreeM proper must be written in C. Bourne shell scripts are permissible where appropriate, and of course M code for the &amp;lt;code&amp;gt;mlib&amp;lt;/code&amp;gt; routines.&lt;br /&gt;
&lt;br /&gt;
===C Standard===&lt;br /&gt;
* FreeM contributions must not use language features unavailable in C89&lt;br /&gt;
* Vendor extensions in C compilers (like GNU extensions) are only permitted if guarded by preprocessor macros, and should be avoided if possible&lt;br /&gt;
* Contributions should be backwards compatible with gcc 2.95.3 (the oldest compiler we support)&lt;br /&gt;
* Contributions should not break compiles on Sun &amp;lt;code&amp;gt;cc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;clang&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the last two guidelines, FreeM core developers will test your contributions and work with you to address any incompatibilities with these older compilers. We do not require every contributor to have access to every compiler.&lt;br /&gt;
&lt;br /&gt;
===Autotools===&lt;br /&gt;
* Contributions to &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; configuration must not use &amp;lt;code&amp;gt;pkg-config&amp;lt;/code&amp;gt;, as it is unavailable on some of our target platforms&lt;br /&gt;
* Target &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; 2.54 and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; 1.7.1 for compatibility&lt;br /&gt;
&lt;br /&gt;
=Anonymous CVS Access=&lt;br /&gt;
&lt;br /&gt;
==Getting Source Code from CVS==&lt;br /&gt;
To fetch the latest FreeM source code from CVS, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
To update a previously-fetched copy of FreeM source code, go into the directory in which FreeM is located, and run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Submitting Changes Without CVS Write Access==&lt;br /&gt;
To submit a change to FreeM as an anonymous user (i.e., a user without writer access to the FreeM CVS repository), generate a &amp;lt;code&amp;gt;.patch&amp;lt;/code&amp;gt; file using the &amp;lt;code&amp;gt;diff&amp;lt;/code&amp;gt; utility, and send it to &amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt; (you must be subscribed to the mailing list), along with a description containing the following information:&lt;br /&gt;
&lt;br /&gt;
* What bug your patch fixes, or feature it implements&lt;br /&gt;
* Your full preferred name (this will be used in order to credit you for your work)&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
&lt;br /&gt;
Each patch should address no more than one bug fix or feature addition. Patches that do not comply with this requirement will be kicked back to the developer for revision.&lt;br /&gt;
&lt;br /&gt;
=CVS Writer Access=&lt;br /&gt;
&lt;br /&gt;
==Requesting Writer Access==&lt;br /&gt;
&lt;br /&gt;
In order to get CVS writer access, you will need to have either a track record of submitting good patches, or be an existing member of the core team. If you meet this criteria, please send a request to &lt;br /&gt;
&amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt;, including the following information:&lt;br /&gt;
&lt;br /&gt;
* Your full preferred name&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
* The username you would like to use for access to our CVS server (we will do our best to accommodate, but you may be required to choose a different username if your preferred username is already taken)&lt;br /&gt;
&lt;br /&gt;
==Configuring CVS==&lt;br /&gt;
&lt;br /&gt;
Once the below changes are made, you will need to log out and log back in to make them take effect.&lt;br /&gt;
&lt;br /&gt;
===Bourne-Again Shell (bash)===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.bashrc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;~/.bash_profile&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export CVS_RSH=/usr/bin/ssh&lt;br /&gt;
export CVSROOT=:ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also need to change the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; value to the correct absolute path to your &amp;lt;code&amp;gt;ssh&amp;lt;/code&amp;gt; binary. You can find this information using &amp;lt;code&amp;gt;which ssh&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===C Shell===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.cshrc&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setenv CVS_RSH /usr/bin/ssh&lt;br /&gt;
setenv CVSROOT :ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Fetching FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
To fetch the latest FreeM source code for the first time, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this fails, make sure you have the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CVSROOT&amp;lt;/code&amp;gt; environment variables correctly configured.&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
In the directory containing the FreeM source code, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Adding Files to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands from the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory, substituting the path and filename (relative to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory) for &amp;lt;code&amp;gt;&amp;amp;lt;filename&amp;amp;gt;&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs add &amp;lt;filename&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Committing Changes and Pushing to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands ''from the parent directory of the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory'', replacing &amp;lt;code&amp;gt;commit-message&amp;lt;/code&amp;gt; with a message describing the change:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs ci -m &amp;quot;commit-message&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Building FreeM=&lt;br /&gt;
&lt;br /&gt;
Please see [[:Category:Platform Notes]] for any additional notes unique to your platform.&lt;br /&gt;
&lt;br /&gt;
Note that the autotools &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; will place FreeM in &amp;lt;code&amp;gt;/usr/local&amp;lt;/code&amp;gt; by default on most platforms. This conflicts with binary packages on Solaris.&lt;br /&gt;
&lt;br /&gt;
You can override the default installation location in the &amp;lt;code&amp;gt;configure&amp;lt;/code&amp;gt; step with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./configure --prefix=/path/to/desired/location&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Build==&lt;br /&gt;
This applies to the first build after you've obtained the FreeM source code.&lt;br /&gt;
&lt;br /&gt;
Follow these steps for the initial build:&lt;br /&gt;
&lt;br /&gt;
# Change directories to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; repository&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./autogen.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./configure&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;sudo make install&amp;lt;/code&amp;gt;&lt;br /&gt;
# Create a &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; group&lt;br /&gt;
# Create a &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; user&lt;br /&gt;
# Run &amp;lt;code&amp;gt;sudo fmadm configure&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you have done the initial build, most changes shouldn't require more than a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Subsequent Builds==&lt;br /&gt;
Most subsequent builds will just need a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;. See the following paragraphs for caveats.&lt;br /&gt;
&lt;br /&gt;
===When to run autogen.sh===&lt;br /&gt;
The &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; script is currently a shorthand for &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
We recommend that FreeM hackers get used to using &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; instead of running &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt; directly, as &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; may eventually contain other auto-generated items in future.&lt;br /&gt;
&lt;br /&gt;
You will need to run &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; only if you change any &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; files. Even then, a fresh &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; will generally check to see if your generated autoconf/automake files are older than &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; and do this step for you automatically.&lt;br /&gt;
&lt;br /&gt;
===When to run make install===&lt;br /&gt;
You should only need to run &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; in the following scenarios:&lt;br /&gt;
&lt;br /&gt;
* You've changed the way the environment catalog (&amp;lt;code&amp;gt;env.conf&amp;lt;/code&amp;gt;) or environment configuration files (&amp;lt;code&amp;gt;freem.conf&amp;lt;/code&amp;gt;) work&lt;br /&gt;
* You've modified a vendor routine in the &amp;lt;code&amp;gt;mlib/&amp;lt;/code&amp;gt; directory&lt;br /&gt;
* You've modified &amp;lt;code&amp;gt;libfreem&amp;lt;/code&amp;gt; and want to test it from a standard system location&lt;br /&gt;
&lt;br /&gt;
Other than these scenarios, you should be able to run the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;fmadm&amp;lt;/code&amp;gt; binaries out of the repository directory hierarchy.&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(Solaris/Illumos)&amp;diff=401</id>
		<title>Platform Notes (Solaris/Illumos)</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(Solaris/Illumos)&amp;diff=401"/>
		<updated>2025-04-16T00:08:38Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Solaris 8 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Port Category ==&lt;br /&gt;
&lt;br /&gt;
The Solaris port is a [[Tier 1 Port]], and Solaris 8 on 64-bit SPARC is the platform where primary development occurs.&lt;br /&gt;
&lt;br /&gt;
== Verified Releases ==&lt;br /&gt;
* 0.62.3 (Solaris 5.8 sparc64, Solaris 5.10 i86pc, Solaris 5.11 i86pc, Solaris 5.11 sparc64, OpenIndiana Hipster 5.11 amd64, 27 Mar 2025&lt;br /&gt;
* 0.62.2 (Solaris 5.8 sparc64, Solaris 5.10 i86pc, Solaris 5.11 i86pc, Solaris 5.11 sparc64, OpenIndiana Hipster 5.11 amd64, 23 Mar 2025)&lt;br /&gt;
* 0.62.1 (Solaris 5.10 i86pc, 17 Mar 2025)&lt;br /&gt;
* &amp;lt;code&amp;gt;cvs-current&amp;lt;/code&amp;gt; (Solaris 5.8 sparc64, Solaris 11.4 sparc64 and i86pc)&lt;br /&gt;
* 0.62.1 (Solaris 5.8 sparc64, Solaris 11.4 sparc64 and i86pc, OpenIndiana Hipster, 16 Mar 2025)&lt;br /&gt;
* 0.61.2 (Solaris 5.8 sparc64, Solaris 11.4 sparc64 and i86pc)&lt;br /&gt;
* 0.59.0 (Solaris 10 sparc64, 4 Aug 2023)&lt;br /&gt;
* 0.59.0 (Solaris 7 sparc32, 4 Aug 2023)&lt;br /&gt;
* 0.59.0 (Solaris 11.4 i86pc, 4 Aug 2023)&lt;br /&gt;
* 0.57.0 (Solaris 11.3 sparc64, 4 Aug 2023)&lt;br /&gt;
&lt;br /&gt;
== Build Notes ==&lt;br /&gt;
=== Solaris 7 ===&lt;br /&gt;
* If using the old &amp;lt;code&amp;gt;sunfreeware.com&amp;lt;/code&amp;gt; GNU toolchain packages on Solaris 7, you will need the latest &amp;lt;code&amp;gt;7_Recommended.zip&amp;lt;/code&amp;gt; patch cluster.&lt;br /&gt;
* The &amp;lt;code&amp;gt;mktemp&amp;lt;/code&amp;gt; utility may lock up several times during the &amp;lt;code&amp;gt;configure&amp;lt;/code&amp;gt; phase. If this happens, you may simply kill the process with &amp;lt;code&amp;gt;pkill -9 mktemp&amp;lt;/code&amp;gt;. This does not appear to harm the build.&lt;br /&gt;
&lt;br /&gt;
=== Solaris 8 ===&lt;br /&gt;
&lt;br /&gt;
==== Binary Packages ====&lt;br /&gt;
On Solaris 8, you can install a binary release:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo pkgadd -d CLDfreem-&amp;lt;version&amp;gt;-solaris5.8-sparcv9.pkg&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once this is done, add yourself to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; group:&lt;br /&gt;
# Open &amp;lt;code&amp;gt;/etc/group&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; in your favorite text editor&lt;br /&gt;
# Find the line beginning with &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt;&lt;br /&gt;
# Append your username to the end of that line&lt;br /&gt;
# Save the file&lt;br /&gt;
# Exit the editor&lt;br /&gt;
&lt;br /&gt;
Now, you can start the FreeM daemon as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo /etc/init.d/freem start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Building From Source ====&lt;br /&gt;
You will need the latest &amp;lt;code&amp;gt;8_Recommended.zip&amp;lt;/code&amp;gt; patch cluster for Solaris, as well as:&lt;br /&gt;
&lt;br /&gt;
* gcc (3.4 or higher recommended)&lt;br /&gt;
* autoconf&lt;br /&gt;
* automake&lt;br /&gt;
* libtool&lt;br /&gt;
* texinfo&lt;br /&gt;
* readline (recommended but not strictly required)&lt;br /&gt;
&lt;br /&gt;
=== Solaris 9 ===&lt;br /&gt;
TBD&lt;br /&gt;
&lt;br /&gt;
=== Solaris 10 ===&lt;br /&gt;
TBD&lt;br /&gt;
&lt;br /&gt;
=== Solaris 11 ===&lt;br /&gt;
We build with the IPS packages for the GNU toolchain here. The Sun C compiler can also be used here (at least the version from Developer Studio 12.6).&lt;br /&gt;
&lt;br /&gt;
==== Necessary Packages ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
$ sudo pkg install gcc automake autoconf gnu-make git readline libtool texinfo ncurses&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Dealing with ncurses ====&lt;br /&gt;
You will need to tell the configure script not to bother with the wide-character ncurses library (does not apply to releases later than 0.61.2):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
$ ./configure --without-ncursesw&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== OpenIndiana ===&lt;br /&gt;
==== Binary Packages ====&lt;br /&gt;
On OpenIndiana, you can install a binary release:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo pkgadd -d CLDfreem-&amp;lt;version&amp;gt;-openindiana5.11-amd64.pkg&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once this is done, add yourself to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; group, and start the FreeM daemon as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo /etc/init.d/freem start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==== Building From Source ====&lt;br /&gt;
See instructions for [[#Solaris 11|Solaris 11]], but with the exception that &amp;lt;code&amp;gt;configure&amp;lt;/code&amp;gt; must be run as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./configure MAKE=gmake&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing Details ==&lt;br /&gt;
&lt;br /&gt;
We build and test the Solaris port of FreeM on the following systems:&lt;br /&gt;
&lt;br /&gt;
=== Sun Ultra 10 ===&lt;br /&gt;
&lt;br /&gt;
* Sun Ultra 10 with a 400MHz UltraSPARC-IIi CPU (64-bit)&lt;br /&gt;
* 640MB RAM&lt;br /&gt;
* Solaris 5.8 Generic_117350-39&lt;br /&gt;
* gcc v3.4.6&lt;br /&gt;
* autoconf 2.69&lt;br /&gt;
* automake 1.16.5&lt;br /&gt;
&lt;br /&gt;
=== Sun SPARCserver 20 ===&lt;br /&gt;
&lt;br /&gt;
* Sun SPARCserver 20 with dual 100MHz Ross HyperSPARC CPUs (32-bit)&lt;br /&gt;
* 512MB RAM&lt;br /&gt;
* Solaris 7 with the latest 7_Recommended.zip patch cluster applied (REQUIRED FOR SOLARIS 7)&lt;br /&gt;
* gcc v3.4.6&lt;br /&gt;
* autoconf 2.68&lt;br /&gt;
* automake 1.11.1&lt;br /&gt;
&lt;br /&gt;
=== SunFire T2000 ===&lt;br /&gt;
&lt;br /&gt;
* Sun UltraSPARC T1 CPU (64-bit)&lt;br /&gt;
* Solaris 10&lt;br /&gt;
&lt;br /&gt;
=== Oracle SPARC T4-1 ===&lt;br /&gt;
* Oracle SPARC T4 CPU (64-bit)&lt;br /&gt;
* Solaris 11.4 11.4.0.15.0&lt;br /&gt;
* gcc v7.3.0&lt;br /&gt;
* autoconf 2.69&lt;br /&gt;
* automake 1.15&lt;br /&gt;
* Oracle Developer Studio 12.6 (SunCC compiler)&lt;br /&gt;
&lt;br /&gt;
=== x86 VM ===&lt;br /&gt;
* Solaris 11.4 11.4.0.15.0&lt;br /&gt;
* gcc v7.3.0&lt;br /&gt;
* autoconf 2.69&lt;br /&gt;
* automake 1.15&lt;br /&gt;
&lt;br /&gt;
=== OpenIndiana (Illumos) ===&lt;br /&gt;
&lt;br /&gt;
* Proxmox VM&lt;br /&gt;
* OpenIndiana Hipster 5.11 illumos-053feb1540&lt;br /&gt;
* gcc 14.2.0&lt;br /&gt;
* autoconf 2.72&lt;br /&gt;
* automake 1.16.5&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This port should theoretically run on any Solaris or Illumos machine running Solaris 7 or newer.&lt;br /&gt;
&lt;br /&gt;
== Required Kernel Tuning ==&lt;br /&gt;
&lt;br /&gt;
=== Solaris 11 ===&lt;br /&gt;
TBD&lt;br /&gt;
&lt;br /&gt;
=== Solaris 8 ===&lt;br /&gt;
Append the following to &amp;lt;code&amp;gt;/etc/system&amp;lt;/code&amp;gt; and reboot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set shmsys:shminfo_shmmax = 67108864                           &lt;br /&gt;
set shmsys:shminfo_shmmni = 0x1000&lt;br /&gt;
set shmsys:shminfo_shmseg = 0x100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Starting FreeM Daemon Automatically ==&lt;br /&gt;
&lt;br /&gt;
These instructions apply only to source builds. The binary packages install the init script automatically.&lt;br /&gt;
&lt;br /&gt;
* Copy &amp;lt;code&amp;gt;scripts/solaris-init/freem&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/etc/init.d&amp;lt;/code&amp;gt;&lt;br /&gt;
* Make a symbolic link from &amp;lt;code&amp;gt;/etc/rc3.d/S20freem&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/etc/init.d/freem&amp;lt;/code&amp;gt;&lt;br /&gt;
* Run &amp;lt;code&amp;gt;/etc/init.d/freem start&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Tier 1 Ports]]&lt;br /&gt;
[[Category:Platform Notes]]&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(FreeBSD)&amp;diff=400</id>
		<title>Platform Notes (FreeBSD)</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(FreeBSD)&amp;diff=400"/>
		<updated>2025-04-16T00:00:53Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Address Space Layout Randomization */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Port Status ==&lt;br /&gt;
FreeBSD is a [[Tier 1 Port]]&lt;br /&gt;
&lt;br /&gt;
== Verified Releases ==&lt;br /&gt;
* FreeM 0.62.3 (27 Mar 2025)&lt;br /&gt;
* FreeM 0.62.2 (23 Mar 2025)&lt;br /&gt;
* FreeM &amp;lt;code&amp;gt;cvs-current&amp;lt;/code&amp;gt;&lt;br /&gt;
* FreeM 0.62.1&lt;br /&gt;
&lt;br /&gt;
== Testing Details ==&lt;br /&gt;
* Bare-metal amd64 system&lt;br /&gt;
* FreeBSD 14.1-RELEASE-p2 amd64&lt;br /&gt;
* gcc 13.2.0&lt;br /&gt;
* autoconf 2.72&lt;br /&gt;
* automake 1.17&lt;br /&gt;
&lt;br /&gt;
== Required Kernel Tuning ==&lt;br /&gt;
=== Shared Memory ===&lt;br /&gt;
FreeM in its default configuration requires just under 17MiB of shared memory. You can check the relevant kernel parameter with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo sysctl kern.ipc.shmmax&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;code&amp;gt;kern.ipc.shmmax&amp;lt;/code&amp;gt; is less than &amp;lt;code&amp;gt;17000000&amp;lt;/code&amp;gt;, add the following lines to &amp;lt;code&amp;gt;/etc/sysctl.conf&amp;lt;/code&amp;gt; and reboot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
kern.ipc.shmmax=17000000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Address Space Layout Randomization ===&lt;br /&gt;
FreeM is incompatible with address space layout randomization (ASLR), which is enabled by default on FreeBSD 13.2 and newer on 64-bit platforms.&lt;br /&gt;
&lt;br /&gt;
To use FreeM on FreeBSD 13.2 and newer, add the following lines to &amp;lt;code&amp;gt;/etc/sysctl.conf&amp;lt;/code&amp;gt; and reboot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
kern.elf64.aslr.pie_enable=0&lt;br /&gt;
kern.elf64.aslr.enable=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do not wish to globally disable ASLR on your system, you can use FreeM by disabling it per-process with each invocation by using the following syntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ proccontrol -m aslr -s disable freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Particularly astute system administrators will likely want to script this, which is an exercise left to the reader.&lt;br /&gt;
&lt;br /&gt;
== Starting Daemon Automatically ==&lt;br /&gt;
* Copy &amp;lt;code&amp;gt;scripts/freebsd-rc/freem&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/usr/local/etc/rc.d&amp;lt;/code&amp;gt;&lt;br /&gt;
* Type the following commands with root privileges:&lt;br /&gt;
 # pw group add freem&lt;br /&gt;
 # pw user add freem -m -g freem&lt;br /&gt;
 # sysrc freem_enable=&amp;quot;YES&amp;quot;&lt;br /&gt;
 # chmod +x /usr/local/etc/rc.d/freem&lt;br /&gt;
* For each user who needs to run FreeM, type the following command:&lt;br /&gt;
 # pw group mod freem -m ''username''&lt;br /&gt;
* Reboot &lt;br /&gt;
&lt;br /&gt;
== Port Challenges ==&lt;br /&gt;
None.&lt;br /&gt;
&lt;br /&gt;
[[Category:Tier 1 Ports]]&lt;br /&gt;
[[Category:Platform Notes]]&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(FreeBSD)&amp;diff=399</id>
		<title>Platform Notes (FreeBSD)</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(FreeBSD)&amp;diff=399"/>
		<updated>2025-04-15T23:58:22Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Address Space Layout Randomization */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Port Status ==&lt;br /&gt;
FreeBSD is a [[Tier 1 Port]]&lt;br /&gt;
&lt;br /&gt;
== Verified Releases ==&lt;br /&gt;
* FreeM 0.62.3 (27 Mar 2025)&lt;br /&gt;
* FreeM 0.62.2 (23 Mar 2025)&lt;br /&gt;
* FreeM &amp;lt;code&amp;gt;cvs-current&amp;lt;/code&amp;gt;&lt;br /&gt;
* FreeM 0.62.1&lt;br /&gt;
&lt;br /&gt;
== Testing Details ==&lt;br /&gt;
* Bare-metal amd64 system&lt;br /&gt;
* FreeBSD 14.1-RELEASE-p2 amd64&lt;br /&gt;
* gcc 13.2.0&lt;br /&gt;
* autoconf 2.72&lt;br /&gt;
* automake 1.17&lt;br /&gt;
&lt;br /&gt;
== Required Kernel Tuning ==&lt;br /&gt;
=== Shared Memory ===&lt;br /&gt;
FreeM in its default configuration requires just under 17MiB of shared memory. You can check the relevant kernel parameter with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo sysctl kern.ipc.shmmax&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;code&amp;gt;kern.ipc.shmmax&amp;lt;/code&amp;gt; is less than &amp;lt;code&amp;gt;17000000&amp;lt;/code&amp;gt;, add the following lines to &amp;lt;code&amp;gt;/etc/sysctl.conf&amp;lt;/code&amp;gt; and reboot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
kern.ipc.shmmax=17000000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Address Space Layout Randomization ===&lt;br /&gt;
FreeM is incompatible with address space layout randomization (ASLR), which is enabled by default on FreeBSD 13.2 and newer on 64-bit platforms.&lt;br /&gt;
&lt;br /&gt;
To use FreeM on FreeBSD 13.2 and newer, add the following lines to &amp;lt;code&amp;gt;/etc/sysctl.conf&amp;lt;/code&amp;gt; and reboot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
kern.elf64.aslr.pie_enable=0&lt;br /&gt;
kern.elf64.aslr.enable=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do not wish to globally disable ASLR on your system, you can use FreeM by disabling it per-process with each invocation by using the following syntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ proccontrol -m aslr -s disable freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Starting Daemon Automatically ==&lt;br /&gt;
* Copy &amp;lt;code&amp;gt;scripts/freebsd-rc/freem&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/usr/local/etc/rc.d&amp;lt;/code&amp;gt;&lt;br /&gt;
* Type the following commands with root privileges:&lt;br /&gt;
 # pw group add freem&lt;br /&gt;
 # pw user add freem -m -g freem&lt;br /&gt;
 # sysrc freem_enable=&amp;quot;YES&amp;quot;&lt;br /&gt;
 # chmod +x /usr/local/etc/rc.d/freem&lt;br /&gt;
* For each user who needs to run FreeM, type the following command:&lt;br /&gt;
 # pw group mod freem -m ''username''&lt;br /&gt;
* Reboot &lt;br /&gt;
&lt;br /&gt;
== Port Challenges ==&lt;br /&gt;
None.&lt;br /&gt;
&lt;br /&gt;
[[Category:Tier 1 Ports]]&lt;br /&gt;
[[Category:Platform Notes]]&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(FreeBSD)&amp;diff=398</id>
		<title>Platform Notes (FreeBSD)</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(FreeBSD)&amp;diff=398"/>
		<updated>2025-04-15T23:57:36Z</updated>

		<summary type="html">&lt;p&gt;Smw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Port Status ==&lt;br /&gt;
FreeBSD is a [[Tier 1 Port]]&lt;br /&gt;
&lt;br /&gt;
== Verified Releases ==&lt;br /&gt;
* FreeM 0.62.3 (27 Mar 2025)&lt;br /&gt;
* FreeM 0.62.2 (23 Mar 2025)&lt;br /&gt;
* FreeM &amp;lt;code&amp;gt;cvs-current&amp;lt;/code&amp;gt;&lt;br /&gt;
* FreeM 0.62.1&lt;br /&gt;
&lt;br /&gt;
== Testing Details ==&lt;br /&gt;
* Bare-metal amd64 system&lt;br /&gt;
* FreeBSD 14.1-RELEASE-p2 amd64&lt;br /&gt;
* gcc 13.2.0&lt;br /&gt;
* autoconf 2.72&lt;br /&gt;
* automake 1.17&lt;br /&gt;
&lt;br /&gt;
== Required Kernel Tuning ==&lt;br /&gt;
=== Shared Memory ===&lt;br /&gt;
FreeM in its default configuration requires just under 17MiB of shared memory. You can check the relevant kernel parameter with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo sysctl kern.ipc.shmmax&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;code&amp;gt;kern.ipc.shmmax&amp;lt;/code&amp;gt; is less than &amp;lt;code&amp;gt;17000000&amp;lt;/code&amp;gt;, add the following lines to &amp;lt;code&amp;gt;/etc/sysctl.conf&amp;lt;/code&amp;gt; and reboot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
kern.ipc.shmmax=17000000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Address Space Layout Randomization ===&lt;br /&gt;
FreeM is incompatible with address space layout randomization (ASLR), which is enabled by default on FreeBSD 13.2 and newer on 64-bit platforms.&lt;br /&gt;
&lt;br /&gt;
To use FreeM on FreeBSD 13 and newer, add the following lines to &amp;lt;code&amp;gt;/etc/sysctl.conf&amp;lt;/code&amp;gt; and reboot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
kern.elf64.aslr.pie_enable=0&lt;br /&gt;
kern.elf64.aslr.enable=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do not wish to globally disable ASLR on your system, you can use FreeM by disabling it per-process with each invocation by using the following syntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ proccontrol -m aslr -s disable freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Starting Daemon Automatically ==&lt;br /&gt;
* Copy &amp;lt;code&amp;gt;scripts/freebsd-rc/freem&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/usr/local/etc/rc.d&amp;lt;/code&amp;gt;&lt;br /&gt;
* Type the following commands with root privileges:&lt;br /&gt;
 # pw group add freem&lt;br /&gt;
 # pw user add freem -m -g freem&lt;br /&gt;
 # sysrc freem_enable=&amp;quot;YES&amp;quot;&lt;br /&gt;
 # chmod +x /usr/local/etc/rc.d/freem&lt;br /&gt;
* For each user who needs to run FreeM, type the following command:&lt;br /&gt;
 # pw group mod freem -m ''username''&lt;br /&gt;
* Reboot &lt;br /&gt;
&lt;br /&gt;
== Port Challenges ==&lt;br /&gt;
None.&lt;br /&gt;
&lt;br /&gt;
[[Category:Tier 1 Ports]]&lt;br /&gt;
[[Category:Platform Notes]]&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(FreeBSD)&amp;diff=397</id>
		<title>Platform Notes (FreeBSD)</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(FreeBSD)&amp;diff=397"/>
		<updated>2025-04-15T23:53:55Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Address Space Layout Randomization */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Port Status ==&lt;br /&gt;
FreeBSD is a [[Tier 1 Port]]&lt;br /&gt;
&lt;br /&gt;
== Verified Releases ==&lt;br /&gt;
* FreeM 0.62.3 (27 Mar 2025)&lt;br /&gt;
* FreeM 0.62.2 (23 Mar 2025)&lt;br /&gt;
* FreeM &amp;lt;code&amp;gt;cvs-current&amp;lt;/code&amp;gt;&lt;br /&gt;
* FreeM 0.62.1&lt;br /&gt;
&lt;br /&gt;
== Testing Details ==&lt;br /&gt;
* Bare-metal amd64 system&lt;br /&gt;
* FreeBSD 14.1-RELEASE-p2 amd64&lt;br /&gt;
* gcc 13.2.0&lt;br /&gt;
* autoconf 2.72&lt;br /&gt;
* automake 1.17&lt;br /&gt;
&lt;br /&gt;
== Required Kernel Tuning ==&lt;br /&gt;
&lt;br /&gt;
=== Address Space Layout Randomization ===&lt;br /&gt;
FreeM is incompatible with address space layout randomization (ASLR), which is enabled by default on FreeBSD 13.2 and newer on 64-bit platforms.&lt;br /&gt;
&lt;br /&gt;
To use FreeM on FreeBSD 13 and newer, add the following lines to &amp;lt;code&amp;gt;/etc/sysctl.conf&amp;lt;/code&amp;gt; and reboot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
kern.elf64.aslr.pie_enable=0&lt;br /&gt;
kern.elf64.aslr.enable=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do not wish to globally disable ASLR on your system, you can use FreeM by disabling it per-process with each invocation by using the following syntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ proccontrol -m aslr -s disable freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Starting Daemon Automatically ==&lt;br /&gt;
* Copy &amp;lt;code&amp;gt;scripts/freebsd-rc/freem&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/usr/local/etc/rc.d&amp;lt;/code&amp;gt;&lt;br /&gt;
* Type the following commands with root privileges:&lt;br /&gt;
 # pw group add freem&lt;br /&gt;
 # pw user add freem -m -g freem&lt;br /&gt;
 # sysrc freem_enable=&amp;quot;YES&amp;quot;&lt;br /&gt;
 # chmod +x /usr/local/etc/rc.d/freem&lt;br /&gt;
* For each user who needs to run FreeM, type the following command:&lt;br /&gt;
 # pw group mod freem -m ''username''&lt;br /&gt;
* Reboot &lt;br /&gt;
&lt;br /&gt;
== Port Challenges ==&lt;br /&gt;
None.&lt;br /&gt;
&lt;br /&gt;
[[Category:Tier 1 Ports]]&lt;br /&gt;
[[Category:Platform Notes]]&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(FreeBSD)&amp;diff=396</id>
		<title>Platform Notes (FreeBSD)</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(FreeBSD)&amp;diff=396"/>
		<updated>2025-04-15T23:52:36Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Required Kernel Tuning */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Port Status ==&lt;br /&gt;
FreeBSD is a [[Tier 1 Port]]&lt;br /&gt;
&lt;br /&gt;
== Verified Releases ==&lt;br /&gt;
* FreeM 0.62.3 (27 Mar 2025)&lt;br /&gt;
* FreeM 0.62.2 (23 Mar 2025)&lt;br /&gt;
* FreeM &amp;lt;code&amp;gt;cvs-current&amp;lt;/code&amp;gt;&lt;br /&gt;
* FreeM 0.62.1&lt;br /&gt;
&lt;br /&gt;
== Testing Details ==&lt;br /&gt;
* Bare-metal amd64 system&lt;br /&gt;
* FreeBSD 14.1-RELEASE-p2 amd64&lt;br /&gt;
* gcc 13.2.0&lt;br /&gt;
* autoconf 2.72&lt;br /&gt;
* automake 1.17&lt;br /&gt;
&lt;br /&gt;
== Required Kernel Tuning ==&lt;br /&gt;
&lt;br /&gt;
=== Address Space Layout Randomization ===&lt;br /&gt;
FreeM shared memory is incompatible with address space layout randomization on FreeBSD 13 and newer.&lt;br /&gt;
&lt;br /&gt;
To use FreeM on FreeBSD 13 and newer, add the following lines to &amp;lt;code&amp;gt;/etc/sysctl.conf&amp;lt;/code&amp;gt; and reboot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
kern.elf64.aslr.pie_enable=0&lt;br /&gt;
kern.elf64.aslr.enable=0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you do not wish to globally disable ASLR on your system, you can use FreeM by disabling it per-process with each invocation by using the following syntax:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ proccontrol -m aslr -s disable freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Starting Daemon Automatically ==&lt;br /&gt;
* Copy &amp;lt;code&amp;gt;scripts/freebsd-rc/freem&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/usr/local/etc/rc.d&amp;lt;/code&amp;gt;&lt;br /&gt;
* Type the following commands with root privileges:&lt;br /&gt;
 # pw group add freem&lt;br /&gt;
 # pw user add freem -m -g freem&lt;br /&gt;
 # sysrc freem_enable=&amp;quot;YES&amp;quot;&lt;br /&gt;
 # chmod +x /usr/local/etc/rc.d/freem&lt;br /&gt;
* For each user who needs to run FreeM, type the following command:&lt;br /&gt;
 # pw group mod freem -m ''username''&lt;br /&gt;
* Reboot &lt;br /&gt;
&lt;br /&gt;
== Port Challenges ==&lt;br /&gt;
None.&lt;br /&gt;
&lt;br /&gt;
[[Category:Tier 1 Ports]]&lt;br /&gt;
[[Category:Platform Notes]]&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(OS/2)&amp;diff=395</id>
		<title>Platform Notes (OS/2)</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(OS/2)&amp;diff=395"/>
		<updated>2025-04-10T16:56:16Z</updated>

		<summary type="html">&lt;p&gt;Smw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Port Status ==&lt;br /&gt;
OS/2 is a [[Tier 2 Port]]&lt;br /&gt;
&lt;br /&gt;
== Verified Releases ==&lt;br /&gt;
* FreeM 0.64.0-rc0 (10 Apr 2025)&lt;br /&gt;
* FreeM 0.62.3 (27 Mar 2025)&lt;br /&gt;
* FreeM cvs-current (23 Mar 2025)&lt;br /&gt;
&lt;br /&gt;
== Testing Details ==&lt;br /&gt;
We build and test the OS/2 port on an ArcaOS 5.1 VM running in VirtualBox.&lt;br /&gt;
&lt;br /&gt;
== Building and Installing ==&lt;br /&gt;
Currently, the OS/2 port is only tested on ArcaOS, and you will need to install several things in order to build and run:&lt;br /&gt;
&lt;br /&gt;
* autoconf&lt;br /&gt;
* automake&lt;br /&gt;
* gcc&lt;br /&gt;
* readline-devel&lt;br /&gt;
* bash&lt;br /&gt;
* binutils-devel&lt;br /&gt;
* coreutils&lt;br /&gt;
* emxrt&lt;br /&gt;
* gawk&lt;br /&gt;
* gcc-wlink&lt;br /&gt;
* gcc-wrt&lt;br /&gt;
* grep&lt;br /&gt;
* info&lt;br /&gt;
* libc-devel&lt;br /&gt;
* libtool&lt;br /&gt;
* kbuild-make&lt;br /&gt;
* sed&lt;br /&gt;
* tar&lt;br /&gt;
* gzip&lt;br /&gt;
&lt;br /&gt;
All of these can be installed with &amp;lt;code&amp;gt;yum install&amp;lt;/code&amp;gt; or the Arca Noae Package Manager (ANPM).&lt;br /&gt;
&lt;br /&gt;
Once the dependencies are met, simply download and extract the FreeM source code, and follow these steps:&lt;br /&gt;
&lt;br /&gt;
* Open an OS/2 Window (in the Command Prompts folder in OS/2 System or Computer on the desktop)&lt;br /&gt;
* Run the following commands:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[C:\] bash&lt;br /&gt;
$ export EMXOMFLD_TYPE=WLINK&lt;br /&gt;
$ export EMXOMFLD_LINKER=wl.exe&lt;br /&gt;
$ ./autogen.sh  # only needed if installing from the CVS repo&lt;br /&gt;
$ ./configure&lt;br /&gt;
$ make install&lt;br /&gt;
$ fmadm configure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once this is done, proceed to the next section.&lt;br /&gt;
&lt;br /&gt;
== Workarounds ==&lt;br /&gt;
Under OS/2 and ArcaOS, FreeM binaries are installed under &amp;lt;code&amp;gt;C:\USR\LOCAL\BIN&amp;lt;/code&amp;gt;, but the FreeM daemon and the FreeM interpreter cannot be launched from the same executable (the daemon will start, but interpreters will give an error resembling &amp;lt;code&amp;gt;Resource busy&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;fmadm configure&amp;lt;/code&amp;gt; (and &amp;lt;code&amp;gt;fmadm reconfigure&amp;lt;/code&amp;gt;) commands will automatically copy &amp;lt;code&amp;gt;C:\USR\LOCAL\BIN\freem.exe&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;C:\USR\LOCAL\BIN\freemd.exe&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Running ==&lt;br /&gt;
# Open an OS/2 Window command prompt&lt;br /&gt;
# Run &amp;lt;code&amp;gt;bash&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;/usr/local/bin/freemd -dk&amp;lt;/code&amp;gt; to start the FreeM daemon&lt;br /&gt;
# Minimize the FreeM daemon process&lt;br /&gt;
# Open a second OS/2 Window command prompt&lt;br /&gt;
# Run the following commands:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[C:\] CD \USR\LOCAL\BIN&lt;br /&gt;
[C:\USR\LOCAL\BIN] FREEM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Platform Limitations ==&lt;br /&gt;
* Only one interpreter instance can be launched at a time&lt;br /&gt;
* &amp;lt;code&amp;gt;JOB&amp;lt;/code&amp;gt; does not work&lt;br /&gt;
* Terminal windows are fixed in size to 80x24&lt;br /&gt;
* The FreeM daemon must be launched in the foreground, as &amp;lt;code&amp;gt;fork()&amp;lt;/code&amp;gt; is unsupported here (&amp;lt;code&amp;gt;freemd.exe&amp;lt;/code&amp;gt; will refuse to launch if you do not pass the &amp;lt;code&amp;gt;-k&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;--nofork&amp;lt;/code&amp;gt; flags).&lt;br /&gt;
* Network sockets functionality is unavailable&lt;br /&gt;
* Building without &amp;lt;code&amp;gt;readline&amp;lt;/code&amp;gt; causes direct mode to echo each line of code entered&lt;br /&gt;
* No binary package is available: once we have an RPM package for Red Hat-derived distributions, an OS/2 RPM should be fairly straightforward&lt;br /&gt;
&lt;br /&gt;
Documentation for porting UNIX applications to OS/2 is scant, which makes many of these issues difficult to work around. However, we do want to iron out all of these shortcomings and promote this port to Tier 1 status.&lt;br /&gt;
&lt;br /&gt;
== Required Kernel Tuning ==&lt;br /&gt;
Coming soon.&lt;br /&gt;
&lt;br /&gt;
[[Category: Tier 2 Ports]]&lt;br /&gt;
[[Category: Platform Notes]]&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(OS/2)&amp;diff=394</id>
		<title>Platform Notes (OS/2)</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(OS/2)&amp;diff=394"/>
		<updated>2025-04-10T16:52:32Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Building and Installing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DevBranchFeature}}&lt;br /&gt;
&lt;br /&gt;
== Port Status ==&lt;br /&gt;
OS/2 is a [[Tier 2 Port]]&lt;br /&gt;
&lt;br /&gt;
== Verified Releases ==&lt;br /&gt;
* FreeM 0.62.3 (27 Mar 2025)&lt;br /&gt;
* FreeM cvs-current (23 Mar 2025)&lt;br /&gt;
&lt;br /&gt;
== Testing Details ==&lt;br /&gt;
We build and test the OS/2 port on an ArcaOS 5.1 VM running in VirtualBox.&lt;br /&gt;
&lt;br /&gt;
== Building and Installing ==&lt;br /&gt;
Currently, the OS/2 port is only tested on ArcaOS, and you will need to install several things in order to build and run:&lt;br /&gt;
&lt;br /&gt;
* autoconf&lt;br /&gt;
* automake&lt;br /&gt;
* gcc&lt;br /&gt;
* readline-devel&lt;br /&gt;
* bash&lt;br /&gt;
* binutils-devel&lt;br /&gt;
* coreutils&lt;br /&gt;
* emxrt&lt;br /&gt;
* gawk&lt;br /&gt;
* gcc-wlink&lt;br /&gt;
* gcc-wrt&lt;br /&gt;
* grep&lt;br /&gt;
* info&lt;br /&gt;
* libc-devel&lt;br /&gt;
* libtool&lt;br /&gt;
* kbuild-make&lt;br /&gt;
* sed&lt;br /&gt;
* tar&lt;br /&gt;
* gzip&lt;br /&gt;
&lt;br /&gt;
All of these can be installed with &amp;lt;code&amp;gt;yum install&amp;lt;/code&amp;gt; or the Arca Noae Package Manager (ANPM).&lt;br /&gt;
&lt;br /&gt;
Once the dependencies are met, simply download and extract the FreeM source code, and follow these steps:&lt;br /&gt;
&lt;br /&gt;
* Open an OS/2 Window (in the Command Prompts folder in OS/2 System or Computer on the desktop)&lt;br /&gt;
* Run the following commands:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[C:\] bash&lt;br /&gt;
$ export EMXOMFLD_TYPE=WLINK&lt;br /&gt;
$ export EMXOMFLD_LINKER=wl.exe&lt;br /&gt;
$ ./autogen.sh  # only needed if installing from the CVS repo&lt;br /&gt;
$ ./configure&lt;br /&gt;
$ make install&lt;br /&gt;
$ fmadm configure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once this is done, proceed to the next section.&lt;br /&gt;
&lt;br /&gt;
== Workarounds ==&lt;br /&gt;
Under OS/2 and ArcaOS, FreeM binaries are installed under &amp;lt;code&amp;gt;C:\USR\LOCAL\BIN&amp;lt;/code&amp;gt;, but the FreeM daemon and the FreeM interpreter cannot be launched from the same executable (the daemon will start, but interpreters will give an error resembling &amp;lt;code&amp;gt;Resource busy&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;fmadm configure&amp;lt;/code&amp;gt; (and &amp;lt;code&amp;gt;fmadm reconfigure&amp;lt;/code&amp;gt;) commands will automatically copy &amp;lt;code&amp;gt;C:\USR\LOCAL\BIN\freem.exe&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;C:\USR\LOCAL\BIN\freemd.exe&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Running ==&lt;br /&gt;
# Open an OS/2 Window command prompt&lt;br /&gt;
# Run &amp;lt;code&amp;gt;bash&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;/usr/local/bin/freemd -dk&amp;lt;/code&amp;gt; to start the FreeM daemon&lt;br /&gt;
# Minimize the FreeM daemon process&lt;br /&gt;
# Open a second OS/2 Window command prompt&lt;br /&gt;
# Run the following commands:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[C:\] CD \USR\LOCAL\BIN&lt;br /&gt;
[C:\USR\LOCAL\BIN] FREEM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Platform Limitations ==&lt;br /&gt;
* Only one interpreter instance can be launched at a time&lt;br /&gt;
* &amp;lt;code&amp;gt;JOB&amp;lt;/code&amp;gt; does not work&lt;br /&gt;
* Terminal windows are fixed in size to 80x24&lt;br /&gt;
* The FreeM daemon must be launched in the foreground, as &amp;lt;code&amp;gt;fork()&amp;lt;/code&amp;gt; is unsupported here (&amp;lt;code&amp;gt;freemd.exe&amp;lt;/code&amp;gt; will refuse to launch if you do not pass the &amp;lt;code&amp;gt;-k&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;--nofork&amp;lt;/code&amp;gt; flags).&lt;br /&gt;
* Network sockets functionality is unavailable&lt;br /&gt;
* Building without &amp;lt;code&amp;gt;readline&amp;lt;/code&amp;gt; causes direct mode to echo each line of code entered&lt;br /&gt;
* No binary package is available: once we have an RPM package for Red Hat-derived distributions, an OS/2 RPM should be fairly straightforward&lt;br /&gt;
&lt;br /&gt;
Documentation for porting UNIX applications to OS/2 is scant, which makes many of these issues difficult to work around. However, we do want to iron out all of these shortcomings and promote this port to Tier 1 status.&lt;br /&gt;
&lt;br /&gt;
== Required Kernel Tuning ==&lt;br /&gt;
Coming soon.&lt;br /&gt;
&lt;br /&gt;
[[Category: Tier 2 Ports]]&lt;br /&gt;
[[Category: Platform Notes]]&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=393</id>
		<title>Contributor Guide</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=393"/>
		<updated>2025-04-05T22:32:46Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* C Standard */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
This article describes the facilities, methods, and commands used to contribute to the FreeM project.&lt;br /&gt;
&lt;br /&gt;
=For All Developers=&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
In order to contribute to FreeM, you must agree to abide by both the [[Code of Conduct]] and the [[General Policies]]. Your code must also conform to the style standards laid out in Appendix F of [https://freem.coherent-logic.com/docs/0.61.2/freem.html The FreeM Manual].&lt;br /&gt;
&lt;br /&gt;
You will also need to have &amp;lt;code&amp;gt;cvs&amp;lt;/code&amp;gt; installed on your machine. This is available in the package repositories of all popular Linux and UNIX operating systems.&lt;br /&gt;
&lt;br /&gt;
==Language==&lt;br /&gt;
All contributions to FreeM proper must be written in C. Bourne shell scripts are permissible where appropriate, and of course M code for the &amp;lt;code&amp;gt;mlib&amp;lt;/code&amp;gt; routines.&lt;br /&gt;
&lt;br /&gt;
===C Standard===&lt;br /&gt;
* FreeM contributions must not use language features unavailable in C89&lt;br /&gt;
* Vendor extensions in C compilers (like GNU extensions) are only permitted if guarded by preprocessor macros, and should be avoided if possible&lt;br /&gt;
* Contributions should be backwards compatible with gcc 2.95.3 (the oldest compiler we support)&lt;br /&gt;
* Contributions should not break compiles on Sun &amp;lt;code&amp;gt;cc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;clang&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the last two guidelines, FreeM core developers will test your contributions and work with you to address any incompatibilities with these older compilers. We do not require every contributor to have access to every compiler.&lt;br /&gt;
&lt;br /&gt;
===Autotools===&lt;br /&gt;
* Contributions to &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; configuration must not use &amp;lt;code&amp;gt;pkg-config&amp;lt;/code&amp;gt;, as it is unavailable on some of our target platforms&lt;br /&gt;
* Target &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; 2.54 and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; 1.7.1 for compatibility&lt;br /&gt;
&lt;br /&gt;
=Anonymous CVS Access=&lt;br /&gt;
&lt;br /&gt;
==Getting Source Code from CVS==&lt;br /&gt;
To fetch the latest FreeM source code from CVS, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
To update a previously-fetched copy of FreeM source code, go into the directory in which FreeM is located, and run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Submitting Changes Without CVS Write Access==&lt;br /&gt;
To submit a change to FreeM as an anonymous user (i.e., a user without writer access to the FreeM CVS repository), generate a &amp;lt;code&amp;gt;.patch&amp;lt;/code&amp;gt; file using the &amp;lt;code&amp;gt;diff&amp;lt;/code&amp;gt; utility, and send it to &amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt; (you must be subscribed to the mailing list), along with a description containing the following information:&lt;br /&gt;
&lt;br /&gt;
* What bug your patch fixes, or feature it implements&lt;br /&gt;
* Your full preferred name (this will be used in order to credit you for your work)&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
&lt;br /&gt;
Each patch should address no more than one bug fix or feature addition. Patches that do not comply with this requirement will be kicked back to the developer for revision.&lt;br /&gt;
&lt;br /&gt;
=CVS Writer Access=&lt;br /&gt;
&lt;br /&gt;
==Requesting Writer Access==&lt;br /&gt;
&lt;br /&gt;
In order to get CVS writer access, you will need to have either a track record of submitting good patches, or be an existing member of the core team. If you meet this criteria, please send a request to &lt;br /&gt;
&amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt;, including the following information:&lt;br /&gt;
&lt;br /&gt;
* Your full preferred name&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
* The username you would like to use for access to our CVS server (we will do our best to accommodate, but you may be required to choose a different username if your preferred username is already taken)&lt;br /&gt;
&lt;br /&gt;
==Configuring CVS==&lt;br /&gt;
&lt;br /&gt;
Once the below changes are made, you will need to log out and log back in to make them take effect.&lt;br /&gt;
&lt;br /&gt;
===Bourne-Again Shell (bash)===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.bashrc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;~/.bash_profile&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export CVS_RSH=/usr/bin/ssh&lt;br /&gt;
export CVSROOT=:ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also need to change the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; value to the correct absolute path to your &amp;lt;code&amp;gt;ssh&amp;lt;/code&amp;gt; binary. You can find this information using &amp;lt;code&amp;gt;which ssh&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===C Shell===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.cshrc&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setenv CVS_RSH /usr/bin/ssh&lt;br /&gt;
setenv CVSROOT :ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Fetching FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
To fetch the latest FreeM source code for the first time, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this fails, make sure you have the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CVSROOT&amp;lt;/code&amp;gt; environment variables correctly configured.&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
In the directory containing the FreeM source code, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Adding Files to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands from the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory, substituting the path and filename (relative to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory) for &amp;lt;code&amp;gt;&amp;amp;lt;filename&amp;amp;gt;&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs add &amp;lt;filename&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Committing Changes and Pushing to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands ''from the parent directory of the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory'', replacing &amp;lt;code&amp;gt;commit-message&amp;lt;/code&amp;gt; with a message describing the change:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs ci -m &amp;quot;commit-message&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Building FreeM=&lt;br /&gt;
&lt;br /&gt;
Please see [[:Category:Platform Notes]] for any additional notes unique to your platform.&lt;br /&gt;
&lt;br /&gt;
Note that the autotools &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; will place FreeM in &amp;lt;code&amp;gt;/usr/local&amp;lt;/code&amp;gt; by default on most platforms. This conflicts with binary packages on Solaris.&lt;br /&gt;
&lt;br /&gt;
You can override the default installation location in the &amp;lt;code&amp;gt;configure&amp;lt;/code&amp;gt; step with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./configure --prefix=/path/to/desired/location&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Build==&lt;br /&gt;
This applies to the first build after you've obtained the FreeM source code.&lt;br /&gt;
&lt;br /&gt;
Follow these steps for the initial build:&lt;br /&gt;
&lt;br /&gt;
# Change directories to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; repository&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./autogen.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./configure&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;sudo make install&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you have done the initial build, most changes shouldn't require more than a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Subsequent Builds==&lt;br /&gt;
Most subsequent builds will just need a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;. See the following paragraphs for caveats.&lt;br /&gt;
&lt;br /&gt;
===When to run autogen.sh===&lt;br /&gt;
The &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; script is currently a shorthand for &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
We recommend that FreeM hackers get used to using &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; instead of running &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt; directly, as &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; may eventually contain other auto-generated items in future.&lt;br /&gt;
&lt;br /&gt;
You will need to run &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; only if you change any &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; files. Even then, a fresh &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; will generally check to see if your generated autoconf/automake files are older than &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; and do this step for you automatically.&lt;br /&gt;
&lt;br /&gt;
===When to run make install===&lt;br /&gt;
You should only need to run &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; in the following scenarios:&lt;br /&gt;
&lt;br /&gt;
* You've changed the way the environment catalog (&amp;lt;code&amp;gt;env.conf&amp;lt;/code&amp;gt;) or environment configuration files (&amp;lt;code&amp;gt;freem.conf&amp;lt;/code&amp;gt;) work&lt;br /&gt;
* You've modified a vendor routine in the &amp;lt;code&amp;gt;mlib/&amp;lt;/code&amp;gt; directory&lt;br /&gt;
* You've modified &amp;lt;code&amp;gt;libfreem&amp;lt;/code&amp;gt; and want to test it from a standard system location&lt;br /&gt;
&lt;br /&gt;
Other than these scenarios, you should be able to run the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;fmadm&amp;lt;/code&amp;gt; binaries out of the repository directory hierarchy.&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=392</id>
		<title>Contributor Guide</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=392"/>
		<updated>2025-04-05T22:31:43Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* C Standard */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
This article describes the facilities, methods, and commands used to contribute to the FreeM project.&lt;br /&gt;
&lt;br /&gt;
=For All Developers=&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
In order to contribute to FreeM, you must agree to abide by both the [[Code of Conduct]] and the [[General Policies]]. Your code must also conform to the style standards laid out in Appendix F of [https://freem.coherent-logic.com/docs/0.61.2/freem.html The FreeM Manual].&lt;br /&gt;
&lt;br /&gt;
You will also need to have &amp;lt;code&amp;gt;cvs&amp;lt;/code&amp;gt; installed on your machine. This is available in the package repositories of all popular Linux and UNIX operating systems.&lt;br /&gt;
&lt;br /&gt;
==Language==&lt;br /&gt;
All contributions to FreeM proper must be written in C. Bourne shell scripts are permissible where appropriate, and of course M code for the &amp;lt;code&amp;gt;mlib&amp;lt;/code&amp;gt; routines.&lt;br /&gt;
&lt;br /&gt;
===C Standard===&lt;br /&gt;
* FreeM contributions must not use language features unavailable in C89&lt;br /&gt;
* Vendor extensions in C compilers (like GNU extensions) are only permitted if guarded by preprocessor macros, and should be avoided if possible&lt;br /&gt;
* Contributions should be backwards compatible with gcc 2.95.3 (the oldest compiler we support)&lt;br /&gt;
* Contributions should not break compiles on Sun &amp;lt;code&amp;gt;cc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;clang&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For the last two guidelines, FreeM core developers will test your contributions and work with you to address any incompatibilities with these older compilers. We do not require every contributor to have access to ever compiler.&lt;br /&gt;
&lt;br /&gt;
===Autotools===&lt;br /&gt;
* Contributions to &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; configuration must not use &amp;lt;code&amp;gt;pkg-config&amp;lt;/code&amp;gt;, as it is unavailable on some of our target platforms&lt;br /&gt;
* Target &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; 2.54 and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; 1.7.1 for compatibility&lt;br /&gt;
&lt;br /&gt;
=Anonymous CVS Access=&lt;br /&gt;
&lt;br /&gt;
==Getting Source Code from CVS==&lt;br /&gt;
To fetch the latest FreeM source code from CVS, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
To update a previously-fetched copy of FreeM source code, go into the directory in which FreeM is located, and run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Submitting Changes Without CVS Write Access==&lt;br /&gt;
To submit a change to FreeM as an anonymous user (i.e., a user without writer access to the FreeM CVS repository), generate a &amp;lt;code&amp;gt;.patch&amp;lt;/code&amp;gt; file using the &amp;lt;code&amp;gt;diff&amp;lt;/code&amp;gt; utility, and send it to &amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt; (you must be subscribed to the mailing list), along with a description containing the following information:&lt;br /&gt;
&lt;br /&gt;
* What bug your patch fixes, or feature it implements&lt;br /&gt;
* Your full preferred name (this will be used in order to credit you for your work)&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
&lt;br /&gt;
Each patch should address no more than one bug fix or feature addition. Patches that do not comply with this requirement will be kicked back to the developer for revision.&lt;br /&gt;
&lt;br /&gt;
=CVS Writer Access=&lt;br /&gt;
&lt;br /&gt;
==Requesting Writer Access==&lt;br /&gt;
&lt;br /&gt;
In order to get CVS writer access, you will need to have either a track record of submitting good patches, or be an existing member of the core team. If you meet this criteria, please send a request to &lt;br /&gt;
&amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt;, including the following information:&lt;br /&gt;
&lt;br /&gt;
* Your full preferred name&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
* The username you would like to use for access to our CVS server (we will do our best to accommodate, but you may be required to choose a different username if your preferred username is already taken)&lt;br /&gt;
&lt;br /&gt;
==Configuring CVS==&lt;br /&gt;
&lt;br /&gt;
Once the below changes are made, you will need to log out and log back in to make them take effect.&lt;br /&gt;
&lt;br /&gt;
===Bourne-Again Shell (bash)===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.bashrc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;~/.bash_profile&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export CVS_RSH=/usr/bin/ssh&lt;br /&gt;
export CVSROOT=:ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also need to change the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; value to the correct absolute path to your &amp;lt;code&amp;gt;ssh&amp;lt;/code&amp;gt; binary. You can find this information using &amp;lt;code&amp;gt;which ssh&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===C Shell===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.cshrc&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setenv CVS_RSH /usr/bin/ssh&lt;br /&gt;
setenv CVSROOT :ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Fetching FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
To fetch the latest FreeM source code for the first time, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this fails, make sure you have the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CVSROOT&amp;lt;/code&amp;gt; environment variables correctly configured.&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
In the directory containing the FreeM source code, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Adding Files to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands from the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory, substituting the path and filename (relative to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory) for &amp;lt;code&amp;gt;&amp;amp;lt;filename&amp;amp;gt;&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs add &amp;lt;filename&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Committing Changes and Pushing to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands ''from the parent directory of the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory'', replacing &amp;lt;code&amp;gt;commit-message&amp;lt;/code&amp;gt; with a message describing the change:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs ci -m &amp;quot;commit-message&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Building FreeM=&lt;br /&gt;
&lt;br /&gt;
Please see [[:Category:Platform Notes]] for any additional notes unique to your platform.&lt;br /&gt;
&lt;br /&gt;
Note that the autotools &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; will place FreeM in &amp;lt;code&amp;gt;/usr/local&amp;lt;/code&amp;gt; by default on most platforms. This conflicts with binary packages on Solaris.&lt;br /&gt;
&lt;br /&gt;
You can override the default installation location in the &amp;lt;code&amp;gt;configure&amp;lt;/code&amp;gt; step with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./configure --prefix=/path/to/desired/location&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Build==&lt;br /&gt;
This applies to the first build after you've obtained the FreeM source code.&lt;br /&gt;
&lt;br /&gt;
Follow these steps for the initial build:&lt;br /&gt;
&lt;br /&gt;
# Change directories to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; repository&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./autogen.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./configure&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;sudo make install&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you have done the initial build, most changes shouldn't require more than a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Subsequent Builds==&lt;br /&gt;
Most subsequent builds will just need a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;. See the following paragraphs for caveats.&lt;br /&gt;
&lt;br /&gt;
===When to run autogen.sh===&lt;br /&gt;
The &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; script is currently a shorthand for &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
We recommend that FreeM hackers get used to using &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; instead of running &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt; directly, as &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; may eventually contain other auto-generated items in future.&lt;br /&gt;
&lt;br /&gt;
You will need to run &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; only if you change any &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; files. Even then, a fresh &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; will generally check to see if your generated autoconf/automake files are older than &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; and do this step for you automatically.&lt;br /&gt;
&lt;br /&gt;
===When to run make install===&lt;br /&gt;
You should only need to run &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; in the following scenarios:&lt;br /&gt;
&lt;br /&gt;
* You've changed the way the environment catalog (&amp;lt;code&amp;gt;env.conf&amp;lt;/code&amp;gt;) or environment configuration files (&amp;lt;code&amp;gt;freem.conf&amp;lt;/code&amp;gt;) work&lt;br /&gt;
* You've modified a vendor routine in the &amp;lt;code&amp;gt;mlib/&amp;lt;/code&amp;gt; directory&lt;br /&gt;
* You've modified &amp;lt;code&amp;gt;libfreem&amp;lt;/code&amp;gt; and want to test it from a standard system location&lt;br /&gt;
&lt;br /&gt;
Other than these scenarios, you should be able to run the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;fmadm&amp;lt;/code&amp;gt; binaries out of the repository directory hierarchy.&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Main_Page&amp;diff=391</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Main_Page&amp;diff=391"/>
		<updated>2025-04-05T22:21:16Z</updated>

		<summary type="html">&lt;p&gt;Smw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki contains documentation not included in the [https://freem.coherent-logic.com/docs FreeM Manual], including platform-specific installation and configuration notes, project policies, technical deep-dives, and release notes.&lt;br /&gt;
&lt;br /&gt;
== Release Notes ==&lt;br /&gt;
* [[Conformance Clause]]&lt;br /&gt;
* [[FreeM 0.62.3]]&lt;br /&gt;
* [[FreeM 0.62.2]]&lt;br /&gt;
* [[FreeM 0.62.1]]&lt;br /&gt;
* [[FreeM Lite]]&lt;br /&gt;
* [[FreeM 0.59.2]]&lt;br /&gt;
&lt;br /&gt;
== Project Policies and Procedures ==&lt;br /&gt;
* [[General Policies]]&lt;br /&gt;
* [[Code of Conduct]]&lt;br /&gt;
&lt;br /&gt;
== Hacking FreeM Code ==&lt;br /&gt;
* [[Contributor Guide]]&lt;br /&gt;
* [[Release Procedure]]&lt;br /&gt;
&lt;br /&gt;
== Port Tiers ==&lt;br /&gt;
* [[Port Tiers]]&lt;br /&gt;
* [[:Category:Tier 1 Ports|Tier 1 Ports]]&lt;br /&gt;
* [[:Category:Tier 2 Ports|Tier 2 Ports]]&lt;br /&gt;
* [[:Category:Tier 3 Ports|Tier 3 Ports]]&lt;br /&gt;
&lt;br /&gt;
== Platform Notes ==&lt;br /&gt;
=== Tier 1 Ports ===&lt;br /&gt;
* [[Platform Notes (Solaris/Illumos)]]&lt;br /&gt;
* [[Platform Notes (NetBSD)]]&lt;br /&gt;
* [[Platform Notes (FreeBSD)]]&lt;br /&gt;
* [[Platform Notes (GNU/Linux)]]&lt;br /&gt;
* [[Platform Notes (OpenBSD)]]&lt;br /&gt;
&lt;br /&gt;
=== Tier 2 Ports ===&lt;br /&gt;
* [[Platform Notes (OS/2)]]&lt;br /&gt;
* [[Platform Notes (SCO OpenServer)]]&lt;br /&gt;
* [[Platform Notes (Compaq Tru64 UNIX)]]&lt;br /&gt;
* [[Platform Notes (IBM AIX)]]&lt;br /&gt;
&lt;br /&gt;
=== Tier 3 Ports ===&lt;br /&gt;
* [[Platform Notes (GNU HURD)]]&lt;br /&gt;
* [[Platform Notes (SGI IRIX)]]&lt;br /&gt;
* [[Platform Notes (HP-UX)]]&lt;br /&gt;
* [[Platform Notes (Mac OS X)]]&lt;br /&gt;
* [[Platform Notes (Minix 3+)]]&lt;br /&gt;
&lt;br /&gt;
== Tips and Tricks ==&lt;br /&gt;
* [[Subscript Rules (Local and Global)]]&lt;br /&gt;
* [[Object-Oriented Programming in FreeM]]&lt;br /&gt;
&lt;br /&gt;
== Technical Deep-Dives ==&lt;br /&gt;
* [[FreeM System Architecture]]&lt;br /&gt;
* [[Event Handling in FreeM]]&lt;br /&gt;
* [[FreeM Transaction Processing Architecture]]&lt;br /&gt;
* [[What is the GUMP?]]&lt;br /&gt;
* [[Namespace Rules]]&lt;br /&gt;
* [[Routine and Global Search Path Internals]]&lt;br /&gt;
&lt;br /&gt;
== History ==&lt;br /&gt;
* [[FreeM History]]&lt;br /&gt;
* [[Original README from Shalom ha-Ashkenaz]]&lt;br /&gt;
&lt;br /&gt;
== Status of Popular M Applications in FreeM ==&lt;br /&gt;
&lt;br /&gt;
* [[Applications: VA VistA]]&lt;br /&gt;
* [[Applications: VA FileMan]]&lt;br /&gt;
* [[Applications: VPE (Victory Programming Environment)]]&lt;br /&gt;
* [[Applications: M Web Server]]&lt;br /&gt;
* [[Applications: GDS/JDS]]&lt;br /&gt;
* [[Applications: MVTS (M Validation and Test Suite)]]&lt;br /&gt;
&lt;br /&gt;
== General M Topics ==&lt;br /&gt;
* [[M User's Group]]&lt;br /&gt;
* [[M Technology Association]]&lt;br /&gt;
* [[M Development Committee]]&lt;br /&gt;
* [[Cache and M Technology Association UK]]&lt;br /&gt;
* [[M User's Group-Deutschland]]&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=390</id>
		<title>Contributor Guide</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=390"/>
		<updated>2025-04-05T22:17:07Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* When to run make install */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
This article describes the facilities, methods, and commands used to contribute to the FreeM project.&lt;br /&gt;
&lt;br /&gt;
=For All Developers=&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
In order to contribute to FreeM, you must agree to abide by both the [[Code of Conduct]] and the [[General Policies]]. Your code must also conform to the style standards laid out in Appendix F of [https://freem.coherent-logic.com/docs/0.61.2/freem.html The FreeM Manual].&lt;br /&gt;
&lt;br /&gt;
You will also need to have &amp;lt;code&amp;gt;cvs&amp;lt;/code&amp;gt; installed on your machine. This is available in the package repositories of all popular Linux and UNIX operating systems.&lt;br /&gt;
&lt;br /&gt;
==Language==&lt;br /&gt;
All contributions to FreeM proper must be written in C. Bourne shell scripts are permissible where appropriate, and of course M code for the &amp;lt;code&amp;gt;mlib&amp;lt;/code&amp;gt; routines.&lt;br /&gt;
&lt;br /&gt;
===C Standard===&lt;br /&gt;
* FreeM contributions must not use language features unavailable in C89&lt;br /&gt;
* Vendor extensions in C compilers (like GNU extensions) are only permitted if guarded by preprocessor macros, and should be avoided if possible&lt;br /&gt;
* Contributions must be backwards compatible with gcc 2.95.3 (the oldest compiler we support)&lt;br /&gt;
* Contributions must not break compiles on Sun &amp;lt;code&amp;gt;cc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;clang&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Autotools===&lt;br /&gt;
* Contributions to &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; configuration must not use &amp;lt;code&amp;gt;pkg-config&amp;lt;/code&amp;gt;, as it is unavailable on some of our target platforms&lt;br /&gt;
* Target &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; 2.54 and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; 1.7.1 for compatibility&lt;br /&gt;
&lt;br /&gt;
=Anonymous CVS Access=&lt;br /&gt;
&lt;br /&gt;
==Getting Source Code from CVS==&lt;br /&gt;
To fetch the latest FreeM source code from CVS, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
To update a previously-fetched copy of FreeM source code, go into the directory in which FreeM is located, and run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Submitting Changes Without CVS Write Access==&lt;br /&gt;
To submit a change to FreeM as an anonymous user (i.e., a user without writer access to the FreeM CVS repository), generate a &amp;lt;code&amp;gt;.patch&amp;lt;/code&amp;gt; file using the &amp;lt;code&amp;gt;diff&amp;lt;/code&amp;gt; utility, and send it to &amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt; (you must be subscribed to the mailing list), along with a description containing the following information:&lt;br /&gt;
&lt;br /&gt;
* What bug your patch fixes, or feature it implements&lt;br /&gt;
* Your full preferred name (this will be used in order to credit you for your work)&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
&lt;br /&gt;
Each patch should address no more than one bug fix or feature addition. Patches that do not comply with this requirement will be kicked back to the developer for revision.&lt;br /&gt;
&lt;br /&gt;
=CVS Writer Access=&lt;br /&gt;
&lt;br /&gt;
==Requesting Writer Access==&lt;br /&gt;
&lt;br /&gt;
In order to get CVS writer access, you will need to have either a track record of submitting good patches, or be an existing member of the core team. If you meet this criteria, please send a request to &lt;br /&gt;
&amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt;, including the following information:&lt;br /&gt;
&lt;br /&gt;
* Your full preferred name&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
* The username you would like to use for access to our CVS server (we will do our best to accommodate, but you may be required to choose a different username if your preferred username is already taken)&lt;br /&gt;
&lt;br /&gt;
==Configuring CVS==&lt;br /&gt;
&lt;br /&gt;
Once the below changes are made, you will need to log out and log back in to make them take effect.&lt;br /&gt;
&lt;br /&gt;
===Bourne-Again Shell (bash)===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.bashrc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;~/.bash_profile&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export CVS_RSH=/usr/bin/ssh&lt;br /&gt;
export CVSROOT=:ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also need to change the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; value to the correct absolute path to your &amp;lt;code&amp;gt;ssh&amp;lt;/code&amp;gt; binary. You can find this information using &amp;lt;code&amp;gt;which ssh&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===C Shell===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.cshrc&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setenv CVS_RSH /usr/bin/ssh&lt;br /&gt;
setenv CVSROOT :ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Fetching FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
To fetch the latest FreeM source code for the first time, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this fails, make sure you have the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CVSROOT&amp;lt;/code&amp;gt; environment variables correctly configured.&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
In the directory containing the FreeM source code, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Adding Files to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands from the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory, substituting the path and filename (relative to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory) for &amp;lt;code&amp;gt;&amp;amp;lt;filename&amp;amp;gt;&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs add &amp;lt;filename&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Committing Changes and Pushing to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands ''from the parent directory of the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory'', replacing &amp;lt;code&amp;gt;commit-message&amp;lt;/code&amp;gt; with a message describing the change:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs ci -m &amp;quot;commit-message&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Building FreeM=&lt;br /&gt;
&lt;br /&gt;
Please see [[:Category:Platform Notes]] for any additional notes unique to your platform.&lt;br /&gt;
&lt;br /&gt;
Note that the autotools &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; will place FreeM in &amp;lt;code&amp;gt;/usr/local&amp;lt;/code&amp;gt; by default on most platforms. This conflicts with binary packages on Solaris.&lt;br /&gt;
&lt;br /&gt;
You can override the default installation location in the &amp;lt;code&amp;gt;configure&amp;lt;/code&amp;gt; step with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./configure --prefix=/path/to/desired/location&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Build==&lt;br /&gt;
This applies to the first build after you've obtained the FreeM source code.&lt;br /&gt;
&lt;br /&gt;
Follow these steps for the initial build:&lt;br /&gt;
&lt;br /&gt;
# Change directories to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; repository&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./autogen.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./configure&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;sudo make install&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you have done the initial build, most changes shouldn't require more than a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Subsequent Builds==&lt;br /&gt;
Most subsequent builds will just need a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;. See the following paragraphs for caveats.&lt;br /&gt;
&lt;br /&gt;
===When to run autogen.sh===&lt;br /&gt;
The &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; script is currently a shorthand for &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
We recommend that FreeM hackers get used to using &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; instead of running &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt; directly, as &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; may eventually contain other auto-generated items in future.&lt;br /&gt;
&lt;br /&gt;
You will need to run &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; only if you change any &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; files. Even then, a fresh &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; will generally check to see if your generated autoconf/automake files are older than &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; and do this step for you automatically.&lt;br /&gt;
&lt;br /&gt;
===When to run make install===&lt;br /&gt;
You should only need to run &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; in the following scenarios:&lt;br /&gt;
&lt;br /&gt;
* You've changed the way the environment catalog (&amp;lt;code&amp;gt;env.conf&amp;lt;/code&amp;gt;) or environment configuration files (&amp;lt;code&amp;gt;freem.conf&amp;lt;/code&amp;gt;) work&lt;br /&gt;
* You've modified a vendor routine in the &amp;lt;code&amp;gt;mlib/&amp;lt;/code&amp;gt; directory&lt;br /&gt;
* You've modified &amp;lt;code&amp;gt;libfreem&amp;lt;/code&amp;gt; and want to test it from a standard system location&lt;br /&gt;
&lt;br /&gt;
Other than these scenarios, you should be able to run the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;fmadm&amp;lt;/code&amp;gt; binaries out of the repository directory hierarchy.&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=389</id>
		<title>Contributor Guide</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=389"/>
		<updated>2025-04-05T22:16:28Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* When to run autogen.sh */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
This article describes the facilities, methods, and commands used to contribute to the FreeM project.&lt;br /&gt;
&lt;br /&gt;
=For All Developers=&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
In order to contribute to FreeM, you must agree to abide by both the [[Code of Conduct]] and the [[General Policies]]. Your code must also conform to the style standards laid out in Appendix F of [https://freem.coherent-logic.com/docs/0.61.2/freem.html The FreeM Manual].&lt;br /&gt;
&lt;br /&gt;
You will also need to have &amp;lt;code&amp;gt;cvs&amp;lt;/code&amp;gt; installed on your machine. This is available in the package repositories of all popular Linux and UNIX operating systems.&lt;br /&gt;
&lt;br /&gt;
==Language==&lt;br /&gt;
All contributions to FreeM proper must be written in C. Bourne shell scripts are permissible where appropriate, and of course M code for the &amp;lt;code&amp;gt;mlib&amp;lt;/code&amp;gt; routines.&lt;br /&gt;
&lt;br /&gt;
===C Standard===&lt;br /&gt;
* FreeM contributions must not use language features unavailable in C89&lt;br /&gt;
* Vendor extensions in C compilers (like GNU extensions) are only permitted if guarded by preprocessor macros, and should be avoided if possible&lt;br /&gt;
* Contributions must be backwards compatible with gcc 2.95.3 (the oldest compiler we support)&lt;br /&gt;
* Contributions must not break compiles on Sun &amp;lt;code&amp;gt;cc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;clang&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Autotools===&lt;br /&gt;
* Contributions to &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; configuration must not use &amp;lt;code&amp;gt;pkg-config&amp;lt;/code&amp;gt;, as it is unavailable on some of our target platforms&lt;br /&gt;
* Target &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; 2.54 and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; 1.7.1 for compatibility&lt;br /&gt;
&lt;br /&gt;
=Anonymous CVS Access=&lt;br /&gt;
&lt;br /&gt;
==Getting Source Code from CVS==&lt;br /&gt;
To fetch the latest FreeM source code from CVS, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
To update a previously-fetched copy of FreeM source code, go into the directory in which FreeM is located, and run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Submitting Changes Without CVS Write Access==&lt;br /&gt;
To submit a change to FreeM as an anonymous user (i.e., a user without writer access to the FreeM CVS repository), generate a &amp;lt;code&amp;gt;.patch&amp;lt;/code&amp;gt; file using the &amp;lt;code&amp;gt;diff&amp;lt;/code&amp;gt; utility, and send it to &amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt; (you must be subscribed to the mailing list), along with a description containing the following information:&lt;br /&gt;
&lt;br /&gt;
* What bug your patch fixes, or feature it implements&lt;br /&gt;
* Your full preferred name (this will be used in order to credit you for your work)&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
&lt;br /&gt;
Each patch should address no more than one bug fix or feature addition. Patches that do not comply with this requirement will be kicked back to the developer for revision.&lt;br /&gt;
&lt;br /&gt;
=CVS Writer Access=&lt;br /&gt;
&lt;br /&gt;
==Requesting Writer Access==&lt;br /&gt;
&lt;br /&gt;
In order to get CVS writer access, you will need to have either a track record of submitting good patches, or be an existing member of the core team. If you meet this criteria, please send a request to &lt;br /&gt;
&amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt;, including the following information:&lt;br /&gt;
&lt;br /&gt;
* Your full preferred name&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
* The username you would like to use for access to our CVS server (we will do our best to accommodate, but you may be required to choose a different username if your preferred username is already taken)&lt;br /&gt;
&lt;br /&gt;
==Configuring CVS==&lt;br /&gt;
&lt;br /&gt;
Once the below changes are made, you will need to log out and log back in to make them take effect.&lt;br /&gt;
&lt;br /&gt;
===Bourne-Again Shell (bash)===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.bashrc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;~/.bash_profile&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export CVS_RSH=/usr/bin/ssh&lt;br /&gt;
export CVSROOT=:ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also need to change the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; value to the correct absolute path to your &amp;lt;code&amp;gt;ssh&amp;lt;/code&amp;gt; binary. You can find this information using &amp;lt;code&amp;gt;which ssh&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===C Shell===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.cshrc&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setenv CVS_RSH /usr/bin/ssh&lt;br /&gt;
setenv CVSROOT :ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Fetching FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
To fetch the latest FreeM source code for the first time, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this fails, make sure you have the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CVSROOT&amp;lt;/code&amp;gt; environment variables correctly configured.&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
In the directory containing the FreeM source code, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Adding Files to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands from the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory, substituting the path and filename (relative to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory) for &amp;lt;code&amp;gt;&amp;amp;lt;filename&amp;amp;gt;&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs add &amp;lt;filename&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Committing Changes and Pushing to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands ''from the parent directory of the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory'', replacing &amp;lt;code&amp;gt;commit-message&amp;lt;/code&amp;gt; with a message describing the change:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs ci -m &amp;quot;commit-message&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Building FreeM=&lt;br /&gt;
&lt;br /&gt;
Please see [[:Category:Platform Notes]] for any additional notes unique to your platform.&lt;br /&gt;
&lt;br /&gt;
Note that the autotools &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; will place FreeM in &amp;lt;code&amp;gt;/usr/local&amp;lt;/code&amp;gt; by default on most platforms. This conflicts with binary packages on Solaris.&lt;br /&gt;
&lt;br /&gt;
You can override the default installation location in the &amp;lt;code&amp;gt;configure&amp;lt;/code&amp;gt; step with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./configure --prefix=/path/to/desired/location&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Build==&lt;br /&gt;
This applies to the first build after you've obtained the FreeM source code.&lt;br /&gt;
&lt;br /&gt;
Follow these steps for the initial build:&lt;br /&gt;
&lt;br /&gt;
# Change directories to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; repository&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./autogen.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./configure&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;sudo make install&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you have done the initial build, most changes shouldn't require more than a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Subsequent Builds==&lt;br /&gt;
Most subsequent builds will just need a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;. See the following paragraphs for caveats.&lt;br /&gt;
&lt;br /&gt;
===When to run autogen.sh===&lt;br /&gt;
The &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; script is currently a shorthand for &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
We recommend that FreeM hackers get used to using &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; instead of running &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt; directly, as &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; may eventually contain other auto-generated items in future.&lt;br /&gt;
&lt;br /&gt;
You will need to run &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; only if you change any &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; files. Even then, a fresh &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; will generally check to see if your generated autoconf/automake files are older than &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; and do this step for you automatically.&lt;br /&gt;
&lt;br /&gt;
===When to run make install===&lt;br /&gt;
You should only need to run &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; in the following scenarios:&lt;br /&gt;
&lt;br /&gt;
* You've changed the way the environment catalog (&amp;lt;code&amp;gt;env.conf&amp;lt;/code&amp;gt;) or environment configuration files (&amp;lt;code&amp;gt;freem.conf&amp;lt;/code&amp;gt;) work&lt;br /&gt;
* You've modified a vendor routine in the &amp;lt;code&amp;gt;mlib/&amp;lt;/code&amp;gt; directory&lt;br /&gt;
&lt;br /&gt;
Other than these scenarios, you should be able to run the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;fmadm&amp;lt;/code&amp;gt; binaries out of the repository directory hierarchy.&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=388</id>
		<title>Contributor Guide</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=388"/>
		<updated>2025-04-05T22:16:12Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* When to run autogen.sh */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
This article describes the facilities, methods, and commands used to contribute to the FreeM project.&lt;br /&gt;
&lt;br /&gt;
=For All Developers=&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
In order to contribute to FreeM, you must agree to abide by both the [[Code of Conduct]] and the [[General Policies]]. Your code must also conform to the style standards laid out in Appendix F of [https://freem.coherent-logic.com/docs/0.61.2/freem.html The FreeM Manual].&lt;br /&gt;
&lt;br /&gt;
You will also need to have &amp;lt;code&amp;gt;cvs&amp;lt;/code&amp;gt; installed on your machine. This is available in the package repositories of all popular Linux and UNIX operating systems.&lt;br /&gt;
&lt;br /&gt;
==Language==&lt;br /&gt;
All contributions to FreeM proper must be written in C. Bourne shell scripts are permissible where appropriate, and of course M code for the &amp;lt;code&amp;gt;mlib&amp;lt;/code&amp;gt; routines.&lt;br /&gt;
&lt;br /&gt;
===C Standard===&lt;br /&gt;
* FreeM contributions must not use language features unavailable in C89&lt;br /&gt;
* Vendor extensions in C compilers (like GNU extensions) are only permitted if guarded by preprocessor macros, and should be avoided if possible&lt;br /&gt;
* Contributions must be backwards compatible with gcc 2.95.3 (the oldest compiler we support)&lt;br /&gt;
* Contributions must not break compiles on Sun &amp;lt;code&amp;gt;cc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;clang&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Autotools===&lt;br /&gt;
* Contributions to &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; configuration must not use &amp;lt;code&amp;gt;pkg-config&amp;lt;/code&amp;gt;, as it is unavailable on some of our target platforms&lt;br /&gt;
* Target &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; 2.54 and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; 1.7.1 for compatibility&lt;br /&gt;
&lt;br /&gt;
=Anonymous CVS Access=&lt;br /&gt;
&lt;br /&gt;
==Getting Source Code from CVS==&lt;br /&gt;
To fetch the latest FreeM source code from CVS, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
To update a previously-fetched copy of FreeM source code, go into the directory in which FreeM is located, and run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Submitting Changes Without CVS Write Access==&lt;br /&gt;
To submit a change to FreeM as an anonymous user (i.e., a user without writer access to the FreeM CVS repository), generate a &amp;lt;code&amp;gt;.patch&amp;lt;/code&amp;gt; file using the &amp;lt;code&amp;gt;diff&amp;lt;/code&amp;gt; utility, and send it to &amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt; (you must be subscribed to the mailing list), along with a description containing the following information:&lt;br /&gt;
&lt;br /&gt;
* What bug your patch fixes, or feature it implements&lt;br /&gt;
* Your full preferred name (this will be used in order to credit you for your work)&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
&lt;br /&gt;
Each patch should address no more than one bug fix or feature addition. Patches that do not comply with this requirement will be kicked back to the developer for revision.&lt;br /&gt;
&lt;br /&gt;
=CVS Writer Access=&lt;br /&gt;
&lt;br /&gt;
==Requesting Writer Access==&lt;br /&gt;
&lt;br /&gt;
In order to get CVS writer access, you will need to have either a track record of submitting good patches, or be an existing member of the core team. If you meet this criteria, please send a request to &lt;br /&gt;
&amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt;, including the following information:&lt;br /&gt;
&lt;br /&gt;
* Your full preferred name&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
* The username you would like to use for access to our CVS server (we will do our best to accommodate, but you may be required to choose a different username if your preferred username is already taken)&lt;br /&gt;
&lt;br /&gt;
==Configuring CVS==&lt;br /&gt;
&lt;br /&gt;
Once the below changes are made, you will need to log out and log back in to make them take effect.&lt;br /&gt;
&lt;br /&gt;
===Bourne-Again Shell (bash)===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.bashrc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;~/.bash_profile&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export CVS_RSH=/usr/bin/ssh&lt;br /&gt;
export CVSROOT=:ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also need to change the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; value to the correct absolute path to your &amp;lt;code&amp;gt;ssh&amp;lt;/code&amp;gt; binary. You can find this information using &amp;lt;code&amp;gt;which ssh&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===C Shell===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.cshrc&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setenv CVS_RSH /usr/bin/ssh&lt;br /&gt;
setenv CVSROOT :ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Fetching FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
To fetch the latest FreeM source code for the first time, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this fails, make sure you have the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CVSROOT&amp;lt;/code&amp;gt; environment variables correctly configured.&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
In the directory containing the FreeM source code, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Adding Files to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands from the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory, substituting the path and filename (relative to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory) for &amp;lt;code&amp;gt;&amp;amp;lt;filename&amp;amp;gt;&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs add &amp;lt;filename&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Committing Changes and Pushing to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands ''from the parent directory of the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory'', replacing &amp;lt;code&amp;gt;commit-message&amp;lt;/code&amp;gt; with a message describing the change:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs ci -m &amp;quot;commit-message&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Building FreeM=&lt;br /&gt;
&lt;br /&gt;
Please see [[:Category:Platform Notes]] for any additional notes unique to your platform.&lt;br /&gt;
&lt;br /&gt;
Note that the autotools &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; will place FreeM in &amp;lt;code&amp;gt;/usr/local&amp;lt;/code&amp;gt; by default on most platforms. This conflicts with binary packages on Solaris.&lt;br /&gt;
&lt;br /&gt;
You can override the default installation location in the &amp;lt;code&amp;gt;configure&amp;lt;/code&amp;gt; step with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./configure --prefix=/path/to/desired/location&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Build==&lt;br /&gt;
This applies to the first build after you've obtained the FreeM source code.&lt;br /&gt;
&lt;br /&gt;
Follow these steps for the initial build:&lt;br /&gt;
&lt;br /&gt;
# Change directories to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; repository&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./autogen.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./configure&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;sudo make install&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you have done the initial build, most changes shouldn't require more than a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Subsequent Builds==&lt;br /&gt;
Most subsequent builds will just need a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;. See the following paragraphs for caveats.&lt;br /&gt;
&lt;br /&gt;
===When to run autogen.sh===&lt;br /&gt;
The &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; script is simply a shorthand for &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt;. We recommend that FreeM hackers get used to using &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; instead of running &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt; directly, as &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; may eventually contain other auto-generated items in future.&lt;br /&gt;
&lt;br /&gt;
You will need to run &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; only if you change any &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; files. Even then, a fresh &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; will generally check to see if your generated autoconf/automake files are older than &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; and do this step for you automatically.&lt;br /&gt;
&lt;br /&gt;
===When to run make install===&lt;br /&gt;
You should only need to run &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; in the following scenarios:&lt;br /&gt;
&lt;br /&gt;
* You've changed the way the environment catalog (&amp;lt;code&amp;gt;env.conf&amp;lt;/code&amp;gt;) or environment configuration files (&amp;lt;code&amp;gt;freem.conf&amp;lt;/code&amp;gt;) work&lt;br /&gt;
* You've modified a vendor routine in the &amp;lt;code&amp;gt;mlib/&amp;lt;/code&amp;gt; directory&lt;br /&gt;
&lt;br /&gt;
Other than these scenarios, you should be able to run the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;fmadm&amp;lt;/code&amp;gt; binaries out of the repository directory hierarchy.&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=387</id>
		<title>Contributor Guide</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=387"/>
		<updated>2025-04-05T22:13:02Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Building FreeM */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
This article describes the facilities, methods, and commands used to contribute to the FreeM project.&lt;br /&gt;
&lt;br /&gt;
=For All Developers=&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
In order to contribute to FreeM, you must agree to abide by both the [[Code of Conduct]] and the [[General Policies]]. Your code must also conform to the style standards laid out in Appendix F of [https://freem.coherent-logic.com/docs/0.61.2/freem.html The FreeM Manual].&lt;br /&gt;
&lt;br /&gt;
You will also need to have &amp;lt;code&amp;gt;cvs&amp;lt;/code&amp;gt; installed on your machine. This is available in the package repositories of all popular Linux and UNIX operating systems.&lt;br /&gt;
&lt;br /&gt;
==Language==&lt;br /&gt;
All contributions to FreeM proper must be written in C. Bourne shell scripts are permissible where appropriate, and of course M code for the &amp;lt;code&amp;gt;mlib&amp;lt;/code&amp;gt; routines.&lt;br /&gt;
&lt;br /&gt;
===C Standard===&lt;br /&gt;
* FreeM contributions must not use language features unavailable in C89&lt;br /&gt;
* Vendor extensions in C compilers (like GNU extensions) are only permitted if guarded by preprocessor macros, and should be avoided if possible&lt;br /&gt;
* Contributions must be backwards compatible with gcc 2.95.3 (the oldest compiler we support)&lt;br /&gt;
* Contributions must not break compiles on Sun &amp;lt;code&amp;gt;cc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;clang&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Autotools===&lt;br /&gt;
* Contributions to &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; configuration must not use &amp;lt;code&amp;gt;pkg-config&amp;lt;/code&amp;gt;, as it is unavailable on some of our target platforms&lt;br /&gt;
* Target &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; 2.54 and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; 1.7.1 for compatibility&lt;br /&gt;
&lt;br /&gt;
=Anonymous CVS Access=&lt;br /&gt;
&lt;br /&gt;
==Getting Source Code from CVS==&lt;br /&gt;
To fetch the latest FreeM source code from CVS, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
To update a previously-fetched copy of FreeM source code, go into the directory in which FreeM is located, and run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Submitting Changes Without CVS Write Access==&lt;br /&gt;
To submit a change to FreeM as an anonymous user (i.e., a user without writer access to the FreeM CVS repository), generate a &amp;lt;code&amp;gt;.patch&amp;lt;/code&amp;gt; file using the &amp;lt;code&amp;gt;diff&amp;lt;/code&amp;gt; utility, and send it to &amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt; (you must be subscribed to the mailing list), along with a description containing the following information:&lt;br /&gt;
&lt;br /&gt;
* What bug your patch fixes, or feature it implements&lt;br /&gt;
* Your full preferred name (this will be used in order to credit you for your work)&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
&lt;br /&gt;
Each patch should address no more than one bug fix or feature addition. Patches that do not comply with this requirement will be kicked back to the developer for revision.&lt;br /&gt;
&lt;br /&gt;
=CVS Writer Access=&lt;br /&gt;
&lt;br /&gt;
==Requesting Writer Access==&lt;br /&gt;
&lt;br /&gt;
In order to get CVS writer access, you will need to have either a track record of submitting good patches, or be an existing member of the core team. If you meet this criteria, please send a request to &lt;br /&gt;
&amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt;, including the following information:&lt;br /&gt;
&lt;br /&gt;
* Your full preferred name&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
* The username you would like to use for access to our CVS server (we will do our best to accommodate, but you may be required to choose a different username if your preferred username is already taken)&lt;br /&gt;
&lt;br /&gt;
==Configuring CVS==&lt;br /&gt;
&lt;br /&gt;
Once the below changes are made, you will need to log out and log back in to make them take effect.&lt;br /&gt;
&lt;br /&gt;
===Bourne-Again Shell (bash)===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.bashrc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;~/.bash_profile&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export CVS_RSH=/usr/bin/ssh&lt;br /&gt;
export CVSROOT=:ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also need to change the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; value to the correct absolute path to your &amp;lt;code&amp;gt;ssh&amp;lt;/code&amp;gt; binary. You can find this information using &amp;lt;code&amp;gt;which ssh&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===C Shell===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.cshrc&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setenv CVS_RSH /usr/bin/ssh&lt;br /&gt;
setenv CVSROOT :ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Fetching FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
To fetch the latest FreeM source code for the first time, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this fails, make sure you have the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CVSROOT&amp;lt;/code&amp;gt; environment variables correctly configured.&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
In the directory containing the FreeM source code, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Adding Files to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands from the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory, substituting the path and filename (relative to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory) for &amp;lt;code&amp;gt;&amp;amp;lt;filename&amp;amp;gt;&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs add &amp;lt;filename&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Committing Changes and Pushing to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands ''from the parent directory of the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory'', replacing &amp;lt;code&amp;gt;commit-message&amp;lt;/code&amp;gt; with a message describing the change:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs ci -m &amp;quot;commit-message&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Building FreeM=&lt;br /&gt;
&lt;br /&gt;
Please see [[:Category:Platform Notes]] for any additional notes unique to your platform.&lt;br /&gt;
&lt;br /&gt;
Note that the autotools &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; will place FreeM in &amp;lt;code&amp;gt;/usr/local&amp;lt;/code&amp;gt; by default on most platforms. This conflicts with binary packages on Solaris.&lt;br /&gt;
&lt;br /&gt;
You can override the default installation location in the &amp;lt;code&amp;gt;configure&amp;lt;/code&amp;gt; step with the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./configure --prefix=/path/to/desired/location&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Build==&lt;br /&gt;
This applies to the first build after you've obtained the FreeM source code.&lt;br /&gt;
&lt;br /&gt;
Follow these steps for the initial build:&lt;br /&gt;
&lt;br /&gt;
# Change directories to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; repository&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./autogen.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./configure&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;sudo make install&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you have done the initial build, most changes shouldn't require more than a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Subsequent Builds==&lt;br /&gt;
Most subsequent builds will just need a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;. See the following paragraphs for caveats.&lt;br /&gt;
&lt;br /&gt;
===When to run autogen.sh===&lt;br /&gt;
The &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; script is simply a shorthand for &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You will need to run &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; only if you change any &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; files. Even then, a fresh &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; will generally check to see if your generated autoconf/automake files are older than &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; and do this step for you automatically.&lt;br /&gt;
&lt;br /&gt;
===When to run make install===&lt;br /&gt;
You should only need to run &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; in the following scenarios:&lt;br /&gt;
&lt;br /&gt;
* You've changed the way the environment catalog (&amp;lt;code&amp;gt;env.conf&amp;lt;/code&amp;gt;) or environment configuration files (&amp;lt;code&amp;gt;freem.conf&amp;lt;/code&amp;gt;) work&lt;br /&gt;
* You've modified a vendor routine in the &amp;lt;code&amp;gt;mlib/&amp;lt;/code&amp;gt; directory&lt;br /&gt;
&lt;br /&gt;
Other than these scenarios, you should be able to run the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;fmadm&amp;lt;/code&amp;gt; binaries out of the repository directory hierarchy.&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=386</id>
		<title>Contributor Guide</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=386"/>
		<updated>2025-04-05T22:11:52Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Building FreeM */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
This article describes the facilities, methods, and commands used to contribute to the FreeM project.&lt;br /&gt;
&lt;br /&gt;
=For All Developers=&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
In order to contribute to FreeM, you must agree to abide by both the [[Code of Conduct]] and the [[General Policies]]. Your code must also conform to the style standards laid out in Appendix F of [https://freem.coherent-logic.com/docs/0.61.2/freem.html The FreeM Manual].&lt;br /&gt;
&lt;br /&gt;
You will also need to have &amp;lt;code&amp;gt;cvs&amp;lt;/code&amp;gt; installed on your machine. This is available in the package repositories of all popular Linux and UNIX operating systems.&lt;br /&gt;
&lt;br /&gt;
==Language==&lt;br /&gt;
All contributions to FreeM proper must be written in C. Bourne shell scripts are permissible where appropriate, and of course M code for the &amp;lt;code&amp;gt;mlib&amp;lt;/code&amp;gt; routines.&lt;br /&gt;
&lt;br /&gt;
===C Standard===&lt;br /&gt;
* FreeM contributions must not use language features unavailable in C89&lt;br /&gt;
* Vendor extensions in C compilers (like GNU extensions) are only permitted if guarded by preprocessor macros, and should be avoided if possible&lt;br /&gt;
* Contributions must be backwards compatible with gcc 2.95.3 (the oldest compiler we support)&lt;br /&gt;
* Contributions must not break compiles on Sun &amp;lt;code&amp;gt;cc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;clang&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Autotools===&lt;br /&gt;
* Contributions to &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; configuration must not use &amp;lt;code&amp;gt;pkg-config&amp;lt;/code&amp;gt;, as it is unavailable on some of our target platforms&lt;br /&gt;
* Target &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; 2.54 and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; 1.7.1 for compatibility&lt;br /&gt;
&lt;br /&gt;
=Anonymous CVS Access=&lt;br /&gt;
&lt;br /&gt;
==Getting Source Code from CVS==&lt;br /&gt;
To fetch the latest FreeM source code from CVS, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
To update a previously-fetched copy of FreeM source code, go into the directory in which FreeM is located, and run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Submitting Changes Without CVS Write Access==&lt;br /&gt;
To submit a change to FreeM as an anonymous user (i.e., a user without writer access to the FreeM CVS repository), generate a &amp;lt;code&amp;gt;.patch&amp;lt;/code&amp;gt; file using the &amp;lt;code&amp;gt;diff&amp;lt;/code&amp;gt; utility, and send it to &amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt; (you must be subscribed to the mailing list), along with a description containing the following information:&lt;br /&gt;
&lt;br /&gt;
* What bug your patch fixes, or feature it implements&lt;br /&gt;
* Your full preferred name (this will be used in order to credit you for your work)&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
&lt;br /&gt;
Each patch should address no more than one bug fix or feature addition. Patches that do not comply with this requirement will be kicked back to the developer for revision.&lt;br /&gt;
&lt;br /&gt;
=CVS Writer Access=&lt;br /&gt;
&lt;br /&gt;
==Requesting Writer Access==&lt;br /&gt;
&lt;br /&gt;
In order to get CVS writer access, you will need to have either a track record of submitting good patches, or be an existing member of the core team. If you meet this criteria, please send a request to &lt;br /&gt;
&amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt;, including the following information:&lt;br /&gt;
&lt;br /&gt;
* Your full preferred name&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
* The username you would like to use for access to our CVS server (we will do our best to accommodate, but you may be required to choose a different username if your preferred username is already taken)&lt;br /&gt;
&lt;br /&gt;
==Configuring CVS==&lt;br /&gt;
&lt;br /&gt;
Once the below changes are made, you will need to log out and log back in to make them take effect.&lt;br /&gt;
&lt;br /&gt;
===Bourne-Again Shell (bash)===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.bashrc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;~/.bash_profile&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export CVS_RSH=/usr/bin/ssh&lt;br /&gt;
export CVSROOT=:ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also need to change the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; value to the correct absolute path to your &amp;lt;code&amp;gt;ssh&amp;lt;/code&amp;gt; binary. You can find this information using &amp;lt;code&amp;gt;which ssh&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===C Shell===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.cshrc&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setenv CVS_RSH /usr/bin/ssh&lt;br /&gt;
setenv CVSROOT :ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Fetching FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
To fetch the latest FreeM source code for the first time, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this fails, make sure you have the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CVSROOT&amp;lt;/code&amp;gt; environment variables correctly configured.&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
In the directory containing the FreeM source code, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Adding Files to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands from the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory, substituting the path and filename (relative to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory) for &amp;lt;code&amp;gt;&amp;amp;lt;filename&amp;amp;gt;&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs add &amp;lt;filename&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Committing Changes and Pushing to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands ''from the parent directory of the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory'', replacing &amp;lt;code&amp;gt;commit-message&amp;lt;/code&amp;gt; with a message describing the change:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs ci -m &amp;quot;commit-message&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Building FreeM=&lt;br /&gt;
&lt;br /&gt;
Please see [[:Category:Platform Notes]] for any additional notes unique to your platform.&lt;br /&gt;
&lt;br /&gt;
Note that the autotools &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; will place FreeM in &amp;lt;code&amp;gt;/usr/local&amp;lt;/code&amp;gt; by default on most platforms. This conflicts with binary packages on Solaris.&lt;br /&gt;
&lt;br /&gt;
==Initial Build==&lt;br /&gt;
This applies to the first build after you've obtained the FreeM source code.&lt;br /&gt;
&lt;br /&gt;
Follow these steps for the initial build:&lt;br /&gt;
&lt;br /&gt;
# Change directories to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; repository&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./autogen.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./configure&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;sudo make install&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you have done the initial build, most changes shouldn't require more than a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Subsequent Builds==&lt;br /&gt;
Most subsequent builds will just need a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;. See the following paragraphs for caveats.&lt;br /&gt;
&lt;br /&gt;
===When to run autogen.sh===&lt;br /&gt;
The &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; script is simply a shorthand for &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You will need to run &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; only if you change any &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; files. Even then, a fresh &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; will generally check to see if your generated autoconf/automake files are older than &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; and do this step for you automatically.&lt;br /&gt;
&lt;br /&gt;
===When to run make install===&lt;br /&gt;
You should only need to run &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; in the following scenarios:&lt;br /&gt;
&lt;br /&gt;
* You've changed the way the environment catalog (&amp;lt;code&amp;gt;env.conf&amp;lt;/code&amp;gt;) or environment configuration files (&amp;lt;code&amp;gt;freem.conf&amp;lt;/code&amp;gt;) work&lt;br /&gt;
* You've modified a vendor routine in the &amp;lt;code&amp;gt;mlib/&amp;lt;/code&amp;gt; directory&lt;br /&gt;
&lt;br /&gt;
Other than these scenarios, you should be able to run the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;fmadm&amp;lt;/code&amp;gt; binaries out of the repository directory hierarchy.&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=385</id>
		<title>Contributor Guide</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=385"/>
		<updated>2025-04-05T22:10:14Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Building FreeM */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
This article describes the facilities, methods, and commands used to contribute to the FreeM project.&lt;br /&gt;
&lt;br /&gt;
=For All Developers=&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
In order to contribute to FreeM, you must agree to abide by both the [[Code of Conduct]] and the [[General Policies]]. Your code must also conform to the style standards laid out in Appendix F of [https://freem.coherent-logic.com/docs/0.61.2/freem.html The FreeM Manual].&lt;br /&gt;
&lt;br /&gt;
You will also need to have &amp;lt;code&amp;gt;cvs&amp;lt;/code&amp;gt; installed on your machine. This is available in the package repositories of all popular Linux and UNIX operating systems.&lt;br /&gt;
&lt;br /&gt;
==Language==&lt;br /&gt;
All contributions to FreeM proper must be written in C. Bourne shell scripts are permissible where appropriate, and of course M code for the &amp;lt;code&amp;gt;mlib&amp;lt;/code&amp;gt; routines.&lt;br /&gt;
&lt;br /&gt;
===C Standard===&lt;br /&gt;
* FreeM contributions must not use language features unavailable in C89&lt;br /&gt;
* Vendor extensions in C compilers (like GNU extensions) are only permitted if guarded by preprocessor macros, and should be avoided if possible&lt;br /&gt;
* Contributions must be backwards compatible with gcc 2.95.3 (the oldest compiler we support)&lt;br /&gt;
* Contributions must not break compiles on Sun &amp;lt;code&amp;gt;cc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;clang&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Autotools===&lt;br /&gt;
* Contributions to &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; configuration must not use &amp;lt;code&amp;gt;pkg-config&amp;lt;/code&amp;gt;, as it is unavailable on some of our target platforms&lt;br /&gt;
* Target &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; 2.54 and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; 1.7.1 for compatibility&lt;br /&gt;
&lt;br /&gt;
=Anonymous CVS Access=&lt;br /&gt;
&lt;br /&gt;
==Getting Source Code from CVS==&lt;br /&gt;
To fetch the latest FreeM source code from CVS, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
To update a previously-fetched copy of FreeM source code, go into the directory in which FreeM is located, and run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Submitting Changes Without CVS Write Access==&lt;br /&gt;
To submit a change to FreeM as an anonymous user (i.e., a user without writer access to the FreeM CVS repository), generate a &amp;lt;code&amp;gt;.patch&amp;lt;/code&amp;gt; file using the &amp;lt;code&amp;gt;diff&amp;lt;/code&amp;gt; utility, and send it to &amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt; (you must be subscribed to the mailing list), along with a description containing the following information:&lt;br /&gt;
&lt;br /&gt;
* What bug your patch fixes, or feature it implements&lt;br /&gt;
* Your full preferred name (this will be used in order to credit you for your work)&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
&lt;br /&gt;
Each patch should address no more than one bug fix or feature addition. Patches that do not comply with this requirement will be kicked back to the developer for revision.&lt;br /&gt;
&lt;br /&gt;
=CVS Writer Access=&lt;br /&gt;
&lt;br /&gt;
==Requesting Writer Access==&lt;br /&gt;
&lt;br /&gt;
In order to get CVS writer access, you will need to have either a track record of submitting good patches, or be an existing member of the core team. If you meet this criteria, please send a request to &lt;br /&gt;
&amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt;, including the following information:&lt;br /&gt;
&lt;br /&gt;
* Your full preferred name&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
* The username you would like to use for access to our CVS server (we will do our best to accommodate, but you may be required to choose a different username if your preferred username is already taken)&lt;br /&gt;
&lt;br /&gt;
==Configuring CVS==&lt;br /&gt;
&lt;br /&gt;
Once the below changes are made, you will need to log out and log back in to make them take effect.&lt;br /&gt;
&lt;br /&gt;
===Bourne-Again Shell (bash)===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.bashrc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;~/.bash_profile&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export CVS_RSH=/usr/bin/ssh&lt;br /&gt;
export CVSROOT=:ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also need to change the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; value to the correct absolute path to your &amp;lt;code&amp;gt;ssh&amp;lt;/code&amp;gt; binary. You can find this information using &amp;lt;code&amp;gt;which ssh&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===C Shell===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.cshrc&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setenv CVS_RSH /usr/bin/ssh&lt;br /&gt;
setenv CVSROOT :ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Fetching FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
To fetch the latest FreeM source code for the first time, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this fails, make sure you have the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CVSROOT&amp;lt;/code&amp;gt; environment variables correctly configured.&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
In the directory containing the FreeM source code, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Adding Files to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands from the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory, substituting the path and filename (relative to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory) for &amp;lt;code&amp;gt;&amp;amp;lt;filename&amp;amp;gt;&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs add &amp;lt;filename&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Committing Changes and Pushing to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands ''from the parent directory of the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory'', replacing &amp;lt;code&amp;gt;commit-message&amp;lt;/code&amp;gt; with a message describing the change:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs ci -m &amp;quot;commit-message&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Building FreeM=&lt;br /&gt;
&lt;br /&gt;
Please see [[:Category:Platform Notes]] for any additional notes unique to your platform.&lt;br /&gt;
&lt;br /&gt;
==Initial Build==&lt;br /&gt;
This applies to the first build after you've obtained the FreeM source code.&lt;br /&gt;
&lt;br /&gt;
Follow these steps for the initial build:&lt;br /&gt;
&lt;br /&gt;
# Change directories to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; repository&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./autogen.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./configure&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;sudo make install&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you have done the initial build, most changes shouldn't require more than a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Subsequent Builds==&lt;br /&gt;
Most subsequent builds will just need a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;. See the following paragraphs for caveats.&lt;br /&gt;
&lt;br /&gt;
===When to run autogen.sh===&lt;br /&gt;
The &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; script is simply a shorthand for &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You will need to run &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; only if you change any &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; files. Even then, a fresh &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; will generally check to see if your generated autoconf/automake files are older than &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; and do this step for you automatically.&lt;br /&gt;
&lt;br /&gt;
===When to run make install===&lt;br /&gt;
You should only need to run &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; in the following scenarios:&lt;br /&gt;
&lt;br /&gt;
* You've changed the way the environment catalog (&amp;lt;code&amp;gt;env.conf&amp;lt;/code&amp;gt;) or environment configuration files (&amp;lt;code&amp;gt;freem.conf&amp;lt;/code&amp;gt;) work&lt;br /&gt;
* You've modified a vendor routine in the &amp;lt;code&amp;gt;mlib/&amp;lt;/code&amp;gt; directory&lt;br /&gt;
&lt;br /&gt;
Other than these scenarios, you should be able to run the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;fmadm&amp;lt;/code&amp;gt; binaries out of the repository directory hierarchy.&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=384</id>
		<title>Contributor Guide</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=384"/>
		<updated>2025-04-05T22:09:49Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Building FreeM */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
This article describes the facilities, methods, and commands used to contribute to the FreeM project.&lt;br /&gt;
&lt;br /&gt;
=For All Developers=&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
In order to contribute to FreeM, you must agree to abide by both the [[Code of Conduct]] and the [[General Policies]]. Your code must also conform to the style standards laid out in Appendix F of [https://freem.coherent-logic.com/docs/0.61.2/freem.html The FreeM Manual].&lt;br /&gt;
&lt;br /&gt;
You will also need to have &amp;lt;code&amp;gt;cvs&amp;lt;/code&amp;gt; installed on your machine. This is available in the package repositories of all popular Linux and UNIX operating systems.&lt;br /&gt;
&lt;br /&gt;
==Language==&lt;br /&gt;
All contributions to FreeM proper must be written in C. Bourne shell scripts are permissible where appropriate, and of course M code for the &amp;lt;code&amp;gt;mlib&amp;lt;/code&amp;gt; routines.&lt;br /&gt;
&lt;br /&gt;
===C Standard===&lt;br /&gt;
* FreeM contributions must not use language features unavailable in C89&lt;br /&gt;
* Vendor extensions in C compilers (like GNU extensions) are only permitted if guarded by preprocessor macros, and should be avoided if possible&lt;br /&gt;
* Contributions must be backwards compatible with gcc 2.95.3 (the oldest compiler we support)&lt;br /&gt;
* Contributions must not break compiles on Sun &amp;lt;code&amp;gt;cc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;clang&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Autotools===&lt;br /&gt;
* Contributions to &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; configuration must not use &amp;lt;code&amp;gt;pkg-config&amp;lt;/code&amp;gt;, as it is unavailable on some of our target platforms&lt;br /&gt;
* Target &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; 2.54 and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; 1.7.1 for compatibility&lt;br /&gt;
&lt;br /&gt;
=Anonymous CVS Access=&lt;br /&gt;
&lt;br /&gt;
==Getting Source Code from CVS==&lt;br /&gt;
To fetch the latest FreeM source code from CVS, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
To update a previously-fetched copy of FreeM source code, go into the directory in which FreeM is located, and run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Submitting Changes Without CVS Write Access==&lt;br /&gt;
To submit a change to FreeM as an anonymous user (i.e., a user without writer access to the FreeM CVS repository), generate a &amp;lt;code&amp;gt;.patch&amp;lt;/code&amp;gt; file using the &amp;lt;code&amp;gt;diff&amp;lt;/code&amp;gt; utility, and send it to &amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt; (you must be subscribed to the mailing list), along with a description containing the following information:&lt;br /&gt;
&lt;br /&gt;
* What bug your patch fixes, or feature it implements&lt;br /&gt;
* Your full preferred name (this will be used in order to credit you for your work)&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
&lt;br /&gt;
Each patch should address no more than one bug fix or feature addition. Patches that do not comply with this requirement will be kicked back to the developer for revision.&lt;br /&gt;
&lt;br /&gt;
=CVS Writer Access=&lt;br /&gt;
&lt;br /&gt;
==Requesting Writer Access==&lt;br /&gt;
&lt;br /&gt;
In order to get CVS writer access, you will need to have either a track record of submitting good patches, or be an existing member of the core team. If you meet this criteria, please send a request to &lt;br /&gt;
&amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt;, including the following information:&lt;br /&gt;
&lt;br /&gt;
* Your full preferred name&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
* The username you would like to use for access to our CVS server (we will do our best to accommodate, but you may be required to choose a different username if your preferred username is already taken)&lt;br /&gt;
&lt;br /&gt;
==Configuring CVS==&lt;br /&gt;
&lt;br /&gt;
Once the below changes are made, you will need to log out and log back in to make them take effect.&lt;br /&gt;
&lt;br /&gt;
===Bourne-Again Shell (bash)===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.bashrc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;~/.bash_profile&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export CVS_RSH=/usr/bin/ssh&lt;br /&gt;
export CVSROOT=:ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also need to change the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; value to the correct absolute path to your &amp;lt;code&amp;gt;ssh&amp;lt;/code&amp;gt; binary. You can find this information using &amp;lt;code&amp;gt;which ssh&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===C Shell===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.cshrc&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setenv CVS_RSH /usr/bin/ssh&lt;br /&gt;
setenv CVSROOT :ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Fetching FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
To fetch the latest FreeM source code for the first time, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this fails, make sure you have the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CVSROOT&amp;lt;/code&amp;gt; environment variables correctly configured.&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
In the directory containing the FreeM source code, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Adding Files to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands from the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory, substituting the path and filename (relative to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory) for &amp;lt;code&amp;gt;&amp;amp;lt;filename&amp;amp;gt;&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs add &amp;lt;filename&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Committing Changes and Pushing to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands ''from the parent directory of the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory'', replacing &amp;lt;code&amp;gt;commit-message&amp;lt;/code&amp;gt; with a message describing the change:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs ci -m &amp;quot;commit-message&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Building FreeM=&lt;br /&gt;
&lt;br /&gt;
Please see [[Category:Platform_Notes]] for any additional notes unique to your platform.&lt;br /&gt;
&lt;br /&gt;
==Initial Build==&lt;br /&gt;
This applies to the first build after you've obtained the FreeM source code.&lt;br /&gt;
&lt;br /&gt;
Follow these steps for the initial build:&lt;br /&gt;
&lt;br /&gt;
# Change directories to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; repository&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./autogen.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./configure&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;sudo make install&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you have done the initial build, most changes shouldn't require more than a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Subsequent Builds==&lt;br /&gt;
Most subsequent builds will just need a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;. See the following paragraphs for caveats.&lt;br /&gt;
&lt;br /&gt;
===When to run autogen.sh===&lt;br /&gt;
The &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; script is simply a shorthand for &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You will need to run &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; only if you change any &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; files. Even then, a fresh &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; will generally check to see if your generated autoconf/automake files are older than &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; and do this step for you automatically.&lt;br /&gt;
&lt;br /&gt;
===When to run make install===&lt;br /&gt;
You should only need to run &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; in the following scenarios:&lt;br /&gt;
&lt;br /&gt;
* You've changed the way the environment catalog (&amp;lt;code&amp;gt;env.conf&amp;lt;/code&amp;gt;) or environment configuration files (&amp;lt;code&amp;gt;freem.conf&amp;lt;/code&amp;gt;) work&lt;br /&gt;
* You've modified a vendor routine in the &amp;lt;code&amp;gt;mlib/&amp;lt;/code&amp;gt; directory&lt;br /&gt;
&lt;br /&gt;
Other than these scenarios, you should be able to run the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;fmadm&amp;lt;/code&amp;gt; binaries out of the repository directory hierarchy.&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=383</id>
		<title>Contributor Guide</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=383"/>
		<updated>2025-04-05T22:09:14Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Building FreeM */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
This article describes the facilities, methods, and commands used to contribute to the FreeM project.&lt;br /&gt;
&lt;br /&gt;
=For All Developers=&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
In order to contribute to FreeM, you must agree to abide by both the [[Code of Conduct]] and the [[General Policies]]. Your code must also conform to the style standards laid out in Appendix F of [https://freem.coherent-logic.com/docs/0.61.2/freem.html The FreeM Manual].&lt;br /&gt;
&lt;br /&gt;
You will also need to have &amp;lt;code&amp;gt;cvs&amp;lt;/code&amp;gt; installed on your machine. This is available in the package repositories of all popular Linux and UNIX operating systems.&lt;br /&gt;
&lt;br /&gt;
==Language==&lt;br /&gt;
All contributions to FreeM proper must be written in C. Bourne shell scripts are permissible where appropriate, and of course M code for the &amp;lt;code&amp;gt;mlib&amp;lt;/code&amp;gt; routines.&lt;br /&gt;
&lt;br /&gt;
===C Standard===&lt;br /&gt;
* FreeM contributions must not use language features unavailable in C89&lt;br /&gt;
* Vendor extensions in C compilers (like GNU extensions) are only permitted if guarded by preprocessor macros, and should be avoided if possible&lt;br /&gt;
* Contributions must be backwards compatible with gcc 2.95.3 (the oldest compiler we support)&lt;br /&gt;
* Contributions must not break compiles on Sun &amp;lt;code&amp;gt;cc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;clang&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Autotools===&lt;br /&gt;
* Contributions to &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; configuration must not use &amp;lt;code&amp;gt;pkg-config&amp;lt;/code&amp;gt;, as it is unavailable on some of our target platforms&lt;br /&gt;
* Target &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; 2.54 and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; 1.7.1 for compatibility&lt;br /&gt;
&lt;br /&gt;
=Anonymous CVS Access=&lt;br /&gt;
&lt;br /&gt;
==Getting Source Code from CVS==&lt;br /&gt;
To fetch the latest FreeM source code from CVS, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
To update a previously-fetched copy of FreeM source code, go into the directory in which FreeM is located, and run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Submitting Changes Without CVS Write Access==&lt;br /&gt;
To submit a change to FreeM as an anonymous user (i.e., a user without writer access to the FreeM CVS repository), generate a &amp;lt;code&amp;gt;.patch&amp;lt;/code&amp;gt; file using the &amp;lt;code&amp;gt;diff&amp;lt;/code&amp;gt; utility, and send it to &amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt; (you must be subscribed to the mailing list), along with a description containing the following information:&lt;br /&gt;
&lt;br /&gt;
* What bug your patch fixes, or feature it implements&lt;br /&gt;
* Your full preferred name (this will be used in order to credit you for your work)&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
&lt;br /&gt;
Each patch should address no more than one bug fix or feature addition. Patches that do not comply with this requirement will be kicked back to the developer for revision.&lt;br /&gt;
&lt;br /&gt;
=CVS Writer Access=&lt;br /&gt;
&lt;br /&gt;
==Requesting Writer Access==&lt;br /&gt;
&lt;br /&gt;
In order to get CVS writer access, you will need to have either a track record of submitting good patches, or be an existing member of the core team. If you meet this criteria, please send a request to &lt;br /&gt;
&amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt;, including the following information:&lt;br /&gt;
&lt;br /&gt;
* Your full preferred name&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
* The username you would like to use for access to our CVS server (we will do our best to accommodate, but you may be required to choose a different username if your preferred username is already taken)&lt;br /&gt;
&lt;br /&gt;
==Configuring CVS==&lt;br /&gt;
&lt;br /&gt;
Once the below changes are made, you will need to log out and log back in to make them take effect.&lt;br /&gt;
&lt;br /&gt;
===Bourne-Again Shell (bash)===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.bashrc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;~/.bash_profile&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export CVS_RSH=/usr/bin/ssh&lt;br /&gt;
export CVSROOT=:ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also need to change the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; value to the correct absolute path to your &amp;lt;code&amp;gt;ssh&amp;lt;/code&amp;gt; binary. You can find this information using &amp;lt;code&amp;gt;which ssh&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===C Shell===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.cshrc&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setenv CVS_RSH /usr/bin/ssh&lt;br /&gt;
setenv CVSROOT :ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Fetching FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
To fetch the latest FreeM source code for the first time, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this fails, make sure you have the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CVSROOT&amp;lt;/code&amp;gt; environment variables correctly configured.&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
In the directory containing the FreeM source code, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Adding Files to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands from the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory, substituting the path and filename (relative to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory) for &amp;lt;code&amp;gt;&amp;amp;lt;filename&amp;amp;gt;&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs add &amp;lt;filename&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Committing Changes and Pushing to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands ''from the parent directory of the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory'', replacing &amp;lt;code&amp;gt;commit-message&amp;lt;/code&amp;gt; with a message describing the change:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs ci -m &amp;quot;commit-message&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Building FreeM=&lt;br /&gt;
&lt;br /&gt;
Please see [[Category:Platform Notes]] for any additional notes unique to your platform.&lt;br /&gt;
&lt;br /&gt;
==Initial Build==&lt;br /&gt;
This applies to the first build after you've obtained the FreeM source code.&lt;br /&gt;
&lt;br /&gt;
Follow these steps for the initial build:&lt;br /&gt;
&lt;br /&gt;
# Change directories to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; repository&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./autogen.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./configure&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;sudo make install&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you have done the initial build, most changes shouldn't require more than a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Subsequent Builds==&lt;br /&gt;
Most subsequent builds will just need a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;. See the following paragraphs for caveats.&lt;br /&gt;
&lt;br /&gt;
===When to run autogen.sh===&lt;br /&gt;
The &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; script is simply a shorthand for &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You will need to run &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; only if you change any &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; files. Even then, a fresh &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; will generally check to see if your generated autoconf/automake files are older than &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; and do this step for you automatically.&lt;br /&gt;
&lt;br /&gt;
===When to run make install===&lt;br /&gt;
You should only need to run &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; in the following scenarios:&lt;br /&gt;
&lt;br /&gt;
* You've changed the way the environment catalog (&amp;lt;code&amp;gt;env.conf&amp;lt;/code&amp;gt;) or environment configuration files (&amp;lt;code&amp;gt;freem.conf&amp;lt;/code&amp;gt;) work&lt;br /&gt;
* You've modified a vendor routine in the &amp;lt;code&amp;gt;mlib/&amp;lt;/code&amp;gt; directory&lt;br /&gt;
&lt;br /&gt;
Other than these scenarios, you should be able to run the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;fmadm&amp;lt;/code&amp;gt; binaries out of the repository directory hierarchy.&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=382</id>
		<title>Contributor Guide</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=382"/>
		<updated>2025-04-05T22:08:04Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Building FreeM */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
This article describes the facilities, methods, and commands used to contribute to the FreeM project.&lt;br /&gt;
&lt;br /&gt;
=For All Developers=&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
In order to contribute to FreeM, you must agree to abide by both the [[Code of Conduct]] and the [[General Policies]]. Your code must also conform to the style standards laid out in Appendix F of [https://freem.coherent-logic.com/docs/0.61.2/freem.html The FreeM Manual].&lt;br /&gt;
&lt;br /&gt;
You will also need to have &amp;lt;code&amp;gt;cvs&amp;lt;/code&amp;gt; installed on your machine. This is available in the package repositories of all popular Linux and UNIX operating systems.&lt;br /&gt;
&lt;br /&gt;
==Language==&lt;br /&gt;
All contributions to FreeM proper must be written in C. Bourne shell scripts are permissible where appropriate, and of course M code for the &amp;lt;code&amp;gt;mlib&amp;lt;/code&amp;gt; routines.&lt;br /&gt;
&lt;br /&gt;
===C Standard===&lt;br /&gt;
* FreeM contributions must not use language features unavailable in C89&lt;br /&gt;
* Vendor extensions in C compilers (like GNU extensions) are only permitted if guarded by preprocessor macros, and should be avoided if possible&lt;br /&gt;
* Contributions must be backwards compatible with gcc 2.95.3 (the oldest compiler we support)&lt;br /&gt;
* Contributions must not break compiles on Sun &amp;lt;code&amp;gt;cc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;clang&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Autotools===&lt;br /&gt;
* Contributions to &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; configuration must not use &amp;lt;code&amp;gt;pkg-config&amp;lt;/code&amp;gt;, as it is unavailable on some of our target platforms&lt;br /&gt;
* Target &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; 2.54 and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; 1.7.1 for compatibility&lt;br /&gt;
&lt;br /&gt;
=Anonymous CVS Access=&lt;br /&gt;
&lt;br /&gt;
==Getting Source Code from CVS==&lt;br /&gt;
To fetch the latest FreeM source code from CVS, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
To update a previously-fetched copy of FreeM source code, go into the directory in which FreeM is located, and run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Submitting Changes Without CVS Write Access==&lt;br /&gt;
To submit a change to FreeM as an anonymous user (i.e., a user without writer access to the FreeM CVS repository), generate a &amp;lt;code&amp;gt;.patch&amp;lt;/code&amp;gt; file using the &amp;lt;code&amp;gt;diff&amp;lt;/code&amp;gt; utility, and send it to &amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt; (you must be subscribed to the mailing list), along with a description containing the following information:&lt;br /&gt;
&lt;br /&gt;
* What bug your patch fixes, or feature it implements&lt;br /&gt;
* Your full preferred name (this will be used in order to credit you for your work)&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
&lt;br /&gt;
Each patch should address no more than one bug fix or feature addition. Patches that do not comply with this requirement will be kicked back to the developer for revision.&lt;br /&gt;
&lt;br /&gt;
=CVS Writer Access=&lt;br /&gt;
&lt;br /&gt;
==Requesting Writer Access==&lt;br /&gt;
&lt;br /&gt;
In order to get CVS writer access, you will need to have either a track record of submitting good patches, or be an existing member of the core team. If you meet this criteria, please send a request to &lt;br /&gt;
&amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt;, including the following information:&lt;br /&gt;
&lt;br /&gt;
* Your full preferred name&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
* The username you would like to use for access to our CVS server (we will do our best to accommodate, but you may be required to choose a different username if your preferred username is already taken)&lt;br /&gt;
&lt;br /&gt;
==Configuring CVS==&lt;br /&gt;
&lt;br /&gt;
Once the below changes are made, you will need to log out and log back in to make them take effect.&lt;br /&gt;
&lt;br /&gt;
===Bourne-Again Shell (bash)===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.bashrc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;~/.bash_profile&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export CVS_RSH=/usr/bin/ssh&lt;br /&gt;
export CVSROOT=:ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also need to change the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; value to the correct absolute path to your &amp;lt;code&amp;gt;ssh&amp;lt;/code&amp;gt; binary. You can find this information using &amp;lt;code&amp;gt;which ssh&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===C Shell===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.cshrc&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setenv CVS_RSH /usr/bin/ssh&lt;br /&gt;
setenv CVSROOT :ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Fetching FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
To fetch the latest FreeM source code for the first time, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this fails, make sure you have the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CVSROOT&amp;lt;/code&amp;gt; environment variables correctly configured.&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
In the directory containing the FreeM source code, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Adding Files to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands from the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory, substituting the path and filename (relative to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory) for &amp;lt;code&amp;gt;&amp;amp;lt;filename&amp;amp;gt;&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs add &amp;lt;filename&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Committing Changes and Pushing to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands ''from the parent directory of the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory'', replacing &amp;lt;code&amp;gt;commit-message&amp;lt;/code&amp;gt; with a message describing the change:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs ci -m &amp;quot;commit-message&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Building FreeM=&lt;br /&gt;
&lt;br /&gt;
Please see [Category:Platform Notes] for any additional notes unique to your platform.&lt;br /&gt;
&lt;br /&gt;
==Initial Build==&lt;br /&gt;
This applies to the first build after you've obtained the FreeM source code.&lt;br /&gt;
&lt;br /&gt;
Follow these steps for the initial build:&lt;br /&gt;
&lt;br /&gt;
# Change directories to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; repository&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./autogen.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./configure&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;sudo make install&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you have done the initial build, most changes shouldn't require more than a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Subsequent Builds==&lt;br /&gt;
Most subsequent builds will just need a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;. See the following paragraphs for caveats.&lt;br /&gt;
&lt;br /&gt;
===When to run autogen.sh===&lt;br /&gt;
The &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; script is simply a shorthand for &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You will need to run &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; only if you change any &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; files. Even then, a fresh &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; will generally check to see if your generated autoconf/automake files are older than &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; and do this step for you automatically.&lt;br /&gt;
&lt;br /&gt;
===When to run make install===&lt;br /&gt;
You should only need to run &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; in the following scenarios:&lt;br /&gt;
&lt;br /&gt;
* You've changed the way the environment catalog (&amp;lt;code&amp;gt;env.conf&amp;lt;/code&amp;gt;) or environment configuration files (&amp;lt;code&amp;gt;freem.conf&amp;lt;/code&amp;gt;) work&lt;br /&gt;
* You've modified a vendor routine in the &amp;lt;code&amp;gt;mlib/&amp;lt;/code&amp;gt; directory&lt;br /&gt;
&lt;br /&gt;
Other than these scenarios, you should be able to run the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;fmadm&amp;lt;/code&amp;gt; binaries out of the repository directory hierarchy.&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=381</id>
		<title>Contributor Guide</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=381"/>
		<updated>2025-04-05T22:07:46Z</updated>

		<summary type="html">&lt;p&gt;Smw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
This article describes the facilities, methods, and commands used to contribute to the FreeM project.&lt;br /&gt;
&lt;br /&gt;
=For All Developers=&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
In order to contribute to FreeM, you must agree to abide by both the [[Code of Conduct]] and the [[General Policies]]. Your code must also conform to the style standards laid out in Appendix F of [https://freem.coherent-logic.com/docs/0.61.2/freem.html The FreeM Manual].&lt;br /&gt;
&lt;br /&gt;
You will also need to have &amp;lt;code&amp;gt;cvs&amp;lt;/code&amp;gt; installed on your machine. This is available in the package repositories of all popular Linux and UNIX operating systems.&lt;br /&gt;
&lt;br /&gt;
==Language==&lt;br /&gt;
All contributions to FreeM proper must be written in C. Bourne shell scripts are permissible where appropriate, and of course M code for the &amp;lt;code&amp;gt;mlib&amp;lt;/code&amp;gt; routines.&lt;br /&gt;
&lt;br /&gt;
===C Standard===&lt;br /&gt;
* FreeM contributions must not use language features unavailable in C89&lt;br /&gt;
* Vendor extensions in C compilers (like GNU extensions) are only permitted if guarded by preprocessor macros, and should be avoided if possible&lt;br /&gt;
* Contributions must be backwards compatible with gcc 2.95.3 (the oldest compiler we support)&lt;br /&gt;
* Contributions must not break compiles on Sun &amp;lt;code&amp;gt;cc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;clang&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Autotools===&lt;br /&gt;
* Contributions to &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; configuration must not use &amp;lt;code&amp;gt;pkg-config&amp;lt;/code&amp;gt;, as it is unavailable on some of our target platforms&lt;br /&gt;
* Target &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; 2.54 and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; 1.7.1 for compatibility&lt;br /&gt;
&lt;br /&gt;
=Anonymous CVS Access=&lt;br /&gt;
&lt;br /&gt;
==Getting Source Code from CVS==&lt;br /&gt;
To fetch the latest FreeM source code from CVS, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
To update a previously-fetched copy of FreeM source code, go into the directory in which FreeM is located, and run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Submitting Changes Without CVS Write Access==&lt;br /&gt;
To submit a change to FreeM as an anonymous user (i.e., a user without writer access to the FreeM CVS repository), generate a &amp;lt;code&amp;gt;.patch&amp;lt;/code&amp;gt; file using the &amp;lt;code&amp;gt;diff&amp;lt;/code&amp;gt; utility, and send it to &amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt; (you must be subscribed to the mailing list), along with a description containing the following information:&lt;br /&gt;
&lt;br /&gt;
* What bug your patch fixes, or feature it implements&lt;br /&gt;
* Your full preferred name (this will be used in order to credit you for your work)&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
&lt;br /&gt;
Each patch should address no more than one bug fix or feature addition. Patches that do not comply with this requirement will be kicked back to the developer for revision.&lt;br /&gt;
&lt;br /&gt;
=CVS Writer Access=&lt;br /&gt;
&lt;br /&gt;
==Requesting Writer Access==&lt;br /&gt;
&lt;br /&gt;
In order to get CVS writer access, you will need to have either a track record of submitting good patches, or be an existing member of the core team. If you meet this criteria, please send a request to &lt;br /&gt;
&amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt;, including the following information:&lt;br /&gt;
&lt;br /&gt;
* Your full preferred name&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
* The username you would like to use for access to our CVS server (we will do our best to accommodate, but you may be required to choose a different username if your preferred username is already taken)&lt;br /&gt;
&lt;br /&gt;
==Configuring CVS==&lt;br /&gt;
&lt;br /&gt;
Once the below changes are made, you will need to log out and log back in to make them take effect.&lt;br /&gt;
&lt;br /&gt;
===Bourne-Again Shell (bash)===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.bashrc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;~/.bash_profile&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export CVS_RSH=/usr/bin/ssh&lt;br /&gt;
export CVSROOT=:ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also need to change the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; value to the correct absolute path to your &amp;lt;code&amp;gt;ssh&amp;lt;/code&amp;gt; binary. You can find this information using &amp;lt;code&amp;gt;which ssh&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===C Shell===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.cshrc&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setenv CVS_RSH /usr/bin/ssh&lt;br /&gt;
setenv CVSROOT :ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Fetching FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
To fetch the latest FreeM source code for the first time, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this fails, make sure you have the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CVSROOT&amp;lt;/code&amp;gt; environment variables correctly configured.&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
In the directory containing the FreeM source code, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Adding Files to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands from the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory, substituting the path and filename (relative to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory) for &amp;lt;code&amp;gt;&amp;amp;lt;filename&amp;amp;gt;&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs add &amp;lt;filename&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Committing Changes and Pushing to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands ''from the parent directory of the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory'', replacing &amp;lt;code&amp;gt;commit-message&amp;lt;/code&amp;gt; with a message describing the change:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs ci -m &amp;quot;commit-message&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Building FreeM=&lt;br /&gt;
&lt;br /&gt;
Please see [[Category:Platform Notes]] for any additional notes unique to your platform.&lt;br /&gt;
&lt;br /&gt;
==Initial Build==&lt;br /&gt;
This applies to the first build after you've obtained the FreeM source code.&lt;br /&gt;
&lt;br /&gt;
Follow these steps for the initial build:&lt;br /&gt;
&lt;br /&gt;
# Change directories to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; repository&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./autogen.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./configure&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;sudo make install&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you have done the initial build, most changes shouldn't require more than a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Subsequent Builds==&lt;br /&gt;
Most subsequent builds will just need a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;. See the following paragraphs for caveats.&lt;br /&gt;
&lt;br /&gt;
===When to run autogen.sh===&lt;br /&gt;
The &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; script is simply a shorthand for &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You will need to run &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; only if you change any &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; files. Even then, a fresh &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; will generally check to see if your generated autoconf/automake files are older than &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; and do this step for you automatically.&lt;br /&gt;
&lt;br /&gt;
===When to run make install===&lt;br /&gt;
You should only need to run &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; in the following scenarios:&lt;br /&gt;
&lt;br /&gt;
* You've changed the way the environment catalog (&amp;lt;code&amp;gt;env.conf&amp;lt;/code&amp;gt;) or environment configuration files (&amp;lt;code&amp;gt;freem.conf&amp;lt;/code&amp;gt;) work&lt;br /&gt;
* You've modified a vendor routine in the &amp;lt;code&amp;gt;mlib/&amp;lt;/code&amp;gt; directory&lt;br /&gt;
&lt;br /&gt;
Other than these scenarios, you should be able to run the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;fmadm&amp;lt;/code&amp;gt; binaries out of the repository directory hierarchy.&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=380</id>
		<title>Contributor Guide</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=380"/>
		<updated>2025-04-05T22:04:05Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Initial Build */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
This article describes the facilities, methods, and commands used to contribute to the FreeM project.&lt;br /&gt;
&lt;br /&gt;
=For All Developers=&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
In order to contribute to FreeM, you must agree to abide by both the [[Code of Conduct]] and the [[General Policies]]. Your code must also conform to the style standards laid out in Appendix F of [https://freem.coherent-logic.com/docs/0.61.2/freem.html The FreeM Manual].&lt;br /&gt;
&lt;br /&gt;
You will also need to have &amp;lt;code&amp;gt;cvs&amp;lt;/code&amp;gt; installed on your machine. This is available in the package repositories of all popular Linux and UNIX operating systems.&lt;br /&gt;
&lt;br /&gt;
==Language==&lt;br /&gt;
All contributions to FreeM proper must be written in C. Bourne shell scripts are permissible where appropriate, and of course M code for the &amp;lt;code&amp;gt;mlib&amp;lt;/code&amp;gt; routines.&lt;br /&gt;
&lt;br /&gt;
===C Standard===&lt;br /&gt;
* FreeM contributions must not use language features unavailable in C89&lt;br /&gt;
* Vendor extensions in C compilers (like GNU extensions) are only permitted if guarded by preprocessor macros, and should be avoided if possible&lt;br /&gt;
* Contributions must be backwards compatible with gcc 2.95.3 (the oldest compiler we support)&lt;br /&gt;
* Contributions must not break compiles on Sun &amp;lt;code&amp;gt;cc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;clang&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Autotools===&lt;br /&gt;
* Contributions to &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; configuration must not use &amp;lt;code&amp;gt;pkg-config&amp;lt;/code&amp;gt;, as it is unavailable on some of our target platforms&lt;br /&gt;
* Target &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; 2.54 and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; 1.7.1 for compatibility&lt;br /&gt;
&lt;br /&gt;
=Anonymous CVS Access=&lt;br /&gt;
&lt;br /&gt;
==Getting Source Code from CVS==&lt;br /&gt;
To fetch the latest FreeM source code from CVS, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
To update a previously-fetched copy of FreeM source code, go into the directory in which FreeM is located, and run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Submitting Changes Without CVS Write Access==&lt;br /&gt;
To submit a change to FreeM as an anonymous user (i.e., a user without writer access to the FreeM CVS repository), generate a &amp;lt;code&amp;gt;.patch&amp;lt;/code&amp;gt; file using the &amp;lt;code&amp;gt;diff&amp;lt;/code&amp;gt; utility, and send it to &amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt; (you must be subscribed to the mailing list), along with a description containing the following information:&lt;br /&gt;
&lt;br /&gt;
* What bug your patch fixes, or feature it implements&lt;br /&gt;
* Your full preferred name (this will be used in order to credit you for your work)&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
&lt;br /&gt;
Each patch should address no more than one bug fix or feature addition. Patches that do not comply with this requirement will be kicked back to the developer for revision.&lt;br /&gt;
&lt;br /&gt;
=CVS Writer Access=&lt;br /&gt;
&lt;br /&gt;
==Requesting Writer Access==&lt;br /&gt;
&lt;br /&gt;
In order to get CVS writer access, you will need to have either a track record of submitting good patches, or be an existing member of the core team. If you meet this criteria, please send a request to &lt;br /&gt;
&amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt;, including the following information:&lt;br /&gt;
&lt;br /&gt;
* Your full preferred name&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
* The username you would like to use for access to our CVS server (we will do our best to accommodate, but you may be required to choose a different username if your preferred username is already taken)&lt;br /&gt;
&lt;br /&gt;
==Configuring CVS==&lt;br /&gt;
&lt;br /&gt;
Once the below changes are made, you will need to log out and log back in to make them take effect.&lt;br /&gt;
&lt;br /&gt;
===Bourne-Again Shell (bash)===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.bashrc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;~/.bash_profile&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export CVS_RSH=/usr/bin/ssh&lt;br /&gt;
export CVSROOT=:ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also need to change the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; value to the correct absolute path to your &amp;lt;code&amp;gt;ssh&amp;lt;/code&amp;gt; binary. You can find this information using &amp;lt;code&amp;gt;which ssh&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===C Shell===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.cshrc&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setenv CVS_RSH /usr/bin/ssh&lt;br /&gt;
setenv CVSROOT :ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Fetching FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
To fetch the latest FreeM source code for the first time, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this fails, make sure you have the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CVSROOT&amp;lt;/code&amp;gt; environment variables correctly configured.&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
In the directory containing the FreeM source code, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Adding Files to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands from the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory, substituting the path and filename (relative to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory) for &amp;lt;code&amp;gt;&amp;amp;lt;filename&amp;amp;gt;&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs add &amp;lt;filename&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Committing Changes and Pushing to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands ''from the parent directory of the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory'', replacing &amp;lt;code&amp;gt;commit-message&amp;lt;/code&amp;gt; with a message describing the change:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs ci -m &amp;quot;commit-message&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Building FreeM=&lt;br /&gt;
&lt;br /&gt;
==Initial Build==&lt;br /&gt;
This applies to the first build after you've obtained the FreeM source code.&lt;br /&gt;
&lt;br /&gt;
Follow these steps for the initial build:&lt;br /&gt;
&lt;br /&gt;
# Change directories to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; repository&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./autogen.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./configure&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;sudo make install&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you have done the initial build, most changes shouldn't require more than a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Subsequent Builds==&lt;br /&gt;
Most subsequent builds will just need a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;. See the following paragraphs for caveats.&lt;br /&gt;
&lt;br /&gt;
===When to run autogen.sh===&lt;br /&gt;
The &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; script is simply a shorthand for &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You will need to run &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; only if you change any &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; files. Even then, a fresh &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; will generally check to see if your generated autoconf/automake files are older than &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; and do this step for you automatically.&lt;br /&gt;
&lt;br /&gt;
===When to run make install===&lt;br /&gt;
You should only need to run &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; in the following scenarios:&lt;br /&gt;
&lt;br /&gt;
* You've changed the way the environment catalog (&amp;lt;code&amp;gt;env.conf&amp;lt;/code&amp;gt;) or environment configuration files (&amp;lt;code&amp;gt;freem.conf&amp;lt;/code&amp;gt;) work&lt;br /&gt;
* You've modified a vendor routine in the &amp;lt;code&amp;gt;mlib/&amp;lt;/code&amp;gt; directory&lt;br /&gt;
&lt;br /&gt;
Other than these scenarios, you should be able to run the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;fmadm&amp;lt;/code&amp;gt; binaries out of the repository directory hierarchy.&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=379</id>
		<title>Contributor Guide</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=379"/>
		<updated>2025-04-05T22:03:39Z</updated>

		<summary type="html">&lt;p&gt;Smw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
This article describes the facilities, methods, and commands used to contribute to the FreeM project.&lt;br /&gt;
&lt;br /&gt;
=For All Developers=&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
In order to contribute to FreeM, you must agree to abide by both the [[Code of Conduct]] and the [[General Policies]]. Your code must also conform to the style standards laid out in Appendix F of [https://freem.coherent-logic.com/docs/0.61.2/freem.html The FreeM Manual].&lt;br /&gt;
&lt;br /&gt;
You will also need to have &amp;lt;code&amp;gt;cvs&amp;lt;/code&amp;gt; installed on your machine. This is available in the package repositories of all popular Linux and UNIX operating systems.&lt;br /&gt;
&lt;br /&gt;
==Language==&lt;br /&gt;
All contributions to FreeM proper must be written in C. Bourne shell scripts are permissible where appropriate, and of course M code for the &amp;lt;code&amp;gt;mlib&amp;lt;/code&amp;gt; routines.&lt;br /&gt;
&lt;br /&gt;
===C Standard===&lt;br /&gt;
* FreeM contributions must not use language features unavailable in C89&lt;br /&gt;
* Vendor extensions in C compilers (like GNU extensions) are only permitted if guarded by preprocessor macros, and should be avoided if possible&lt;br /&gt;
* Contributions must be backwards compatible with gcc 2.95.3 (the oldest compiler we support)&lt;br /&gt;
* Contributions must not break compiles on Sun &amp;lt;code&amp;gt;cc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;clang&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Autotools===&lt;br /&gt;
* Contributions to &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; configuration must not use &amp;lt;code&amp;gt;pkg-config&amp;lt;/code&amp;gt;, as it is unavailable on some of our target platforms&lt;br /&gt;
* Target &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; 2.54 and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; 1.7.1 for compatibility&lt;br /&gt;
&lt;br /&gt;
=Anonymous CVS Access=&lt;br /&gt;
&lt;br /&gt;
==Getting Source Code from CVS==&lt;br /&gt;
To fetch the latest FreeM source code from CVS, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
To update a previously-fetched copy of FreeM source code, go into the directory in which FreeM is located, and run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Submitting Changes Without CVS Write Access==&lt;br /&gt;
To submit a change to FreeM as an anonymous user (i.e., a user without writer access to the FreeM CVS repository), generate a &amp;lt;code&amp;gt;.patch&amp;lt;/code&amp;gt; file using the &amp;lt;code&amp;gt;diff&amp;lt;/code&amp;gt; utility, and send it to &amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt; (you must be subscribed to the mailing list), along with a description containing the following information:&lt;br /&gt;
&lt;br /&gt;
* What bug your patch fixes, or feature it implements&lt;br /&gt;
* Your full preferred name (this will be used in order to credit you for your work)&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
&lt;br /&gt;
Each patch should address no more than one bug fix or feature addition. Patches that do not comply with this requirement will be kicked back to the developer for revision.&lt;br /&gt;
&lt;br /&gt;
=CVS Writer Access=&lt;br /&gt;
&lt;br /&gt;
==Requesting Writer Access==&lt;br /&gt;
&lt;br /&gt;
In order to get CVS writer access, you will need to have either a track record of submitting good patches, or be an existing member of the core team. If you meet this criteria, please send a request to &lt;br /&gt;
&amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt;, including the following information:&lt;br /&gt;
&lt;br /&gt;
* Your full preferred name&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
* The username you would like to use for access to our CVS server (we will do our best to accommodate, but you may be required to choose a different username if your preferred username is already taken)&lt;br /&gt;
&lt;br /&gt;
==Configuring CVS==&lt;br /&gt;
&lt;br /&gt;
Once the below changes are made, you will need to log out and log back in to make them take effect.&lt;br /&gt;
&lt;br /&gt;
===Bourne-Again Shell (bash)===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.bashrc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;~/.bash_profile&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export CVS_RSH=/usr/bin/ssh&lt;br /&gt;
export CVSROOT=:ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also need to change the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; value to the correct absolute path to your &amp;lt;code&amp;gt;ssh&amp;lt;/code&amp;gt; binary. You can find this information using &amp;lt;code&amp;gt;which ssh&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===C Shell===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.cshrc&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setenv CVS_RSH /usr/bin/ssh&lt;br /&gt;
setenv CVSROOT :ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Fetching FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
To fetch the latest FreeM source code for the first time, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this fails, make sure you have the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CVSROOT&amp;lt;/code&amp;gt; environment variables correctly configured.&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
In the directory containing the FreeM source code, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Adding Files to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands from the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory, substituting the path and filename (relative to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory) for &amp;lt;code&amp;gt;&amp;amp;lt;filename&amp;amp;gt;&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs add &amp;lt;filename&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Committing Changes and Pushing to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands ''from the parent directory of the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory'', replacing &amp;lt;code&amp;gt;commit-message&amp;lt;/code&amp;gt; with a message describing the change:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs ci -m &amp;quot;commit-message&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Building FreeM=&lt;br /&gt;
&lt;br /&gt;
==Initial Build==&lt;br /&gt;
Follow these steps for the initial build:&lt;br /&gt;
&lt;br /&gt;
# Change directories to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; repository&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./autogen.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./configure&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;sudo make install&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you have done the initial build, most changes shouldn't require more than a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
==Subsequent Builds==&lt;br /&gt;
Most subsequent builds will just need a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;. See the following paragraphs for caveats.&lt;br /&gt;
&lt;br /&gt;
===When to run autogen.sh===&lt;br /&gt;
The &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; script is simply a shorthand for &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You will need to run &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; only if you change any &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; files. Even then, a fresh &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; will generally check to see if your generated autoconf/automake files are older than &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; and do this step for you automatically.&lt;br /&gt;
&lt;br /&gt;
===When to run make install===&lt;br /&gt;
You should only need to run &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; in the following scenarios:&lt;br /&gt;
&lt;br /&gt;
* You've changed the way the environment catalog (&amp;lt;code&amp;gt;env.conf&amp;lt;/code&amp;gt;) or environment configuration files (&amp;lt;code&amp;gt;freem.conf&amp;lt;/code&amp;gt;) work&lt;br /&gt;
* You've modified a vendor routine in the &amp;lt;code&amp;gt;mlib/&amp;lt;/code&amp;gt; directory&lt;br /&gt;
&lt;br /&gt;
Other than these scenarios, you should be able to run the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;fmadm&amp;lt;/code&amp;gt; binaries out of the repository directory hierarchy.&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=378</id>
		<title>Contributor Guide</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Contributor_Guide&amp;diff=378"/>
		<updated>2025-04-05T22:01:56Z</updated>

		<summary type="html">&lt;p&gt;Smw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Overview=&lt;br /&gt;
&lt;br /&gt;
This article describes the facilities, methods, and commands used to contribute to the FreeM project.&lt;br /&gt;
&lt;br /&gt;
=For All Developers=&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
In order to contribute to FreeM, you must agree to abide by both the [[Code of Conduct]] and the [[General Policies]]. Your code must also conform to the style standards laid out in Appendix F of [https://freem.coherent-logic.com/docs/0.61.2/freem.html The FreeM Manual].&lt;br /&gt;
&lt;br /&gt;
You will also need to have &amp;lt;code&amp;gt;cvs&amp;lt;/code&amp;gt; installed on your machine. This is available in the package repositories of all popular Linux and UNIX operating systems.&lt;br /&gt;
&lt;br /&gt;
==Language==&lt;br /&gt;
All contributions to FreeM proper must be written in C. Bourne shell scripts are permissible where appropriate, and of course M code for the &amp;lt;code&amp;gt;mlib&amp;lt;/code&amp;gt; routines.&lt;br /&gt;
&lt;br /&gt;
===C Standard===&lt;br /&gt;
* FreeM contributions must not use language features unavailable in C89&lt;br /&gt;
* Vendor extensions in C compilers (like GNU extensions) are only permitted if guarded by preprocessor macros, and should be avoided if possible&lt;br /&gt;
* Contributions must be backwards compatible with gcc 2.95.3 (the oldest compiler we support)&lt;br /&gt;
* Contributions must not break compiles on Sun &amp;lt;code&amp;gt;cc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;clang&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Autotools===&lt;br /&gt;
* Contributions to &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; configuration must not use &amp;lt;code&amp;gt;pkg-config&amp;lt;/code&amp;gt;, as it is unavailable on some of our target platforms&lt;br /&gt;
* Target &amp;lt;code&amp;gt;autoconf&amp;lt;/code&amp;gt; 2.54 and &amp;lt;code&amp;gt;automake&amp;lt;/code&amp;gt; 1.7.1 for compatibility&lt;br /&gt;
&lt;br /&gt;
=Anonymous CVS Access=&lt;br /&gt;
&lt;br /&gt;
==Getting Source Code from CVS==&lt;br /&gt;
To fetch the latest FreeM source code from CVS, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
To update a previously-fetched copy of FreeM source code, go into the directory in which FreeM is located, and run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs -d:pserver:anonymous@cvs.coherent-logic.com:/home/cvsroot update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Submitting Changes Without CVS Write Access==&lt;br /&gt;
To submit a change to FreeM as an anonymous user (i.e., a user without writer access to the FreeM CVS repository), generate a &amp;lt;code&amp;gt;.patch&amp;lt;/code&amp;gt; file using the &amp;lt;code&amp;gt;diff&amp;lt;/code&amp;gt; utility, and send it to &amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt; (you must be subscribed to the mailing list), along with a description containing the following information:&lt;br /&gt;
&lt;br /&gt;
* What bug your patch fixes, or feature it implements&lt;br /&gt;
* Your full preferred name (this will be used in order to credit you for your work)&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
&lt;br /&gt;
Each patch should address no more than one bug fix or feature addition. Patches that do not comply with this requirement will be kicked back to the developer for revision.&lt;br /&gt;
&lt;br /&gt;
=CVS Writer Access=&lt;br /&gt;
&lt;br /&gt;
==Requesting Writer Access==&lt;br /&gt;
&lt;br /&gt;
In order to get CVS writer access, you will need to have either a track record of submitting good patches, or be an existing member of the core team. If you meet this criteria, please send a request to &lt;br /&gt;
&amp;lt;code&amp;gt;freem-dev@mailman.chivanet.org&amp;lt;/code&amp;gt;, including the following information:&lt;br /&gt;
&lt;br /&gt;
* Your full preferred name&lt;br /&gt;
* Your preferred e-mail address&lt;br /&gt;
* The username you would like to use for access to our CVS server (we will do our best to accommodate, but you may be required to choose a different username if your preferred username is already taken)&lt;br /&gt;
&lt;br /&gt;
==Configuring CVS==&lt;br /&gt;
&lt;br /&gt;
Once the below changes are made, you will need to log out and log back in to make them take effect.&lt;br /&gt;
&lt;br /&gt;
===Bourne-Again Shell (bash)===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.bashrc&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;~/.bash_profile&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
export CVS_RSH=/usr/bin/ssh&lt;br /&gt;
export CVSROOT=:ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also need to change the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; value to the correct absolute path to your &amp;lt;code&amp;gt;ssh&amp;lt;/code&amp;gt; binary. You can find this information using &amp;lt;code&amp;gt;which ssh&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===C Shell===&lt;br /&gt;
In &amp;lt;code&amp;gt;~/.cshrc&amp;lt;/code&amp;gt;, add the following lines, substituting your &amp;lt;code&amp;gt;cvs.coherent-logic.com&amp;lt;/code&amp;gt; username for ''username'':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
setenv CVS_RSH /usr/bin/ssh&lt;br /&gt;
setenv CVSROOT :ext:username@cvs.coherent-logic.com:/home/cvsroot&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Fetching FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
To fetch the latest FreeM source code for the first time, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs co freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If this fails, make sure you have the &amp;lt;code&amp;gt;CVS_RSH&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CVSROOT&amp;lt;/code&amp;gt; environment variables correctly configured.&lt;br /&gt;
&lt;br /&gt;
==Updating Your Copy of FreeM Source Code==&lt;br /&gt;
&lt;br /&gt;
In the directory containing the FreeM source code, run the following command:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs update -Pd&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Initial Build==&lt;br /&gt;
Follow these steps for the initial build:&lt;br /&gt;
&lt;br /&gt;
# Change directories to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; repository&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./autogen.sh&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;./configure&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;sudo make install&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you have done the initial build, most changes shouldn't require more than a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
==Subsequent Builds==&lt;br /&gt;
Most subsequent builds will just need a &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;. See the following paragraphs for caveats.&lt;br /&gt;
&lt;br /&gt;
===When to run autogen.sh===&lt;br /&gt;
The &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; script is simply a shorthand for &amp;lt;code&amp;gt;autoreconf --install&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
You will need to run &amp;lt;code&amp;gt;autogen.sh&amp;lt;/code&amp;gt; only if you change any &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; files. Even then, a fresh &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; will generally check to see if your generated autoconf/automake files are older than &amp;lt;code&amp;gt;configure.ac&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;Makefile.am&amp;lt;/code&amp;gt; and do this step for you automatically.&lt;br /&gt;
&lt;br /&gt;
===When to run make install===&lt;br /&gt;
You should only need to run &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt; in the following scenarios:&lt;br /&gt;
&lt;br /&gt;
* You've changed the way the environment catalog (&amp;lt;code&amp;gt;env.conf&amp;lt;/code&amp;gt;) or environment configuration files (&amp;lt;code&amp;gt;freem.conf&amp;lt;/code&amp;gt;) work&lt;br /&gt;
* You've modified a vendor routine in the &amp;lt;code&amp;gt;mlib/&amp;lt;/code&amp;gt; directory&lt;br /&gt;
&lt;br /&gt;
Other than these scenarios, you should be able to run the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;fmadm&amp;lt;/code&amp;gt; binaries out of the repository directory hierarchy.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Adding Files to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands from the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory, substituting the path and filename (relative to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory) for &amp;lt;code&amp;gt;&amp;amp;lt;filename&amp;amp;gt;&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs add &amp;lt;filename&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Committing Changes and Pushing to the Repository==&lt;br /&gt;
&lt;br /&gt;
Run the following commands ''from the parent directory of the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; directory'', replacing &amp;lt;code&amp;gt;commit-message&amp;lt;/code&amp;gt; with a message describing the change:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs ci -m &amp;quot;commit-message&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Database_Format&amp;diff=377</id>
		<title>Database Format</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Database_Format&amp;diff=377"/>
		<updated>2025-04-05T17:25:33Z</updated>

		<summary type="html">&lt;p&gt;Smw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;From David Wicksell&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
The first block in my global is a bottom level pointer. Maybe that's what a ROOT block always is? But there is no data in any other block, as it's a brand new global. Confusing.&lt;br /&gt;
Oh, I take that back. There is another block!&lt;br /&gt;
So with a global with even just one small record in it, there will be more than one block.&lt;br /&gt;
I suspect bottom pointer is called that because it's abstracted to be an upside down tree, and it's the root block for the global, which is the &amp;quot;bottom&amp;quot; of the global tree.&lt;br /&gt;
I still don't quite understand this format though.&lt;br /&gt;
That's block 0 of ^dlw. The 1, 3, and 1 on the top line appear to be pointers to another block, block 1.&lt;br /&gt;
[4:33 PM]&lt;br /&gt;
The end of that block has the metadata about the type of block it is, but the front of this block has at least one pointer to block number 1.&lt;br /&gt;
Yep, that is definitive now. Block 1, or the second block, contains my first key, the only key, in the global, so far.&lt;br /&gt;
[4:37 PM]&lt;br /&gt;
I will figure this out.&lt;br /&gt;
Ok, I see where key compression is done.&lt;br /&gt;
[4:46 PM]&lt;br /&gt;
I almost have the first block structure figured out.&lt;br /&gt;
[4:51 PM]&lt;br /&gt;
Ok, if the key you are going to insert isn't in the data block where it sorts to, then FreeM will lseek back in to the ROOT, and add the pointer first. So it has to traverse the path twice.&lt;br /&gt;
Ok, that's strange. The key format for canonical numbers is odd. It turns a subscript of (2) in to a 5 in the key.&lt;br /&gt;
[4:58 PM]&lt;br /&gt;
I believe it also turns a (0) in to a 3 and a (1) in to a 4. I guess it can't use ASCII 0, 1, or 2 for that. (edited)&lt;br /&gt;
[5:01 PM]&lt;br /&gt;
I can definitelly see ways to speed up globals in FreeM! For one thing, it recalculates the file path to the global over and over, even when it has the file descriptor stored already.&lt;br /&gt;
Ok, so I have the ROOT block, which is a bottom pointer block figured out, format wise.&lt;br /&gt;
[5:21 PM]&lt;br /&gt;
[5:24 PM]&lt;br /&gt;
Starting at the first byte of the block, the 1 is the length of the first key in the global. Then it skips a byte, and the 3 is the first key. Then, because the block is a pointer block, all keys are hard-coded with a 3 byte pointer to their data block. So the next three bytes, 00 00 01 are a pointer to the block containing key 3. Now key 3 is actually ^dlw(1), but that 1 is encoded in to a compact key form, and ends up as 3. I'm not 100% sure why yet. So that points to block 1. I'm inserting a new pointer for ^dlw(2) right now, so in a few minutes, this first block will have another key up on the top line, and I'll show that to you once it's there.&lt;br /&gt;
[5:25 PM]&lt;br /&gt;
FreeM also maintains a path through the blocks in a global, just like RSM does and just like GT.M/YottaDB do.&lt;br /&gt;
[5:28 PM]&lt;br /&gt;
In RSM, that path is recorded in an array of pointers to global buffer descriptors in shared memory, called blk, it is 12 pointers long. In FreeM, the path seems to be in 2 arrays of longs, the first traceblk stores the block numbers in the path, and the second, traceadr also stores numbers, but shorts instead of unsigned longs. So far, I haven't figured out what it stores semantically. Both hold 32 numbers, so that would support the idea that it can handle a B-tree of 32 levels, which is gigantic&lt;br /&gt;
dlw — Yesterday at 6:56 PM&lt;br /&gt;
Ok, before inserting the second key, here is what block 0, the ROOT, a BOTTOM pointer for ^dlw looks like:&lt;br /&gt;
&amp;quot;\001\000\003\000\000\001&amp;quot;, '\000' &amp;lt;repeats 1010 times&amp;gt;, &amp;quot;\001\000\000\000\000\006\000\006&amp;quot;&lt;br /&gt;
You can see stuff at the beginning and the end. Starting at the beginning, is 001 then 000, which added together is 1 (because of key compression), the length of the first key. Then the key is 003 (which is the compact form of (1) I guess). Then, since it's a BOTTOM block, which is a pointer, and pointers are always 3 bytes, the next 3 bytes are 000 000 001, which when calculated is a pointer to block 1.&lt;br /&gt;
&lt;br /&gt;
Then, looking at the end of the block, the third to last byte is 006, which is the block type, BOTTOM. Then the last two bytes are 000 006, which, when calculated is an offset in to the block itself, of 6, meaning that it's the beginning of the free space in the block, offset from the beginning of the block. Then, to the left of the 006 type, is 3 bytes of 000 000 000, which would be the right pointer in a data block (maybe a pointer block too), but in the ROOT block, it's the number of free blocks in the global, which is 0, since there are only 2 blocks right now, and neither are empty. Then, one byte to the left of that is 000, which is the collation for the block, and a 0 is just M collation. Then, the three bytes before that are 000 000 001, and if this were a data block (maybe a pointer block too), it would be the left pointer, but since this is the ROOT block, it's the number of total blocks in the global, in this case 1. Since there is the ROOT block and a data block, the total block count must not include the ROOT block, but is how many more blocks.&lt;br /&gt;
&lt;br /&gt;
Next we'll look at the second block, a data block.&lt;br /&gt;
dlw — Yesterday at 7:04 PM&lt;br /&gt;
Ok, before inserting the second key, here is what block 1, the DATA block, for ^dlw looks like:&lt;br /&gt;
&amp;quot;\001\000\003\0011&amp;quot;, '\000' &amp;lt;repeats 1016 times&amp;gt;, &amp;quot;\b\000\005&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You can see stuff at the beginning and the end. Starting at the beginning, is 001 then 000, which added together is 1 (because of key compression), the length of the first key. Then the key is 003 (which is the compact form of (1) I guess). So far, identical to the ROOT, but once more keys are there, enough to need more blocks, then that will likely change. Then, since it's a DATA block, which is not a pointer, the next byte is the length of the data record at the key, which is a length of 1. Then, the next byte is 1 (ASCII 49, since the compact form is only in keys, and this is data), the data at ^dlw(1).&lt;br /&gt;
&lt;br /&gt;
Then, looking at the end of the block, the third to last byte is \b (which is 008), which is the block type, DATA. Then the lsat two bytes are 000 005, which, when calculated is an offset in to the block itself, of 5, meaning that it's the beginning of the free space in the block, offset from the beginning of the block. Then, to the left of the 008 type, is 3 bytes of 000 000 000, which would be the number of free blocks in the ROOT, but since this is DATA, is the right pointer. There are no blocks to the right, so it's 0. The, one byte to the left of that is 000, which in a DATA block is a reserved byte, and always 0. You could do something with that in the future. Then, the three bytes before that are 000 000 000, which would be the number of total blocks in the ROOT, but since this is DATA, is the left pointer. There are not blocks to the left, so it's 0.&lt;br /&gt;
[7:06 PM]&lt;br /&gt;
So that's what I've worked out so far. One observation, currently a key length is stored in two bytes, a byte for the length, and one for how much is compressed. So a key in a global in FreeM is restricted to 255 bytes without changing the format. The more important observatoin is that the length of a data record, or node, is stored in a single byte, also limiting it to 255 bytes without changing the format. Since I know you want to raise your string limits, you'll have to look at that first. I can help you figure out where to go and what to do if you like.&lt;br /&gt;
&lt;br /&gt;
dlw — Yesterday at 7:11 PM&lt;br /&gt;
By the way, I'm doing this for two reasons. First, I love this sort of code, so I'm enjoying it. Second, and more importantly, I know you hate it, so I'm trying to help you out, because I want you to succeed at increasing the string length in FreeM.&lt;br /&gt;
&lt;br /&gt;
dlw — Yesterday at 7:55 PM&lt;br /&gt;
Ok, I understand the FreeM block structure much better now.&lt;br /&gt;
Ok, some weird things happen, they may or may not matter. I'll have to look in to that. But no block joins happen at all. Rather, most of a block that has all of its keys removed stays there empty.&lt;br /&gt;
[12:37 AM]&lt;br /&gt;
I had a global with 1 pointer block and 3 data blocks, and I killed all the records in the first and third data block, and for the most part, they are just sitting there all empty, while the second block is still full. The weirdness is that they both have one record still in them, and I'm not sure why. It's the last key, and it appears to have been moved to the front of the block. So maybe a FOR loop in FreeM is not inclusive in its END condtion, but exclusive. Or maybe something else is going on. Now I'm going to remove keys from the middle of the second block to see what happens.&lt;br /&gt;
[12:41 AM]&lt;br /&gt;
Blocks in FreeM do not contain their block number.&lt;br /&gt;
[12:41 AM]&lt;br /&gt;
I guess I just assumed they would.&lt;br /&gt;
Ok, so that weirdness seems to just be an artifact, and I know why.&lt;br /&gt;
&lt;br /&gt;
dlw — 1:06 AM&lt;br /&gt;
I was removing records in a loop, and when it got to the last record in a block, it didn't bother to remove it, instead it left it there, and just marked the block as empty. So it definitely does not do joins, it will remove records, and each time it does, it will re-key the block so that the keys after the one that was removed, are moved up to fill in the empty spot. Once it gets to that last record, it just marks the block free and leaves the record there, as the first record in the block.&lt;br /&gt;
&lt;br /&gt;
One thing I don't quite understand is that I created records to fill 3 data blocks, so there was 1 bottom pointer and 3 data blocks, but after all of that, what was left was block 0 was the bottom pointer, it has one pointer to block 2. Block 1 is marked empty and has one record in it, the original last record, as according to my last paragraph. Block 2 which I removed like 50 records from the middle of the block, and the records after it were moved up to fill the hole. Block 3 is marked empty and has one record in it at the beginning, the original last record, as according to my last paragraph. It also has a bunch of records at the end, but it's marked empty, so that seems fine. But why did leave them there, and why don't they match what I'd expect? They have records that were originally in block 3, and some of them are still there in block 3. So that part is a mystery, based on the code I ran, and the state of the blocks at each point. Block 5 is really weird. It was never used for data. But it has a few bits of things in it, and is marked as something I have no clue about, an FBLK. So not an EMPTY, but an FBLK. It is used though, as it has an offset and something before that offset and has that FBLK marker. So I'll have to figure out what an FBLK is and what it's used for. It's the one block type I don't know yet.&lt;br /&gt;
[1:07 AM]&lt;br /&gt;
Long story short, FreeM will always fill in holes during record deletion, by moving later records up to fill them, and it does not do block joins, it will just mark the block as empty. Both are things RSM does not do.&lt;br /&gt;
[1:10 AM]&lt;br /&gt;
Ohhhh!&lt;br /&gt;
[1:10 AM]&lt;br /&gt;
I know what it is!&lt;br /&gt;
[1:10 AM]&lt;br /&gt;
Clever!&lt;br /&gt;
[1:12 AM]&lt;br /&gt;
It's the free block list! So once FreeM has freed a block that had data in it, it creates a new block called the free block (FBLK), which is just a list of pointers to free blocks in order. So in my testing data, it just has a pointer to block 1 and block 3, which I told you above are both free. Does it always maintain that block at the end of the global somehow, or does it have another way of knowing where to find it? I'll have to figure that out.&lt;br /&gt;
&lt;br /&gt;
dlw — 1:15 AM&lt;br /&gt;
Ooo, that's how!&lt;br /&gt;
[1:17 AM]&lt;br /&gt;
Remember earlier I told you that the ROOT block, always a BOTTOM pointer, didn't have a left and right pointer, since it has no siblings, so instead it uses those fields to store the number of blocks other than the ROOT that are in the global, and the number of free blocks? Yeah, it's not the number of free blocks, it's the block number that stores the FBLK, or free block list! So it can always find that block when it needs a new block, before it would add a new block to the global. So instead of a map block using a bitmap, like RSM uses, it has a pointer from the ROOT block to a FBLK, which maintains the list of free blocks!&lt;br /&gt;
[1:18 AM]&lt;br /&gt;
So there you go, other than a few details on internal key formats, I have taught you pretty much the entire globals module tonight! I have not dug in to block splits, but I'll do that soon, and let you know any details.&lt;br /&gt;
[1:21 AM]&lt;br /&gt;
So, remember that because all of the block pointers are 3 bytes, that means a global in FreeM can be at most, 16 MiB blocks, and at 1 KiB per block, that means no larger than 16 GiB.&lt;br /&gt;
[1:22 AM]&lt;br /&gt;
Just an FYI or a reminder.&lt;br /&gt;
One other thing, FreeM's index/pointer block keys are different than RSM or GT.M/YottaDB.&lt;br /&gt;
&lt;br /&gt;
In GT.M/YottaDB, an index/pointer block stores keys such that the first key, which points to the first data block for that global, is a key that points to every key from the root of the global all the way to, and including, that key. In other words, the keys in the index blocks are the last keys stored in the data block they point to. Then at the end, there is a star pointer (a literal *, for everything else) that points to the last data block, containing any keys that collate after the previous key.&lt;br /&gt;
&lt;br /&gt;
In RSM, an index/pointer block stores keys such that the first key (always the null/empty/root key), which points to the first data block for that global, is a key that points to every key from the root of the global all the way to, and excluding the next key in the index block. In other words, the keys in the index blocks are the first keys stored in the data block they point to, and for the first key, even if there is no data at the root of the global, that key is still stored, just with no data if it doesn't exist (and it flagged as such in the entry for the global in the global directory). So the last key points at the first key in the last block that contains the keys to the end.&lt;br /&gt;
&lt;br /&gt;
In FreeM, an index/pointer block stores keys such that the first key, which points to the first data block for that global, is a key that points to every key, starting with that key, up to, and excluding, the next key in the index block. In other words, the keys in the index blocks are the first keys stored in the data block they point to. But unlike RSM, there is no key for before the first stored key (the null/empty/root key), the first key stored is the first key in the global. Also, unlike GT.M, there is no star pointer at the end. So every index pointer has to be updated if that key is deleted, with another one.&lt;br /&gt;
t's basically a separately maintained linked-list that stores pointers to free blocks. I'm not sure if it would reorganize the pointers in order to keep them in block number order or not though.&lt;br /&gt;
[11:14 AM]&lt;br /&gt;
The root bottom pointer block stores the first free block in its footer, and then that block maintains a right pointer to the next free blook in the linked list, which itself has a left pointer back to the first, and so on. So it's a doubly-linked list.&lt;br /&gt;
[11:16 AM]&lt;br /&gt;
So if you wanted to calculate how many used blocks there are, you'd have to grab the block total from the ROOT footer, and then grab the block free pointer to the first free block, and walk through it, and its siblings, via the right pointers, marking down every block as free, and then what's left is used. There is no direct way to know what blocks are used, without walking the entire B-tree, other than the free block walk I just mentioned, which would be much faster.&lt;br /&gt;
￼&lt;br /&gt;
dlw — 11:21 AM&lt;br /&gt;
The FBLK format is super simple. The footer maintains a left and right pointer, a block type of FBLK or 1, and an offset to the next available free space in the block. And then is just lists block numbers, 3 bytes at a time.&lt;br /&gt;
[11:21 AM]&lt;br /&gt;
No keys, or data, or anything else, just block pointers to free blocks, blocks with types of FREE or 0.&lt;br /&gt;
[11:23 AM]&lt;br /&gt;
The ROOT block's &amp;quot;right&amp;quot; pointer, points to the first FBLK for that global. The ROOT block's &amp;quot;left&amp;quot; pointer, stores the total number of blocks in the global, not including itself.&lt;br /&gt;
[11:23 AM]&lt;br /&gt;
But that does include FREE blocks and FBLK blocks.&lt;br /&gt;
[11:25 AM]&lt;br /&gt;
Because no spaces are allowed between keys, you can easily calculate how full a block is by simply subtracting the OFFSET (stored as the last two bytes in the footer) from DATALIM (the size of the block minus the footer, hard-coded), which then gives you how much free space is left in that block. True for all block types, other than FREE, which just have DATALIM of free space.&lt;br /&gt;
[11:26 AM]&lt;br /&gt;
Unlike RSM, which zeroes out blocks when they are garbage collected, FreeM leaves the data as-is when using or reusing a block, just setting the type to FREE, and the OFFSET to 0.&lt;br /&gt;
[11:26 AM]&lt;br /&gt;
Though when it goes to fill data in to a formerly FREE block, it will then zero the block I believe.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An older conversation about the key format:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
The first byte is 1, that says that the key is 1 byte in length. The second byte is 0, that says there is no key compression. The third byte is 4B, which is 75 in decimal. That is the encoded character that encodes for this first key of length one. Here we use our decoding chops.&lt;br /&gt;
[12:09 PM]&lt;br /&gt;
75 is greater than 31, so we shift its bit pattern `0100 1011` to the right by 1, resulting in `0010 0101`, which is decimal 37. And since it was greater than 31, that's all you do to decode it (between 0 and 19 you do something else, and between 20 and 31, you do something else as well). And ASCII 37 is a % character, which is the full key for that node!&lt;br /&gt;
￼&lt;br /&gt;
dlw — 12/16/23, 12:10 PM&lt;br /&gt;
The fourth byte is 0C, which is 12 decimal, which is the length of the data at that node, so 12 characters. Then the next 12 characters make up the data, and they don't encode subscript delimiters of course, so it's straight forward. Here that is:&lt;br /&gt;
￼&lt;br /&gt;
dlw — 12/16/23, 12:18 PM&lt;br /&gt;
53 63 72 61  74 63 68 20  61 72 65 61 - which in decimal are - 83 99 114 97  116 99 104 32  97 114 101 97 - which are the ASCII codes for &amp;quot;Scratch area&amp;quot;.&lt;br /&gt;
[12:18 PM]&lt;br /&gt;
So that key and its data are ^XVEMS(&amp;quot;%&amp;quot;)=&amp;quot;Scratch area&amp;quot;, which you can see is what FreeM things as well:&lt;br /&gt;
USER&amp;gt; w ^XVEMS(&amp;quot;%&amp;quot;)&lt;br /&gt;
Scratch area&lt;br /&gt;
USER&amp;gt;&lt;br /&gt;
[12:19 PM]&lt;br /&gt;
There was your first walk through of how to decode a FreeM key in a global! (edited)&lt;br /&gt;
[12:20 PM]&lt;br /&gt;
I'll do the next key, just to show you.&lt;br /&gt;
[12:21 PM]&lt;br /&gt;
￼&lt;br /&gt;
[12:21 PM]&lt;br /&gt;
This one has a longer key, and a shorter data node.&lt;br /&gt;
￼&lt;br /&gt;
dlw — 12/16/23, 12:28 PM&lt;br /&gt;
So, the first byte is 9, so the key is 9 bytes. The second byte is 0, so no key compression here either. So then the next 9 bytes, the key, are:&lt;br /&gt;
4B 12 02 04  12 11 A6 90  99 - which converted to the decimal we find easier to think about is - 75 18 2 4  18 17 166 144  153 - so now we have to decode them each in turn. First up is 75, which is higher than 31, so we take its bit pattern `0100 1011` and shift it to the right by one, leading to `0010 0101`, which is 37 decimal, or `%` again. That really should have been part of key compression, no idea what it wasn't. But,here we remember that these characters can encode that they are a subscript boundary, and they do that in their encoded form, which for `%` here, was 75. Remember the 75 bit pattern? It ended with a 1 in the LSB, which means this encodes as a delimiter too, so we now have `&amp;quot;%&amp;quot;,` at this point.&lt;br /&gt;
&lt;br /&gt;
I'll continue on the next message.&lt;br /&gt;
[12:31 PM]&lt;br /&gt;
The second key byte is 18, with a bit pattern of 0001 0010 which does not end in 1, so this does not encode another , or the end of the key. Since this is between 0 and 19, we have to do an addition after the shift, but the shift is still one to the right, for 0000 1001, which is 9. Then, we add '0' to it, since this is numeric, and '0' is ASCII 48, so we get ASCII 57, which codes the number 9 as a string. So now our key is &amp;quot;%&amp;quot;,9. On to the next byte, the third byte, which is 2. The bit pattern is 0000 0010 which doesn't end in 1, so doesn't end the subscript. It's a 2. That gets right shifted, to a 0000 0001, or a 1,  which is then added to '0' (ASCII 48) to get ASCII 49, which is the code for a string of 1, which is not surprising, now that you see the patter. The key is at &amp;quot;%&amp;quot;,91 now. (edited)&lt;br /&gt;
￼&lt;br /&gt;
dlw — 12/16/23, 12:41 PM&lt;br /&gt;
Now we do the fourth byte, which is 4, same story, bit pattern is 0000 0100, not the end of a subscript, and it shifts to 0000 0010 a 2, which when added to '0' 48 again, becomes the string 2. Notice the pattern? When dealing with numerics or numbers, FreeM encodes them as what their ASCII code number is, and then just adds 48 to them, to get back their string equivalent. But since the get right shifted, and lose their last bit, they take up two places in the ASCII code.&lt;br /&gt;
&lt;br /&gt;
For example, ASCII 0 and 1 will result in a 0, 2 and 3 will result in a 1, 4 and 5 will result in a 2, and so on. So, you can take the ASCII number, if it's even, and cut it in half to get right to the number in a string form. And if it's odd, that means it is the last character for that subscript, and you can then subtract 1, and then cut it half to get the character, so an 18 is the number 9, while a 19 is the number 9, and it's the last character of the subsript!&lt;br /&gt;
&lt;br /&gt;
So to finish up the key, we are now at the fifth character, an 18, followed by a sixth, which is a 17. After that, the numbers are way over the 0 to 19 range for numbers. So an 18 is even and cut in half is 9, the next character decoded. The 17 is the first odd one, so it's the end of the subscript, take off 1, and cut in half, and you have 16 to 8, the last character. So our key now looks like &amp;quot;%&amp;quot;,91298,.&lt;br /&gt;
[12:41 PM]&lt;br /&gt;
Now on to the last three characters, 166 144 153! (edited)&lt;br /&gt;
[12:46 PM]&lt;br /&gt;
So all are over 31, so only get right shifted. The first two are even, so they are part of a subscript, and the last one is odd, so it's the end of a subscript. But since the key was only 9 characters, FreeM won't put a , after them, but will end it with the ) instead.&lt;br /&gt;
&lt;br /&gt;
So 166 is 1010 0110, which right shifted is 0101 0011, which is a decimal 83, or the character S. 144 is 1001 0000 shifted right is 0100 1000a decimal 72, ASCII H. Then a 153, which is 1001 1001, shifted right is 0100 1100, a decimal 76, an ASCII L, so the last subscript is &amp;quot;SHL&amp;quot;, and our key is finished!&lt;br /&gt;
&lt;br /&gt;
It is (&amp;quot;%&amp;quot;,91298,&amp;quot;SHL&amp;quot;).&lt;br /&gt;
The next byte is a 3, so the data node is 3 characters, which are 52 55 4E, convert them to decimal and we have 82 85 78, which are the ASCII codes for R U N, and as data nodes aren't encoded with any shifting or masking or anything, that's just what they are! So the (&amp;quot;%&amp;quot;,91298,&amp;quot;SHL&amp;quot;) key stores &amp;quot;RUN&amp;quot;. Now let's see if I was correct.&lt;br /&gt;
[12:50 PM]&lt;br /&gt;
USER&amp;gt; w $q(^XVEMS)&lt;br /&gt;
^XVEMS(&amp;quot;%&amp;quot;)&lt;br /&gt;
USER&amp;gt; w $q(^XVEMS(&amp;quot;%&amp;quot;))&lt;br /&gt;
^XVEMS(&amp;quot;%&amp;quot;,91298,&amp;quot;SHL&amp;quot;)&lt;br /&gt;
USER&amp;gt; w ^XVEMS(&amp;quot;%&amp;quot;)&lt;br /&gt;
Scratch area&lt;br /&gt;
USER&amp;gt; w ^XVEMS(&amp;quot;%&amp;quot;,91298,&amp;quot;SHL&amp;quot;)&lt;br /&gt;
RUN&lt;br /&gt;
USER&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Yep! So that is how you decode global data in FreeM!&lt;br /&gt;
Canonical numbers are shifted down in the control character range, so that they collate before strings, and that means control characters are unavailable for use. . and - are likewise moved to the area right after that, taking up a few other control characters. And strings are shifted up to over ASCII 127, taking over the higher bit, meaning only 7-bit ASCII is supported, no extended character sets.&lt;br /&gt;
&lt;br /&gt;
So the characters that it intends to allow in keys are ASCII 32 - 126, and that's it. Though it does something with 127, but I haven't figured it out yet.&lt;br /&gt;
￼&lt;br /&gt;
Serena Bloodfeather — 12/16/23, 1:22 PM&lt;br /&gt;
in light of everything you learned, have you gotten any new insights into how difficult it would be to get us to where we can support block sizes larger than 1KiB and a commensurate increase in key and node length? strictly in the globals themselves, not accounting for the interpreter having its own issues with long strings.&lt;br /&gt;
￼&lt;br /&gt;
dlw — 12/16/23, 1:25 PM&lt;br /&gt;
There are only two things preventing a larger block size. First, BLOCKLEN is hard-coded, but you know that. Second, all the macros that offset off of BLOCKLEN are hard-coded, and would need to support scaling.&lt;br /&gt;
&lt;br /&gt;
If you fix those two things, you can have bigger block sizes. But, for longer keys and longer data, right now, each stores their lengths in a byte, limiting them to 255 characters. So you'd have to adjust the data size for key and/or record lengths to support larger ones.&lt;br /&gt;
￼&lt;br /&gt;
Serena Bloodfeather — 12/16/23, 1:25 PM&lt;br /&gt;
that's basically what I was thinking&lt;br /&gt;
￼&lt;br /&gt;
dlw — 12/16/23, 1:26 PM&lt;br /&gt;
Sorry, they would not need to support scaling, they just need to follow the offset of a different BLOCKLEN. That's even easier than I was saying.&lt;br /&gt;
￼&lt;br /&gt;
Serena Bloodfeather — 12/16/23, 1:26 PM&lt;br /&gt;
haha that's what I thought you meant by scaling&lt;br /&gt;
￼&lt;br /&gt;
dlw — 12/16/23, 1:26 PM&lt;br /&gt;
So if you set BLOCKLEN based on a user configuration, that should support block sizes larger than 1024 without much else.&lt;br /&gt;
[1:26 PM]&lt;br /&gt;
Scaling is multiplying, offsetting is adding.&lt;br /&gt;
￼&lt;br /&gt;
Serena Bloodfeather — 12/16/23, 1:26 PM&lt;br /&gt;
I've tried changing the BLOCKLEN macro to larger values, and FreeM did not behave well at all&lt;br /&gt;
￼&lt;br /&gt;
dlw — 12/16/23, 1:27 PM&lt;br /&gt;
I'd have to follow all the places that use it to see why.&lt;br /&gt;
[1:30 PM]&lt;br /&gt;
BLOCKLEN is defined in 3 places. It should just work if you change it in all three to the same size.&lt;br /&gt;
￼&lt;br /&gt;
Serena Bloodfeather — 12/16/23, 1:31 PM&lt;br /&gt;
gfix.c, fma_globals.h, and mpsdef0.h?&lt;br /&gt;
￼&lt;br /&gt;
dlw — 12/16/23, 1:31 PM&lt;br /&gt;
Yes&lt;br /&gt;
[1:31 PM]&lt;br /&gt;
But, you'd have to blow away every global you already have, and start with a brand new instance environment.&lt;br /&gt;
￼&lt;br /&gt;
Serena Bloodfeather — 12/16/23, 1:31 PM&lt;br /&gt;
yeah&lt;br /&gt;
[1:32 PM]&lt;br /&gt;
it wouldn't have much utility until nodes and/or keys can be longer than 255 characters&lt;br /&gt;
￼&lt;br /&gt;
dlw — 12/16/23, 1:32 PM&lt;br /&gt;
Until you store the BLOCKLEN itself in block 0, which is totally possible, and probably easy.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
So in FreeM, when you insert a key between two existing keys in the same block, it will insert that key by moving the key after it, and every other key after it, down in the block, so that it keeps the block from having holes in between keys. But that can be expensive when it's inserting towards the front of a nearly full block. Though small blocks do help in that regard.&lt;br /&gt;
&lt;br /&gt;
In RSM, other than when it is doing things like block splits, block joins, or block reorganizations, it never moves keys, it stores them at the end of the block and keeps them tight, storing them in the order they are inserted, not in collation order like FreeM. Instead, it has a key index at the front of the block, right after the header, and the index uses fixed size offsets, and its that index that is kept in collation order. So when you insert a key between two existing keys in the same block, it will insert it in the next available space, pointed to by Last Free: above (scaled by 4), and then it will move the index for it, and every other key after it, down in the index. That also keeps the block from having holes in between keys, at least on inserts.&lt;br /&gt;
&lt;br /&gt;
On key removal, FreeM does the same exact thing as it does for inserts, but RSM will instead get a new block and copy all the keys to the new block, now in order not just in the index, but in the block key space itself, and skips removed keys.&lt;br /&gt;
&lt;br /&gt;
So to summarize, on insert, it just puts the key in the next available space and then rebuilds the block index in sorted order. On removal, it marks the key as undefined, and then grabs a new block, and copies everything to the new block except for the undefined key. (edited)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Database_Format&amp;diff=376</id>
		<title>Database Format</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Database_Format&amp;diff=376"/>
		<updated>2025-03-29T21:12:52Z</updated>

		<summary type="html">&lt;p&gt;Smw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;From David Wicksell&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
The first block in my global is a bottom level pointer. Maybe that's what a ROOT block always is? But there is no data in any other block, as it's a brand new global. Confusing.&lt;br /&gt;
Oh, I take that back. There is another block!&lt;br /&gt;
So with a global with even just one small record in it, there will be more than one block.&lt;br /&gt;
I suspect bottom pointer is called that because it's abstracted to be an upside down tree, and it's the root block for the global, which is the &amp;quot;bottom&amp;quot; of the global tree.&lt;br /&gt;
I still don't quite understand this format though.&lt;br /&gt;
That's block 0 of ^dlw. The 1, 3, and 1 on the top line appear to be pointers to another block, block 1.&lt;br /&gt;
[4:33 PM]&lt;br /&gt;
The end of that block has the metadata about the type of block it is, but the front of this block has at least one pointer to block number 1.&lt;br /&gt;
Yep, that is definitive now. Block 1, or the second block, contains my first key, the only key, in the global, so far.&lt;br /&gt;
[4:37 PM]&lt;br /&gt;
I will figure this out.&lt;br /&gt;
Ok, I see where key compression is done.&lt;br /&gt;
[4:46 PM]&lt;br /&gt;
I almost have the first block structure figured out.&lt;br /&gt;
[4:51 PM]&lt;br /&gt;
Ok, if the key you are going to insert isn't in the data block where it sorts to, then FreeM will lseek back in to the ROOT, and add the pointer first. So it has to traverse the path twice.&lt;br /&gt;
Ok, that's strange. The key format for canonical numbers is odd. It turns a subscript of (2) in to a 5 in the key.&lt;br /&gt;
[4:58 PM]&lt;br /&gt;
I believe it also turns a (0) in to a 3 and a (1) in to a 4. I guess it can't use ASCII 0, 1, or 2 for that. (edited)&lt;br /&gt;
[5:01 PM]&lt;br /&gt;
I can definitelly see ways to speed up globals in FreeM! For one thing, it recalculates the file path to the global over and over, even when it has the file descriptor stored already.&lt;br /&gt;
Ok, so I have the ROOT block, which is a bottom pointer block figured out, format wise.&lt;br /&gt;
[5:21 PM]&lt;br /&gt;
[5:24 PM]&lt;br /&gt;
Starting at the first byte of the block, the 1 is the length of the first key in the global. Then it skips a byte, and the 3 is the first key. Then, because the block is a pointer block, all keys are hard-coded with a 3 byte pointer to their data block. So the next three bytes, 00 00 01 are a pointer to the block containing key 3. Now key 3 is actually ^dlw(1), but that 1 is encoded in to a compact key form, and ends up as 3. I'm not 100% sure why yet. So that points to block 1. I'm inserting a new pointer for ^dlw(2) right now, so in a few minutes, this first block will have another key up on the top line, and I'll show that to you once it's there.&lt;br /&gt;
[5:25 PM]&lt;br /&gt;
FreeM also maintains a path through the blocks in a global, just like RSM does and just like GT.M/YottaDB do.&lt;br /&gt;
[5:28 PM]&lt;br /&gt;
In RSM, that path is recorded in an array of pointers to global buffer descriptors in shared memory, called blk, it is 12 pointers long. In FreeM, the path seems to be in 2 arrays of longs, the first traceblk stores the block numbers in the path, and the second, traceadr also stores numbers, but shorts instead of unsigned longs. So far, I haven't figured out what it stores semantically. Both hold 32 numbers, so that would support the idea that it can handle a B-tree of 32 levels, which is gigantic&lt;br /&gt;
dlw — Yesterday at 6:56 PM&lt;br /&gt;
Ok, before inserting the second key, here is what block 0, the ROOT, a BOTTOM pointer for ^dlw looks like:&lt;br /&gt;
&amp;quot;\001\000\003\000\000\001&amp;quot;, '\000' &amp;lt;repeats 1010 times&amp;gt;, &amp;quot;\001\000\000\000\000\006\000\006&amp;quot;&lt;br /&gt;
You can see stuff at the beginning and the end. Starting at the beginning, is 001 then 000, which added together is 1 (because of key compression), the length of the first key. Then the key is 003 (which is the compact form of (1) I guess). Then, since it's a BOTTOM block, which is a pointer, and pointers are always 3 bytes, the next 3 bytes are 000 000 001, which when calculated is a pointer to block 1.&lt;br /&gt;
&lt;br /&gt;
Then, looking at the end of the block, the third to last byte is 006, which is the block type, BOTTOM. Then the last two bytes are 000 006, which, when calculated is an offset in to the block itself, of 6, meaning that it's the beginning of the free space in the block, offset from the beginning of the block. Then, to the left of the 006 type, is 3 bytes of 000 000 000, which would be the right pointer in a data block (maybe a pointer block too), but in the ROOT block, it's the number of free blocks in the global, which is 0, since there are only 2 blocks right now, and neither are empty. Then, one byte to the left of that is 000, which is the collation for the block, and a 0 is just M collation. Then, the three bytes before that are 000 000 001, and if this were a data block (maybe a pointer block too), it would be the left pointer, but since this is the ROOT block, it's the number of total blocks in the global, in this case 1. Since there is the ROOT block and a data block, the total block count must not include the ROOT block, but is how many more blocks.&lt;br /&gt;
&lt;br /&gt;
Next we'll look at the second block, a data block.&lt;br /&gt;
dlw — Yesterday at 7:04 PM&lt;br /&gt;
Ok, before inserting the second key, here is what block 1, the DATA block, for ^dlw looks like:&lt;br /&gt;
&amp;quot;\001\000\003\0011&amp;quot;, '\000' &amp;lt;repeats 1016 times&amp;gt;, &amp;quot;\b\000\005&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You can see stuff at the beginning and the end. Starting at the beginning, is 001 then 000, which added together is 1 (because of key compression), the length of the first key. Then the key is 003 (which is the compact form of (1) I guess). So far, identical to the ROOT, but once more keys are there, enough to need more blocks, then that will likely change. Then, since it's a DATA block, which is not a pointer, the next byte is the length of the data record at the key, which is a length of 1. Then, the next byte is 1 (ASCII 49, since the compact form is only in keys, and this is data), the data at ^dlw(1).&lt;br /&gt;
&lt;br /&gt;
Then, looking at the end of the block, the third to last byte is \b (which is 008), which is the block type, DATA. Then the lsat two bytes are 000 005, which, when calculated is an offset in to the block itself, of 5, meaning that it's the beginning of the free space in the block, offset from the beginning of the block. Then, to the left of the 008 type, is 3 bytes of 000 000 000, which would be the number of free blocks in the ROOT, but since this is DATA, is the right pointer. There are no blocks to the right, so it's 0. The, one byte to the left of that is 000, which in a DATA block is a reserved byte, and always 0. You could do something with that in the future. Then, the three bytes before that are 000 000 000, which would be the number of total blocks in the ROOT, but since this is DATA, is the left pointer. There are not blocks to the left, so it's 0.&lt;br /&gt;
[7:06 PM]&lt;br /&gt;
So that's what I've worked out so far. One observation, currently a key length is stored in two bytes, a byte for the length, and one for how much is compressed. So a key in a global in FreeM is restricted to 255 bytes without changing the format. The more important observatoin is that the length of a data record, or node, is stored in a single byte, also limiting it to 255 bytes without changing the format. Since I know you want to raise your string limits, you'll have to look at that first. I can help you figure out where to go and what to do if you like.&lt;br /&gt;
&lt;br /&gt;
dlw — Yesterday at 7:11 PM&lt;br /&gt;
By the way, I'm doing this for two reasons. First, I love this sort of code, so I'm enjoying it. Second, and more importantly, I know you hate it, so I'm trying to help you out, because I want you to succeed at increasing the string length in FreeM.&lt;br /&gt;
&lt;br /&gt;
dlw — Yesterday at 7:55 PM&lt;br /&gt;
Ok, I understand the FreeM block structure much better now.&lt;br /&gt;
Ok, some weird things happen, they may or may not matter. I'll have to look in to that. But no block joins happen at all. Rather, most of a block that has all of its keys removed stays there empty.&lt;br /&gt;
[12:37 AM]&lt;br /&gt;
I had a global with 1 pointer block and 3 data blocks, and I killed all the records in the first and third data block, and for the most part, they are just sitting there all empty, while the second block is still full. The weirdness is that they both have one record still in them, and I'm not sure why. It's the last key, and it appears to have been moved to the front of the block. So maybe a FOR loop in FreeM is not inclusive in its END condtion, but exclusive. Or maybe something else is going on. Now I'm going to remove keys from the middle of the second block to see what happens.&lt;br /&gt;
[12:41 AM]&lt;br /&gt;
Blocks in FreeM do not contain their block number.&lt;br /&gt;
[12:41 AM]&lt;br /&gt;
I guess I just assumed they would.&lt;br /&gt;
Ok, so that weirdness seems to just be an artifact, and I know why.&lt;br /&gt;
&lt;br /&gt;
dlw — 1:06 AM&lt;br /&gt;
I was removing records in a loop, and when it got to the last record in a block, it didn't bother to remove it, instead it left it there, and just marked the block as empty. So it definitely does not do joins, it will remove records, and each time it does, it will re-key the block so that the keys after the one that was removed, are moved up to fill in the empty spot. Once it gets to that last record, it just marks the block free and leaves the record there, as the first record in the block.&lt;br /&gt;
&lt;br /&gt;
One thing I don't quite understand is that I created records to fill 3 data blocks, so there was 1 bottom pointer and 3 data blocks, but after all of that, what was left was block 0 was the bottom pointer, it has one pointer to block 2. Block 1 is marked empty and has one record in it, the original last record, as according to my last paragraph. Block 2 which I removed like 50 records from the middle of the block, and the records after it were moved up to fill the hole. Block 3 is marked empty and has one record in it at the beginning, the original last record, as according to my last paragraph. It also has a bunch of records at the end, but it's marked empty, so that seems fine. But why did leave them there, and why don't they match what I'd expect? They have records that were originally in block 3, and some of them are still there in block 3. So that part is a mystery, based on the code I ran, and the state of the blocks at each point. Block 5 is really weird. It was never used for data. But it has a few bits of things in it, and is marked as something I have no clue about, an FBLK. So not an EMPTY, but an FBLK. It is used though, as it has an offset and something before that offset and has that FBLK marker. So I'll have to figure out what an FBLK is and what it's used for. It's the one block type I don't know yet.&lt;br /&gt;
[1:07 AM]&lt;br /&gt;
Long story short, FreeM will always fill in holes during record deletion, by moving later records up to fill them, and it does not do block joins, it will just mark the block as empty. Both are things RSM does not do.&lt;br /&gt;
[1:10 AM]&lt;br /&gt;
Ohhhh!&lt;br /&gt;
[1:10 AM]&lt;br /&gt;
I know what it is!&lt;br /&gt;
[1:10 AM]&lt;br /&gt;
Clever!&lt;br /&gt;
[1:12 AM]&lt;br /&gt;
It's the free block list! So once FreeM has freed a block that had data in it, it creates a new block called the free block (FBLK), which is just a list of pointers to free blocks in order. So in my testing data, it just has a pointer to block 1 and block 3, which I told you above are both free. Does it always maintain that block at the end of the global somehow, or does it have another way of knowing where to find it? I'll have to figure that out.&lt;br /&gt;
&lt;br /&gt;
dlw — 1:15 AM&lt;br /&gt;
Ooo, that's how!&lt;br /&gt;
[1:17 AM]&lt;br /&gt;
Remember earlier I told you that the ROOT block, always a BOTTOM pointer, didn't have a left and right pointer, since it has no siblings, so instead it uses those fields to store the number of blocks other than the ROOT that are in the global, and the number of free blocks? Yeah, it's not the number of free blocks, it's the block number that stores the FBLK, or free block list! So it can always find that block when it needs a new block, before it would add a new block to the global. So instead of a map block using a bitmap, like RSM uses, it has a pointer from the ROOT block to a FBLK, which maintains the list of free blocks!&lt;br /&gt;
[1:18 AM]&lt;br /&gt;
So there you go, other than a few details on internal key formats, I have taught you pretty much the entire globals module tonight! I have not dug in to block splits, but I'll do that soon, and let you know any details.&lt;br /&gt;
[1:21 AM]&lt;br /&gt;
So, remember that because all of the block pointers are 3 bytes, that means a global in FreeM can be at most, 16 MiB blocks, and at 1 KiB per block, that means no larger than 16 GiB.&lt;br /&gt;
[1:22 AM]&lt;br /&gt;
Just an FYI or a reminder.&lt;br /&gt;
One other thing, FreeM's index/pointer block keys are different than RSM or GT.M/YottaDB.&lt;br /&gt;
&lt;br /&gt;
In GT.M/YottaDB, an index/pointer block stores keys such that the first key, which points to the first data block for that global, is a key that points to every key from the root of the global all the way to, and including, that key. In other words, the keys in the index blocks are the last keys stored in the data block they point to. Then at the end, there is a star pointer (a literal *, for everything else) that points to the last data block, containing any keys that collate after the previous key.&lt;br /&gt;
&lt;br /&gt;
In RSM, an index/pointer block stores keys such that the first key (always the null/empty/root key), which points to the first data block for that global, is a key that points to every key from the root of the global all the way to, and excluding the next key in the index block. In other words, the keys in the index blocks are the first keys stored in the data block they point to, and for the first key, even if there is no data at the root of the global, that key is still stored, just with no data if it doesn't exist (and it flagged as such in the entry for the global in the global directory). So the last key points at the first key in the last block that contains the keys to the end.&lt;br /&gt;
&lt;br /&gt;
In FreeM, an index/pointer block stores keys such that the first key, which points to the first data block for that global, is a key that points to every key, starting with that key, up to, and excluding, the next key in the index block. In other words, the keys in the index blocks are the first keys stored in the data block they point to. But unlike RSM, there is no key for before the first stored key (the null/empty/root key), the first key stored is the first key in the global. Also, unlike GT.M, there is no star pointer at the end. So every index pointer has to be updated if that key is deleted, with another one.&lt;br /&gt;
t's basically a separately maintained linked-list that stores pointers to free blocks. I'm not sure if it would reorganize the pointers in order to keep them in block number order or not though.&lt;br /&gt;
[11:14 AM]&lt;br /&gt;
The root bottom pointer block stores the first free block in its footer, and then that block maintains a right pointer to the next free blook in the linked list, which itself has a left pointer back to the first, and so on. So it's a doubly-linked list.&lt;br /&gt;
[11:16 AM]&lt;br /&gt;
So if you wanted to calculate how many used blocks there are, you'd have to grab the block total from the ROOT footer, and then grab the block free pointer to the first free block, and walk through it, and its siblings, via the right pointers, marking down every block as free, and then what's left is used. There is no direct way to know what blocks are used, without walking the entire B-tree, other than the free block walk I just mentioned, which would be much faster.&lt;br /&gt;
￼&lt;br /&gt;
dlw — 11:21 AM&lt;br /&gt;
The FBLK format is super simple. The footer maintains a left and right pointer, a block type of FBLK or 1, and an offset to the next available free space in the block. And then is just lists block numbers, 3 bytes at a time.&lt;br /&gt;
[11:21 AM]&lt;br /&gt;
No keys, or data, or anything else, just block pointers to free blocks, blocks with types of FREE or 0.&lt;br /&gt;
[11:23 AM]&lt;br /&gt;
The ROOT block's &amp;quot;right&amp;quot; pointer, points to the first FBLK for that global. The ROOT block's &amp;quot;left&amp;quot; pointer, stores the total number of blocks in the global, not including itself.&lt;br /&gt;
[11:23 AM]&lt;br /&gt;
But that does include FREE blocks and FBLK blocks.&lt;br /&gt;
[11:25 AM]&lt;br /&gt;
Because no spaces are allowed between keys, you can easily calculate how full a block is by simply subtracting the OFFSET (stored as the last two bytes in the footer) from DATALIM (the size of the block minus the footer, hard-coded), which then gives you how much free space is left in that block. True for all block types, other than FREE, which just have DATALIM of free space.&lt;br /&gt;
[11:26 AM]&lt;br /&gt;
Unlike RSM, which zeroes out blocks when they are garbage collected, FreeM leaves the data as-is when using or reusing a block, just setting the type to FREE, and the OFFSET to 0.&lt;br /&gt;
[11:26 AM]&lt;br /&gt;
Though when it goes to fill data in to a formerly FREE block, it will then zero the block I believe.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An older conversation about the key format:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
The first byte is 1, that says that the key is 1 byte in length. The second byte is 0, that says there is no key compression. The third byte is 4B, which is 75 in decimal. That is the encoded character that encodes for this first key of length one. Here we use our decoding chops.&lt;br /&gt;
[12:09 PM]&lt;br /&gt;
75 is greater than 31, so we shift its bit pattern `0100 1011` to the right by 1, resulting in `0010 0101`, which is decimal 37. And since it was greater than 31, that's all you do to decode it (between 0 and 19 you do something else, and between 20 and 31, you do something else as well). And ASCII 37 is a % character, which is the full key for that node!&lt;br /&gt;
￼&lt;br /&gt;
dlw — 12/16/23, 12:10 PM&lt;br /&gt;
The fourth byte is 0C, which is 12 decimal, which is the length of the data at that node, so 12 characters. Then the next 12 characters make up the data, and they don't encode subscript delimiters of course, so it's straight forward. Here that is:&lt;br /&gt;
￼&lt;br /&gt;
dlw — 12/16/23, 12:18 PM&lt;br /&gt;
53 63 72 61  74 63 68 20  61 72 65 61 - which in decimal are - 83 99 114 97  116 99 104 32  97 114 101 97 - which are the ASCII codes for &amp;quot;Scratch area&amp;quot;.&lt;br /&gt;
[12:18 PM]&lt;br /&gt;
So that key and its data are ^XVEMS(&amp;quot;%&amp;quot;)=&amp;quot;Scratch area&amp;quot;, which you can see is what FreeM things as well:&lt;br /&gt;
USER&amp;gt; w ^XVEMS(&amp;quot;%&amp;quot;)&lt;br /&gt;
Scratch area&lt;br /&gt;
USER&amp;gt;&lt;br /&gt;
[12:19 PM]&lt;br /&gt;
There was your first walk through of how to decode a FreeM key in a global! (edited)&lt;br /&gt;
[12:20 PM]&lt;br /&gt;
I'll do the next key, just to show you.&lt;br /&gt;
[12:21 PM]&lt;br /&gt;
￼&lt;br /&gt;
[12:21 PM]&lt;br /&gt;
This one has a longer key, and a shorter data node.&lt;br /&gt;
￼&lt;br /&gt;
dlw — 12/16/23, 12:28 PM&lt;br /&gt;
So, the first byte is 9, so the key is 9 bytes. The second byte is 0, so no key compression here either. So then the next 9 bytes, the key, are:&lt;br /&gt;
4B 12 02 04  12 11 A6 90  99 - which converted to the decimal we find easier to think about is - 75 18 2 4  18 17 166 144  153 - so now we have to decode them each in turn. First up is 75, which is higher than 31, so we take its bit pattern `0100 1011` and shift it to the right by one, leading to `0010 0101`, which is 37 decimal, or `%` again. That really should have been part of key compression, no idea what it wasn't. But,here we remember that these characters can encode that they are a subscript boundary, and they do that in their encoded form, which for `%` here, was 75. Remember the 75 bit pattern? It ended with a 1 in the LSB, which means this encodes as a delimiter too, so we now have `&amp;quot;%&amp;quot;,` at this point.&lt;br /&gt;
&lt;br /&gt;
I'll continue on the next message.&lt;br /&gt;
[12:31 PM]&lt;br /&gt;
The second key byte is 18, with a bit pattern of 0001 0010 which does not end in 1, so this does not encode another , or the end of the key. Since this is between 0 and 19, we have to do an addition after the shift, but the shift is still one to the right, for 0000 1001, which is 9. Then, we add '0' to it, since this is numeric, and '0' is ASCII 48, so we get ASCII 57, which codes the number 9 as a string. So now our key is &amp;quot;%&amp;quot;,9. On to the next byte, the third byte, which is 2. The bit pattern is 0000 0010 which doesn't end in 1, so doesn't end the subscript. It's a 2. That gets right shifted, to a 0000 0001, or a 1,  which is then added to '0' (ASCII 48) to get ASCII 49, which is the code for a string of 1, which is not surprising, now that you see the patter. The key is at &amp;quot;%&amp;quot;,91 now. (edited)&lt;br /&gt;
￼&lt;br /&gt;
dlw — 12/16/23, 12:41 PM&lt;br /&gt;
Now we do the fourth byte, which is 4, same story, bit pattern is 0000 0100, not the end of a subscript, and it shifts to 0000 0010 a 2, which when added to '0' 48 again, becomes the string 2. Notice the pattern? When dealing with numerics or numbers, FreeM encodes them as what their ASCII code number is, and then just adds 48 to them, to get back their string equivalent. But since the get right shifted, and lose their last bit, they take up two places in the ASCII code.&lt;br /&gt;
&lt;br /&gt;
For example, ASCII 0 and 1 will result in a 0, 2 and 3 will result in a 1, 4 and 5 will result in a 2, and so on. So, you can take the ASCII number, if it's even, and cut it in half to get right to the number in a string form. And if it's odd, that means it is the last character for that subscript, and you can then subtract 1, and then cut it half to get the character, so an 18 is the number 9, while a 19 is the number 9, and it's the last character of the subsript!&lt;br /&gt;
&lt;br /&gt;
So to finish up the key, we are now at the fifth character, an 18, followed by a sixth, which is a 17. After that, the numbers are way over the 0 to 19 range for numbers. So an 18 is even and cut in half is 9, the next character decoded. The 17 is the first odd one, so it's the end of the subscript, take off 1, and cut in half, and you have 16 to 8, the last character. So our key now looks like &amp;quot;%&amp;quot;,91298,.&lt;br /&gt;
[12:41 PM]&lt;br /&gt;
Now on to the last three characters, 166 144 153! (edited)&lt;br /&gt;
[12:46 PM]&lt;br /&gt;
So all are over 31, so only get right shifted. The first two are even, so they are part of a subscript, and the last one is odd, so it's the end of a subscript. But since the key was only 9 characters, FreeM won't put a , after them, but will end it with the ) instead.&lt;br /&gt;
&lt;br /&gt;
So 166 is 1010 0110, which right shifted is 0101 0011, which is a decimal 83, or the character S. 144 is 1001 0000 shifted right is 0100 1000a decimal 72, ASCII H. Then a 153, which is 1001 1001, shifted right is 0100 1100, a decimal 76, an ASCII L, so the last subscript is &amp;quot;SHL&amp;quot;, and our key is finished!&lt;br /&gt;
&lt;br /&gt;
It is (&amp;quot;%&amp;quot;,91298,&amp;quot;SHL&amp;quot;).&lt;br /&gt;
The next byte is a 3, so the data node is 3 characters, which are 52 55 4E, convert them to decimal and we have 82 85 78, which are the ASCII codes for R U N, and as data nodes aren't encoded with any shifting or masking or anything, that's just what they are! So the (&amp;quot;%&amp;quot;,91298,&amp;quot;SHL&amp;quot;) key stores &amp;quot;RUN&amp;quot;. Now let's see if I was correct.&lt;br /&gt;
[12:50 PM]&lt;br /&gt;
USER&amp;gt; w $q(^XVEMS)&lt;br /&gt;
^XVEMS(&amp;quot;%&amp;quot;)&lt;br /&gt;
USER&amp;gt; w $q(^XVEMS(&amp;quot;%&amp;quot;))&lt;br /&gt;
^XVEMS(&amp;quot;%&amp;quot;,91298,&amp;quot;SHL&amp;quot;)&lt;br /&gt;
USER&amp;gt; w ^XVEMS(&amp;quot;%&amp;quot;)&lt;br /&gt;
Scratch area&lt;br /&gt;
USER&amp;gt; w ^XVEMS(&amp;quot;%&amp;quot;,91298,&amp;quot;SHL&amp;quot;)&lt;br /&gt;
RUN&lt;br /&gt;
USER&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Yep! So that is how you decode global data in FreeM!&lt;br /&gt;
Canonical numbers are shifted down in the control character range, so that they collate before strings, and that means control characters are unavailable for use. . and - are likewise moved to the area right after that, taking up a few other control characters. And strings are shifted up to over ASCII 127, taking over the higher bit, meaning only 7-bit ASCII is supported, no extended character sets.&lt;br /&gt;
&lt;br /&gt;
So the characters that it intends to allow in keys are ASCII 32 - 126, and that's it. Though it does something with 127, but I haven't figured it out yet.&lt;br /&gt;
￼&lt;br /&gt;
Serena Bloodfeather — 12/16/23, 1:22 PM&lt;br /&gt;
in light of everything you learned, have you gotten any new insights into how difficult it would be to get us to where we can support block sizes larger than 1KiB and a commensurate increase in key and node length? strictly in the globals themselves, not accounting for the interpreter having its own issues with long strings.&lt;br /&gt;
￼&lt;br /&gt;
dlw — 12/16/23, 1:25 PM&lt;br /&gt;
There are only two things preventing a larger block size. First, BLOCKLEN is hard-coded, but you know that. Second, all the macros that offset off of BLOCKLEN are hard-coded, and would need to support scaling.&lt;br /&gt;
&lt;br /&gt;
If you fix those two things, you can have bigger block sizes. But, for longer keys and longer data, right now, each stores their lengths in a byte, limiting them to 255 characters. So you'd have to adjust the data size for key and/or record lengths to support larger ones.&lt;br /&gt;
￼&lt;br /&gt;
Serena Bloodfeather — 12/16/23, 1:25 PM&lt;br /&gt;
that's basically what I was thinking&lt;br /&gt;
￼&lt;br /&gt;
dlw — 12/16/23, 1:26 PM&lt;br /&gt;
Sorry, they would not need to support scaling, they just need to follow the offset of a different BLOCKLEN. That's even easier than I was saying.&lt;br /&gt;
￼&lt;br /&gt;
Serena Bloodfeather — 12/16/23, 1:26 PM&lt;br /&gt;
haha that's what I thought you meant by scaling&lt;br /&gt;
￼&lt;br /&gt;
dlw — 12/16/23, 1:26 PM&lt;br /&gt;
So if you set BLOCKLEN based on a user configuration, that should support block sizes larger than 1024 without much else.&lt;br /&gt;
[1:26 PM]&lt;br /&gt;
Scaling is multiplying, offsetting is adding.&lt;br /&gt;
￼&lt;br /&gt;
Serena Bloodfeather — 12/16/23, 1:26 PM&lt;br /&gt;
I've tried changing the BLOCKLEN macro to larger values, and FreeM did not behave well at all&lt;br /&gt;
￼&lt;br /&gt;
dlw — 12/16/23, 1:27 PM&lt;br /&gt;
I'd have to follow all the places that use it to see why.&lt;br /&gt;
[1:30 PM]&lt;br /&gt;
BLOCKLEN is defined in 3 places. It should just work if you change it in all three to the same size.&lt;br /&gt;
￼&lt;br /&gt;
Serena Bloodfeather — 12/16/23, 1:31 PM&lt;br /&gt;
gfix.c, fma_globals.h, and mpsdef0.h?&lt;br /&gt;
￼&lt;br /&gt;
dlw — 12/16/23, 1:31 PM&lt;br /&gt;
Yes&lt;br /&gt;
[1:31 PM]&lt;br /&gt;
But, you'd have to blow away every global you already have, and start with a brand new instance environment.&lt;br /&gt;
￼&lt;br /&gt;
Serena Bloodfeather — 12/16/23, 1:31 PM&lt;br /&gt;
yeah&lt;br /&gt;
[1:32 PM]&lt;br /&gt;
it wouldn't have much utility until nodes and/or keys can be longer than 255 characters&lt;br /&gt;
￼&lt;br /&gt;
dlw — 12/16/23, 1:32 PM&lt;br /&gt;
Until you store the BLOCKLEN itself in block 0, which is totally possible, and probably easy.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Database_Format&amp;diff=375</id>
		<title>Database Format</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Database_Format&amp;diff=375"/>
		<updated>2025-03-29T18:42:43Z</updated>

		<summary type="html">&lt;p&gt;Smw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;From David Wicksell&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
The first block in my global is a bottom level pointer. Maybe that's what a ROOT block always is? But there is no data in any other block, as it's a brand new global. Confusing.&lt;br /&gt;
Oh, I take that back. There is another block!&lt;br /&gt;
So with a global with even just one small record in it, there will be more than one block.&lt;br /&gt;
I suspect bottom pointer is called that because it's abstracted to be an upside down tree, and it's the root block for the global, which is the &amp;quot;bottom&amp;quot; of the global tree.&lt;br /&gt;
I still don't quite understand this format though.&lt;br /&gt;
That's block 0 of ^dlw. The 1, 3, and 1 on the top line appear to be pointers to another block, block 1.&lt;br /&gt;
[4:33 PM]&lt;br /&gt;
The end of that block has the metadata about the type of block it is, but the front of this block has at least one pointer to block number 1.&lt;br /&gt;
Yep, that is definitive now. Block 1, or the second block, contains my first key, the only key, in the global, so far.&lt;br /&gt;
[4:37 PM]&lt;br /&gt;
I will figure this out.&lt;br /&gt;
Ok, I see where key compression is done.&lt;br /&gt;
[4:46 PM]&lt;br /&gt;
I almost have the first block structure figured out.&lt;br /&gt;
[4:51 PM]&lt;br /&gt;
Ok, if the key you are going to insert isn't in the data block where it sorts to, then FreeM will lseek back in to the ROOT, and add the pointer first. So it has to traverse the path twice.&lt;br /&gt;
Ok, that's strange. The key format for canonical numbers is odd. It turns a subscript of (2) in to a 5 in the key.&lt;br /&gt;
[4:58 PM]&lt;br /&gt;
I believe it also turns a (0) in to a 3 and a (1) in to a 4. I guess it can't use ASCII 0, 1, or 2 for that. (edited)&lt;br /&gt;
[5:01 PM]&lt;br /&gt;
I can definitelly see ways to speed up globals in FreeM! For one thing, it recalculates the file path to the global over and over, even when it has the file descriptor stored already.&lt;br /&gt;
Ok, so I have the ROOT block, which is a bottom pointer block figured out, format wise.&lt;br /&gt;
[5:21 PM]&lt;br /&gt;
[5:24 PM]&lt;br /&gt;
Starting at the first byte of the block, the 1 is the length of the first key in the global. Then it skips a byte, and the 3 is the first key. Then, because the block is a pointer block, all keys are hard-coded with a 3 byte pointer to their data block. So the next three bytes, 00 00 01 are a pointer to the block containing key 3. Now key 3 is actually ^dlw(1), but that 1 is encoded in to a compact key form, and ends up as 3. I'm not 100% sure why yet. So that points to block 1. I'm inserting a new pointer for ^dlw(2) right now, so in a few minutes, this first block will have another key up on the top line, and I'll show that to you once it's there.&lt;br /&gt;
[5:25 PM]&lt;br /&gt;
FreeM also maintains a path through the blocks in a global, just like RSM does and just like GT.M/YottaDB do.&lt;br /&gt;
[5:28 PM]&lt;br /&gt;
In RSM, that path is recorded in an array of pointers to global buffer descriptors in shared memory, called blk, it is 12 pointers long. In FreeM, the path seems to be in 2 arrays of longs, the first traceblk stores the block numbers in the path, and the second, traceadr also stores numbers, but shorts instead of unsigned longs. So far, I haven't figured out what it stores semantically. Both hold 32 numbers, so that would support the idea that it can handle a B-tree of 32 levels, which is gigantic&lt;br /&gt;
dlw — Yesterday at 6:56 PM&lt;br /&gt;
Ok, before inserting the second key, here is what block 0, the ROOT, a BOTTOM pointer for ^dlw looks like:&lt;br /&gt;
&amp;quot;\001\000\003\000\000\001&amp;quot;, '\000' &amp;lt;repeats 1010 times&amp;gt;, &amp;quot;\001\000\000\000\000\006\000\006&amp;quot;&lt;br /&gt;
You can see stuff at the beginning and the end. Starting at the beginning, is 001 then 000, which added together is 1 (because of key compression), the length of the first key. Then the key is 003 (which is the compact form of (1) I guess). Then, since it's a BOTTOM block, which is a pointer, and pointers are always 3 bytes, the next 3 bytes are 000 000 001, which when calculated is a pointer to block 1.&lt;br /&gt;
&lt;br /&gt;
Then, looking at the end of the block, the third to last byte is 006, which is the block type, BOTTOM. Then the last two bytes are 000 006, which, when calculated is an offset in to the block itself, of 6, meaning that it's the beginning of the free space in the block, offset from the beginning of the block. Then, to the left of the 006 type, is 3 bytes of 000 000 000, which would be the right pointer in a data block (maybe a pointer block too), but in the ROOT block, it's the number of free blocks in the global, which is 0, since there are only 2 blocks right now, and neither are empty. Then, one byte to the left of that is 000, which is the collation for the block, and a 0 is just M collation. Then, the three bytes before that are 000 000 001, and if this were a data block (maybe a pointer block too), it would be the left pointer, but since this is the ROOT block, it's the number of total blocks in the global, in this case 1. Since there is the ROOT block and a data block, the total block count must not include the ROOT block, but is how many more blocks.&lt;br /&gt;
&lt;br /&gt;
Next we'll look at the second block, a data block.&lt;br /&gt;
dlw — Yesterday at 7:04 PM&lt;br /&gt;
Ok, before inserting the second key, here is what block 1, the DATA block, for ^dlw looks like:&lt;br /&gt;
&amp;quot;\001\000\003\0011&amp;quot;, '\000' &amp;lt;repeats 1016 times&amp;gt;, &amp;quot;\b\000\005&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You can see stuff at the beginning and the end. Starting at the beginning, is 001 then 000, which added together is 1 (because of key compression), the length of the first key. Then the key is 003 (which is the compact form of (1) I guess). So far, identical to the ROOT, but once more keys are there, enough to need more blocks, then that will likely change. Then, since it's a DATA block, which is not a pointer, the next byte is the length of the data record at the key, which is a length of 1. Then, the next byte is 1 (ASCII 49, since the compact form is only in keys, and this is data), the data at ^dlw(1).&lt;br /&gt;
&lt;br /&gt;
Then, looking at the end of the block, the third to last byte is \b (which is 008), which is the block type, DATA. Then the lsat two bytes are 000 005, which, when calculated is an offset in to the block itself, of 5, meaning that it's the beginning of the free space in the block, offset from the beginning of the block. Then, to the left of the 008 type, is 3 bytes of 000 000 000, which would be the number of free blocks in the ROOT, but since this is DATA, is the right pointer. There are no blocks to the right, so it's 0. The, one byte to the left of that is 000, which in a DATA block is a reserved byte, and always 0. You could do something with that in the future. Then, the three bytes before that are 000 000 000, which would be the number of total blocks in the ROOT, but since this is DATA, is the left pointer. There are not blocks to the left, so it's 0.&lt;br /&gt;
[7:06 PM]&lt;br /&gt;
So that's what I've worked out so far. One observation, currently a key length is stored in two bytes, a byte for the length, and one for how much is compressed. So a key in a global in FreeM is restricted to 255 bytes without changing the format. The more important observatoin is that the length of a data record, or node, is stored in a single byte, also limiting it to 255 bytes without changing the format. Since I know you want to raise your string limits, you'll have to look at that first. I can help you figure out where to go and what to do if you like.&lt;br /&gt;
&lt;br /&gt;
dlw — Yesterday at 7:11 PM&lt;br /&gt;
By the way, I'm doing this for two reasons. First, I love this sort of code, so I'm enjoying it. Second, and more importantly, I know you hate it, so I'm trying to help you out, because I want you to succeed at increasing the string length in FreeM.&lt;br /&gt;
&lt;br /&gt;
dlw — Yesterday at 7:55 PM&lt;br /&gt;
Ok, I understand the FreeM block structure much better now.&lt;br /&gt;
Ok, some weird things happen, they may or may not matter. I'll have to look in to that. But no block joins happen at all. Rather, most of a block that has all of its keys removed stays there empty.&lt;br /&gt;
[12:37 AM]&lt;br /&gt;
I had a global with 1 pointer block and 3 data blocks, and I killed all the records in the first and third data block, and for the most part, they are just sitting there all empty, while the second block is still full. The weirdness is that they both have one record still in them, and I'm not sure why. It's the last key, and it appears to have been moved to the front of the block. So maybe a FOR loop in FreeM is not inclusive in its END condtion, but exclusive. Or maybe something else is going on. Now I'm going to remove keys from the middle of the second block to see what happens.&lt;br /&gt;
[12:41 AM]&lt;br /&gt;
Blocks in FreeM do not contain their block number.&lt;br /&gt;
[12:41 AM]&lt;br /&gt;
I guess I just assumed they would.&lt;br /&gt;
Ok, so that weirdness seems to just be an artifact, and I know why.&lt;br /&gt;
&lt;br /&gt;
dlw — 1:06 AM&lt;br /&gt;
I was removing records in a loop, and when it got to the last record in a block, it didn't bother to remove it, instead it left it there, and just marked the block as empty. So it definitely does not do joins, it will remove records, and each time it does, it will re-key the block so that the keys after the one that was removed, are moved up to fill in the empty spot. Once it gets to that last record, it just marks the block free and leaves the record there, as the first record in the block.&lt;br /&gt;
&lt;br /&gt;
One thing I don't quite understand is that I created records to fill 3 data blocks, so there was 1 bottom pointer and 3 data blocks, but after all of that, what was left was block 0 was the bottom pointer, it has one pointer to block 2. Block 1 is marked empty and has one record in it, the original last record, as according to my last paragraph. Block 2 which I removed like 50 records from the middle of the block, and the records after it were moved up to fill the hole. Block 3 is marked empty and has one record in it at the beginning, the original last record, as according to my last paragraph. It also has a bunch of records at the end, but it's marked empty, so that seems fine. But why did leave them there, and why don't they match what I'd expect? They have records that were originally in block 3, and some of them are still there in block 3. So that part is a mystery, based on the code I ran, and the state of the blocks at each point. Block 5 is really weird. It was never used for data. But it has a few bits of things in it, and is marked as something I have no clue about, an FBLK. So not an EMPTY, but an FBLK. It is used though, as it has an offset and something before that offset and has that FBLK marker. So I'll have to figure out what an FBLK is and what it's used for. It's the one block type I don't know yet.&lt;br /&gt;
[1:07 AM]&lt;br /&gt;
Long story short, FreeM will always fill in holes during record deletion, by moving later records up to fill them, and it does not do block joins, it will just mark the block as empty. Both are things RSM does not do.&lt;br /&gt;
[1:10 AM]&lt;br /&gt;
Ohhhh!&lt;br /&gt;
[1:10 AM]&lt;br /&gt;
I know what it is!&lt;br /&gt;
[1:10 AM]&lt;br /&gt;
Clever!&lt;br /&gt;
[1:12 AM]&lt;br /&gt;
It's the free block list! So once FreeM has freed a block that had data in it, it creates a new block called the free block (FBLK), which is just a list of pointers to free blocks in order. So in my testing data, it just has a pointer to block 1 and block 3, which I told you above are both free. Does it always maintain that block at the end of the global somehow, or does it have another way of knowing where to find it? I'll have to figure that out.&lt;br /&gt;
&lt;br /&gt;
dlw — 1:15 AM&lt;br /&gt;
Ooo, that's how!&lt;br /&gt;
[1:17 AM]&lt;br /&gt;
Remember earlier I told you that the ROOT block, always a BOTTOM pointer, didn't have a left and right pointer, since it has no siblings, so instead it uses those fields to store the number of blocks other than the ROOT that are in the global, and the number of free blocks? Yeah, it's not the number of free blocks, it's the block number that stores the FBLK, or free block list! So it can always find that block when it needs a new block, before it would add a new block to the global. So instead of a map block using a bitmap, like RSM uses, it has a pointer from the ROOT block to a FBLK, which maintains the list of free blocks!&lt;br /&gt;
[1:18 AM]&lt;br /&gt;
So there you go, other than a few details on internal key formats, I have taught you pretty much the entire globals module tonight! I have not dug in to block splits, but I'll do that soon, and let you know any details.&lt;br /&gt;
[1:21 AM]&lt;br /&gt;
So, remember that because all of the block pointers are 3 bytes, that means a global in FreeM can be at most, 16 MiB blocks, and at 1 KiB per block, that means no larger than 16 GiB.&lt;br /&gt;
[1:22 AM]&lt;br /&gt;
Just an FYI or a reminder.&lt;br /&gt;
One other thing, FreeM's index/pointer block keys are different than RSM or GT.M/YottaDB.&lt;br /&gt;
&lt;br /&gt;
In GT.M/YottaDB, an index/pointer block stores keys such that the first key, which points to the first data block for that global, is a key that points to every key from the root of the global all the way to, and including, that key. In other words, the keys in the index blocks are the last keys stored in the data block they point to. Then at the end, there is a star pointer (a literal *, for everything else) that points to the last data block, containing any keys that collate after the previous key.&lt;br /&gt;
&lt;br /&gt;
In RSM, an index/pointer block stores keys such that the first key (always the null/empty/root key), which points to the first data block for that global, is a key that points to every key from the root of the global all the way to, and excluding the next key in the index block. In other words, the keys in the index blocks are the first keys stored in the data block they point to, and for the first key, even if there is no data at the root of the global, that key is still stored, just with no data if it doesn't exist (and it flagged as such in the entry for the global in the global directory). So the last key points at the first key in the last block that contains the keys to the end.&lt;br /&gt;
&lt;br /&gt;
In FreeM, an index/pointer block stores keys such that the first key, which points to the first data block for that global, is a key that points to every key, starting with that key, up to, and excluding, the next key in the index block. In other words, the keys in the index blocks are the first keys stored in the data block they point to. But unlike RSM, there is no key for before the first stored key (the null/empty/root key), the first key stored is the first key in the global. Also, unlike GT.M, there is no star pointer at the end. So every index pointer has to be updated if that key is deleted, with another one.&lt;br /&gt;
t's basically a separately maintained linked-list that stores pointers to free blocks. I'm not sure if it would reorganize the pointers in order to keep them in block number order or not though.&lt;br /&gt;
[11:14 AM]&lt;br /&gt;
The root bottom pointer block stores the first free block in its footer, and then that block maintains a right pointer to the next free blook in the linked list, which itself has a left pointer back to the first, and so on. So it's a doubly-linked list.&lt;br /&gt;
[11:16 AM]&lt;br /&gt;
So if you wanted to calculate how many used blocks there are, you'd have to grab the block total from the ROOT footer, and then grab the block free pointer to the first free block, and walk through it, and its siblings, via the right pointers, marking down every block as free, and then what's left is used. There is no direct way to know what blocks are used, without walking the entire B-tree, other than the free block walk I just mentioned, which would be much faster.&lt;br /&gt;
￼&lt;br /&gt;
dlw — 11:21 AM&lt;br /&gt;
The FBLK format is super simple. The footer maintains a left and right pointer, a block type of FBLK or 1, and an offset to the next available free space in the block. And then is just lists block numbers, 3 bytes at a time.&lt;br /&gt;
[11:21 AM]&lt;br /&gt;
No keys, or data, or anything else, just block pointers to free blocks, blocks with types of FREE or 0.&lt;br /&gt;
[11:23 AM]&lt;br /&gt;
The ROOT block's &amp;quot;right&amp;quot; pointer, points to the first FBLK for that global. The ROOT block's &amp;quot;left&amp;quot; pointer, stores the total number of blocks in the global, not including itself.&lt;br /&gt;
[11:23 AM]&lt;br /&gt;
But that does include FREE blocks and FBLK blocks.&lt;br /&gt;
[11:25 AM]&lt;br /&gt;
Because no spaces are allowed between keys, you can easily calculate how full a block is by simply subtracting the OFFSET (stored as the last two bytes in the footer) from DATALIM (the size of the block minus the footer, hard-coded), which then gives you how much free space is left in that block. True for all block types, other than FREE, which just have DATALIM of free space.&lt;br /&gt;
[11:26 AM]&lt;br /&gt;
Unlike RSM, which zeroes out blocks when they are garbage collected, FreeM leaves the data as-is when using or reusing a block, just setting the type to FREE, and the OFFSET to 0.&lt;br /&gt;
[11:26 AM]&lt;br /&gt;
Though when it goes to fill data in to a formerly FREE block, it will then zero the block I believe.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Database_Format&amp;diff=374</id>
		<title>Database Format</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Database_Format&amp;diff=374"/>
		<updated>2025-03-29T16:48:23Z</updated>

		<summary type="html">&lt;p&gt;Smw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;From David Wicksell&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
The first block in my global is a bottom level pointer. Maybe that's what a ROOT block always is? But there is no data in any other block, as it's a brand new global. Confusing.&lt;br /&gt;
Oh, I take that back. There is another block!&lt;br /&gt;
So with a global with even just one small record in it, there will be more than one block.&lt;br /&gt;
I suspect bottom pointer is called that because it's abstracted to be an upside down tree, and it's the root block for the global, which is the &amp;quot;bottom&amp;quot; of the global tree.&lt;br /&gt;
I still don't quite understand this format though.&lt;br /&gt;
That's block 0 of ^dlw. The 1, 3, and 1 on the top line appear to be pointers to another block, block 1.&lt;br /&gt;
[4:33 PM]&lt;br /&gt;
The end of that block has the metadata about the type of block it is, but the front of this block has at least one pointer to block number 1.&lt;br /&gt;
Yep, that is definitive now. Block 1, or the second block, contains my first key, the only key, in the global, so far.&lt;br /&gt;
[4:37 PM]&lt;br /&gt;
I will figure this out.&lt;br /&gt;
Ok, I see where key compression is done.&lt;br /&gt;
[4:46 PM]&lt;br /&gt;
I almost have the first block structure figured out.&lt;br /&gt;
[4:51 PM]&lt;br /&gt;
Ok, if the key you are going to insert isn't in the data block where it sorts to, then FreeM will lseek back in to the ROOT, and add the pointer first. So it has to traverse the path twice.&lt;br /&gt;
Ok, that's strange. The key format for canonical numbers is odd. It turns a subscript of (2) in to a 5 in the key.&lt;br /&gt;
[4:58 PM]&lt;br /&gt;
I believe it also turns a (0) in to a 3 and a (1) in to a 4. I guess it can't use ASCII 0, 1, or 2 for that. (edited)&lt;br /&gt;
[5:01 PM]&lt;br /&gt;
I can definitelly see ways to speed up globals in FreeM! For one thing, it recalculates the file path to the global over and over, even when it has the file descriptor stored already.&lt;br /&gt;
Ok, so I have the ROOT block, which is a bottom pointer block figured out, format wise.&lt;br /&gt;
[5:21 PM]&lt;br /&gt;
[5:24 PM]&lt;br /&gt;
Starting at the first byte of the block, the 1 is the length of the first key in the global. Then it skips a byte, and the 3 is the first key. Then, because the block is a pointer block, all keys are hard-coded with a 3 byte pointer to their data block. So the next three bytes, 00 00 01 are a pointer to the block containing key 3. Now key 3 is actually ^dlw(1), but that 1 is encoded in to a compact key form, and ends up as 3. I'm not 100% sure why yet. So that points to block 1. I'm inserting a new pointer for ^dlw(2) right now, so in a few minutes, this first block will have another key up on the top line, and I'll show that to you once it's there.&lt;br /&gt;
[5:25 PM]&lt;br /&gt;
FreeM also maintains a path through the blocks in a global, just like RSM does and just like GT.M/YottaDB do.&lt;br /&gt;
[5:28 PM]&lt;br /&gt;
In RSM, that path is recorded in an array of pointers to global buffer descriptors in shared memory, called blk, it is 12 pointers long. In FreeM, the path seems to be in 2 arrays of longs, the first traceblk stores the block numbers in the path, and the second, traceadr also stores numbers, but shorts instead of unsigned longs. So far, I haven't figured out what it stores semantically. Both hold 32 numbers, so that would support the idea that it can handle a B-tree of 32 levels, which is gigantic&lt;br /&gt;
dlw — Yesterday at 6:56 PM&lt;br /&gt;
Ok, before inserting the second key, here is what block 0, the ROOT, a BOTTOM pointer for ^dlw looks like:&lt;br /&gt;
&amp;quot;\001\000\003\000\000\001&amp;quot;, '\000' &amp;lt;repeats 1010 times&amp;gt;, &amp;quot;\001\000\000\000\000\006\000\006&amp;quot;&lt;br /&gt;
You can see stuff at the beginning and the end. Starting at the beginning, is 001 then 000, which added together is 1 (because of key compression), the length of the first key. Then the key is 003 (which is the compact form of (1) I guess). Then, since it's a BOTTOM block, which is a pointer, and pointers are always 3 bytes, the next 3 bytes are 000 000 001, which when calculated is a pointer to block 1.&lt;br /&gt;
&lt;br /&gt;
Then, looking at the end of the block, the third to last byte is 006, which is the block type, BOTTOM. Then the last two bytes are 000 006, which, when calculated is an offset in to the block itself, of 6, meaning that it's the beginning of the free space in the block, offset from the beginning of the block. Then, to the left of the 006 type, is 3 bytes of 000 000 000, which would be the right pointer in a data block (maybe a pointer block too), but in the ROOT block, it's the number of free blocks in the global, which is 0, since there are only 2 blocks right now, and neither are empty. Then, one byte to the left of that is 000, which is the collation for the block, and a 0 is just M collation. Then, the three bytes before that are 000 000 001, and if this were a data block (maybe a pointer block too), it would be the left pointer, but since this is the ROOT block, it's the number of total blocks in the global, in this case 1. Since there is the ROOT block and a data block, the total block count must not include the ROOT block, but is how many more blocks.&lt;br /&gt;
&lt;br /&gt;
Next we'll look at the second block, a data block.&lt;br /&gt;
dlw — Yesterday at 7:04 PM&lt;br /&gt;
Ok, before inserting the second key, here is what block 1, the DATA block, for ^dlw looks like:&lt;br /&gt;
&amp;quot;\001\000\003\0011&amp;quot;, '\000' &amp;lt;repeats 1016 times&amp;gt;, &amp;quot;\b\000\005&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You can see stuff at the beginning and the end. Starting at the beginning, is 001 then 000, which added together is 1 (because of key compression), the length of the first key. Then the key is 003 (which is the compact form of (1) I guess). So far, identical to the ROOT, but once more keys are there, enough to need more blocks, then that will likely change. Then, since it's a DATA block, which is not a pointer, the next byte is the length of the data record at the key, which is a length of 1. Then, the next byte is 1 (ASCII 49, since the compact form is only in keys, and this is data), the data at ^dlw(1).&lt;br /&gt;
&lt;br /&gt;
Then, looking at the end of the block, the third to last byte is \b (which is 008), which is the block type, DATA. Then the lsat two bytes are 000 005, which, when calculated is an offset in to the block itself, of 5, meaning that it's the beginning of the free space in the block, offset from the beginning of the block. Then, to the left of the 008 type, is 3 bytes of 000 000 000, which would be the number of free blocks in the ROOT, but since this is DATA, is the right pointer. There are no blocks to the right, so it's 0. The, one byte to the left of that is 000, which in a DATA block is a reserved byte, and always 0. You could do something with that in the future. Then, the three bytes before that are 000 000 000, which would be the number of total blocks in the ROOT, but since this is DATA, is the left pointer. There are not blocks to the left, so it's 0.&lt;br /&gt;
[7:06 PM]&lt;br /&gt;
So that's what I've worked out so far. One observation, currently a key length is stored in two bytes, a byte for the length, and one for how much is compressed. So a key in a global in FreeM is restricted to 255 bytes without changing the format. The more important observatoin is that the length of a data record, or node, is stored in a single byte, also limiting it to 255 bytes without changing the format. Since I know you want to raise your string limits, you'll have to look at that first. I can help you figure out where to go and what to do if you like.&lt;br /&gt;
&lt;br /&gt;
dlw — Yesterday at 7:11 PM&lt;br /&gt;
By the way, I'm doing this for two reasons. First, I love this sort of code, so I'm enjoying it. Second, and more importantly, I know you hate it, so I'm trying to help you out, because I want you to succeed at increasing the string length in FreeM.&lt;br /&gt;
&lt;br /&gt;
dlw — Yesterday at 7:55 PM&lt;br /&gt;
Ok, I understand the FreeM block structure much better now.&lt;br /&gt;
Ok, some weird things happen, they may or may not matter. I'll have to look in to that. But no block joins happen at all. Rather, most of a block that has all of its keys removed stays there empty.&lt;br /&gt;
[12:37 AM]&lt;br /&gt;
I had a global with 1 pointer block and 3 data blocks, and I killed all the records in the first and third data block, and for the most part, they are just sitting there all empty, while the second block is still full. The weirdness is that they both have one record still in them, and I'm not sure why. It's the last key, and it appears to have been moved to the front of the block. So maybe a FOR loop in FreeM is not inclusive in its END condtion, but exclusive. Or maybe something else is going on. Now I'm going to remove keys from the middle of the second block to see what happens.&lt;br /&gt;
[12:41 AM]&lt;br /&gt;
Blocks in FreeM do not contain their block number.&lt;br /&gt;
[12:41 AM]&lt;br /&gt;
I guess I just assumed they would.&lt;br /&gt;
Ok, so that weirdness seems to just be an artifact, and I know why.&lt;br /&gt;
&lt;br /&gt;
dlw — 1:06 AM&lt;br /&gt;
I was removing records in a loop, and when it got to the last record in a block, it didn't bother to remove it, instead it left it there, and just marked the block as empty. So it definitely does not do joins, it will remove records, and each time it does, it will re-key the block so that the keys after the one that was removed, are moved up to fill in the empty spot. Once it gets to that last record, it just marks the block free and leaves the record there, as the first record in the block.&lt;br /&gt;
&lt;br /&gt;
One thing I don't quite understand is that I created records to fill 3 data blocks, so there was 1 bottom pointer and 3 data blocks, but after all of that, what was left was block 0 was the bottom pointer, it has one pointer to block 2. Block 1 is marked empty and has one record in it, the original last record, as according to my last paragraph. Block 2 which I removed like 50 records from the middle of the block, and the records after it were moved up to fill the hole. Block 3 is marked empty and has one record in it at the beginning, the original last record, as according to my last paragraph. It also has a bunch of records at the end, but it's marked empty, so that seems fine. But why did leave them there, and why don't they match what I'd expect? They have records that were originally in block 3, and some of them are still there in block 3. So that part is a mystery, based on the code I ran, and the state of the blocks at each point. Block 5 is really weird. It was never used for data. But it has a few bits of things in it, and is marked as something I have no clue about, an FBLK. So not an EMPTY, but an FBLK. It is used though, as it has an offset and something before that offset and has that FBLK marker. So I'll have to figure out what an FBLK is and what it's used for. It's the one block type I don't know yet.&lt;br /&gt;
[1:07 AM]&lt;br /&gt;
Long story short, FreeM will always fill in holes during record deletion, by moving later records up to fill them, and it does not do block joins, it will just mark the block as empty. Both are things RSM does not do.&lt;br /&gt;
[1:10 AM]&lt;br /&gt;
Ohhhh!&lt;br /&gt;
[1:10 AM]&lt;br /&gt;
I know what it is!&lt;br /&gt;
[1:10 AM]&lt;br /&gt;
Clever!&lt;br /&gt;
[1:12 AM]&lt;br /&gt;
It's the free block list! So once FreeM has freed a block that had data in it, it creates a new block called the free block (FBLK), which is just a list of pointers to free blocks in order. So in my testing data, it just has a pointer to block 1 and block 3, which I told you above are both free. Does it always maintain that block at the end of the global somehow, or does it have another way of knowing where to find it? I'll have to figure that out.&lt;br /&gt;
&lt;br /&gt;
dlw — 1:15 AM&lt;br /&gt;
Ooo, that's how!&lt;br /&gt;
[1:17 AM]&lt;br /&gt;
Remember earlier I told you that the ROOT block, always a BOTTOM pointer, didn't have a left and right pointer, since it has no siblings, so instead it uses those fields to store the number of blocks other than the ROOT that are in the global, and the number of free blocks? Yeah, it's not the number of free blocks, it's the block number that stores the FBLK, or free block list! So it can always find that block when it needs a new block, before it would add a new block to the global. So instead of a map block using a bitmap, like RSM uses, it has a pointer from the ROOT block to a FBLK, which maintains the list of free blocks!&lt;br /&gt;
[1:18 AM]&lt;br /&gt;
So there you go, other than a few details on internal key formats, I have taught you pretty much the entire globals module tonight! I have not dug in to block splits, but I'll do that soon, and let you know any details.&lt;br /&gt;
[1:21 AM]&lt;br /&gt;
So, remember that because all of the block pointers are 3 bytes, that means a global in FreeM can be at most, 16 MiB blocks, and at 1 KiB per block, that means no larger than 16 GiB.&lt;br /&gt;
[1:22 AM]&lt;br /&gt;
Just an FYI or a reminder.&lt;br /&gt;
One other thing, FreeM's index/pointer block keys are different than RSM or GT.M/YottaDB.&lt;br /&gt;
&lt;br /&gt;
In GT.M/YottaDB, an index/pointer block stores keys such that the first key, which points to the first data block for that global, is a key that points to every key from the root of the global all the way to, and including, that key. In other words, the keys in the index blocks are the last keys stored in the data block they point to. Then at the end, there is a star pointer (a literal *, for everything else) that points to the last data block, containing any keys that collate after the previous key.&lt;br /&gt;
&lt;br /&gt;
In RSM, an index/pointer block stores keys such that the first key (always the null/empty/root key), which points to the first data block for that global, is a key that points to every key from the root of the global all the way to, and excluding the next key in the index block. In other words, the keys in the index blocks are the first keys stored in the data block they point to, and for the first key, even if there is no data at the root of the global, that key is still stored, just with no data if it doesn't exist (and it flagged as such in the entry for the global in the global directory). So the last key points at the first key in the last block that contains the keys to the end.&lt;br /&gt;
&lt;br /&gt;
In FreeM, an index/pointer block stores keys such that the first key, which points to the first data block for that global, is a key that points to every key, starting with that key, up to, and excluding, the next key in the index block. In other words, the keys in the index blocks are the first keys stored in the data block they point to. But unlike RSM, there is no key for before the first stored key (the null/empty/root key), the first key stored is the first key in the global. Also, unlike GT.M, there is no star pointer at the end. So every index pointer has to be updated if that key is deleted, with another one.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Database_Format&amp;diff=373</id>
		<title>Database Format</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Database_Format&amp;diff=373"/>
		<updated>2025-03-29T16:40:13Z</updated>

		<summary type="html">&lt;p&gt;Smw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;From David Wicksell&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
The first block in my global is a bottom level pointer. Maybe that's what a ROOT block always is? But there is no data in any other block, as it's a brand new global. Confusing.&lt;br /&gt;
Oh, I take that back. There is another block!&lt;br /&gt;
So with a global with even just one small record in it, there will be more than one block.&lt;br /&gt;
I suspect bottom pointer is called that because it's abstracted to be an upside down tree, and it's the root block for the global, which is the &amp;quot;bottom&amp;quot; of the global tree.&lt;br /&gt;
I still don't quite understand this format though.&lt;br /&gt;
That's block 0 of ^dlw. The 1, 3, and 1 on the top line appear to be pointers to another block, block 1.&lt;br /&gt;
[4:33 PM]&lt;br /&gt;
The end of that block has the metadata about the type of block it is, but the front of this block has at least one pointer to block number 1.&lt;br /&gt;
Yep, that is definitive now. Block 1, or the second block, contains my first key, the only key, in the global, so far.&lt;br /&gt;
[4:37 PM]&lt;br /&gt;
I will figure this out.&lt;br /&gt;
Ok, I see where key compression is done.&lt;br /&gt;
[4:46 PM]&lt;br /&gt;
I almost have the first block structure figured out.&lt;br /&gt;
[4:51 PM]&lt;br /&gt;
Ok, if the key you are going to insert isn't in the data block where it sorts to, then FreeM will lseek back in to the ROOT, and add the pointer first. So it has to traverse the path twice.&lt;br /&gt;
Ok, that's strange. The key format for canonical numbers is odd. It turns a subscript of (2) in to a 5 in the key.&lt;br /&gt;
[4:58 PM]&lt;br /&gt;
I believe it also turns a (0) in to a 3 and a (1) in to a 4. I guess it can't use ASCII 0, 1, or 2 for that. (edited)&lt;br /&gt;
[5:01 PM]&lt;br /&gt;
I can definitelly see ways to speed up globals in FreeM! For one thing, it recalculates the file path to the global over and over, even when it has the file descriptor stored already.&lt;br /&gt;
Ok, so I have the ROOT block, which is a bottom pointer block figured out, format wise.&lt;br /&gt;
[5:21 PM]&lt;br /&gt;
[5:24 PM]&lt;br /&gt;
Starting at the first byte of the block, the 1 is the length of the first key in the global. Then it skips a byte, and the 3 is the first key. Then, because the block is a pointer block, all keys are hard-coded with a 3 byte pointer to their data block. So the next three bytes, 00 00 01 are a pointer to the block containing key 3. Now key 3 is actually ^dlw(1), but that 1 is encoded in to a compact key form, and ends up as 3. I'm not 100% sure why yet. So that points to block 1. I'm inserting a new pointer for ^dlw(2) right now, so in a few minutes, this first block will have another key up on the top line, and I'll show that to you once it's there.&lt;br /&gt;
[5:25 PM]&lt;br /&gt;
FreeM also maintains a path through the blocks in a global, just like RSM does and just like GT.M/YottaDB do.&lt;br /&gt;
[5:28 PM]&lt;br /&gt;
In RSM, that path is recorded in an array of pointers to global buffer descriptors in shared memory, called blk, it is 12 pointers long. In FreeM, the path seems to be in 2 arrays of longs, the first traceblk stores the block numbers in the path, and the second, traceadr also stores numbers, but shorts instead of unsigned longs. So far, I haven't figured out what it stores semantically. Both hold 32 numbers, so that would support the idea that it can handle a B-tree of 32 levels, which is gigantic&lt;br /&gt;
dlw — Yesterday at 6:56 PM&lt;br /&gt;
Ok, before inserting the second key, here is what block 0, the ROOT, a BOTTOM pointer for ^dlw looks like:&lt;br /&gt;
&amp;quot;\001\000\003\000\000\001&amp;quot;, '\000' &amp;lt;repeats 1010 times&amp;gt;, &amp;quot;\001\000\000\000\000\006\000\006&amp;quot;&lt;br /&gt;
You can see stuff at the beginning and the end. Starting at the beginning, is 001 then 000, which added together is 1 (because of key compression), the length of the first key. Then the key is 003 (which is the compact form of (1) I guess). Then, since it's a BOTTOM block, which is a pointer, and pointers are always 3 bytes, the next 3 bytes are 000 000 001, which when calculated is a pointer to block 1.&lt;br /&gt;
&lt;br /&gt;
Then, looking at the end of the block, the third to last byte is 006, which is the block type, BOTTOM. Then the last two bytes are 000 006, which, when calculated is an offset in to the block itself, of 6, meaning that it's the beginning of the free space in the block, offset from the beginning of the block. Then, to the left of the 006 type, is 3 bytes of 000 000 000, which would be the right pointer in a data block (maybe a pointer block too), but in the ROOT block, it's the number of free blocks in the global, which is 0, since there are only 2 blocks right now, and neither are empty. Then, one byte to the left of that is 000, which is the collation for the block, and a 0 is just M collation. Then, the three bytes before that are 000 000 001, and if this were a data block (maybe a pointer block too), it would be the left pointer, but since this is the ROOT block, it's the number of total blocks in the global, in this case 1. Since there is the ROOT block and a data block, the total block count must not include the ROOT block, but is how many more blocks.&lt;br /&gt;
&lt;br /&gt;
Next we'll look at the second block, a data block.&lt;br /&gt;
dlw — Yesterday at 7:04 PM&lt;br /&gt;
Ok, before inserting the second key, here is what block 1, the DATA block, for ^dlw looks like:&lt;br /&gt;
&amp;quot;\001\000\003\0011&amp;quot;, '\000' &amp;lt;repeats 1016 times&amp;gt;, &amp;quot;\b\000\005&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You can see stuff at the beginning and the end. Starting at the beginning, is 001 then 000, which added together is 1 (because of key compression), the length of the first key. Then the key is 003 (which is the compact form of (1) I guess). So far, identical to the ROOT, but once more keys are there, enough to need more blocks, then that will likely change. Then, since it's a DATA block, which is not a pointer, the next byte is the length of the data record at the key, which is a length of 1. Then, the next byte is 1 (ASCII 49, since the compact form is only in keys, and this is data), the data at ^dlw(1).&lt;br /&gt;
&lt;br /&gt;
Then, looking at the end of the block, the third to last byte is \b (which is 008), which is the block type, DATA. Then the lsat two bytes are 000 005, which, when calculated is an offset in to the block itself, of 5, meaning that it's the beginning of the free space in the block, offset from the beginning of the block. Then, to the left of the 008 type, is 3 bytes of 000 000 000, which would be the number of free blocks in the ROOT, but since this is DATA, is the right pointer. There are no blocks to the right, so it's 0. The, one byte to the left of that is 000, which in a DATA block is a reserved byte, and always 0. You could do something with that in the future. Then, the three bytes before that are 000 000 000, which would be the number of total blocks in the ROOT, but since this is DATA, is the left pointer. There are not blocks to the left, so it's 0.&lt;br /&gt;
[7:06 PM]&lt;br /&gt;
So that's what I've worked out so far. One observation, currently a key length is stored in two bytes, a byte for the length, and one for how much is compressed. So a key in a global in FreeM is restricted to 255 bytes without changing the format. The more important observatoin is that the length of a data record, or node, is stored in a single byte, also limiting it to 255 bytes without changing the format. Since I know you want to raise your string limits, you'll have to look at that first. I can help you figure out where to go and what to do if you like.&lt;br /&gt;
&lt;br /&gt;
dlw — Yesterday at 7:11 PM&lt;br /&gt;
By the way, I'm doing this for two reasons. First, I love this sort of code, so I'm enjoying it. Second, and more importantly, I know you hate it, so I'm trying to help you out, because I want you to succeed at increasing the string length in FreeM.&lt;br /&gt;
&lt;br /&gt;
dlw — Yesterday at 7:55 PM&lt;br /&gt;
Ok, I understand the FreeM block structure much better now.&lt;br /&gt;
Ok, some weird things happen, they may or may not matter. I'll have to look in to that. But no block joins happen at all. Rather, most of a block that has all of its keys removed stays there empty.&lt;br /&gt;
[12:37 AM]&lt;br /&gt;
I had a global with 1 pointer block and 3 data blocks, and I killed all the records in the first and third data block, and for the most part, they are just sitting there all empty, while the second block is still full. The weirdness is that they both have one record still in them, and I'm not sure why. It's the last key, and it appears to have been moved to the front of the block. So maybe a FOR loop in FreeM is not inclusive in its END condtion, but exclusive. Or maybe something else is going on. Now I'm going to remove keys from the middle of the second block to see what happens.&lt;br /&gt;
[12:41 AM]&lt;br /&gt;
Blocks in FreeM do not contain their block number.&lt;br /&gt;
[12:41 AM]&lt;br /&gt;
I guess I just assumed they would.&lt;br /&gt;
Ok, so that weirdness seems to just be an artifact, and I know why.&lt;br /&gt;
&lt;br /&gt;
dlw — 1:06 AM&lt;br /&gt;
I was removing records in a loop, and when it got to the last record in a block, it didn't bother to remove it, instead it left it there, and just marked the block as empty. So it definitely does not do joins, it will remove records, and each time it does, it will re-key the block so that the keys after the one that was removed, are moved up to fill in the empty spot. Once it gets to that last record, it just marks the block free and leaves the record there, as the first record in the block.&lt;br /&gt;
&lt;br /&gt;
One thing I don't quite understand is that I created records to fill 3 data blocks, so there was 1 bottom pointer and 3 data blocks, but after all of that, what was left was block 0 was the bottom pointer, it has one pointer to block 2. Block 1 is marked empty and has one record in it, the original last record, as according to my last paragraph. Block 2 which I removed like 50 records from the middle of the block, and the records after it were moved up to fill the hole. Block 3 is marked empty and has one record in it at the beginning, the original last record, as according to my last paragraph. It also has a bunch of records at the end, but it's marked empty, so that seems fine. But why did leave them there, and why don't they match what I'd expect? They have records that were originally in block 3, and some of them are still there in block 3. So that part is a mystery, based on the code I ran, and the state of the blocks at each point. Block 5 is really weird. It was never used for data. But it has a few bits of things in it, and is marked as something I have no clue about, an FBLK. So not an EMPTY, but an FBLK. It is used though, as it has an offset and something before that offset and has that FBLK marker. So I'll have to figure out what an FBLK is and what it's used for. It's the one block type I don't know yet.&lt;br /&gt;
[1:07 AM]&lt;br /&gt;
Long story short, FreeM will always fill in holes during record deletion, by moving later records up to fill them, and it does not do block joins, it will just mark the block as empty. Both are things RSM does not do.&lt;br /&gt;
[1:10 AM]&lt;br /&gt;
Ohhhh!&lt;br /&gt;
[1:10 AM]&lt;br /&gt;
I know what it is!&lt;br /&gt;
[1:10 AM]&lt;br /&gt;
Clever!&lt;br /&gt;
[1:12 AM]&lt;br /&gt;
It's the free block list! So once FreeM has freed a block that had data in it, it creates a new block called the free block (FBLK), which is just a list of pointers to free blocks in order. So in my testing data, it just has a pointer to block 1 and block 3, which I told you above are both free. Does it always maintain that block at the end of the global somehow, or does it have another way of knowing where to find it? I'll have to figure that out.&lt;br /&gt;
&lt;br /&gt;
dlw — 1:15 AM&lt;br /&gt;
Ooo, that's how!&lt;br /&gt;
[1:17 AM]&lt;br /&gt;
Remember earlier I told you that the ROOT block, always a BOTTOM pointer, didn't have a left and right pointer, since it has no siblings, so instead it uses those fields to store the number of blocks other than the ROOT that are in the global, and the number of free blocks? Yeah, it's not the number of free blocks, it's the block number that stores the FBLK, or free block list! So it can always find that block when it needs a new block, before it would add a new block to the global. So instead of a map block using a bitmap, like RSM uses, it has a pointer from the ROOT block to a FBLK, which maintains the list of free blocks!&lt;br /&gt;
[1:18 AM]&lt;br /&gt;
So there you go, other than a few details on internal key formats, I have taught you pretty much the entire globals module tonight! I have not dug in to block splits, but I'll do that soon, and let you know any details.&lt;br /&gt;
[1:21 AM]&lt;br /&gt;
So, remember that because all of the block pointers are 3 bytes, that means a global in FreeM can be at most, 16 MiB blocks, and at 1 KiB per block, that means no larger than 16 GiB.&lt;br /&gt;
[1:22 AM]&lt;br /&gt;
Just an FYI or a reminder.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Database_Format&amp;diff=372</id>
		<title>Database Format</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Database_Format&amp;diff=372"/>
		<updated>2025-03-29T16:38:48Z</updated>

		<summary type="html">&lt;p&gt;Smw: Created page with &amp;quot;&amp;lt;pre&amp;gt; The first block in my global is a bottom level pointer. Maybe that's what a ROOT block always is? But there is no data in any other block, as it's a brand new global. Co...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
The first block in my global is a bottom level pointer. Maybe that's what a ROOT block always is? But there is no data in any other block, as it's a brand new global. Confusing.&lt;br /&gt;
Oh, I take that back. There is another block!&lt;br /&gt;
So with a global with even just one small record in it, there will be more than one block.&lt;br /&gt;
I suspect bottom pointer is called that because it's abstracted to be an upside down tree, and it's the root block for the global, which is the &amp;quot;bottom&amp;quot; of the global tree.&lt;br /&gt;
I still don't quite understand this format though.&lt;br /&gt;
That's block 0 of ^dlw. The 1, 3, and 1 on the top line appear to be pointers to another block, block 1.&lt;br /&gt;
[4:33 PM]&lt;br /&gt;
The end of that block has the metadata about the type of block it is, but the front of this block has at least one pointer to block number 1.&lt;br /&gt;
Yep, that is definitive now. Block 1, or the second block, contains my first key, the only key, in the global, so far.&lt;br /&gt;
[4:37 PM]&lt;br /&gt;
I will figure this out.&lt;br /&gt;
Ok, I see where key compression is done.&lt;br /&gt;
[4:46 PM]&lt;br /&gt;
I almost have the first block structure figured out.&lt;br /&gt;
[4:51 PM]&lt;br /&gt;
Ok, if the key you are going to insert isn't in the data block where it sorts to, then FreeM will lseek back in to the ROOT, and add the pointer first. So it has to traverse the path twice.&lt;br /&gt;
Ok, that's strange. The key format for canonical numbers is odd. It turns a subscript of (2) in to a 5 in the key.&lt;br /&gt;
[4:58 PM]&lt;br /&gt;
I believe it also turns a (0) in to a 3 and a (1) in to a 4. I guess it can't use ASCII 0, 1, or 2 for that. (edited)&lt;br /&gt;
[5:01 PM]&lt;br /&gt;
I can definitelly see ways to speed up globals in FreeM! For one thing, it recalculates the file path to the global over and over, even when it has the file descriptor stored already.&lt;br /&gt;
Ok, so I have the ROOT block, which is a bottom pointer block figured out, format wise.&lt;br /&gt;
[5:21 PM]&lt;br /&gt;
[5:24 PM]&lt;br /&gt;
Starting at the first byte of the block, the 1 is the length of the first key in the global. Then it skips a byte, and the 3 is the first key. Then, because the block is a pointer block, all keys are hard-coded with a 3 byte pointer to their data block. So the next three bytes, 00 00 01 are a pointer to the block containing key 3. Now key 3 is actually ^dlw(1), but that 1 is encoded in to a compact key form, and ends up as 3. I'm not 100% sure why yet. So that points to block 1. I'm inserting a new pointer for ^dlw(2) right now, so in a few minutes, this first block will have another key up on the top line, and I'll show that to you once it's there.&lt;br /&gt;
[5:25 PM]&lt;br /&gt;
FreeM also maintains a path through the blocks in a global, just like RSM does and just like GT.M/YottaDB do.&lt;br /&gt;
[5:28 PM]&lt;br /&gt;
In RSM, that path is recorded in an array of pointers to global buffer descriptors in shared memory, called blk, it is 12 pointers long. In FreeM, the path seems to be in 2 arrays of longs, the first traceblk stores the block numbers in the path, and the second, traceadr also stores numbers, but shorts instead of unsigned longs. So far, I haven't figured out what it stores semantically. Both hold 32 numbers, so that would support the idea that it can handle a B-tree of 32 levels, which is gigantic&lt;br /&gt;
dlw — Yesterday at 6:56 PM&lt;br /&gt;
Ok, before inserting the second key, here is what block 0, the ROOT, a BOTTOM pointer for ^dlw looks like:&lt;br /&gt;
&amp;quot;\001\000\003\000\000\001&amp;quot;, '\000' &amp;lt;repeats 1010 times&amp;gt;, &amp;quot;\001\000\000\000\000\006\000\006&amp;quot;&lt;br /&gt;
You can see stuff at the beginning and the end. Starting at the beginning, is 001 then 000, which added together is 1 (because of key compression), the length of the first key. Then the key is 003 (which is the compact form of (1) I guess). Then, since it's a BOTTOM block, which is a pointer, and pointers are always 3 bytes, the next 3 bytes are 000 000 001, which when calculated is a pointer to block 1.&lt;br /&gt;
&lt;br /&gt;
Then, looking at the end of the block, the third to last byte is 006, which is the block type, BOTTOM. Then the last two bytes are 000 006, which, when calculated is an offset in to the block itself, of 6, meaning that it's the beginning of the free space in the block, offset from the beginning of the block. Then, to the left of the 006 type, is 3 bytes of 000 000 000, which would be the right pointer in a data block (maybe a pointer block too), but in the ROOT block, it's the number of free blocks in the global, which is 0, since there are only 2 blocks right now, and neither are empty. Then, one byte to the left of that is 000, which is the collation for the block, and a 0 is just M collation. Then, the three bytes before that are 000 000 001, and if this were a data block (maybe a pointer block too), it would be the left pointer, but since this is the ROOT block, it's the number of total blocks in the global, in this case 1. Since there is the ROOT block and a data block, the total block count must not include the ROOT block, but is how many more blocks.&lt;br /&gt;
&lt;br /&gt;
Next we'll look at the second block, a data block.&lt;br /&gt;
dlw — Yesterday at 7:04 PM&lt;br /&gt;
Ok, before inserting the second key, here is what block 1, the DATA block, for ^dlw looks like:&lt;br /&gt;
&amp;quot;\001\000\003\0011&amp;quot;, '\000' &amp;lt;repeats 1016 times&amp;gt;, &amp;quot;\b\000\005&amp;quot;&lt;br /&gt;
&lt;br /&gt;
You can see stuff at the beginning and the end. Starting at the beginning, is 001 then 000, which added together is 1 (because of key compression), the length of the first key. Then the key is 003 (which is the compact form of (1) I guess). So far, identical to the ROOT, but once more keys are there, enough to need more blocks, then that will likely change. Then, since it's a DATA block, which is not a pointer, the next byte is the length of the data record at the key, which is a length of 1. Then, the next byte is 1 (ASCII 49, since the compact form is only in keys, and this is data), the data at ^dlw(1).&lt;br /&gt;
&lt;br /&gt;
Then, looking at the end of the block, the third to last byte is \b (which is 008), which is the block type, DATA. Then the lsat two bytes are 000 005, which, when calculated is an offset in to the block itself, of 5, meaning that it's the beginning of the free space in the block, offset from the beginning of the block. Then, to the left of the 008 type, is 3 bytes of 000 000 000, which would be the number of free blocks in the ROOT, but since this is DATA, is the right pointer. There are no blocks to the right, so it's 0. The, one byte to the left of that is 000, which in a DATA block is a reserved byte, and always 0. You could do something with that in the future. Then, the three bytes before that are 000 000 000, which would be the number of total blocks in the ROOT, but since this is DATA, is the left pointer. There are not blocks to the left, so it's 0.&lt;br /&gt;
[7:06 PM]&lt;br /&gt;
So that's what I've worked out so far. One observation, currently a key length is stored in two bytes, a byte for the length, and one for how much is compressed. So a key in a global in FreeM is restricted to 255 bytes without changing the format. The more important observatoin is that the length of a data record, or node, is stored in a single byte, also limiting it to 255 bytes without changing the format. Since I know you want to raise your string limits, you'll have to look at that first. I can help you figure out where to go and what to do if you like.&lt;br /&gt;
&lt;br /&gt;
dlw — Yesterday at 7:11 PM&lt;br /&gt;
By the way, I'm doing this for two reasons. First, I love this sort of code, so I'm enjoying it. Second, and more importantly, I know you hate it, so I'm trying to help you out, because I want you to succeed at increasing the string length in FreeM.&lt;br /&gt;
&lt;br /&gt;
dlw — Yesterday at 7:55 PM&lt;br /&gt;
Ok, I understand the FreeM block structure much better now.&lt;br /&gt;
Ok, some weird things happen, they may or may not matter. I'll have to look in to that. But no block joins happen at all. Rather, most of a block that has all of its keys removed stays there empty.&lt;br /&gt;
[12:37 AM]&lt;br /&gt;
I had a global with 1 pointer block and 3 data blocks, and I killed all the records in the first and third data block, and for the most part, they are just sitting there all empty, while the second block is still full. The weirdness is that they both have one record still in them, and I'm not sure why. It's the last key, and it appears to have been moved to the front of the block. So maybe a FOR loop in FreeM is not inclusive in its END condtion, but exclusive. Or maybe something else is going on. Now I'm going to remove keys from the middle of the second block to see what happens.&lt;br /&gt;
[12:41 AM]&lt;br /&gt;
Blocks in FreeM do not contain their block number.&lt;br /&gt;
[12:41 AM]&lt;br /&gt;
I guess I just assumed they would.&lt;br /&gt;
Ok, so that weirdness seems to just be an artifact, and I know why.&lt;br /&gt;
&lt;br /&gt;
dlw — 1:06 AM&lt;br /&gt;
I was removing records in a loop, and when it got to the last record in a block, it didn't bother to remove it, instead it left it there, and just marked the block as empty. So it definitely does not do joins, it will remove records, and each time it does, it will re-key the block so that the keys after the one that was removed, are moved up to fill in the empty spot. Once it gets to that last record, it just marks the block free and leaves the record there, as the first record in the block.&lt;br /&gt;
&lt;br /&gt;
One thing I don't quite understand is that I created records to fill 3 data blocks, so there was 1 bottom pointer and 3 data blocks, but after all of that, what was left was block 0 was the bottom pointer, it has one pointer to block 2. Block 1 is marked empty and has one record in it, the original last record, as according to my last paragraph. Block 2 which I removed like 50 records from the middle of the block, and the records after it were moved up to fill the hole. Block 3 is marked empty and has one record in it at the beginning, the original last record, as according to my last paragraph. It also has a bunch of records at the end, but it's marked empty, so that seems fine. But why did leave them there, and why don't they match what I'd expect? They have records that were originally in block 3, and some of them are still there in block 3. So that part is a mystery, based on the code I ran, and the state of the blocks at each point. Block 5 is really weird. It was never used for data. But it has a few bits of things in it, and is marked as something I have no clue about, an FBLK. So not an EMPTY, but an FBLK. It is used though, as it has an offset and something before that offset and has that FBLK marker. So I'll have to figure out what an FBLK is and what it's used for. It's the one block type I don't know yet.&lt;br /&gt;
[1:07 AM]&lt;br /&gt;
Long story short, FreeM will always fill in holes during record deletion, by moving later records up to fill them, and it does not do block joins, it will just mark the block as empty. Both are things RSM does not do.&lt;br /&gt;
[1:10 AM]&lt;br /&gt;
Ohhhh!&lt;br /&gt;
[1:10 AM]&lt;br /&gt;
I know what it is!&lt;br /&gt;
[1:10 AM]&lt;br /&gt;
Clever!&lt;br /&gt;
[1:12 AM]&lt;br /&gt;
It's the free block list! So once FreeM has freed a block that had data in it, it creates a new block called the free block (FBLK), which is just a list of pointers to free blocks in order. So in my testing data, it just has a pointer to block 1 and block 3, which I told you above are both free. Does it always maintain that block at the end of the global somehow, or does it have another way of knowing where to find it? I'll have to figure that out.&lt;br /&gt;
&lt;br /&gt;
dlw — 1:15 AM&lt;br /&gt;
Ooo, that's how!&lt;br /&gt;
[1:17 AM]&lt;br /&gt;
Remember earlier I told you that the ROOT block, always a BOTTOM pointer, didn't have a left and right pointer, since it has no siblings, so instead it uses those fields to store the number of blocks other than the ROOT that are in the global, and the number of free blocks? Yeah, it's not the number of free blocks, it's the block number that stores the FBLK, or free block list! So it can always find that block when it needs a new block, before it would add a new block to the global. So instead of a map block using a bitmap, like RSM uses, it has a pointer from the ROOT block to a FBLK, which maintains the list of free blocks!&lt;br /&gt;
[1:18 AM]&lt;br /&gt;
So there you go, other than a few details on internal key formats, I have taught you pretty much the entire globals module tonight! I have not dug in to block splits, but I'll do that soon, and let you know any details.&lt;br /&gt;
[1:21 AM]&lt;br /&gt;
So, remember that because all of the block pointers are 3 bytes, that means a global in FreeM can be at most, 16 MiB blocks, and at 1 KiB per block, that means no larger than 16 GiB.&lt;br /&gt;
[1:22 AM]&lt;br /&gt;
Just an FYI or a reminder.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Release_Procedure&amp;diff=371</id>
		<title>Release Procedure</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Release_Procedure&amp;diff=371"/>
		<updated>2025-03-28T13:01:26Z</updated>

		<summary type="html">&lt;p&gt;Smw: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{InternalUseFeature}}&lt;br /&gt;
=Overview=&lt;br /&gt;
&lt;br /&gt;
In all steps, replace ''version'' with the new version you want to release.&lt;br /&gt;
&lt;br /&gt;
==Prepare the FreeM Repository==&lt;br /&gt;
&lt;br /&gt;
===Set the Release Version===&lt;br /&gt;
In the root of the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; repository, run &amp;lt;code&amp;gt;scripts/set-version ''version''&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Update the ChangeLog===&lt;br /&gt;
Make sure the &amp;lt;code&amp;gt;ChangeLog&amp;lt;/code&amp;gt; file summarizes the changes present in this version&lt;br /&gt;
&lt;br /&gt;
===Commit and Tag===&lt;br /&gt;
In the root of the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; repository, run these commands:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs ci -m &amp;quot;Commit message&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, wait for the build farm to crunch through the build on all platforms. If there are issues during this phase, fix them and commit to CVS before proceeding to the next step.&lt;br /&gt;
&lt;br /&gt;
===Verify Tier 1 Ports===&lt;br /&gt;
Verify the correct operation of FreeM for the Tier 1 ports, and update their Platform Notes in the wiki:&lt;br /&gt;
* Solaris (5.8/sparcv9, 5.7/sparc, 5.11/amd64, 5.11/sparcv9, 5.10/sparcv9)&lt;br /&gt;
* OpenIndiana (5.11/amd64)&lt;br /&gt;
* NetBSD&lt;br /&gt;
* FreeBSD&lt;br /&gt;
* GNU/Linux (one amd64 machine, one i386 machine, Raspberry Pi, and Pine Phone should be sufficient)&lt;br /&gt;
&lt;br /&gt;
Once the build is clean, go to the parent directory of the freem repository and run the following commands to tag the release:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs tag vMaj-Min-Patch freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, wait for the &amp;lt;code&amp;gt;freem-current-source-tarball&amp;lt;/code&amp;gt; Jenkins job to complete. Once it does, you may proceed.&lt;br /&gt;
&lt;br /&gt;
==Update Documentation==&lt;br /&gt;
&lt;br /&gt;
Let's update the FreeM documentation on the website. To do so, run the following command in the root of the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; repository:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ scripts/upload-docs jpw@freem.coherent-logic.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Build Distribution Packages==&lt;br /&gt;
&lt;br /&gt;
===Solaris/Illumos===&lt;br /&gt;
* Connect to the following machines:&lt;br /&gt;
** yuna&lt;br /&gt;
** bh-openindiana-amd64-01&lt;br /&gt;
** bh-sol10-amd64-01&lt;br /&gt;
* On each of the above machines, do the following:&lt;br /&gt;
** Update the FreeM CVS repo&lt;br /&gt;
** Do a clean rebuild of the source (installation not necessary)&lt;br /&gt;
** Generate the package: &amp;lt;code&amp;gt;./mk-solaris-package ''architecture'' ''OS''&amp;lt;/code&amp;gt;&lt;br /&gt;
** Upload the package: &amp;lt;code&amp;gt;scp CLDfreem-maj.min.patch-osMaj.Min-arch.pkg jpw@freem.coherent-logic.com://var/www/freem.coherent-logic.com/downloads/binaries/''os''/''os-version''/&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===NetBSD pkgsrc-wip===&lt;br /&gt;
* Connect to &amp;lt;code&amp;gt;eucleia&amp;lt;/code&amp;gt;&lt;br /&gt;
* Navigate to &amp;lt;code&amp;gt;/usr/pkgsrc/wip&amp;lt;/code&amp;gt;&lt;br /&gt;
* Run &amp;lt;code&amp;gt;git pull -r&amp;lt;/code&amp;gt;&lt;br /&gt;
* Navigate to &amp;lt;code&amp;gt;/usr/pkgsrc/wip/freem&amp;lt;/code&amp;gt;&lt;br /&gt;
* Update &amp;lt;code&amp;gt;COMMIT_MSG&amp;lt;/code&amp;gt;&lt;br /&gt;
* Update the &amp;lt;code&amp;gt;DISTNAME=&amp;lt;/code&amp;gt; field in &amp;lt;code&amp;gt;Makefile&amp;lt;/code&amp;gt; with the new version information&lt;br /&gt;
* Run &amp;lt;code&amp;gt;make distinfo&amp;lt;/code&amp;gt;&lt;br /&gt;
* Run &amp;lt;code&amp;gt;pkglint -e&amp;lt;/code&amp;gt; to check for errors&lt;br /&gt;
* Once &amp;lt;code&amp;gt;pkglint&amp;lt;/code&amp;gt; comes back clean, commit everything (&amp;lt;code&amp;gt;git commit -a&amp;lt;/code&amp;gt;) using the following commit message as a template:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
freem: Update to major.minor.patch&lt;br /&gt;
&lt;br /&gt;
Packaging changes:&lt;br /&gt;
 * &amp;lt;changes-to-pkgsrc-packaging&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Upstream changes:&lt;br /&gt;
 * &amp;lt;Contents-of-ChangeLog&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Run &amp;lt;code&amp;gt;git push&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Debian GNU/Linux===&lt;br /&gt;
&lt;br /&gt;
* Update ''debian/changelog'' in the ''freem-mk-debian-package'' repository with the correct versioning information and commit to CVS&lt;br /&gt;
* Connect to the following machines:&lt;br /&gt;
** bh-deb12-amd64-01&lt;br /&gt;
** bh-deb12-i386-01&lt;br /&gt;
** dryades&lt;br /&gt;
** hybris&lt;br /&gt;
* On each machine, go to &amp;lt;code&amp;gt;~/development/freem-mk-debian-package&amp;lt;/code&amp;gt; and run the following commands:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cvs update -Pd&lt;br /&gt;
$ ./mk-debian-package ''maj.min.patch pkg-version'' jpw@freem.coherent-logic.com&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Connect to &amp;lt;code&amp;gt;packages.clogic-int.com&amp;lt;/code&amp;gt;&lt;br /&gt;
* Run the following commands to get the new release packages signed and into the repository:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ fradd ''maj.min.patch pkg-ver'' amd64&lt;br /&gt;
$ fradd ''maj.min.patch pkg-ver'' armhf&lt;br /&gt;
$ fradd ''maj.min.patch pkg-ver'' i386&lt;br /&gt;
$ fradd ''maj.min.patch pkg-ver'' arm64&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Update Wiki==&lt;br /&gt;
* Generate a Release Notes page for this version on freem-wiki.coherent-logic.com&lt;br /&gt;
&lt;br /&gt;
==Announce Release==&lt;br /&gt;
* Post to &amp;lt;code&amp;gt;freem-users&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;freem-dev&amp;lt;/code&amp;gt; mailing lists&lt;br /&gt;
* Post to Discord &lt;br /&gt;
* Post to Facebook&lt;br /&gt;
* Post to LinkedIn&lt;br /&gt;
* Post to &amp;lt;code&amp;gt;comp.lang.mumps&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Spot Test Tier 2 Ports==&lt;br /&gt;
This includes ports like OpenBSD and SCO OpenServer.&lt;br /&gt;
&lt;br /&gt;
==Prepare to Resume Development==&lt;br /&gt;
Once the release cycle is done, run the following command in the root of the FreeM repository to set the version back to &amp;lt;code&amp;gt;cvs-current&amp;lt;/code&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ scripts/set-version cvs-current&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
And then commit back to CVS.&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Template:InternalUseFeature&amp;diff=370</id>
		<title>Template:InternalUseFeature</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Template:InternalUseFeature&amp;diff=370"/>
		<updated>2025-03-28T13:01:04Z</updated>

		<summary type="html">&lt;p&gt;Smw: Created page with &amp;quot;{{Box|''This article documents a procedure intended for internal use by members of the FreeM team. It probably lacks utility for most users and developers.''}} Category:Inte...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Box|''This article documents a procedure intended for internal use by members of the FreeM team. It probably lacks utility for most users and developers.''}}&lt;br /&gt;
[[Category:Internal Use]]&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=FreeM_0.62.3&amp;diff=369</id>
		<title>FreeM 0.62.3</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=FreeM_0.62.3&amp;diff=369"/>
		<updated>2025-03-28T04:39:48Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Packaging */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
FreeM 0.62.3 was released on March 27, 2025&lt;br /&gt;
&lt;br /&gt;
== Changes ==&lt;br /&gt;
&lt;br /&gt;
=== Fix OO regression in method dispatch ===&lt;br /&gt;
The method dispatch code now has the following improvements:&lt;br /&gt;
* Method tag parsing skips comments, fixing a regression in inheritance scanning&lt;br /&gt;
* When any method is called, its class (routine name) is stored in a memory index, preventing the process from having to walk the inheritance chain on subsequent calls to the method, improving dispatch performance&lt;br /&gt;
* &amp;lt;code&amp;gt;%STRING&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;%SYSOOP&amp;lt;/code&amp;gt; are cached this way automatically as soon as a FreeM process launches&lt;br /&gt;
&lt;br /&gt;
=== Fix port for SCO OpenServer ===&lt;br /&gt;
Fixed all the bit rot in this port and made it work for the first time in a couple of years&lt;br /&gt;
&lt;br /&gt;
=== Fix port for Tru64 UNIX ===&lt;br /&gt;
Made Tru64 work by reverting to global-backed SSVNs on this system&lt;br /&gt;
&lt;br /&gt;
=== Port to OS/2 4.52+ ===&lt;br /&gt;
Requires the full GCC toolchain; tested only on ArcaOS 5.1.&lt;br /&gt;
&lt;br /&gt;
This port required using the OS/2-native &amp;lt;code&amp;gt;DosCopy&amp;lt;/code&amp;gt; API instead of FreeM's internal file copy function (I should not have had to implement file copy myself to begin with, and it's utterly brain dead for an OS not to have this functionality built-in; I'm talking to you, UNIX!)&lt;br /&gt;
&lt;br /&gt;
Currently, the OS/2 port only supports one environment with one daemon and a single interpreter instance.&lt;br /&gt;
&lt;br /&gt;
Work is in progress to create an RPM package for FreeM on OS/2, just need to resolve some linker errors and gain access to the OS/2 World forums or some community where I can ask questions.&lt;br /&gt;
&lt;br /&gt;
=== RPM Packaging ===&lt;br /&gt;
We now ship binary packages of FreeM in RPM and SRPM formats; tested on Rocky Linux 9 and Fedora 41 (should work on RHEL as well)&lt;br /&gt;
&lt;br /&gt;
=== Make systemd units friendlier to RPM packaging ===&lt;br /&gt;
Including more init scripts in the source distribution of FreeM was necessary for RPM packaging&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Packaging ==&lt;br /&gt;
&lt;br /&gt;
FreeM 0.62.3 is natively packaged for:&lt;br /&gt;
&lt;br /&gt;
* Solaris 5.8 on 64-bit SPARC&lt;br /&gt;
* Solaris 5.10 on 64-bit Intel&lt;br /&gt;
* OpenIndiana Hipster 5.11 on 64-bit Intel&lt;br /&gt;
* Debian Bookworm, Bullseye, and Trixie on amd64, i386, armhf, and arm64&lt;br /&gt;
* Ubuntu Noble and Oracular on amd64, armhf, and arm64&lt;br /&gt;
* NetBSD &amp;lt;code&amp;gt;pkgsrc-wip&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fedora 41/Rocky Linux 9 (should work on other Red Hat derivatives as well)&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Downloads: [https://freem.coherent-logic.com/downloads.cfm https://freem.coherent-logic.com/downloads.cfm]&lt;br /&gt;
* Documentation: [https://freem.coherent-logic.com/docs/0.62.3/freem.html https://freem.coherent-logic.com/docs/0.62.3/freem.html]&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Main_Page&amp;diff=368</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Main_Page&amp;diff=368"/>
		<updated>2025-03-28T04:35:54Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Release Notes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wiki contains documentation not included in the [https://freem.coherent-logic.com/docs FreeM Manual], including platform-specific installation and configuration notes, project policies, technical deep-dives, and release notes.&lt;br /&gt;
&lt;br /&gt;
== Release Notes ==&lt;br /&gt;
* [[Conformance Clause]]&lt;br /&gt;
* [[FreeM 0.62.3]]&lt;br /&gt;
* [[FreeM 0.62.2]]&lt;br /&gt;
* [[FreeM 0.62.1]]&lt;br /&gt;
* [[FreeM Lite]]&lt;br /&gt;
* [[FreeM 0.59.2]]&lt;br /&gt;
&lt;br /&gt;
== Project Policies and Procedures ==&lt;br /&gt;
* [[General Policies]]&lt;br /&gt;
* [[Code of Conduct]]&lt;br /&gt;
* [[Contributor Guide]]&lt;br /&gt;
* [[Release Procedure]]&lt;br /&gt;
&lt;br /&gt;
== Port Tiers ==&lt;br /&gt;
* [[Port Tiers]]&lt;br /&gt;
* [[:Category:Tier 1 Ports|Tier 1 Ports]]&lt;br /&gt;
* [[:Category:Tier 2 Ports|Tier 2 Ports]]&lt;br /&gt;
* [[:Category:Tier 3 Ports|Tier 3 Ports]]&lt;br /&gt;
&lt;br /&gt;
== Platform Notes ==&lt;br /&gt;
=== Tier 1 Ports ===&lt;br /&gt;
* [[Platform Notes (Solaris/Illumos)]]&lt;br /&gt;
* [[Platform Notes (NetBSD)]]&lt;br /&gt;
* [[Platform Notes (FreeBSD)]]&lt;br /&gt;
* [[Platform Notes (GNU/Linux)]]&lt;br /&gt;
* [[Platform Notes (OpenBSD)]]&lt;br /&gt;
&lt;br /&gt;
=== Tier 2 Ports ===&lt;br /&gt;
* [[Platform Notes (OS/2)]]&lt;br /&gt;
* [[Platform Notes (SCO OpenServer)]]&lt;br /&gt;
* [[Platform Notes (Compaq Tru64 UNIX)]]&lt;br /&gt;
* [[Platform Notes (IBM AIX)]]&lt;br /&gt;
&lt;br /&gt;
=== Tier 3 Ports ===&lt;br /&gt;
* [[Platform Notes (GNU HURD)]]&lt;br /&gt;
* [[Platform Notes (SGI IRIX)]]&lt;br /&gt;
* [[Platform Notes (HP-UX)]]&lt;br /&gt;
* [[Platform Notes (Mac OS X)]]&lt;br /&gt;
* [[Platform Notes (Minix 3+)]]&lt;br /&gt;
&lt;br /&gt;
== Tips and Tricks ==&lt;br /&gt;
* [[Subscript Rules (Local and Global)]]&lt;br /&gt;
* [[Object-Oriented Programming in FreeM]]&lt;br /&gt;
&lt;br /&gt;
== Technical Deep-Dives ==&lt;br /&gt;
* [[FreeM System Architecture]]&lt;br /&gt;
* [[Event Handling in FreeM]]&lt;br /&gt;
* [[FreeM Transaction Processing Architecture]]&lt;br /&gt;
* [[What is the GUMP?]]&lt;br /&gt;
* [[Namespace Rules]]&lt;br /&gt;
* [[Routine and Global Search Path Internals]]&lt;br /&gt;
&lt;br /&gt;
== History ==&lt;br /&gt;
* [[FreeM History]]&lt;br /&gt;
* [[Original README from Shalom ha-Ashkenaz]]&lt;br /&gt;
&lt;br /&gt;
== Status of Popular M Applications in FreeM ==&lt;br /&gt;
&lt;br /&gt;
* [[Applications: VA VistA]]&lt;br /&gt;
* [[Applications: VA FileMan]]&lt;br /&gt;
* [[Applications: VPE (Victory Programming Environment)]]&lt;br /&gt;
* [[Applications: M Web Server]]&lt;br /&gt;
* [[Applications: GDS/JDS]]&lt;br /&gt;
* [[Applications: MVTS (M Validation and Test Suite)]]&lt;br /&gt;
&lt;br /&gt;
== General M Topics ==&lt;br /&gt;
* [[M User's Group]]&lt;br /&gt;
* [[M Technology Association]]&lt;br /&gt;
* [[M Development Committee]]&lt;br /&gt;
* [[Cache and M Technology Association UK]]&lt;br /&gt;
* [[M User's Group-Deutschland]]&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=FreeM_0.62.3&amp;diff=367</id>
		<title>FreeM 0.62.3</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=FreeM_0.62.3&amp;diff=367"/>
		<updated>2025-03-28T04:35:31Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Port to OS/2 4.52+ */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
FreeM 0.62.3 was released on March 27, 2025&lt;br /&gt;
&lt;br /&gt;
== Changes ==&lt;br /&gt;
&lt;br /&gt;
=== Fix OO regression in method dispatch ===&lt;br /&gt;
The method dispatch code now has the following improvements:&lt;br /&gt;
* Method tag parsing skips comments, fixing a regression in inheritance scanning&lt;br /&gt;
* When any method is called, its class (routine name) is stored in a memory index, preventing the process from having to walk the inheritance chain on subsequent calls to the method, improving dispatch performance&lt;br /&gt;
* &amp;lt;code&amp;gt;%STRING&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;%SYSOOP&amp;lt;/code&amp;gt; are cached this way automatically as soon as a FreeM process launches&lt;br /&gt;
&lt;br /&gt;
=== Fix port for SCO OpenServer ===&lt;br /&gt;
Fixed all the bit rot in this port and made it work for the first time in a couple of years&lt;br /&gt;
&lt;br /&gt;
=== Fix port for Tru64 UNIX ===&lt;br /&gt;
Made Tru64 work by reverting to global-backed SSVNs on this system&lt;br /&gt;
&lt;br /&gt;
=== Port to OS/2 4.52+ ===&lt;br /&gt;
Requires the full GCC toolchain; tested only on ArcaOS 5.1.&lt;br /&gt;
&lt;br /&gt;
This port required using the OS/2-native &amp;lt;code&amp;gt;DosCopy&amp;lt;/code&amp;gt; API instead of FreeM's internal file copy function (I should not have had to implement file copy myself to begin with, and it's utterly brain dead for an OS not to have this functionality built-in; I'm talking to you, UNIX!)&lt;br /&gt;
&lt;br /&gt;
Currently, the OS/2 port only supports one environment with one daemon and a single interpreter instance.&lt;br /&gt;
&lt;br /&gt;
Work is in progress to create an RPM package for FreeM on OS/2, just need to resolve some linker errors and gain access to the OS/2 World forums or some community where I can ask questions.&lt;br /&gt;
&lt;br /&gt;
=== RPM Packaging ===&lt;br /&gt;
We now ship binary packages of FreeM in RPM and SRPM formats; tested on Rocky Linux 9 and Fedora 41 (should work on RHEL as well)&lt;br /&gt;
&lt;br /&gt;
=== Make systemd units friendlier to RPM packaging ===&lt;br /&gt;
Including more init scripts in the source distribution of FreeM was necessary for RPM packaging&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Packaging ==&lt;br /&gt;
&lt;br /&gt;
FreeM 0.62.3 is natively packaged for:&lt;br /&gt;
&lt;br /&gt;
* Solaris 5.8 on 64-bit SPARC&lt;br /&gt;
* Solaris 5.10 on 64-bit Intel&lt;br /&gt;
* OpenIndiana Hipster 5.11 on 64-bit Intel&lt;br /&gt;
* Debian Bookworm, Bullseye, and Trixie on amd64, i386, armhf, and arm64&lt;br /&gt;
* Ubuntu Noble and Oracular on amd64, armhf, and arm64&lt;br /&gt;
* NetBSD &amp;lt;code&amp;gt;pkgsrc-wip&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fedora 41/Rocky Linux 9 (should also work on other Red Hat derivatives as well)&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Downloads: [https://freem.coherent-logic.com/downloads.cfm https://freem.coherent-logic.com/downloads.cfm]&lt;br /&gt;
* Documentation: [https://freem.coherent-logic.com/docs/0.62.3/freem.html https://freem.coherent-logic.com/docs/0.62.3/freem.html]&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=FreeM_0.62.3&amp;diff=366</id>
		<title>FreeM 0.62.3</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=FreeM_0.62.3&amp;diff=366"/>
		<updated>2025-03-28T04:31:34Z</updated>

		<summary type="html">&lt;p&gt;Smw: Created page with &amp;quot;== Overview == FreeM 0.62.3 was released on March 27, 2025  == Changes ==  === Fix OO regression in method dispatch === The method dispatch code now has the following improvem...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Overview ==&lt;br /&gt;
FreeM 0.62.3 was released on March 27, 2025&lt;br /&gt;
&lt;br /&gt;
== Changes ==&lt;br /&gt;
&lt;br /&gt;
=== Fix OO regression in method dispatch ===&lt;br /&gt;
The method dispatch code now has the following improvements:&lt;br /&gt;
* Method tag parsing skips comments, fixing a regression in inheritance scanning&lt;br /&gt;
* When any method is called, its class (routine name) is stored in a memory index, preventing the process from having to walk the inheritance chain on subsequent calls to the method, improving dispatch performance&lt;br /&gt;
* &amp;lt;code&amp;gt;%STRING&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;%SYSOOP&amp;lt;/code&amp;gt; are cached this way automatically as soon as a FreeM process launches&lt;br /&gt;
&lt;br /&gt;
=== Fix port for SCO OpenServer ===&lt;br /&gt;
Fixed all the bit rot in this port and made it work for the first time in a couple of years&lt;br /&gt;
&lt;br /&gt;
=== Fix port for Tru64 UNIX ===&lt;br /&gt;
Made Tru64 work by reverting to global-backed SSVNs on this system&lt;br /&gt;
&lt;br /&gt;
=== Port to OS/2 4.52+ ===&lt;br /&gt;
Requires the full GCC toolchain; tested only on ArcaOS 5.1&lt;br /&gt;
&lt;br /&gt;
=== RPM Packaging ===&lt;br /&gt;
We now ship binary packages of FreeM in RPM and SRPM formats; tested on Rocky Linux 9 and Fedora 41 (should work on RHEL as well)&lt;br /&gt;
&lt;br /&gt;
=== Make systemd units friendlier to RPM packaging ===&lt;br /&gt;
Including more init scripts in the source distribution of FreeM was necessary for RPM packaging&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Packaging ==&lt;br /&gt;
&lt;br /&gt;
FreeM 0.62.3 is natively packaged for:&lt;br /&gt;
&lt;br /&gt;
* Solaris 5.8 on 64-bit SPARC&lt;br /&gt;
* Solaris 5.10 on 64-bit Intel&lt;br /&gt;
* OpenIndiana Hipster 5.11 on 64-bit Intel&lt;br /&gt;
* Debian Bookworm, Bullseye, and Trixie on amd64, i386, armhf, and arm64&lt;br /&gt;
* Ubuntu Noble and Oracular on amd64, armhf, and arm64&lt;br /&gt;
* NetBSD &amp;lt;code&amp;gt;pkgsrc-wip&amp;lt;/code&amp;gt;&lt;br /&gt;
* Fedora 41/Rocky Linux 9 (should also work on other Red Hat derivatives as well)&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
* Downloads: [https://freem.coherent-logic.com/downloads.cfm https://freem.coherent-logic.com/downloads.cfm]&lt;br /&gt;
* Documentation: [https://freem.coherent-logic.com/docs/0.62.3/freem.html https://freem.coherent-logic.com/docs/0.62.3/freem.html]&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(OS/2)&amp;diff=365</id>
		<title>Platform Notes (OS/2)</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(OS/2)&amp;diff=365"/>
		<updated>2025-03-28T04:09:59Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Verified Releases */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{DevBranchFeature}}&lt;br /&gt;
&lt;br /&gt;
== Port Status ==&lt;br /&gt;
OS/2 is a [[Tier 2 Port]]&lt;br /&gt;
&lt;br /&gt;
== Verified Releases ==&lt;br /&gt;
* FreeM 0.62.3 (27 Mar 2025)&lt;br /&gt;
* FreeM cvs-current (23 Mar 2025)&lt;br /&gt;
&lt;br /&gt;
== Testing Details ==&lt;br /&gt;
We build and test the OS/2 port on an ArcaOS 5.1 VM running in VirtualBox.&lt;br /&gt;
&lt;br /&gt;
== Building and Installing ==&lt;br /&gt;
Currently, the OS/2 port is only tested on ArcaOS, and you will need to install several things in order to build and run:&lt;br /&gt;
&lt;br /&gt;
* autoconf&lt;br /&gt;
* automake&lt;br /&gt;
* gcc&lt;br /&gt;
* readline-devel&lt;br /&gt;
* bash&lt;br /&gt;
* binutils-devel&lt;br /&gt;
* coreutils&lt;br /&gt;
* emxrt&lt;br /&gt;
* gawk&lt;br /&gt;
* gcc-wlink&lt;br /&gt;
* gcc-wrt&lt;br /&gt;
* grep&lt;br /&gt;
* info&lt;br /&gt;
* libc-devel&lt;br /&gt;
* libtool&lt;br /&gt;
* kbuild-make&lt;br /&gt;
* sed&lt;br /&gt;
* tar&lt;br /&gt;
* gzip&lt;br /&gt;
&lt;br /&gt;
All of these can be installed with &amp;lt;code&amp;gt;yum install&amp;lt;/code&amp;gt; or the Arca Noae Package Manager (ANPM).&lt;br /&gt;
&lt;br /&gt;
Once the dependencies are met, simply download and extract the FreeM source code, and follow these steps:&lt;br /&gt;
&lt;br /&gt;
* Open an OS/2 Window (in the Command Prompts folder in OS/2 System or Computer on the desktop)&lt;br /&gt;
* Run the following commands:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[C:\] bash&lt;br /&gt;
$ autoreconf --install  # only needed if installing from the CVS repo&lt;br /&gt;
$ ./configure CC=gcc GREP=grep&lt;br /&gt;
$ make&lt;br /&gt;
$ make install&lt;br /&gt;
$ fmadm configure&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once this is done, proceed to the next section.&lt;br /&gt;
&lt;br /&gt;
== Workarounds ==&lt;br /&gt;
Under OS/2 and ArcaOS, FreeM binaries are installed under &amp;lt;code&amp;gt;C:\USR\LOCAL\BIN&amp;lt;/code&amp;gt;, but the FreeM daemon and the FreeM interpreter cannot be launched from the same executable (the daemon will start, but interpreters will give an error resembling &amp;lt;code&amp;gt;Resource busy&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;fmadm configure&amp;lt;/code&amp;gt; (and &amp;lt;code&amp;gt;fmadm reconfigure&amp;lt;/code&amp;gt;) commands will automatically copy &amp;lt;code&amp;gt;C:\USR\LOCAL\BIN\freem.exe&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;C:\USR\LOCAL\BIN\freemd.exe&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Running ==&lt;br /&gt;
# Open an OS/2 Window command prompt&lt;br /&gt;
# Run &amp;lt;code&amp;gt;bash&amp;lt;/code&amp;gt;&lt;br /&gt;
# Run &amp;lt;code&amp;gt;/usr/local/bin/freemd -dk&amp;lt;/code&amp;gt; to start the FreeM daemon&lt;br /&gt;
# Minimize the FreeM daemon process&lt;br /&gt;
# Open a second OS/2 Window command prompt&lt;br /&gt;
# Run the following commands:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[C:\] CD \USR\LOCAL\BIN&lt;br /&gt;
[C:\USR\LOCAL\BIN] FREEM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Platform Limitations ==&lt;br /&gt;
* Only one interpreter instance can be launched at a time&lt;br /&gt;
* &amp;lt;code&amp;gt;JOB&amp;lt;/code&amp;gt; does not work&lt;br /&gt;
* Terminal windows are fixed in size to 80x24&lt;br /&gt;
* The FreeM daemon must be launched in the foreground, as &amp;lt;code&amp;gt;fork()&amp;lt;/code&amp;gt; is unsupported here (&amp;lt;code&amp;gt;freemd.exe&amp;lt;/code&amp;gt; will refuse to launch if you do not pass the &amp;lt;code&amp;gt;-k&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;--nofork&amp;lt;/code&amp;gt; flags).&lt;br /&gt;
* Network sockets functionality is unavailable&lt;br /&gt;
* Building without &amp;lt;code&amp;gt;readline&amp;lt;/code&amp;gt; causes direct mode to echo each line of code entered&lt;br /&gt;
* No binary package is available: once we have an RPM package for Red Hat-derived distributions, an OS/2 RPM should be fairly straightforward&lt;br /&gt;
&lt;br /&gt;
Documentation for porting UNIX applications to OS/2 is scant, which makes many of these issues difficult to work around. However, we do want to iron out all of these shortcomings and promote this port to Tier 1 status.&lt;br /&gt;
&lt;br /&gt;
== Required Kernel Tuning ==&lt;br /&gt;
Coming soon.&lt;br /&gt;
&lt;br /&gt;
[[Category: Tier 2 Ports]]&lt;br /&gt;
[[Category: Platform Notes]]&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(SCO_OpenServer)&amp;diff=364</id>
		<title>Platform Notes (SCO OpenServer)</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(SCO_OpenServer)&amp;diff=364"/>
		<updated>2025-03-28T04:09:35Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Verified Releases */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Port Status ==&lt;br /&gt;
&lt;br /&gt;
SCO OpenServer is a [[Tier 2 Port]]&lt;br /&gt;
&lt;br /&gt;
== Verified Releases ==&lt;br /&gt;
* 0.62.3 (27 Mar 2025)&lt;br /&gt;
* 0.62.2 (25 Mar 2025)&lt;br /&gt;
* 0.56.2 (4 Aug 2023)&lt;br /&gt;
&lt;br /&gt;
== Build Details ==&lt;br /&gt;
You will need to set the &amp;lt;code&amp;gt;ACCEPT_INFERIOR_RM_PROGRAM&amp;lt;/code&amp;gt; environment variable to &amp;lt;code&amp;gt;yes&amp;lt;/code&amp;gt; before running &amp;lt;code&amp;gt;configure&amp;lt;/code&amp;gt; if GNU &amp;lt;code&amp;gt;coreutils&amp;lt;/code&amp;gt; is not installed. An invocation such as the following should be sufficient:&lt;br /&gt;
 $ export ACCEPT_INFERIOR_RM_PROGRAM=yes&lt;br /&gt;
 $ ./configure MAKE=/usr/gnu/bin/gmake GAWK=/usr/gnu/bin/gawk&lt;br /&gt;
&lt;br /&gt;
== Testing Details ==&lt;br /&gt;
&lt;br /&gt;
We build and test the SCO OpenServer port on a system with the following specifications:&lt;br /&gt;
&lt;br /&gt;
* ESXi Virtual Machine&lt;br /&gt;
* SCO OpenServer 5.0.7&lt;br /&gt;
* gcc v2.95.3&lt;br /&gt;
* autoconf 2.54&lt;br /&gt;
* automake 1.7.1&lt;br /&gt;
&lt;br /&gt;
This port requires significant manual intervention to build, given the old version of GNU autotools in play.&lt;br /&gt;
&lt;br /&gt;
== Required Kernel Tuning ==&lt;br /&gt;
&lt;br /&gt;
You must set the maximum size of a shared memory segment to at least 17000000. This can be accomplished with the &amp;lt;code&amp;gt;scoadmin&amp;lt;/code&amp;gt; utility.&lt;br /&gt;
&lt;br /&gt;
Once this parameter is adjusted, you must re-link the kernel, also from &amp;lt;code&amp;gt;scoadmin&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Port Challenges ==&lt;br /&gt;
&lt;br /&gt;
The build system presents significant challenges.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category: Tier 2 Ports]]&lt;br /&gt;
[[Category: Platform Notes]]&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(Compaq_Tru64_UNIX)&amp;diff=363</id>
		<title>Platform Notes (Compaq Tru64 UNIX)</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(Compaq_Tru64_UNIX)&amp;diff=363"/>
		<updated>2025-03-28T04:09:16Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Verified Releases */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Port Status ==&lt;br /&gt;
&lt;br /&gt;
Compaq Tru64 UNIX is a [[Tier 2 Port]]&lt;br /&gt;
&lt;br /&gt;
== Verified Releases ==&lt;br /&gt;
* FreeM 0.62.3 (27 Mar 2025)&lt;br /&gt;
* &amp;lt;code&amp;gt;cvs-current&amp;lt;/code&amp;gt; (26 Mar 2025) (builds and runs cleanly, but will use global-backed SSVNs)&lt;br /&gt;
&lt;br /&gt;
FreeM 0.62.2 builds, but errors out when launching the daemon:&lt;br /&gt;
 freem [FATAL]:  memory allocation failure in symtab_init [errno 0 Successful]&lt;br /&gt;
&lt;br /&gt;
There is an issue on this at https://bugs.coherent-logic.com/view.php?id=16&lt;br /&gt;
&lt;br /&gt;
== Testing Details ==&lt;br /&gt;
&lt;br /&gt;
We build and test the Tru64 UNIX port on a system with the following specifications:&lt;br /&gt;
&lt;br /&gt;
* Alpha EV67-based host&lt;br /&gt;
* Compaq Tru64 UNIX 5.1b&lt;br /&gt;
* GNU gcc v4.7.7&lt;br /&gt;
* GNU autoconf 2.71&lt;br /&gt;
* GNU automake 1.16.4&lt;br /&gt;
&lt;br /&gt;
This port should theoretically run on DEC OSF/1 or Digital UNIX, given a compatible GNU toolchain, but we do not have the resources to test such configurations.&lt;br /&gt;
&lt;br /&gt;
== Required Kernel Tuning ==&lt;br /&gt;
&lt;br /&gt;
For the default daemon configuration, you will need a kernel &amp;lt;code&amp;gt;shm_max&amp;lt;/code&amp;gt; parameter of at least 16795968. We recommend 17000000.&lt;br /&gt;
&lt;br /&gt;
To apply an shm_max of 17000000, you will need to do the following:&lt;br /&gt;
&lt;br /&gt;
* Gain root privileges on your system&lt;br /&gt;
* Create a file called &amp;quot;pstanza&amp;quot; with the following data:&lt;br /&gt;
 ipc:&lt;br /&gt;
     shm_max = 17000000&lt;br /&gt;
* If no &amp;lt;code&amp;gt;shm_max&amp;lt;/code&amp;gt; parameter exists in &amp;lt;code&amp;gt;/etc/sysconfigtab&amp;lt;/code&amp;gt;:&lt;br /&gt;
 # sysconfigdb -a -f pstanza ipc&lt;br /&gt;
* If a previous &amp;lt;code&amp;gt;shm_max&amp;lt;/code&amp;gt; configuration exists:&lt;br /&gt;
 # sysconfigdb -m -f pstanza ipc&lt;br /&gt;
* Reboot the system&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category: Tier 2 Ports]]&lt;br /&gt;
[[Category: Platform Notes]]&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(NetBSD)&amp;diff=362</id>
		<title>Platform Notes (NetBSD)</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(NetBSD)&amp;diff=362"/>
		<updated>2025-03-28T04:08:36Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Verified Releases */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Port Status ==&lt;br /&gt;
NetBSD is a [[Tier 1 Port]]&lt;br /&gt;
&lt;br /&gt;
== Verified Releases ==&lt;br /&gt;
* FreeM 0.62.3 (27 Mar 2025)&lt;br /&gt;
* FreeM 0.62.2 (23 Mar 2025)&lt;br /&gt;
* FreeM cvs-current&lt;br /&gt;
* FreeM 0.62.1 (14 Mar 2025)&lt;br /&gt;
* FreeM 0.59.0 (04 Aug 2023)&lt;br /&gt;
&lt;br /&gt;
== Testing Details ==&lt;br /&gt;
&lt;br /&gt;
* Proxmox Virtual Machine (64-bit)&lt;br /&gt;
* NetBSD/amd64 10.0&lt;br /&gt;
* gcc v10.5.0&lt;br /&gt;
* autoconf 2.72&lt;br /&gt;
* automake 1.16.5&lt;br /&gt;
&lt;br /&gt;
[[Category:Platform Notes]]&lt;br /&gt;
[[Category:Tier 1 Ports]]&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(GNU/Linux)&amp;diff=361</id>
		<title>Platform Notes (GNU/Linux)</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(GNU/Linux)&amp;diff=361"/>
		<updated>2025-03-28T04:08:18Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Verified Releases */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Port Status ==&lt;br /&gt;
The GNU/Linux port is a [[Tier 1 Port]]&lt;br /&gt;
&lt;br /&gt;
== Verified Releases ==&lt;br /&gt;
* FreeM 0.62.3 (27 Mar 2025)&lt;br /&gt;
* FreeM &amp;lt;code&amp;gt;cvs-current&amp;lt;/code&amp;gt;&lt;br /&gt;
* FreeM 0.62.1 (14 Mar 2025)&lt;br /&gt;
* FreeM 0.61.2&lt;br /&gt;
* FreeM 0.59.2 (04 Aug 2023)&lt;br /&gt;
&lt;br /&gt;
== Testing Details ==&lt;br /&gt;
&lt;br /&gt;
We build and test the GNU/Linux port on a system with the following specifications:&lt;br /&gt;
&lt;br /&gt;
* amd64-based host&lt;br /&gt;
* Arch Linux running the 6.12.18-1-lts Linux kernel&lt;br /&gt;
* GNU gcc v14.2.1&lt;br /&gt;
* GNU autoconf 2.72&lt;br /&gt;
* GNU automake 1.17&lt;br /&gt;
&lt;br /&gt;
== Required Kernel Tuning ==&lt;br /&gt;
&lt;br /&gt;
For the default daemon configuration, you will need a &amp;lt;code&amp;gt;kernel.shmmax&amp;lt;/code&amp;gt; parameter of at least &amp;lt;code&amp;gt;6000000&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
To check the current value of this kernel parameter, enter the following command:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 $ sudo sysctl kernel.shmmax&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the reported value is less than 6000000, continue with the following procedure. Otherwise, your system already meets the requirements for running FreeM in the default configuration.&lt;br /&gt;
&lt;br /&gt;
To apply an &amp;lt;code&amp;gt;shm_max&amp;lt;/code&amp;gt; of &amp;lt;code&amp;gt;6000000&amp;lt;/code&amp;gt;, you will need to do the following:&lt;br /&gt;
&lt;br /&gt;
* Create a file called &amp;lt;code&amp;gt;10-shmmax.conf&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;/etc/sysctl.d&amp;lt;/code&amp;gt;, containing the following information:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
kernel.shmmax = 6000000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Reboot your system&lt;br /&gt;
&lt;br /&gt;
== Installing on Debian GNU/Linux and derivatives ==&lt;br /&gt;
&lt;br /&gt;
=== Repository Installation ===&lt;br /&gt;
On recent releases of Debian (Bullseye, Bookworm, and Trixie) and Ubuntu (Noble Numbat and Oracular Oriole), you can use the [https://packages.coherent-logic.com Coherent Logic Package Repository] to install pre-built binary packages for &amp;lt;code&amp;gt;amd64&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;armhf&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;arm64&amp;lt;/code&amp;gt; architectures.&lt;br /&gt;
&lt;br /&gt;
# Follow the instructions at [https://packages.coherent-logic.com https://packages.coherent-logic.com] to set up your computer for use with our package repository&lt;br /&gt;
# Run &amp;lt;code&amp;gt;sudo apt install freem&amp;lt;/code&amp;gt; to install FreeM&lt;br /&gt;
&lt;br /&gt;
=== Direct Package Installation ===&lt;br /&gt;
# Download the appropriate package from [https://freem.coherent-logic.com/binaries.cfm https://freem.coherent-logic.com/binaries.cfm]&lt;br /&gt;
# Install the package with &amp;lt;code&amp;gt;sudo dpkg -i &amp;amp;lt;package-file&amp;amp;gt;&amp;lt;/code&amp;gt;, substituting the name of the downloaded file for &amp;lt;code&amp;gt;&amp;amp;lt;package-file&amp;amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Starting the FreeM Daemon Automatically ==&lt;br /&gt;
&lt;br /&gt;
=== systemd ===&lt;br /&gt;
&lt;br /&gt;
To start the FreeM daemon automatically with systemd, you will need to first decide if you want the daemon to run as a system-level service, or as a user service under your normal user account.&lt;br /&gt;
&lt;br /&gt;
==== System-Level Service ====&lt;br /&gt;
&lt;br /&gt;
* Copy &amp;lt;code&amp;gt;scripts/systemd/system/freem.service&amp;lt;/code&amp;gt; from the FreeM distribution to &amp;lt;code&amp;gt;/etc/systemd/system&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
# Type the following commands as root:&lt;br /&gt;
## &amp;lt;code&amp;gt;groupadd freem&amp;lt;/code&amp;gt;&lt;br /&gt;
## &amp;lt;code&amp;gt;useradd -m -d /home/freem -g freem freem&amp;lt;/code&amp;gt;&lt;br /&gt;
# Type the following command for each user who will use FreeM, substituting the user's login name for &amp;lt;code&amp;gt;username&amp;lt;/code&amp;gt;:&lt;br /&gt;
## &amp;lt;code&amp;gt;usermod -aG freem ''username''&amp;lt;/code&amp;gt;&lt;br /&gt;
# Type the following commands as root:&lt;br /&gt;
## &amp;lt;code&amp;gt;systemctl daemon-reload&amp;lt;/code&amp;gt;&lt;br /&gt;
## &amp;lt;code&amp;gt;systemctl enable freem&amp;lt;/code&amp;gt;&lt;br /&gt;
## &amp;lt;code&amp;gt;systemctl start freem&amp;lt;/code&amp;gt;&lt;br /&gt;
# You may then check the status of the daemon with the following command:&lt;br /&gt;
## &amp;lt;code&amp;gt;systemctl status freem&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the third line of output contains the text &amp;lt;code&amp;gt;active (running)&amp;lt;/code&amp;gt;, the service has been successfully configured and started.&lt;br /&gt;
&lt;br /&gt;
==== User-Level Service ====&lt;br /&gt;
&lt;br /&gt;
# Copy &amp;lt;code&amp;gt;scripts/systemd/user/freem.service&amp;lt;/code&amp;gt; from the FreeM distribution to &amp;lt;code&amp;gt;$HOME/.config/systemd/user&amp;lt;/code&amp;gt;&lt;br /&gt;
# Type the following commands:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ systemctl --user enable freem&lt;br /&gt;
$ systemctl --user start freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
# You may then check the status of the daemon with the following command:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo systemctl --user status freem&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the third line of output contains the text &amp;lt;code&amp;gt;active (running)&amp;lt;/code&amp;gt;, the service has been successfully configured and started.&lt;br /&gt;
&lt;br /&gt;
=== sysvinit ===&lt;br /&gt;
Coming soon.&lt;br /&gt;
&lt;br /&gt;
[[Category:Tier 1 Ports]]&lt;br /&gt;
[[Category:Platform Notes]]&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(FreeBSD)&amp;diff=360</id>
		<title>Platform Notes (FreeBSD)</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(FreeBSD)&amp;diff=360"/>
		<updated>2025-03-28T04:07:58Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Verified Releases */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Port Status ==&lt;br /&gt;
FreeBSD is a [[Tier 1 Port]]&lt;br /&gt;
&lt;br /&gt;
== Verified Releases ==&lt;br /&gt;
* FreeM 0.62.3 (27 Mar 2025)&lt;br /&gt;
* FreeM 0.62.2 (23 Mar 2025)&lt;br /&gt;
* FreeM &amp;lt;code&amp;gt;cvs-current&amp;lt;/code&amp;gt;&lt;br /&gt;
* FreeM 0.62.1&lt;br /&gt;
&lt;br /&gt;
== Testing Details ==&lt;br /&gt;
* Bare-metal amd64 system&lt;br /&gt;
* FreeBSD 14.1-RELEASE-p2 amd64&lt;br /&gt;
* gcc 13.2.0&lt;br /&gt;
* autoconf 2.72&lt;br /&gt;
* automake 1.17&lt;br /&gt;
&lt;br /&gt;
== Required Kernel Tuning ==&lt;br /&gt;
Coming soon&lt;br /&gt;
&lt;br /&gt;
== Starting Daemon Automatically ==&lt;br /&gt;
* Copy &amp;lt;code&amp;gt;scripts/freebsd-rc/freem&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/usr/local/etc/rc.d&amp;lt;/code&amp;gt;&lt;br /&gt;
* Type the following commands with root privileges:&lt;br /&gt;
 # pw group add freem&lt;br /&gt;
 # pw user add freem -m -g freem&lt;br /&gt;
 # sysrc freem_enable=&amp;quot;YES&amp;quot;&lt;br /&gt;
 # chmod +x /usr/local/etc/rc.d/freem&lt;br /&gt;
* For each user who needs to run FreeM, type the following command:&lt;br /&gt;
 # pw group mod freem -m ''username''&lt;br /&gt;
* Reboot &lt;br /&gt;
&lt;br /&gt;
== Port Challenges ==&lt;br /&gt;
None.&lt;br /&gt;
&lt;br /&gt;
[[Category:Tier 1 Ports]]&lt;br /&gt;
[[Category:Platform Notes]]&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
	<entry>
		<id>https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(Solaris/Illumos)&amp;diff=359</id>
		<title>Platform Notes (Solaris/Illumos)</title>
		<link rel="alternate" type="text/html" href="https://freem-wiki.coherent-logic.com/index.php?title=Platform_Notes_(Solaris/Illumos)&amp;diff=359"/>
		<updated>2025-03-28T04:07:27Z</updated>

		<summary type="html">&lt;p&gt;Smw: /* Verified Releases */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Port Category ==&lt;br /&gt;
&lt;br /&gt;
The Solaris port is a [[Tier 1 Port]], and Solaris 8 on 64-bit SPARC is the platform where primary development occurs.&lt;br /&gt;
&lt;br /&gt;
== Verified Releases ==&lt;br /&gt;
* 0.62.3 (Solaris 5.8 sparc64, Solaris 5.10 i86pc, Solaris 5.11 i86pc, Solaris 5.11 sparc64, OpenIndiana Hipster 5.11 amd64, 27 Mar 2025&lt;br /&gt;
* 0.62.2 (Solaris 5.8 sparc64, Solaris 5.10 i86pc, Solaris 5.11 i86pc, Solaris 5.11 sparc64, OpenIndiana Hipster 5.11 amd64, 23 Mar 2025)&lt;br /&gt;
* 0.62.1 (Solaris 5.10 i86pc, 17 Mar 2025)&lt;br /&gt;
* &amp;lt;code&amp;gt;cvs-current&amp;lt;/code&amp;gt; (Solaris 5.8 sparc64, Solaris 11.4 sparc64 and i86pc)&lt;br /&gt;
* 0.62.1 (Solaris 5.8 sparc64, Solaris 11.4 sparc64 and i86pc, OpenIndiana Hipster, 16 Mar 2025)&lt;br /&gt;
* 0.61.2 (Solaris 5.8 sparc64, Solaris 11.4 sparc64 and i86pc)&lt;br /&gt;
* 0.59.0 (Solaris 10 sparc64, 4 Aug 2023)&lt;br /&gt;
* 0.59.0 (Solaris 7 sparc32, 4 Aug 2023)&lt;br /&gt;
* 0.59.0 (Solaris 11.4 i86pc, 4 Aug 2023)&lt;br /&gt;
* 0.57.0 (Solaris 11.3 sparc64, 4 Aug 2023)&lt;br /&gt;
&lt;br /&gt;
== Build Notes ==&lt;br /&gt;
=== Solaris 7 ===&lt;br /&gt;
* If using the old &amp;lt;code&amp;gt;sunfreeware.com&amp;lt;/code&amp;gt; GNU toolchain packages on Solaris 7, you will need the latest &amp;lt;code&amp;gt;7_Recommended.zip&amp;lt;/code&amp;gt; patch cluster.&lt;br /&gt;
* The &amp;lt;code&amp;gt;mktemp&amp;lt;/code&amp;gt; utility may lock up several times during the &amp;lt;code&amp;gt;configure&amp;lt;/code&amp;gt; phase. If this happens, you may simply kill the process with &amp;lt;code&amp;gt;pkill -9 mktemp&amp;lt;/code&amp;gt;. This does not appear to harm the build.&lt;br /&gt;
&lt;br /&gt;
=== Solaris 8 ===&lt;br /&gt;
&lt;br /&gt;
==== Binary Packages ====&lt;br /&gt;
On Solaris 8, you can install a binary release:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo pkgadd -d CLDfreem-&amp;lt;version&amp;gt;-solaris5.8-sparcv9.pkg&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once this is done, add yourself to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; group:&lt;br /&gt;
# Open &amp;lt;code&amp;gt;/etc/group&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;root&amp;lt;/code&amp;gt; in your favorite text editor&lt;br /&gt;
# Find the line beginning with &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt;&lt;br /&gt;
# Append your username to the end of that line&lt;br /&gt;
# Save the file&lt;br /&gt;
# Exit the editor&lt;br /&gt;
&lt;br /&gt;
Now, you can start the FreeM daemon as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo /etc/init.d/freem start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Building From Source ====&lt;br /&gt;
You will need the latest &amp;lt;code&amp;gt;8_Recommended.zip&amp;lt;/code&amp;gt; patch cluster for Solaris, as well as:&lt;br /&gt;
&lt;br /&gt;
* gcc (3.4 or higher recommended)&lt;br /&gt;
* autoconf&lt;br /&gt;
* automake&lt;br /&gt;
* libtool&lt;br /&gt;
* texinfo&lt;br /&gt;
* readline (recommended but not strictly required)&lt;br /&gt;
&lt;br /&gt;
=== Solaris 9 ===&lt;br /&gt;
TBD&lt;br /&gt;
&lt;br /&gt;
=== Solaris 10 ===&lt;br /&gt;
TBD&lt;br /&gt;
&lt;br /&gt;
=== Solaris 11 ===&lt;br /&gt;
We build with the IPS packages for the GNU toolchain here. The Sun C compiler can also be used here (at least the version from Developer Studio 12.6).&lt;br /&gt;
&lt;br /&gt;
==== Necessary Packages ====&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
$ sudo pkg install gcc automake autoconf gnu-make git readline libtool texinfo ncurses&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Dealing with ncurses ====&lt;br /&gt;
You will need to tell the configure script not to bother with the wide-character ncurses library (does not apply to releases later than 0.61.2):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
$ ./configure --without-ncursesw&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== OpenIndiana ===&lt;br /&gt;
==== Binary Packages ====&lt;br /&gt;
On OpenIndiana, you can install a binary release:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo pkgadd -d CLDfreem-&amp;lt;version&amp;gt;-openindiana5.11-amd64.pkg&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once this is done, add yourself to the &amp;lt;code&amp;gt;freem&amp;lt;/code&amp;gt; group, and start the FreeM daemon as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo /etc/init.d/freem start&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==== Building From Source ====&lt;br /&gt;
See instructions for [[#Solaris 11|Solaris 11]], but with the exception that &amp;lt;code&amp;gt;configure&amp;lt;/code&amp;gt; must be run as follows:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./configure MAKE=gmake&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Testing Details ==&lt;br /&gt;
&lt;br /&gt;
We build and test the Solaris port of FreeM on the following systems:&lt;br /&gt;
&lt;br /&gt;
=== Sun Ultra 10 ===&lt;br /&gt;
&lt;br /&gt;
* Sun Ultra 10 with a 400MHz UltraSPARC-IIi CPU (64-bit)&lt;br /&gt;
* 640MB RAM&lt;br /&gt;
* Solaris 5.8 Generic_117350-39&lt;br /&gt;
* gcc v3.4.6&lt;br /&gt;
* autoconf 2.69&lt;br /&gt;
* automake 1.16.5&lt;br /&gt;
&lt;br /&gt;
=== Sun SPARCserver 20 ===&lt;br /&gt;
&lt;br /&gt;
* Sun SPARCserver 20 with dual 100MHz Ross HyperSPARC CPUs (32-bit)&lt;br /&gt;
* 512MB RAM&lt;br /&gt;
* Solaris 7 with the latest 7_Recommended.zip patch cluster applied (REQUIRED FOR SOLARIS 7)&lt;br /&gt;
* gcc v3.4.6&lt;br /&gt;
* autoconf 2.68&lt;br /&gt;
* automake 1.11.1&lt;br /&gt;
&lt;br /&gt;
=== SunFire T2000 ===&lt;br /&gt;
&lt;br /&gt;
* Sun UltraSPARC T1 CPU (64-bit)&lt;br /&gt;
* Solaris 10&lt;br /&gt;
&lt;br /&gt;
=== Oracle SPARC T4-1 ===&lt;br /&gt;
* Oracle SPARC T4 CPU (64-bit)&lt;br /&gt;
* Solaris 11.4 11.4.0.15.0&lt;br /&gt;
* gcc v7.3.0&lt;br /&gt;
* autoconf 2.69&lt;br /&gt;
* automake 1.15&lt;br /&gt;
* Oracle Developer Studio 12.6 (SunCC compiler)&lt;br /&gt;
&lt;br /&gt;
=== x86 VM ===&lt;br /&gt;
* Solaris 11.4 11.4.0.15.0&lt;br /&gt;
* gcc v7.3.0&lt;br /&gt;
* autoconf 2.69&lt;br /&gt;
* automake 1.15&lt;br /&gt;
&lt;br /&gt;
=== OpenIndiana (Illumos) ===&lt;br /&gt;
&lt;br /&gt;
* Proxmox VM&lt;br /&gt;
* OpenIndiana Hipster 5.11 illumos-053feb1540&lt;br /&gt;
* gcc 14.2.0&lt;br /&gt;
* autoconf 2.72&lt;br /&gt;
* automake 1.16.5&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This port should theoretically run on any Solaris or Illumos machine running Solaris 7 or newer.&lt;br /&gt;
&lt;br /&gt;
== Required Kernel Tuning ==&lt;br /&gt;
&lt;br /&gt;
=== Solaris 11 ===&lt;br /&gt;
TBD&lt;br /&gt;
&lt;br /&gt;
=== Solaris 8 ===&lt;br /&gt;
Append the following to &amp;lt;code&amp;gt;/etc/system&amp;lt;/code&amp;gt; and reboot:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
set shmsys:shminfo_shmmax = 67108864&lt;br /&gt;
set shmsys:shminfo_shmmni = 0x1000&lt;br /&gt;
set shmsys:shminfo_shmseg = 0x100&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Starting FreeM Daemon Automatically ==&lt;br /&gt;
&lt;br /&gt;
These instructions apply only to source builds. The binary packages install the init script automatically.&lt;br /&gt;
&lt;br /&gt;
* Copy &amp;lt;code&amp;gt;scripts/solaris-init/freem&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/etc/init.d&amp;lt;/code&amp;gt;&lt;br /&gt;
* Make a symbolic link from &amp;lt;code&amp;gt;/etc/rc3.d/S20freem&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;/etc/init.d/freem&amp;lt;/code&amp;gt;&lt;br /&gt;
* Run &amp;lt;code&amp;gt;/etc/init.d/freem start&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Tier 1 Ports]]&lt;br /&gt;
[[Category:Platform Notes]]&lt;/div&gt;</summary>
		<author><name>Smw</name></author>
		
	</entry>
</feed>