fix even more broken markdown links
Added `bin/find-missing-links.sh` tool to check for
markdown links to missing local files.
Regarding the missing link tool:
```
Here be extended regular expression magic dragons! :-)
```
Added `make find_missing_links` to the top level Makefile.
Added `make find_missing_links` to `make www` and `make quick_www`.
Ran `make www` to perform the above.
TODO: Fix markdown links to missing local files.
This commit is contained in:
1 parent
58d19725b4
commit
217836e33f
41 files changed
+1773
-635
No files matched your search
@@ -157,7 +157,7 @@ tackle this project.
|
||||
on smaller machines; `m[]` needs to be at least 2000 long, though.
|
||||
|
||||
I say `first` is portable mainly because it uses native types. Unlike
|
||||
[FORTH](https://en.wikipedia.org/wiki/Forth_(programming_language), which
|
||||
[FORTH](https://en.wikipedia.org/wiki/Forth_(programming_language)), which
|
||||
traditionally allows byte and multi-byte operations, all operations are
|
||||
performed on C `int`s. That means `first` code is only as portable as the same
|
||||
code would be in C. As in C, the result of dividing `-1` by `2` is machine (or
|
||||
@@ -205,7 +205,7 @@ represents a step backwards, in more ways than one.)
|
||||
### What exactly is `first`, then?
|
||||
|
||||
`first` is a tiny interpreter which implements a sufficient pseudo-subset of
|
||||
[FORTH](https://en.wikipedia.org/wiki/Forth_(programming_language)) to allow it
|
||||
[FORTH](https://en.wikipedia.org/wiki/Forth_(programming_language)) to allow it
|
||||
to bootstrap a relatively complete version of FORTH (based loosely on forth79),
|
||||
which I call THIRD. Complete relative to what, I'm not sure.
|
||||
|
||||
@@ -217,11 +217,11 @@ the design file, design, I give a justification for why each primitive in
|
||||
|
||||
THIRD is sorta slow, because `first` has so few primitives that many things that
|
||||
are primitives in
|
||||
[FORTH](https://en.wikipedia.org/wiki/Forth_(programming_language)) (like swap)
|
||||
[FORTH](https://en.wikipedia.org/wiki/Forth_(programming_language)) (like swap)
|
||||
take a significant amount of time in THIRD.
|
||||
|
||||
When you get the `Ok.` message from `third`, try out some sample
|
||||
[FORTH](https://en.wikipedia.org/wiki/Forth_(programming_language)) code
|
||||
[FORTH](https://en.wikipedia.org/wiki/Forth_(programming_language)) code
|
||||
(`first` has no way of knowing if keyboard input is waiting, so it can't actually prompt
|
||||
you in a normal way. It only prints `'Ok.'` after you define a word).
|
||||
|
||||
@@ -266,7 +266,7 @@ If you compile the basic THIRD system without the help word (strings take up one
|
||||
1000 `int`s (plus the return stack).
|
||||
|
||||
Thus THIRD gives you a relatively complete
|
||||
[FORTH](https://en.wikipedia.org/wiki/Forth_(programming_language)) system in
|
||||
[FORTH](https://en.wikipedia.org/wiki/Forth_(programming_language)) system in
|
||||
less than 700 chars of C source + about 1000 `int`s of memory--and it's portable
|
||||
too (you could copy over the THIRD memory dump to another machine, in theory).
|
||||
If the above numbers seem to you to be mixing apples and oranges (C source and
|
||||
|
||||
@@ -484,7 +484,7 @@ tackle this project.</p>
|
||||
<p><code>first</code> is reasonably portable. You may need to adjust the size of the buffers
|
||||
on smaller machines; <code>m[]</code> needs to be at least 2000 long, though.</p>
|
||||
<p>I say <code>first</code> is portable mainly because it uses native types. Unlike
|
||||
[FORTH](https://en.wikipedia.org/wiki/Forth_(programming_language), which
|
||||
<a href="https://en.wikipedia.org/wiki/Forth_(programming_language)">FORTH</a>, which
|
||||
traditionally allows byte and multi-byte operations, all operations are
|
||||
performed on C <code>int</code>s. That means <code>first</code> code is only as portable as the same
|
||||
code would be in C. As in C, the result of dividing <code>-1</code> by <code>2</code> is machine (or
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ International Internet community.
|
||||
## Author's remarks:
|
||||
|
||||
This program plays
|
||||
[Mastermind](https://en.wikipedia.org/wiki/Mastermind_(board_game), if you call
|
||||
[Mastermind](https://en.wikipedia.org/wiki/Mastermind_(board_game)), if you call
|
||||
it by a name ending by 'd', otherwise it _solves_ Mastermind. Call it without
|
||||
parameters to use 6 digits (colors), or indicate the number of possible digits
|
||||
(you cannot change the number of positions so easily).
|
||||
|
||||
+1
-1
@@ -414,7 +414,7 @@ for instructions of how to play.</p>
|
||||
International Internet community.</p>
|
||||
<h2 id="authors-remarks">Author’s remarks:</h2>
|
||||
<p>This program plays
|
||||
[Mastermind](https://en.wikipedia.org/wiki/Mastermind_(board_game), if you call
|
||||
<a href="https://en.wikipedia.org/wiki/Mastermind_(board_game)">Mastermind</a>, if you call
|
||||
it by a name ending by ‘d’, otherwise it <em>solves</em> Mastermind. Call it without
|
||||
parameters to use 6 digits (colors), or indicate the number of possible digits
|
||||
(you cannot change the number of positions so easily).</p>
|
||||
|
||||
@@ -74,7 +74,7 @@ Use `rince.alt` or `rince.alt2` as you would `rince` above.
|
||||
The author has provided several CABBAGE files for your amusement:
|
||||
|
||||
- [rince.data1](%%REPO_URL%%/1993/rince/rince.data1) plays
|
||||
[Breakout](https://en.wikipedia.org/wiki/Breakout_(video_game). Keys are `,`
|
||||
[Breakout](https://en.wikipedia.org/wiki/Breakout_(video_game)). Keys are `,`
|
||||
for left, `/` for right, and `.` for 'fire the ball'.
|
||||
|
||||
- [rince.data2](%%REPO_URL%%/1993/rince/rince.data2) plays the old [James Bonfield](../../authors.html#James_Bonfield)'s
|
||||
|
||||
@@ -430,7 +430,7 @@ changed).</p>
|
||||
<p>The author has provided several CABBAGE files for your amusement:</p>
|
||||
<ul>
|
||||
<li><p><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1993/rince/rince.data1">rince.data1</a> plays
|
||||
[Breakout](https://en.wikipedia.org/wiki/Breakout_(video_game). Keys are <code>,</code>
|
||||
<a href="https://en.wikipedia.org/wiki/Breakout_(video_game)">Breakout</a>. Keys are <code>,</code>
|
||||
for left, <code>/</code> for right, and <code>.</code> for ‘fire the ball’.</p></li>
|
||||
<li><p><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1993/rince/rince.data2">rince.data2</a> plays the old <a href="../../authors.html#James_Bonfield">James Bonfield</a>’s
|
||||
(<a href="../../1991/rince/index.html">1991/rince</a> game from IOCCC 1991.</p></li>
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ them for the next IOCCC.
|
||||
We believe you will be impressed with this year's winning entries The [Best of
|
||||
Show](ollinger/index.html) is a fine example of obfuscation. But don't ignore
|
||||
the other entries! There are games, programs that speak, ones that compile code
|
||||
and [one that _might_ run binaries you already have](2001/anonymous/index.html).
|
||||
and [one that _might_ run binaries you already have](anonymous/index.html).
|
||||
|
||||
The [Best/Worst Abuse of the Rules](bellard/index.html) is technically allowed by the
|
||||
[rules](rules.txt). This year we awarded it again, but don't assume you can get
|
||||
|
||||
+1
-1
@@ -412,7 +412,7 @@ them for the next IOCCC.</p>
|
||||
<p>We believe you will be impressed with this year’s winning entries The <a href="ollinger/index.html">Best of
|
||||
Show</a> is a fine example of obfuscation. But don’t ignore
|
||||
the other entries! There are games, programs that speak, ones that compile code
|
||||
and <a href="2001/anonymous/index.html">one that <em>might</em> run binaries you already have</a>.</p>
|
||||
and <a href="anonymous/index.html">one that <em>might</em> run binaries you already have</a>.</p>
|
||||
<p>The <a href="bellard/index.html">Best/Worst Abuse of the Rules</a> is technically allowed by the
|
||||
<a href="rules.txt">rules</a>. This year we awarded it again, but don’t assume you can get
|
||||
away with using the same technique next time … :-)</p>
|
||||
|
||||
@@ -48,7 +48,7 @@ aren't familiar with it. Back in its day, this demo inspired lust and awe in
|
||||
geeks around the world.
|
||||
|
||||
The graphics are
|
||||
[raytraced](https://en.wikipedia.org/wiki/Ray_tracing_(graphics), with
|
||||
[raytraced](https://en.wikipedia.org/wiki/Ray_tracing_(graphics)), with
|
||||
procedural textures on the ball and the back wall. I did cheat a little to
|
||||
simplify the calculations: it uses a parallel projection, but textures the back
|
||||
wall to look as if there were a floor being viewed in perspective. The shadow
|
||||
|
||||
@@ -421,7 +421,7 @@ the Commodore Amiga. See <a href="https://www.youtube.com/watch?v=-ga41edXw3A" c
|
||||
aren’t familiar with it. Back in its day, this demo inspired lust and awe in
|
||||
geeks around the world.</p>
|
||||
<p>The graphics are
|
||||
[raytraced](https://en.wikipedia.org/wiki/Ray_tracing_(graphics), with
|
||||
<a href="https://en.wikipedia.org/wiki/Ray_tracing_(graphics)">raytraced</a>, with
|
||||
procedural textures on the ball and the back wall. I did cheat a little to
|
||||
simplify the calculations: it uses a parallel projection, but textures the back
|
||||
wall to look as if there were a floor being viewed in perspective. The shadow
|
||||
|
||||
@@ -292,7 +292,7 @@ casting) it to an integer-type variable.
|
||||
[pour-out.txt](%%REPO_URL%%/2012/endoh1/pour-out.txt) pours you a cup of tea.
|
||||
|
||||
[tanada.txt](%%REPO_URL%%/2012/endoh1/tanada.txt) simulates "Terrace farming". ("Tanada" means a
|
||||
"[terraced rice](https://en.wikipedia.org/wiki/Terrace_(earthworks) fields)" in Japanese.)
|
||||
"[terraced rice](https://en.wikipedia.org/wiki/Terrace_(earthworks) fields)" in Japanese.)
|
||||
|
||||
[clock.txt](%%REPO_URL%%/2012/endoh1/clock.txt) is a "water" clock created by HAMANO Tsukasa.
|
||||
|
||||
|
||||
+1
-1
@@ -132,7 +132,7 @@ As an extra tweak, the text message actually does something useful. Remove the
|
||||
|
||||
[^1]: [Russ Cox, Regular Expression Matching: the Virtual Machine Approach](http://swtch.com/~rsc/regexp/regexp2.html)
|
||||
|
||||
[^2]: [Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby, ...](http://swtch.com/~rsc/regexp/regexp1.html)
|
||||
[^2]: [Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby, ...)](http://swtch.com/~rsc/regexp/regexp1.html)
|
||||
|
||||
|
||||
<!--
|
||||
|
||||
+1
-1
@@ -460,7 +460,7 @@ amount of spaghetti branches and virtual thread creations. Finally, the VM in
|
||||
“Make a contract with me” catch line and the program would cease to function.</p>
|
||||
<h3 id="references">References</h3>
|
||||
<p>[1] <a href="http://swtch.com/~rsc/regexp/regexp2.html">Russ Cox, Regular Expression Matching: the Virtual Machine Approach</a></p>
|
||||
<p>[2] <a href="http://swtch.com/~rsc/regexp/regexp1.html">Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby, …</a></p>
|
||||
<p>[2] <a href="http://swtch.com/~rsc/regexp/regexp1.html">Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby, …)</a></p>
|
||||
<hr style="width:10%;text-align:left;margin-left:0">
|
||||
<p>Jump to: <a href="#">top</a></p>
|
||||
<!--
|
||||
|
||||
+1
-1
@@ -129,7 +129,7 @@ As an extra tweak, the text message actually does something useful. Remove the
|
||||
|
||||
[1] [Russ Cox, Regular Expression Matching: the Virtual Machine Approach](http://swtch.com/~rsc/regexp/regexp2.html)
|
||||
|
||||
[2] [Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby, ...](http://swtch.com/~rsc/regexp/regexp1.html)
|
||||
[2] [Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby, ...)](http://swtch.com/~rsc/regexp/regexp1.html)
|
||||
|
||||
|
||||
<hr style="width:10%;text-align:left;margin-left:0">
|
||||
|
||||
+1
-1
@@ -492,7 +492,7 @@ amount of spaghetti branches and virtual thread creations. Finally, the VM in
|
||||
<section id="footnotes" class="footnotes footnotes-end-of-document" role="doc-endnotes">
|
||||
<h5>Footnotes</h5>
|
||||
<ol>
|
||||
<li id="fn1"><p><a href="http://swtch.com/~rsc/regexp/regexp1.html">Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby, …</a><a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
|
||||
<li id="fn1"><p><a href="http://swtch.com/~rsc/regexp/regexp1.html">Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby, …)</a><a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
|
||||
<li id="fn2"><p><a href="http://swtch.com/~rsc/regexp/regexp2.html">Russ Cox, Regular Expression Matching: the Virtual Machine Approach</a><a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
|
||||
<li id="fn3"><p><a href="http://swtch.com/~rsc/regexp/regexp2.html">Russ Cox, Regular Expression Matching: the Virtual Machine Approach</a><a href="#fnref3" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
|
||||
</ol>
|
||||
|
||||
@@ -180,7 +180,7 @@ for [Khan](https://memory-alpha.fandom.com/wiki/Khan_Noonien_Singh) (in the
|
||||
final engagement in [Star Trek II: The Wrath of
|
||||
Khan](https://memory-alpha.fandom.com/wiki/Star_Trek_II:_The_Wrath_of_Khan), the
|
||||
damaged Enterprise managed to disable the USS
|
||||
[Reliant](https://memory-alpha.fandom.com/wiki/USS_Reliant_(NCC-1864) ship)'s shield
|
||||
[Reliant](https://memory-alpha.fandom.com/wiki/USS_Reliant_(NCC-1864) ship)'s shield
|
||||
generator by accessing its prefix code: 16309).
|
||||
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ Who will be the first to tweet this source? How many re-tweets will such tweet
|
||||
get? And how many people will really understand the tweet?
|
||||
|
||||
Judges' 2023 update: Last year we would have referred to a
|
||||
[toot](https://en.wikipedia.org/wiki/Mastodon_\(social_network\)#Comparison_to_Twitter),
|
||||
[toot](https://en.wikipedia.org/wiki/Mastodon_(social_network)#Comparison_to_Twitter),
|
||||
as in a [Mastodon](https://fosstodon.org/@ioccc) *toot*.
|
||||
This year we might have mentioned the term
|
||||
[publish](https://www.itechpost.com/articles/115087/20221116/mastodon-officially-replaced-toot-publish.htm)
|
||||
|
||||
+2
-2
@@ -49,8 +49,8 @@ It is something completely different.
|
||||
|
||||
The [Most likely to be awarded - 2018/ciura](ciura/index.html) has an amazing vocabulary!
|
||||
|
||||
There are also nods to entries of the years [2000/bellard](2000/bellard/index.html),
|
||||
[1989/yang](1989/yang/index.html), ...
|
||||
There are also nods to entries of the years [2000/bellard](../2000/bellard/index.html),
|
||||
[1989/yang](../1989/yang/index.html), ...
|
||||
|
||||
...We'll stop spouting spoilers now. Have fun exploring all the entries!
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ sketch [comté](https://en.wikipedia.org/wiki/Comté_cheese) called ["Dead
|
||||
Parrot"](https://en.wikipedia.org/wiki/Dead_Parrot_sketch) from the British
|
||||
sitcom ["Monty Python's Flying Circus"](https://en.wikipedia.org/wiki/Monty_Python%27s_Flying_Circus)
|
||||
The "_Python_" in the award name refers to Monty Python, **not** the
|
||||
[programming language Python](https://en.wikipedia.org/wiki/Python_(programming_language)
|
||||
[programming language Python](https://en.wikipedia.org/wiki/Python_(programming_language)
|
||||
(the name of the programming language Python is derived from Monty Python).
|
||||
|
||||
The shape of [prog.c](%%REPO_URL%%/2018/endoh2/prog.c) is "Undead Parrot" based on "dead parrot". The
|
||||
|
||||
+2
-2
@@ -415,8 +415,8 @@ of the <a href="poikola/index.html">Most stellar - 2018/poikola</a>.</p>
|
||||
<p>The <a href="endoh2/index.html">Best use of python - 2018/endoh2</a> is a not what you might think it is.
|
||||
It is something completely different.</p>
|
||||
<p>The <a href="ciura/index.html">Most likely to be awarded - 2018/ciura</a> has an amazing vocabulary!</p>
|
||||
<p>There are also nods to entries of the years <a href="2000/bellard/index.html">2000/bellard</a>,
|
||||
<a href="1989/yang/index.html">1989/yang</a>, …</p>
|
||||
<p>There are also nods to entries of the years <a href="../2000/bellard/index.html">2000/bellard</a>,
|
||||
<a href="../1989/yang/index.html">1989/yang</a>, …</p>
|
||||
<p>…We’ll stop spouting spoilers now. Have fun exploring all the entries!</p>
|
||||
<h2 id="remarks-on-some-of-submissions-that-did-not-win">Remarks on some of submissions that did not win</h2>
|
||||
<p>The number of entries that would have made it into the final rounds
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ These nods to not run afoul of the guideline:
|
||||
are rather similar to previous entries
|
||||
```
|
||||
|
||||
because the entry [2019/dogon](2019/dogon/index.html) appropriately pays homage
|
||||
because the entry [2019/dogon](dogon/index.html) appropriately pays homage
|
||||
to past entries without blatantly reusing their code.
|
||||
|
||||
...We'll stop spouting spoilers now. Have fun exploring all the entries!
|
||||
|
||||
+1
-1
@@ -412,7 +412,7 @@ vocabulary!</p>
|
||||
<pre><code> We tend to dislike programs that:
|
||||
...
|
||||
are rather similar to previous entries</code></pre>
|
||||
<p>because the entry <a href="2019/dogon/index.html">2019/dogon</a> appropriately pays homage
|
||||
<p>because the entry <a href="dogon/index.html">2019/dogon</a> appropriately pays homage
|
||||
to past entries without blatantly reusing their code.</p>
|
||||
<p>…We’ll stop spouting spoilers now. Have fun exploring all the entries!</p>
|
||||
<h2 id="remarks-on-some-of-submissions-that-did-not-win">Remarks on some of submissions that did not win</h2>
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ For some reason, this year's set of winning entries contains three nostalgic gam
|
||||
and [Snake - 2020/ferguson1](ferguson1/index.html).
|
||||
|
||||
An entry, [kurdyukov1](kurdyukov1/index.html), pays homage to previous entry
|
||||
[2015/hou](2015/hou/index.html).
|
||||
[2015/hou](../2015/hou/index.html).
|
||||
|
||||
...We'll stop spouting spoilers now. Have fun exploring all the entries!
|
||||
|
||||
|
||||
+1
-1
@@ -405,7 +405,7 @@ IOCCC list!</p>
|
||||
<a href="tsoj/index.html">Asteroids - 2020/tsoj</a>, <a href="endoh1/index.html">Minesweeper - 2020/endoh1</a>,
|
||||
and <a href="ferguson1/index.html">Snake - 2020/ferguson1</a>.</p>
|
||||
<p>An entry, <a href="kurdyukov1/index.html">kurdyukov1</a>, pays homage to previous entry
|
||||
<a href="2015/hou/index.html">2015/hou</a>.</p>
|
||||
<a href="../2015/hou/index.html">2015/hou</a>.</p>
|
||||
<p>…We’ll stop spouting spoilers now. Have fun exploring all the entries!</p>
|
||||
<h2 id="remarks-on-some-of-submissions-that-did-not-win">Remarks on some of submissions that did not win</h2>
|
||||
<p>As a rule, we try to compile the entries on a variety of platforms. Quite a few
|
||||
|
||||
@@ -65,6 +65,7 @@ TAR_YEAR= bin/tar-year.sh
|
||||
GEN_STATUS= bin/gen-status.sh
|
||||
GEN_SITEMAP= bin/gen-sitemap.sh
|
||||
SORT_GITIGNORE= bin/sort.gitignore.sh
|
||||
FIND_MISSING_LINKS= bin/find-missing-links.sh
|
||||
|
||||
|
||||
#############
|
||||
@@ -241,7 +242,7 @@ indent.c:
|
||||
# simple want to examine, run / test winning IOCCC entries.
|
||||
|
||||
.PHONY: help genpath genfilelist verify_entry_files gen_authors gen_location gen_years \
|
||||
entry_index gen_top_html thanks gen_other_html quick_entry_index \
|
||||
find_missing_links entry_index gen_top_html thanks gen_other_html quick_entry_index \
|
||||
gen_year_index quick_www www \
|
||||
untar_entry_tarball untar_year_tarball \
|
||||
form_entry_tarball form_year_tarball tar \
|
||||
@@ -271,6 +272,7 @@ help:
|
||||
@echo "make gen_top_html - generate a number of the top level HTML files from markdown"
|
||||
@echo "make gen_status - generate status.json and status.html"
|
||||
@echo "make quick_entry_index - build winner index.html files that might be out of date"
|
||||
@echo "make find_missing_links - find markdown links to missing local files"
|
||||
@echo "make quick_www - generate html files more quickly, checking timestamps"
|
||||
@echo "make www - build html pages for web site"
|
||||
@echo
|
||||
@@ -335,6 +337,7 @@ genfilelist:
|
||||
verify_entry_files: ${ALL_RUN} ${CHK_ENTRY}
|
||||
@echo '=-=-=-=-= IOCCC begin make $@ =-=-=-=-='
|
||||
${ALL_RUN} -v 3 ${CHK_ENTRY}
|
||||
@echo '=-=-=-=-= IOCCC complete make $@ =-=-=-=-='
|
||||
|
||||
# sort .gitignore files according to rules in bin/sgi.sh
|
||||
#
|
||||
@@ -433,6 +436,13 @@ quick_entry_index quick_readme2index: ${ALL_RUN} ${QUICK_README2INDEX}
|
||||
${ALL_RUN} -v 3 ${QUICK_README2INDEX} -v 1
|
||||
@echo '=-=-=-=-= IOCCC complete make $@ =-=-=-=-='
|
||||
|
||||
# find markdown links to missing local files
|
||||
#
|
||||
find_missing_links:
|
||||
@echo '=-=-=-=-= IOCCC begin make $@ =-=-=-=-='
|
||||
${FIND_MISSING_LINKS} -v 1
|
||||
@echo '=-=-=-=-= IOCCC complete make $@ =-=-=-=-='
|
||||
|
||||
# do work to build HTML content for the web site
|
||||
#
|
||||
# This rule uses quick_entry_index, not slow_entry_index, so
|
||||
@@ -456,6 +466,7 @@ quick_www:
|
||||
${MAKE} gen_top_html
|
||||
${MAKE} gen_status
|
||||
${MAKE} quick_entry_index
|
||||
${MAKE} find_missing_links
|
||||
@echo '=-=-=-=-= IOCCC complete make $@ =-=-=-=-='
|
||||
|
||||
# do everything needed to build HTML content for the web site
|
||||
@@ -477,6 +488,7 @@ www:
|
||||
${MAKE} gen_top_html
|
||||
${MAKE} gen_status
|
||||
${MAKE} entry_index
|
||||
${MAKE} find_missing_links
|
||||
@echo '=-=-=-=-= IOCCC complete make $@ =-=-=-=-='
|
||||
|
||||
# untar all entry tarballs
|
||||
|
||||
@@ -75,6 +75,37 @@ For example:
|
||||
```
|
||||
|
||||
|
||||
### [find-missing-links.sh](%%DOCROOT_SLASH%%bin/find-missing-links.sh)
|
||||
|
||||
Find all markdown links to local files that do not exist.
|
||||
|
||||
This tool does **NOT** check of a remote URL exists.
|
||||
This tool only checks on links to local files.
|
||||
|
||||
This tool does **NOT** check links into a given place in a file.
|
||||
This tool only checks that local files linked by markdown exist.
|
||||
|
||||
This tool does **NOT** check HTML file links.
|
||||
This tool only checks markdown based links.
|
||||
|
||||
Usage:
|
||||
|
||||
``` <!---sh-->
|
||||
bin/find-missing-links.sh -v 1
|
||||
```
|
||||
|
||||
If no missing links are found, this tool exits 0 with no output
|
||||
(debug messages not withstanding), otherwise this tool will exit non-zero.
|
||||
|
||||
NOTE: If the markdown link is malformed, this tool
|
||||
might generate an error about a file that does exist.
|
||||
If this tool claims that a file is missing that does exist,
|
||||
look for a malformed markdown line and/or use of markdown
|
||||
that is **NOT** an IOCCC markdown best practice.
|
||||
|
||||
See [IOCCC markdown best practices](markdown.html) for more info.
|
||||
|
||||
|
||||
### [gen-authors.sh](%%DOCROOT_SLASH%%bin/gen-authors.sh)
|
||||
|
||||
Generate the top level `/authors.html` page.
|
||||
|
||||
Executable
+532
@@ -0,0 +1,532 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# find-missing-links.sh - find markdown links to missing local files
|
||||
#
|
||||
# Find all markdown links to local files that do not exist.
|
||||
#
|
||||
# This tool does **NOT** check of a remote URL exists.
|
||||
# This tool only checks on links to local files.
|
||||
#
|
||||
# This tool does **NOT** check links into a given place in a file.
|
||||
# This tool only checks that local files linked by markdown exist.
|
||||
#
|
||||
# This tool does **NOT** check HTML file links.
|
||||
# This tool only checks markdown based links.
|
||||
#
|
||||
# NOTE: If the markdown link is malformed, this tool
|
||||
# might generate an error about a file that does exist.
|
||||
# If this tool claims that a file is missing that does exist,
|
||||
# look for a malformed markdown line and/or use of markdown
|
||||
# that is **NOT** an IOCCC markdown best practice.
|
||||
#
|
||||
# See the IOCCC markdown best practices file, markdown.html, for more info.
|
||||
#
|
||||
# Copyright (c) 2024 by Landon Curt Noll. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and
|
||||
# its documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright, this permission notice and text
|
||||
# this comment, and the disclaimer below appear in all of the following:
|
||||
#
|
||||
# supporting documentation
|
||||
# source copies
|
||||
# source works derived from this source
|
||||
# binaries derived from this source or from derived source
|
||||
#
|
||||
# LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
||||
# EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# chongo (Landon Curt Noll, http://www.isthe.com/chongo/index.html) /\oo/\
|
||||
#
|
||||
# Share and enjoy! :-)
|
||||
|
||||
# firewall - run only with a bash that is version 5.1.8 or later
|
||||
#
|
||||
# The "/usr/bin/env bash" command must result in using a bash that
|
||||
# is version 5.1.8 or later.
|
||||
#
|
||||
# We could relax this version and insist on version 4.2 or later. Versions
|
||||
# of bash between 4.2 and 5.1.7 might work. However, to be safe, we will require
|
||||
# bash version 5.1.8 or later.
|
||||
#
|
||||
# WHY 5.1.8 and not 4.2? This safely is done because macOS Homebrew bash we
|
||||
# often use is "version 5.2.26(1)-release" or later, and the RHEL Linux bash we
|
||||
# use often use is "version 5.1.8(1)-release" or later. These versions are what
|
||||
# we initially tested. We recommend you either upgrade bash or install a newer
|
||||
# version of bash and adjust your $PATH so that "/usr/bin/env bash" finds a bash
|
||||
# that is version 5.1.8 or later.
|
||||
#
|
||||
# NOTE: The macOS shipped, as of 2024 March 15, a version of bash is something like
|
||||
# bash "version 3.2.57(1)-release". That macOS shipped version of bash
|
||||
# will NOT work. For users of macOS we recommend you install Homebrew,
|
||||
# (see https://brew.sh), and then run "brew install bash" which will
|
||||
# typically install it into /opt/homebrew/bin/bash, and then arrange your $PATH
|
||||
# so that "/usr/bin/env bash" finds "/opt/homebrew/bin" (or whatever the
|
||||
# Homebrew bash is).
|
||||
#
|
||||
# NOTE: And while MacPorts might work, we noticed a number of subtle differences
|
||||
# with some of their ported tools to suggest you might be better off
|
||||
# with installing Homebrew (see https://brew.sh). No disrespect is intended
|
||||
# to the MacPorts team as they do a commendable job. Nevertheless we ran
|
||||
# into enough differences with MacPorts environments to suggest you
|
||||
# might find a better experience with this tool under Homebrew instead.
|
||||
#
|
||||
if [[ -z ${BASH_VERSINFO[0]} ||
|
||||
${BASH_VERSINFO[0]} -lt 5 ||
|
||||
${BASH_VERSINFO[0]} -eq 5 && ${BASH_VERSINFO[1]} -lt 1 ||
|
||||
${BASH_VERSINFO[0]} -eq 5 && ${BASH_VERSINFO[1]} -eq 1 && ${BASH_VERSINFO[2]} -lt 8 ]]; then
|
||||
echo "$0: ERROR: bash version needs to be >= 5.1.8: $BASH_VERSION" 1>&2
|
||||
echo "$0: Warning: bash version >= 4.2 might work but 5.1.8 was the minimum we tested" 1>&2
|
||||
echo "$0: Notice: For macOS users: install Homebrew (see https://brew.sh), then run" \
|
||||
""brew install bash" and then modify your \$PATH so that \"#!/usr/bin/env bash\"" \
|
||||
"finds the Homebrew installed (usually /opt/homebrew/bin/bash) version of bash" 1>&2
|
||||
exit 4
|
||||
fi
|
||||
|
||||
|
||||
# setup bash file matching
|
||||
#
|
||||
# We must declare arrays with -ag or -Ag, and we need loops to "export" modified variables.
|
||||
# This requires a bash with a version 4.2 or later. See the larger comment above about bash versions.
|
||||
#
|
||||
shopt -s nullglob # enable expanded to nothing rather than remaining unexpanded
|
||||
shopt -u failglob # disable error message if no matches are found
|
||||
shopt -u dotglob # disable matching files starting with .
|
||||
shopt -u nocaseglob # disable strict case matching
|
||||
shopt -u extglob # enable extended globbing patterns
|
||||
shopt -s globstar # enable ** to match all files and zero or more directories and subdirectories
|
||||
|
||||
# set variables referenced in the usage message
|
||||
#
|
||||
export VERSION="1.0 2024-04-28"
|
||||
NAME=$(basename "$0")
|
||||
export NAME
|
||||
export V_FLAG=0
|
||||
GIT_TOOL=$(type -P git)
|
||||
export GIT_TOOL
|
||||
if [[ -z "$GIT_TOOL" ]]; then
|
||||
echo "$0: FATAL: git tool is not installed or not in \$PATH" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
"$GIT_TOOL" rev-parse --is-inside-work-tree >/dev/null 2>&1
|
||||
status="$?"
|
||||
if [[ $status -eq 0 ]]; then
|
||||
TOPDIR=$("$GIT_TOOL" rev-parse --show-toplevel)
|
||||
fi
|
||||
export TOPDIR
|
||||
|
||||
|
||||
# usage
|
||||
#
|
||||
export USAGE="usage: $0 [-h] [-v level] [-V] [-d topdir]
|
||||
|
||||
-h print help message and exit
|
||||
-v level set verbosity level (def level: 0)
|
||||
-V print version string and exit
|
||||
|
||||
-d topdir set topdir (def: $TOPDIR)
|
||||
|
||||
Exit codes:
|
||||
0 all OK
|
||||
1 missing links found
|
||||
2 -h and help string printed or -V and version string printed
|
||||
3 command line error
|
||||
4 bash version is too old
|
||||
6 problems found with or in the topdir or topdir/YYYY directory
|
||||
7 problems found with or in the entry topdir/YYYY/dir directory
|
||||
>= 10 internal error
|
||||
|
||||
$NAME version: $VERSION"
|
||||
|
||||
|
||||
# fast_dirname - perform dirname(1) without calling a command
|
||||
#
|
||||
# This is very similar with dirname(1) except it is much faster.
|
||||
#
|
||||
# usage:
|
||||
# fast_dirname path_name
|
||||
#
|
||||
# path to obtain the directory from
|
||||
#
|
||||
function fast_dirname
|
||||
{
|
||||
local PATH_NAME; # path_name argument to be modified
|
||||
|
||||
# parse args
|
||||
#
|
||||
if [[ $# -ne 1 ]]; then
|
||||
echo "$0: ERROR: in fast_dirname: debug_parameters requires 1 arg, found: $#" 1>&2
|
||||
exit 10
|
||||
fi
|
||||
PATH_NAME="$1"
|
||||
|
||||
# firewall - reject empty paths
|
||||
#
|
||||
if [[ -z $PATH_NAME ]]; then
|
||||
echo "$0: ERROR: in fast_dirname: pathname arg is empty" 1>&2
|
||||
exit 11
|
||||
fi
|
||||
|
||||
# reduce multiple consecutive /'s to just /
|
||||
#
|
||||
while :; do
|
||||
case "$PATH_NAME" in
|
||||
*//*) PATH_NAME="${PATH_NAME//\/\//\/}" ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# trim any trailing /
|
||||
#
|
||||
PATH_NAME=${PATH_NAME%%/}
|
||||
|
||||
# case: if we only had /'s return /
|
||||
#
|
||||
if [[ -z "$PATH_NAME" ]]; then
|
||||
echo '/'
|
||||
return;
|
||||
fi
|
||||
|
||||
# case: PATH_NAME is an absolute path starting with /
|
||||
#
|
||||
case "$PATH_NAME" in
|
||||
/*) echo "${PATH_NAME%/*}"; return ;;
|
||||
*/*) echo "${PATH_NAME%/*}"; return ;;
|
||||
*) echo '.'; return ;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
# parse command line
|
||||
#
|
||||
while getopts :hv:Vd:nN flag; do
|
||||
case "$flag" in
|
||||
h) echo "$USAGE" 1>&2
|
||||
exit 2
|
||||
;;
|
||||
v) V_FLAG="$OPTARG"
|
||||
;;
|
||||
V) echo "$VERSION"
|
||||
exit 2
|
||||
;;
|
||||
d) TOPDIR="$OPTARG"
|
||||
;;
|
||||
\?) echo "$0: ERROR: invalid option: -$OPTARG" 1>&2
|
||||
echo 1>&2
|
||||
print_usage 1>&2
|
||||
exit 3
|
||||
;;
|
||||
:) echo "$0: ERROR: option -$OPTARG requires an argument" 1>&2
|
||||
echo 1>&2
|
||||
echo "$USAGE" 1>&2
|
||||
exit 3
|
||||
;;
|
||||
*) echo "$0: ERROR: unexpected value from getopts: $flag" 1>&2
|
||||
echo 1>&2
|
||||
echo "$USAGE" 1>&2
|
||||
exit 3
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# remove the options
|
||||
#
|
||||
shift $(( OPTIND - 1 ));
|
||||
#
|
||||
if [[ $V_FLAG -ge 5 ]]; then
|
||||
echo "$0: debug[5]: file argument count: $#" 1>&2
|
||||
fi
|
||||
#
|
||||
# verify arg count and parse args
|
||||
#
|
||||
export TOOL
|
||||
case "$#" in
|
||||
0) ;;
|
||||
*) echo "$0: ERROR: expected 0 args, found: $#" 1>&2
|
||||
echo "$USAGE" 1>&2
|
||||
exit 3
|
||||
;;
|
||||
esac
|
||||
#
|
||||
if [[ $V_FLAG -ge 1 ]]; then
|
||||
echo "$0: debug[1]: start scan for missing links" 1>&2
|
||||
fi
|
||||
|
||||
# print running info if verbose
|
||||
#
|
||||
# If -v 3 or higher, print exported variables in order that they were exported.
|
||||
#
|
||||
if [[ $V_FLAG -ge 3 ]]; then
|
||||
echo "$0: debug[3]: VERSION=$VERSION" 1>&2
|
||||
echo "$0: debug[3]: NAME=$NAME" 1>&2
|
||||
echo "$0: debug[3]: V_FLAG=$V_FLAG" 1>&2
|
||||
echo "$0: debug[3]: GIT_TOOL=$GIT_TOOL" 1>&2
|
||||
echo "$0: debug[3]: TOPDIR=$TOPDIR" 1>&2
|
||||
fi
|
||||
|
||||
|
||||
# cd to topdir
|
||||
#
|
||||
if [[ ! -e $TOPDIR ]]; then
|
||||
echo "$0: ERROR: cannot cd to non-existent path: $TOPDIR" 1>&2
|
||||
exit 6
|
||||
fi
|
||||
if [[ ! -d $TOPDIR ]]; then
|
||||
echo "$0: ERROR: cannot cd to a non-directory: $TOPDIR" 1>&2
|
||||
exit 6
|
||||
fi
|
||||
export CD_FAILED
|
||||
if [[ $V_FLAG -ge 5 ]]; then
|
||||
echo "$0: debug[5]: about to: cd $TOPDIR" 1>&2
|
||||
fi
|
||||
cd "$TOPDIR" || CD_FAILED="true"
|
||||
if [[ -n $CD_FAILED ]]; then
|
||||
echo "$0: ERROR: cd $TOPDIR failed" 1>&2
|
||||
exit 6
|
||||
fi
|
||||
if [[ $V_FLAG -ge 3 ]]; then
|
||||
echo "$0: debug[3]: now in directory: $(/bin/pwd)" 1>&2
|
||||
fi
|
||||
|
||||
|
||||
# create a temporary missing link error message file
|
||||
#
|
||||
export TMP_MISSING_LINK=".$NAME.$$.missing_link.md"
|
||||
if [[ $V_FLAG -ge 3 ]]; then
|
||||
echo "$0: debug[3]: temporary missing link error message file: $TMP_MISSING_LINK" 1>&2
|
||||
fi
|
||||
if [[ -z $NOOP ]]; then
|
||||
trap 'rm -f $TMP_MISSING_LINK; exit' 0 1 2 3 15
|
||||
rm -f "$TMP_MISSING_LINK"
|
||||
if [[ -e $TMP_MISSING_LINK ]]; then
|
||||
echo "$0: ERROR: cannot remove temporary missing link error message file: $TMP_MISSING_LINK" 1>&2
|
||||
exit 12
|
||||
fi
|
||||
:> "$TMP_MISSING_LINK"
|
||||
if [[ ! -e $TMP_MISSING_LINK ]]; then
|
||||
echo "$0: ERROR: cannot create temporary missing link error message file: $TMP_MISSING_LINK" 1>&2
|
||||
exit 13
|
||||
fi
|
||||
elif [[ $V_FLAG -ge 3 ]]; then
|
||||
echo "$0: debug[3]: because of -n, temporary missing link error message file is not used: $TMP_MISSING_LINK" 1>&2
|
||||
fi
|
||||
|
||||
|
||||
# collect markdown links
|
||||
#
|
||||
# Here be extended regular expression magic dragons! :-)
|
||||
#
|
||||
# We will try to explain, as best as we can, these complex regular expressions.
|
||||
#
|
||||
# After grep of markdown files (files in sorted dictionary order) for markdown line lines, we sed:
|
||||
#
|
||||
# # remove any "[some string]" that is not immediately followed by "("
|
||||
#
|
||||
# -e 's/\[[^]]*\]([^(])/\1/' \
|
||||
#
|
||||
# # remove any trialing "[followed by text without a closing bracket"
|
||||
#
|
||||
# -e 's/\[[^]]*$//' \
|
||||
#
|
||||
# Then processing the second file (after the filename field) we sed:
|
||||
#
|
||||
# # remove any leading "..non-[-stuff..["
|
||||
#
|
||||
# -e 's/^[^[]()+\[/[/' \
|
||||
#
|
||||
# # replace "beginning text stuff](" with "[text stuff]("
|
||||
# # because the previous line might have ended with "[beginning"
|
||||
#
|
||||
# -e 's/^([^][]*\]\()/[\1/g' \
|
||||
#
|
||||
# # remove any "[..non-]-stuff..][..more-non-]-stuff..]"
|
||||
#
|
||||
# -e 's/(\[[^][]*\])+([^(])/\2/g' \
|
||||
#
|
||||
# # remove any non-link before the first "[some string](path)"
|
||||
#
|
||||
# -e 's/^[^][]+(\[[^]]*\]\([^(]*\))/\1/' \
|
||||
#
|
||||
# # remove any final "[..non-]-stuff..$"
|
||||
#
|
||||
# -e 's/\[[^]]*$//' \
|
||||
#
|
||||
# # remove any final "(..non-)-stuff..)..non-[-stuff.."
|
||||
#
|
||||
# -e 's/(\([^)]*\))[^[]*$/\1/' \
|
||||
#
|
||||
# # remove any trailing non-[-text after the final "[some string](path)"
|
||||
#
|
||||
# -e 's/(\[[^]]*\]\([^(]*\))[^[]+$/\1/' \
|
||||
#
|
||||
# # replace ")..non-open-bracket-stuff.[" with ") ["
|
||||
#
|
||||
# -e 's/\)[^[]*\[/) [/g' \
|
||||
#
|
||||
# # replace "[some string](apath) [other string](bpath)" with two lines:
|
||||
# #
|
||||
# # "[some string](apath)"
|
||||
# # "[other string](bpath)"
|
||||
#
|
||||
# -e 's/(\[[^]]*\]\([^(]*\))/\1\n/g' \
|
||||
#
|
||||
# # remove blank and empty lines
|
||||
#
|
||||
# -e '/^\s*$/d' \
|
||||
#
|
||||
# Then pipe the lines into another sed:
|
||||
#
|
||||
# # replace multiple space with a single space
|
||||
#
|
||||
# -e 's/ +/ /g' \
|
||||
#
|
||||
# # remove the leading "[pseudo title]("
|
||||
#
|
||||
# -e 's/\[[^]]*\]\(//' \
|
||||
#
|
||||
# # remove trailing ")":
|
||||
#
|
||||
# -e 's/\)$//' \
|
||||
#
|
||||
# # remove and trailing #name
|
||||
#
|
||||
# -e 's/#.*$//' \
|
||||
#
|
||||
# # remove any leading whitespace
|
||||
#
|
||||
# -e 's/^ //' \
|
||||
#
|
||||
# # remove blank and empty lines
|
||||
#
|
||||
# -e '/^\s*$/d' \
|
||||
#
|
||||
# # delete all http: and https: URLs
|
||||
#
|
||||
# -e '/^https?:/d' \
|
||||
#
|
||||
# # delete all mailto: URLs
|
||||
#
|
||||
# -e '/^mailto:/d' \
|
||||
#
|
||||
#
|
||||
# -e 's;%%DOCROOT_SLASH%%/*;/;' \
|
||||
#
|
||||
# # add current directory in front of absolute paths
|
||||
#
|
||||
# -e "s;^/;$PWD;" \
|
||||
#
|
||||
# # add current directory followed by / in front of relative paths
|
||||
#
|
||||
# -e "s;^([^/]);$PWD/\1;" \
|
||||
#
|
||||
# # convert "%%REPO_URL%%/" into TOPDIR
|
||||
#
|
||||
# -e "s;%%REPO_URL%%/*;$TOPDIR/;" \
|
||||
#
|
||||
# # convert "%%DOCROOT_SLASH%%" into TOPDIR
|
||||
#
|
||||
# -e "s;%%DOCROOT_SLASH%%/*;$TOPDIR/;" \
|
||||
#
|
||||
# # relative paths have the directory of the markdown file added to them
|
||||
#
|
||||
# -e "s;^([^/]);$TOPDIR/$MD_DIR/\1;" \
|
||||
#
|
||||
# # delete all lines containing "%%TOKEN%%" as this is a just a test/example token
|
||||
#
|
||||
# -e '/%%TOKEN%%/d' \
|
||||
#
|
||||
# At this point in the pipe, we have absolute /-based paths to markdown linked local files.
|
||||
# We test if those file exist, and if not report a problem in the form:
|
||||
#
|
||||
# # Missing file linked in: markdown_file_name.md
|
||||
# # Markdown line: ..the markdown line containing the line..
|
||||
# /missing/filename
|
||||
#
|
||||
find . -name '*.md' ! -name markdown.md ! -path './tmp/*' -print |
|
||||
LANG=C sort -d |
|
||||
xargs grep '\]([^)][^)]*)' /dev/null |
|
||||
sed -E \
|
||||
-e 's;^\.\/;;' \
|
||||
-e 's/^([^:]+):\s*/\1 /' \
|
||||
|
|
||||
while read -r MD_PATH MD_LINE; do
|
||||
|
||||
# note directory containing the markdown file
|
||||
#
|
||||
MD_DIR=$(fast_dirname "$MD_PATH")
|
||||
export MD_DIR
|
||||
|
||||
# extract markdown parts from the given markdown file
|
||||
#
|
||||
echo "$MD_LINE" |
|
||||
sed -E \
|
||||
-e 's/^[^[]()+\[/[/' \
|
||||
-e 's/^([^][]*\]\()/[\1/g' \
|
||||
-e 's/(\[[^][]*\])+([^(])/\2/g' \
|
||||
-e 's/^[^][]+(\[[^]]*\]\([^(]*\))/\1/' \
|
||||
-e 's/\[[^]]*$//' \
|
||||
-e 's/(\([^)]*\))[^[]*$/\1/' \
|
||||
-e 's/(\[[^]]*\]\([^(]*\))[^[]+$/\1/' \
|
||||
-e 's/\)[^[]*\[/) [/g' \
|
||||
-e 's/(\[[^]]*\]\([^(]*\))/\1\n/g' \
|
||||
-e '/^\s*$/d' \
|
||||
|
|
||||
sed -E \
|
||||
-e 's/ +/ /g' \
|
||||
-e 's/\[[^]]*\]\(//' \
|
||||
-e 's/\)$//' \
|
||||
-e 's/#.*$//' \
|
||||
-e 's/^ //' \
|
||||
-e '/^\s*$/d' \
|
||||
-e '/^https?:/d' \
|
||||
-e '/^mailto:/d' \
|
||||
-e "s;%%REPO_URL%%/*;$TOPDIR/;" \
|
||||
-e "s;%%DOCROOT_SLASH%%/*;$TOPDIR/;" \
|
||||
-e "s;^([^/]);$TOPDIR/$MD_DIR/\1;" \
|
||||
-e '/%%TOKEN%%/d' \
|
||||
|
|
||||
|
||||
# write to stderr, missing file messages
|
||||
#
|
||||
# The absolute path is written to stderr, while
|
||||
# info about the possible cause is written to stderr with lines starting with #
|
||||
#
|
||||
# We output exact 4 lines per missing link.
|
||||
#
|
||||
while read -r ABS_LOCAL_FILE_PATH; do
|
||||
if [[ ! -e $ABS_LOCAL_FILE_PATH ]]; then
|
||||
echo "# Missing file linked in: $MD_PATH"
|
||||
echo "# Markdown line: $MD_LINE"
|
||||
echo "$ABS_LOCAL_FILE_PATH"
|
||||
echo
|
||||
fi
|
||||
done
|
||||
done > "$TMP_MISSING_LINK"
|
||||
|
||||
# count the missing links
|
||||
#
|
||||
MISSING_LINK_COUNT=$(wc -l < "$TMP_MISSING_LINK" | tr -d ' ')
|
||||
export MISSING_LINK_COUNT
|
||||
((MISSING_LINK_COUNT=MISSING_LINK_COUNT/4))
|
||||
|
||||
# report on any missing links
|
||||
#
|
||||
if [[ -s $TMP_MISSING_LINK ]]; then
|
||||
cat "$TMP_MISSING_LINK" 1>&2
|
||||
fi
|
||||
|
||||
# All Done!!! -- Jessica Noll, Age 2
|
||||
#
|
||||
if [[ -s $TMP_MISSING_LINK ]]; then
|
||||
echo "$0: ERROR: $MISSING_LINK_COUNT missing link(s) found" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ $V_FLAG -ge 1 ]]; then
|
||||
echo "$0: debug[1]: $MISSING_LINK_COUNT missing link(s) found" 1>&2
|
||||
fi
|
||||
exit 0
|
||||
@@ -409,6 +409,24 @@ repo</a>.</p>
|
||||
<p>Generate the list of files in the entry’s manifest, <code>.entry.json</code>.</p>
|
||||
<p>For example:</p>
|
||||
<pre><code> awk -f bin/filelist.entry.json.awk 2020/ferguson1/.entry.json</code></pre>
|
||||
<h3 id="find-missing-links.sh"><a href="../bin/find-missing-links.sh">find-missing-links.sh</a></h3>
|
||||
<p>Find all markdown links to local files that do not exist.</p>
|
||||
<p>This tool does <strong>NOT</strong> check of a remote URL exists.
|
||||
This tool only checks on links to local files.</p>
|
||||
<p>This tool does <strong>NOT</strong> check links into a given place in a file.
|
||||
This tool only checks that local files linked by markdown exist.</p>
|
||||
<p>This tool does <strong>NOT</strong> check HTML file links.
|
||||
This tool only checks markdown based links.</p>
|
||||
<p>Usage:</p>
|
||||
<pre><code> bin/find-missing-links.sh -v 1</code></pre>
|
||||
<p>If no missing links are found, this tool exits 0 with no output
|
||||
(debug messages not withstanding), otherwise this tool will exit non-zero.</p>
|
||||
<p>NOTE: If the markdown link is malformed, this tool
|
||||
might generate an error about a file that does exist.
|
||||
If this tool claims that a file is missing that does exist,
|
||||
look for a malformed markdown line and/or use of markdown
|
||||
that is <strong>NOT</strong> an IOCCC markdown best practice.</p>
|
||||
<p>See <a href="markdown.html">IOCCC markdown best practices</a> for more info.</p>
|
||||
<h3 id="gen-authors.sh"><a href="../bin/gen-authors.sh">gen-authors.sh</a></h3>
|
||||
<p>Generate the top level <code>/authors.html</code> page.</p>
|
||||
<p>Usage:</p>
|
||||
|
||||
@@ -1981,7 +1981,7 @@ remarks and always the author’s or authors’ remarks, you look at the origina
|
||||
code. When the entry source code is called <code>prog.c</code> the original code is in
|
||||
<code>prog.orig.c</code>; otherwise it is <code>dirname.orig.c</code>. For instance one of Landon’s all
|
||||
time favourite entries is <a href="1984/mullender/index.html">1984/mullender</a> and the
|
||||
original code is in <a href="1984/mullender/mullender.orig.c">mullender.orig.c</a>. In
|
||||
original code is in <a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1984/mullender/mullender.orig.c">mullender.orig.c</a>. In
|
||||
some cases, such as <code>1984/mullender</code>, the original code is the same as the code
|
||||
as no changes were made (there is an alt version for systems that are not
|
||||
VAX-11/PDP-11, however).</p>
|
||||
@@ -2219,7 +2219,7 @@ longer fit within the year’s size restrictions. Invariably the length of colum
|
||||
and/or number of rows have also changed.</p>
|
||||
<p>The <code>winner.orig.c</code> file contains the original source code that was
|
||||
subjected to rule 2 of the given IOCCC. You may also wish to see
|
||||
the <a href="archive">/archive</a> directory where you can find all the
|
||||
the <a href="archive">archive</a> directory where you can find all the
|
||||
original winning entries as compressed tar files for a given year.</p>
|
||||
<p>In some cases the entry may have abused rule 2 and declared an
|
||||
“abuse of the rules” (although now blatant abuse of the rules to
|
||||
@@ -2314,7 +2314,7 @@ author.</p>
|
||||
<p>The latter form is in case there are more than one anonymous author in a given
|
||||
year.</p>
|
||||
<p>NOTE: even if the directory name is not <code>anonymous</code> the above rules apply as in
|
||||
in the case of <a href="2005/anon/anon.c">2005/anon</a>.</p>
|
||||
in the case of <a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2005/anon/anon.c">2005/anon</a>.</p>
|
||||
<p>Anonymous <code>author_handle</code>’s match this regexp:</p>
|
||||
<pre><code> Anonymous_[0-9][0-9][0-9][0-9][.0-9]*$</code></pre>
|
||||
<p>See <a href="#fix_author">FAQ 5.5</a> for information about how to update
|
||||
@@ -2619,7 +2619,7 @@ of IOCCC years.</p>
|
||||
of the IOCCC entry directories for a given year. For example, see the <a href=".1984/.year">1984/.year</a> file.</p>
|
||||
<p>Under each IOCCC entry directory, you will find a <code>.path</code> file.
|
||||
These files contain the directory path from the top directory.
|
||||
For example see <a href="1984/anonymous/.path">1984/anonymous/.path</a>.</p>
|
||||
For example see <a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1984/anonymous/.path">1984/anonymous/.path</a>.</p>
|
||||
<p>The .top, .year and .path files are generated from the top level Makefile, by:</p>
|
||||
<pre><code> make genpath</code></pre>
|
||||
<div id="faq6_9">
|
||||
@@ -2735,7 +2735,7 @@ it will be that. For instance using the above example you might do:</p>
|
||||
<h4 id="making-changes-fixes-etc.">Making changes, fixes etc.</h4>
|
||||
<p>Here you must use your wits, knowledge, creativity and whatever else you have.
|
||||
Let’s say that Cody wants to update his file
|
||||
<a href="2020/ferguson1/play.sh">/2020/ferguson1/play.sh</a> script. He would open it in
|
||||
<a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2020/ferguson1/play.sh">2020/ferguson1/play.sh</a> script. He would open it in
|
||||
his editor of choice (in his case vim) and make the changes. He would then make
|
||||
sure (as there is a last updated date) to update the last updated date. For
|
||||
instance he might add the following:</p>
|
||||
@@ -2767,7 +2767,7 @@ with your ssh key. To do this you need to do:</p>
|
||||
<p>Now you’d be ready to make your commits.</p>
|
||||
<p>Before doing anything else, however, a new branch needs to be created.
|
||||
Continuing the example above for
|
||||
<a href="2020/ferguson1/play.sh">2020/ferguson1/play.sh</a>, it might be that:</p>
|
||||
<a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/2020/ferguson1/play.sh">2020/ferguson1/play.sh</a>, it might be that:</p>
|
||||
<pre><code> git checkout -B human-snakes</code></pre>
|
||||
<p>This would change the branch to the newly created branch <code>human-snakes</code> branch.
|
||||
Now Cody could commit the changes:</p>
|
||||
|
||||
@@ -2344,7 +2344,7 @@ remarks and always the author's or authors' remarks, you look at the original
|
||||
code. When the entry source code is called `prog.c` the original code is in
|
||||
`prog.orig.c`; otherwise it is `dirname.orig.c`. For instance one of Landon's all
|
||||
time favourite entries is [1984/mullender](1984/mullender/index.html) and the
|
||||
original code is in [mullender.orig.c](1984/mullender/mullender.orig.c). In
|
||||
original code is in [mullender.orig.c](%%REPO_URL%%/1984/mullender/mullender.orig.c). In
|
||||
some cases, such as `1984/mullender`, the original code is the same as the code
|
||||
as no changes were made (there is an alt version for systems that are not
|
||||
VAX-11/PDP-11, however).
|
||||
@@ -2675,7 +2675,7 @@ and/or number of rows have also changed.
|
||||
|
||||
The `winner.orig.c` file contains the original source code that was
|
||||
subjected to rule 2 of the given IOCCC. You may also wish to see
|
||||
the [/archive](archive) directory where you can find all the
|
||||
the [archive](archive) directory where you can find all the
|
||||
original winning entries as compressed tar files for a given year.
|
||||
|
||||
In some cases the entry may have abused rule 2 and declared an
|
||||
@@ -2817,7 +2817,7 @@ The latter form is in case there are more than one anonymous author in a given
|
||||
year.
|
||||
|
||||
NOTE: even if the directory name is not `anonymous` the above rules apply as in
|
||||
in the case of [2005/anon](2005/anon/anon.c).
|
||||
in the case of [2005/anon](%%REPO_URL%%/2005/anon/anon.c).
|
||||
|
||||
Anonymous `author_handle`'s match this regexp:
|
||||
|
||||
@@ -3352,7 +3352,7 @@ of the IOCCC entry directories for a given year. For example, see the [1984/.ye
|
||||
|
||||
Under each IOCCC entry directory, you will find a `.path` file.
|
||||
These files contain the directory path from the top directory.
|
||||
For example see [1984/anonymous/.path](1984/anonymous/.path).
|
||||
For example see [1984/anonymous/.path](%%REPO_URL%%/1984/anonymous/.path).
|
||||
|
||||
The .top, .year and .path files are generated from the top level Makefile, by:
|
||||
|
||||
@@ -3513,7 +3513,7 @@ You're ready to make your changes now!
|
||||
|
||||
Here you must use your wits, knowledge, creativity and whatever else you have.
|
||||
Let's say that Cody wants to update his file
|
||||
[/2020/ferguson1/play.sh](2020/ferguson1/play.sh) script. He would open it in
|
||||
[2020/ferguson1/play.sh](%%REPO_URL%%/2020/ferguson1/play.sh) script. He would open it in
|
||||
his editor of choice (in his case vim) and make the changes. He would then make
|
||||
sure (as there is a last updated date) to update the last updated date. For
|
||||
instance he might add the following:
|
||||
@@ -3563,7 +3563,7 @@ Now you'd be ready to make your commits.
|
||||
|
||||
Before doing anything else, however, a new branch needs to be created.
|
||||
Continuing the example above for
|
||||
[2020/ferguson1/play.sh](2020/ferguson1/play.sh), it might be that:
|
||||
[2020/ferguson1/play.sh](%%REPO_URL%%/2020/ferguson1/play.sh), it might be that:
|
||||
|
||||
|
||||
``` <!---sh-->
|
||||
|
||||
+30
-11
@@ -473,11 +473,24 @@ unquoted attribute values.</p>
|
||||
<pre><code> <del>...</del></code></pre>
|
||||
<h2 id="do-not-use-tt-html-elements">Do not use tt HTML elements</h2>
|
||||
<p>Please do not use the tt HTML elements:</p>
|
||||
<div class="sourceCode" id="cb16"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a> <span class="dt"><</span><span class="kw">tt</span><span class="dt">></span>The HTML 5 obsolete tt element is obsolete<span class="dt"></</span><span class="kw">tt</span><span class="dt">></span></span></code></pre></div>
|
||||
<div class="sourceCode" id="cb16"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a> <span class="dt"><</span><span class="kw">tt</span><span class="dt">></span>The HTML 5 obsolete tt element is obsolete<span class="dt"></</span><span class="kw">tt</span><span class="dt">></span> <span class="er"><</span>=== no thank you</span></code></pre></div>
|
||||
<p>Instead use either a monospaced span:</p>
|
||||
<div class="sourceCode" id="cb17"><pre class="sourceCode html"><code class="sourceCode html"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a> <span class="dt"><</span><span class="kw">span</span><span class="ot"> style</span><span class="op">=</span><span class="st">"font-family: monospace;"</span><span class="dt">></span>Use of monospaced font is one option<span class="dt"></</span><span class="kw">span</span><span class="dt">></span></span></code></pre></div>
|
||||
<p>Or better and easier still, use an inline markdown code block:</p>
|
||||
<pre><code> `inline markdown code block is easier and much better`</code></pre>
|
||||
<h2 id="do-not-use-un-indented-code-clocks">Do not use un-indented code clocks</h2>
|
||||
<p>Please do not start code blocks at the left-hand edge.</p>
|
||||
<pre><code>```
|
||||
This code block <=== no thank you
|
||||
is not indendted
|
||||
```
|
||||
```
|
||||
|
||||
We request that you indent the code block by 4 spaces:
|
||||
</code></pre>
|
||||
<pre><code> This code block
|
||||
is intented 4 spaces</code></pre>
|
||||
<p>````</p>
|
||||
<h2 id="do-not-add-trailing-slash-on-void-html-elements">Do not add trailing slash on void HTML elements</h2>
|
||||
<p>Please do not use trailing slash on <a href="https://github.com/validator/validator/wiki/Markup-»-Void-elements">void HTML
|
||||
elements</a>.</p>
|
||||
@@ -506,18 +519,24 @@ tags</a>.</p>
|
||||
<p>Markdown links that end in “))” complicate parsing and sometimes lead
|
||||
to incorrect URLs or file paths.</p>
|
||||
<p>Instead of:</p>
|
||||
<pre><code>[some text](https://example.com/foo_(bar)) <=== no thank you</code></pre>
|
||||
<pre><code> [some text](https://example.com/foo_(bar)) <=== no thank you</code></pre>
|
||||
<p>Use:</p>
|
||||
<pre><code>[some text](https://example.com/foo_&#x28;bar&#x29;)</code></pre>
|
||||
<pre><code> [some text](https://example.com/foo_&#x28;bar&#x29;)</code></pre>
|
||||
<p>Instead of:</p>
|
||||
<pre><code>This thing ([some text](some/path)) is not ideal. <=== no thank you
|
||||
``
|
||||
|
||||
Use:
|
||||
</code></pre>
|
||||
<p>This thing, <a href="some/path">some text</a>, is better.
|
||||
```
|
||||
<!-- AFTER: last line of markdown file: markdown.md --></p>
|
||||
<pre><code> This thing ([some text](some/path)) is not ideal. <=== no thank you</code></pre>
|
||||
<p>Use:</p>
|
||||
<pre><code> This thing, [some text](some/path), is better.</code></pre>
|
||||
<h2 id="do-not-put-s-or-markdown-link-titles">Do not put (‘s or )’ markdown link titles</h2>
|
||||
<p>Please do not use parenthesis inside the markdown link titles.</p>
|
||||
<p>Instead of:</p>
|
||||
<pre><code> [some (text)](https://example.com/cyrds) <=== no thank you</code></pre>
|
||||
<p>Use:</p>
|
||||
<pre><code> [some &#x28;text&#x29;](https://example.com/cyrds)</code></pre>
|
||||
<p>Instead of:</p>
|
||||
<pre><code> [ls(1)](https://example.com/ls-man-page.1) <=== no thank you</code></pre>
|
||||
<p>Use:</p>
|
||||
<pre><code> [ls&#x28;1&#x29;](https://example.com/ls-man-page.1)</code></pre>
|
||||
<!-- AFTER: last line of markdown file: markdown.md -->
|
||||
|
||||
<!-- END: this line ends content for HTML phase 21 by: bin/pandoc-wrapper.sh via bin/md2html.sh -->
|
||||
<!-- START: this line starts content from: inc/after-content.default.html -->
|
||||
|
||||
+57
-6
@@ -183,7 +183,7 @@ Use instead:
|
||||
Please do not use the tt HTML elements:
|
||||
|
||||
```html
|
||||
<tt>The HTML 5 obsolete tt element is obsolete</tt>
|
||||
<tt>The HTML 5 obsolete tt element is obsolete</tt> <=== no thank you
|
||||
```
|
||||
|
||||
Instead use either a monospaced span:
|
||||
@@ -199,6 +199,27 @@ Or better and easier still, use an inline markdown code block:
|
||||
```
|
||||
|
||||
|
||||
## Do not use un-indented code clocks
|
||||
|
||||
Please do not start code blocks at the left-hand edge.
|
||||
|
||||
````
|
||||
```
|
||||
This code block <=== no thank you
|
||||
is not indendted
|
||||
```
|
||||
```
|
||||
|
||||
We request that you indent the code block by 4 spaces:
|
||||
|
||||
````
|
||||
```
|
||||
This code block
|
||||
is intented 4 spaces
|
||||
```
|
||||
````
|
||||
|
||||
|
||||
## Do not add trailing slash on void HTML elements
|
||||
|
||||
Please do not use trailing slash on [void HTML
|
||||
@@ -251,6 +272,7 @@ Instead use just:
|
||||
|
||||
etc.
|
||||
|
||||
|
||||
## Do not end markdown links in ))
|
||||
|
||||
Please do not end a markdown links with a double closed parenthesis "))".
|
||||
@@ -261,23 +283,52 @@ to incorrect URLs or file paths.
|
||||
Instead of:
|
||||
|
||||
```
|
||||
[some text](https://example.com/foo_(bar)) <=== no thank you
|
||||
[some text](https://example.com/foo_(bar)) <=== no thank you
|
||||
```
|
||||
|
||||
Use:
|
||||
|
||||
```
|
||||
[some text](https://example.com/foo_(bar))
|
||||
[some text](https://example.com/foo_(bar))
|
||||
```
|
||||
|
||||
Instead of:
|
||||
|
||||
```
|
||||
This thing ([some text](some/path)) is not ideal. <=== no thank you
|
||||
``
|
||||
This thing ([some text](some/path)) is not ideal. <=== no thank you
|
||||
```
|
||||
|
||||
Use:
|
||||
|
||||
```
|
||||
This thing, [some text](some/path), is better.
|
||||
This thing, [some text](some/path), is better.
|
||||
```
|
||||
|
||||
|
||||
## Do not put ('s or )' markdown link titles
|
||||
|
||||
Please do not use parenthesis inside the markdown link titles.
|
||||
|
||||
Instead of:
|
||||
|
||||
```
|
||||
[some (text)](https://example.com/cyrds) <=== no thank you
|
||||
```
|
||||
|
||||
Use:
|
||||
|
||||
```
|
||||
[some (text)](https://example.com/cyrds)
|
||||
```
|
||||
|
||||
Instead of:
|
||||
|
||||
```
|
||||
[ls(1)](https://example.com/ls-man-page.1) <=== no thank you
|
||||
```
|
||||
|
||||
Use:
|
||||
|
||||
```
|
||||
[ls(1)](https://example.com/ls-man-page.1)
|
||||
```
|
||||
@@ -15,7 +15,7 @@ Nearly all of the [temp-test-ioccc web site](https://ioccc-src.github.io/temp-te
|
||||
web site has undergone editorial review. Nearly all [IOCCC winning entries](years.html)
|
||||
compile on modern systems and many have `try.sh` scripts to help you run them.
|
||||
For those that cannot compile and/or do not work, we have made a
|
||||
[Bugs and (Mis)features](bugs.html) page.
|
||||
[Bugs and (Mis)features](bugs.html) page.
|
||||
|
||||
We have made nearly 4823 changes to date!
|
||||
|
||||
|
||||
+1
-1
@@ -387,7 +387,7 @@
|
||||
"no_comment" : "mandatory comment: because comments were removed from the original JSON spec",
|
||||
"IOCCC_status_version" : "1.0 2024-03-09",
|
||||
"contest_status" : "closed",
|
||||
"news_update" : "2024-04-21T22:08:12+00:00",
|
||||
"news_update" : "2024-04-28T06:28:19+00:00",
|
||||
"status_update" : "2024-03-31T05:02:06+00:00"
|
||||
}</code></pre>
|
||||
|
||||
|
||||
+1
-1
@@ -2,6 +2,6 @@
|
||||
"no_comment" : "mandatory comment: because comments were removed from the original JSON spec",
|
||||
"IOCCC_status_version" : "1.0 2024-03-09",
|
||||
"contest_status" : "closed",
|
||||
"news_update" : "2024-04-21T22:08:12+00:00",
|
||||
"news_update" : "2024-04-28T06:28:19+00:00",
|
||||
"status_update" : "2024-03-31T05:02:06+00:00"
|
||||
}
|
||||
+146
-146
File diff suppressed because it is too large.
Load diff
+146
-146
File diff suppressed because it is too large.
Load diff
@@ -348,6 +348,17 @@ Examples:
|
||||
```
|
||||
|
||||
|
||||
## [md-chk-paths.sh](%%DOCROOT_SLASH%%tmp/md-chk-paths.sh)
|
||||
|
||||
Print full directories of local (non-remote URL) markdown paths.
|
||||
|
||||
Usage:
|
||||
|
||||
``` <!---sh-->
|
||||
tmp/md-chk-paths.sh
|
||||
```
|
||||
|
||||
|
||||
## [md-links.sh](%%DOCROOT_SLASH%%tmp/md-links.sh)
|
||||
|
||||
For all markdown files, print markdown links.
|
||||
|
||||
Executable
+463
@@ -0,0 +1,463 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# md-chk-paths.sh - print local file paths referenced in markdown links
|
||||
#
|
||||
# For all markdown files, print markdown links that are local.
|
||||
# We ignore URLs that start with "http:" or "https:".
|
||||
# We ignore links that are internal to the file (i.e., "#name").
|
||||
# We strip all "#name" from paths.
|
||||
#
|
||||
# Copyright (c) 2024 by Landon Curt Noll. All Rights Reserved.
|
||||
#
|
||||
# Permission to use, copy, modify, and distribute this software and
|
||||
# its documentation for any purpose and without fee is hereby granted,
|
||||
# provided that the above copyright, this permission notice and text
|
||||
# this comment, and the disclaimer below appear in all of the following:
|
||||
#
|
||||
# supporting documentation
|
||||
# source copies
|
||||
# source works derived from this source
|
||||
# binaries derived from this source or from derived source
|
||||
#
|
||||
# LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
||||
# EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
# USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
# OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
# chongo (Landon Curt Noll, http://www.isthe.com/chongo/index.html) /\oo/\
|
||||
#
|
||||
# Share and enjoy! :-)
|
||||
|
||||
# firewall - run only with a bash that is version 5.1.8 or later
|
||||
#
|
||||
# The "/usr/bin/env bash" command must result in using a bash that
|
||||
# is version 5.1.8 or later.
|
||||
#
|
||||
# We could relax this version and insist on version 4.2 or later. Versions
|
||||
# of bash between 4.2 and 5.1.7 might work. However, to be safe, we will require
|
||||
# bash version 5.1.8 or later.
|
||||
#
|
||||
# WHY 5.1.8 and not 4.2? This safely is done because macOS Homebrew bash we
|
||||
# often use is "version 5.2.26(1)-release" or later, and the RHEL Linux bash we
|
||||
# use often use is "version 5.1.8(1)-release" or later. These versions are what
|
||||
# we initially tested. We recommend you either upgrade bash or install a newer
|
||||
# version of bash and adjust your $PATH so that "/usr/bin/env bash" finds a bash
|
||||
# that is version 5.1.8 or later.
|
||||
#
|
||||
# NOTE: The macOS shipped, as of 2024 March 15, a version of bash is something like
|
||||
# bash "version 3.2.57(1)-release". That macOS shipped version of bash
|
||||
# will NOT work. For users of macOS we recommend you install Homebrew,
|
||||
# (see https://brew.sh), and then run "brew install bash" which will
|
||||
# typically install it into /opt/homebrew/bin/bash, and then arrange your $PATH
|
||||
# so that "/usr/bin/env bash" finds "/opt/homebrew/bin" (or whatever the
|
||||
# Homebrew bash is).
|
||||
#
|
||||
# NOTE: And while MacPorts might work, we noticed a number of subtle differences
|
||||
# with some of their ported tools to suggest you might be better off
|
||||
# with installing Homebrew (see https://brew.sh). No disrespect is intended
|
||||
# to the MacPorts team as they do a commendable job. Nevertheless we ran
|
||||
# into enough differences with MacPorts environments to suggest you
|
||||
# might find a better experience with this tool under Homebrew instead.
|
||||
#
|
||||
if [[ -z ${BASH_VERSINFO[0]} ||
|
||||
${BASH_VERSINFO[0]} -lt 5 ||
|
||||
${BASH_VERSINFO[0]} -eq 5 && ${BASH_VERSINFO[1]} -lt 1 ||
|
||||
${BASH_VERSINFO[0]} -eq 5 && ${BASH_VERSINFO[1]} -eq 1 && ${BASH_VERSINFO[2]} -lt 8 ]]; then
|
||||
echo "$0: ERROR: bash version needs to be >= 5.1.8: $BASH_VERSION" 1>&2
|
||||
echo "$0: Warning: bash version >= 4.2 might work but 5.1.8 was the minimum we tested" 1>&2
|
||||
echo "$0: Notice: For macOS users: install Homebrew (see https://brew.sh), then run" \
|
||||
""brew install bash" and then modify your \$PATH so that \"#!/usr/bin/env bash\"" \
|
||||
"finds the Homebrew installed (usually /opt/homebrew/bin/bash) version of bash" 1>&2
|
||||
exit 4
|
||||
fi
|
||||
|
||||
|
||||
# setup bash file matching
|
||||
#
|
||||
# We must declare arrays with -ag or -Ag, and we need loops to "export" modified variables.
|
||||
# This requires a bash with a version 4.2 or later. See the larger comment above about bash versions.
|
||||
#
|
||||
shopt -s nullglob # enable expanded to nothing rather than remaining unexpanded
|
||||
shopt -u failglob # disable error message if no matches are found
|
||||
shopt -u dotglob # disable matching files starting with .
|
||||
shopt -u nocaseglob # disable strict case matching
|
||||
shopt -u extglob # enable extended globbing patterns
|
||||
shopt -s globstar # enable ** to match all files and zero or more directories and subdirectories
|
||||
|
||||
# set variables referenced in the usage message
|
||||
#
|
||||
export VERSION="1.0 2024-04-25"
|
||||
NAME=$(basename "$0")
|
||||
export NAME
|
||||
export V_FLAG=0
|
||||
GIT_TOOL=$(type -P git)
|
||||
export GIT_TOOL
|
||||
if [[ -z "$GIT_TOOL" ]]; then
|
||||
echo "$0: FATAL: git tool is not installed or not in \$PATH" 1>&2
|
||||
exit 5
|
||||
fi
|
||||
"$GIT_TOOL" rev-parse --is-inside-work-tree >/dev/null 2>&1
|
||||
status="$?"
|
||||
if [[ $status -eq 0 ]]; then
|
||||
TOPDIR=$("$GIT_TOOL" rev-parse --show-toplevel)
|
||||
fi
|
||||
export TOPDIR
|
||||
|
||||
|
||||
# usage
|
||||
#
|
||||
export USAGE="usage: $0 [-h] [-v level] [-V] [-d topdir]
|
||||
|
||||
-h print help message and exit
|
||||
-v level set verbosity level (def level: 0)
|
||||
-V print version string and exit
|
||||
|
||||
-d topdir set topdir (def: $TOPDIR)
|
||||
|
||||
Exit codes:
|
||||
0 all OK
|
||||
1 some internal tool exited non-zero
|
||||
2 -h and help string printed or -V and version string printed
|
||||
3 command line error
|
||||
4 bash version is too old
|
||||
6 problems found with or in the topdir or topdir/YYYY directory
|
||||
7 problems found with or in the entry topdir/YYYY/dir directory
|
||||
>= 10 internal error
|
||||
|
||||
$NAME version: $VERSION"
|
||||
|
||||
|
||||
# fast_dirname - perform dirname(1) without calling a command
|
||||
#
|
||||
# This is very similar with dirname(1) except it is much faster.
|
||||
#
|
||||
# usage:
|
||||
# fast_dirname path_name
|
||||
#
|
||||
# path to obtain the directory from
|
||||
#
|
||||
function fast_dirname
|
||||
{
|
||||
local PATH_NAME; # path_name argument to be modified
|
||||
|
||||
# parse args
|
||||
#
|
||||
if [[ $# -ne 1 ]]; then
|
||||
echo "$0: ERROR: in fast_dirname: debug_parameters requires 1 arg, found: $#" 1>&2
|
||||
exit 10
|
||||
fi
|
||||
PATH_NAME="$1"
|
||||
|
||||
# firewall - reject empty paths
|
||||
#
|
||||
if [[ -z $PATH_NAME ]]; then
|
||||
echo "$0: ERROR: in fast_dirname: pathname arg is empty" 1>&2
|
||||
exit 11
|
||||
fi
|
||||
|
||||
# reduce multiple consecutive /'s to just /
|
||||
#
|
||||
while :; do
|
||||
case "$PATH_NAME" in
|
||||
*//*) PATH_NAME="${PATH_NAME//\/\//\/}" ;;
|
||||
*) break ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# trim any trailing /
|
||||
#
|
||||
PATH_NAME=${PATH_NAME%%/}
|
||||
|
||||
# case: if we only had /'s return /
|
||||
#
|
||||
if [[ -z "$PATH_NAME" ]]; then
|
||||
echo '/'
|
||||
return;
|
||||
fi
|
||||
|
||||
# case: PATH_NAME is an absolute path starting with /
|
||||
#
|
||||
case "$PATH_NAME" in
|
||||
/*) echo "${PATH_NAME%/*}"; return ;;
|
||||
*/*) echo "${PATH_NAME%/*}"; return ;;
|
||||
*) echo '.'; return ;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
||||
# parse command line
|
||||
#
|
||||
while getopts :hv:Vd:nN flag; do
|
||||
case "$flag" in
|
||||
h) echo "$USAGE" 1>&2
|
||||
exit 2
|
||||
;;
|
||||
v) V_FLAG="$OPTARG"
|
||||
;;
|
||||
V) echo "$VERSION"
|
||||
exit 2
|
||||
;;
|
||||
d) TOPDIR="$OPTARG"
|
||||
;;
|
||||
\?) echo "$0: ERROR: invalid option: -$OPTARG" 1>&2
|
||||
echo 1>&2
|
||||
print_usage 1>&2
|
||||
exit 3
|
||||
;;
|
||||
:) echo "$0: ERROR: option -$OPTARG requires an argument" 1>&2
|
||||
echo 1>&2
|
||||
echo "$USAGE" 1>&2
|
||||
exit 3
|
||||
;;
|
||||
*) echo "$0: ERROR: unexpected value from getopts: $flag" 1>&2
|
||||
echo 1>&2
|
||||
echo "$USAGE" 1>&2
|
||||
exit 3
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# remove the options
|
||||
#
|
||||
shift $(( OPTIND - 1 ));
|
||||
#
|
||||
if [[ $V_FLAG -ge 5 ]]; then
|
||||
echo "$0: debug[5]: file argument count: $#" 1>&2
|
||||
fi
|
||||
#
|
||||
# verify arg count and parse args
|
||||
#
|
||||
export TOOL
|
||||
case "$#" in
|
||||
0) ;;
|
||||
*) echo "$0: ERROR: expected 0 args, found: $#" 1>&2
|
||||
echo "$USAGE" 1>&2
|
||||
exit 3
|
||||
;;
|
||||
esac
|
||||
|
||||
# print running info if verbose
|
||||
#
|
||||
# If -v 3 or higher, print exported variables in order that they were exported.
|
||||
#
|
||||
if [[ $V_FLAG -ge 3 ]]; then
|
||||
echo "$0: debug[3]: VERSION=$VERSION" 1>&2
|
||||
echo "$0: debug[3]: NAME=$NAME" 1>&2
|
||||
echo "$0: debug[3]: V_FLAG=$V_FLAG" 1>&2
|
||||
echo "$0: debug[3]: GIT_TOOL=$GIT_TOOL" 1>&2
|
||||
echo "$0: debug[3]: TOPDIR=$TOPDIR" 1>&2
|
||||
fi
|
||||
|
||||
|
||||
# cd to topdir
|
||||
#
|
||||
if [[ ! -e $TOPDIR ]]; then
|
||||
echo "$0: ERROR: cannot cd to non-existent path: $TOPDIR" 1>&2
|
||||
exit 6
|
||||
fi
|
||||
if [[ ! -d $TOPDIR ]]; then
|
||||
echo "$0: ERROR: cannot cd to a non-directory: $TOPDIR" 1>&2
|
||||
exit 6
|
||||
fi
|
||||
export CD_FAILED
|
||||
if [[ $V_FLAG -ge 5 ]]; then
|
||||
echo "$0: debug[5]: about to: cd $TOPDIR" 1>&2
|
||||
fi
|
||||
cd "$TOPDIR" || CD_FAILED="true"
|
||||
if [[ -n $CD_FAILED ]]; then
|
||||
echo "$0: ERROR: cd $TOPDIR failed" 1>&2
|
||||
exit 6
|
||||
fi
|
||||
if [[ $V_FLAG -ge 3 ]]; then
|
||||
echo "$0: debug[3]: now in directory: $(/bin/pwd)" 1>&2
|
||||
fi
|
||||
|
||||
|
||||
# collect markdown links
|
||||
#
|
||||
# Here be extended regular expression magic dragons! :-)
|
||||
#
|
||||
# We will try to explain, as best as we can, these complex regular expressions.
|
||||
#
|
||||
# After grep of markdown files (files in sorted dictionary order) for markdown line lines, we sed:
|
||||
#
|
||||
# # remove any "[some string]" that is not immediately followed by "("
|
||||
#
|
||||
# -e 's/\[[^]]*\]([^(])/\1/' \
|
||||
#
|
||||
# # remove any trialing "[followed by text without a closing bracket"
|
||||
#
|
||||
# -e 's/\[[^]]*$//' \
|
||||
#
|
||||
# Then processing the second file (after the filename field) we sed:
|
||||
#
|
||||
# # remove any leading "..non-[-stuff..["
|
||||
#
|
||||
# -e 's/^[^[]()+\[/[/' \
|
||||
#
|
||||
# # replace "beginning text stuff](" with "[text stuff]("
|
||||
# # because the previous line might have ended with "[beginning"
|
||||
#
|
||||
# -e 's/^([^][]*\]\()/[\1/g' \
|
||||
#
|
||||
# # remove any "[..non-]-stuff..][..more-non-]-stuff..]"
|
||||
#
|
||||
# -e 's/(\[[^][]*\])+([^(])/\2/g' \
|
||||
#
|
||||
# # remove any non-link before the first "[some string](path)"
|
||||
#
|
||||
# -e 's/^[^][]+(\[[^]]*\]\([^(]*\))/\1/' \
|
||||
#
|
||||
# # remove any final "[..non-]-stuff..$"
|
||||
#
|
||||
# -e 's/\[[^]]*$//' \
|
||||
#
|
||||
# # remove any final "(..non-)-stuff..)..non-[-stuff.."
|
||||
#
|
||||
# -e 's/(\([^)]*\))[^[]*$/\1/' \
|
||||
#
|
||||
# # remove any trailing non-[-text after the final "[some string](path)"
|
||||
#
|
||||
# -e 's/(\[[^]]*\]\([^(]*\))[^[]+$/\1/' \
|
||||
#
|
||||
# # replace ")..non-open-bracket-stuff.[" with ") ["
|
||||
#
|
||||
# -e 's/\)[^[]*\[/) [/g' \
|
||||
#
|
||||
# # replace "[some string](apath) [other string](bpath)" with two lines:
|
||||
# #
|
||||
# # "[some string](apath)"
|
||||
# # "[other string](bpath)"
|
||||
#
|
||||
# -e 's/(\[[^]]*\]\([^(]*\))/\1\n/g' \
|
||||
#
|
||||
# # remove blank and empty lines
|
||||
#
|
||||
# -e '/^\s*$/d' \
|
||||
#
|
||||
# Then pipe the lines into another sed:
|
||||
#
|
||||
# # replace multiple space with a single space
|
||||
#
|
||||
# -e 's/ +/ /g' \
|
||||
#
|
||||
# # remove the leading "[pseudo title]("
|
||||
#
|
||||
# -e 's/\[[^]]*\]\(//' \
|
||||
#
|
||||
# # remove trailing ")":
|
||||
#
|
||||
# -e 's/\)$//' \
|
||||
#
|
||||
# # remove and trailing #name
|
||||
#
|
||||
# -e 's/#.*$//' \
|
||||
#
|
||||
# # remove any leading whitespace
|
||||
#
|
||||
# -e 's/^ //' \
|
||||
#
|
||||
# # remove blank and empty lines
|
||||
#
|
||||
# -e '/^\s*$/d' \
|
||||
#
|
||||
# # delete all http: and https: URLs
|
||||
#
|
||||
# -e '/^https?:/d' \
|
||||
#
|
||||
# # delete all mailto: URLs
|
||||
#
|
||||
# -e '/^mailto:/d' \
|
||||
#
|
||||
#
|
||||
# -e 's;%%DOCROOT_SLASH%%/*;/;' \
|
||||
#
|
||||
# # add current directory in front of absolute paths
|
||||
#
|
||||
# -e "s;^/;$PWD;" \
|
||||
#
|
||||
# # add current directory followed by / in front of relative paths
|
||||
#
|
||||
# -e "s;^([^/]);$PWD/\1;" \
|
||||
#
|
||||
# # convert "%%REPO_URL%%/" into TOPDIR
|
||||
#
|
||||
# -e "s;%%REPO_URL%%/*;$TOPDIR/;" \
|
||||
#
|
||||
# # convert "%%DOCROOT_SLASH%%" into TOPDIR
|
||||
#
|
||||
# -e "s;%%DOCROOT_SLASH%%/*;$TOPDIR/;" \
|
||||
#
|
||||
# # relative paths have the directory of the markdown file added to them
|
||||
#
|
||||
# -e "s;^([^/]);$TOPDIR/$MD_DIR/\1;" \
|
||||
#
|
||||
# # delete all lines containing "%%TOKEN%%" as this is a just a test/example token
|
||||
#
|
||||
# -e '/%%TOKEN%%/d' \
|
||||
#
|
||||
# At this point in the pipe, we have absolute /-based paths to markdown linked local files.
|
||||
# We test if those file exist, and if not report a problem in the form:
|
||||
#
|
||||
# # Missing file linked in: markdown_file_name.md
|
||||
# # Markdown line: ..the markdown line containing the line..
|
||||
# /missing/filename
|
||||
#
|
||||
find . -name '*.md' ! -name markdown.md ! -path './tmp/*' -print |
|
||||
LANG=C sort -d |
|
||||
xargs grep '\]([^)][^)]*)' /dev/null |
|
||||
sed -E \
|
||||
-e 's;^\.\/;;' \
|
||||
-e 's/^([^:]+):\s*/\1 /' \
|
||||
|
|
||||
while read -r MD_PATH MD_LINE; do
|
||||
|
||||
# note directory containing the markdown file
|
||||
#
|
||||
MD_DIR=$(fast_dirname "$MD_PATH")
|
||||
export MD_DIR
|
||||
|
||||
# extract markdown parts from the given markdown file
|
||||
#
|
||||
echo "$MD_LINE" |
|
||||
sed -E \
|
||||
-e 's/^[^[]()+\[/[/' \
|
||||
-e 's/^([^][]*\]\()/[\1/g' \
|
||||
-e 's/(\[[^][]*\])+([^(])/\2/g' \
|
||||
-e 's/^[^][]+(\[[^]]*\]\([^(]*\))/\1/' \
|
||||
-e 's/\[[^]]*$//' \
|
||||
-e 's/(\([^)]*\))[^[]*$/\1/' \
|
||||
-e 's/(\[[^]]*\]\([^(]*\))[^[]+$/\1/' \
|
||||
-e 's/\)[^[]*\[/) [/g' \
|
||||
-e 's/(\[[^]]*\]\([^(]*\))/\1\n/g' \
|
||||
-e '/^\s*$/d' \
|
||||
|
|
||||
sed -E \
|
||||
-e 's/ +/ /g' \
|
||||
-e 's/\[[^]]*\]\(//' \
|
||||
-e 's/\)$//' \
|
||||
-e 's/#.*$//' \
|
||||
-e 's/^ //' \
|
||||
-e '/^\s*$/d' \
|
||||
-e '/^https?:/d' \
|
||||
-e '/^mailto:/d' \
|
||||
-e "s;%%REPO_URL%%/*;$TOPDIR/;" \
|
||||
-e "s;%%DOCROOT_SLASH%%/*;$TOPDIR/;" \
|
||||
-e "s;^([^/]);$TOPDIR/$MD_DIR/\1;" \
|
||||
-e '/%%TOKEN%%/d' \
|
||||
|
|
||||
while read -r ABS_LOCAL_FILE_PATH; do
|
||||
if [[ ! -e $ABS_LOCAL_FILE_PATH ]]; then
|
||||
echo "# Missing file linked in: $MD_PATH" 1>&2
|
||||
echo "# Markdown line: $MD_LINE" 1>&2
|
||||
echo "$ABS_LOCAL_FILE_PATH" 1>&2
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
# All Done!!! -- Jessica Noll, Age 2
|
||||
#
|
||||
exit 0
|
||||
Reference in new issue
Block a user