use text file instead of sql
authorJohannes Berg <johannes@sipsolutions.net>
Fri, 23 May 2008 01:55:37 +0000 (03:55 +0200)
committerJohannes Berg <johannes@sipsolutions.net>
Fri, 23 May 2008 01:55:37 +0000 (03:55 +0200)
13 files changed:
.gitignore
Makefile
db.txt [new file with mode: 0644]
db/00-database.sql [deleted file]
db/01-regulatory.sql [deleted file]
db/02-freq_range.sql [deleted file]
db/03-power_rule.sql [deleted file]
db/04-reg_rule.sql [deleted file]
db/05-reg_rules_collection.sql [deleted file]
db/06-reg_country.sql [deleted file]
db2bin.py [new file with mode: 0755]
dbgen.py [deleted file]
dbparse.py [new file with mode: 0644]

index 8919b0f..b4bdbc0 100644 (file)
@@ -2,3 +2,4 @@
 regulatory.sqlite
 regulatory.bin
 daemon/dump
+*.pyc
index ea8a8a9..876bbde 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,18 +1,10 @@
 all:   regulatory.bin
 
-
-regulatory.bin:        regulatory.sqlite dbgen.py key.priv.pem
-       @./dbgen.py
+regulatory.bin:        db2bin.py key.priv.pem db.txt dbparse.py
+       @./db2bin.py
 
 clean:
-       @rm -f regulatory.sqlite regulatory.bin *~
-
-regulatory.sqlite: db/*.sql
-       @rm -f requlatory.sqlite
-       @(for i in db/*.sql ; do \
-               if [ $$i = "db/00-database.sql" ] ; then continue ; fi ;\
-               sed 's/AUTO_INCREMENT/AUTOINCREMENT/; s/use regulatory;//' < $$i ;\
-       done) | sqlite3 regulatory.sqlite
+       @rm -f regulatory.bin *~ *.pyc
 
 generate_keys:
        openssl genrsa -out key.priv.pem 2048
diff --git a/db.txt b/db.txt
new file mode 100644 (file)
index 0000000..0c49d25
--- /dev/null
+++ b/db.txt
@@ -0,0 +1,201 @@
+############
+# First: band definitions
+
+band WORLD: 2432 - 2442 @ 20, OFDM, CCK
+
+band FCCA-1: 2412 - 2462 @ 20, OFDM, CCK
+band FCCA-2: 2437 - 2437 @ 40, OFDM, CCK
+band FCCA-3: 2442 - 2462 @ 20, OFDM, CCK
+
+# ETSIC also uses FCCA-1/-2
+band ETSIC: 2442 - 2472 @ 20, OFDM, CCK
+
+band MKKA-1: 2412 - 2472 @ 20, OFDM, CCK
+band MKKA-2: 2484 - 2484 @ 20, CCK
+
+band DEBUG-24: 2412 - 2732 @ 40, OFDM, CCK
+
+# 5 GHz ranges follow
+
+band APL1: 5745 - 5825 @ 20, OFDM
+band APL2: 5745 - 5805 @ 20, OFDM
+
+band APL3-1: 5280 - 5320 @ 20, OFDM
+band APL3-2: 5745 - 5805 @ 20, OFDM
+
+# DMN_APL4 --- DMN_ETSI2 uses only the first frequency range
+# DMN_ETS5 uses the same freq range as DMN_ETSI2 so we can combine these two
+band APL4-1: 5180 - 5240 @ 20, OFDM
+band APL4-2: 5745 - 5825 @ 20, OFDM
+
+# DMN_ETSI1 -- DMN_ETSI3 and DMN_ETSI4 uses the first freq range of DMN_ETSI1
+# DMN_ETSI4 overlaps with ETSI3 so we deleted it
+band ETSI1: 5180 - 5320 @ 20, OFDM
+band ETSI2: 5500 - 5700 @ 20, OFDM
+
+band ETSI6-1: 5180 - 5280 @ 20, OFDM
+band ETSI6-2: 5500 - 5700 @ 20, OFDM
+
+band FCC1-1: 5180 - 5200 @ 20, OFDM
+band FCC1-2: 5210 - 5210 @ 40, OFDM
+band FCC1-3: 5220 - 5240 @ 20, OFDM
+band FCC1-4: 5250 - 5250 @ 40, OFDM
+band FCC1-5: 5260 - 5280 @ 20, OFDM
+band FCC1-6: 5290 - 5290 @ 40, OFDM
+band FCC1-7: 5300 - 5320 @ 20, OFDM
+band FCC1-8: 5745 - 5745 @ 20, OFDM
+band FCC1-9: 5760 - 5760 @ 40, OFDM
+band FCC1-10: 5765 - 5785 @ 20, OFDM
+band FCC1-11: 5800 - 5800 @ 40, OFDM
+band FCC1-12: 5805 - 5825 @ 20, OFDM
+
+# FCC3 is FCC1 + this
+band FCC3: 5500 - 5700 @ 20, OFDM
+
+# MKK1
+band MKK1: 5170 - 5230 @ 20, OFDM
+
+# MKK2 is MKK1 + this
+band MKK2: 5040 - 5080 @ 20, OFDM
+
+band DEBUG-50: 5005 - 6100 @ 40, OFDM, CCK
+
+
+############
+# Second: power definitions
+
+# OI is the identifier we use for outdoor+indoor which is usually a space
+power DEFAULT: OI, 6, 30, 30, 36, 255
+
+############
+# Finally, country definitions
+
+country 00:
+       WORLD, DEFAULT
+
+country 01:
+       DEBUG-24, DEFAULT
+
+country 02:
+       DEBUG-50, DEFAULT
+
+country 03:
+       DEBUG-24, DEFAULT
+       DEBUG-50, DEFAULT
+
+country BR, BZ:
+       FCCA-1, DEFAULT
+       FCCA-2, DEFAULT
+       ETSIC, DEFAULT
+
+country PH:
+       FCC1-1, DEFAULT
+       FCC1-2, DEFAULT
+       FCC1-3, DEFAULT
+       FCC1-4, DEFAULT
+       FCC1-5, DEFAULT
+       FCC1-6, DEFAULT
+       FCC1-7, DEFAULT
+       FCC1-8, DEFAULT
+       FCC1-9, DEFAULT
+       FCC1-10, DEFAULT
+       FCC1-11, DEFAULT
+       FCC1-12, DEFAULT
+       WORLD, DEFAULT
+
+country CO, DO, GT, MX, PA, PR, US:
+       ETSI1, DEFAULT
+       ETSI2, DEFAULT
+       WORLD, DEFAULT
+
+country AU, HK, MO:
+       FCCA-1, DEFAULT
+       FCCA-2, DEFAULT
+       FCCA-3, DEFAULT
+       ETSI1, DEFAULT
+       ETSI2, DEFAULT
+
+country CA:
+       FCCA-1, DEFAULT
+       FCCA-2, DEFAULT
+       ETSIC, DEFAULT
+
+country NZ:
+       FCC1-1, DEFAULT
+       FCC1-2, DEFAULT
+       FCC1-3, DEFAULT
+       FCC1-4, DEFAULT
+       FCC1-5, DEFAULT
+       FCC1-6, DEFAULT
+       FCC1-7, DEFAULT
+       FCC1-8, DEFAULT
+       FCC1-9, DEFAULT
+       FCC1-10, DEFAULT
+       FCC1-11, DEFAULT
+       FCC1-12, DEFAULT
+       FCC3, DEFAULT
+
+country UZ:
+       ETSI1, DEFAULT
+       ETSI2, DEFAULT
+       WORLD, DEFAULT
+
+country CY, DE, DK, EE, ES, FI, GB, IE, IS, IT, LT, LU, LN, NO, PL, PT, SE, SI, UK, ZA:
+       APL4-1, DEFAULT
+       WORLD, DEFAULT
+
+country CH, HU, LI, AT:
+       ETSI1, DEFAULT
+       WORLD, DEFAULT
+
+country CZ, F2, HR, SK, TN, TR, AM, AZ, BE, GE, MC, TT:
+       ETSI6-1, DEFAULT
+       ETSI6-2, DEFAULT
+       WORLD, DEFAULT
+
+country BG:
+       MKKA-1, DEFAULT
+       MKKA-2, DEFAULT
+       MKK1, DEFAULT
+
+country JP:
+       MKK1, DEFAULT
+       FCCA-1, DEFAULT
+       FCCA-2, DEFAULT
+       FCCA-3, DEFAULT
+
+country J2:
+       MKKA-1, DEFAULT
+       MKKA-2, DEFAULT
+       MKK1, DEFAULT
+       MKK2, DEFAULT
+
+country BN, CH, IR, CL:
+       APL1, DEFAULT
+       WORLD, DEFAULT
+
+country BO:
+       APL1, DEFAULT
+       FCCA-1, DEFAULT
+       FCCA-2, DEFAULT
+       ETSIC, DEFAULT
+
+country KP, KR, TH, UY:
+       APL2, DEFAULT
+       WORLD, DEFAULT
+
+country VE:
+       APL2, DEFAULT
+       FCCA-1, DEFAULT
+       FCCA-2, DEFAULT
+       ETSIC, DEFAULT
+
+country AR, TW:
+       APL3-1, DEFAULT
+       APL3-2, DEFAULT
+       WORLD, DEFAULT
+
+country SG:
+       APL4-1, DEFAULT
+       APL4-2, DEFAULT
+       WORLD, DEFAULT
diff --git a/db/00-database.sql b/db/00-database.sql
deleted file mode 100644 (file)
index 5a8ac67..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/* create database */
-
-create database if not exists regulatory;
-
-/* add permissions */
-use regulatory;
-grant all privileges on regulatory.* to admin@localhost identified by '802.11r';
diff --git a/db/01-regulatory.sql b/db/01-regulatory.sql
deleted file mode 100644 (file)
index d1bc5fe..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-use regulatory;
-
-/* This is the DB schema of the CRDA database */
-
-/* Each regulatory rule defined has a set of frequency ranges with
- * an attached power rule. */
-drop table if exists reg_rule;
-CREATE TABLE reg_rule (
-        reg_rule_id    INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
-        freq_range_id  INTEGER NOT NULL default '0',
-        power_rule_id  INTEGER NOT NULL default '0'
-);
-
-/* Frequency ranges */
-drop table if exists freq_range;
-CREATE TABLE freq_range (
-        freq_range_id          INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
-        start_freq_khz         INTEGER NOT NULL default '0',
-        end_freq_khz           INTEGER NOT NULL default '0',
-        max_bandwidth_khz      INTEGER NOT NULL default '0',
-        modulation_cap         INTEGER NOT NULL default '0',
-        misc_restrictions      INTEGER NOT NULL default '0'
-);
-
-/* Power rule. Each power rule can be attached to a frequency range.
- * We use mili to avoid floating point in the kernel.
- * EIRP and IR is given in mili Bells with respect to 1 mili Watt, so mbm
- * Antenna gain        is given in mili Bells with respect to the isotropic, so mbi.
- *
- * Note: a dipole antenna has a gain of 2.14 dBi, so 2140 mBi)
- */
-drop table if exists power_rule;
-CREATE TABLE power_rule (
-        power_rule_id          INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
-        environment_cap                char(1) NOT NULL,
-        max_antenna_gain_mbi   INTEGER NOT NULL default '0',
-        max_ir_ptmp_mbm                INTEGER NOT NULL default '0',
-        max_ir_ptp_mbm         INTEGER NOT NULL default '0',
-        max_eirp_pmtp_mbm      INTEGER NOT NULL default '0',
-        max_eirp_ptp_mbm       INTEGER NOT NULL default '0'
-);
-
-/* Each collection has a list of rules attached it. The reg_collection_id is what we use
- * to group together a bunch of rules into a group. */
-drop table if exists reg_rules_collection;
-CREATE TABLE reg_rules_collection (
-        entry_id               INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
-       reg_collection_id       INTEGER NOT NULL default '0',
-        reg_rule_id            INTEGER NOT NULL default '0'
-);
-
-/* ISO3166-alpha2 <--> regulatory collection id mapping. Each country can have
- * more than one collection id. This allows for large flexibility on how
- * we can group together in collections rule ids. Right now we group together
- * common rules into bands groups (2 GHz and 5 GHz for now) */
-drop table if exists reg_country;
-CREATE TABLE reg_country (
-        reg_country_id         INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
-        alpha2                 char(2) NOT NULL,
-        reg_collection_id      INTEGER NOT NULL default '0'
-);
diff --git a/db/02-freq_range.sql b/db/02-freq_range.sql
deleted file mode 100644 (file)
index f086b3c..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-use regulatory;
-/* DMN_WORLD */
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (2432 * 1000, 2442 * 1000, 20 * 1000, 3);
-
-/* DMN_FCCA */
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (2412 * 1000, 2462 * 1000, 20 * 1000, 3);
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (2437 * 1000, 2437 * 1000, 40 * 1000, 3);
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (2442 * 1000, 2462 * 1000, 20 * 1000, 3);
-
-/* DMN_ETSIC */
-/* first two freq ranges of DMN_FCCA and: */
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (2442 * 1000, 2472 * 1000, 20 * 1000, 3);
-
-/* DMN_MKKA -- 1 freq ranges! */
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (2412 * 1000, 2472 * 1000, 20 * 1000, 3);
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (2484 * 1000, 2484 * 1000, 20 * 1000, 1);
-
-/* DMN_DEBUG */
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (2412 * 1000, 2732 * 1000, 40 * 1000, 3);
-/* There's nother 5 GHz debug below */
-
-/************     5 GHz freq ranges now    ********************/
-
-/* DMN_APL1 */
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5745 * 1000, 5825 * 1000, 20 * 1000, 2);
-
-/* DMN_APL2 */
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5745 * 1000, 5805 * 1000, 20 * 1000, 2);
-
-/* DMN_APL3 */
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5280 * 1000, 5320 * 1000, 20 * 1000, 2);
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5745 * 1000, 5805 * 1000, 20 * 1000, 2);
-
-/* DMN_APL4 --- DMN_ETSI2 uses only the first frequency range */
-/* DMN_ETS5 uses the same freq range as DMN_ETSI2 so we can combine these two */
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5180 * 1000, 5240 * 1000, 20 * 1000, 2);
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5745 * 1000, 5825 * 1000, 20 * 1000, 2);
-
-/* DMN_ETSI1 -- DMN_ETSI3 and DMN_ETSI4 uses the first freq range of DMN_ETSI1 */
-/* DMN_ETSI4 overlaps with ETSI3 so we deleted it */
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5180 * 1000, 5320 * 1000, 20 * 1000, 2);
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5500 * 1000, 5700 * 1000, 20 * 1000, 2);
-
-/* DMN_ETSI6 */
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5180 * 1000, 5280 * 1000, 20 * 1000, 2);
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5500 * 1000, 5700 * 1000, 20 * 1000, 2);
-
-/* DMN_FCC1 */
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5180 * 1000, 5200 * 1000, 20 * 1000, 2);
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5210 * 1000, 5210 * 1000, 40 * 1000, 2);
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5220 * 1000, 5240 * 1000, 20 * 1000, 2);
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5250 * 1000, 5250 * 1000, 40 * 1000, 2);
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5260 * 1000, 5280 * 1000, 20 * 1000, 2);
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5290 * 1000, 5290 * 1000, 40 * 1000, 2);
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5300 * 1000, 5320 * 1000, 20 * 1000, 2);
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5745 * 1000, 5745 * 1000, 20 * 1000, 2);
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5760 * 1000, 5760 * 1000, 40 * 1000, 2);
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5765 * 1000, 5785 * 1000, 20 * 1000, 2);
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5800 * 1000, 5800 * 1000, 40 * 1000, 2);
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5805 * 1000, 5825 * 1000, 20 * 1000, 2);
-
-/* DMN_FCC2 -- the first freq is from ETSI1 (5180 - 5320), the other one is the second one from DMN_APL4 (5745 - 5825) */
-
-/* DMN_FCC3 is DMN_FCC1 + the freqs below */
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5500 * 1000, 5700 * 1000, 20 * 1000, 2);
-
-/* DMN_MKK1 */
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5170 * 1000, 5230 * 1000, 20 * 1000, 2);
-
-/* DMN_MKK2 is DMN_MKK1 + the freqs below */
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5040 * 1000, 5080 * 1000, 20 * 1000, 2);
-
-/* DMN_DEBUG */
-insert into freq_range (start_freq_khz, end_freq_khz, max_bandwidth_khz, modulation_cap) values (5005 * 1000, 6100 * 1000, 40 * 1000, 3);
diff --git a/db/03-power_rule.sql b/db/03-power_rule.sql
deleted file mode 100644 (file)
index e19f3a2..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-use regulatory;
-/*        environment_cap         varchar(255) not null,
-        max_antenna_gain_mbi   int(11) UNSIGNED not null default '0',
-        max_ir_ptmp_mbm        int(11) UNSIGNED not null default '0',
-        max_ir_ptp_mbm         int(11) UNSIGNED not null default '0',
-        max_eirp_pmtp_mbm      int(11) UNSIGNED not null default '0',
-        max_eirp_ptp_mbm       int(11) UNSIGNED not null default '0'
-*/
-insert into power_rule (environment_cap, max_antenna_gain_mbi, max_ir_ptmp_mbm, max_ir_ptp_mbm, max_eirp_pmtp_mbm, max_eirp_ptp_mbm) values (" ", 6 * 1000, 30 * 1000, 30 * 1000, 36 * 1000, 255 * 1000);
diff --git a/db/04-reg_rule.sql b/db/04-reg_rule.sql
deleted file mode 100644 (file)
index 539bdd2..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-use regulatory;
-/*
-        reg_rule_id     int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
-        freq_range_id   int(11) UNSIGNED not null default '0',
-        power_rule_id   int(11) UNSIGNED not null default '0',
-        PRIMARY KEY(reg_rule_id)
-*/
-
-insert into reg_rule (freq_range_id, power_rule_id) values (1, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (2, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (3, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (4, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (5, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (6, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (7, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (8, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (9, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (10, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (11, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (12, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (13, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (14, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (15, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (16, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (17, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (18, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (19, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (20, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (21, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (22, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (23, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (24, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (25, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (26, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (27, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (28, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (29, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (30, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (31, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (32, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (33, 1);
-insert into reg_rule (freq_range_id, power_rule_id) values (34, 1);
diff --git a/db/05-reg_rules_collection.sql b/db/05-reg_rules_collection.sql
deleted file mode 100644 (file)
index 669126a..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-use regulatory;
-/*
-        entry_id                int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
-        reg_collection_id       int(11) UNSIGNED not null default '0',
-        reg_rule_id             int(11) UNSIGNED not null default '0',
-*/
-
-/* Global collection of rules */
-
-/* DMN_NULL_WORLD */
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (1, 1);
-
-/* DMN_NULL_DEBUG */
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (2, 8);
-
-/* DMN_DEBUG_NULL */
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (3, 34);
-
-/* DMN_DEBUG_DEBUG */
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (4, 8);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (4, 34);
-
-/* DMN_NULL_ETSIC */
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (5, 2);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (5, 3);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (5, 5);
-
-/* DMN_FCC1_WORLD */
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (6, 19);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (6, 20);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (6, 21);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (6, 22);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (6, 23);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (6, 24);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (6, 25);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (6, 26);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (6, 27);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (6, 28);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (6, 29);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (6, 30);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (6, 1);
-
-/* DMN_FCC2_WORLD */
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (7, 15);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (7, 14);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (7, 1);
-
-/* DMN_FCC2_FCCA */
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (8, 2);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (8, 3);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (8, 4);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (8, 15);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (8, 14);
-
-/* DMN_FCC2_ETSIC */
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (9, 2);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (9, 3);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (9, 4);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (9, 2);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (9, 3);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (9, 5);
-
-/* DMN_FCC3_FCCA */
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (10, 19);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (10, 20);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (10, 21);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (10, 22);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (10, 23);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (10, 24);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (10, 25);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (10, 26);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (10, 27);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (10, 28);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (10, 29);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (10, 30);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (10, 31);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (10, 15);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (10, 14);
-
-/* DMN_ETSI1_WORLD */
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (11, 15);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (11, 16);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (11, 1);
-
-/* DMN_ETSI2_WORLD */
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (12, 13);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (12, 1);
-
-/* DMN_ETSI3_WORLD */
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (13, 15);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (13, 1);
-
-/* DMN_ETSI6_WORLD */
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (14, 17);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (14, 18);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (14, 1);
-
-/* DMN_MKK1_MKKA */
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (15, 32);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (15, 6);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (15, 7);
-
-/* DMN_MKK1_FCCA */
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (16, 32);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (16, 2);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (16, 3);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (16, 4);
-
-/* DMN_MKK2_MKKA */
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (18, 32);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (18, 33);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (18, 6);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (18, 7);
-
-/* DMN_APL1_WORLD */
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (19, 9);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (19, 1);
-
-/* DMN_APL1_ETSIC */
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (20, 9);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (20, 2);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (20, 3);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (20, 5);
-
-/* DMN_APL2_WORLD */
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (21, 10);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (21, 1);
-
-/* DMN_APL2_ETSIC */
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (22, 10);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (22, 2);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (22, 3);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (22, 5);
-
-/* DMN_APL3_WORLD */
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (23, 11);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (23, 12);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (23, 1);
-
-/* DMN_APL4_WORLD */
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (24, 13);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (24, 14);
-insert into reg_rules_collection (reg_collection_id, reg_rule_id) values (24, 1);
diff --git a/db/06-reg_country.sql b/db/06-reg_country.sql
deleted file mode 100644 (file)
index cb9ffa1..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-use regulatory;
-/*
-        reg_country_id          int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
-        alpha2                  varchar(2) not null,
-        reg_collection_id       int(11) UNSIGNED not null default '0',
-        PRIMARY KEY(reg_country_id)
-*/
-
-/* DMN_NULL_WORLD */
-insert into reg_country (alpha2, reg_collection_id) values ("00", 1);
-/* DMN_NULL_DEBUG*/
-insert into reg_country (alpha2, reg_collection_id) values ("01", 2);
-/* DMN_DEBUG_NULL */
-insert into reg_country (alpha2, reg_collection_id) values ("02", 3);
-/* DMN_DEBUG_DEBUG */
-insert into reg_country (alpha2, reg_collection_id) values ("03", 4);
-
-/* DMN_NULL_ETSIC */
-insert into reg_country (alpha2, reg_collection_id) values ("BR", 5);
-insert into reg_country (alpha2, reg_collection_id) values ("BZ", 5);
-
-/* DMN_FCC1_WORLD */
-insert into reg_country (alpha2, reg_collection_id) values ("PH", 6);
-
-/* DMN_FCC1_FCCA */
-insert into reg_country (alpha2, reg_collection_id) values ("CO", 7);
-insert into reg_country (alpha2, reg_collection_id) values ("DO", 7);
-insert into reg_country (alpha2, reg_collection_id) values ("GT", 7);
-insert into reg_country (alpha2, reg_collection_id) values ("MX", 7);
-insert into reg_country (alpha2, reg_collection_id) values ("PA", 7);
-insert into reg_country (alpha2, reg_collection_id) values ("PR", 7);
-insert into reg_country (alpha2, reg_collection_id) values ("US", 7);
-
-/* DMN_FCC2_WORLD */
-insert into reg_country (alpha2, reg_collection_id) values ("AU", 8);
-insert into reg_country (alpha2, reg_collection_id) values ("HK", 8);
-insert into reg_country (alpha2, reg_collection_id) values ("MO", 8);
-
-/* DMN_FCC2_FCCA */
-insert into reg_country (alpha2, reg_collection_id) values ("CA", 9);
-
-/* DMN_FCC2_ETSIC */
-insert into reg_country (alpha2, reg_collection_id) values ("NZ", 10);
-
-/* DMN_FCC3_FCCA */
-insert into reg_country (alpha2, reg_collection_id) values ("UZ", 11);
-
-/* DMN_ETSI1_WORLD */
-insert into reg_country (alpha2, reg_collection_id) values ("CY", 12);
-insert into reg_country (alpha2, reg_collection_id) values ("DE", 12);
-insert into reg_country (alpha2, reg_collection_id) values ("DK", 12);
-insert into reg_country (alpha2, reg_collection_id) values ("EE", 12);
-insert into reg_country (alpha2, reg_collection_id) values ("ES", 12);
-insert into reg_country (alpha2, reg_collection_id) values ("FI", 12);
-insert into reg_country (alpha2, reg_collection_id) values ("GB", 12);
-insert into reg_country (alpha2, reg_collection_id) values ("IE", 12);
-insert into reg_country (alpha2, reg_collection_id) values ("IS", 12);
-insert into reg_country (alpha2, reg_collection_id) values ("IT", 12);
-insert into reg_country (alpha2, reg_collection_id) values ("LT", 12);
-insert into reg_country (alpha2, reg_collection_id) values ("LU", 12);
-insert into reg_country (alpha2, reg_collection_id) values ("LN", 12);
-insert into reg_country (alpha2, reg_collection_id) values ("NO", 12);
-insert into reg_country (alpha2, reg_collection_id) values ("PL", 12);
-insert into reg_country (alpha2, reg_collection_id) values ("PT", 12);
-insert into reg_country (alpha2, reg_collection_id) values ("SE", 12);
-insert into reg_country (alpha2, reg_collection_id) values ("SI", 12);
-insert into reg_country (alpha2, reg_collection_id) values ("UK", 12);
-insert into reg_country (alpha2, reg_collection_id) values ("ZA", 12);
-
-/* DMN_ETSI2_WORLD */
-insert into reg_country (alpha2, reg_collection_id) values ("CH", 13);
-insert into reg_country (alpha2, reg_collection_id) values ("HU", 13);
-insert into reg_country (alpha2, reg_collection_id) values ("LI", 13);
-insert into reg_country (alpha2, reg_collection_id) values ("AT", 13);
-
-/* DMN_ETSI3_WORLD */
-insert into reg_country (alpha2, reg_collection_id) values ("CZ", 14);
-insert into reg_country (alpha2, reg_collection_id) values ("F2", 14); /* ? */
-insert into reg_country (alpha2, reg_collection_id) values ("HR", 14);
-insert into reg_country (alpha2, reg_collection_id) values ("SK", 14);
-insert into reg_country (alpha2, reg_collection_id) values ("TN", 14);
-insert into reg_country (alpha2, reg_collection_id) values ("TR", 14);
-insert into reg_country (alpha2, reg_collection_id) values ("AM", 14);
-insert into reg_country (alpha2, reg_collection_id) values ("AZ", 14);
-insert into reg_country (alpha2, reg_collection_id) values ("BE", 14);
-insert into reg_country (alpha2, reg_collection_id) values ("GE", 14);
-insert into reg_country (alpha2, reg_collection_id) values ("MC", 14);
-insert into reg_country (alpha2, reg_collection_id) values ("TT", 14);
-
-/* DMN_ETSI6_WORLD */
-insert into reg_country (alpha2, reg_collection_id) values ("BG", 15);
-
-/* DMN_MKK1_MKKA */
-insert into reg_country (alpha2, reg_collection_id) values ("JP", 16);
-/* DMN_MKK2_MKKA */
-insert into reg_country (alpha2, reg_collection_id) values ("J2", 18);
-
-/* DMN_APL1_WORLD */
-insert into reg_country (alpha2, reg_collection_id) values ("BN", 19);
-insert into reg_country (alpha2, reg_collection_id) values ("CH", 19);
-insert into reg_country (alpha2, reg_collection_id) values ("IR", 19);
-insert into reg_country (alpha2, reg_collection_id) values ("CL", 19);
-
-/* DMN_APL1_ETSIC */
-insert into reg_country (alpha2, reg_collection_id) values ("BO", 20);
-
-/* DMN_APL2_WORLD */
-insert into reg_country (alpha2, reg_collection_id) values ("KP", 21);
-insert into reg_country (alpha2, reg_collection_id) values ("KR", 21);
-insert into reg_country (alpha2, reg_collection_id) values ("TH", 21);
-insert into reg_country (alpha2, reg_collection_id) values ("UY", 21);
-
-/* DMN_APL2_ETSIC */
-insert into reg_country (alpha2, reg_collection_id) values ("VE", 22);
-
-/* DMN_APL3_WORLD */
-insert into reg_country (alpha2, reg_collection_id) values ("AR", 23);
-insert into reg_country (alpha2, reg_collection_id) values ("TW", 23);
-
-/* DMN_APL4_WORLD */
-insert into reg_country (alpha2, reg_collection_id) values ("SG", 24);
-
-
diff --git a/db2bin.py b/db2bin.py
new file mode 100755 (executable)
index 0000000..b7d5de4
--- /dev/null
+++ b/db2bin.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+
+from cStringIO import StringIO
+import struct
+import sha
+from dbparse import DBParser, create_rules, create_collections
+
+MAGIC = 0x52474442
+VERSION = 19
+
+def be32(output, val):
+    output.write(struct.pack('>I', val))
+
+class PTR(object):
+    def __init__(self, output):
+        self._output = output
+        self._pos = output.tell()
+        be32(output, 0xFFFFFFFF)
+
+    def set(self, val=None):
+        if val is None:
+            val = self._output.tell()
+        self._offset = val
+        pos = self._output.tell()
+        self._output.seek(self._pos)
+        be32(self._output, val)
+        self._output.seek(pos)
+
+    def get(self):
+        return self._offset
+
+p = DBParser()
+bands, power, countries = p.parse(file('db.txt'))
+rules = create_rules(countries)
+collections = create_collections(countries)
+
+output = StringIO()
+
+# struct regdb_file_header
+be32(output, MAGIC)
+be32(output, VERSION)
+reg_country_ptr = PTR(output)
+# add number of countries
+be32(output, len(countries))
+siglen = PTR(output)
+
+power_rules = {}
+for power_rule_id, pr in power.iteritems():
+    environ = pr[0]
+    pr = [int(v * 1000) for v in pr[1:]]
+    power_rules[power_rule_id] = output.tell()
+    # struct regdb_file_power_rule
+    output.write(struct.pack('>cxxxIIIII', str(environ), *pr))
+
+freq_ranges = {}
+for freq_range_id, fr in bands.iteritems():
+    freq_ranges[freq_range_id] = output.tell()
+    fl = fr[3]
+    fr = [int(f * 1000) for f in fr[:3]]
+    # struct regdb_file_freq_range
+    output.write(struct.pack('>IIIII', fl, fr[0], fr[1], fr[2], 0))
+
+
+reg_rules = {}
+for reg_rule in rules:
+    freq_range_id, power_rule_id = reg_rule
+    reg_rules[reg_rule] = output.tell()
+    # struct regdb_file_reg_rule
+    output.write(struct.pack('>II', freq_ranges[freq_range_id], power_rules[power_rule_id]))
+
+
+reg_rules_collections = {}
+
+for coll in collections:
+    reg_rules_collections[coll] = output.tell()
+    # struct regdb_file_reg_rules_collection
+    be32(output, len(coll))
+    for regrule in coll:
+        be32(output, reg_rules[regrule])
+
+# update country pointer now!
+reg_country_ptr.set()
+
+for alpha2, coll in countries.iteritems():
+    # struct regdb_file_reg_country
+    output.write(struct.pack('>ccxxI', str(alpha2[0]), str(alpha2[1]), reg_rules_collections[coll]))
+
+# Load RSA only now so people can use this script
+# without having those libraries installed to verify
+# their SQL changes
+from M2Crypto import RSA
+
+# determine signature length
+key = RSA.load_key('key.priv.pem')
+hash = sha.new()
+hash.update(output.getvalue())
+sig = key.sign(hash.digest())
+# write it to file
+siglen.set(len(sig))
+# sign again
+hash = sha.new()
+hash.update(output.getvalue())
+sig = key.sign(hash.digest())
+
+output.write(sig)
+
+outfile = open('regulatory.bin', 'w')
+outfile.write(output.getvalue())
diff --git a/dbgen.py b/dbgen.py
deleted file mode 100755 (executable)
index 5a15dfb..0000000
--- a/dbgen.py
+++ /dev/null
@@ -1,134 +0,0 @@
-#!/usr/bin/env python
-
-from pysqlite2 import dbapi2 as db
-from cStringIO import StringIO
-import struct
-import sha
-
-MAGIC = 0x52474442
-VERSION = 19
-
-def be32(output, val):
-    output.write(struct.pack('>I', val))
-
-class PTR(object):
-    def __init__(self, output):
-        self._output = output
-        self._pos = output.tell()
-        be32(output, 0xFFFFFFFF)
-
-    def set(self, val=None):
-        if val is None:
-            val = self._output.tell()
-        self._offset = val
-        pos = self._output.tell()
-        self._output.seek(self._pos)
-        be32(self._output, val)
-        self._output.seek(pos)
-
-    def get(self):
-        return self._offset
-
-regdb = db.connect('regulatory.sqlite')
-cursor = regdb.cursor()
-
-output = StringIO()
-
-# struct regdb_file_header
-be32(output, MAGIC)
-be32(output, VERSION)
-reg_country_ptr = PTR(output)
-# add number of countries
-cursor.execute('SELECT COUNT(*) FROM reg_country;')
-be32(output, cursor.fetchone()[0])
-siglen = PTR(output)
-
-power_rules = {}
-# just to make sure db scheme isn't bad
-cursor.execute('''SELECT power_rule_id,
-                         environment_cap,
-                         max_antenna_gain_mbi,
-                         max_ir_ptmp_mbm,
-                         max_ir_ptp_mbm,
-                         max_eirp_pmtp_mbm,
-                         max_eirp_ptp_mbm FROM power_rule;''')
-for pr in cursor:
-    power_rule_id = pr[0]
-    power_rules[power_rule_id] = output.tell()
-    # struct regdb_file_power_rule
-    output.write(struct.pack('>cxxxIIIII', str(pr[1]), *pr[2:]))
-
-freq_ranges = {}
-# just to make sure db scheme isn't bad
-cursor.execute('''SELECT freq_range_id,
-                         start_freq_khz,
-                         end_freq_khz,
-                         max_bandwidth_khz,
-                         modulation_cap,
-                         misc_restrictions FROM freq_range;''')
-for fr in cursor:
-    freq_range_id = fr[0]
-    freq_ranges[freq_range_id] = output.tell()
-    # struct regdb_file_freq_range
-    output.write(struct.pack('>IIIII', *fr[1:]))
-
-
-reg_rules = {}
-# just to make sure db scheme isn't bad
-cursor.execute('SELECT reg_rule_id, freq_range_id, power_rule_id FROM reg_rule;')
-for reg_rule in cursor:
-    reg_rule_id, freq_range_id, power_rule_id = reg_rule
-    reg_rules[reg_rule_id] = output.tell()
-    # struct regdb_file_reg_rule
-    output.write(struct.pack('>II', freq_ranges[freq_range_id], power_rules[power_rule_id]))
-
-
-collection_data = {}
-# just to make sure db scheme isn't bad
-cursor.execute('SELECT entry_id, reg_collection_id, reg_rule_id FROM reg_rules_collection;')
-for coll in cursor:
-    entry_id, reg_collection_id, reg_rule_id = coll
-    l = collection_data.get(reg_collection_id, [])
-    l.append(reg_rule_id)
-    collection_data[reg_collection_id] = l
-
-reg_rules_collections = {}
-
-for rc, l in collection_data.iteritems():
-    reg_rules_collections[rc] = output.tell()
-    # struct regdb_file_reg_rules_collection
-    be32(output, len(l))
-    for regrule in l:
-        be32(output, reg_rules[regrule])
-
-# update country pointer now!
-reg_country_ptr.set()
-
-# just to make sure db scheme isn't bad
-cursor.execute('SELECT reg_country_id, alpha2, reg_collection_id FROM reg_country;')
-for country in cursor:
-    reg_country_id, alpha2, reg_collection_id = country
-    # struct regdb_file_reg_country
-    output.write(struct.pack('>ccxxI', str(alpha2[0]), str(alpha2[1]), reg_rules_collections[reg_collection_id]))
-
-# Load RSA only now so people can use this script
-# without having those libraries installed to verify
-# their SQL changes
-from M2Crypto import RSA
-
-# determine signature length
-key = RSA.load_key('key.priv.pem')
-hash = sha.new()
-hash.update(output.getvalue())
-sig = key.sign(hash.digest())
-# write it to file
-siglen.set(len(sig))
-# sign again
-hash = sha.new()
-hash.update(output.getvalue())
-sig = key.sign(hash.digest())
-
-output.write(sig)
-
-outfile = open('regulatory.bin', 'w')
-outfile.write(output.getvalue())
diff --git a/dbparse.py b/dbparse.py
new file mode 100644 (file)
index 0000000..d9f0130
--- /dev/null
@@ -0,0 +1,203 @@
+#!/usr/bin/env python
+
+import sys
+
+power_flags = {
+    'OFDM': 2,
+    'CCK': 1,
+}
+
+class SyntaxError(Exception):
+    pass
+
+class DBParser(object):
+    def __init__(self):
+        pass
+
+    def _syntax_error(self, txt=None):
+        txt = txt and ' (%s)' % txt or ''
+        raise SyntaxError("Syntax error in line %d%s" % (self._lineno, txt))
+
+    def _parse_band(self, line):
+        try:
+            bname, line = line.split(':', 1)
+            if not bname:
+                self._syntax_error("'band' keyword must be followed by name")
+        except ValueError:
+            self._syntax_error("band name must be followed by colon")
+
+        try:
+            freqs, line = line.split(',', 1)
+        except ValueError:
+            freqs = line
+            line = ''
+
+        flags = [f.upper() for f in line.split(',') if f]
+
+        try:
+            freqs, bw = freqs.split('@')
+            bw = float(bw)
+        except ValueError:
+            bw = 20.0
+
+        try:
+            start, end = freqs.split('-')
+            start = float(start)
+            end = float(start)
+        except ValueError:
+            self._syntax_error("band must have frequency range")
+
+        fl = 0
+        for f in flags:
+            if not f in power_flags:
+                self._syntax_error("Invalid band flag")
+            fl |= power_flags[f]
+
+        b = (start, end, bw, fl)
+        self._banddup[bname] = bname
+        if b in self._bandrev:
+            sys.stderr.write('Duplicate band definition (%s and %s)\n' % (bname, self._bandrev[b]))
+            self._banddup[bname] = self._bandrev[b]
+        self._bands[bname] = b
+        self._bandrev[b] = bname
+
+    def _parse_power(self, line):
+        try:
+            pname, line = line.split(':', 1)
+            if not pname:
+                self._syntax_error("'power' keyword must be followed by name")
+        except ValueError:
+            self._syntax_error("power name must be followed by colon")
+
+        try:
+            (environ,
+             max_ant_gain,
+             max_ir_ptmp,
+             max_ir_ptp,
+             max_eirp_ptmp,
+             max_eirp_ptp) = line.split(',')
+            max_ant_gain = float(max_ant_gain)
+            max_ir_ptmp = float(max_ir_ptmp)
+            max_ir_ptp = float(max_ir_ptp)
+            max_eirp_ptmp = float(max_eirp_ptmp)
+            max_eirp_ptp = float(max_eirp_ptp)
+        except ValueError:
+            self._syntax_error("invalid power data")
+
+        if environ == 'OI':
+            environ = ' '
+        if not environ in ('I', 'O', ' '):
+            self._syntax_error("Invalid environment specifier")
+
+        p = (environ, max_ant_gain, max_ir_ptmp,
+             max_ir_ptp, max_eirp_ptmp, max_eirp_ptp)
+        self._powerdup[pname] = pname
+        if p in self._powerrev:
+            sys.stderr.write('Duplicate power definition (%s and %s)\n' % (pname, self._powerrev[p]))
+            self._powerdup[pname] = self._powerrev[p]
+        self._power[pname] = p
+        self._powerrev[p] = pname
+
+    def _parse_country(self, line):
+        try:
+            cname, line = line.split(':', 1)
+            if not cname:
+                self._syntax_error("'country' keyword must be followed by name")
+            if line:
+                self._syntax_error("extra data at end of country line")
+        except ValueError:
+            self._syntax_error("country name must be followed by colon")
+
+        if not cname in self._countries:
+            self._countries[cname] = []
+        self._current_country = self._countries[cname]
+
+    def _parse_country_item(self, line):
+        try:
+            bname, pname = line.split(',', 1)
+            if not bname:
+                self._syntax_error("country definition must have band name")
+            if not pname:
+                self._syntax_error("country definition must have power name")
+        except ValueError:
+            self._syntax_error("country definition must have band and power names")
+        if not bname in self._bands:
+            self._syntax_error("band does not exist")
+        if not pname in self._power:
+            self._syntax_error("power does not exist")
+        self._bands_used[bname] = True
+        self._power_used[pname] = True
+        # de-duplicate so binary database is more compact
+        self._current_country.append((self._banddup[bname], self._powerdup[pname]))
+
+    def parse(self, f):
+        self._current_country = None
+        self._bands = {}
+        self._power = {}
+        self._countries = {}
+        self._bands_used = {}
+        self._power_used = {}
+        self._bandrev = {}
+        self._powerrev = {}
+        self._banddup = {}
+        self._powerdup = {}
+
+        self._lineno = 0
+        for line in f:
+            self._lineno += 1
+            line = line.strip()
+            line = line.replace(' ', '').replace('\t', '')
+            line = line.split('#')[0]
+            if not line:
+                continue
+            if line[0:4] == 'band':
+                self._parse_band(line[4:])
+                self._current_country = None
+            elif line[0:5] == 'power':
+                self._parse_power(line[5:])
+                self._current_country = None
+            elif line[0:7] == 'country':
+                self._parse_country(line[7:])
+            elif self._current_country is not None:
+                self._parse_country_item(line)
+            else:
+                self._syntax_error("Expected band, power or country definition")
+
+        countries = {}
+        for k, v in self._countries.iteritems():
+            v.sort()
+            for k in k.split(','):
+                countries[k] = tuple(v)
+        for u in self._bands:
+            if u in self._bands_used:
+                continue
+            sys.stderr.write('Unused band definition "%s"\n' % u)
+        for u in self._power:
+            if u in self._power_used:
+                continue
+            sys.stderr.write('Unused power definition "%s"\n' % u)
+        return self._bands, self._power, countries
+
+def create_rules(countries):
+    result = {}
+    for c in countries.itervalues():
+        for rule in c:
+            result[rule] = 1
+    return result.keys()
+
+def create_collections(countries):
+    result = {}
+    for c in countries.itervalues():
+        c = tuple(c)
+        result[c] = 1
+    return result.keys()
+
+if __name__ == '__main__':
+    import sys
+    p = DBParser()
+    b, p, c = p.parse(sys.stdin)
+    print b
+    print p
+    print c
+    print create_rules(c)
+    print create_collections(c)