[net.cse] Documentation within code, i.e., comments

chris@umcp-cs.UUCP (Chris Torek) (03/08/86)

For some time now, I have made a practice of writing first just
the code, then (a few hours or days later) adding comments.  I do
this simply because while I am writing the code, I am `too close'
to the problem: I know every little detail about the routine with
which I am involved.  This is perfect for coding: an algorithm
should be precise; but not for commenting: comments should be
concise.  After the coding fever has abated, I then take a more
rational look at the overall structure of the routines and the
code, and write comments (or, often, revise the code instead).

Of course, the true test of any method is how well it works.  As
to that, I have my own opinion, but I shall let you form your own.
Here is a small part of one routine in a new UDA50 device driver
on which I am now working.  (Keep in mind that this *is* a device
driver, and as such is full of 4BSD-style Unibus idioms, such as
using `um' for the name of pointers to Unibus controller information
data structures.  Such names are automatically familiar to anyone
working on Unibus drivers.  Those that are specific to this device
are all [I hope] explained where they are defined.)

/*
 * Find a slave.  We allow wildcard slave numbers (something autoconf
 * is not really prepared to deal with); and we need to know the
 * controller number to talk to the UDA.  For the latter, we keep
 * track of the last controller probed, since a controller probe
 * immediately precedes all slave probes for that controller.  For the
 * former, we simply put the unit number into ui->ui_slave after we
 * have found one.
 *
 * Note that by the time udaslave is called, the interrupt vector
 * for the UDA50 has been set up (so that udaintr() will be called).
 */
udaslave(ui, reg)
	register struct uba_device *ui;
	caddr_t reg;
{
	register struct uba_ctlr *um = probeum;
	register struct mscp *mp;
	register struct uda_softc *sc;
	int next = 0, type, timeout, tries, i;

#ifdef lint
	i = 0; i = i;
#endif
	/*
	 * Make sure the controller is fully initialised, by waiting
	 * for it if necessary.
	 */
	sc = &uda_softc[um->um_ctlr];
	if (sc->sc_state == S_RUN)
		goto findunit;
	tries = 0;
again:
	if (udainit(ui->ui_ctlr))
		return (0);
	timeout = mfpr(TODR) + 1000;		/* 10 seconds */
	while (mfpr(TODR) < timeout)
		if (sc->sc_state == S_RUN)	/* made it */
			goto findunit;
	if (++tries < 2)
		goto again;
	printf("uda%d: controller hung\n", um->um_ctlr);
	return (0);

	/*
	 * The controller is all set; go find the unit.  Grab an
	 * MSCP packet and send out a Get Unit Status command, with
	 * the `next unit' modifier if we are looking for a generic
	 * unit.  We set the `in slave' flag so that udaintr() knows
	 * to copy the response to `udaonline'.
	 */
findunit:
	udaonline.mscp_opcode = 0;
	sc->sc_flags |= SC_INSLAVE;
	if ((mp = mscp_getcp(&sc->sc_mi, MSCP_DONTWAIT)) == NULL)
		panic("udaslave");		/* `cannot happen' */
	mp->mscp_opcode = M_OP_GETUNITST;
	if (ui->ui_slave == '?') {
		mp->mscp_unit = next;
		mp->mscp_modifier = M_GUM_NEXTUNIT;
	} else {
		mp->mscp_unit = ui->ui_slave;
		mp->mscp_modifier = 0;
	}
	*mp->mscp_seq.seq_addr |= MSCP_OWN | MSCP_INT;
	i = ((struct udadevice *) reg)->udaip;	/* initiate polling */
	mp = &udaonline;
	timeout = mfpr(TODR) + 1000;
	while (mfpr(TODR) < timeout)
		if (mp->mscp_opcode)
			goto gotit;
	printf("uda%d: no response to Get Unit Status request\n",
		um->um_ctlr);
	sc->sc_flags &= ~SC_INSLAVE;
	return (0);

gotit:
	sc->sc_flags &= ~SC_INSLAVE;

[The remainder of the routine processes the response, and may go back
to `findunit' if it needs to find another unit number.]
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1415)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@mimsy.umd.edu