My main.c
includes this header file. Please let me know how I can improve it. I did my best but I don't know much about code conventions in C (I come from Java and Python).
#define _XOPEN_SOURCE 500
#ifndef OPENSHELL_OPENSHELL_H
#define OPENSHELL_OPENSHELL_H
#define CMD_LEN 1024
#define EXPAND_ALLOC 1024
#define PATH_LEN 1024
#define isBlank(ch) (((ch) == ' ') || ((ch) == '\t'))
#define isDecimal(ch) (((ch) >= '0') && ((ch) <= '9'))
#define MAX_SOURCE 10
#define isWildCard(ch) (((ch) == '*') || ((ch) == '?') || ((ch) == '['))
#define CHUNK_INIT_SIZE 4
#define DEBUG TRUE
#ifndef VERSION
#define VERSION2 "v0.1a"
#endif
#include <string.h>
#include <dirent.h>
#include <utime.h>
#include <stdbool.h>
#include <getopt.h>
/*
* A chunk of data.
* Chunks contain data which is allocated as needed, but which is
* not freed until all of the data needs freeing, such as at
* the beginning of the next command.
*/
typedef struct chunk CHUNK;
struct chunk {
CHUNK *next;
char data[CHUNK_INIT_SIZE]; /* actually of varying length */
};
/*
* One entry of the command table.
*/
typedef struct {
const char *name;
int (*func)(int argc, const char **argv);
int minArgs;
int maxArgs;
const char *description;
const char *usage;
} CommandEntry;
typedef int Pipe[2];
static struct option options[] = {
{"with_param", 1, 0, 'p'},
{"version", 0, 0, 'v'},
{"help", 0, 0, 'h'},
{0, 0, 0, 0}
};
struct command {
char *const *argv;
};
extern void freeChunks(void);
extern char **str_split(char *a[], char *a_str, const char a_delim);
extern int do_checkenv(int argc, const char **argv);
extern int do_cd(int argc, const char **argv);
extern int do_add2path(int argc, const char **argv);
extern int do_exit(int argc, const char **argv);
extern int do_help(int argc, const char **argv);
extern int do_kill(int argc, const char **argv);
int spawn_proc(int in, int out, struct command *cmd);
void fork_pipes(int n, struct command *cmd);
int file_exist(char *filename);
extern bool makeArgs(const char *cmd, int *argcPtr, const char ***argvPtr, bool pipe, int g, int h);
#endif
#define VERSION "v0.160429-21-g54bb-dirty"
The above file is versioned at github. You can also review the project's Makefile
:
CC = gcc
GIT_VERSION := $(shell git describe --abbrev=4 --dirty --always --tags)
CFLAGS := $(CFLAGS) -L/usr/local/include/ -L/usr/include -pedantic -std=c99 -Wall -O3 -g -DVERSION=\"$(GIT_VERSION)\" -ledit -lncurses
LDIRS = -L/usr/local/lib -L/usr/lib
LIBS =su -lcurses
shell: main.o
$(CC) -o shell main.o errors.c util.c pipeline.c -ledit -lncurses -lcurses
main.o: main.c errors.c util.c
USERNAME := $(shell whoami >> username.txt)
GIT:= $(shell head -n -1 openshell.h > temp.txt ; mv temp.txt openshell.h;git describe --abbrev=4 --dirty --always --tags > VERSION; echo "\#define VERSION \"$(GIT_VERSION)\"" >> openshell.h)
.PHONY: clean
clean:
rm -f *.o
As seen in the Makefile
, I'm writing the git version number to the header file with a shell instruction. Maybe I should do this before I compile to be able to get a "clean" version, otherwise I will always differ from a tag just by writing the new tag.
1 Answer 1
What is the header file's name? The point being that the name of the header file, like
xopen.h
should have some connection to the items inside. Further, the objects declares and macros defines are all over the name space. Consider some convention. Putdo_...()
indo.h
,CommandEntry
inCommandEntry.h
.Strange
#define
. Did you mean#define VERSION "v0.1a"
?#ifndef VERSION //#define VERSION2 "v0.1a" #define VERSION "v0.1a" #endif
static struct option options[]
will create aoptions[]
with each *.c this include file is used. Certainly not a good idea because it isstatic
. `static objects are best for the *.c file and not *.h header files.Odd to have
#define _XOPEN_SOURCE 500
and#define VERSION "v0.160429-21-g54bb-dirty"
outside the include guard#ifndef OPENSHELL_OPENSHELL_H
. Suggest putting them inside unless you are attempting something novel.Line spacing is odd. Why no line space after a
struct
definition, yet spaces between similar function declarations.struct command { char *const *argv; }; extern void freeChunks(void); extern char **str_split(char *a[], char *a_str, const char a_delim); extern int do_checkenv(int argc, const char **argv);
The horizontal space is odd here - perhaps an effect of using tabs?
#define CMD_LEN 1024 #define EXPAND_ALLOC 1024 #define PATH_LEN 1024 #define isBlank(ch) (((ch) == ' ') || ((ch) == '\t')) #define isDecimal(ch) (((ch) >= '0') && ((ch) <= '9')) #define MAX_SOURCE 10
All UPPERCASE identifiers are often considered macros. Code with
CHUNK
may confuse viewers of your code. Re:typedef struct chunk CHUNK;
Not using all UPPERCASE for defines like with
#define isBlank(ch)
is a problem as a user of that macro does not benefit from the all uppercase hint that it is a macro. That macro usesch
twice(((ch) == ' ') || ((ch) == '\t'))
. Consider the effect of this usageint ch; while (isBlank(ch = getchar())) { ... }
Standard suggestion. Add name and date (year) to your code.
// 2016 Programmer 400
C has a boolean
_Bool
. By using<stdbool.h>
, code has access tobool
,true
,false
. Suggesttrue
rather thanTRUE
in#define DEBUG TRUE
.Order: In general, it is cleaner to do the
define
first,struct, union, typedef
, then global variables and lastly function declaration. This is highly a style issue though.Unclear why some function have a preceding
extern
and others do not. With function declarations,extern
is not necessary. To use or not is a style issue, but it should certainly be consistent within a *.h file.// to extern or not to extern, that is the question. extern int do_kill(int argc, const char **argv); int spawn_proc(int in, int out, struct command *cmd);
-
\$\begingroup\$ Nice answer with lots of possibility for me to improve. Thank you! The name of the header file is
openshell.h
and it is my first non-trivial header file. \$\endgroup\$Niklas Rosencrantz– Niklas Rosencrantz2016年04月30日 00:37:09 +00:00Commented Apr 30, 2016 at 0:37 -
1\$\begingroup\$ @Programmer 400 Welcome to C - programing without a net nor training wheels. \$\endgroup\$chux– chux2016年04月30日 01:25:38 +00:00Commented Apr 30, 2016 at 1:25