Output #line directives as part of nuweb tangling.

This makes error location easier.
This commit is contained in:
2024-03-15 08:31:10 +00:00
parent d8f33c3ce4
commit 1dcf5ae370

172
nuweb.w
View File

@@ -822,7 +822,7 @@ Processing a web requires three major steps:
I have divided the program into several files for quicker
recompilation during development.
@o global.h -cc
@o global.h -cc -d
@{@<Include files@>
@<Type declarations@>
@<Limits@>
@@ -874,14 +874,14 @@ The code is divided into four main files (introduced here) and five
support files (introduced in the next section).
The file \verb|main.c| will contain the driver for the whole program
(see Section~\ref{main-routine}).
@o main.c -cc
@o main.c -cc -d
@{#include "global.h"
@}
The first pass over the source file is contained in \verb|pass1.c|.
It handles collection of all the file names, fragments names, and scraps
(see Section~\ref{pass-one}).
@o pass1.c -cc
@o pass1.c -cc -d
@{#include "global.h"
@}
@@ -889,7 +889,7 @@ The \verb|.tex| file is created during a second pass over the source
file. The file \verb|latex.c| contains the code controlling the
construction of the \verb|.tex| file
(see Section~\ref{latex-file}).
@o latex.c -cc
@o latex.c -cc -d
@{#include "global.h"
static int scraps = 1;
@}
@@ -904,7 +904,7 @@ static int scraps = 1;
The code controlling the creation of the output files is in \verb|output.c|
(see Section~\ref{output-files}).
@o output.c -cc
@o output.c -cc -d
@{#include "global.h"
@}
@@ -915,32 +915,32 @@ The support files contain a variety of support routines used to define
and manipulate the major data abstractions.
The file \verb|input.c| holds all the routines used for referring to
source files (see Section~\ref{source-files}).
@o input.c -cc
@o input.c -cc -d
@{#include "global.h"
@}
Creation and lookup of scraps is handled by routines in \verb|scraps.c|
(see Section~\ref{scraps}).
@o scraps.c -cc
@o scraps.c -cc -d
@{#include "global.h"
@}
The handling of file names and fragment names is detailed in \verb|names.c|
(see Section~\ref{names}).
@o names.c -cc
@o names.c -cc -d
@{#include "global.h"
@}
Memory allocation and deallocation is handled by routines in \verb|arena.c|
(see Section~\ref{memory-management}).
@o arena.c -cc
@o arena.c -cc -d
@{#include "global.h"
@}
Finally, for best portability, I seem to need a file containing
(useless!) definitions of all the global variables.
@o global.c -cc
@o global.c -cc -d
@{#include "global.h"
@<Operating System Dependencies@>
@<Global variable definitions@>
@@ -951,7 +951,7 @@ Finally, for best portability, I seem to need a file containing
The main routine is quite simple in structure.
It wades through the optional command-line arguments,
then handles any files listed on the command line.
@o main.c -cc
@o main.c -cc -d
@{
#include <stdlib.h>
int main(argc, argv)
@@ -1412,7 +1412,7 @@ necessary preparation, we make a pass over the file, filling in all
our data structures. Next, we seach all the scraps for references to
the user-specified index entries. Finally, we must reverse all the
cross-reference lists accumulated while scanning the scraps.
@o pass1.c -cc
@o pass1.c -cc -d
@{void pass1(file_name)
char *file_name;
{
@@ -1814,7 +1814,7 @@ Fragment parameters were added on later in nuweb's development.
There still is not, for example, an index of fragment parameters.
We need a data type to keep track of fragment parameters.
@o global.h -cc
@o global.h -cc -d
@{typedef int *Parameters;
@| Parameters @}
@@ -2040,7 +2040,7 @@ be the place to look.
We need a few local function declarations before we get into the body
of \verb|write_tex|.
@o latex.c -cc
@o latex.c -cc -d
@{static void copy_scrap(); /* formats the body of a scrap */
static void print_scrap_numbers(); /* formats a list of scrap numbers */
static void format_entry(); /* formats an index entry */
@@ -2054,7 +2054,7 @@ static void write_ArglistElement();
The routine \verb|write_tex| takes two file names as parameters: the
name of the web source file and the name of the \verb|.tex| output file.
@o latex.c -cc
@o latex.c -cc -d
@{void write_tex(file_name, tex_name, sector)
char *file_name;
char *tex_name;
@@ -2318,7 +2318,7 @@ might want to use italics or bold face in the midst of the name.
}
}@}
@o latex.c -cc
@o latex.c -cc -d
@{static void write_arg(FILE * tex_file, char * p)
{
fputs("\\hbox{\\slshape\\sffamily ", tex_file);
@@ -2495,7 +2495,7 @@ list.
}
}@}
@o latex.c -cc
@o latex.c -cc -d
@{static void print_scrap_numbers(tex_file, scraps)
FILE *tex_file;
Scrap_Node *scraps;
@@ -2589,7 +2589,7 @@ command.
@{int scrap_type = 0;
@| scrap_type @}
@o latex.c -cc
@o latex.c -cc -d
@{static void write_literal(FILE * tex_file, char * p, int mode)
{
fputs(delimit_scrap[mode][0], tex_file);
@@ -2604,7 +2604,7 @@ command.
}
@| write_literal @}
@o latex.c -cc
@o latex.c -cc -d
@{static void copy_scrap(file, prefix, name)
FILE *file;
int prefix;
@@ -2859,7 +2859,7 @@ This scrap helps deal with bold keywords:
fputs(", \\ldots\\ ", file);
}@}
@o latex.c -cc
@o latex.c -cc -d
@{static void
write_ArglistElement(FILE * file, Arglist * args, char ** params)
{
@@ -2929,7 +2929,7 @@ write_ArglistElement(FILE * file, Arglist * args, char ** params)
c = source_get();
}@}
@o latex.c -cc
@o latex.c -cc -d
@{static void format_file_entry(name, tex_file)
Name *name;
FILE *tex_file;
@@ -2990,7 +2990,7 @@ putc('\n', tex_file);@}
c = source_get();
@}
@o latex.c -cc
@o latex.c -cc -d
@{static int load_entry(Name * name, Name ** nms, int n)
{
while (name) {
@@ -3002,7 +3002,7 @@ c = source_get();
}
@| load_entry @}
@o latex.c -cc
@o latex.c -cc -d
@{static void format_entry(name, tex_file, sector)
Name *name;
FILE *tex_file;
@@ -3111,7 +3111,7 @@ for (j = 1; j < @2; j++)
@{extern int has_sector(Name *, unsigned char);
@}
@o latex.c -cc
@o latex.c -cc -d
@{int has_sector(Name * name, unsigned char sector)
{
while(name) {
@@ -3143,7 +3143,7 @@ for (j = 1; j < @2; j++)
}@}
@o latex.c -cc
@o latex.c -cc -d
@{static void format_user_entry(name, tex_file, sector)
Name *name;
FILE *tex_file;
@@ -3789,7 +3789,7 @@ pointed out any during the first pass.
@{extern void write_files();
@}
@o output.c -cc
@o output.c -cc -d
@{void write_files(files)
Name *files;
{
@@ -3934,14 +3934,14 @@ int source_line = 0;
\subsection{Local Declarations}
@o input.c -cc
@o input.c -cc -d
@{static FILE *source_file; /* the current input file */
static int double_at;
static int include_depth;
@| source_file double_at include_depth @}
@o input.c -cc
@o input.c -cc -d
@{static struct {
FILE *file;
char *name;
@@ -3958,7 +3958,7 @@ current source file. It notices newlines and keeps the line counter
for \verb|@@|~characters. All other characters are immediately returned.
We define \verb|source_last| to let us tell which type of scrap we
are defining.
@o input.c -cc
@o input.c -cc -d
@{
int source_peek;
int source_last;
@@ -3989,7 +3989,7 @@ int source_get()
@}
@o input.c -cc
@o input.c -cc -d
@{void source_ungetc(int *c)
{
ungetc(source_peek, source_file);
@@ -4127,7 +4127,7 @@ on the stack, the \verb|EOF| is returned.
The routine \verb|source_open| takes a file name and tries to open the
file. If unsuccessful, it complains and halts. Otherwise, it sets
\verb|source_name|, \verb|source_line|, and \verb|double_at|.
@o input.c -cc
@o input.c -cc -d
@{void source_open(name)
char *name;
{
@@ -4151,7 +4151,7 @@ file. If unsuccessful, it complains and halts. Otherwise, it sets
\section{Scraps} \label{scraps}
@o scraps.c -cc
@o scraps.c -cc -d
@{#define SLAB_SIZE 1024
typedef struct slab {
@@ -4160,7 +4160,7 @@ typedef struct slab {
} Slab;
@| Slab next SLAB_SIZE @}
@o scraps.c -cc
@o scraps.c -cc -d
@{typedef struct {
char *file_name;
Slab *slab;
@@ -4175,7 +4175,7 @@ typedef struct slab {
There's some issue with reading the auxiliary file if it has more than 255 lines, so (as a workround only) increase the size of the array of \verb|ScrapEntry|s held in \verb|SCRAP[n]|.
@o scraps.c -cc
@o scraps.c -cc -d
@{
#define SCRAP_BITS 10
#define SCRAP_SIZE (1<<SCRAP_BITS)
@@ -4204,7 +4204,7 @@ extern int num_scraps();
@}
@o scraps.c -cc
@o scraps.c -cc -d
@{void init_scraps()
{
scraps = 1;
@@ -4212,7 +4212,7 @@ extern int num_scraps();
}
@| init_scraps @}
@o scraps.c -cc
@o scraps.c -cc -d
@{void write_scrap_ref(file, num, first, page)
FILE *file;
int num;
@@ -4239,7 +4239,7 @@ extern int num_scraps();
}
@| write_scrap_ref @}
@o scraps.c -cc
@o scraps.c -cc -d
@{void write_single_scrap_ref(file, num)
FILE *file;
int num;
@@ -4267,7 +4267,7 @@ extern int num_scraps();
@{int already_warned = 0;
@}
@o scraps.c -cc
@o scraps.c -cc -d
@{typedef struct {
Slab *scrap;
Slab *prev;
@@ -4277,7 +4277,7 @@ extern int num_scraps();
@o scraps.c -cc
@o scraps.c -cc -d
@{static void push(c, manager)
char c;
Manager *manager;
@@ -4295,7 +4295,7 @@ extern int num_scraps();
}
@| push @}
@o scraps.c -cc
@o scraps.c -cc -d
@{static void pushs(s, manager)
char *s;
Manager *manager;
@@ -4305,7 +4305,7 @@ extern int num_scraps();
}
@| pushs @}
@o scraps.c -cc
@o scraps.c -cc -d
@{int collect_scrap()
{
int current_scrap, lblseq = 0;
@@ -4514,7 +4514,7 @@ if (!name->defs || name->defs->scrap != current_scrap) {
pushs(buff, &writer);
}@}
@o scraps.c -cc
@o scraps.c -cc -d
@{void
add_to_use(Name * name, int current_scrap)
{
@@ -4530,7 +4530,7 @@ add_to_use(Name * name, int current_scrap)
@d Function...
@{extern void add_to_use(Name * name, int current_scrap);
@}
@o scraps.c -cc
@o scraps.c -cc -d
@{static char pop(manager)
Manager *manager;
{
@@ -4547,7 +4547,7 @@ add_to_use(Name * name, int current_scrap)
}
@| pop @}
@o scraps.c -cc
@o scraps.c -cc -d
@{static void backup(n, manager)
int n;
Manager *manager;
@@ -4564,7 +4564,7 @@ add_to_use(Name * name, int current_scrap)
}
@| backup @}
@o scraps.c -cc
@o scraps.c -cc -d
@{void
lookup(int n, Arglist * par, char * arg[9], Name **name, Arglist ** args)
{
@@ -4586,7 +4586,7 @@ lookup(int n, Arglist * par, char * arg[9], Name **name, Arglist ** args)
}
@| lookup @}
@o scraps.c -cc
@o scraps.c -cc -d
@{Arglist * instance(Arglist * a, Arglist * par, char * arg[9], int * ch)
{
if (a != NULL) {
@@ -4636,7 +4636,7 @@ a->name = name;
a->args = args;
a->next = next;@}
@o scraps.c -cc
@o scraps.c -cc -d
@{static Arglist *pop_scrap_name(manager, parameters)
Manager *manager;
Parameters *parameters;
@@ -4671,7 +4671,7 @@ a->next = next;@}
@<Check for macro parameters@>
}@}
@o scraps.c -cc
@o scraps.c -cc -d
@{int write_scraps(file, spelling, defs, global_indent, indent_chars,
debug_flag, tab_flag, indent_flag,
comment_flag, inArgs, inParams, parameters, title)
@@ -5029,7 +5029,7 @@ fputc('>', file);@}
@{extern void collect_numbers();
@}
@o scraps.c -cc
@o scraps.c -cc -d
@{void collect_numbers(aux_name)
char *aux_name;
{
@@ -5168,7 +5168,7 @@ extern char *save_string();
extern void reverse_lists();
@}
@o names.c -cc
@o names.c -cc -d
@{enum { LESS, GREATER, EQUAL, PREFIX, EXTENSION };
static int compare(x, y)
@@ -5199,7 +5199,7 @@ static int compare(x, y)
@| compare LESS GREATER EQUAL PREFIX EXTENSION @}
@o names.c -cc
@o names.c -cc -d
@{char *save_string(s)
char *s;
{
@@ -5209,7 +5209,7 @@ static int compare(x, y)
}
@| save_string @}
@o names.c -cc
@o names.c -cc -d
@{static int ambiguous_prefix();
static char * found_name = NULL;
@@ -5263,7 +5263,7 @@ continue the search down {\em both\/} branches of the tree.
command_name, nw_char, spelling, nw_char, source_name, source_line);
}@}
@o names.c -cc
@o names.c -cc -d
@{static int ambiguous_prefix(node, spelling, sector)
Name *node;
char *spelling;
@@ -5314,7 +5314,7 @@ and 2 for alphabetically greater-than.
@{extern int robs_strcmp(char*, char*);
@}
@o names.c -cc
@o names.c -cc -d
@{int robs_strcmp(char* x, char* y)
{
int cmp = 0;
@@ -5353,7 +5353,7 @@ them to be considered for the alphabetical ordering.
@1++;
@}
@o names.c -cc
@o names.c -cc -d
@{Name *name_add(rt, spelling, sector)
Name **rt;
char *spelling;
@@ -5416,7 +5416,7 @@ them to be considered for the alphabetical ordering.
Name terminated by whitespace. Also check for ``per-file'' flags. Keep
skipping white space until we reach scrap.
@o names.c -cc
@o names.c -cc -d
@{Name *collect_file_name()
{
Name *new_name;
@@ -5499,7 +5499,7 @@ char * comment_end[4] = { "", " */", "", ""};
@| comment_begin comment_end comment_mid @}
Name terminated by \verb+\n+ or \verb+@@{+; but keep skipping until \verb+@@{+
@o names.c -cc
@o names.c -cc -d
@{Name *collect_macro_name()
{
char name[MAX_NAME_LEN];
@@ -5636,7 +5636,7 @@ while ((c = source_get()) != EOF) {
@{extern Name *install_args();
@}
@o names.c -cc
@o names.c -cc -d
@{Name *install_args(Name * name, int argc, char *arg[9])
{
int i;
@@ -5657,7 +5657,7 @@ struct arglist * next;
} Arglist;
@| Arglist @}
@o names.c -cc
@o names.c -cc -d
@{Arglist * buildArglist(Name * name, Arglist * a)
{
Arglist * args = (Arglist *)arena_getmem(sizeof(Arglist));
@@ -5670,7 +5670,7 @@ struct arglist * next;
@| buildArglist @}
Terminated by \verb+@@>+
@o names.c -cc
@o names.c -cc -d
@{Arglist * collect_scrap_name(int current_scrap)
{
char name[MAX_NAME_LEN];
@@ -5832,7 +5832,7 @@ tail = &(*tail)->next;
tail = &(*tail)->next;
@}
@o names.c -cc
@o names.c -cc -d
@{static Scrap_Node *reverse(); /* a forward declaration */
void reverse_lists(names)
@@ -5850,7 +5850,7 @@ void reverse_lists(names)
Just for fun, here's a non-recursive version of the traditional list
reversal code. Note that it reverses the list in place; that is, it
does no new allocations.
@o names.c -cc
@o names.c -cc -d
@{static Scrap_Node *reverse(a)
Scrap_Node *a;
{
@@ -5878,14 +5878,14 @@ however, there is an interesting paper describing an efficient
solution~\cite{aho:75}.
@o scraps.c -cc
@o scraps.c -cc -d
@{typedef struct name_node {
struct name_node *next;
Name *name;
} Name_Node;
@| Name_Node @}
@o scraps.c -cc
@o scraps.c -cc -d
@{typedef struct goto_node {
Name_Node *output; /* list of words ending in this state */
struct move_node *moves; /* list of possible moves */
@@ -5894,7 +5894,7 @@ solution~\cite{aho:75}.
} Goto_Node;
@| Goto_Node @}
@o scraps.c -cc
@o scraps.c -cc -d
@{typedef struct move_node {
struct move_node *next;
Goto_Node *state;
@@ -5902,14 +5902,14 @@ solution~\cite{aho:75}.
} Move_Node;
@| Move_Node @}
@o scraps.c -cc
@o scraps.c -cc -d
@{static Goto_Node *root[256];
static int max_depth;
static Goto_Node **depths;
@| root max_depth depths @}
@o scraps.c -cc
@o scraps.c -cc -d
@{static Goto_Node *goto_lookup(c, g)
char c;
Goto_Node *g;
@@ -5926,7 +5926,7 @@ static Goto_Node **depths;
\subsection{Retrieving scrap uses}
@o scraps.c -cc
@o scraps.c -cc -d
@{typedef struct ArgMgr_s
{
char * pv;
@@ -5936,7 +5936,7 @@ static Goto_Node **depths;
} ArgMgr;
@| ArgMgr @}
@o scraps.c -cc
@o scraps.c -cc -d
@{typedef struct ArgManager_s
{
Manager * m;
@@ -5944,7 +5944,7 @@ static Goto_Node **depths;
} ArgManager;
@| ArgManager @}
@o scraps.c -cc
@o scraps.c -cc -d
@{static void
pushArglist(ArgManager * mgr, Arglist * a)
{
@@ -5962,7 +5962,7 @@ pushArglist(ArgManager * mgr, Arglist * a)
}
@| pushArglist @}
@o scraps.c -cc
@o scraps.c -cc -d
@{static char argpop(ArgManager * mgr)
{
while (mgr->a != NULL)
@@ -6015,7 +6015,7 @@ the others can occur in this context, which makes the whole
free(a);
}@}
@o scraps.c -cc
@o scraps.c -cc -d
@{static char
prev_char(ArgManager * mgr, int n)
{
@@ -6061,7 +6061,7 @@ else if (m->prev)
@{extern void search();
@}
@o scraps.c -cc
@o scraps.c -cc -d
@{static void build_gotos();
static int reject_match();
@@ -6082,7 +6082,7 @@ void search()
@o scraps.c -cc
@o scraps.c -cc -d
@{static void build_gotos(tree)
Name *tree;
{
@@ -6265,7 +6265,7 @@ static void add_uses();
static int scrap_is_in();
@}
@o scraps.c -cc
@o scraps.c -cc -d
@{
static int scrap_is_in(Scrap_Node * list, int i)
{
@@ -6278,7 +6278,7 @@ static int scrap_is_in(Scrap_Node * list, int i)
}
@| scrap_is_in@}
@o scraps.c -cc
@o scraps.c -cc -d
@{
static void add_uses(Uses * * root, Name *name)
{
@@ -6309,7 +6309,7 @@ static void add_uses(Uses * * root, Name *name)
@{extern void format_uses_refs(FILE *, int);
@}
@o scraps.c -cc
@o scraps.c -cc -d
@{
void
format_uses_refs(FILE * tex_file, int scrap)
@@ -6364,7 +6364,7 @@ fputs("}", tex_file);@}
@{extern void format_defs_refs(FILE *, int);
@}
@o scraps.c -cc
@o scraps.c -cc -d
@{
void
format_defs_refs(FILE * tex_file, int scrap)
@@ -6419,7 +6419,7 @@ longer token. Of course, the concept of {\sl token\/} is
language-dependent, so we may be occasionally mistaken.
For the present, we'll consider the mechanism an experiment.
@o scraps.c -cc
@o scraps.c -cc -d
@{#define sym_char(c) (isalnum(c) || (c) == '_')
static int op_char(c)
@@ -6436,7 +6436,7 @@ static int op_char(c)
}
@| sym_char op_char @}
@o scraps.c -cc
@o scraps.c -cc -d
@{static int reject_match(name, post, reader)
Name *name;
char post;
@@ -6469,7 +6469,7 @@ while (c = @1, c != nw_char) /* Here is @xlabel@x */
c = @1;
@}
@o scraps.c -cc
@o scraps.c -cc -d
@{void
write_label(char label_name[], FILE * file)
@<Search for label(@<Write the label to file@>,@<Complain about missing label@>)@>
@@ -6540,7 +6540,7 @@ lbl->seq = ++lblseq;
}
@}
@o global.c -cc
@o global.c -cc -d
@{label_node * label_tab = NULL;
@| label_tab@}
@@ -6574,7 +6574,7 @@ extern void arena_free();
@}
@o arena.c -cc
@o arena.c -cc -d
@{typedef struct chunk {
struct chunk *next;
char *limit;
@@ -6588,7 +6588,7 @@ at the current chunk of memory; it's initially pointed at \verb|first|.
As soon as some storage is required, a ``real'' chunk of memory will
be allocated and attached to \verb|first->next|; storage will be
allocated from the new chunk (and later chunks if necessary).
@o arena.c -cc
@o arena.c -cc -d
@{static Chunk first = { NULL, NULL, NULL };
static Chunk *arena = &first;
@| first arena @}
@@ -6602,7 +6602,7 @@ that returned pointers are always aligned. We align to the nearest
8-byte segment, since that'll satisfy the more common 2-byte and
4-byte alignment restrictions too.
@o arena.c -cc
@o arena.c -cc -d
@{void *arena_getmem(n)
size_t n;
{
@@ -6661,7 +6661,7 @@ need to allocate a new one.
To free all the memory in the arena, we need only point \verb|arena|
back to the first empty chunk.
@o arena.c -cc
@o arena.c -cc -d
@{void arena_free()
{
arena = &first;