AllegroPro Coding Conventions

AllegroPro will be built as a C library.

Variable Naming and Use

No global variables will be exposed to the user. Any global variable-like system should expose an appropriate "get"/"set" accessor function.

The naming conventions of local variables and internal global variables should be in all lowercase, with underscores (_) between words. Names should be descriptive.


Function Naming

All API functions, those exposed to the user, will begin with 'al'. Following this 'al' will be a character, based on the component to which the API function belongs. For example, all API functions that are based in the graphics system will be 'alg'. The character 'i' will be used for input, the character 's' will be used for audio, and the 'f' character for the file system. API functions in the core, that do not belong to a component, will begin with simply 'al'.

Non-API functions (or functions that are not a normal part of the API, like functions a driver developer might use) should not use this prefix. In general, functions that are internal to a specific component will have a short component-specific prefix ("core_", "gfx_", "snd_", "inp_", etc). 

Following this prefix should be an underscore, followed by a descriptive name of the function. Where possible, these should follow "verb-noun" syntax. Prefer "alg_upload_bitmap" to "alg_bitmap_upload".

Function Argument conventions

Argument names should follow the naming conventions for variables.

If a function takes an argument that, in an object-oriented sense, is a "this"-type member, then that member should be first. Prefer "alg_get_framebuffer(alg_driver *driver, int32_t *buffer_number)" to "alg_get_framebuffer(int32_t *buffer_number, alg_driver *driver)".

After this point, arguments should be ordered from destination to source. Prefer "alg_blit(alg_bitmap_t *dest, alg_bitmap_t *src)" to "alg_blit(alg_bitmap_t *src, alg_bitmap_t *dest)". In this particular case, the first is preferred due to the effective "this" pointer coming from the destination rather than the source.

2D coordinates, when not using a container struct for them, should be in x, y order. Rectangular parameters, when not using a container struct for them, should be defined as an x, y upper-left position followed by a width, height parameter set.

To deal with 64-bit issues, all integral types must use explicit typedefs that specify the size of the integer.

API Functions

API functions are special functions that the user is allowed to call. All of these functions should have a special macro in front of their declaration: AL_API. This macro allows for building the library as a .dll file. Any other functions that are not explicit API functions, but that are in the "include" directory, should also be defined with AL_API.


Struct/enum/type Naming

All types, structs, enums, or other typedef things, will be in lowercase. They are prefixed in the same way as functions. They will end in "_t". For example, "alg_bitmap_t".

API types are those that are exposed in API header files for public use. API types are prefixed as for API functions.

There may be a number of auxiliary types created for internal use only. These can be used by any system. These will have their own "int_" prefix. Functions on these are prefixed as above.

The exception to the prefixing rule will be for simple type aliases such as "uint16_t", etc. They do not need a prefix, but they still need the "_t" suffix.

Function typedefs, for callbacks, need not have the suffix, but they do need the prefix. These should end in a "_func" prefix, and follow the conventions for callbacks as defined under Miscellaneous.

Justification: Change from standard Allegro 4 conventions

The fundamental standard that virtually all C and C++ code follows for #define macros is full uppercase with underscores; there are very few programs that do not follow this convention. And when this standardized convention is violated, it is usually with a specific intent, such as redefining main().

This is done for a number of reasons, but one of the important ones is to be able to readily pick out a macro out of a piece of code. Using standard macro conventions for types works against the logic of using all uppercase for easily finding macros in code. Macros can be potentially quite destructive, if not properly used and carefully constructed. As such, it is vital to be able to recognize when macros are in use.


#define Macros: Definition and Use

Under standard C/C++ conventions, #define macros are in full uppercase with underscores separating words. Additionally, they will use prefixes as defined for functions, but these will also be in uppercase.

Any #ifdef or #ifndef (including include guards) should appear as the following form:

#ifdef AL_DEFINE
#endif //AL_DEFINE

In particular, note the comment at the #endif that repeats the #ifdef's argument. This is useful for finding the matching #ifdef if all you can see is a #endif.

A comment for a #else is not required, but it is sometimes nice to do the following, especially if the "stuff" is large:

#ifdef AL_DEFINE
#else //!AL_DEFINE
//Other stuff
#endif //AL_DEFINE


File Spacing

Files will use spaces instead of tabs for indentures. Each indent should be 2 spaces. Avoid lines longer than 80-100 characters.


File Naming

API header files should be prefixed with "al", but no need for underscores. Non-API headers should not be prefixed, except for certain specific system headers. If the non-API header has some API analog (for example, the thread API and the internal thread header), then the file should end in "int". For corresponding files like this, the names should match except for the prefix/suffix.

Platform-specific headers/source files should end in "plat". Compiler-specific headers/source files should end in "comp".

All files and directories must be in all lowercase.


Miscellaneous Conventions

Any and all callback functions should also pass along a void* parameter that the user registers at the time of setting the callback. Some may additionally wish to pass along an integer parameter, but the void* parameter is not optional. The void* should come at the end of the parameter list. If there is an integer parameter as well (or others), then it should come last, with the void* being just before those arguments.

The standard define "AL_CONST" should be used for constant arguments of pointer type (basic types do not need it). On C compilers that support 'const', this will actually evaluate to a "const" keyword; on other compilers, it will evaluate to nothing.

All headers should have include guards. Include guards for API or driver files should begin with "ALPRO_", and end with "_H". In general, the include guard should be very reminiscent of the file's actual name.