Module Name: src
Committed By: rillig
Date: Sat Nov 28 18:55:52 UTC 2020
Modified Files:
src/usr.bin/make: compat.c cond.c job.c lst.c lst.h main.c make.c
make.h meta.c parse.c suff.c targ.c
Log Message:
make(1): remove pointer indirection from GNode.commands
Just to save a few memory allocations. No noticeable effect on the
performance though.
To generate a diff of this commit:
cvs rdiff -u -r1.192 -r1.193 src/usr.bin/make/compat.c
cvs rdiff -u -r1.217 -r1.218 src/usr.bin/make/cond.c
cvs rdiff -u -r1.331 -r1.332 src/usr.bin/make/job.c
cvs rdiff -u -r1.94 -r1.95 src/usr.bin/make/lst.c
cvs rdiff -u -r1.87 -r1.88 src/usr.bin/make/lst.h
cvs rdiff -u -r1.482 -r1.483 src/usr.bin/make/main.c
cvs rdiff -u -r1.218 -r1.219 src/usr.bin/make/make.c
cvs rdiff -u -r1.220 -r1.221 src/usr.bin/make/make.h
cvs rdiff -u -r1.152 -r1.153 src/usr.bin/make/meta.c
cvs rdiff -u -r1.453 -r1.454 src/usr.bin/make/parse.c
cvs rdiff -u -r1.308 -r1.309 src/usr.bin/make/suff.c
cvs rdiff -u -r1.141 -r1.142 src/usr.bin/make/targ.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/usr.bin/make/compat.c
diff -u src/usr.bin/make/compat.c:1.192 src/usr.bin/make/compat.c:1.193
--- src/usr.bin/make/compat.c:1.192 Tue Nov 24 19:04:42 2020
+++ src/usr.bin/make/compat.c Sat Nov 28 18:55:52 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: compat.c,v 1.192 2020/11/24 19:04:42 rillig Exp $ */
+/* $NetBSD: compat.c,v 1.193 2020/11/28 18:55:52 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -96,7 +96,7 @@
#include "pathnames.h"
/* "@(#)compat.c 8.2 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: compat.c,v 1.192 2020/11/24 19:04:42 rillig Exp $");
+MAKE_RCSID("$NetBSD: compat.c,v 1.193 2020/11/28 18:55:52 rillig Exp $");
static GNode *curTarg = NULL;
static pid_t compatChild;
@@ -218,7 +218,7 @@ Compat_RunCommand(const char *cmdp, GNod
* for delayed commands, run in parallel mode, using the same shell
* command line more than once; see JobPrintCommand.
* TODO: write a unit-test to protect against this potential bug. */
- cmdNode = Lst_FindDatum(gn->commands, cmd);
+ cmdNode = Lst_FindDatum(&gn->commands, cmd);
(void)Var_Subst(cmd, gn, VARE_WANTRES, &cmdStart);
/* TODO: handle errors */
@@ -232,7 +232,7 @@ Compat_RunCommand(const char *cmdp, GNod
if (gn->type & OP_SAVE_CMDS) {
GNode *endNode = Targ_GetEndNode();
if (gn != endNode) {
- Lst_Append(endNode->commands, cmdStart);
+ Lst_Append(&endNode->commands, cmdStart);
return 0;
}
}
@@ -449,7 +449,7 @@ RunCommands(GNode *gn)
{
StringListNode *ln;
- for (ln = gn->commands->first; ln != NULL; ln = ln->next) {
+ for (ln = gn->commands.first; ln != NULL; ln = ln->next) {
const char *cmd = ln->datum;
if (Compat_RunCommand(cmd, gn) != 0)
break;
Index: src/usr.bin/make/cond.c
diff -u src/usr.bin/make/cond.c:1.217 src/usr.bin/make/cond.c:1.218
--- src/usr.bin/make/cond.c:1.217 Mon Nov 23 20:52:59 2020
+++ src/usr.bin/make/cond.c Sat Nov 28 18:55:52 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: cond.c,v 1.217 2020/11/23 20:52:59 rillig Exp $ */
+/* $NetBSD: cond.c,v 1.218 2020/11/28 18:55:52 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -94,7 +94,7 @@
#include "dir.h"
/* "@(#)cond.c 8.2 (Berkeley) 1/2/94" */
-MAKE_RCSID("$NetBSD: cond.c,v 1.217 2020/11/23 20:52:59 rillig Exp $");
+MAKE_RCSID("$NetBSD: cond.c,v 1.218 2020/11/28 18:55:52 rillig Exp $");
/*
* The parsing of conditional expressions is based on this grammar:
@@ -335,7 +335,7 @@ static Boolean
FuncCommands(size_t argLen MAKE_ATTR_UNUSED, const char *arg)
{
GNode *gn = Targ_FindNode(arg);
- return gn != NULL && GNode_IsTarget(gn) && !Lst_IsEmpty(gn->commands);
+ return gn != NULL && GNode_IsTarget(gn) && !Lst_IsEmpty(&gn->commands);
}
/*
Index: src/usr.bin/make/job.c
diff -u src/usr.bin/make/job.c:1.331 src/usr.bin/make/job.c:1.332
--- src/usr.bin/make/job.c:1.331 Sat Nov 28 08:40:05 2020
+++ src/usr.bin/make/job.c Sat Nov 28 18:55:52 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: job.c,v 1.331 2020/11/28 08:40:05 rillig Exp $ */
+/* $NetBSD: job.c,v 1.332 2020/11/28 18:55:52 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -143,7 +143,7 @@
#include "trace.h"
/* "@(#)job.c 8.2 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: job.c,v 1.331 2020/11/28 08:40:05 rillig Exp $");
+MAKE_RCSID("$NetBSD: job.c,v 1.332 2020/11/28 18:55:52 rillig Exp $");
/* A shell defines how the commands are run. All commands for a target are
* written into a single file, which is then given to the shell to execute
@@ -902,7 +902,7 @@ JobPrintCommands(Job *job)
{
StringListNode *ln;
- for (ln = job->node->commands->first; ln != NULL; ln = ln->next) {
+ for (ln = job->node->commands.first; ln != NULL; ln = ln->next) {
const char *cmd = ln->datum;
if (strcmp(cmd, "...") == 0) {
@@ -929,7 +929,7 @@ JobSaveCommands(Job *job)
* expand the other variables as well; see deptgt-end.mk. */
(void)Var_Subst(cmd, job->node, VARE_WANTRES, &expanded_cmd);
/* TODO: handle errors */
- Lst_Append(Targ_GetEndNode()->commands, expanded_cmd);
+ Lst_Append(&Targ_GetEndNode()->commands, expanded_cmd);
}
}
@@ -1175,7 +1175,7 @@ Job_CheckCommands(GNode *gn, void (*abor
{
if (GNode_IsTarget(gn))
return TRUE;
- if (!Lst_IsEmpty(gn->commands))
+ if (!Lst_IsEmpty(&gn->commands))
return TRUE;
if ((gn->type & OP_LIB) && !Lst_IsEmpty(gn->children))
return TRUE;
@@ -1184,7 +1184,7 @@ Job_CheckCommands(GNode *gn, void (*abor
* No commands. Look for .DEFAULT rule from which we might infer
* commands.
*/
- if (defaultNode != NULL && !Lst_IsEmpty(defaultNode->commands) &&
+ if (defaultNode != NULL && !Lst_IsEmpty(&defaultNode->commands) &&
!(gn->type & OP_SPECIAL)) {
/*
* The traditional Make only looks for a .DEFAULT if the node was
@@ -2451,7 +2451,7 @@ int
Job_Finish(void)
{
GNode *endNode = Targ_GetEndNode();
- if (!Lst_IsEmpty(endNode->commands) || !Lst_IsEmpty(endNode->children)) {
+ if (!Lst_IsEmpty(&endNode->commands) || !Lst_IsEmpty(endNode->children)) {
if (job_errors != 0) {
Error("Errors reported so .END ignored");
} else {
Index: src/usr.bin/make/lst.c
diff -u src/usr.bin/make/lst.c:1.94 src/usr.bin/make/lst.c:1.95
--- src/usr.bin/make/lst.c:1.94 Fri Nov 27 08:07:26 2020
+++ src/usr.bin/make/lst.c Sat Nov 28 18:55:52 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: lst.c,v 1.94 2020/11/27 08:07:26 rillig Exp $ */
+/* $NetBSD: lst.c,v 1.95 2020/11/28 18:55:52 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -34,7 +34,7 @@
#include "make.h"
-MAKE_RCSID("$NetBSD: lst.c,v 1.94 2020/11/27 08:07:26 rillig Exp $");
+MAKE_RCSID("$NetBSD: lst.c,v 1.95 2020/11/28 18:55:52 rillig Exp $");
static ListNode *
LstNodeNew(ListNode *prev, ListNode *next, void *datum)
@@ -53,16 +53,12 @@ List *
Lst_New(void)
{
List *list = bmake_malloc(sizeof *list);
-
- list->first = NULL;
- list->last = NULL;
-
+ Lst_Init(list);
return list;
}
-/* Free a list and all its nodes. The node data are not freed though. */
void
-Lst_Free(List *list)
+Lst_Done(List *list)
{
ListNode *ln, *next;
@@ -70,7 +66,14 @@ Lst_Free(List *list)
next = ln->next;
free(ln);
}
+}
+
+/* Free a list and all its nodes. The node data are not freed though. */
+void
+Lst_Free(List *list)
+{
+ Lst_Done(list);
free(list);
}
Index: src/usr.bin/make/lst.h
diff -u src/usr.bin/make/lst.h:1.87 src/usr.bin/make/lst.h:1.88
--- src/usr.bin/make/lst.h:1.87 Fri Nov 27 08:07:26 2020
+++ src/usr.bin/make/lst.h Sat Nov 28 18:55:52 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: lst.h,v 1.87 2020/11/27 08:07:26 rillig Exp $ */
+/* $NetBSD: lst.h,v 1.88 2020/11/28 18:55:52 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -109,11 +109,21 @@ typedef void LstFreeProc(void *);
/* Create a new list. */
List *Lst_New(void);
+/* Free the list nodes, but not the list itself. */
+void Lst_Done(List *);
/* Free the list, leaving the node data unmodified. */
void Lst_Free(List *);
/* Free the list, freeing the node data using the given function. */
void Lst_Destroy(List *, LstFreeProc);
+/* Initialize a list, without memory allocation. */
+MAKE_INLINE void
+Lst_Init(List *list)
+{
+ list->first = NULL;
+ list->last = NULL;
+}
+
/* Get information about a list */
MAKE_INLINE Boolean
Index: src/usr.bin/make/main.c
diff -u src/usr.bin/make/main.c:1.482 src/usr.bin/make/main.c:1.483
--- src/usr.bin/make/main.c:1.482 Sat Nov 28 10:00:25 2020
+++ src/usr.bin/make/main.c Sat Nov 28 18:55:52 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: main.c,v 1.482 2020/11/28 10:00:25 rillig Exp $ */
+/* $NetBSD: main.c,v 1.483 2020/11/28 18:55:52 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -109,7 +109,7 @@
#include "trace.h"
/* "@(#)main.c 8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: main.c,v 1.482 2020/11/28 10:00:25 rillig Exp $");
+MAKE_RCSID("$NetBSD: main.c,v 1.483 2020/11/28 18:55:52 rillig Exp $");
#if defined(MAKE_NATIVE) && !defined(lint)
__COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 "
"The Regents of the University of California. "
@@ -2093,7 +2093,7 @@ SetErrorVars(GNode *gn)
Var_Set(".ERROR_TARGET", gn->name, VAR_GLOBAL);
Var_Delete(".ERROR_CMD", VAR_GLOBAL);
- for (ln = gn->commands->first; ln != NULL; ln = ln->next) {
+ for (ln = gn->commands.first; ln != NULL; ln = ln->next) {
const char *cmd = ln->datum;
if (cmd == NULL)
Index: src/usr.bin/make/make.c
diff -u src/usr.bin/make/make.c:1.218 src/usr.bin/make/make.c:1.219
--- src/usr.bin/make/make.c:1.218 Fri Nov 27 08:07:26 2020
+++ src/usr.bin/make/make.c Sat Nov 28 18:55:52 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: make.c,v 1.218 2020/11/27 08:07:26 rillig Exp $ */
+/* $NetBSD: make.c,v 1.219 2020/11/28 18:55:52 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -102,7 +102,7 @@
#include "job.h"
/* "@(#)make.c 8.1 (Berkeley) 6/6/93" */
-MAKE_RCSID("$NetBSD: make.c,v 1.218 2020/11/27 08:07:26 rillig Exp $");
+MAKE_RCSID("$NetBSD: make.c,v 1.219 2020/11/28 18:55:52 rillig Exp $");
/* Sequence # to detect recursion. */
static unsigned int checked_seqno = 1;
@@ -376,13 +376,13 @@ Make_HandleUse(GNode *cgn, GNode *pgn)
}
#endif
- if ((cgn->type & (OP_USE | OP_USEBEFORE)) || Lst_IsEmpty(pgn->commands)) {
+ if ((cgn->type & (OP_USE | OP_USEBEFORE)) || Lst_IsEmpty(&pgn->commands)) {
if (cgn->type & OP_USEBEFORE) {
/* .USEBEFORE */
- Lst_PrependAll(pgn->commands, cgn->commands);
+ Lst_PrependAll(&pgn->commands, &cgn->commands);
} else {
/* .USE, or target has no commands */
- Lst_AppendAll(pgn->commands, cgn->commands);
+ Lst_AppendAll(&pgn->commands, &cgn->commands);
}
}
Index: src/usr.bin/make/make.h
diff -u src/usr.bin/make/make.h:1.220 src/usr.bin/make/make.h:1.221
--- src/usr.bin/make/make.h:1.220 Sat Nov 28 09:45:01 2020
+++ src/usr.bin/make/make.h Sat Nov 28 18:55:52 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: make.h,v 1.220 2020/11/28 09:45:01 rillig Exp $ */
+/* $NetBSD: make.h,v 1.221 2020/11/28 18:55:52 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -421,7 +421,7 @@ typedef struct GNode {
HashTable /* of Var pointer */ vars;
/* The commands to be given to a shell to create this target. */
- StringList *commands;
+ StringList commands;
/* Suffix for the node (determined by Suff_FindDeps and opaque to
* everyone but the Suff module) */
Index: src/usr.bin/make/meta.c
diff -u src/usr.bin/make/meta.c:1.152 src/usr.bin/make/meta.c:1.153
--- src/usr.bin/make/meta.c:1.152 Sat Nov 28 10:28:53 2020
+++ src/usr.bin/make/meta.c Sat Nov 28 18:55:52 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: meta.c,v 1.152 2020/11/28 10:28:53 rillig Exp $ */
+/* $NetBSD: meta.c,v 1.153 2020/11/28 18:55:52 rillig Exp $ */
/*
* Implement 'meta' mode.
@@ -364,7 +364,7 @@ any_is_submake(GNode *gn)
{
StringListNode *ln;
- for (ln = gn->commands->first; ln != NULL; ln = ln->next)
+ for (ln = gn->commands.first; ln != NULL; ln = ln->next)
if (is_submake(ln->datum, gn))
return TRUE;
return FALSE;
@@ -389,7 +389,7 @@ printCMDs(GNode *gn, FILE *fp)
{
GNodeListNode *ln;
- for (ln = gn->commands->first; ln != NULL; ln = ln->next)
+ for (ln = gn->commands.first; ln != NULL; ln = ln->next)
printCMD(ln->datum, fp, gn);
}
@@ -431,7 +431,7 @@ meta_needed(GNode *gn, const char *dname
}
/* Check if there are no commands to execute. */
- if (Lst_IsEmpty(gn->commands)) {
+ if (Lst_IsEmpty(&gn->commands)) {
if (verbose)
debug_printf("Skipping meta for %s: no commands\n", gn->name);
return FALSE;
@@ -1156,7 +1156,7 @@ meta_oodate(GNode *gn, Boolean oodate)
/* we want to track all the .meta we read */
Var_Append(".MAKE.META.FILES", fname, VAR_GLOBAL);
- cmdNode = gn->commands->first;
+ cmdNode = gn->commands.first;
while (!oodate && (x = fgetLine(&buf, &bufsz, 0, fp)) > 0) {
lineno++;
if (buf[x - 1] == '\n')
Index: src/usr.bin/make/parse.c
diff -u src/usr.bin/make/parse.c:1.453 src/usr.bin/make/parse.c:1.454
--- src/usr.bin/make/parse.c:1.453 Sat Nov 28 16:34:13 2020
+++ src/usr.bin/make/parse.c Sat Nov 28 18:55:52 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: parse.c,v 1.453 2020/11/28 16:34:13 rillig Exp $ */
+/* $NetBSD: parse.c,v 1.454 2020/11/28 18:55:52 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -117,7 +117,7 @@
#include "pathnames.h"
/* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: parse.c,v 1.453 2020/11/28 16:34:13 rillig Exp $");
+MAKE_RCSID("$NetBSD: parse.c,v 1.454 2020/11/28 18:55:52 rillig Exp $");
/* types and constants */
@@ -2060,7 +2060,7 @@ ParseAddCmd(GNode *gn, char *cmd)
/* if target already supplied, ignore commands */
if (!(gn->type & OP_HAS_COMMANDS)) {
- Lst_Append(gn->commands, cmd);
+ Lst_Append(&gn->commands, cmd);
if (MaybeSubMake(cmd))
gn->type |= OP_SUBMAKE;
ParseMark(gn);
@@ -2832,7 +2832,7 @@ FinishDependencyGroup(void)
/* Mark the target as already having commands if it does, to
* keep from having shell commands on multiple dependency lines. */
- if (!Lst_IsEmpty(gn->commands))
+ if (!Lst_IsEmpty(&gn->commands))
gn->type |= OP_HAS_COMMANDS;
}
Index: src/usr.bin/make/suff.c
diff -u src/usr.bin/make/suff.c:1.308 src/usr.bin/make/suff.c:1.309
--- src/usr.bin/make/suff.c:1.308 Mon Nov 23 20:41:20 2020
+++ src/usr.bin/make/suff.c Sat Nov 28 18:55:52 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: suff.c,v 1.308 2020/11/23 20:41:20 rillig Exp $ */
+/* $NetBSD: suff.c,v 1.309 2020/11/28 18:55:52 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -114,7 +114,7 @@
#include "dir.h"
/* "@(#)suff.c 8.4 (Berkeley) 3/21/94" */
-MAKE_RCSID("$NetBSD: suff.c,v 1.308 2020/11/23 20:41:20 rillig Exp $");
+MAKE_RCSID("$NetBSD: suff.c,v 1.309 2020/11/28 18:55:52 rillig Exp $");
#define SUFF_DEBUG0(text) DEBUG0(SUFF, text)
#define SUFF_DEBUG1(fmt, arg1) DEBUG1(SUFF, fmt, arg1)
@@ -568,9 +568,9 @@ Suff_AddTransform(const char *name)
* free the commands themselves, because a given command can be
* attached to several different transformations.
*/
- Lst_Free(gn->commands);
+ Lst_Done(&gn->commands);
Lst_Free(gn->children);
- gn->commands = Lst_New();
+ Lst_Init(&gn->commands);
gn->children = Lst_New();
}
@@ -613,7 +613,7 @@ Suff_EndTransform(GNode *gn)
if (!(gn->type & OP_TRANSFORM))
return;
- if (!Lst_IsEmpty(gn->commands) || !Lst_IsEmpty(gn->children)) {
+ if (!Lst_IsEmpty(&gn->commands) || !Lst_IsEmpty(gn->children)) {
SUFF_DEBUG1("transformation %s complete\n", gn->name);
return;
}
@@ -1128,7 +1128,7 @@ FindCmds(Candidate *targ, CandidateSearc
for (gln = tgn->children->first; gln != NULL; gln = gln->next) {
sgn = gln->datum;
- if (sgn->type & OP_OPTIONAL && Lst_IsEmpty(tgn->commands)) {
+ if (sgn->type & OP_OPTIONAL && Lst_IsEmpty(&tgn->commands)) {
/*
* We haven't looked to see if .OPTIONAL files exist yet, so
* don't use one as the implicit source.
@@ -1701,7 +1701,7 @@ FindDepsRegularUnknown(GNode *gn, const
* not define suffix rules if the gnode had children but we
* don't do this anymore.
*/
- if (Lst_IsEmpty(gn->commands))
+ if (Lst_IsEmpty(&gn->commands))
CandidateList_AddCandidatesFor(srcs, targ);
else {
SUFF_DEBUG0("not ");
Index: src/usr.bin/make/targ.c
diff -u src/usr.bin/make/targ.c:1.141 src/usr.bin/make/targ.c:1.142
--- src/usr.bin/make/targ.c:1.141 Mon Nov 23 23:41:11 2020
+++ src/usr.bin/make/targ.c Sat Nov 28 18:55:52 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: targ.c,v 1.141 2020/11/23 23:41:11 rillig Exp $ */
+/* $NetBSD: targ.c,v 1.142 2020/11/28 18:55:52 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -119,7 +119,7 @@
#include "dir.h"
/* "@(#)targ.c 8.2 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: targ.c,v 1.141 2020/11/23 23:41:11 rillig Exp $");
+MAKE_RCSID("$NetBSD: targ.c,v 1.142 2020/11/28 18:55:52 rillig Exp $");
/*
* All target nodes that appeared on the left-hand side of one of the
@@ -212,7 +212,7 @@ GNode_New(const char *name)
gn->centurion = NULL;
gn->checked_seqno = 0;
HashTable_Init(&gn->vars);
- gn->commands = Lst_New();
+ Lst_Init(&gn->commands);
gn->suffix = NULL;
gn->fname = NULL;
gn->lineno = 0;
@@ -243,7 +243,7 @@ GNode_Free(void *gnp)
HashTable_Done(&gn->vars); /* Do not free the variables themselves,
* even though they are owned by this node.
* XXX: they should probably be freed. */
- Lst_Free(gn->commands); /* Do not free the commands themselves,
+ Lst_Done(&gn->commands); /* Do not free the commands themselves,
* as they may be shared with other nodes. */
/* gn->suffix is not owned by this node. */
/* XXX: gn->suffix should be unreferenced here. This requires a thorough
@@ -384,7 +384,7 @@ void
Targ_PrintCmds(GNode *gn)
{
StringListNode *ln;
- for (ln = gn->commands->first; ln != NULL; ln = ln->next) {
+ for (ln = gn->commands.first; ln != NULL; ln = ln->next) {
const char *cmd = ln->datum;
debug_printf("\t%s\n", cmd);
}