> You can have 100% MISRA conformant spaghetti.
IMHO some of MISRA rules lead directly to hard to read/maintain code. Consider a function that:
1. opens a file
2. allocates enough memory to store the whole file
3. reads the file
4. return the allocated buffer on success or NULL on failure
You want to write it so it doesn't leak either memory or file handles whether successful or not (if successful ownership of the memory buffer is passed to the caller so it must not be freed in that case).
To be MISRA compliant you'd either end up with a "Christmas tree" of nested scopes or if-statements with extra && in them (pseudo C-code):
char *buf = NULL;
FILE *fh = fopen(...);
if (fh) {
if (success(fseek(fh, end))) {
long int sz = ftell(fh);
if (sz > 0) {
buf = malloc(sz);
if (buf) {
if (failed(fread(fh, buf))) {
report_error();
free(buf);
buf = NULL;
}
} else {
report_error();
}
} else {
report_error();
}
} else {
report_error();
}
fclose(fh);
} else {
report_error();
}
return buf;
However if you were allowed to use goto with a single exit-label the code would be much cleaner and easier to follow:
char *buf = NULL;
char *rv = NULL;
FILE *fh = fopen(...);
if (!fh) {
report_error();
goto exit;
}
if (fail(fseek(fh, end))) {
report_error();
goto exit;
}
long int sz = ftell(fh);
if (sz <= 0) {
report_error();
goto exit;
}
buf = malloc(sz);
if (!buf) {
report_error();
goto exit;
}
if (failed(fread(fh, buf))) {
report_error();
goto exit;
}
rv = buf;
buf = NULL;
exit:
if (fh) {
fclose(fh);
}
if (buf) {
free(buf);
}
return rv;