NDK 3.2 Developer Tools

The Tools/ directory of NDK 3.2 contains a set of Shell utilities that Commodore and the AmigaOS 3.2 team used to build and document the operating system. According to ReadMe-NDK.txt, Autodoc, BumpRev, CatComp and Localize were "integrated in the Tools directory" with NDK 3.2 R2 (31.05.2021). The directory also holds AG2HTML and AGuideCheck, both with source code.

Tool Location Version (from sources) Purpose
Autodoc Tools/Autodoc/ man page dated 21 Aug 1989 Extract autodoc comments from source files into .doc files
BumpRev Tools/bumprev/ documentation 47.1 (06.02.2022) Generate and increment _rev.h / _rev.i version files
CatComp Tools/Catcomp/ documentation 40.7 (15.10.2021) Compile locale catalogs; see CatComp and Installer
Localize Tools/Localize/ 2.9 (ChangeLog, June 1992) Find string literals in C sources and replace them with catalog calls
AG2HTML Tools/AG2HTML/ 1.5 (2.10.98) Convert AmigaGuide databases to linked HTML pages
AGuideCheck Tools/AGuideCheck/ 3.0 (11.5.2020) Check AmigaGuide files for broken links and syntax problems

Autodoc

autodoc extracts the autodoc comment blocks from source files, sorts them and writes them to standard output. Every Autodocs/*.doc file in the NDK has this layout: a table of contents followed by one entry per function, separated by form feeds.

Synopsis

autodoc [-tnum] [-i] [-a] [-s] [-C] [-lnum] [-w] [-c] [-f] [-r] [-Ffile] [-I] file1 [file2] [...]
Option Meaning
-tnum Convert tabs into num spaces
-i Extract only internal autodocs, which have an i as the 6th character of the opening line
-a Process autodocs that begin with an asterisk in column 1 (assembler style). Turns off C autodocs unless you add -C
-s Process autodocs that begin with a semicolon in column 1. Turns off C autodocs unless you add -C
-C Process C-language autodocs (the default). Use it to force C processing together with -a or -s
-lnum Line length (default 78)
-w Turn off word wrap. Longer lines are cut off
-c Do not convert C comments (backslash-asterisk to slash-asterisk), so autodocs can contain comments without nesting them
-f No form feeds between entries
-r troff output (documented as "currently not implemented")
-Ffile Temporary file to use (default tmpfile)
-I Leave out the table of contents

The man page says the tool "must be used only with text files".

Comment format

An autodoc starts with a line whose first characters are /****** followed by a space, the module/function name and a row of asterisks. A line of asterisks ends it. The sections use the standard headings. This example is from the trackfile.device sources in the NDK:

/****** trackfile.device/TFStopUnitTagList ***********************************
*
*   NAME
*   TFStopUnitTagList - Stop a trackfile.device unit, releasing as much
*       memory possible.
*
*   SYNOPSIS
*   error = TFStopUnitTagList(which_unit, tags)
*     D0                         D0        A0
*
*   LONG TFStopUnitTagList(LONG which_unit, CONST struct TagItem *tags);
*
*   FUNCTION
*   ...
*   INPUTS
*   ...
*   RESULT
*   ...
*   SEE ALSO
*   TFEjectMediaTagList(), TFStartUnitTagList()
******************************************************************************
*/

An internal entry has i in place of the 6th asterisk (/*****i* ...). It is skipped by default and is the only thing extracted with -i.

Examples (from the man page)

autodoc file1 > outfile             ; all C autodocs except internal, with TOC
autodoc -s file1 > outfile          ; only semicolon-style (assembler) autodocs
autodoc -a -s -C file1 > outfile    ; every style except internal

BumpRev

BumpRev creates and increments the revision files that put an AmigaDOS version string into your binary, so the Version command can report it. It is meant to be run from makefiles.

BumpRev <version> <revname>

bumprev 49 my_program increments the revision of my_program by one. If no revision files exist in the current directory yet, it creates them at 49.1. It writes three files:

<name>_rev.h (C):

#define VERSION         49
#define REVISION        1
#define DATE            "6.2.2022"
#define VERS            "myprogram 49.1"
#define VSTRING         "myprogram 49.1 (6.2.2022)\r\n"
#define VERSTAG         "\0$VER: myprogram 49.1 (6.2.2022)"

<name>_rev.i (assembler): VERSION/REVISION as EQU, plus DATE, VERS, VSTRING and VERSTAG as dc.b macros:

VERSION         EQU     49
REVISION        EQU     1
VERSTAG MACRO
                dc.b 0,'$VER: myprogram 49.1 (6.2.2022)',0
                ENDM

<name>_rev.rev: stores the current revision number (1), which BumpRev reads on its next run.

Using the macros

#include "myprogram_rev.h"

static const char version_tag[] = VERSTAG;   /* found by the Version command */

trackfile_device.c in the NDK shows the usage for a device: VERSION goes in rt_Version and VSTRING in rt_IDString of the Resident structure, and REVISION is stored in lib_Revision at init time.

Makefile pattern

The NDK's own Tools/AG2HTML/smakefile uses this pattern. It sets the .rev file so that the next bump produces the revision written in the makefile:

VERSION =   1
REVISION =  5
PROJECT_NAME = AG2HTML

version:
    echo >$(PROJECT_NAME)_rev.rev `eval $(REVISION) - 1`
    bumprev $(VERSION) $(PROJECT_NAME)

ag2html.o: ag2html.c ag2html_rev.h

The trackfile.device and DAControl sources in DAControl+trackfile/ ship their generated *_rev.h and *_rev.rev files in the same way.

Localize

Localize helps convert an existing C program to use locale.library. It works in two passes: parse, which lists the string literals, and patch, which rewrites the source and writes a catalog description file.

Template

PATCH/S,DIR=DIRECTORY/K,MC=MERGECATALOG/K,SORT/S,MIN=MINIMUM/K/N,NEST/S,
EXF=EXCEPTFUNCS/K,EXS=EXCEPTSTRINGS/K,FUNC=FUNCTION/K,TEMP=TEMPLATE/K,
PS=PREPENDSTRING/K,PF=PREPENDFILE/K,AS=APPENDSTRING/K,AF=APPENDFILE/K,
SH=SILENT/S,FILES/A/M

Parse mode

Without PATCH, Localize scans the files and prints one record per string literal. In this mode all other keywords are silently ignored.

file|type|line|start column|end column|message tag|string
Type Meaning
S Localizable string inside a function
E 1.3+ String outside any function, so not patchable. It is written to the .cd file as a comment
D String inside a #define. Not patched by default. Change it to S only if the macro is used solely inside functions
1> LOCALIZE >RAM:strings hello.c
1> type RAM:strings
hello.c|S|3|11|26|MSG_0000|hello world\n

Edit the record file: delete strings that must not be translated (assigns, font names, debug output), rename the message tags, and give repeated strings a single tag. Do not reorder the lines. Records must stay sorted by line and then by column, or the result is undefined.

Patch mode

1> LOCALIZE PATCH RAM:strings
Processing RAM:strings...
  hello.c -> hello.c.new & hello.c.cd
  patching line 3

The output goes to Localized-Source/ by default. Patched strings become calls built from the TEMPLATE.

Keyword Effect
DIRECTORY Output directory. A name containing : is used as is; otherwise it is relative to each source file's directory
MERGECATALOG Write one combined .cd file instead of one per source file
SORT Sort the .cd file by message ID. The default is the order in which strings were found
MINIMUM n Skip strings shorter than n
NEST Allow nested comments
EXCEPTFUNCS File listing function names (one per line, case-sensitive) whose string arguments are left alone
EXCEPTSTRINGS File of match, Cmatch, contains and Ccontains "pattern" rules for strings to skip
FUNCTION Name of the lookup function (default GetCatalogStr)
TEMPLATE Call template. %F = function, %I = message tag, %S = tag + _STR, %D = default string. Default "(catalog ? %F(catalog, %I, %S) : %S)"
PREPENDSTRING / PREPENDFILE Text or file inserted at the top of the generated source
APPENDSTRING / APPENDFILE Text or file added at the end
SILENT Suppress progress output

The generated .cd entry for the example looks like this ((//) lets CatComp assign the ID):

; line 3
;
MSG_0000 (//)
hello world\n

Strings outside functions

Localize cannot patch initialised global data such as char *help[] = { "...", ... } or the text pointer of a static IntuiText. localize.doc suggests two fixes. One is to move the assignments into an initialize_strings() function that runs at startup. The other is to loop over the message IDs with a GetString(catalog, id) helper, adapted from the 1991 DevCon notes, that looks the ID up in an AppStrings[] table and falls back to the built-in text.

Example scripts

examples/localize1 runs the three steps: parse into ram:localize, edit, then patch. examples/localize2 uses MC catalog.cd, DIR work:ls, FUNC S, TEMP "%F(%I)" and PF getstring.pf to produce short S(MSG_x) calls. The sample localize-except-functions and localize-except-strings files show the exception file syntax.

Typical workflow

  1. LOCALIZE >RAM:strings #?.c, then edit RAM:strings.
  2. LOCALIZE PATCH MC app.cd RAM:strings.
  3. Check the generated app.cd and run CatComp app.cd CFILE app_strings.h to get the MSG_* IDs and _STR defaults.
  4. Open the catalog with OpenCatalog() at startup. See Writing Localized Applications.

AG2HTML

AG2HTML 1.5 converts one or more AmigaGuide databases into a set of linked HTML pages. It follows links into other guide files and keeps scanning until every referenced document is included.

AG2HTML FILES/M,TO/K

TO names the output directory (default: the current directory). It must already exist.

What the source shows:

  • File layout. The MAIN node of name.guide becomes name.html. Every other node becomes name_guide/nodeXXXX.html (hexadecimal node number). Names are cut to 30 characters.
  • Navigation bar. Each page gets Contents, Index, Help, Retrace, Browse < and Browse > buttons. Disabled buttons use the _d variants. The GIFs are built into the program and written to images/ (toc.gif, index.gif, help.gif, retrace.gif, prev.gif, next.gif and their _d versions).
  • Commands handled. @node/@endnode, @title, @toc, @index, @prev, @next, @wordwrap, and link attributes. @database, @master, @remark, @author, @(c), @$VER:, @font and @help are skipped. The V39 text attributes b/ub, i/ui, u/uu, fg/bg become HTML markup, with pen names mapped to fixed colours.
  • Pictures. A link target that datatypes.library identifies as a picture (GID_PICTURE) is rendered and saved as a GIF (convert_picture.c, write_gif.c), then embedded with <img> and its width and height.

It builds with SAS/C (smakefile: ag2html.c write_gif.c convert_picture.c, linked with lib:sc.lib).

AGuideCheck

AGuideCheck 3.0 checks AmigaGuide files. It reports invalid links and nodes that are never referenced, and it can also generate an index node. It requires locale.library V38 and utility.library.

AGuideCheck FROM/A,INDEX,FMTCHECK/S,ALL/S
Argument Meaning
FROM File or wildcard pattern to check
ALL Recurse into directories matched by FROM
INDEX If the check is clean, write an @NODE INDEX "Index" file here. Entries are sorted by node title and grouped by initial letter (locale-aware), with "Other..." for titles that don't start with a letter
FMTCHECK Also warn about a command at the end of a line followed by text, which causes formatting problems under word wrap

It follows links into other .guide files (by checking their MAIN nodes) and reports:

  • Undefined node <file>/<node> referenced at line N of <file> (return code 7)
  • Node X defined at line N of <file> is unreferenced (5)
  • Node X ... has no title (6)
  • Problem found at line N: <reason> for syntax errors. Examples: commands not at the start of a line, unknown commands or attributes, duplicate nodes, @NODE inside a node, @DATABASE not at the start of the file, global commands (@$VER, @(c), @AUTHOR, @MASTER, @WIDTH, @HEIGHT, @TAB) inside a node, node commands (@NEXT, @PREV, @TOC, @TITLE, @KEYWORDS) outside a node, unterminated strings and attributes, and obsolete ALINK, CLOSE, QUIT and DNODE

Lines longer than 8192 bytes abort the check. Files that don't look like AmigaGuide are reported and ignored. Ctrl-C stops the scan.

1> AGuideCheck MyApp.guide INDEX RAM:index.part
1> AGuideCheck Docs:#?.guide ALL FMTCHECK

Putting it together

A typical NDK-style project uses the tools like this:

  1. Version: run bumprev from the version: makefile target and include name_rev.h for VERSTAG and the Resident fields.
  2. Strings: run Localize once on legacy code, then keep the .cd file up to date by hand. Generate headers with CatComp ... CFILE, and catalogs with CatComp app.cd lang.ct CATALOG ....
  3. API documentation: write autodoc headers in the source and run autodoc to produce Autodocs/*.doc.
  4. User documentation: write an AmigaGuide file, check it with AGuideCheck (optionally generating the index node), and publish it as HTML with AG2HTML.

See Also


Sources: NDK 3.2 R4 ReadMe-NDK.txt, Tools/Autodoc/autodoc.man, Tools/bumprev/BumpRev.doc, Tools/Localize/{localize.doc,ChangeLog,MANIFEST,examples/}, Tools/AG2HTML/{ag2html.c,convert_picture.c,smakefile,AG2HTML_rev.h}, Tools/AGuideCheck/AGuideCheck.c, Tools/Catcomp/CatComp.doc, DAControl+trackfile/trackfile/{functions.c,trackfile_device.c} Updated: 2026-11-13