Hello, this is a page from the workspace that I wanted you to see. This
page is also available for viewing or editing on the web at:

http://www.perlfoundation.org/parrot/index.cgi?headerizer

Headerizer creates function declarations based on function definitions.
It scans the source files passed to it and extracts the function
declarations. Then it puts them into the appropriate .h file or, in the
case of static functions, back into the source file itself.

The headerizer also adds function attributes as specified by the
decorations on the source.

All of these macros are GCC-specific right now, but soon will have
equivalent semantics for lint added to them. This will make lint a far
more powerful tool. If/when we ever get splint going, too, we can add
semantics there as well.

^ The goal

I'm trying to create as many seat belts and idiot lights as possible.
Using C macros and automatic function declaration generation makes this
much easier for me to do, and is far more maintainable.

^ What's a shim?

Think of "shim" as shorthand for "placeholder". It's 64% shorter.

GCC (and lint) likes to complain (as well it should) if you pass an
argument into a function and don't use it. If we know that we're not
going to use an argument, we can either remove the argument from the
function declaration, or mark it as unused.

Throwing the argument away is not always possible. Usually, it's because
the function is one that gets referred to by a function pointer, and all
functions of this group must have the same, say, three args: Interp, Foo
and Bar. Maybe a given function doesn't use Foo, but we still have to
accept Foo. In this case, we can in the body of the func, UNUSED(Foo),
if we plan to use it in the future. Or, if we never will use it, mark it
as a `SHIM(Foo)` in the declaration.

^ Decorators

^^ Function decorators

* `/* WARN_UNUSED */` ** Use this to flag functions where it is
  definitely an error to call it without checking its return value. **
  Headerizes to `__attribute__warn_unused_result__`
* `/* MALLOC */` ** Denotes functions that return a new piece of memory,
  such that losing the return value would cause a memory leak. **
  Headerizes to `__attribute__malloc__`
* `/* CONST */` ** For functions that operate only on their operands, do
  not use global memory, and have no side effects. The compiler can
  optimize away repeated calls to CONST functions. mod() is a good
  example. rand() is an anti-example. Note that this sense of const is
  unrelated to the const qualifier on variables. ** Headerizes to
  `__attribute__malloc__`
* `/* PURE */` ** Less stringent than CONST. Can check global memory or
  dereference pointers. strlen() is a good example. ** Headerizes to
  `__attribute__pure__`
* `/* NORETURN */` ** For functions that never return. This can help the
  compiler's program flow analysis. Functions like exit() the compiler
  already knows about, but others like internal_exception() we have to
  tell it about. ** Headerizes to `__attribute__noreturn__`

^^ Function argument decorators

* `/* NN */` ** GCC warns if it determines that a NULL could be passed
  to this argument. ** Headerizes to `__attribute__nonnull__`
* SHIM(int foo) ** Squelches warnings about being unused, and since it
  manges the argument name, you can't accidentally use the argument
  without specfically unshimming the argument. ** Headerizes to `int
  foo_unused __attribute__unused__`.

^^ Interpreters

There are only two states for the interpreter: Used, or shimmed. If
we're using it, it has to be /NN/. (Except in a couple of cases like
real_exception) The interpreter is so common in functions, we give it
its own two macros: INTERP and SHIM_INTERP.

* `SHIM_INTERP` ** Headerizes to `SHIM(Interp *interp)` ** Because it's
  shimmed, we're guaranteed we won't accidentally use it.
* `INTERP` ** Any interpreter that isn't a shimmed interpreter must be
  non-null. ** Headerizes to `Interp *interp /*NN*/`

^ Examples

.pre PARROT_API INTVAL string_str_index(INTERP, const STRING *s /*NN*/,
const STRING *s2 /*NN*/, INTVAL start) /* WARN_UNUSED */ .pre

`string_bool` is part of the Parrot API, and returns in INTVAL. The
interpreter is used somewhere in the function. String `s` and `s2`
cannot be NULL. If the calling function ignores the return value, it's
an error, because you'd never want to call `string_str_index()` without
wanting to know its value.

.pre PARROT_API INTVAL parrot_hash_size(SHIM_INTERP, const Hash *hash
/*NN*/) /* PURE, WARN_UNUSED */ { return hash->entries; } .pre

This function is a pure function because it only looks at its parameters
or global memory. The interpreter doesn't get used, but needs to be
passed because all PARROT_API functions have interpreters passed, so is
flagged as a SHIM_INTERP.

Reply via email to