summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Plattner <aplattner@nvidia.com>2008-02-13 10:26:52 -0800
committerAaron Plattner <aplattner@nvidia.com>2008-02-13 10:26:52 -0800
commitc1cb49fc2abcb44580f7544e2ac8f987da5205cc (patch)
treec4f28e1ec22fab18a7f95fa2768badd263d0fd6b
-rw-r--r--Makefile232
-rw-r--r--XF86Config-parser/Configint.h212
-rw-r--r--XF86Config-parser/DRI.c160
-rw-r--r--XF86Config-parser/Device.c502
-rw-r--r--XF86Config-parser/Extensions.c102
-rw-r--r--XF86Config-parser/Files.c283
-rw-r--r--XF86Config-parser/Flags.c550
-rw-r--r--XF86Config-parser/Generate.c1238
-rw-r--r--XF86Config-parser/Input.c395
-rw-r--r--XF86Config-parser/Keyboard.c308
-rw-r--r--XF86Config-parser/Layout.c580
-rw-r--r--XF86Config-parser/Makefile48
-rw-r--r--XF86Config-parser/Module.c286
-rw-r--r--XF86Config-parser/Monitor.c901
-rw-r--r--XF86Config-parser/Pointer.c240
-rw-r--r--XF86Config-parser/Read.c353
-rw-r--r--XF86Config-parser/Scan.c946
-rw-r--r--XF86Config-parser/Screen.c617
-rw-r--r--XF86Config-parser/Util.c185
-rw-r--r--XF86Config-parser/Vendor.c253
-rw-r--r--XF86Config-parser/Video.c292
-rw-r--r--XF86Config-parser/Write.c114
-rw-r--r--XF86Config-parser/configProcs.h118
-rw-r--r--XF86Config-parser/xf86Parser.h724
-rw-r--r--XF86Config-parser/xf86tokens.h276
-rw-r--r--gen-manpage-opts.c70
-rw-r--r--lscf.c279
-rw-r--r--make_usable.c271
-rw-r--r--multiple_screens.c910
-rw-r--r--nvgetopt.c276
-rw-r--r--nvgetopt.h48
-rw-r--r--nvidia-cfg.h229
-rw-r--r--nvidia-xconfig.1.m495
-rw-r--r--nvidia-xconfig.c848
-rw-r--r--nvidia-xconfig.h201
-rw-r--r--option_table.h333
-rw-r--r--options.c300
-rw-r--r--tree.c310
-rw-r--r--util.c806
39 files changed, 14891 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..4164fca
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,232 @@
+#
+# nvidia-xconfig: A tool for manipulating X config files,
+# specifically for use by the NVIDIA Linux graphics driver.
+#
+# Copyright (C) 2005 NVIDIA Corporation
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the:
+#
+# Free Software Foundation, Inc.
+# 59 Temple Place - Suite 330
+# Boston, MA 02111-1307, USA
+#
+#
+# Makefile
+#
+
+# default definitions; can be overwritten by users
+
+SHELL = /bin/sh
+INSTALL = install
+BUILD_OS := $(shell uname)
+BUILD_ARCH := $(shell uname -m)
+
+ifndef CC
+ CC = gcc
+endif
+
+ifndef HOST_CC
+ HOST_CC = $(CC)
+endif
+
+CPP = cpp
+
+ifndef CFLAGS
+ CFLAGS = -g -O -Wall
+endif
+ifdef NV_CFLAGS
+ CFLAGS += $(NV_CFLAGS)
+endif
+
+# the NVDEBUG environment variable controls whether we build debug or retail
+
+ifeq ($(NVDEBUG),1)
+ STRIP = true
+ CFLAGS += -g -DDEBUG
+else
+ STRIP = strip
+ CFLAGS += -O
+endif
+
+# default prefix
+ifdef ROOT
+ prefix = $(ROOT)/usr
+else
+ prefix = /usr/local
+endif
+
+# default echo within SunOS sh does not have -n option. Use /usr/ucb/echo instead.
+# Solaris install has a different argument syntax
+# Also, man pages are not gzipped on Solaris.
+ifeq ($(BUILD_OS),SunOS)
+ECHO=/usr/ucb/echo
+define INSTALL_RULE
+ $(INSTALL) -m 755 -f $(bindir) $<
+ mkdir -p $(mandir)
+ $(INSTALL) -m 644 -f $(mandir) $(MANPAGE)
+endef
+LLSCF=-lscf
+else
+ECHO=echo
+define INSTALL_RULE
+ $(INSTALL) -m 755 $< $(bindir)
+ mkdir -p $(mandir)
+ $(INSTALL) -m 644 $(MANPAGE) $(mandir)
+ gzip -9f $(mandir)/$(MANPAGE)
+endef
+LLSCF=
+endif
+
+exec_prefix = $(prefix)
+bindir = $(exec_prefix)/bin
+mandir = $(exec_prefix)/share/man/man1
+
+NVIDIA_XCONFIG = nvidia-xconfig
+NVIDIA_XCONFIG_VERSION = 1.0
+
+NVIDIA_XCONFIG_DISTDIR = $(NVIDIA_XCONFIG)-$(NVIDIA_XCONFIG_VERSION)
+
+EXTRA_DIST = \
+ nvgetopt.h \
+ nvidia-xconfig.h \
+ nvidia-cfg.h \
+ option_table.h \
+ Makefile \
+ XF86Config-parser/*.c \
+ XF86Config-parser/*.h \
+ XF86Config-parser/Makefile \
+ nvidia-xconfig.1.m4 \
+ gen-manpage-opts.c
+
+MANPAGE = nvidia-xconfig.1
+
+STAMP_C = g_stamp.c
+
+SRC = util.c \
+ nvidia-xconfig.c \
+ make_usable.c \
+ multiple_screens.c \
+ tree.c \
+ nvgetopt.c \
+ options.c \
+ lscf.c
+
+ALL_SRC = $(SRC) $(STAMP_C)
+
+OBJS = $(ALL_SRC:.c=.o)
+
+SUBDIR = XF86Config-parser
+
+
+CFLAGS += -I $(SUBDIR)
+CPPFLAGS = $(CFLAGS)
+LDFLAGS = -lm $(LLSCF)
+
+ifneq ($(BUILD_OS),FreeBSD)
+LDFLAGS += -ldl
+endif
+
+
+LIB = $(SUBDIR)/libXF86Config-parser.a
+
+default: all
+
+all: $(NVIDIA_XCONFIG) $(MANPAGE)
+
+install: $(NVIDIA_XCONFIG)
+ $(STRIP) $<
+ $(INSTALL_RULE)
+
+$(NVIDIA_XCONFIG): $(OBJS) $(LIB)
+ $(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) -o $@ $(LIB)
+
+.PHONY: $(LIB) dist clean clobber
+
+$(LIB):
+ $(MAKE) NV_CFLAGS='$(NV_CFLAGS)' -C $(SUBDIR)
+
+%.o: %.c
+ $(CC) -c $(CFLAGS) $< -o $@
+
+%.d: %.c
+ @set -e; $(CC) -MM $(CPPFLAGS) $< \
+ | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
+ [ -s $@ ] || rm -f $@
+
+$(STAMP_C): $(filter-out $(STAMP_C:.c=.o), $(OBJS))
+ @ rm -f $@
+ @ $(ECHO) -n "const char NV_ID[] = \"nvidia id: " >> $@
+ @ $(ECHO) -n "$(NVIDIA_XCONFIG): " >> $@
+ @ $(ECHO) -n "version $(NVIDIA_XCONFIG_VERSION) " >> $@
+ @ $(ECHO) -n "($(shell whoami)@$(shell hostname)) " >> $@
+ @ $(ECHO) "$(shell date)\";" >> $@
+ @ $(ECHO) "const char *pNV_ID = NV_ID + 11;" >> $@
+
+.PHONY: dist print_version clean clobber
+
+dist: $(EXTRA_DIST)
+ @ if [ -d $(NVIDIA_XCONFIG_DISTDIR) ]; then \
+ chmod 755 $(NVIDIA_XCONFIG_DISTDIR); \
+ fi
+ @ if [ -f $(NVIDIA_XCONFIG_DISTDIR).tar.gz ]; \
+ then chmod 644 $(NVIDIA_XCONFIG_DISTDIR).tar.gz; \
+ fi
+ rm -rf $(NVIDIA_XCONFIG_DISTDIR) $(NVIDIA_XCONFIG_DISTDIR).tar.gz
+ mkdir -p $(NVIDIA_XCONFIG_DISTDIR)/$(SUBDIR)
+ @ for i in $(SRC); do \
+ if [ $$i ]; then \
+ cp $$i $(NVIDIA_XCONFIG_DISTDIR)/$$i ; \
+ chmod 644 $(NVIDIA_XCONFIG_DISTDIR)/$$i ; \
+ fi ; \
+ done
+ @ for i in $(EXTRA_DIST); do \
+ if [ $$i ]; then \
+ cp $$i $(NVIDIA_XCONFIG_DISTDIR)/$$i ; \
+ chmod 644 $(NVIDIA_XCONFIG_DISTDIR)/$$i ; \
+ fi ; \
+ done
+ tar czf $(NVIDIA_XCONFIG_DISTDIR).tar.gz $(NVIDIA_XCONFIG_DISTDIR)
+ rm -rf $(NVIDIA_XCONFIG_DISTDIR)
+
+print_version:
+ @ $(ECHO) $(NVIDIA_XCONFIG_VERSION)
+
+clean clobber:
+ rm -rf *.o *~ *.d $(STAMP_C) $(NVIDIA_XCONFIG) $(MANPAGE) gen-manpage-opts options.1.inc
+ $(MAKE) -C $(SUBDIR) $@
+
+### Documentation
+
+AUTO_TEXT = ".\\\" WARNING: THIS FILE IS AUTO-GENERATED! Edit $< instead."
+
+doc: $(MANPAGE)
+
+gen-manpage-opts.o: gen-manpage-opts.c
+ $(HOST_CC) $(CFLAGS) -c $<
+
+gen-manpage-opts: gen-manpage-opts.o
+ $(HOST_CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
+
+-include gen-manpage-opts.d
+
+options.1.inc: gen-manpage-opts
+ ./$< > $@
+
+nvidia-xconfig.1: nvidia-xconfig.1.m4 options.1.inc
+ m4 -D__HEADER__=$(AUTO_TEXT) $< > $@
+
+###
+
+-include $(SRC:.c=.d)
+
diff --git a/XF86Config-parser/Configint.h b/XF86Config-parser/Configint.h
new file mode 100644
index 0000000..f91c6ee
--- /dev/null
+++ b/XF86Config-parser/Configint.h
@@ -0,0 +1,212 @@
+/*
+ *
+ * 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-2002 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).
+ */
+
+
+/*
+ * These definitions are used through out the configuration file parser, but
+ * they should not be visible outside of the parser.
+ */
+
+#ifndef _Configint_h_
+#define _Configint_h_
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include "xf86Parser.h"
+
+typedef struct
+{
+ int num; /* returned number */
+ char *str; /* private copy of the return-string */
+ double realnum; /* returned number as a real */
+}
+LexRec, *LexPtr;
+
+
+#include "configProcs.h"
+#include <stdlib.h>
+
+#define TEST_FREE(a) \
+ if (a) { \
+ free (a); \
+ a = NULL; \
+ }
+
+
+#define PARSE_PROLOGUE(typeptr,typerec) \
+ typeptr ptr; \
+ if ((ptr = (typeptr) calloc(1, sizeof(typerec))) == NULL) { \
+ return NULL; \
+ } \
+ memset(ptr, 0, sizeof(typerec));
+
+
+#define HANDLE_LIST(field,func,type) \
+{ \
+ type p = func(); \
+ if (p == NULL) \
+ { \
+ CLEANUP (ptr); \
+ return (NULL); \
+ } else { \
+ ptr->field = (type) \
+ xconfigAddListItem((GenericListPtr) ptr->field, \
+ (GenericListPtr) p); \
+ } \
+}
+
+
+#define Error(a,b) \
+ do { \
+ xconfigErrorMsg(ParseErrorMsg, a, b); \
+ CLEANUP (ptr); \
+ return NULL; \
+ } while (0) \
+
+/*
+ * These are defines for error messages to promote consistency.
+ * error messages are preceded by the line number, section and file name,
+ * so these messages should be about the specific keyword and syntax in error.
+ * To help limit namespace polution, end each with _MSG.
+ * limit messages to 70 characters if possible.
+ */
+
+#define BAD_OPTION_MSG \
+"The Option keyword requires 1 or 2 quoted strings to follow it."
+#define INVALID_KEYWORD_MSG \
+"\"%s\" is not a valid keyword in this section."
+#define INVALID_SECTION_MSG \
+"\"%s\" is not a valid section name."
+#define UNEXPECTED_EOF_MSG \
+"Unexpected EOF. Missing EndSection keyword?"
+#define QUOTE_MSG \
+"The %s keyword requires a quoted string to follow it."
+#define NUMBER_MSG \
+"The %s keyword requires a number to follow it."
+#define POSITIVE_INT_MSG \
+"The %s keyword requires a positive integer to follow it."
+#define ZAXISMAPPING_MSG \
+"The ZAxisMapping keyword requires 2 positive numbers or X or Y to follow it."
+#define AUTOREPEAT_MSG \
+"The AutoRepeat keyword requires 2 numbers (delay and rate) to follow it."
+#define XLEDS_MSG \
+"The XLeds keyword requries one or more numbers to follow it."
+#define DACSPEED_MSG \
+"The DacSpeed keyword must be followed by a list of up to %d numbers."
+#define DISPLAYSIZE_MSG \
+"The DisplaySize keyword must be followed by the width and height in mm."
+#define HORIZSYNC_MSG \
+"The HorizSync keyword must be followed by a list of numbers or ranges."
+#define VERTREFRESH_MSG \
+"The VertRefresh keyword must be followed by a list of numbers or ranges."
+#define VIEWPORT_MSG \
+"The Viewport keyword must be followed by an X and Y value."
+#define VIRTUAL_MSG \
+"The Virtual keyword must be followed by a width and height value."
+#define WEIGHT_MSG \
+"The Weight keyword must be followed by red, green and blue values."
+#define BLACK_MSG \
+"The Black keyword must be followed by red, green and blue values."
+#define WHITE_MSG \
+"The White keyword must be followed by red, green and blue values."
+#define SCREEN_MSG \
+"The Screen keyword must be followed by an optional number, a screen name\n" \
+"\tin quotes, and optional position/layout information."
+#define INVALID_SCR_MSG \
+"Invalid Screen line."
+#define INPUTDEV_MSG \
+"The InputDevice keyword must be followed by an input device name in quotes."
+#define INACTIVE_MSG \
+"The Inactive keyword must be followed by a Device name in quotes."
+#define UNDEFINED_SCREEN_MSG \
+"Undefined Screen \"%s\" referenced by ServerLayout \"%s\"."
+#define UNDEFINED_MONITOR_MSG \
+"Undefined Monitor \"%s\" referenced by Screen \"%s\"."
+#define UNDEFINED_MODES_MSG \
+"Undefined Modes Section \"%s\" referenced by Monitor \"%s\"."
+#define UNDEFINED_DEVICE_MSG \
+"Undefined Device \"%s\" referenced by Screen \"%s\"."
+#define UNDEFINED_ADAPTOR_MSG \
+"Undefined VideoAdaptor \"%s\" referenced by Screen \"%s\"."
+#define ADAPTOR_REF_TWICE_MSG \
+"VideoAdaptor \"%s\" already referenced by Screen \"%s\"."
+#define UNDEFINED_DEVICE_LAY_MSG \
+"Undefined Device \"%s\" referenced by ServerLayout \"%s\"."
+#define UNDEFINED_INPUT_MSG \
+"Undefined InputDevice \"%s\" referenced by ServerLayout \"%s\"."
+#define NO_IDENT_MSG \
+"This section must have an Identifier line."
+#define ONLY_ONE_MSG \
+"This section must have only one of either %s line."
+#define UNDEFINED_DRIVER_MSG \
+"Device section \"%s\" must have a Driver line."
+#define UNDEFINED_INPUTDRIVER_MSG \
+"InputDevice section \"%s\" must have a Driver line."
+#define INVALID_GAMMA_MSG \
+"gamma correction value(s) expected\n either one value or three r/g/b values."
+#define GROUP_MSG \
+"The Group keyword must be followed by either a group name in quotes or\n" \
+"\ta numerical group id."
+#define MULTIPLE_MSG \
+"Multiple \"%s\" lines."
+
+/* Warning messages */
+#define OBSOLETE_MSG \
+"Ignoring obsolete keyword \"%s\"."
+#define MOVED_TO_FLAGS_MSG \
+"Keyword \"%s\" is now an Option flag in the ServerFlags section."
+
+#endif /* _Configint_h_ */
diff --git a/XF86Config-parser/DRI.c b/XF86Config-parser/DRI.c
new file mode 100644
index 0000000..03f14d9
--- /dev/null
+++ b/XF86Config-parser/DRI.c
@@ -0,0 +1,160 @@
+/* DRI.c -- DRI Section in XF86Config file
+ * Created: Fri Mar 19 08:40:22 1999 by faith@precisioninsight.com
+ * Revised: Thu Jun 17 16:08:05 1999 by faith@precisioninsight.com
+ *
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * 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 (including the next
+ * paragraph) 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
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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.
+ *
+ */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+extern LexRec val;
+
+static XConfigSymTabRec DRITab[] =
+{
+ {ENDSECTION, "endsection"},
+ {GROUP, "group"},
+ {BUFFERS, "buffers"},
+ {MODE, "mode"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeBuffersList
+
+XConfigBuffersPtr
+xconfigParseBuffers (void)
+{
+ int token;
+ PARSE_PROLOGUE (XConfigBuffersPtr, XConfigBuffersRec)
+
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error("Buffers count expected", NULL);
+ ptr->count = val.num;
+
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error("Buffers size expected", NULL);
+ ptr->size = val.num;
+
+ if ((token = xconfigGetSubToken (&(ptr->comment))) == STRING) {
+ ptr->flags = val.str;
+ if ((token = xconfigGetToken (NULL)) == COMMENT)
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ else
+ xconfigUnGetToken(token);
+ }
+
+#ifdef DEBUG
+ xconfigErrorMsg(DebugMsg, "Buffers parsed\n");
+#endif
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+#define CLEANUP xconfigFreeDRI
+
+XConfigDRIPtr
+xconfigParseDRISection (void)
+{
+ int token;
+ PARSE_PROLOGUE (XConfigDRIPtr, XConfigDRIRec);
+
+ /* Zero is a valid value for this. */
+ ptr->group = -1;
+ while ((token = xconfigGetToken (DRITab)) != ENDSECTION) {
+ switch (token)
+ {
+ case GROUP:
+ if ((token = xconfigGetSubToken (&(ptr->comment))) == STRING)
+ ptr->group_name = val.str;
+ else if (token == NUMBER)
+ ptr->group = val.num;
+ else
+ Error (GROUP_MSG, NULL);
+ break;
+ case MODE:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "Mode");
+ ptr->mode = val.num;
+ break;
+ case BUFFERS:
+ HANDLE_LIST (buffers, xconfigParseBuffers,
+ XConfigBuffersPtr);
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ }
+
+#ifdef DEBUG
+ ErrorF("DRI section parsed\n");
+#endif
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+void
+xconfigPrintDRISection (FILE * cf, XConfigDRIPtr ptr)
+{
+ /* we never need the DRI section for the NVIDIA driver */
+
+ return;
+}
+
+void
+xconfigFreeDRI (XConfigDRIPtr ptr)
+{
+ if (ptr == NULL)
+ return;
+
+ xconfigFreeBuffersList (ptr->buffers);
+ TEST_FREE (ptr->comment);
+ free (ptr);
+}
+
+void
+xconfigFreeBuffersList (XConfigBuffersPtr ptr)
+{
+ XConfigBuffersPtr prev;
+
+ while (ptr) {
+ TEST_FREE (ptr->flags);
+ TEST_FREE (ptr->comment);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
diff --git a/XF86Config-parser/Device.c b/XF86Config-parser/Device.c
new file mode 100644
index 0000000..29359d8
--- /dev/null
+++ b/XF86Config-parser/Device.c
@@ -0,0 +1,502 @@
+/*
+ *
+ * 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).
+ */
+
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+#include <ctype.h>
+
+extern LexRec val;
+
+static
+XConfigSymTabRec DeviceTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {IDENTIFIER, "identifier"},
+ {VENDOR, "vendorname"},
+ {BOARD, "boardname"},
+ {CHIPSET, "chipset"},
+ {RAMDAC, "ramdac"},
+ {DACSPEED, "dacspeed"},
+ {CLOCKS, "clocks"},
+ {OPTION, "option"},
+ {VIDEORAM, "videoram"},
+ {BIOSBASE, "biosbase"},
+ {MEMBASE, "membase"},
+ {IOBASE, "iobase"},
+ {CLOCKCHIP, "clockchip"},
+ {CHIPID, "chipid"},
+ {CHIPREV, "chiprev"},
+ {CARD, "card"},
+ {DRIVER, "driver"},
+ {BUSID, "busid"},
+ {TEXTCLOCKFRQ, "textclockfreq"},
+ {IRQ, "irq"},
+ {SCREEN, "screen"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeDeviceList
+
+XConfigDevicePtr
+xconfigParseDeviceSection (void)
+{
+ int i;
+ int has_ident = FALSE;
+ int token;
+ PARSE_PROLOGUE (XConfigDevicePtr, XConfigDeviceRec)
+
+ /* Zero is a valid value for these */
+ ptr->chipid = -1;
+ ptr->chiprev = -1;
+ ptr->irq = -1;
+ ptr->screen = -1;
+ while ((token = xconfigGetToken (DeviceTab)) != ENDSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case IDENTIFIER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Identifier");
+ if (has_ident == TRUE)
+ Error (MULTIPLE_MSG, "Identifier");
+ ptr->identifier = val.str;
+ has_ident = TRUE;
+ break;
+ case VENDOR:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Vendor");
+ ptr->vendor = val.str;
+ break;
+ case BOARD:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Board");
+ ptr->board = val.str;
+ break;
+ case CHIPSET:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Chipset");
+ ptr->chipset = val.str;
+ break;
+ case CARD:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Card");
+ ptr->card = val.str;
+ break;
+ case DRIVER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Driver");
+ ptr->driver = val.str;
+ break;
+ case RAMDAC:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Ramdac");
+ ptr->ramdac = val.str;
+ break;
+ case DACSPEED:
+ for (i = 0; i < CONF_MAXDACSPEEDS; i++)
+ ptr->dacSpeeds[i] = 0;
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ {
+ Error (DACSPEED_MSG, CONF_MAXDACSPEEDS);
+ }
+ else
+ {
+ ptr->dacSpeeds[0] = (int) (val.realnum * 1000.0 + 0.5);
+ for (i = 1; i < CONF_MAXDACSPEEDS; i++)
+ {
+ if (xconfigGetSubToken (&(ptr->comment)) == NUMBER)
+ ptr->dacSpeeds[i] = (int)
+ (val.realnum * 1000.0 + 0.5);
+ else
+ {
+ xconfigUnGetToken (token);
+ break;
+ }
+ }
+ }
+ break;
+ case VIDEORAM:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "VideoRam");
+ ptr->videoram = val.num;
+ break;
+ case BIOSBASE:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "BIOSBase");
+ ptr->bios_base = val.num;
+ break;
+ case MEMBASE:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "MemBase");
+ ptr->mem_base = val.num;
+ break;
+ case IOBASE:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "IOBase");
+ ptr->io_base = val.num;
+ break;
+ case CLOCKCHIP:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "ClockChip");
+ ptr->clockchip = val.str;
+ break;
+ case CHIPID:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "ChipID");
+ ptr->chipid = val.num;
+ break;
+ case CHIPREV:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "ChipRev");
+ ptr->chiprev = val.num;
+ break;
+
+ case CLOCKS:
+ token = xconfigGetSubToken(&(ptr->comment));
+ for( i = ptr->clocks;
+ token == NUMBER && i < CONF_MAXCLOCKS; i++ ) {
+ ptr->clock[i] = (int)(val.realnum * 1000.0 + 0.5);
+ token = xconfigGetSubToken(&(ptr->comment));
+ }
+ ptr->clocks = i;
+ xconfigUnGetToken (token);
+ break;
+ case TEXTCLOCKFRQ:
+ if ((token = xconfigGetSubToken(&(ptr->comment))) != NUMBER)
+ Error (NUMBER_MSG, "TextClockFreq");
+ ptr->textclockfreq = (int)(val.realnum * 1000.0 + 0.5);
+ break;
+ case OPTION:
+ ptr->options = xconfigParseOption(ptr->options);
+ break;
+ case BUSID:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "BusID");
+ ptr->busid = val.str;
+ break;
+ case IRQ:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (QUOTE_MSG, "IRQ");
+ ptr->irq = val.num;
+ break;
+ case SCREEN:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "Screen");
+ ptr->screen = val.num;
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ }
+
+ if (!has_ident)
+ Error (NO_IDENT_MSG, NULL);
+
+#ifdef DEBUG
+ xconfigErrorMsg(DebugMsg, "Device section parsed\n");
+#endif
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+void
+xconfigPrintDeviceSection (FILE * cf, XConfigDevicePtr ptr)
+{
+ int i;
+
+ while (ptr)
+ {
+ fprintf (cf, "Section \"Device\"\n");
+ if (ptr->comment)
+ fprintf (cf, "%s", ptr->comment);
+ if (ptr->identifier)
+ fprintf (cf, " Identifier \"%s\"\n", ptr->identifier);
+ if (ptr->driver)
+ fprintf (cf, " Driver \"%s\"\n", ptr->driver);
+ if (ptr->vendor)
+ fprintf (cf, " VendorName \"%s\"\n", ptr->vendor);
+ if (ptr->board)
+ fprintf (cf, " BoardName \"%s\"\n", ptr->board);
+ if (ptr->chipset)
+ fprintf (cf, " ChipSet \"%s\"\n", ptr->chipset);
+ if (ptr->card)
+ fprintf (cf, " Card \"%s\"\n", ptr->card);
+ if (ptr->ramdac)
+ fprintf (cf, " RamDac \"%s\"\n", ptr->ramdac);
+ if (ptr->dacSpeeds[0] > 0 ) {
+ fprintf (cf, " DacSpeed ");
+ for (i = 0; i < CONF_MAXDACSPEEDS
+ && ptr->dacSpeeds[i] > 0; i++ )
+ fprintf (cf, "%g ", (double) (ptr->dacSpeeds[i])/ 1000.0 );
+ fprintf (cf, "\n");
+ }
+ if (ptr->videoram)
+ fprintf (cf, " VideoRam %d\n", ptr->videoram);
+ if (ptr->bios_base)
+ fprintf (cf, " BiosBase 0x%lx\n", ptr->bios_base);
+ if (ptr->mem_base)
+ fprintf (cf, " MemBase 0x%lx\n", ptr->mem_base);
+ if (ptr->io_base)
+ fprintf (cf, " IOBase 0x%lx\n", ptr->io_base);
+ if (ptr->clockchip)
+ fprintf (cf, " ClockChip \"%s\"\n", ptr->clockchip);
+ if (ptr->chipid != -1)
+ fprintf (cf, " ChipId 0x%x\n", ptr->chipid);
+ if (ptr->chiprev != -1)
+ fprintf (cf, " ChipRev 0x%x\n", ptr->chiprev);
+
+ xconfigPrintOptionList(cf, ptr->options, 1);
+ if (ptr->clocks > 0 ) {
+ fprintf (cf, " Clocks ");
+ for (i = 0; i < ptr->clocks; i++ )
+ fprintf (cf, "%.1f ", (double)ptr->clock[i] / 1000.0 );
+ fprintf (cf, "\n");
+ }
+ if (ptr->textclockfreq) {
+ fprintf (cf, " TextClockFreq %.1f\n",
+ (double)ptr->textclockfreq / 1000.0);
+ }
+ if (ptr->busid)
+ fprintf (cf, " BusID \"%s\"\n", ptr->busid);
+ if (ptr->screen > -1)
+ fprintf (cf, " Screen %d\n", ptr->screen);
+ if (ptr->irq >= 0)
+ fprintf (cf, " IRQ %d\n", ptr->irq);
+ fprintf (cf, "EndSection\n\n");
+ ptr = ptr->next;
+ }
+}
+
+void
+xconfigFreeDeviceList (XConfigDevicePtr ptr)
+{
+ XConfigDevicePtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->identifier);
+ TEST_FREE (ptr->vendor);
+ TEST_FREE (ptr->board);
+ TEST_FREE (ptr->chipset);
+ TEST_FREE (ptr->card);
+ TEST_FREE (ptr->driver);
+ TEST_FREE (ptr->ramdac);
+ TEST_FREE (ptr->clockchip);
+ TEST_FREE (ptr->comment);
+ xconfigOptionListFree (ptr->options);
+
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+int
+xconfigValidateDevice (XConfigPtr p)
+{
+ XConfigDevicePtr device = p->devices;
+
+ if (!device) {
+ xconfigErrorMsg(ValidationErrorMsg, "At least one Device section "
+ "is required.");
+ return (FALSE);
+ }
+
+ while (device) {
+ if (!device->driver) {
+ xconfigErrorMsg(ValidationErrorMsg, UNDEFINED_DRIVER_MSG,
+ device->identifier);
+ return (FALSE);
+ }
+ device = device->next;
+ }
+ return (TRUE);
+}
+
+XConfigDevicePtr
+xconfigFindDevice (const char *ident, XConfigDevicePtr p)
+{
+ while (p)
+ {
+ if (xconfigNameCompare (ident, p->identifier) == 0)
+ return (p);
+
+ p = p->next;
+ }
+ return (NULL);
+}
+
+
+/*
+ * Determine what bus type the busID string represents. The start of the
+ * bus-dependent part of the string is returned as retID.
+ */
+
+static int isPci(const char* busID, const char **retID)
+{
+ char *p, *s;
+ int ret = FALSE;
+
+ /* If no type field, Default to PCI */
+ if (isdigit(busID[0])) {
+ if (retID)
+ *retID = busID;
+ return TRUE;
+ }
+
+ s = strdup(busID);
+ p = strtok(s, ":");
+ if (p == NULL || *p == 0) {
+ free(s);
+ return FALSE;
+ }
+ if (!xconfigNameCompare(p, "pci") || !xconfigNameCompare(p, "agp")) {
+ if (retID)
+ *retID = busID + strlen(p) + 1;
+ ret = TRUE;
+ }
+ free(s);
+ return ret;
+}
+
+
+/*
+ * Parse a BUS ID string, and return the PCI bus parameters if it was
+ * in the correct format for a PCI bus id.
+ */
+
+int xconfigParsePciBusString(const char *busID,
+ int *bus, int *device, int *func)
+{
+ /*
+ * The format is assumed to be "bus[@domain]:device[:func]", where domain,
+ * bus, device and func are decimal integers. domain and func may be
+ * omitted and assumed to be zero, although doing this isn't encouraged.
+ */
+
+ char *p, *s, *d;
+ const char *id;
+ int i;
+
+ if (!isPci(busID, &id))
+ return FALSE;
+
+ s = strdup(id);
+ p = strtok(s, ":");
+ if (p == NULL || *p == 0) {
+ free(s);
+ return FALSE;
+ }
+ d = strpbrk(p, "@");
+ if (d != NULL) {
+ *(d++) = 0;
+ for (i = 0; d[i] != 0; i++) {
+ if (!isdigit(d[i])) {
+ free(s);
+ return FALSE;
+ }
+ }
+ }
+ for (i = 0; p[i] != 0; i++) {
+ if (!isdigit(p[i])) {
+ free(s);
+ return FALSE;
+ }
+ }
+ *bus = atoi(p);
+ if (d != NULL && *d != 0)
+ *bus += atoi(d) << 8;
+ p = strtok(NULL, ":");
+ if (p == NULL || *p == 0) {
+ free(s);
+ return FALSE;
+ }
+ for (i = 0; p[i] != 0; i++) {
+ if (!isdigit(p[i])) {
+ free(s);
+ return FALSE;
+ }
+ }
+ *device = atoi(p);
+ *func = 0;
+ p = strtok(NULL, ":");
+ if (p == NULL || *p == 0) {
+ free(s);
+ return TRUE;
+ }
+ for (i = 0; p[i] != 0; i++) {
+ if (!isdigit(p[i])) {
+ free(s);
+ return FALSE;
+ }
+ }
+ *func = atoi(p);
+ free(s);
+ return TRUE;
+}
+
diff --git a/XF86Config-parser/Extensions.c b/XF86Config-parser/Extensions.c
new file mode 100644
index 0000000..7482a6d
--- /dev/null
+++ b/XF86Config-parser/Extensions.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2004 Red Hat Inc., Raleigh, North Carolina.
+ *
+ * All Rights Reserved.
+ *
+ * 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 on 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 (including the
+ * next paragraph) 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * 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.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <kem@redhat.com>
+ *
+ */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+extern LexRec val;
+
+static XConfigSymTabRec ExtensionsTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {OPTION, "option"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeExtensions
+
+XConfigExtensionsPtr
+xconfigParseExtensionsSection (void)
+{
+ int token;
+
+ PARSE_PROLOGUE (XConfigExtensionsPtr, XConfigExtensionsRec);
+
+ while ((token = xconfigGetToken (ExtensionsTab)) != ENDSECTION) {
+ switch (token) {
+ case OPTION:
+ ptr->options = xconfigParseOption(ptr->options);
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ }
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+void
+xconfigPrintExtensionsSection (FILE * cf, XConfigExtensionsPtr ptr)
+{
+ XConfigOptionPtr p;
+
+ if (ptr == NULL || ptr->options == NULL)
+ return;
+
+ p = ptr->options;
+ fprintf (cf, "Section \"Extensions\"\n");
+ if (ptr->comment) fprintf (cf, "%s", ptr->comment);
+ xconfigPrintOptionList(cf, p, 1);
+ fprintf (cf, "EndSection\n\n");
+}
+
+void
+xconfigFreeExtensions (XConfigExtensionsPtr ptr)
+{
+ if (ptr == NULL)
+ return;
+
+ xconfigOptionListFree (ptr->options);
+ TEST_FREE (ptr->comment);
+ free (ptr);
+}
diff --git a/XF86Config-parser/Files.c b/XF86Config-parser/Files.c
new file mode 100644
index 0000000..8285c5c
--- /dev/null
+++ b/XF86Config-parser/Files.c
@@ -0,0 +1,283 @@
+/*
+ *
+ * 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).
+ */
+
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+extern LexRec val;
+
+static XConfigSymTabRec FilesTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {FONTPATH, "fontpath"},
+ {RGBPATH, "rgbpath"},
+ {MODULEPATH, "modulepath"},
+ {INPUTDEVICES, "inputdevices"},
+ {LOGFILEPATH, "logfile"},
+ {-1, ""},
+};
+
+static char *
+prependRoot (char *pathname)
+{
+ return pathname;
+}
+
+#define CLEANUP xconfigFreeFiles
+
+XConfigFilesPtr
+xconfigParseFilesSection (void)
+{
+ int i, j;
+ int k, l;
+ char *str;
+ int token;
+ PARSE_PROLOGUE (XConfigFilesPtr, XConfigFilesRec)
+
+ while ((token = xconfigGetToken (FilesTab)) != ENDSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case FONTPATH:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "FontPath");
+ j = FALSE;
+ str = prependRoot (val.str);
+ if (ptr->fontpath == NULL)
+ {
+ ptr->fontpath = malloc (1);
+ ptr->fontpath[0] = '\0';
+ i = strlen (str) + 1;
+ }
+ else
+ {
+ i = strlen (ptr->fontpath) + strlen (str) + 1;
+ if (ptr->fontpath[strlen (ptr->fontpath) - 1] != ',')
+ {
+ i++;
+ j = TRUE;
+ }
+ }
+ ptr->fontpath = realloc (ptr->fontpath, i);
+ if (j)
+ strcat (ptr->fontpath, ",");
+
+ strcat (ptr->fontpath, str);
+ free (val.str);
+ break;
+ case RGBPATH:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "RGBPath");
+ ptr->rgbpath = val.str;
+ break;
+ case MODULEPATH:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "ModulePath");
+ l = FALSE;
+ str = prependRoot (val.str);
+ if (ptr->modulepath == NULL)
+ {
+ ptr->modulepath = malloc (1);
+ ptr->modulepath[0] = '\0';
+ k = strlen (str) + 1;
+ }
+ else
+ {
+ k = strlen (ptr->modulepath) + strlen (str) + 1;
+ if (ptr->modulepath[strlen (ptr->modulepath) - 1] != ',')
+ {
+ k++;
+ l = TRUE;
+ }
+ }
+ ptr->modulepath = realloc (ptr->modulepath, k);
+ if (l)
+ strcat (ptr->modulepath, ",");
+
+ strcat (ptr->modulepath, str);
+ free (val.str);
+ break;
+ case INPUTDEVICES:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "InputDevices");
+ l = FALSE;
+ str = prependRoot (val.str);
+ if (ptr->inputdevs == NULL)
+ {
+ ptr->inputdevs = malloc (1);
+ ptr->inputdevs[0] = '\0';
+ k = strlen (str) + 1;
+ }
+ else
+ {
+ k = strlen (ptr->inputdevs) + strlen (str) + 1;
+ if (ptr->inputdevs[strlen (ptr->inputdevs) - 1] != ',')
+ {
+ k++;
+ l = TRUE;
+ }
+ }
+ ptr->inputdevs = realloc (ptr->inputdevs, k);
+ if (l)
+ strcat (ptr->inputdevs, ",");
+
+ strcat (ptr->inputdevs, str);
+ free (val.str);
+ break;
+ case LOGFILEPATH:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "LogFile");
+ ptr->logfile = val.str;
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ }
+
+#ifdef DEBUG
+ xconfigErrorMsg(DebugMsg, "File section parsed\n");
+#endif
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+void
+xconfigPrintFileSection (FILE * cf, XConfigFilesPtr ptr)
+{
+ char *p, *s;
+
+ if (ptr == NULL)
+ return;
+
+ if (ptr->comment)
+ fprintf (cf, "%s", ptr->comment);
+ if (ptr->logfile)
+ fprintf (cf, " LogFile \"%s\"\n", ptr->logfile);
+ if (ptr->rgbpath)
+ fprintf (cf, " RgbPath \"%s\"\n", ptr->rgbpath);
+ if (ptr->modulepath)
+ {
+ s = ptr->modulepath;
+ p = index (s, ',');
+ while (p)
+ {
+ *p = '\000';
+ fprintf (cf, " ModulePath \"%s\"\n", s);
+ *p = ',';
+ s = p;
+ s++;
+ p = index (s, ',');
+ }
+ fprintf (cf, " ModulePath \"%s\"\n", s);
+ }
+ if (ptr->inputdevs)
+ {
+ s = ptr->inputdevs;
+ p = index (s, ',');
+ while (p)
+ {
+ *p = '\000';
+ fprintf (cf, " InputDevices \"%s\"\n", s);
+ *p = ',';
+ s = p;
+ s++;
+ p = index (s, ',');
+ }
+ fprintf (cf, " InputDevices \"%s\"\n", s);
+ }
+ if (ptr->fontpath)
+ {
+ s = ptr->fontpath;
+ p = index (s, ',');
+ while (p)
+ {
+ *p = '\000';
+ fprintf (cf, " FontPath \"%s\"\n", s);
+ *p = ',';
+ s = p;
+ s++;
+ p = index (s, ',');
+ }
+ fprintf (cf, " FontPath \"%s\"\n", s);
+ }
+}
+
+void
+xconfigFreeFiles (XConfigFilesPtr p)
+{
+ if (p == NULL)
+ return;
+
+ TEST_FREE (p->logfile);
+ TEST_FREE (p->rgbpath);
+ TEST_FREE (p->modulepath);
+ TEST_FREE (p->inputdevs);
+ TEST_FREE (p->fontpath);
+ TEST_FREE (p->comment);
+
+ free (p);
+}
diff --git a/XF86Config-parser/Flags.c b/XF86Config-parser/Flags.c
new file mode 100644
index 0000000..62eeb12
--- /dev/null
+++ b/XF86Config-parser/Flags.c
@@ -0,0 +1,550 @@
+/*
+ *
+ * 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).
+ */
+
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+#include <math.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)
+ {
+ char *tmp;
+
+ if (ServerFlagsTab[i].token == token)
+ {
+ char *valstr = NULL;
+ /* can't use strdup because it calls malloc */
+ tmp = xconfigStrdup (ServerFlagsTab[i].name);
+ if (hasvalue)
+ {
+ tokentype = xconfigGetSubToken(&(ptr->comment));
+ if (strvalue) {
+ if (tokentype != STRING)
+ Error (QUOTE_MSG, tmp);
+ valstr = val.str;
+ } else {
+ if (tokentype != NUMBER)
+ Error (NUMBER_MSG, tmp);
+ valstr = malloc(16);
+ if (valstr)
+ sprintf(valstr, "%d", val.num);
+ }
+ }
+ ptr->options = xconfigAddNewOption
+ (ptr->options, tmp, 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;
+ }
+ }
+
+#ifdef DEBUG
+ xconfigErrorMsg(DebugMsg, "Flags section parsed\n");
+#endif
+
+ 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");
+}
+
+static XConfigOptionPtr
+addNewOption2 (XConfigOptionPtr head, char *name, char *val, int used)
+{
+ XConfigOptionPtr new, old = NULL;
+
+ /* Don't allow duplicates */
+ if (head != NULL && (old = xconfigFindOption(head, name)) != NULL) {
+ TEST_FREE(old->name);
+ TEST_FREE(old->val);
+ new = old;
+ } else {
+ new = calloc (1, sizeof (XConfigOptionRec));
+ new->next = NULL;
+ }
+ new->name = name;
+ new->val = val;
+ new->used = used;
+
+ if (old == NULL)
+ return ((XConfigOptionPtr) xconfigAddListItem ((GenericListPtr) head,
+ (GenericListPtr) new));
+ else
+ return head;
+}
+
+XConfigOptionPtr
+xconfigAddNewOption (XConfigOptionPtr head, char *name, char *val)
+{
+ return addNewOption2(head, name, val, 0);
+}
+
+void
+xconfigFreeFlags (XConfigFlagsPtr flags)
+{
+ if (flags == NULL)
+ return;
+ xconfigOptionListFree (flags->options);
+ TEST_FREE(flags->comment);
+ free (flags);
+}
+
+XConfigOptionPtr
+xconfigOptionListDup (XConfigOptionPtr opt)
+{
+ XConfigOptionPtr newopt = NULL;
+
+ while (opt)
+ {
+ newopt = xconfigAddNewOption(newopt, xconfigStrdup(opt->name),
+ xconfigStrdup(opt->val));
+ newopt->used = opt->used;
+ if (opt->comment)
+ newopt->comment = xconfigStrdup(opt->comment);
+ opt = opt->next;
+ }
+ return newopt;
+}
+
+void
+xconfigOptionListFree (XConfigOptionPtr opt)
+{
+ XConfigOptionPtr prev;
+
+ 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(char *name, char *value)
+{
+ XConfigOptionPtr opt;
+
+ opt = calloc(1, sizeof (XConfigOptionRec));
+ if (!opt)
+ return NULL;
+
+ opt->used = 0;
+ opt->next = 0;
+ opt->name = name;
+ opt->val = value;
+
+ return opt;
+}
+
+XConfigOptionPtr
+xconfigRemoveOption(XConfigOptionPtr list, XConfigOptionPtr opt)
+{
+ XConfigOptionPtr prev = NULL;
+ XConfigOptionPtr p = list;
+
+ while (p) {
+ if (p == opt) {
+ if (prev) prev->next = opt->next;
+ if (list == opt) list = opt->next;
+
+ TEST_FREE(opt->name);
+ TEST_FREE(opt->val);
+ TEST_FREE(opt->comment);
+ free(opt);
+ break;
+ }
+ prev = p;
+ p = p->next;
+ }
+
+ return list;
+}
+
+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);
+}
+
+XConfigOptionPtr
+xconfigOptionListCreate( const char **options, int count, int used )
+{
+ XConfigOptionPtr p = NULL;
+ char *t1, *t2;
+ int i;
+
+ if (count == -1)
+ {
+ for (count = 0; options[count]; count++)
+ ;
+ }
+ if( (count % 2) != 0 )
+ {
+ xconfigErrorMsg(InternalErrorMsg, "xconfigOptionListCreate: count must "
+ "be an even number.\n");
+ return (NULL);
+ }
+ for (i = 0; i < count; i += 2)
+ {
+ /* can't use strdup because it calls malloc */
+ t1 = malloc (sizeof (char) *
+ (strlen (options[i]) + 1));
+ strcpy (t1, options[i]);
+ t2 = malloc (sizeof (char) *
+ (strlen (options[i + 1]) + 1));
+ strcpy (t2, options[i + 1]);
+ p = addNewOption2 (p, t1, t2, used);
+ }
+
+ return (p);
+}
+
+/* the 2 given lists are merged. If an option with the same name is present in
+ * 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;
+ xconfigOptionListFree (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;
+}
+
+void
+xconfigDebugListOptions(XConfigOptionPtr Options)
+{
+ while (Options) {
+ xconfigErrorMsg(DebugMsg, "Option: %s Value: %s\n",
+ Options->name, Options->val);
+ Options = Options->next;
+ }
+}
+
+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;
+
+ /* Don't allow duplicates */
+ 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)
+ return ((XConfigOptionPtr)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;
+ }
+}
diff --git a/XF86Config-parser/Generate.c b/XF86Config-parser/Generate.c
new file mode 100644
index 0000000..7561aa9
--- /dev/null
+++ b/XF86Config-parser/Generate.c
@@ -0,0 +1,1238 @@
+/*
+ * nvidia-xconfig: A tool for manipulating X config files,
+ * specifically for use by the NVIDIA Linux graphics driver.
+ *
+ * Copyright (C) 2005 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ * Generate.c
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+
+
+#include "xf86Parser.h"
+#include "Configint.h"
+
+#define MOUSE_IDENTIFER "Mouse0"
+#define KEYBOARD_IDENTIFER "Keyboard0"
+
+#define SCREEN_IDENTIFIER "Screen%d"
+#define DEVICE_IDENTIFIER "Device%d"
+#define MONITOR_IDENTIFIER "Monitor%d"
+
+
+static int is_file(const char *filename);
+
+static void add_files(GenerateOptions *gop, XConfigPtr config);
+static void add_font_path(GenerateOptions *gop, XConfigPtr config);
+static void add_modules(GenerateOptions *gop, XConfigPtr config);
+
+static XConfigMonitorPtr
+add_monitor(XConfigPtr config, int count);
+
+static XConfigDevicePtr
+add_device(XConfigPtr config, int bus, int slot, char *boardname, int count);
+
+static XConfigDisplayPtr add_display(int depth);
+static void add_layout(GenerateOptions *gop, XConfigPtr config);
+
+static void add_inputref(XConfigPtr config, XConfigLayoutPtr layout,
+ char *name, char *coreKeyword);
+
+static int add_keyboard(GenerateOptions *gop, XConfigPtr config);
+static int add_mouse(GenerateOptions *gop, XConfigPtr config);
+
+/*
+ * xconfigGenerate() - generate a new XConfig from scratch
+ */
+
+XConfigPtr xconfigGenerate(GenerateOptions *gop)
+{
+ XConfigPtr config;
+
+ config = xconfigAlloc(sizeof(XConfigRec));
+
+ /* add files, fonts, and modules */
+
+ add_files(gop, config);
+ add_font_path(gop, config);
+ add_modules(gop, config);
+
+ /* add the keyboard and mouse */
+
+ add_keyboard(gop, config);
+ add_mouse(gop, config);
+
+ /* add the layout */
+
+ add_layout(gop, config);
+
+ return config;
+
+} /* xconfigGenerate() */
+
+
+
+/*
+ * xconfigGenerateAddScreen() - add a new screen to the config; bus
+ * and slot can be -1 to be ignored; boardname can be NULL to be
+ * ignored; count is used when building the identifier name, eg
+ * '"Screen%d", count'. Note that this does not append the screen to
+ * any layout's adjacency list.
+ */
+
+XConfigScreenPtr xconfigGenerateAddScreen(XConfigPtr config,
+ int bus, int slot,
+ char *boardname, int count)
+{
+ XConfigScreenPtr screen, s;
+ XConfigDevicePtr device;
+ XConfigMonitorPtr monitor;
+
+ monitor = add_monitor(config, count);
+ device = add_device(config, bus, slot, boardname, count);
+
+ screen = xconfigAlloc(sizeof(XConfigScreenRec));
+
+ screen->identifier = xconfigAlloc(32);
+ snprintf(screen->identifier, 32, SCREEN_IDENTIFIER, count);
+
+ screen->device_name = xconfigStrdup(device->identifier);
+ screen->device = device;
+
+ screen->monitor_name = xconfigStrdup(monitor->identifier);
+ screen->monitor = monitor;
+
+ screen->defaultdepth = 24;
+
+ screen->displays = add_display(screen->defaultdepth);
+
+ /* append to the end of the screen list */
+
+ if (!config->screens) {
+ config->screens = screen;
+ } else {
+ for (s = config->screens; s->next; s = s->next);
+ s->next = screen;
+ }
+
+ return screen;
+
+} /* xconfigGenerateAddScreen() */
+
+
+
+/*
+ * assign_screen_adjacencies() - setup all the adjacency information
+ * for the X screens in the given layout. Nothing fancy here: just
+ * position all the screens horizontally, moving from left to right.
+ */
+
+void xconfigGenerateAssignScreenAdjacencies(XConfigLayoutPtr layout)
+{
+ XConfigAdjacencyPtr adj, prev = NULL;
+
+ for (adj = layout->adjacencies; adj; adj = adj->next) {
+
+ if (prev) {
+ adj->where = CONF_ADJ_RIGHTOF;
+ adj->refscreen = xconfigStrdup(prev->screen_name);
+ } else {
+ adj->x = adj->y = -1;
+ }
+
+ /* make sure all the obsolete positioning is empty */
+
+ adj->top = NULL;
+ adj->top_name = NULL;
+ adj->bottom = NULL;
+ adj->bottom_name = NULL;
+ adj->left = NULL;
+ adj->left_name = NULL;
+ adj->right = NULL;
+ adj->right_name = NULL;
+
+ prev = adj;
+ }
+
+} /* xconfigGenerateAssignScreenAdjacencies() */
+
+
+
+/*********************************************************************/
+
+
+
+/*
+ * is_file()
+ */
+
+static int is_file(const char *filename)
+{
+ return (access(filename, F_OK) == 0);
+
+} /* is_file() */
+
+
+
+/*
+ * add_files() -
+ */
+
+static void add_files(GenerateOptions *gop, XConfigPtr config)
+{
+ config->files = xconfigAlloc(sizeof(XConfigFilesRec));
+ config->files->rgbpath = xconfigStrcat(gop->x_project_root,
+ "/lib/X11/rgb", NULL);
+} /* add_files() */
+
+
+/*
+ * add_font_path() - scan through the __font_paths[] array,
+ * temporarily chop off the ":unscaled" appendage, and check for the
+ * file "fonts.dir" in the directory. If fonts.dir exists, append the
+ * path to config->files->fontpath.
+ */
+
+static void add_font_path(GenerateOptions *gop, XConfigPtr config)
+{
+ int i, ret;
+ char *path, *p, *orig, *fonts_dir;
+
+ /*
+ * The below font path has been constructed from various examples
+ * and uses some suggests from the Font De-uglification HOWTO
+ */
+
+ static const char *__font_paths[] = {
+ "ROOT/lib/X11/fonts/local/",
+ "ROOT/lib/X11/fonts/misc/:unscaled",
+ "ROOT/lib/X11/fonts/100dpi/:unscaled",
+ "ROOT/lib/X11/fonts/75dpi/:unscaled",
+ "ROOT/lib/X11/fonts/misc/",
+ "ROOT/lib/X11/fonts/Type1/",
+ "ROOT/lib/X11/fonts/CID/",
+ "ROOT/lib/X11/fonts/Speedo/",
+ "ROOT/lib/X11/fonts/100dpi/",
+ "ROOT/lib/X11/fonts/75dpi/",
+ "ROOT/lib/X11/fonts/cyrillic/",
+ "ROOT/lib/X11/fonts/TTF/",
+ "ROOT/lib/X11/fonts/truetype/",
+ "/usr/local/share/fonts/ttfonts",
+ "/usr/share/fonts/default/Type1",
+ "/usr/lib/openoffice/share/fonts/truetype",
+ NULL
+ };
+
+ /*
+ * if a font server is running, set the font path to that
+ *
+ * XXX should we check the port the font server is using?
+ */
+#if defined(NV_SUNOS)
+ ret = system("ps -e -o fname | grep -v grep | egrep \"^xfs$\" > /dev/null");
+#elif defined(NV_BSD)
+ ret = system("ps -e -o comm | grep -v grep | egrep \"^xfs$\" > /dev/null");
+#else
+ ret = system("ps -C xfs 2>&1 > /dev/null");
+#endif
+ if (WEXITSTATUS(ret) == 0) {
+ config->files->fontpath = "unix/:7100";
+ } else {
+ for (i = 0; __font_paths[i]; i++) {
+ path = xconfigStrdup(__font_paths[i]);
+
+ /* replace ROOT with the project root */
+
+ if (strncmp(path, "ROOT", 4) == 0) {
+ p = xconfigStrcat(gop->x_project_root, path + 4, NULL);
+ free(path);
+ path = p;
+ }
+
+ /* temporarily chop off any ":unscaled" appendage */
+
+ p = strchr(path, ':');
+ if (p) *p = '\0';
+
+ /* skip this entry if the fonts.dir does not exist */
+
+ fonts_dir = xconfigStrcat(path, "/fonts.dir", NULL);
+ if (!is_file(fonts_dir)) {
+ /* does not exist */
+ free(path);
+ free(fonts_dir);
+ continue;
+ }
+ free(fonts_dir);
+
+ /* add the ":unscaled" back */
+
+ if (p) *p = ':';
+
+ /*
+ * either use this path as the fontpath, or append to the
+ * existing fontpath
+ */
+
+ if (config->files->fontpath) {
+ orig = config->files->fontpath;
+ config->files->fontpath = xconfigStrcat(orig, ",", path, NULL);
+ free(orig);
+ free(path);
+ } else {
+ config->files->fontpath = path;
+ }
+ }
+ }
+} /* add_font_path() */
+
+
+
+/*
+ * add_modules()
+ */
+
+static void add_modules(GenerateOptions *gop, XConfigPtr config)
+{
+ XConfigLoadPtr l = NULL;
+
+ config->modules = xconfigAlloc(sizeof(XConfigModuleRec));
+
+ l = xconfigAddNewLoadDirective(l, "dbe", XCONFIG_LOAD_MODULE,
+ NULL, FALSE);
+ l = xconfigAddNewLoadDirective(l, "extmod", XCONFIG_LOAD_MODULE,
+ NULL, FALSE);
+ l = xconfigAddNewLoadDirective(l, "type1", XCONFIG_LOAD_MODULE,
+ NULL, FALSE);
+#if defined(NV_SUNOS)
+ l = xconfigAddNewLoadDirective(l, "IA", XCONFIG_LOAD_MODULE,
+ NULL, FALSE);
+ l = xconfigAddNewLoadDirective(l, "Xst", XCONFIG_LOAD_MODULE,
+ NULL, FALSE);
+ l = xconfigAddNewLoadDirective(l, "bitstream", XCONFIG_LOAD_MODULE,
+ NULL, FALSE);
+#else
+ l = xconfigAddNewLoadDirective(l, "freetype", XCONFIG_LOAD_MODULE,
+ NULL, FALSE);
+#endif
+ l = xconfigAddNewLoadDirective(l, "glx", XCONFIG_LOAD_MODULE,
+ NULL, FALSE);
+
+ config->modules->loads = l;
+
+} /* add_modules() */
+
+
+
+/*
+ * add_monitor() -
+ *
+ * XXX pass EDID values into this...
+ */
+
+static XConfigMonitorPtr
+add_monitor(XConfigPtr config, int count)
+{
+ XConfigMonitorPtr monitor, m;
+ XConfigOptionPtr opt = NULL;
+
+ /* XXX need to query resman for the EDID */
+
+ monitor = xconfigAlloc(sizeof(XConfigMonitorRec));
+
+ monitor->identifier = xconfigAlloc(32);
+ snprintf(monitor->identifier, 32, MONITOR_IDENTIFIER, count);
+ monitor->vendor = "Unknown"; /* XXX */
+ monitor->modelname = "Unknown"; /* XXX */
+
+ /* XXX check EDID for freq ranges */
+
+ monitor->n_hsync = 1;
+ monitor->hsync[0].lo = 30.0;
+ monitor->hsync[0].hi = 110.0;
+
+ monitor->n_vrefresh = 1;
+ monitor->vrefresh[0].lo = 50.0;
+ monitor->vrefresh[0].hi = 150.0;
+
+ opt = xconfigAddNewOption(opt, xconfigStrdup("DPMS"), NULL);
+
+ monitor->options = opt;
+
+ /* append to the end of the monitor list */
+
+ if (!config->monitors) {
+ config->monitors = monitor;
+ } else {
+ for (m = config->monitors; m->next; m = m->next);
+ m->next = monitor;
+ }
+
+ return monitor;
+
+} /* add_monitor() */
+
+
+
+/*
+ * add_device()
+ */
+
+static XConfigDevicePtr
+add_device(XConfigPtr config, int bus, int slot, char *boardname, int count)
+{
+ XConfigDevicePtr device, d;
+
+ device = xconfigAlloc(sizeof(XConfigDeviceRec));
+
+ device->identifier = xconfigAlloc(32);
+ snprintf(device->identifier, 32, DEVICE_IDENTIFIER, count);
+ device->driver = xconfigStrdup("nvidia");
+ device->vendor = xconfigStrdup("NVIDIA Corporation");
+
+ if (bus != -1 && slot != -1) {
+ device->busid = xconfigAlloc(32);
+ snprintf(device->busid, 32, "PCI:%d:%d:0", bus, slot);
+ }
+
+ if (boardname) device->board = xconfigStrdup(boardname);
+
+ device->chipid = -1;
+ device->chiprev = -1;
+ device->irq = -1;
+ device->screen = -1;
+
+ /* append to the end of the device list */
+
+ if (!config->devices) {
+ config->devices = device;
+ } else {
+ for (d = config->devices; d->next; d = d->next);
+ d->next = device;
+ }
+
+ return device;
+
+} /* add_device() */
+
+
+
+static XConfigDisplayPtr add_display(int depth)
+{
+ XConfigDisplayPtr display;
+ XConfigModePtr mode = NULL;
+
+ mode = xconfigAddMode(mode, "640x480");
+ mode = xconfigAddMode(mode, "800x600");
+ mode = xconfigAddMode(mode, "1024x768");
+ mode = xconfigAddMode(mode, "1280x1024");
+ mode = xconfigAddMode(mode, "1600x1200");
+
+ display = xconfigAlloc(sizeof(XConfigDisplayRec));
+ display->depth = depth;
+ display->modes = mode;
+ display->frameX0 = -1;
+ display->frameY0 = -1;
+ display->black.red = -1;
+ display->white.red = -1;
+
+ return display;
+}
+
+
+
+/*
+ * add_layout() - add a layout section to the XConfigPtr
+ */
+
+static void add_layout(GenerateOptions *gop, XConfigPtr config)
+{
+ XConfigLayoutPtr layout;
+ XConfigAdjacencyPtr adj;
+ XConfigScreenPtr screen;
+
+ /* assume 1 X screen */
+
+ screen = xconfigGenerateAddScreen(config, -1, -1, NULL, 0);
+
+ /* create layout */
+
+ layout = xconfigAlloc(sizeof(XConfigLayoutRec));
+
+ layout->identifier = "Layout0";
+
+ adj = xconfigAlloc(sizeof(XConfigAdjacencyRec));
+
+ adj->scrnum = 0;
+ adj->screen = screen;
+ adj->screen_name = xconfigStrdup(screen->identifier);
+
+ layout->adjacencies = adj;
+
+ xconfigGenerateAssignScreenAdjacencies(layout);
+
+ add_inputref(config, layout, MOUSE_IDENTIFER, "CorePointer");
+ add_inputref(config, layout, KEYBOARD_IDENTIFER, "CoreKeyboard");
+
+ layout->next = config->layouts;
+ config->layouts = layout;
+
+} /* add_layout() */
+
+
+
+/*
+ * add_inputref() - add a new XConfigInputrefPtr to the given layout
+ */
+
+static void add_inputref(XConfigPtr config, XConfigLayoutPtr layout,
+ char *name, char *coreKeyword)
+{
+ XConfigInputrefPtr inputRef;
+
+ inputRef = xconfigAlloc(sizeof(XConfigInputrefRec));
+ inputRef->input_name = name;
+ inputRef->input = xconfigFindInput(inputRef->input_name, config->inputs);
+ inputRef->options =
+ xconfigAddNewOption(NULL, xconfigStrdup(coreKeyword), NULL);
+ inputRef->next = layout->inputs;
+ layout->inputs = inputRef;
+
+} /* add_inputref() */
+
+
+
+/*********************************************************************/
+
+/*
+ * Mouse detection
+ */
+
+
+typedef struct {
+ char *shortname; /* commandline name */
+ char *name; /* mouse name */
+ char *gpmproto; /* protocol used by gpm */
+ char *Xproto; /* XFree86 Protocol */
+ char *device; /* /dev/ file */
+ int emulate3; /* Emulate3Buttons */
+} MouseEntry;
+
+
+/*
+ * This table is based on data contained in
+ * /usr/lib/python2.2/site-packages/rhpl/mouse.py on Red Hat Fedora
+ * core 1. That file contains the following copyright:
+ *
+ *
+ *
+ * mouse.py: mouse configuration data
+ *
+ * Copyright 1999-2002 Red Hat, Inc.
+ *
+ * This software may be freely redistributed under the terms of the GNU
+ * library public license.
+ *
+ * You should have received a copy of the GNU Library Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+static const MouseEntry __mice[] = {
+ /* shortname name gpm protocol X protocol device emulate3 */
+ { "alpsps/2", "ALPS - GlidePoint (PS/2)", "ps/2", "GlidePointPS/2", "psaux", TRUE },
+ { "ascii", "ASCII - MieMouse (serial)", "ms3", "IntelliMouse", "ttyS", FALSE },
+ { "asciips/2", "ASCII - MieMouse (PS/2)", "ps/2", "NetMousePS/2", "psaux", TRUE },
+ { "atibm", "ATI - Bus Mouse", "Busmouse", "BusMouse", "atibm", TRUE },
+ { "generic", "Generic - 2 Button Mouse (serial)", "Microsoft", "Microsoft", "ttyS", TRUE },
+ { "generic3", "Generic - 3 Button Mouse (serial)", "Microsoft", "Microsoft", "ttyS", FALSE },
+ { "genericps/2", "Generic - 2 Button Mouse (PS/2)", "ps/2", "PS/2", "psaux", TRUE },
+ { "generic3ps/2", "Generic - 3 Button Mouse (PS/2)", "ps/2", "PS/2", "psaux", FALSE },
+ { "genericwheelps/2", "Generic - Wheel Mouse (PS/2)", "imps2", "IMPS/2", "psaux", FALSE },
+ { "genericusb", "Generic - 2 Button Mouse (USB)", "imps2", "IMPS/2", "input/mice", TRUE },
+ { "generic3usb", "Generic - 3 Button Mouse (USB)", "imps2", "IMPS/2", "input/mice", FALSE },
+ { "genericwheelusb", "Generic - Wheel Mouse (USB)", "imps2", "IMPS/2", "input/mice", FALSE },
+ { "geniusnm", "Genius - NetMouse (serial)", "ms3", "IntelliMouse", "ttyS", TRUE },
+ { "geniusnmps/2", "Genius - NetMouse (PS/2)", "netmouse", "NetMousePS/2", "psaux", TRUE },
+ { "geniusprops/2", "Genius - NetMouse Pro (PS/2)", "netmouse", "NetMousePS/2", "psaux", TRUE },
+ { "geniusscrollps/2", "Genius - NetScroll (PS/2)", "netmouse", "NetScrollPS/2", "psaux", TRUE },
+ { "geniusscrollps/2+", "Genius - NetScroll+ (PS/2)", "netmouse", "NetMousePS/2", "psaux", FALSE },
+ { "thinking", "Kensington - Thinking Mouse (serial)", "Microsoft", "ThinkingMouse", "ttyS", TRUE },
+ { "thinkingps/2", "Kensington - Thinking Mouse (PS/2)", "ps/2", "ThinkingMousePS/2", "psaux", TRUE },
+ { "logitech", "Logitech - C7 Mouse (serial, old C7 type)", "Logitech", "Logitech", "ttyS", FALSE },
+ { "logitechcc", "Logitech - CC Series (serial)", "logim", "MouseMan", "ttyS", FALSE },
+ { "logibm", "Logitech - Bus Mouse", "Busmouse", "BusMouse", "logibm", FALSE },
+ { "logimman", "Logitech - MouseMan/FirstMouse (serial)", "MouseMan", "MouseMan", "ttyS", FALSE },
+ { "logimmanps/2", "Logitech - MouseMan/FirstMouse (PS/2)", "ps/2", "PS/2", "psaux", FALSE },
+ { "logimman+", "Logitech - MouseMan+/FirstMouse+ (serial)", "pnp", "IntelliMouse", "ttyS", FALSE },
+ { "logimman+ps/2", "Logitech - MouseMan+/FirstMouse+ (PS/2)", "ps/2", "MouseManPlusPS/2", "psaux", FALSE },
+ { "logimmusb", "Logitech - MouseMan Wheel (USB)", "ps/2", "IMPS/2", "input/mice", FALSE },
+ { "logimmusboptical", "Logitech - Cordless Optical Mouse (USB)", "ps/2", "IMPS/2", "input/mice", FALSE },
+ { "microsoft", "Microsoft - Compatible Mouse (serial)", "Microsoft", "Microsoft", "ttyS", TRUE },
+ { "msnew", "Microsoft - Rev 2.1A or higher (serial)", "pnp", "Auto", "ttyS", TRUE },
+ { "msintelli", "Microsoft - IntelliMouse (serial)", "ms3", "IntelliMouse", "ttyS", FALSE },
+ { "msintellips/2", "Microsoft - IntelliMouse (PS/2)", "imps2", "IMPS/2", "psaux", FALSE },
+ { "msintelliusb", "Microsoft - IntelliMouse (USB)", "ps/2", "IMPS/2", "input/mice", FALSE },
+ { "msintelliusboptical","Microsoft - IntelliMouse Optical (USB)", "ps/2", "IMPS/2", "input/mice", FALSE },
+ { "msbm", "Microsoft - Bus Mouse", "Busmouse", "BusMouse", "inportbm", TRUE },
+ { "mousesystems", "Mouse Systems - Mouse (serial)", "MouseSystems", "MouseSystems", "ttyS", TRUE },
+ { "mmseries", "MM - Series (serial)", "MMSeries", "MMSeries", "ttyS", TRUE },
+ { "mmhittab", "MM - HitTablet (serial)", "MMHitTab", "MMHittab", "ttyS", TRUE },
+ { "sun", "Sun - Mouse", "sun", "sun", "sunmouse", FALSE },
+ { NULL, NULL, NULL, NULL, NULL, FALSE },
+};
+
+
+
+/*
+ * This table maps between the mouse protocol name used for gpm and
+ * for the X server "protocol" mouse option.
+ */
+
+typedef struct {
+ char *gpmproto;
+ char *Xproto;
+} ProtocolEntry;
+
+static const ProtocolEntry __protocols[] = {
+ /* gpm protocol X protocol */
+ { "ms3", "IntelliMouse" },
+ { "Busmouse", "BusMouse" },
+ { "Microsoft", "Microsoft" },
+ { "imps2", "IMPS/2" },
+ { "netmouse", "NetMousePS/2" },
+ { "Logitech", "Logitech" },
+ { "logim", "MouseMan" },
+ { "MouseMan", "MouseMan" },
+ { "ps/2", "PS/2" },
+ { "pnp", "Auto" },
+ { "MouseSystems", "MouseSystems" },
+ { "MMSeries", "MMSeries" },
+ { "MMHitTab", "MMHittab" },
+ { "sun", "sun" },
+ { NULL, NULL },
+};
+
+
+/*
+ * gpm_proto_to_X_proto() - map from gpm mouse protocol to X mouse
+ * protocol
+ */
+
+static char* gpm_proto_to_X_proto(const char *gpm)
+{
+ int i;
+
+ for (i = 0; __protocols[i].gpmproto; i++) {
+ if (strcmp(gpm, __protocols[i].gpmproto) == 0) {
+ return __protocols[i].Xproto;
+ }
+ }
+ return NULL;
+
+} /* gpm_proto_to_X_proto() */
+
+
+
+/*
+ * find_mouse_entry() - scan the __mice[] table for the entry that
+ * corresponds to the specified value; return a pointer to the
+ * matching entry in the table, if any.
+ */
+
+static const MouseEntry *find_mouse_entry(char *value)
+{
+ int i;
+
+ if (!value) return NULL;
+
+ for (i = 0; __mice[i].name; i++) {
+ if (strcmp(value, __mice[i].shortname) == 0) {
+ return &__mice[i];
+ }
+ }
+ return NULL;
+
+} /* find_mouse_entry() */
+
+
+
+/*
+ * find_closest_mouse_entry() - scan the __mice[] table for the entry that
+ * matches all of the specified values; any of the values can be NULL,
+ * in which case we do not use them as part of the comparison. Note
+ * that device is compared case sensitive, proto is compared case
+ * insensitive, and emulate3 is just a boolean.
+ */
+
+static const MouseEntry *find_closest_mouse_entry(const char *device,
+ const char *proto,
+ const char *emulate3_str)
+{
+ int i;
+ int emulate3 = FALSE;
+
+ /*
+ * translate the emulate3 string into a boolean we can use below
+ * for comparison
+ */
+
+ if ((emulate3_str) &&
+ ((strcasecmp(emulate3_str, "yes") == 0) ||
+ (strcasecmp(emulate3_str, "true") == 0) ||
+ (strcasecmp(emulate3_str, "1") == 0))) {
+ emulate3 = TRUE;
+ }
+
+ /*
+ * skip the "/dev/" part of the device filename
+ */
+
+ if (device && (strncmp(device, "/dev/", 5) == 0)) {
+ device += 5; /* strlen("/dev/") */
+ }
+
+ for (i = 0; __mice[i].name; i++) {
+ if ((device) && (strcmp(device, __mice[i].device) != 0)) continue;
+ if ((proto) && (strcasecmp(proto, __mice[i].Xproto)) != 0) continue;
+ if ((emulate3_str) && (emulate3 != __mice[i].emulate3)) continue;
+ return &__mice[i];
+ }
+
+ return NULL;
+
+} /* find_closest_mouse_entry() */
+
+
+
+/*
+ * find_config_entry() - scan the specified filename for the specified
+ * keyword; return the value that the keyword is assigned to, or NULL
+ * if any error occurs.
+ */
+
+static char *find_config_entry(const char *filename, const char *keyword)
+{
+ int fd = -1;
+ char *data = NULL;
+ char *value = NULL;
+ char *tmp, *start, *c, *end;
+ struct stat stat_buf;
+ size_t len;
+
+ if ((fd = open(filename, O_RDONLY)) == -1) goto done;
+
+ if (fstat(fd, &stat_buf) == -1) goto done;
+
+ if ((data = mmap(0, stat_buf.st_size, PROT_READ, MAP_SHARED,
+ fd, 0)) == (void *) -1) goto done;
+
+ /* search for the keyword */
+
+ start = data;
+
+ while (TRUE) {
+ tmp = strstr(start, keyword);
+ if (!tmp) goto done;
+
+ /*
+ * make sure this line is not commented out: search back from
+ * tmp: if we hit a "#" before a newline, then this line is
+ * commented out and we should search again
+ */
+
+ c = tmp;
+ while ((c >= start) && (*c != '\n') && (*c != '#')) c--;
+
+ if (*c == '#') {
+ /* keyword was commented out... search again */
+ start = tmp+1;
+ } else {
+ /* keyword is not commented out */
+ break;
+ }
+ }
+
+ start = tmp + strlen(keyword);
+ end = strchr(start, '\n');
+ if (!end) goto done;
+
+ /* there must be something between the start and the end */
+
+ if (start == end) goto done;
+
+ /* take what is between as the value */
+
+ len = end - start;
+ value = xconfigAlloc(len + 1);
+ strncpy(value, start, len);
+ value[len] = '\0';
+
+ /* if the first and last characters are quotation marks, remove them */
+
+ if ((value[0] == '\"') && (value[len-1] == '\"')) {
+ tmp = xconfigAlloc(len - 1);
+ strncpy(tmp, value + 1, len - 2);
+ tmp[len-2] = '\0';
+ free(value);
+ value = tmp;
+ }
+
+ done:
+
+ if (data) munmap(data, stat_buf.st_size);
+ if (fd != -1) close(fd);
+
+ return value;
+
+} /* find_config_entry() */
+
+
+
+/*
+ * xconfigGeneratePrintPossibleMice() - print the mouse table to stdout
+ */
+
+void xconfigGeneratePrintPossibleMice(void)
+{
+ int i;
+
+ printf("%-25s%-35s\n\n", "Short Name", "Name");
+
+ for (i = 0; __mice[i].name; i++) {
+ printf("%-25s%-35s\n", __mice[i].shortname, __mice[i].name);
+ }
+
+ printf("\n");
+
+} /* xconfigGeneratePrintPossibleMice() */
+
+
+
+/*
+ * add_mouse() - determine the mouse type, and then add an
+ * XConfigInputRec with the appropriate options.
+ *
+ * - if the user specified on the commandline, use that
+ *
+ * - if /etc/sysconfig/mouse exists and contains valid data, use
+ * that
+ *
+ * - if /etc/conf.d/gpm exists and contains valid data, use that
+ *
+ * - infer the settings from the commandline options gpm is using XXX?
+ *
+ * - default to "auto" on /dev/mouse
+ */
+
+static int add_mouse(GenerateOptions *gop, XConfigPtr config)
+{
+ const MouseEntry *entry = NULL;
+ XConfigInputPtr input;
+ XConfigOptionPtr opt = NULL;
+ char *device_path, *comment = "default";
+
+ /* if the user specified on the commandline, use that */
+
+ if (gop->mouse) {
+ entry = find_mouse_entry(gop->mouse);
+ if (entry) {
+ comment = "commandline input";
+ } else {
+ xconfigErrorMsg(WarnMsg, "Unable to find mouse \"%s\".",
+ gop->mouse);
+ }
+ }
+
+ /*
+ * if /etc/sysconfig/mouse exists, and contains valid data, use
+ * that
+ */
+
+ if (!entry) {
+ char *protocol, *device, *emulate3;
+
+ device = find_config_entry("/etc/sysconfig/mouse", "DEVICE=");
+ protocol = find_config_entry("/etc/sysconfig/mouse", "XMOUSETYPE=");
+ emulate3 = find_config_entry("/etc/sysconfig/mouse", "XEMU3=");
+
+ if (device || protocol || emulate3) {
+ entry = find_closest_mouse_entry(device, protocol, emulate3);
+ if (entry) {
+ comment = "data in \"/etc/sysconfig/mouse\"";
+ }
+ }
+ }
+
+ /* if /etc/conf.d/gpm exists and contains valid data, use that */
+
+ if (!entry) {
+ char *protocol, *device;
+
+ protocol = find_config_entry("/etc/conf.d/gpm", "MOUSE=");
+ device = find_config_entry("/etc/conf.d/gpm", "MOUSEDEV=");
+
+ if (protocol && device) {
+ MouseEntry *e = xconfigAlloc(sizeof(MouseEntry));
+ e->shortname = "custom";
+ e->name = "inferred from /etc/conf.d/gpm";
+ e->gpmproto = protocol;
+ e->Xproto = gpm_proto_to_X_proto(protocol);
+ e->device = device + strlen("/dev/");
+ e->emulate3 = FALSE; // XXX?
+ entry = e;
+ comment = "data in \"/etc/conf.d/gpm\"";
+ }
+ }
+
+ /*
+ * XXX we could try to infer the settings from the commandline
+ * options gpm is using
+ */
+
+ if (!entry) {
+ /* XXX implement me */
+ }
+
+ /* at this point, we must have a mouse entry */
+
+ if (!entry) {
+ MouseEntry *e = xconfigAlloc(sizeof(MouseEntry));
+ e->Xproto = "auto";
+
+ if (access("/dev/psaux", F_OK) == 0) {
+ e->device = "psaux";
+ } else if (access("/dev/input/mice", F_OK) == 0) {
+ e->device = "input/mice";
+ } else {
+ e->device = "mouse";
+ }
+
+ e->emulate3 = FALSE;
+ entry = e;
+ }
+
+ /* add a new mouse input section */
+
+ input = xconfigAlloc(sizeof(XConfigInputRec));
+
+ input->comment = xconfigStrcat(" # generated from ",
+ comment, "\n", NULL);
+ input->identifier = "Mouse0";
+ input->driver = "mouse";
+
+ device_path = xconfigStrcat("/dev/", entry->device, NULL);
+
+ opt = xconfigAddNewOption(opt, xconfigStrdup("Protocol"), entry->Xproto);
+ opt = xconfigAddNewOption(opt, xconfigStrdup("Device"), device_path);
+ opt = xconfigAddNewOption(opt, xconfigStrdup("Emulate3Buttons"),
+ entry->emulate3 ?
+ xconfigStrdup("yes") : xconfigStrdup("no"));
+
+ /*
+ * This will make wheel mice work, and non-wheel mice should
+ * ignore ZAxisMapping
+ */
+
+ opt = xconfigAddNewOption(opt, "ZAxisMapping", "4 5");
+
+ input->options = opt;
+
+ input->next = config->inputs;
+ config->inputs = input;
+
+ return TRUE;
+
+} /* add_mouse() */
+
+
+
+
+
+/*********************************************************************/
+
+/*
+ * keyboard detection
+ */
+
+typedef struct {
+ char *keytable;
+ char *name;
+ char *layout; /* XkbLayout */
+ char *model; /* XkbModel */
+ char *variant; /* XkbVariant */
+ char *options; /* XkbOptions */
+} KeyboardEntry;
+
+
+/*
+ * This table is based on data contained in
+ * /usr/lib/python2.2/site-packages/rhpl/keyboard_models.py on Red Hat
+ * Fedora core 1. That file contains the following copyright:
+ *
+ *
+ * keyboard_models.py - keyboard model list
+ *
+ * Brent Fox <bfox@redhat.com>
+ * Mike Fulbright <msf@redhat.com>
+ * Jeremy Katz <katzj@redhat.com>
+ *
+ * Copyright 2002 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+static const KeyboardEntry __keyboards[] = {
+
+ /* keytable name layout model variant options */
+
+ { "be-latin1", "Belgian (be-latin1)", "be", "pc105", NULL, NULL },
+ { "bg", "Bulgarian", "bg,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
+ { "br-abnt2", "Brazilian (ABNT2)", "br", "abnt2", NULL, NULL },
+ { "cf", "French Canadian", "ca_enhanced", "pc105", NULL, NULL },
+ { "croat", "Croatian", "hr", "pc105", NULL, NULL },
+ { "cz-us-qwertz", "Czechoslovakian (qwertz)", "cz,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
+ { "cz-lat2", "Czechoslovakian", "cz_qwerty", "pc105", NULL, NULL },
+ { "de", "German", "de", "pc105", NULL, NULL },
+ { "de-latin1", "German (latin1)", "de", "pc105", NULL, NULL },
+ { "de-latin1-nodeadkeys", "German (latin1 w/ no deadkeys)", "de", "pc105", "nodeadkeys", NULL },
+ { "dvorak", "Dvorak", "dvorak", "pc105", NULL, NULL },
+ { "dk", "Danish", "dk", "pc105", NULL, NULL },
+ { "dk-latin1", "Danish (latin1)", "dk", "pc105", NULL, NULL },
+ { "es", "Spanish", "es", "pc105", NULL, NULL },
+ { "et", "Estonian", "ee", "pc105", NULL, NULL },
+ { "fi", "Finnish", "fi", "pc105", NULL, NULL },
+ { "fi-latin1", "Finnish (latin1)", "fi", "pc105", NULL, NULL },
+ { "fr", "French", "fr", "pc105", NULL, NULL },
+ { "fr-latin0", "French (latin0)", "fr", "pc105", NULL, NULL },
+ { "fr-latin1", "French (latin1)", "fr", "pc105", NULL, NULL },
+ { "fr-pc", "French (pc)", "fr", "pc105", NULL, NULL },
+ { "fr_CH", "Swiss French", "fr_CH", "pc105", NULL, NULL },
+ { "fr_CH-latin1", "Swiss French (latin1)", "fr_CH", "pc105", NULL, NULL },
+ { "gr", "Greek", "us,el", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
+ { "hu", "Hungarian", "hu", "pc105", NULL, NULL },
+ { "hu101", "Hungarian (101 key)", "hu", "pc105", NULL, NULL },
+ { "is-latin1", "Icelandic", "is", "pc105", NULL, NULL },
+ { "it", "Italian", "it", "pc105", NULL, NULL },
+ { "it-ibm", "Italian (IBM)", "it", "pc105", NULL, NULL },
+ { "it2", "Italian (it2)", "it", "pc105", NULL, NULL },
+ { "jp106", "Japanese", "jp", "jp106", NULL, NULL },
+ { "la-latin1", "Latin American", "la", "pc105", NULL, NULL },
+ { "mk-utf", "Macedonian", "mk,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
+ { "no", "Norwegian", "no", "pc105", NULL, NULL },
+ { "pl", "Polish", "pl", "pc105", NULL, NULL },
+ { "pt-latin1", "Portuguese", "pt", "pc105", NULL, NULL },
+ { "ro_win", "Romanian", "ro", "pc105", NULL, NULL },
+ { "ru", "Russian", "ru,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
+ { "ru-cp1251", "Russian (cp1251)", "ru,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
+ { "ru-ms", "Russian (Microsoft)", "ru,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
+ { "ru1", "Russian (ru1)", "ru,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
+ { "ru2", "Russian (ru2)", "ru,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
+ { "ru_win", "Russian (win)", "ru,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
+ { "speakup", "Speakup", "us", "pc105", NULL, NULL },
+ { "speakup-lt", "Speakup (laptop)", "us", "pc105", NULL, NULL },
+ { "sv-latin1", "Swedish", "se", "pc105", NULL, NULL },
+ { "sg", "Swiss German", "de_CH", "pc105", NULL, NULL },
+ { "sg-latin1", "Swiss German (latin1)", "de_CH", "pc105", NULL, NULL },
+ { "sk-qwerty", "Slovakian", "sk_qwerty", "pc105", NULL, NULL },
+ { "slovene", "Slovenian", "si", "pc105", NULL, NULL },
+ { "trq", "Turkish", "tr", "pc105", NULL, NULL },
+ { "uk", "United Kingdom", "gb", "pc105", NULL, NULL },
+ { "ua", "Ukrainian", "ua,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
+ { "us-acentos", "U.S. International", "us_intl", "pc105", NULL, NULL },
+ { "us", "U.S. English", "us", "pc105", NULL, NULL },
+ { NULL, NULL, NULL, NULL, NULL, NULL },
+};
+
+
+
+/*
+ * find_keyboard_entry() - scan the __keyboards[] table for the entry that
+ * corresponds to the specified value; return a pointer to the
+ * matching entry in the table, if any.
+ */
+
+static const KeyboardEntry *find_keyboard_entry(char *value)
+{
+ int i;
+
+ if (!value) return NULL;
+
+ for (i = 0; __keyboards[i].name; i++) {
+ if (strcmp(value, __keyboards[i].keytable) == 0) {
+ return &__keyboards[i];
+ }
+ }
+ return NULL;
+
+} /* find_keyboard_entry() */
+
+
+
+/*
+ * xconfigGeneratePrintPossibleKeyboards() - print the keyboard table
+ */
+
+void xconfigGeneratePrintPossibleKeyboards(void)
+{
+ int i;
+
+ printf("%-25s%-35s\n\n", "Short Name", "Name");
+
+ for (i = 0; __keyboards[i].name; i++) {
+ printf("%-25s%-35s\n", __keyboards[i].keytable, __keyboards[i].name);
+ }
+
+ printf("\n");
+
+} /* xconfigGeneratePrintPossibleKeyboards() */
+
+
+
+/*
+ * add_keyboard() - determine the keyboard type, and then add an
+ * XConfigInputRec with the appropriate options.
+ *
+ * How to detect the keyboard:
+ *
+ * - if the user specified on the command line, use that
+ *
+ * - if /etc/sysconfig/keyboard exists, and contains a valid
+ * KEYTABLE entry, use that
+ */
+
+static int add_keyboard(GenerateOptions *gop, XConfigPtr config)
+{
+ char *value, *comment = "default";
+ const KeyboardEntry *entry = NULL;
+
+ XConfigInputPtr input;
+ XConfigOptionPtr opt = NULL;
+
+ /*
+ * if the user specified on the command line, use that
+ */
+
+ if (gop->keyboard) {
+ entry = find_keyboard_entry(gop->keyboard);
+ if (entry) {
+ comment = "commandline input";
+ } else {
+ xconfigErrorMsg(WarnMsg, "Unable to find keyboard \"%s\".",
+ gop->keyboard);
+ }
+ }
+
+ /*
+ * if /etc/sysconfig/keyboard exists, and contains a valid
+ * KEYTABLE entry, use that
+ */
+
+ if (!entry) {
+ value = find_config_entry("/etc/sysconfig/keyboard", "KEYTABLE=");
+ entry = find_keyboard_entry(value);
+ if (value) {
+ free(value);
+ }
+ if (entry) {
+ comment = "data in \"/etc/sysconfig/keyboard\"";
+ }
+ }
+
+ /* add a new keyboard input section */
+
+ input = xconfigAlloc(sizeof(XConfigInputRec));
+
+ input->comment = xconfigStrcat(" # generated from ",
+ comment, "\n", NULL);
+ input->identifier = "Keyboard0";
+
+ /*
+ * determine which keyboard driver should be used (either "kbd" or
+ * "keyboard"); if the user specified a keyboard driver use that;
+ * if 'ROOT/lib/modules/input/kbd_drv.(o|so)' exists, use "kbd";
+ * otherwise, use "keyboard".
+ * On Solaris, use the default "keyboard"
+ */
+
+ if (gop->keyboard_driver) {
+ input->driver = gop->keyboard_driver;
+ } else {
+#if defined(NV_SUNOS) || defined(NV_BSD)
+ input->driver = "keyboard";
+#else
+ if (gop->xserver == X_IS_XORG) {
+ input->driver = "kbd";
+ } else {
+ input->driver = "keyboard";
+ }
+#endif
+ }
+
+ /*
+ * set additional keyboard options, based on the Keyboard table
+ * entry we found above
+ */
+
+ if (entry && entry->layout)
+ opt = xconfigAddNewOption(opt,
+ xconfigStrdup("XkbLayout"), entry->layout);
+ if (entry && entry->model)
+ opt = xconfigAddNewOption(opt,
+ xconfigStrdup("XkbModel"), entry->model);
+ if (entry && entry->variant)
+ opt = xconfigAddNewOption(opt,
+ xconfigStrdup("XkbVariant"), entry->variant);
+ if (entry && entry->options)
+ opt = xconfigAddNewOption(opt,
+ xconfigStrdup("XkbOptions"), entry->options);
+
+ input->options = opt;
+
+ input->next = config->inputs;
+ config->inputs = input;
+
+ return TRUE;
+
+} /* add_keyboard() */
diff --git a/XF86Config-parser/Input.c b/XF86Config-parser/Input.c
new file mode 100644
index 0000000..b368ba7
--- /dev/null
+++ b/XF86Config-parser/Input.c
@@ -0,0 +1,395 @@
+/*
+ *
+ * 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).
+ */
+
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+extern LexRec val;
+
+static
+XConfigSymTabRec InputTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {IDENTIFIER, "identifier"},
+ {OPTION, "option"},
+ {DRIVER, "driver"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeInputList
+
+XConfigInputPtr
+xconfigParseInputSection (void)
+{
+ int has_ident = FALSE;
+ int token;
+ PARSE_PROLOGUE (XConfigInputPtr, XConfigInputRec)
+
+ while ((token = xconfigGetToken (InputTab)) != ENDSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case IDENTIFIER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Identifier");
+ if (has_ident == TRUE)
+ Error (MULTIPLE_MSG, "Identifier");
+ ptr->identifier = val.str;
+ has_ident = TRUE;
+ break;
+ case DRIVER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Driver");
+ ptr->driver = val.str;
+ 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;
+ }
+ }
+
+ if (!has_ident)
+ Error (NO_IDENT_MSG, NULL);
+
+#ifdef DEBUG
+ xconfigErrorMsg(DebugMsg, "InputDevice section parsed\n");
+#endif
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+void
+xconfigPrintInputSection (FILE * cf, XConfigInputPtr ptr)
+{
+ while (ptr)
+ {
+ fprintf (cf, "Section \"InputDevice\"\n");
+ if (ptr->comment)
+ fprintf (cf, "%s", ptr->comment);
+ if (ptr->identifier)
+ fprintf (cf, " Identifier \"%s\"\n", ptr->identifier);
+ if (ptr->driver)
+ fprintf (cf, " Driver \"%s\"\n", ptr->driver);
+ xconfigPrintOptionList(cf, ptr->options, 1);
+ fprintf (cf, "EndSection\n\n");
+ ptr = ptr->next;
+ }
+}
+
+void
+xconfigFreeInputList (XConfigInputPtr ptr)
+{
+ XConfigInputPtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->identifier);
+ TEST_FREE (ptr->driver);
+ TEST_FREE (ptr->comment);
+ xconfigOptionListFree (ptr->options);
+
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+int
+xconfigValidateInput (XConfigPtr p)
+{
+ XConfigInputPtr input = p->inputs;
+
+#if 0 /* Enable this later */
+ if (!input) {
+ xconfigErrorMsg(ValidationErrorMsg, "At least one InputDevice section "
+ "is required.");
+ return (FALSE);
+ }
+#endif
+
+ while (input) {
+ if (!input->driver) {
+ xconfigErrorMsg(ValidationErrorMsg, UNDEFINED_INPUTDRIVER_MSG,
+ input->identifier);
+ return (FALSE);
+ }
+ input = input->next;
+ }
+ return (TRUE);
+}
+
+XConfigInputPtr
+xconfigFindInput (const char *ident, XConfigInputPtr p)
+{
+ while (p)
+ {
+ if (xconfigNameCompare (ident, p->identifier) == 0)
+ return (p);
+
+ p = p->next;
+ }
+ return (NULL);
+}
+
+XConfigInputPtr
+xconfigFindInputByDriver (const char *driver, XConfigInputPtr p)
+{
+ while (p)
+ {
+ if (xconfigNameCompare (driver, p->driver) == 0)
+ return (p);
+
+ p = p->next;
+ }
+ return (NULL);
+}
+
+
+
+static int getCoreInputDevice(XConfigPtr config,
+ XConfigLayoutPtr layout,
+ const char *coreKeyword,
+ const char *implicitDriverName,
+ const char *defaultDriver0,
+ const char *defaultDriver1,
+ const char *foundMsg0,
+ const char *foundMsg1)
+{
+ XConfigInputPtr input, core = NULL;
+ XConfigInputrefPtr inputRef;
+ int found;
+ const char *found_msg = NULL;
+
+ /*
+ * First check if the core input device has been specified in the
+ * active ServerLayout. If more than one is specified, remove the
+ * core attribute from the later ones.
+ */
+
+ for (inputRef = layout->inputs; inputRef; inputRef = inputRef->next) {
+ XConfigOptionPtr opt1 = NULL, opt2 = NULL;
+
+ input = inputRef->input;
+
+ opt1 = xconfigFindOption(input->options, coreKeyword);
+ opt2 = xconfigFindOption(inputRef->options, coreKeyword);
+
+ if (opt1 || opt2) {
+ if (!core) {
+ core = input;
+ } else {
+ if (opt1) input->options =
+ xconfigRemoveOption(input->options, opt1);
+ if (opt2) inputRef->options =
+ xconfigRemoveOption(inputRef->options, opt2);
+ xconfigErrorMsg(WarnMsg, "Duplicate %s devices; removing %s "
+ "attribute from \"%s\"\n",
+ coreKeyword, coreKeyword, input->identifier);
+ }
+ }
+ }
+
+ /*
+ * XXX XFree86 allows the commandline to override the core input
+ * devices; let's not bother with that, here.
+ */
+
+ /*
+ * if we didn't find a core input device above in the
+ * serverLayout, scan through the config's entire input list and
+ * pick the first one with the coreKeyword.
+ */
+
+ if (!core) {
+ for (input = config->inputs; input; input = input->next) {
+ if (xconfigFindOption(input->options, coreKeyword)) {
+ core = input;
+ found_msg = foundMsg0;
+ break;
+ }
+ }
+ }
+
+ /*
+ * if we didn't find a core input device above, then select the
+ * first input with the correct driver
+ */
+
+ if (!core) {
+ input = xconfigFindInput(implicitDriverName, config->inputs);
+ if (!input && defaultDriver0) {
+ input = xconfigFindInputByDriver(defaultDriver0, config->inputs);
+ }
+ if (!input && defaultDriver1) {
+ input = xconfigFindInputByDriver(defaultDriver0, config->inputs);
+ }
+ if (input) {
+ core = input;
+ found_msg = foundMsg1;
+ }
+ }
+
+ /*
+ * if we *still* can't find a core input device, print a warning
+ * message and give up; hopefully the X server's builtin config
+ * will do.
+ */
+
+ if (!core) {
+ xconfigErrorMsg(WarnMsg, "Unable to determine %s; will rely on X "
+ "server's built-in default configuration.",
+ coreKeyword);
+
+ /* don't return FALSE here -- we don't want nvidia-xconfig to fail */
+
+ return TRUE;
+ }
+
+
+ /*
+ * make sure the core input device is in the layout's input list
+ */
+
+ found = FALSE;
+ for (inputRef = layout->inputs; inputRef; inputRef = inputRef->next) {
+ if (inputRef->input == core) {
+ found = TRUE;
+ break;
+ }
+ }
+ if (!found) {
+ inputRef = calloc(1, sizeof(XConfigInputrefRec));
+ inputRef->input = core;
+ inputRef->input_name = strdup(core->identifier);
+ inputRef->next = layout->inputs;
+ layout->inputs = inputRef;
+ }
+
+ /*
+ * make sure the core input device has the core keyword set
+ */
+
+ for (inputRef = layout->inputs; inputRef; inputRef = inputRef->next) {
+ if (inputRef->input == core) {
+ XConfigOptionPtr opt1 = NULL, opt2 = NULL;
+
+ opt1 = xconfigFindOption(inputRef->input->options, coreKeyword);
+ opt2 = xconfigFindOption(inputRef->options, coreKeyword);
+
+ if (!opt1 && !opt2) {
+ inputRef->options = xconfigAddNewOption(inputRef->options,
+ strdup(coreKeyword),
+ NULL);
+ }
+ break;
+ }
+ }
+
+ if (found_msg) {
+ xconfigErrorMsg(WarnMsg, "The %s device was not specified explicitly "
+ "in the layout; using the %s.\n", coreKeyword, found_msg);
+ }
+
+ return TRUE;
+}
+
+
+
+/*
+ * xconfigCheckCoreInputDevices() - check that the specified layout has a
+ * corePointer and coreKeyboard. If it does not have them, they will
+ * be added from the current list of input devices.
+ */
+
+int xconfigCheckCoreInputDevices(XConfigPtr config,
+ XConfigLayoutPtr layout)
+{
+ int ret;
+
+ ret = getCoreInputDevice(config,
+ layout,
+ "CorePointer",
+ CONF_IMPLICIT_POINTER,
+ "mouse", NULL,
+ "first CorePointer in the config input list",
+ "first mouse device");
+
+ if (!ret) return FALSE;
+
+ ret = getCoreInputDevice(config,
+ layout,
+ "CoreKeyboard",
+ CONF_IMPLICIT_KEYBOARD,
+ "keyboard", "kbd",
+ "first CoreKeyboard in the config input list",
+ "first keyboard device");
+ if (!ret) return FALSE;
+
+ return TRUE;
+}
diff --git a/XF86Config-parser/Keyboard.c b/XF86Config-parser/Keyboard.c
new file mode 100644
index 0000000..753fbf1
--- /dev/null
+++ b/XF86Config-parser/Keyboard.c
@@ -0,0 +1,308 @@
+/*
+ *
+ * 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).
+ */
+
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+#include "ctype.h"
+
+extern LexRec val;
+
+static XConfigSymTabRec KeyboardTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {KPROTOCOL, "protocol"},
+ {AUTOREPEAT, "autorepeat"},
+ {XLEDS, "xleds"},
+ {PANIX106, "panix106"},
+ {XKBKEYMAP, "xkbkeymap"},
+ {XKBCOMPAT, "xkbcompat"},
+ {XKBTYPES, "xkbtypes"},
+ {XKBKEYCODES, "xkbkeycodes"},
+ {XKBGEOMETRY, "xkbgeometry"},
+ {XKBSYMBOLS, "xkbsymbols"},
+ {XKBDISABLE, "xkbdisable"},
+ {XKBRULES, "xkbrules"},
+ {XKBMODEL, "xkbmodel"},
+ {XKBLAYOUT, "xkblayout"},
+ {XKBVARIANT, "xkbvariant"},
+ {XKBOPTIONS, "xkboptions"},
+ /* The next two have become ServerFlags options */
+ {VTINIT, "vtinit"},
+ {VTSYSREQ, "vtsysreq"},
+ /* Obsolete keywords */
+ {SERVERNUM, "servernumlock"},
+ {LEFTALT, "leftalt"},
+ {RIGHTALT, "rightalt"},
+ {RIGHTALT, "altgr"},
+ {SCROLLLOCK_TOK, "scrolllock"},
+ {RIGHTCTL, "rightctl"},
+ {-1, ""},
+};
+
+/* Obsolete */
+static XConfigSymTabRec KeyMapTab[] =
+{
+ {CONF_KM_META, "meta"},
+ {CONF_KM_COMPOSE, "compose"},
+ {CONF_KM_MODESHIFT, "modeshift"},
+ {CONF_KM_MODELOCK, "modelock"},
+ {CONF_KM_SCROLLLOCK, "scrolllock"},
+ {CONF_KM_CONTROL, "control"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeInputList
+
+XConfigInputPtr
+xconfigParseKeyboardSection (void)
+{
+ char *s, *s1, *s2;
+ int l;
+ int token, ntoken;
+ PARSE_PROLOGUE (XConfigInputPtr, XConfigInputRec)
+
+ while ((token = xconfigGetToken (KeyboardTab)) != ENDSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case KPROTOCOL:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Protocol");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("Protocol"),
+ val.str);
+ break;
+ case AUTOREPEAT:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (AUTOREPEAT_MSG, NULL);
+ s1 = xconfigULongToString(val.num);
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (AUTOREPEAT_MSG, NULL);
+ s2 = xconfigULongToString(val.num);
+ l = strlen(s1) + 1 + strlen(s2) + 1;
+ s = malloc(l);
+ sprintf(s, "%s %s", s1, s2);
+ free(s1);
+ free(s2);
+ ptr->options =
+ xconfigAddNewOption(ptr->options,
+ xconfigStrdup("AutoRepeat"), s);
+ break;
+ case XLEDS:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (XLEDS_MSG, NULL);
+ s = xconfigULongToString(val.num);
+ l = strlen(s) + 1;
+ while ((token = xconfigGetSubToken(&(ptr->comment))) == NUMBER)
+ {
+ s1 = xconfigULongToString(val.num);
+ l += (1 + strlen(s1));
+ s = realloc(s, l);
+ strcat(s, " ");
+ strcat(s, s1);
+ free(s1);
+ }
+ xconfigUnGetToken (token);
+ break;
+ case SERVERNUM:
+ xconfigErrorMsg(ParseWarningMsg, OBSOLETE_MSG,
+ xconfigTokenString());
+ break;
+ case LEFTALT:
+ case RIGHTALT:
+ case SCROLLLOCK_TOK:
+ case RIGHTCTL:
+ xconfigErrorMsg(ParseWarningMsg, OBSOLETE_MSG,
+ xconfigTokenString());
+ break;
+ ntoken = xconfigGetToken (KeyMapTab);
+ switch (ntoken)
+ {
+ case EOF_TOKEN:
+ xconfigErrorMsg(ParseErrorMsg, UNEXPECTED_EOF_MSG);
+ CLEANUP (ptr);
+ return (NULL);
+ break;
+
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ break;
+ case VTINIT:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "VTInit");
+ xconfigErrorMsg(ParseWarningMsg, MOVED_TO_FLAGS_MSG, "VTInit");
+ break;
+ case VTSYSREQ:
+ xconfigErrorMsg(ParseWarningMsg,
+ MOVED_TO_FLAGS_MSG, "VTSysReq");
+ break;
+ case XKBDISABLE:
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("XkbDisable"),
+ NULL);
+ break;
+ case XKBKEYMAP:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "XKBKeymap");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("XkbKeymap"),
+ val.str);
+ break;
+ case XKBCOMPAT:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "XKBCompat");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("XkbCompat"),
+ val.str);
+ break;
+ case XKBTYPES:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "XKBTypes");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("XkbTypes"),
+ val.str);
+ break;
+ case XKBKEYCODES:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "XKBKeycodes");
+ ptr->options =
+ xconfigAddNewOption(ptr->options,
+ xconfigStrdup("XkbKeycodes"),
+ val.str);
+ break;
+ case XKBGEOMETRY:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "XKBGeometry");
+ ptr->options =
+ xconfigAddNewOption(ptr->options,
+ xconfigStrdup("XkbGeometry"),
+ val.str);
+ break;
+ case XKBSYMBOLS:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "XKBSymbols");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("XkbSymbols"),
+ val.str);
+ break;
+ case XKBRULES:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "XKBRules");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("XkbRules"),
+ val.str);
+ break;
+ case XKBMODEL:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "XKBModel");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("XkbModel"),
+ val.str);
+ break;
+ case XKBLAYOUT:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "XKBLayout");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("XkbLayout"),
+ val.str);
+ break;
+ case XKBVARIANT:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "XKBVariant");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("XkbVariant"),
+ val.str);
+ break;
+ case XKBOPTIONS:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "XKBOptions");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("XkbOptions"),
+ val.str);
+ break;
+ case PANIX106:
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("Panix106"),
+ NULL);
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ }
+
+ ptr->identifier = xconfigStrdup(CONF_IMPLICIT_KEYBOARD);
+ ptr->driver = xconfigStrdup("keyboard");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("CoreKeyboard"), NULL);
+
+#ifdef DEBUG
+ xconfigErrorMsg(DebugMsg, "Keyboard section parsed\n");
+#endif
+
+ return ptr;
+}
+
diff --git a/XF86Config-parser/Layout.c b/XF86Config-parser/Layout.c
new file mode 100644
index 0000000..46cea64
--- /dev/null
+++ b/XF86Config-parser/Layout.c
@@ -0,0 +1,580 @@
+/*
+ *
+ * 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).
+ */
+
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+#include <string.h>
+
+extern LexRec val;
+
+static XConfigSymTabRec LayoutTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {SCREEN, "screen"},
+ {IDENTIFIER, "identifier"},
+ {INACTIVE, "inactive"},
+ {INPUTDEVICE, "inputdevice"},
+ {OPTION, "option"},
+ {-1, ""},
+};
+
+static XConfigSymTabRec AdjTab[] =
+{
+ {RIGHTOF, "rightof"},
+ {LEFTOF, "leftof"},
+ {ABOVE, "above"},
+ {BELOW, "below"},
+ {RELATIVE, "relative"},
+ {ABSOLUTE, "absolute"},
+ {-1, ""},
+};
+
+
+static int addImpliedLayout(XConfigPtr config, const char *screenName);
+
+
+#define CLEANUP xconfigFreeLayoutList
+
+XConfigLayoutPtr
+xconfigParseLayoutSection (void)
+{
+ int has_ident = FALSE;
+ int token;
+ PARSE_PROLOGUE (XConfigLayoutPtr, XConfigLayoutRec)
+
+ while ((token = xconfigGetToken (LayoutTab)) != ENDSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case IDENTIFIER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Identifier");
+ if (has_ident == TRUE)
+ Error (MULTIPLE_MSG, "Identifier");
+ ptr->identifier = val.str;
+ has_ident = TRUE;
+ break;
+ case INACTIVE:
+ {
+ XConfigInactivePtr iptr;
+
+ iptr = calloc (1, sizeof (XConfigInactiveRec));
+ iptr->next = NULL;
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (INACTIVE_MSG, NULL);
+ iptr->device_name = val.str;
+ ptr->inactives = (XConfigInactivePtr)
+ xconfigAddListItem((GenericListPtr) ptr->inactives,
+ (GenericListPtr) iptr);
+ }
+ break;
+ case SCREEN:
+ {
+ XConfigAdjacencyPtr aptr;
+ int absKeyword = 0;
+
+ aptr = calloc (1, sizeof (XConfigAdjacencyRec));
+ aptr->next = NULL;
+ aptr->scrnum = -1;
+ aptr->where = CONF_ADJ_OBSOLETE;
+ aptr->x = 0;
+ aptr->y = 0;
+ aptr->refscreen = NULL;
+ if ((token = xconfigGetSubToken (&(ptr->comment))) == NUMBER)
+ aptr->scrnum = val.num;
+ else
+ xconfigUnGetToken (token);
+ token = xconfigGetSubToken(&(ptr->comment));
+ if (token != STRING)
+ Error (SCREEN_MSG, NULL);
+ aptr->screen_name = val.str;
+
+ token = xconfigGetSubTokenWithTab(&(ptr->comment), AdjTab);
+ switch (token)
+ {
+ case RIGHTOF:
+ aptr->where = CONF_ADJ_RIGHTOF;
+ break;
+ case LEFTOF:
+ aptr->where = CONF_ADJ_LEFTOF;
+ break;
+ case ABOVE:
+ aptr->where = CONF_ADJ_ABOVE;
+ break;
+ case BELOW:
+ aptr->where = CONF_ADJ_BELOW;
+ break;
+ case RELATIVE:
+ aptr->where = CONF_ADJ_RELATIVE;
+ break;
+ case ABSOLUTE:
+ aptr->where = CONF_ADJ_ABSOLUTE;
+ absKeyword = 1;
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ xconfigUnGetToken (token);
+ token = xconfigGetSubToken(&(ptr->comment));
+ if (token == STRING)
+ aptr->where = CONF_ADJ_OBSOLETE;
+ else
+ aptr->where = CONF_ADJ_ABSOLUTE;
+ }
+ switch (aptr->where)
+ {
+ case CONF_ADJ_ABSOLUTE:
+ if (absKeyword)
+ token = xconfigGetSubToken(&(ptr->comment));
+ if (token == NUMBER)
+ {
+ aptr->x = val.num;
+ token = xconfigGetSubToken(&(ptr->comment));
+ if (token != NUMBER)
+ Error(INVALID_SCR_MSG, NULL);
+ aptr->y = val.num;
+ } else {
+ if (absKeyword)
+ Error(INVALID_SCR_MSG, NULL);
+ else
+ xconfigUnGetToken (token);
+ }
+ break;
+ case CONF_ADJ_RIGHTOF:
+ case CONF_ADJ_LEFTOF:
+ case CONF_ADJ_ABOVE:
+ case CONF_ADJ_BELOW:
+ case CONF_ADJ_RELATIVE:
+ token = xconfigGetSubToken(&(ptr->comment));
+ if (token != STRING)
+ Error(INVALID_SCR_MSG, NULL);
+ aptr->refscreen = val.str;
+ if (aptr->where == CONF_ADJ_RELATIVE)
+ {
+ token = xconfigGetSubToken(&(ptr->comment));
+ if (token != NUMBER)
+ Error(INVALID_SCR_MSG, NULL);
+ aptr->x = val.num;
+ token = xconfigGetSubToken(&(ptr->comment));
+ if (token != NUMBER)
+ Error(INVALID_SCR_MSG, NULL);
+ aptr->y = val.num;
+ }
+ break;
+ case CONF_ADJ_OBSOLETE:
+ /* top */
+ aptr->top_name = val.str;
+
+ /* bottom */
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (SCREEN_MSG, NULL);
+ aptr->bottom_name = val.str;
+
+ /* left */
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (SCREEN_MSG, NULL);
+ aptr->left_name = val.str;
+
+ /* right */
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (SCREEN_MSG, NULL);
+ aptr->right_name = val.str;
+
+ }
+ ptr->adjacencies = (XConfigAdjacencyPtr)
+ xconfigAddListItem((GenericListPtr) ptr->adjacencies,
+ (GenericListPtr) aptr);
+ }
+ break;
+ case INPUTDEVICE:
+ {
+ XConfigInputrefPtr iptr;
+
+ iptr = calloc (1, sizeof (XConfigInputrefRec));
+ iptr->next = NULL;
+ iptr->options = NULL;
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (INPUTDEV_MSG, NULL);
+ iptr->input_name = val.str;
+ while ((token = xconfigGetSubToken (&(ptr->comment))) == STRING)
+ {
+ iptr->options =
+ xconfigAddNewOption (iptr->options, val.str, NULL);
+ }
+ xconfigUnGetToken (token);
+ ptr->inputs = (XConfigInputrefPtr)
+ xconfigAddListItem((GenericListPtr) ptr->inputs,
+ (GenericListPtr) iptr);
+ }
+ 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;
+ }
+ }
+
+ if (!has_ident)
+ Error (NO_IDENT_MSG, NULL);
+
+#ifdef DEBUG
+ xconfigErrorMsg(DebugMsg, "Layout section parsed\n");
+#endif
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+void
+xconfigPrintLayoutSection (FILE * cf, XConfigLayoutPtr ptr)
+{
+ XConfigAdjacencyPtr aptr;
+ XConfigInactivePtr iptr;
+ XConfigInputrefPtr inptr;
+ XConfigOptionPtr optr;
+
+ while (ptr)
+ {
+ fprintf (cf, "Section \"ServerLayout\"\n");
+ if (ptr->comment)
+ fprintf (cf, "%s", ptr->comment);
+ if (ptr->identifier)
+ fprintf (cf, " Identifier \"%s\"\n", ptr->identifier);
+
+ for (aptr = ptr->adjacencies; aptr; aptr = aptr->next)
+ {
+ fprintf (cf, " Screen ");
+ if (aptr->scrnum >= 0)
+ fprintf (cf, "%2d", aptr->scrnum);
+ else
+ fprintf (cf, " ");
+ fprintf (cf, " \"%s\"", aptr->screen_name);
+ switch(aptr->where)
+ {
+ case CONF_ADJ_OBSOLETE:
+ fprintf (cf, " \"%s\"", aptr->top_name);
+ fprintf (cf, " \"%s\"", aptr->bottom_name);
+ fprintf (cf, " \"%s\"", aptr->right_name);
+ fprintf (cf, " \"%s\"\n", aptr->left_name);
+ break;
+ case CONF_ADJ_ABSOLUTE:
+ if (aptr->x != -1)
+ fprintf (cf, " %d %d\n", aptr->x, aptr->y);
+ else
+ fprintf (cf, "\n");
+ break;
+ case CONF_ADJ_RIGHTOF:
+ fprintf (cf, " RightOf \"%s\"\n", aptr->refscreen);
+ break;
+ case CONF_ADJ_LEFTOF:
+ fprintf (cf, " LeftOf \"%s\"\n", aptr->refscreen);
+ break;
+ case CONF_ADJ_ABOVE:
+ fprintf (cf, " Above \"%s\"\n", aptr->refscreen);
+ break;
+ case CONF_ADJ_BELOW:
+ fprintf (cf, " Below \"%s\"\n", aptr->refscreen);
+ break;
+ case CONF_ADJ_RELATIVE:
+ fprintf (cf, " Relative \"%s\" %d %d\n", aptr->refscreen,
+ aptr->x, aptr->y);
+ break;
+ }
+ }
+ for (iptr = ptr->inactives; iptr; iptr = iptr->next)
+ fprintf (cf, " Inactive \"%s\"\n", iptr->device_name);
+ for (inptr = ptr->inputs; inptr; inptr = inptr->next)
+ {
+ fprintf (cf, " InputDevice \"%s\"", inptr->input_name);
+ for (optr = inptr->options; optr; optr = optr->next)
+ {
+ fprintf(cf, " \"%s\"", optr->name);
+ }
+ fprintf(cf, "\n");
+ }
+ xconfigPrintOptionList(cf, ptr->options, 1);
+ fprintf (cf, "EndSection\n\n");
+ ptr = ptr->next;
+ }
+}
+
+void
+xconfigFreeLayoutList (XConfigLayoutPtr ptr)
+{
+ XConfigLayoutPtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->identifier);
+ TEST_FREE (ptr->comment);
+ xconfigFreeAdjacencyList (ptr->adjacencies);
+ xconfigFreeInputrefList (ptr->inputs);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+void
+xconfigFreeAdjacencyList (XConfigAdjacencyPtr ptr)
+{
+ XConfigAdjacencyPtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->screen_name);
+ TEST_FREE (ptr->top_name);
+ TEST_FREE (ptr->bottom_name);
+ TEST_FREE (ptr->left_name);
+ TEST_FREE (ptr->right_name);
+
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+
+}
+
+void
+xconfigFreeInputrefList (XConfigInputrefPtr ptr)
+{
+ XConfigInputrefPtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->input_name);
+ xconfigOptionListFree (ptr->options);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+
+}
+
+#define CheckScreen(str, ptr)\
+if (str[0] != '\0') \
+{ \
+screen = xconfigFindScreen (str, p->conf_screen_lst); \
+if (!screen) \
+{ \
+ xconfigErrorMsg(ValidationErrorMsg, UNDEFINED_SCREEN_MSG, \
+ str, layout->identifier); \
+ return (FALSE); \
+} \
+else \
+ ptr = screen; \
+}
+
+int
+xconfigValidateLayout (XConfigPtr p, const char *screenName)
+{
+ XConfigLayoutPtr layout = p->layouts;
+ XConfigAdjacencyPtr adj;
+ XConfigInactivePtr iptr;
+ XConfigInputrefPtr inptr;
+ XConfigScreenPtr screen;
+ XConfigDevicePtr device;
+ XConfigInputPtr input;
+
+ if (!layout) {
+ if (!addImpliedLayout(p, screenName)) return FALSE;
+ }
+
+ while (layout)
+ {
+ adj = layout->adjacencies;
+ while (adj)
+ {
+ /* the first one can't be "" but all others can */
+ screen = xconfigFindScreen (adj->screen_name, p->screens);
+ if (!screen)
+ {
+ xconfigErrorMsg(ValidationErrorMsg, UNDEFINED_SCREEN_MSG,
+ adj->screen_name, layout->identifier);
+ return (FALSE);
+ }
+ else
+ adj->screen = screen;
+
+#if 0
+ CheckScreen (adj->top_name, adj->top);
+ CheckScreen (adj->bottom_name, adj->bottom);
+ CheckScreen (adj->left_name, adj->left);
+ CheckScreen (adj->right_name, adj->right);
+#endif
+
+ adj = adj->next;
+ }
+ iptr = layout->inactives;
+ while (iptr)
+ {
+ device = xconfigFindDevice (iptr->device_name,
+ p->devices);
+ if (!device)
+ {
+ xconfigErrorMsg(ValidationErrorMsg, UNDEFINED_DEVICE_MSG,
+ iptr->device_name, layout->identifier);
+ return (FALSE);
+ }
+ else
+ iptr->device = device;
+ iptr = iptr->next;
+ }
+ inptr = layout->inputs;
+ while (inptr)
+ {
+ input = xconfigFindInput (inptr->input_name,
+ p->inputs);
+ if (!input)
+ {
+ xconfigErrorMsg(ValidationErrorMsg, UNDEFINED_INPUT_MSG,
+ inptr->input_name, layout->identifier);
+ return (FALSE);
+ }
+ else {
+ inptr->input = input;
+ }
+ inptr = inptr->next;
+ }
+ layout = layout->next;
+ }
+ return (TRUE);
+}
+
+XConfigLayoutPtr
+xconfigFindLayout (const char *name, XConfigLayoutPtr list)
+{
+ while (list)
+ {
+ if (xconfigNameCompare (list->identifier, name) == 0)
+ return (list);
+ list = list->next;
+ }
+ return (NULL);
+}
+
+
+static int addImpliedLayout(XConfigPtr config, const char *screenName)
+{
+ XConfigScreenPtr screen;
+ XConfigLayoutPtr layout;
+ XConfigAdjacencyPtr adj;
+
+ if (config->layouts) return TRUE;
+
+ /*
+ * which screen section is the active one?
+ *
+ * If there is a -screen option, use that one, otherwise use the first
+ * screen in the config's list.
+ */
+
+ if (screenName) {
+ screen = xconfigFindScreen(screenName, config->screens);
+ if (!screen) {
+ xconfigErrorMsg(ErrorMsg, "No Screen section called \"%s\"\n",
+ screenName);
+ return FALSE;
+ }
+ } else {
+ screen = config->screens;
+ }
+
+ xconfigErrorMsg(WarnMsg, "No Layout specified, constructing implicit "
+ "layout section using screen \"%s\".\n",
+ screen->identifier);
+
+ /* allocate the new layout section */
+
+ layout = calloc(1, sizeof(XConfigLayoutRec));
+
+ layout->identifier = "Default Layout";
+
+ adj = calloc(1, sizeof(XConfigAdjacencyRec));
+ adj->scrnum = -1;
+ adj->screen = screen;
+ adj->screen_name = strdup(screen->identifier);
+
+ layout->adjacencies = adj;
+
+ config->layouts = layout;
+
+ /*
+ * xconfigCheckCoreInputDevices() will add a keyboard and mouse to
+ * the layout.
+ */
+
+ if (!xconfigCheckCoreInputDevices(config, layout)) {
+ free(adj);
+ free(layout);
+ config->layouts = NULL;
+ return FALSE;
+ }
+
+ return TRUE;
+}
diff --git a/XF86Config-parser/Makefile b/XF86Config-parser/Makefile
new file mode 100644
index 0000000..34a206a
--- /dev/null
+++ b/XF86Config-parser/Makefile
@@ -0,0 +1,48 @@
+SRC = DRI.c \
+ Device.c \
+ Files.c \
+ Flags.c \
+ Input.c \
+ Keyboard.c \
+ Layout.c \
+ Module.c \
+ Monitor.c \
+ Pointer.c \
+ Screen.c \
+ Vendor.c \
+ Video.c \
+ Read.c \
+ Scan.c \
+ Write.c \
+ Util.c \
+ Extensions.c \
+ Generate.c
+
+OBJS = $(SRC:.c=.o)
+
+CFLAGS = -Wall -g
+
+ifdef NV_CFLAGS
+ CFLAGS += $(NV_CFLAGS)
+endif
+
+LIB = libXF86Config-parser.a
+LIB_O = $(LIB:.a=.o)
+
+$(LIB): $(OBJS)
+ $(LD) -r -o $(LIB_O) $(OBJS)
+ $(AR) ruv $(LIB) $(LIB_O)
+ ranlib $(LIB)
+
+%.o: %.c
+ $(CC) -c $(CFLAGS) $< -o $@
+
+%.d: %.c
+ @set -e; $(CC) -MM $(CPPFLAGS) $< \
+ | sed 's/\($*\)\.o[ :]*/\1.o $@ : /g' > $@; \
+ [ -s $@ ] || rm -f $@
+
+clean clobber:
+ rm -rf *.o *~ *.d $(LIB) $(LIB_O)
+
+-include $(SRC:.c=.d)
diff --git a/XF86Config-parser/Module.c b/XF86Config-parser/Module.c
new file mode 100644
index 0000000..e7e7a42
--- /dev/null
+++ b/XF86Config-parser/Module.c
@@ -0,0 +1,286 @@
+/*
+ *
+ * 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).
+ */
+
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+extern LexRec val;
+
+static XConfigSymTabRec SubModuleTab[] =
+{
+ {ENDSUBSECTION, "endsubsection"},
+ {OPTION, "option"},
+ {-1, ""},
+};
+
+static XConfigSymTabRec ModuleTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {LOAD, "load"},
+ {LOAD_DRIVER, "loaddriver"},
+ {SUBSECTION, "subsection"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeModules
+
+XConfigLoadPtr
+xconfigParseModuleSubSection (XConfigLoadPtr head, char *name)
+{
+ int token;
+ PARSE_PROLOGUE (XConfigLoadPtr, XConfigLoadRec)
+
+ ptr->name = name;
+ ptr->type = XCONFIG_LOAD_MODULE;
+ ptr->opt = NULL;
+ ptr->next = NULL;
+
+ while ((token = xconfigGetToken (SubModuleTab)) != ENDSUBSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case OPTION:
+ ptr->opt = xconfigParseOption(ptr->opt);
+ break;
+ case EOF_TOKEN:
+ xconfigErrorMsg(ParseErrorMsg, UNEXPECTED_EOF_MSG);
+ free(ptr);
+ return NULL;
+ default:
+ xconfigErrorMsg(ParseErrorMsg, INVALID_KEYWORD_MSG,
+ xconfigTokenString());
+ free(ptr);
+ return NULL;
+ break;
+ }
+
+ }
+
+ return ((XConfigLoadPtr) xconfigAddListItem ((GenericListPtr) head,
+ (GenericListPtr) ptr));
+}
+
+XConfigModulePtr
+xconfigParseModuleSection (void)
+{
+ int token;
+ PARSE_PROLOGUE (XConfigModulePtr, XConfigModuleRec)
+
+ while ((token = xconfigGetToken (ModuleTab)) != ENDSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case LOAD:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Load");
+ ptr->loads =
+ xconfigAddNewLoadDirective (ptr->loads, val.str,
+ XCONFIG_LOAD_MODULE, NULL, TRUE);
+ break;
+ case LOAD_DRIVER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "LoadDriver");
+ ptr->loads =
+ xconfigAddNewLoadDirective (ptr->loads, val.str,
+ XCONFIG_LOAD_DRIVER, NULL, TRUE);
+ break;
+ case SUBSECTION:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "SubSection");
+ ptr->loads =
+ xconfigParseModuleSubSection (ptr->loads, val.str);
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ }
+
+#ifdef DEBUG
+ xconfigErrorMsg(DebugMsg, "Module section parsed\n");
+#endif
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+void
+xconfigPrintModuleSection (FILE * cf, XConfigModulePtr ptr)
+{
+ XConfigLoadPtr lptr;
+
+ if (ptr == NULL)
+ return;
+
+ if (ptr->comment)
+ fprintf(cf, "%s", ptr->comment);
+ for (lptr = ptr->loads; lptr; lptr = lptr->next)
+ {
+ switch (lptr->type)
+ {
+ case XCONFIG_LOAD_MODULE:
+ if( lptr->opt == NULL ) {
+ fprintf (cf, " Load \"%s\"", lptr->name);
+ if (lptr->comment)
+ fprintf(cf, "%s", lptr->comment);
+ else
+ fputc('\n', cf);
+ }
+ else
+ {
+ fprintf (cf, " SubSection \"%s\"\n", lptr->name);
+ if (lptr->comment)
+ fprintf(cf, "%s", lptr->comment);
+ xconfigPrintOptionList(cf, lptr->opt, 2);
+ fprintf (cf, " EndSubSection\n");
+ }
+ break;
+ case XCONFIG_LOAD_DRIVER:
+ fprintf (cf, " LoadDriver \"%s\"", lptr->name);
+ if (lptr->comment)
+ fprintf(cf, "%s", lptr->comment);
+ else
+ fputc('\n', cf);
+ break;
+#if 0
+ default:
+ fprintf (cf, "# Unknown type \"%s\"\n", lptr->name);
+ break;
+#endif
+ }
+ }
+}
+
+XConfigLoadPtr
+xconfigAddNewLoadDirective (XConfigLoadPtr head, char *name, int type,
+ XConfigOptionPtr opts, int do_token)
+{
+ XConfigLoadPtr new;
+ int token;
+
+ new = calloc (1, sizeof (XConfigLoadRec));
+ new->name = name;
+ new->type = type;
+ new->opt = opts;
+ new->next = NULL;
+
+ if (do_token) {
+ if ((token = xconfigGetToken(NULL)) == COMMENT)
+ new->comment = xconfigAddComment(new->comment, val.str);
+ else
+ xconfigUnGetToken(token);
+ }
+
+ return ((XConfigLoadPtr) xconfigAddListItem ((GenericListPtr) head,
+ (GenericListPtr) new));
+}
+
+XConfigLoadPtr
+xconfigRemoveLoadDirective(XConfigLoadPtr head, XConfigLoadPtr load)
+{
+ XConfigLoadPtr prev = NULL;
+ XConfigLoadPtr l = head;
+
+ while (l) {
+ if (l == load) {
+ if (prev) prev->next = load->next;
+ if (head == load) head = load->next;
+ TEST_FREE(load->name);
+ TEST_FREE(load->comment);
+ xconfigOptionListFree(load->opt);
+ free(load);
+ break;
+ }
+
+ prev = l;
+ l = l->next;
+ }
+
+ return head;
+}
+
+void
+xconfigFreeModules (XConfigModulePtr ptr)
+{
+ XConfigLoadPtr lptr;
+ XConfigLoadPtr prev;
+
+ if (ptr == NULL)
+ return;
+ lptr = ptr->loads;
+ while (lptr)
+ {
+ TEST_FREE (lptr->name);
+ TEST_FREE (lptr->comment);
+ prev = lptr;
+ lptr = lptr->next;
+ free (prev);
+ }
+ TEST_FREE (ptr->comment);
+ free (ptr);
+}
diff --git a/XF86Config-parser/Monitor.c b/XF86Config-parser/Monitor.c
new file mode 100644
index 0000000..c657fd4
--- /dev/null
+++ b/XF86Config-parser/Monitor.c
@@ -0,0 +1,901 @@
+/*
+ *
+ * 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).
+ */
+
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+extern LexRec val;
+
+static XConfigSymTabRec MonitorTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {IDENTIFIER, "identifier"},
+ {VENDOR, "vendorname"},
+ {MODEL, "modelname"},
+ {USEMODES, "usemodes"},
+ {MODELINE, "modeline"},
+ {DISPLAYSIZE, "displaysize"},
+ {HORIZSYNC, "horizsync"},
+ {VERTREFRESH, "vertrefresh"},
+ {MODE, "mode"},
+ {GAMMA, "gamma"},
+ {OPTION, "option"},
+ {-1, ""},
+};
+
+static XConfigSymTabRec ModesTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {IDENTIFIER, "identifier"},
+ {MODELINE, "modeline"},
+ {MODE, "mode"},
+ {-1, ""},
+};
+
+static XConfigSymTabRec TimingTab[] =
+{
+ {TT_INTERLACE, "interlace"},
+ {TT_PHSYNC, "+hsync"},
+ {TT_NHSYNC, "-hsync"},
+ {TT_PVSYNC, "+vsync"},
+ {TT_NVSYNC, "-vsync"},
+ {TT_CSYNC, "composite"},
+ {TT_PCSYNC, "+csync"},
+ {TT_NCSYNC, "-csync"},
+ {TT_DBLSCAN, "doublescan"},
+ {TT_HSKEW, "hskew"},
+ {TT_BCAST, "bcast"},
+ {TT_VSCAN, "vscan"},
+ {TT_CUSTOM, "CUSTOM"},
+ {-1, ""},
+};
+
+static XConfigSymTabRec ModeTab[] =
+{
+ {DOTCLOCK, "dotclock"},
+ {HTIMINGS, "htimings"},
+ {VTIMINGS, "vtimings"},
+ {FLAGS, "flags"},
+ {HSKEW, "hskew"},
+ {BCAST, "bcast"},
+ {VSCAN, "vscan"},
+ {ENDMODE, "endmode"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeModeLineList
+
+XConfigModeLinePtr
+xconfigParseModeLine (void)
+{
+ int token;
+ PARSE_PROLOGUE (XConfigModeLinePtr, XConfigModeLineRec)
+
+ /* Identifier */
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error ("ModeLine identifier expected", NULL);
+ ptr->identifier = val.str;
+
+ /* DotClock */
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error ("ModeLine dotclock expected", NULL);
+ ptr->clock = (int) (val.realnum * 1000.0 + 0.5);
+
+ /* HDisplay */
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error ("ModeLine Hdisplay expected", NULL);
+ ptr->hdisplay = val.num;
+
+ /* HSyncStart */
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error ("ModeLine HSyncStart expected", NULL);
+ ptr->hsyncstart = val.num;
+
+ /* HSyncEnd */
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error ("ModeLine HSyncEnd expected", NULL);
+ ptr->hsyncend = val.num;
+
+ /* HTotal */
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error ("ModeLine HTotal expected", NULL);
+ ptr->htotal = val.num;
+
+ /* VDisplay */
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error ("ModeLine Vdisplay expected", NULL);
+ ptr->vdisplay = val.num;
+
+ /* VSyncStart */
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error ("ModeLine VSyncStart expected", NULL);
+ ptr->vsyncstart = val.num;
+
+ /* VSyncEnd */
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error ("ModeLine VSyncEnd expected", NULL);
+ ptr->vsyncend = val.num;
+
+ /* VTotal */
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error ("ModeLine VTotal expected", NULL);
+ ptr->vtotal = val.num;
+
+ token = xconfigGetSubTokenWithTab (&(ptr->comment), TimingTab);
+ while ((token == TT_INTERLACE) || (token == TT_PHSYNC) ||
+ (token == TT_NHSYNC) || (token == TT_PVSYNC) ||
+ (token == TT_NVSYNC) || (token == TT_CSYNC) ||
+ (token == TT_PCSYNC) || (token == TT_NCSYNC) ||
+ (token == TT_DBLSCAN) || (token == TT_HSKEW) ||
+ (token == TT_VSCAN) || (token == TT_BCAST))
+ {
+ switch (token)
+ {
+
+ case TT_INTERLACE:
+ ptr->flags |= XCONFIG_MODE_INTERLACE;
+ break;
+ case TT_PHSYNC:
+ ptr->flags |= XCONFIG_MODE_PHSYNC;
+ break;
+ case TT_NHSYNC:
+ ptr->flags |= XCONFIG_MODE_NHSYNC;
+ break;
+ case TT_PVSYNC:
+ ptr->flags |= XCONFIG_MODE_PVSYNC;
+ break;
+ case TT_NVSYNC:
+ ptr->flags |= XCONFIG_MODE_NVSYNC;
+ break;
+ case TT_CSYNC:
+ ptr->flags |= XCONFIG_MODE_CSYNC;
+ break;
+ case TT_PCSYNC:
+ ptr->flags |= XCONFIG_MODE_PCSYNC;
+ break;
+ case TT_NCSYNC:
+ ptr->flags |= XCONFIG_MODE_NCSYNC;
+ break;
+ case TT_DBLSCAN:
+ ptr->flags |= XCONFIG_MODE_DBLSCAN;
+ break;
+ case TT_HSKEW:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "Hskew");
+ ptr->hskew = val.num;
+ ptr->flags |= XCONFIG_MODE_HSKEW;
+ break;
+ case TT_BCAST:
+ ptr->flags |= XCONFIG_MODE_BCAST;
+ break;
+ case TT_VSCAN:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "Vscan");
+ ptr->vscan = val.num;
+ ptr->flags |= XCONFIG_MODE_VSCAN;
+ break;
+ case TT_CUSTOM:
+ ptr->flags |= XCONFIG_MODE_CUSTOM;
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ token = xconfigGetSubTokenWithTab (&(ptr->comment), TimingTab);
+ }
+ xconfigUnGetToken (token);
+
+#ifdef DEBUG
+ xconfigErrorMsg(DebugMsg, "ModeLine parsed\n");
+#endif
+ return (ptr);
+}
+
+XConfigModeLinePtr
+xconfigParseVerboseMode (void)
+{
+ int token, token2;
+ int had_dotclock = 0, had_htimings = 0, had_vtimings = 0;
+ PARSE_PROLOGUE (XConfigModeLinePtr, XConfigModeLineRec)
+
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error ("Mode name expected", NULL);
+ ptr->identifier = val.str;
+ while ((token = xconfigGetToken (ModeTab)) != ENDMODE)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case DOTCLOCK:
+ if ((token = xconfigGetSubToken (&(ptr->comment))) != NUMBER)
+ Error (NUMBER_MSG, "DotClock");
+ ptr->clock = (int) (val.realnum * 1000.0 + 0.5);
+ had_dotclock = 1;
+ break;
+ case HTIMINGS:
+ if (xconfigGetSubToken (&(ptr->comment)) == NUMBER)
+ ptr->hdisplay = val.num;
+ else
+ Error ("Horizontal display expected", NULL);
+
+ if (xconfigGetSubToken (&(ptr->comment)) == NUMBER)
+ ptr->hsyncstart = val.num;
+ else
+ Error ("Horizontal sync start expected", NULL);
+
+ if (xconfigGetSubToken (&(ptr->comment)) == NUMBER)
+ ptr->hsyncend = val.num;
+ else
+ Error ("Horizontal sync end expected", NULL);
+
+ if (xconfigGetSubToken (&(ptr->comment)) == NUMBER)
+ ptr->htotal = val.num;
+ else
+ Error ("Horizontal total expected", NULL);
+ had_htimings = 1;
+ break;
+ case VTIMINGS:
+ if (xconfigGetSubToken (&(ptr->comment)) == NUMBER)
+ ptr->vdisplay = val.num;
+ else
+ Error ("Vertical display expected", NULL);
+
+ if (xconfigGetSubToken (&(ptr->comment)) == NUMBER)
+ ptr->vsyncstart = val.num;
+ else
+ Error ("Vertical sync start expected", NULL);
+
+ if (xconfigGetSubToken (&(ptr->comment)) == NUMBER)
+ ptr->vsyncend = val.num;
+ else
+ Error ("Vertical sync end expected", NULL);
+
+ if (xconfigGetSubToken (&(ptr->comment)) == NUMBER)
+ ptr->vtotal = val.num;
+ else
+ Error ("Vertical total expected", NULL);
+ had_vtimings = 1;
+ break;
+ case FLAGS:
+ token = xconfigGetSubToken (&(ptr->comment));
+ if (token != STRING)
+ Error (QUOTE_MSG, "Flags");
+ while (token == STRING)
+ {
+ token2 = xconfigGetStringToken (TimingTab);
+ switch (token2)
+ {
+ case TT_INTERLACE:
+ ptr->flags |= XCONFIG_MODE_INTERLACE;
+ break;
+ case TT_PHSYNC:
+ ptr->flags |= XCONFIG_MODE_PHSYNC;
+ break;
+ case TT_NHSYNC:
+ ptr->flags |= XCONFIG_MODE_NHSYNC;
+ break;
+ case TT_PVSYNC:
+ ptr->flags |= XCONFIG_MODE_PVSYNC;
+ break;
+ case TT_NVSYNC:
+ ptr->flags |= XCONFIG_MODE_NVSYNC;
+ break;
+ case TT_CSYNC:
+ ptr->flags |= XCONFIG_MODE_CSYNC;
+ break;
+ case TT_PCSYNC:
+ ptr->flags |= XCONFIG_MODE_PCSYNC;
+ break;
+ case TT_NCSYNC:
+ ptr->flags |= XCONFIG_MODE_NCSYNC;
+ break;
+ case TT_DBLSCAN:
+ ptr->flags |= XCONFIG_MODE_DBLSCAN;
+ break;
+ case TT_CUSTOM:
+ ptr->flags |= XCONFIG_MODE_CUSTOM;
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error ("Unknown flag string", NULL);
+ break;
+ }
+ token = xconfigGetSubToken (&(ptr->comment));
+ }
+ xconfigUnGetToken (token);
+ break;
+ case HSKEW:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error ("Horizontal skew expected", NULL);
+ ptr->flags |= XCONFIG_MODE_HSKEW;
+ ptr->hskew = val.num;
+ break;
+ case VSCAN:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error ("Vertical scan count expected", NULL);
+ ptr->flags |= XCONFIG_MODE_VSCAN;
+ ptr->vscan = val.num;
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error ("Unexepcted token in verbose \"Mode\" entry\n", NULL);
+ }
+ }
+ if (!had_dotclock)
+ Error ("the dotclock is missing", NULL);
+ if (!had_htimings)
+ Error ("the horizontal timings are missing", NULL);
+ if (!had_vtimings)
+ Error ("the vertical timings are missing", NULL);
+
+#ifdef DEBUG
+ xconfigErrorMsg(DebugMsg, "Verbose Mode parsed\n");
+#endif
+ return (ptr);
+}
+
+#undef CLEANUP
+
+#define CLEANUP xconfigFreeMonitorList
+
+XConfigMonitorPtr
+xconfigParseMonitorSection (void)
+{
+ int has_ident = FALSE;
+ int token;
+ PARSE_PROLOGUE (XConfigMonitorPtr, XConfigMonitorRec)
+
+ while ((token = xconfigGetToken (MonitorTab)) != ENDSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case IDENTIFIER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Identifier");
+ if (has_ident == TRUE)
+ Error (MULTIPLE_MSG, "Identifier");
+ ptr->identifier = val.str;
+ has_ident = TRUE;
+ break;
+ case VENDOR:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Vendor");
+ ptr->vendor = val.str;
+ break;
+ case MODEL:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "ModelName");
+ ptr->modelname = val.str;
+ break;
+ case MODE:
+ HANDLE_LIST (modelines, xconfigParseVerboseMode,
+ XConfigModeLinePtr);
+ break;
+ case MODELINE:
+ HANDLE_LIST (modelines, xconfigParseModeLine,
+ XConfigModeLinePtr);
+ break;
+ case DISPLAYSIZE:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (DISPLAYSIZE_MSG, NULL);
+ ptr->width = val.realnum;
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (DISPLAYSIZE_MSG, NULL);
+ ptr->height = val.realnum;
+ break;
+
+ case HORIZSYNC:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (HORIZSYNC_MSG, NULL);
+ do {
+ ptr->hsync[ptr->n_hsync].lo = val.realnum;
+ switch (token = xconfigGetSubToken (&(ptr->comment)))
+ {
+ case COMMA:
+ ptr->hsync[ptr->n_hsync].hi =
+ ptr->hsync[ptr->n_hsync].lo;
+ break;
+ case DASH:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER ||
+ (float)val.realnum < ptr->hsync[ptr->n_hsync].lo)
+ Error (HORIZSYNC_MSG, NULL);
+ ptr->hsync[ptr->n_hsync].hi = val.realnum;
+ if ((token = xconfigGetSubToken (&(ptr->comment))) == COMMA)
+ break;
+ ptr->n_hsync++;
+ goto HorizDone;
+ default:
+ /* We cannot currently know if a '\n' was found,
+ * or this is a real error
+ */
+ ptr->hsync[ptr->n_hsync].hi =
+ ptr->hsync[ptr->n_hsync].lo;
+ ptr->n_hsync++;
+ goto HorizDone;
+ }
+ if (ptr->n_hsync >= CONF_MAX_HSYNC)
+ Error ("Sorry. Too many horizontal sync intervals.", NULL);
+ ptr->n_hsync++;
+ } while ((token = xconfigGetSubToken (&(ptr->comment))) == NUMBER);
+HorizDone:
+ xconfigUnGetToken (token);
+ break;
+
+ case VERTREFRESH:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (VERTREFRESH_MSG, NULL);
+ do {
+ ptr->vrefresh[ptr->n_vrefresh].lo = val.realnum;
+ switch (token = xconfigGetSubToken (&(ptr->comment)))
+ {
+ case COMMA:
+ ptr->vrefresh[ptr->n_vrefresh].hi =
+ ptr->vrefresh[ptr->n_vrefresh].lo;
+ break;
+ case DASH:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER ||
+ (float)val.realnum < ptr->vrefresh[ptr->n_vrefresh].lo)
+ Error (VERTREFRESH_MSG, NULL);
+ ptr->vrefresh[ptr->n_vrefresh].hi = val.realnum;
+ if ((token = xconfigGetSubToken (&(ptr->comment))) == COMMA)
+ break;
+ ptr->n_vrefresh++;
+ goto VertDone;
+ default:
+ /* We cannot currently know if a '\n' was found,
+ * or this is a real error
+ */
+ ptr->vrefresh[ptr->n_vrefresh].hi =
+ ptr->vrefresh[ptr->n_vrefresh].lo;
+ ptr->n_vrefresh++;
+ goto VertDone;
+ }
+ if (ptr->n_vrefresh >= CONF_MAX_VREFRESH)
+ Error ("Sorry. Too many vertical refresh intervals.", NULL);
+ ptr->n_vrefresh++;
+ } while ((token = xconfigGetSubToken (&(ptr->comment))) == NUMBER);
+VertDone:
+ xconfigUnGetToken (token);
+ break;
+
+ case GAMMA:
+ if( xconfigGetSubToken (&(ptr->comment)) != NUMBER )
+ {
+ Error (INVALID_GAMMA_MSG, NULL);
+ }
+ else
+ {
+ ptr->gamma_red = ptr->gamma_green =
+ ptr->gamma_blue = val.realnum;
+ if( xconfigGetSubToken (&(ptr->comment)) == NUMBER )
+ {
+ ptr->gamma_green = val.realnum;
+ if( xconfigGetSubToken (&(ptr->comment)) == NUMBER )
+ {
+ ptr->gamma_blue = val.realnum;
+ }
+ else
+ {
+ Error (INVALID_GAMMA_MSG, NULL);
+ }
+ }
+ else
+ xconfigUnGetToken (token);
+ }
+ break;
+ case OPTION:
+ ptr->options = xconfigParseOption(ptr->options);
+ break;
+ case USEMODES:
+ {
+ XConfigModesLinkPtr mptr;
+
+ if ((token = xconfigGetSubToken (&(ptr->comment))) != STRING)
+ Error (QUOTE_MSG, "UseModes");
+
+ /* add to the end of the list of modes sections
+ referenced here */
+ mptr = calloc (1, sizeof (XConfigModesLinkRec));
+ mptr->next = NULL;
+ mptr->modes_name = val.str;
+ mptr->modes = NULL;
+ ptr->modes_sections = (XConfigModesLinkPtr)
+ xconfigAddListItem((GenericListPtr)ptr->modes_sections,
+ (GenericListPtr)mptr);
+ }
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ xconfigErrorMsg(ParseErrorMsg, INVALID_KEYWORD_MSG,
+ xconfigTokenString());
+ CLEANUP (ptr);
+ return NULL;
+ break;
+ }
+ }
+
+ if (!has_ident)
+ Error (NO_IDENT_MSG, NULL);
+
+#ifdef DEBUG
+ xconfigErrorMsg(DebugMsg, "Monitor section parsed\n");
+#endif
+ return ptr;
+}
+
+#undef CLEANUP
+#define CLEANUP xconfigFreeModesList
+
+XConfigModesPtr
+xconfigParseModesSection (void)
+{
+ int has_ident = FALSE;
+ int token;
+ PARSE_PROLOGUE (XConfigModesPtr, XConfigModesRec)
+
+ while ((token = xconfigGetToken (ModesTab)) != ENDSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case IDENTIFIER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Identifier");
+ if (has_ident == TRUE)
+ Error (MULTIPLE_MSG, "Identifier");
+ ptr->identifier = val.str;
+ has_ident = TRUE;
+ break;
+ case MODE:
+ HANDLE_LIST (modelines, xconfigParseVerboseMode,
+ XConfigModeLinePtr);
+ break;
+ case MODELINE:
+ HANDLE_LIST (modelines, xconfigParseModeLine,
+ XConfigModeLinePtr);
+ break;
+ default:
+ xconfigErrorMsg(ParseErrorMsg, INVALID_KEYWORD_MSG,
+ xconfigTokenString());
+ CLEANUP (ptr);
+ return NULL;
+ break;
+ }
+ }
+
+ if (!has_ident)
+ Error (NO_IDENT_MSG, NULL);
+
+#ifdef DEBUG
+ xconfigErrorMsg(DebugMsg, "Modes section parsed\n");
+#endif
+ return ptr;
+}
+
+#undef CLEANUP
+
+void
+xconfigPrintMonitorSection (FILE * cf, XConfigMonitorPtr ptr)
+{
+ int i;
+ XConfigModeLinePtr mlptr;
+ XConfigModesLinkPtr mptr;
+
+ while (ptr)
+ {
+ mptr = ptr->modes_sections;
+ fprintf (cf, "Section \"Monitor\"\n");
+ if (ptr->comment)
+ fprintf (cf, "%s", ptr->comment);
+ if (ptr->identifier)
+ fprintf (cf, " Identifier \"%s\"\n", ptr->identifier);
+ if (ptr->vendor)
+ fprintf (cf, " VendorName \"%s\"\n", ptr->vendor);
+ if (ptr->modelname)
+ fprintf (cf, " ModelName \"%s\"\n", ptr->modelname);
+ while (mptr) {
+ fprintf (cf, " UseModes \"%s\"\n", mptr->modes_name);
+ mptr = mptr->next;
+ }
+ if (ptr->width)
+ fprintf (cf, " DisplaySize %d %d\n",
+ ptr->width,
+ ptr->height);
+ for (i = 0; i < ptr->n_hsync; i++)
+ {
+ fprintf (cf, " HorizSync %2.1f - %2.1f\n",
+ ptr->hsync[i].lo,
+ ptr->hsync[i].hi);
+ }
+ for (i = 0; i < ptr->n_vrefresh; i++)
+ {
+ fprintf (cf, " VertRefresh %2.1f - %2.1f\n",
+ ptr->vrefresh[i].lo,
+ ptr->vrefresh[i].hi);
+ }
+ if (ptr->gamma_red) {
+ if (ptr->gamma_red == ptr->gamma_green
+ && ptr->gamma_red == ptr->gamma_blue)
+ {
+ fprintf (cf, " Gamma %.4g\n",
+ ptr->gamma_red);
+ } else {
+ fprintf (cf, " Gamma %.4g %.4g %.4g\n",
+ ptr->gamma_red,
+ ptr->gamma_green,
+ ptr->gamma_blue);
+ }
+ }
+ for (mlptr = ptr->modelines; mlptr; mlptr = mlptr->next)
+ {
+ fprintf (cf, " ModeLine \"%s\" %2.1f ",
+ mlptr->identifier, mlptr->clock / 1000.0);
+ fprintf (cf, "%d %d %d %d %d %d %d %d",
+ mlptr->hdisplay, mlptr->hsyncstart,
+ mlptr->hsyncend, mlptr->htotal,
+ mlptr->vdisplay, mlptr->vsyncstart,
+ mlptr->vsyncend, mlptr->vtotal);
+ if (mlptr->flags & XCONFIG_MODE_PHSYNC)
+ fprintf (cf, " +hsync");
+ if (mlptr->flags & XCONFIG_MODE_NHSYNC)
+ fprintf (cf, " -hsync");
+ if (mlptr->flags & XCONFIG_MODE_PVSYNC)
+ fprintf (cf, " +vsync");
+ if (mlptr->flags & XCONFIG_MODE_NVSYNC)
+ fprintf (cf, " -vsync");
+ if (mlptr->flags & XCONFIG_MODE_INTERLACE)
+ fprintf (cf, " interlace");
+ if (mlptr->flags & XCONFIG_MODE_CSYNC)
+ fprintf (cf, " composite");
+ if (mlptr->flags & XCONFIG_MODE_PCSYNC)
+ fprintf (cf, " +csync");
+ if (mlptr->flags & XCONFIG_MODE_NCSYNC)
+ fprintf (cf, " -csync");
+ if (mlptr->flags & XCONFIG_MODE_DBLSCAN)
+ fprintf (cf, " doublescan");
+ if (mlptr->flags & XCONFIG_MODE_HSKEW)
+ fprintf (cf, " hskew %d", mlptr->hskew);
+ if (mlptr->flags & XCONFIG_MODE_BCAST)
+ fprintf (cf, " bcast");
+ fprintf (cf, "\n");
+ }
+ xconfigPrintOptionList(cf, ptr->options, 1);
+ fprintf (cf, "EndSection\n\n");
+ ptr = ptr->next;
+ }
+}
+
+void
+xconfigPrintModesSection (FILE * cf, XConfigModesPtr ptr)
+{
+ XConfigModeLinePtr mlptr;
+
+ while (ptr)
+ {
+ fprintf (cf, "Section \"Modes\"\n");
+ if (ptr->comment)
+ fprintf (cf, "%s", ptr->comment);
+ if (ptr->identifier)
+ fprintf (cf, " Identifier \"%s\"\n", ptr->identifier);
+ for (mlptr = ptr->modelines; mlptr; mlptr = mlptr->next)
+ {
+ fprintf (cf, " ModeLine \"%s\" %2.1f ",
+ mlptr->identifier, mlptr->clock / 1000.0);
+ fprintf (cf, "%d %d %d %d %d %d %d %d",
+ mlptr->hdisplay, mlptr->hsyncstart,
+ mlptr->hsyncend, mlptr->htotal,
+ mlptr->vdisplay, mlptr->vsyncstart,
+ mlptr->vsyncend, mlptr->vtotal);
+ if (mlptr->flags & XCONFIG_MODE_PHSYNC)
+ fprintf (cf, " +hsync");
+ if (mlptr->flags & XCONFIG_MODE_NHSYNC)
+ fprintf (cf, " -hsync");
+ if (mlptr->flags & XCONFIG_MODE_PVSYNC)
+ fprintf (cf, " +vsync");
+ if (mlptr->flags & XCONFIG_MODE_NVSYNC)
+ fprintf (cf, " -vsync");
+ if (mlptr->flags & XCONFIG_MODE_INTERLACE)
+ fprintf (cf, " interlace");
+ if (mlptr->flags & XCONFIG_MODE_CSYNC)
+ fprintf (cf, " composite");
+ if (mlptr->flags & XCONFIG_MODE_PCSYNC)
+ fprintf (cf, " +csync");
+ if (mlptr->flags & XCONFIG_MODE_NCSYNC)
+ fprintf (cf, " -csync");
+ if (mlptr->flags & XCONFIG_MODE_DBLSCAN)
+ fprintf (cf, " doublescan");
+ if (mlptr->flags & XCONFIG_MODE_HSKEW)
+ fprintf (cf, " hskew %d", mlptr->hskew);
+ if (mlptr->flags & XCONFIG_MODE_VSCAN)
+ fprintf (cf, " vscan %d", mlptr->vscan);
+ if (mlptr->flags & XCONFIG_MODE_BCAST)
+ fprintf (cf, " bcast");
+ if (mlptr->comment)
+ fprintf (cf, "%s", mlptr->comment);
+ else
+ fprintf (cf, "\n");
+ }
+ fprintf (cf, "EndSection\n\n");
+ ptr = ptr->next;
+ }
+}
+
+void
+xconfigFreeMonitorList (XConfigMonitorPtr ptr)
+{
+ XConfigMonitorPtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->identifier);
+ TEST_FREE (ptr->vendor);
+ TEST_FREE (ptr->modelname);
+ TEST_FREE (ptr->comment);
+ xconfigOptionListFree (ptr->options);
+ xconfigFreeModeLineList (ptr->modelines);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+void
+xconfigFreeModesList (XConfigModesPtr ptr)
+{
+ XConfigModesPtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->identifier);
+ TEST_FREE (ptr->comment);
+ xconfigFreeModeLineList (ptr->modelines);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+void
+xconfigFreeModeLineList (XConfigModeLinePtr ptr)
+{
+ XConfigModeLinePtr prev;
+ while (ptr)
+ {
+ TEST_FREE (ptr->identifier);
+ TEST_FREE (ptr->comment);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+XConfigMonitorPtr
+xconfigFindMonitor (const char *ident, XConfigMonitorPtr p)
+{
+ while (p)
+ {
+ if (xconfigNameCompare (ident, p->identifier) == 0)
+ return (p);
+
+ p = p->next;
+ }
+ return (NULL);
+}
+
+XConfigModesPtr
+xconfigFindModes (const char *ident, XConfigModesPtr p)
+{
+ while (p)
+ {
+ if (xconfigNameCompare (ident, p->identifier) == 0)
+ return (p);
+
+ p = p->next;
+ }
+ return (NULL);
+}
+
+XConfigModeLinePtr
+xconfigFindModeLine (const char *ident, XConfigModeLinePtr p)
+{
+ while (p)
+ {
+ if (xconfigNameCompare (ident, p->identifier) == 0)
+ return (p);
+
+ p = p->next;
+ }
+ return (NULL);
+}
+
+int
+xconfigValidateMonitor (XConfigPtr p, XConfigScreenPtr screen)
+{
+ XConfigMonitorPtr monitor = screen->monitor;
+ XConfigModesLinkPtr modeslnk = monitor->modes_sections;
+ XConfigModesPtr modes;
+ while(modeslnk)
+ {
+ modes = xconfigFindModes (modeslnk->modes_name, p->modes);
+ if (!modes)
+ {
+ xconfigErrorMsg(ValidationErrorMsg, UNDEFINED_MODES_MSG,
+ modeslnk->modes_name, screen->identifier);
+ return (FALSE);
+ }
+ modeslnk->modes = modes;
+ modeslnk = modeslnk->next;
+ }
+ return (TRUE);
+}
diff --git a/XF86Config-parser/Pointer.c b/XF86Config-parser/Pointer.c
new file mode 100644
index 0000000..bc2ceb3
--- /dev/null
+++ b/XF86Config-parser/Pointer.c
@@ -0,0 +1,240 @@
+/*
+ *
+ * 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).
+ */
+
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+extern LexRec val;
+
+static XConfigSymTabRec PointerTab[] =
+{
+ {PROTOCOL, "protocol"},
+ {EMULATE3, "emulate3buttons"},
+ {EM3TIMEOUT, "emulate3timeout"},
+ {ENDSUBSECTION, "endsubsection"},
+ {ENDSECTION, "endsection"},
+ {PDEVICE, "device"},
+ {PDEVICE, "port"},
+ {BAUDRATE, "baudrate"},
+ {SAMPLERATE, "samplerate"},
+ {CLEARDTR, "cleardtr"},
+ {CLEARRTS, "clearrts"},
+ {CHORDMIDDLE, "chordmiddle"},
+ {PRESOLUTION, "resolution"},
+ {DEVICE_NAME, "devicename"},
+ {ALWAYSCORE, "alwayscore"},
+ {PBUTTONS, "buttons"},
+ {ZAXISMAPPING, "zaxismapping"},
+ {-1, ""},
+};
+
+static XConfigSymTabRec ZMapTab[] =
+{
+ {XAXIS, "x"},
+ {YAXIS, "y"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeInputList
+
+XConfigInputPtr
+xconfigParsePointerSection (void)
+{
+ char *s, *s1, *s2;
+ int l;
+ int token;
+ PARSE_PROLOGUE (XConfigInputPtr, XConfigInputRec)
+
+ while ((token = xconfigGetToken (PointerTab)) != ENDSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case PROTOCOL:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Protocol");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("Protocol"),
+ val.str);
+ break;
+ case PDEVICE:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Device");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("Device"),
+ val.str);
+ break;
+ case EMULATE3:
+ ptr->options =
+ xconfigAddNewOption(ptr->options,
+ xconfigStrdup("Emulate3Buttons"),
+ NULL);
+ break;
+ case EM3TIMEOUT:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER || val.num < 0)
+ Error (POSITIVE_INT_MSG, "Emulate3Timeout");
+ s = xconfigULongToString(val.num);
+ ptr->options =
+ xconfigAddNewOption(ptr->options,
+ xconfigStrdup("Emulate3Timeout"),
+ s);
+ break;
+ case CHORDMIDDLE:
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("ChordMiddle"),
+ NULL);
+ break;
+ case PBUTTONS:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER || val.num < 0)
+ Error (POSITIVE_INT_MSG, "Buttons");
+ s = xconfigULongToString(val.num);
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("Buttons"), s);
+ break;
+ case BAUDRATE:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER || val.num < 0)
+ Error (POSITIVE_INT_MSG, "BaudRate");
+ s = xconfigULongToString(val.num);
+ ptr->options =
+ xconfigAddNewOption(ptr->options,
+ xconfigStrdup("BaudRate"), s);
+ break;
+ case SAMPLERATE:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER || val.num < 0)
+ Error (POSITIVE_INT_MSG, "SampleRate");
+ s = xconfigULongToString(val.num);
+ ptr->options =
+ xconfigAddNewOption(ptr->options,
+ xconfigStrdup("SampleRate"), s);
+ break;
+ case PRESOLUTION:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER || val.num < 0)
+ Error (POSITIVE_INT_MSG, "Resolution");
+ s = xconfigULongToString(val.num);
+ ptr->options =
+ xconfigAddNewOption(ptr->options,
+ xconfigStrdup("Resolution"), s);
+ break;
+ case CLEARDTR:
+ ptr->options =
+ xconfigAddNewOption(ptr->options,
+ xconfigStrdup("ClearDTR"), NULL);
+ break;
+ case CLEARRTS:
+ ptr->options =
+ xconfigAddNewOption(ptr->options,
+ xconfigStrdup("ClearRTS"), NULL);
+ break;
+ case ZAXISMAPPING:
+ switch (xconfigGetToken(ZMapTab)) {
+ case NUMBER:
+ if (val.num < 0)
+ Error (ZAXISMAPPING_MSG, NULL);
+ s1 = xconfigULongToString(val.num);
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER ||
+ val.num < 0)
+ Error (ZAXISMAPPING_MSG, NULL);
+ s2 = xconfigULongToString(val.num);
+ l = strlen(s1) + 1 + strlen(s2) + 1;
+ s = malloc(l);
+ sprintf(s, "%s %s", s1, s2);
+ free(s1);
+ free(s2);
+ break;
+ case XAXIS:
+ s = xconfigStrdup("x");
+ break;
+ case YAXIS:
+ s = xconfigStrdup("y");
+ break;
+ default:
+ Error (ZAXISMAPPING_MSG, NULL);
+ break;
+ }
+ ptr->options =
+ xconfigAddNewOption(ptr->options,
+ xconfigStrdup("ZAxisMapping"),
+ s);
+ break;
+ case ALWAYSCORE:
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ }
+
+ ptr->identifier = xconfigStrdup(CONF_IMPLICIT_POINTER);
+ ptr->driver = xconfigStrdup("mouse");
+ ptr->options = xconfigAddNewOption(ptr->options,
+ xconfigStrdup("CorePointer"), NULL);
+
+#ifdef DEBUG
+ xconfigErrorMsg(DebugMsg, "Pointer section parsed\n");
+#endif
+
+ return ptr;
+}
+
+#undef CLEANUP
+
diff --git a/XF86Config-parser/Read.c b/XF86Config-parser/Read.c
new file mode 100644
index 0000000..2983447
--- /dev/null
+++ b/XF86Config-parser/Read.c
@@ -0,0 +1,353 @@
+/*
+ *
+ * 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"
+
+extern LexRec val;
+
+static XConfigSymTabRec TopLevelTab[] =
+{
+ {SECTION, "section"},
+ {-1, ""},
+};
+
+
+#define CLEANUP xconfigFreeConfig
+
+#define READ_HANDLE_RETURN(f,func) \
+ if ((ptr->f=func) == NULL) { \
+ xconfigFreeConfig(ptr); \
+ return XCONFIG_RETURN_PARSE_ERROR; \
+ }
+
+#define READ_HANDLE_LIST(field,func,type) \
+{ \
+ type p = func(); \
+ if (p == NULL) { \
+ xconfigFreeConfig(ptr); \
+ return XCONFIG_RETURN_PARSE_ERROR; \
+ } else { \
+ ptr->field = (type) \
+ xconfigAddListItem((GenericListPtr) ptr->field, \
+ (GenericListPtr) p); \
+ } \
+}
+
+#define READ_ERROR(a,b) \
+ do { \
+ xconfigErrorMsg(ParseErrorMsg, a, b); \
+ xconfigFreeConfig(ptr); \
+ return XCONFIG_RETURN_PARSE_ERROR; \
+ } while (0) \
+
+
+
+/*
+ * xconfigReadConfigFile() - read the open XConfig file, returning the
+ * parsed data as XConfigPtr. The screenName argument is used
+ * during validation in the case that no layout was specified and we
+ * have to build an implicit layout and need to choose a screen.
+ */
+
+XConfigError xconfigReadConfigFile(const char *screenName, XConfigPtr *configPtr)
+{
+ int token;
+ XConfigPtr ptr = NULL;
+
+ *configPtr = NULL;
+
+ ptr = xconfigAlloc(sizeof(XConfigRec));
+
+ while ((token = xconfigGetToken(TopLevelTab)) != EOF_TOKEN) {
+
+ switch (token) {
+
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+
+ case SECTION:
+ if (xconfigGetSubToken(&(ptr->comment)) != STRING) {
+ xconfigErrorMsg(ParseErrorMsg, QUOTE_MSG, "Section");
+ xconfigFreeConfig(ptr);
+ return XCONFIG_RETURN_PARSE_ERROR;
+ }
+
+ xconfigSetSection(val.str);
+
+ if (xconfigNameCompare(val.str, "files") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_RETURN(files, xconfigParseFilesSection());
+ }
+ else if (xconfigNameCompare(val.str, "serverflags") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_RETURN(flags, xconfigParseFlagsSection());
+ }
+ else if (xconfigNameCompare(val.str, "keyboard") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_LIST(inputs, xconfigParseKeyboardSection,
+ XConfigInputPtr);
+ }
+ else if (xconfigNameCompare(val.str, "pointer") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_LIST(inputs, xconfigParsePointerSection,
+ XConfigInputPtr);
+ }
+ else if (xconfigNameCompare(val.str, "videoadaptor") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_LIST(videoadaptors,
+ xconfigParseVideoAdaptorSection,
+ XConfigVideoAdaptorPtr);
+ }
+ else if (xconfigNameCompare(val.str, "device") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_LIST(devices, xconfigParseDeviceSection,
+ XConfigDevicePtr);
+ }
+ else if (xconfigNameCompare(val.str, "monitor") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_LIST(monitors, xconfigParseMonitorSection,
+ XConfigMonitorPtr);
+ }
+ else if (xconfigNameCompare(val.str, "modes") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_LIST(modes, xconfigParseModesSection,
+ XConfigModesPtr);
+ }
+ else if (xconfigNameCompare(val.str, "screen") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_LIST(screens, xconfigParseScreenSection,
+ XConfigScreenPtr);
+ }
+ else if (xconfigNameCompare(val.str, "inputdevice") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_LIST(inputs, xconfigParseInputSection,
+ XConfigInputPtr);
+ }
+ else if (xconfigNameCompare(val.str, "module") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_RETURN(modules, xconfigParseModuleSection());
+ }
+ else if (xconfigNameCompare(val.str, "serverlayout") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_LIST(layouts, xconfigParseLayoutSection,
+ XConfigLayoutPtr);
+ }
+ else if (xconfigNameCompare(val.str, "vendor") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_LIST(vendors, xconfigParseVendorSection,
+ XConfigVendorPtr);
+ }
+ else if (xconfigNameCompare(val.str, "dri") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_RETURN(dri, xconfigParseDRISection());
+ }
+ else if (xconfigNameCompare (val.str, "extensions") == 0)
+ {
+ free(val.str);
+ val.str = NULL;
+ READ_HANDLE_RETURN(extensions, xconfigParseExtensionsSection());
+ }
+ else
+ {
+ READ_ERROR(INVALID_SECTION_MSG, xconfigTokenString());
+ free(val.str);
+ val.str = NULL;
+ }
+ break;
+
+ default:
+ READ_ERROR(INVALID_KEYWORD_MSG, xconfigTokenString());
+ free(val.str);
+ val.str = NULL;
+ }
+ }
+
+ if (xconfigValidateConfig(ptr, screenName)) {
+ ptr->filename = strdup(xconfigGetConfigFileName());
+ *configPtr = ptr;
+ return XCONFIG_RETURN_SUCCESS;
+ } else {
+ xconfigFreeConfig(ptr);
+ return XCONFIG_RETURN_VALIDATION_ERROR;
+ }
+}
+
+#undef CLEANUP
+
+
+/*
+ * This function resolves name references and reports errors if the named
+ * objects cannot be found.
+ */
+
+int xconfigValidateConfig(XConfigPtr p, const char *screenName)
+{
+ if (!xconfigValidateDevice(p))
+ return FALSE;
+ if (!xconfigValidateScreen(p))
+ return FALSE;
+ if (!xconfigValidateInput(p))
+ return FALSE;
+ if (!xconfigValidateLayout(p, screenName))
+ return FALSE;
+
+ return(TRUE);
+}
+
+
+/*
+ * adds an item to the end of the linked list. Any record whose first field
+ * is a GenericListRec can be cast to this type and used with this function.
+ * A pointer to the head of the list is returned to handle the addition of
+ * the first item.
+ */
+GenericListPtr
+xconfigAddListItem (GenericListPtr head, GenericListPtr new)
+{
+ GenericListPtr p = head;
+ GenericListPtr last = NULL;
+
+ while (p)
+ {
+ last = p;
+ p = p->next;
+ }
+
+ if (last)
+ {
+ last->next = new;
+ return (head);
+ }
+ else
+ return (new);
+}
+
+/*
+ * Test if one chained list contains the other.
+ * In this case both list have the same endpoint (provided they don't loop)
+ */
+int
+xconfigItemNotSublist(GenericListPtr list_1, GenericListPtr list_2)
+{
+ GenericListPtr p = list_1;
+ GenericListPtr last_1 = NULL, last_2 = NULL;
+
+ while (p) {
+ last_1 = p;
+ p = p->next;
+ }
+
+ p = list_2;
+ while (p) {
+ last_2 = p;
+ p = p->next;
+ }
+
+ return (!(last_1 == last_2));
+}
+
+void
+xconfigFreeConfig (XConfigPtr p)
+{
+ if (p == NULL)
+ return;
+
+ xconfigFreeFiles (p->files);
+ xconfigFreeModules (p->modules);
+ xconfigFreeFlags (p->flags);
+ xconfigFreeMonitorList (p->monitors);
+ xconfigFreeModesList (p->modes);
+ xconfigFreeVideoAdaptorList (p->videoadaptors);
+ xconfigFreeDeviceList (p->devices);
+ xconfigFreeScreenList (p->screens);
+ xconfigFreeLayoutList (p->layouts);
+ xconfigFreeInputList (p->inputs);
+ xconfigFreeVendorList (p->vendors);
+ xconfigFreeDRI (p->dri);
+ TEST_FREE(p->comment);
+
+ free (p);
+}
diff --git a/XF86Config-parser/Scan.c b/XF86Config-parser/Scan.c
new file mode 100644
index 0000000..e57a3d1
--- /dev/null
+++ b/XF86Config-parser/Scan.c
@@ -0,0 +1,946 @@
+/*
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#if !defined(X_NOT_POSIX)
+#if defined(_POSIX_SOURCE)
+#include <limits.h>
+#else
+#define _POSIX_SOURCE
+#include <limits.h>
+#undef _POSIX_SOURCE
+#endif /* _POSIX_SOURCE */
+#endif /* !X_NOT_POSIX */
+#if !defined(PATH_MAX)
+#if defined(MAXPATHLEN)
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 1024
+#endif /* MAXPATHLEN */
+#endif /* !PATH_MAX */
+
+#if !defined(MAXHOSTNAMELEN)
+#define MAXHOSTNAMELEN 32
+#endif /* !MAXHOSTNAMELEN */
+
+#include "Configint.h"
+#include "xf86tokens.h"
+
+#define CONFIG_BUF_LEN 1024
+
+static int StringToToken (char *, XConfigSymTabRec *);
+
+static FILE *configFile = NULL;
+static const char **builtinConfig = NULL;
+static int builtinIndex = 0;
+static int configPos = 0; /* current readers position */
+static char *configBuf, *configRBuf; /* buffer for lines */
+static int pushToken = LOCK_TOKEN;
+static int eol_seen = 0; /* private state to handle comments */
+LexRec val;
+
+int configLineNo = 0; /* linenumber */
+char *configSection = NULL; /* name of current section being parsed */
+char *configPath; /* path to config file */
+
+
+
+
+static int xconfigIsAlpha(char c)
+{
+ return (((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')));
+}
+
+static int xconfigIsDigit(char c)
+{
+ return ((c >= '0') && (c <= '9'));
+}
+
+static int xconfigIsUpper(char c)
+{
+ return ((c >= 'A') && (c <= 'Z'));
+}
+
+static char xconfigToLower(char c)
+{
+ if ((c >= 'A') && (c <= 'Z')) {
+ return c + ('a' - 'A');
+ } else {
+ return c;
+ }
+}
+
+
+/*
+ * xconfigStrToUL --
+ *
+ * A portable, but restricted, version of strtoul(). It only understands
+ * hex, octal, and decimal. But it's good enough for our needs.
+ */
+
+static unsigned int xconfigStrToUL (char *str)
+{
+ int base = 10;
+ char *p = str;
+ unsigned int tot = 0;
+
+ if (*p == '0')
+ {
+ p++;
+ if ((*p == 'x') || (*p == 'X'))
+ {
+ p++;
+ base = 16;
+ }
+ else
+ base = 8;
+ }
+ while (*p)
+ {
+ if ((*p >= '0') && (*p <= ((base == 8) ? '7' : '9')))
+ {
+ tot = tot * base + (*p - '0');
+ }
+ else if ((base == 16) && (*p >= 'a') && (*p <= 'f'))
+ {
+ tot = tot * base + 10 + (*p - 'a');
+ }
+ else if ((base == 16) && (*p >= 'A') && (*p <= 'F'))
+ {
+ tot = tot * base + 10 + (*p - 'A');
+ }
+ else
+ {
+ return (tot);
+ }
+ p++;
+ }
+ return (tot);
+}
+
+
+
+/*
+ * xconfigGetToken --
+ * Read next Token form the config file. Handle the global variable
+ * pushToken.
+ */
+
+int xconfigGetToken (XConfigSymTabRec * tab)
+{
+ int c, i;
+
+ /*
+ * First check whether pushToken has a different value than LOCK_TOKEN.
+ * In this case rBuf[] contains a valid STRING/TOKEN/NUMBER. But in the
+ * oth * case the next token must be read from the input.
+ */
+ if (pushToken == EOF_TOKEN)
+ return (EOF_TOKEN);
+ else if (pushToken == LOCK_TOKEN)
+ {
+ /*
+ * eol_seen is only set for the first token after a newline.
+ */
+ eol_seen = 0;
+
+ c = configBuf[configPos];
+
+ /*
+ * Get start of next Token. EOF is handled,
+ * whitespaces are skipped.
+ */
+
+again:
+ if (!c)
+ {
+ char *ret;
+ if (configFile)
+ ret = fgets (configBuf, CONFIG_BUF_LEN - 1, configFile);
+ else {
+ if (builtinConfig[builtinIndex] == NULL)
+ ret = NULL;
+ else {
+ ret = strncpy(configBuf, builtinConfig[builtinIndex],
+ CONFIG_BUF_LEN);
+ builtinIndex++;
+ }
+ }
+ if (ret == NULL)
+ {
+ return (pushToken = EOF_TOKEN);
+ }
+ configLineNo++;
+ configPos = 0;
+ eol_seen = 1;
+ }
+
+ i = 0;
+ for (;;) {
+ c = configBuf[configPos++];
+ configRBuf[i++] = c;
+ switch (c) {
+ case ' ':
+ case '\t':
+ case '\r':
+ continue;
+ case '\n':
+ i = 0;
+ continue;
+ }
+ break;
+ }
+ if (c == '\0')
+ goto again;
+
+ if (c == '#')
+ {
+ do
+ {
+ configRBuf[i++] = (c = configBuf[configPos++]);
+ }
+ while ((c != '\n') && (c != '\r') && (c != '\0'));
+ configRBuf[i] = '\0';
+ /* XXX no private copy.
+ * Use xconfigAddComment when setting a comment.
+ */
+ val.str = configRBuf;
+ return (COMMENT);
+ }
+
+ /* GJA -- handle '-' and ',' * Be careful: "-hsync" is a keyword. */
+ else if ((c == ',') && !xconfigIsAlpha(configBuf[configPos]))
+ {
+ return COMMA;
+ }
+ else if ((c == '-') && !xconfigIsAlpha(configBuf[configPos]))
+ {
+ return DASH;
+ }
+
+ /*
+ * Numbers are returned immediately ...
+ */
+ if (xconfigIsDigit(c))
+ {
+ int base;
+
+ if (c == '0')
+ if ((configBuf[configPos] == 'x') ||
+ (configBuf[configPos] == 'X'))
+ base = 16;
+ else
+ base = 8;
+ else
+ base = 10;
+
+ configRBuf[0] = c;
+ i = 1;
+ while (xconfigIsDigit(c = configBuf[configPos++]) ||
+ (c == '.') || (c == 'x') || (c == 'X') ||
+ ((base == 16) && (((c >= 'a') && (c <= 'f')) ||
+ ((c >= 'A') && (c <= 'F')))))
+ configRBuf[i++] = c;
+ configPos--; /* GJA -- one too far */
+ configRBuf[i] = '\0';
+ val.num = xconfigStrToUL (configRBuf);
+ val.realnum = atof (configRBuf);
+ return (NUMBER);
+ }
+
+ /*
+ * All Strings START with a \" ...
+ */
+ else if (c == '\"')
+ {
+ i = -1;
+ do
+ {
+ configRBuf[++i] = (c = configBuf[configPos++]);
+ }
+ while ((c != '\"') && (c != '\n') && (c != '\r') && (c != '\0'));
+ configRBuf[i] = '\0';
+ val.str = malloc (strlen (configRBuf) + 1);
+ strcpy (val.str, configRBuf); /* private copy ! */
+ return (STRING);
+ }
+
+ /*
+ * ... and now we MUST have a valid token. The search is
+ * handled later along with the pushed tokens.
+ */
+ else
+ {
+ configRBuf[0] = c;
+ i = 0;
+ do
+ {
+ configRBuf[++i] = (c = configBuf[configPos++]);;
+ }
+ while ((c != ' ') &&
+ (c != '\t') &&
+ (c != '\n') &&
+ (c != '\r') &&
+ (c != '\0') &&
+ (c != '#'));
+
+ --configPos;
+ configRBuf[i] = '\0';
+ i = 0;
+ }
+
+ }
+ else
+ {
+
+ /*
+ * Here we deal with pushed tokens. Reinitialize pushToken again. If
+ * the pushed token was NUMBER || STRING return them again ...
+ */
+ int temp = pushToken;
+ pushToken = LOCK_TOKEN;
+
+ if (temp == COMMA || temp == DASH)
+ return (temp);
+ if (temp == NUMBER || temp == STRING)
+ return (temp);
+ }
+
+ /*
+ * Joop, at last we have to lookup the token ...
+ */
+ if (tab)
+ {
+ i = 0;
+ while (tab[i].token != -1)
+ if (xconfigNameCompare (configRBuf, tab[i].name) == 0)
+ return (tab[i].token);
+ else
+ i++;
+ }
+
+ return (ERROR_TOKEN); /* Error catcher */
+}
+
+int xconfigGetSubToken (char **comment)
+{
+ int token;
+
+ for (;;) {
+ token = xconfigGetToken(NULL);
+ if (token == COMMENT) {
+ if (comment)
+ *comment = xconfigAddComment(*comment, val.str);
+ }
+ else
+ return (token);
+ }
+ /*NOTREACHED*/
+}
+
+int xconfigGetSubTokenWithTab (char **comment, XConfigSymTabRec *tab)
+{
+ int token;
+
+ for (;;) {
+ token = xconfigGetToken(tab);
+ if (token == COMMENT) {
+ if (comment)
+ *comment = xconfigAddComment(*comment, val.str);
+ }
+ else
+ return (token);
+ }
+ /*NOTREACHED*/
+}
+
+void xconfigUnGetToken (int token)
+{
+ pushToken = token;
+}
+
+char *xconfigTokenString (void)
+{
+ return configRBuf;
+}
+
+static int pathIsAbsolute(const char *path)
+{
+ if (path && path[0] == '/')
+ return 1;
+ return 0;
+}
+
+/* A path is "safe" if it is relative and if it contains no ".." elements. */
+static int pathIsSafe(const char *path)
+{
+ if (pathIsAbsolute(path))
+ return 0;
+
+ /* Compare with ".." */
+ if (!strcmp(path, ".."))
+ return 0;
+
+ /* Look for leading "../" */
+ if (!strncmp(path, "../", 3))
+ return 0;
+
+ /* Look for trailing "/.." */
+ if ((strlen(path) > 3) && !strcmp(path + strlen(path) - 3, "/.."))
+ return 0;
+
+ /* Look for "/../" */
+ if (strstr(path, "/../"))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * This function substitutes the following escape sequences:
+ *
+ * %A cmdline argument as an absolute path (must be absolute to match)
+ * %R cmdline argument as a relative path
+ * %S cmdline argument as a "safe" path (relative, and no ".." elements)
+ * %X default config file name ("XF86Config")
+ * %H hostname
+ * %E config file environment ($XF86CONFIG) as an absolute path
+ * %F config file environment ($XF86CONFIG) as a relative path
+ * %G config file environment ($XF86CONFIG) as a safe path
+ * %D $HOME
+ * %P projroot
+ * %M major version number
+ * %% %
+ * %& UNIXOS2 only: prepend X11ROOT env var
+ */
+
+#ifndef XCONFIGFILE
+#define XCONFIGFILE "xorg.conf"
+#endif
+#ifndef PROJECTROOT
+#define PROJECTROOT "/usr/X11R6"
+#endif
+#ifndef XCONFENV
+#define XCONFENV "XF86CONFIG"
+#endif
+#define XFREE86CFGFILE "XF86Config"
+#ifndef X_VERSION_MAJOR
+#ifdef XVERSION
+#if XVERSION > 40000000
+#define X_VERSION_MAJOR (XVERSION / 10000000)
+#else
+#define X_VERSION_MAJOR (XVERSION / 1000)
+#endif
+#else
+#define X_VERSION_MAJOR 4
+#endif
+#endif
+
+#define BAIL_OUT do { \
+ free(result); \
+ return NULL; \
+ } while (0)
+
+#define CHECK_LENGTH do { \
+ if (l > PATH_MAX) { \
+ BAIL_OUT; \
+ } \
+ } while (0)
+
+#define APPEND_STR(s) do { \
+ if (strlen(s) + l > PATH_MAX) { \
+ BAIL_OUT; \
+ } else { \
+ strcpy(result + l, s); \
+ l += strlen(s); \
+ } \
+ } while (0)
+
+static char *DoSubstitution(const char *template,
+ const char *cmdline,
+ const char *projroot,
+ int *cmdlineUsed, int *envUsed, char *XConfigFile)
+{
+ char *result;
+ int i, l;
+ static const char *env = NULL, *home = NULL;
+ static char *hostname = NULL;
+ static char majorvers[3] = "";
+
+ if (!template)
+ return NULL;
+
+ if (cmdlineUsed)
+ *cmdlineUsed = 0;
+ if (envUsed)
+ *envUsed = 0;
+
+ result = malloc(PATH_MAX + 1);
+ l = 0;
+ for (i = 0; template[i]; i++) {
+ if (template[i] != '%') {
+ result[l++] = template[i];
+ CHECK_LENGTH;
+ } else {
+ switch (template[++i]) {
+ case 'A':
+ if (cmdline && pathIsAbsolute(cmdline)) {
+ APPEND_STR(cmdline);
+ if (cmdlineUsed)
+ *cmdlineUsed = 1;
+ } else
+ BAIL_OUT;
+ break;
+ case 'R':
+ if (cmdline && !pathIsAbsolute(cmdline)) {
+ APPEND_STR(cmdline);
+ if (cmdlineUsed)
+ *cmdlineUsed = 1;
+ } else
+ BAIL_OUT;
+ break;
+ case 'S':
+ if (cmdline && pathIsSafe(cmdline)) {
+ APPEND_STR(cmdline);
+ if (cmdlineUsed)
+ *cmdlineUsed = 1;
+ } else
+ BAIL_OUT;
+ break;
+ case 'X':
+ APPEND_STR(XConfigFile);
+ break;
+ case 'H':
+ if (!hostname) {
+ if ((hostname = malloc(MAXHOSTNAMELEN + 1))) {
+ if (gethostname(hostname, MAXHOSTNAMELEN) == 0) {
+ hostname[MAXHOSTNAMELEN] = '\0';
+ } else {
+ free(hostname);
+ hostname = NULL;
+ }
+ }
+ }
+ if (hostname)
+ APPEND_STR(hostname);
+ break;
+ case 'E':
+ if (!env)
+ env = getenv(XCONFENV);
+ if (env && pathIsAbsolute(env)) {
+ APPEND_STR(env);
+ if (envUsed)
+ *envUsed = 1;
+ } else
+ BAIL_OUT;
+ break;
+ case 'F':
+ if (!env)
+ env = getenv(XCONFENV);
+ if (env && !pathIsAbsolute(env)) {
+ APPEND_STR(env);
+ if (envUsed)
+ *envUsed = 1;
+ } else
+ BAIL_OUT;
+ break;
+ case 'G':
+ if (!env)
+ env = getenv(XCONFENV);
+ if (env && pathIsSafe(env)) {
+ APPEND_STR(env);
+ if (envUsed)
+ *envUsed = 1;
+ } else
+ BAIL_OUT;
+ break;
+ case 'D':
+ if (!home)
+ home = getenv("HOME");
+ if (home && pathIsAbsolute(home))
+ APPEND_STR(home);
+ else
+ BAIL_OUT;
+ break;
+ case 'P':
+ if (projroot && pathIsAbsolute(projroot))
+ APPEND_STR(projroot);
+ else
+ BAIL_OUT;
+ break;
+ case 'M':
+ if (!majorvers[0]) {
+ sprintf(majorvers, "%d", X_VERSION_MAJOR);
+ }
+ APPEND_STR(majorvers);
+ break;
+ case '%':
+ result[l++] = '%';
+ CHECK_LENGTH;
+ break;
+ default:
+ xconfigErrorMsg(InternalErrorMsg,
+ "invalid escape %%%c found in path template\n",
+ template[i]);
+ BAIL_OUT;
+ break;
+ }
+ }
+ }
+ return result;
+}
+
+/*
+ * xconfigOpenConfigFile --
+ *
+ * This function takes a config file search path (optional), a
+ * command-line specified file name (optional) and the ProjectRoot
+ * path (optional) and locates and opens a config file based on that
+ * information. If a command-line file name is specified, then this
+ * function fails if none of the located files.
+ *
+ * The return value is a pointer to the actual name of the file that
+ * was opened. When no file is found, the return value is NULL.
+ *
+ * The escape sequences allowed in the search path are defined above.
+ *
+ */
+
+
+/*
+ * __root_configpath[] - this is the XconfigConfig search path used by
+ * XFree86 when the server runs as root.
+ */
+
+static const char __root_configpath[] =
+"%A," /* <cmdline> */
+"%R," /* <cmdline> (as relative path) */
+"/etc/X11/%R," /* /etc/X11/<cmdline> */
+"%P/etc/X11/%R," /* /usr/X11R6/etc/X11/<cmdline> */
+"%E," /* $XF86CONFIG */
+"%F," /* $XF86CONFIG (as relative path) */
+"/etc/X11/%F," /* /etc/X11/$XF86CONFIG */
+"%P/etc/X11/%F," /* /usr/X11R6/etc/X11/$XF86CONFIG */
+"%D/%X," /* $HOME/XF86Config */
+"/etc/X11/%X-%M," /* /etc/X11/XF86Config-4 */
+"/etc/X11/%X," /* /etc/X11/XF86Config */
+"/etc/%X," /* /etc/XF86Config */
+"%P/etc/X11/%X.%H," /* /usr/X11R6/etc/X11/XF86Config.<hostname> */
+"%P/etc/X11/%X-%M," /* /usr/X11R6/etc/X11/XF86Config-4 */
+"%P/etc/X11/%X," /* /usr/X11R6/etc/X11/XF86Config */
+"%P/lib/X11/%X.%H," /* /usr/X11R6/lib/X11/XF86Config.<hostname> */
+"%P/lib/X11/%X-%M," /* /usr/X11R6/lib/X11/XF86Config-4 */
+"%P/lib/X11/%X"; /* /usr/X11R6/lib/X11/XF86Config */
+
+
+
+/*
+ * __user_configpath[] - this is the XF86Config search path used by
+ * XFree86 when the server runs as a normal user
+ */
+
+static const char __user_configpath[] =
+"%A," /* <cmdline> XXX */
+"%R," /* <cmdline> (as relative path) XXX */
+"/etc/X11/%S," /* /etc/X11/<cmdline> */
+"%P/etc/X11/%S," /* /usr/X11R6/etc/X11/<cmdline> */
+"/etc/X11/%G," /* /etc/X11/$XF86CONFIG */
+"%P/etc/X11/%G," /* /usr/X11R6/etc/X11/$XF86CONFIG */
+"/etc/X11/%X-%M," /* /etc/X11/XF86Config-4 */
+"/etc/X11/%X," /* /etc/X11/XF86Config */
+"/etc/%X," /* /etc/XF86Config */
+"%P/etc/X11/%X.%H," /* /usr/X11R6/etc/X11/XF86Config.<hostname> */
+"%P/etc/X11/%X-%M," /* /usr/X11R6/etc/X11/XF86Config-4 */
+"%P/etc/X11/%X," /* /usr/X11R6/etc/X11/XF86Config */
+"%P/lib/X11/%X.%H," /* /usr/X11R6/lib/X11/XF86Config.<hostname> */
+"%P/lib/X11/%X-%M," /* /usr/X11R6/lib/X11/XF86Config-4 */
+"%P/lib/X11/%X"; /* /usr/X11R6/lib/X11/XF86Config */
+
+
+
+const char *xconfigOpenConfigFile(const char *cmdline, const char *projroot)
+{
+ const char *searchpath;
+ char *pathcopy;
+ const char *template;
+ int cmdlineUsed = 0;
+
+ configFile = NULL;
+ configPos = 0; /* current readers position */
+ configLineNo = 0; /* linenumber */
+ pushToken = LOCK_TOKEN;
+
+ /*
+ * select the search path: XFree86 uses a slightly different path
+ * depending on whether the user is root
+ */
+
+ if (getuid() == 0) {
+ searchpath = __root_configpath;
+ } else {
+ searchpath = __user_configpath;
+ }
+
+ if (!projroot) projroot = PROJECTROOT;
+
+ pathcopy = strdup(searchpath);
+
+ template = strtok(pathcopy, ",");
+
+ /* First, search for a config file. */
+ while (template && !configFile) {
+ if ((configPath = DoSubstitution(template, cmdline, projroot,
+ &cmdlineUsed, NULL, XCONFIGFILE))) {
+ if ((configFile = fopen(configPath, "r")) != 0) {
+ if (cmdline && !cmdlineUsed) {
+ fclose(configFile);
+ configFile = NULL;
+ }
+ }
+ }
+ if (configPath && !configFile) {
+ free(configPath);
+ configPath = NULL;
+ }
+ template = strtok(NULL, ",");
+ }
+
+ /* Then search for fallback */
+ if (!configFile) {
+ strcpy(pathcopy, searchpath);
+ template = strtok(pathcopy, ",");
+
+ while (template && !configFile) {
+ if ((configPath = DoSubstitution(template, cmdline, projroot,
+ &cmdlineUsed, NULL,
+ XFREE86CFGFILE))) {
+ if ((configFile = fopen(configPath, "r")) != 0) {
+ if (cmdline && !cmdlineUsed) {
+ fclose(configFile);
+ configFile = NULL;
+ }
+ }
+ }
+ if (configPath && !configFile) {
+ free(configPath);
+ configPath = NULL;
+ }
+ template = strtok(NULL, ",");
+ }
+ }
+
+ free(pathcopy);
+
+ if (!configFile) {
+ return NULL;
+ }
+
+ configBuf = malloc(CONFIG_BUF_LEN);
+ configRBuf = malloc(CONFIG_BUF_LEN);
+ configBuf[0] = '\0';
+
+ return configPath;
+}
+
+void xconfigCloseConfigFile (void)
+{
+ free (configPath);
+ configPath = NULL;
+ free (configRBuf);
+ configRBuf = NULL;
+ free (configBuf);
+ configBuf = NULL;
+
+ if (configFile) {
+ fclose (configFile);
+ configFile = NULL;
+ } else {
+ builtinConfig = NULL;
+ builtinIndex = 0;
+ }
+}
+
+
+char *xconfigGetConfigFileName(void)
+{
+ return configPath;
+}
+
+
+void
+xconfigSetSection (char *section)
+{
+ if (configSection)
+ free(configSection);
+ configSection = malloc(strlen (section) + 1);
+ strcpy (configSection, section);
+}
+
+/*
+ * xconfigGetToken --
+ * Lookup a string if it is actually a token in disguise.
+ */
+
+
+char *
+xconfigAddComment(char *cur, char *add)
+{
+ char *str;
+ int len, curlen, iscomment, hasnewline = 0, endnewline;
+
+ if (add == NULL || add[0] == '\0')
+ return (cur);
+
+ if (cur) {
+ curlen = strlen(cur);
+ if (curlen)
+ hasnewline = cur[curlen - 1] == '\n';
+ eol_seen = 0;
+ }
+ else
+ curlen = 0;
+
+ str = add;
+ iscomment = 0;
+ while (*str) {
+ if (*str != ' ' && *str != '\t')
+ break;
+ ++str;
+ }
+ iscomment = (*str == '#');
+
+ len = strlen(add);
+ endnewline = add[len - 1] == '\n';
+ len += 1 + iscomment + (!hasnewline) + (!endnewline) + eol_seen;
+
+ if ((str = realloc(cur, len + curlen)) == NULL)
+ return (cur);
+
+ cur = str;
+
+ if (eol_seen || (curlen && !hasnewline))
+ cur[curlen++] = '\n';
+ if (!iscomment)
+ cur[curlen++] = '#';
+ strcpy(cur + curlen, add);
+ if (!endnewline)
+ strcat(cur, "\n");
+
+ return (cur);
+}
+
+int
+xconfigGetStringToken (XConfigSymTabRec * tab)
+{
+ return StringToToken (val.str, tab);
+}
+
+static int
+StringToToken (char *str, XConfigSymTabRec * tab)
+{
+ int i;
+
+ for (i = 0; tab[i].token != -1; i++)
+ {
+ if (!xconfigNameCompare (tab[i].name, str))
+ return tab[i].token;
+ }
+ return (ERROR_TOKEN);
+}
+
+
+/*
+ * Compare two names. The characters '_', ' ', and '\t' are ignored
+ * in the comparison.
+ */
+int
+xconfigNameCompare (const char *s1, const char *s2)
+{
+ char c1, c2;
+
+ if (!s1 || *s1 == 0) {
+ if (!s2 || *s2 == 0)
+ return (0);
+ else
+ return (1);
+ }
+
+ while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
+ s1++;
+ while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
+ s2++;
+ c1 = (xconfigIsUpper(*s1) ? xconfigToLower(*s1) : *s1);
+ c2 = (xconfigIsUpper(*s2) ? xconfigToLower(*s2) : *s2);
+ while (c1 == c2)
+ {
+ if (c1 == '\0')
+ return (0);
+ s1++;
+ s2++;
+ while (*s1 == '_' || *s1 == ' ' || *s1 == '\t')
+ s1++;
+ while (*s2 == '_' || *s2 == ' ' || *s2 == '\t')
+ s2++;
+ c1 = (xconfigIsUpper(*s1) ? xconfigToLower(*s1) : *s1);
+ c2 = (xconfigIsUpper(*s2) ? xconfigToLower(*s2) : *s2);
+ }
+ return (c1 - c2);
+}
diff --git a/XF86Config-parser/Screen.c b/XF86Config-parser/Screen.c
new file mode 100644
index 0000000..62e4730
--- /dev/null
+++ b/XF86Config-parser/Screen.c
@@ -0,0 +1,617 @@
+/*
+ *
+ * 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).
+ */
+
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+extern LexRec val;
+
+static XConfigSymTabRec DisplayTab[] =
+{
+ {ENDSUBSECTION, "endsubsection"},
+ {MODES, "modes"},
+ {VIEWPORT, "viewport"},
+ {VIRTUAL, "virtual"},
+ {VISUAL, "visual"},
+ {BLACK_TOK, "black"},
+ {WHITE_TOK, "white"},
+ {DEPTH, "depth"},
+ {BPP, "fbbpp"},
+ {WEIGHT, "weight"},
+ {OPTION, "option"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeDisplayList
+
+XConfigDisplayPtr
+xconfigParseDisplaySubSection (void)
+{
+ int token;
+ PARSE_PROLOGUE (XConfigDisplayPtr, XConfigDisplayRec)
+
+ ptr->black.red = ptr->black.green = ptr->black.blue = -1;
+ ptr->white.red = ptr->white.green = ptr->white.blue = -1;
+ ptr->frameX0 = ptr->frameY0 = -1;
+ while ((token = xconfigGetToken (DisplayTab)) != ENDSUBSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case VIEWPORT:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (VIEWPORT_MSG, NULL);
+ ptr->frameX0 = val.num;
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (VIEWPORT_MSG, NULL);
+ ptr->frameY0 = val.num;
+ break;
+ case VIRTUAL:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (VIRTUAL_MSG, NULL);
+ ptr->virtualX = val.num;
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (VIRTUAL_MSG, NULL);
+ ptr->virtualY = val.num;
+ break;
+ case DEPTH:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "Display");
+ ptr->depth = val.num;
+ break;
+ case BPP:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "Display");
+ ptr->bpp = val.num;
+ break;
+ case VISUAL:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Display");
+ ptr->visual = val.str;
+ break;
+ case WEIGHT:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (WEIGHT_MSG, NULL);
+ ptr->weight.red = val.num;
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (WEIGHT_MSG, NULL);
+ ptr->weight.green = val.num;
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (WEIGHT_MSG, NULL);
+ ptr->weight.blue = val.num;
+ break;
+ case BLACK_TOK:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (BLACK_MSG, NULL);
+ ptr->black.red = val.num;
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (BLACK_MSG, NULL);
+ ptr->black.green = val.num;
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (BLACK_MSG, NULL);
+ ptr->black.blue = val.num;
+ break;
+ case WHITE_TOK:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (WHITE_MSG, NULL);
+ ptr->white.red = val.num;
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (WHITE_MSG, NULL);
+ ptr->white.green = val.num;
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (WHITE_MSG, NULL);
+ ptr->white.blue = val.num;
+ break;
+ case MODES:
+ {
+ XConfigModePtr mptr;
+
+ while ((token =
+ xconfigGetSubTokenWithTab(&(ptr->comment),
+ DisplayTab)) == STRING)
+ {
+ mptr = calloc (1, sizeof (XConfigModeRec));
+ mptr->mode_name = val.str;
+ mptr->next = NULL;
+ ptr->modes = (XConfigModePtr)
+ xconfigAddListItem ((GenericListPtr) ptr->modes,
+ (GenericListPtr) mptr);
+ }
+ xconfigUnGetToken (token);
+ }
+ 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;
+ }
+ }
+
+#ifdef DEBUG
+ xconfigErrorMsg(DebugMsg, "Display subsection parsed\n");
+#endif
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+static XConfigSymTabRec ScreenTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {IDENTIFIER, "identifier"},
+ {OBSDRIVER, "driver"},
+ {MDEVICE, "device"},
+ {MONITOR, "monitor"},
+ {VIDEOADAPTOR, "videoadaptor"},
+ {SCREENNO, "screenno"},
+ {SUBSECTION, "subsection"},
+ {DEFAULTDEPTH, "defaultcolordepth"},
+ {DEFAULTDEPTH, "defaultdepth"},
+ {DEFAULTBPP, "defaultbpp"},
+ {DEFAULTFBBPP, "defaultfbbpp"},
+ {OPTION, "option"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeScreenList
+XConfigScreenPtr
+xconfigParseScreenSection (void)
+{
+ int has_ident = FALSE;
+ int has_driver= FALSE;
+ int token;
+
+ PARSE_PROLOGUE (XConfigScreenPtr, XConfigScreenRec)
+
+ while ((token = xconfigGetToken (ScreenTab)) != ENDSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case IDENTIFIER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Identifier");
+ ptr->identifier = val.str;
+ if (has_ident || has_driver)
+ Error (ONLY_ONE_MSG,"Identifier or Driver");
+ has_ident = TRUE;
+ break;
+ case OBSDRIVER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Driver");
+ ptr->obsolete_driver = val.str;
+ if (has_ident || has_driver)
+ Error (ONLY_ONE_MSG,"Identifier or Driver");
+ has_driver = TRUE;
+ break;
+ case DEFAULTDEPTH:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "DefaultDepth");
+ ptr->defaultdepth = val.num;
+ break;
+ case DEFAULTBPP:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "DefaultBPP");
+ ptr->defaultbpp = val.num;
+ break;
+ case DEFAULTFBBPP:
+ if (xconfigGetSubToken (&(ptr->comment)) != NUMBER)
+ Error (NUMBER_MSG, "DefaultFbBPP");
+ ptr->defaultfbbpp = val.num;
+ break;
+ case MDEVICE:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Device");
+ ptr->device_name = val.str;
+ break;
+ case MONITOR:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Monitor");
+ ptr->monitor_name = val.str;
+ break;
+ case VIDEOADAPTOR:
+ {
+ XConfigAdaptorLinkPtr aptr;
+
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "VideoAdaptor");
+
+ /* Don't allow duplicates */
+ for (aptr = ptr->adaptors; aptr;
+ aptr = (XConfigAdaptorLinkPtr) aptr->next)
+ if (xconfigNameCompare (val.str, aptr->adaptor_name) == 0)
+ break;
+
+ if (aptr == NULL)
+ {
+ aptr = calloc (1, sizeof (XConfigAdaptorLinkRec));
+ aptr->next = NULL;
+ aptr->adaptor_name = val.str;
+ ptr->adaptors = (XConfigAdaptorLinkPtr)
+ xconfigAddListItem ((GenericListPtr) ptr->adaptors,
+ (GenericListPtr) aptr);
+ }
+ }
+ break;
+ case OPTION:
+ ptr->options = xconfigParseOption(ptr->options);
+ break;
+ case SUBSECTION:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "SubSection");
+ {
+ free(val.str);
+ HANDLE_LIST (displays, xconfigParseDisplaySubSection,
+ XConfigDisplayPtr);
+ }
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ }
+
+ if (!has_ident && !has_driver)
+ Error (NO_IDENT_MSG, NULL);
+
+#ifdef DEBUG
+ xconfigErrorMsg(DebugMsg, "Screen section parsed\n");
+#endif
+
+ return ptr;
+}
+
+void
+xconfigPrintScreenSection (FILE * cf, XConfigScreenPtr ptr)
+{
+ XConfigAdaptorLinkPtr aptr;
+ XConfigDisplayPtr dptr;
+ XConfigModePtr mptr;
+
+ while (ptr)
+ {
+ fprintf (cf, "Section \"Screen\"\n");
+ if (ptr->comment)
+ fprintf (cf, "%s", ptr->comment);
+ if (ptr->identifier)
+ fprintf (cf, " Identifier \"%s\"\n", ptr->identifier);
+ if (ptr->obsolete_driver)
+ fprintf (cf, " Driver \"%s\"\n", ptr->obsolete_driver);
+ if (ptr->device_name)
+ fprintf (cf, " Device \"%s\"\n", ptr->device_name);
+ if (ptr->monitor_name)
+ fprintf (cf, " Monitor \"%s\"\n", ptr->monitor_name);
+ if (ptr->defaultdepth)
+ fprintf (cf, " DefaultDepth %d\n",
+ ptr->defaultdepth);
+ if (ptr->defaultbpp)
+ fprintf (cf, " DefaultBPP %d\n",
+ ptr->defaultbpp);
+ if (ptr->defaultfbbpp)
+ fprintf (cf, " DefaultFbBPP %d\n",
+ ptr->defaultfbbpp);
+ xconfigPrintOptionList(cf, ptr->options, 1);
+ for (aptr = ptr->adaptors; aptr; aptr = aptr->next)
+ {
+ fprintf (cf, " VideoAdaptor \"%s\"\n", aptr->adaptor_name);
+ }
+ for (dptr = ptr->displays; dptr; dptr = dptr->next)
+ {
+ fprintf (cf, " SubSection \"Display\"\n");
+ if (dptr->comment)
+ fprintf (cf, "%s", dptr->comment);
+ if (dptr->frameX0 >= 0 || dptr->frameY0 >= 0)
+ {
+ fprintf (cf, " Viewport %d %d\n",
+ dptr->frameX0, dptr->frameY0);
+ }
+ if (dptr->virtualX != 0 || dptr->virtualY != 0)
+ {
+ fprintf (cf, " Virtual %d %d\n",
+ dptr->virtualX, dptr->virtualY);
+ }
+ if (dptr->depth)
+ {
+ fprintf (cf, " Depth %d\n", dptr->depth);
+ }
+ if (dptr->bpp)
+ {
+ fprintf (cf, " FbBPP %d\n", dptr->bpp);
+ }
+ if (dptr->visual)
+ {
+ fprintf (cf, " Visual \"%s\"\n", dptr->visual);
+ }
+ if (dptr->weight.red != 0)
+ {
+ fprintf (cf, " Weight %d %d %d\n",
+ dptr->weight.red, dptr->weight.green, dptr->weight.blue);
+ }
+ if (dptr->black.red != -1)
+ {
+ fprintf (cf, " Black 0x%04x 0x%04x 0x%04x\n",
+ dptr->black.red, dptr->black.green, dptr->black.blue);
+ }
+ if (dptr->white.red != -1)
+ {
+ fprintf (cf, " White 0x%04x 0x%04x 0x%04x\n",
+ dptr->white.red, dptr->white.green, dptr->white.blue);
+ }
+ if (dptr->modes)
+ {
+ fprintf (cf, " Modes ");
+ }
+ for (mptr = dptr->modes; mptr; mptr = mptr->next)
+ {
+ fprintf (cf, " \"%s\"", mptr->mode_name);
+ }
+ if (dptr->modes)
+ {
+ fprintf (cf, "\n");
+ }
+ xconfigPrintOptionList(cf, dptr->options, 2);
+ fprintf (cf, " EndSubSection\n");
+ }
+ fprintf (cf, "EndSection\n\n");
+ ptr = ptr->next;
+ }
+
+}
+
+void
+xconfigFreeScreenList (XConfigScreenPtr ptr)
+{
+ XConfigScreenPtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->identifier);
+ TEST_FREE (ptr->monitor_name);
+ TEST_FREE (ptr->device_name);
+ TEST_FREE (ptr->comment);
+ xconfigOptionListFree (ptr->options);
+ xconfigFreeAdaptorLinkList (ptr->adaptors);
+ xconfigFreeDisplayList (ptr->displays);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+void
+xconfigFreeAdaptorLinkList (XConfigAdaptorLinkPtr ptr)
+{
+ XConfigAdaptorLinkPtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->adaptor_name);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+void
+xconfigFreeDisplayList (XConfigDisplayPtr ptr)
+{
+ XConfigDisplayPtr prev;
+
+ while (ptr)
+ {
+ xconfigFreeModeList (ptr->modes);
+ xconfigOptionListFree (ptr->options);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+void
+xconfigFreeModeList (XConfigModePtr ptr)
+{
+ XConfigModePtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->mode_name);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+int
+xconfigValidateScreen (XConfigPtr p)
+{
+ XConfigScreenPtr screen = p->screens;
+ XConfigMonitorPtr monitor;
+ XConfigDevicePtr device;
+ XConfigAdaptorLinkPtr adaptor;
+
+ if (!screen)
+ {
+ xconfigErrorMsg(ValidationErrorMsg, "At least one Screen section "
+ "is required.");
+ return (FALSE);
+ }
+
+ while (screen)
+ {
+ if (screen->obsolete_driver && !screen->identifier)
+ screen->identifier = screen->obsolete_driver;
+
+ monitor = xconfigFindMonitor (screen->monitor_name, p->monitors);
+ if (screen->monitor_name)
+ {
+ if (!monitor)
+ {
+ xconfigErrorMsg(ValidationErrorMsg, UNDEFINED_MONITOR_MSG,
+ screen->monitor_name, screen->identifier);
+ return (FALSE);
+ }
+ else
+ {
+ screen->monitor = monitor;
+ if (!xconfigValidateMonitor(p, screen))
+ return (FALSE);
+ }
+ }
+
+ device = xconfigFindDevice (screen->device_name, p->devices);
+ if (!device)
+ {
+ xconfigErrorMsg(ValidationErrorMsg, UNDEFINED_DEVICE_MSG,
+ screen->device_name, screen->identifier);
+ return (FALSE);
+ }
+ else
+ screen->device = device;
+
+ adaptor = screen->adaptors;
+ while (adaptor) {
+ adaptor->adaptor = xconfigFindVideoAdaptor(adaptor->adaptor_name,
+ p->videoadaptors);
+ if (!adaptor->adaptor) {
+ xconfigErrorMsg(ValidationErrorMsg, UNDEFINED_ADAPTOR_MSG,
+ adaptor->adaptor_name,
+ screen->identifier);
+ return (FALSE);
+ } else if (adaptor->adaptor->fwdref) {
+ xconfigErrorMsg(ValidationErrorMsg, ADAPTOR_REF_TWICE_MSG,
+ adaptor->adaptor_name,
+ adaptor->adaptor->fwdref);
+ return (FALSE);
+ }
+
+ adaptor->adaptor->fwdref = xconfigStrdup(screen->identifier);
+ adaptor = adaptor->next;
+ }
+
+ screen = screen->next;
+ }
+
+ return (TRUE);
+}
+
+XConfigScreenPtr
+xconfigFindScreen (const char *ident, XConfigScreenPtr p)
+{
+ while (p)
+ {
+ if (xconfigNameCompare (ident, p->identifier) == 0)
+ return (p);
+
+ p = p->next;
+ }
+ return (NULL);
+}
+
+
+XConfigModePtr
+xconfigAddMode(XConfigModePtr head, const char *name)
+{
+ XConfigModePtr mode;
+
+ mode = xconfigAlloc(sizeof(XConfigModeRec));
+ mode->mode_name = xconfigStrdup(name);
+
+ mode->next = head;
+
+ return mode;
+
+}
+
+
+XConfigModePtr
+xconfigRemoveMode(XConfigModePtr head, const char *name)
+{
+ XConfigModePtr prev = NULL;
+ XConfigModePtr m = head;
+
+ while (m) {
+ if (xconfigNameCompare(m->mode_name, name) == 0) {
+ if (prev) prev->next = m->next;
+ if (head == m) head = m->next;
+ free(m->mode_name);
+ free(m);
+ break;
+ }
+ prev = m;
+ m = m->next;
+ }
+
+ return head;
+}
+
+
+
diff --git a/XF86Config-parser/Util.c b/XF86Config-parser/Util.c
new file mode 100644
index 0000000..f149afa
--- /dev/null
+++ b/XF86Config-parser/Util.c
@@ -0,0 +1,185 @@
+/*
+ * nvidia-xconfig: A tool for manipulating X config files,
+ * specifically for use by the NVIDIA Linux graphics driver.
+ *
+ * Copyright (C) 2005 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ * Util.c
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "xf86Parser.h"
+#include "Configint.h"
+
+void *xconfigAlloc(size_t size)
+{
+ void *m = malloc(size);
+
+ if (!m) {
+ fprintf(stderr, "memory allocation failure (%s)! \n", strerror(errno));
+ exit(1);
+ }
+ memset((char *) m, 0, size);
+ return m;
+
+} /* xconfigAlloc() */
+
+
+/*
+ * xconfigStrdup() - wrapper for strdup() that checks the return
+ * value; if an error occurs, an error is printed to stderr and exit
+ * is called -- this function will only return on success.
+ */
+
+char *xconfigStrdup(const char *s)
+{
+ char *m;
+
+ if (!s) return NULL;
+
+ m = strdup(s);
+
+ if (!m) {
+ fprintf(stderr, "memory allocation failure during strdup (%s)! \n",
+ strerror(errno));
+ exit(1);
+ }
+ return m;
+
+} /* xconfigStrdup() */
+
+
+/*
+ * xconfigStrcat() - allocate a new string, copying all given strings
+ * into it. taken from glib
+ */
+
+char *xconfigStrcat(const char *str, ...)
+{
+ unsigned int l;
+ va_list args;
+ char *s;
+ char *concat;
+
+ l = 1 + strlen(str);
+ va_start(args, str);
+ s = va_arg(args, char *);
+
+ while (s) {
+ l += strlen(s);
+ s = va_arg(args, char *);
+ }
+ va_end(args);
+
+ concat = xconfigAlloc(l);
+ concat[0] = 0;
+
+ strcat(concat, str);
+ va_start(args, str);
+ s = va_arg(args, char *);
+ while (s) {
+ strcat(concat, s);
+ s = va_arg(args, char *);
+ }
+ va_end(args);
+
+ return concat;
+
+} /* xconfigStrcat() */
+
+
+
+
+
+
+#define NV_FMT_BUF_LEN 64
+
+extern int configLineNo;
+extern char *configSection;
+extern char *configPath;
+
+void xconfigErrorMsg(MsgType t, char *fmt, ...)
+{
+ va_list ap;
+ int len, current_len = NV_FMT_BUF_LEN;
+ char *b, *pre = NULL, *msg;
+ char scratch[64];
+
+ b = xconfigAlloc(current_len);
+
+ while (1) {
+ va_start(ap, fmt);
+ len = vsnprintf(b, current_len, fmt, ap);
+ va_end(ap);
+
+ if ((len > -1) && (len < current_len)) {
+ break;
+ } else if (len > -1) {
+ current_len = len + 1;
+ } else {
+ current_len += NV_FMT_BUF_LEN;
+ }
+
+ free(b);
+ b = xconfigAlloc(current_len);
+ }
+
+ switch (t) {
+ case ParseErrorMsg:
+ sprintf(scratch, "%d", configLineNo);
+ pre = xconfigStrcat("Parse error on line ", scratch, " of section ",
+ configSection, " in file ", configPath, ".\n", NULL);
+ break;
+ case ParseWarningMsg:
+ sprintf(scratch, "%d", configLineNo);
+ pre = xconfigStrcat("Parse warning on line ", scratch, " of section ",
+ configSection, " in file ", configPath, ".\n", NULL);
+ break;
+ case ValidationErrorMsg:
+ pre = xconfigStrcat("Data incomplete in file ", configPath, ".\n", NULL);
+ break;
+ case InternalErrorMsg: break;
+ case WriteErrorMsg: break;
+ case WarnMsg: break;
+ case ErrorMsg: break;
+ case DebugMsg: break;
+ case UnknownMsg: break;
+ }
+
+ if (pre) {
+ msg = xconfigStrcat(pre, b, NULL);
+ } else {
+ msg = strdup(b);
+ }
+
+ /* call back into the host to print the message */
+
+ xconfigPrint(t, msg);
+
+
+ free(b);
+ free(msg);
+ if (pre) free(pre);
+}
diff --git a/XF86Config-parser/Vendor.c b/XF86Config-parser/Vendor.c
new file mode 100644
index 0000000..aa57005
--- /dev/null
+++ b/XF86Config-parser/Vendor.c
@@ -0,0 +1,253 @@
+/*
+ *
+ * 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).
+ */
+
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+extern LexRec val;
+
+static XConfigSymTabRec VendorSubTab[] =
+{
+ {ENDSUBSECTION, "endsubsection"},
+ {IDENTIFIER, "identifier"},
+ {OPTION, "option"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeVendorSubList
+
+XConfigVendSubPtr
+xconfigParseVendorSubSection (void)
+{
+ int has_ident = FALSE;
+ int token;
+ PARSE_PROLOGUE (XConfigVendSubPtr, XConfigVendSubRec)
+
+ while ((token = xconfigGetToken (VendorSubTab)) != ENDSUBSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case IDENTIFIER:
+ if (xconfigGetSubToken (&(ptr->comment)))
+ Error (QUOTE_MSG, "Identifier");
+ if (has_ident == TRUE)
+ Error (MULTIPLE_MSG, "Identifier");
+ ptr->identifier = val.str;
+ has_ident = TRUE;
+ 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;
+ }
+ }
+
+#ifdef DEBUG
+ xconfigErrorMsg(DebugMsg, "Vendor subsection parsed\n");
+#endif
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+static XConfigSymTabRec VendorTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {IDENTIFIER, "identifier"},
+ {OPTION, "option"},
+ {SUBSECTION, "subsection"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeVendorList
+
+XConfigVendorPtr
+xconfigParseVendorSection (void)
+{
+ int has_ident = FALSE;
+ int token;
+ PARSE_PROLOGUE (XConfigVendorPtr, XConfigVendorRec)
+
+ while ((token = xconfigGetToken (VendorTab)) != ENDSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case IDENTIFIER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Identifier");
+ if (has_ident == TRUE)
+ Error (MULTIPLE_MSG, "Identifier");
+ ptr->identifier = val.str;
+ has_ident = TRUE;
+ break;
+ case OPTION:
+ ptr->options = xconfigParseOption(ptr->options);
+ break;
+ case SUBSECTION:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "SubSection");
+ {
+ HANDLE_LIST (subs, xconfigParseVendorSubSection,
+ XConfigVendSubPtr);
+ }
+ break;
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+
+ }
+
+ if (!has_ident)
+ Error (NO_IDENT_MSG, NULL);
+
+#ifdef DEBUG
+ xconfigErrorMsg(DebugMsg, "Vendor section parsed\n");
+#endif
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+void
+xconfigPrintVendorSection (FILE * cf, XConfigVendorPtr ptr)
+{
+ XConfigVendSubPtr pptr;
+
+ while (ptr)
+ {
+ fprintf (cf, "Section \"Vendor\"\n");
+ if (ptr->comment)
+ fprintf (cf, "%s", ptr->comment);
+ if (ptr->identifier)
+ fprintf (cf, " Identifier \"%s\"\n", ptr->identifier);
+
+ xconfigPrintOptionList(cf, ptr->options, 1);
+ for (pptr = ptr->subs; pptr; pptr = pptr->next)
+ {
+ fprintf (cf, " SubSection \"Vendor\"\n");
+ if (pptr->comment)
+ fprintf (cf, "%s", pptr->comment);
+ if (pptr->identifier)
+ fprintf (cf, " Identifier \"%s\"\n", pptr->identifier);
+ xconfigPrintOptionList(cf, pptr->options, 2);
+ fprintf (cf, " EndSubSection\n");
+ }
+ fprintf (cf, "EndSection\n\n");
+ ptr = ptr->next;
+ }
+}
+
+void
+xconfigFreeVendorList (XConfigVendorPtr p)
+{
+ if (p == NULL)
+ return;
+ xconfigFreeVendorSubList (p->subs);
+ TEST_FREE (p->identifier);
+ TEST_FREE (p->comment);
+ xconfigOptionListFree (p->options);
+ free (p);
+}
+
+void
+xconfigFreeVendorSubList (XConfigVendSubPtr ptr)
+{
+ XConfigVendSubPtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->identifier);
+ TEST_FREE (ptr->name);
+ TEST_FREE (ptr->comment);
+ xconfigOptionListFree (ptr->options);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+XConfigVendorPtr
+xconfigFindVendor (const char *name, XConfigVendorPtr list)
+{
+ while (list)
+ {
+ if (xconfigNameCompare (list->identifier, name) == 0)
+ return (list);
+ list = list->next;
+ }
+ return (NULL);
+}
+
diff --git a/XF86Config-parser/Video.c b/XF86Config-parser/Video.c
new file mode 100644
index 0000000..12846b2
--- /dev/null
+++ b/XF86Config-parser/Video.c
@@ -0,0 +1,292 @@
+/*
+ *
+ * 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).
+ */
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+extern LexRec val;
+
+static XConfigSymTabRec VideoPortTab[] =
+{
+ {ENDSUBSECTION, "endsubsection"},
+ {IDENTIFIER, "identifier"},
+ {OPTION, "option"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeVideoPortList
+
+XConfigVideoPortPtr
+xconfigParseVideoPortSubSection (void)
+{
+ int has_ident = FALSE;
+ int token;
+ PARSE_PROLOGUE (XConfigVideoPortPtr, XConfigVideoPortRec)
+
+ while ((token = xconfigGetToken (VideoPortTab)) != ENDSUBSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case IDENTIFIER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Identifier");
+ if (has_ident == TRUE)
+ Error (MULTIPLE_MSG, "Identifier");
+ ptr->identifier = val.str;
+ has_ident = TRUE;
+ 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;
+ }
+ }
+
+#ifdef DEBUG
+ xconfigErrorMsg(DebugMsg, "VideoPort subsection parsed\n");
+#endif
+
+ return ptr;
+}
+
+#undef CLEANUP
+
+static XConfigSymTabRec VideoAdaptorTab[] =
+{
+ {ENDSECTION, "endsection"},
+ {IDENTIFIER, "identifier"},
+ {VENDOR, "vendorname"},
+ {BOARD, "boardname"},
+ {BUSID, "busid"},
+ {DRIVER, "driver"},
+ {OPTION, "option"},
+ {SUBSECTION, "subsection"},
+ {-1, ""},
+};
+
+#define CLEANUP xconfigFreeVideoAdaptorList
+
+XConfigVideoAdaptorPtr
+xconfigParseVideoAdaptorSection (void)
+{
+ int has_ident = FALSE;
+ int token;
+
+ PARSE_PROLOGUE (XConfigVideoAdaptorPtr, XConfigVideoAdaptorRec)
+
+ while ((token = xconfigGetToken (VideoAdaptorTab)) != ENDSECTION)
+ {
+ switch (token)
+ {
+ case COMMENT:
+ ptr->comment = xconfigAddComment(ptr->comment, val.str);
+ break;
+ case IDENTIFIER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Identifier");
+ ptr->identifier = val.str;
+ if (has_ident == TRUE)
+ Error (MULTIPLE_MSG, "Identifier");
+ has_ident = TRUE;
+ break;
+ case VENDOR:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Vendor");
+ ptr->vendor = val.str;
+ break;
+ case BOARD:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Board");
+ ptr->board = val.str;
+ break;
+ case BUSID:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "BusID");
+ ptr->busid = val.str;
+ break;
+ case DRIVER:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "Driver");
+ ptr->driver = val.str;
+ break;
+ case OPTION:
+ ptr->options = xconfigParseOption(ptr->options);
+ break;
+ case SUBSECTION:
+ if (xconfigGetSubToken (&(ptr->comment)) != STRING)
+ Error (QUOTE_MSG, "SubSection");
+ {
+ HANDLE_LIST (ports, xconfigParseVideoPortSubSection,
+ XConfigVideoPortPtr);
+ }
+ break;
+
+ case EOF_TOKEN:
+ Error (UNEXPECTED_EOF_MSG, NULL);
+ break;
+ default:
+ Error (INVALID_KEYWORD_MSG, xconfigTokenString ());
+ break;
+ }
+ }
+
+ if (!has_ident)
+ Error (NO_IDENT_MSG, NULL);
+
+#ifdef DEBUG
+ xconfigErrorMsg(DebugMsg, "VideoAdaptor section parsed\n");
+#endif
+
+ return ptr;
+}
+
+void
+xconfigPrintVideoAdaptorSection (FILE * cf, XConfigVideoAdaptorPtr ptr)
+{
+ XConfigVideoPortPtr pptr;
+
+ while (ptr)
+ {
+ fprintf (cf, "Section \"VideoAdaptor\"\n");
+ if (ptr->comment)
+ fprintf (cf, "%s", ptr->comment);
+ if (ptr->identifier)
+ fprintf (cf, " Identifier \"%s\"\n", ptr->identifier);
+ if (ptr->vendor)
+ fprintf (cf, " VendorName \"%s\"\n", ptr->vendor);
+ if (ptr->board)
+ fprintf (cf, " BoardName \"%s\"\n", ptr->board);
+ if (ptr->busid)
+ fprintf (cf, " BusID \"%s\"\n", ptr->busid);
+ if (ptr->driver)
+ fprintf (cf, " Driver \"%s\"\n", ptr->driver);
+ xconfigPrintOptionList(cf, ptr->options, 1);
+ for (pptr = ptr->ports; pptr; pptr = pptr->next)
+ {
+ fprintf (cf, " SubSection \"VideoPort\"\n");
+ if (pptr->comment)
+ fprintf (cf, "%s", pptr->comment);
+ if (pptr->identifier)
+ fprintf (cf, " Identifier \"%s\"\n", pptr->identifier);
+ xconfigPrintOptionList(cf, pptr->options, 2);
+ fprintf (cf, " EndSubSection\n");
+ }
+ fprintf (cf, "EndSection\n\n");
+ ptr = ptr->next;
+ }
+
+}
+
+void
+xconfigFreeVideoAdaptorList (XConfigVideoAdaptorPtr ptr)
+{
+ XConfigVideoAdaptorPtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->identifier);
+ TEST_FREE (ptr->vendor);
+ TEST_FREE (ptr->board);
+ TEST_FREE (ptr->busid);
+ TEST_FREE (ptr->driver);
+ TEST_FREE (ptr->fwdref);
+ TEST_FREE (ptr->comment);
+ xconfigFreeVideoPortList (ptr->ports);
+ xconfigOptionListFree (ptr->options);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+void
+xconfigFreeVideoPortList (XConfigVideoPortPtr ptr)
+{
+ XConfigVideoPortPtr prev;
+
+ while (ptr)
+ {
+ TEST_FREE (ptr->identifier);
+ TEST_FREE (ptr->comment);
+ xconfigOptionListFree (ptr->options);
+ prev = ptr;
+ ptr = ptr->next;
+ free (prev);
+ }
+}
+
+XConfigVideoAdaptorPtr
+xconfigFindVideoAdaptor (const char *ident, XConfigVideoAdaptorPtr p)
+{
+ while (p)
+ {
+ if (xconfigNameCompare (ident, p->identifier) == 0)
+ return (p);
+
+ p = p->next;
+ }
+ return (NULL);
+}
diff --git a/XF86Config-parser/Write.c b/XF86Config-parser/Write.c
new file mode 100644
index 0000000..a1658e2
--- /dev/null
+++ b/XF86Config-parser/Write.c
@@ -0,0 +1,114 @@
+/*
+ *
+ * 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).
+ */
+
+
+/* View/edit this file with tab stops set to 4 */
+
+#include "xf86Parser.h"
+#include "xf86tokens.h"
+#include "Configint.h"
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <errno.h>
+
+int xconfigWriteConfigFile (const char *filename, XConfigPtr cptr)
+{
+ FILE *cf;
+
+ if ((cf = fopen(filename, "w")) == NULL)
+ {
+ xconfigErrorMsg(WriteErrorMsg, "Unable to open the file \"%s\" for "
+ "writing (%s).\n", filename, strerror(errno));
+ return FALSE;
+ }
+
+ if (cptr->comment)
+ fprintf (cf, "%s\n", cptr->comment);
+
+ xconfigPrintLayoutSection (cf, cptr->layouts);
+
+ fprintf (cf, "Section \"Files\"\n");
+ xconfigPrintFileSection (cf, cptr->files);
+ fprintf (cf, "EndSection\n\n");
+
+ fprintf (cf, "Section \"Module\"\n");
+ xconfigPrintModuleSection (cf, cptr->modules);
+ fprintf (cf, "EndSection\n\n");
+
+ xconfigPrintVendorSection (cf, cptr->vendors);
+
+ xconfigPrintServerFlagsSection (cf, cptr->flags);
+
+ xconfigPrintInputSection (cf, cptr->inputs);
+
+ xconfigPrintVideoAdaptorSection (cf, cptr->videoadaptors);
+
+ xconfigPrintModesSection (cf, cptr->modes);
+
+ xconfigPrintMonitorSection (cf, cptr->monitors);
+
+ xconfigPrintDeviceSection (cf, cptr->devices);
+
+ xconfigPrintScreenSection (cf, cptr->screens);
+
+ xconfigPrintDRISection (cf, cptr->dri);
+
+ xconfigPrintExtensionsSection (cf, cptr->extensions);
+
+ fclose(cf);
+ return TRUE;
+}
diff --git a/XF86Config-parser/configProcs.h b/XF86Config-parser/configProcs.h
new file mode 100644
index 0000000..f8b0c24
--- /dev/null
+++ b/XF86Config-parser/configProcs.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 1997-2001 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).
+ */
+
+/* Private procs. Public procs are in xf86Parser.h and xf86Optrec.h */
+
+#include "xf86Parser.h"
+
+
+/* Device.c */
+XConfigDevicePtr xconfigParseDeviceSection(void);
+void xconfigPrintDeviceSection(FILE *cf, XConfigDevicePtr ptr);
+int xconfigValidateDevice(XConfigPtr p);
+
+/* Files.c */
+XConfigFilesPtr xconfigParseFilesSection(void);
+void xconfigPrintFileSection(FILE *cf, XConfigFilesPtr ptr);
+
+/* Flags.c */
+XConfigFlagsPtr xconfigParseFlagsSection(void);
+void xconfigPrintServerFlagsSection(FILE *f, XConfigFlagsPtr flags);
+
+/* Input.c */
+XConfigInputPtr xconfigParseInputSection(void);
+void xconfigPrintInputSection(FILE *f, XConfigInputPtr ptr);
+int xconfigValidateInput (XConfigPtr p);
+
+/* Keyboard.c */
+XConfigInputPtr xconfigParseKeyboardSection(void);
+
+/* Layout.c */
+XConfigLayoutPtr xconfigParseLayoutSection(void);
+void xconfigPrintLayoutSection(FILE *cf, XConfigLayoutPtr ptr);
+int xconfigValidateLayout(XConfigPtr p, const char *screenName);
+
+/* Module.c */
+XConfigLoadPtr xconfigParseModuleSubSection(XConfigLoadPtr head, char *name);
+XConfigModulePtr xconfigParseModuleSection(void);
+void xconfigPrintModuleSection(FILE *cf, XConfigModulePtr ptr);
+
+/* Monitor.c */
+XConfigModeLinePtr xconfigParseModeLine(void);
+XConfigModeLinePtr xconfigParseVerboseMode(void);
+XConfigMonitorPtr xconfigParseMonitorSection(void);
+XConfigModesPtr xconfigParseModesSection(void);
+void xconfigPrintMonitorSection(FILE *cf, XConfigMonitorPtr ptr);
+void xconfigPrintModesSection(FILE *cf, XConfigModesPtr ptr);
+int xconfigValidateMonitor(XConfigPtr p, XConfigScreenPtr screen);
+
+/* Pointer.c */
+XConfigInputPtr xconfigParsePointerSection(void);
+
+/* Screen.c */
+XConfigDisplayPtr xconfigParseDisplaySubSection(void);
+XConfigScreenPtr xconfigParseScreenSection(void);
+void xconfigPrintScreenSection(FILE *cf, XConfigScreenPtr ptr);
+int xconfigValidateScreen(XConfigPtr p);
+
+/* Vendor.c */
+XConfigVendorPtr xconfigParseVendorSection(void);
+XConfigVendSubPtr xconfigParseVendorSubSection (void);
+void xconfigPrintVendorSection(FILE * cf, XConfigVendorPtr ptr);
+
+/* Video.c */
+XConfigVideoPortPtr xconfigParseVideoPortSubSection(void);
+XConfigVideoAdaptorPtr xconfigParseVideoAdaptorSection(void);
+void xconfigPrintVideoAdaptorSection(FILE *cf, XConfigVideoAdaptorPtr ptr);
+
+/* Read.c */
+int xconfigValidateConfig(XConfigPtr p, const char *);
+
+/* Scan.c */
+int xconfigGetToken(XConfigSymTabRec *tab);
+int xconfigGetSubToken(char **comment);
+int xconfigGetSubTokenWithTab(char **comment, XConfigSymTabRec *tab);
+void xconfigUnGetToken(int token);
+char *xconfigTokenString(void);
+void xconfigSetSection(char *section);
+int xconfigGetStringToken(XConfigSymTabRec *tab);
+char *xconfigGetConfigFileName(void);
+
+/* Write.c */
+
+/* DRI.c */
+XConfigBuffersPtr xconfigParseBuffers (void);
+XConfigDRIPtr xconfigParseDRISection (void);
+void xconfigPrintDRISection (FILE * cf, XConfigDRIPtr ptr);
+
+/* Util.c */
+void *xconfigAlloc(size_t size);
+void xconfigErrorMsg(MsgType, char *fmt, ...);
+
+/* Extensions.c */
+XConfigExtensionsPtr xconfigParseExtensionsSection (void);
+void xconfigPrintExtensionsSection (FILE * cf, XConfigExtensionsPtr ptr);
diff --git a/XF86Config-parser/xf86Parser.h b/XF86Config-parser/xf86Parser.h
new file mode 100644
index 0000000..3347690
--- /dev/null
+++ b/XF86Config-parser/xf86Parser.h
@@ -0,0 +1,724 @@
+/*
+ *
+ * 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).
+ */
+
+
+/*
+ * This file specifies the external interface for the X configuration
+ * file parser; based loosely on the XFree86 and Xorg X server
+ * configuration code.
+ */
+
+
+#ifndef _xf86Parser_h_
+#define _xf86Parser_h_
+
+#include <stdio.h>
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+// Unix variations: Linux
+#if !defined(NV_LINUX) && defined(__linux__)
+# define NV_LINUX
+#endif // defined(__linux__)
+
+// Unix variations: SunOS
+#if !defined(NV_SUNOS) && defined(__sun__) || defined(__sun)
+# define NV_SUNOS
+#endif // defined(__sun__)
+
+// Unix variations: FreeBSD
+#if !defined(NV_BSD) && defined(__FreeBSD__)
+# define NV_BSD
+#endif // defined(__FreeBSD__)
+
+
+/*
+ * return codes
+ */
+
+typedef enum {
+ XCONFIG_RETURN_SUCCESS = 0,
+ XCONFIG_RETURN_NO_XCONFIG_FOUND,
+ XCONFIG_RETURN_PARSE_ERROR,
+ XCONFIG_RETURN_ALLOCATION_ERROR,
+ XCONFIG_RETURN_VALIDATION_ERROR,
+ XCONFIG_RETURN_INVALID_COMMAND_LINE,
+ XCONFIG_RETURN_SANITY_ERROR,
+ XCONFIG_RETURN_WRITE_ERROR
+} XConfigError;
+
+
+/*
+ * Message types
+ */
+
+typedef enum {
+ ParseErrorMsg,
+ ParseWarningMsg,
+ ValidationErrorMsg,
+ InternalErrorMsg,
+ WriteErrorMsg,
+ WarnMsg,
+ ErrorMsg,
+ DebugMsg,
+ UnknownMsg
+} MsgType;
+
+
+/*
+ * The user of libXF86Config-parser should provide an implementation
+ * of xconfigPrint()
+ */
+
+void xconfigPrint(MsgType t, const char *msg);
+
+
+/*
+ * all records that need to be linked lists should contain a next
+ * pointer as their first field, so that they can be cast as a
+ * GenericListRec
+ */
+
+typedef struct { void *next; } GenericListRec, *GenericListPtr;
+
+
+
+/*
+ * Options are stored in the XConfigOptionRec structure
+ */
+
+typedef struct __xconfigoptionrec {
+ struct __xconfigoptionrec *next;
+ char *name;
+ char *val;
+ int used;
+ char *comment;
+} XConfigOptionRec, *XConfigOptionPtr;
+
+
+
+/*
+ * Files Section
+ */
+
+typedef struct {
+ char *logfile;
+ char *rgbpath;
+ char *modulepath;
+ char *inputdevs;
+ char *fontpath;
+ char *comment;
+} XConfigFilesRec, *XConfigFilesPtr;
+
+/* Values for load_type */
+#define XCONFIG_LOAD_MODULE 0
+#define XCONFIG_LOAD_DRIVER 1
+
+
+
+/*
+ * Modules Section
+ */
+
+typedef struct __xconfigloadrec {
+ struct __xconfigloadrec *next;
+ int type;
+ char *name;
+ XConfigOptionPtr opt;
+ char *comment;
+} XConfigLoadRec, *XConfigLoadPtr;
+
+typedef struct {
+ XConfigLoadPtr loads;
+ char *comment;
+} XConfigModuleRec, *XConfigModulePtr;
+
+#define CONF_IMPLICIT_KEYBOARD "Implicit Core Keyboard"
+
+#define CONF_IMPLICIT_POINTER "Implicit Core Pointer"
+
+
+
+/*
+ * Modeline structure
+ */
+
+#define XCONFIG_MODE_PHSYNC 0x0001
+#define XCONFIG_MODE_NHSYNC 0x0002
+#define XCONFIG_MODE_PVSYNC 0x0004
+#define XCONFIG_MODE_NVSYNC 0x0008
+#define XCONFIG_MODE_INTERLACE 0x0010
+#define XCONFIG_MODE_DBLSCAN 0x0020
+#define XCONFIG_MODE_CSYNC 0x0040
+#define XCONFIG_MODE_PCSYNC 0x0080
+#define XCONFIG_MODE_NCSYNC 0x0100
+#define XCONFIG_MODE_HSKEW 0x0200 /* hskew provided */
+#define XCONFIG_MODE_BCAST 0x0400
+#define XCONFIG_MODE_CUSTOM 0x0800 /* timing numbers customized by editor */
+#define XCONFIG_MODE_VSCAN 0x1000
+
+typedef struct __xconfigconfmodelinerec {
+ struct __xconfigconfmodelinerec *next;
+ char *identifier;
+ int clock;
+ int hdisplay;
+ int hsyncstart;
+ int hsyncend;
+ int htotal;
+ int vdisplay;
+ int vsyncstart;
+ int vsyncend;
+ int vtotal;
+ int vscan;
+ int flags;
+ int hskew;
+ char *comment;
+} XConfigModeLineRec, *XConfigModeLinePtr;
+
+
+
+/*
+ * VideoPort and VideoAdapter XXX what are these?
+ */
+
+typedef struct __xconfigconfvideoportrec {
+ struct __xconfigconfvideoportrec *next;
+ char *identifier;
+ XConfigOptionPtr options;
+ char *comment;
+} XConfigVideoPortRec, *XConfigVideoPortPtr;
+
+typedef struct __xconfigconfvideoadaptorrec {
+ struct __xconfigconfvideoadaptorrec *next;
+ char *identifier;
+ char *vendor;
+ char *board;
+ char *busid;
+ char *driver;
+ XConfigOptionPtr options;
+ XConfigVideoPortPtr ports;
+ char *fwdref;
+ char *comment;
+} XConfigVideoAdaptorRec, *XConfigVideoAdaptorPtr;
+
+
+
+/*
+ * Monitor Section
+ */
+
+#define CONF_MAX_HSYNC 8
+#define CONF_MAX_VREFRESH 8
+
+typedef struct { float hi, lo; } parser_range;
+
+typedef struct { int red, green, blue; } parser_rgb;
+
+typedef struct __xconfigconfmodesrec {
+ struct __xconfigconfmodesrec *next;
+ char *identifier;
+ XConfigModeLinePtr modelines;
+ char *comment;
+} XConfigModesRec, *XConfigModesPtr;
+
+typedef struct __xconfigconfmodeslinkrec {
+ struct __xconfigconfmodeslinkrec *next;
+ char *modes_name;
+ XConfigModesPtr modes;
+} XConfigModesLinkRec, *XConfigModesLinkPtr;
+
+typedef struct __xconfigconfmonitorrec {
+ struct __xconfigconfmonitorrec *next;
+ char *identifier;
+ char *vendor;
+ char *modelname;
+ int width; /* in mm */
+ int height; /* in mm */
+ XConfigModeLinePtr modelines;
+ int n_hsync;
+ parser_range hsync[CONF_MAX_HSYNC];
+ int n_vrefresh;
+ parser_range vrefresh[CONF_MAX_VREFRESH];
+ float gamma_red;
+ float gamma_green;
+ float gamma_blue;
+ XConfigOptionPtr options;
+ XConfigModesLinkPtr modes_sections;
+ char *comment;
+} XConfigMonitorRec, *XConfigMonitorPtr;
+
+
+
+/*
+ * Device Section
+ */
+
+#define CONF_MAXDACSPEEDS 4
+#define CONF_MAXCLOCKS 128
+
+typedef struct __xconfigconfdevicerec {
+ struct __xconfigconfdevicerec *next;
+ char *identifier;
+ char *vendor;
+ char *board;
+ char *chipset;
+ char *busid;
+ char *card;
+ char *driver;
+ char *ramdac;
+ int dacSpeeds[CONF_MAXDACSPEEDS];
+ int videoram;
+ int textclockfreq;
+ unsigned long bios_base;
+ unsigned long mem_base;
+ unsigned long io_base;
+ char *clockchip;
+ int clocks;
+ int clock[CONF_MAXCLOCKS];
+ int chipid;
+ int chiprev;
+ int irq;
+ int screen;
+ XConfigOptionPtr options;
+ char *comment;
+} XConfigDeviceRec, *XConfigDevicePtr;
+
+
+
+/*
+ * Screen Section
+ */
+
+typedef struct __xconfigmoderec {
+ struct __xconfigmoderec *next;
+ char *mode_name;
+} XConfigModeRec, *XConfigModePtr;
+
+typedef struct __xconfigconfdisplayrec {
+ struct __xconfigconfdisplayrec *next;
+ int frameX0;
+ int frameY0;
+ int virtualX;
+ int virtualY;
+ int depth;
+ int bpp;
+ char *visual;
+ parser_rgb weight;
+ parser_rgb black;
+ parser_rgb white;
+ XConfigModePtr modes;
+ XConfigOptionPtr options;
+ char *comment;
+} XConfigDisplayRec, *XConfigDisplayPtr;
+
+typedef struct __xconfigconfadaptorlinkrec {
+ struct __xconfigconfadaptorlinkrec *next;
+ char *adaptor_name;
+ XConfigVideoAdaptorPtr adaptor;
+} XConfigAdaptorLinkRec, *XConfigAdaptorLinkPtr;
+
+typedef struct __xconfigconfscreenrec {
+ struct __xconfigconfscreenrec *next;
+ char *identifier;
+ char *obsolete_driver;
+ int defaultdepth;
+ int defaultbpp;
+ int defaultfbbpp;
+ char *monitor_name;
+ XConfigMonitorPtr monitor;
+ char *device_name;
+ XConfigDevicePtr device;
+ XConfigAdaptorLinkPtr adaptors;
+ XConfigDisplayPtr displays;
+ XConfigOptionPtr options;
+ char *comment;
+} XConfigScreenRec, *XConfigScreenPtr;
+
+
+
+/*
+ * Input Section
+ */
+
+typedef struct __xconfigconfinputrec {
+ struct __xconfigconfinputrec *next;
+ char *identifier;
+ char *driver;
+ XConfigOptionPtr options;
+ char *comment;
+} XConfigInputRec, *XConfigInputPtr;
+
+
+
+/*
+ * Input Reference; used by layout to store list of XConfigInputPtrs
+ */
+
+typedef struct __xconfigconfinputrefrec {
+ struct __xconfigconfinputrefrec *next;
+ XConfigInputPtr input;
+ char *input_name;
+ XConfigOptionPtr options;
+} XConfigInputrefRec, *XConfigInputrefPtr;
+
+
+
+/*
+ * Adjacency structure; used by layout to store list of
+ * XConfigScreenPtrs
+ */
+
+/* Values for adj_where */
+#define CONF_ADJ_OBSOLETE -1
+#define CONF_ADJ_ABSOLUTE 0
+#define CONF_ADJ_RIGHTOF 1
+#define CONF_ADJ_LEFTOF 2
+#define CONF_ADJ_ABOVE 3
+#define CONF_ADJ_BELOW 4
+#define CONF_ADJ_RELATIVE 5
+
+typedef struct __xconfigconfadjacencyrec {
+ struct __xconfigconfadjacencyrec *next;
+ int scrnum;
+ XConfigScreenPtr screen;
+ char *screen_name;
+ XConfigScreenPtr top;
+ char *top_name;
+ XConfigScreenPtr bottom;
+ char *bottom_name;
+ XConfigScreenPtr left;
+ char *left_name;
+ XConfigScreenPtr right;
+ char *right_name;
+ int where;
+ int x;
+ int y;
+ char *refscreen;
+} XConfigAdjacencyRec, *XConfigAdjacencyPtr;
+
+
+
+/*
+ * XConfigInactiveRec XXX what is this?
+ */
+
+typedef struct __xconfigconfinactiverec {
+ struct __xconfigconfinactiverec *next;
+ char *device_name;
+ XConfigDevicePtr device;
+} XConfigInactiveRec, *XConfigInactivePtr;
+
+
+
+/*
+ * Layout Section
+ */
+
+typedef struct __xconfigconflayoutrec {
+ struct __xconfigconflayoutrec *next;
+ char *identifier;
+ XConfigAdjacencyPtr adjacencies;
+ XConfigInactivePtr inactives;
+ XConfigInputrefPtr inputs;
+ XConfigOptionPtr options;
+ char *comment;
+} XConfigLayoutRec, *XConfigLayoutPtr;
+
+
+
+/*
+ * Vendor Section XXX what is this?
+ */
+
+typedef struct __xconfigconfvendsubrec {
+ struct __xconfigconfvendsubrec *next;
+ char *name;
+ char *identifier;
+ XConfigOptionPtr options;
+ char *comment;
+} XConfigVendSubRec, *XConfigVendSubPtr;
+
+typedef struct __xconfigconfvendorrec {
+ struct __xconfigconfvendorrec *next;
+ char *identifier;
+ XConfigOptionPtr options;
+ XConfigVendSubPtr subs;
+ char *comment;
+} XConfigVendorRec, *XConfigVendorPtr;
+
+
+
+/*
+ * DRI section
+ */
+
+typedef struct __xconfigconfbuffersrec {
+ struct __xconfigconfbuffersrec *next;
+ int count;
+ int size;
+ char *flags;
+ char *comment;
+} XConfigBuffersRec, *XConfigBuffersPtr;
+
+typedef struct {
+ char *group_name;
+ int group;
+ int mode;
+ XConfigBuffersPtr buffers;
+ char * comment;
+} XConfigDRIRec, *XConfigDRIPtr;
+
+
+
+/*
+ * ServerFlags Section
+ */
+
+typedef struct {
+ XConfigOptionPtr options;
+ char *comment;
+} XConfigFlagsRec, *XConfigFlagsPtr;
+
+
+
+/*
+ * Extensions Section
+ */
+
+typedef struct
+{
+ XConfigOptionPtr options;
+ char *comment;
+}
+XConfigExtensionsRec, *XConfigExtensionsPtr;
+
+
+/*
+ * Configuration file structure
+ */
+
+typedef struct {
+ XConfigFilesPtr files;
+ XConfigModulePtr modules;
+ XConfigFlagsPtr flags;
+ XConfigVideoAdaptorPtr videoadaptors;
+ XConfigModesPtr modes;
+ XConfigMonitorPtr monitors;
+ XConfigDevicePtr devices;
+ XConfigScreenPtr screens;
+ XConfigInputPtr inputs;
+ XConfigLayoutPtr layouts;
+ XConfigVendorPtr vendors;
+ XConfigDRIPtr dri;
+ XConfigExtensionsPtr extensions;
+ char *comment;
+ char *filename;
+} XConfigRec, *XConfigPtr;
+
+typedef struct {
+ int token; /* id of the token */
+ char *name; /* pointer to the LOWERCASED name */
+} XConfigSymTabRec, *XConfigSymTabPtr;
+
+
+
+/*
+ * Functions for open, reading, and writing XConfig files.
+ */
+const char *xconfigOpenConfigFile(const char *, const char *);
+XConfigError xconfigReadConfigFile(const char *, XConfigPtr *);
+void xconfigCloseConfigFile(void);
+int xconfigWriteConfigFile(const char *, XConfigPtr);
+
+void xconfigFreeConfig(XConfigPtr p);
+
+/*
+ * Functions for searching for entries in lists
+ */
+
+XConfigDevicePtr xconfigFindDevice(const char *ident, XConfigDevicePtr p);
+XConfigLayoutPtr xconfigFindLayout(const char *name, XConfigLayoutPtr list);
+XConfigMonitorPtr xconfigFindMonitor(const char *ident, XConfigMonitorPtr p);
+XConfigModesPtr xconfigFindModes(const char *ident, XConfigModesPtr p);
+XConfigModeLinePtr xconfigFindModeLine(const char *ident,
+ XConfigModeLinePtr p);
+XConfigScreenPtr xconfigFindScreen(const char *ident, XConfigScreenPtr p);
+XConfigInputPtr xconfigFindInput(const char *ident, XConfigInputPtr p);
+XConfigInputPtr xconfigFindInputByDriver(const char *driver,
+ XConfigInputPtr p);
+XConfigVendorPtr xconfigFindVendor(const char *name, XConfigVendorPtr list);
+XConfigVideoAdaptorPtr xconfigFindVideoAdaptor(const char *ident,
+ XConfigVideoAdaptorPtr p);
+
+/*
+ * Functions for freeing lists
+ */
+
+void xconfigFreeDeviceList(XConfigDevicePtr ptr);
+void xconfigFreeFiles(XConfigFilesPtr p);
+void xconfigFreeFlags(XConfigFlagsPtr flags);
+void xconfigFreeInputList(XConfigInputPtr ptr);
+void xconfigFreeLayoutList(XConfigLayoutPtr ptr);
+void xconfigFreeAdjacencyList(XConfigAdjacencyPtr ptr);
+void xconfigFreeInputrefList(XConfigInputrefPtr ptr);
+void xconfigFreeModules(XConfigModulePtr ptr);
+void xconfigFreeMonitorList(XConfigMonitorPtr ptr);
+void xconfigFreeModesList(XConfigModesPtr ptr);
+void xconfigFreeModeLineList(XConfigModeLinePtr ptr);
+void xconfigFreeScreenList(XConfigScreenPtr ptr);
+void xconfigFreeAdaptorLinkList(XConfigAdaptorLinkPtr ptr);
+void xconfigFreeDisplayList(XConfigDisplayPtr ptr);
+void xconfigFreeModeList(XConfigModePtr ptr);
+void xconfigFreeVendorList(XConfigVendorPtr p);
+void xconfigFreeVendorSubList(XConfigVendSubPtr ptr);
+void xconfigFreeVideoAdaptorList(XConfigVideoAdaptorPtr ptr);
+void xconfigFreeVideoPortList(XConfigVideoPortPtr ptr);
+void xconfigFreeBuffersList (XConfigBuffersPtr ptr);
+void xconfigFreeDRI(XConfigDRIPtr ptr);
+void xconfigFreeExtensions(XConfigExtensionsPtr ptr);
+
+
+/*
+ * check (and update, if necessary) the inputs in the specified layout
+ * section
+ */
+
+int xconfigCheckCoreInputDevices(XConfigPtr config, XConfigLayoutPtr layout);
+
+/*
+ * item/list manipulation
+ */
+
+GenericListPtr xconfigAddListItem(GenericListPtr head, GenericListPtr c_new);
+int xconfigItemNotSublist(GenericListPtr list_1, GenericListPtr list_2);
+char *xconfigAddComment(char *cur, char *add);
+XConfigLoadPtr xconfigAddNewLoadDirective(XConfigLoadPtr head,
+ char *name, int type,
+ XConfigOptionPtr opts, int do_token);
+XConfigLoadPtr xconfigRemoveLoadDirective(XConfigLoadPtr head,
+ XConfigLoadPtr load);
+
+/*
+ * Functions for manipulating Options
+ */
+
+XConfigOptionPtr xconfigAddNewOption(XConfigOptionPtr head,
+ char *name, char *val);
+XConfigOptionPtr xconfigRemoveOption(XConfigOptionPtr list,
+ XConfigOptionPtr opt);
+XConfigOptionPtr xconfigOptionListDup(XConfigOptionPtr opt);
+void xconfigOptionListFree(XConfigOptionPtr opt);
+char *xconfigOptionName(XConfigOptionPtr opt);
+char *xconfigOptionValue(XConfigOptionPtr opt);
+XConfigOptionPtr xconfigNewOption(char *name, char *value);
+XConfigOptionPtr xconfigNextOption(XConfigOptionPtr list);
+XConfigOptionPtr xconfigFindOption(XConfigOptionPtr list, const char *name);
+char *xconfigFindOptionValue(XConfigOptionPtr list,
+ const char *name);
+int xconfigFindOptionBoolean (XConfigOptionPtr,
+ const char *, int);
+XConfigOptionPtr xconfigOptionListCreate(const char **options,
+ int count, int used);
+XConfigOptionPtr xconfigOptionListMerge(XConfigOptionPtr head,
+ XConfigOptionPtr tail);
+
+/*
+ * Miscellaneous utility routines
+ */
+
+char *xconfigStrdup(const char *s);
+char *xconfigStrcat(const char *str, ...);
+int xconfigNameCompare(const char *s1, const char *s2);
+char *xconfigULongToString(unsigned long i);
+void xconfigDebugListOptions(XConfigOptionPtr);
+XConfigOptionPtr xconfigParseOption(XConfigOptionPtr head);
+void xconfigPrintOptionList(FILE *fp, XConfigOptionPtr list, int tabs);
+int xconfigParsePciBusString(const char *busID,
+ int *bus, int *device, int *func);
+
+XConfigModePtr
+xconfigAddMode(XConfigModePtr head, const char *name);
+
+XConfigModePtr
+xconfigRemoveMode(XConfigModePtr head, const char *name);
+
+
+#define X_IS_XF86 0
+#define X_IS_XORG 1
+
+typedef struct {
+ int xserver;
+ char *x_project_root;
+ char *keyboard;
+ char *mouse;
+ char *keyboard_driver;
+} GenerateOptions;
+
+XConfigPtr xconfigGenerate(GenerateOptions *gop);
+
+XConfigScreenPtr xconfigGenerateAddScreen(XConfigPtr config, int bus, int slot,
+ char *boardname, int count);
+
+void xconfigGenerateAssignScreenAdjacencies(XConfigLayoutPtr layout);
+
+void xconfigGeneratePrintPossibleMice(void);
+void xconfigGeneratePrintPossibleKeyboards(void);
+
+#endif /* _xf86Parser_h_ */
diff --git a/XF86Config-parser/xf86tokens.h b/XF86Config-parser/xf86tokens.h
new file mode 100644
index 0000000..1189bc0
--- /dev/null
+++ b/XF86Config-parser/xf86tokens.h
@@ -0,0 +1,276 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/parser/xf86tokens.h,v 1.20 2003/08/24 17:37:09 dawes Exp $ */
+/*
+ *
+ * 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).
+ */
+
+
+#ifndef _xf86_tokens_h
+#define _xf86_tokens_h
+
+/* Undefine symbols that some OSs might define */
+#undef IOBASE
+
+/*
+ * Each token should have a unique value regardless of the section
+ * it is used in.
+ */
+
+typedef enum {
+ /* errno-style tokens */
+ EOF_TOKEN = -4,
+ LOCK_TOKEN = -3,
+ ERROR_TOKEN = -2,
+
+ /* value type tokens */
+ NUMBER = 1,
+ STRING,
+
+ /* Tokens that can appear in many sections */
+ SECTION,
+ SUBSECTION,
+ ENDSECTION,
+ ENDSUBSECTION,
+ IDENTIFIER,
+ VENDOR,
+ DASH,
+ COMMA,
+ OPTION,
+ COMMENT,
+
+ /* Frequency units */
+ HRZ,
+ KHZ,
+ MHZ,
+
+ /* File tokens */
+ FONTPATH,
+ RGBPATH,
+ MODULEPATH,
+ INPUTDEVICES,
+ LOGFILEPATH,
+
+ /* Server Flag tokens. These are deprecated in favour of generic Options */
+ NOTRAPSIGNALS,
+ DONTZAP,
+ DONTZOOM,
+ DISABLEVIDMODE,
+ ALLOWNONLOCAL,
+ DISABLEMODINDEV,
+ MODINDEVALLOWNONLOCAL,
+ ALLOWMOUSEOPENFAIL,
+ BLANKTIME,
+ STANDBYTIME,
+ SUSPENDTIME,
+ OFFTIME,
+ DEFAULTLAYOUT,
+
+ /* Monitor tokens */
+ MODEL,
+ MODELINE,
+ DISPLAYSIZE,
+ HORIZSYNC,
+ VERTREFRESH,
+ MODE,
+ GAMMA,
+ USEMODES,
+
+ /* Modes tokens */
+ /* no new ones */
+
+ /* Mode tokens */
+ DOTCLOCK,
+ HTIMINGS,
+ VTIMINGS,
+ FLAGS,
+ HSKEW,
+ BCAST,
+ VSCAN,
+ ENDMODE,
+
+ /* Screen tokens */
+ OBSDRIVER,
+ MDEVICE,
+ MONITOR,
+ SCREENNO,
+ DEFAULTDEPTH,
+ DEFAULTBPP,
+ DEFAULTFBBPP,
+
+ /* VideoAdaptor tokens */
+ VIDEOADAPTOR,
+
+ /* Mode timing tokens */
+ TT_INTERLACE,
+ TT_PHSYNC,
+ TT_NHSYNC,
+ TT_PVSYNC,
+ TT_NVSYNC,
+ TT_CSYNC,
+ TT_PCSYNC,
+ TT_NCSYNC,
+ TT_DBLSCAN,
+ TT_HSKEW,
+ TT_BCAST,
+ TT_VSCAN,
+ TT_CUSTOM,
+
+ /* Module tokens */
+ LOAD,
+ LOAD_DRIVER,
+
+ /* Device tokens */
+ DRIVER,
+ CHIPSET,
+ CLOCKS,
+ VIDEORAM,
+ BOARD,
+ IOBASE,
+ RAMDAC,
+ DACSPEED,
+ BIOSBASE,
+ MEMBASE,
+ CLOCKCHIP,
+ CHIPID,
+ CHIPREV,
+ CARD,
+ BUSID,
+ TEXTCLOCKFRQ,
+ IRQ,
+
+ /* Keyboard tokens */
+ AUTOREPEAT,
+ XLEDS,
+ KPROTOCOL,
+ XKBKEYMAP,
+ XKBCOMPAT,
+ XKBTYPES,
+ XKBKEYCODES,
+ XKBGEOMETRY,
+ XKBSYMBOLS,
+ XKBDISABLE,
+ PANIX106,
+ XKBRULES,
+ XKBMODEL,
+ XKBLAYOUT,
+ XKBVARIANT,
+ XKBOPTIONS,
+ /* The next two have become ServerFlags options */
+ VTINIT,
+ VTSYSREQ,
+ /* Obsolete keyboard tokens */
+ SERVERNUM,
+ LEFTALT,
+ RIGHTALT,
+ SCROLLLOCK_TOK,
+ RIGHTCTL,
+ /* arguments for the above obsolete tokens */
+ CONF_KM_META,
+ CONF_KM_COMPOSE,
+ CONF_KM_MODESHIFT,
+ CONF_KM_MODELOCK,
+ CONF_KM_SCROLLLOCK,
+ CONF_KM_CONTROL,
+
+ /* Pointer tokens */
+ EMULATE3,
+ BAUDRATE,
+ SAMPLERATE,
+ PRESOLUTION,
+ CLEARDTR,
+ CLEARRTS,
+ CHORDMIDDLE,
+ PROTOCOL,
+ PDEVICE,
+ EM3TIMEOUT,
+ DEVICE_NAME,
+ ALWAYSCORE,
+ PBUTTONS,
+ ZAXISMAPPING,
+
+ /* Pointer Z axis mapping tokens */
+ XAXIS,
+ YAXIS,
+
+ /* Display tokens */
+ MODES,
+ VIEWPORT,
+ VIRTUAL,
+ VISUAL,
+ BLACK_TOK,
+ WHITE_TOK,
+ DEPTH,
+ BPP,
+ WEIGHT,
+
+ /* Layout Tokens */
+ SCREEN,
+ INACTIVE,
+ INPUTDEVICE,
+
+ /* Adjaceny Tokens */
+ RIGHTOF,
+ LEFTOF,
+ ABOVE,
+ BELOW,
+ RELATIVE,
+ ABSOLUTE,
+
+ /* Vendor Tokens */
+ VENDORNAME,
+
+ /* DRI Tokens */
+ GROUP,
+ BUFFERS
+} ParserTokens;
+
+#endif /* _xf86_tokens_h */
diff --git a/gen-manpage-opts.c b/gen-manpage-opts.c
new file mode 100644
index 0000000..c656003
--- /dev/null
+++ b/gen-manpage-opts.c
@@ -0,0 +1,70 @@
+/*
+ * Prints the option help in a form that is suitable to include in the manpage.
+ */
+#include <stdio.h>
+#include <ctype.h>
+
+#include "XF86Config-parser/xf86Parser.h"
+#include "nvidia-xconfig.h"
+#include "nvgetopt.h"
+#include "option_table.h"
+
+static void print_option(const NVGetoptOption *o)
+{
+ printf(".TP\n.BI ");
+ /* Print the name of the option */
+ /* XXX We should backslashify the '-' characters in o->name. */
+ if (o->flags & NVGETOPT_IS_BOOLEAN) {
+ /* "\-\-name, \-\-no\-name */
+ printf("\"\\-\\-%s, \\-\\-no\\-%s", o->name, o->name);
+ } else if (isalpha(o->val)) {
+ /* "\-c, \-\-name */
+ printf("\"\\-%c, \\-\\-%s", o->val, o->name);
+ } else {
+ /* "\-\-name */
+ printf("\"\\-\\-%s", o->name);
+ }
+
+ if (o->flags & NVGETOPT_HAS_ARGUMENT) {
+ printf("=\" \"%s", o->name);
+ }
+
+ printf("\"\n");
+
+ /* Print the option description */
+ /* XXX Each sentence should be on its own line! */
+ /* XXX We need to backslashify the '-' characters here. */
+ printf("%s\n", o->description);
+}
+
+int main(int argc, char* argv[])
+{
+ int i;
+ const NVGetoptOption *o;
+
+ /* Print the "simple" options, i.e. the ones you get by running
+ * nvidia-xconfig --help.
+ */
+ printf(".SH OPTIONS\n");
+ for (i = 0; __options[i].name; i++) {
+ o = &__options[i];
+
+ if (!(o->flags & OPTION_HELP_ALWAYS))
+ continue;
+
+ print_option(o);
+ }
+
+ /* Print the advanced options. */
+ printf(".SH \"ADVANCED OPTIONS\"\n");
+ for (i = 0; __options[i].name; i++) {
+ o = &__options[i];
+
+ if (o->flags & OPTION_HELP_ALWAYS)
+ continue;
+
+ print_option(o);
+ }
+
+ return 0;
+}
diff --git a/lscf.c b/lscf.c
new file mode 100644
index 0000000..7404ba9
--- /dev/null
+++ b/lscf.c
@@ -0,0 +1,279 @@
+#include <stdio.h>
+#include "nvidia-xconfig.h"
+#if defined(NV_SUNOS)
+
+/* Interface to the Solaris Service Management Facility.
+ * This facility is responsible for running programs and services
+ * and store their configuration informations (named properties)
+ * The configuration informations for the X server are managed by
+ * this facility. The functions in this source file use the library
+ * libscf (Service Configuration Facility) to access and modify
+ * the properties for the X server, more specifically the default depth.
+ * On Solaris, changing the default depth in the xorg.conf file is not
+ * enough. The session manager overrides the xorg.conf default depth:
+ * it passes the option -defdepth to the X server with the value
+ * retrieved from the Service Management Facility.
+ *
+ * For more information refer to the manpages of fmf(5), libsfc(3LIB),
+ * and to the source code of svccfg(1M) available on cvs.opensolaris.org.
+ */
+
+
+#include <libscf.h>
+
+static int lscf_init_handle(scf_handle_t **scf_handle,
+ scf_scope_t **scf_scope);
+static int lscf_select(scf_handle_t *scf_handle,
+ scf_scope_t *scf_scope,
+ const char *selection,
+ scf_service_t **current_svc);
+static int lscf_setprop_int(scf_handle_t *scf_handle,
+ scf_scope_t *scf_scope,
+ scf_service_t *current_svc,
+ const char *group,
+ const char *name, int value);
+
+
+/* UPDATE THE DEFAULT DEPTH PROPERTY IN SMF WITH THE LIBSCF FUNCTIONS */
+int update_scf_depth(int depth)
+{
+ static scf_handle_t *scf_handle = NULL;
+ static scf_scope_t *scf_scope = NULL;
+ scf_service_t *curren_svc = NULL;
+ int status = 1;
+
+ // Initialization of the handles
+ lscf_init_handle(&scf_handle, &scf_scope);
+ if (scf_handle == NULL) {
+ status =0;
+ goto done;
+ }
+
+ // Set the current selection
+ if(!lscf_select(scf_handle, scf_scope, "application/x11/x11-server",
+ &curren_svc)) {
+ status =0;
+ goto done;
+ }
+
+ // Set the depth property of the current selection
+ if(!lscf_setprop_int(scf_handle, scf_scope, curren_svc,
+ "options", "default_depth", depth)) {
+ status =0;
+ goto done;
+ }
+
+done:
+ if(curren_svc) scf_service_destroy(curren_svc);
+ if(scf_scope) scf_scope_destroy(scf_scope);
+ if(scf_handle) {
+ scf_handle_unbind(scf_handle);
+ scf_handle_destroy(scf_handle);
+ }
+ if (!status) {
+ fmterr("Unable to set X server default depth through "
+ "Solaris Service Management Facility");
+ }
+ return status;
+}
+
+
+/* INITIALIZATION OF THE HANDLES */
+static int lscf_init_handle(scf_handle_t **scf_handle,
+ scf_scope_t **scf_scope)
+{
+ scf_handle_t *handle = NULL;
+ scf_scope_t *scope = NULL;;
+
+ *scf_handle = NULL;
+ *scf_scope = NULL;
+
+ // Create a new Service Configuration Facility
+ // handle, needed for the communication with the
+ // configuration repository.
+ handle = scf_handle_create(SCF_VERSION);
+ if (handle == NULL) {
+ return 0;
+ }
+
+ // Bind the handle to the running svc.config daemon
+ if (scf_handle_bind(handle) != 0) {
+ scf_handle_destroy(handle);
+ return 0;
+ }
+
+
+ // Allocate a new scope. A scope is a top level of the
+ // SCF repository tree.
+ scope = scf_scope_create(handle);
+ if (scope == NULL) {
+ scf_handle_unbind(handle);
+ scf_handle_destroy(handle);
+ return 0;
+ }
+
+ // Set the scope to the root of the local SCF repository tree.
+ if (scf_handle_get_scope(handle, SCF_SCOPE_LOCAL, scope) !=0) {
+ scf_scope_destroy(scope);
+ scf_handle_unbind(handle);
+ scf_handle_destroy(handle);
+ return 0;
+ }
+
+ *scf_handle = handle;
+ *scf_scope = scope;
+
+ return 1;
+}
+
+
+/* EQUIVALENT TO THE SVCCFG SELECT COMMAND */
+static int lscf_select(scf_handle_t *scf_handle,
+ scf_scope_t *scf_scope,
+ const char *selection,
+ scf_service_t **current_svc)
+{
+ scf_service_t *svc;
+
+ // Services are childrens of a scope, and
+ // contain configuration informations for
+ // the service.
+ svc = scf_service_create(scf_handle);
+ if (svc == NULL) {
+ return 0;
+ }
+
+ // Set the service 'svc' to the service specified
+ // by 'selection', in the scope 'scf_scope'.
+ if (scf_scope_get_service(scf_scope, selection, svc) == SCF_SUCCESS) {
+ *current_svc = svc;
+ return 1;
+ }
+
+ scf_service_destroy(svc);
+ return 0;
+}
+
+/* EQUIVALENT TO THE SVCCFG SETPROP COMMAND FOR AN INTEGER TYPED VALUE */
+static int lscf_setprop_int(scf_handle_t *scf_handle,
+ scf_scope_t *scf_scope,
+ scf_service_t *current_svc,
+ const char *group,
+ const char *name, int value)
+{
+ scf_transaction_entry_t *entry=NULL;
+ scf_propertygroup_t *pg = NULL;
+ scf_property_t *prop = NULL;
+ scf_transaction_t *transax = NULL;
+ scf_value_t *v = NULL;
+ int status = 1;
+
+ // Allocate a new transaction entry handle
+ entry = scf_entry_create(scf_handle);
+ if (entry == NULL) {
+ status=0;
+ goto done;
+ }
+
+ // Allocate a property group.
+ pg = scf_pg_create(scf_handle);
+ if (pg == NULL) {
+ status=0;
+ goto done;
+ }
+
+ // Allocate a property. A property is a named set
+ // of values.
+ prop = scf_property_create(scf_handle);
+ if (prop == NULL) {
+ status=0;
+ goto done;
+ }
+
+ // Allocate a transaction, used to change
+ // property groups.
+ transax = scf_transaction_create(scf_handle);
+ if (transax == NULL) {
+ status=0;
+ goto done;
+ }
+
+ // Allocate a value.
+ v = scf_value_create(scf_handle);
+ if (v == NULL) {
+ status=0;
+ goto done;
+ }
+
+ // Set the the property group 'pg' to the
+ // groups specified by 'group' in the service
+ // specified by 'current_svc'
+ if (scf_service_get_pg(current_svc, group, pg) != SCF_SUCCESS) {
+ status=0;
+ goto done;
+ }
+
+ // Update the property group.
+ if (scf_pg_update(pg) == -1) {
+ status=0;
+ goto done;
+ }
+
+ // Set up the transaction to modify the property group.
+ if (scf_transaction_start(transax, pg) != SCF_SUCCESS) {
+ status=0;
+ goto done;
+ }
+
+ // Set the property 'prop' to the property
+ // specified ny 'name' in the property group 'pg'
+ if (scf_pg_get_property(pg, name, prop) == SCF_SUCCESS) {
+ // Found
+ // It should be already of integer type.
+ // To be secure, reset the property type to integer.
+ if (scf_transaction_property_change_type(transax, entry,
+ name, SCF_TYPE_INTEGER) == -1) {
+ status=0;
+ goto done;
+ }
+ } else {
+ // Not found
+ // Add a new property to the property group.
+ if (scf_transaction_property_new(transax, entry,
+ name, SCF_TYPE_INTEGER)
+ == -1) {
+ status=0;
+ goto done;
+ }
+ }
+
+ // Set the integer value
+ scf_value_set_integer(v, value);
+
+ // Set up the value to the property.
+ if (scf_entry_add_value(entry, v) != SCF_SUCCESS) {
+ status=0;
+ goto done;
+ }
+
+ // Commit the transaction
+ if (scf_transaction_commit(transax) < 0) {
+ status=0;
+ }
+
+done:
+ if (entry) scf_entry_destroy(entry);
+ if (pg) scf_pg_destroy(pg);
+ if (prop) scf_property_destroy(prop);
+ if (transax) scf_transaction_destroy(transax);
+ if (v) scf_value_destroy(v);
+ return status;
+}
+
+
+#else // NOT SOLARIS
+int update_scf_depth(int depth)
+{
+ return 1;
+}
+#endif
diff --git a/make_usable.c b/make_usable.c
new file mode 100644
index 0000000..0f6c189
--- /dev/null
+++ b/make_usable.c
@@ -0,0 +1,271 @@
+/*
+ * nvidia-xconfig: A tool for manipulating X config files,
+ * specifically for use by the NVIDIA Linux graphics driver.
+ *
+ * Copyright (C) 2005 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ * make_usable.c
+ */
+
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "nvidia-xconfig.h"
+#include "xf86Parser.h"
+
+
+static int update_device(XConfigPtr config, XConfigDevicePtr device);
+static void update_depth(Options *op, XConfigScreenPtr screen);
+static void update_display(Options *op, XConfigScreenPtr screen);
+
+
+/*
+ * update_modules() - make sure the glx module is present, and remove
+ * the GLcore and dri modules if they are present.
+ */
+
+int update_modules(XConfigPtr config)
+{
+ XConfigLoadPtr load, next;
+ int found;
+
+ /* make sure glx is loaded */
+
+ found = FALSE;
+ for (load = config->modules->loads; load; load = load->next) {
+ if (xconfigNameCompare("glx", load->name) == 0) found = TRUE;
+ }
+
+ if (!found) {
+ config->modules->loads =
+ xconfigAddNewLoadDirective(config->modules->loads,
+ "glx", XCONFIG_LOAD_MODULE,
+ NULL, FALSE);
+ }
+
+ /* make sure GLcore and dri are not loaded */
+
+ load = config->modules->loads;
+ while (load) {
+ next = load->next;
+ if (xconfigNameCompare("GLcore", load->name) == 0) {
+ config->modules->loads =
+ xconfigRemoveLoadDirective(config->modules->loads, load);
+ } else if (xconfigNameCompare("dri", load->name) == 0) {
+ config->modules->loads =
+ xconfigRemoveLoadDirective(config->modules->loads, load);
+ }
+ load = next;
+ }
+
+ return TRUE;
+
+} /* update_modules() */
+
+
+
+/*
+ * update_screen() - apply any requested updates to the given screen
+ */
+
+int update_screen(Options *op, XConfigPtr config, XConfigScreenPtr screen)
+{
+ /* migrate any options from device to screen to avoid conflicts */
+ screen->options = xconfigOptionListMerge(screen->options,
+ screen->device->options);
+ screen->device->options = NULL;
+
+ update_display(op, screen);
+ update_depth(op, screen);
+ update_device(config, screen->device);
+ update_options(op, screen);
+
+ return TRUE;
+
+} /* update_screen() */
+
+
+
+/*
+ * get_layout() - get the right layout from the config that we should
+ * edit
+ */
+
+XConfigLayoutPtr get_layout(Options *op, XConfigPtr config)
+{
+ XConfigLayoutPtr layout;
+
+ /* select a screenLayout to use */
+
+ if (op->layout) {
+
+ /* if a layout was specified on the commandline, use that */
+
+ layout = xconfigFindLayout(op->layout, config->layouts);
+ if (!layout) {
+ fmterr("Unable to find layout \"%s\".\n", op->layout);
+ return NULL;
+ }
+ } else {
+
+ /* otherwise, use the first layout in the config file */
+
+ if (!config->layouts) {
+ fmterr("unable to select ScreenLayout to use.\n");
+ return NULL;
+ }
+
+ layout = config->layouts;
+ }
+
+ return layout;
+
+} /* get_layout() */
+
+
+
+/*
+ * update_device() - update the device; there is a lot of information
+ * in the device that is not relevant to the NVIDIA X driver. In
+ * fact, some options, like "Chipset" can actually prevent XFree86
+ * from using the NVIDIA driver. The simplest solution is to zero out
+ * the device, and only retain the few fields that are meaningful for
+ * the NVIDIA X driver.
+ */
+
+static int update_device(XConfigPtr config, XConfigDevicePtr device)
+{
+ char *identifier, *vendor, *comment, *board, *busid;
+ int screen;
+ XConfigDevicePtr next;
+ XConfigOptionPtr options;
+
+ next = device->next;
+ options = device->options;
+ identifier = device->identifier;
+ vendor = device->vendor;
+ comment = device->comment;
+ screen = device->screen;
+ board = device->board;
+ busid = device->busid;
+
+ memset(device, 0, sizeof(XConfigDeviceRec));
+
+ device->next = next;
+ device->options = options;
+ device->identifier = identifier;
+ device->vendor = vendor;
+ device->comment = comment;
+ device->screen = screen;
+ device->board = board;
+ device->busid = busid;
+
+ device->chipid = -1;
+ device->chiprev = -1;
+ device->irq = -1;
+
+ device->driver = "nvidia";
+
+ /*
+ * XXX do we really want to preserve the BusID line? Let's only
+ * preserve the BusID if there are multiple screens in this
+ * config; not a very good heuristic
+ */
+
+ if (!config->screens->next) {
+ device->busid = NULL;
+ }
+
+ return TRUE;
+
+} /* update_device() */
+
+
+
+/*
+ * update_depth() - make sure there is a display section with the
+ * default depth, and possibly update the default depth
+ */
+
+static void update_depth(Options *op, XConfigScreenPtr screen)
+{
+ XConfigDisplayPtr display;
+ int found;
+
+ /* update the depth */
+ if ((op->depth == 8) || (op->depth == 15) ||
+ (op->depth == 16) || (op->depth == 24)) {
+ screen->defaultdepth = op->depth;
+ }
+
+ /*
+ * if there is no display at the default depth, force the first
+ * display section to that depth
+ */
+
+ found = FALSE;
+
+ for (display = screen->displays; display; display = display->next) {
+ if (display->depth == screen->defaultdepth) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found) {
+ screen->displays->depth = screen->defaultdepth;
+ }
+
+} /* update_depth() */
+
+
+
+/*
+ * update_display() - if there are no display subsections, create one
+ */
+
+static void update_display(Options *op, XConfigScreenPtr screen)
+{
+
+ if (!screen->displays) {
+ XConfigDisplayPtr display;
+ XConfigModePtr mode = NULL;
+
+ mode = xconfigAddMode(mode, "640x480");
+ mode = xconfigAddMode(mode, "800x600");
+ mode = xconfigAddMode(mode, "1024x768");
+ mode = xconfigAddMode(mode, "1280x1024");
+ mode = xconfigAddMode(mode, "1600x1200");
+
+ display = nvalloc(sizeof(XConfigDisplayRec));
+ display->depth = screen->defaultdepth;
+ display->modes = mode;
+ display->frameX0 = -1;
+ display->frameY0 = -1;
+ display->black.red = -1;
+ display->white.red = -1;
+
+ screen->displays = display;
+ }
+} /* update_display() */
+
+
diff --git a/multiple_screens.c b/multiple_screens.c
new file mode 100644
index 0000000..5b4597c
--- /dev/null
+++ b/multiple_screens.c
@@ -0,0 +1,910 @@
+/*
+ * nvidia-xconfig: A tool for manipulating X config files,
+ * specifically for use by the NVIDIA Linux graphics driver.
+ *
+ * Copyright (C) 2005 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ * multiple_screens.c
+ */
+
+#include "nvidia-xconfig.h"
+#include "xf86Parser.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+
+
+typedef struct _device_rec {
+ NvCfgDevice dev;
+ NvCfgDisplayDeviceInformation info[2];
+ int edid_valid;
+ int crtcs;
+ char *name;
+ unsigned int display_device_mask;
+} DeviceRec, *DevicePtr;
+
+static DevicePtr find_devices(Options *op, int *num);
+
+static int enable_separate_x_screens(Options *op, XConfigPtr config,
+ XConfigLayoutPtr layout);
+static int disable_separate_x_screens(Options *op, XConfigPtr config,
+ XConfigLayoutPtr layout);
+
+static int set_xinerama(int xinerama_enabled, XConfigPtr config);
+
+static XConfigDisplayPtr clone_display_list(XConfigDisplayPtr display0);
+static XConfigDevicePtr clone_device(XConfigDevicePtr device0);
+static XConfigScreenPtr clone_screen(XConfigScreenPtr screen0);
+
+static void create_adjacencies(Options *op, XConfigPtr config,
+ XConfigLayoutPtr layout);
+
+static int enable_all_gpus(Options *op, XConfigPtr config,
+ XConfigLayoutPtr layout);
+
+static void free_unused_devices(Options *op, XConfigPtr config);
+static void free_unused_monitors(Options *op, XConfigPtr config);
+
+static int only_one_screen(Options *op, XConfigPtr config,
+ XConfigLayoutPtr layout);
+
+/*
+ * apply_multi_screen_options() - there are 4 options that can affect
+ * multiple X screens:
+ *
+ * - add X screens for all GPUS in the system
+ * - separate X screens on one GPU (turned on or off)
+ * - only one X screen
+ * - Xinerama
+ *
+ * apply these options in that order
+ */
+
+int apply_multi_screen_options(Options *op, XConfigPtr config,
+ XConfigLayoutPtr layout)
+{
+ if (op->enable_all_gpus) {
+ if (!enable_all_gpus(op, config, layout)) return FALSE;
+ }
+
+
+ if (GET_BOOL_OPTION(op->boolean_options,
+ SEPARATE_X_SCREENS_OPTION)) {
+ if (GET_BOOL_OPTION(op->boolean_option_values,
+ SEPARATE_X_SCREENS_OPTION)) {
+ if (!enable_separate_x_screens(op, config, layout)) return FALSE;
+ } else {
+ if (!disable_separate_x_screens(op, config, layout)) return FALSE;
+ }
+ }
+
+ if (GET_BOOL_OPTION(op->boolean_options,
+ XINERAMA_OPTION)) {
+ if (!set_xinerama(GET_BOOL_OPTION(op->boolean_option_values,
+ XINERAMA_OPTION),
+ config)) return FALSE;
+ }
+
+ if (op->only_one_screen) {
+ if (!only_one_screen(op, config, layout)) return FALSE;
+ }
+
+ return TRUE;
+
+} /* apply_multi_screen_options() */
+
+
+
+/*
+ * find_devices() - dlopen the nvidia-cfg library and query the
+ * available information about the GPUs in the system.
+ */
+
+static DevicePtr find_devices(Options *op, int *num)
+{
+ DevicePtr devices = NULL;
+ int i, j, n, count = 0;
+ unsigned int mask, bit;
+ NvCfgDeviceHandle handle;
+ NvCfgDevice *devs = NULL;
+ char *lib_path;
+ void *lib_handle;
+
+ NvCfgBool (*__getDevices)(int *n, NvCfgDevice **devs);
+ NvCfgBool (*__openDevice)(int bus, int slot, NvCfgDeviceHandle *handle);
+ NvCfgBool (*__getNumCRTCs)(NvCfgDeviceHandle handle, int *crtcs);
+ NvCfgBool (*__getProductName)(NvCfgDeviceHandle handle, char **name);
+ NvCfgBool (*__getDisplayDevices)(NvCfgDeviceHandle handle,
+ unsigned int *display_device_mask);
+ NvCfgBool (*__getEDID)(NvCfgDeviceHandle handle,
+ unsigned int display_device,
+ NvCfgDisplayDeviceInformation *info);
+ NvCfgBool (*__closeDevice)(NvCfgDeviceHandle handle);
+
+ *num = 0;
+
+ /* dlopen() the nvidia-cfg library */
+
+#define __LIB_NAME "libnvidia-cfg.so.1"
+
+ if (op->nvidia_cfg_path) {
+ lib_path = nvstrcat(op->nvidia_cfg_path, "/", __LIB_NAME, NULL);
+ } else {
+ lib_path = strdup(__LIB_NAME);
+ }
+
+ lib_handle = dlopen(lib_path, RTLD_NOW);
+
+ nvfree(lib_path);
+
+ if (!lib_handle) {
+ fmtwarn("error opening %s: %s.", __LIB_NAME, dlerror());
+ return NULL;
+ }
+
+#define __GET_FUNC(proc, name) \
+ (proc) = dlsym(lib_handle, (name)); \
+ if (!(proc)) { \
+ fmtwarn("error retrieving symbol %s from %s: %s", \
+ (name), __LIB_NAME, dlerror()); \
+ dlclose(lib_handle); \
+ return NULL; \
+ }
+
+ __GET_FUNC(__getDevices, "nvCfgGetDevices");
+ __GET_FUNC(__openDevice, "nvCfgOpenDevice");
+ __GET_FUNC(__getNumCRTCs, "nvCfgGetNumCRTCs");
+ __GET_FUNC(__getProductName, "nvCfgGetProductName");
+ __GET_FUNC(__getDisplayDevices, "nvCfgGetDisplayDevices");
+ __GET_FUNC(__getEDID, "nvCfgGetEDID");
+ __GET_FUNC(__closeDevice, "nvCfgCloseDevice");
+
+ if (__getDevices(&count, &devs) != NVCFG_TRUE) {
+ return NULL;
+ }
+
+ if (count == 0) return NULL;
+
+ devices = nvalloc(sizeof(DeviceRec) * count);
+
+ for (i = 0; i < count; i++) {
+
+ devices[i].dev = devs[i];
+
+ if (__openDevice(devs[i].bus, devs[i].slot, &handle) != NVCFG_TRUE)
+ goto fail;
+
+ if (__getNumCRTCs(handle, &devices[i].crtcs) != NVCFG_TRUE)
+ goto fail;
+
+ if (__getProductName(handle, &devices[i].name) != NVCFG_TRUE)
+ goto fail;
+
+ if (__getDisplayDevices(handle, &mask) != NVCFG_TRUE)
+ goto fail;
+
+ devices[i].display_device_mask = mask;
+
+ for (n = j = 0; j < 32; j++) {
+ bit = 1 << j;
+ if (!(bit & mask)) continue;
+
+ if (__getEDID(handle, bit, &devices[i].info[n]) != NVCFG_TRUE) {
+ devices[i].edid_valid = FALSE;
+ } else {
+ devices[i].edid_valid = TRUE;
+ }
+
+ n++;
+ }
+
+ if (__closeDevice(handle) != NVCFG_TRUE)
+ goto fail;
+ }
+
+ *num = count;
+
+ return devices;
+
+ fail:
+
+ *num = 0;
+ if (devices) nvfree((void *) devices);
+ if (devs) free(devs);
+
+ fmtwarn("Unable to use the nvidia-cfg library to query NVIDIA "
+ "hardware.");
+
+ return NULL;
+
+} /* find_devices() */
+
+
+
+/*
+ * set_xinerama() - This makes sure there is a ServerFlags
+ * section and sets the "Xinerama" option
+ */
+
+static int set_xinerama(int xinerama_enabled, XConfigPtr config)
+{
+ if (!config->flags) {
+ config->flags = nvalloc(sizeof(XConfigFlagsRec));
+ if ( !config->flags ) {
+ return FALSE;
+ }
+ }
+
+ if (config->flags->options) {
+ remove_option_from_list(&(config->flags->options), "Xinerama");
+ }
+
+ config->flags->options =
+ xconfigAddNewOption(config->flags->options,
+ nvstrdup("Xinerama"),
+ nvstrdup(xinerama_enabled?"1":"0"));
+
+ return TRUE;
+
+} /* set_xinerama() */
+
+
+
+/*
+ * enable_separate_x_screens() - this effectively clones each screen
+ * that is on a unique GPU.
+ *
+ * Algorithm:
+ *
+ * step 1: build a list of screens to be cloned
+ *
+ * step 2: assign a busID to every screen that is in the list (if
+ * BusIDs are not already assigned)
+ *
+ * step 3: for every candidate screen, check if it is already one of
+ * multiple screens on a gpu; if so, then it is not eligible for
+ * cloning. Note that this has to check all screens in the adjacency
+ * list, not just the ones in the candidate list.
+ *
+ * step 4: clone each eligible screen
+ *
+ * step 5: update adjacency list (just wipe the list and restart)
+ *
+ * XXX we need to check that there are actually 2 CRTCs on this GPU
+ */
+
+static int enable_separate_x_screens(Options *op, XConfigPtr config,
+ XConfigLayoutPtr layout)
+{
+ XConfigScreenPtr screen, *screenlist = NULL;
+ XConfigAdjacencyPtr adj;
+
+ int i, nscreens = 0;
+ int have_busids;
+
+ /* build the list of screens that are candidate to be cloned */
+
+ if (op->screen) {
+ screen = xconfigFindScreen(op->screen, config->screens);
+ if (!screen) {
+ fmterr("Unable to find screen '%s'.", op->screen);
+ return FALSE;
+ }
+
+ screenlist = nvalloc(sizeof(XConfigScreenPtr));
+ screenlist[0] = screen;
+ nscreens = 1;
+
+ } else {
+ for (adj = layout->adjacencies; adj; adj = adj->next) {
+ nscreens++;
+ screenlist = realloc(screenlist,
+ sizeof(XConfigScreenPtr) * nscreens);
+
+ screenlist[nscreens-1] = adj->screen;
+ }
+ }
+
+ if (!nscreens) return FALSE;
+
+ /* do all screens in the list have a bus ID? */
+
+ have_busids = TRUE;
+
+ for (i = 0; i < nscreens; i++) {
+ if (screenlist[i] &&
+ screenlist[i]->device &&
+ screenlist[i]->device->busid) {
+ // this screen has a busid
+ } else {
+ have_busids = FALSE;
+ break;
+ }
+ }
+
+ /*
+ * if not everyone has a bus id, then let's assign bus ids to all
+ * the screens; XXX what if _some_ already have busids? Too bad,
+ * we're going to reassign all of them.
+ */
+
+ if (!have_busids) {
+ DevicePtr devs;
+ int ndevs;
+
+ devs = find_devices(op, &ndevs);
+ if (!devs) {
+ fmterr("Unable to determine number or location of "
+ "GPUs in system; cannot "
+ "honor '--separate-x-screens' option.");
+ return FALSE;
+ }
+
+ for (i = 0; i < nscreens; i++) {
+ if (i > ndevs) {
+ /*
+ * we have more screens than GPUs, this screen is no
+ * longer a candidate
+ */
+ screenlist[i] = NULL;
+ continue;
+ }
+
+ screenlist[i]->device->busid = nvalloc(32);
+ snprintf(screenlist[i]->device->busid, 32,
+ "PCI:%d:%d:0", devs[i].dev.bus, devs[i].dev.slot);
+ screenlist[i]->device->board = nvstrdup(devs[i].name);
+ }
+ }
+
+ /*
+ * step 3: for every candidate screen, check if it is already one
+ * of multiple screens on a gpu; if so, then it is not eligible
+ * for cloning. Note that this has to check all screens in the
+ * adjacency list, not just the ones in the candidate list
+ */
+
+ for (i = 0; i < nscreens; i++) {
+ int bus0, bus1, slot0, slot1, scratch;
+ if (!screenlist[i]) continue;
+
+ /* parse the bus id for this candidate screen */
+
+ if (!xconfigParsePciBusString(screenlist[i]->device->busid,
+ &bus0, &slot0, &scratch)) {
+ /* parsing failed; this screen is no longer a candidate */
+ screenlist[i] = NULL;
+ continue;
+ }
+
+ /*
+ * scan through all the screens; if any screen, other than
+ * *this* screen, have the same busid, then this screen is no
+ * longer a candidate
+ */
+
+ for (screen = config->screens; screen; screen = screen->next) {
+ if (screen == screenlist[i]) continue;
+ if (!screen->device) continue;
+ if (!screen->device->busid) continue;
+ if (!xconfigParsePciBusString(screen->device->busid,
+ &bus1, &slot1, &scratch)) continue;
+ if ((bus0 == bus1) && (slot0 == slot1)) {
+ screenlist[i] = NULL; /* no longer a candidate */
+ }
+ }
+ }
+
+ /* clone each eligible screen */
+
+ for (i = 0; i < nscreens; i++) {
+ if (!screenlist[i]) continue;
+ clone_screen(screenlist[i]);
+ }
+
+ /* wipe the existing adjacencies and recreate them */
+
+ xconfigFreeAdjacencyList(layout->adjacencies);
+ layout->adjacencies = NULL;
+
+ create_adjacencies(op, config, layout);
+
+ /* free stuff */
+
+ free(screenlist);
+
+ return TRUE;
+
+} /* enable_separate_x_screens() */
+
+
+/*
+ * disable_separate_x_screens() - remove multiple screens that are
+ * configured for the same GPU.
+ *
+ * Algorithm:
+ *
+ * step 1: find which screens need to be "de-cloned" (either
+ * op->screen or all screens in the layout)
+ *
+ * step 2: narrow that list down to screens that have a busid
+ * specified
+ *
+ * step 3: find all other screens that have the same busid and remove
+ * them
+ *
+ * step 3: recompute the adjacency list
+ */
+
+static int disable_separate_x_screens(Options *op, XConfigPtr config,
+ XConfigLayoutPtr layout)
+{
+ XConfigScreenPtr screen, prev, next, *screenlist = NULL;
+ XConfigAdjacencyPtr adj;
+
+ int i, j, nscreens = 0;
+ int *bus, *slot, scratch;
+
+ /* build the list of screens that are candidate to be de-cloned */
+
+ if (op->screen) {
+ screen = xconfigFindScreen(op->screen, config->screens);
+ if (!screen) {
+ fmterr("Unable to find screen '%s'.", op->screen);
+ return FALSE;
+ }
+
+ screenlist = nvalloc(sizeof(XConfigScreenPtr));
+ screenlist[0] = screen;
+ nscreens = 1;
+
+ } else {
+ for (adj = layout->adjacencies; adj; adj = adj->next) {
+ nscreens++;
+ screenlist = realloc(screenlist,
+ sizeof(XConfigScreenPtr) * nscreens);
+
+ screenlist[nscreens-1] = adj->screen;
+ }
+ }
+
+ /*
+ * limit the list to screens that have a BusID; parse the busIDs
+ * while we're at it
+ */
+
+ bus = nvalloc(sizeof(int) * nscreens);
+ slot = nvalloc(sizeof(int) * nscreens);
+
+ for (i = 0; i < nscreens; i++) {
+ if (screenlist[i] &&
+ screenlist[i]->device &&
+ screenlist[i]->device->busid &&
+ xconfigParsePciBusString(screenlist[i]->device->busid,
+ &bus[i], &slot[i], &scratch)) {
+ // this screen has a valid busid
+ } else {
+ screenlist[i] = NULL;
+ }
+ }
+
+ /* trim out duplicates */
+
+ for (i = 0; i < nscreens; i++) {
+
+ if (!screenlist[i]) continue;
+
+ for (j = i+1; j < nscreens; j++) {
+ if (!screenlist[j]) continue;
+ if ((bus[i] == bus[j]) && (slot[i] == slot[j])) {
+ screenlist[j] = NULL;
+ }
+ }
+ }
+
+ /*
+ * for every screen in the de-clone list, scan through all
+ * screens; if any screen, other than *this* screen has the same
+ * busid, remove it
+ */
+
+ for (i = 0; i < nscreens; i++) {
+ int bus0, slot0;
+ if (!screenlist[i]) continue;
+
+ screen = config->screens;
+ prev = NULL;
+
+ while (screen) {
+ if (screenlist[i] == screen) goto next_screen;
+ if (!screen->device) goto next_screen;
+ if (!screen->device->busid) goto next_screen;
+ if (!xconfigParsePciBusString(screen->device->busid,
+ &bus0, &slot0, &scratch))
+ goto next_screen;
+
+ if ((bus0 == bus[i]) && (slot0 == slot[i])) {
+ if (prev) {
+ prev->next = screen->next;
+ } else {
+ config->screens = screen->next;
+ }
+ next = screen->next;
+ screen->next = NULL;
+ xconfigFreeScreenList(screen);
+ screen = next;
+ } else {
+
+ next_screen:
+
+ prev = screen;
+ screen = screen->next;
+ }
+ }
+
+ screenlist[i]->device->screen = -1;
+ }
+
+ /* wipe the existing adjacencies and recreate them */
+
+ xconfigFreeAdjacencyList(layout->adjacencies);
+ layout->adjacencies = NULL;
+
+ create_adjacencies(op, config, layout);
+
+ /* free unused device and monitor sections */
+
+ free_unused_devices(op, config);
+ free_unused_monitors(op, config);
+
+ /* free stuff */
+
+ free(screenlist);
+ free(bus);
+ free(slot);
+
+ return TRUE;
+
+} /* disable_separate_x_screens() */
+
+
+/*
+ * clone_display_list() - create a duplicate of the specified display
+ * subsection.
+ */
+
+static XConfigDisplayPtr clone_display_list(XConfigDisplayPtr display0)
+{
+ XConfigDisplayPtr d = NULL, prev = NULL, head = NULL;
+
+ while (display0) {
+ d = nvalloc(sizeof(XConfigDisplayRec));
+ memcpy(d, display0, sizeof(XConfigDisplayRec));
+ if (display0->visual) d->visual = nvstrdup(display0->visual);
+ if (display0->comment) d->comment = nvstrdup(display0->comment);
+ d->options = xconfigOptionListDup(display0->options);
+ d->next = NULL;
+ if (prev) prev->next = d;
+ if (!head) head = d;
+ prev = d;
+ display0 = display0->next;
+ }
+
+ return head;
+
+} /* clone_display_list() */
+
+
+
+/*
+ * clone_device() - duplicate the specified device section, updating
+ * the screen indices as approprate for multiple X screens on one GPU
+ */
+
+static XConfigDevicePtr clone_device(XConfigDevicePtr device0)
+{
+ XConfigDevicePtr device;
+
+ device = nvalloc(sizeof(XConfigDeviceRec));
+
+ device->identifier = nvstrcat(device0->identifier, " (2nd)", NULL);
+
+ if (device0->vendor) device->vendor = nvstrdup(device0->vendor);
+ if (device0->board) device->board = nvstrdup(device0->board);
+ if (device0->chipset) device->chipset = nvstrdup(device0->chipset);
+ if (device0->busid) device->busid = nvstrdup(device0->busid);
+ if (device0->card) device->card = nvstrdup(device0->card);
+ if (device0->driver) device->driver = nvstrdup(device0->driver);
+ if (device0->ramdac) device->ramdac = nvstrdup(device0->ramdac);
+ if (device0->comment) device->comment = nvstrdup(device0->comment);
+
+ /* these are needed for multiple X screens on one GPU */
+
+ device->screen = 1;
+ device0->screen = 0;
+
+ device->chipid = -1;
+ device->chiprev = -1;
+ device->irq = -1;
+
+ device->options = xconfigOptionListDup(device0->options);
+
+ /* insert the new device after the original device */
+
+ device->next = device0->next;
+ device0->next = device;
+
+ return device;
+
+} /* clone_device() */
+
+
+
+/*
+ * clone_screen() - duplicate the given screen, for use as the second
+ * X screen on one GPU
+ */
+
+static XConfigScreenPtr clone_screen(XConfigScreenPtr screen0)
+{
+ XConfigScreenPtr screen = nvalloc(sizeof(XConfigScreenRec));
+
+ screen->identifier = nvstrcat(screen0->identifier, " (2nd)", NULL);
+
+ screen->device = clone_device(screen0->device);
+ screen->device_name = nvstrdup(screen->device->identifier);
+
+ screen->monitor = screen0->monitor;
+ screen->monitor_name = nvstrdup(screen0->monitor_name);
+
+ screen->defaultdepth = screen0->defaultdepth;
+
+ screen->displays = clone_display_list(screen0->displays);
+
+ screen->options = xconfigOptionListDup(screen0->options);
+ if (screen0->comment) screen->comment = nvstrdup(screen0->comment);
+
+ /* insert the new screen after the original screen */
+
+ screen->next = screen0->next;
+ screen0->next = screen;
+
+ return screen;
+
+} /* clone_screen() */
+
+
+
+/*
+ * create_adjacencies() - loop through all the screens in the config,
+ * and add an adjacency section to the layout; this assumes that there
+ * are no existing adjacencies in the layout
+ */
+
+static void create_adjacencies(Options *op, XConfigPtr config,
+ XConfigLayoutPtr layout)
+{
+ XConfigAdjacencyPtr adj, prev_adj;
+ XConfigScreenPtr screen, prev;
+ int i;
+
+ prev = NULL;
+ i = 0;
+ prev_adj = NULL;
+
+ for (screen = config->screens; screen; screen = screen->next) {
+
+ adj = nvalloc(sizeof(XConfigAdjacencyRec));
+
+ adj->scrnum = i;
+ adj->screen_name = nvstrdup(screen->identifier);
+ adj->screen = screen;
+
+ if (prev_adj) {
+ prev_adj->next = adj;
+ } else {
+ layout->adjacencies = adj;
+ }
+
+ prev_adj = adj;
+ prev = screen;
+ i++;
+ }
+
+ xconfigGenerateAssignScreenAdjacencies(layout);
+
+} /* create_adjacencies() */
+
+
+/*
+ * enable_all_gpus() - get information for every GPU in the system,
+ * and create a screen section for each
+ *
+ * XXX do we add new screens with reasonable defaults, or do we clone
+ * the first existing X screen N times? For now, we'll just add all
+ * new X screens
+ */
+
+static int enable_all_gpus(Options *op, XConfigPtr config,
+ XConfigLayoutPtr layout)
+{
+ DevicePtr devs;
+ int n, i;
+
+ devs = find_devices(op, &n);
+ if (!devs) {
+ fmterr("Unable to determine number of GPUs in system; cannot "
+ "honor '--enable-all-gpus' option.");
+ return FALSE;
+ }
+
+ /* free all existing X screens, monitors, devices, and adjacencies */
+
+ xconfigFreeScreenList(config->screens);
+ config->screens = NULL;
+
+ xconfigFreeDeviceList(config->devices);
+ config->devices = NULL;
+
+ xconfigFreeMonitorList(config->monitors);
+ config->monitors = NULL;
+
+ xconfigFreeAdjacencyList(layout->adjacencies);
+ layout->adjacencies = NULL;
+
+ /* add N new screens; this will also add device and monitor sections */
+
+ for (i = 0; i < n; i++) {
+ xconfigGenerateAddScreen(config, devs[i].dev.bus, devs[i].dev.slot,
+ devs[i].name, i);
+ }
+
+ /* create adjacencies for the layout */
+
+ create_adjacencies(op, config, layout);
+
+ return TRUE;
+
+} /* enable_all_gpus() */
+
+
+
+/*
+ * free_unused_devices() - free unused device sections
+ */
+
+static void free_unused_devices(Options *op, XConfigPtr config)
+{
+ XConfigDevicePtr device, prev, next;
+ XConfigScreenPtr screen;
+ int found;
+
+ /* free any unused device sections */
+
+ device = config->devices;
+ prev = NULL;
+
+ while (device) {
+ found = FALSE;
+
+ for (screen = config->screens; screen; screen = screen->next) {
+ if (device == screen->device) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found) {
+ if (prev) {
+ prev->next = device->next;
+ } else {
+ config->devices = device->next;
+ }
+ next = device->next;
+ device->next = NULL;
+ xconfigFreeDeviceList(device);
+ device = next;
+ } else {
+ prev = device;
+ device = device->next;
+ }
+ }
+} /* free_unused_devices() */
+
+
+
+/*
+ * free_unused_monitors() - free unused monitor sections
+ */
+
+static void free_unused_monitors(Options *op, XConfigPtr config)
+{
+ XConfigMonitorPtr monitor, prev, next;
+ XConfigScreenPtr screen;
+ int found;
+
+ /* free any unused monitor sections */
+
+ monitor = config->monitors;
+ prev = NULL;
+
+ while (monitor) {
+ found = FALSE;
+
+ for (screen = config->screens; screen; screen = screen->next) {
+ if (monitor == screen->monitor) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found) {
+ if (prev) {
+ prev->next = monitor->next;
+ } else {
+ config->monitors = monitor->next;
+ }
+ next = monitor->next;
+ monitor->next = NULL;
+ xconfigFreeMonitorList(monitor);
+ monitor = next;
+ } else {
+ prev = monitor;
+ monitor = monitor->next;
+ }
+ }
+} /* free_unused_monitors() */
+
+
+
+/*
+ * only_one_screen() - delete all screens after the first one
+ */
+
+static int only_one_screen(Options *op, XConfigPtr config,
+ XConfigLayoutPtr layout)
+{
+ if (!config->screens) return FALSE;
+
+ /* free all existing X screens after the first */
+
+ xconfigFreeScreenList(config->screens->next);
+ config->screens->next = NULL;
+
+ /* free all adjacencies */
+
+ xconfigFreeAdjacencyList(layout->adjacencies);
+ layout->adjacencies = NULL;
+
+ /* add new adjacency */
+
+ create_adjacencies(op, config, layout);
+
+ /* removed unused device and monitor sections */
+
+ free_unused_devices(op, config);
+ free_unused_monitors(op, config);
+
+ return TRUE;
+
+} /* only_one_screen() */
+
diff --git a/nvgetopt.c b/nvgetopt.c
new file mode 100644
index 0000000..13bc364
--- /dev/null
+++ b/nvgetopt.c
@@ -0,0 +1,276 @@
+/*
+ * nvidia-xconfig: A tool for manipulating X config files,
+ * specifically for use by the NVIDIA Linux graphics driver.
+ *
+ * Copyright (C) 2005 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ * nvgetopt.c - portable getopt_long() replacement; removes the need
+ * for the stupid optstring argument. Also adds support for the
+ * "-feature"/"+feature" syntax.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "nvgetopt.h"
+
+
+
+/*
+ * nvgetopt() - see the glibc getopt_long(3) manpage for usage
+ * description. Options can be prepended with "--" or "-".
+ *
+ * A global variable stores the current index into the argv array, so
+ * subsequent calls to nvgetopt() will advance through argv[].
+ *
+ * On success, the matching NVGetoptOption.val is returned.
+ *
+ * On failure, an error is printed to stderr, and 0 is returned.
+ *
+ * When there are no more options to parse, -1 is returned.
+ */
+
+int nvgetopt(int argc, char *argv[], const NVGetoptOption *options,
+ char **strval, int *boolval, int *intval)
+{
+ char *c, *a, *arg, *name = NULL, *argument=NULL;
+ int i, found = NVGETOPT_FALSE, ret = 0, val = NVGETOPT_FALSE;
+ const NVGetoptOption *o = NULL;
+ static int argv_index = 0;
+
+ argv_index++;
+
+ /* if no more options, return -1 */
+
+ if (argv_index >= argc) return -1;
+
+ /* get the argument in question */
+
+ arg = strdup(argv[argv_index]);
+
+ /* look for "--no-", "--" or "-" */
+
+ if ((arg[0] == '-') && (arg[1] == '-') &&
+ (arg[2] == 'n') && (arg[3] == 'o') && (arg[4] == '-')) {
+ name = arg + 5;
+ val = NVGETOPT_FALSE;
+ } else if ((arg[0] == '-') && (arg[1] == '-')) {
+ name = arg + 2;
+ val = NVGETOPT_TRUE;
+ } else if (arg[0] == '-') {
+ name = arg + 1;
+ val = NVGETOPT_TRUE;
+ } else {
+ fprintf(stderr, "%s: invalid option: \"%s\"\n", argv[0], arg);
+ goto done;
+ }
+
+ /*
+ * if there is an "=" in the string, then assign argument and zero
+ * out the equal sign so that name will match what is in the
+ * option table.
+ */
+
+ c = name;
+ while (*c) {
+ if (*c == '=') { argument = c + 1; *c = '\0'; break; }
+ c++;
+ }
+
+ /*
+ * if the string is terminated after one character, interpret it
+ * as a short option. Otherwise, interpret it as a long option.
+ */
+
+ if (name[1] == '\0') { /* short option */
+ for (i = 0; options[i].name; i++) {
+ if (options[i].val == name[0]) {
+ o = &options[i];
+ break;
+ }
+ }
+ } else { /* long option */
+ for (i = 0; options[i].name; i++) {
+ if (strcmp(options[i].name, name) == 0) {
+ o = &options[i];
+ break;
+ }
+ }
+ }
+
+ /*
+ * if we didn't find a match, maybe this is multiple short options
+ * stored together; is each character a short option?
+ */
+
+ if (!o) {
+ for (c = name; *c; c++) {
+ found = NVGETOPT_FALSE;
+ for (i = 0; options[i].name; i++) {
+ if (options[i].val == *c) {
+ found = NVGETOPT_TRUE;
+ break;
+ }
+ }
+ if (!found) break;
+ }
+
+ if (found) {
+
+ /*
+ * all characters individually are short options, so
+ * interpret them that way
+ */
+
+ for (i = 0; options[i].name; i++) {
+ if (options[i].val == name[0]) {
+
+ /*
+ * don't allow options with arguments to be
+ * processed in this way
+ */
+
+ if (options[i].flags & NVGETOPT_HAS_ARGUMENT) break;
+
+ /*
+ * remove the first short option from
+ * argv[argv_index]
+ */
+
+ a = argv[argv_index];
+ if (a[0] == '-') a++;
+ if (a[0] == '-') a++;
+ if (a[0] == '+') a++;
+
+ while(a[0]) { a[0] = a[1]; a++; }
+
+ /*
+ * decrement argv_index so that we process this
+ * entry again
+ */
+
+ argv_index--;
+
+ o = &options[i];
+ break;
+ }
+ }
+ }
+ }
+
+ /* if we didn't find an option, return */
+
+ if (!o) {
+ fprintf(stderr, "%s: unrecognized option: \"%s\"\n", argv[0], arg);
+ goto done;
+ }
+
+ if (o->flags & NVGETOPT_IS_BOOLEAN) {
+
+ /* assign boolval */
+
+ if (boolval) *boolval = val;
+ }
+
+
+ /*
+ * if this option takes an integer argument, then let the "--no-"
+ * prefix set the integer argument to -2 (remove option from x config).
+ * Otherwise, get the string argument and interpret it as an integer.
+ */
+
+ if (o->flags & NVGETOPT_IS_INTEGER) {
+
+ if (val == NVGETOPT_FALSE) {
+ if (intval) {
+ *intval = -2;
+ }
+ } else {
+ if (argument) {
+ if (!argument[0]) {
+ fprintf(stderr, "%s: option \"%s\" requires an "
+ "argument.\n", argv[0], arg);
+ goto done;
+ }
+ } else {
+ argv_index++;
+ if (argv_index >= argc) {
+ fprintf(stderr, "%s: option \"%s\" requires an "
+ "argument.\n", argv[0], arg);
+ goto done;
+ }
+ argument = argv[argv_index];
+ }
+
+ /* argument is now a valid string: parse it */
+
+ if (intval) {
+ char *endptr;
+ *intval = (int) strtol(argument, &endptr, 0);
+ if (*endptr) {
+ fprintf(stderr, "%s: \"%s\" is not a valid argument for "
+ "option \"%s\".\n", argv[0], argument, arg);
+ goto done;
+ }
+ }
+ }
+
+ /*
+ * if this option takes an argument, then we either need to use
+ * what was after the "=" in this argv[] entry, or we need to pull
+ * the next entry off of argv[]
+ */
+
+ } else if (o->flags & NVGETOPT_HAS_ARGUMENT) {
+ if (argument) {
+ if (!argument[0]) {
+ fprintf(stderr, "%s: option \"%s\" requires an argument.\n",
+ argv[0], arg);
+ goto done;
+ }
+ if (strval) *strval = strdup(argument);
+ } else {
+ argv_index++;
+ if (argv_index >= argc) {
+ fprintf(stderr, "%s: option \"%s\" requires an argument.\n",
+ argv[0], arg);
+ goto done;
+ }
+ if (strval) *strval = argv[argv_index];
+ }
+ } else {
+ if (argument) {
+ fprintf(stderr, "%s: option \"%s\" does not take an argument, but "
+ "was given an argument of \"%s\".\n",
+ argv[0], arg, argument);
+ goto done;
+ }
+ }
+
+ ret = o->val;
+
+ done:
+
+ free(arg);
+ return ret;
+
+} /* nvgetopt() */
diff --git a/nvgetopt.h b/nvgetopt.h
new file mode 100644
index 0000000..135bc99
--- /dev/null
+++ b/nvgetopt.h
@@ -0,0 +1,48 @@
+/*
+ * nvidia-xconfig: A tool for manipulating X config files,
+ * specifically for use by the NVIDIA Linux graphics driver.
+ *
+ * Copyright (C) 2004 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ * nvgetopt.h
+ */
+
+#ifndef __NVGETOPT_H__
+#define __NVGETOPT_H__
+
+#define NVGETOPT_FALSE 0
+#define NVGETOPT_TRUE 1
+
+#define NVGETOPT_HAS_ARGUMENT 0x1
+#define NVGETOPT_IS_BOOLEAN 0x2
+#define NVGETOPT_IS_INTEGER 0x4
+
+typedef struct {
+ const char *name;
+ int val;
+ unsigned int flags;
+ char *description; /* not used by nvgetopt() */
+} NVGetoptOption;
+
+int nvgetopt(int argc, char *argv[], const NVGetoptOption *options,
+ char **strval, int *boolval, int *intval);
+
+#endif /* __NVGETOPT_H__ */
diff --git a/nvidia-cfg.h b/nvidia-cfg.h
new file mode 100644
index 0000000..020d947
--- /dev/null
+++ b/nvidia-cfg.h
@@ -0,0 +1,229 @@
+/*
+ * nvidia-cfg
+ *
+ * Copyright (c) 2004 NVIDIA Corp. All rights reserved.
+ *
+ * NOTICE TO USER: The source code is copyrighted under U.S. and
+ * international laws. NVIDIA, Corp. of Santa Clara, California owns
+ * the copyright and as design patents pending on the design and
+ * interface of the NV chips. Users and possessors of this source
+ * code are hereby granted a nonexclusive, royalty-free copyright
+ * and design patent license to use this code in individual and
+ * commercial software.
+ *
+ * Any use of this source code must include, in the user documenta-
+ * tion and internal comments to the code, notices to the end user
+ * as follows:
+ *
+ * Copyright (c) 2004 NVIDIA Corp. NVIDIA design patents pending in
+ * the U.S. and foreign countries.
+ *
+ * NVIDIA CORP. MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF
+ * THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT
+ * EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORP. DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA, CORP. BE LIABLE
+ * FOR ANY SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOURCE CODE.
+ *
+ *
+ * This header file defines the public interface to the
+ * libnvidia-cfg.so library.
+ */
+
+#ifndef __NVIDIA_CFG_H__
+#define __NVIDIA_CFG_H__
+
+
+
+/*
+ * NvCfgDevice - data structure containing bus:slot pairs
+ */
+
+typedef struct {
+ int bus;
+ int slot;
+} NvCfgDevice;
+
+
+
+/*
+ * NvCfgDisplayDeviceInformation - this data structure contains
+ * various limits and other useful data parsed from the EDID.
+ */
+
+typedef struct {
+
+ /*
+ * The monitor name is the name of the monitor as specified by an
+ * EDID 1.x Monitor Descriptors, or an EDID 2.x
+ * Manufacturer/Product ID string.
+ */
+
+ char monitor_name[64];
+
+ /*
+ * The horiz_sync and vert_refresh ranges are retrieved from an
+ * EDID 1.x Monitor Descriptor, or an EDID 2.x Range Limit.
+ */
+
+ unsigned int min_horiz_sync; /* in Hz */
+ unsigned int max_horiz_sync; /* in Hz */
+ unsigned int min_vert_refresh; /* in Hz */
+ unsigned int max_vert_refresh; /* in Hz */
+
+ unsigned int max_pixel_clock; /* in kHz */
+
+ /*
+ * The max xres, yres, and refresh, if not 0, are taken from the
+ * largest mode in the EDID.
+ */
+
+ unsigned int max_xres; /* in pixels */
+ unsigned int max_yres; /* in pixels */
+ unsigned int max_refresh; /* in Hz */
+
+ /*
+ * the preferred xres, yres, and refresh, if not 0, are the values
+ * specified by the EDID as the preferred timing mode of the
+ * display device.
+ */
+
+ unsigned int preferred_xres; /* in pixels */
+ unsigned int preferred_yres; /* in pixels */
+ unsigned int preferred_refresh; /* in Hz */
+
+ /*
+ * the physical width and height, if not 0, are the physical
+ * dimensions of the display device.
+ */
+
+ unsigned int physical_width; /* in mm */
+ unsigned int physical_height; /* in mm */
+
+} NvCfgDisplayDeviceInformation;
+
+
+
+/*
+ * NvCfgDeviceHandle - this is an opaque handle identifying a
+ * connection to an NVIDIA VGA adapter.
+ */
+
+typedef void * NvCfgDeviceHandle;
+
+
+
+/*
+ * NvCfg Boolean values
+ */
+
+typedef enum {
+ NVCFG_TRUE = 1,
+ NVCFG_FALSE = 0,
+} NvCfgBool;
+
+
+
+/*
+ * nvCfgGetDevices() - retrieve an array of NvCfgDevice's indicating
+ * what PCI devices are present on the system. On success, NVCFG_TRUE
+ * will be returned, n will contain the number of NVIDIA PCI VGA
+ * adapters present in the system, and devs will be an allocated array
+ * containing the bus address of each NVIDIA PCI VGA adapter. When
+ * the caller is done, it should free the devs array. On failure,
+ * NVCFG_FALSE will be returned.
+ */
+
+NvCfgBool nvCfgGetDevices(int *n, NvCfgDevice **devs);
+
+
+
+/*
+ * nvCfgOpenDevice() - open a connection to the NVIDIA device
+ * identified by the bus:slot PCI address. On success, NVCFG_TRUE
+ * will be returned and handle be assigned. On failure, NVCFG_FALSE
+ * will be returned.
+ */
+
+NvCfgBool nvCfgOpenDevice(int bus, int slot, NvCfgDeviceHandle *handle);
+
+
+
+/*
+ * nvCfgCloseDevice() - close the previously opened connection to an
+ * NVIDIA device.
+ */
+
+NvCfgBool nvCfgCloseDevice(NvCfgDeviceHandle handle);
+
+
+
+/*
+ * nvCfgGetNumCRTCs() - return the number of CRTCs (aka "heads")
+ * present on the specified NVIDIA device. On success, NVCFG_TRUE
+ * will be returned and crtcs will be assigned. On failure,
+ * NVCFG_FALSE will be returned.
+ */
+
+NvCfgBool nvCfgGetNumCRTCs(NvCfgDeviceHandle handle, int *crtcs);
+
+
+
+/*
+ * nvCfgGetProductName() - return an allocated string containing the
+ * product name of the specified NVIDIA device. It is the caller's
+ * responsibility to free the returned string. On success, NVCFG_TRUE
+ * will be returned and name will be assigned. On failure,
+ * NVCFG_FALSE will be returned.
+ */
+
+NvCfgBool nvCfgGetProductName(NvCfgDeviceHandle handle, char **name);
+
+
+
+/*
+ * nvCfgGetDisplayDevices() - retrieve a bitmask describing the
+ * currently connected display devices: this "display device mask" is
+ * an unsigned 32 bit value that identifies one or more display
+ * devices. The first 8 bits each identify a CRT, the next 8 bits
+ * each identify a TV, and the next 8 each identify a DFP. For
+ * example, 0x1 refers to CRT-0, 0x3 refers to CRT-0 and CRT-1,
+ * 0x10001 refers to CRT-0 and DFP-0, etc. On success, NVCFG_TRUE
+ * will be returned and display_device_mask will be assigned. On
+ * failure, NVCFG_FALSE will be returned.
+ */
+
+NvCfgBool nvCfgGetDisplayDevices(NvCfgDeviceHandle handle,
+ unsigned int *display_device_mask);
+
+
+/*
+ * nvCfgGetEDIDData() - return an allocated byte array containing the
+ * EDID for the specified display device, if any. On success,
+ * NVCFG_TRUE will be returned and edidSize and edid will be assigned.
+ * On failure, NVCFG_FALSE will be returned. It is the caller's
+ * responsibility to free the allocated EDID.
+ */
+
+NvCfgBool nvCfgGetEDIDData(NvCfgDeviceHandle handle,
+ unsigned int display_device,
+ int *edidSize, void **edid);
+
+
+/*
+ * nvCfgGetEDIDMonitorData() - Initialize the fields in the
+ * NvCfgDisplayDeviceInformation data structure, using data from the
+ * EDID. On success, NVCFG_TRUE will be returned and info will be
+ * assigned. On failure, NVCFG_FALSE will be returned.
+ */
+
+NvCfgBool nvCfgGetEDID(NvCfgDeviceHandle handle,
+ unsigned int display_device,
+ NvCfgDisplayDeviceInformation *info);
+
+#endif /* __NVIDIA_CFG__ */
diff --git a/nvidia-xconfig.1.m4 b/nvidia-xconfig.1.m4
new file mode 100644
index 0000000..e0f5278
--- /dev/null
+++ b/nvidia-xconfig.1.m4
@@ -0,0 +1,95 @@
+dnl This file is to be preprocessed by m4.
+changequote([[[, ]]])dnl
+define(__OPTIONS__, [[[include([[[options.1.inc]]])dnl]]])dnl
+.\" Copyright (C) 2005 NVIDIA Corporation.
+.\"
+__HEADER__
+.TH nvidia-xconfig 1 2005-08-19 "nvidia-xconfig 1.0"
+.SH NAME
+nvidia-xconfig \- manipulate X configuration files for the NVIDIA driver
+.SH SYNOPSIS
+.B nvidia-xconfig
+[
+.I options
+]
+.SH DESCRIPTION
+.PP
+.B nvidia-xconfig
+is a tool intended to provide basic control over configuration options available in the NVIDIA X driver.
+.PP
+.B nvidia-xconfig
+performs its operations in several steps:
+.TP
+1)
+The system X configuration file is found and read into memory.
+If no configuration file can be found,
+.B nvidia-xconfig
+generates one from scratch using default settings; in this case,
+.B nvidia-xconfig
+will automatically determine the name of the X
+configuration file to create:
+.I /etc/X11/xorg.conf
+if the X server
+in use is X.org or
+.I /etc/X11/XF86Config
+if the X server in use is XFree86."
+.TP
+2)
+The configuration in memory is modified to support the NVIDIA driver.
+This consists of changing the display driver to "nvidia", removing the commands to load the "GLcore" and "dri" modules, and adding the command to load the "glx" module.
+.TP
+3)
+The configuration in memory is modified according to the options specified on the command line.
+Please see the NVIDIA README for a description of the NVIDIA X configuration file options.
+Note that
+.B nvidia-xconfig
+does not perform any validation of the X configuration file options requested on the command line;
+X configuration file option validation is left for the NVIDIA X driver.
+.TP
+4)
+The configuration is written back to the file from which it was read.
+A backup of the original configuration is created with "\.backup" appended.
+For example, if your X configuration is
+.I /etc/X11/xorg.conf
+then
+.B nvidia-xconfig
+will copy it to
+.I /etc/X11/xorg.conf.backup
+before writing the new configuration.
+The
+.B \-\-post\-tree (\-T)
+option can be used to print the new configuration to standard out in tree form instead. This option is useful to see what
+.B nvidia-xconfig
+will do while leaving the original configuration intact.
+dnl Call gen-manpage-opts to generate this section.
+__OPTIONS__
+.SH EXAMPLES
+.TP
+.B nvidia-xconfig
+Reads an existing X config file and adapts it to use the NVIDIA driver.
+If no X config file can be found, a new one is created at /etc/X11/XF86Config with default settings.
+.TP
+.B nvidia-xconfig \-\-post\-tree \-\-twinview
+Reads the existing X configuration file, adds the TwinView option, and then prints the resulting config file to standard out in tree form.
+The configuration file is not modified.
+.TP
+.B nvidia-xconfig \-\-enable\-all\-gpus
+Examines the system and configures an X screen for each display device it finds.
+.TP
+.BI "nvidia-xconfig \-\-mode=" 1600x1200
+Adds a 1600x1200 mode to an existing X configuration.
+.TP
+.B nvidia-xconfig \-\-only\-one\-x\-screen \-\-sli=Auto
+Configures the X server to have just one X screen that will use SLI when available.
+.\" .SH FILES
+.\" .I /etc/X11/XF86Config
+.\" .I /etc/X11/xorg.conf
+.SH AUTHOR
+Aaron Plattner
+.br
+NVIDIA Corporation
+.SH "SEE ALSO"
+.BR nvidia-settings (1),
+.I /usr/share/doc/NVIDIA_GLX-1.0/README.txt
+.SH COPYRIGHT
+Copyright \(co 2005 NVIDIA Corporation.
diff --git a/nvidia-xconfig.c b/nvidia-xconfig.c
new file mode 100644
index 0000000..b5fd719
--- /dev/null
+++ b/nvidia-xconfig.c
@@ -0,0 +1,848 @@
+/*
+ * nvidia-xconfig: A tool for manipulating X config files,
+ * specifically for use by the NVIDIA Linux graphics driver.
+ *
+ * Copyright (C) 2005 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ * nvidia-xconfig.c
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <libgen.h>
+
+#include "nvidia-xconfig.h"
+#include "nvgetopt.h"
+
+#define TAB " "
+#define BIGTAB " "
+
+
+
+/*
+ * print_version() - print version information
+ */
+
+extern const char *pNV_ID;
+
+static void print_version(void)
+{
+ fmtout("");
+ fmtout(pNV_ID);
+ fmtoutp(TAB, "The NVIDIA X Configuration Tool.");
+ fmtout("");
+ fmtoutp(TAB, "This program is used to manipulate X configuration files, "
+ "specifically to enable NVIDIA X driver functionality.");
+ fmtout("");
+ fmtoutp(TAB, "Copyright (C) 2005 NVIDIA Corporation.");
+ fmtout("");
+
+} /* print_version() */
+
+
+static void print_summary(void)
+{
+ fmtout("");
+ fmtoutp(TAB, "In its normal operation, nvidia-xconfig finds the system "
+ "X configuration file (or generates a new X configuration if it "
+ "cannot find the system file), makes sure the configuration is "
+ "usable by the NVIDIA X driver, applies any updates requested "
+ "on the commandline, and writes the new configuration to file.");
+ fmtout("");
+ fmtoutp(TAB, "Please see the NVIDIA README for a description of NVIDIA "
+ "X configuration file options.");
+ fmtout("");
+}
+
+
+#include "option_table.h"
+
+
+/*
+ * print_help() - loop through the __options[] table, and print the
+ * description of each option.
+ */
+
+static void print_help(int advanced)
+{
+ int i, j, len;
+ char *msg, *tmp, scratch[64];
+ const NVGetoptOption *o;
+
+ print_version();
+ print_summary();
+
+ fmtout("");
+ fmtout("nvidia-xconfig [options]");
+ fmtout("");
+
+ for (i = 0; __options[i].name; i++) {
+ o = &__options[i];
+
+ /*
+ * if non-advanced help is requested, and the ALWAYS flag is
+ * not set, then skip this option
+ */
+
+ if (!advanced && !(o->flags & OPTION_HELP_ALWAYS)) continue;
+
+ if (isalpha(o->val)) {
+ sprintf(scratch, "%c", o->val);
+ msg = nvstrcat("-", scratch, ", --", o->name, NULL);
+ } else {
+ msg = nvstrcat("--", o->name, NULL);
+ }
+ if (o->flags & NVGETOPT_HAS_ARGUMENT) {
+ len = strlen(o->name);
+ for (j = 0; j < len; j++) scratch[j] = toupper(o->name[j]);
+ scratch[len] = '\0';
+ tmp = nvstrcat(msg, "=[", scratch, "]", NULL);
+ free(msg);
+ msg = tmp;
+ }
+ if (o->flags & NVGETOPT_IS_BOOLEAN ||
+ o->flags & NVGETOPT_IS_INTEGER) {
+ tmp = nvstrcat(msg, "/--no-", o->name, NULL);
+ free(msg);
+ msg = tmp;
+ }
+
+ fmtoutp(TAB, msg);
+ if (o->description) fmtoutp(BIGTAB, o->description);
+ fmtout("");
+ free(msg);
+ }
+} /* print_help() */
+
+
+
+/*
+ * parse_commandline() - malloc an Options structure, initialize it,
+ * and fill in any pertinent data from the commandline arguments
+ */
+
+Options *parse_commandline(int argc, char *argv[])
+{
+ Options *op;
+ int c, boolval;
+ u32 bit;
+ char *strval;
+ int intval;
+
+ op = (Options *) nvalloc(sizeof(Options));
+
+ op->gop.x_project_root = "/usr/X11R6";
+ op->nvagp = -1;
+ op->digital_vibrance = -1;
+ op->transparent_index = -1;
+ op->stereo = -1;
+
+ while (1) {
+
+ c = nvgetopt(argc, argv, __options, &strval, &boolval, &intval);
+
+ if (c == -1)
+ break;
+
+ /* catch the boolean options */
+
+ if ((c >= XCONFIG_OPTION_START) &&
+ (c <= (XCONFIG_OPTION_START + XCONFIG_BOOL_OPTION_COUNT))) {
+
+ bit = GET_BOOL_OPTION_BIT(c - XCONFIG_OPTION_START);
+ GET_BOOL_OPTION_SLOT(op->boolean_options,
+ c - XCONFIG_OPTION_START) |= bit;
+ if (boolval) {
+ GET_BOOL_OPTION_SLOT(op->boolean_option_values,
+ c - XCONFIG_OPTION_START) |= bit;
+ } else {
+ GET_BOOL_OPTION_SLOT(op->boolean_option_values,
+ c - XCONFIG_OPTION_START) &= ~bit;
+ }
+ continue;
+ }
+
+ switch (c) {
+
+ case 'v': print_version(); exit(0); break;
+ case 'c': op->xconfig = strval; break;
+ case 'o': op->output_xconfig = strval; break;
+ case 't': op->tree = TRUE; break;
+ case 'T': op->post_tree = TRUE; break;
+ case 'h': print_help(FALSE); exit(0); break;
+ case 'A': print_help(TRUE); exit(0); break;
+ case 's': op->silent = TRUE; break;
+ case 'a': op->enable_all_gpus = TRUE; break;
+ case '1': op->only_one_screen = TRUE; break;
+
+ case 'd': op->depth = atoi(strval);
+ if ((op->depth != 8) &&
+ (op->depth != 15) &&
+ (op->depth != 16) &&
+ (op->depth != 24)) {
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Invalid depth: %d.\n", op->depth);
+ fprintf(stderr, "\n");
+ goto fail;
+ }
+ break;
+
+ case LAYOUT_OPTION: op->layout = strval; break;
+ case SCREEN_OPTION: op->screen = strval; break;
+
+ case X_PREFIX_OPTION: op->gop.x_project_root = strval; break;
+
+ case KEYBOARD_OPTION: op->gop.keyboard = strval; break;
+ case KEYBOARD_LIST_OPTION: op->keyboard_list = TRUE; break;
+ case KEYBOARD_DRIVER_OPTION: op->gop.keyboard_driver = strval; break;
+
+ case MOUSE_OPTION: op->gop.mouse = strval; break;
+ case MOUSE_LIST_OPTION: op->mouse_list = TRUE; break;
+
+ case NVIDIA_CFG_PATH_OPTION: op->nvidia_cfg_path = strval; break;
+
+ case FORCE_GENERATE_OPTION: op->force_generate = TRUE; break;
+
+ case NVAGP_OPTION:
+ if (strcasecmp(strval, "none") == 0) op->nvagp = 0;
+ else if (strcasecmp(strval, "nvagp") == 0) op->nvagp = 1;
+ else if (strcasecmp(strval, "agpgart") == 0) op->nvagp = 2;
+ else if (strcasecmp(strval, "any") == 0) op->nvagp = 3;
+ else if ((strval[0] == '0') && (strval[1] == '\0')) op->nvagp = 0;
+ else if ((strval[0] == '1') && (strval[1] == '\0')) op->nvagp = 1;
+ else if ((strval[0] == '2') && (strval[1] == '\0')) op->nvagp = 2;
+ else if ((strval[0] == '3') && (strval[1] == '\0')) op->nvagp = 3;
+ else {
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Invalid nvagp: %s.\n", strval);
+ fprintf(stderr, "\n");
+ goto fail;
+ }
+ break;
+
+ case DIGITAL_VIBRANCE_OPTION:
+ if ( intval != -2 && (intval < 0 || intval > 255) ) {
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Invalid digital vibrance: %d.\n", intval);
+ fprintf(stderr, "\n");
+ goto fail;
+ }
+ op->digital_vibrance = intval;
+ break;
+
+ case TRANSPARENT_INDEX_OPTION:
+ if ( intval != -2 && (intval < 0 || intval > 255) ) {
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Invalid transparent index: %d.\n", intval);
+ fprintf(stderr, "\n");
+ goto fail;
+ }
+ op->transparent_index = intval;
+ break;
+
+ case STEREO_OPTION:
+ if ( intval != -2 && (intval < 1 || intval > 6) ) {
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Invalid stereo: %d.\n", intval);
+ fprintf(stderr, "\n");
+ goto fail;
+ }
+ op->stereo = intval;
+ break;
+
+ case MODE_OPTION:
+ if (boolval) {
+ /* add this mode */
+ nv_text_rows_append(&op->add_modes, strval);
+ } else {
+ /* remove this mode */
+ nv_text_rows_append(&op->remove_modes, strval);
+ }
+ break;
+
+ case SLI_OPTION:
+ {
+ const char* valid_values[] = {
+ "0",
+ "no",
+ "off",
+ "false",
+ "single",
+ "1",
+ "yes",
+ "on",
+ "true",
+ "auto",
+ "afr",
+ "sfr",
+ "sliaa",
+ NULL
+ };
+ int i;
+
+ for (i = 0; valid_values[i]; i++) {
+ if (!strcasecmp(strval, valid_values[i]))
+ break;
+ }
+
+ if (valid_values[i]) {
+ op->sli = strval;
+ } else {
+ fprintf(stderr, "Invalid SLI option: %s.\n", strval);
+ goto fail;
+ }
+ }
+ break;
+
+ case ROTATE_OPTION:
+ {
+ const char* valid_values[] = {
+ "0",
+ "no",
+ "off",
+ "normal",
+ "left",
+ "CCW",
+ "inverted",
+ "right",
+ "CW",
+ NULL
+ };
+ int i;
+
+ for (i = 0; valid_values[i]; i++) {
+ if (!strcasecmp(strval, valid_values[i]))
+ break;
+ }
+
+ if (valid_values[i]) {
+ op->rotate = strval;
+ } else {
+ fprintf(stderr, "Invalid Rotate option: %s.\n", strval);
+ goto fail;
+ }
+ }
+ break;
+
+ case DISABLE_SCF_OPTION: op->disable_scf = TRUE; break;
+
+ default:
+ goto fail;
+ }
+ }
+
+ /* do tilde expansion on the filenames given */
+
+ op->xconfig = tilde_expansion(op->xconfig);
+ op->output_xconfig = tilde_expansion(op->output_xconfig);
+
+ /*
+ * XXX save the option structure so that printing routines can
+ * access it (and so that we don't have to carry the op everywhere
+ * just so that we can pass it to printing routines).
+ */
+ {
+ extern Options *__op;
+
+ __op = op;
+ }
+
+ return (op);
+
+ fail:
+
+ fprintf(stderr, "\n");
+ fprintf(stderr, "Invalid commandline, please run `%s --help` "
+ "for usage information.\n", argv[0]);
+ fprintf(stderr, "\n");
+ exit(1);
+
+ return NULL;
+
+} /* parse_commandline() */
+
+
+
+
+/*
+ * backup_file() - create a backup of orig_filename, naming the backup
+ * file "<original>.backup".
+ *
+ * XXX If we fail to write to the backup file (eg, it is in a
+ * read-only directory), then we should do something intelligent like
+ * write the backup to the user's home directory.
+ */
+
+int backup_file(Options *op, const char *orig_filename)
+{
+ char *filename;
+ int ret = FALSE;
+
+ /* construct the backup filename */
+
+ filename = nvstrcat(orig_filename, ".backup", NULL);
+
+ /* if the backup file already exists, remove it */
+
+ if (access(filename, F_OK) == 0) {
+ if (unlink(filename) != 0) {
+ fmterr("Unable to create backup file '%s' (%s)",
+ filename, strerror(errno));
+ goto done;
+ }
+ }
+
+ /* copy the file */
+
+ if (!copy_file(orig_filename, filename, 0644)) {
+ /* copy_file() prints out its own error messages */
+ goto done;
+ }
+
+ fmtmsg("Backed up file '%s' as '%s'", orig_filename, filename);
+ ret = TRUE;
+
+ done:
+
+ free(filename);
+
+ return ret;
+
+} /* backup_file() */
+
+
+
+/*
+ * write_xconfig() - write the Xconfig to file.
+ *
+ * We search for the filename is this order:
+ *
+ * 1) "--output-xconfig" option
+ *
+ * 2) config->filename
+ *
+ * 3) use xf86openConfigFile()
+ *
+ * 4) If the detected X server is XFree86, we use use "/etc/X11/XF86Config"
+ * Otherwise we use "/etc/X11/xorg.conf",.
+ */
+
+int write_xconfig(Options *op, XConfigPtr config)
+{
+ char *filename = NULL;
+ char *d, *tmp = NULL;
+ int ret = FALSE;
+
+ /* 1) "--output-xconfig" option */
+
+ if (op->output_xconfig) {
+ filename = nvstrdup(op->output_xconfig);
+ }
+
+ /* config->filename */
+
+ if (!filename && config->filename) {
+ filename = nvstrdup(config->filename);
+ }
+
+ /* use xf86openConfigFile() */
+
+ if (!filename) {
+ const char *f;
+ f = xconfigOpenConfigFile(NULL, op->gop.x_project_root);
+ if (f) {
+ /* dup the string since closing the config file will free
+ the string */
+ filename = nvstrdup(f);
+ xconfigCloseConfigFile();
+ }
+ }
+
+ /* fall back to "/etc/X11/XF86Config" or "/etc/X11/xorg.conf" */
+
+ if (!filename) {
+ if (op->gop.xserver == X_IS_XF86) {
+ filename = nvstrdup("/etc/X11/XF86Config");
+ } else {
+ filename = nvstrdup("/etc/X11/xorg.conf");
+ }
+ }
+
+ /*
+ * XXX it's strange that lack of permission to write to the target
+ * location (the likely case with users not having write
+ * permission on /etc/X11/ will fail at backup time, rather than
+ * when we try to write the new file. Perhaps we should backup to
+ * a temporary location where we know we will have write access,
+ * try to do the write, and only if we succeed in the write, move
+ * the backup file into place.
+ */
+
+ /* check that we can write to this location */
+
+ tmp = nvstrdup(filename);
+ d = dirname(tmp);
+ if (access(d, W_OK) != 0) {
+ fmterr("Unable to write to directory '%s'.", d);
+ goto done;
+ }
+
+ /* if the file already exists, create a backup first */
+
+ if (access(filename, F_OK) == 0) {
+ if (!backup_file(op, filename)) goto done;
+ }
+
+ /* write the config file */
+
+ if (!xconfigWriteConfigFile(filename, config)) {
+ fmterr("Unable to write file \"%s\"; please use the "
+ "\"--output-xconfig\" commandline "
+ "option to specify an alternative output file.", filename);
+ goto done;
+ }
+
+ fmtmsg("New X configuration file written to '%s'", filename);
+ fmtmsg("");
+
+ ret = TRUE;
+
+ done:
+
+ if (filename) free(filename);
+ if (tmp) free(tmp);
+
+ return ret;
+
+} /* write_xconfig() */
+
+
+
+/*
+ * update_banner() - add our banner at the top of the config, but
+ * first we need to remove any lines that already include our prefix
+ * (because presumably they are a banner from an earlier run of
+ * nvidia-xconfig)
+ */
+
+static void update_banner(XConfigPtr config)
+{
+ static const char *banner =
+ "X configuration file generated by nvidia-xconfig\n";
+ static const char *prefix =
+ "# nvidia-xconfig: ";
+
+ char *s = config->comment;
+ char *line, *eol, *tmp;
+
+ /* remove all lines that begin with the prefix */
+
+ while (s && (line = strstr(s, prefix))) {
+
+ eol = strchr(line, '\n'); /* find the end of the line */
+
+ if (eol) {
+ eol++;
+ if (*eol == '\0') eol = NULL;
+ }
+
+ if (line == s) { /* the line with the prefix is at the start */
+ if (eol) { /* there is more after the prefix line */
+ tmp = strdup(eol);
+ free(s);
+ s = tmp;
+ } else { /* the prefix line is the only line */
+ free(s);
+ s = NULL;
+ }
+ } else { /* prefix line is in the middle or end */
+ *line = '\0';
+ tmp = nvstrcat(s, eol, NULL);
+ free(s);
+ s = tmp;
+ }
+ }
+
+ /* add our prefix lines at the start of the comment */
+
+ config->comment = nvstrcat(prefix, banner, "# ", pNV_ID, "\n", s, NULL);
+
+ if (s) free(s);
+
+} /* update_banner() */
+
+
+
+/*
+ * find_system_xconfig() - find the system X config file and parse it;
+ * returns XConfigPtr if successful, otherwise returns NULL.
+ */
+
+static XConfigPtr find_system_xconfig(Options *op)
+{
+ const char *filename;
+ XConfigPtr config;
+ XConfigError error;
+
+ /* Find and open the existing X config file */
+
+ filename = xconfigOpenConfigFile(op->xconfig, op->gop.x_project_root);
+
+ if (filename) {
+ fmtmsg("");
+ fmtmsg("Using X configuration file: \"%s\".", filename);
+ } else {
+ fmtwarn("Unable to locate/open X configuration file.");
+ return NULL;
+ }
+
+ /* Read the opened X config file */
+
+ error = xconfigReadConfigFile(op->screen, &config);
+ if (error != XCONFIG_RETURN_SUCCESS) {
+ xconfigCloseConfigFile();
+ return NULL;;
+ }
+
+ /* Close the X config file */
+
+ xconfigCloseConfigFile();
+
+ return config;
+
+} /* find_system_xconfig() */
+
+
+
+int update_xconfig(Options *op, XConfigPtr config)
+{
+ XConfigLayoutPtr layout;
+ XConfigScreenPtr screen;
+ XConfigAdjacencyPtr adj;
+
+ /* get the layout to update */
+
+ layout = get_layout(op, config);
+ if (!layout) {
+ return FALSE;
+ }
+
+ /* make sure the layout has the needed input devices */
+
+ if (!xconfigCheckCoreInputDevices(config, layout)) {
+ return FALSE;
+ }
+
+ /* apply multi-display options */
+
+ if (!apply_multi_screen_options(op, config, layout)) {
+ return FALSE;
+ }
+
+ /*
+ * update the device and option for all screens, or the screen
+ * that was requested
+ */
+
+ if (op->screen) {
+ screen = xconfigFindScreen(op->screen, config->screens);
+ if (!screen) {
+ fmterr("Unable to find screen '%s'", op->screen);
+ return FALSE;
+ }
+ update_screen(op, config, screen);
+ } else {
+ for (adj = layout->adjacencies; adj; adj = adj->next) {
+ update_screen(op, config, adj->screen);
+ }
+ }
+
+ update_modules(config);
+
+ update_banner(config);
+
+ return TRUE;
+
+} /* update_xconfig() */
+
+
+# define NV_LINE_LEN 1024
+static void get_xserver_in_use(Options *op)
+{
+#if defined(NV_SUNOS)
+ op->gop.xserver=X_IS_XORG;
+#else
+ char *cmd;
+ FILE *stream = NULL;
+ int xserver = -1;
+
+ cmd = xconfigStrcat(op->gop.x_project_root, "/bin/X -version 2>&1", NULL);
+ if ((stream = popen(cmd, "r"))) {
+ char buf[NV_LINE_LEN];
+
+ while (1) {
+ if (fgets(buf, NV_LINE_LEN-1, stream) == NULL) break;
+
+ if (xserver == -1) {
+ if (strcmp(buf, "XFree86") >= 0) {
+ xserver = X_IS_XF86;
+ } else if (strcmp(buf, "X Window System") >= 0) {
+ xserver = X_IS_XORG;
+ }
+ }
+ }
+ }
+ /* Close the popen()'ed stream. */
+ pclose(stream);
+ free(cmd);
+
+ if (xserver == -1) {
+ char *xorgpath;
+
+ xorgpath = xconfigStrcat(op->gop.x_project_root, "/bin/Xorg", NULL);
+ if (access(xorgpath, F_OK)==0) {
+ xserver = X_IS_XORG;
+ } else {
+ xserver = X_IS_XF86;
+ }
+ free(xorgpath);
+ }
+
+ op->gop.xserver=xserver;
+#endif
+} /* get_xserver_in_use */
+
+
+
+/*
+ * main program entry point
+ *
+ * The intended behavior is that, by default, nvidia-xconfig make the
+ * system's X config file usable by the NVIDIA X driver. If
+ * nvidia-xconfig cannot file the system's X config file, then it
+ * attempts to create one and make that usable.
+ *
+ *
+ */
+
+int main(int argc, char *argv[])
+{
+ Options *op;
+ int ret;
+ XConfigPtr config = NULL;
+
+ /* parse the commandline */
+
+ op = parse_commandline(argc, argv);
+
+ /*
+ * first, check for any of special options that cause us to exit
+ * early
+ */
+
+ if (op->keyboard_list) {
+ fmtout("\nPossible keyboard types; the short name is what should be "
+ "passed to the \"--keyboard\" option.\n\n");
+ xconfigGeneratePrintPossibleKeyboards();
+ return 0;
+ }
+
+ if (op->mouse_list) {
+ fmtout("\nPossible mouse types; the short name is what should be "
+ "passed to the \"--mouse\" option.\n\n");
+ xconfigGeneratePrintPossibleMice();
+ return 0;
+ }
+
+ /*
+ * we want to open and parse the system's existing X config file,
+ * if possible
+ */
+
+ if (!op->force_generate) {
+ config = find_system_xconfig(op);
+ }
+
+ /*
+ * pass the system config (if any) to the tree printer
+ */
+
+ if (op->tree) {
+ ret = print_tree(op, config);
+ return (ret ? 0 : 1);
+ }
+
+ /*
+ * Get which X server is in use: Xorg or XFree86
+ */
+ get_xserver_in_use(op);
+
+ /*
+ * if we failed to find the system's config file, generate a new
+ * one
+ */
+
+ if (!config) {
+ config = xconfigGenerate(&op->gop);
+ }
+
+ /*
+ * if we don't have a valid config by now, something catestrophic
+ * happened
+ */
+
+ if (!config) {
+ fmterr("Unable to generate a usable X configuration file.");
+ return 1;
+ }
+
+ /* now, we have a good config; apply whatever the user requested */
+
+ update_xconfig(op, config);
+
+ /* print the config in tree format, if requested */
+
+ if (op->post_tree) {
+ ret = print_tree(op, config);
+ return (ret ? 0 : 1);
+ }
+
+ /* write the config back out to file */
+
+ if (!write_xconfig(op, config)) {
+ return 1;
+ }
+
+ /* Set the default depth in the Solaris Management Facility
+ * to the default depth of the first screen
+ */
+ if (op->disable_scf == TRUE) {
+ return 0;
+ } else if(!update_scf_depth(config->screens[0].defaultdepth)) {
+ return 1;
+ }
+ return 0;
+
+} /* main() */
diff --git a/nvidia-xconfig.h b/nvidia-xconfig.h
new file mode 100644
index 0000000..4786992
--- /dev/null
+++ b/nvidia-xconfig.h
@@ -0,0 +1,201 @@
+/*
+ * nvidia-xconfig: A tool for manipulating X config files,
+ * specifically for use by the NVIDIA Linux graphics driver.
+ *
+ * Copyright (C) 2004 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ * nvidia-xconfig.h
+ */
+
+#ifndef __NVIDIA_XCONFIG_H__
+#define __NVIDIA_XCONFIG_H__
+
+#define PROGRAM_NAME "nvidia-xconfig"
+
+#include "xf86Parser.h"
+#include "nvidia-cfg.h"
+
+#include <sys/types.h>
+
+#if !defined(TRUE)
+#define TRUE 1
+#endif
+
+#if !defined(FALSE)
+#define FALSE 0
+#endif
+
+
+typedef struct {
+ char **t; /* the text rows */
+ int n; /* number of rows */
+ int m; /* maximum row length */
+} TextRows;
+
+
+/* Boolean options */
+#define NOLOGO_OPTION 1
+#define UBB_OPTION 2
+#define RENDER_ACCEL_OPTION 3
+#define NO_RENDER_EXTENSION_OPTION 4
+#define OVERLAY_OPTION 5
+#define CIOVERLAY_OPTION 6
+#define OVERLAY_DEFAULT_VISUAL_OPTION 7
+#define NO_BANDWIDTH_TEST_OPTION 8
+#define NO_POWER_CONNECTOR_CHECK_OPTION 9
+#define ALLOW_DFP_STEREO_OPTION 10
+#define ALLOW_GLX_WITH_COMPOSITE_OPTION 11
+#define RANDR_ROTATION_OPTION 12
+#define TWINVIEW_OPTION 13
+#define SEPARATE_X_SCREENS_OPTION 14
+#define XINERAMA_OPTION 15
+#define NO_TWINVIEW_XINERAMA_INFO_OPTION 16
+#define NOFLIP_OPTION 17
+#define DAC_8BIT_OPTION 18
+#define USE_EDID_FREQS_OPTION 19
+#define IGNORE_EDID_OPTION 20
+#define USE_INT10_MODULE_OPTION 21
+#define FORCE_STEREO_FLIPPING_OPTION 22
+#define MULTISAMPLE_COMPATIBILITY_OPTION 23
+#define XVMC_USES_TEXTURES_OPTION 24
+#define EXACT_MODE_TIMINGS_DVI_OPTION 25
+#define ALLOW_DDCCI_OPTION 26
+#define LOAD_KERNEL_MODULE_OPTION 27
+
+#define XCONFIG_BOOL_OPTION_COUNT LOAD_KERNEL_MODULE_OPTION
+
+/* # of 32-bit variables needed to hold all the boolean options (bits) */
+#define XCONFIG_BOOL_OPTION_SLOTS \
+ ((XCONFIG_BOOL_OPTION_COUNT)/32) + \
+ (((XCONFIG_BOOL_OPTION_COUNT)%32)?1:0)
+
+#define GET_BOOL_OPTION_SLOT(BLOCKS, VAR) \
+ ((BLOCKS)[(u32)((VAR)/32)])
+
+#define GET_BOOL_OPTION_BIT(VAR) \
+ (1<<(u32)((VAR)%32))
+
+#define GET_BOOL_OPTION(BLOCKS, VAR) \
+ (GET_BOOL_OPTION_SLOT((BLOCKS), (VAR)) & \
+ GET_BOOL_OPTION_BIT(VAR))
+
+/* 32 bit unsigned variable (used to pack booleans) */
+typedef unsigned int u32;
+
+
+typedef struct __options {
+ int force_generate;
+ int tree;
+ int post_tree;
+ int silent;
+ int keyboard_list;
+ int mouse_list;
+ int enable_all_gpus;
+ int only_one_screen;
+ int disable_scf;
+
+ /*
+ * the option parser will set bits in boolean_options to indicate
+ * whether an option was set, and will then turn the corresponding
+ * bit in boolean_option_values on or off to indicate if the
+ * option was true or false.
+ */
+
+ u32 boolean_options[XCONFIG_BOOL_OPTION_SLOTS];
+ u32 boolean_option_values[XCONFIG_BOOL_OPTION_SLOTS];
+
+ int depth;
+ int nvagp;
+ int digital_vibrance;
+ int transparent_index;
+ int stereo;
+
+ char *xconfig;
+ char *output_xconfig;
+ char *layout;
+ char *screen;
+ char *sli;
+ char *rotate;
+
+ char *nvidia_cfg_path;
+
+ TextRows add_modes;
+ TextRows remove_modes;
+
+ GenerateOptions gop;
+
+} Options;
+
+
+/* util.c */
+
+void *nvalloc(size_t size);
+char *nvstrcat(const char *str, ...);
+void *nvrealloc(void *ptr, size_t size);
+char *nvstrdup(const char *s);
+void nvfree(char *s);
+int copy_file(const char *srcfile, const char *dstfile, mode_t mode);
+
+int directory_exists(const char *dir);
+char *tilde_expansion(char *str);
+
+void reset_current_terminal_width(unsigned short new_val);
+
+TextRows *nv_format_text_rows(const char *prefix,
+ const char *str,
+ int width, int word_boundary);
+void nv_text_rows_append(TextRows *t, const char *msg);
+void nv_free_text_rows(TextRows *t);
+void nv_concat_text_rows(TextRows *t0, TextRows *t1);
+
+char *fget_next_line(FILE *fp, int *eof);
+
+void fmtout(const char *fmt, ...);
+void fmtoutp(const char *prefix, const char *fmt, ...);
+void fmtmsg(const char *fmt, ...);
+void fmterr(const char *fmt, ...);
+void fmtwarn(const char *fmt, ...);
+
+
+/* make_usable.c */
+
+int update_modules(XConfigPtr config);
+int update_screen(Options *op, XConfigPtr config, XConfigScreenPtr screen);
+XConfigLayoutPtr get_layout(Options *op, XConfigPtr config);
+
+/* multiple_screens.c */
+
+int apply_multi_screen_options(Options *op, XConfigPtr config,
+ XConfigLayoutPtr layout);
+
+/* tree.c */
+
+int print_tree(Options *op, XConfigPtr config);
+
+/* options.c */
+
+void remove_option_from_list(XConfigOptionPtr *list, const char *name);
+void update_options(Options *op, XConfigScreenPtr screen);
+
+/* lscf.c */
+int update_scf_depth(int depth);
+
+#endif /* __NVIDIA_XCONFIG_H__ */
diff --git a/option_table.h b/option_table.h
new file mode 100644
index 0000000..5d42994
--- /dev/null
+++ b/option_table.h
@@ -0,0 +1,333 @@
+/*
+ * Options table; the fields are:
+ *
+ * name - this is the long option name
+ *
+ * shortname - this is the one character short option name
+ *
+ * flags - bitmask; possible values are NVGETOPT_HAS_ARGUMENT and
+ * NVGETOPT_IS_BOOLEAN
+ *
+ * description - text for use by print_help() to describe the option
+ */
+
+#define SCREEN_OPTION 1
+#define LAYOUT_OPTION 2
+#define X_PREFIX_OPTION 3
+#define KEYBOARD_OPTION 5
+#define KEYBOARD_LIST_OPTION 6
+#define KEYBOARD_DRIVER_OPTION 7
+#define MOUSE_OPTION 8
+#define FORCE_GENERATE_OPTION 9
+#define MOUSE_LIST_OPTION 10
+#define MODE_OPTION 11
+#define NVIDIA_CFG_PATH_OPTION 12
+#define NVAGP_OPTION 13
+#define SLI_OPTION 14
+#define DISABLE_SCF_OPTION 15
+#define DIGITAL_VIBRANCE_OPTION 16
+#define TRANSPARENT_INDEX_OPTION 17
+#define STEREO_OPTION 18
+#define ROTATE_OPTION 19
+
+#define XCONFIG_OPTION_START 128
+
+/*
+ * The OPTION_HELP_ALWAYS flag is or'ed into the nvgetopts flags, but
+ * is used by print_help() to know whether to print the help
+ * information for that option all the time, or only when advanced
+ * help is requested.
+ */
+
+#define OPTION_HELP_ALWAYS 0x8000
+
+static const NVGetoptOption __options[] = {
+ /* These options are printed by "nvidia-xconfig --help" */
+
+ { "xconfig", 'c', NVGETOPT_HAS_ARGUMENT | OPTION_HELP_ALWAYS,
+ "Use [XCONFIG] as the input X config file; if this option is not "
+ "specified, then the same search path used by the X server will be "
+ "used to find the X configuration file." },
+
+ { "output-xconfig", 'o', NVGETOPT_HAS_ARGUMENT | OPTION_HELP_ALWAYS,
+ "Use [OUTPUT-XCONFIG] as the output X configuration file; if this "
+ "option is not specified, then the input X configuration filename will "
+ "also be used as the output filename." },
+
+ { "silent", 's', OPTION_HELP_ALWAYS,
+ "Run silently; no messages will be printed to stdout, except for "
+ "warning and error messages to stderr." },
+
+ { "tree", 't', OPTION_HELP_ALWAYS,
+ "Read the X configuration file, print to stdout the X "
+ "configuration data in a tree format, and exit." },
+
+ { "version", 'v', OPTION_HELP_ALWAYS,
+ "Print the nvidia-xconfig version and exit." },
+
+ { "help", 'h', OPTION_HELP_ALWAYS, "Print usage information for the "
+ "common commandline options and exit." },
+
+ { "advanced-help", 'A', OPTION_HELP_ALWAYS, "Print usage information "
+ "for the common commandline options as well as the advanced options, "
+ "and then exit." },
+
+ /* These options are only printed by "nvidia-xconfig --advanced-help" */
+
+ { "allow-ddcci", XCONFIG_OPTION_START + ALLOW_DDCCI_OPTION,
+ NVGETOPT_IS_BOOLEAN, "Enables or disables DDC/CI support in the "
+ "NV-CONTROL X extension." },
+
+ { "allow-dfp-stereo",
+ XCONFIG_OPTION_START + ALLOW_DFP_STEREO_OPTION, NVGETOPT_IS_BOOLEAN,
+ "Enable or disable the \"AllowDFPStereo\" X configuration option." },
+
+ { "allow-glx-with-composite",
+ XCONFIG_OPTION_START + ALLOW_GLX_WITH_COMPOSITE_OPTION,
+ NVGETOPT_IS_BOOLEAN, "Enable or disable the \"AllowGLXWithComposite\" "
+ "X configuration option." },
+
+ { "bandwidth-test",
+ XCONFIG_OPTION_START + NO_BANDWIDTH_TEST_OPTION, NVGETOPT_IS_BOOLEAN,
+ "Disable or enable the \"NoBandWidthTest\" X configuration option." },
+
+ { "dac-8bit", XCONFIG_OPTION_START + DAC_8BIT_OPTION, NVGETOPT_IS_BOOLEAN,
+ "Most Quadro parts by default use a 10 bit color look up table (LUT) "
+ "by default; setting this option to TRUE forces these graphics chips "
+ "to use an 8 bit (LUT)." },
+
+ { "ddc",
+ XCONFIG_OPTION_START + IGNORE_EDID_OPTION, NVGETOPT_IS_BOOLEAN,
+ "Synonym for \"ignore-edid\"" },
+
+ { "depth", 'd', NVGETOPT_HAS_ARGUMENT,
+ "Set the default depth to [DEPTH]; valid values are 8, 15, 16 and 24." },
+
+ { "digital-vibrance", DIGITAL_VIBRANCE_OPTION,
+ NVGETOPT_IS_INTEGER | NVGETOPT_HAS_ARGUMENT,
+ "Enables digital vibrance control. Valid values are 0-255." },
+
+ { "enable-all-gpus", 'a', 0,
+ "Configure an X screen on every GPU in the system." },
+
+ { "exact-mode-timings-dvi",
+ XCONFIG_OPTION_START + EXACT_MODE_TIMINGS_DVI_OPTION,
+ NVGETOPT_IS_BOOLEAN, "Forces the initialization of the X server with "
+ "the exact timings specified in the ModeLine." },
+
+ { "flip", XCONFIG_OPTION_START + NOFLIP_OPTION, NVGETOPT_IS_BOOLEAN,
+ "Enable or disable OpenGL flipping" },
+
+ { "force-generate", FORCE_GENERATE_OPTION, 0,
+ "Force generation of a new X config file, ignoring any existing "
+ "system X config file. This is not typically recommended, as things "
+ "like the mouse protocol, keyboard layout, font paths, etc, are setup "
+ "by your Unix distribution. While nvidia-xconfig can attempt to "
+ "infer these values, it is best to use your Unix distribution's "
+ "X config file for the basis of anything that nvidia-xconfig creates." },
+
+ { "force-stereo-flipping",
+ XCONFIG_OPTION_START + FORCE_STEREO_FLIPPING_OPTION, NVGETOPT_IS_BOOLEAN,
+ "Normally, stereo flipping is only performed when a stereo drawable is "
+ "visible. This option forces stereo flipping even when no stereo "
+ "drawables are visible." },
+
+ { "ignore-edid",
+ XCONFIG_OPTION_START + IGNORE_EDID_OPTION, NVGETOPT_IS_BOOLEAN,
+ "Disable or enable probing of EDID (Extended Display Identification "
+ "Data) from your monitor." },
+
+ { "use-edid-freqs",
+ XCONFIG_OPTION_START + USE_EDID_FREQS_OPTION, NVGETOPT_IS_BOOLEAN,
+ "Allow or disallow the X server to use the HorizSync and VertRefresh "
+ "ranges given in a display device's EDID, if any. EDID provided "
+ "range information will override the HorizSync and VertRefresh ranges "
+ "specified in the Monitor section." },
+
+ { "keyboard", KEYBOARD_OPTION, NVGETOPT_HAS_ARGUMENT,
+ "When generating a new X configuration file (which happens when no "
+ "system X configuration file can be found, or the '--force-generate' "
+ "option is specified), use [KEYBOARD] as the keyboard type, rather "
+ "than attempting to probe the system for the keyboard type. "
+ "For a list of possible keyboard types, see the '--keyboard-list' "
+ "option." },
+
+ { "keyboard-driver", KEYBOARD_DRIVER_OPTION, NVGETOPT_HAS_ARGUMENT,
+ "In most cases nvidia-xconfig can automatically determine the correct "
+ "keyboard driver to use (either 'kbd' or 'keyboard'). Use this "
+ "option to override what nvidia-xconfig detects. Typically, if you are "
+ "using an X.org X server, use 'kdb'; if you are using an XFree86 X "
+ "server, use 'keyboard'." },
+
+ { "keyboard-list", KEYBOARD_LIST_OPTION, 0,
+ "Print to stdout the available keyboard types recognized by the "
+ "'--keyboard' option, and then exit." },
+
+ { "layout", LAYOUT_OPTION, NVGETOPT_HAS_ARGUMENT,
+ "The nvidia-xconfig utility operates on a Server Layout within the X "
+ "configuration file. If this option is specified, the layout named "
+ "[LAYOUT] in the X configuration file will be used. If this option is "
+ "not specified, the first Server Layout in the X configuration "
+ "file is used." },
+
+ { "screen", SCREEN_OPTION, NVGETOPT_HAS_ARGUMENT,
+ "The nvidia-xconfig utility operates on one or more screens within a "
+ "Server Layout in the X configuration file. If this option is "
+ "specified, the screen named [SCREEN] in the X configuration file will "
+ "be used. If this option is not specified, all screens within the "
+ "selected Server Layout in the X configuration file "
+ "will be used used." },
+
+ { "load-kernel-module",
+ XCONFIG_OPTION_START + LOAD_KERNEL_MODULE_OPTION, NVGETOPT_IS_BOOLEAN,
+ "Allow or disallow NVIDIA Linux X driver module to load the NVIDIA "
+ "Linux kernel module automatically."},
+
+ { "logo",
+ XCONFIG_OPTION_START + NOLOGO_OPTION, NVGETOPT_IS_BOOLEAN,
+ "Disable or enable the \"NoLogo\" X configuration option." },
+
+ { "mode", MODE_OPTION, NVGETOPT_IS_BOOLEAN | NVGETOPT_HAS_ARGUMENT,
+ "Adds or removes the specified mode from the mode list." },
+
+ { "mouse", MOUSE_OPTION, NVGETOPT_HAS_ARGUMENT,
+ "When generating a new X configuration file (which happens when no "
+ "system X configuration file can be found, or the '--force-generate' "
+ "option is specified), use [MOUSE] as the mouse type, rather than "
+ "attempting to probe the system for the mouse type. For a list of "
+ "possible mouse types, see the '--mouse-list' option." },
+
+ { "mouse-list", MOUSE_LIST_OPTION, 0,
+ "Print to stdout the available mouse types recognized by the "
+ "'--mouse' option, and then exit." },
+
+ { "multisample-compatibility",
+ XCONFIG_OPTION_START + MULTISAMPLE_COMPATIBILITY_OPTION,
+ NVGETOPT_IS_BOOLEAN, "Enable or disable the use of separate front and "
+ "back multisample buffers." },
+
+ { "nvagp", NVAGP_OPTION, NVGETOPT_HAS_ARGUMENT,
+ "Set the NvAGP X config option value. Possible values are 0 (no AGP), "
+ "1 (NVIDIA's AGP), 2 (AGPGART), 3 (try AGPGART, then try NVIDIA's AGP); "
+ "these values can also be specified as 'none', 'nvagp', 'agpgart', or "
+ "'any'." },
+
+ { "nvidia-cfg-path", NVIDIA_CFG_PATH_OPTION, NVGETOPT_HAS_ARGUMENT,
+ "The nvidia-cfg library is used to communicate with the NVIDIA kernel "
+ "module to query basic properties of every GPU in the system. This "
+ "library is typically only used by nvidia-xconfig when configuring "
+ "multiple X screens. This option tells nvidia-xconfig where to look "
+ "for this library (in case it cannot find it on its own). This option "
+ "should normally not be needed." },
+
+ { "only-one-x-screen", '1', 0,
+ "Disable all but one X screen." },
+
+ { "overlay",
+ XCONFIG_OPTION_START + OVERLAY_OPTION, NVGETOPT_IS_BOOLEAN,
+ "Enable or disable the \"Overlay\" X configuration option." },
+
+ { "cioverlay",
+ XCONFIG_OPTION_START + CIOVERLAY_OPTION, NVGETOPT_IS_BOOLEAN,
+ "Enable or disable the color index overlay." },
+
+ { "transparent-index", TRANSPARENT_INDEX_OPTION,
+ NVGETOPT_IS_INTEGER | NVGETOPT_HAS_ARGUMENT,
+ "Pixel to use as transparent when using color index overlays. "
+ "Valid values are 0-255."},
+
+ { "overlay-default-visual",
+ XCONFIG_OPTION_START + OVERLAY_DEFAULT_VISUAL_OPTION,
+ NVGETOPT_IS_BOOLEAN, "Enable or disable the \"OverlayDefaultVisual\" "
+ "X configuration option." },
+
+ { "post-tree", 'T', 0,
+ "Like the '--tree' option, but goes through the full process of "
+ "applying any user requested updates to the X configuration, before "
+ "printing the final configuration to stdout in a tree format. "
+ "Effectively, this option just causes the configuration to be printed "
+ "to stdout as a tree instead of writing the results to file." },
+
+ { "power-connector-check",
+ XCONFIG_OPTION_START + NO_POWER_CONNECTOR_CHECK_OPTION,
+ NVGETOPT_IS_BOOLEAN, "Disable or enable the \"NoPowerConnectorCheck\" "
+ "X configuration option." },
+
+ { "randr-rotation",
+ XCONFIG_OPTION_START + RANDR_ROTATION_OPTION, NVGETOPT_IS_BOOLEAN,
+ "Enable or disable the \"RandRRotation\" X configuration option." },
+
+ { "rotate",
+ ROTATE_OPTION, NVGETOPT_HAS_ARGUMENT,
+ "Enable or disable the \"Rotate\" X configuration option. Valid values "
+ "are 'normal', 'left', 'inverted', and 'right'." },
+
+ { "render-accel",
+ XCONFIG_OPTION_START + RENDER_ACCEL_OPTION, NVGETOPT_IS_BOOLEAN,
+ "Enable or disable the \"RenderAccel\" X configuration option." },
+
+ { "render-extension",
+ XCONFIG_OPTION_START + NO_RENDER_EXTENSION_OPTION, NVGETOPT_IS_BOOLEAN,
+ "Disable or enable the \"NoRenderExtension\" X configuration option." },
+
+ { "separate-x-screens",
+ XCONFIG_OPTION_START + SEPARATE_X_SCREENS_OPTION, NVGETOPT_IS_BOOLEAN,
+ "A GPU that supports multiple simultaneous display devices can either "
+ "drive these display devices in TwinView, or as separate X screens. "
+ "When the '--separate-x-screens' option is specified, each GPU on which "
+ "an X screen is currently configured will be updated to have two X "
+ "screens configured. The '--no-separate-x-screens' option will remove "
+ "the second configured X screen on each GPU. Please see the NVIDIA "
+ "README description of \"Separate X Screens on One GPU\" for further "
+ "details." },
+
+ { "sli", SLI_OPTION, NVGETOPT_HAS_ARGUMENT,
+ "Enable or disable SLI. Valid options are 'Off', 'Auto', 'AFR', 'SFR', "
+ "and 'SLIAA'." },
+
+ { "stereo", STEREO_OPTION, NVGETOPT_IS_INTEGER | NVGETOPT_HAS_ARGUMENT,
+ "Enable/Disable the stereo mode. Valid options are: 1 (DCC glasses), "
+ "2 (Blueline glasses), 3 (Onboard stereo), 4 (TwinView clone mode "
+ "stereo), 5 (SeeReal digital flat panel), 6 (Sharp3D digital flat "
+ "panel)." },
+
+ { "twinview", XCONFIG_OPTION_START + TWINVIEW_OPTION, NVGETOPT_IS_BOOLEAN,
+ "Enable or disable TwinView." },
+
+ { "twinview-xinerama-info",
+ XCONFIG_OPTION_START + NO_TWINVIEW_XINERAMA_INFO_OPTION,
+ NVGETOPT_IS_BOOLEAN,
+ "Prohibits providing Xinerama information when in TwinView." },
+
+ { "ubb",
+ XCONFIG_OPTION_START + UBB_OPTION, NVGETOPT_IS_BOOLEAN,
+ "Enable or disable the \"UBB\" X configuration option." },
+
+ { "use-int10-module",
+ XCONFIG_OPTION_START + USE_INT10_MODULE_OPTION, NVGETOPT_IS_BOOLEAN,
+ "Enable use of the X Int10 module to soft-boot all secondary cards, "
+ "rather than POSTing the cards through the NVIDIA kernel module." },
+
+ { "x-prefix", X_PREFIX_OPTION, NVGETOPT_HAS_ARGUMENT,
+ "The X installation prefix; the default is /usr/X11R6/. Only "
+ "under rare circumstances should this option be needed." },
+
+ { "xinerama", XCONFIG_OPTION_START + XINERAMA_OPTION, NVGETOPT_IS_BOOLEAN,
+ "Enable or disable Xinerama." },
+
+ { "xvmc-uses-textures",
+ XCONFIG_OPTION_START + XVMC_USES_TEXTURES_OPTION, NVGETOPT_IS_BOOLEAN,
+ "Forces XvMC to use the 3D engine for XvMCPutSurface requests rather "
+ "than the video overlay." },
+
+#if defined(NV_SUNOS)
+ { "disable-scf", DISABLE_SCF_OPTION, 0,
+ "On Solaris, nvidia-xconfig updates the service configuration repository "
+ "with the default depth being set in the X configuration file. "
+ "The property 'default_depth' of the group 'options' in the "
+ "selection 'application/x11/x11-server' is set to the default depth. "
+ "Use this option to disable the service configuration repository update." },
+#endif
+
+ { NULL, 0 , 0, NULL },
+};
diff --git a/options.c b/options.c
new file mode 100644
index 0000000..dfb5b70
--- /dev/null
+++ b/options.c
@@ -0,0 +1,300 @@
+/*
+ * nvidia-xconfig: A tool for manipulating X config files,
+ * specifically for use by the NVIDIA Linux graphics driver.
+ *
+ * Copyright (C) 2004 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ * options.c
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "nvidia-xconfig.h"
+#include "xf86Parser.h"
+
+
+typedef struct {
+ unsigned int num;
+ int invert;
+ const char *name;
+} NvidiaXConfigOption;
+
+static const NvidiaXConfigOption __options[] = {
+
+ { NOLOGO_OPTION, TRUE, "NoLogo" },
+ { UBB_OPTION, FALSE, "UBB" },
+ { RENDER_ACCEL_OPTION, FALSE, "RenderAccel" },
+ { NO_RENDER_EXTENSION_OPTION, TRUE, "NoRenderExtension" },
+ { OVERLAY_OPTION, FALSE, "Overlay" },
+ { CIOVERLAY_OPTION, FALSE, "CIOverlay" },
+ { OVERLAY_DEFAULT_VISUAL_OPTION, FALSE, "OverlayDefaultVisual" },
+ { NO_BANDWIDTH_TEST_OPTION, TRUE, "NoBandWidthTest" },
+ { NO_POWER_CONNECTOR_CHECK_OPTION, TRUE, "NoPowerConnectorCheck" },
+ { ALLOW_DFP_STEREO_OPTION, FALSE, "AllowDFPStereo" },
+ { ALLOW_GLX_WITH_COMPOSITE_OPTION, FALSE, "AllowGLXWithComposite" },
+ { RANDR_ROTATION_OPTION, FALSE, "RandRRotation" },
+ { TWINVIEW_OPTION, FALSE, "TwinView" },
+ { XINERAMA_OPTION, FALSE, "Xinerama" },
+ { NO_TWINVIEW_XINERAMA_INFO_OPTION, TRUE, "NoTwinViewXineramaInfo" },
+ { NOFLIP_OPTION, TRUE, "NoFlip" },
+ { DAC_8BIT_OPTION, FALSE, "Dac8Bit" },
+ { USE_EDID_FREQS_OPTION, FALSE, "UseEdidFreqs" },
+ { IGNORE_EDID_OPTION, FALSE, "IgnoreEDID" },
+ { USE_INT10_MODULE_OPTION, FALSE, "UseInt10Module" },
+ { FORCE_STEREO_FLIPPING_OPTION, FALSE, "ForceStereoFlipping" },
+ { MULTISAMPLE_COMPATIBILITY_OPTION, FALSE, "MultisampleCompatibility" },
+ { XVMC_USES_TEXTURES_OPTION, FALSE, "XvmcUsesTextures" },
+ { EXACT_MODE_TIMINGS_DVI_OPTION, FALSE, "ExactModeTimingsDVI" },
+ { ALLOW_DDCCI_OPTION, FALSE, "AllowDDCCI" },
+ { LOAD_KERNEL_MODULE_OPTION, FALSE, "LoadKernelModule" },
+ { 0, FALSE, NULL },
+};
+
+
+
+/*
+ * get_option() - get the NvidiaXConfigOption entry for the given
+ * option index
+ */
+
+static const NvidiaXConfigOption *get_option(const int n)
+{
+ int i;
+
+ for (i = 0; __options[i].name; i++) {
+ if (__options[i].num == n) return &__options[i];
+ }
+ return NULL;
+
+} /* get_option() */
+
+
+
+/*
+ * remove_option_from_list() - remove the option with the given name
+ * from the list
+ */
+
+void remove_option_from_list(XConfigOptionPtr *list, const char *name)
+{
+ XConfigOptionPtr opt = xconfigFindOption(*list, name);
+ if (opt) {
+ *list = xconfigRemoveOption(*list, opt);
+ }
+} /* remove_option_from_list() */
+
+
+
+/*
+ * remove_option() - make sure the named option does not exist in any
+ * of the possible option lists:
+ *
+ * Options related to drivers can be present in the Screen, Device and
+ * Monitor sections and the Display subsections. The order of
+ * precedence is Display, Screen, Monitor, Device.
+ */
+
+static void remove_option(XConfigScreenPtr screen, const char *name)
+{
+ XConfigDisplayPtr display;
+
+ remove_option_from_list(&screen->device->options, name);
+ remove_option_from_list(&screen->monitor->options, name);
+ remove_option_from_list(&screen->options, name);
+
+ for (display = screen->displays; display; display = display->next) {
+ remove_option_from_list(&display->options, name);
+ }
+} /* remove_option() */
+
+
+
+/*
+ * set_option_value() - set the given option to the specified value
+ */
+
+static void set_option_value(XConfigScreenPtr screen,
+ const char *name, const char *val)
+{
+ /* first, remove the option to make sure it doesn't exist
+ elsewhere */
+
+ remove_option(screen, name);
+
+ /* then, add the option to the screen's option list */
+
+ screen->options = xconfigAddNewOption(screen->options,
+ nvstrdup(name), nvstrdup(val));
+} /* set_option_value() */
+
+
+
+/*
+ * update_twinview_options() - update the TwinView options
+ */
+
+static void update_twinview_options(Options *op, XConfigScreenPtr screen)
+{
+ /*
+ * if TwinView was specified, enable/disable the other TwinView
+ * options, too
+ */
+
+ if (GET_BOOL_OPTION(op->boolean_options, TWINVIEW_OPTION)) {
+ if (GET_BOOL_OPTION(op->boolean_option_values, TWINVIEW_OPTION)) {
+ set_option_value(screen, "TwinViewOrientation", "RightOf");
+ set_option_value(screen, "UseEdidFreqs", "True"); /* XXX */
+ set_option_value(screen, "MetaModes", "1024x768, 1024x768");
+ } else {
+ remove_option(screen, "TwinViewOrientation");
+ remove_option(screen, "SecondMonitorHorizSync");
+ remove_option(screen, "SecondMonitorVertRefresh");
+ remove_option(screen, "MetaModes");
+ }
+ }
+} /* update_twinview_options() */
+
+
+
+/*
+ * update_options() - update the X Config options, based on the
+ * command line arguments.
+ */
+
+void update_options(Options *op, XConfigScreenPtr screen)
+{
+ int i;
+ XConfigDisplayPtr display;
+ const NvidiaXConfigOption *o;
+ char *val;
+ char scratch[8];
+
+ /* update any boolean options specified on the commandline */
+
+ for (i = 0; i < XCONFIG_BOOL_OPTION_COUNT; i++) {
+ if (GET_BOOL_OPTION(op->boolean_options, i)) {
+
+ /*
+ * SEPARATE_X_SCREENS_OPTION and XINERAMA_OPTION are
+ * handled separately
+ */
+
+ if (i == SEPARATE_X_SCREENS_OPTION) continue;
+ if (i == XINERAMA_OPTION) continue;
+
+ o = get_option(i);
+
+ if (!o) {
+ fmterr("Unrecognized X Config option %d", i);
+ continue;
+ }
+
+ if (GET_BOOL_OPTION(op->boolean_option_values, i)) {
+ val = o->invert ? "False" : "True";
+ } else {
+ val = o->invert ? "True" : "False";
+ }
+
+ set_option_value(screen, o->name, val);
+ fmtmsg("Option \"%s\" \"%s\" added to "
+ "Screen \"%s\".", o->name, val, screen->identifier);
+ }
+ }
+
+ /* update the TwinView-related options */
+
+ update_twinview_options(op, screen);
+
+ /* update the mode list, based on what we have on the commandline */
+
+ for (display = screen->displays; display; display = display->next) {
+ for (i = 0; i < op->remove_modes.n; i++) {
+ display->modes = xconfigRemoveMode(display->modes,
+ op->remove_modes.t[i]);
+ }
+ for (i = 0; i < op->add_modes.n; i++) {
+ display->modes = xconfigAddMode(display->modes,
+ op->add_modes.t[i]);
+ }
+
+ /* XXX should we sort the mode list? */
+
+ /*
+ * XXX should we update the mode list with what we can get
+ * through libnvidia-cfg?
+ */
+ }
+
+ /* add the nvagp option */
+
+ if (op->nvagp != -1) {
+ remove_option(screen, "nvagp");
+ if (op->nvagp != -2) {
+ snprintf(scratch, 8, "%d", op->nvagp);
+ set_option_value(screen, "NvAGP", scratch);
+ }
+ }
+
+ /* add the digital vibrance option */
+
+ if (op->digital_vibrance != -1) {
+ remove_option(screen, "digitalvibrance");
+ if (op->digital_vibrance != -2) {
+ snprintf(scratch, 8, "%d", op->digital_vibrance);
+ set_option_value(screen, "DigitalVibrance", scratch);
+ }
+ }
+
+ /* add the transparent index option */
+
+ if (op->transparent_index != -1) {
+ remove_option(screen, "transparentindex");
+ if (op->transparent_index != -2) {
+ snprintf(scratch, 8, "%d", op->transparent_index);
+ set_option_value(screen, "TransparentIndex", scratch);
+ }
+ }
+
+ /* add the stereo option */
+
+ if (op->stereo != -1) {
+ remove_option(screen, "stereo");
+ if (op->stereo != -2) {
+ snprintf(scratch, 8, "%d", op->stereo);
+ set_option_value(screen, "Stereo", scratch);
+ }
+ }
+
+ /* add the SLI option */
+
+ if (op->sli) {
+ remove_option(screen, "SLI");
+ set_option_value(screen, "SLI", op->sli);
+ }
+
+ /* add the rotate option */
+
+ if (op->rotate) {
+ remove_option(screen, "Rotate");
+ set_option_value(screen, "Rotate", op->rotate);
+ }
+} /* update_options() */
diff --git a/tree.c b/tree.c
new file mode 100644
index 0000000..4f05eb9
--- /dev/null
+++ b/tree.c
@@ -0,0 +1,310 @@
+/*
+ * nvidia-xconfig: A tool for manipulating XConfig files,
+ * specifically for use by the NVIDIA Linux graphics driver.
+ *
+ * Copyright (C) 2004 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ * tree.c - this source file contains routines for printing an
+ * XConfig in a tree format, rooted at the ServerLayout section.
+ *
+ * Note that the tree is just printed to stdout (not through an
+ * ncurses ui) so we can just call printf directly here.
+ *
+ * TODO: there are many fields that we are not yet printed
+ */
+
+
+#include <stdio.h>
+
+#include "nvidia-xconfig.h"
+
+
+
+/*
+ * print_options()
+ */
+
+static void print_options(XConfigOptionPtr options, int indents)
+{
+ XConfigOptionPtr opt;
+ int i;
+
+ for (opt = options; opt; opt = opt->next) {
+ printf(" |");
+ for (i = 1; i < indents; i++) printf(" |");
+ printf("--> Option \"%s\"", opt->name);
+ if (opt->val) printf(" \"%s\"", opt->val);
+ printf("\n");
+ }
+} /* print_options() */
+
+
+
+/*
+ * print_range()
+ */
+
+static void print_range(parser_range* range, int n)
+{
+ int i;
+ for (i = 0; i < n; i++) {
+ if (i > 0) printf(", ");
+ printf("%.1f-%.1f", range[i].lo, range[i].hi);
+ }
+ printf("\n");
+
+} /* print_range() */
+
+
+
+/*
+ * print_monitor()
+ */
+
+static void print_monitor(XConfigMonitorPtr monitor)
+{
+ XConfigModeLinePtr modeline;
+
+ printf(" | |--> Monitor \"%s\"\n", monitor->identifier);
+ printf(" | | |\n");
+
+ if (monitor->vendor) {
+ printf(" | | |--> VendorName \"%s\"\n",
+ monitor->vendor);
+ }
+
+ if (monitor->modelname) {
+ printf(" | | |--> ModelName \"%s\"\n",
+ monitor->modelname);
+ }
+
+ printf(" | | |--> HorizSync ");
+ print_range(monitor->hsync, monitor->n_hsync);
+
+ printf(" | | |--> VertRefresh ");
+ print_range(monitor->vrefresh, monitor->n_vrefresh);
+
+ for (modeline = monitor->modelines; modeline; modeline = modeline->next) {
+ printf(" | | |--> Modeline \"%s\" ...\n",
+ modeline->identifier);
+ }
+
+ print_options(monitor->options, 3);
+
+ printf(" | |\n");
+
+} /* print_monitor() */
+
+
+
+/*
+ * print_device()
+ */
+
+static void print_device(XConfigDevicePtr device)
+{
+ printf(" | |--> Device \"%s\"\n", device->identifier);
+
+ if (device->driver) {
+ printf(" | | |--> Driver \"%s\"\n",
+ device->driver);
+ }
+ if (device->vendor) {
+ printf(" | | |--> VendorName \"%s\"\n",
+ device->vendor);
+ }
+ if (device->board) {
+ printf(" | | |--> BoardName \"%s\"\n",
+ device->board);
+ }
+ if (device->busid) {
+ printf(" | | |--> BusID \"%s\"\n",
+ device->busid);
+ }
+ if (device->screen >= 0) {
+ printf(" | | |--> Screen \"%d\"\n",
+ device->screen);
+ }
+
+ print_options(device->options, 3);
+
+ printf(" | |\n");
+
+} /* print_device() */
+
+
+
+/*
+ * print_modes()
+ */
+
+static void print_modes(XConfigScreenPtr screen)
+{
+ XConfigDisplayPtr display;
+ XConfigModePtr mode;
+
+ printf(" | |--> Modes");
+
+ for (display = screen->displays; display; display = display->next) {
+ if (display->depth == screen->defaultdepth) {
+ for (mode = display->modes; mode; mode = mode->next) {
+ printf(" \"%s\"", mode->mode_name);
+ }
+ break;
+ }
+ }
+
+ printf("\n");
+
+} /* print_modes() */
+
+
+
+/*
+ * print_screen()
+ */
+
+static void print_screen(XConfigScreenPtr screen)
+{
+ printf(" |--> Screen \"%s\"\n", screen->identifier);
+ printf(" | |\n");
+ print_monitor(screen->monitor);
+
+ print_device(screen->device);
+
+ print_options(screen->options, 2);
+
+ printf(" | |--> DefaultColorDepth %d\n",
+ screen->defaultdepth);
+ print_modes(screen);
+
+ printf(" |\n");
+
+} /* print_screen() */
+
+
+
+/*
+ * print_input()
+ */
+
+static void print_input(XConfigInputrefPtr inputRef)
+{
+ XConfigInputPtr input = inputRef->input;
+
+ printf(" |--> InputDevice \"%s\"\n", input->identifier);
+ printf(" | |\n");
+ printf(" | |--> Driver \"%s\"\n", input->driver);
+
+ print_options(input->options, 2);
+ print_options(inputRef->options, 2);
+
+ printf(" |\n");
+
+} /* print_input() */
+
+
+
+/*
+ * print_layout()
+ */
+
+static void print_layout(XConfigLayoutPtr layout)
+{
+ XConfigAdjacencyPtr adj;
+ XConfigInputrefPtr input;
+
+ printf("\n");
+ printf(" ServerLayout \"%s\"\n", layout->identifier);
+ printf(" |\n");
+
+ for (adj = layout->adjacencies; adj; adj = adj->next) {
+ print_screen(adj->screen);
+ }
+
+ for (input = layout->inputs; input; input = input->next) {
+ print_input(input);
+ }
+
+ print_options(layout->options, 1);
+
+} /* print_layout() */
+
+
+
+/*
+ * print_server_flags()
+ */
+
+static void print_server_flags(XConfigPtr config)
+{
+ if (!config->flags || !config->flags->options) return;
+
+ printf("\n");
+ printf(" ServerFlags\n");
+ printf(" |\n");
+
+ print_options(config->flags->options, 1);
+
+ printf("\n");
+
+} /* print_server_flags() */
+
+
+
+/*
+ * print_tree()
+ */
+
+int print_tree(Options *op, XConfigPtr config)
+{
+ XConfigLayoutPtr layout;
+
+ if (!config) {
+ printf("Unable to locate/open XConfig file.\n");
+ return FALSE;
+ }
+
+ /*
+ * either use the requested layout or loop over all the layouts in
+ * the file
+ */
+
+ if (op->layout) {
+ layout = xconfigFindLayout(op->layout, config->layouts);
+ if (!layout) {
+ printf("Unable to find layout \"%s\".\n", op->layout);
+ return FALSE;
+ }
+ print_layout(layout);
+ } else {
+ for (layout = config->layouts; layout; layout = layout->next) {
+ print_layout(layout);
+ }
+ }
+
+ printf("\n");
+
+ print_server_flags(config);
+
+ return TRUE;
+
+} /* print_tree() */
diff --git a/util.c b/util.c
new file mode 100644
index 0000000..c2dad50
--- /dev/null
+++ b/util.c
@@ -0,0 +1,806 @@
+/*
+ * nvidia-xconfig: A tool for manipulating XF86Config files,
+ * specifically for use by the NVIDIA Linux graphics driver.
+ *
+ * Copyright (C) 2004 NVIDIA Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the:
+ *
+ * Free Software Foundation, Inc.
+ * 59 Temple Place - Suite 330
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ * util.c
+ */
+
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <pwd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <sys/termios.h>
+
+#include "nvidia-xconfig.h"
+
+Options *__op = NULL;
+
+static void vformat(FILE *stream, const char *prefix, const char *msg);
+
+
+/*
+ * NV_VSNPRINTF(): macro that assigns b using vsnprintf(). This is
+ * supposedly correct for differing semantics of vsnprintf() in
+ * different versions of glibc:
+ *
+ * different semantics of the return value from (v)snprintf:
+ *
+ * -1 when the buffer is not long enough (glibc < 2.1)
+ *
+ * or
+ *
+ * the length the string would have been if the buffer had been large
+ * enough (glibc >= 2.1)
+ *
+ * This macro allocates memory for b; the caller should free it when
+ * done.
+ */
+
+#define NV_FMT_BUF_LEN 64
+
+#define NV_VSNPRINTF(b, f) \
+{ \
+ va_list ap; \
+ int len, current_len = NV_FMT_BUF_LEN; \
+ \
+ (b) = nvalloc(current_len); \
+ \
+ while (1) { \
+ va_start(ap, f); \
+ len = vsnprintf((b), current_len, (f), ap); \
+ va_end(ap); \
+ \
+ if ((len > -1) && (len < current_len)) { \
+ break; \
+ } else if (len > -1) { \
+ current_len = len + 1; \
+ } else { \
+ current_len += NV_FMT_BUF_LEN; \
+ } \
+ \
+ free(b); \
+ (b) = nvalloc(current_len); \
+ } \
+}
+
+
+/*
+ * nvalloc() - malloc wrapper that checks for errors, and zeros out
+ * the memory; if an error occurs, an error is printed to stderr and
+ * exit is called -- this function will only return on success.
+ */
+
+void *nvalloc(size_t size)
+{
+ void *m = malloc(size);
+
+ if (!m) {
+ fprintf(stderr, "%s: memory allocation failure (%s)! \n",
+ PROGRAM_NAME, strerror(errno));
+ exit(1);
+ }
+ memset((char *) m, 0, size);
+ return m;
+
+} /* nvalloc() */
+
+
+
+/*
+ * nvstrcat() - allocate a new string, copying all given strings
+ * into it. taken from glib
+ */
+
+char *nvstrcat(const char *str, ...)
+{
+ unsigned int l;
+ va_list args;
+ char *s;
+ char *concat;
+
+ l = 1 + strlen(str);
+ va_start(args, str);
+ s = va_arg(args, char *);
+
+ while (s) {
+ l += strlen(s);
+ s = va_arg(args, char *);
+ }
+ va_end(args);
+
+ concat = nvalloc(l);
+ concat[0] = 0;
+
+ strcat(concat, str);
+ va_start(args, str);
+ s = va_arg(args, char *);
+ while (s) {
+ strcat(concat, s);
+ s = va_arg(args, char *);
+ }
+ va_end(args);
+
+ return concat;
+
+} /* nvstrcat() */
+
+
+
+/*
+ * nvrealloc() - realloc wrapper that checks for errors; if an error
+ * occurs, an error is printed to stderr and exit is called -- this
+ * function will only return on success.
+ */
+
+void *nvrealloc(void *ptr, size_t size)
+{
+ void *m;
+
+ if (ptr == NULL) return nvalloc(size);
+
+ m = realloc(ptr, size);
+ if (!m) {
+ fprintf(stderr, "%s: memory re-allocation failure (%s)! \n",
+ PROGRAM_NAME, strerror(errno));
+ exit(1);
+ }
+ return m;
+
+} /* nvrealloc() */
+
+
+
+/*
+ * nvstrdup() - wrapper for strdup() that checks the return value; if
+ * an error occurs, an error is printed to stderr and exit is called
+ * -- this function will only return on success.
+ */
+
+char *nvstrdup(const char *s)
+{
+ char *m;
+
+ if (!s) return NULL;
+
+ m = strdup(s);
+
+ if (!m) {
+ fprintf(stderr, "%s: memory allocation failure during strdup (%s)! \n",
+ PROGRAM_NAME, strerror(errno));
+ exit(1);
+ }
+ return m;
+
+} /* nvstrdup() */
+
+
+
+/*
+ * nvfree() -
+ */
+void nvfree(char *s)
+{
+ if (s) free(s);
+
+} /* nvfree() */
+
+
+
+/*
+ * copy_file() - copy the file specified by srcfile to dstfile, using
+ * mmap and memcpy. The destination file is created with the
+ * permissions specified by mode. Roughly based on code presented by
+ * Richard Stevens, in Advanced Programming in the Unix Environment,
+ * 12.9.
+ */
+
+int copy_file(const char *srcfile, const char *dstfile, mode_t mode)
+{
+ int src_fd = -1, dst_fd = -1;
+ struct stat stat_buf;
+ char *src, *dst;
+ int ret = FALSE;
+
+ if ((src_fd = open(srcfile, O_RDONLY)) == -1) {
+ fmterr("Unable to open '%s' for copying (%s)",
+ srcfile, strerror (errno));
+ goto done;
+ }
+ if ((dst_fd = open(dstfile, O_RDWR | O_CREAT | O_TRUNC, mode)) == -1) {
+ fmterr("Unable to create '%s' for copying (%s)",
+ dstfile, strerror (errno));
+ goto done;
+ }
+ if (fstat(src_fd, &stat_buf) == -1) {
+ fmterr("Unable to determine size of '%s' (%s)",
+ srcfile, strerror (errno));
+ goto done;
+ }
+ if (stat_buf.st_size == 0) {
+ /* src file is empty; silently ignore */
+ ret = TRUE;
+ goto done;
+ }
+ if (lseek(dst_fd, stat_buf.st_size - 1, SEEK_SET) == -1) {
+ fmterr("Unable to set file size for '%s' (%s)",
+ dstfile, strerror (errno));
+ goto done;
+ }
+ if (write(dst_fd, "", 1) != 1) {
+ fmterr("Unable to write file size for '%s' (%s)",
+ dstfile, strerror (errno));
+ goto done;
+ }
+ if ((src = mmap(0, stat_buf.st_size, PROT_READ,
+ MAP_SHARED, src_fd, 0)) == (void *) -1) {
+ fmterr("Unable to map source file '%s' for "
+ "copying (%s)", srcfile, strerror (errno));
+ goto done;
+ }
+ if ((dst = mmap(0, stat_buf.st_size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, dst_fd, 0)) == (void *) -1) {
+ fmterr("Unable to map destination file '%s' for "
+ "copying (%s)", dstfile, strerror (errno));
+ goto done;
+ }
+
+ memcpy(dst, src, stat_buf.st_size);
+
+ if (munmap (src, stat_buf.st_size) == -1) {
+ fmterr("Unable to unmap source file '%s' after "
+ "copying (%s)", srcfile, strerror (errno));
+ goto done;
+ }
+ if (munmap (dst, stat_buf.st_size) == -1) {
+ fmterr("Unable to unmap destination file '%s' after "
+ "copying (%s)", dstfile, strerror (errno));
+ goto done;
+ }
+
+ ret = TRUE;
+
+ done:
+
+ if (src_fd != -1) close(src_fd);
+ if (dst_fd != -1) close(dst_fd);
+
+ return ret;
+
+} /* copy_file() */
+
+
+/*
+ * directory_exists() -
+ */
+
+int directory_exists(const char *dir)
+{
+ struct stat stat_buf;
+
+ if ((stat (dir, &stat_buf) == -1) || (!S_ISDIR(stat_buf.st_mode))) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+} /* directory_exists() */
+
+
+
+/*
+ * tilde_expansion() - do tilde expansion on the given path name;
+ * based loosely on code snippets found in the comp.unix.programmer
+ * FAQ. The tilde expansion rule is: if a tilde ('~') is alone or
+ * followed by a '/', then substitute the current user's home
+ * directory; if followed by the name of a user, then substitute that
+ * user's home directory.
+ */
+
+char *tilde_expansion(char *str)
+{
+ char *prefix = NULL;
+ char *replace, *user, *ret;
+ struct passwd *pw;
+ int len;
+
+ if ((!str) || (str[0] != '~')) return str;
+
+ if ((str[1] == '/') || (str[1] == '\0')) {
+
+ /* expand to the current user's home directory */
+
+ prefix = getenv("HOME");
+ if (!prefix) {
+
+ /* $HOME isn't set; get the home directory from /etc/passwd */
+
+ pw = getpwuid(getuid());
+ if (pw) prefix = pw->pw_dir;
+ }
+
+ replace = str + 1;
+
+ } else {
+
+ /* expand to the specified user's home directory */
+
+ replace = strchr(str, '/');
+ if (!replace) replace = str + strlen(str);
+
+ len = replace - str;
+ user = malloc(len + 1);
+ strncpy(user, str+1, len-1);
+ user[len] = '\0';
+ pw = getpwnam(user);
+ if (pw) prefix = pw->pw_dir;
+ free (user);
+ }
+
+ if (!prefix) return str;
+
+ ret = malloc(strlen(prefix) + strlen(replace) + 1);
+ strcpy(ret, prefix);
+ strcat(ret, replace);
+
+ return ret;
+
+} /* tilde_expansion() */
+
+
+
+/*
+ * xconfigPrint() - this is the one entry point that a user of the
+ * XF86Config-Parser library must provide.
+ */
+
+void xconfigPrint(MsgType t, const char *msg)
+{
+ typedef struct {
+ MsgType msg_type;
+ char *prefix;
+ FILE *stream;
+ int newline;
+ } MessageTypeAttributes;
+
+ char *prefix = NULL;
+ int i, newline = FALSE;
+ FILE *stream = stdout;
+
+ const MessageTypeAttributes msg_types[] = {
+ { ParseErrorMsg, "PARSE ERROR: ", stderr, TRUE },
+ { ParseWarningMsg, "PARSE WARNING: ", stderr, TRUE },
+ { ValidationErrorMsg, "VALIDATION ERROR: ", stderr, TRUE },
+ { InternalErrorMsg, "INTERNAL ERROR: ", stderr, TRUE },
+ { WriteErrorMsg, "ERROR: ", stderr, TRUE },
+ { WarnMsg, "WARNING: ", stderr, TRUE },
+ { ErrorMsg, "ERROR: ", stderr, TRUE },
+ { DebugMsg, "DEBUG: ", stdout, FALSE },
+ { UnknownMsg, NULL, stdout, FALSE },
+ };
+
+ for (i = 0; msg_types[i].msg_type != UnknownMsg; i++) {
+ if (msg_types[i].msg_type == t) {
+ prefix = msg_types[i].prefix;
+ newline = msg_types[i].newline;
+ stream = msg_types[i].stream;
+ break;
+ }
+ }
+
+ if (newline) vformat(stream, NULL, "");
+ vformat(stream, prefix, msg);
+ if (newline) vformat(stream, NULL, "");
+
+} /* xconfigPrint */
+
+
+
+static unsigned short __terminal_width = 0;
+
+#define DEFAULT_WIDTH 75
+
+/*
+ * reset_current_terminal_width() - if new_val is zero, then use the
+ * TIOCGWINSZ ioctl to get the current width of the terminal, and
+ * assign it the value to __terminal_width. If the ioctl fails, use a
+ * hardcoded constant. If new_val is non-zero, then use new_val.
+ */
+
+void reset_current_terminal_width(unsigned short new_val)
+{
+ struct winsize ws;
+
+ if (new_val) {
+ __terminal_width = new_val;
+ return;
+ }
+
+ if (ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == -1 || ws.ws_col == 0) {
+ __terminal_width = DEFAULT_WIDTH;
+ } else {
+ __terminal_width = ws.ws_col - 1;
+ }
+} /* get_current_terminal_width() */
+
+
+
+/*
+ * vformat() - we use nv_format_text_rows() to format the string so
+ * that not more than __terminal_width characters are printed across.
+ *
+ * The resulting formatted output is written to the specified stream.
+ * The output may also include an optional prefix (to be prepended on
+ * the first line, and filled with spaces on subsequent lines.
+ */
+
+static void vformat(FILE *stream, const char *prefix, const char *msg)
+{
+ int i;
+ TextRows *t;
+
+ if (!__terminal_width) reset_current_terminal_width(0);
+
+ t = nv_format_text_rows(prefix, msg, __terminal_width, TRUE);
+
+ for (i = 0; i < t->n; i++) fprintf(stream, "%s\n", t->t[i]);
+
+ nv_free_text_rows(t);
+
+} /* vformat() */
+
+
+
+/*
+ * nv_format_text_rows() - this function breaks the given string str
+ * into some number of rows, where each row is not longer than the
+ * specified width.
+ *
+ * If prefix is non-NULL, the first line is prepended with the prefix,
+ * and subsequent lines are indented to line up with the prefix.
+ *
+ * If word_boundary is TRUE, then attempt to only break lines on
+ * boundaries between words.
+ */
+
+TextRows *nv_format_text_rows(const char *prefix,
+ const char *str,
+ int width, int word_boundary)
+{
+ int len, prefix_len, z, w, i;
+ char *line, *buf, *local_prefix, *a, *b, *c;
+ TextRows *t;
+
+ /* initialize the TextRows structure */
+
+ t = (TextRows *) nvalloc(sizeof(TextRows));
+ t->t = NULL;
+ t->n = 0;
+ t->m = 0;
+
+ if (!str) return t;
+
+ buf = strdup(str);
+
+ z = strlen(buf); /* length of entire string */
+ a = buf; /* pointer to the start of the string */
+
+ /* initialize the prefix fields */
+
+ if (prefix) {
+ prefix_len = strlen(prefix);
+ local_prefix = strdup(prefix);
+ } else {
+ prefix_len = 0;
+ local_prefix = NULL;
+ }
+
+ /* adjust the max width for any prefix */
+
+ w = width - prefix_len;
+
+ do {
+ /*
+ * if the string will fit on one line, point b to the end of the
+ * string
+ */
+
+ if (z < w) b = a + z;
+
+ /*
+ * if the string won't fit on one line, move b to where the
+ * end of the line should be, and then move b back until we
+ * find a space; if we don't find a space before we back b all
+ * the way up to a, just assign b to where the line should end.
+ */
+
+ else {
+ b = a + w;
+
+ if (word_boundary) {
+ while ((b >= a) && (!isspace(*b))) b--;
+ if (b <= a) b = a + w;
+ }
+ }
+
+ /* look for any newline inbetween a and b, and move b to it */
+
+ for (c = a; c < b; c++) if (*c == '\n') { b = c; break; }
+
+ /*
+ * copy the string that starts at a and ends at b, prepending
+ * with a prefix, if present
+ */
+
+ len = b-a;
+ len += prefix_len;
+ line = (char *) malloc(len+1);
+ if (local_prefix) strncpy(line, local_prefix, prefix_len);
+ strncpy(line + prefix_len, a, len - prefix_len);
+ line[len] = '\0';
+
+ /* append the new line to the array of text rows */
+
+ t->t = (char **) realloc(t->t, sizeof(char *) * (t->n + 1));
+ t->t[t->n] = line;
+ t->n++;
+
+ if (t->m < len) t->m = len;
+
+ /*
+ * adjust the length of the string and move the pointer to the
+ * beginning of the new line
+ */
+
+ z -= (b - a + 1);
+ a = b + 1;
+
+ /* move to the first non whitespace character (excluding newlines) */
+
+ if (word_boundary && isspace(*b)) {
+ while ((z) && (isspace(*a)) && (*a != '\n')) a++, z--;
+ } else {
+ if (!isspace(*b)) z++, a--;
+ }
+
+ if (local_prefix) {
+ for (i = 0; i < prefix_len; i++) local_prefix[i] = ' ';
+ }
+
+ } while (z > 0);
+
+ if (local_prefix) free(local_prefix);
+ free(buf);
+
+ return t;
+
+} /* nv_format_text_rows() */
+
+
+
+void nv_text_rows_append(TextRows *t, const char *msg)
+{
+ int len;
+
+ t->t = (char **) nvrealloc(t->t, sizeof(char *) * (t->n + 1));
+
+ if (msg) {
+ t->t[t->n] = strdup(msg);
+ len = strlen(msg);
+ if (t->m < len) t->m = len;
+ } else {
+ t->t[t->n] = NULL;
+ }
+
+ t->n++;
+}
+
+/*
+ * nv_concat_text_rows() - concatenate two text rows
+ */
+
+#define NV_MAX(x,y) ((x) > (y) ? (x) : (y))
+
+void nv_concat_text_rows(TextRows *t0, TextRows *t1)
+{
+ int n, i;
+
+ n = t0->n + t1->n;
+
+ t0->t = (char **) nvrealloc(t0->t, sizeof(char *) * n);
+
+ for (i = 0; i < t1->n; i++) {
+ t0->t[i + t0->n] = nvstrdup(t1->t[i]);
+ }
+
+ t0->m = NV_MAX(t0->m, t1->m);
+ t0->n = n;
+
+} /* nv_concat_text_rows() */
+
+
+
+
+/*
+ * nv_free_text_rows() - free the TextRows data structure allocated by
+ * nv_format_text_rows()
+ */
+
+void nv_free_text_rows(TextRows *t)
+{
+ int i;
+
+ if (!t) return;
+ for (i = 0; i < t->n; i++) free(t->t[i]);
+ if (t->t) free(t->t);
+ free(t);
+
+} /* nv_free_text_rows() */
+
+
+/*
+ * fget_next_line() - read from the given FILE stream until a newline,
+ * EOF, or null terminator is encountered, writing data into a
+ * growable buffer. The eof parameter is set to TRUE when EOF is
+ * encountered. In all cases, the returned string is null-terminated.
+ *
+ * XXX this function will be rather slow because it uses fgetc() to
+ * pull each character off the stream one at a time; this is done so
+ * that each character can be examined as it's read so that we can
+ * appropriately deal with EOFs and newlines. A better implementation
+ * would use fgets(), but that would still require us to parse each
+ * read line, checking for newlines or guessing if we hit an EOF.
+ */
+
+#define NV_LINE_LEN 32
+
+char *fget_next_line(FILE *fp, int *eof)
+{
+ char *buf = NULL, *tmpbuf;
+ char *c = NULL;
+ int len = 0, buflen = 0;
+
+ if (eof) *eof = FALSE;
+
+ while (1) {
+ if (buflen == len) { /* buffer isn't big enough -- grow it */
+ buflen += NV_LINE_LEN;
+ tmpbuf = (char *) nvalloc (buflen);
+ if (buf) {
+ memcpy (tmpbuf, buf, len);
+ free (buf);
+ }
+ buf = tmpbuf;
+ c = buf + len;
+ }
+
+ *c = fgetc(fp);
+
+ if ((*c == EOF) && (eof)) *eof = TRUE;
+ if ((*c == EOF) || (*c == '\n') || (*c == '\0')) {
+ *c = '\0';
+ return buf;
+ }
+
+ len++;
+ c++;
+
+ } /* while (1) */
+
+ return NULL; /* should never get here */
+
+} /* fget_next_line() */
+
+
+#define NV_MSG_LEVEL_LINE 0
+#define NV_MSG_LEVEL_MESSAGE 1
+#define NV_MSG_LEVEL_WARNING 2
+#define NV_MSG_LEVEL_ERROR 3
+
+static void __print_message(const int level, const char *caller_prefix,
+ const char *msg)
+{
+ typedef struct {
+ char *prefix;
+ FILE *stream;
+ int newline;
+ } MessageLevelAttributes;
+
+ const char *prefix = NULL;
+
+ const MessageLevelAttributes msg_attrs[] = {
+ { NULL, stdout, FALSE }, /* NV_MSG_LEVEL_LOG */
+ { NULL, stdout, FALSE }, /* NV_MSG_LEVEL_MESSAGE */
+ { "WARNING: ", stderr, TRUE }, /* NV_MSG_LEVEL_WARNING */
+ { "ERROR: ", stderr, TRUE } /* NV_MSG_LEVEL_ERROR */
+ };
+
+ if (caller_prefix) {
+ prefix = caller_prefix;
+ } else {
+ prefix = msg_attrs[level].prefix;
+ }
+
+ if (msg_attrs[level].newline) vformat(msg_attrs[level].stream, NULL, "");
+ vformat(msg_attrs[level].stream, prefix, msg);
+ if (msg_attrs[level].newline) vformat(msg_attrs[level].stream, NULL, "");
+}
+
+void fmtout(const char *fmt, ...)
+{
+ char *msg;
+
+ NV_VSNPRINTF(msg, fmt);
+ if (!__op || !__op->silent)
+ __print_message(NV_MSG_LEVEL_LINE, NULL, msg);
+ free(msg);
+}
+
+void fmtoutp(const char *prefix, const char *fmt, ...)
+{
+ char *msg;
+
+ NV_VSNPRINTF(msg, fmt);
+ if (!__op || !__op->silent)
+ __print_message(NV_MSG_LEVEL_LINE, prefix, msg);
+ free(msg);
+}
+
+void fmtmsg(const char *fmt, ...)
+{
+ char *msg;
+
+ NV_VSNPRINTF(msg, fmt);
+ if (!__op || !__op->silent)
+ __print_message(NV_MSG_LEVEL_MESSAGE, NULL, msg);
+ free(msg);
+}
+
+void fmterr(const char *fmt, ...)
+{
+ char *msg;
+
+ NV_VSNPRINTF(msg, fmt);
+ __print_message(NV_MSG_LEVEL_ERROR, NULL, msg);
+ free(msg);
+}
+
+void fmtwarn(const char *fmt, ...)
+{
+ char *msg;
+
+ NV_VSNPRINTF(msg, fmt);
+ __print_message(NV_MSG_LEVEL_WARNING, NULL, msg);
+ free(msg);
+}
+