summaryrefslogtreecommitdiff
path: root/math/gnuplot+/files/patch-xk
blob: f17e69895bc36250d164bacf919973ce04213468 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
# command-substitution
--- command.c.ORIG	Thu Aug 19 15:42:21 1999
+++ command.c	Thu Dec  9 17:13:18 1999
@@ -248,7 +248,7 @@
 	    (void) fputs("!\n", stderr);	/* why do we need this ? */
 	return (0);
     }
-    num_tokens = scanner(input_line);
+    num_tokens = scanner(&input_line, &input_line_len);
     c_token = 0;
     while (c_token < num_tokens) {
 	if (command())
@@ -728,7 +728,7 @@
     plot_token = 0;		/* whole line to be saved as replot line */
 
     screen_ok = FALSE;
-    num_tokens = scanner(input_line);
+    num_tokens = scanner(&input_line, &input_line_len);
     c_token = 1;		/* skip the 'plot' part */
     if (is_3d_plot)
 	plot3drequest();
@@ -1006,7 +1006,7 @@
 		    else
 			(void) strcpy(prompt, "Help topic: ");
 		    read_line(prompt);
-		    num_tokens = scanner(input_line);
+		    num_tokens = scanner(&input_line, &input_line_len);
 		    c_token = 0;
 		    more_help = !(END_OF_COMMAND);
 		    if (more_help)
--- docs/gnuplot.doc.ORIG	Wed Oct 27 11:10:16 1999
+++ docs/gnuplot.doc	Thu Dec  9 17:13:25 1999
@@ -1257,7 +1257,7 @@
  blanks.
 
  Command-line substitution can be used anywhere on the `gnuplot` command
- line.
+ line, except inside strings delimited by single quotes.
 
  Example:
 
@@ -1267,6 +1267,11 @@
 
  or, in VMS
        f(x) = `run leastsq`
+
+ These will generate labels with the current time and userid:
+       set label "generated on `date +%Y-%m-%d`by `whoami`" at 1,1
+       set timestamp "generated on %Y-%m-%d by `whoami`"
+
 2 Syntax
 ?syntax
 ?specify
--- protos.h.ORIG	Fri Oct  1 11:37:23 1999
+++ protos.h	Thu Dec  9 17:13:18 1999
@@ -224,7 +224,7 @@
 
 /* Prototypes from file "scanner.c" */
 
-int scanner __PROTO((char expression[]));
+int scanner __PROTO((char **expression, int *line_lengthp));
 
 
 /* Prototypes from "stdfn.c" */
--- scanner.c.ORIG	Wed Nov  4 14:49:57 1998
+++ scanner.c	Thu Dec  9 17:13:18 1999
@@ -37,7 +37,7 @@
 #include "plot.h"
 
 static int get_num __PROTO((char str[]));
-static void substitute __PROTO((char *str, int max));
+static void substitute __PROTO((char **strp, int *str_lenp, int current));
 
 #ifdef AMIGA_AC_5
 #define O_RDONLY	0
@@ -74,9 +74,10 @@
 
 /*
  * scanner() breaks expression[] into lexical units, storing them in token[].
- *   The total number of tokens found is returned as the function value.
- *   Scanning will stop when '\0' is found in expression[], or when token[]
- *     is full.
+ *   The total number of tokens found is returned as the function
+ *   value.  Scanning will stop when '\0' is found in expression[], or
+ *   when token[] is full.  extend_input_line() is called to extend
+ *   expression array if needed.
  *
  *       Scanning is performed by following rules:
  *
@@ -95,13 +96,19 @@
  *      5.  !,<,>       current char; also next if next is =
  *      6.  ", '        all chars up until matching quote
  *      7.  #           this token cuts off scanning of the line (DFK).
+ *      8.  `           (command substitution: all characters through the
+ *                      matching backtic are replaced by the output of
+ *                      the contained command, then scanning is restarted.)
  *
  *                      white space between tokens is ignored
  */
-int scanner(expression)
-char expression[];
+int
+scanner(expressionp, expressionlenp)
+char **expressionp;
+int *expressionlenp;
 {
     register int current;	/* index of current char in expression[] */
+    char *expression = *expressionp;
     register int quote;
     char brace;
 
@@ -118,7 +125,8 @@
 	token[t_num].is_token = TRUE;	/* to start with... */
 
 	if (expression[current] == '`') {
-	    substitute(&expression[current], MAX_LINE_LEN - current);
+	    substitute(expressionp, expressionlenp, current);
+	    expression = *expressionp; /* expression might have moved */
 	    goto again;
 	}
 	/* allow _ to be the first character of an identifier */
@@ -165,6 +173,10 @@
 			   && expression[current + 1]) {
 		    current++;
 		    token[t_num].length += 2;
+		} else if (quote == '\"' && expression[current] == '`') {
+		    substitute(expressionp, expressionlenp, current);
+		    expression = *expressionp; /* it might have moved */
+		    current--;
 		} else
 		    token[t_num].length++;
 	    }
@@ -267,10 +279,6 @@
 
 #if defined(VMS) || defined(PIPES) || (defined(ATARI) || defined(MTOS)) && defined(__PUREC__)
 
-/* this really ought to make use of the dynamic-growth of the
- * input line in 3.6.  And it definitely should not have
- * static arrays !
- */
 /* A macro to reduce clutter ... */
 # ifdef AMIGA_AC_5
 #  define CLOSE_FILE_OR_PIPE ((void) close(fd))
@@ -280,42 +288,58 @@
 #  define CLOSE_FILE_OR_PIPE ((void) pclose(f))
 # endif
 
-static void substitute(str, max)	/* substitute output from ` ` */
-char *str;
-int max;
+/* substitute output from ` ` 
+ * *strp points to the input string.  (*strp)[current] is expected to
+ * be the initial back tic.  Characters through the following back tic
+ * are replaced by the output of the command.  extend_input_line()
+* is called to extend *strp array if needed.
+ */
+static void substitute(strp, str_lenp, current)        
+char **strp;
+int *str_lenp;
+int current;
 {
     register char *last;
-    register int i, c;
+    register int c;
     register FILE *f;
 # ifdef AMIGA_AC_5
     int fd;
 # elif (defined(ATARI) || defined(MTOS)) && defined(__PUREC__)
     char *atari_tmpfile;
-    char *atari_pgm[MAX_LINE_LEN+100];
 # endif /* !AMIGA_AC_5 */
-    static char pgm[MAX_LINE_LEN+1], output[MAX_LINE_LEN+1];
+    char *str, *pgm, *rest = NULL;
+    int pgm_len, rest_len;
 
 # ifdef VMS
     int chan, one = 1;
-    static $DESCRIPTOR(pgmdsc, pgm);
+    struct dsc$descriptor_s pgmdsc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
     static $DESCRIPTOR(lognamedsc, MAILBOX);
 # endif /* VMS */
 
     /* forgive missing closing backquote at end of line */
-    i = 0;
+    str = *strp + current;
     last = str;
     while (*++last) {
-	if (*last == '`') {
-	    ++last;		/* move past it */
+	if (*last == '`')
 	    break;
+    }
+    pgm_len = last - str;
+    pgm = gp_alloc(pgm_len, "command string");
+    safe_strncpy(pgm, str + 1, pgm_len); /* omit ` to leave room for NUL */
+
+    /* save rest of line, if any */
+    if (*last) {
+	last++;                 /* advance past ` */
+	rest_len = strlen(last) + 1;
+	if (rest_len > 1) {
+	    rest = gp_alloc(rest_len, "input line copy");
+	    strcpy(rest, last);
 	}
-	pgm[i++] = *last;
     }
-    pgm[i] = NUL;		/* end with null */
-    max -= strlen(last);	/* max is now the max length of output sub. */
 
 # ifdef VMS
-    pgmdsc.dsc$w_length = i;
+    pgmdsc.dsc$a_pointer = pgm;
+    pgmdsc.dsc$w_length = pgm_len;
     if (!((vaxc$errno = sys$crembx(0, &chan, 0, 0, 0, 0, &lognamedsc)) & 1))
 	os_error("sys$crembx failed", NO_CARET);
 
@@ -327,13 +351,11 @@
 # elif (defined(ATARI) || defined(MTOS)) && defined(__PUREC__)
     if (system(NULL) == 0)
 	os_error("no command shell", NO_CARET);
-    if ((strlen(atari_tmpfile) + strlen(pgm) + 5) > MAX_LINE_LEN + 100)
-	os_error("sorry, command to long", NO_CARET);
     atari_tmpfile = tmpnam(NULL);
-    strcpy(atari_pgm, pgm);
-    strcat(atari_pgm, " >> ");
-    strcat(atari_pgm, atari_tmpfile);
-    system(atari_pgm);
+    gp_realloc(pgm, pgm_len + 5 + strlen(atari_tmpfile), "command string");
+    strcat(pgm, " >> ");
+    strcat(pgm, atari_tmpfile);
+    system(pgm);
     if ((f = fopen(atari_tmpfile, "r")) == NULL)
 # elif defined(AMIGA_AC_5)
     if ((fd = open(pgm, "O_RDONLY")) == -1)
@@ -342,23 +364,36 @@
 	os_error("popen failed", NO_CARET);
 # endif /* !VMS */
 
-    i = 0;
-    while ((c = getc(f)) != EOF) {
-	output[i++] = ((c == '\n') ? ' ' : c);	/* newlines become blanks */
-	if (i == max) {
-	    CLOSE_FILE_OR_PIPE;
-	    int_error("substitution overflow", t_num);
-	}
+    free(pgm);
+
+    /* now replace ` ` with output */
+    while (1) {
+# if defined(AMIGA_AC_5)
+	char ch;
+	if (read(fd, &ch, 1) != 1)
+	    break;
+	c = ch;
+# else
+	if ((c = getc(f)) == EOF)
+	    break;
+# endif /* !AMIGA_AC_5 */
+	/* newlines become blanks */
+	(*strp)[current++] = ((c == '\n') ? ' ' : c); 
+	if (current == *str_lenp)
+	    extend_input_line();
     }
+    (*strp)[current] = 0;
 
     CLOSE_FILE_OR_PIPE;
 
-    if (i + strlen(last) > max)
-	int_error("substitution overflowed rest of line", t_num);
     /* tack on rest of line to output */
-    safe_strncpy(output + i, last, MAX_LINE_LEN - i);
-    /* now replace ` ` with output */
-    safe_strncpy(str, output, max);
+    if (rest) {
+	while (current + rest_len > *str_lenp)
+	    extend_input_line();
+	strcpy(*strp+current, rest);
+	free(rest);
+    }
+
     screen_ok = FALSE;
 }