diff options
author | Aaron Plattner <aplattner@nvidia.com> | 2008-02-13 10:26:52 -0800 |
---|---|---|
committer | Aaron Plattner <aplattner@nvidia.com> | 2008-02-13 10:26:52 -0800 |
commit | c1cb49fc2abcb44580f7544e2ac8f987da5205cc (patch) | |
tree | c4f28e1ec22fab18a7f95fa2768badd263d0fd6b |
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; +} @@ -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", + ¤_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() */ @@ -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() */ @@ -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); +} + |