norme ***** Cette norme a pour but d'uniformiser l'écriture des programmes au sein d'EPITA. Table of Contents ***************** norme Nomination des objets Présentation globale Présentation locale Les headers Les fichiers Interdictions Recommandations Nomination des objets ********************* * Les noms de variables, fonctions, macros, types, fichiers ou répertoires doivent être explicites et en anglais. * Les abréviations sont _tolérées_ dans la mesure où elles permettent de réduire significativement la taille du nom sans en perdre le sens. Les parties des noms composites seront séparées par `_'. #define MAX_LINE_SIZE 256 #define COMMENT_CHAR '#' #define MAX_ANIM_NAME_LENGTH 64 #define MAX_FILE_NAME_LENGTH 1024 * Les noms de variables, de fonctions, fichiers et de répertoires doivent être décrits par l'expression régulière suivante: [a-z][a-z.0-9_]* * Les noms des variables de macros doivent être écrits en majuscules. Leurs arguments ont des noms comme `Ceci', pas comme `CELA', et pas plus `ainsi'. #define XFREE(Var) \ do \ { \ if (Var) \ free(Var); \ } \ while (0) avec les `\' bien alignés par des tabulations (avec M-i dans Emacs). * Les macros ne doivent pas servir à contourner la norme. * Dans le cas de la déclaration d'une structure le nom commencera par `s_', par `t_' pour un alias de type (`typedef'), par `u_' pour une union et `e_' pour une énumération. typedef unsigned char t_cmap[CMAP_NBR_COL * CMAP_SIZE]; typedef unsigned char t_pixel; struct s_picture { int width; int height; t_cmap cmap; t_pixel *picture; }; * Les noms de globales (si elles sont autorisées) commenceront par `gl_'. Présentation globale ******************** * L'indentation sera celle obtenue avec Emacs (avec la configuration dans `/u/a1/.env/.Emacs') int example_align(char *str) { int i; for (i = 0; i < 4; ++i) if (i > 2) return 1; return 0; } * On passe toujours à la ligne après `{', `}' ou une structure de contrôle. On indente une première fois pour les accolades, puis une seconde pour leur contenu. if (cp) return cp; => Incorrect if (cp) {return cp;} => Incorrect if (cp) => Correct { return cp; } if (cp) => Correct { return cp; } * On sautera une ligne entre la déclaration de variable et les instructions. int example_foo(char c) { int i; for (i = 0; i < 42; ++i) ; return i; } * Une ligne ne doit pas excéder 79 caractères. * On fera attention à avoir des fonctions courtes et claires, de 25 lignes maximum (entre les 2 accolades de la fonction, les lignes vides comptent). * Il vous est interdit d'avoir plus de 10 fonctions par fichier dont 5 maximum peuvent être exportées (non déclarées _static_). * Il ne doit pas y avoir de commentaires dans les fonctions. S'il y a besoin de commentaires ils doivent se trouver avant la fonction et être rédigés en anglais. /* ** this function is useless */ void example_foo(void) { return; } * Les commentaires sont commencés et terminés par une ligne seule. Toutes les lignes intermédiaires s'alignent sur elle, et commencent par `**'. /* ** Comment => Correct */ /* * Comment => Incorrect */ * La déclaration d'arguments se fera dans le style ISO/ANSI C. void example_func(struct s_list *p1, struct s_tree *p2) { } et si cela dépasse les 79 colonnes: void example_func(struct s_list *p1, struct s_tree *p2, struct s_double_list *p3) { } en respectant l'alignement par tabulations (avec M-i dans Emacs). * Cas des fonctions ne prenant pas d'argument: void example_foo() => Incorrect { } void example_foo(void) => Correct { } Présentation locale ******************* * Un espace derrière la `,' et derrière le `;', sauf en fin de ligne: void example_foo(struct s_acu *acu) { int i; for (i = 0; i < 255; ++i) { int j; j = i + 2; example_sum(acu, j); } } * Il n'y a pas d'espace entre le nom d'une fonction et la parenthèse. Cependant, il faut toujours un espace entre un mot clé C (avec argument) et la parenthèse. str = xmalloc(sizeof (char) * 256); exit(0); Ceci concerne `for' _etc._ mais aussi `sizeof'. * Le mot-clé `return' ne sera pas suivi de parenthèses. return 1; return str; return; Pour les autres mots-clefs sans argument, il ne faut pas d'espace avant le point-virgule: break; continue; ... * Une fonction doit avoir au plus 4 arguments. * Le symbole de pointeur `*' porte toujours sur la variable (ou fonction), et jamais sur le type: char *cp; => Correct char* cp; => Incorrect * On respectera un alignement par fonction des déclarations avec le nom de la fonction, obtenu avec des tabulations (M-i avec Emacs). char c; struct s_toto *example; * Lors de la déclaration les variables peuvent être initialisées ; à cet effet les appels de fonctions et les expressions composées sont interdites. En outre, une seule déclaration par ligne est autorisée. int titi = strlen("toto"); => Incorrect char c = (str++, *str); => Incorrect unsigned int i, j; => Incorrect unsigned int *toto = &titi; => Correct unsigned int foo = 1; => Correct static int bar = -1; => Correct unsigned int baz; => Correct * Affectations : il doit y avoir un espace entre la variable gauche et le signe d'affectation, de même pour la variable à droite. var1 = var2 var1 += var2 var1 *= var2 * Opérateurs unaires. Pas d'espace. *cp &cp -n * Opérateurs bi/ternaires. Tous les opérateurs binaires et ternaires sont séparés des arguments par un espace de part et d'autre. if (a % 10) return a; return str ? str : DEFAULT_STRING; * Les `#if' et `#ifdef' indentent d'un caractère les directives cpp qui suivent. Les `#else' et `#endif' marquent les conditions dont ils sont issus. #ifndef DEV_BSIZE # ifdef BSIZE # define DEV_BSIZE BSIZE # else /* !BSIZE */ # define DEV_BSIZE 4096 # endif /* !BSIZE */ #endif /* !DEV_BSIZE */ Les headers *********** * La norme dans son intégralité est valide pour les headers. * On les protégera d'une double inclusion. Si le fichier est `foo.h', la macro témoin est `FOO_H_'. #ifndef FOO_H_ # define FOO_H_ /* ** Content of foo.h */ #endif /* !FOO_H_ */ * Les fonctions et variables non exportées sont dites déclarées _static_. * Toutes les fonctions exportées par `foo.c' doivent être correctement prototypées dans un entête inclus par `foo.c'. De même, les variables globales exportées par `foo.c' doivent être déclarées `extern' dans un entête inclus par `foo.c'. * Les headers doivent inclure les autres headers dont ils sont directement dépendants, et aucun autre. Les fichiers ************ * Les fichiers doivent avoir l'entête ci-dessous (obtenu à Epita avec C-c C-h sous Emacs). /* ** for in ** ** Made by ** Login ** ** Started on * Les fichiers ne doivent pas contenir de caractère CR (ASCII 13) en fin de ligne. Interdictions ************* * switch (sauf les switches sur enum). * goto * le cast * les `typedef' sur `struct' et `union'. Recommandations *************** * Il est fortement recommandé de préfixer les noms des fonctions par le nom du fichier dans lequel elles sont définies. * Certaines fonctions de la bibliothèque C peuvent retourner une valeur particulière lorsqu'elles échouent. Le code principal ne doit pas être pollué par le traitement de ces valeurs exceptionnelles, aussi faut-il introduire des versions de ces fonctions qui traitent les erreurs elles-mêmes. Ces fonctions doivent porter le nom de la fonction de la lib C standard, préfixé par "x". void *xmalloc(size_t n) { void *p; p = malloc(n); if (NULL == p) exit(1); return p; }