diff --git a/98-misc/toc.tex b/98-misc/toc.tex
new file mode 100644
index 0000000000000000000000000000000000000000..74be4dd46d29f5abc99371b0a3933d9a443f7a96
--- /dev/null
+++ b/98-misc/toc.tex
@@ -0,0 +1,39 @@
+\fakechapter{Table of contents}
+
+\def\tocchaplabel#1#2^^X{\if0#1\else#1#2~\fi}
+\def\tocchapter#1#2#3#4{\bigskip
+	\line{\bf\tocchaplabel#2^^X\toclink{#2}{#4}\hfil\pagelink{#1}}
+	\tocoutline{#2}{#4}
+}
+\def\tocsection#1#2#3#4{%
+	\line{\qquad#2#3~~\toclink{#2}{#4}\hfil\pagelink{#1}}
+	\tocoutline{#2}{#4}
+}
+\def\toclink#1#2{%
+	\ifprint
+		#2
+	\else
+		\pdfextension startlink\commonlinkargs goto name {s#1}\relax #2\pdfextension endlink
+	\fi
+}
+\def\tocoutline#1#2{
+	\ifprint\else
+		\directlua{pdfmeta.add_outline('\luaescapestring{#1}', '\luaescapestring{s#1}', '\luaescapestring{#2}')}
+	\fi
+}
+\def\tocstar{\rlap{*}}
+
+{
+\catcode`@=11
+\catcode`*=\active
+\let*=\tocstar
+\input toc.aux
+\catcode`@=12
+}
+
+\bigskip
+
+Sections and exercises marked with one or two asterisks contain advanced material.
+We suggest that the reader skips them first time.
+
+\vfill\eject
diff --git a/ds.tex b/ds.tex
index 86d3472fbdf6b4ec2b75c17fc5f025a7082d42f9..5a6af27378285d62eb837016716d8b5f96bfbca0 100644
--- a/ds.tex
+++ b/ds.tex
@@ -4,6 +4,8 @@
 %\debuggrid
 %\debugindex
 
+\input 98-misc/toc.tex
+
 \def\includechapaux#1-#2@{\input #1-#2/#2.tex}
 \def\includechapter#1{\includechapaux#1@}
 \input chapters.tex