Mark hash_corrupted() as pg_attribute_noreturn.
[pgsql.git] / src / tools / pgflex
blobbaabe2df1c8eb0ffba360a29ea7d62863d833adf
1 #!/usr/bin/env python3
4 # Wrapper around flex that:
5 # - ensures lex.backup is created in a private directory
6 # - can error out if lex.backup is created (--no-backup)
7 # - can fix warnings (--fix-warnings)
8 # - works around concurrency issues with win_flex.exe:
9 #   https://github.com/lexxmark/winflexbison/issues/86
11 import argparse
12 import os
13 import subprocess
14 import sys
15 from os.path import abspath
17 parser = argparse.ArgumentParser()
19 parser.add_argument('--flex', type=abspath, required=True)
20 parser.add_argument('--perl', type=abspath, required=True)
21 parser.add_argument('--builddir', type=abspath, required=True)
22 parser.add_argument('--srcdir', type=abspath, required=True)
23 parser.add_argument('--privatedir', type=abspath, required=True,
24                     help='private directory for target')
26 parser.add_argument('-o', dest='output_file', type=abspath, required=True,
27                     help='output file')
28 parser.add_argument('-i', dest='input_file', type=abspath, help='input file')
31 parser.add_argument('--fix-warnings', action='store_true',
32                     help='whether to fix warnings in generated file')
33 parser.add_argument('--no-backup', action='store_true',
34                     help='whether no_backup is enabled or not')
36 parser.add_argument('flex_flags', nargs='*', help='flags passed on to flex')
38 args = parser.parse_args()
40 # Since 'lex.backup' is always named that and ninja uses the top level build
41 # directory as current directory for all commands, change directory to
42 # temporary directory to avoid conflicts between concurrent flex
43 # invocations. Only unreleased versions of flex have an argument to change
44 # lex.filename to be named differently.
45 if not os.path.isdir(args.privatedir):
46     os.mkdir(args.privatedir)
47 os.chdir(args.privatedir)
49 # win_flex.exe generates names in a racy way, sometimes leading to random
50 # "error deleting file" failures and sometimes to intermingled file
51 # contents. Set FLEX_TMP_DIR to the target private directory to avoid
52 # that. That environment variable isn't consulted on other platforms, so we
53 # don't even need to make this conditional.
54 env = {'FLEX_TMP_DIR': args.privatedir}
56 # build flex invocation
57 command = [args.flex, '-o', args.output_file]
58 if args.no_backup:
59     command += ['-b']
60 command += args.flex_flags
61 command += [args.input_file]
63 # create .c file from .l file
64 sp = subprocess.run(command, env=env)
65 if sp.returncode != 0:
66     sys.exit(sp.returncode)
68 # check lex.backup
69 if args.no_backup:
70     with open('lex.backup') as lex:
71         if len(lex.readlines()) != 1:
72             sys.exit('Scanner requires backup; see lex.backup.')
73     os.remove('lex.backup')
75 # fix warnings
76 if args.fix_warnings:
77     fix_warning_script = os.path.join(args.srcdir,
78                                       'src/tools/fix-old-flex-code.pl')
80     command = [args.perl, fix_warning_script, args.output_file]
81     sp = subprocess.run(command)
82     if sp.returncode != 0:
83         sys.exit(sp.returncode)
85 sys.exit(0)