| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- \documentclass[final,a4paper,10pt, oneside]{article}
- \usepackage[latin1]{inputenc}
- \usepackage[T1]{fontenc}
- \usepackage{a4wide}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- %%%% important definitions at the beginning
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \title{Coding Rules for\\ \emph{OpENer} --- Open Source EtherNet/IP$^{TM}$ Adapter Stack\\\large Version 2.0}
- \author{Martin Melik Merkumians\thanks{melik-merkumians\@@acin.tuwien.ac.at}}
- \date{2015-11-15}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- % Links
- \usepackage{ifpdf}
- \ifpdf
- \usepackage[pdftex, colorlinks, pdfstartview=FitH, plainpages=false, pdfpagelabels]{hyperref}
- \pdfcompresslevel=9
- \else
- \usepackage[dvipdfm, colorlinks]{hyperref}
- \fi
- \hypersetup{colorlinks, linkcolor=black, filecolor=black, urlcolor=black, citecolor=black, pdftitle={Coding Rules for OpENer},pdfauthor={Alois Zoitl}}
- % Font
- \usepackage{mathpazo}
- \usepackage[centerlast,small,bf]{caption} %zentriert, kleiner als fliesstext, fett (gilt nur fuer 'Abbildung x:')
- % Figures
- \usepackage[dvips]{graphicx}
- % Listings
- \usepackage{listings}
- \lstset{language=C++}
- \lstset{commentstyle=\textit}
- \lstset{linewidth=\textwidth}
- \lstset{basicstyle=\scriptsize}
- \usepackage{fancyref}
- \usepackage{hyperref}
- \begin{document}
- \maketitle
- \tableofcontents
- \section{Introduction}
- This document describes the coding rules, which has to be used in the OpENer project. These rules are mainly the Google C++ style rules, with some extensions specific to C and the OpENer project. If something is not covered by the rules given in this document, please check the official Google C++ style guide, available at \url{http://google.github.io/styleguide/cppguide.html}. Additional code style examples can be found at \url{https://gist.github.com/davidzchen/9187878}.
- As the OpENer code style aims to be as close as possible to the established Google C++ code style, please file an issue if anything in this guide contradicts the Google C++ code style.
- \section{Comments}
- A sufficient amount of comments has to be written. There are never too many comments, whereas invalid comments are worse than none --- thus invalid comments have to be removed from the source code. Comments have to be written in English.
- Comments for function, structure, \ldots~ definitions have to follow the conventions of \emph{Doxygen} to allow the automated generation of documentation for the source code. Hereby Java-style Doxygen comments shall be used. Doxygen comments shall therefore start with slash and two starts, and use the @ symbol to indicate Doxygen keywords. For enums, variables, and strucutres inline documentation with \emph{/**<} shall be used. Autobrief behavior shall not be assumed for Doxygen comments. See the example below.
- \begin{lstlisting}[frame=trbl]{}
- /** @brief function, structure, enum, etc. to comment
- *
- * Detailed explanation, spanning multiple lines if needed.
- * @param parameter1 Parameter1 description
- * @return Return value description
- */
- int foo(char bar) {
- ...
- }
- const int g_kFooBar = 1; /**< Global constant which needs documentation */
- \end{lstlisting}
- Comments have to be meaningful, to describe to program and to be up to date.
- \subsection{Fileheaders}
- Every source-file must contain a fileheader as follows:
- \begin{lstlisting}[frame=trbl]{}
- /*******************************************************************************
- * Copyright (c) 2009, Rockwell Automation, Inc.
- * All rights reserved.
- *
- * Contributors:
- * <date>: <author>, <author email> - changes
- ******************************************************************************/
- \end{lstlisting}
- Each author needs to explain his changes in the code.
- \subsection{Revision History}
- %To track changes in the source files every new file version must contain it's version information in the following form:
- %\begin{center}
- % @version: $<$date$>$/$<$author$>$: $<$description$>$
- %\end{center}
- %An additional example is given in the appendix \ref{subsec:FileHeader} of this document.
- The revision history has to be done in a style usable by Doxygen. This means that the history is independent of the files, but all classes are documented.
- \subsection{Keywords}
- The following Keywords should be used in the source code to mark special comments:
- \begin{itemize}
- \item \textbf{TODO:} For comments about possible or needed extensions
- \item \textbf{FIXME:} To be used for comments about potential (or known) bugs
- \end{itemize}
- \section{Datatypes}
- \Fref{tab:datatypes} contains the definitions of important standard datatypes. This is done to ensure a machine independant defintion of the bit-width of the standard data types. For \emph{OpENer}-development these definitions are in the file: \verb|src/typedefs.h|
- \begin{table}[h]
- \caption{Data types used in OpENer} \label{tab:datatypes}
- \centering
- \begin{tabular}{lll}
- defined data type & bit-width / description & used C-datatype \\
- \hline
- EipByte & 8 bit unsigned & uint8\_t\\
- EipInt8 & 8 bit signed & int8\_t \\
- EipInt16 & 16 bit signed & int16\_t \\
- EipInt32 & 32 bit signed & int32\_t \\
- EipInt64 & 64 bit signed & int64\_t \\
- EipUint8 & 8 bit unsigned & uint8\_t \\
- EipUint16 & 16 bit unsigned & uint16\_t \\
- EipUint32 & 32 bit unsigned & uint32\_t \\
- EipUint64 & 64 bit unsigned & uint64\_t \\
- EipFloat & single precission IEEE float (32 bit) & float \\
- EipDfloat & double precission IEEE float (64 bit) & double \\
- EipBool8 & byte variable as boolean value & unit8\_t \\
- CipOctet & unspecified type & uint8\_t \\
- CipBool & byte variable as boolean value & uint8\_t \\
- CipByte & 8 bit unsigned & uint8\_t \\
- CipWord & 16 bit unsigned & uint16\_t \\
- CipDword & 32 bit unsigned & uint32\_t \\
- CipUsint & 8 bit unsigned & uint8\_t \\
- CipUint & 16 bit unsigned & uint16\_t \\
- CipUdint & 32 bit unsigned & uint32\_t \\
- CipSint & 8 bit signed & int8\_t \\
- CipInt & 16 bit signed & int16\_t \\
- CipDint & 32 bit signed & int32\_t \\
- CipReal & single precission IEEE float (32 bit) & float \\
- CipLreal & double precission IEEE float (64 bit) & double \\
- CipLint & 64 bit signed & int64\_t \\
- CipUlint & 64 bit unsigned & uint64\_t \\
- CipLword & 64 bit unsigned & uint64\_t
- \end{tabular}
- \end{table}
- These data types shall only be used when the bit size is important for the correct operation of the code, whereby Eip-prefixed data types shall be used for communication functions, and Cip-prefixed data types shall be used for CIP related functions and objects. If not we advice to use the type \verb|int| or \verb|unsigned int| for most variables, as this is the most efficient data type and can lead on some platforms (e.g., ARM) even to smaller code size.
- \section{Naming of Identifiers}
- Every identifier has to be named in English. The first character of an identifier must not contain underscores (there are some compiler directives which start with underscores and this could lead to conflicts). Mixed case letters has to be used and the appropriate prefixes have to be inserted where necessary.
- \subsection{Pre- \& Postfixes}
- The following prefixes have to be applied to identifiers:\\
- \begin{itemize}
- \item \emph{"g\_"} shall be prefixed for global variables.
- \item \emph{"\_"} shall be postfixed for member variables. These are usually CIP object variables with file-global scope.
- \end{itemize}
- \subsection{Variables}
- Variables have to be named self explanatory. The names have to be provided with the appropriate pre- or postfix and shall be all lowercase letters, and if a name consists of more than one word underscores shall be used for separating these words. The only exception are loop variables (thereby the use of i, j, k is allowed). Only one variable declaration per line is allowed. Pointer operators at the declaration have to be located in front of the variable (not after the type identifier). If possible initializations have to be done directly at the declaration.
- \paragraph{Examples}
- \begin{quote}
- \begin{lstlisting}
- int i;
- int local_variable;
- CipBool boolean_flag_in_cip_object_;
- \end{lstlisting}
- \end{quote}
- \subsection{Constants}
- The preferred way to declare constants is to define them as\emph{const} data types, if this is not possible constants shall be defined as pre-processor statements, via \emph{\#define}.
- If constants are defined as C constants the name of the constant shall start with \emph{k}, followed by the constant name in Pascal case.
- If a constant is defined as a pre-processor statement the constant name shall be all upper case, separating multiple words with underscored.
- Avoid the using ``magic numbers'' (e.g. \verb|if (x == 3){...}|). Instead use constants.
- \paragraph{Examples}
- \begin{quote}
- \begin{lstlisting}
- static int g_global_variable;
- static const int g_kAGlobalConstant = 73:
- const int kAnImportantConstant = 42;
- #define DO_NOT_DO_THIS_IF_IT_IS_NOT_NECESSARY bad
- \end{lstlisting}
- \end{quote}
- \subsection{Functions}
- Functions names shall be Pascal cased, function parameters shall be named like variables. The parameter list shall adhere to the following rules:
- \begin{itemize}
- \item Input parameters shall come first
- \item Input parameters shall be const
- \item Output parameters shall be last
- \end{itemize}
- \paragraph{Examples}
- \begin{quote}
- \begin{lstlisting}
- int FooBar(const int foo, const char* const bar, double* additional_return_value)
- \end{lstlisting}
- \end{quote}
- \subsection{Structs}
- The default case for structs shall be, that they are defined as anonymous structs, giving them a type name via the \emph{typedef} keyword. Struct names shall be pascal cased. If a struct type is needed, before a typedef alias can be created (usually inside the same struct), the struct name shall be repeated in the struct type name, following the conventions for variable names, with all lowercase and words separated with underscores.
- The element names inside the struct are following the normal conventions for their types.
- \paragraph{Examples}
- \begin{quote}
- \begin{lstlisting}
- typedef struct {
- int foo;
- char bar;
- } TheDefaultCase;
- typedef the_excpetion {
- struct the_exection *needed_the_struct_definition_already_here;
- char other_elements;
- } TheException;
- \end{lstlisting}
- \end{quote}
- \subsection{Enums}
- Enums shall be defined anonymous and typedef'ed to a type name. As the values inside an enum are constant, the naming scheme of constants apply for enum members. As Enums do not define their own namespace, the enum type name shall be added between the initial \emph{k} and the constant name.
- \paragraph{Examples}
- \begin{quote}
- \begin{lstlisting}
- typedef enum {
- kImportantEnumConstant1 = 0,
- kImportantEnumConstant2 = 1
- } ImportantEnum;
- \end{lstlisting}
- \end{quote}
- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
- \section{Code Formatting}
- In order to have consistent code formating the Google C++ coding style rules shall apply. When using Eclipse as development environment the coding format xml file is available at \url{https://github.com/google/styleguide}. By pressing \verb|<ctrl><shift>f| the formatter will format the code according to these rules.
- \section{Assertions}
- The \lstinline!OPENER_ASSERT(e)! macro is available for traditional
- assertion checks, halting the program if the expression provided as the
- argument \lstinline!e! evaluates false. This macro shall \emph{only} be used
- to test conditions where the only possible cause of failure is an
- unquestionable bug with this program, typically leading to undefined behavior
- or a crash if execution were permitted to continue.
- In other words, an assertion shall \emph{never} fail
- as a result of any external input, valid or invalid,
- or other similar foreseeable condition, such as a memory allocation failure.
- These latter type of failures must be handled by normal code execution paths
- that yield responses with appropriate error codes or possibly
- terminating the program with a non-zero exit code, not an assertion failure.
- The following listing of a function to set an attribute's value based
- on received data is an example to help illustrate proper use of assertions.
- The \lstinline!raw! and \lstinline!len! parameters
- refer to the received data and length, and the \lstinline!foo! parameter
- points to the target attribute; the function returns true only if the attribute
- was set successfully.
- \begin{quote}
- \begin{lstlisting}
- bool SetAttributeFoo(const void *raw, size_t len, CipDint *foo) {
- /*
- * This function should never be called with NULL pointers, regardless of
- * what was received over the network, so assertions should be used to
- * validate the pointer arguments.
- */
- OPENER_ASSERT(NULL != raw);
- OPENER_ASSERT(NULL != foo);
- /*
- * Ensuring enough data was received to satisfy the target data type
- * must not be done with an assertion as a malformed message containing
- * insufficient data shall not halt the program.
- */
- if (sizeof(CipDint) > len) {
- return false;
- }
- CipDint new_value = &(int *)raw;
- /*
- * Here the received value is tested for conformance to acceptable values;
- * assume for the sake of this example that allowable values are nonzero.
- * Validating values received from external sources must not be done
- * with assertions.
- */
- if (0 == new_value) {
- return false;
- }
- *foo = new_value;
- return true;
- }
- \end{lstlisting}
- \end{quote}
- \end{document}
|