1/*****************************************************************************/ 2/* 3 * names.c -- USB name database manipulation routines 4 * 5 * Copyright (C) 1999, 2000 Thomas Sailer (sailer@ife.ee.ethz.ch) 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 * 21 * 22 */ 23 24/* 25 * Copyright (C) 2005 Takahiro Hirofuchi 26 * - names_deinit() is added. 27 */ 28 29/*****************************************************************************/ 30 31#include <sys/types.h> 32#include <sys/stat.h> 33#include <fcntl.h> 34#include <dirent.h> 35#include <string.h> 36#include <errno.h> 37#include <stdlib.h> 38#include <unistd.h> 39#include <stdio.h> 40#include <ctype.h> 41 42 43#include "names.h" 44 45 46/* ---------------------------------------------------------------------- */ 47 48struct vendor { 49 struct vendor *next; 50 u_int16_t vendorid; 51 char name[1]; 52}; 53 54struct product { 55 struct product *next; 56 u_int16_t vendorid, productid; 57 char name[1]; 58}; 59 60struct class { 61 struct class *next; 62 u_int8_t classid; 63 char name[1]; 64}; 65 66struct subclass { 67 struct subclass *next; 68 u_int8_t classid, subclassid; 69 char name[1]; 70}; 71 72struct protocol { 73 struct protocol *next; 74 u_int8_t classid, subclassid, protocolid; 75 char name[1]; 76}; 77 78struct audioterminal { 79 struct audioterminal *next; 80 u_int16_t termt; 81 char name[1]; 82}; 83 84struct genericstrtable { 85 struct genericstrtable *next; 86 unsigned int num; 87 char name[1]; 88}; 89 90/* ---------------------------------------------------------------------- */ 91 92#define HASH1 0x10 93#define HASH2 0x02 94#define HASHSZ 16 95 96static unsigned int hashnum(unsigned int num) 97{ 98 unsigned int mask1 = HASH1 << 27, mask2 = HASH2 << 27; 99 100 for (; mask1 >= HASH1; mask1 >>= 1, mask2 >>= 1) 101 if (num & mask1) 102 num ^= mask2; 103 return num & (HASHSZ-1); 104} 105 106/* ---------------------------------------------------------------------- */ 107 108static struct vendor *vendors[HASHSZ] = { NULL, }; 109static struct product *products[HASHSZ] = { NULL, }; 110static struct class *classes[HASHSZ] = { NULL, }; 111static struct subclass *subclasses[HASHSZ] = { NULL, }; 112static struct protocol *protocols[HASHSZ] = { NULL, }; 113static struct audioterminal *audioterminals[HASHSZ] = { NULL, }; 114static struct genericstrtable *hiddescriptors[HASHSZ] = { NULL, }; 115static struct genericstrtable *reports[HASHSZ] = { NULL, }; 116static struct genericstrtable *huts[HASHSZ] = { NULL, }; 117static struct genericstrtable *biass[HASHSZ] = { NULL, }; 118static struct genericstrtable *physdess[HASHSZ] = { NULL, }; 119static struct genericstrtable *hutus[HASHSZ] = { NULL, }; 120static struct genericstrtable *langids[HASHSZ] = { NULL, }; 121static struct genericstrtable *countrycodes[HASHSZ] = { NULL, }; 122 123/* ---------------------------------------------------------------------- */ 124 125static const char *names_genericstrtable(struct genericstrtable *t[HASHSZ], unsigned int index) 126{ 127 struct genericstrtable *h; 128 129 for (h = t[hashnum(index)]; h; h = h->next) 130 if (h->num == index) 131 return h->name; 132 return NULL; 133} 134 135const char *names_hid(u_int8_t hidd) 136{ 137 return names_genericstrtable(hiddescriptors, hidd); 138} 139 140const char *names_reporttag(u_int8_t rt) 141{ 142 return names_genericstrtable(reports, rt); 143} 144 145const char *names_huts(unsigned int data) 146{ 147 return names_genericstrtable(huts, data); 148} 149 150const char *names_hutus(unsigned int data) 151{ 152 return names_genericstrtable(hutus, data); 153} 154 155const char *names_langid(u_int16_t langid) 156{ 157 return names_genericstrtable(langids, langid); 158} 159 160const char *names_physdes(u_int8_t ph) 161{ 162 return names_genericstrtable(physdess, ph); 163} 164 165const char *names_bias(u_int8_t b) 166{ 167 return names_genericstrtable(biass, b); 168} 169 170const char *names_countrycode(unsigned int countrycode) 171{ 172 return names_genericstrtable(countrycodes, countrycode); 173} 174 175const char *names_vendor(u_int16_t vendorid) 176{ 177 struct vendor *v; 178 179 v = vendors[hashnum(vendorid)]; 180 for (; v; v = v->next) 181 if (v->vendorid == vendorid) 182 return v->name; 183 return NULL; 184} 185 186const char *names_product(u_int16_t vendorid, u_int16_t productid) 187{ 188 struct product *p; 189 190 p = products[hashnum((vendorid << 16) | productid)]; 191 for (; p; p = p->next) 192 if (p->vendorid == vendorid && p->productid == productid) 193 return p->name; 194 return NULL; 195} 196 197const char *names_class(u_int8_t classid) 198{ 199 struct class *c; 200 201 c = classes[hashnum(classid)]; 202 for (; c; c = c->next) 203 if (c->classid == classid) 204 return c->name; 205 return NULL; 206} 207 208const char *names_subclass(u_int8_t classid, u_int8_t subclassid) 209{ 210 struct subclass *s; 211 212 s = subclasses[hashnum((classid << 8) | subclassid)]; 213 for (; s; s = s->next) 214 if (s->classid == classid && s->subclassid == subclassid) 215 return s->name; 216 return NULL; 217} 218 219const char *names_protocol(u_int8_t classid, u_int8_t subclassid, u_int8_t protocolid) 220{ 221 struct protocol *p; 222 223 p = protocols[hashnum((classid << 16) | (subclassid << 8) | protocolid)]; 224 for (; p; p = p->next) 225 if (p->classid == classid && p->subclassid == subclassid && p->protocolid == protocolid) 226 return p->name; 227 return NULL; 228} 229 230const char *names_audioterminal(u_int16_t termt) 231{ 232 struct audioterminal *at; 233 234 at = audioterminals[hashnum(termt)]; 235 for (; at; at = at->next) 236 if (at->termt == termt) 237 return at->name; 238 return NULL; 239} 240 241/* ---------------------------------------------------------------------- */ 242/* add a cleanup function by takahiro */ 243 244struct pool { 245 struct pool *next; 246 void *mem; 247}; 248 249static struct pool *pool_head = NULL; 250 251static void *my_malloc(size_t size) 252{ 253 struct pool *p; 254 255 p = calloc(1, sizeof(struct pool)); 256 if (!p) { 257 free(p); 258 return NULL; 259 } 260 261 p->mem = calloc(1, size); 262 if (!p->mem) 263 return NULL; 264 265 p->next = pool_head; 266 pool_head = p; 267 268 return p->mem; 269} 270 271void names_free(void) 272{ 273 struct pool *pool; 274 275 if (!pool_head) 276 return; 277 278 for (pool = pool_head; pool != NULL; ) { 279 struct pool *tmp; 280 281 if (pool->mem) 282 free(pool->mem); 283 284 tmp = pool; 285 pool = pool->next; 286 free(tmp); 287 } 288} 289 290/* ---------------------------------------------------------------------- */ 291 292static int new_vendor(const char *name, u_int16_t vendorid) 293{ 294 struct vendor *v; 295 unsigned int h = hashnum(vendorid); 296 297 v = vendors[h]; 298 for (; v; v = v->next) 299 if (v->vendorid == vendorid) 300 return -1; 301 v = my_malloc(sizeof(struct vendor) + strlen(name)); 302 if (!v) 303 return -1; 304 strcpy(v->name, name); 305 v->vendorid = vendorid; 306 v->next = vendors[h]; 307 vendors[h] = v; 308 return 0; 309} 310 311static int new_product(const char *name, u_int16_t vendorid, u_int16_t productid) 312{ 313 struct product *p; 314 unsigned int h = hashnum((vendorid << 16) | productid); 315 316 p = products[h]; 317 for (; p; p = p->next) 318 if (p->vendorid == vendorid && p->productid == productid) 319 return -1; 320 p = my_malloc(sizeof(struct product) + strlen(name)); 321 if (!p) 322 return -1; 323 strcpy(p->name, name); 324 p->vendorid = vendorid; 325 p->productid = productid; 326 p->next = products[h]; 327 products[h] = p; 328 return 0; 329} 330 331static int new_class(const char *name, u_int8_t classid) 332{ 333 struct class *c; 334 unsigned int h = hashnum(classid); 335 336 c = classes[h]; 337 for (; c; c = c->next) 338 if (c->classid == classid) 339 return -1; 340 c = my_malloc(sizeof(struct class) + strlen(name)); 341 if (!c) 342 return -1; 343 strcpy(c->name, name); 344 c->classid = classid; 345 c->next = classes[h]; 346 classes[h] = c; 347 return 0; 348} 349 350static int new_subclass(const char *name, u_int8_t classid, u_int8_t subclassid) 351{ 352 struct subclass *s; 353 unsigned int h = hashnum((classid << 8) | subclassid); 354 355 s = subclasses[h]; 356 for (; s; s = s->next) 357 if (s->classid == classid && s->subclassid == subclassid) 358 return -1; 359 s = my_malloc(sizeof(struct subclass) + strlen(name)); 360 if (!s) 361 return -1; 362 strcpy(s->name, name); 363 s->classid = classid; 364 s->subclassid = subclassid; 365 s->next = subclasses[h]; 366 subclasses[h] = s; 367 return 0; 368} 369 370static int new_protocol(const char *name, u_int8_t classid, u_int8_t subclassid, u_int8_t protocolid) 371{ 372 struct protocol *p; 373 unsigned int h = hashnum((classid << 16) | (subclassid << 8) | protocolid); 374 375 p = protocols[h]; 376 for (; p; p = p->next) 377 if (p->classid == classid && p->subclassid == subclassid && p->protocolid == protocolid) 378 return -1; 379 p = my_malloc(sizeof(struct protocol) + strlen(name)); 380 if (!p) 381 return -1; 382 strcpy(p->name, name); 383 p->classid = classid; 384 p->subclassid = subclassid; 385 p->protocolid = protocolid; 386 p->next = protocols[h]; 387 protocols[h] = p; 388 return 0; 389} 390 391static int new_audioterminal(const char *name, u_int16_t termt) 392{ 393 struct audioterminal *at; 394 unsigned int h = hashnum(termt); 395 396 at = audioterminals[h]; 397 for (; at; at = at->next) 398 if (at->termt == termt) 399 return -1; 400 at = my_malloc(sizeof(struct audioterminal) + strlen(name)); 401 if (!at) 402 return -1; 403 strcpy(at->name, name); 404 at->termt = termt; 405 at->next = audioterminals[h]; 406 audioterminals[h] = at; 407 return 0; 408} 409 410static int new_genericstrtable(struct genericstrtable *t[HASHSZ], const char *name, unsigned int index) 411{ 412 struct genericstrtable *g; 413 unsigned int h = hashnum(index); 414 415 for (g = t[h]; g; g = g->next) 416 if (g->num == index) 417 return -1; 418 g = my_malloc(sizeof(struct genericstrtable) + strlen(name)); 419 if (!g) 420 return -1; 421 strcpy(g->name, name); 422 g->num = index; 423 g->next = t[h]; 424 t[h] = g; 425 return 0; 426} 427 428static int new_hid(const char *name, u_int8_t hidd) 429{ 430 return new_genericstrtable(hiddescriptors, name, hidd); 431} 432 433static int new_reporttag(const char *name, u_int8_t rt) 434{ 435 return new_genericstrtable(reports, name, rt); 436} 437 438static int new_huts(const char *name, unsigned int data) 439{ 440 return new_genericstrtable(huts, name, data); 441} 442 443static int new_hutus(const char *name, unsigned int data) 444{ 445 return new_genericstrtable(hutus, name, data); 446} 447 448static int new_langid(const char *name, u_int16_t langid) 449{ 450 return new_genericstrtable(langids, name, langid); 451} 452 453static int new_physdes(const char *name, u_int8_t ph) 454{ 455 return new_genericstrtable(physdess, name, ph); 456} 457static int new_bias(const char *name, u_int8_t b) 458{ 459 return new_genericstrtable(biass, name, b); 460} 461 462static int new_countrycode(const char *name, unsigned int countrycode) 463{ 464 return new_genericstrtable(countrycodes, name, countrycode); 465} 466 467/* ---------------------------------------------------------------------- */ 468 469#define DBG(x) 470 471static void parse(FILE *f) 472{ 473 char buf[512], *cp; 474 unsigned int linectr = 0; 475 int lastvendor = -1, lastclass = -1, lastsubclass = -1, lasthut=-1, lastlang=-1; 476 unsigned int u; 477 478 while (fgets(buf, sizeof(buf), f)) { 479 linectr++; 480 /* remove line ends */ 481 if ((cp = strchr(buf, 13))) 482 *cp = 0; 483 if ((cp = strchr(buf, 10))) 484 *cp = 0; 485 if (buf[0] == '#' || !buf[0]) 486 continue; 487 cp = buf; 488 if (buf[0] == 'P' && buf[1] == 'H' && buf[2] == 'Y' && buf[3] == 'S' && buf[4] == 'D' && 489 buf[5] == 'E' && buf[6] == 'S' && /*isspace(buf[7])*/ buf[7] == ' ') { 490 cp = buf + 8; 491 while (isspace(*cp)) 492 cp++; 493 if (!isxdigit(*cp)) { 494 fprintf(stderr, "Invalid Physdes type at line %u\n", linectr); 495 continue; 496 } 497 u = strtoul(cp, &cp, 16); 498 while (isspace(*cp)) 499 cp++; 500 if (!*cp) { 501 fprintf(stderr, "Invalid Physdes type at line %u\n", linectr); 502 continue; 503 } 504 if (new_physdes(cp, u)) 505 fprintf(stderr, "Duplicate Physdes type spec at line %u terminal type %04x %s\n", linectr, u, cp); 506 DBG(printf("line %5u physdes type %02x %s\n", linectr, u, cp)); 507 continue; 508 509 } 510 if (buf[0] == 'P' && buf[1] == 'H' && buf[2] == 'Y' && /*isspace(buf[3])*/ buf[3] == ' ') { 511 cp = buf + 4; 512 while (isspace(*cp)) 513 cp++; 514 if (!isxdigit(*cp)) { 515 fprintf(stderr, "Invalid PHY type at line %u\n", linectr); 516 continue; 517 } 518 u = strtoul(cp, &cp, 16); 519 while (isspace(*cp)) 520 cp++; 521 if (!*cp) { 522 fprintf(stderr, "Invalid PHY type at line %u\n", linectr); 523 continue; 524 } 525 if (new_physdes(cp, u)) 526 fprintf(stderr, "Duplicate PHY type spec at line %u terminal type %04x %s\n", linectr, u, cp); 527 DBG(printf("line %5u PHY type %02x %s\n", linectr, u, cp)); 528 continue; 529 530 } 531 if (buf[0] == 'B' && buf[1] == 'I' && buf[2] == 'A' && buf[3] == 'S' && /*isspace(buf[4])*/ buf[4] == ' ') { 532 cp = buf + 5; 533 while (isspace(*cp)) 534 cp++; 535 if (!isxdigit(*cp)) { 536 fprintf(stderr, "Invalid BIAS type at line %u\n", linectr); 537 continue; 538 } 539 u = strtoul(cp, &cp, 16); 540 while (isspace(*cp)) 541 cp++; 542 if (!*cp) { 543 fprintf(stderr, "Invalid BIAS type at line %u\n", linectr); 544 continue; 545 } 546 if (new_bias(cp, u)) 547 fprintf(stderr, "Duplicate BIAS type spec at line %u terminal type %04x %s\n", linectr, u, cp); 548 DBG(printf("line %5u BIAS type %02x %s\n", linectr, u, cp)); 549 continue; 550 551 } 552 if (buf[0] == 'L' && /*isspace(buf[1])*/ buf[1] == ' ') { 553 cp = buf+2; 554 while (isspace(*cp)) 555 cp++; 556 if (!isxdigit(*cp)) { 557 fprintf(stderr, "Invalid LANGID spec at line %u\n", linectr); 558 continue; 559 } 560 u = strtoul(cp, &cp, 16); 561 while (isspace(*cp)) 562 cp++; 563 if (!*cp) { 564 fprintf(stderr, "Invalid LANGID spec at line %u\n", linectr); 565 continue; 566 } 567 if (new_langid(cp, u)) 568 fprintf(stderr, "Duplicate LANGID spec at line %u language-id %04x %s\n", linectr, u, cp); 569 DBG(printf("line %5u LANGID %02x %s\n", linectr, u, cp)); 570 lasthut = lastclass = lastvendor = lastsubclass = -1; 571 lastlang = u; 572 continue; 573 } 574 if (buf[0] == 'C' && /*isspace(buf[1])*/ buf[1] == ' ') { 575 /* class spec */ 576 cp = buf+2; 577 while (isspace(*cp)) 578 cp++; 579 if (!isxdigit(*cp)) { 580 fprintf(stderr, "Invalid class spec at line %u\n", linectr); 581 continue; 582 } 583 u = strtoul(cp, &cp, 16); 584 while (isspace(*cp)) 585 cp++; 586 if (!*cp) { 587 fprintf(stderr, "Invalid class spec at line %u\n", linectr); 588 continue; 589 } 590 if (new_class(cp, u)) 591 fprintf(stderr, "Duplicate class spec at line %u class %04x %s\n", linectr, u, cp); 592 DBG(printf("line %5u class %02x %s\n", linectr, u, cp)); 593 lasthut = lastlang = lastvendor = lastsubclass = -1; 594 lastclass = u; 595 continue; 596 } 597 if (buf[0] == 'A' && buf[1] == 'T' && isspace(buf[2])) { 598 /* audio terminal type spec */ 599 cp = buf+3; 600 while (isspace(*cp)) 601 cp++; 602 if (!isxdigit(*cp)) { 603 fprintf(stderr, "Invalid audio terminal type at line %u\n", linectr); 604 continue; 605 } 606 u = strtoul(cp, &cp, 16); 607 while (isspace(*cp)) 608 cp++; 609 if (!*cp) { 610 fprintf(stderr, "Invalid audio terminal type at line %u\n", linectr); 611 continue; 612 } 613 if (new_audioterminal(cp, u)) 614 fprintf(stderr, "Duplicate audio terminal type spec at line %u terminal type %04x %s\n", linectr, u, cp); 615 DBG(printf("line %5u audio terminal type %02x %s\n", linectr, u, cp)); 616 continue; 617 } 618 if (buf[0] == 'H' && buf[1] == 'C' && buf[2] == 'C' && isspace(buf[3])) { 619 /* HID Descriptor bCountryCode */ 620 cp = buf+3; 621 while (isspace(*cp)) 622 cp++; 623 if (!isxdigit(*cp)) { 624 fprintf(stderr, "Invalid HID country code at line %u\n", linectr); 625 continue; 626 } 627 u = strtoul(cp, &cp, 10); 628 while (isspace(*cp)) 629 cp++; 630 if (!*cp) { 631 fprintf(stderr, "Invalid HID country code at line %u\n", linectr); 632 continue; 633 } 634 if (new_countrycode(cp, u)) 635 fprintf(stderr, "Duplicate HID country code at line %u country %02u %s\n", linectr, u, cp); 636 DBG(printf("line %5u keyboard country code %02u %s\n", linectr, u, cp)); 637 continue; 638 } 639 if (isxdigit(*cp)) { 640 /* vendor */ 641 u = strtoul(cp, &cp, 16); 642 while (isspace(*cp)) 643 cp++; 644 if (!*cp) { 645 fprintf(stderr, "Invalid vendor spec at line %u\n", linectr); 646 continue; 647 } 648 if (new_vendor(cp, u)) 649 fprintf(stderr, "Duplicate vendor spec at line %u vendor %04x %s\n", linectr, u, cp); 650 DBG(printf("line %5u vendor %04x %s\n", linectr, u, cp)); 651 lastvendor = u; 652 lasthut = lastlang = lastclass = lastsubclass = -1; 653 continue; 654 } 655 if (buf[0] == '\t' && isxdigit(buf[1])) { 656 /* product or subclass spec */ 657 u = strtoul(buf+1, &cp, 16); 658 while (isspace(*cp)) 659 cp++; 660 if (!*cp) { 661 fprintf(stderr, "Invalid product/subclass spec at line %u\n", linectr); 662 continue; 663 } 664 if (lastvendor != -1) { 665 if (new_product(cp, lastvendor, u)) 666 fprintf(stderr, "Duplicate product spec at line %u product %04x:%04x %s\n", linectr, lastvendor, u, cp); 667 DBG(printf("line %5u product %04x:%04x %s\n", linectr, lastvendor, u, cp)); 668 continue; 669 } 670 if (lastclass != -1) { 671 if (new_subclass(cp, lastclass, u)) 672 fprintf(stderr, "Duplicate subclass spec at line %u class %02x:%02x %s\n", linectr, lastclass, u, cp); 673 DBG(printf("line %5u subclass %02x:%02x %s\n", linectr, lastclass, u, cp)); 674 lastsubclass = u; 675 continue; 676 } 677 if (lasthut != -1) { 678 if (new_hutus(cp, (lasthut << 16)+u)) 679 fprintf(stderr, "Duplicate HUT Usage Spec at line %u\n", linectr); 680 continue; 681 } 682 if (lastlang != -1) { 683 if (new_langid(cp, lastlang+(u<<10))) 684 fprintf(stderr, "Duplicate LANGID Usage Spec at line %u\n", linectr); 685 continue; 686 } 687 fprintf(stderr, "Product/Subclass spec without prior Vendor/Class spec at line %u\n", linectr); 688 continue; 689 } 690 if (buf[0] == '\t' && buf[1] == '\t' && isxdigit(buf[2])) { 691 /* protocol spec */ 692 u = strtoul(buf+2, &cp, 16); 693 while (isspace(*cp)) 694 cp++; 695 if (!*cp) { 696 fprintf(stderr, "Invalid protocol spec at line %u\n", linectr); 697 continue; 698 } 699 if (lastclass != -1 && lastsubclass != -1) { 700 if (new_protocol(cp, lastclass, lastsubclass, u)) 701 fprintf(stderr, "Duplicate protocol spec at line %u class %02x:%02x:%02x %s\n", linectr, lastclass, lastsubclass, u, cp); 702 DBG(printf("line %5u protocol %02x:%02x:%02x %s\n", linectr, lastclass, lastsubclass, u, cp)); 703 continue; 704 } 705 fprintf(stderr, "Protocol spec without prior Class and Subclass spec at line %u\n", linectr); 706 continue; 707 } 708 if (buf[0] == 'H' && buf[1] == 'I' && buf[2] == 'D' && /*isspace(buf[3])*/ buf[3] == ' ') { 709 cp = buf + 4; 710 while (isspace(*cp)) 711 cp++; 712 if (!isxdigit(*cp)) { 713 fprintf(stderr, "Invalid HID type at line %u\n", linectr); 714 continue; 715 } 716 u = strtoul(cp, &cp, 16); 717 while (isspace(*cp)) 718 cp++; 719 if (!*cp) { 720 fprintf(stderr, "Invalid HID type at line %u\n", linectr); 721 continue; 722 } 723 if (new_hid(cp, u)) 724 fprintf(stderr, "Duplicate HID type spec at line %u terminal type %04x %s\n", linectr, u, cp); 725 DBG(printf("line %5u HID type %02x %s\n", linectr, u, cp)); 726 continue; 727 728 } 729 if (buf[0] == 'H' && buf[1] == 'U' && buf[2] == 'T' && /*isspace(buf[3])*/ buf[3] == ' ') { 730 cp = buf + 4; 731 while (isspace(*cp)) 732 cp++; 733 if (!isxdigit(*cp)) { 734 fprintf(stderr, "Invalid HUT type at line %u\n", linectr); 735 continue; 736 } 737 u = strtoul(cp, &cp, 16); 738 while (isspace(*cp)) 739 cp++; 740 if (!*cp) { 741 fprintf(stderr, "Invalid HUT type at line %u\n", linectr); 742 continue; 743 } 744 if (new_huts(cp, u)) 745 fprintf(stderr, "Duplicate HUT type spec at line %u terminal type %04x %s\n", linectr, u, cp); 746 lastlang = lastclass = lastvendor = lastsubclass = -1; 747 lasthut = u; 748 DBG(printf("line %5u HUT type %02x %s\n", linectr, u, cp)); 749 continue; 750 751 } 752 if (buf[0] == 'R' && buf[1] == ' ') { 753 cp = buf + 2; 754 while (isspace(*cp)) 755 cp++; 756 if (!isxdigit(*cp)) { 757 fprintf(stderr, "Invalid Report type at line %u\n", linectr); 758 continue; 759 } 760 u = strtoul(cp, &cp, 16); 761 while (isspace(*cp)) 762 cp++; 763 if (!*cp) { 764 fprintf(stderr, "Invalid Report type at line %u\n", linectr); 765 continue; 766 } 767 if (new_reporttag(cp, u)) 768 fprintf(stderr, "Duplicate Report type spec at line %u terminal type %04x %s\n", linectr, u, cp); 769 DBG(printf("line %5u Report type %02x %s\n", linectr, u, cp)); 770 continue; 771 772 } 773 if (buf[0] == 'V' && buf[1] == 'T') { 774 /* add here */ 775 continue; 776 } 777 fprintf(stderr, "Unknown line at line %u\n", linectr); 778 } 779} 780 781/* ---------------------------------------------------------------------- */ 782 783int names_init(char *n) 784{ 785 FILE *f; 786 787 if (!(f = fopen(n, "r"))) { 788 return errno; 789 } 790 parse(f); 791 fclose(f); 792 return 0; 793} 794