History

tcc options: document behavior and clashes (no-op)

The tcc options behavior is non trivial, and it's also susceptible to ambiguities - which do exist (but currently are not painful). - Add a script 'optclash' which detects clashes/ambiguities. - Document the parsing behaviour and current clashes/resolutions as comments in libtcc.c .

Avi Halachmi (:avih) committed 1 year ago

Commit 234e2dd1 parent 01d1b7b2 files · +83 −0Browse files

Unified · Split

2 files
  1. libtcc.c +45 −0
  2. optclash +38 −0
libtcc.c+45−0
@@ -1571,6 +1571,30 @@ enum { · 1570 unmodified lines
1571#define TCC_OPTION_HAS_ARG 0x00011571#define TCC_OPTION_HAS_ARG 0x0001
1572#define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */1572#define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
1573 1573
1574/*
1575 * in tcc_options, if opt-string A is a prefix of opt-string B,
1576 * it's un-ambiguous if and only if option A is without TCC_OPTION_HAS_ARG.
1577 * otherwise (A with HAS_ARG), if, for instance, A is FOO and B is FOOBAR,
1578 * then "-FOOBAR" is either A with arg BAR, or B (-FOOBARX too, if B HAS_ARG).
1579 *
1580 * tcc_parse_args searches tcc_options in order, so if ambiguous:
1581 * - if the shorter (A) is earlier: the longer (B) is completely unreachable.
1582 * - else B wins, and A can't be used with adjacent arg if it also matches B.
1583 *
1584 * there are few clashes currently, and the longer is always earlier/reachable.
1585 * when it's ambiguous, shorter-concat-arg is not useful currently.
1586 * the sh(1) script 'optclash' can identifiy clashes (tcc root dir, try "-h").
1587 * at the time of writing, running './optclash' prints this:
1588
1589 -Wl,... (1642) overrides -W... (1644)
1590 -Wp,... (1643) overrides -W... (1644)
1591 -dumpmachine (1630) overrides -d... (1632)
1592 -dumpversion (1631) overrides -d... (1632)
1593 -dynamiclib (1623) overrides -d... (1632)
1594 -flat_namespace (1624) overrides -f... (1650)
1595 -mfloat-abi... (1647) overrides -m... (1649)
1596
1597 */
1574static const TCCOption tcc_options[] = {1598static const TCCOption tcc_options[] = {
1575 { "h", TCC_OPTION_HELP, 0 },1599 { "h", TCC_OPTION_HELP, 0 },
1576 { "-help", TCC_OPTION_HELP, 0 },1600 { "-help", TCC_OPTION_HELP, 0 },
@@ -1808,6 +1832,27 @@ static void args_parser_add_file(TCCState *s, const char* filename, int filetype · 231 unmodified lines
1808 ++s->nb_libraries;1832 ++s->nb_libraries;
1809}1833}
1810 1834
1835/* parsing is between getopt(3) and getopt_long(3), and permuting-like:
1836 * - an option is 1 or more chars.
1837 * - at most 1 option per arg in argv.
1838 * - an option in argv is "-OPT[...]" (few are --OPT, if OPT is "-...").
1839 * - optarg is next arg, or adjacent non-empty (no '='. -std=.. is arg "=..").
1840 * - supports also adjacent-only optarg (typically optional).
1841 * - supports mixed options and operands ("--" is ignored, except with -run).
1842 * - -OPT[...] can be ambiguous, which is resolved using tcc_options's order.
1843 * (see tcc_options for details)
1844 *
1845 * specifically, per arg of argv, in order:
1846 * - if arg begins with '@' and is not exactly "@": process as @listfile.
1847 * - elif arg is exactly "-" or doesn't begin with '-': process as input file.
1848 * - if -run... is already set: also stop, arg... become argv of run_main.
1849 * - elif arg is "--":
1850 * - if -run... is already set: stop, arg... become argv of run_main.
1851 * - else ignore it.
1852 * - else ("-STRING") try to apply it as option, maybe with next (opt)arg.
1853 *
1854 * after all args, if -run... but no "stop": run_main gets our argv (tcc ...)
1855 */
1811/* using * to argc/argv to let "tcc -ar" benefit from @listfile expansion */1856/* using * to argc/argv to let "tcc -ar" benefit from @listfile expansion */
1812PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv)1857PUB_FUNC int tcc_parse_args(TCCState *s, int *pargc, char ***pargv)
1813{1858{
optclash+38−0
@@ -0,0 +1,38 @@
1#!/bin/sh
2
3export LC_ALL=C
4
5defname=libtcc.c
6
7# $1 is the line number, $2... is the actual source line
8extract_opts() { awk '/tcc_options\[\]/ {x=1}; x; x && $2~/^}/ {exit}'; }
9
10case $1 in -h|--help)
11 echo "Usage: $0 [INFILE]"
12 echo "Detect tcc_options[] clashes in $defname-like INFILE."
13 echo "If INFILE is missing, use $defname at the same dir as this script."
14 echo "Clashes are reported as longer-overrides, or longer-unreachable."
15 exit
16esac
17
18f=${1-$(dirname "$0")/$defname}
19[ -r "$f" ] || { >&2 echo "$0: can't read -- $f"; exit 1; }
20
21nl -b a <"$f" | extract_opts | tr \" ' ' | awk '$2=="{"' | sort -b -k 3 |
22# "<line-num> { <unquoted-opt> <rest-of-line>" sorted-up by opt
23# unavoidable O(N^2). the sort simplifies the awk code - only test prior opts.
24awk '
25 {
26 n=$1; opt=$3; h=/HAS_ARG/
27 for (pn in prevs) { # pn: line-num
28 po = prevs[pn] # po: opt-with-has-arg
29 if (index(opt,po) == 1) {
30 clash=1
31 printf("-%s%s (%d) %s -%s... (%s)\n", opt,h?"...":"",n,
32 n>pn? "is not reachable! by":"overrides", po,pn)
33 }
34 }
35 }
36 h {prevs[n] = opt}
37 END {if (clash) exit 1; print "no clashes"}
38'

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t