Wednesday, February 23, 2022
How I spent my day updating yak shaving
Updates.
That's all I've been doing this week on Belial, the annoying Mac Laptop.
Updates.
So I'm all ready to checkout our source code repositories:
[sconner]belial:~/repo>svn checkout https://www.example.com/path/to/repo -bash: svn: command not found [sconner]belial:~/repo>
Seriously?
I install the developer tools, and Subversion is not installed?
[sconner]belial:~/repo>git usage: git [--version] [--help] [-C <path>] [-c <name>=<value>] [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path] [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare] [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>] <command> [<args>] These are common Git commands used in various situations: start a working area (see also: git help tutorial) clone Clone a repository into a new directory init Create an empty Git repository or reinitialize an existing one work on the current change (see also: git help everyday) add Add file contents to the index mv Move or rename a file, a directory, or a symlink restore Restore working tree files rm Remove files from the working tree and from the index sparse-checkout Initialize and modify the sparse-checkout examine the history and state (see also: git help revisions) bisect Use binary search to find the commit that introduced a bug diff Show changes between commits, commit and working tree, etc grep Print lines matching a pattern log Show commit logs show Show various types of objects status Show the working tree status grow, mark and tweak your common history branch List, create, or delete branches commit Record changes to the repository merge Join two or more development histories together rebase Reapply commits on top of another base tip reset Reset current HEAD to the specified state switch Switch branches tag Create, list, delete or verify a tag object signed with GPG collaborate (see also: git help workflows) fetch Download objects and refs from another repository pull Fetch from and integrate with another repository or a local branch push Update remote refs along with associated objects 'git help -a' and 'git help -g' list available subcommands and some concept guides. See 'git help <command>' or 'git help <concept>' to read about a specific subcommand or concept. See 'git help git' for an overview of the system. [sconner]belial:~/repo>
So you have git
but not Subversion.
Oh! You removed Subversion from the developer tools!
Lovely.
Oh, I can install it with MacPorts? Cool.
belial:~ root# port install subversion -sh: port: command not found belial:~ root#
Oh. Okay. I see. How do I get it installed? Oh, I need to install Xcode and the Xcode command line tools. I just have the command line tools.
Oh, XCode is only available via the Apple Store. I don't have an account to use the Apple Store. I mean, I do, but there's no way in XXXX I'm going to use my private account for work. Let me see if I can compile Subversion from source.
I'll spare you the details—I can't. Subversion requires The Apache Portable Runtime Project and that project can't quite figure out the system and I'm not versed enough (nor paid enough) to debug autoconf tool issues.
When I ask the Corporate Overlords about updates via the Apple Store, I'm told that that particular issue hasn't actually been hashed out yet. Nice to know that Mac users aren't second class citizens in our Corporate Overlords' eyes. I end up creating a new account for use with the annoying Mac laptop and hope any changes to my credit card can get expensed.
Oh, XCode is over 12G in size?
Sigh.
The initial estimated 104 hours to update is actually turning out to be rather accurate.
Of course I'm opinionated—if I wasn't, I would be in a cult
One of the other developers on my team ran part of our code through SonarQube and well … I have issues with its issues with our C code.
Out of the 600+ issues it flagged,
about 500 or so seem to be related to the use of restrict
in the code.
For example (using my own code):
int btm_cmp( struct btm const *restrict d1, /* it doesn't like this */ struct btm const *restrict d2 /* or this */ ) { int rc; assert(d1 != NULL); assert(d2 != NULL); if ((rc = d1->year - d2->year)) return rc; if ((rc = d1->month - d2->month)) return rc; if ((rc = d1->day - d2->day)) return rc; if ((rc = d1->part - d2->part)) return rc; return 0; }
I don't care what MISRA says about it—it signals intent.
That these two pointer parameters to the same type are distinct objects and should not be the same object!
All you have to see is the function prototypes for the standard functions memcpy()
and memmove()
to see this.
memcpy()
is:
extern void *memcpy(void *restrict s1,void const *restrict s2,size_t n);
and thus,
the two memory regions aren't supposed to overlap; for memmove()
:
extern void *memmove(void *s1, void const *s2,size_t n);
the function states the memory regions can overlap. Intent. Geeze.
Of the rest,
I don't agree its arbitrary limit of 20 items in a union.
The union in question describes packet types of a custom protocol,
and I will not split it up just to satisfy some arbitrary limit in the scanning software.
Who came up with goto
labels being all upper case?
No, I don't agree with that as it clashes with over fourty years of C convention where purely uppercase is reserved for constants and macros.
I don't agree with the excessive casts it suggests,
and I don't agree with removing the one cast I do have.
I disagree about the “useless” parentheses around isdigit
because I'm signalling my itent to take the address of the function,
not the macro.
The C99 standard says this (from section 7.1.4):
Any function declared in a header may be additionally implemented as a function-like macro defined in the header, so if a library function is declared explicitly when its header is included, one of the techniques shown below can be used to ensure the declaration is not affected by such a macro. Any macro definition of a function can be suppressed locally by enclosing the name of the function in parentheses, because the name is then not followed by the left parenthesis that indicates expansion of a macro function name. For the same syntactic reason, it is permitted to take the address of a library function even if it is also defined as a macro.
(emphasis added). The code it's complaining about is:
if (!extract_token(tmp,sizeof(tmp),&p,(isdigit))) { /* ... */ }
The various is*()
functions are often defined as macros
(they are on the compilers we use).
I also dislik the “remove useless parentheses” crowd,
if only because the C precedence table is screwed up compared to most other languages.
I'm not going to refactor the code just because some scanner thinks the function is doing too much—it's not. Yes, the function itself might be long, but it's converting a rather complex structure from C to Lua (or Lua back to C). I'm not going to break it up just because. Besides, naming things is one of the two hard problems in Computer Science (the others being cache invalidation and off-by-one errors) and I would have to come up with some name for all the new one-use only functions.
But I'm not going to reject everything it said.
The suggestions such as reducing scope of variables or making some const
are fine.
And there were two bugs found,
but overall,
there was quite a bit of noise to go through.
Hopefully,
I can argue my case for the ones I disagree with.
We shall see.
Get thee behind me, Satan, part II
Woo hoo! I just received the shipping label to return Satan, the useless Windows Laptop!