summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Plattner <aplattner@nvidia.com>2012-05-02 08:06:55 -0700
committerAaron Plattner <aplattner@nvidia.com>2012-05-02 08:06:55 -0700
commit783a1b15e786c5fd75928dfb1b4b31900de94df0 (patch)
tree6cab864eee729ae5bb2c078b20b79f2dc4a441e1
parentd2681269ec685639076b13c493cbb22215aa0eeb (diff)
302.07302.07
-rw-r--r--Makefile34
-rw-r--r--common-utils/common-utils.c338
-rw-r--r--common-utils/common-utils.h78
-rw-r--r--common-utils/gen-manpage-opts-helper.c181
-rw-r--r--common-utils/gen-manpage-opts-helper.h24
-rw-r--r--common-utils/nvgetopt.c125
-rw-r--r--common-utils/nvgetopt.h24
-rw-r--r--common-utils/src.mk6
-rw-r--r--extract_edids.c210
-rw-r--r--gen-manpage-opts.c140
-rw-r--r--nvidia-xconfig.c269
-rw-r--r--nvidia-xconfig.h24
-rw-r--r--option_table.h58
-rw-r--r--options.c4
-rw-r--r--query_gpu_info.c2
-rw-r--r--util.c381
-rw-r--r--utils.mk30
-rw-r--r--version.mk2
18 files changed, 1099 insertions, 831 deletions
diff --git a/Makefile b/Makefile
index 53097fe..2290430 100644
--- a/Makefile
+++ b/Makefile
@@ -88,14 +88,14 @@ CFLAGS += -DPROGRAM_NAME=\"nvidia-xconfig\"
HOST_CFLAGS += $(CFLAGS)
-LDFLAGS += -lm
+LIBS += -lm
ifneq ($(TARGET_OS),FreeBSD)
- LDFLAGS += -ldl
+ LIBS += -ldl
endif
ifeq ($(TARGET_OS),SunOS)
- LDFLAGS += -lscf
+ LIBS += -lscf
endif
@@ -110,16 +110,16 @@ all: $(NVIDIA_XCONFIG) $(MANPAGE)
install: NVIDIA_XCONFIG_install MANPAGE_install
NVIDIA_XCONFIG_install: $(NVIDIA_XCONFIG)
- $(MKDIR) $(bindir)
- $(INSTALL) $(INSTALL_BIN_ARGS) $< $(bindir)/$(notdir $<)
+ $(MKDIR) $(BINDIR)
+ $(INSTALL) $(INSTALL_BIN_ARGS) $< $(BINDIR)/$(notdir $<)
MANPAGE_install: $(MANPAGE)
- $(MKDIR) $(mandir)
- $(INSTALL) $(INSTALL_DOC_ARGS) $< $(mandir)/$(notdir $<)
+ $(MKDIR) $(MANDIR)
+ $(INSTALL) $(INSTALL_DOC_ARGS) $< $(MANDIR)/$(notdir $<)
$(NVIDIA_XCONFIG): $(OBJS)
- $(call quiet_cmd,LINK) -o $@ $(OBJS) $(CFLAGS) \
- $(LDFLAGS) $(BIN_LDFLAGS)
+ $(call quiet_cmd,LINK) $(CFLAGS) $(LDFLAGS) $(BIN_LDFLAGS) \
+ -o $@ $(OBJS) $(LIBS)
$(call quiet_cmd,STRIP_CMD) $@
# define the rule to build each object file
@@ -142,16 +142,22 @@ AUTO_TEXT = ".\\\" WARNING: THIS FILE IS AUTO-GENERATED! Edit $< instead."
doc: $(MANPAGE)
-$(eval $(call DEFINE_OBJECT_RULE,HOST_CC,gen-manpage-opts.c))
+GEN_MANPAGE_OPTS_SRC = gen-manpage-opts.c
+GEN_MANPAGE_OPTS_SRC += $(COMMON_UTILS_DIR)/gen-manpage-opts-helper.c
-$(GEN_MANPAGE_OPTS): $(call BUILD_OBJECT_LIST,gen-manpage-opts.c)
- $(call quiet_cmd,HOST_LINK) $< -o $@ \
- $(HOST_CFLAGS) $(HOST_LDFLAGS) $(HOST_BIN_LDFLAGS)
+GEN_MANPAGE_OPTS_OBJS = $(call BUILD_OBJECT_LIST,$(GEN_MANPAGE_OPTS_SRC))
+
+$(foreach src, $(GEN_MANPAGE_OPTS_SRC), \
+ $(eval $(call DEFINE_OBJECT_RULE,HOST_CC,$(src))))
+
+$(GEN_MANPAGE_OPTS): $(GEN_MANPAGE_OPTS_OBJS)
+ $(call quiet_cmd,HOST_LINK) \
+ $(HOST_CFLAGS) $(HOST_LDFLAGS) $(HOST_BIN_LDFLAGS) $^ -o $@
$(OPTIONS_1_INC): $(GEN_MANPAGE_OPTS)
@./$< > $@
-$(MANPAGE_not_gzipped): nvidia-xconfig.1.m4 $(OPTIONS_1_INC)
+$(MANPAGE_not_gzipped): nvidia-xconfig.1.m4 $(OPTIONS_1_INC) $(VERSION_MK)
$(call quiet_cmd,M4) -D__HEADER__=$(AUTO_TEXT) -I $(OUTPUTDIR) \
-D__VERSION__=$(NVIDIA_VERSION) \
-D__DATE__="`$(DATE) +%F`" \
diff --git a/common-utils/common-utils.c b/common-utils/common-utils.c
index 701bb07..98b92fe 100644
--- a/common-utils/common-utils.c
+++ b/common-utils/common-utils.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 NVIDIA Corporation
+ * Copyright (C) 2010-2012 NVIDIA Corporation
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -150,6 +150,35 @@ char *nvstrdup(const char *s)
/*
+ * nvstrndup() - implementation of strndup() that checks return values; if
+ * an error occurs, an error is printed to stderr and exit is called
+ * -- this function will only return on success.
+ */
+
+char *nvstrndup(const char *s, size_t n)
+{
+ char *m;
+
+ if (!s) return NULL;
+
+ m = malloc(n + 1);
+
+ if (!m) {
+ fprintf(stderr, "%s: memory allocation failure during malloc (%s)! \n",
+ PROGRAM_NAME, strerror(errno));
+ exit(1);
+ }
+
+ strncpy (m, s, n);
+ m[n] = '\0';
+
+ return m;
+
+} /* nvstrndup() */
+
+
+
+/*
* nvstrtolower() - convert the given string to lowercase.
*/
@@ -250,3 +279,310 @@ char *tilde_expansion(const char *str)
return ret;
} /* tilde_expansion() */
+
+
+/****************************************************************************/
+/* TextRows helper functions */
+/****************************************************************************/
+
+/*
+ * 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 *) malloc(sizeof(TextRows));
+
+ if (!t) return NULL;
+
+ t->t = NULL;
+ t->n = 0;
+ t->m = 0;
+
+ if (!str) return t;
+
+ buf = strdup(str);
+
+ if (!buf) return t;
+
+ 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_text_rows_append() - append the given msg to the existing TextRows
+ */
+
+void nv_text_rows_append(TextRows *t, const char *msg)
+{
+ int len;
+
+ t->t = realloc(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, storing the
+ * result in t0
+ */
+
+#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 = realloc(t0->t, sizeof(char *) * n);
+
+ for (i = 0; i < t1->n; i++) {
+ t0->t[i + t0->n] = strdup(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() */
+
+
+/****************************************************************************/
+/* printing helper functions */
+/****************************************************************************/
+
+#define DEFAULT_WIDTH 75
+
+static unsigned short __terminal_width = 0;
+
+/*
+ * 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;
+ }
+}
+
+/*
+ * Call silence_fmt(1) to turn fmtout(), fmtoutp() and format() into noops.
+ */
+static int __silent = 0;
+
+void silence_fmt(int val)
+{
+ __silent = val;
+}
+
+
+static void vformat(FILE *stream, const int wb,
+ const char *prefix, const char *buf)
+{
+ int i;
+ TextRows *t;
+
+ if (!__terminal_width) reset_current_terminal_width(0);
+
+ t = nv_format_text_rows(prefix, buf, __terminal_width, wb);
+
+ for (i = 0; i < t->n; i++) fprintf(stream, "%s\n", t->t[i]);
+
+ nv_free_text_rows(t);
+}
+
+
+#define NV_VFORMAT(stream, wb, prefix, fmt) \
+do { \
+ char *buf; \
+ NV_VSNPRINTF(buf, fmt); \
+ vformat(stream, wb, prefix, buf); \
+ free (buf); \
+} while(0)
+
+
+void fmtout(const char *fmt, ...)
+{
+ if (__silent > 0) {
+ return;
+ }
+ NV_VFORMAT(stdout, TRUE, NULL, fmt);
+}
+
+
+void fmtoutp(const char *prefix, const char *fmt, ...)
+{
+ if (__silent > 0) {
+ return;
+ }
+ NV_VFORMAT(stdout, TRUE, prefix, fmt);
+}
+
+
+void fmterr(const char *fmt, ...)
+{
+ vformat(stderr, 0, NULL, "");
+ NV_VFORMAT(stderr, TRUE, "ERROR: ", fmt);
+ vformat(stderr, 0, NULL, "");
+}
+
+
+void fmtwarn(const char *fmt, ...)
+{
+ vformat(stderr, 0, NULL, "");
+ NV_VFORMAT(stderr, TRUE, "WARNING: ", fmt);
+ vformat(stderr, 0, NULL, "");
+}
+
+
+void fmt(FILE *stream, const char *prefix, const char *fmt, ...)
+{
+ if (__silent > 0) {
+ return;
+ }
+ NV_VFORMAT(stream, TRUE, prefix, fmt);
+}
diff --git a/common-utils/common-utils.h b/common-utils/common-utils.h
index 04d5f3b..e0d9314 100644
--- a/common-utils/common-utils.h
+++ b/common-utils/common-utils.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 NVIDIA Corporation
+ * Copyright (C) 2010-2012 NVIDIA Corporation
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -17,6 +17,9 @@
#ifndef __COMMON_UTILS_H__
#define __COMMON_UTILS_H__
+#include <stdio.h>
+#include <stdarg.h>
+
#if !defined(TRUE)
#define TRUE 1
#endif
@@ -25,13 +28,86 @@
#define FALSE 0
#endif
+#define ARRAY_LEN(_arr) (sizeof(_arr) / sizeof(_arr[0]))
+
+#define TAB " "
+#define BIGTAB " "
+
+typedef struct {
+ char **t; /* the text rows */
+ int n; /* number of rows */
+ int m; /* maximum row length */
+} TextRows;
+
void *nvalloc(size_t size);
char *nvstrcat(const char *str, ...);
void *nvrealloc(void *ptr, size_t size);
char *nvstrdup(const char *s);
+char *nvstrndup(const char *s, size_t n);
char *nvstrtolower(char *s);
void nvfree(void *s);
char *tilde_expansion(const char *str);
+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_concat_text_rows(TextRows *t0, TextRows *t1);
+void nv_free_text_rows(TextRows *t);
+
+void reset_current_terminal_width(unsigned short new_val);
+
+void silence_fmt(int val);
+void fmtout(const char *fmt, ...);
+void fmtoutp(const char *prefix, const char *fmt, ...);
+void fmterr(const char *fmt, ...);
+void fmtwarn(const char *fmt, ...);
+void fmt(FILE *stream, const char *prefix, const char *fmt, ...);
+
+/*
+ * NV_VSNPRINTF(): macro that assigns buf using vsnprintf(). This is
+ * correct for differing semantics of the vsnprintf() return value:
+ *
+ * -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 buf; the caller should free it when
+ * done.
+ */
+
+#define NV_FMT_BUF_LEN 256
+
+#define NV_VSNPRINTF(buf, fmt) \
+do { \
+ if (!fmt) { \
+ (buf) = NULL; \
+ } else { \
+ va_list ap; \
+ int len, current_len = NV_FMT_BUF_LEN; \
+ \
+ (buf) = malloc(current_len); \
+ \
+ while (1) { \
+ va_start(ap, fmt); \
+ len = vsnprintf((buf), 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(buf); \
+ (buf) = malloc(current_len); \
+ } \
+ } \
+} while (0)
+
#endif /* __COMMON_UTILS_H__ */
diff --git a/common-utils/gen-manpage-opts-helper.c b/common-utils/gen-manpage-opts-helper.c
new file mode 100644
index 0000000..d2abb1c
--- /dev/null
+++ b/common-utils/gen-manpage-opts-helper.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "nvgetopt.h"
+#include "gen-manpage-opts-helper.h"
+
+static void print_option(const NVGetoptOption *o)
+{
+ char scratch[64], *s;
+ int j, len;
+
+ int italics, bold, omitWhiteSpace;
+
+ /* if we are going to need the argument, process it now */
+ if (o->flags & NVGETOPT_HAS_ARGUMENT) {
+ if (o->arg_name) {
+ strcpy(scratch, o->arg_name);
+ } else {
+ len = strlen(o->name);
+ for (j = 0; j < len; j++) scratch[j] = toupper(o->name[j]);
+ scratch[len] = '\0';
+ }
+ }
+
+ printf(".TP\n.BI \"");
+ /* Print the name of the option */
+ /* XXX We should backslashify the '-' characters in o->name. */
+
+ if (isalpha(o->val)) {
+ /* '\-c' */
+ printf("\\-%c", o->val);
+
+ if (o->flags & NVGETOPT_HAS_ARGUMENT) {
+ /* ' " "ARG" "' */
+ printf(" \" \"%s\" \"", scratch);
+ }
+ /* ', ' */
+ printf(", ");
+ }
+
+ /* '\-\-name' */
+ printf("\\-\\-%s", o->name);
+
+ /* '=" "ARG' */
+ if (o->flags & NVGETOPT_HAS_ARGUMENT) {
+ printf("=\" \"%s", scratch);
+
+ /* '" "' */
+ if ((o->flags & NVGETOPT_IS_BOOLEAN) ||
+ (o->flags & NVGETOPT_ALLOW_DISABLE)) {
+ printf("\" \"");
+ }
+ }
+
+ /* ', \-\-no\-name' */
+ if (((o->flags & NVGETOPT_IS_BOOLEAN) &&
+ !(o->flags & NVGETOPT_HAS_ARGUMENT)) ||
+ (o->flags & NVGETOPT_ALLOW_DISABLE)) {
+ printf(", \\-\\-no\\-%s", o->name);
+ }
+
+ printf("\"\n");
+
+ /* Print the option description */
+ /* XXX Each sentence should be on its own line! */
+
+ /*
+ * Print the option description: write each character one at a
+ * time (ugh) so that we can special-case a few characters:
+ *
+ * '&' : toggles italics on and off
+ * '^' : toggles bold on and off
+ * '-' : is backslashified: "\-"
+ *
+ * Whitespace is omited when italics or bold is on
+ */
+
+ italics = 0;
+ bold = 0;
+ omitWhiteSpace = 0;
+
+ for (s = o->description; s && *s; s++) {
+
+ switch (*s) {
+ case '&':
+ if (italics) {
+ printf("\n");
+ } else {
+ printf("\n.I ");
+ }
+ omitWhiteSpace = italics;
+ italics = !italics;
+ break;
+ case '^':
+ if (bold) {
+ printf("\n");
+ } else {
+ printf("\n.B ");
+ }
+ omitWhiteSpace = bold;
+ bold = !bold;
+ break;
+ case '-':
+ printf("\\-");
+ omitWhiteSpace = 0;
+ break;
+ case ' ':
+ if (!omitWhiteSpace) {
+ printf(" ");
+ }
+ break;
+ default:
+ printf("%c", *s);
+ omitWhiteSpace = 0;
+ break;
+ }
+ }
+
+ printf("\n");
+}
+
+void gen_manpage_opts_helper(const NVGetoptOption *options)
+{
+ int i;
+ int has_advanced_options = 0;
+
+ /* Print the "simple" options; i.e. the ones you get with --help. */
+ printf(".SH OPTIONS\n");
+ for (i = 0; options[i].name; i++) {
+ const NVGetoptOption *o = &options[i];
+
+ if (!o->description) {
+ continue;
+ }
+
+ if (!(o->flags & NVGETOPT_HELP_ALWAYS)) {
+ has_advanced_options = 1;
+ continue;
+ }
+
+ print_option(o);
+ }
+
+ if (has_advanced_options) {
+ /*
+ * If any exist, print the advanced options; i.e., the ones
+ * you get with --advanced-help
+ */
+ printf(".SH \"ADVANCED OPTIONS\"\n");
+ for (i = 0; options[i].name; i++) {
+ const NVGetoptOption *o = &options[i];
+
+ if (!o->description) {
+ continue;
+ }
+
+ if (o->flags & NVGETOPT_HELP_ALWAYS) {
+ continue;
+ }
+
+ print_option(o);
+ }
+ }
+}
diff --git a/common-utils/gen-manpage-opts-helper.h b/common-utils/gen-manpage-opts-helper.h
new file mode 100644
index 0000000..b09852e
--- /dev/null
+++ b/common-utils/gen-manpage-opts-helper.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#if !defined(__GEN_MANPAGE_OPTS_HELPER_H__)
+#define __GEN_MANPAGE_OPTS_HELPER_H__
+
+#include "nvgetopt.h"
+
+void gen_manpage_opts_helper(const NVGetoptOption *options);
+
+#endif /* __GEN_MANPAGE_OPTS_HELPER_H__ */
diff --git a/common-utils/nvgetopt.c b/common-utils/nvgetopt.c
index a89dcac..f04cef3 100644
--- a/common-utils/nvgetopt.c
+++ b/common-utils/nvgetopt.c
@@ -21,8 +21,10 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <ctype.h>
#include "nvgetopt.h"
+#include "common-utils.h"
int nvgetopt(int argc,
@@ -309,3 +311,126 @@ int nvgetopt(int argc,
return ret;
} /* nvgetopt() */
+
+
+/*
+ * cook_description() - the description string may contain text within
+ * special characters which are interpreted by the manpage generator.
+ * We want to omit those characters here.
+ */
+
+static char *cook_description(const char *description)
+{
+ const char *src;
+ char *s, *dst;
+
+ if (!description) {
+ return NULL;
+ }
+
+ s = strdup(description);
+
+ if (!s) {
+ return NULL;
+ }
+
+ for (src = description, dst = s; *src; src++) {
+ if ((*src == '&') || (*src == '^')) {
+ continue;
+ }
+ *dst = *src;
+ dst++;
+ }
+
+ *dst = '\0';
+
+ return s;
+}
+
+
+void nvgetopt_print_help(const NVGetoptOption *options,
+ unsigned int include_mask,
+ nvgetopt_print_help_callback_ptr callback)
+{
+ const NVGetoptOption *o;
+ int i;
+
+ for (i = 0; options[i].name; i++) {
+
+ char *msg = NULL, *arg = NULL, *description = NULL;
+
+ o = &options[i];
+
+ /* Skip options with no help text */
+ if (!o->description) {
+ continue;
+ }
+
+ /* skip options who don't have all the bits of include_mask */
+ if ((o->flags & include_mask) != include_mask) {
+ continue;
+ }
+
+ /* if we are going to need the argument, process it now */
+ arg = NULL;
+ if (o->flags & NVGETOPT_HAS_ARGUMENT) {
+ if (o->arg_name) {
+ arg = strdup(o->arg_name);
+ } else {
+ char *tmp;
+ arg = strdup(o->name);
+ for (tmp = arg; tmp && *tmp; tmp++) {
+ *tmp = toupper(*tmp);
+ }
+ }
+ }
+
+ msg = NULL;
+
+ /*
+ * create the long version of the option, possibly with an
+ * argument; e.g., "--foo" or "--foo=BAR"
+ */
+ if (arg) {
+ msg = nvstrcat("--", o->name, "=", arg, NULL);
+ } else {
+ msg = nvstrcat("--", o->name, NULL);
+ }
+
+ /*
+ * prepend the single character version of the option,
+ * possibly with an argument; e.g., "-f" or "-f BAR"
+ */
+ if (isalpha(o->val)) {
+ char scratch[16];
+ char *tmp;
+ snprintf(scratch, sizeof(scratch), "%c", o->val);
+ if (arg) {
+ tmp = nvstrcat("-", scratch, " ", arg, ", ", msg, NULL);
+ } else {
+ tmp = nvstrcat("-", scratch, ", ", msg, NULL);
+ }
+ free(msg);
+ msg = tmp;
+ }
+
+ /* append the boolean version of the option; e.g., "--no-foo" */
+ if (((o->flags & NVGETOPT_IS_BOOLEAN) &&
+ !(o->flags & NVGETOPT_HAS_ARGUMENT)) ||
+ (o->flags & NVGETOPT_ALLOW_DISABLE)) {
+ char *tmp = nvstrcat(msg, ", --no-", o->name, NULL);
+ free(msg);
+ msg = tmp;
+ }
+
+ /* process the description text */
+ description = cook_description(o->description);
+
+ /* give the strings to the caller to format and print */
+ callback(msg, description);
+
+ free(msg);
+ free(arg);
+ free(description);
+ }
+}
diff --git a/common-utils/nvgetopt.h b/common-utils/nvgetopt.h
index 127f40b..5847546 100644
--- a/common-utils/nvgetopt.h
+++ b/common-utils/nvgetopt.h
@@ -155,5 +155,29 @@ int nvgetopt(int argc,
double *doubleval,
int *disable_val);
+/*
+ * nvgetopt_print_help() - print a help message for each option in the
+ * provided NVGetoptOption array. This is useful for a utility's
+ * "--help" output.
+ *
+ * Options will only be printed if they have every bit set that
+ * include_mask includes.
+ *
+ * For each option, the provided callback function wil be called with
+ * two strings: a name string that lists the option's name, and a
+ * description string for the option. The callback function is
+ * responsible for actually printing these strings. Examples:
+ *
+ * name = "-v, --version";
+ * description = "Print usage information for the common commandline "
+ * "options and exit.";
+ */
+
+typedef void nvgetopt_print_help_callback_ptr(const char *name,
+ const char *description);
+
+void nvgetopt_print_help(const NVGetoptOption *options,
+ unsigned int include_mask,
+ nvgetopt_print_help_callback_ptr callback);
#endif /* __NVGETOPT_H__ */
diff --git a/common-utils/src.mk b/common-utils/src.mk
index 14e4131..12ba143 100644
--- a/common-utils/src.mk
+++ b/common-utils/src.mk
@@ -7,3 +7,9 @@ COMMON_UTILS_EXTRA_DIST += nvgetopt.h
COMMON_UTILS_EXTRA_DIST += common-utils.h
COMMON_UTILS_EXTRA_DIST += src.mk
+# gen-manpage-opts-helper.c is listed in EXTRA_DIST, rather than SRC,
+# because it is not compiled into the utilities themselves, but used
+# when building the utility's gen-manpage-opts
+COMMON_UTILS_EXTRA_DIST += gen-manpage-opts-helper.c
+COMMON_UTILS_EXTRA_DIST += gen-manpage-opts-helper.h
+
diff --git a/extract_edids.c b/extract_edids.c
index b62ad4c..cd0569d 100644
--- a/extract_edids.c
+++ b/extract_edids.c
@@ -34,7 +34,6 @@
* (--) NVIDIA(0): 69 65 77 53 6f 6e 69 63 20 56 50 44 00 00 00 fc
* (--) NVIDIA(0): 00 31 35 30 0a 20 20 20 20 20 20 20 20 20 00 ce
* (--) NVIDIA(0):
- * (--) NVIDIA(0): --- End of EDID for ViewSonic VPD150 (DFP-1) ---
*
* The added possibilities for the X log are, that the log file contains
* timestamps along with the raw EDID byte dump like this:
@@ -54,6 +53,9 @@
* (STATE_LOOKING_FOR_START_OF_LABEL & STATE_LOOKING_FOR_SCREEN_NUMBER_IN_LABEL)
* for handling these special cases.
*
+ * Note that in some cases the label could have the form
+ * "NVIDIA(GPU-0)" rather than "NVIDIA(0)".
+
* A .txt file will contain a raw EDID byte dump like this:
*
* 00 FF FF FF FF FF FF 00-06 10 F4 01 01 01 01 01 ................
@@ -146,6 +148,27 @@ static int writeEdidFile(EdidPtr pEdid, char *filename);
static void freeEdid(EdidPtr pEdid);
+/*
+ * Moves FilePtr::current to the end of the next occurrence of the
+ * specified string within the file. Return TRUE if the string is
+ * found in the file; return FALSE otherwise.
+ */
+
+static inline int moveFilePointerPastString(FilePtr pFile, const char *s)
+{
+ size_t len = strlen(s);
+
+ while (((pFile->current - pFile->start) + len) <= pFile->length) {
+
+ if (strncmp(pFile->current, s, len) == 0) {
+
+ pFile->current += len;
+ return TRUE;
+ }
+ pFile->current++;
+ }
+ return FALSE;
+}
/*
@@ -373,31 +396,7 @@ static EdidPtr findEdidforTextFile(FilePtr pFile)
static int findEdidHeaderforLogFile(FilePtr pFile)
{
- while (((pFile->current - pFile->start) + 15) <= pFile->length) {
-
- if ((pFile->current[0] == 'R') &&
- (pFile->current[1] == 'a') &&
- (pFile->current[2] == 'w') &&
- (pFile->current[3] == ' ') &&
- (pFile->current[4] == 'E') &&
- (pFile->current[5] == 'D') &&
- (pFile->current[6] == 'I') &&
- (pFile->current[7] == 'D') &&
- (pFile->current[8] == ' ') &&
- (pFile->current[9] == 'b') &&
- (pFile->current[10] == 'y') &&
- (pFile->current[11] == 't') &&
- (pFile->current[12] == 'e') &&
- (pFile->current[13] == 's') &&
- (pFile->current[14] == ':')) {
-
- pFile->current += 15;
- return TRUE;
- }
- pFile->current++;
- }
-
- return FALSE;
+ return moveFilePointerPastString(pFile, "Raw EDID bytes:");
} // findEdidHeaderforLogFile()
@@ -413,21 +412,30 @@ static int findEdidHeaderforLogFile(FilePtr pFile)
* character of the string, because the readEdidDataforLogFile()
* state machine will move pFile->current forward one character when
* findLogFileLineLabel() succeeds.
+ *
+ * This handles both "NVIDIA(#)" and "NVIDIA(GPU-#)".
*/
static int findLogFileLineLabel(FilePtr pFile)
{
- while (((pFile->current - pFile->start) + 7) <= pFile->length) {
+ while ((pFile->current - pFile->start) <= pFile->length) {
+
+ const char *gpuTag = "NVIDIA(GPU";
+ const char *screenTag = "NVIDIA(";
- if ((pFile->current[0] == 'N') &&
- (pFile->current[1] == 'V') &&
- (pFile->current[2] == 'I') &&
- (pFile->current[3] == 'D') &&
- (pFile->current[4] == 'I') &&
- (pFile->current[5] == 'A') &&
- (pFile->current[6] == '(')) {
+ size_t remainder = pFile->length - (pFile->current - pFile->start);
- pFile->current += 6;
+ if ((remainder > strlen(gpuTag)) &&
+ (strncmp(pFile->current, gpuTag, strlen(gpuTag)) == 0)) {
+
+ pFile->current += strlen(gpuTag);
+ return TRUE;
+ }
+
+ if ((remainder > strlen(screenTag)) &&
+ (strncmp(pFile->current, screenTag, strlen(screenTag)) == 0)) {
+
+ pFile->current += strlen(screenTag);
return TRUE;
}
pFile->current++;
@@ -510,18 +518,11 @@ static int readEdidDataforLogFile(FilePtr pFile, EdidPtr pEdid)
}
/*
- * if we find the text "--- End of EDID for ... ---", then
- * we want to parse that to find out the name of the
- * display device whose EDID we are reading; this is also
- * our exit condition for the state machine
+ * if we hit anything else, we have reached the end of the
+ * EDID: exit the state machine.
*/
- if (c == '-') {
goto done;
- }
-
- goto fail; /* anything else is an error */
-
break;
case STATE_LOOKING_FOR_BOTTOM_NIBBLE:
@@ -803,68 +804,61 @@ static int readEdidDataforTextFile(FilePtr pFile, EdidPtr pEdid)
} // readEdidDataforTextFile()
/*
- * readEdidFooter() - the EDID footer is in the form:
+ * readEdidFooter() - the optional EDID footer is in the form:
*
* --- End of EDID for [dpy name] ---
*
- * Parse the footer to get the dpy name. pFile->current is expected
- * to point at the start of the footer. On success, pEdid->name is
- * assigned and TRUE is returned. On failure, FALSE is returned.
+ * Parse the footer to get the dpy name. If a footer is present,
+ * pFile->current is expected to point at the start of it. On
+ * success, pEdid->name is assigned and TRUE is returned. On failure,
+ * FALSE is returned.
*/
static int readEdidFooterforLogFile(FilePtr pFile, EdidPtr pEdid)
{
char *begin;
- int len;
+ int len, ret;
+ const char *edidFooterStart = "--- End of EDID for ";
+ const char *edidFooterEnd = " ---";
/* check that the mapping is large enough */
- if (((pFile->current - pFile->start) + 20) > pFile->length) {
+ if (((pFile->current - pFile->start) + strlen(edidFooterStart)) >
+ pFile->length) {
return FALSE;
}
- /* make sure that the expected text is there */
-
- if ((pFile->current[0] != '-') ||
- (pFile->current[1] != '-') ||
- (pFile->current[2] != '-') ||
- (pFile->current[3] != ' ') ||
- (pFile->current[4] != 'E') ||
- (pFile->current[5] != 'n') ||
- (pFile->current[6] != 'd') ||
- (pFile->current[7] != ' ') ||
- (pFile->current[8] != 'o') ||
- (pFile->current[9] != 'f') ||
- (pFile->current[10] != ' ') ||
- (pFile->current[11] != 'E') ||
- (pFile->current[12] != 'D') ||
- (pFile->current[13] != 'I') ||
- (pFile->current[14] != 'D') ||
- (pFile->current[15] != ' ') ||
- (pFile->current[16] != 'f') ||
- (pFile->current[17] != 'o') ||
- (pFile->current[18] != 'r') ||
- (pFile->current[19] != ' ')) {
+ /* check whether the footer text is there */
- return FALSE;
+ if (strncmp(pFile->current, edidFooterStart, strlen(edidFooterStart)) != 0) {
+
+ /* if not, we do not know the name of the display device */
+
+ pEdid->name = strdup("unknown");
+
+ return TRUE;
}
/* skip past the start */
- pFile->current += 20;
+ pFile->current += strlen(edidFooterStart);
begin = pFile->current;
/* search for the end of the expected text */
- while (((pFile->current - pFile->start) + 5) <= pFile->length) {
+ ret = moveFilePointerPastString(pFile, edidFooterEnd);
+
+ if (!ret) {
+ return FALSE;
+ }
- if ((pFile->current[0] == ' ') &&
- (pFile->current[1] == '-') &&
- (pFile->current[2] == '-') &&
- (pFile->current[3] == '-')) {
+ /*
+ * moveFilePointerPastString() will have moved current past the
+ * end of the footer
+ */
- len = pFile->current - begin;
+ len = pFile->current - begin - strlen(edidFooterEnd);
/* make sure the name length seems reasonable */
@@ -878,12 +872,6 @@ static int readEdidFooterforLogFile(FilePtr pFile, EdidPtr pEdid)
pEdid->name[len] = '\0';
return TRUE;
- }
-
- pFile->current++;
- }
-
- return FALSE;
} // readEdidFooterforLogFile()
@@ -895,29 +883,7 @@ static int readEdidFooterforLogFile(FilePtr pFile, EdidPtr pEdid)
static int findEdidfooterforTextFile(FilePtr pFile)
{
- pFile->current = pFile->start;
- while (((pFile->current - pFile->start) + 12) <= pFile->length) {
-
- if ((pFile->current[0] == 'E') &&
- (pFile->current[1] == 'D') &&
- (pFile->current[2] == 'I') &&
- (pFile->current[3] == 'D') &&
- (pFile->current[4] == ' ') &&
- (pFile->current[5] == 'V') &&
- (pFile->current[6] == 'e') &&
- (pFile->current[7] == 'r') &&
- (pFile->current[8] == 's') &&
- (pFile->current[9] == 'i') &&
- (pFile->current[10] == 'o') &&
- (pFile->current[11] == 'n')) {
-
- pFile->current = pFile->start;
- return TRUE;
- }
- pFile->current++;
- }
-
-return FALSE;
+ return moveFilePointerPastString(pFile, "EDID Version");
} // findEdidfooterforTextFile()
@@ -928,31 +894,11 @@ static int readMonitorNameforTextFile(FilePtr pFile, EdidPtr pEdid)
char *begin;
int len;
- while (((pFile->current - pFile->start) + 12) <= pFile->length) {
-
- if ((pFile->current[0] == 'M') &&
- (pFile->current[1] == 'o') &&
- (pFile->current[2] == 'n') &&
- (pFile->current[3] == 'i') &&
- (pFile->current[4] == 't') &&
- (pFile->current[5] == 'o') &&
- (pFile->current[6] == 'r') &&
- (pFile->current[7] == ' ') &&
- (pFile->current[8] == 'N') &&
- (pFile->current[9] == 'a') &&
- (pFile->current[10] == 'm') &&
- (pFile->current[11] == 'e')) {
-
- pFile->current += 12;
- goto next;
- }
-
- pFile->current++;
+ int ret = moveFilePointerPastString(pFile, "Monitor Name");
- }
+ if (!ret) {
return FALSE;
-
- next:
+ }
/* search for start of the expected text */
diff --git a/gen-manpage-opts.c b/gen-manpage-opts.c
index c8d82b1..00d0b9f 100644
--- a/gen-manpage-opts.c
+++ b/gen-manpage-opts.c
@@ -5,145 +5,11 @@
#include <ctype.h>
#include <string.h>
-#include "XF86Config-parser/xf86Parser.h"
-#include "nvidia-xconfig.h"
-#include "nvgetopt.h"
+#include "gen-manpage-opts-helper.h"
#include "option_table.h"
-static void print_option(const NVGetoptOption *o)
+int main(void)
{
- char scratch[64], *s;
- int j, len;
-
- int omitWhiteSpace;
-
- /* if we are going to need the argument, process it now */
- if (o->flags & NVGETOPT_HAS_ARGUMENT) {
- if (o->arg_name) {
- strcpy(scratch, o->arg_name);
- } else {
- len = strlen(o->name);
- for (j = 0; j < len; j++) scratch[j] = toupper(o->name[j]);
- scratch[len] = '\0';
- }
- }
-
- printf(".TP\n.BI \"");
- /* Print the name of the option */
- /* XXX We should backslashify the '-' characters in o->name. */
-
- if (isalpha(o->val)) {
- /* '\-c' */
- printf("\\-%c", o->val);
-
- if (o->flags & NVGETOPT_HAS_ARGUMENT) {
- /* ' " "ARG" "' */
- printf(" \" \"%s\" \"", scratch);
- }
- /* ', ' */
- printf(", ");
- }
-
- /* '\-\-name' */
- printf("\\-\\-%s", o->name);
-
- /* '=" "ARG' */
- if (o->flags & NVGETOPT_HAS_ARGUMENT) {
- printf("=\" \"%s", scratch);
-
- /* '" "' */
- if ((o->flags & NVGETOPT_IS_BOOLEAN) ||
- (o->flags & NVGETOPT_ALLOW_DISABLE)) {
- printf("\" \"");
- }
- }
-
- /* ', \-\-no\-name' */
- if (((o->flags & NVGETOPT_IS_BOOLEAN) &&
- !(o->flags & NVGETOPT_HAS_ARGUMENT)) ||
- (o->flags & NVGETOPT_ALLOW_DISABLE)) {
- printf(", \\-\\-no\\-%s", o->name);
- }
-
- printf("\"\n");
-
- /* Print the option description */
- /* XXX Each sentence should be on its own line! */
-
- /*
- * Print the option description: write each character one at a
- * time (ugh) so that we can special-case a few characters:
- *
- * "[" --> "\n.I "
- * "]" --> "\n"
- * "-" --> "\-"
- *
- * Brackets are used to mark the text inbetween as italics.
- * '-' is special cased so that we can backslashify it.
- *
- * XXX Each sentence should be on its own line!
- */
-
- omitWhiteSpace = 0;
-
- for (s = o->description; s && *s; s++) {
-
- switch (*s) {
- case '[':
- printf("\n.I ");
- omitWhiteSpace = 0;
- break;
- case ']':
- printf("\n");
- omitWhiteSpace = 1;
- break;
- case '-':
- printf("\\-");
- omitWhiteSpace = 0;
- break;
- case ' ':
- if (!omitWhiteSpace) {
- printf("%c", *s);
- }
- break;
- default:
- printf("%c", *s);
- omitWhiteSpace = 0;
- break;
- }
- }
-
- printf("\n");
-}
-
-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 & NVGETOPT_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 & NVGETOPT_HELP_ALWAYS)
- continue;
-
- print_option(o);
- }
-
+ gen_manpage_opts_helper(__options);
return 0;
}
diff --git a/nvidia-xconfig.c b/nvidia-xconfig.c
index 54934cc..afd4cdf 100644
--- a/nvidia-xconfig.c
+++ b/nvidia-xconfig.c
@@ -37,6 +37,8 @@
#define TAB " "
#define BIGTAB " "
+#define ORIG_SUFFIX ".nvidia-xconfig-original"
+#define BACKUP_SUFFIX ".backup"
/*
@@ -79,44 +81,20 @@ static void print_summary(void)
/*
- * cook_description() - the description string may contain text within
- * brackets, which is used by the manpage generator to denote text to
- * be italicized. We want to omit the bracket characters here.
+ * print_help() - loop through the __options[] table, and print the
+ * description of each option.
*/
-static char *cook_description(const char *description)
+static void print_help_helper(const char *name, const char *description)
{
- int len;
- char *s, *dst;
- const char *src;
-
- len = strlen(description);
- s = nvalloc(len + 1);
-
- for (src = description, dst = s; *src; src++) {
- if (*src != '[' && (*src != ']')) {
- *dst = *src;
- dst++;
- }
+ fmtoutp(TAB, name);
+ fmtoutp(BIGTAB, description);
+ fmtout("");
}
- *dst = '\0';
-
- return s;
-
-} /* cook_description() */
-
-
-/*
- * 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[8], arg[64];
- const NVGetoptOption *o;
+ unsigned int include_mask = 0;
print_version();
print_summary();
@@ -125,66 +103,14 @@ static void print_help(int advanced)
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 & NVGETOPT_HELP_ALWAYS)) continue;
-
- /* if we are going to need the argument, process it now */
-
- if (o->flags & NVGETOPT_HAS_ARGUMENT) {
- if (o->arg_name) {
- strcpy(arg, o->arg_name);
- } else {
- len = strlen(o->name);
- for (j = 0; j < len; j++) arg[j] = toupper(o->name[j]);
- arg[len] = '\0';
+ if (!advanced) {
+ /* only print options with the ALWAYS flag */
+ include_mask |= NVGETOPT_HELP_ALWAYS;
}
- }
-
- msg = nvstrcat("--", o->name, NULL);
- if (isalpha(o->val)) {
- sprintf(scratch, "%c", o->val);
-
- if (o->flags & NVGETOPT_HAS_ARGUMENT) {
- tmp = nvstrcat("-", scratch, " ", arg, ", ", msg, NULL);
- } else {
- tmp = nvstrcat("-", scratch, ", ", msg, NULL);
- }
- free(msg);
- msg = tmp;
+ nvgetopt_print_help(__options, include_mask, print_help_helper);
}
- if (o->flags & NVGETOPT_HAS_ARGUMENT) {
- tmp = nvstrcat(msg, "=", arg, NULL);
- free(msg);
- msg = tmp;
- }
- if (((o->flags & NVGETOPT_IS_BOOLEAN) &&
- !(o->flags & NVGETOPT_HAS_ARGUMENT)) ||
- (o->flags & NVGETOPT_ALLOW_DISABLE)) {
- tmp = nvstrcat(msg, ", --no-", o->name, NULL);
- free(msg);
- msg = tmp;
- }
-
- fmtoutp(TAB, msg);
- if (o->description) {
- tmp = cook_description(o->description);
- fmtoutp(BIGTAB, tmp);
- free(tmp);
- }
- fmtout("");
- free(msg);
- }
-} /* print_help() */
-
/*
@@ -227,7 +153,7 @@ static void parse_commandline(Options *op, int argc, char *argv[])
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 's': silence_fmt(1); break;
case 'a': op->enable_all_gpus = TRUE; break;
case '1': op->only_one_screen = TRUE; break;
@@ -751,6 +677,10 @@ static void parse_commandline(Options *op, int argc, char *argv[])
op->nvidia_3dvision_display_type = intval;
break;
+ case RESTORE_ORIGINAL_BACKUP_OPTION:
+ op->restore_original_backup = TRUE;
+ break;
+
default:
goto fail;
}
@@ -816,21 +746,22 @@ static Options *load_default_options(void)
/*
* backup_file() - create a backup of orig_filename, naming the backup
- * file "<original>.backup".
+ * file "<orig_filename>.<suffix>".
*
* 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.
*/
-static int backup_file(Options *op, const char *orig_filename)
+static int backup_file(Options *op, const char *orig_filename,
+ const char *suffix)
{
char *filename;
int ret = FALSE;
/* construct the backup filename */
- filename = nvstrcat(orig_filename, ".backup", NULL);
+ filename = nvstrcat(orig_filename, suffix, NULL);
/* if the backup file already exists, remove it */
@@ -849,7 +780,7 @@ static int backup_file(Options *op, const char *orig_filename)
goto done;
}
- fmtmsg("Backed up file '%s' as '%s'", orig_filename, filename);
+ fmtout("Backed up file '%s' as '%s'", orig_filename, filename);
ret = TRUE;
done:
@@ -863,7 +794,7 @@ static int backup_file(Options *op, const char *orig_filename)
/*
- * write_xconfig() - write the Xconfig to file.
+ * find_xconfig() - search for an X config file.
*
* We search for the filename is this order:
*
@@ -874,14 +805,12 @@ static int backup_file(Options *op, const char *orig_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",.
+ * Otherwise we use "/etc/X11/xorg.conf".
*/
-static int write_xconfig(Options *op, XConfigPtr config)
+static char *find_xconfig(Options *op, XConfigPtr config)
{
char *filename = NULL;
- char *d, *tmp = NULL;
- int ret = FALSE;
/* 1) "--output-xconfig" option */
@@ -891,7 +820,7 @@ static int write_xconfig(Options *op, XConfigPtr config)
/* config->filename */
- if (!filename && config->filename) {
+ if (!filename && config && config->filename) {
filename = nvstrdup(config->filename);
}
@@ -918,6 +847,102 @@ static int write_xconfig(Options *op, XConfigPtr config)
}
}
+ return filename;
+} /* find_xconfig() */
+
+
+/*
+ * restore_backup - search for a backup file with the given suffix;
+ * if one is found, restore it.
+ */
+static int restore_backup(Options *op, XConfigPtr config, const char *suffix)
+{
+ char *filename = find_xconfig(op, config);
+ char *backup = nvstrcat(filename, suffix, NULL);
+ struct stat st;
+ int ret = FALSE;
+
+ if (lstat(backup, &st) != 0) {
+ fmterr("Unable to restore from original backup file '%s' (%s)",
+ backup, strerror(errno));
+ goto done;
+ }
+
+ /*
+ * do not restore files if the permissions might allow a malicious user to
+ * modify the backup, potentially tricking an administrator into restoring
+ * the modified backup.
+ */
+ if (!S_ISREG(st.st_mode) /* non-regular files */ ||
+ st.st_uid != 0 /* not owned by root*/ ||
+ (st.st_gid != 0 && (st.st_mode & S_IWGRP)) /* non-root group write */ ||
+ (st.st_mode & S_IWOTH) /* world writable */ ) {
+ fmterr("The permissions of the original backup file '%s' are too loose "
+ "to be trusted. The file will not be restored.", backup);
+ goto done;
+ }
+
+ /*
+ * if the backup is empty, assume that no original x config file existed
+ * and delete the current X config file.
+ */
+
+ if (st.st_size == 0) {
+ if (unlink(filename) != 0) {
+ fmterr("Unable to remove file '%s' (%s)",
+ filename, strerror(errno));
+ goto done;
+ }
+ } else {
+ /* copy the file */
+
+ if (!copy_file(backup, filename, 0644)) {
+ /* copy_file() prints out its own error messages */
+ goto done;
+ }
+ }
+
+ /* remove backup: a new one is created if nvidia-xconfig is run again */
+
+ if (access(backup, F_OK) == 0) {
+ if (unlink(backup) != 0) {
+ fmterr("Unable to remove backup file '%s' (%s)",
+ backup, strerror(errno));
+ goto done;
+ }
+ }
+
+ if (st.st_size == 0) {
+ fmtout("The backup file '%s' was empty. This usually means that nvidia-"
+ "xconfig did not find an X configuration file the first time it "
+ "was run. The X configuration file '%s' was deleted.",
+ backup, filename);
+ } else {
+ fmtout("Restored backup file '%s' to '%s'", backup, filename);
+ }
+
+ ret = TRUE;
+
+ done:
+
+ free(backup);
+ free(filename);
+
+ return ret;
+} /* restore_backup() */
+
+
+
+/*
+ * write_xconfig() - write the Xconfig to file.
+ */
+
+static int write_xconfig(Options *op, XConfigPtr config, int first_touch)
+{
+ char *filename = find_xconfig(op, config);
+ char *d, *tmp = NULL;
+ int ret = FALSE;
+
/*
* XXX it's strange that lack of permission to write to the target
* location (the likely case with users not having write
@@ -937,10 +962,27 @@ static int write_xconfig(Options *op, XConfigPtr config)
goto done;
}
- /* if the file already exists, create a backup first */
+ /*
+ * if the file already exists, create a backup first. if this is our first
+ * time writing the x config, create a separate "original" backup file.
+ */
if (access(filename, F_OK) == 0) {
- if (!backup_file(op, filename)) goto done;
+ if (first_touch && !backup_file(op, filename, ORIG_SUFFIX)) goto done;
+ if (!backup_file(op, filename, BACKUP_SUFFIX)) goto done;
+ }
+
+ /*
+ * if no file exists, and this is our first time writing the x config, back
+ * up an empty file to use as the "original" backup.
+ */
+
+ else if (first_touch) {
+ char *fakeorig = nvstrcat(filename, ORIG_SUFFIX, NULL);
+ if (!copy_file("/dev/null", fakeorig, 0644)) {
+ fmtwarn("Unable to write an empty backup file \"%s\".", fakeorig);
+ }
+ free(fakeorig);
}
/* write the config file */
@@ -952,8 +994,8 @@ static int write_xconfig(Options *op, XConfigPtr config)
goto done;
}
- fmtmsg("New X configuration file written to '%s'", filename);
- fmtmsg("");
+ fmtout("New X configuration file written to '%s'", filename);
+ fmtout("");
/* Set the default depth in the Solaris Management Facility
@@ -1092,8 +1134,8 @@ static XConfigPtr find_system_xconfig(Options *op)
filename = xconfigOpenConfigFile(op->xconfig, op->gop.x_project_root);
if (filename) {
- fmtmsg("");
- fmtmsg("Using X configuration file: \"%s\".", filename);
+ fmtout("");
+ fmtout("Using X configuration file: \"%s\".", filename);
} else {
fmtwarn("Unable to locate/open X configuration file.");
return NULL;
@@ -1213,6 +1255,7 @@ int main(int argc, char *argv[])
Options *op;
int ret;
XConfigPtr config = NULL;
+ int first_touch = 0;
/* Load defaults */
@@ -1256,6 +1299,13 @@ int main(int argc, char *argv[])
return (ret ? 0 : 1);
}
+ if (op->restore_original_backup) {
+ config = find_system_xconfig(op);
+ xconfigGetXServerInUse(&op->gop);
+ ret = restore_backup(op, config, ORIG_SUFFIX);
+ return (ret ? 0 : 1);
+ }
+
/*
* we want to open and parse the system's existing X config file,
* if possible
@@ -1286,6 +1336,7 @@ int main(int argc, char *argv[])
if (!config) {
config = xconfigGenerate(&op->gop);
+ first_touch = 1;
}
/*
@@ -1298,6 +1349,14 @@ int main(int argc, char *argv[])
return 1;
}
+ /* if a config file existed, check to see if it had an nvidia-xconfig
+ * banner: this would suggest that we've touched this file before.
+ */
+
+ if (!first_touch) {
+ first_touch = (find_banner_prefix(config->comment) == NULL);
+ }
+
/* now, we have a good config; apply whatever the user requested */
update_xconfig(op, config);
@@ -1311,7 +1370,7 @@ int main(int argc, char *argv[])
/* write the config back out to file */
- if (!write_xconfig(op, config)) {
+ if (!write_xconfig(op, config, first_touch)) {
return 1;
}
diff --git a/nvidia-xconfig.h b/nvidia-xconfig.h
index ef55d8d..99402e2 100644
--- a/nvidia-xconfig.h
+++ b/nvidia-xconfig.h
@@ -29,12 +29,6 @@
#include <sys/types.h>
-typedef struct {
- char **t; /* the text rows */
- int n; /* number of rows */
- int m; /* maximum row length */
-} TextRows;
-
/* Boolean options */
#define NOLOGO_BOOL_OPTION 0
@@ -107,7 +101,6 @@ typedef struct __options {
int force_generate;
int tree;
int post_tree;
- int silent;
int keyboard_list;
int mouse_list;
int enable_all_gpus;
@@ -115,6 +108,7 @@ typedef struct __options {
int disable_scf;
int query_gpu_info;
int preserve_driver;
+ int restore_original_backup;
/*
* the option parser will set bits in boolean_options to indicate
@@ -208,24 +202,8 @@ int copy_file(const char *srcfile, const char *dstfile, mode_t mode);
int directory_exists(const char *dir);
-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);
diff --git a/option_table.h b/option_table.h
index fa247da..e2e627d 100644
--- a/option_table.h
+++ b/option_table.h
@@ -10,6 +10,8 @@
* description - text for use by print_help() to describe the option
*/
+#include "nvidia-xconfig.h"
+
#define SCREEN_OPTION 1
#define LAYOUT_OPTION 2
#define X_PREFIX_OPTION 3
@@ -56,6 +58,8 @@
#define NVIDIA_3DVISION_USB_PATH_OPTION 45
#define NVIDIA_3DVISIONPRO_CONFIG_FILE_OPTION 46
#define NVIDIA_3DVISION_DISPLAY_TYPE_OPTION 47
+/* skip 48-57, as these are '0' - '9' */
+#define RESTORE_ORIGINAL_BACKUP_OPTION 58
/*
* To add a boolean option to nvidia-xconfig:
@@ -95,13 +99,13 @@ static const NVGetoptOption __options[] = {
/* These options are printed by "nvidia-xconfig --help" */
{ "xconfig", 'c', NVGETOPT_STRING_ARGUMENT | NVGETOPT_HELP_ALWAYS, NULL,
- "Use [XCONFIG] as the input X config file; if this option is not "
+ "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_STRING_ARGUMENT | NVGETOPT_HELP_ALWAYS, NULL,
- "Use [OUTPUT-XCONFIG] as the output X configuration file; if this "
+ "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 X configuration filename." },
@@ -213,13 +217,13 @@ static const NVGetoptOption __options[] = {
"to use an 8 bit (LUT)." },
{ "depth", 'd', NVGETOPT_INTEGER_ARGUMENT, NULL,
- "Set the default depth to [DEPTH]; valid values for [DEPTH] are "
+ "Set the default depth to &DEPTH&; valid values for &DEPTH& are "
"8, 15, 16, 24, and 30." },
{ "device", DEVICE_OPTION, NVGETOPT_STRING_ARGUMENT, NULL,
"The nvidia-xconfig utility operates on one or more devices in "
"the X configuration file. If this option is specified, the "
- "device named [DEVICE] in the X configuration file will be "
+ "device named &DEVICE& in the X configuration file will be "
"used. If this option is not specified, all the devices within "
"the X configuration file will be used." },
@@ -273,7 +277,7 @@ static const NVGetoptOption __options[] = {
{ "extract-edids-from-file", 'E', NVGETOPT_STRING_ARGUMENT, "FILE",
"Extract any raw EDID byte blocks contained in the specified X "
- "log file [LOG]; raw EDID bytes are printed by the NVIDIA X driver to "
+ "log file &LOG&; raw EDID bytes are printed by the NVIDIA X driver to "
"the X log as hexidecimal when verbose logging is enabled with the "
"\"-logverbose 6\" X server commandline option. Any extracted EDIDs "
"are then written as binary data to individual files. These files "
@@ -291,8 +295,8 @@ static const NVGetoptOption __options[] = {
{ "flatpanel-properties", FLATPANEL_PROPERTIES_OPTION,
NVGETOPT_STRING_ARGUMENT | NVGETOPT_ALLOW_DISABLE, NULL,
- "Set the flat panel properties. The supported properties are: "
- "'scaling', 'dithering' & 'ditheringmode'. Please see the NVIDIA "
+ "Set the flat panel properties. The supported properties are "
+ "'scaling', 'dithering' and 'ditheringmode'. Please see the NVIDIA "
"README 'Appendix B. X Config Options' for more details on the "
"possible values and syntax." },
@@ -318,7 +322,7 @@ static const NVGetoptOption __options[] = {
NVGETOPT_STRING_ARGUMENT | NVGETOPT_ALLOW_DISABLE, "WHEN",
"Specify when the X server should use the builtin keyboard handler to "
"process special key combinations (such as Ctrl+Alt+Backspace); see "
- "the X configuration man page for details. The value of [WHEN] can be "
+ "the X configuration man page for details. The value of &WHEN& can be "
"'Always', 'Never', or 'WhenNeeded'." },
{ "include-implicit-metamodes",
@@ -330,7 +334,7 @@ static const NVGetoptOption __options[] = {
{ "keyboard", KEYBOARD_OPTION, NVGETOPT_STRING_ARGUMENT, NULL,
"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 "
+ "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." },
@@ -350,7 +354,7 @@ static const NVGetoptOption __options[] = {
{ "layout", LAYOUT_OPTION, NVGETOPT_STRING_ARGUMENT, NULL,
"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 "
+ "&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." },
@@ -375,20 +379,20 @@ static const NVGetoptOption __options[] = {
{ "mode-list", MODE_LIST_OPTION, NVGETOPT_STRING_ARGUMENT, "MODELIST",
"Remove all existing modes from the X configuration's modelist and "
- "add the one(s) specified in the [MODELIST] string." },
+ "add the one(s) specified in the &MODELIST& string." },
{ "remove-mode", REMOVE_MODE_OPTION, NVGETOPT_STRING_ARGUMENT, "MODE",
"Remove the specified mode from the mode list." },
{ "metamodes", META_MODES_OPTION, NVGETOPT_STRING_ARGUMENT, "METAMODES",
- "Add the MetaMode X configuration option with the value [METAMODES] "
+ "Add the MetaMode X configuration option with the value &METAMODES& "
"which will replace any existing MetaMode option already in the X "
"configuration file." },
{ "mouse", MOUSE_OPTION, NVGETOPT_STRING_ARGUMENT, NULL,
"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 "
+ "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." },
@@ -398,8 +402,8 @@ static const NVGetoptOption __options[] = {
{ "multigpu", MULTI_GPU_OPTION,
NVGETOPT_STRING_ARGUMENT | NVGETOPT_ALLOW_DISABLE, NULL,
- "Enable or disable MultiGPU. Valid values for [MULTIGPU] are 'Off', 'On',"
- " 'Auto', 'AFR', 'SFR', 'AA'." },
+ "Enable or disable MultiGPU. Valid values for &MULTIGPU& are "
+ "'Off', 'On', 'Auto', 'AFR', 'SFR', 'AA'." },
{ "multisample-compatibility",
XCONFIG_BOOL_VAL(MULTISAMPLE_COMPATIBILITY_BOOL_OPTION),
@@ -443,7 +447,7 @@ static const NVGetoptOption __options[] = {
{ "transparent-index", TRANSPARENT_INDEX_OPTION,
NVGETOPT_INTEGER_ARGUMENT | NVGETOPT_ALLOW_DISABLE, "INDEX",
"Pixel to use as transparent when using color index overlays. "
- "Valid values for [TRANSPARENT-INDEX] are 0-255."},
+ "Valid values for &TRANSPARENT-INDEX& are 0-255."},
{ "post-tree", 'T', 0, NULL,
"Like the '--tree' option, but goes through the full process of "
@@ -485,13 +489,13 @@ static const NVGetoptOption __options[] = {
{ "rotate",
ROTATE_OPTION, NVGETOPT_STRING_ARGUMENT | NVGETOPT_ALLOW_DISABLE, NULL,
"Enable or disable the \"Rotate\" X configuration option. Valid values "
- "for [ROTATE] are 'normal', 'left', 'CCW', 'inverted', "
+ "for &ROTATE& are 'normal', 'left', 'CCW', 'inverted', "
"'right', and 'CW'. Rotation can be disabled " },
{ "screen", SCREEN_OPTION, NVGETOPT_STRING_ARGUMENT, NULL,
"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 "
+ "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." },
@@ -510,12 +514,12 @@ static const NVGetoptOption __options[] = {
{ "sli", SLI_OPTION,
NVGETOPT_STRING_ARGUMENT | NVGETOPT_ALLOW_DISABLE, NULL,
- "Enable or disable SLI. Valid values for [SLI] are 'Off', 'On', 'Auto', "
+ "Enable or disable SLI. Valid values for &SLI& are 'Off', 'On', 'Auto', "
"'AFR', 'SFR', 'AA', 'AFRofAA', 'Mosaic'." },
{ "stereo", STEREO_OPTION,
NVGETOPT_INTEGER_ARGUMENT | NVGETOPT_ALLOW_DISABLE, NULL,
- "Enable or disable the stereo mode. Valid values for [STEREO] are: 0 "
+ "Enable or disable the stereo mode. Valid values for &STEREO& are: 0 "
"(Disabled), 1 (DDC glasses), 2 (Blueline glasses), 3 (Onboard stereo), "
"4 (TwinView clone mode stereo), 5 (SeeReal digital flat panel), 6 "
"(Sharp3D digital flat panel), 7 (Arisawa/Hyundai/Zalman/Pavione/Miracube), "
@@ -551,7 +555,7 @@ static const NVGetoptOption __options[] = {
{ "twinview-orientation", TWINVIEW_ORIENTATION_OPTION,
NVGETOPT_STRING_ARGUMENT | NVGETOPT_ALLOW_DISABLE, "ORIENTATION",
- "Specify the TwinViewOrientation. Valid values for [ORIENTATION] are: "
+ "Specify the TwinViewOrientation. Valid values for &ORIENTATION& are: "
"\"RightOf\" (the default), \"LeftOf\", \"Above\", \"Below\", or "
"\"Clone\"." },
@@ -564,7 +568,7 @@ static const NVGetoptOption __options[] = {
TWINVIEW_XINERAMA_INFO_ORDER_OPTION,
NVGETOPT_STRING_ARGUMENT | NVGETOPT_ALLOW_DISABLE, NULL,
"Enable or disable the \"TwinViewXineramaInfoOrder\" X configuration "
- "option. [TWINVIEW-XINERAMA-INFO-ORDER] is a comma-separated list "
+ "option. &TWINVIEW-XINERAMA-INFO-ORDER& is a comma-separated list "
"of display device names that describe the order in which "
"TwinViewXineramaInfo should be reported. E.g., \"CRT, DFP, TV\"." },
@@ -667,5 +671,15 @@ static const NVGetoptOption __options[] = {
XCONFIG_BOOL_VAL(BASE_MOSAIC_BOOL_OPTION), NVGETOPT_IS_BOOLEAN, NULL,
"Enable or disable the \"BaseMosaic\" X configuration option." },
+ { "restore-original-backup", RESTORE_ORIGINAL_BACKUP_OPTION, 0, NULL,
+ "Restore a backup of the X configuration that was made before any "
+ "changes were made by nvidia-xconfig, if such a backup is available. "
+ "This type of backup is made by nvidia-xconfig before it modifies an "
+ "X configuration file that it has not previously touched; this is "
+ "assumed to be an X configuration file that predates the involvement "
+ "of the NVIDIA X driver. As an example, nvidia-xconfig will copy an "
+ "X configuration file at /etc/X11/xorg.conf to /etc/X11/xorg.conf."
+ "nvidia-xconfig-original the first time it makes changes to that file."},
+
{ NULL, 0, 0, NULL, NULL },
};
diff --git a/options.c b/options.c
index 89a29dd..998b0fb 100644
--- a/options.c
+++ b/options.c
@@ -563,7 +563,7 @@ void update_options(Options *op, XConfigScreenPtr screen)
}
set_option_value(screen, o->name, val);
- fmtmsg("Option \"%s\" \"%s\" added to "
+ fmtout("Option \"%s\" \"%s\" added to "
"Screen \"%s\".", o->name, val, screen->identifier);
}
}
@@ -672,7 +672,6 @@ void update_options(Options *op, XConfigScreenPtr screen)
op->twinview_orientation);
if (remove_metamode_offsets(screen,
&old_metamodes, &new_metamodes)) {
- fmtmsg("");
fmtwarn("The MetaModes option contained explicit offsets, "
"which would have overridden the specified "
"TwinViewOrientation; in order to honor the "
@@ -681,7 +680,6 @@ void update_options(Options *op, XConfigScreenPtr screen)
"Old MetaModes option: \"%s\"\n"
"New MetaModes option: \"%s\".",
old_metamodes, new_metamodes);
- fmtmsg("");
nvfree(old_metamodes);
nvfree(new_metamodes);
}
diff --git a/query_gpu_info.c b/query_gpu_info.c
index 762c05f..3caf7a7 100644
--- a/query_gpu_info.c
+++ b/query_gpu_info.c
@@ -26,8 +26,6 @@
static char *display_device_mask_to_display_device_name(unsigned int mask);
-#define TAB " "
-#define BIGTAB " "
#define BUS_ID_STRING_LENGTH 32
diff --git a/util.c b/util.c
index db9b0bc..63adfb2 100644
--- a/util.c
+++ b/util.c
@@ -42,54 +42,6 @@
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); \
- } \
-}
-
/*
* copy_file() - copy the file specified by srcfile to dstfile, using
@@ -230,256 +182,13 @@ void xconfigPrint(MsgType t, const char *msg)
}
}
- if (newline) vformat(stream, NULL, "");
- vformat(stream, prefix, msg);
- if (newline) vformat(stream, NULL, "");
+ if (newline) fmt(stream, NULL, "");
+ fmt(stream, prefix, msg);
+ if (newline) fmt(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
@@ -532,87 +241,3 @@ char *fget_next_line(FILE *fp, int *eof)
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);
-}
-
diff --git a/utils.mk b/utils.mk
index 32014a3..2a7a9cf 100644
--- a/utils.mk
+++ b/utils.mk
@@ -28,9 +28,10 @@
CC ?= gcc
LD ?= ld
-CFLAGS ?=
-CFLAGS += -Wall -fno-strict-aliasing -Wno-unused-parameter
-CFLAGS += -O2 -fno-omit-frame-pointer
+# only set these warnings and optimizations if CFLAGS is unset
+CFLAGS ?= -Wall -Wno-unused-parameter -O2
+# always set these -f CFLAGS
+CFLAGS += -fno-strict-aliasing -fno-omit-frame-pointer
CC_ONLY_CFLAGS ?=
LDFLAGS ?=
BIN_LDFLAGS ?=
@@ -93,9 +94,9 @@ ifndef TARGET_ARCH
endif
ifeq ($(TARGET_OS),Linux)
- LIBDL_LDFLAGS = -ldl
+ LIBDL_LIBS = -ldl
else
- LIBDL_LDFLAGS =
+ LIBDL_LIBS =
endif
OUTPUTDIR ?= _out/$(TARGET_OS)_$(TARGET_ARCH)
@@ -124,11 +125,10 @@ endif
# the source tarball
##############################################################################
-prefix = /usr/local
+PREFIX ?= /usr/local
-exec_prefix = $(prefix)
-bindir = $(exec_prefix)/bin
-mandir = $(exec_prefix)/share/man/man1
+BINDIR = $(DESTDIR)$(PREFIX)/bin
+MANDIR = $(DESTDIR)$(PREFIX)/share/man/man1
##############################################################################
@@ -145,10 +145,16 @@ default build: all
# version.mk may be in one of two places: either in $(OUTPUTDIR) when
# building as part of the NVIDIA driver build, or directly in the
# source directory when building from the source tarball
+#
+# Throw an error if one of these two places did not define NVIDIA_VERSION.
##############################################################################
-include $(wildcard $(OUTPUTDIR)/version.mk version.mk)
+VERSION_MK := $(wildcard $(OUTPUTDIR)/version.mk version.mk)
+include $(VERSION_MK)
+ifndef NVIDIA_VERSION
+$(error NVIDIA_VERSION undefined)
+endif
##############################################################################
# to generate the dependency files, use the compiler's "-MM" option to
@@ -260,7 +266,7 @@ BUILD_DEPENDENCY_LIST = \
define DEFINE_OBJECT_RULE_WITH_OBJECT_NAME
$(3): $(2)
@$(MKDIR) $(OUTPUTDIR)
- $$(call quiet_cmd,$(1)) -c $$< -o $$@ $$(CFLAGS) \
+ $$(call quiet_cmd,$(1)) $$(CFLAGS) -c $$< -o $$@ \
$(call AUTO_DEP_CMD,$(1),$(2),$(3))
-include $$(call BUILD_DEPENDENCY_LIST,$(3))
@@ -298,7 +304,7 @@ define DEFINE_STAMP_C_RULE
$$(STAMP_C): $$(filter-out \
$$(call BUILD_OBJECT_LIST,$$(STAMP_C)),$(1)) \
- $$(wildcard version.mk $$(OUTPUTDIR)/version.mk)
+ $$(VERSION_MK)
@ $$(RM) $$@
@ $$(PRINTF) "const char NV_ID[] = \"nvidia id: " >> $$@
@ $$(PRINTF) "$(2): " >> $$@
diff --git a/version.mk b/version.mk
index 11eb84d..c29a7ba 100644
--- a/version.mk
+++ b/version.mk
@@ -1 +1 @@
-NVIDIA_VERSION = 295.40
+NVIDIA_VERSION = 302.07