1 /******************************************************************************
2 * This file is Copyright 1992 by Philip G. Richards. All Rights Reserved.
3 * See the file README that came with this distribution for permissions on
4 * code usage, copying, and distribution. It comes with absolutely no warranty.
5 ******************************************************************************/
6
7 #include "client.h"
8 #include "main.h"
9 #include "macro.h"
10 #include <stdlib.h>
11
12 typedef struct MACRO {
13 char *name;
14 int length;
15 char **text;
16 char *help;
17 } MACRO;
18
19 static int maxmacro = 0, nummacro = 0;
20 static MACRO *macrotable = (MACRO*)0;
21
22 static int *macrostack = (int*)0;
23 static int stacktop = 0;
24 static int stacklimit = 0;
25 static int *cntstack = (int*)0;
26
27 static void
clean_macro(MACRO * macro)28 clean_macro(MACRO *macro)
29 {
30 if (macro == (MACRO*)0)
31 return;
32
33 macro->name = (char*)0;
34 macro->length = 0;
35 macro->text = (char**)0;
36 macro->help = (char*)0;
37 }
38
39 static void
destroy_macro(MACRO * macro)40 destroy_macro(MACRO *macro)
41 {
42 int i;
43
44 if (macro == (MACRO*)0)
45 return;
46
47 for (i = 0; i < macro->length; i++)
48 (void)free((char*)(macro->text[i]));
49
50 (void)free((char*)(macro->name));
51 (void)free((char*)(macro->help));
52
53 nummacro--;
54
55 clean_macro(macro);
56 }
57
58 static MACRO *
lookup_macro(char * name)59 lookup_macro(char *name)
60 {
61 int i;
62
63 if (macrotable == (MACRO*)0)
64 return (MACRO*)0;
65
66 for (i = 0; i < nummacro; i++)
67 if (macrotable[i].name && strcmp(macrotable[i].name, name) == 0)
68 break;
69
70 return (i < nummacro)? (¯otable[i]): (MACRO*)0;
71 }
72
73 int
remove_macro(char * name)74 remove_macro(char *name)
75 {
76 MACRO *macro;
77
78 macro = lookup_macro(name);
79
80 if (macro)
81 destroy_macro(macro);
82 else
83 ffprintf(STDERR, "?no macro `%s'\n", name);
84
85 return (macro == 0);
86 }
87
88 int
list_macro(char * name)89 list_macro(char *name)
90 {
91 MACRO *macro;
92
93 macro = lookup_macro(name);
94
95 if (macro)
96 {
97 int i;
98
99 ffprintf(STDOUT, "--- Macro `%s': %d lines\n",
100 macro->name, macro->length);
101
102 if (macro->help)
103 ffprintf(STDOUT, " Help text: `%s'\n", macro->help);
104 else
105 ffprintf(STDOUT, " No help text defined\n");
106
107 for (i = 0; i < macro->length; i++)
108 if (macro->text[i])
109 ffprintf(STDOUT, "\t%s\n", macro->text[i]);
110 else
111 ffprintf(STDOUT, "\n");
112
113 ffprintf(STDERR, ".\n");
114 }
115 else
116 ffprintf(STDERR, "?no macro `%s'\n", name);
117
118 return (macro == 0);
119 }
120
121 /***************************************************************************
122 * it is assumed that name will be free'd by the caller (if necessary)
123 * but that macrotext is being handed over fully to this function;
124 * i.e., do what you like with name back in the calling environment,
125 * but under no circumstances free macrotext!
126 ***************************************************************************/
127 int
install_macro(char * name,int macrolen,char ** macrotext,char * macrohelp)128 install_macro(char *name, int macrolen, char **macrotext, char *macrohelp)
129 {
130 MACRO *oldmacro;
131 MACRO *newmacro = (MACRO*)0;
132
133 if (name == (char*)0 || *name == '\0')
134 {
135 ffprintf(STDERR, "?attempt to install null named macro failed\n");
136 return 1;
137 }
138
139 oldmacro = lookup_macro(name);
140
141 if (oldmacro != (MACRO*)0)
142 { /* free the old macro; the new macro can take its place */
143 ffprintf(STDINFO, "?overwriting old macro definition for `%s'\n",
144 name);
145 destroy_macro(oldmacro);
146 newmacro = oldmacro;
147 }
148 else if (nummacro < maxmacro)
149 { /* there is a free space in the table */
150 int i;
151 for (i = 0; i < maxmacro; i++)
152 if (!macrotable[i].name)
153 break;
154
155 /* if this fails then we have *big* problems, oh well, check anyway */
156 if (i < maxmacro)
157 newmacro = ¯otable[i];
158 else
159 {
160 ffprintf(STDERR,"??internal error: nummacro(%d) < maxmacro(%d) and no gap found\n", nummacro, maxmacro);
161 return 1;
162 }
163 }
164 else
165 { /* no free space in table; extend by a bit */
166 maxmacro += 4;
167
168 if (macrotable)
169 macrotable = (MACRO*)realloc((char*)macrotable,
170 sizeof(MACRO) * maxmacro);
171 else
172 macrotable = (MACRO*)malloc(sizeof(MACRO) * maxmacro);
173
174 if (macrotable == (MACRO*)0)
175 {
176 ffprintf(STDERR, "??run out of memory in install_macro()\n");
177 abort();
178 }
179 else
180 {
181 int i;
182 for (i = nummacro + 1; i < maxmacro; i++)
183 clean_macro(¯otable[i]);
184 }
185
186 newmacro = ¯otable[nummacro];
187 }
188
189 nummacro++;
190
191 newmacro->name = strdup(name);
192 newmacro->length = macrolen;
193 newmacro->text = macrotext;
194 newmacro->help = macrohelp? strdup(macrohelp): 0;
195
196 return 0;
197 }
198
199 int
deinstall_macro(char * name)200 deinstall_macro(char *name)
201 {
202 MACRO *macro;
203
204 macro = lookup_macro(name);
205
206 if (macro == (MACRO*)0)
207 {
208 ffprintf(STDERR, "?can not delete macro `%s': doesn't exist\n", name);
209 return 1;
210 }
211
212 destroy_macro(macro);
213
214 return 0;
215 }
216
217 int
initialise_macro(int argc,char ** argv)218 initialise_macro(int argc, char **argv)
219 {
220 MACRO *macro;
221 int i;
222
223 macro = lookup_macro(argv[0]);
224 if (macro == (MACRO*)0)
225 return 1;
226
227 if (dbug_flag > 0)
228 {
229 int i;
230 ffprintf(STDDBG, "\nmacro initialise called with valid macro name:\n");
231 for (i = 0; i <= argc; i++)
232 ffprintf(STDDBG, " $%-2d = \"%s\"\n", i, argv[i]);
233
234 ffprintf(STDDBG, "\ndefinition:\n");
235 for (i = 0; i < macro->length; i++)
236 ffprintf(STDDBG, "%02d: %s\n", i, macro->text[i]);
237
238 ffprintf(STDDBG, "\n");
239 }
240
241 /* we don't allow recursion (yet) so check this isn't trying to */
242 for (i = 0; i < stacktop; i++)
243 if (macro == ¯otable[macrostack[i]])
244 {
245 ffprintf(STDERR,
246 "?attempted recursion in macro `%s' -- ignoring call to `%s'\n",
247 macrotable[macrostack[stacktop-1]].name, macro->name);
248 (void)fflush(STDERR);
249 return 0;
250 }
251
252 /* push this macro onto the macro execution stack */
253 if (stacktop >= stacklimit)
254 {
255 stacklimit += 8;
256
257 if (macrostack)
258 macrostack = (int*)realloc((char*)macrostack,
259 stacklimit * sizeof(int));
260 else
261 macrostack = (int*)malloc(stacklimit * sizeof(int));
262
263 if (cntstack)
264 cntstack = (int*)realloc((char*)cntstack,
265 stacklimit * sizeof(int));
266 else
267 cntstack = (int*)malloc(stacklimit * sizeof(int));
268 }
269
270 macrostack[stacktop] = (int)(macro - macrotable);
271 cntstack[stacktop++] = 0;
272
273 return 0;
274 }
275
276 char *
get_macroline(void)277 get_macroline(void)
278 {
279 if (stacktop > 0)
280 {
281 int st = stacktop - 1;
282 if (cntstack[st] < macrotable[macrostack[st]].length)
283 return (macrotable[macrostack[st]].text[cntstack[st]++]);
284 else
285 stacktop--;
286 }
287
288 return (char*)0;
289 }
290
291 #define NCO 6
292 void
fsp_macro_long_help_all(void)293 fsp_macro_long_help_all(void)
294 {
295 int i;
296 int notext = 0;
297
298 if (macrotable == (MACRO*)0 || nummacro == 0)
299 {
300 ffprintf(STDOUT,"No macros defined\n");
301 return;
302 }
303
304 ffprintf(STDOUT,"Macros are:\n");
305
306 for (i = 0; i < maxmacro; i++)
307 if (macrotable[i].name)
308 {
309 if (macrotable[i].help)
310 ffprintf(STDOUT," %-10s %s\n",
311 macrotable[i].name, macrotable[i].help);
312 else
313 notext++;
314 }
315
316 if (notext)
317 {
318 int j;
319
320 ffprintf(STDOUT,"\nUndocumented macros are:\n");
321
322 for (i = 0, j = 0; i < maxmacro; i++)
323 if (macrotable[i].name)
324 if (!macrotable[i].help)
325 {
326 ffprintf(STDOUT," %-10s%s",
327 macrotable[i].name, j == NCO-1? "\n" : "");
328 j = (j+1) % NCO;
329 }
330
331 if (j)
332 ffprintf(STDOUT,"\n");
333 }
334 }
335
336 int
fsp_macro_long_help(char * name)337 fsp_macro_long_help(char *name)
338 {
339 MACRO *macro;
340
341 macro = lookup_macro(name);
342
343 if (macro)
344 {
345 if (macro->help)
346 ffprintf(STDOUT,"%-10s %s\n", macro->name, macro->help);
347 else
348 ffprintf(STDOUT, "no help available for macro `%s'\n", name);
349 }
350 else
351 return 1;
352
353 return 0;
354 }
355
356 void
fsp_macro_short_help(void)357 fsp_macro_short_help(void)
358 {
359 int i, j;
360
361 if (macrotable == (MACRO*)0 || nummacro == 0)
362 {
363 ffprintf(STDOUT,"No macros defined\n");
364 return;
365 }
366
367 ffprintf(STDOUT,"Macros are:\n");
368
369 for (i = 0, j = 0; i < maxmacro; i++)
370 if (macrotable[i].name)
371 {
372 ffprintf(STDOUT," %-10s%s",
373 macrotable[i].name, j == NCO-1? "\n" : "");
374 j = (j+1) % NCO;
375 }
376
377 if (j)
378 ffprintf(STDOUT,"\n");
379 }
380