Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion docs/man/man1/halcompile.1
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,13 @@ Install \fB.c\fR and \fB.py\fR files into the proper directory for HAL non-realt
Extract documentation from \fB.comp\fR files into \fB.9\fR manpage files in the proper system directory (the \fB\-\-install\fR flag), which may require \fIsudo\fR to write to system directories.
.IP \(bu 4
Preprocess \fB.comp\fR files into \fB.c\fR files (the \fB\-\-preprocess\fR flag)
.SH "SEE ALSO"
.SH NAMES
A name declared in a \fB.comp\fR file is a C identifier, but it is exported under a mangled HAL identifier: underscores become dashes, and a trailing dash or period is removed.
\fBpin in float my_input\fR is reached from HAL as \fBcomponent.N.my\-input\fR, and \fBloadrt my_comp\fR exports its pins under \fBmy\-comp.N.\fR
Two declarations that mangle to the same HAL name are rejected.
.PP
See HALNAME under \fISyntax\fR in the \fIHalcompile HAL Component Generator\fR documentation for the full rules.
.SH "SEE ALSO\"
\fIHalcompile HAL Component Generator\fR in the LinuxCNC documentation for a full description of the \fB.comp\fR syntax, along with examples

\fBpydoc, HAL\fR and \fICreating Non-realtime Python Components\fR in the LinuxCNC documentation for documentation on the Python interface to HAL components
5 changes: 5 additions & 0 deletions docs/src/hal/comp.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,11 @@ A trailing "_" is retained, so that HAL identifiers which would otherwise collid
|x.## | x(MM) | x.MM
|===

[NOTE]
Two declarations that produce the same HAL identifier -- 'x_y_z' and 'x_y_z_' in
the table above -- are rejected by `halcompile`; they would otherwise fail at
`loadrt` with "HAL: ERROR: duplicate variable".

* 'if CONDITION' - An expression involving the variable 'personality' which is nonzero when the pin or parameter should be created.

* 'SIZE' - A number that gives the size of an array. The array items are numbered from 0 to 'SIZE'-1.
Expand Down
22 changes: 21 additions & 1 deletion src/hal/utils/halcompile.g
Original file line number Diff line number Diff line change
Expand Up @@ -151,13 +151,15 @@ deprecated = ['s32', 'u32']

def initialize():
global functions, params, pins, comp_name, names, docs, variables
global modparams, includes
global modparams, includes, hal_pin_names, hal_funct_names

functions = []; params = []; pins = []; options = {}; variables = []
modparams = []; docs = []; includes = [];
comp_name = None

names = {}
hal_pin_names = {}
hal_funct_names = {}

def Warn(msg, *args):
if args:
Expand Down Expand Up @@ -215,10 +217,25 @@ def check_name_ok(name):
if name in names:
Error("Duplicate item name %s" % name)

def check_hal_name(seen, name):
"""A declaration is a C identifier, but it is exported under a mangled HAL
identifier. check_name_ok() only compares declared names, so two
declarations that mangle to one HAL name would compile cleanly and fail
later, at loadrt, with "HAL: ERROR: duplicate variable"."""
if name == "_": return # the unnamed singleton function
hal_name = to_hal(name)
if hal_name in seen:
Error("'%s' and '%s' both export the HAL name '%s'; see HALNAME under "
"'Syntax' in the Halcompile HAL Component Generator "
"documentation, https://linuxcnc.org/docs/html/hal/comp.html"
% (seen[hal_name], name, hal_name))
seen[hal_name] = name

def pin(name, type, array, dir, doc, value, personality):
checkarray(name, array)
type = type2type(type)
check_name_ok(name)
check_hal_name(hal_pin_names, name)
docs.append(('pin', name, type, array, dir, doc, value, personality))
names[name] = None
pins.append((name, type, array, dir, value, personality))
Expand All @@ -227,12 +244,15 @@ def param(name, type, array, dir, doc, value, personality):
checkarray(name, array)
type = type2type(type)
check_name_ok(name)
check_hal_name(hal_pin_names, name) # hal_lib.c: setp cannot tell a pin
# and a param of one name apart
docs.append(('param', name, type, array, dir, doc, value, personality))
names[name] = None
params.append((name, type, array, dir, value, personality))

def function(name, fp, doc):
check_name_ok(name)
check_hal_name(hal_funct_names, name)
docs.append(('funct', name, fp, doc))
names[name] = None
functions.append((name, fp))
Expand Down
1 change: 1 addition & 0 deletions tests/halcompile/halname/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
halname_mangled.c
3 changes: 3 additions & 0 deletions tests/halcompile/halname/expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
halname_collision.comp:4:18: 'x_y' and 'x_y_' both export the HAL name 'x-y'; see HALNAME under 'Syntax' in the Halcompile HAL Component Generator documentation, https://linuxcnc.org/docs/html/hal/comp.html
> pin out bit x_y_;
> ^
7 changes: 7 additions & 0 deletions tests/halcompile/halname/halname_collision.comp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
component halname_collision;
license "GPL";
pin in bit x_y;
pin out bit x_y_;
function _;
;;
FUNCTION(_) {}
6 changes: 6 additions & 0 deletions tests/halcompile/halname/halname_mangled.comp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
component halname_mangled;
license "GPL";
pin in bit my_pin;
function _;
;;
FUNCTION(_) {}
15 changes: 15 additions & 0 deletions tests/halcompile/halname/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash
set -e

# A name that is exported under a different HAL name must still compile.
rm -f halname_mangled.c
halcompile --preprocess halname_mangled.comp 2>&1
test -f halname_mangled.c || echo 'halcompile failed to produce halname_mangled.c'

# Two declarations that mangle to one HAL name must be rejected, not left to
# fail at loadrt as "HAL: ERROR: duplicate variable".
rm -f halname_collision.c
if halcompile --preprocess halname_collision.comp 2>&1; then
echo 'halcompile erroneously accepted halname_collision.comp'
fi
test ! -f halname_collision.c || echo 'halcompile erroneously produced halname_collision.c'