~ubuntu-branches/ubuntu/precise/nvidia-settings/precise-proposed

« back to all changes in this revision

Viewing changes to nvidia-settings-1.0/src/parse.c

  • Committer: Bazaar Package Importer
  • Author(s): Randall Donald
  • Date: 2004-07-03 19:09:17 UTC
  • Revision ID: james.westby@ubuntu.com-20040703190917-rqkze2s58ux5pamy
Tags: upstream-1.0
ImportĀ upstreamĀ versionĀ 1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * nvidia-settings: A tool for configuring the NVIDIA X driver on Unix
 
3
 * and Linux systems.
 
4
 *
 
5
 * Copyright (C) 2004 NVIDIA Corporation.
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or
 
8
 * modify it under the terms of Version 2 of the GNU General Public
 
9
 * License as published by the Free Software Foundation.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful, but
 
12
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See Version 2
 
14
 * of the GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the:
 
18
 *
 
19
 *           Free Software Foundation, Inc.
 
20
 *           59 Temple Place - Suite 330
 
21
 *           Boston, MA 02111-1307, USA
 
22
 *
 
23
 */
 
24
 
 
25
#include <stdio.h>
 
26
#include <stdlib.h>
 
27
#include <ctype.h>
 
28
#include <string.h>
 
29
#include <sys/utsname.h>
 
30
 
 
31
#include "NVCtrl.h"
 
32
 
 
33
#include "parse.h"
 
34
#include "NvCtrlAttributes.h"
 
35
 
 
36
/* local helper functions */
 
37
 
 
38
static char **nv_strtok(char *s, char c, int *n);
 
39
static void nv_free_strtoks(char **s, int n);
 
40
static int ctoi(const char c);
 
41
static int count_number_of_chars(char *o, char d);
 
42
static char *nv_strndup(char *s, int n);
 
43
 
 
44
/*
 
45
 * Table of all attribute names recognized by the attribute string
 
46
 * parser.  Binds attribute names to attribute integers (for use in
 
47
 * the NvControl protocol).  The flags describe qualities of each
 
48
 * attribute.
 
49
 */
 
50
 
 
51
#define F NV_PARSER_TYPE_FRAMELOCK 
 
52
#define C NV_PARSER_TYPE_COLOR_ATTRIBUTE
 
53
#define N NV_PARSER_TYPE_NO_CONFIG_WRITE
 
54
#define G NV_PARSER_TYPE_GUI_ATTRIUBUTE
 
55
#define V NV_PARSER_TYPE_XVIDEO_ATTRIBUTE
 
56
 
 
57
AttributeTableEntry attributeTable[] = {
 
58
   
 
59
    /* name                    constant                             flags */
 
60
 
 
61
    { "FlatpanelScaling",      NV_CTRL_FLATPANEL_SCALING,           0     },
 
62
    { "FlatpanelDithering",    NV_CTRL_FLATPANEL_DITHERING,         0     },
 
63
    { "DigitalVibrance",       NV_CTRL_DIGITAL_VIBRANCE,            0     },
 
64
    { "ImageSharpening",       NV_CTRL_IMAGE_SHARPENING,            0,    },
 
65
    { "BusType",               NV_CTRL_BUS_TYPE,                    0     },
 
66
    { "VideoRam",              NV_CTRL_VIDEO_RAM,                   0     },
 
67
    { "Irq",                   NV_CTRL_IRQ,                         0     },
 
68
    { "OperatingSystem",       NV_CTRL_OPERATING_SYSTEM,            0     },
 
69
    { "SyncToVBlank",          NV_CTRL_SYNC_TO_VBLANK,              0     },
 
70
    { "LogAniso",              NV_CTRL_LOG_ANISO,                   0     },
 
71
    { "FSAA",                  NV_CTRL_FSAA_MODE,                   0     },
 
72
    { "TextureSharpen",        NV_CTRL_TEXTURE_SHARPEN,             0     },
 
73
    { "Ubb",                   NV_CTRL_UBB,                         0     },
 
74
    { "Overlay",               NV_CTRL_OVERLAY,                     0     },
 
75
    { "Stereo",                NV_CTRL_STEREO,                      0     },
 
76
    { "TwinView",              NV_CTRL_TWINVIEW,                    0     },
 
77
    { "ConnectedDisplays",     NV_CTRL_CONNECTED_DISPLAYS,          0     },
 
78
    { "EnabledDisplays",       NV_CTRL_ENABLED_DISPLAYS,            0     },
 
79
    { "ForceGenericCpu",       NV_CTRL_FORCE_GENERIC_CPU,           0     },
 
80
    { "GammaCorrectedAALines", NV_CTRL_OPENGL_AA_LINE_GAMMA,        0     },
 
81
    { "CursorShadow",          NV_CTRL_CURSOR_SHADOW,               0     },
 
82
    { "CursorShadowXOffset",   NV_CTRL_CURSOR_SHADOW_X_OFFSET,      0     },
 
83
    { "CursorShadowYOffset",   NV_CTRL_CURSOR_SHADOW_Y_OFFSET,      0     },
 
84
    { "CursorShadowAlpha",     NV_CTRL_CURSOR_SHADOW_ALPHA,         0     },
 
85
    { "CursorShadowRed",       NV_CTRL_CURSOR_SHADOW_RED,           0     },
 
86
    { "CursorShadowGreen",     NV_CTRL_CURSOR_SHADOW_GREEN,         0     },
 
87
    { "CursorShadowBlue",      NV_CTRL_CURSOR_SHADOW_BLUE,          0     },
 
88
    { "FSAAAppControlled",     NV_CTRL_FSAA_APPLICATION_CONTROLLED, 0     },
 
89
    { "LogAnisoAppControlled", NV_CTRL_LOG_ANISO_APPLICATION_CONTROLLED,0 },
 
90
    { "FrameLockMaster",       NV_CTRL_FRAMELOCK_MASTER,            N|F|G },
 
91
    { "FrameLockPolarity",     NV_CTRL_FRAMELOCK_POLARITY,          N|F|G },
 
92
    { "FrameLockSyncDelay",    NV_CTRL_FRAMELOCK_SYNC_DELAY,        N|F|G },
 
93
    { "FrameLockEnable",       NV_CTRL_FRAMELOCK_SYNC,              N|F|G },
 
94
    { "FrameLockSyncInterval", NV_CTRL_FRAMELOCK_SYNC_INTERVAL,     N|F|G },
 
95
    { "FrameLockHouseFormat",  NV_CTRL_FRAMELOCK_VIDEO_MODE,        N|F|G },
 
96
    { "Brightness",            BRIGHTNESS_VALUE|ALL_CHANNELS,       N|C|G },
 
97
    { "RedBrightness",         BRIGHTNESS_VALUE|RED_CHANNEL,        C|G   },
 
98
    { "GreenBrightness",       BRIGHTNESS_VALUE|GREEN_CHANNEL,      C|G   },
 
99
    { "BlueBrightness",        BRIGHTNESS_VALUE|BLUE_CHANNEL,       C|G   },
 
100
    { "Contrast",              CONTRAST_VALUE|ALL_CHANNELS,         N|C|G },
 
101
    { "RedContrast",           CONTRAST_VALUE|RED_CHANNEL,          C|G   },
 
102
    { "GreenContrast",         CONTRAST_VALUE|GREEN_CHANNEL,        C|G   },
 
103
    { "BlueContrast",          CONTRAST_VALUE|BLUE_CHANNEL,         C|G   },
 
104
    { "Gamma",                 GAMMA_VALUE|ALL_CHANNELS,            N|C|G },
 
105
    { "RedGamma",              GAMMA_VALUE|RED_CHANNEL,             C|G   },
 
106
    { "GreenGamma",            GAMMA_VALUE|GREEN_CHANNEL,           C|G   },
 
107
    { "BlueGamma",             GAMMA_VALUE|BLUE_CHANNEL,            C|G   },
 
108
    { "TVOverScan",            NV_CTRL_TV_OVERSCAN,                 0,    },
 
109
    { "TVFlickerFilter",       NV_CTRL_TV_FLICKER_FILTER,           0,    },
 
110
    { "TVBrightness",          NV_CTRL_TV_BRIGHTNESS,               0,    },
 
111
    { "TVHue",                 NV_CTRL_TV_HUE,                      0,    },
 
112
    { "TVContrast",            NV_CTRL_TV_CONTRAST,                 0,    },
 
113
    { "TVSaturation",          NV_CTRL_TV_SATURATION,               0,    },
 
114
    { "GPUCoreTemp",           NV_CTRL_GPU_CORE_TEMPERATURE,        N     },
 
115
    { "GPUAmbientTemp",        NV_CTRL_AMBIENT_TEMPERATURE,         N     },
 
116
 
 
117
    { "XVideoOverlaySaturation",   NV_CTRL_ATTR_XV_OVERLAY_SATURATION,     V },
 
118
    { "XVideoOverlayContrast",     NV_CTRL_ATTR_XV_OVERLAY_CONTRAST,       V },
 
119
    { "XVideoOverlayBrightness",   NV_CTRL_ATTR_XV_OVERLAY_BRIGHTNESS,     V },
 
120
    { "XVideoOverlayHue",          NV_CTRL_ATTR_XV_OVERLAY_HUE,            V },
 
121
    { "XVideoTextureSyncToVBlank", NV_CTRL_ATTR_XV_TEXTURE_SYNC_TO_VBLANK, V },
 
122
    { "XVideoBlitterSyncToVBlank", NV_CTRL_ATTR_XV_BLITTER_SYNC_TO_VBLANK, V },
 
123
 
 
124
    { NULL,                    0,                                   0     }
 
125
};
 
126
 
 
127
#undef F
 
128
#undef C
 
129
#undef N
 
130
#undef G
 
131
#undef V
 
132
 
 
133
/*
 
134
 * nv_parse_attribute_string() - see comments in parse.h
 
135
 */
 
136
 
 
137
int nv_parse_attribute_string(const char *str, int query, ParsedAttribute *a)
 
138
{
 
139
    char *s, *tmp, *name, *start, *display_device_name, *no_spaces = NULL;
 
140
    char tmpname[NV_PARSER_MAX_NAME_LEN];
 
141
    AttributeTableEntry *t;
 
142
    int len, digits_only;
 
143
 
 
144
#define stop(x) { if (no_spaces) free(no_spaces); return (x); }
 
145
    
 
146
    if (!a) stop(NV_PARSER_STATUS_BAD_ARGUMENT);
 
147
 
 
148
    /* clear the ParsedAttribute struct */
 
149
 
 
150
    memset((void *) a, 0, sizeof(ParsedAttribute));
 
151
 
 
152
    /* remove any white space from the string, to simplify parsing */
 
153
 
 
154
    no_spaces = remove_spaces(str);
 
155
    if (!no_spaces) stop(NV_PARSER_STATUS_EMPTY_STRING);
 
156
    
 
157
    /*
 
158
     * get the display name... ie: everything before the
 
159
     * DISPLAY_NAME_SEPARATOR
 
160
     */
 
161
 
 
162
    s = strchr(no_spaces, DISPLAY_NAME_SEPARATOR);
 
163
 
 
164
    /*
 
165
     * If we found a DISPLAY_NAME_SEPARATOR, and there is some text
 
166
     * before it, it is either a screen number (if all characters
 
167
     * between no_spaces and s are digits), or a display name.
 
168
     */
 
169
 
 
170
    if ((s) && (s != no_spaces)) {
 
171
        
 
172
        /* are all characters numeric? */
 
173
 
 
174
        digits_only = NV_TRUE;
 
175
        a->screen = 0;
 
176
        for (tmp = no_spaces; tmp != s; tmp++) {
 
177
            if (!isdigit(*tmp)) {
 
178
                digits_only = NV_FALSE;
 
179
                a->screen = 0;
 
180
            }
 
181
            a->screen *= 10;
 
182
            a->screen += ctoi(*tmp);
 
183
        }
 
184
 
 
185
        if (digits_only) {
 
186
            a->display = NULL;
 
187
            a->flags |= NV_PARSER_HAS_X_SCREEN;
 
188
        } else {
 
189
            a->display = nv_strndup(no_spaces, s - no_spaces);
 
190
            a->flags |= NV_PARSER_HAS_X_DISPLAY;
 
191
            
 
192
            /*
 
193
             * this will attempt to parse out any screen number from the
 
194
             * display name
 
195
             */
 
196
            
 
197
            nv_assign_default_display(a, NULL);
 
198
        }
 
199
    }
 
200
    
 
201
    /* move past the DISPLAY_NAME_SEPARATOR */
 
202
    
 
203
    if (s) s++;
 
204
    else s = no_spaces;
 
205
    
 
206
    /* read the attribute name */
 
207
 
 
208
    name = s;
 
209
    len = 0;
 
210
    while (*s && isalnum(*s)) { s++; len++; }
 
211
    
 
212
    if (len == 0) stop(NV_PARSER_STATUS_ATTR_NAME_MISSING);
 
213
    if (len >= NV_PARSER_MAX_NAME_LEN)
 
214
        stop(NV_PARSER_STATUS_ATTR_NAME_TOO_LONG);
 
215
 
 
216
    strncpy(tmpname, name, len);
 
217
    tmpname[len] = '\0';
 
218
    
 
219
    /* look up the requested name */
 
220
 
 
221
    for (t = attributeTable; t->name; t++) {
 
222
        if (nv_strcasecmp(tmpname, t->name)) {
 
223
            a->name = t->name;
 
224
            a->attr = t->attr;
 
225
            a->flags |= t->flags;
 
226
            break;
 
227
        }
 
228
    }
 
229
    
 
230
    if (!a->name) stop(NV_PARSER_STATUS_UNKNOWN_ATTR_NAME);
 
231
    
 
232
    /* read the display device name, if any */
 
233
    
 
234
    if (*s == '[') {
 
235
        s++;
 
236
        start = s;
 
237
        while (*s && *s != ']') s++;
 
238
        display_device_name = nv_strndup(start, s - start);
 
239
        a->display_device_mask =
 
240
            display_device_name_to_display_device_mask(display_device_name);
 
241
        if (a->display_device_mask == INVALID_DISPLAY_DEVICE_MASK)
 
242
            stop(NV_PARSER_STATUS_BAD_DISPLAY_DEVICE);
 
243
        a->flags |= NV_PARSER_HAS_DISPLAY_DEVICE;
 
244
        if (*s == ']') s++;
 
245
    }
 
246
    
 
247
    if (query == NV_PARSER_ASSIGNMENT) {
 
248
        
 
249
        /* there should be an equal sign */
 
250
    
 
251
        if (*s == '=') s++;
 
252
        else stop(NV_PARSER_STATUS_MISSING_EQUAL_SIGN);
 
253
        
 
254
        /* read the value */
 
255
    
 
256
        tmp = s;
 
257
        if (a->flags & NV_PARSER_TYPE_COLOR_ATTRIBUTE) {
 
258
            /* color attributes are floating point */
 
259
            a->fval = strtod(s, &tmp);
 
260
        } else {
 
261
            /* all other attributes are integer */
 
262
            a->val = strtol(s, &tmp, 10);
 
263
        }
 
264
         
 
265
        if (tmp && (s != tmp)) a->flags |= NV_PARSER_HAS_VAL;
 
266
        s = tmp;
 
267
        
 
268
        if (!(a->flags & NV_PARSER_HAS_VAL)) stop(NV_PARSER_STATUS_NO_VALUE);
 
269
    }
 
270
    
 
271
    /* this should be the end of the string */
 
272
 
 
273
    if (*s != '\0') stop(NV_PARSER_STATUS_TRAILING_GARBAGE);
 
274
 
 
275
    stop(NV_PARSER_STATUS_SUCCESS);
 
276
    
 
277
} /* nv_parse_attribute_string() */
 
278
 
 
279
 
 
280
 
 
281
/*
 
282
 * nv_parse_strerror() - given the error status returned by
 
283
 * nv_parse_attribute_string(), return a string describing the
 
284
 * error.
 
285
 */
 
286
 
 
287
char *nv_parse_strerror(int status)
 
288
{
 
289
    switch (status) {
 
290
    case NV_PARSER_STATUS_SUCCESS :
 
291
        return "No error"; break;
 
292
    case NV_PARSER_STATUS_BAD_ARGUMENT :
 
293
        return "Bad argument"; break;
 
294
    case NV_PARSER_STATUS_EMPTY_STRING :
 
295
        return "Emtpy string"; break;
 
296
    case NV_PARSER_STATUS_ATTR_NAME_TOO_LONG :
 
297
        return "The attribute name is too long"; break;
 
298
    case NV_PARSER_STATUS_ATTR_NAME_MISSING :
 
299
        return "Missing attribute name"; break;
 
300
    case NV_PARSER_STATUS_BAD_DISPLAY_DEVICE :
 
301
        return "Malformed display device identification"; break;
 
302
    case NV_PARSER_STATUS_MISSING_EQUAL_SIGN :
 
303
        return "Missing equal sign after attribute name"; break;
 
304
    case NV_PARSER_STATUS_NO_VALUE :
 
305
        return "No attribute value specified"; break;
 
306
    case NV_PARSER_STATUS_TRAILING_GARBAGE :
 
307
        return "Trailing garbage"; break;
 
308
    case NV_PARSER_STATUS_UNKNOWN_ATTR_NAME :
 
309
        return "Unrecognized attribute name"; break;
 
310
    default:
 
311
        return "Unknown error"; break;
 
312
    }
 
313
} /* nv_parse_strerror() */
 
314
 
 
315
 
 
316
 
 
317
/*
 
318
 * *sigh* strcasecmp() is a BSDism, and when building with "-ansi" we
 
319
 * don't get the prototype, so reimplement it to avoid a compiler
 
320
 * warning.  Returns NV_TRUE if a match, returns NV_FALSE if there is
 
321
 * no match.
 
322
 */
 
323
 
 
324
int nv_strcasecmp(const char *a, const char *b)
 
325
{
 
326
    if (!a && !b) return NV_TRUE;
 
327
    if (!a &&  b) return NV_FALSE;
 
328
    if ( a && !b) return NV_FALSE;
 
329
 
 
330
    while (toupper(*a) == toupper(*b)) {
 
331
        a++;
 
332
        b++;
 
333
        if ((*a == '\0') && (*b == '\0')) return NV_TRUE;
 
334
    }
 
335
 
 
336
    return NV_FALSE;
 
337
 
 
338
} /* nv_strcasecmp() */
 
339
 
 
340
 
 
341
 
 
342
/*
 
343
 * display_name_to_display_device_mask() - parse the string that describes a
 
344
 * display device mask; the string is a comma-separated list of
 
345
 * display device names, where valid names are:
 
346
 *
 
347
 * CRT-[0,7] TV-[0,7] and DFP[0,7]
 
348
 *
 
349
 * Non-specific names ("CRT", "TV", and "DFP") are also allowed; if
 
350
 * these are specified, then the appropriate WILDCARD flag in the
 
351
 * upper-most byte of the display device mask is set:
 
352
 *
 
353
 *    DISPLAY_DEVICES_WILDCARD_CRT
 
354
 *    DISPLAY_DEVICES_WILDCARD_TV
 
355
 *    DISPLAY_DEVICES_WILDCARD_DFP
 
356
 *
 
357
 * If a parse error occurs, INVALID_DISPLAY_DEVICE_MASK is returned,
 
358
 * otherwise the display mask is returned.
 
359
 
 
360
 */
 
361
 
 
362
uint32 display_device_name_to_display_device_mask(const char *str)
 
363
{
 
364
    uint32 mask = 0;
 
365
    char *s, **toks;
 
366
    int i, n;
 
367
 
 
368
    /* sanity check */
 
369
 
 
370
    if (!str || !*str) return INVALID_DISPLAY_DEVICE_MASK;
 
371
    
 
372
    /* remove spaces from the string */
 
373
 
 
374
    s = remove_spaces(str);
 
375
    if (!s || !*s) return INVALID_DISPLAY_DEVICE_MASK;
 
376
    
 
377
    /* break up the string by commas */
 
378
 
 
379
    toks = nv_strtok(s, ',', &n);
 
380
    if (!toks) {
 
381
        free(s);
 
382
        return INVALID_DISPLAY_DEVICE_MASK;
 
383
    }
 
384
 
 
385
    /* match each token, updating mask as appropriate */
 
386
 
 
387
    for (i = 0; i < n; i++) {
 
388
        
 
389
        if      (nv_strcasecmp(toks[i], "CRT-0")) mask |= ((1 << 0) << 0);
 
390
        else if (nv_strcasecmp(toks[i], "CRT-1")) mask |= ((1 << 1) << 0);
 
391
        else if (nv_strcasecmp(toks[i], "CRT-2")) mask |= ((1 << 2) << 0);
 
392
        else if (nv_strcasecmp(toks[i], "CRT-3")) mask |= ((1 << 3) << 0);
 
393
        else if (nv_strcasecmp(toks[i], "CRT-4")) mask |= ((1 << 4) << 0);
 
394
        else if (nv_strcasecmp(toks[i], "CRT-5")) mask |= ((1 << 5) << 0);
 
395
        else if (nv_strcasecmp(toks[i], "CRT-6")) mask |= ((1 << 6) << 0);
 
396
        else if (nv_strcasecmp(toks[i], "CRT-7")) mask |= ((1 << 7) << 0);
 
397
 
 
398
        else if (nv_strcasecmp(toks[i], "TV-0" )) mask |= ((1 << 0) << 8);
 
399
        else if (nv_strcasecmp(toks[i], "TV-1" )) mask |= ((1 << 1) << 8);
 
400
        else if (nv_strcasecmp(toks[i], "TV-2" )) mask |= ((1 << 2) << 8);
 
401
        else if (nv_strcasecmp(toks[i], "TV-3" )) mask |= ((1 << 3) << 8);
 
402
        else if (nv_strcasecmp(toks[i], "TV-4" )) mask |= ((1 << 4) << 8);
 
403
        else if (nv_strcasecmp(toks[i], "TV-5" )) mask |= ((1 << 5) << 8);
 
404
        else if (nv_strcasecmp(toks[i], "TV-6" )) mask |= ((1 << 6) << 8);
 
405
        else if (nv_strcasecmp(toks[i], "TV-7" )) mask |= ((1 << 7) << 8);
 
406
 
 
407
        else if (nv_strcasecmp(toks[i], "DFP-0")) mask |= ((1 << 0) << 16);
 
408
        else if (nv_strcasecmp(toks[i], "DFP-1")) mask |= ((1 << 1) << 16);
 
409
        else if (nv_strcasecmp(toks[i], "DFP-2")) mask |= ((1 << 2) << 16);
 
410
        else if (nv_strcasecmp(toks[i], "DFP-3")) mask |= ((1 << 3) << 16);
 
411
        else if (nv_strcasecmp(toks[i], "DFP-4")) mask |= ((1 << 4) << 16);
 
412
        else if (nv_strcasecmp(toks[i], "DFP-5")) mask |= ((1 << 5) << 16);
 
413
        else if (nv_strcasecmp(toks[i], "DFP-6")) mask |= ((1 << 6) << 16);
 
414
        else if (nv_strcasecmp(toks[i], "DFP-7")) mask |= ((1 << 7) << 16);
 
415
        
 
416
        else if (nv_strcasecmp(toks[i], "CRT"))
 
417
            mask |= DISPLAY_DEVICES_WILDCARD_CRT;
 
418
        
 
419
        else if (nv_strcasecmp(toks[i], "TV"))
 
420
            mask |= DISPLAY_DEVICES_WILDCARD_TV;
 
421
                
 
422
        else if (nv_strcasecmp(toks[i], "DFP"))
 
423
            mask |= DISPLAY_DEVICES_WILDCARD_DFP;
 
424
 
 
425
        else {
 
426
            mask = INVALID_DISPLAY_DEVICE_MASK;
 
427
            break;
 
428
        }
 
429
    }
 
430
    
 
431
    nv_free_strtoks(toks, n);
 
432
    
 
433
    free(s);
 
434
 
 
435
    return mask;
 
436
    
 
437
} /* display_name_to_display_device_mask() */
 
438
 
 
439
 
 
440
 
 
441
/*
 
442
 * display_device_mask_to_display_name() - construct a string
 
443
 * describing the given display device mask.  The returned pointer
 
444
 * points to a global character buffer, so subsequent calls to
 
445
 * display_device_mask_to_display_device_name() will clobber the
 
446
 * contents.
 
447
 */
 
448
 
 
449
#define DISPLAY_DEVICE_STRING_LEN 256
 
450
 
 
451
char *display_device_mask_to_display_device_name(const uint32 mask)
 
452
{
 
453
    char *s;
 
454
    int first = NV_TRUE;
 
455
    uint32 devcnt, devmask;
 
456
    char *display_device_name_string;
 
457
 
 
458
    display_device_name_string = malloc(DISPLAY_DEVICE_STRING_LEN);
 
459
 
 
460
    s = display_device_name_string;
 
461
 
 
462
    devmask = 1 << BITSHIFT_CRT;
 
463
    devcnt = 0;
 
464
    while (devmask & BITMASK_ALL_CRT) {
 
465
        if (devmask & mask) {
 
466
            if (first) first = NV_FALSE;
 
467
            else s += sprintf(s, ", ");
 
468
            s += sprintf(s, "CRT-%X", devcnt);
 
469
        }
 
470
        devmask <<= 1;
 
471
        devcnt++;
 
472
    }
 
473
 
 
474
    devmask = 1 << BITSHIFT_DFP;
 
475
    devcnt = 0;
 
476
    while (devmask & BITMASK_ALL_DFP) {
 
477
        if (devmask & mask)  {
 
478
            if (first) first = NV_FALSE;
 
479
            else s += sprintf(s, ", ");
 
480
            s += sprintf(s, "DFP-%X", devcnt);
 
481
        }
 
482
        devmask <<= 1;
 
483
        devcnt++;
 
484
    }
 
485
    
 
486
    devmask = 1 << BITSHIFT_TV;
 
487
    devcnt = 0;
 
488
    while (devmask & BITMASK_ALL_TV) {
 
489
        if (devmask & mask)  {
 
490
            if (first) first = NV_FALSE;
 
491
            else s += sprintf(s, ", ");
 
492
            s += sprintf(s, "TV-%X", devcnt);
 
493
        }
 
494
        devmask <<= 1;
 
495
        devcnt++;
 
496
    }
 
497
    
 
498
    if (mask & DISPLAY_DEVICES_WILDCARD_CRT) {
 
499
        if (first) first = NV_FALSE;
 
500
        else s += sprintf(s, ", ");
 
501
        s += sprintf(s, "CRT");
 
502
    }
 
503
 
 
504
    if (mask & DISPLAY_DEVICES_WILDCARD_TV) {
 
505
        if (first) first = NV_FALSE;
 
506
        else s += sprintf(s, ", ");
 
507
        s += sprintf(s, "TV");
 
508
    }
 
509
 
 
510
    if (mask & DISPLAY_DEVICES_WILDCARD_DFP) {
 
511
        if (first) first = NV_FALSE;
 
512
        else s += sprintf(s, ", ");
 
513
        s += sprintf(s, "DFP");
 
514
    }
 
515
    
 
516
    *s = '\0';
 
517
    
 
518
    return (display_device_name_string);
 
519
 
 
520
} /* display_device_mask_to_display_name() */
 
521
 
 
522
 
 
523
 
 
524
/*
 
525
 * expand_display_device_mask_wildcards() - build a display mask by
 
526
 * taking any of the real display mask bits; if there are any wildcard
 
527
 * flags set, or in all display devices of that type into the display
 
528
 * mask.
 
529
 */
 
530
 
 
531
uint32 expand_display_device_mask_wildcards(const uint32 d, const uint32 e)
 
532
{
 
533
    uint32 mask = d & VALID_DISPLAY_DEVICES_MASK;
 
534
 
 
535
    if (d & DISPLAY_DEVICES_WILDCARD_CRT) mask |= (e & BITMASK_ALL_CRT);
 
536
    if (d & DISPLAY_DEVICES_WILDCARD_TV)  mask |= (e & BITMASK_ALL_TV);
 
537
    if (d & DISPLAY_DEVICES_WILDCARD_DFP) mask |= (e & BITMASK_ALL_DFP);
 
538
    
 
539
    return mask;
 
540
 
 
541
} /* expand_display_device_mask_wildcards() */
 
542
 
 
543
 
 
544
 
 
545
/*
 
546
 * nv_assign_default_display() - assign an X display, if none has been
 
547
 * assigned already.  Also, parse the the display name to find any
 
548
 * specified X screen.
 
549
 */
 
550
 
 
551
void nv_assign_default_display(ParsedAttribute *a, const char *display)
 
552
{
 
553
    char *colon, *dot, *s;
 
554
 
 
555
    if (!(a->flags & NV_PARSER_HAS_X_DISPLAY)) {
 
556
        if (display) a->display = strdup(display);
 
557
        else a->display = NULL;
 
558
        a->flags |= NV_PARSER_HAS_X_DISPLAY;
 
559
    }
 
560
 
 
561
    if (!(a->flags & NV_PARSER_HAS_X_SCREEN) && a->display) {
 
562
        colon = strchr(a->display, ':');
 
563
        if (colon) {
 
564
            dot = strchr(colon, '.');
 
565
            if (dot) {
 
566
                a->screen = 0;
 
567
                s = dot + 1;
 
568
                while (*s && isdigit(*s)) {
 
569
                    a->screen *= 10;
 
570
                    a->screen += ctoi(*s);
 
571
                    a->flags |= NV_PARSER_HAS_X_SCREEN;
 
572
                    s++;
 
573
                }
 
574
            }
 
575
        }
 
576
    }
 
577
} /* nv_assign_default_display() */
 
578
 
 
579
 
 
580
 
 
581
/* 
 
582
 * nv_parsed_attribute_init() - initialize a ParsedAttribute linked
 
583
 * list
 
584
 */
 
585
 
 
586
ParsedAttribute *nv_parsed_attribute_init(void)
 
587
{
 
588
    ParsedAttribute *p = calloc(1, sizeof(ParsedAttribute));
 
589
 
 
590
    p->next = NULL;
 
591
 
 
592
    return p;
 
593
    
 
594
} /* nv_parsed_attribute_init() */
 
595
 
 
596
 
 
597
 
 
598
/*
 
599
 * nv_parsed_attribute_add() - add a new parsed attribute node to the
 
600
 * linked list
 
601
 */
 
602
 
 
603
void nv_parsed_attribute_add(ParsedAttribute *head, ParsedAttribute *a)
 
604
{
 
605
    ParsedAttribute *p, *t;
 
606
 
 
607
    p = calloc(1, sizeof(ParsedAttribute));
 
608
 
 
609
    p->next = NULL;
 
610
    
 
611
    for (t = head; t->next; t = t->next);
 
612
    
 
613
    t->next = p;
 
614
    
 
615
    if (a->display) t->display = strdup(a->display);
 
616
    else t->display = NULL;
 
617
    
 
618
    t->screen              = a->screen;
 
619
    t->attr                = a->attr;
 
620
    t->val                 = a->val;
 
621
    t->fval                = a->fval;
 
622
    t->display_device_mask = a->display_device_mask;
 
623
    t->flags               = a->flags;
 
624
    
 
625
} /* nv_parsed_attribute_add() */
 
626
 
 
627
 
 
628
 
 
629
/*
 
630
 * nv_parsed_attribute_free() - free the linked list
 
631
 */
 
632
 
 
633
void nv_parsed_attribute_free(ParsedAttribute *p)
 
634
{
 
635
    ParsedAttribute *n;
 
636
    
 
637
    while(p) {
 
638
        n = p->next;
 
639
        if (p->display) free(p->display);
 
640
        free(p);
 
641
        p = n;
 
642
    }
 
643
 
 
644
} /* nv_parsed_attribute_free() */
 
645
 
 
646
 
 
647
 
 
648
/*
 
649
 * nv_parsed_attribute_clean() - clean out the ParsedAttribute list,
 
650
 * so that only the empty head node remains.
 
651
 */
 
652
 
 
653
void nv_parsed_attribute_clean(ParsedAttribute *p)
 
654
{
 
655
    nv_parsed_attribute_free(p->next);
 
656
 
 
657
    if (p->display) free(p->display);
 
658
    if (p->name) free(p->name);
 
659
    
 
660
    memset(p, 0, sizeof(ParsedAttribute));
 
661
 
 
662
} /* nv_parsed_attribute_clean() */
 
663
 
 
664
 
 
665
 
 
666
/*
 
667
 * nv_get_attribute_name() - scan the attributeTable for the name that
 
668
 * corresponds to the attribute constant.
 
669
 */
 
670
 
 
671
char *nv_get_attribute_name(const int attr)
 
672
{
 
673
    int i;
 
674
 
 
675
    for (i = 0; attributeTable[i].name; i++) {
 
676
        if (attributeTable[i].attr == attr) return attributeTable[i].name;
 
677
    }
 
678
 
 
679
    return NULL;
 
680
    
 
681
} /* nv_get_attribute_name() */
 
682
 
 
683
 
 
684
char *nv_standardize_screen_name(const char *orig, int screen)
 
685
{
 
686
    char *display_name, *screen_name, *colon, *dot, *tmp;
 
687
    struct utsname uname_buf;
 
688
    int len;
 
689
    
 
690
    /* get the string describing this display connection */
 
691
    
 
692
    if (!orig) return NULL;
 
693
    
 
694
    /* create a working copy */
 
695
    
 
696
    display_name = strdup(orig);
 
697
    if (!display_name) return NULL;
 
698
    
 
699
    /* skip past the host */
 
700
    
 
701
    colon = strchr(display_name, ':');
 
702
    if (!colon) return NULL;
 
703
    
 
704
    /* if no host is specified, prepend the local hostname */
 
705
    
 
706
    /* XXX should we try to catch "localhost"? */
 
707
 
 
708
    if (display_name == colon) {
 
709
        if (uname(&uname_buf) == 0) {
 
710
            len = strlen(display_name) + strlen(uname_buf.nodename) + 1;
 
711
            tmp = malloc(len);
 
712
            snprintf(tmp, len, "%s%s", uname_buf.nodename, display_name);
 
713
            free(display_name);
 
714
            display_name = tmp;
 
715
            colon = strchr(display_name, ':');
 
716
            if (!colon) return NULL;
 
717
        }
 
718
    }
 
719
    
 
720
    /*
 
721
     * if the screen parameter is -1, then extract the screen number,
 
722
     * either from the string or default to 0
 
723
     */
 
724
    
 
725
    if (screen == -1) {
 
726
        dot = strchr(colon, '.');
 
727
        if (dot) {
 
728
            screen = atoi(dot + 1);
 
729
        } else {
 
730
            screen = 0;
 
731
        }
 
732
    }
 
733
    
 
734
    /*
 
735
     * find the separation between the display and the screen; if we
 
736
     * find it, then truncate the string before the screen, so that we
 
737
     * can append the correct screen number.
 
738
     */
 
739
    
 
740
    dot = strchr(colon, '.');
 
741
    if (dot) *dot = '\0';
 
742
    
 
743
    len = strlen(display_name) + 8;
 
744
    screen_name = malloc(len);
 
745
    snprintf(screen_name, len, "%s.%d", display_name, screen);
 
746
    
 
747
    free(display_name);
 
748
    
 
749
    return (screen_name);
 
750
}
 
751
 
 
752
 
 
753
 
 
754
/*
 
755
 * allocate an output string, and copy the input string to the output
 
756
 * string, omitting whitespace
 
757
 */
 
758
 
 
759
char *remove_spaces(const char *o)
 
760
{
 
761
    int len;
 
762
    char *m, *no_spaces;
 
763
   
 
764
    if (!o) return (NULL);
 
765
    
 
766
    len = strlen (o);
 
767
    
 
768
    no_spaces = (char *) malloc (len+1);
 
769
 
 
770
    m = no_spaces;
 
771
    while (*o) {
 
772
        if (!isspace (*o)) { *m++ = *o; }
 
773
        o++;
 
774
    }
 
775
    *m = '\0';
 
776
    
 
777
    len = m - no_spaces + 1;
 
778
    no_spaces = (char *) (realloc (no_spaces, len));
 
779
    
 
780
    return (no_spaces);
 
781
 
 
782
} /* remove_spaces() */
 
783
 
 
784
 
 
785
 
 
786
/**************************************************************************/
 
787
 
 
788
 
 
789
 
 
790
/*
 
791
 * nv_strtok () - returns a dynamically allocated array of strings,
 
792
 * which are the separate segments of the passed in string, divided by
 
793
 * the character indicated.  The passed-by-reference argument num will
 
794
 * hold the number of segments found.  When you are done with the
 
795
 * array of strings, it is best to call nvFreeStrToks () to free the
 
796
 * memory allocated here.
 
797
 */
 
798
 
 
799
static char **nv_strtok(char *s, char c, int *n)
 
800
{
 
801
    int count, i, len;
 
802
    char **delims, **tokens, *m;
 
803
    
 
804
    count = count_number_of_chars(s, c);
 
805
    
 
806
    /*
 
807
     * allocate and set pointers to each division (each instance of the
 
808
     * dividing character, and the terminating NULL of the string)
 
809
     */
 
810
    
 
811
    delims = (char **) malloc((count+1) * sizeof(char *));
 
812
    m = s;
 
813
    for (i = 0; i < count; i++) {
 
814
        while (*m != c) m++;
 
815
        delims[i] = m;
 
816
        m++;
 
817
    }
 
818
    delims[count] = (char *) strchr(s, '\0');
 
819
    
 
820
    /*
 
821
     * so now, we have pointers to each deliminator; copy what's in between
 
822
     * the divisions (the tokens) into the dynamic array of strings
 
823
     */
 
824
    
 
825
    tokens = (char **) malloc((count+1) * sizeof(char *));
 
826
    len = delims[0] - s;
 
827
    tokens[0] = nv_strndup(s, len);
 
828
    
 
829
    for (i = 1; i < count+1; i++) {
 
830
        len = delims[i] - delims[i-1];
 
831
        tokens[i] = nv_strndup(delims[i-1]+1, len-1);
 
832
    }
 
833
    
 
834
    free(delims);
 
835
    
 
836
    *n = count+1;
 
837
    return (tokens);
 
838
    
 
839
} /* nv_strtok() */
 
840
 
 
841
 
 
842
 
 
843
/*
 
844
 * nv_free_strtoks() - free an array of arrays, such as what is
 
845
 * allocated and returned by nv_strtok()
 
846
 */
 
847
 
 
848
static void nv_free_strtoks(char **s, int n)
 
849
{
 
850
    int i;
 
851
    for (i = 0; i < n; i++) free(s[i]);
 
852
    free(s);
 
853
    
 
854
} /* nv_free_strtoks() */
 
855
 
 
856
 
 
857
 
 
858
/*
 
859
 * character to integer conversion
 
860
 */
 
861
 
 
862
static int ctoi(const char c)
 
863
{
 
864
    return (c - '0');
 
865
 
 
866
} /* ctoi */
 
867
 
 
868
 
 
869
 
 
870
/*
 
871
 * count_number_of_chars() - return the number of times the
 
872
 * character d appears in the string
 
873
 */
 
874
 
 
875
static int count_number_of_chars(char *o, char d)
 
876
{
 
877
    int c = 0;
 
878
    while (*o) {
 
879
        if (*o == d) c++;
 
880
        o++;
 
881
    }
 
882
    return (c);
 
883
    
 
884
} /* count_number_of_chars() */
 
885
 
 
886
 
 
887
 
 
888
/*
 
889
 * nv_strndup() - this function takes a pointer to a string and a
 
890
 * length n, mallocs a new string of n+1, copies the first n chars
 
891
 * from the original string into the new, and null terminates the new
 
892
 * string.  The caller should free the string.
 
893
 */
 
894
 
 
895
static char *nv_strndup(char *s, int n)
 
896
{
 
897
    char *m = (char *) malloc(n+1);
 
898
    strncpy (m, s, n);
 
899
    m[n] = '\0';
 
900
    return (m);
 
901
    
 
902
} /* nv_strndup() */