forked from pool/transfig
1837 lines
55 KiB
Diff
1837 lines
55 KiB
Diff
Based on 41b9bb838a3d544539f6e68aa4f87d70ef7d45ce Mon Sep 17 00:00:00 2001
|
||
From: Thomas Loimer <thomas.loimer@tuwien.ac.at>
|
||
Date: Sun, 5 Jan 2020 19:22:12 +0100
|
||
Subject: [PATCH] Replace most calls to fgets() by getline() in read.c
|
||
|
||
Also, fig files version 1.4 must begin with `#FIG 1.4`. Previously, a `#` in the
|
||
first line was sufficient to detect at least a version 1.4 fig file.
|
||
Move some variables with file scope into functions.
|
||
|
||
This commit fixes tickets #58, #59, #61, #62, #67, #78 and #79.
|
||
|
||
In fig2dev/lib/, replacements are provided for some library functions used in
|
||
fig2dev, e.g., strncasecmp(), strrchr(), etc. The getline() function was
|
||
introduced more recently than any of the functions provided in fig2dev/lib.
|
||
Nevertheless, for getline() a replacement function is not provided. It seems,
|
||
that all the replacement functions do not work, but nobody noticed. Therefore,
|
||
only provide a replacement function for getline() if that turns out to
|
||
be useful.
|
||
The replacement functions do not work, because a header file providing the
|
||
necessary function declarations is missing.
|
||
---
|
||
configure.ac | 1
|
||
fig2dev/fig2dev.c | 4
|
||
fig2dev/fig2dev.h | 4
|
||
fig2dev/read.c | 908 +++++++++++++++++++++++++++-----------------------
|
||
fig2dev/read1_3.c | 12
|
||
fig2dev/tests/read.at | 29 +
|
||
6 files changed, 534 insertions(+), 424 deletions(-)
|
||
|
||
--- configure.ac
|
||
+++ configure.ac 2020-01-21 11:31:32.048794834 +0000
|
||
@@ -327,6 +327,7 @@ dnl Just provide our own pi
|
||
# example.
|
||
AC_HEADER_STDBOOL
|
||
AC_TYPE_SIZE_T
|
||
+AC_TYPE_SSIZE_T
|
||
|
||
#
|
||
# Checks for library functions.
|
||
--- fig2dev/fig2dev.c
|
||
+++ fig2dev/fig2dev.c 2020-01-21 11:31:32.048794834 +0000
|
||
@@ -3,7 +3,7 @@
|
||
* Copyright (c) 1991 by Micah Beck
|
||
* Parts Copyright (c) 1985-1988 by Supoj Sutanthavibul
|
||
* Parts Copyright (c) 1989-2015 by Brian V. Smith
|
||
- * Parts Copyright (c) 2015-2019 by Thomas Loimer
|
||
+ * Parts Copyright (c) 2015-2020 by Thomas Loimer
|
||
*
|
||
* Any party obtaining a copy of these files is granted, free of charge, a
|
||
* full and unrestricted irrevocable, world-wide, paid up, royalty-free,
|
||
@@ -81,7 +81,7 @@ bool bgspec = false; /* flag to say -g
|
||
bool support_i18n = false;
|
||
#endif
|
||
char gif_transparent[20]="\0"; /* GIF transp color hex name (e.g. #ff00dd) */
|
||
-char papersize[20]; /* paper size */
|
||
+char papersize[]; /* paper size */
|
||
char boundingbox[64]; /* boundingbox */
|
||
char lang[40]; /* selected output language */
|
||
RGB background; /* background (if specified by -g) */
|
||
--- fig2dev/fig2dev.h
|
||
+++ fig2dev/fig2dev.h 2020-01-21 11:31:32.048794834 +0000
|
||
@@ -3,7 +3,7 @@
|
||
* Copyright (c) 1991 by Micah Beck
|
||
* Parts Copyright (c) 1985-1988 by Supoj Sutanthavibul
|
||
* Parts Copyright (c) 1989-2015 by Brian V. Smith
|
||
- * Parts Copyright (c) 2015-2019 by Thomas Loimer
|
||
+ * Parts Copyright (c) 2015-2020 by Thomas Loimer
|
||
*
|
||
* Any party obtaining a copy of these files is granted, free of charge, a
|
||
* full and unrestricted irrevocable, world-wide, paid up, royalty-free,
|
||
@@ -101,7 +101,7 @@ extern bool bgspec; /* flag to say -g w
|
||
extern bool support_i18n;
|
||
#endif
|
||
extern char gif_transparent[];/* GIF transp color hex name (e.g. #ff00dd) */
|
||
-extern char papersize[]; /* paper size */
|
||
+extern char papersize[16]; /* paper size */
|
||
extern char boundingbox[]; /* boundingbox */
|
||
extern char lang[]; /* selected output language */
|
||
extern const char *Fig_color_names[]; /* hex names for Fig colors */
|
||
--- fig2dev/read.c
|
||
+++ fig2dev/read.c 2020-01-21 11:31:32.048794834 +0000
|
||
@@ -3,7 +3,7 @@
|
||
* Copyright (c) 1991 by Micah Beck
|
||
* Parts Copyright (c) 1985-1988 by Supoj Sutanthavibul
|
||
* Parts Copyright (c) 1989-2015 by Brian V. Smith
|
||
- * Parts Copyright (c) 2015-2019 by Thomas Loimer
|
||
+ * Parts Copyright (c) 2015-2020 by Thomas Loimer
|
||
*
|
||
* Any party obtaining a copy of these files is granted, free of charge, a
|
||
* full and unrestricted irrevocable, world-wide, paid up, royalty-free,
|
||
@@ -45,28 +45,34 @@ extern F_arrow *make_arrow(int type, int
|
||
User_color user_colors[MAX_USR_COLS]; /* fig2dev.h */
|
||
int user_col_indx[MAX_USR_COLS]; /* fig2dev.h */
|
||
int num_usr_cols; /* fig2dev.h */
|
||
-int num_object; /* read1_3.c */
|
||
/* flags, psfonts.h, genps.c */
|
||
int v2_flag; /* Protocol V2.0 or higher */
|
||
int v21_flag; /* Protocol V2.1 or higher */
|
||
int v30_flag; /* Protocol V3.0 or higher */
|
||
int v32_flag; /* Protocol V3.2 or higher */
|
||
|
||
-static void read_colordef(void);
|
||
-static F_ellipse *read_ellipseobject(void);
|
||
-static F_line *read_lineobject(FILE *fp);
|
||
-static F_text *read_textobject(FILE *fp);
|
||
-static F_spline *read_splineobject(FILE *fp);
|
||
-static F_arc *read_arcobject(FILE *fp);
|
||
-static F_compound *read_compoundobject(FILE *fp);
|
||
+static void read_colordef(char *line, int line_no);
|
||
+static F_ellipse *read_ellipseobject(char *line, int line_no);
|
||
+static F_line *read_lineobject(FILE *fp, char **restrict line,
|
||
+ size_t *line_len, int *line_no);
|
||
+static F_text *read_textobject(FILE *fp, char **restrict line,
|
||
+ size_t *line_len, int *line_no);
|
||
+static F_spline *read_splineobject(FILE *fp, char **restrict line,
|
||
+ size_t *line_len, int *line_no);
|
||
+static F_arc *read_arcobject(FILE *fp, char **restrict line,
|
||
+ size_t *line_len, int *line_no);
|
||
+static F_compound *read_compoundobject(FILE *fp, char **restrict line,
|
||
+ size_t *line_len, int *line_no);
|
||
static F_comment *attach_comments(void);
|
||
-static void count_lines_correctly(FILE *fp);
|
||
-static void init_pats_used(void);
|
||
-static int read_objects(FILE *fp, F_compound *obj);
|
||
-static int get_line(FILE *fp);
|
||
-static void skip_line(FILE *fp);
|
||
-static int backslash_count(char cp[], int start);
|
||
-static int save_comment(void);
|
||
+static void count_lines_correctly(FILE *fp, int *line_no);
|
||
+static void init_pats_used(void);
|
||
+static int read_objects(FILE *fp, F_compound *obj);
|
||
+static ssize_t get_line(FILE *fp, char **restrict line,
|
||
+ size_t *line_len, int *line_no);
|
||
+static void skip_line(FILE *fp);
|
||
+static ptrdiff_t backslash_count(const char *restrict cp,
|
||
+ ptrdiff_t start);
|
||
+
|
||
static char Err_incomp[] = "Incomplete %s object at line %d.";
|
||
static char Err_invalid[] = "Invalid %s object at line %d.";
|
||
static char Err_arrow[] = "Invalid %s arrow at line %d.";
|
||
@@ -77,9 +83,6 @@ static char Err_arrow[] = "Invalid %s ar
|
||
/* max number of comments that can be stored with each object */
|
||
#define MAXCOMMENTS 100
|
||
|
||
-static int gif_colnum = 0;
|
||
-static char buf[BUFSIZ];
|
||
-static int line_no = 0;
|
||
static char *comments[MAXCOMMENTS]; /* comments saved for current object */
|
||
static int numcom; /* current comment index */
|
||
static bool com_alloc = false; /* whether or not the comment array
|
||
@@ -148,7 +151,6 @@ readfp_fig(FILE *fp, F_compound *obj)
|
||
char c;
|
||
int i, status;
|
||
|
||
- num_object = 0;
|
||
num_usr_cols = 0;
|
||
init_pats_used();
|
||
|
||
@@ -157,15 +159,14 @@ readfp_fig(FILE *fp, F_compound *obj)
|
||
/* initialize the comment array */
|
||
if (!com_alloc)
|
||
for (i = 0; i < MAXCOMMENTS; ++i)
|
||
- comments[i] = (char *) NULL;
|
||
+ comments[i] = (char *)NULL;
|
||
com_alloc = true;
|
||
- memset((char*)obj, '\0', COMOBJ_SIZE);
|
||
+ memset((void *)obj, '\0', COMOBJ_SIZE);
|
||
|
||
/* read first character to see if it is "#" (#FIG 1.4 and newer) */
|
||
c = fgetc(fp);
|
||
if (feof(fp))
|
||
return -2;
|
||
- memset((char*)obj, '\0', COMOBJ_SIZE);
|
||
/* put the character back */
|
||
ungetc(c, fp);
|
||
if (c == '#')
|
||
@@ -185,25 +186,30 @@ read_objects(FILE *fp, F_compound *obj)
|
||
F_spline *s, *ls = NULL;
|
||
F_arc *a, *la = NULL;
|
||
F_compound *c, *lc = NULL;
|
||
- int object, coord_sys, len;
|
||
-
|
||
- memset((char*)obj, '\0', COMOBJ_SIZE);
|
||
-
|
||
- (void) fgets(buf, BUFSIZ, fp); /* get the version line */
|
||
- if (strncmp(buf, "#FIG ", 5)) {
|
||
- put_msg("Incorrect format string in first line of input file.");
|
||
+ bool objects = false;
|
||
+ int object, coord_sys;
|
||
+ int line_no;
|
||
+ int gif_colnum = 0;
|
||
+ char *line;
|
||
+ char buf[16];
|
||
+ size_t line_len = 256;
|
||
+
|
||
+ /* Get the 15 chars of the first line.
|
||
+ Use fgets(), because get_line() would store the line as a comment */
|
||
+ if (fgets(buf, sizeof buf, fp) == NULL) {
|
||
+ put_msg("Could not read input file.");
|
||
return -1;
|
||
}
|
||
+ /* seek to the end of the first line */
|
||
+ if (strchr(buf, '\n') == NULL) {
|
||
+ int c;
|
||
+ do
|
||
+ c = fgetc(fp);
|
||
+ while (c != '\n' && c != EOF);
|
||
+ }
|
||
|
||
- /* remove newline and any carriage return (from a PC, perhaps) */
|
||
- len = strlen(buf);
|
||
- if (buf[len-1] == '\n') {
|
||
- if (buf[len-2] == '\r')
|
||
- buf[len-2] = '\0';
|
||
- else
|
||
- buf[len-1] = '\0';
|
||
- } else { /* fgets() only stops at newline and end-of-file */
|
||
- put_msg("File is truncated at first line.");
|
||
+ if (strncmp(buf, "#FIG ", 5)) {
|
||
+ put_msg("Incorrect format string in first line of input file.");
|
||
return -1;
|
||
}
|
||
|
||
@@ -211,49 +217,65 @@ read_objects(FILE *fp, F_compound *obj)
|
||
v2_flag = (!strncmp(buf, "#FIG 2", 6) || !strncmp(buf, "#FIG 3", 6));
|
||
/* v21_flag is for version 2.1 or higher */
|
||
v21_flag = (!strncmp(buf, "#FIG 2.1", 8) || !strncmp(buf, "#FIG 3", 6));
|
||
- /* version 2.2 was only beta - 3.0 is the official release (they are identical) */
|
||
+ /* version 2.2 was only beta - 3.0 is the official release
|
||
+ (they are identical) */
|
||
v30_flag = (!strncmp(buf, "#FIG 3", 6) || !strncmp(buf, "#FIG 2.2", 8));
|
||
- /* version 3.2 contains paper size, magnif, multiple page and transparent color
|
||
- in Fig file */
|
||
+ /* version 3.2 contains paper size, magnif, multiple page
|
||
+ and transparent color in Fig file */
|
||
v32_flag = (!strncmp(buf, "#FIG 3.2", 8));
|
||
if (strncmp(&buf[5], PACKAGE_VERSION, 3) > 0) {
|
||
- put_msg("Fig file format (%s) newer than this version of fig2dev (%s), exiting",
|
||
- &buf[5], PACKAGE_VERSION);
|
||
- exit(1);
|
||
+ put_msg("Fig file format (%s) newer than this version of fig2dev (%s), exiting",
|
||
+ &buf[5], PACKAGE_VERSION);
|
||
+ exit(EXIT_FAILURE);
|
||
+ }
|
||
+
|
||
+ if ((v2_flag | v21_flag | v30_flag | v32_flag) == 0 &&
|
||
+ strncmp(buf, "#FIG 1.4", 8)) {
|
||
+ put_msg("Cannot determine fig file format from string '%s'.",
|
||
+ &buf[5]);
|
||
+ exit(EXIT_FAILURE);
|
||
+ }
|
||
+
|
||
+ if ((line = malloc(line_len)) == NULL) {
|
||
+ put_msg(Err_mem);
|
||
+ return -1;
|
||
}
|
||
|
||
+ line_no = 1;
|
||
if (v30_flag) {
|
||
/* read the orientation spec (landscape/portrait) */
|
||
- line_no=1;
|
||
- if (get_line(fp) < 0) {
|
||
+ if (get_line(fp, &line, &line_len, &line_no) < 0) {
|
||
put_msg("File is truncated at landscape/portrait specification.");
|
||
+ free(line);
|
||
return -1;
|
||
}
|
||
/* but set only if the user didn't specify the orientation
|
||
on the command line */
|
||
if (!orientspec)
|
||
- landscape = !strncasecmp(buf,"land",4);
|
||
+ landscape = !strncasecmp(line, "land", 4);
|
||
|
||
/* now read the metric/inches spec OR centering spec */
|
||
- if (get_line(fp) < 0) {
|
||
+ if (get_line(fp, &line, &line_len, &line_no) < 0) {
|
||
put_msg("File is truncated at metric/inches or centering specification.");
|
||
+ free(line);
|
||
return -1;
|
||
}
|
||
/* read justification spec */
|
||
- if ((strncasecmp(buf,"center",6) == 0) ||
|
||
- (strncasecmp(buf,"flush",5) == 0)) {
|
||
+ if ((strncasecmp(line, "center", 6) == 0) ||
|
||
+ (strncasecmp(line, "flush", 5) == 0)) {
|
||
/* but set only if user didn't specify it */
|
||
if (!centerspec)
|
||
- center = strncasecmp(buf,"flush",5);
|
||
+ center = strncasecmp(line, "flush", 5);
|
||
/* now read metric/inches spec */
|
||
- if (get_line(fp) < 0) {
|
||
+ if (get_line(fp, &line, &line_len, &line_no) < 0) {
|
||
put_msg("File is truncated at metric/inches specification.");
|
||
+ free(line);
|
||
return -1;
|
||
}
|
||
}
|
||
/* read metric/inches spec */
|
||
/* if metric, scale magnification to correct for xfig display error */
|
||
- if (strncasecmp(buf,"metric", 6) == 0) {
|
||
+ if (strncasecmp(line, "metric", 6) == 0) {
|
||
metric = 1;
|
||
} else {
|
||
metric = 0;
|
||
@@ -261,56 +283,67 @@ read_objects(FILE *fp, F_compound *obj)
|
||
|
||
/* new stuff in 3.2 */
|
||
if (v32_flag) {
|
||
- char *p;
|
||
/* read the paper size */
|
||
- if (get_line(fp) < 0) {
|
||
+ if (get_line(fp, &line, &line_len, &line_no) < 0) {
|
||
put_msg("File is truncated at paper size specification.");
|
||
+ free(line);
|
||
return -1;
|
||
}
|
||
if (!paperspec) {
|
||
- strcpy(papersize,buf);
|
||
- /* and truncate at first blank, if any */
|
||
- if ((p=strchr(papersize,' ')))
|
||
+ char *p;
|
||
+ /* truncate at first blank, if any */
|
||
+ if ((p = strchr(line, ' ')))
|
||
*p = '\0';
|
||
+ if (strlen(line) + 1 > sizeof papersize) {
|
||
+ put_msg("Invalid paper size specification at line %d: %s",
|
||
+ line_no, line);
|
||
+ free(line);
|
||
+ return -1;
|
||
+ }
|
||
+ strcpy(papersize, line);
|
||
}
|
||
|
||
/* read the magnification */
|
||
- if (get_line(fp) < 0) {
|
||
+ if (get_line(fp, &line, &line_len, &line_no) < 0) {
|
||
put_msg("File is truncated at magnification specification.");
|
||
+ free(line);
|
||
return -1;
|
||
}
|
||
- /* if the users hasn't specified a magnification on the command line,
|
||
- use the one in the file */
|
||
+ /* if the users hasn't specified a magnification on
|
||
+ the command line, use the one in the file */
|
||
if (!magspec) {
|
||
- mag = atof(buf)/100.0;
|
||
+ mag = atof(line)/100.0;
|
||
if (mag <= 0.)
|
||
mag = 1.;
|
||
fontmag = mag;
|
||
}
|
||
|
||
/* read the multiple page flag */
|
||
- if (get_line(fp) < 0) {
|
||
+ if (get_line(fp, &line, &line_len, &line_no) < 0) {
|
||
put_msg("File is truncated at multiple page specification.");
|
||
+ free(line);
|
||
return -1;
|
||
}
|
||
if (!multispec)
|
||
- multi_page = (strncasecmp(buf,"multiple",8) == 0);
|
||
+ multi_page = (strncasecmp(line, "multiple", 8) == 0);
|
||
|
||
/* Read the GIF transparent color. */
|
||
- if (get_line(fp) < 0) {
|
||
+ if (get_line(fp, &line, &line_len, &line_no) < 0) {
|
||
put_msg("File is truncated at transparent color specification.");
|
||
+ free(line);
|
||
return -1;
|
||
}
|
||
if (!transspec) {
|
||
- gif_colnum = atoi(buf);
|
||
+ gif_colnum = atoi(line);
|
||
if (gif_colnum < -3) {
|
||
put_msg("Invalid color number for transparent color.");
|
||
+ free(line);
|
||
return -1;
|
||
}
|
||
/* if standard color, get the name from the array */
|
||
/* for user colors, wait till we've read in the file to get the value */
|
||
if (gif_colnum < NUM_STD_COLS && gif_colnum >= 0)
|
||
- strcpy(gif_transparent,Fig_color_names[gif_colnum]);
|
||
+ strcpy(gif_transparent, Fig_color_names[gif_colnum]);
|
||
}
|
||
}
|
||
} else {
|
||
@@ -329,17 +362,20 @@ read_objects(FILE *fp, F_compound *obj)
|
||
}
|
||
|
||
/* now read for resolution and coord_sys (coord_sys is not used) */
|
||
- if (get_line(fp) < 0) {
|
||
+ if (get_line(fp, &line, &line_len, &line_no) < 0) {
|
||
put_msg("File is truncated at resolution specification.");
|
||
+ free(line);
|
||
return -1;
|
||
}
|
||
- if (sscanf(buf,"%lf%d\n", &ppi, &coord_sys) != 2) {
|
||
+ if (sscanf(line, "%lf%d", &ppi, &coord_sys) != 2) {
|
||
put_msg("Incomplete resolution information at line %d.", line_no);
|
||
+ free(line);
|
||
return -1;
|
||
}
|
||
if (ppi <= 0.) {
|
||
put_msg("Invalid resolution information (%g) at line %d.",
|
||
ppi, line_no);
|
||
+ free(line);
|
||
return -1;
|
||
}
|
||
|
||
@@ -349,24 +385,28 @@ read_objects(FILE *fp, F_compound *obj)
|
||
/* attach any comments found thus far to the whole figure */
|
||
obj->comments = attach_comments();
|
||
|
||
- while (get_line(fp) > 0) {
|
||
- if (sscanf(buf, "%d", &object) != 1) {
|
||
+ while (get_line(fp, &line, &line_len, &line_no) > 0) {
|
||
+ if (sscanf(line, "%d", &object) != 1) {
|
||
put_msg("Incorrect format at line %d.", line_no);
|
||
+ free(line);
|
||
return -1;
|
||
}
|
||
switch (object) {
|
||
case OBJ_COLOR_DEF:
|
||
- read_colordef();
|
||
- if (num_object) {
|
||
+ if (objects) {
|
||
put_msg("Color definitions must come before other objects (line %d).",
|
||
line_no);
|
||
- return (-1);
|
||
+ free(line);
|
||
+ return -1;
|
||
}
|
||
- ++num_usr_cols;
|
||
+ read_colordef(line, line_no);
|
||
break;
|
||
case OBJ_POLYLINE :
|
||
- if ((l = read_lineobject(fp)) == NULL)
|
||
+ if ((l = read_lineobject(fp, &line, &line_len, &line_no)) ==
|
||
+ NULL) {
|
||
+ free(line);
|
||
return -1;
|
||
+ }
|
||
#ifdef V4_0
|
||
if ((l->pic != NULL) && (l->pic->figure != NULL)) {
|
||
if (lc)
|
||
@@ -388,79 +428,97 @@ read_objects(FILE *fp, F_compound *obj)
|
||
ll = (ll->next = l);
|
||
else
|
||
ll = obj->lines = l;
|
||
- num_object++;
|
||
+ objects = true;
|
||
break;
|
||
#endif /* V4_0 */
|
||
case OBJ_SPLINE :
|
||
- if ((s = read_splineobject(fp)) == NULL) {
|
||
+ if ((s = read_splineobject(fp, &line, &line_len, &line_no))
|
||
+ == NULL) {
|
||
+ free(line);
|
||
return -1;
|
||
- }
|
||
+ }
|
||
if (v32_flag){ /* s is a line */
|
||
if (ll)
|
||
ll = (ll->next = (F_line *) s);
|
||
else
|
||
ll = obj->lines = (F_line *) s;
|
||
- num_object++;
|
||
+ objects = true;
|
||
break;
|
||
}
|
||
if (ls)
|
||
ls = (ls->next = s);
|
||
else
|
||
ls = obj->splines = s;
|
||
- num_object++;
|
||
+ objects = true;
|
||
break;
|
||
case OBJ_ELLIPSE :
|
||
- if ((e = read_ellipseobject()) == NULL)
|
||
+ if ((e = read_ellipseobject(line, line_no)) == NULL) {
|
||
+ free(line);
|
||
return -1;
|
||
+ }
|
||
if (le)
|
||
le = (le->next = e);
|
||
else
|
||
le = obj->ellipses = e;
|
||
- num_object++;
|
||
+ objects = true;
|
||
break;
|
||
case OBJ_ARC :
|
||
- if ((a = read_arcobject(fp)) == NULL)
|
||
+ if ((a = read_arcobject(fp, &line, &line_len, &line_no)) ==
|
||
+ NULL) {
|
||
+ free(line);
|
||
return -1;
|
||
+ }
|
||
if (la)
|
||
la = (la->next = a);
|
||
else
|
||
la = obj->arcs = a;
|
||
- num_object++;
|
||
+ objects = true;
|
||
break;
|
||
case OBJ_TEXT :
|
||
- if ((t = read_textobject(fp)) == NULL)
|
||
+ if ((t = read_textobject(fp, &line, &line_len, &line_no)) ==
|
||
+ NULL) {
|
||
+ free(line);
|
||
return -1;
|
||
+ }
|
||
if (lt)
|
||
lt = (lt->next = t);
|
||
else
|
||
lt = obj->texts = t;
|
||
- num_object++;
|
||
+ objects = true;
|
||
break;
|
||
case OBJ_COMPOUND :
|
||
- if ((c = read_compoundobject(fp)) == NULL)
|
||
+ if ((c = read_compoundobject(fp, &line, &line_len,&line_no))
|
||
+ == NULL) {
|
||
+ free(line);
|
||
return -1;
|
||
+ }
|
||
if (lc)
|
||
lc = (lc->next = c);
|
||
else
|
||
lc = obj->compounds = c;
|
||
- num_object++;
|
||
+ objects = true;
|
||
break;
|
||
default :
|
||
put_msg("Incorrect object code at line %d.", line_no);
|
||
+ free(line);
|
||
return -1;
|
||
} /* switch */
|
||
- } /* while (get_line(fp)) */
|
||
+ } /* while (get_line(...)) */
|
||
+ free(line);
|
||
|
||
/* if user color was requested for GIF transparent color, get the
|
||
rgb values from the user color array now that we've read them in */
|
||
if (gif_colnum >= NUM_STD_COLS) {
|
||
int i;
|
||
- for (i=0; i<num_usr_cols; ++i)
|
||
+ /* read_colordef() counted, but ignored too many user colors */
|
||
+ if (num_usr_cols > MAX_USR_COLS)
|
||
+ num_usr_cols = MAX_USR_COLS;
|
||
+ for (i=0; i < num_usr_cols; ++i)
|
||
if (user_col_indx[i] == gif_colnum)
|
||
break;
|
||
if (i < num_usr_cols)
|
||
- sprintf(gif_transparent,"#%2x%2x%2x",
|
||
- user_colors[i].r,user_colors[i].g,user_colors[i].b);
|
||
+ sprintf(gif_transparent, "#%2x%2x%2x",
|
||
+ user_colors[i].r, user_colors[i].g, user_colors[i].b);
|
||
}
|
||
|
||
if (feof(fp))
|
||
@@ -474,55 +532,72 @@ read_objects(FILE *fp, F_compound *obj)
|
||
} /* read_objects */
|
||
|
||
static void
|
||
-read_colordef(void)
|
||
+read_colordef(char *line, int line_no)
|
||
{
|
||
- int c;
|
||
- unsigned int r,g,b;
|
||
+ int c;
|
||
+ unsigned int r,g,b;
|
||
|
||
- if ((sscanf(buf, "%*d %d #%2x%2x%2x", &c, &r, &g, &b) != 4) ||
|
||
- (c < NUM_STD_COLS)) {
|
||
- buf[strlen(buf)-1]='\0'; /* remove the newline */
|
||
- put_msg("Invalid color definition: %s, setting to black (#00000).",buf);
|
||
- r=g=b=0;
|
||
- }
|
||
- user_col_indx[num_usr_cols] = c;
|
||
- user_colors[num_usr_cols].r = r;
|
||
- user_colors[num_usr_cols].g = g;
|
||
- user_colors[num_usr_cols].b = b;
|
||
+ if (num_usr_cols >= MAX_USR_COLS) {
|
||
+ if (num_usr_cols == MAX_USR_COLS) {
|
||
+ put_msg("Maximum number of color definitions (%d) exceeded at line %d.",
|
||
+ MAX_USR_COLS, line_no);
|
||
+ ++num_usr_cols;
|
||
+ }
|
||
+ /* ignore additional colors */
|
||
+ return;
|
||
+ }
|
||
+ if (sscanf(line, "%*d %d #%2x%2x%2x", &c, &r, &g, &b) != 4) {
|
||
+ if (c >= NUM_STD_COLS && c < NUM_STD_COLS + MAX_USR_COLS) {
|
||
+ put_msg("Invalid color definition at line %d: %s, setting to black (#00000).",
|
||
+ line_no, line);
|
||
+ r = g = b = 0;
|
||
+ } else {
|
||
+ put_msg("User color number at line %d out of range (%d), should be between %d and %d.",
|
||
+ line_no, c, NUM_STD_COLS,
|
||
+ NUM_STD_COLS + MAX_USR_COLS - 1);
|
||
+ return;
|
||
+ }
|
||
+ }
|
||
+ user_col_indx[num_usr_cols] = c;
|
||
+ user_colors[num_usr_cols].r = r;
|
||
+ user_colors[num_usr_cols].g = g;
|
||
+ user_colors[num_usr_cols].b = b;
|
||
+ ++num_usr_cols;
|
||
}
|
||
|
||
static void
|
||
-fix_and_note_color(int *color)
|
||
+fix_and_note_color(int *color, int line_no)
|
||
{
|
||
- int i;
|
||
- if (*color < DEFAULT) {
|
||
- put_msg("Invalid color number %d at line %d, using default color.",
|
||
- *color, line_no);
|
||
- *color = DEFAULT;
|
||
- return;
|
||
- }
|
||
- if (*color < NUM_STD_COLS) {
|
||
- if (*color >= BLACK_COLOR) {
|
||
- std_color_used[*color] = true;
|
||
+ int i;
|
||
+
|
||
+ if (*color < DEFAULT) {
|
||
+ put_msg("Invalid color number %d at line %d, using default color.",
|
||
+ *color, line_no);
|
||
+ *color = DEFAULT;
|
||
+ return;
|
||
}
|
||
- return;
|
||
- }
|
||
- for (i=0; i<num_usr_cols; ++i)
|
||
- if (*color == user_col_indx[i]) {
|
||
- *color = i + NUM_STD_COLS;
|
||
+ if (*color < NUM_STD_COLS) {
|
||
+ if (*color >= BLACK_COLOR) {
|
||
+ std_color_used[*color] = true;
|
||
+ }
|
||
return;
|
||
}
|
||
- put_msg("Cannot locate user color %d, using default color at line %d.",
|
||
- *color, line_no);
|
||
- *color = DEFAULT;
|
||
- return;
|
||
+ for (i = 0; i < MIN(num_usr_cols, MAX_USR_COLS); ++i)
|
||
+ if (*color == user_col_indx[i]) {
|
||
+ *color = i + NUM_STD_COLS;
|
||
+ return;
|
||
+ }
|
||
+ put_msg("Cannot locate user color %d, using default color at line %d.",
|
||
+ *color, line_no);
|
||
+ *color = DEFAULT;
|
||
+ return;
|
||
}
|
||
|
||
static void
|
||
-note_fill(int fill, int *color)
|
||
+note_fill(int fill, int *color, int line_no)
|
||
{
|
||
if (fill != UNFILLED) {
|
||
- fix_and_note_color(color);
|
||
+ fix_and_note_color(color, line_no);
|
||
if (fill >= NUMSHADES + NUMTINTS) {
|
||
pattern_used[fill - NUMSHADES - NUMTINTS] = true;
|
||
pats_used = true;
|
||
@@ -531,7 +606,7 @@ note_fill(int fill, int *color)
|
||
}
|
||
|
||
static F_arc *
|
||
-read_arcobject(FILE *fp)
|
||
+read_arcobject(FILE *fp, char **restrict line, size_t *line_len, int *line_no)
|
||
{
|
||
F_arc *a;
|
||
int n, fa, ba;
|
||
@@ -548,7 +623,7 @@ read_arcobject(FILE *fp)
|
||
a->back_arrow = NULL;
|
||
a->next = NULL;
|
||
if (v30_flag) {
|
||
- n = sscanf(buf, "%*d%d%d%d%d%d%d%d%d%lf%d%d%d%d%lf%lf%d%d%d%d%d%d\n",
|
||
+ n = sscanf(*line,"%*d%d%d%d%d%d%d%d%d%lf%d%d%d%d%lf%lf%d%d%d%d%d%d",
|
||
&a->type, &a->style, &a->thickness,
|
||
&a->pen_color, &a->fill_color, &a->depth, &a->pen, &a->fill_style,
|
||
&a->style_val, &a->cap_style,
|
||
@@ -558,7 +633,7 @@ read_arcobject(FILE *fp)
|
||
&a->point[1].x, &a->point[1].y,
|
||
&a->point[2].x, &a->point[2].y);
|
||
} else {
|
||
- n = sscanf(buf, "%*d%d%d%d%d%d%d%d%lf%d%d%d%lf%lf%d%d%d%d%d%d\n",
|
||
+ n = sscanf(*line, "%*d%d%d%d%d%d%d%d%lf%d%d%d%lf%lf%d%d%d%d%d%d",
|
||
&a->type, &a->style, &a->thickness,
|
||
&a->pen_color, &a->depth, &a->pen, &a->fill_style,
|
||
&a->style_val, &a->direction, &fa, &ba,
|
||
@@ -570,45 +645,45 @@ read_arcobject(FILE *fp)
|
||
a->cap_style = 0; /* butt line cap */
|
||
}
|
||
if ((v30_flag && n != 21) || (!v30_flag && n != 19)) {
|
||
- put_msg(Err_incomp, "arc", line_no);
|
||
+ put_msg(Err_incomp, "arc", *line_no);
|
||
free(a);
|
||
return NULL;
|
||
}
|
||
a->thickness *= round(THICK_SCALE);
|
||
a->fill_style = FILL_CONVERT(a->fill_style);
|
||
if (INVALID_ARC(a)) {
|
||
- put_msg(Err_invalid, "arc", line_no);
|
||
+ put_msg(Err_invalid, "arc", *line_no);
|
||
free(a);
|
||
return NULL;
|
||
}
|
||
- fix_and_note_color(&a->pen_color);
|
||
- note_fill(a->fill_style, &a->fill_color);
|
||
+ fix_and_note_color(&a->pen_color, *line_no);
|
||
+ note_fill(a->fill_style, &a->fill_color, *line_no);
|
||
if (fa) {
|
||
- if (get_line(fp) < 0 ||
|
||
- sscanf(buf, "%d%d%lf%lf%lf",
|
||
+ if (get_line(fp, line, line_len, line_no) < 0 ||
|
||
+ sscanf(*line, "%d%d%lf%lf%lf",
|
||
&type, &style, &thickness, &wid, &ht) != 5) {
|
||
- put_msg(Err_incomp, "arc", line_no);
|
||
+ put_msg(Err_incomp, "arc", *line_no);
|
||
free(a);
|
||
return NULL;
|
||
}
|
||
if ((a->for_arrow = make_arrow(type, style, thickness, wid, ht))
|
||
== NULL) {
|
||
- put_msg(Err_arrow, "forward", line_no);
|
||
+ put_msg(Err_arrow, "forward", *line_no);
|
||
free(a);
|
||
return NULL;
|
||
}
|
||
}
|
||
if (ba) {
|
||
- if (get_line(fp) < 0 ||
|
||
- sscanf(buf, "%d%d%lf%lf%lf",
|
||
+ if (get_line(fp, line, line_len, line_no) < 0 ||
|
||
+ sscanf(*line, "%d%d%lf%lf%lf",
|
||
&type, &style, &thickness, &wid, &ht) != 5) {
|
||
- put_msg(Err_incomp, "arc", line_no);
|
||
+ put_msg(Err_incomp, "arc", *line_no);
|
||
free(a);
|
||
return NULL;
|
||
}
|
||
if ((a->back_arrow = make_arrow(type, style, thickness, wid, ht))
|
||
== NULL) {
|
||
- put_msg(Err_arrow, "backward", line_no);
|
||
+ put_msg(Err_arrow, "backward", *line_no);
|
||
free(a);
|
||
return NULL;
|
||
}
|
||
@@ -618,7 +693,8 @@ read_arcobject(FILE *fp)
|
||
}
|
||
|
||
static F_compound *
|
||
-read_compoundobject(FILE *fp)
|
||
+read_compoundobject(FILE *fp, char **restrict line, size_t *line_len,
|
||
+ int *line_no)
|
||
{
|
||
F_arc *a, *la = NULL;
|
||
F_ellipse *e, *le = NULL;
|
||
@@ -638,22 +714,23 @@ read_compoundobject(FILE *fp)
|
||
com->next = NULL;
|
||
com->comments = attach_comments(); /* attach any comments */
|
||
|
||
- n = sscanf(buf, "%*d%d%d%d%d\n", &com->nwcorner.x, &com->nwcorner.y,
|
||
+ n = sscanf(*line, "%*d%d%d%d%d", &com->nwcorner.x, &com->nwcorner.y,
|
||
&com->secorner.x, &com->secorner.y);
|
||
if (n != 4) {
|
||
- put_msg(Err_incomp, "compound", line_no);
|
||
+ put_msg(Err_incomp, "compound", *line_no);
|
||
free(com);
|
||
return NULL;
|
||
}
|
||
- while (get_line(fp) > 0) {
|
||
- if (sscanf(buf, "%d", &object) != 1) {
|
||
- put_msg(Err_incomp, "compound", line_no);
|
||
+ while (get_line(fp, line, line_len, line_no) > 0) {
|
||
+ if (sscanf(*line, "%d", &object) != 1) {
|
||
+ put_msg(Err_incomp, "compound", *line_no);
|
||
free_compound(&com);
|
||
return NULL;
|
||
- }
|
||
+ }
|
||
switch (object) {
|
||
case OBJ_POLYLINE :
|
||
- if ((l = read_lineobject(fp)) == NULL) {
|
||
+ if ((l = read_lineobject(fp, line, line_len, line_no)) ==
|
||
+ NULL) {
|
||
return NULL;
|
||
}
|
||
#ifdef V4_0
|
||
@@ -674,7 +751,8 @@ read_compoundobject(FILE *fp)
|
||
#endif /* V4_0 */
|
||
break;
|
||
case OBJ_SPLINE :
|
||
- if ((s = read_splineobject(fp)) == NULL) {
|
||
+ if ((s = read_splineobject(fp, line, line_len, line_no)) ==
|
||
+ NULL) {
|
||
return NULL;
|
||
}
|
||
if (v32_flag){ /* s is a line */
|
||
@@ -690,7 +768,7 @@ read_compoundobject(FILE *fp)
|
||
ls = com->splines = s;
|
||
break;
|
||
case OBJ_ELLIPSE :
|
||
- if ((e = read_ellipseobject()) == NULL) {
|
||
+ if ((e = read_ellipseobject(*line, *line_no)) == NULL) {
|
||
return NULL;
|
||
}
|
||
if (le)
|
||
@@ -699,7 +777,8 @@ read_compoundobject(FILE *fp)
|
||
le = com->ellipses = e;
|
||
break;
|
||
case OBJ_ARC :
|
||
- if ((a = read_arcobject(fp)) == NULL) {
|
||
+ if ((a = read_arcobject(fp, line, line_len, line_no)) ==
|
||
+ NULL) {
|
||
return NULL;
|
||
}
|
||
if (la)
|
||
@@ -708,7 +787,8 @@ read_compoundobject(FILE *fp)
|
||
la = com->arcs = a;
|
||
break;
|
||
case OBJ_TEXT :
|
||
- if ((t = read_textobject(fp)) == NULL) {
|
||
+ if ((t = read_textobject(fp, line, line_len, line_no)) ==
|
||
+ NULL) {
|
||
return NULL;
|
||
}
|
||
if (lt)
|
||
@@ -717,7 +797,8 @@ read_compoundobject(FILE *fp)
|
||
lt = com->texts = t;
|
||
break;
|
||
case OBJ_COMPOUND :
|
||
- if ((c = read_compoundobject(fp)) == NULL) {
|
||
+ if ((c = read_compoundobject(fp, line, line_len, line_no))
|
||
+ == NULL) {
|
||
return NULL;
|
||
}
|
||
if (lc)
|
||
@@ -728,7 +809,7 @@ read_compoundobject(FILE *fp)
|
||
case OBJ_END_COMPOUND :
|
||
return com;
|
||
default :
|
||
- put_msg("Wrong object code at line %d", line_no);
|
||
+ put_msg("Wrong object code at line %d", *line_no);
|
||
return NULL;
|
||
} /* switch */
|
||
}
|
||
@@ -739,7 +820,7 @@ read_compoundobject(FILE *fp)
|
||
}
|
||
|
||
static F_ellipse *
|
||
-read_ellipseobject(void)
|
||
+read_ellipseobject(char *line, int line_no)
|
||
{
|
||
F_ellipse *e;
|
||
int n;
|
||
@@ -749,7 +830,7 @@ read_ellipseobject(void)
|
||
e->pen = 0;
|
||
e->next = NULL;
|
||
if (v30_flag) {
|
||
- n = sscanf(buf, "%*d%d%d%d%d%d%d%d%d%lf%d%lf%d%d%d%d%d%d%d%d\n",
|
||
+ n = sscanf(line, "%*d%d%d%d%d%d%d%d%d%lf%d%lf%d%d%d%d%d%d%d%d",
|
||
&e->type, &e->style, &e->thickness,
|
||
&e->pen_color, &e->fill_color, &e->depth, &e->pen, &e->fill_style,
|
||
&e->style_val, &e->direction, &e->angle,
|
||
@@ -758,7 +839,7 @@ read_ellipseobject(void)
|
||
&e->start.x, &e->start.y,
|
||
&e->end.x, &e->end.y);
|
||
} else {
|
||
- n = sscanf(buf, "%*d%d%d%d%d%d%d%d%lf%d%lf%d%d%d%d%d%d%d%d\n",
|
||
+ n = sscanf(line, "%*d%d%d%d%d%d%d%d%lf%d%lf%d%d%d%d%d%d%d%d",
|
||
&e->type, &e->style, &e->thickness,
|
||
&e->pen_color, &e->depth, &e->pen, &e->fill_style,
|
||
&e->style_val, &e->direction, &e->angle,
|
||
@@ -773,7 +854,7 @@ read_ellipseobject(void)
|
||
free(e);
|
||
return NULL;
|
||
}
|
||
- fix_and_note_color(&e->pen_color);
|
||
+ fix_and_note_color(&e->pen_color, line_no);
|
||
e->thickness *= round(THICK_SCALE);
|
||
e->fill_style = FILL_CONVERT(e->fill_style);
|
||
if (e->radiuses.x < 0)
|
||
@@ -785,7 +866,7 @@ read_ellipseobject(void)
|
||
free(e);
|
||
return NULL;
|
||
}
|
||
- note_fill(e->fill_style, &e->fill_color);
|
||
+ note_fill(e->fill_style, &e->fill_color, line_no);
|
||
e->comments = attach_comments(); /* attach any comments */
|
||
return e;
|
||
}
|
||
@@ -804,8 +885,9 @@ read_ellipseobject(void)
|
||
*/
|
||
static int
|
||
sanitize_lineobject(
|
||
- F_line *l, /* the line */
|
||
- F_point *p /* the last point of the line */
|
||
+ F_line *l, /* the line */
|
||
+ F_point *p, /* the last point of the line */
|
||
+ int line_no
|
||
)
|
||
{
|
||
F_point *q;
|
||
@@ -912,7 +994,7 @@ sanitize_lineobject(
|
||
}
|
||
|
||
static F_line *
|
||
-read_lineobject(FILE *fp)
|
||
+read_lineobject(FILE *fp, char **restrict line, size_t *line_len, int *line_no)
|
||
{
|
||
F_line *l;
|
||
F_point *o = NULL, *p, *q;
|
||
@@ -933,40 +1015,38 @@ read_lineobject(FILE *fp)
|
||
l->pic = NULL;
|
||
l->comments = NULL;
|
||
|
||
- sscanf(buf,"%*d%d",&l->type); /* get the line type */
|
||
+ sscanf(*line, "%*d%d", &l->type); /* get the line type */
|
||
|
||
radius_flag = v30_flag || v21_flag || (v2_flag && l->type == T_ARC_BOX);
|
||
if (radius_flag) {
|
||
if (v30_flag) {
|
||
- n = sscanf(buf, "%*d%d%d%d%d%d%d%d%d%lf%d%d%d%d%d%d",
|
||
+ n = sscanf(*line, "%*d%d%d%d%d%d%d%d%d%lf%d%d%d%d%d%d",
|
||
&l->type,&l->style,&l->thickness,&l->pen_color,&l->fill_color,
|
||
&l->depth,&l->pen,&l->fill_style,&l->style_val,
|
||
&l->join_style,&l->cap_style,
|
||
&l->radius,&fa,&ba,&npts);
|
||
} else {
|
||
- n = sscanf(buf, "%*d%d%d%d%d%d%d%d%lf%d%d%d",
|
||
- &l->type,&l->style,&l->thickness,&l->pen_color,
|
||
- &l->depth,&l->pen,&l->fill_style,&l->style_val,&l->radius,&fa, &ba);
|
||
+ n = sscanf(*line, "%*d%d%d%d%d%d%d%d%lf%d%d%d",
|
||
+ &l->type,&l->style,&l->thickness,&l->pen_color,&l->depth,
|
||
+ &l->pen,&l->fill_style,&l->style_val,&l->radius,&fa, &ba);
|
||
l->fill_color = l->pen_color;
|
||
}
|
||
}
|
||
/* old format uses pen for radius of arc-box corners */
|
||
else {
|
||
- n = sscanf(buf, "%*d%d%d%d%d%d%d%d%lf%d%d",
|
||
+ n = sscanf(*line, "%*d%d%d%d%d%d%d%d%lf%d%d",
|
||
&l->type,&l->style,&l->thickness,&l->pen_color,
|
||
&l->depth,&l->pen,&l->fill_style,&l->style_val,&fa,&ba);
|
||
l->fill_color = l->pen_color;
|
||
- if (l->type == T_ARC_BOX)
|
||
- {
|
||
- l->radius = (int) l->pen;
|
||
+ if (l->type == T_ARC_BOX) {
|
||
+ l->radius = l->pen;
|
||
l->pen = 0;
|
||
- }
|
||
- else
|
||
+ } else
|
||
l->radius = 0;
|
||
}
|
||
if ((!radius_flag && n!=10) ||
|
||
(radius_flag && ((!v30_flag && n!=11)||(v30_flag && n!=15)))) {
|
||
- put_msg(Err_incomp, "line", line_no);
|
||
+ put_msg(Err_incomp, "line", *line_no);
|
||
free(l);
|
||
return NULL;
|
||
}
|
||
@@ -974,45 +1054,47 @@ read_lineobject(FILE *fp)
|
||
l->thickness *= round(THICK_SCALE);
|
||
l->fill_style = FILL_CONVERT(l->fill_style);
|
||
if (INVALID_LINE(l)) {
|
||
- put_msg(Err_invalid, "line", line_no);
|
||
+ put_msg(Err_invalid, "line", *line_no);
|
||
free(l);
|
||
return NULL;
|
||
}
|
||
- note_fill(l->fill_style, &l->fill_color);
|
||
- fix_and_note_color(&l->pen_color);
|
||
+ note_fill(l->fill_style, &l->fill_color, *line_no);
|
||
+ fix_and_note_color(&l->pen_color, *line_no);
|
||
if (fa) {
|
||
- if (get_line(fp) < 0 ||
|
||
- sscanf(buf, "%d%d%lf%lf%lf",
|
||
+ if (get_line(fp, line, line_len, line_no) < 0 ||
|
||
+ sscanf(*line, "%d%d%lf%lf%lf",
|
||
&type, &style, &thickness, &wid, &ht) != 5) {
|
||
- put_msg(Err_incomp, "line", line_no);
|
||
+ put_msg(Err_incomp, "line", *line_no);
|
||
free(l);
|
||
return NULL;
|
||
}
|
||
if ((l->for_arrow = make_arrow(type, style, thickness, wid, ht))
|
||
== NULL) {
|
||
- put_msg(Err_arrow, "forward", line_no);
|
||
+ put_msg(Err_arrow, "forward", *line_no);
|
||
free(l);
|
||
return NULL;
|
||
}
|
||
}
|
||
if (ba) {
|
||
- if (get_line(fp) < 0 ||
|
||
- sscanf(buf, "%d%d%lf%lf%lf",
|
||
+ if (get_line(fp, line, line_len, line_no) < 0 ||
|
||
+ sscanf(*line, "%d%d%lf%lf%lf",
|
||
&type, &style, &thickness, &wid, &ht) != 5) {
|
||
- put_msg(Err_incomp, "line", line_no);
|
||
+ put_msg(Err_incomp, "line", *line_no);
|
||
free_linestorage(l);
|
||
return NULL;
|
||
}
|
||
if ((l->back_arrow = make_arrow(type, style, thickness, wid, ht))
|
||
== NULL) {
|
||
- put_msg(Err_arrow, "backward", line_no);
|
||
+ put_msg(Err_arrow, "backward", *line_no);
|
||
free_linestorage(l);
|
||
return NULL;
|
||
}
|
||
}
|
||
if (l->type == T_PIC_BOX) {
|
||
- char file[BUFSIZ], *c;
|
||
+ char *file, *c;
|
||
+ int pos;
|
||
size_t len;
|
||
+ ssize_t chars;
|
||
|
||
if ((Pic_malloc(l->pic)) == NULL) {
|
||
free(l);
|
||
@@ -1026,21 +1108,22 @@ read_lineobject(FILE *fp)
|
||
XpmCreateXpmImageFromBuffer("", &l->pic->xpmimage, NULL);
|
||
#endif
|
||
|
||
- /* %[^\n]: really, read until first '\0' in buf */
|
||
- if (get_line(fp) < 0 || sscanf(buf, "%d %[^\n]",
|
||
- &l->pic->flipped, file) != 2) {
|
||
- put_msg(Err_incomp, "picture", line_no);
|
||
- free(l);
|
||
- return NULL;
|
||
+ if ((chars = get_line(fp, line, line_len, line_no)) < 0 ||
|
||
+ sscanf(*line, "%d %n", &l->pic->flipped, &pos) != 1) {
|
||
+ put_msg(Err_incomp, "picture", *line_no);
|
||
+ free(l);
|
||
+ return NULL;
|
||
}
|
||
+ file = *line + pos;
|
||
+ len = chars - pos; /* strlen(file) */
|
||
+
|
||
/* if there is a path in the .fig filename, and the path of the
|
||
* imported picture filename is NOT absolute, prepend the
|
||
* .fig file path to it
|
||
*/
|
||
if (from && (c = strrchr(from, '/')) && file[0] != '/') {
|
||
- if ((l->pic->file = malloc((size_t)(c - from + 2) +
|
||
- (len = strlen(file)))) ==
|
||
- NULL) {
|
||
+ if ((l->pic->file = malloc((size_t)(c - from + 2) + len)) ==
|
||
+ NULL) {
|
||
put_msg(Err_mem);
|
||
free(l); /* Points not read yet. */
|
||
return NULL;
|
||
@@ -1049,8 +1132,8 @@ read_lineobject(FILE *fp)
|
||
memcpy(l->pic->file + (c - from + 1), file, len + 1);
|
||
} else {
|
||
/* either absolute picture path or no path in .fig filename */
|
||
- l->pic->file = malloc(len = strlen(file) + 1);
|
||
- memcpy(l->pic->file, file, len);
|
||
+ l->pic->file = malloc(len + 1);
|
||
+ memcpy(l->pic->file, file, len + 1);
|
||
}
|
||
}
|
||
|
||
@@ -1062,9 +1145,9 @@ read_lineobject(FILE *fp)
|
||
p->next = NULL;
|
||
|
||
/* read first point of line */
|
||
- ++line_no;
|
||
+ ++(*line_no);
|
||
if (fscanf(fp, "%d%d", &p->x, &p->y) != 2) {
|
||
- put_msg(Err_incomp, "line", line_no);
|
||
+ put_msg(Err_incomp, "line", *line_no);
|
||
free_linestorage(l);
|
||
return NULL;
|
||
}
|
||
@@ -1072,9 +1155,9 @@ read_lineobject(FILE *fp)
|
||
if (!v30_flag)
|
||
npts = 1000000;
|
||
for (--npts; npts > 0; --npts) {
|
||
- count_lines_correctly(fp);
|
||
+ count_lines_correctly(fp, line_no);
|
||
if (fscanf(fp, "%d%d", &x, &y) != 2) {
|
||
- put_msg(Err_incomp, "line", line_no);
|
||
+ put_msg(Err_incomp, "line", *line_no);
|
||
free_linestorage(l);
|
||
return NULL;
|
||
}
|
||
@@ -1103,7 +1186,7 @@ read_lineobject(FILE *fp)
|
||
l->last[1].y = o->y;
|
||
}
|
||
|
||
- if (sanitize_lineobject(l, p)) {
|
||
+ if (sanitize_lineobject(l, p, *line_no)) {
|
||
free_linestorage(l);
|
||
return NULL;
|
||
}
|
||
@@ -1115,7 +1198,8 @@ read_lineobject(FILE *fp)
|
||
}
|
||
|
||
static F_spline *
|
||
-read_splineobject(FILE *fp)
|
||
+read_splineobject(FILE *fp, char **restrict line, size_t *line_len,
|
||
+ int *line_no)
|
||
{
|
||
F_spline *s;
|
||
F_line *l;
|
||
@@ -1137,58 +1221,58 @@ read_splineobject(FILE *fp)
|
||
s->next = NULL;
|
||
|
||
if (v30_flag) {
|
||
- n = sscanf(buf, "%*d%d%d%d%d%d%d%d%d%lf%d%d%d%d",
|
||
+ n = sscanf(*line, "%*d%d%d%d%d%d%d%d%d%lf%d%d%d%d",
|
||
&s->type, &s->style, &s->thickness,
|
||
&s->pen_color, &s->fill_color,
|
||
&s->depth, &s->pen, &s->fill_style, &s->style_val,
|
||
&s->cap_style, &fa, &ba, &npts);
|
||
} else {
|
||
- n = sscanf(buf, "%*d%d%d%d%d%d%d%d%lf%d%d",
|
||
+ n = sscanf(*line, "%*d%d%d%d%d%d%d%d%lf%d%d",
|
||
&s->type, &s->style, &s->thickness, &s->pen_color,
|
||
&s->depth, &s->pen, &s->fill_style, &s->style_val, &fa, &ba);
|
||
s->fill_color = s->pen_color;
|
||
s->cap_style = 0; /* butt line cap */
|
||
}
|
||
if ((v30_flag && n != 13) || (!v30_flag && n != 10)) {
|
||
- put_msg(Err_incomp, "spline", line_no);
|
||
+ put_msg(Err_incomp, "spline", *line_no);
|
||
free(s);
|
||
return NULL;
|
||
}
|
||
s->thickness *= round(THICK_SCALE);
|
||
s->fill_style = FILL_CONVERT(s->fill_style);
|
||
if (INVALID_SPLINE(s)) {
|
||
- put_msg(Err_invalid, "spline", line_no);
|
||
+ put_msg(Err_invalid, "spline", *line_no);
|
||
free(s);
|
||
return NULL;
|
||
}
|
||
- note_fill(s->fill_style, &s->fill_color);
|
||
- fix_and_note_color(&s->pen_color);
|
||
+ note_fill(s->fill_style, &s->fill_color, *line_no);
|
||
+ fix_and_note_color(&s->pen_color, *line_no);
|
||
if (fa) {
|
||
- if (get_line(fp) < 0 ||
|
||
- sscanf(buf, "%d%d%lf%lf%lf",
|
||
+ if (get_line(fp, line, line_len, line_no) < 0 ||
|
||
+ sscanf(*line, "%d%d%lf%lf%lf",
|
||
&type, &style, &thickness, &wid, &ht) != 5) {
|
||
- put_msg(Err_incomp, "spline", line_no);
|
||
+ put_msg(Err_incomp, "spline", *line_no);
|
||
free(s);
|
||
return NULL;
|
||
}
|
||
if ((s->for_arrow = make_arrow(type, style, thickness, wid, ht))
|
||
== NULL) {
|
||
- put_msg(Err_arrow, "forward", line_no);
|
||
+ put_msg(Err_arrow, "forward", *line_no);
|
||
free(s);
|
||
return NULL;
|
||
}
|
||
}
|
||
if (ba) {
|
||
- if (get_line(fp) < 0 ||
|
||
- sscanf(buf, "%d%d%lf%lf%lf",
|
||
+ if (get_line(fp, line, line_len, line_no) < 0 ||
|
||
+ sscanf(*line, "%d%d%lf%lf%lf",
|
||
&type, &style, &thickness, &wid, &ht) != 5) {
|
||
- put_msg(Err_incomp, "spline", line_no);
|
||
+ put_msg(Err_incomp, "spline", *line_no);
|
||
free_splinestorage(s);
|
||
return NULL;
|
||
}
|
||
if ((s->back_arrow = make_arrow(type, style, thickness, wid, ht))
|
||
== NULL) {
|
||
- put_msg(Err_arrow, "backward", line_no);
|
||
+ put_msg(Err_arrow, "backward", *line_no);
|
||
free_splinestorage(s);
|
||
return NULL;
|
||
}
|
||
@@ -1196,9 +1280,9 @@ read_splineobject(FILE *fp)
|
||
|
||
/* Read points */
|
||
/* read first point of line */
|
||
- ++line_no;
|
||
+ ++(*line_no);
|
||
if ((n = fscanf(fp, "%d%d", &x, &y)) != 2) {
|
||
- put_msg(Err_incomp, "spline", line_no);
|
||
+ put_msg(Err_incomp, "spline", *line_no);
|
||
free_splinestorage(s);
|
||
return NULL;
|
||
};
|
||
@@ -1212,15 +1296,15 @@ read_splineobject(FILE *fp)
|
||
if (!v30_flag)
|
||
npts = 1000000;
|
||
if (npts < 2) {
|
||
- put_msg(Err_incomp, "spline", line_no);
|
||
+ put_msg(Err_incomp, "spline", *line_no);
|
||
free_splinestorage(s);
|
||
return NULL;
|
||
}
|
||
for (--npts; npts > 0; --npts) {
|
||
/* keep track of newlines for line counter */
|
||
- count_lines_correctly(fp);
|
||
+ count_lines_correctly(fp, line_no);
|
||
if (fscanf(fp, "%d%d", &x, &y) != 2) {
|
||
- put_msg(Err_incomp, "spline", line_no);
|
||
+ put_msg(Err_incomp, "spline", *line_no);
|
||
free_splinestorage(s);
|
||
return NULL;
|
||
};
|
||
@@ -1250,9 +1334,9 @@ read_splineobject(FILE *fp)
|
||
ptr = s->controls;
|
||
while (ptr) { /* read controls */
|
||
/* keep track of newlines for line counter */
|
||
- count_lines_correctly(fp);
|
||
+ count_lines_correctly(fp, line_no);
|
||
if ((n = fscanf(fp, "%lf", &control_s)) != 1) {
|
||
- put_msg(Err_incomp, "spline", line_no);
|
||
+ put_msg(Err_incomp, "spline", *line_no);
|
||
free_splinestorage(s);
|
||
return NULL;
|
||
}
|
||
@@ -1275,9 +1359,9 @@ read_splineobject(FILE *fp)
|
||
}
|
||
/* Read controls from older versions */
|
||
/* keep track of newlines for line counter */
|
||
- count_lines_correctly(fp);
|
||
+ count_lines_correctly(fp, line_no);
|
||
if ((n = fscanf(fp, "%lf%lf%lf%lf", &lx, &ly, &rx, &ry)) != 4) {
|
||
- put_msg(Err_incomp, "spline", line_no);
|
||
+ put_msg(Err_incomp, "spline", *line_no);
|
||
free_splinestorage(s);
|
||
return NULL;
|
||
}
|
||
@@ -1290,9 +1374,9 @@ read_splineobject(FILE *fp)
|
||
cp->rx = rx; cp->ry = ry;
|
||
while (--c) {
|
||
/* keep track of newlines for line counter */
|
||
- count_lines_correctly(fp);
|
||
+ count_lines_correctly(fp, line_no);
|
||
if (fscanf(fp, "%lf%lf%lf%lf", &lx, &ly, &rx, &ry) != 4) {
|
||
- put_msg(Err_incomp, "spline", line_no);
|
||
+ put_msg(Err_incomp, "spline", *line_no);
|
||
cp->next = NULL;
|
||
free_splinestorage(s);
|
||
return NULL;
|
||
@@ -1315,13 +1399,37 @@ read_splineobject(FILE *fp)
|
||
return s;
|
||
}
|
||
|
||
+static char *
|
||
+find_end(const char *str, int v30flag)
|
||
+{
|
||
+ const char endmark[] = "\\001";
|
||
+ char *end;
|
||
+
|
||
+ if (v30flag) {
|
||
+ /* A string is terminated with the literal '\001',
|
||
+ and 8-bit characters may be represented as \xxx */
|
||
+ end = strstr(str, endmark);
|
||
+ /* is this not '\\001', or '\\\\001', etc? */
|
||
+ while (end && backslash_count(str, end - str) % 2 == 0)
|
||
+ end = strstr(end + 3, endmark);
|
||
+ } else {
|
||
+ /* The text object is terminated by a CONTROL-A.
|
||
+ If there is no CONTROL-A on this line, then this
|
||
+ must be a multi-line text object. */
|
||
+ end = strchr(str, '\1');
|
||
+ }
|
||
+ return end;
|
||
+}
|
||
+
|
||
+
|
||
static F_text *
|
||
-read_textobject(FILE *fp)
|
||
+read_textobject(FILE *fp, char **restrict line, size_t *line_len, int *line_no)
|
||
{
|
||
F_text *t;
|
||
- int n, ignore = 0;
|
||
- char s[BUFSIZ], s_temp[BUFSIZ], junk[2];
|
||
- int more, len, l;
|
||
+ bool freestart = false;
|
||
+ int i, n;
|
||
+ char *end, *start;
|
||
+ size_t len;
|
||
|
||
Text_malloc(t);
|
||
t->font = 0;
|
||
@@ -1329,32 +1437,101 @@ read_textobject(FILE *fp)
|
||
t->comments = NULL;
|
||
t->next = NULL;
|
||
|
||
- if (v30_flag) { /* order of parms is more like other objects now,
|
||
- string is now terminated with the literal '\001',
|
||
- and 8-bit characters are represented as \xxx */
|
||
-
|
||
- n = sscanf(buf, "%*d%d%d%d%d%d%lf%lf%d%lf%lf%d%d%[^\n]",
|
||
- &t->type, &t->color, &t->depth, &t->pen,
|
||
- &t->font, &t->size, &t->angle,
|
||
- &t->flags, &t->height, &t->length,
|
||
- &t->base_x, &t->base_y, s);
|
||
+ n = sscanf(*line, "%*d%d%d%d%d%d%lf%lf%d%lf%lf%d%d %n",
|
||
+ &t->type, &t->color, &t->depth, &t->pen, &t->font,
|
||
+ &t->size, &t->angle, &t->flags, &t->height, &t->length,
|
||
+ &t->base_x, &t->base_y, &i);
|
||
+ if (n != 12) {
|
||
+ put_msg(Err_incomp, "text", *line_no);
|
||
+ free(t);
|
||
+ return NULL;
|
||
+ }
|
||
+ start = *line + i;
|
||
+ end = find_end(start, v30_flag);
|
||
+
|
||
+ if (end) {
|
||
+ *end = '\0';
|
||
+ len = end - start;
|
||
} else {
|
||
- /* The text object is terminated by a CONTROL-A, so we read
|
||
- everything up to the CONTROL-A and then read that character.
|
||
- If we do not find the CONTROL-A on this line then this must
|
||
- be a multi-line text object and we will have to read more. */
|
||
-
|
||
- n = sscanf(buf,"%*d%d%d%lf%d%d%d%lf%d%lf%lf%d%d%[^\1]%1[\1]",
|
||
- &t->type, &t->font, &t->size, &t->pen,
|
||
- &t->color, &t->depth, &t->angle,
|
||
- &t->flags, &t->height, &t->length,
|
||
- &t->base_x, &t->base_y, s, junk);
|
||
- }
|
||
- if ((n != 14) && (n != 13)) {
|
||
- put_msg(Err_incomp, "text", line_no);
|
||
- free(t);
|
||
- return NULL;
|
||
+ ssize_t chars;
|
||
+ char *next;
|
||
+
|
||
+ len = strlen(start);
|
||
+ start[len++] = '\n'; /* put back the newline */
|
||
+
|
||
+ /* allocate plenty of space */
|
||
+ next = malloc(len + BUFSIZ);
|
||
+ if (next == NULL) {
|
||
+ put_msg(Err_mem);
|
||
+ free(t);
|
||
+ return NULL;
|
||
+ }
|
||
+ memcpy(next, start, len);
|
||
+
|
||
+ while ((chars = getline(line, line_len, fp)) != -1) {
|
||
+ ++(*line_no);
|
||
+ end = find_end(*line, v30_flag);
|
||
+ if (end) {
|
||
+ *end = '\0';
|
||
+ next = realloc(next, len + end - *line + 1);
|
||
+ memcpy(next + len, *line, end - *line + 1);
|
||
+ len += end - *line;
|
||
+ break;
|
||
+ } else {
|
||
+ if (**line + chars - 1 == '\n' && chars > 1 &&
|
||
+ **line + chars - 2 == '\r')
|
||
+ (*line)[chars-- - 2] = '\n';
|
||
+ next = realloc(next, len + chars + 1);
|
||
+ memcpy(next + len, *line, chars + 1);
|
||
+ len += chars;
|
||
+ }
|
||
+ }
|
||
+ start = next;
|
||
+ freestart = true;
|
||
+ }
|
||
+
|
||
+ /* convert any \xxx to characters */
|
||
+ if (v30_flag && (end = strchr(start, '\\'))) {
|
||
+ unsigned char num;
|
||
+ char *c = start;
|
||
+ size_t l;
|
||
+
|
||
+ len = end - start;
|
||
+ l = len;
|
||
+ while (c[l] != '\0') {
|
||
+ if (c[l] == '\\') {
|
||
+ /* convert 3 digit octal value */
|
||
+ if (isdigit(c[l+1]) && c[l+2] != '\0' &&
|
||
+ c[l+3] != '\0') {
|
||
+ if (sscanf(c+l+1, "%3hho", &num) != 1) {
|
||
+ put_msg("Error in parsing text string on line %d",
|
||
+ *line_no);
|
||
+ return NULL;
|
||
+ }
|
||
+ /* no check of unsigned char overflow */
|
||
+ c[len++] = num;
|
||
+ l += 3;
|
||
+ } else {
|
||
+ /* an escaped char is un-escaped */
|
||
+ c[len++] = c[++l];
|
||
+ }
|
||
+ } else {
|
||
+ c[len++] = c[l];
|
||
+ }
|
||
+ ++l;
|
||
+ }
|
||
+ c[len] = '\0'; /* terminate */
|
||
+ }
|
||
+
|
||
+ t->cstring = malloc(len + 1);
|
||
+ if (t->cstring == NULL) {
|
||
+ put_msg(Err_mem);
|
||
+ free(t);
|
||
+ return NULL;
|
||
}
|
||
+ memcpy(t->cstring, start, len + 1);
|
||
+ if (freestart)
|
||
+ free(start);
|
||
|
||
if (font_size != 0.0) {
|
||
/* scale length/height of text by ratio of requested font size to actual size */
|
||
@@ -1364,89 +1541,6 @@ read_textobject(FILE *fp)
|
||
}
|
||
if (t->size <= 0.0)
|
||
t->size = (float) DEFAULT_FONT_SIZE;
|
||
- more = 0;
|
||
- if (!v30_flag && n == 13)
|
||
- more = 1; /* in older xfig there is more if ^A wasn't found yet */
|
||
- else if (v30_flag) { /* in 3.0 there is more if \001 wasn't found */
|
||
- len = strlen(s);
|
||
- if ((strcmp(&s[len-4],"\\001") == 0) && /* if we find '\000' */
|
||
- !(backslash_count(s, len-5) % 2)) { /* and not '\\000' */
|
||
- more = 0; /* then there are no more lines */
|
||
- s[len-4]='\0'; /* and get rid of the '\001' */
|
||
- } else {
|
||
- more = 1;
|
||
- s[len++]='\n'; /* put back the end of line char */
|
||
- s[len] = '\0'; /* and terminate it */
|
||
- }
|
||
- }
|
||
- if (more) {
|
||
- /* Read in the subsequent lines of the text if there are more */
|
||
- do {
|
||
- ++line_no; /* As is done in get_line */
|
||
- if (fgets(s_temp, BUFSIZ, fp) == NULL)
|
||
- break;
|
||
- len = strlen(s_temp)-1; /* ignore newline */
|
||
- if (len > 0 && s_temp[len-1] == '\r') { /* strip any trailing CR */
|
||
- s_temp[len-1] = '\0';
|
||
- len--;
|
||
- }
|
||
- if (v30_flag) {
|
||
- if ((strncmp(&s_temp[len-4],"\\001",4) == 0) &&
|
||
- !(backslash_count(s_temp, len-5) % 2)) {
|
||
- n=0; /* found the '\001', set n to stop */
|
||
- s_temp[len-4]='\0'; /* and get rid of the '\001' */
|
||
- } else {
|
||
- n=1; /* keep going (more lines) */
|
||
- }
|
||
- } else {
|
||
- n = sscanf(buf, "%[^\1]%[\1]", s_temp, junk);
|
||
- }
|
||
- /* Safety check */
|
||
- if (strlen(s)+1 + strlen(s_temp)+1 > BUFSIZ) {
|
||
- /* Too many characters. Ignore the rest. */
|
||
- ignore = 1;
|
||
- }
|
||
- if (!ignore)
|
||
- strcat(s, s_temp);
|
||
- } while (n == 1);
|
||
- }
|
||
-
|
||
- if (v30_flag) { /* now convert any \xxx to ascii characters */
|
||
- if (strchr(s,'\\')) {
|
||
- unsigned int num;
|
||
- len = strlen(s);
|
||
- for (l=0,n=0; l < len; ++l) {
|
||
- if (s[l]=='\\') {
|
||
- /* a backslash, see if a digit follows */
|
||
- if (l < len && isdigit(s[l+1])) {
|
||
- /* yes, scan for 3 digit octal value */
|
||
- if (sscanf(&s[l+1],"%3o",&num)!=1) {
|
||
- put_msg("Error in parsing text string on line %d",
|
||
- line_no);
|
||
- return NULL;
|
||
- }
|
||
- buf[n++]= (unsigned char) num; /* put char in */
|
||
- l += 3; /* skip over digits */
|
||
- } else {
|
||
- buf[n++] = s[++l]; /* some other escaped character */
|
||
- }
|
||
- } else {
|
||
- buf[n++] = s[l]; /* ordinary character */
|
||
- }
|
||
- }
|
||
- buf[n]='\0'; /* terminate */
|
||
- strcpy(s,buf); /* copy back to s */
|
||
- }
|
||
- }
|
||
- if (strlen(s) == 0)
|
||
- (void)strcpy(s, " ");
|
||
- t->cstring = calloc((unsigned)(strlen(s)), sizeof(char));
|
||
- if (NULL == t->cstring) {
|
||
- put_msg(Err_mem);
|
||
- free(t);
|
||
- return NULL;
|
||
- }
|
||
- (void)strcpy(t->cstring, s+1);
|
||
|
||
if (!v21_flag && (t->font == 0 || t->font == DEFAULT))
|
||
t->flags = ((t->flags != DEFAULT) ? t->flags : 0)
|
||
@@ -1457,11 +1551,11 @@ read_textobject(FILE *fp)
|
||
| PSFONT_TEXT;
|
||
|
||
if (INVALID_TEXT(t)) {
|
||
- put_msg(Err_invalid, "text", line_no);
|
||
+ put_msg(Err_invalid, "text", *line_no);
|
||
free_text(&t);
|
||
return NULL;
|
||
}
|
||
- fix_and_note_color(&t->color);
|
||
+ fix_and_note_color(&t->color, *line_no);
|
||
t->comments = attach_comments(); /* attach any comments */
|
||
return t;
|
||
}
|
||
@@ -1469,18 +1563,19 @@ read_textobject(FILE *fp)
|
||
|
||
/* count consecutive backslashes backwards */
|
||
|
||
-static int
|
||
-backslash_count(char cp[], int start)
|
||
+static ptrdiff_t
|
||
+backslash_count(const char *restrict cp, ptrdiff_t start)
|
||
{
|
||
- int i, count = 0;
|
||
+ ptrdiff_t i;
|
||
+ ptrdiff_t count = 0;
|
||
|
||
- for(i=start; i>=0; i--) {
|
||
- if (cp[i] == '\\')
|
||
- count++;
|
||
- else
|
||
- break;
|
||
- }
|
||
- return count;
|
||
+ for(i = start; i >= 0; --i) {
|
||
+ if (cp[i] == '\\')
|
||
+ ++count;
|
||
+ else
|
||
+ break;
|
||
+ }
|
||
+ return count;
|
||
}
|
||
|
||
/* attach comments in linked list */
|
||
@@ -1509,55 +1604,64 @@ attach_comments(void)
|
||
return icomp;
|
||
}
|
||
|
||
+/* save a comment line to be stored with the *subsequent* object */
|
||
+
|
||
static int
|
||
-get_line(FILE *fp)
|
||
+save_comment(char *restrict line, size_t len)
|
||
{
|
||
- int len;
|
||
- while (1) {
|
||
- if (NULL == fgets(buf, BUFSIZ, fp)) {
|
||
- return -1;
|
||
- }
|
||
- ++line_no;
|
||
- if (*buf == '#') { /* save any comments */
|
||
- if (save_comment() < 0)
|
||
- return -1;
|
||
- /* skip empty lines */
|
||
- } else if (*buf != '\n' || !(*buf == '\r' && buf[1] == '\n')) {
|
||
- len = strlen(buf);
|
||
- /* remove newline and possibly a carriage return */
|
||
- if (buf[len-1] == '\n')
|
||
- buf[len - (buf[len-2] == '\r' ? 2 : 1)] = '\0';
|
||
- return 1;
|
||
- }
|
||
- }
|
||
-}
|
||
+ int i;
|
||
|
||
-/* save a comment line to be stored with the *subsequent* object */
|
||
+ /* skip too many comment lines */
|
||
+ if (numcom == MAXCOMMENTS)
|
||
+ return 2;
|
||
+
|
||
+ /* remove one leading blank from the comment, if there is one */
|
||
+ i = 1;
|
||
+ if (line[i] == ' ')
|
||
+ i = 2;
|
||
+
|
||
+ /* see if we've allocated space for this comment */
|
||
+ if (comments[numcom])
|
||
+ free(comments[numcom]);
|
||
+ if ((comments[numcom] = malloc(len + (1 - i))) == NULL)
|
||
+ return -1;
|
||
|
||
-static int
|
||
-save_comment(void)
|
||
+ strcpy(comments[numcom++], &line[i]);
|
||
+ return 1;
|
||
+}
|
||
+
|
||
+static ssize_t
|
||
+get_line(FILE *fp, char **restrict line, size_t *line_len, int *line_no)
|
||
{
|
||
- int i;
|
||
+ ssize_t chars;
|
||
|
||
- /* skip too many comment lines */
|
||
- if (numcom == MAXCOMMENTS)
|
||
- return 2;
|
||
- i=strlen(buf);
|
||
- /* see if we've allocated space for this comment */
|
||
- if (comments[numcom])
|
||
- free(comments[numcom]);
|
||
- if ((comments[numcom] = malloc(i+1)) == NULL)
|
||
- return -1;
|
||
- /* remove any newline */
|
||
- if (buf[i-1] == '\n')
|
||
- buf[i-1] = '\0';
|
||
- i=1;
|
||
- if (buf[1] == ' ') /* remove one leading blank from the comment, if there is one */
|
||
- i=2;
|
||
- strcpy(comments[numcom++], &buf[i]);
|
||
- return 1;
|
||
+ while ((chars = getline(line, line_len, fp)) != -1) {
|
||
+ ++(*line_no);
|
||
+ /* skip empty lines */
|
||
+ if (**line == '\n' || (**line == '\r' &&
|
||
+ chars == 2 && (*line)[1] == '\n'))
|
||
+ continue;
|
||
+ /* remove newline and possibly a carriage return */
|
||
+ if ((*line)[chars-1] == '\n') {
|
||
+ chars -= (*line)[chars - 2] == '\r' ? 2 : 1;
|
||
+ (*line)[chars] = '\0';
|
||
+ }
|
||
+ /* save any comments */
|
||
+ if (**line == '#') {
|
||
+ if (save_comment(*line, (size_t)chars) < 0)
|
||
+ return -1;
|
||
+ continue;
|
||
+ }
|
||
+ /* return the line */
|
||
+ return chars;
|
||
+ }
|
||
+ /* chars == -1 */
|
||
+ return chars;
|
||
+ /* getline() only fails with EINVAL, and probably ENOMEM from malloc().
|
||
+ No use to check for errno. */
|
||
}
|
||
|
||
+
|
||
/* skip to the end of the current line and any subsequent blank lines */
|
||
|
||
static void
|
||
@@ -1714,15 +1818,15 @@ static int pop() {
|
||
*/
|
||
|
||
static void
|
||
-count_lines_correctly(FILE *fp)
|
||
+count_lines_correctly(FILE *fp, int *line_no)
|
||
{
|
||
int cc;
|
||
do {
|
||
- cc = getc(fp);
|
||
- if (cc == '\n') {
|
||
- ++line_no;
|
||
- cc=getc(fp);
|
||
- }
|
||
+ cc = getc(fp);
|
||
+ if (cc == '\n') {
|
||
+ ++(*line_no);
|
||
+ cc=getc(fp);
|
||
+ }
|
||
} while (cc == ' ' || cc == '\t');
|
||
ungetc(cc,fp);
|
||
}
|
||
--- fig2dev/read1_3.c
|
||
+++ fig2dev/read1_3.c 2020-01-21 11:31:32.048794834 +0000
|
||
@@ -2,8 +2,8 @@
|
||
* Fig2dev: Translate Fig code to various Devices
|
||
* Copyright (c) 1991 by Micah Beck
|
||
* Parts Copyright (c) 1985-1988 by Supoj Sutanthavibul
|
||
- * Parts Copyright (c) 1989-2012 by Brian V. Smith
|
||
- * Parts Copyright (c) 2015-2019 by Thomas Loimer
|
||
+ * Parts Copyright (c) 1989-2015 by Brian V. Smith
|
||
+ * Parts Copyright (c) 2015-2020 by Thomas Loimer
|
||
*
|
||
* Any party obtaining a copy of these files is granted, free of charge, a
|
||
* full and unrestricted irrevocable, world-wide, paid up, royalty-free,
|
||
@@ -51,8 +51,6 @@
|
||
|
||
extern F_arrow *forward_arrow(void), *backward_arrow(void);
|
||
extern int figure_modified;
|
||
-//extern int line_no;
|
||
-extern int num_object;
|
||
|
||
static F_ellipse *read_ellipseobject(FILE *fp);
|
||
static F_line *read_lineobject(FILE *fp);
|
||
@@ -103,7 +101,6 @@ read_1_3_objects(FILE *fp, F_compound *o
|
||
ll = (ll->next = l);
|
||
else
|
||
ll = obj->lines = l;
|
||
- num_object++;
|
||
break;
|
||
case OBJ_SPLINE :
|
||
if ((s = read_splineobject(fp)) == NULL) return(-1);
|
||
@@ -111,7 +108,6 @@ read_1_3_objects(FILE *fp, F_compound *o
|
||
ls = (ls->next = s);
|
||
else
|
||
ls = obj->splines = s;
|
||
- num_object++;
|
||
break;
|
||
case OBJ_ELLIPSE :
|
||
if ((e = read_ellipseobject(fp)) == NULL) return(-1);
|
||
@@ -119,7 +115,6 @@ read_1_3_objects(FILE *fp, F_compound *o
|
||
le = (le->next = e);
|
||
else
|
||
le = obj->ellipses = e;
|
||
- num_object++;
|
||
break;
|
||
case OBJ_ARC :
|
||
if ((a = read_arcobject(fp)) == NULL) return(-1);
|
||
@@ -127,7 +122,6 @@ read_1_3_objects(FILE *fp, F_compound *o
|
||
la = (la->next = a);
|
||
else
|
||
la = obj->arcs = a;
|
||
- num_object++;
|
||
break;
|
||
case OBJ_TEXT :
|
||
if ((t = read_textobject(fp)) == NULL) return(-1);
|
||
@@ -135,7 +129,6 @@ read_1_3_objects(FILE *fp, F_compound *o
|
||
lt = (lt->next = t);
|
||
else
|
||
lt = obj->texts = t;
|
||
- num_object++;
|
||
break;
|
||
case OBJ_COMPOUND :
|
||
if ((c = read_compoundobject(fp)) == NULL) return(-1);
|
||
@@ -143,7 +136,6 @@ read_1_3_objects(FILE *fp, F_compound *o
|
||
lc = (lc->next = c);
|
||
else
|
||
lc = obj->compounds = c;
|
||
- num_object++;
|
||
break;
|
||
default:
|
||
put_msg("Incorrect object code %d", object);
|
||
--- fig2dev/tests/read.at
|
||
+++ fig2dev/tests/read.at 2020-01-21 11:31:32.048794834 +0000
|
||
@@ -2,7 +2,7 @@ dnl Fig2dev: Translate Fig code to vario
|
||
dnl Copyright (c) 1991 by Micah Beck
|
||
dnl Parts Copyright (c) 1985-1988 by Supoj Sutanthavibul
|
||
dnl Parts Copyright (c) 1989-2015 by Brian V. Smith
|
||
-dnl Parts Copyright (c) 2015-2019 by Thomas Loimer
|
||
+dnl Parts Copyright (c) 2015-2020 by Thomas Loimer
|
||
dnl
|
||
dnl Any party obtaining a copy of these files is granted, free of charge, a
|
||
dnl full and unrestricted irrevocable, world-wide, paid up, royalty-free,
|
||
@@ -14,7 +14,7 @@ dnl party to do so, with the only requir
|
||
dnl and this permission notice remain intact.
|
||
|
||
dnl read.at
|
||
-dnl Author: Thomas Loimer, 2017-2019
|
||
+dnl Author: Thomas Loimer, 2017-2020
|
||
|
||
|
||
AT_BANNER([Sanitize and harden input.])
|
||
@@ -279,7 +279,7 @@ AT_CHECK([fig2dev -L box <<EOF
|
||
3 0 0 0 0 0 0 0 0. 0 1
|
||
0
|
||
EOF
|
||
-],1,ignore,[Incomplete spline object at line 3.
|
||
+],1,ignore,[Incomplete spline object at line 4.
|
||
])
|
||
AT_CLEANUP
|
||
|
||
@@ -287,7 +287,7 @@ AT_SETUP([allow last line without newlin
|
||
AT_KEYWORDS([read.c])
|
||
AT_CHECK([AS_ECHO_N(['#FIG 2
|
||
0']) | fig2dev -L box],
|
||
-1, ignore, [Incomplete resolution information at line 1.
|
||
+1, ignore, [Incomplete resolution information at line 2.
|
||
])
|
||
AT_CLEANUP
|
||
|
||
@@ -299,7 +299,7 @@ AT_CHECK([fig2dev -L box <<EOF
|
||
2 1 1 1 -1 50 0 0 0. 0 0
|
||
0
|
||
EOF
|
||
-], 1, ignore, [Incomplete line object at line 3.
|
||
+], 1, ignore, [Incomplete line object at line 4.
|
||
])
|
||
AT_CLEANUP
|
||
|
||
@@ -345,7 +345,7 @@ AT_CHECK([fig2dev -L pict2e <<EOF
|
||
2 1 1 1 -502350 50 0 0 0. 0 0
|
||
0 0 100 100 9999 0
|
||
EOF
|
||
-],0,ignore-nolog,[Invalid color number -502350 at line 2, using default color.
|
||
+],0,ignore-nolog,[Invalid color number -502350 at line 3, using default color.
|
||
])
|
||
AT_CLEANUP
|
||
|
||
@@ -387,9 +387,22 @@ AT_KEYWORDS([read.c])
|
||
AT_CHECK([fig2dev -L box <<EOF
|
||
#FIG 2
|
||
1200 2
|
||
-4 2 0 0 1 0 0 390 306 110 376 639 5 Text
|
||
+4 2 0 0 1 0 0 0 6 110 376 639 5 Text
|
||
EOF
|
||
-], 1, ignore, [Invalid text object at line 2.
|
||
+], 0, ignore)
|
||
+AT_CLEANUP
|
||
+
|
||
+AT_SETUP([reject too long papersize specification])
|
||
+AT_KEYWORDS([read.c])
|
||
+AT_CHECK([fig2dev -L box <<EOF
|
||
+#FIG 3.2
|
||
+Landscape
|
||
+Center
|
||
+Inches
|
||
+Papersize_name_too_long
|
||
+EOF
|
||
+], 1, ignore,
|
||
+ [Invalid paper size specification at line 5: Papersize_name_too_long
|
||
])
|
||
AT_CLEANUP
|
||
|