Warning! This site is under development.
Approximate overview
TPS
https://gankra.github.io/blah/c-isnt-a-language/
Who is the audience?
What are the main points of the article (and, perhaps, any related articles you read)?
Point one: ABIs
Once upon a time, thoughtful/forward-looking designers could have dealt with this. Now so much is ingrained that it’s too late to fix things. We are screwed.
In the end, most language designers end up relying on a hidden C/C++ backend because (a) parsing C sucks and (b) C is used everywhere and (c) every architecture/C compiler pair may make different decisions on ABI issues (and there are 176 or so “common” pairs/triplets).
You can’t make big changes because (a) there’s too much legacy code out there that you can’t break; (b) programmers are slow to update.
So …
No matter what you have to do, at some time you have to understand some C.
TPS
What is command-line processing?
What common flags do you know about? (Are there any common flags?)
-o and a file name, which may represent an output file
foo -ooutput.txt ; short, no spacefoo -o output.txt ; short, with a spacefoo --output output.txt ; verbose, preferred by non-C folks-a (for “all”, in GitHub, ls, perhaps more)-l (for “list”, if that makes sense in context)-r (for “recursive”, e.g., on directories)-f (for “force”)-v (for “version” or “verbose”)-h (for “help”)-g (for “guess this means something”)Conclusion: Unix sucks for standardized UI design.
What complications do you anticipate in parsing the command line?
foo -t "a\nb"tar -xvfDo it by hand (using argc and argv)!
Task: Write a program that has
-v, for verbose mode.-o FILE, for an output file. (If there is no
input file, writes to standard output.)-c CHARS, for a number of characters. (If -c is not
specified, use 1.)-h, which prints out a help message and stops.Your program should then read all the other files specified on the command line and print the first CHARS characters of each file to the specified output file (or standard output, if it exists).
Normal program template
#include <stdio.h>
#include <stdlib.h>
int
main (int argc, char *argv[])
{
exit (EXIT_SUCCESS);
} // main
Declare setting variables and set defaults
int chars = 1;
char *outfile = 0;
int verbose = 0;
Validate argc
if (argc < 2)
{
fprintf (stderr, "You idiot! I need more command-line arguments.\n");
help (argv[0]);
exit (EXIT_FAILURE);
}
Read the command line
for (int i = 1; i < argc; i++)
{
if (argv[i][0] == '-')
{
// Optional : Validate number of characters in flag
// Make a decision based on the character
switch (argv[i][1])
{
case 'v': // Verbose
verbose = 1;
break;
case 'c':
chars = atoi (argv[++i]); // EEECH!
// Todo: Add a sanity check that ++i is okay
// Todo: Make sure that argv[++i] is only digits
break;
default:
fprintf ("Thank you for that helpful parameter which I do not understand, '%s'\n", argv[i]);
help (argv[0]);
exit (EXIT_FAILURE);
} // switch
} // if
else
{
// We've run out of arguments, break out of the loop
// Or skip over them
// Or ...
} // else
} // for
Question: What if we wanted to support -c 5 and -c5?
case 'c':
if (argv[i][2] == 0)
{
chars = atoi (argv[++i]);
}
else
{
chars = atoi (argv[i] + 2);
}
break;
argc
and argv in C) andgetopt is the primary library and getopt_long is an extended
version of it.Here’s the declaration of getopt
int getopt(int argc, char * const argv[],
const char *optstring);
extern char *optarg;
extern int optind, opterr, optopt;
What’s going on here?
getopt programStolen from the getopt man page.
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int
main (int argc, char *argv[])
{
int flags, opt;
int nsecs, tfnd;
nsecs = 0;
tfnd = 0;
flags = 0;
while ((opt = getopt (argc, argv, "nt:")) != -1)
{
switch (opt)
{
case 'n':
flags = 1;
break;
case 't':
nsecs = atoi (optarg);
tfnd = 1;
break;
default: /* '?' */
fprintf (stderr, "Usage: %s [-t nsecs] [-n] name\n",
argv[0]);
exit (EXIT_FAILURE);
} // switch
} // while
printf ("flags=%d; tfnd=%d; nsecs=%d; optind=%d\n",
flags, tfnd, nsecs, optind);
if (optind >= argc)
{
fprintf (stderr, "Expected argument after options\n");
exit (EXIT_FAILURE);
}
exit (EXIT_SUCCESS);
} // main