summaryrefslogtreecommitdiffstats
path: root/src/tools/pgflex
blob: baabe2df1c8eb0ffba360a29ea7d62863d833adf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#!/usr/bin/env python3

#
# Wrapper around flex that:
# - ensures lex.backup is created in a private directory
# - can error out if lex.backup is created (--no-backup)
# - can fix warnings (--fix-warnings)
# - works around concurrency issues with win_flex.exe:
#   https://github.com/lexxmark/winflexbison/issues/86

import argparse
import os
import subprocess
import sys
from os.path import abspath

parser = argparse.ArgumentParser()

parser.add_argument('--flex', type=abspath, required=True)
parser.add_argument('--perl', type=abspath, required=True)
parser.add_argument('--builddir', type=abspath, required=True)
parser.add_argument('--srcdir', type=abspath, required=True)
parser.add_argument('--privatedir', type=abspath, required=True,
                    help='private directory for target')

parser.add_argument('-o', dest='output_file', type=abspath, required=True,
                    help='output file')
parser.add_argument('-i', dest='input_file', type=abspath, help='input file')


parser.add_argument('--fix-warnings', action='store_true',
                    help='whether to fix warnings in generated file')
parser.add_argument('--no-backup', action='store_true',
                    help='whether no_backup is enabled or not')

parser.add_argument('flex_flags', nargs='*', help='flags passed on to flex')

args = parser.parse_args()

# Since 'lex.backup' is always named that and ninja uses the top level build
# directory as current directory for all commands, change directory to
# temporary directory to avoid conflicts between concurrent flex
# invocations. Only unreleased versions of flex have an argument to change
# lex.filename to be named differently.
if not os.path.isdir(args.privatedir):
    os.mkdir(args.privatedir)
os.chdir(args.privatedir)

# win_flex.exe generates names in a racy way, sometimes leading to random
# "error deleting file" failures and sometimes to intermingled file
# contents. Set FLEX_TMP_DIR to the target private directory to avoid
# that. That environment variable isn't consulted on other platforms, so we
# don't even need to make this conditional.
env = {'FLEX_TMP_DIR': args.privatedir}

# build flex invocation
command = [args.flex, '-o', args.output_file]
if args.no_backup:
    command += ['-b']
command += args.flex_flags
command += [args.input_file]

# create .c file from .l file
sp = subprocess.run(command, env=env)
if sp.returncode != 0:
    sys.exit(sp.returncode)

# check lex.backup
if args.no_backup:
    with open('lex.backup') as lex:
        if len(lex.readlines()) != 1:
            sys.exit('Scanner requires backup; see lex.backup.')
    os.remove('lex.backup')

# fix warnings
if args.fix_warnings:
    fix_warning_script = os.path.join(args.srcdir,
                                      'src/tools/fix-old-flex-code.pl')

    command = [args.perl, fix_warning_script, args.output_file]
    sp = subprocess.run(command)
    if sp.returncode != 0:
        sys.exit(sp.returncode)

sys.exit(0)