Follow-up Comment #1, bug #64576 (project groff):
[comment #0 original submission:] > An immense amount of code in _pdf.tmac_ seems to be dedicated to an exploration of the question "hey, what if we chucked established _roff_ programming idioms out the window and re-implemented _getopt_long_(3) in it so that shell script programmers had macro interfaces that looked vaguely familiar"? This indeed seems to be the problem--bad interface design. The problem is that `pdfhref` doesn't require, and internal macros like `pdf*href` doesn't expect, operand-style arguments in its argument list that aren't valid _roff_ identifiers--that is, ones that aren't preceded by an option argument. I prepared an example based on the first figure in [https://en.wikipedia.org/wiki/Internationalized_domain_name Wikipedia's "Internationalized domain name" article], figuring that this would be adequately demonstrative of real-world use. $ cat EXPERIMENTS/pdfhref-whack.groff Hello .pdfhref W -D http://\(*o\(*u\(*t\(*o\(*p\(*i\(*a.\(*d\(*p\(*h.gr \ http://\(*o\(*u\(*t\(*o\(*p\(*i\(*a.\(*d\(*p\(*h.gr Here's an annotated run of that. $ ./build/test-groff -a -ww -b -Tpdf EXPERIMENTS/pdfhref-whack.groff <beginning of page> GBR: pdfhref: arguments: "W" "-D" "http://\(*o\(*u\(*t\(*o\(*p\(*i\(*a.\(*d\(*p\(*h.gr" "http://\(*o\(*u\(*t\(*o\(*p\(*i\(*a.\(*d\(*p\(*h.gr" GBR: pdfhref: checking existence of string "pdf*hrefW" GBR: pdfhref: checking existence of string "pdf*href-W" GBR: pdfhref: calling pdf*href "-D" "http://\(*o\(*u\(*t\(*o\(*p\(*i\(*a.\(*d\(*p\(*h.gr" "http://\(*o\(*u\(*t\(*o\(*p\(*i\(*a.\(*d\(*p\(*h.gr" GBR: pdf*href: arguments: "-D" "http://\(*o\(*u\(*t\(*o\(*p\(*i\(*a.\(*d\(*p\(*h.gr" "http://\(*o\(*u\(*t\(*o\(*p\(*i\(*a.\(*d\(*p\(*h.gr" GBR: pdf*href: while dpdf:href.opt-D GBR: pdf*href: argument list is now "-D" "http://\(*o\(*u\(*t\(*o\(*p\(*i\(*a.\(*d\(*p\(*h.gr" "http://\(*o\(*u\(*t\(*o\(*p\(*i\(*a.\(*d\(*p\(*h.gr" GBR: pdf*href: .pdf:href.opt-D "-D" "http://\(*o\(*u\(*t\(*o\(*p\(*i\(*a.\(*d\(*p\(*h.gr" "http://\(*o\(*u\(*t\(*o\(*p\(*i\(*a.\(*d\(*p\(*h.gr" GBR: pdf:href.opt-D: ds pdf:href-D http://\(*o\(*u\(*t\(*o\(*p\(*i\(*a.\(*d\(*p\(*h.gr GBR: pdf:href.opt-D: nr pdf:href.argc 2 GBR: pdf:href.opt-D: outta here GBR: pdf*href: .shift 2 troff: backtrace: '/home/branden/src/GIT/groff/build/../tmac/pdf.tmac':457 troff: backtrace: '/home/branden/src/GIT/groff/build/../tmac/pdf.tmac':665: while loop troff: backtrace: '/home/branden/src/GIT/groff/build/../tmac/pdf.tmac':671: macro 'pdf*href' troff: backtrace: '/home/branden/src/GIT/groff/build/../tmac/pdf.tmac':457: while loop troff: backtrace: '/home/branden/src/GIT/groff/build/../tmac/pdf.tmac':482: macro 'pdfhref' troff: backtrace: file 'EXPERIMENTS/pdfhref-whack.groff':3 troff:EXPERIMENTS/pdfhref-whack.groff:3: error: a special character is not allowed in an identifier GBR: pdf*href: done with while loop GBR: pdfhref: How did that go? Hello http://<*o><*u><*t><*o><*p><*i><*a>.<*d><*p><*h>.gr Long story short... 658 .\" Now we interpret, and remove any specified options from the 659 .\" argument list. (Note that only options with a declared handler 660 .\" will be processed; there is no provision for detecting invalid 661 .\" options -- anything which is not recognised is assumed to start 662 .\" the "link text" component of the argument list). 663 .\" 664 .tm GBR: \\$0: while dpdf:href.opt\\$1 665 .while dpdf:href.opt\\$1 \{\ 666 . tm GBR: \\$0: argument list is now \\$@ 667 . tm GBR: \\$0: .pdf:href.opt\\$1 \\$@ 668 . pdf:href.opt\\$1 \\$@ 669 . tm GBR: \\$0: .shift \\n[pdf:href.argc] 670 . shift \\n[pdf:href.argc] 671 . \} 672 .tm GBR: \\$0: done with while loop ...isn't up to scratch. Sure, some option arguments have been shifted off, but the very next one might be link text, have escape sequences in it, and cause the formatter to scream when it tests to see if that argument is defined as a string/macro/diversion with the 'd' operator. The subsequent logic is telling: 673 .\" 674 .\" If we found "--", to mark the end of the options, then we should 675 .\" discard it. 676 .\" 677 .if '\\$1'--' .shift This doesn't cut it. It's too late. For this to work, '--' is going to have to be a _mandatory_ part of the interface. I'll see how easy that is to do. _______________________________________________________ Reply to this item at: <https://savannah.gnu.org/bugs/?64576> _______________________________________________ Message sent via Savannah https://savannah.gnu.org/