~ubuntu-branches/ubuntu/intrepid/xserver-xgl/intrepid

« back to all changes in this revision

Viewing changes to hw/xfree86/utils/xorgcfg/cards.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-13 14:21:43 UTC
  • Revision ID: james.westby@ubuntu.com-20060213142143-mad6z9xzem7hzxz9
Tags: upstream-7.0.0
ImportĀ upstreamĀ versionĀ 7.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2000 by Conectiva S.A. (http://www.conectiva.com)
 
3
 * 
 
4
 * Permission is hereby granted, free of charge, to any person obtaining a
 
5
 * copy of this software and associated documentation files (the "Software"),
 
6
 * to deal in the Software without restriction, including without limitation
 
7
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
8
 * and/or sell copies of the Software, and to permit persons to whom the
 
9
 * Software is furnished to do so, subject to the following conditions:
 
10
 * 
 
11
 * The above copyright notice and this permission notice shall be included in
 
12
 * all copies or substantial portions of the Software.
 
13
 *  
 
14
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
15
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
16
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
17
 * CONECTIVA LINUX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 
18
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
 
19
 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 
20
 * SOFTWARE.
 
21
 * 
 
22
 * Except as contained in this notice, the name of Conectiva Linux shall
 
23
 * not be used in advertising or otherwise to promote the sale, use or other
 
24
 * dealings in this Software without prior written authorization from
 
25
 * Conectiva Linux.
 
26
 *
 
27
 * Author: Paulo CĆ©sar Pereira de Andrade <pcpa@conectiva.com.br>
 
28
 *
 
29
 * $XFree86: xc/programs/Xserver/hw/xfree86/xf86cfg/cards.c,v 1.14 2002/09/12 15:19:07 tsi Exp $
 
30
 */
 
31
 
 
32
#define CARDS_PRIVATE
 
33
#include "cards.h"
 
34
 
 
35
#undef SERVER   /* defined in config.h, but of no use here */
 
36
 
 
37
/* return values from ReadCardsLine. */
 
38
#define ERROR           -3
 
39
#define UNKNOWN         -2
 
40
#define END             -1
 
41
#define NOTUSEFUL       0
 
42
#define NAME            1
 
43
#define CHIPSET         2
 
44
#define SERVER          3
 
45
#define DRIVER          4
 
46
#define RAMDAC          5
 
47
#define CLOCKCHIP       6
 
48
#define DACSPEED        7
 
49
#define NOCLOCKPROBE    8
 
50
#define UNSUPPORTED     9
 
51
#define SEE             10
 
52
#define LINE            11
 
53
 
 
54
/*
 
55
 * Prototypes
 
56
 */
 
57
static int ReadCardsLine(FILE*, char*); /* must have 256 bytes */
 
58
static int CompareCards(_Xconst void *left, _Xconst void *right);
 
59
static int BCompareCards(_Xconst void *left, _Xconst void *right);
 
60
static void DoReadCardsDatabase(void);
 
61
static char **DoFilterCardNames(char *pattern, int *result);
 
62
 
 
63
#ifdef USE_MODULES
 
64
 
 
65
typedef struct {
 
66
    int ivendor;
 
67
    unsigned short vendor;
 
68
    unsigned short valid_vendor;
 
69
    char *chipsets;
 
70
    int num_chipsets;
 
71
} chipset_check;
 
72
#endif
 
73
 
 
74
/*
 
75
 * Initialization
 
76
 */
 
77
static int linenum = 0;
 
78
static char *Cards = "lib/X11/Cards";
 
79
CardsEntry **CardsDB;
 
80
int NumCardsEntry;
 
81
 
 
82
/*
 
83
 * Implementation
 
84
 */
 
85
#ifdef USE_MODULES
 
86
const pciVendorInfo *xf86PCIVendorInfo;
 
87
#endif
 
88
 
 
89
#ifdef USE_MODULES
 
90
void
 
91
InitializePciInfo(void)
 
92
{
 
93
    xf86PCIVendorInfo = pciVendorInfoList;
 
94
}
 
95
 
 
96
void
 
97
CheckChipsets(xf86cfgModuleOptions *opts, int *err)
 
98
{
 
99
    int i, j, ichk, ivnd = 0, vendor = -1, device;
 
100
    const pciDeviceInfo **pDev;
 
101
    SymTabPtr chips = opts->chipsets;
 
102
    chipset_check *check = NULL;
 
103
    int num_check = 0;
 
104
 
 
105
    if (!chips) {
 
106
        CheckMsg(CHECKER_NO_CHIPSETS, "WARNING No chipsets specified.\n");
 
107
        ++*err;
 
108
        return;
 
109
    }
 
110
 
 
111
    while (chips->name) {
 
112
        device = chips->token & 0xffff;
 
113
        vendor = (chips->token & 0xffff0000) >> 16;
 
114
        if (vendor == 0)
 
115
            vendor = opts->vendor;
 
116
 
 
117
        for (ichk = 0; ichk < num_check; ichk++)
 
118
            if (check[ichk].vendor == vendor)
 
119
                break;
 
120
        if (ichk >= num_check) {
 
121
            check = (chipset_check*)
 
122
                XtRealloc((XtPointer)check,
 
123
                          sizeof(chipset_check) * (num_check + 1));
 
124
            check[num_check].vendor = vendor;
 
125
            memset(&check[num_check], 0, sizeof(chipset_check));
 
126
            ++num_check;
 
127
        }
 
128
 
 
129
        /* Search for vendor in xf86PCIVendorInfo */
 
130
        if (xf86PCIVendorInfo) {
 
131
            for (ivnd = 0; xf86PCIVendorInfo[ivnd].VendorID; ivnd++)
 
132
                if (vendor == xf86PCIVendorInfo[ivnd].VendorID)
 
133
                    break;
 
134
        }
 
135
        if (xf86PCIVendorInfo && xf86PCIVendorInfo[ivnd].VendorID) {
 
136
            check[ichk].valid_vendor = 1;
 
137
            check[ichk].ivendor = ivnd;
 
138
        }
 
139
        else {
 
140
            CheckMsg(CHECKER_CANNOT_VERIFY_CHIPSET,
 
141
                     "WARNING Cannot verify chipset \"%s\" (0x%x)\n",
 
142
                      chips->name, device);
 
143
            ++*err;
 
144
            ++chips;
 
145
            continue;
 
146
        }
 
147
 
 
148
        if (xf86PCIVendorInfo &&
 
149
            (pDev = xf86PCIVendorInfo[ivnd].Device) != NULL) {
 
150
            if (check[ichk].chipsets == NULL) {
 
151
                for (j = 0; pDev[j]; j++)
 
152
                    ;
 
153
                check[ichk].chipsets = (char*)XtCalloc(1, j);
 
154
            }
 
155
            for (j = 0; pDev[j]; j++) {
 
156
                if (device == pDev[j]->DeviceID) {
 
157
                    if (strcmp(chips->name, pDev[j]->DeviceName)) {
 
158
                        CheckMsg(CHECKER_NOMATCH_CHIPSET_STRINGS,
 
159
                             "WARNING chipset strings don't match: \"%s\" \"%s\" (0x%x)\n",
 
160
                             chips->name, xf86PCIVendorInfo[ivnd].Device[j]->DeviceName,
 
161
                             device);
 
162
                        ++*err;
 
163
                    }
 
164
                    break;
 
165
                }
 
166
            }
 
167
            if (!pDev[j]) {
 
168
                CheckMsg(CHECKER_CHIPSET_NOT_LISTED,
 
169
                     "WARNING chipset \"%s\" (0x%x) not in list.\n", chips->name, device);
 
170
                ++*err;
 
171
            }
 
172
            else
 
173
                check[ichk].chipsets[j] = 1;
 
174
        }
 
175
        ++chips;
 
176
    }
 
177
 
 
178
    for (i = 0; i < num_check; i++) {
 
179
        if (!check[i].valid_vendor) {
 
180
            CheckMsg(CHECKER_CHIPSET_NO_VENDOR,
 
181
                     "WARNING No such vendor 0x%x\n", vendor);
 
182
            ++*err;
 
183
        }
 
184
        for (j = 0; j < check[i].num_chipsets; j++) {
 
185
            if (xf86PCIVendorInfo && !check[i].chipsets[j]) {
 
186
                CheckMsg(CHECKER_CHIPSET_NOT_SUPPORTED,
 
187
                         "NOTICE chipset \"%s\" (0x%x) not listed as supported.\n",
 
188
                         xf86PCIVendorInfo[check[i].ivendor].Device[j]->DeviceName,
 
189
                         xf86PCIVendorInfo[check[i].ivendor].Device[j]->DeviceID);
 
190
            }
 
191
        }
 
192
        XtFree(check[i].chipsets);
 
193
    }
 
194
 
 
195
    XtFree((XtPointer)check);
 
196
}
 
197
#endif
 
198
 
 
199
void
 
200
ReadCardsDatabase(void)
 
201
{
 
202
#ifdef USE_MODULES
 
203
    if (!nomodules) {
 
204
        int i, j, ivendor, idevice;
 
205
        char name[256];
 
206
        _Xconst char *vendor, *device;
 
207
        CardsEntry *entry = NULL, *tmp;
 
208
        xf86cfgModuleOptions *opts = module_options;
 
209
        const pciDeviceInfo **pDev;
 
210
 
 
211
        /* Only list cards that have a driver installed */
 
212
        while (opts) {
 
213
            if (opts->chipsets) {
 
214
                SymTabPtr chips = opts->chipsets;
 
215
 
 
216
                while (chips->name) {
 
217
                    vendor = opts->name;
 
218
                    device = chips->name;
 
219
                    ivendor = (chips->token & 0xffff0000) >> 16;
 
220
                    idevice = chips->token & 0xffff0;
 
221
                    if (ivendor == 0)
 
222
                        ivendor = opts->vendor;
 
223
 
 
224
                    if (xf86PCIVendorInfo) {
 
225
                        for (i = 0; xf86PCIVendorInfo[i].VendorName; i++)
 
226
                            if (ivendor == xf86PCIVendorInfo[i].VendorID) {
 
227
                                vendor = xf86PCIVendorInfo[i].VendorName;
 
228
                                break;
 
229
                            }
 
230
                        if (xf86PCIVendorInfo[i].VendorName) {
 
231
                            if ((pDev = xf86PCIVendorInfo[i].Device)) {
 
232
                                for (j = 0; pDev[j]; j++)
 
233
                                    if (idevice == pDev[j]->DeviceID) {
 
234
                                        device = pDev[j]->DeviceName;
 
235
                                        break;
 
236
                                    }
 
237
                            }
 
238
                        }
 
239
                    }
 
240
 
 
241
                    /* Since frequently there is more than one driver for a
 
242
                     * single vendor, it is required to avoid duplicates.
 
243
                     */
 
244
                    XmuSnprintf(name, sizeof(name), "%s %s", vendor, device);
 
245
                    tmp = LookupCard(name);
 
246
 
 
247
                    if (tmp == NULL || strcmp(tmp->chipset, chips->name) ||
 
248
                        strcmp(tmp->driver, opts->name)) {
 
249
                        entry = (CardsEntry*)XtCalloc(1, sizeof(CardsEntry));
 
250
                        if (NumCardsEntry % 16 == 0) {
 
251
                            CardsDB = (CardsEntry**)XtRealloc((XtPointer)CardsDB,
 
252
                                    sizeof(CardsEntry*) * (NumCardsEntry + 16));
 
253
                        }
 
254
                        CardsDB[NumCardsEntry++] = entry;
 
255
                        entry->name = XtNewString(name);
 
256
 
 
257
                        /* XXX no private copy of strings */
 
258
                        entry->chipset = (char*)chips->name;
 
259
                        entry->driver = opts->name;
 
260
 
 
261
                        /* better than linear searchs to find duplicates */
 
262
                        qsort(CardsDB, NumCardsEntry, sizeof(CardsEntry*),
 
263
                              CompareCards);
 
264
                    }
 
265
                    ++chips;
 
266
                }
 
267
            }
 
268
            opts = opts->next;
 
269
        }
 
270
 
 
271
        /* fix entries with the same name */
 
272
        for (i = 0; i < NumCardsEntry - 2;) {
 
273
            for (j = i + 1; j < NumCardsEntry - 1 &&
 
274
                 strcmp(CardsDB[i]->name, CardsDB[j]->name) == 0; j++)
 
275
                    ;
 
276
 
 
277
            if (i + 1 != j) {
 
278
                while (i < j) {
 
279
                    char *str;
 
280
 
 
281
                    if (strcmp(CardsDB[i]->chipset, CardsDB[j]->chipset))
 
282
                        str = CardsDB[i]->chipset;
 
283
                    else
 
284
                        str = CardsDB[i]->driver;
 
285
 
 
286
                    XmuSnprintf(name, sizeof(name), "%s (%s)",
 
287
                                CardsDB[i]->name, str);
 
288
                    XtFree(CardsDB[i]->name);
 
289
                    CardsDB[i]->name = XtNewString(name);
 
290
 
 
291
                    ++i;
 
292
                }
 
293
            }
 
294
            else
 
295
                ++i;
 
296
        }
 
297
 
 
298
        /* make sure data is valid to bsearch in */
 
299
        qsort(CardsDB, NumCardsEntry, sizeof(CardsEntry*), CompareCards);
 
300
    }
 
301
    else
 
302
#endif
 
303
        DoReadCardsDatabase();
 
304
}
 
305
 
 
306
static void
 
307
DoReadCardsDatabase(void)
 
308
{
 
309
    char buffer[256];
 
310
    FILE *fp = fopen(Cards, "r");
 
311
    int i, result;
 
312
    CardsEntry *entry = NULL;
 
313
    static char *CardsError = "Error reading Cards database, at line %d (%s).\n";
 
314
 
 
315
    if (fp == NULL) {
 
316
        fprintf(stderr, "Cannot open Cards database.\n");
 
317
        exit(1);
 
318
    }
 
319
 
 
320
    while ((result = ReadCardsLine(fp, buffer)) != END) {
 
321
        switch (result) {
 
322
            case ERROR:
 
323
                fprintf(stderr, CardsError, linenum, buffer);
 
324
                break;
 
325
            case UNKNOWN:
 
326
                fprintf(stderr,
 
327
                        "Unknown field type in Cards database, at line %d (%s).\n",
 
328
                        linenum, buffer);
 
329
                break;
 
330
            case NAME:
 
331
                entry = calloc(1, sizeof(CardsEntry));
 
332
                if (NumCardsEntry % 16 == 0) {
 
333
                    CardsDB = realloc(CardsDB, sizeof(CardsEntry*) *
 
334
                                      (NumCardsEntry + 16));
 
335
                    if (CardsDB == NULL) {
 
336
                        fprintf(stderr, "Out of memory reading Cards database.\n");
 
337
                        exit(1);
 
338
                    }
 
339
                }
 
340
                CardsDB[NumCardsEntry++] = entry;
 
341
                entry->name = strdup(buffer);
 
342
                break;
 
343
            case CHIPSET:
 
344
                if (entry == NULL || entry->chipset != NULL) {
 
345
                    fprintf(stderr, CardsError, linenum, buffer);
 
346
                }
 
347
#if 0
 
348
                else
 
349
                    entry->chipset = strdup(buffer);
 
350
#endif
 
351
                break;
 
352
            case SERVER:
 
353
                if (entry == NULL || entry->server != NULL) {
 
354
                    fprintf(stderr, CardsError, linenum, buffer);
 
355
                }
 
356
                else
 
357
                    entry->server = strdup(buffer);
 
358
                break;
 
359
            case DRIVER:
 
360
                if (entry == NULL || entry->driver != NULL) {
 
361
                    fprintf(stderr, CardsError, linenum, buffer);
 
362
                }
 
363
                else
 
364
                    entry->driver = strdup(buffer);
 
365
                break;
 
366
            case RAMDAC:
 
367
                if (entry == NULL || entry->ramdac != NULL) {
 
368
                    fprintf(stderr, CardsError, linenum, buffer);
 
369
                }
 
370
                else
 
371
                    entry->ramdac = strdup(buffer);
 
372
                break;
 
373
            case CLOCKCHIP:
 
374
                if (entry == NULL || entry->clockchip != NULL) {
 
375
                    fprintf(stderr, CardsError, linenum, buffer);
 
376
                }
 
377
                else
 
378
                    entry->clockchip = strdup(buffer);
 
379
                break;
 
380
            case DACSPEED:
 
381
                if (entry == NULL || entry->dacspeed != NULL) {
 
382
                    fprintf(stderr, CardsError, linenum, buffer);
 
383
                }
 
384
                else
 
385
                    entry->dacspeed = strdup(buffer);
 
386
                break;
 
387
            case NOCLOCKPROBE:
 
388
                if (entry == NULL) {
 
389
                    fprintf(stderr, CardsError, linenum, buffer);
 
390
                }
 
391
                else
 
392
                    entry->flags |= F_NOCLOCKPROBE;
 
393
                break;
 
394
            case UNSUPPORTED:
 
395
                if (entry == NULL) {
 
396
                    fprintf(stderr, CardsError, linenum, buffer);
 
397
                }
 
398
                else
 
399
                    entry->flags |= F_UNSUPPORTED;
 
400
                break;
 
401
            case SEE:
 
402
                if (entry == NULL || entry->see != NULL) {
 
403
                    fprintf(stderr, CardsError, linenum, buffer);
 
404
                }
 
405
                else
 
406
                    entry->see = strdup(buffer);
 
407
                break;
 
408
            case LINE:
 
409
                if (entry == NULL) {
 
410
                    fprintf(stderr, CardsError, linenum, buffer);
 
411
                }
 
412
                else if (entry->lines == NULL)
 
413
                    entry->lines = strdup(buffer);
 
414
                else {
 
415
                    char *str = malloc(strlen(entry->lines) + strlen(buffer) + 2);
 
416
 
 
417
                    sprintf(str, "%s\n%s", entry->lines, buffer);
 
418
                    free(entry->lines);
 
419
                    entry->lines = str;
 
420
                }
 
421
                break;
 
422
        }
 
423
    }
 
424
 
 
425
    fclose(fp);
 
426
 
 
427
    qsort(CardsDB, NumCardsEntry, sizeof(CardsEntry*), CompareCards);
 
428
 
 
429
#ifdef DEBUG
 
430
    for (i = 0; i < NumCardsEntry - 1; i++) {
 
431
        if (strcmp(CardsDB[i]->name, CardsDB[i+1]->name) == 0)
 
432
            fprintf(stderr, "Duplicate entry in Cards database: (%s).\n",
 
433
                    CardsDB[i]->name);
 
434
    }
 
435
#endif
 
436
 
 
437
    for (i = 0; i < NumCardsEntry - 1; i++) {
 
438
        if (CardsDB[i]->see != NULL) {
 
439
            if ((entry = LookupCard(CardsDB[i]->see)) == NULL) {
 
440
                fprintf(stderr, "Cannot find card '%s' for filling defaults.\n",
 
441
                        CardsDB[i]->see);
 
442
                continue;
 
443
            }
 
444
            if (CardsDB[i]->chipset == NULL && entry->chipset != NULL)
 
445
                CardsDB[i]->chipset = strdup(entry->chipset);
 
446
            if (CardsDB[i]->server == NULL && entry->server != NULL)
 
447
                CardsDB[i]->server = strdup(entry->server);
 
448
            if (CardsDB[i]->driver == NULL && entry->driver != NULL)
 
449
                CardsDB[i]->driver = strdup(entry->driver);
 
450
            if (CardsDB[i]->ramdac == NULL && entry->ramdac != NULL)
 
451
                CardsDB[i]->ramdac = strdup(entry->ramdac);
 
452
            if (CardsDB[i]->clockchip == NULL && entry->clockchip != NULL)
 
453
                CardsDB[i]->clockchip = strdup(entry->clockchip);
 
454
            if (CardsDB[i]->dacspeed == NULL && entry->dacspeed != NULL)
 
455
                CardsDB[i]->dacspeed = strdup(entry->dacspeed);
 
456
            if (CardsDB[i]->flags & F_NOCLOCKPROBE)
 
457
                CardsDB[i]->flags |= F_NOCLOCKPROBE;
 
458
            if (CardsDB[i]->flags & F_UNSUPPORTED)
 
459
                CardsDB[i]->flags |= F_UNSUPPORTED;
 
460
            if (entry->lines != NULL) {
 
461
                if (CardsDB[i]->lines == NULL)
 
462
                    CardsDB[i]->lines = strdup(entry->lines);
 
463
                else {
 
464
                    char *str = malloc(strlen(entry->lines) +
 
465
                                              strlen(CardsDB[i]->lines) + 2);
 
466
 
 
467
                    sprintf(str, "%s\n%s", CardsDB[i]->lines, entry->lines);
 
468
                    free(CardsDB[i]->lines);
 
469
                    CardsDB[i]->lines = str;
 
470
                }
 
471
            }
 
472
            if (entry->see != NULL) {
 
473
#ifdef DEBUG
 
474
                fprintf(stderr, "Nested SEE entry: %s -> %s -> %s\n",
 
475
                        CardsDB[i]->name, CardsDB[i]->see, entry->see);
 
476
#endif
 
477
                CardsDB[i]->see = strdup(entry->see);
 
478
                --i;
 
479
                continue;
 
480
            }
 
481
            free(CardsDB[i]->see);
 
482
            CardsDB[i]->see = NULL;
 
483
        }
 
484
    }
 
485
}
 
486
 
 
487
CardsEntry *
 
488
LookupCard(char *name)
 
489
{
 
490
    CardsEntry **ptr;
 
491
 
 
492
    if (NumCardsEntry == 0 || CardsDB == 0)
 
493
        return NULL;
 
494
 
 
495
    ptr = (CardsEntry**)bsearch(name, CardsDB, NumCardsEntry,
 
496
                                sizeof(CardsEntry*), BCompareCards);
 
497
 
 
498
    return (ptr != NULL ? *ptr : NULL);
 
499
}
 
500
 
 
501
char **
 
502
GetCardNames(int *result)
 
503
{
 
504
    char **cards = NULL;
 
505
    int ncards;
 
506
 
 
507
    for (ncards = 0; ncards < NumCardsEntry; ncards++) {
 
508
        if (ncards % 16 == 0) {
 
509
            if ((cards = (char**)realloc(cards, sizeof(char*) *
 
510
                                         (ncards + 16))) == NULL) {
 
511
                fprintf(stderr, "Out of memory.\n");
 
512
                exit(1);
 
513
            }
 
514
        }
 
515
        cards[ncards] = strdup(CardsDB[ncards]->name);
 
516
    }
 
517
 
 
518
    *result = ncards;
 
519
 
 
520
    return (cards);
 
521
}
 
522
 
 
523
char **
 
524
FilterCardNames(char *pattern, int *result)
 
525
{
 
526
#ifdef USE_MODULES
 
527
    if (!nomodules) {
 
528
        char **cards = NULL;
 
529
        int i, ncards = 0;
 
530
 
 
531
        for (i = 0; i < NumCardsEntry; i++) {
 
532
            if (strstr(CardsDB[i]->name, pattern) == NULL)
 
533
                continue;
 
534
            if (ncards % 16 == 0) {
 
535
                if ((cards = (char**)realloc(cards, sizeof(char*) *
 
536
                                             (ncards + 16))) == NULL) {
 
537
                    fprintf(stderr, "Out of memory.\n");
 
538
                    exit(1);
 
539
                }
 
540
            }
 
541
            cards[ncards] = strdup(CardsDB[i]->name);
 
542
            ++ncards;
 
543
        }
 
544
 
 
545
        *result = ncards;
 
546
 
 
547
        return (cards);
 
548
    }
 
549
#endif
 
550
    return (DoFilterCardNames(pattern, result));
 
551
}
 
552
 
 
553
static char **
 
554
DoFilterCardNames(char *pattern, int *result)
 
555
{
 
556
    FILE *fp;
 
557
    char **cards = NULL;
 
558
    int len, ncards = 0;
 
559
    char *cmd, *ptr, buffer[256];
 
560
 
 
561
    cmd = malloc(32 + (strlen(pattern) * 2) + strlen(Cards));
 
562
 
 
563
    strcpy(cmd, "egrep -i '^NAME\\ .*");
 
564
    len = strlen(cmd);
 
565
    ptr = pattern;
 
566
    while (*ptr) {
 
567
        if (!isalnum(*ptr)) {
 
568
            cmd[len++] = '\\';
 
569
        }
 
570
        cmd[len++] = *ptr++;
 
571
    }
 
572
    cmd[len] = '\0';
 
573
    strcat(cmd, ".*$' ");
 
574
    strcat(cmd, Cards);
 
575
    strcat(cmd, " | sort");
 
576
    /*sprintf(cmd, "egrep -i '^NAME\\ .*%s.*$' %s | sort", pattern, Cards);*/
 
577
 
 
578
    if ((fp = popen(cmd, "r")) == NULL) {
 
579
        fprintf(stderr, "Cannot read Cards database.\n");
 
580
        exit(1);
 
581
    }
 
582
    while (fgets(buffer, sizeof(buffer), fp) != NULL) {
 
583
        ptr = buffer + strlen(buffer) - 1;
 
584
        while (isspace(*ptr) && ptr > buffer)
 
585
            --ptr;
 
586
        if (!isspace(*ptr) && ptr > buffer)
 
587
            ptr[1] = '\0';
 
588
        ptr = buffer;
 
589
        while (!isspace(*ptr) && *ptr)  /* skip NAME */
 
590
            ++ptr;
 
591
        while (isspace(*ptr) && *ptr)
 
592
            ++ptr;
 
593
        if (ncards % 16 == 0) {
 
594
            if ((cards = (char**)realloc(cards, sizeof(char*) *
 
595
                                         (ncards + 16))) == NULL) {
 
596
                fprintf(stderr, "Out of memory.\n");
 
597
                exit(1);
 
598
            }
 
599
        }
 
600
        cards[ncards++] = strdup(ptr);
 
601
    }
 
602
    free(cmd);
 
603
 
 
604
    *result = ncards;
 
605
 
 
606
    return (cards);
 
607
}
 
608
 
 
609
static int
 
610
ReadCardsLine(FILE *fp, char *value)
 
611
{
 
612
    char name[32], buffer[256], *ptr, *end;
 
613
    int result = NOTUSEFUL;
 
614
 
 
615
    ++linenum;
 
616
 
 
617
    if (fgets(buffer, sizeof(buffer), fp) == NULL)
 
618
        return (END);
 
619
 
 
620
    ptr = buffer;
 
621
    /* skip initial spaces; should'nt bother about this.. */
 
622
    while (isspace(*ptr) && *ptr)
 
623
        ++ptr;
 
624
 
 
625
    if (*ptr == '#' || *ptr == '\0')
 
626
        return (NOTUSEFUL);
 
627
 
 
628
    end = ptr;
 
629
    while (!isspace(*end) && *end)
 
630
        ++end;
 
631
    if (end - ptr > sizeof(buffer) - 1) {
 
632
        strncpy(value, buffer, 255);
 
633
        value[255] = '\0';
 
634
        return (ERROR);
 
635
    }
 
636
    strncpy(name, ptr, end - ptr);
 
637
    name[end - ptr] = '\0';
 
638
 
 
639
    /* read the optional arguments */
 
640
    ptr = end;
 
641
    while (isspace(*ptr) && *ptr)
 
642
        ++ptr;
 
643
 
 
644
    end = ptr + strlen(ptr) - 1;
 
645
    while (isspace(*end) && end > ptr)
 
646
        --end;
 
647
    if (!isspace(*end))
 
648
        ++end;
 
649
    *end = '\0';
 
650
 
 
651
    if (strcmp(name, "NAME") == 0)
 
652
        result = NAME;
 
653
    else if (strcmp(name, "CHIPSET") == 0)
 
654
        result = CHIPSET;
 
655
    else if (strcmp(name, "SERVER") == 0)
 
656
        result = SERVER;
 
657
    else if (strcmp(name, "DRIVER") == 0)
 
658
        result = DRIVER;
 
659
    else if (strcmp(name, "RAMDAC") == 0)
 
660
        result = RAMDAC;
 
661
    else if (strcmp(name, "CLOCKCHIP") == 0)
 
662
        result = CLOCKCHIP;
 
663
    else if (strcmp(name, "DACSPEED") == 0)
 
664
        result = DACSPEED;
 
665
    else if (strcmp(name, "NOCLOCKPROBE") == 0)
 
666
        result = NOCLOCKPROBE;
 
667
    else if (strcmp(name, "UNSUPPORTED") == 0)
 
668
        result = UNSUPPORTED;
 
669
    else if (strcmp(name, "SEE") == 0)
 
670
        result = SEE;
 
671
    else if (strcmp(name, "LINE") == 0)
 
672
        result = LINE;
 
673
    else if (strcmp(name, "END") == 0)
 
674
        result = END;
 
675
    else {
 
676
        strcpy(value, name);
 
677
        return (UNKNOWN);
 
678
    }
 
679
 
 
680
    /* value *must* have at least 256 bytes */
 
681
    strcpy(value, ptr);
 
682
 
 
683
    return (result);
 
684
}
 
685
 
 
686
static int
 
687
CompareCards(_Xconst void *left, _Xconst void *right)
 
688
{
 
689
    return strcasecmp((*(CardsEntry**)left)->name, (*(CardsEntry**)right)->name);
 
690
}
 
691
 
 
692
static int
 
693
BCompareCards(_Xconst void *name, _Xconst void *card)
 
694
{
 
695
  return (strcasecmp((char*)name, (*(CardsEntry**)card)->name));
 
696
}