1#!/usr/local/bin/python3.8 2# 3# This file is Copyright (c) 2010 by the GPSD project 4# SPDX-License-Identifier: BSD-2-clause 5# 6# With -p, dump a Python status mask list translated from the C one. 7# 8# With -c, generate C code to dump masks for debugging purposes. 9# 10# With -t, tabulate usage of defines to find unused ones. Requires -c or -d. 11 12# This code runs compatibly under Python 2 and 3.x for x >= 2. 13# Preserve this property! 14from __future__ import absolute_import, print_function, division 15 16import getopt 17import glob 18import sys 19 20try: 21 from subprocess import getstatusoutput 22except ImportError: 23 from commands import getstatusoutput 24 25 26class SourceExtractor(object): 27 def __init__(self, sourcefile, clientside): 28 self.sourcefile = sourcefile 29 self.clientside = clientside 30 self.daemonfiles = [ 31 "gpsd.c", 32 "libgpsd_core.c", 33 "pseudonmea.c", 34 "drivers.c", 35 "gpsmon.c", 36 "subframe.c" 37 ] + glob.glob("driver_*.c") + glob.glob("monitor_*.c") 38 self.masks = [] 39 self.primitive_masks = [] 40 for line in open(self.sourcefile): 41 if (((line.startswith("#define") and 42 ("_SET" in line or "_IS" in line)))): 43 fields = line.split() 44 self.masks.append((fields[1], fields[2])) 45 if ((fields[2].startswith("(1llu<<") or 46 fields[2].startswith("INTERNAL_SET"))): 47 self.primitive_masks.append((fields[1], fields[2])) 48 49 def in_library(self, flag): 50 (status, _output) = getstatusoutput( 51 "grep '%s' libgps_core.c libgps_json.c gpsctl.c" % flag) 52 return status == 0 53 54 def in_daemon(self, flag): 55 (status, _output) = getstatusoutput( 56 "grep '%s' %s" % (flag, " ".join(self.daemonfiles))) 57 return status == 0 58 59 def relevant(self, flag): 60 if self.clientside: 61 return self.in_library(flag) 62 63 return self.in_daemon(flag) 64 65 66if __name__ == '__main__': 67 try: 68 (options, arguments) = getopt.getopt(sys.argv[1:], "cdpt") 69 pythonize = tabulate = False 70 clientgen = daemongen = False 71 for (switch, val) in options: 72 if switch == '-p': 73 pythonize = True 74 if switch == '-c': 75 clientgen = True 76 if switch == '-d': 77 daemongen = True 78 if switch == '-t': 79 tabulate = True 80 81 if not arguments: 82 srcdir = '.' 83 else: 84 srcdir = arguments[0] 85 86 clientside = SourceExtractor(srcdir + "/gps.h", clientside=True) 87 daemonside = SourceExtractor(srcdir + "/gpsd.h", clientside=False) 88 if clientgen: 89 source = clientside 90 banner = "Library" 91 elif daemongen: 92 source = daemonside 93 banner = "Daemon" 94 else: 95 sys.stderr.write("maskaudit: need -c or -d option\n") 96 sys.exit(1) 97 98 if tabulate: 99 print("%-14s %8s" % (" ", banner)) 100 for (flag, value) in source.masks: 101 print("%-14s %8s" % (flag, source.relevant(flag))) 102 if pythonize: 103 for (d, v) in source.masks: 104 if v[-1] == 'u': 105 v = v[:-1] 106 print("%-15s\t= %s" % (d, v)) 107 if not pythonize and not tabulate: 108 maxout = 0 109 for (d, v) in source.primitive_masks: 110 if source.relevant(d): 111 stem = d 112 if stem.endswith("_SET"): 113 stem = stem[:-4] 114 if stem.endswith("_IS"): 115 stem = stem[:-3] 116 maxout += len(stem) + 1 117 print("""/* This code is generated. Do not hand-hack it! */ 118 119/* 120 * Also, beware that it is something of a CPU hog when called on every packet. 121 * Try to write guards so it is only called at higher log levels. 122 */ 123 124#include \"gpsd_config.h\" /* must be before all includes */ 125 126#include <stdio.h> 127#include <string.h> 128 129#include \"gpsd.h\" 130 131const char *gps_maskdump(gps_mask_t set) 132{ 133 static char buf[%d]; 134 const struct { 135 gps_mask_t mask; 136 const char *name; 137 } *sp, names[] = {""" % (maxout + 3,)) 138 masks = clientside.primitive_masks + daemonside.primitive_masks 139 for (flag, value) in masks: 140 stem = flag 141 if stem.endswith("_SET"): 142 stem = stem[:-4] 143 if stem.endswith("_IS"): 144 stem = stem[:-3] 145 print(" {%s,\t\"%s\"}," % (flag, stem)) 146 print('''\ 147 }; 148 149 memset(buf, '\\0', sizeof(buf)); 150 buf[0] = '{'; 151 for (sp = names; sp < names + sizeof(names)/sizeof(names[0]); sp++) 152 if ((set & sp->mask)!=0) { 153 (void)strlcat(buf, sp->name, sizeof(buf)); 154 (void)strlcat(buf, "|", sizeof(buf)); 155 } 156 if (buf[1] != \'\\0\') 157 buf[strlen(buf)-1] = \'\\0\'; 158 (void)strlcat(buf, "}", sizeof(buf)); 159 return buf; 160} 161''') 162 except KeyboardInterrupt: 163 pass 164 165# The following sets edit modes for GNU EMACS 166# Local Variables: 167# mode:python 168# End: 169