8 I'm desperate ... an attempt to create C #defines from WSPP bitmaps
10 This takes a text bitmap from WSPP on stdin and produces C defines
13 Here is an example from MS-DRSR section 5.37
15 0 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 20 1 2 3 4 5 6 7 8 9 30 1
18 A G A A W I P M A T C G G X S F X F X X R X X S X S D D U N S G
20 S C R L R S S R S S O A S N S S G S F A P C N P P
31 X: Unused. MUST be zero and ignored.
33 AS (DRS_ASYNC_OP): Perform the operation asynchronously.
35 GC (DRS_GETCHG_CHECK): Treat ERROR_DS_DRA_REF_NOT_FOUND and
36 ERROR_DS_DRA_REF_ALREADY_EXISTS as success for calls to IDL_DRSUpdateRefs (section
39 AR (DRS_ADD_REF): Register a client DC for notifications of updates to the NC replica.
41 ALL (DRS_SYNC_ALL): Replicate from all server DCs.
43 DR (DRS_DEL_REF): Deregister a client DC from notifications of updates to the NC replica.
45 WR (DRS_WRIT_REP): Replicate a writable replica, not a read-only partial replica or read-only full
48 IS (DRS_INIT_SYNC): Perform replication at startup.
50 PS (DRS_PER_SYNC): Perform replication periodically.
52 MR (DRS_MAIL_REP): Perform replication using SMTP as a transport.
54 ASR (DRS_ASYNC_REP): Populate the NC replica asynchronously.
56 IE (DRS_IGNORE_ERROR): Ignore errors.
58 TS (DRS_TWOWAY_SYNC): Inform the server DC to replicate from the client DC.
60 CO (DRS_CRITICAL_ONLY): Replicate only system-critical objects.
62 GA (DRS_GET_ANC): Include updates to ancestor objects before updates to their descendants.
64 GS (DRS_GET_NC_SIZE): Get the approximate size of the server NC replica.
66 LO (DRS_LOCAL_ONLY): Perform the operation locally without contacting any other DC.
68 SN (DRS_SYNC_BYNAME): Choose the source server by network name.
70 RF (DRS_REF_OK): Allow the NC replica to be removed even if other DCs use this DC as a
71 replication server DC.
73 FS (DRS_FULL_SYNC_NOW): Replicate all updates in the replication cycle, even those that would
76 NS (DRS_NO_SOURCE): The NC replica has no server DCs.
78 FSP (DRS_FULL_SYNC_PACKET): Replicate all updates in the replication request, even those that
79 would normally be filtered.
81 RG (DRS_REF_GCSPN): Requests that the server add an entry to repsTo for the client on the root
82 object of the NC replica that is being replicated. When repsTo is set using this flag, the server
83 contacts the client using GC SPN (section 2.2.3.2).
85 SS (DRS_SPECIAL_SECRET_PROCESSING): Do not replicate attribute values of attributes that
88 SF (DRS_SYNC_FORCED): Force replication, even if the replication system is otherwise disabled.
90 DAS (DRS_DISABLE_AUTO_SYNC): Disable replication induced by update notifications.
92 DPS (DRS_DISABLE_PERIODIC_SYNC): Disable periodic replication.
94 UC (DRS_USE_COMPRESSION): Compress response messages.
96 NN (DRS_NEVER_NOTIFY): Do not send update notifications.
98 SP (DRS_SYNC_PAS): Expand the partial attribute set of the partial replica.
100 GP (DRS_GET_ALL_GROUP_MEMBERSHIP): Replicate all kinds of group membership. If this flag
101 is not present nonuniversal group membership will not be replicated.
103 I got the above from "pdftotext -layout [MS-DRSR].pdf"
107 #define BIT_DRS_ASYNC_OP 0x00000001
108 #define BIT_DRS_GETCHG_CHECK 0x00000002
109 #define BIT_DRS_ADD_REF 0x00000004
110 #define BIT_DRS_SYNC_ALL 0x00000008
111 #define BIT_DRS_DEL_REF 0x00000008
112 #define BIT_DRS_WRIT_REP 0x00000010
113 #define BIT_DRS_INIT_SYNC 0x00000020
114 #define BIT_DRS_PER_SYNC 0x00000040
115 #define BIT_DRS_MAIL_REP 0x00000080
116 #define BIT_DRS_ASYNC_REP 0x00000100
117 #define BIT_DRS_IGNORE_ERROR 0x00000100
118 #define BIT_DRS_TWOWAY_SYNC 0x00000200
119 #define BIT_DRS_CRITICAL_ONLY 0x00000400
120 #define BIT_DRS_GET_ANC 0x00000800
121 #define BIT_DRS_GET_NC_SIZE 0x00001000
122 #define BIT_DRS_LOCAL_ONLY 0x00001000
123 #define BIT_DRS_SYNC_BYNAME 0x00004000
124 #define BIT_DRS_REF_OK 0x00004000
125 #define BIT_DRS_FULL_SYNC_NOW 0x00008000
126 #define BIT_DRS_NO_SOURCE 0x00008000
127 #define BIT_DRS_FULL_SYNC_PACKET 0x00020000
128 #define BIT_DRS_REF_GCSPN 0x00100000
129 #define BIT_DRS_SPECIAL_SECRET_PROCESSING 0x00800000
130 #define BIT_DRS_SYNC_FORCED 0x02000000
131 #define BIT_DRS_DISABLE_AUTO_SYNC 0x04000000
132 #define BIT_DRS_DISABLE_PERIODIC_SYNC 0x08000000
133 #define BIT_DRS_USE_COMPRESSION 0x10000000
134 #define BIT_DRS_NEVER_NOTIFY 0x20000000
135 #define BIT_DRS_SYNC_PAS 0x40000000
136 #define BIT_DRS_GET_ALL_GROUP_MEMBERSHIP 0x80000000
143 #define MAX_MAPPINGS 100
144 static int num_mappings;
146 const char *short_form;
147 const char *long_form;
148 } mappings[MAX_MAPPINGS];
149 static int longest_mapping;
151 static void add_mapping(char *line)
155 if (num_mappings == MAX_MAPPINGS) {
156 printf("/* (%d) too many mappings! */\n", line_num);
160 p = strchr(line, ':');
161 if (p == NULL) return;
163 p = strchr(line, '(');
164 if (p == NULL) return;
166 mappings[num_mappings].long_form = strdup(p+1);
167 for (p=line; isspace(*p); p++) ;
168 mappings[num_mappings].short_form = strdup(p);
169 p = strchr(mappings[num_mappings].long_form, ')');
170 if (p == NULL) return;
173 p = strchr(mappings[num_mappings].short_form, ' ');
174 if (p == NULL) return;
177 if (strlen(mappings[num_mappings].long_form) > longest_mapping) {
178 longest_mapping = strlen(mappings[num_mappings].long_form);
184 static const char *map_name(const char *s)
187 for (i=0; i<num_mappings; i++) {
188 if (strcmp(s, mappings[i].short_form) == 0) {
189 return mappings[i].long_form;
195 static char *remove_spaces(const char *s)
197 char *ret = strdup(s);
209 #define MAX_WIDTH 200
211 static int nlines = 0;
212 static char lines[MAX_LINES][MAX_WIDTH];
214 static void report(void)
218 for (i=0; i<nlines; i++) {
219 printf(" line[%d]: %s\n", i, lines[i]);
224 static void fatal(void)
226 printf("/* fatal error on line %d\n", line_num);
231 static void shift_it(int lnum, int to, int from)
235 for (i=lnum; i<nlines; i++) {
236 if (lines[i][from] == ' ') break;
237 if (lines[i][to] != ' ') {
238 printf("/* (line %d) Non-empty to position at line %d posn %d\n */", line_num, i, to);
241 lines[i][to] = lines[i][from];
242 lines[i][from] = ' ';
247 try to detect section boundaries
249 int section_start(const char *line)
252 if (!isdigit(line[0])) return 0;
253 p = strchr(line, ' ');
255 if (strspn(line, "0123456789.") != (p-line)) return 0;
259 static const char *prefix = "BIT_";
260 static int idl_format = 0;
261 static int little_endian = 0;
262 static int big_endian = 0;
263 static int auto_endian = 0;
265 static int process_bitmap(const char *comment, FILE *f, char **next_section)
272 int more_sections = 0;
273 int this_one_little_endian = little_endian;
274 int this_one_big_endian = big_endian;
276 memset(lines, 0, sizeof(lines));
281 while (fgets(lines[nlines], MAX_WIDTH-1, f)) {
282 char *line = lines[nlines];
287 if (line[strlen(line)-1] == '\n') {
288 line[strlen(line)-1] = 0;
290 if (line[0] == 0xC) {
291 memmove(&line[0], &line[1], strlen(line));
294 if (section_start(line)) {
296 (*next_section) = strdup(line);
302 strstr(line, "little-endian byte order")) {
303 this_one_little_endian = 1;
307 strstr(line, "big-endian byte order")) {
308 this_one_big_endian = 1;
312 /* discard preamble lines */
313 if (strncmp(remove_spaces(line), "0123456789", 10) != 0) {
318 if (sscanf(line, "%u / %u", &dummy, &dummy) == 2) {
322 /* detect the start of the descriptions */
323 for (i=0; line[i]; i++) {
324 if (line[i] != ' ' &&
338 /* some bitmaps contain 10/20/30 instead of 0 */
339 if ((p = strstr(line, "10 "))) {
342 if ((p = strstr(line, "20 "))) {
345 if ((p = strstr(line, "30 "))) {
348 /* discard empty lines */
349 if (strlen(line) > 0) {
351 if (strlen(line) > max_len) {
352 max_len = strlen(line);
358 return more_sections;
361 /* pad lines with spaces if needed */
362 for (i=0; i<nlines; i++) {
363 if (strlen(lines[i]) < max_len) {
364 memset(&lines[i][strlen(lines[i])], ' ', max_len - strlen(lines[i]));
368 /* normalise the 2nd line */
369 for (i=0; lines[0][i]; i++) {
372 if (lines[0][i] == ' ' && lines[1][i] == ' ') continue;
374 if (lines[0][i] != ' ' && lines[1][i] != ' ') {
375 /* already aligned */
379 if (lines[0][i] == ' ') {
380 /* we need to shift the next digit left */
381 for (tpos = i+1; tpos<max_len; tpos++) {
382 if (lines[0][tpos] != ' ') {
386 if (tpos == max_len) {
387 printf("/* (line %d) no digit match at pos %d */\n", line_num, i);
389 return more_sections;
391 lines[0][i] = lines[0][tpos];
392 lines[0][tpos] = ' ';
396 /* now we need to look for the missing tag either to
397 * the left or right. Try left first */
398 for (tpos = i-1; tpos>=0; tpos--) {
399 if (lines[0][tpos] != ' ') {
400 /* already taken - give up going left */
403 if (lines[1][tpos] != ' ') {
408 shift_it(1, i, tpos);
412 for (tpos = i+1; tpos<max_len; tpos++) {
413 if (lines[1][tpos] != ' ') {
417 if (tpos < max_len) {
418 shift_it(1, i, tpos);
421 printf("/* (line %d) No match at position %d of line 1 */\n", line_num, i);
423 return more_sections;
427 /* normalise the subsequent lines */
428 for (lnum=2; lnum<nlines; lnum++) {
429 for (i=0; lines[0][i]; i++) {
431 if (lines[0][i] == ' ' && lines[lnum][i] != ' ') {
432 /* a little lost character ... try to
434 for (tpos = i-1; tpos>=0; tpos--) {
435 if (lines[lnum][tpos] != ' ') {
436 /* already taken - give up going left */
439 if (lines[0][tpos] != ' ') {
443 if (tpos >= 0 && lines[lnum][tpos] == ' ') {
444 shift_it(lnum, tpos, i);
447 for (tpos = i+1; tpos<max_len; tpos++) {
448 if (lines[0][tpos] != ' ') {
452 if (tpos < max_len) {
453 if (lines[lnum][tpos] != ' ') {
454 if (lines[lnum][tpos+1] == ' ') {
455 shift_it(lnum, tpos+1, tpos);
458 if (lines[lnum][tpos] == ' ') {
459 shift_it(lnum, tpos, i);
463 printf("/* (line %d) Nowhere to put character '%c' at pos %d of subline %d */\n",
464 line_num, lines[lnum][i], i, lnum);
466 return more_sections;
472 printf("/* (line %d): \n", line_num);
473 for (i=0; i<nlines; i++) {
474 printf(" line[%d]: %s\n", i, lines[i]);
482 printf("/* %s */\n", comment);
484 for (i=0; lines[0][i]; i++) {
486 char name[MAX_LINES+1] = "";
489 if (lines[0][i] == ' ') continue;
490 for (n=1; n<nlines; n++) {
491 if (lines[n][i] == ' ') break;
492 name[n-1] = lines[n][i];
494 for (t = strtok(name, "/"); t; t=strtok(NULL, "/")) {
495 const char *mapped_name = map_name(t);
498 if (this_one_little_endian) {
499 int bpos, bnum = bitpos/8;
500 bpos = (bnum*8) + (7 - (bitpos%8));
502 } else if (this_one_big_endian) {
503 value = (1U<<(31-bitpos));
505 value = (1U<<bitpos);
507 if (strcmp(t, "X") == 0 || strcmp(t, "0") == 0) continue;
509 printf("%s%-*s = 0x%08x,\n", prefix, longest_mapping, mapped_name, value);
511 printf("#define %s%-*s 0x%08x\n", prefix, longest_mapping, mapped_name, value);
518 return more_sections;
522 static void usage(void)
524 printf("wspp_bits [options] <file>\n");
525 printf("Options:\n");
526 printf("\t-i use IDL bitmap format\n");
527 printf("\t-L use little-endian bit order\n");
528 printf("\t-A attempt to auto-detect endianness\n");
529 printf("\t-p PREFIX use the given prefix\n");
530 printf("\t-v increase verbosity\n");
533 int main(int argc, char * const argv[])
537 char *sect_name = NULL;
539 while ((opt = getopt(argc, argv, "vip:ALBh")) != -1) {
571 f = fopen(argv[0], "r");
578 while (process_bitmap(sect_name, f, §_name)) ;