From 94ecba323e9fb4ba5ccd6696b6cb4fdf3dc8659d Mon Sep 17 00:00:00 2001 From: jmallett Date: Thu, 18 Apr 2002 18:57:23 +0000 Subject: [PATCH 1/3] Import OpenBSD m4 as of today. --- usr.bin/m4/m4.1 | 408 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 304 insertions(+), 104 deletions(-) diff --git a/usr.bin/m4/m4.1 b/usr.bin/m4/m4.1 index 53180191e8f5..ccd793d6e2a3 100644 --- a/usr.bin/m4/m4.1 +++ b/usr.bin/m4/m4.1 @@ -1,181 +1,381 @@ +.\" @(#) $OpenBSD: m4.1,v 1.24 2002/04/18 18:57:23 espie Exp $ .\" -.\" @(#) $Id: m4.1,v 1.4 1994/01/16 00:30:31 swallace Exp $ .\" .Dd January 26, 1993 -.Dt m4 1 +.Dt M4 1 .Os .Sh NAME .Nm m4 .Nd macro language processor .Sh SYNOPSIS .Nm m4 +.Op Fl d Ar flags +.Op Fl t Ar name +.Op Fl g .Oo .Fl D Ns Ar name Ns Op Ar =value .Oc .Op Fl U Ns Ar name -.Op Ar filename -\|.\|.\|. +.Op Fl I Ar dirname .Sh DESCRIPTION The .Nm m4 utility is a macro processor that can be used as a front end to any language (e.g., C, ratfor, fortran, lex, and yacc). -Each of the argument files is processed in order. -If there are no files, or if a filename is \`-\', the standard input is read. -The processed text is sent to the standard output. +.Nm m4 +reads from the standard input and writes +the processed text to the standard output. .Pp -Macro calls have the form name(argument1[, argument2, ...,] argumentN). +Macro calls have the form name(argument1[, argument2, ..., argumentN]). .Pp There cannot be any space following the macro name and the open -parentheses '('. If the macro name is not followed by an open -parentheses it is processed with no arguments. +parenthesis +.Pq Ql ( . +If the macro name is not followed by an open +parenthesis it is processed with no arguments. .Pp Macro names consist of a leading alphabetic or underscore -possibly followed by alphanumeric or underscore characters, therefore -valid macro names match this pattern [a-zA-Z_][a-zA-Z0-9_]*. +possibly followed by alphanumeric or underscore characters, e.g., +valid macro names match the pattern +.Dq [a-zA-Z_][a-zA-Z0-9_]* . .Pp -In arguments to macros, leading unquoted space, tab and newline -characters are ignored. To quote strings use left and right single -quotes (e.g., ` this is a string with a leading space'). You can change -the quote characters with the changequote built-in macro. +In arguments to macros, leading unquoted space, tab, and newline +.Pq Ql \en +characters are ignored. +To quote strings, use left and right single +quotes (e.g., +.Sq \ this is a string with a leading space ) . +You can change the quote characters with the +.Ic changequote +built-in macro. +.Pp +Most built-ins don't make any sense without arguments, and hence are not +recognized as special when not followed by an open parenthesis. .Pp The options are as follows: -.Bl -tag -width "-Dname[=value]xxx" +.Bl -tag -width Ds .It Fl D Ns Ar name Ns Oo .Ar =value .Oc Define the symbol .Ar name -to have some value (or NULL). +to have some value (or +.Dv NULL ) . .It Fl "U" Ns Ar "name" Undefine the symbol .Ar name . +.It Fl I Ar "dirname" +Add directory +.Ar dirname +to the include path. +.It Fl d Ar "flags" +Set trace flags. +.Ar flags +may hold the following: +.Bl -tag -width Ds +.It Ar a +print macro arguments. +.It Ar c +print macro expansion over several lines. +.It Ar e +print result of macro expansion. +.It Ar f +print filename location. +.It Ar l +print line number. +.It Ar q +quote arguments and expansion with the current quotes. +.It Ar t +start with all macros traced. +.It Ar x +number macro expansions. +.It Ar V +turn on all options. +.El +.Pp +By default, trace is set to +.Qq eq . +.It Fl t Ar macro +Turn tracing on for +.Ar macro . +.It Fl g +Activate GNU-m4 compatibility mode. +In this mode, changequote with +two empty parameters deactivates quotes, translit handles simple character +ranges (e.g., a-z), regular expressions mimic emacs behavior, +and the number of diversions is unlimited. .El .Sh SYNTAX .Nm m4 -provides the following built-in macros. They may be -redefined, loosing their original meaning. -Return values are NULL unless otherwise stated. +provides the following built-in macros. +They may be redefined, losing their original meaning. +Return values are null unless otherwise stated. .Bl -tag -width changequotexxx -.It changecom -Change the start and end comment sequences. The default is -the pound sign `#' and the newline character. With no arguments -comments are turned off. The maximum length for a comment marker is -five characters. -.It changequote +.It Ic builtin +Calls a built-in by its name, overriding possible redefinitions. +.It Ic changecom +Change the start and end comment sequences. +The default is the pound sign +.Pq Ql # +and the newline character. +With no arguments comments are turned off. +The maximum length for a comment marker is five characters. +.It Ic changequote Defines the quote symbols to be the first and second arguments. -The symbols may be up to five characters long. If no arguments are +The symbols may be up to five characters long. +If no arguments are given it restores the default open and close single quotes. -.It decr -Decrements the argument by 1. The argument must be a valid numeric string. -.It define +.It Ic decr +Decrements the argument by 1. +The argument must be a valid numeric string. +.It Ic define Define a new macro named by the first argument to have the -value of the second argument. Each occurrence of $n (where n -is 0 through 9) is replaced by the n'th argument. $0 is the name -of the calling macro. Undefined arguments are replaced by a -NULL string. $# is replaced by the number of arguments; $* -is replaced by all arguments comma separated; $@ is the same -as $* but all arguments are quoted against further expansion. -.It defn -Returns the quoted definition for each argument. This can be used to rename +value of the second argument. +Each occurrence of +.Ql $n +(where +.Ar n +is 0 through 9) is replaced by the +.Ar n Ns 'th +argument. +.Ql $0 +is the name of the calling macro. +Undefined arguments are replaced by a null string. +.Ql $# +is replaced by the number of arguments; +.Ql $* +is replaced by all arguments comma separated; +.Ql $@ +is the same as +.Ql $* +but all arguments are quoted against further expansion. +.It Ic defn +Returns the quoted definition for each argument. +This can be used to rename macro definitions (even for built-in macros). -.It divert +.It Ic divert There are 10 output queues (numbered 0-9). At the end of processing .Nm m4 concatenates all the queues in numerical order to produce the -final output. Initially the output queue is 0. The divert +final output. +Initially the output queue is 0. +The divert macro allows you to select a new output queue (an invalid argument passed to divert causes output to be discarded). -.It divnum +.It Ic divnum Returns the current output queue number. -.It dnl +.It Ic dnl Discard input characters up to and including the next newline. -.It dumpdef +.It Ic dumpdef Prints the names and definitions for the named items, or for everything if no arguments are passed. -.It errprint +.It Ic errprint Prints the first argument on the standard error output stream. -.It eval +.It Ic esyscmd +Pass its first argument to a shell and returns the shell's standard output. +Note that the shell shares its standard input and standard error with +.Nm +.It Ic eval Computes the first argument as an arithmetic expression using 32-bit -arithmetic. Operators are the standard C ternary, arithmetic, logical, -shift, relational, bitwise, and parentheses operators. You can specify -octal, decimal, and hexadecimal numbers as in C. The second argument (if -any) specifies the radix for the result and the third argument (if -any) specifies the minimum number of digits in the result. -.It expr -This is an alias for eval. -.It ifdef +arithmetic. +Operators are the standard C ternary, arithmetic, logical, +shift, relational, bitwise, and parentheses operators. +You can specify +octal, decimal, and hexadecimal numbers as in C. +The second argument (if any) +specifies the radix for the result and the third argument (if any) +specifies the minimum number of digits in the result. +.It Ic expr +This is an alias for +.Ic eval . +.It Ic ifdef If the macro named by the first argument is defined then return the second -argument, otherwise the third. If there is no third argument, -the value is NULL. The word `unix' is predefined. -.It ifelse -If the first argument matches the second argument then ifelse returns -the third argument. If the match fails the three arguments are +argument, otherwise the third. +If there is no third argument, the value is +.Dv NULL . +The word +.Qq unix +is predefined. +.It Ic ifelse +If the first argument matches the second argument then +.Ic ifelse +returns +the third argument. +If the match fails the three arguments are discarded and the next three arguments are used until there is -zero or one arguments left, either this last argument or NULL is -returned if no other matches were found. -.It include +zero or one arguments left, either this last argument or +.Dv NULL +is returned if no other matches were found. +.It Ic include Returns the contents of the file specified in the first argument. +If the file is not found as is, look through the include path: +first the directories specified with +.Fl I +on the command line, then the environment variable +.Ev M4PATH , +as a colon-separated list of directories. Include aborts with an error message if the file cannot be included. -.It incr -Increments the argument by 1. The argument must be a valid numeric string. -.It index +.It Ic incr +Increments the argument by 1. +The argument must be a valid numeric string. +.It Ic index Returns the index of the second argument in the first argument (e.g., -index(the quick brown fox jumped, fox) returns 16). If the second -argument is not found index returns -1. -.It len -Returns the number of characters in the first argument. Extra arguments +.Ic index(the quick brown fox jumped, fox) +returns 16). +If the second +argument is not found index returns \-1. +.It Ic indir +Indirectly calls the macro whose name is passed as the first arguments, +with the remaining arguments passed as first, ... arguments. +.It Ic len +Returns the number of characters in the first argument. +Extra arguments are ignored. -.It m4exit +.It Ic m4exit Immediately exits with the return value specified by the first argument, 0 if none. -.It m4wrap -Allows you to define what happens at the final EOF, usually for cleanup -purposes (e.g., m4wrap("cleanup(tempfile)") causes the macro cleanup to -invoked after all other processing is done.) -.It maketemp -Translates the string XXXXX in the first argument with the current process -ID leaving other characters alone. This can be used to create unique +.It Ic m4wrap +Allows you to define what happens at the final +.Dv EOF , +usually for cleanup purposes (e.g., +.Ic m4wrap("cleanup(tempfile)") +causes the macro cleanup to be +invoked after all other processing is done). +.It Ic maketemp +Translates the string +.Dq XXXXX +in the first argument with the current process +ID leaving other characters alone. +This can be used to create unique temporary file names. -.It paste +.It Ic paste Includes the contents of the file specified by the first argument without -any macro processing. Aborts with an error message if the file cannot be +any macro processing. +Aborts with an error message if the file cannot be included. -.It popdef -Restores the pushdef'ed definition for each argument. -.It pushdef -Takes the same arguments as define, but it saves the definition on a -stack for later retrieval by popdef. -.It shift +.It Ic patsubst +Substitutes a regular expression in a string with a replacement string. +Usual substitution patterns apply: an ampersand +.Pq Ql & +is replaced by the string matching the regular expression. +The string +.Ql \e# , +where +.Ql # +is a digit, is replaced by the corresponding back-reference. +.It Ic popdef +Restores the +.Ic pushdef Ns ed +definition for each argument. +.It Ic pushdef +Takes the same arguments as +.Ic define , +but it saves the definition on a +stack for later retrieval by +.Ic popdef . +.It Ic regexp +Finds a regular expression in a string. +If no further arguments are given, +it returns the first match position or \-1 if no match. +If a third argument +is provided, it returns the replacement string, with sub-patterns replaced. +.It Ic shift Returns all but the first argument, the remaining arguments are -quoted and pushed back with commas in between. The quoting +quoted and pushed back with commas in between. +The quoting nullifies the effect of the extra scan that will subsequently be performed. -.It sinclude -Similar to include, except it ignores any errors. -.It spaste -Similar to spaste, except it ignores any errors. -.It substr +.It Ic sinclude +Similar to +.Ic include , +except it ignores any errors. +.It Ic spaste +Similar to +.Ic paste , +except it ignores any errors. +.It Ic substr Returns a substring of the first argument starting at the offset specified by the second argument and the length specified by the third argument. If no third argument is present it returns the rest of the string. -.It syscmd -Passes the first argument to the shell. Nothing is returned. -.It sysval -Returns the return value from the last syscmd. -.It translit +.It Ic syscmd +Passes the first argument to the shell. +Nothing is returned. +.It Ic sysval +Returns the return value from the last +.Ic syscmd . +.It Ic traceon +Enables tracing of macro expansions for the given arguments, or for all +macros if no argument is given. +.It Ic traceoff +Disables tracing of macro expansions for the given arguments, or for all +macros if no argument is given. +.It Ic translit Transliterate the characters in the first argument from the set -given by the second argument to the set given by the third. You cannot -use +given by the second argument to the set given by the third. +You cannot use .Xr tr 1 style abbreviations. -.It undefine -Removes the definition for the macro specified by the first argument. -.It undivert +.It Ic undefine +Removes the definition for the macros specified by its arguments. +.It Ic undivert Flushes the named output queues (or all queues if no arguments). -.It unix +.It Ic unix A pre-defined macro for testing the OS platform. +.It Ic __line__ +Returns the current file's line number. +.It Ic __file__ +Returns the current file's name. .El -.Sh AUTHOR -Ozan Yigit and Richard A. O'Keefe (ok@goanna.cs.rmit.OZ.AU) +.Sh COMPATIBILITY +.Nm +follows the Single Unix 2 specification, along with a few extensions taken +from +.Nm gnu-m4 . +.Pp +The +.Fl s +option +.Po +.Xr cpp 1 's +#line directives +.Pc +is currently not supported. +Flags +.Fl I , +.Fl d , +.Fl t +are non-standard. +.Pp +The output format of tracing and of +.Ic dumpdef +are not specified in any standard, +are likely to change and should not be relied upon. +The current format of tracing is closely modelled on +.Nm gnu-m4 , +to allow +.Nm autoconf +to work. +.Pp +For portability, one should not use the macros +.Ic builtin , +.Ic esycmd , +.Ic expr , +.Ic indir , +.Ic paste , +.Ic patsubst , +.Ic regexp , +.Ic spaste , +.Ic unix , +.Ic __line__ , +.Ic __file__ . +.Pp +All builtins do expand without arguments in many other +.Nm m4 . +.Pp +Many other +.Nm +have dire size limitations with respect to buffer sizes. +.Sh AUTHORS +Ozan Yigit and Richard A. O'Keefe (ok@goanna.cs.rmit.OZ.AU). +GNU-m4 compatibility extensions by Marc Espie . From 3053e3eaae2d48b48e13789406d08ab1b6db7915 Mon Sep 17 00:00:00 2001 From: jmallett Date: Wed, 1 May 2002 21:36:07 +0000 Subject: [PATCH 2/3] Import OpenBSD m4(1) as of April 26. Mostly ANSIfication changes. --- usr.bin/m4/Makefile | 8 +--- usr.bin/m4/eval.c | 90 ++++++++++++--------------------------------- usr.bin/m4/expr.c | 18 ++++----- usr.bin/m4/gnum4.c | 80 ++++++++++------------------------------ usr.bin/m4/look.c | 20 ++++------ usr.bin/m4/main.c | 33 +++++------------ usr.bin/m4/misc.c | 59 ++++++++++------------------- usr.bin/m4/trace.c | 40 +++++++------------- 8 files changed, 103 insertions(+), 245 deletions(-) diff --git a/usr.bin/m4/Makefile b/usr.bin/m4/Makefile index 0d3c0f59b3aa..ef065c05a428 100644 --- a/usr.bin/m4/Makefile +++ b/usr.bin/m4/Makefile @@ -1,16 +1,12 @@ -# $OpenBSD: Makefile,v 1.8 2001/09/18 14:55:52 espie Exp $ +# $OpenBSD: Makefile,v 1.10 2002/04/26 13:13:41 espie Exp $ # -DEXTENDED # if you want the paste & spaste macros. PROG= m4 CFLAGS+=-DEXTENDED -CDIAGFLAGS=-W -Wall -Wstrict-prototypes \ +CDIAGFLAGS=-W -Wall -Wstrict-prototypes -pedantic \ -Wno-unused -Wno-char-subscripts -Wno-sign-compare -# No optimization for m88k -.if (${MACHINE_ARCH} == "m88k") -CFLAGS+=-O0 -.endif SRCS= eval.c expr.c look.c main.c misc.c gnum4.c trace.c MAN= m4.1 diff --git a/usr.bin/m4/eval.c b/usr.bin/m4/eval.c index 870bffdeb89f..5af3c8774c41 100644 --- a/usr.bin/m4/eval.c +++ b/usr.bin/m4/eval.c @@ -1,4 +1,4 @@ -/* $OpenBSD: eval.c,v 1.43 2002/02/16 21:27:48 millert Exp $ */ +/* $OpenBSD: eval.c,v 1.44 2002/04/26 16:15:16 espie Exp $ */ /* $NetBSD: eval.c,v 1.7 1996/11/10 21:21:29 pk Exp $ */ /* @@ -41,7 +41,7 @@ #if 0 static char sccsid[] = "@(#)eval.c 8.2 (Berkeley) 4/27/95"; #else -static char rcsid[] = "$OpenBSD: eval.c,v 1.43 2002/02/16 21:27:48 millert Exp $"; +static char rcsid[] = "$OpenBSD: eval.c,v 1.44 2002/04/26 16:15:16 espie Exp $"; #endif #endif /* not lint */ @@ -109,10 +109,7 @@ unsigned long expansion_id; * argc is 3 for macro-or-builtin() and 2 for macro-or-builtin */ void -eval(argv, argc, td) - const char *argv[]; - int argc; - int td; +eval(const char *argv[], int argc, int td) { ssize_t mark = -1; @@ -134,10 +131,7 @@ eval(argv, argc, td) * expand_builtin - evaluate built-in macros. */ void -expand_builtin(argv, argc, td) - const char *argv[]; - int argc; - int td; +expand_builtin(const char *argv[], int argc, int td) { int c, n; int ac; @@ -501,9 +495,7 @@ expand_builtin(argv, argc, td) * expand_macro - user-defined macro expansion */ void -expand_macro(argv, argc) - const char *argv[]; - int argc; +expand_macro(const char *argv[], int argc) { const char *t; const char *p; @@ -576,9 +568,7 @@ expand_macro(argv, argc) * dodefine - install definition in the table */ void -dodefine(name, defn) - const char *name; - const char *defn; +dodefine(const char *name, const char *defn) { ndptr p; int n; @@ -614,8 +604,7 @@ dodefine(name, defn) * the given name. */ static void -dodefn(name) - const char *name; +dodefn(const char *name) { ndptr p; char *real; @@ -640,9 +629,7 @@ dodefn(name) * lookup. */ static void -dopushdef(name, defn) - const char *name; - const char *defn; +dopushdef(const char *name, const char *defn) { ndptr p; @@ -663,8 +650,7 @@ dopushdef(name, defn) * dump_one_def - dump the specified definition. */ static void -dump_one_def(p) - ndptr p; +dump_one_def(ndptr p) { char *real; @@ -687,9 +673,7 @@ dump_one_def(p) * hash table is dumped. */ static void -dodump(argv, argc) - const char *argv[]; - int argc; +dodump(const char *argv[], int argc) { int n; ndptr p; @@ -709,10 +693,7 @@ dodump(argv, argc) * dotrace - mark some macros as traced/untraced depending upon on. */ static void -dotrace(argv, argc, on) - const char *argv[]; - int argc; - int on; +dotrace(const char *argv[], int argc, int on) { int n; @@ -727,9 +708,7 @@ dotrace(argv, argc, on) * doifelse - select one of two alternatives - loop. */ static void -doifelse(argv, argc) - const char *argv[]; - int argc; +doifelse(const char *argv[], int argc) { cycle { if (STREQ(argv[2], argv[3])) @@ -749,8 +728,7 @@ doifelse(argv, argc) * doinclude - include a given file. */ static int -doincl(ifile) - const char *ifile; +doincl(const char *ifile) { if (ilevel + 1 == MAXINP) errx(1, "%s at line %lu: too many include files.", @@ -769,8 +747,7 @@ doincl(ifile) * macro processing. */ static int -dopaste(pfile) - const char *pfile; +dopaste(const char *pfile) { FILE *pf; int c; @@ -786,9 +763,7 @@ dopaste(pfile) #endif static void -gnu_dochq(argv, ac) - const char *argv[]; - int ac; +gnu_dochq(const char *argv[], int ac) { /* In gnu-m4 mode, the only way to restore quotes is to have no * arguments at all. */ @@ -808,9 +783,7 @@ gnu_dochq(argv, ac) * dochq - change quote characters */ static void -dochq(argv, argc) - const char *argv[]; - int argc; +dochq(const char *argv[], int argc) { if (argc > 2) { if (*argv[2]) @@ -831,9 +804,7 @@ dochq(argv, argc) } static void -gnu_dochc(argv, ac) - const char *argv[]; - int ac; +gnu_dochc(const char *argv[], int ac) { /* In gnu-m4 mode, no arguments mean no comment * arguments at all. */ @@ -855,9 +826,7 @@ gnu_dochc(argv, ac) * dochc - change comment characters */ static void -dochc(argv, argc) - const char *argv[]; - int argc; +dochc(const char *argv[], int argc) { if (argc > 2) { if (*argv[2]) @@ -879,8 +848,7 @@ dochc(argv, argc) * dodivert - divert the output to a temporary file */ static void -dodiv(n) - int n; +dodiv(int n) { int fd; @@ -911,9 +879,7 @@ dodiv(n) * other outputs, in numerical order. */ static void -doundiv(argv, argc) - const char *argv[]; - int argc; +doundiv(const char *argv[], int argc) { int ind; int n; @@ -936,9 +902,7 @@ doundiv(argv, argc) * dosub - select substring */ static void -dosub(argv, argc) - const char *argv[]; - int argc; +dosub(const char *argv[], int argc) { const char *ap, *fc, *k; int nc; @@ -987,11 +951,7 @@ dosub(argv, argc) * destination string. */ static void -map(dest, src, from, to) - char *dest; - const char *src; - const char *from; - const char *to; +map(char *dest, const char *src, const char *from, const char *to) { const char *tmp; unsigned char sch, dch; @@ -1063,10 +1023,7 @@ map(dest, src, from, to) * on the way. */ static const char * -handledash(buffer, end, src) - char *buffer; - char *end; - const char *src; +handledash(char *buffer, char *end, const char *src) { char *p; @@ -1091,4 +1048,3 @@ handledash(buffer, end, src) *p = '\0'; return buffer; } - diff --git a/usr.bin/m4/expr.c b/usr.bin/m4/expr.c index d73e7123d8f3..10eacc91bd1e 100644 --- a/usr.bin/m4/expr.c +++ b/usr.bin/m4/expr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: expr.c,v 1.12 2002/02/16 21:27:48 millert Exp $ */ +/* $OpenBSD: expr.c,v 1.14 2002/04/26 16:15:16 espie Exp $ */ /* $NetBSD: expr.c,v 1.7 1995/09/28 05:37:31 tls Exp $ */ /* @@ -41,7 +41,7 @@ #if 0 static char sccsid[] = "@(#)expr.c 8.2 (Berkeley) 4/29/95"; #else -static char rcsid[] = "$OpenBSD: expr.c,v 1.12 2002/02/16 21:27:48 millert Exp $"; +static char rcsid[] = "$OpenBSD: expr.c,v 1.14 2002/04/26 16:15:16 espie Exp $"; #endif #endif /* not lint */ @@ -142,8 +142,7 @@ static jmp_buf expjump; #define getch() *nxtch++ int -expr(expbuf) - const char *expbuf; +expr(const char *expbuf) { int rval; @@ -166,12 +165,12 @@ expr(expbuf) static int query() { - int bool, true_val, false_val; + int result, true_val, false_val; - bool = lor(); + result = lor(); if (skipws() != '?') { ungetch(); - return bool; + return result; } true_val = query(); @@ -179,7 +178,7 @@ query() experr("bad query"); false_val = query(); - return bool ? true_val : false_val; + return result ? true_val : false_val; } /* @@ -615,8 +614,7 @@ skipws() * and forces eval to return FALSE. */ static void -experr(msg) - const char *msg; +experr(const char *msg) { printf("m4: %s in expr %s.\n", msg, where); longjmp(expjump, -1); diff --git a/usr.bin/m4/gnum4.c b/usr.bin/m4/gnum4.c index 782090d3a0ed..0383ef4c745b 100644 --- a/usr.bin/m4/gnum4.c +++ b/usr.bin/m4/gnum4.c @@ -1,4 +1,4 @@ -/* $OpenBSD: gnum4.c,v 1.16 2002/02/16 21:27:48 millert Exp $ */ +/* $OpenBSD: gnum4.c,v 1.18 2002/04/26 16:15:16 espie Exp $ */ /* * Copyright (c) 1999 Marc Espie @@ -67,8 +67,7 @@ static void ensure_m4path(void); static struct input_file *dopath(struct input_file *, const char *); static struct path_entry * -new_path_entry(dirname) - const char *dirname; +new_path_entry(const char *dirname) { struct path_entry *n; @@ -83,8 +82,7 @@ new_path_entry(dirname) } void -addtoincludepath(dirname) - const char *dirname; +addtoincludepath(const char *dirname) { struct path_entry *n; @@ -124,9 +122,7 @@ ensure_m4path() static struct input_file * -dopath(i, filename) - struct input_file *i; - const char *filename; +dopath(struct input_file *i, const char *filename) { char path[MAXPATHLEN]; struct path_entry *pe; @@ -143,9 +139,7 @@ dopath(i, filename) } struct input_file * -fopen_trypath(i, filename) - struct input_file *i; - const char *filename; +fopen_trypath(struct input_file *i, const char *filename) { FILE *f; @@ -163,9 +157,7 @@ fopen_trypath(i, filename) } void -doindir(argv, argc) - const char *argv[]; - int argc; +doindir(const char *argv[], int argc) { ndptr p; @@ -177,9 +169,7 @@ doindir(argv, argc) } void -dobuiltin(argv, argc) - const char *argv[]; - int argc; +dobuiltin(const char *argv[], int argc) { int n; argv[1] = NULL; @@ -198,7 +188,7 @@ static size_t bufsize = 0; static size_t current = 0; static void addchars(const char *, size_t); -static void addchar(char); +static void addchar(int); static char *twiddle(const char *); static char *getstring(void); static void exit_regerror(int, regex_t *); @@ -210,9 +200,7 @@ static void add_replace(const char *, regex_t *, const char *, regmatch_t *); #define addconstantstring(s) addchars((s), sizeof(s)-1) static void -addchars(c, n) - const char *c; - size_t n; +addchars(const char *c, size_t n) { if (n == 0) return; @@ -230,8 +218,7 @@ addchars(c, n) } static void -addchar(c) - char c; +addchar(int c) { if (current +1 > bufsize) { if (bufsize == 0) @@ -255,9 +242,7 @@ getstring() static void -exit_regerror(er, re) - int er; - regex_t *re; +exit_regerror(int er, regex_t *re) { size_t errlen; char *errbuf; @@ -269,11 +254,7 @@ exit_regerror(er, re) } static void -add_sub(n, string, re, pm) - int n; - const char *string; - regex_t *re; - regmatch_t *pm; +add_sub(int n, const char *string, regex_t *re, regmatch_t *pm) { if (n > re->re_nsub) warnx("No subexpression %d", n); @@ -290,11 +271,7 @@ add_sub(n, string, re, pm) * constructs and replacing them with substrings of the original string. */ static void -add_replace(string, re, replace, pm) - const char *string; - regex_t *re; - const char *replace; - regmatch_t *pm; +add_replace(const char *string, regex_t *re, const char *replace, regmatch_t *pm) { const char *p; @@ -327,11 +304,7 @@ add_replace(string, re, replace, pm) } static void -do_subst(string, re, replace, pm) - const char *string; - regex_t *re; - const char *replace; - regmatch_t *pm; +do_subst(const char *string, regex_t *re, const char *replace, regmatch_t *pm) { int error; int flags = 0; @@ -371,11 +344,7 @@ do_subst(string, re, replace, pm) } static void -do_regexp(string, re, replace, pm) - const char *string; - regex_t *re; - const char *replace; - regmatch_t *pm; +do_regexp(const char *string, regex_t *re, const char *replace, regmatch_t *pm) { int error; @@ -392,10 +361,7 @@ do_regexp(string, re, replace, pm) } static void -do_regexpindex(string, re, pm) - const char *string; - regex_t *re; - regmatch_t *pm; +do_regexpindex(const char *string, regex_t *re, regmatch_t *pm) { int error; @@ -415,8 +381,7 @@ do_regexpindex(string, re, pm) * says. So we twiddle with the regexp before passing it to regcomp. */ static char * -twiddle(p) - const char *p; +twiddle(const char *p) { /* This could use strcspn for speed... */ while (*p != '\0') { @@ -461,9 +426,7 @@ twiddle(p) * argv[4]: opt rep */ void -dopatsubst(argv, argc) - const char *argv[]; - int argc; +dopatsubst(const char *argv[], int argc) { int error; regex_t re; @@ -487,9 +450,7 @@ dopatsubst(argv, argc) } void -doregexp(argv, argc) - const char *argv[]; - int argc; +doregexp(const char *argv[], int argc) { int error; regex_t re; @@ -514,8 +475,7 @@ doregexp(argv, argc) } void -doesyscmd(cmd) - const char *cmd; +doesyscmd(const char *cmd) { int p[2]; pid_t pid, cpid; diff --git a/usr.bin/m4/look.c b/usr.bin/m4/look.c index ffb58e05167c..ba76e805fda7 100644 --- a/usr.bin/m4/look.c +++ b/usr.bin/m4/look.c @@ -1,4 +1,4 @@ -/* $OpenBSD: look.c,v 1.9 2002/02/16 21:27:48 millert Exp $ */ +/* $OpenBSD: look.c,v 1.10 2002/04/26 16:15:16 espie Exp $ */ /* * Copyright (c) 1989, 1993 @@ -57,9 +57,8 @@ static char sccsid[] = "@(#)look.c 8.1 (Berkeley) 6/6/93"; static void freent(ndptr); -unsigned -hash(name) - const char *name; +unsigned int +hash(const char *name) { unsigned int h = 0; while (*name) @@ -71,8 +70,7 @@ hash(name) * find name in the hash table */ ndptr -lookup(name) - const char *name; +lookup(const char *name) { ndptr p; unsigned int h; @@ -89,8 +87,7 @@ lookup(name) * The new entry is added in front of a hash bucket. */ ndptr -addent(name) - const char *name; +addent(const char *name) { unsigned int h; ndptr p; @@ -105,8 +102,7 @@ addent(name) } static void -freent(p) - ndptr p; +freent(ndptr p) { free((char *) p->name); if (p->defn != null) @@ -118,9 +114,7 @@ freent(p) * remove an entry from the hashtable */ void -remhash(name, all) - const char *name; - int all; +remhash(const char *name, int all) { unsigned int h; ndptr xp, tp, mp; diff --git a/usr.bin/m4/main.c b/usr.bin/m4/main.c index 644b8978844b..9e29700fcb75 100644 --- a/usr.bin/m4/main.c +++ b/usr.bin/m4/main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: main.c,v 1.52 2002/02/16 21:27:48 millert Exp $ */ +/* $OpenBSD: main.c,v 1.53 2002/04/26 16:15:16 espie Exp $ */ /* $NetBSD: main.c,v 1.12 1997/02/08 23:54:49 cgd Exp $ */ /*- @@ -47,7 +47,7 @@ static char copyright[] = #if 0 static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93"; #else -static char rcsid[] = "$OpenBSD: main.c,v 1.52 2002/02/16 21:27:48 millert Exp $"; +static char rcsid[] = "$OpenBSD: main.c,v 1.53 2002/04/26 16:15:16 espie Exp $"; #endif #endif /* not lint */ @@ -172,9 +172,7 @@ static void enlarge_stack(void); int main(int, char *[]); int -main(argc,argv) - int argc; - char *argv[]; +main(int argc, char *argv[]) { int c; int n; @@ -279,9 +277,7 @@ main(argc,argv) * 0 if `token' not found; all characters pushed back */ static int -do_look_ahead(t, token) - int t; - const char *token; +do_look_ahead(int t, const char *token) { int i; @@ -489,8 +485,7 @@ macro() * output string directly, without pushing it for reparses. */ void -outputstr(s) - const char *s; +outputstr(const char *s) { if (sp < 0) while (*s) @@ -506,9 +501,7 @@ outputstr(s) * combo with lookup to speed things up. */ static ndptr -inspect(c, tp) - int c; - char *tp; +inspect(int c, char *tp) { char *name = tp; char *etp = tp+MAXTOK; @@ -572,8 +565,7 @@ initkwds() /* Look up a builtin type, even if overridden by the user */ int -builtin_type(key) - const char *key; +builtin_type(const char *key) { int i; @@ -584,8 +576,7 @@ builtin_type(key) } char * -builtin_realname(n) - int n; +builtin_realname(int n) { int i; @@ -596,9 +587,7 @@ builtin_realname(n) } static void -record(t, lev) - struct position *t; - int lev; +record(struct position *t, int lev) { if (lev < MAXRECORD) { t[lev].name = CURRENT_NAME; @@ -607,9 +596,7 @@ record(t, lev) } static void -dump_stack(t, lev) - struct position *t; - int lev; +dump_stack(struct position *t, int lev) { int i; diff --git a/usr.bin/m4/misc.c b/usr.bin/m4/misc.c index e4bfa7ef1a8b..291c2192fde5 100644 --- a/usr.bin/m4/misc.c +++ b/usr.bin/m4/misc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: misc.c,v 1.26 2001/11/16 23:50:40 deraadt Exp $ */ +/* $OpenBSD: misc.c,v 1.27 2002/04/26 16:15:16 espie Exp $ */ /* $NetBSD: misc.c,v 1.6 1995/09/28 05:37:41 tls Exp $ */ /* @@ -41,7 +41,7 @@ #if 0 static char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 6/6/93"; #else -static char rcsid[] = "$OpenBSD: misc.c,v 1.26 2001/11/16 23:50:40 deraadt Exp $"; +static char rcsid[] = "$OpenBSD: misc.c,v 1.27 2002/04/26 16:15:16 espie Exp $"; #endif #endif /* not lint */ @@ -76,9 +76,7 @@ char *endpbb; /* end of push-back buffer */ * find the index of second str in the first str. */ ptrdiff_t -indx(s1, s2) - const char *s1; - const char *s2; +indx(const char *s1, const char *s2) { char *t; @@ -92,8 +90,7 @@ indx(s1, s2) * putback - push character back onto input */ void -putback(c) - int c; +putback(int c) { if (c == EOF) return; @@ -108,8 +105,7 @@ putback(c) * performance. */ void -pbstr(s) - const char *s; +pbstr(const char *s) { size_t n; @@ -124,8 +120,7 @@ pbstr(s) * pbnum - convert number to string, push back on input. */ void -pbnum(n) - int n; +pbnum(int n) { int num; @@ -143,8 +138,7 @@ pbnum(n) * pbunsigned - convert unsigned long to string, push back on input. */ void -pbunsigned(n) - unsigned long n; +pbunsigned(unsigned long n) { do { putback(n % 10 + '0'); @@ -211,8 +205,7 @@ enlarge_bufspace() * chrsave - put single char on string space */ void -chrsave(c) - int c; +chrsave(int c) { if (ep >= endest) enlarge_strspace(); @@ -223,8 +216,7 @@ chrsave(c) * read in a diversion file, and dispose it. */ void -getdiv(n) - int n; +getdiv(int n) { int c; @@ -238,8 +230,7 @@ getdiv(n) } void -onintr(signo) - int signo; +onintr(int signo) { #define intrmessage "m4: interrupted.\n" write(STDERR_FILENO, intrmessage, sizeof(intrmessage)-1); @@ -263,8 +254,7 @@ killdiv() /* * resizedivs: allocate more diversion files */ void -resizedivs(n) - int n; +resizedivs(int n) { int i; @@ -277,8 +267,7 @@ resizedivs(n) } void * -xalloc(n) - size_t n; +xalloc(size_t n) { char *p = malloc(n); @@ -288,8 +277,7 @@ xalloc(n) } char * -xstrdup(s) - const char *s; +xstrdup(const char *s) { char *p = strdup(s); if (p == NULL) @@ -305,8 +293,7 @@ usage() } int -obtain_char(f) - struct input_file *f; +obtain_char(struct input_file *f) { if (f->c == EOF) return EOF; @@ -318,10 +305,7 @@ obtain_char(f) } void -set_input(f, real, name) - struct input_file *f; - FILE *real; - const char *name; +set_input(struct input_file *f, FILE *real, const char *name) { f->file = real; f->lineno = 1; @@ -330,8 +314,7 @@ set_input(f, real, name) } void -release_input(f) - struct input_file *f; +release_input(struct input_file *f) { if (f->file != stdin) fclose(f->file); @@ -343,15 +326,13 @@ release_input(f) } void -doprintlineno(f) - struct input_file *f; +doprintlineno(struct input_file *f) { pbunsigned(f->lineno); } void -doprintfilename(f) - struct input_file *f; +doprintfilename(struct input_file *f) { pbstr(rquote); pbstr(f->name); @@ -370,9 +351,7 @@ buffer_mark() void -dump_buffer(f, m) - FILE *f; - size_t m; +dump_buffer(FILE *f, size_t m) { char *s; diff --git a/usr.bin/m4/trace.c b/usr.bin/m4/trace.c index 231667edd360..99c72aba2db2 100644 --- a/usr.bin/m4/trace.c +++ b/usr.bin/m4/trace.c @@ -1,4 +1,4 @@ -/* $OpenBSD: trace.c,v 1.4 2002/02/16 21:27:48 millert Exp $ */ +/* $OpenBSD: trace.c,v 1.6 2002/04/26 16:15:16 espie Exp $ */ /* * Copyright (c) 2001 Marc Espie. * @@ -62,8 +62,7 @@ static int frame_level(void); static unsigned int flags = TRACE_QUOTE | TRACE_EXPANSION; static struct t * -find_trace_entry(name) - const char *name; +find_trace_entry(const char *name) { struct t *n; @@ -75,9 +74,7 @@ find_trace_entry(name) void -mark_traced(name, on) - const char *name; - int on; +mark_traced(const char *name, int on) { struct t *n, *n2; @@ -99,18 +96,17 @@ mark_traced(name, on) } else { n = find_trace_entry(name); if (n == NULL) { - n = xalloc(sizeof(struct t)); - n->name = xstrdup(name); - n->next = l; - l = n; + n = xalloc(sizeof(struct t)); + n->name = xstrdup(name); + n->next = l; + l = n; } n->on = on; } } int -is_traced(name) - const char *name; +is_traced(const char *name) { struct t *n; @@ -121,8 +117,7 @@ is_traced(name) } void -trace_file(name) - const char *name; +trace_file(const char *name) { if (traceout != stderr) @@ -133,8 +128,7 @@ trace_file(name) } static unsigned int -letter_to_flag(c) - int c; +letter_to_flag(int c) { switch(c) { case 'a': @@ -165,8 +159,7 @@ letter_to_flag(c) } void -set_trace_flags(s) - const char *s; +set_trace_flags(const char *s) { char mode = 0; unsigned int f = 0; @@ -203,8 +196,7 @@ frame_level() } static void -print_header(inp) - struct input_file *inp; +print_header(struct input_file *inp) { fprintf(traceout, "m4trace:"); if (flags & TRACE_FILENAME) @@ -217,10 +209,7 @@ print_header(inp) } ssize_t -trace(argv, argc, inp) - const char **argv; - int argc; - struct input_file *inp; +trace(const char *argv[], int argc, struct input_file *inp) { print_header(inp); if (flags & TRACE_CONT) { @@ -259,8 +248,7 @@ trace(argv, argc, inp) } void -finish_trace(mark) -size_t mark; +finish_trace(size_t mark) { fprintf(traceout, " -> "); if (flags & TRACE_QUOTE) From 75f4088eb71e33df49f38e40409a74ea045e3ed8 Mon Sep 17 00:00:00 2001 From: des Date: Sun, 23 Jun 2002 14:41:09 +0000 Subject: [PATCH 3/3] Import the documentation for Obtained from: OpenBSD --- share/man/man3/tree.3 | 453 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 453 insertions(+) create mode 100644 share/man/man3/tree.3 diff --git a/share/man/man3/tree.3 b/share/man/man3/tree.3 new file mode 100644 index 000000000000..2d43ac1f09b0 --- /dev/null +++ b/share/man/man3/tree.3 @@ -0,0 +1,453 @@ +.\" $OpenBSD: tree.3,v 1.7 2002/06/12 01:09:20 provos Exp $ +.\"/* +.\" * Copyright 2002 Niels Provos +.\" * All rights reserved. +.\" * +.\" * Redistribution and use in source and binary forms, with or without +.\" * modification, are permitted provided that the following conditions +.\" * are met: +.\" * 1. Redistributions of source code must retain the above copyright +.\" * notice, this list of conditions and the following disclaimer. +.\" * 2. Redistributions in binary form must reproduce the above copyright +.\" * notice, this list of conditions and the following disclaimer in the +.\" * documentation and/or other materials provided with the distribution. +.\" * 3. All advertising materials mentioning features or use of this software +.\" * must display the following acknowledgement: +.\" * This product includes software developed by Niels Provos. +.\" * 4. The name of the author may not be used to endorse or promote products +.\" * derived from this software without specific prior written permission. +.\" * +.\" * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" */ +.Dd February 24, 2002 +.Dt TREE 3 +.Os +.Sh NAME +.Nm SPLAY_PROTOTYPE, +.Nm SPLAY_GENERATE, +.Nm SPLAY_ENTRY , +.Nm SPLAY_HEAD , +.Nm SPLAY_INITIALIZER , +.Nm SPLAY_ROOT , +.Nm SPLAY_EMPTY , +.Nm SPLAY_NEXT , +.Nm SPLAY_MIN , +.Nm SPLAY_MAX , +.Nm SPLAY_FIND , +.Nm SPLAY_LEFT , +.Nm SPLAY_RIGHT , +.Nm SPLAY_FOREACH , +.Nm SPLAY_INIT , +.Nm SPLAY_INSERT , +.Nm SPLAY_REMOVE , +.Nm RB_PROTOTYPE, +.Nm RB_GENERATE, +.Nm RB_ENTRY , +.Nm RB_HEAD , +.Nm RB_INITIALIZER , +.Nm RB_ROOT , +.Nm RB_EMPTY , +.Nm RB_NEXT , +.Nm RB_MIN , +.Nm RB_MAX , +.Nm RB_FIND , +.Nm RB_LEFT , +.Nm RB_RIGHT , +.Nm RB_PARENT , +.Nm RB_FOREACH , +.Nm RB_INIT , +.Nm RB_INSERT , +.Nm RB_REMOVE +.Nd "implementations of splay and red-black trees" +.Sh SYNOPSIS +.Fd #include +.Pp +.Fn SPLAY_PROTOTYPE "NAME" "TYPE" "FIELD" "CMP" +.Fn SPLAY_GENERATE "NAME" "TYPE" "FIELD" "CMP" +.Fn SPLAY_ENTRY "TYPE" +.Fn SPLAY_HEAD "HEADNAME" "TYPE" +.Ft "struct TYPE *" +.Fn SPLAY_INITIALIZER "SPLAY_HEAD *head" +.Fn SPLAY_ROOT "SPLAY_HEAD *head" +.Ft "bool" +.Fn SPLAY_EMPTY "SPLAY_HEAD *head" +.Ft "struct TYPE *" +.Fn SPLAY_NEXT "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" +.Ft "struct TYPE *" +.Fn SPLAY_MIN "NAME" "SPLAY_HEAD *head" +.Ft "struct TYPE *" +.Fn SPLAY_MAX "NAME" "SPLAY_HEAD *head" +.Ft "struct TYPE *" +.Fn SPLAY_FIND "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" +.Ft "struct TYPE *" +.Fn SPLAY_LEFT "struct TYPE *elm" "SPLAY_ENTRY NAME" +.Ft "struct TYPE *" +.Fn SPLAY_RIGHT "struct TYPE *elm" "SPLAY_ENTRY NAME" +.Fn SPLAY_FOREACH "VARNAME" "NAME" "SPLAY_HEAD *head" +.Ft void +.Fn SPLAY_INIT "SPLAY_HEAD *head" +.Ft "struct TYPE *" +.Fn SPLAY_INSERT "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" +.Ft "struct TYPE *" +.Fn SPLAY_REMOVE "NAME" "SPLAY_HEAD *head" "struct TYPE *elm" +.Pp +.Fn RB_PROTOTYPE "NAME" "TYPE" "FIELD" "CMP" +.Fn RB_GENERATE "NAME" "TYPE" "FIELD" "CMP" +.Fn RB_ENTRY "TYPE" +.Fn RB_HEAD "HEADNAME" "TYPE" +.Fn RB_INITIALIZER "RB_HEAD *head" +.Ft "struct TYPE *" +.Fn RB_ROOT "RB_HEAD *head" +.Ft "bool" +.Fn RB_EMPTY "RB_HEAD *head" +.Ft "struct TYPE *" +.Fn RB_NEXT "NAME" "RB_HEAD *head" "struct TYPE *elm" +.Ft "struct TYPE *" +.Fn RB_MIN "NAME" "RB_HEAD *head" +.Ft "struct TYPE *" +.Fn RB_MAX "NAME" "RB_HEAD *head" +.Ft "struct TYPE *" +.Fn RB_FIND "NAME" "RB_HEAD *head" "struct TYPE *elm" +.Ft "struct TYPE *" +.Fn RB_LEFT "struct TYPE *elm" "RB_ENTRY NAME" +.Ft "struct TYPE *" +.Fn RB_RIGHT "struct TYPE *elm" "RB_ENTRY NAME" +.Ft "struct TYPE *" +.Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME" +.Fn RB_FOREACH "VARNAME" "NAME" "RB_HEAD *head" +.Ft void +.Fn RB_INIT "RB_HEAD *head" +.Ft "struct TYPE *" +.Fn RB_INSERT "NAME" "RB_HEAD *head" "struct TYPE *elm" +.Ft "struct TYPE *" +.Fn RB_REMOVE "NAME" "RB_HEAD *head" "struct TYPE *elm" +.Sh DESCRIPTION +These macros defines data structures for different types of trees: +splay trees and red-black trees. +.Pp +In the macro definitions, +.Fa TYPE +is the name tag of a user defined structure that must contain a field of type +.Li SPLAY_ENTRY , +or +.Li RB_ENTRY , +named +.Fa ENTRYNAME . +The argument +.Fa HEADNAME +is the name tag of a user defined structure that must be declared +using the macros +.Fn SPLAY_HEAD , +or +.Fn RB_HEAD . +The argument +.Fa NAME +has to be a unique name prefix for every tree that is defined. +.Pp +The function prototypes are declared with either +.Li SPLAY_PROTOTYPE, +or +.Li RB_PROTOTYPE . +The function bodies are generated with either +.Li SPLAY_GENERATE, +or +.Li RB_GENERATE . +See the examples below for further explanation of how these macros are used. +.Sh SPLAY TREES +A splay tree is a self-organizing data structure. Every operation +on the tree causes a splay to happen. The splay moves the requested +node to the root of the tree and partly rebalances it. +.Pp +This has the benefit that request locality causes faster lookups as +the requested nodes move to the top of the tree. On the other hand, +every lookup causes memory writes. +.Pp +The Balance Theorem bounds the total access time for m operations +and n inserts on an initially empty tree as O((m + n)lg n). The +amortized cost for a sequence of m accesses to a splay tree is O(lg n); +.Pp +A splay tree is headed by a structure defined by the +.Fn SPLAY_HEAD +macro. +A +.Fa SPLAY_HEAD +structure is declared as follows: +.Bd -literal -offset indent +SPLAY_HEAD(HEADNAME, TYPE) head; +.Ed +.Pp +where +.Fa HEADNAME +is the name of the structure to be defined, and struct +.Fa TYPE +is the type of the elements to be inserted into the tree. +.Pp +The +.Fn SPLAY_ENTRY +macro declares a structure that allows elements to be connected in the tree. +.Pp +In order to use the functions that manipulate the tree structure, +their prototypes need to be declared with the +.Fn SPLAY_PROTOTYPE +macro, +where +.Fa NAME +is a unique identifier for this particular tree. +The +.Fa TYPE +argument is the type of the structure that is being managed +by the tree. +The +.Fa FIELD +argument is the name of the element defined by +.Fn SPLAY_ENTRY . +.Pp +The function bodies are generated with the +.Fn SPLAY_GENERATE +macro. It takes the same arguments as the +.Fn SPLAY_PROTOTYPE +macro, but should be used only once. +.Pp +Finally, +the +.Fa CMP +argument is the name of a function used to compare tree noded +with each other. The function takes two arguments of type +.Fa "struct TYPE *" . +If the first argument is smaller than the second, the function returns a +value smaller than zero. If they are equal, the function returns zero. +Otherwise, it should return a value greater than zero. The compare +function defines the order of the tree elements. +.Pp +The +.Fn SPLAY_INIT +macro initializes the tree referenced by +.Fa head . +.Pp +The splay tree can also be initialized statically by using the +.Fn SPLAY_INITIALIZER +macro like this: +.Bd -literal -offset indent +SPLAY_HEAD(HEADNAME, TYPE) head = SPLAY_INITIALIZER(&head); +.Ed +.Pp +The +.Fn SPLAY_INSERT +macro inserts the new element +.Fa elm +into the tree. +.Pp +The +.Fn SPLAY_REMOVE +macro removes the element +.Fa elm +from the tree pointed by +.Fa head . +.Pp +The +.Fn SPLAY_FIND +macro can be used to find a particular element in the tree. +.Bd -literal -offset indent +struct TYPE find, *res; +find.key = 30; +res = SPLAY_FIND(NAME, head, &find); +.Ed +.Pp +The +.Fn SPLAY_ROOT , +.Fn SPLAY_MIN , +.Fn SPLAY_MAX , +and +.Fn SPLAY_NEXT +macros can be used to traverse the tree: +.Bd -literal -offset indent +for (np = SPLAY_MIN(NAME, &head); np != NULL; np = SPLAY_NEXT(NAME, &head, np)) +.Ed +.Pp +Or, for simplicity, one can use the +.Fn SPLAY_FOREACH +macro: +.Bd -literal -offset indent +SPLAY_FOREACH(np, NAME, head) +.Ed +.Pp +The +.Fn SPLAY_EMPTY +macro should be used to check whether a splay tree is empty. +.Pp +.Sh RED-BLACK TREES +A red-black tree is a binary search tree with the node color as an +extra attribute. It fulfills a set of conditions: +.Bl -enum -compact -offset indent +.It +every search path from the root to a leaf consists of the same number of +black nodes, +.It +each red node (except for the root) has a black parent, +.It +each leaf node is black. +.El +.Pp +Every operation on a red-black tree is bounded as O(lg n). +The maximum height of a red-black tree is 2lg (n+1). +.Pp +A red-black tree is headed by a structure defined by the +.Fn RB_HEAD +macro. +A +.Fa RB_HEAD +structure is declared as follows: +.Bd -literal -offset indent +RB_HEAD(HEADNAME, TYPE) head; +.Ed +.Pp +where +.Fa HEADNAME +is the name of the structure to be defined, and struct +.Fa TYPE +is the type of the elements to be inserted into the tree. +.Pp +The +.Fn RB_ENTRY +macro declares a structure that allows elements to be connected in the tree. +.Pp +In order to use the functions that manipulate the tree structure, +their prototypes need to be declared with the +.Fn RB_PROTOTYPE +macro, +where +.Fa NAME +is a unique identifier for this particular tree. +The +.Fa TYPE +argument is the type of the structure that is being managed +by the tree. +The +.Fa FIELD +argument is the name of the element defined by +.Fn RB_ENTRY . +.Pp +The function bodies are generated with the +.Fn RB_GENERATE +macro. It takes the same arguments as the +.Fn RB_PROTOTYPE +macro, but should be used only once. +.Pp +Finally, +the +.Fa CMP +argument is the name of a function used to compare tree noded +with each other. The function takes two arguments of type +.Fa "struct TYPE *" . +If the first argument is smaller than the second, the function returns a +value smaller than zero. If they are equal, the function returns zero. +Otherwise, it should return a value greater than zero. The compare +function defines the order of the tree elements. +.Pp +The +.Fn RB_INIT +macro initializes the tree referenced by +.Fa head . +.Pp +The redblack tree can also be initialized statically by using the +.Fn RB_INITIALIZER +macro like this: +.Bd -literal -offset indent +RB_HEAD(HEADNAME, TYPE) head = RB_INITIALIZER(&head); +.Ed +.Pp +The +.Fn RB_INSERT +macro inserts the new element +.Fa elm +into the tree. +.Pp +The +.Fn RB_REMOVE +macro removes the element +.Fa elm +from the tree pointed by +.Fa head . +.Pp +The +.Fn RB_FIND +macro can be used to find a particular element in the tree. +.Bd -literal -offset indent +struct TYPE find, *res; +find.key = 30; +res = RB_FIND(NAME, head, &find); +.Ed +.Pp +The +.Fn RB_ROOT , +.Fn RB_MIN , +.Fn RB_MAX , +and +.Fn RB_NEXT +macros can be used to traverse the tree: +.Bd -literal -offset indent +for (np = RB_MIN(NAME, &head); np != NULL; np = RB_NEXT(NAME, &head, np)) +.Ed +.Pp +Or, for simplicity, one can use the +.Fn RB_FOREACH +macro: +.Bd -literal -offset indent +RB_FOREACH(np, NAME, head) +.Ed +.Pp +The +.Fn RB_EMPTY +macro should be used to check whether a splay tree is empty. +.Pp +.Sh NOTES +Trying to free a tree in the following way is a common error: +.Bd -literal -offset indent +SPLAY_FOREACH(var, NAME, head) { + SPLAY_REMOVE(NAME, head, var); + free(var); +} +free(head); +.Ed +.Pp +Since +.Va var +is free'd, the +.Fn FOREACH +macro refers to a pointer that may have been reallocated already. +Proper code needs a second variable. +.Bd -literal -offset indent +for (var = SPLAY_MIN(NAME, head); var != NULL; var = nxt) { + nxt = SPLAY_NEXT(NAME, head, var); + SPLAY_REMOVE(NAME, head, var); + free(var); +} +.Ed +.Pp +Both +.Fn RB_INSERT +and +.Fn SPLAY_INSERT +return +.Va NULL +if the element was inserted in the tree successfully, otherwise they +return a pointer to the element with the colliding key. +.Pp +Accordingly, +.Fn RB_REMOVE +and +.Fn SPLAY_REMOVE +return the pointer to the removed element otherwise they return +.Va NULL +to indicate an error. +.Sh AUTHORS +The author of the tree macros is Niels Provos.