*
* Copyright (c) 1997 Metro Link Incorporated
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Metro Link shall not be
* used in advertising or otherwise to promote the sale, use or other dealings
* in this Software without prior written authorization from Metro Link.
*
*/
* Copyright (c) 1997-2003 by The XFree86 Project, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Except as contained in this notice, the name of the copyright holder(s)
* and author(s) shall not be used in advertising or otherwise to promote
* the sale, use or other dealings in this Software without prior written
* authorization from the copyright holder(s) and author(s).
*/
#include "xf86Parser.h"
#include "xf86tokens.h"
#include "Configint.h"
#include <math.h>
#include "common-utils.h"
extern LexRec val;
static XConfigSymTabRec ServerFlagsTab[] =
{
{ENDSECTION, "endsection"},
{NOTRAPSIGNALS, "notrapsignals"},
{DONTZAP, "dontzap"},
{DONTZOOM, "dontzoom"},
{DISABLEVIDMODE, "disablevidmodeextension"},
{ALLOWNONLOCAL, "allownonlocalxvidtune"},
{DISABLEMODINDEV, "disablemodindev"},
{MODINDEVALLOWNONLOCAL, "allownonlocalmodindev"},
{ALLOWMOUSEOPENFAIL, "allowmouseopenfail"},
{OPTION, "option"},
{BLANKTIME, "blanktime"},
{STANDBYTIME, "standbytime"},
{SUSPENDTIME, "suspendtime"},
{OFFTIME, "offtime"},
{DEFAULTLAYOUT, "defaultserverlayout"},
{-1, ""},
};
#define CLEANUP xconfigFreeFlags
XConfigFlagsPtr
xconfigParseFlagsSection (void)
{
int token;
PARSE_PROLOGUE (XConfigFlagsPtr, XConfigFlagsRec)
while ((token = xconfigGetToken (ServerFlagsTab)) != ENDSECTION)
{
int hasvalue = FALSE;
int strvalue = FALSE;
int tokentype;
switch (token)
{
case COMMENT:
ptr->comment = xconfigAddComment(ptr->comment, val.str);
break;
* these old keywords are turned into standard generic options.
* we fall through here on purpose
*/
case DEFAULTLAYOUT:
strvalue = TRUE;
case BLANKTIME:
case STANDBYTIME:
case SUSPENDTIME:
case OFFTIME:
hasvalue = TRUE;
case NOTRAPSIGNALS:
case DONTZAP:
case DONTZOOM:
case DISABLEVIDMODE:
case ALLOWNONLOCAL:
case DISABLEMODINDEV:
case MODINDEVALLOWNONLOCAL:
case ALLOWMOUSEOPENFAIL:
{
int i = 0;
while (ServerFlagsTab[i].token != -1)
{
if (ServerFlagsTab[i].token == token)
{
char buff[16];
char *valstr = NULL;
if (hasvalue)
{
tokentype = xconfigGetSubToken(&(ptr->comment));
if (strvalue) {
if (tokentype != STRING)
Error (QUOTE_MSG, ServerFlagsTab[i].name);
valstr = val.str;
} else {
if (tokentype != NUMBER)
Error (NUMBER_MSG, ServerFlagsTab[i].name);
snprintf(buff, 16, "%d", val.num);
valstr = buff;
}
}
xconfigAddNewOption(&ptr->options,
ServerFlagsTab[i].name, valstr);
}
i++;
}
}
break;
case OPTION:
ptr->options = xconfigParseOption(ptr->options);
break;
case EOF_TOKEN:
Error (UNEXPECTED_EOF_MSG, NULL);
break;
default:
Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
break;
}
}
return ptr;
}
#undef CLEANUP
void
xconfigPrintServerFlagsSection (FILE * f, XConfigFlagsPtr flags)
{
XConfigOptionPtr p;
if ((!flags) || (!flags->options))
return;
p = flags->options;
fprintf (f, "Section \"ServerFlags\"\n");
if (flags->comment)
fprintf (f, "%s", flags->comment);
xconfigPrintOptionList(f, p, 1);
fprintf (f, "EndSection\n\n");
}
void
xconfigAddNewOption (XConfigOptionPtr *pHead, const char *name,
const char *val)
{
XConfigOptionPtr new;
XConfigOptionPtr old = NULL;
if (*pHead != NULL &&
((old = xconfigFindOption(*pHead, name)) != NULL)) {
TEST_FREE(old->name);
TEST_FREE(old->val);
new = old;
} else {
new = calloc(1, sizeof (XConfigOptionRec));
new->next = NULL;
}
new->name = xconfigStrdup(name);
new->val = xconfigStrdup(val);
if (old == NULL) {
xconfigAddListItem((GenericListPtr *)(pHead), (GenericListPtr)new);
}
}
void
xconfigFreeFlags (XConfigFlagsPtr *flags)
{
if (flags == NULL || *flags == NULL)
return;
xconfigFreeOptionList (&((*flags)->options));
TEST_FREE((*flags)->comment);
free (*flags);
*flags = NULL;
}
XConfigOptionPtr
xconfigOptionListDup (XConfigOptionPtr opt)
{
XConfigOptionPtr newopt = NULL;
while (opt) {
xconfigAddNewOption(&newopt, opt->name, opt->val);
if (newopt) {
newopt->comment = xconfigStrdup(opt->comment);
}
opt = opt->next;
}
return newopt;
}
void
xconfigFreeOptionList (XConfigOptionPtr *opt)
{
XConfigOptionPtr prev;
if (opt == NULL || *opt == NULL)
return;
while (*opt)
{
TEST_FREE ((*opt)->name);
TEST_FREE ((*opt)->val);
TEST_FREE ((*opt)->comment);
prev = *opt;
*opt = (*opt)->next;
free (prev);
}
}
char *
xconfigOptionName(XConfigOptionPtr opt)
{
if (opt)
return opt->name;
return 0;
}
char *
xconfigOptionValue(XConfigOptionPtr opt)
{
if (opt)
return opt->val;
return 0;
}
XConfigOptionPtr
xconfigNewOption(const char *name, const char *value)
{
XConfigOptionPtr opt;
opt = calloc(1, sizeof (XConfigOptionRec));
if (!opt)
return NULL;
opt->name = xconfigStrdup(name);
opt->val = xconfigStrdup(value);
opt->next = NULL;
return opt;
}
void
xconfigRemoveOption(XConfigOptionPtr *pHead, XConfigOptionPtr opt)
{
xconfigRemoveListItem((GenericListPtr *)pHead, (GenericListPtr)opt);
TEST_FREE(opt->name);
TEST_FREE(opt->val);
TEST_FREE(opt->comment);
free(opt);
}
XConfigOptionPtr
xconfigNextOption(XConfigOptionPtr list)
{
if (!list)
return NULL;
return list->next;
}
* this function searches the given option list for the named option and
* returns a pointer to the option rec if found. If not found, it returns
* NULL
*/
XConfigOptionPtr
xconfigFindOption (XConfigOptionPtr list, const char *name)
{
while (list)
{
if (xconfigNameCompare (list->name, name) == 0)
return (list);
list = list->next;
}
return (NULL);
}
* this function searches the given option list for the named option. If
* found and the option has a parameter, a pointer to the parameter is
* returned. If the option does not have a parameter an empty string is
* returned. If the option is not found, a NULL is returned.
*/
char *
xconfigFindOptionValue (XConfigOptionPtr list, const char *name)
{
XConfigOptionPtr p = xconfigFindOption (list, name);
if (p)
{
if (p->val)
return (p->val);
else
return "";
}
return (NULL);
}
* this function searches the given option list for the named option. If
* found and the the value of the option is set to "1", "ON", "YES" or
* "TRUE", 1 is returned. Otherwise, 0 is returned.
*/
int
xconfigFindOptionBoolean (XConfigOptionPtr list, const char *name)
{
XConfigOptionPtr p = xconfigFindOption (list, name);
if (p && p->val)
{
if ( strcasecmp(p->val, "1") == 0 ||
strcasecmp(p->val, "ON") == 0 ||
strcasecmp(p->val, "YES") == 0 ||
strcasecmp(p->val, "TRUE") == 0 )
{
return 1;
}
}
return 0;
}
* both, the option from the user list - specified in the second argument -
* is used. The end result is a single valid list of options. Duplicates
* are freed, and the original lists are no longer guaranteed to be complete.
*/
XConfigOptionPtr
xconfigOptionListMerge (XConfigOptionPtr head, XConfigOptionPtr tail)
{
XConfigOptionPtr a, b, ap = NULL, bp = NULL;
a = tail;
b = head;
while (tail && b) {
if (xconfigNameCompare (a->name, b->name) == 0) {
if (b == head)
head = a;
else
bp->next = a;
if (a == tail)
tail = a->next;
else
ap->next = a->next;
a->next = b->next;
b->next = NULL;
xconfigFreeOptionList (&b);
b = a->next;
bp = a;
a = tail;
ap = NULL;
} else {
ap = a;
if (!(a = a->next)) {
a = tail;
bp = b;
b = b->next;
ap = NULL;
}
}
}
if (head) {
for (a = head; a->next; a = a->next)
;
a->next = tail;
} else
head = tail;
return (head);
}
char *
xconfigULongToString(unsigned long i)
{
char *s;
int l;
l = (int)(ceil(log10((double)i) + 2.5));
s = malloc(l);
if (!s)
return NULL;
sprintf(s, "%lu", i);
return s;
}
XConfigOptionPtr
xconfigParseOption(XConfigOptionPtr head)
{
XConfigOptionPtr option, cnew, old;
char *name, *comment = NULL;
int token;
if ((token = xconfigGetSubToken(&comment)) != STRING) {
xconfigErrorMsg(ParseErrorMsg, BAD_OPTION_MSG);
if (comment)
free(comment);
return (head);
}
name = val.str;
if ((token = xconfigGetSubToken(&comment)) == STRING) {
option = xconfigNewOption(name, val.str);
option->comment = comment;
if ((token = xconfigGetToken(NULL)) == COMMENT)
option->comment = xconfigAddComment(option->comment, val.str);
else
xconfigUnGetToken(token);
}
else {
option = xconfigNewOption(name, NULL);
option->comment = comment;
if (token == COMMENT)
option->comment = xconfigAddComment(option->comment, val.str);
else
xconfigUnGetToken(token);
}
old = NULL;
if (head != NULL && (old = xconfigFindOption(head, name)) != NULL) {
cnew = old;
free(option->name);
TEST_FREE(option->val);
TEST_FREE(option->comment);
free(option);
}
else
cnew = option;
if (old == NULL) {
xconfigAddListItem((GenericListPtr *)(&head), (GenericListPtr)cnew);
}
return head;
}
void
xconfigPrintOptionList(FILE *fp, XConfigOptionPtr list, int tabs)
{
int i;
if (!list)
return;
while (list) {
for (i = 0; i < tabs; i++)
fprintf(fp, " ");
if (list->val)
fprintf(fp, "Option \"%s\" \"%s\"", list->name, list->val);
else
fprintf(fp, "Option \"%s\"", list->name);
if (list->comment)
fprintf(fp, "%s", list->comment);
else
fputc('\n', fp);
list = list->next;
}
}
* Determines if the Composite extension should be disabled or not.
*
* - If the extension can be enabled, this function returns NULL.
*
* - If the extension should be disabled, this function returns a
* string that lists the conflicting options that are enabled. The string
* returned has to be freed by the caller.
*/
char *xconfigValidateComposite(XConfigPtr config,
GenerateOptions *gop,
int composite_specified,
int xinerama_enabled,
int depth,
int overlay_enabled,
int cioverlay_enabled,
int ubb_enabled,
int stereo_enabled)
{
int i, n;
char *err_str;
const struct {
const char *name;
int value;
} composite_incompatible_options[] = {
{ "Xinerama", xinerama_enabled && !gop->xinerama_plus_composite_works },
{ "Overlay", overlay_enabled },
{ "CIOverlay", cioverlay_enabled },
};
* We need to be careful to only set the option value if the X
* server is going to recognize the Extension section and the
* composite option. We guess whether the server will recognize
* the option: if get_xserver_in_use() thinks the X server
* supports the "Composite" extension, or the current config
* already has an extension section, or the user specified the
* composite option.
*/
if (!gop->supports_extension_section &&
!config->extensions &&
!composite_specified) {
return NULL;
}
n = 0;
err_str = NULL;
for (i = 0; i < ARRAY_LEN(composite_incompatible_options); i++) {
int value = composite_incompatible_options[i].value;
const char *name = composite_incompatible_options[i].name;
if (value) {
err_str = nv_prepend_to_string_list(err_str, name,
(n > 1) ? ", " : " or ");
n++;
}
}
if (depth <= 8) {
err_str = nv_prepend_to_string_list(err_str, "depth=8",
(n > 1) ? ", " : " or ");
}
return err_str;
}