]> git.saurik.com Git - wxWidgets.git/blob - utils/Install/sfxzip/rexxapi.c
test for bug with new wu-ftpd
[wxWidgets.git] / utils / Install / sfxzip / rexxapi.c
1 /**********************************************************************
2 * REXXAPI.C *
3 * *
4 * This program adds a ZIP engine directly to the REXX language. *
5 * The functions are: *
6 * UZDropFuncs -- Makes all functions in this package *
7 * unknown to REXX. *
8 * UZLoadFuncs -- Makes all functions in this package *
9 * known to REXX so REXX programs may *
10 * call them. *
11 * UZFileTree -- Searches for files matching a given *
12 * filespec, including files in *
13 * subdirectories. *
14 * UZUnZip -- Unzip command-line entry point. *
15 * This is functionally equivalent to *
16 * using Unzip as an external program. *
17 * UZUnZipToVar -- Unzip one file to a variable *
18 * UZUnZipToStem -- Unzip files to a variable array *
19 * UZVer -- Returns the Unzip version number *
20 * *
21 **********************************************************************/
22 /* Include files */
23
24 #ifdef OS2DLL
25
26 #define INCL_DOS
27 #define INCL_DOSMEMMGR
28 #include <string.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <stdarg.h>
32
33 #define UNZIP_INTERNAL
34 #include "../unzip.h"
35 #include "../version.h"
36
37
38 /*********************************************************************/
39 /* Various definitions used by various functions. */
40 /*********************************************************************/
41
42 RexxFunctionHandler UZDropFuncs;
43 RexxFunctionHandler UZLoadFuncs;
44 RexxFunctionHandler UZFileTree;
45 RexxFunctionHandler UZUnZip;
46 RexxFunctionHandler UZUnZipToVar;
47 RexxFunctionHandler UZUnZipToStem;
48 RexxFunctionHandler UZVer;
49 RexxFunctionHandler UZAPIVer;
50
51
52 int SetOutputVar(__GPRO__ const char *name);
53 int SetOutputVarStem(__GPRO__ const char *name);
54 int SetOutputVarLength(__GPRO);
55 int WriteToVariable(__GPRO__ const char *name, char *buffer, int len);
56 int PrintToSubVariable(__GPRO__ int idx, const char *format,...);
57 int PrintToVariable(__GPRO__ const char *name, const char *format,...);
58 int _PrintToVariable(__GPRO__ const char *name, const char *format, va_list arg_ptr);
59 int TextSetNext(__GPRO__ char *format, int len, int all);
60
61 #define EZRXSTRING(r,p) {(r).strptr=(PCH)p;(r).strlength=(ULONG)strlen((r).strptr);}
62
63
64 /*********************************************************************/
65 /* RxFncTable */
66 /* Array of names of the UNZIPAPI functions. */
67 /* This list is used for registration and deregistration. */
68 /*********************************************************************/
69
70 static PSZ RxFncTable[] =
71 {
72 "UZDropFuncs",
73 "UZLoadFuncs",
74 "UZFileSearch",
75 "UZFileTree",
76 "UZUnZip",
77 "UZUnZipToVar",
78 "UZUnZipToStem",
79 "UZVer",
80 };
81
82 /*********************************************************************/
83 /* Numeric Error Return Strings */
84 /*********************************************************************/
85
86 #define NO_UTIL_ERROR "0" /* No error whatsoever */
87 #define ERROR_NOMEM "2" /* Insufficient memory */
88
89 /*********************************************************************/
90 /* Numeric Return calls */
91 /*********************************************************************/
92
93 #define INVALID_ROUTINE 40 /* Raise Rexx error */
94 #define VALID_ROUTINE 0 /* Successful completion */
95
96 /*********************************************************************/
97 /* Some useful macros */
98 /*********************************************************************/
99
100 #define BUILDRXSTRING(t, s) { \
101 strcpy((t)->strptr,(s));\
102 (t)->strlength = strlen((s)); \
103 }
104
105
106 /*********************************************************************/
107 /**************** UNZIPAPI Supporting Functions ********************/
108 /**************** UNZIPAPI Supporting Functions ********************/
109 /**************** UNZIPAPI Supporting Functions ********************/
110 /*********************************************************************/
111
112
113 int RexxReturn(__GPRO__ int nodefault, RXSTRING *retstr)
114 {
115 int ret = G.os2.rexx_error;
116 if (G.filenotfound)
117 G.os2.rexx_mes = "file not found";
118 if (*G.os2.rexx_mes != '0') {
119 if (retstr->strlength > 255) {
120 DosFreeMem(retstr->strptr);
121 retstr->strptr = NULL;
122 }
123 } else if (nodefault)
124 goto noBuild;
125 BUILDRXSTRING(retstr, G.os2.rexx_mes);
126 noBuild:
127 DESTROYGLOBALS();
128 return ret;
129 }
130
131 /* Get a variable from REXX, return 0 if OK */
132 int GetVariable(__GPRO__ const char *name)
133 {
134 G.os2.request.shvnext = NULL;
135 EZRXSTRING(G.os2.request.shvname, name);
136 G.os2.request.shvnamelen = G.os2.request.shvname.strlength;
137 G.os2.request.shvvalue.strptr = G.os2.buffer;
138 G.os2.request.shvvalue.strlength = IBUF_LEN;
139 G.os2.request.shvvaluelen = IBUF_LEN;
140 G.os2.request.shvcode = RXSHV_SYFET;
141 G.os2.request.shvret = 0;
142 switch (RexxVariablePool(&G.os2.request)) {
143 case RXSHV_MEMFL:
144 G.os2.rexx_mes = ERROR_NOMEM;
145 break;
146 case RXSHV_BADN:
147 case RXSHV_NEWV:
148 G.os2.request.shvvaluelen = 0;
149 case RXSHV_OK:
150 *(G.os2.buffer+G.os2.request.shvvaluelen) = 0;
151 return G.os2.request.shvvaluelen;
152 }
153 return 0;
154 }
155
156
157 /* Get REXX compound variable */
158 /* Stem must exist in G.os2.getvar_buf w/ length in G.os2.getvar_len */
159 int GetVariableIndex(__GPRO__ int index)
160 {
161 sprintf(G.os2.getvar_buf+G.os2.getvar_len,"%d",index);
162 return GetVariable(__G__ G.os2.getvar_buf);
163 }
164
165
166 /* Transfer REXX array to standard C string array */
167 /* Returns number of elements */
168 /* User is responsible for calling KillStringArray */
169
170 int CompoundToStringArray(__GPRO__ char ***pointer, const char *name)
171 {
172 int count;
173 int total;
174 char **trav;
175
176 G.os2.getvar_len = strlen(name);
177 memcpy(G.os2.getvar_buf,name,G.os2.getvar_len+1);
178 if (*(G.os2.getvar_buf+G.os2.getvar_len-1) != '.')
179 *(G.os2.getvar_buf+G.os2.getvar_len++) = '.', *(G.os2.getvar_buf+G.os2.getvar_len) = 0;
180
181 if (GetVariableIndex(__G__ 0))
182 return 0;
183
184 total = atoi(G.os2.buffer);
185 *pointer = (char **)malloc((total+1)<<2);
186 trav = *pointer;
187 for (count = 1; count <= total; count++) {
188 GetVariableIndex(__G__ count);
189 trav[count-1] = (char *)malloc(strlen(G.os2.buffer)+1);
190 strcpy(trav[count-1],G.os2.buffer);
191 }
192 trav[count-1] = NULL;
193 return total;
194 }
195
196
197 /* Kill string array created by CompoundToStringArray */
198
199 void KillStringArray(char **pointer)
200 {
201 char **trav=pointer;
202 while (*trav != NULL) {
203 free(*trav);
204 trav++;
205 }
206 free(pointer);
207 }
208
209
210 /*************************************************************************
211 * Function: UZDropFuncs *
212 * *
213 * Syntax: call UZDropFuncs *
214 * *
215 * Return: NO_UTIL_ERROR - Successful. *
216 *************************************************************************/
217
218 ULONG UZDropFuncs(CHAR *name, ULONG numargs, RXSTRING args[],
219 CHAR *queuename, RXSTRING *retstr)
220 {
221 INT entries; /* Num of entries */
222 INT j; /* Counter */
223
224 if (numargs != 0) /* no arguments for this */
225 return INVALID_ROUTINE; /* raise an error */
226
227 retstr->strlength = 0; /* return a null string result*/
228
229 entries = sizeof(RxFncTable)/sizeof(PSZ);
230
231 for (j = 0; j < entries; j++)
232 RexxDeregisterFunction(RxFncTable[j]);
233
234 return VALID_ROUTINE; /* no error on call */
235 }
236
237
238 /*************************************************************************
239 * Function: UZFileTree *
240 * *
241 * Syntax: call UZFileTree zipfile, stem[, include-filespec] *
242 * [, exclude-filespec][, options] *
243 * *
244 * Params: zipfile - Name of zip file to search. *
245 * stem - Name of stem var to store results in. *
246 * include - Filespec to search for (may include * and ?). *
247 * exclude - Filespec to exclude (may include * and ?). *
248 * options - Either of the following: *
249 * 'F' - Give file statistics. *
250 * Length Date Time Name *
251 * 'Z' - Give zip statistics, too. *
252 * Length Method Size Ratio Date Time CRC-32 Name*
253 * Default is to return only filenames *
254 * *
255 * Return: NO_UTIL_ERROR - Successful. *
256 * ERROR_NOMEM - Out of memory. *
257 *************************************************************************/
258
259 ULONG UZFileTree(CHAR *name, ULONG numargs, RXSTRING args[],
260 CHAR *queuename, RXSTRING *retstr)
261 {
262 /* validate arguments */
263 char *incname[2];
264 char *excname[2];
265 CONSTRUCTGLOBALS();
266
267 if (numargs < 2 || numargs > 5 ||
268 !RXVALIDSTRING(args[0]) ||
269 !RXVALIDSTRING(args[1]) ||
270 args[0].strlength > 255) {
271 DESTROYGLOBALS();
272 return INVALID_ROUTINE; /* Invalid call to routine */
273 }
274 /* initialize data area */
275 SetOutputVarStem(__G__ args[1].strptr);
276 G.wildzipfn = args[0].strptr;
277 G.process_all_files = TRUE;
278
279 uO.lflag = 1;
280 uO.zipinfo_mode = TRUE;
281 uO.C_flag = 1;
282 G.extract_flag = FALSE;
283 uO.qflag = 2;
284
285 if (numargs >= 3 && /* check third option */
286 !RXNULLSTRING(args[2]) &&
287 args[2].strlength > 0) { /* a zero length string isn't */
288 if (!(G.filespecs = CompoundToStringArray(__G__ &G.pfnames,args[2].strptr))) {
289 G.pfnames = incname;
290 incname[0] = args[2].strptr;
291 incname[1] = NULL;
292 G.filespecs = 1;
293 }
294 G.process_all_files = FALSE;
295 }
296
297 if (numargs >= 4 && /* check third option */
298 !RXNULLSTRING(args[3]) &&
299 args[3].strlength > 0) { /* a zero length string isn't */
300 if (!(G.xfilespecs = CompoundToStringArray(__G__ &G.pxnames,args[3].strptr))) {
301 G.pxnames = excname;
302 excname[0] = args[3].strptr;
303 excname[1] = NULL;
304 G.xfilespecs = 1;
305 }
306 G.process_all_files = FALSE;
307 }
308
309 if (numargs == 5 && /* check third option */
310 !RXNULLSTRING(args[4]) &&
311 args[4].strlength > 0) { /* a zero length string isn't */
312 int first = *args[4].strptr & 0x5f;
313
314 if (first == 'Z')
315 uO.vflag = 2, uO.lflag = 0, uO.zipinfo_mode = FALSE;
316 else if (first == 'F')
317 uO.vflag = 1, uO.lflag = 0, uO.zipinfo_mode = FALSE;
318 }
319
320 process_zipfiles(__G);
321 SetOutputVarLength(__G);
322 if (G.filespecs > 0 && G.pfnames != incname)
323 KillStringArray(G.pfnames);
324 if (G.xfilespecs > 0 && G.pxnames != excname)
325 KillStringArray(G.pxnames);
326 return RexxReturn(__G__ 0,retstr); /* no error on call */
327 }
328
329
330 /*************************************************************************
331 * Function: UZUnZipToVar *
332 * *
333 * Syntax: call UZUnZipToVar zipfile, filespec [, stem] *
334 * *
335 * Params: zipfile - Name of zip file to search. *
336 * filespec - File to extract *
337 * stem - If you specify a stem variable, the file will be *
338 * extracted to the variable, one line per index *
339 * In this case, 0 will be returned *
340 * *
341 * Return: Extracted file *
342 * ERROR_NOMEM - Out of memory. *
343 *************************************************************************/
344
345 ULONG UZUnZipToVar(CHAR *name, ULONG numargs, RXSTRING args[],
346 CHAR *queuename, RXSTRING *retstr)
347 {
348 CONSTRUCTGLOBALS();
349 UzpBuffer *ub = (UzpBuffer *)retstr;
350 /* validate arguments */
351 if (numargs < 2 || numargs > 3 ||
352 !RXVALIDSTRING(args[0]) ||
353 !RXVALIDSTRING(args[1]) ||
354 args[0].strlength == 0 ||
355 args[1].strlength == 0) {
356 DESTROYGLOBALS();
357 return INVALID_ROUTINE; /* Invalid call to routine */
358 }
359
360 uO.C_flag = 1;
361 G.redirect_data=1;
362 if (numargs == 3) {
363 if (!RXVALIDSTRING(args[2]) ||
364 RXNULLSTRING(args[1]) ||
365 args[2].strlength == 0) {
366 DESTROYGLOBALS();
367 return INVALID_ROUTINE; /* Invalid call to routine */
368 }
369 SetOutputVarStem(__G__ args[2].strptr);
370 G.redirect_text = 0;
371 G.redirect_data++;
372 }
373 unzipToMemory(__G__ args[0].strptr, args[1].strptr,
374 G.redirect_data==1 ? ub : NULL);
375 return RexxReturn(__G__ G.redirect_data==1,retstr);
376 }
377
378
379 /*************************************************************************
380 * Function: UZUnZipToStem *
381 * *
382 * Syntax: call UZUnZipToStem zipfile, stem[, include-filespec] *
383 * [, exclude-filespec][, mode] *
384 * *
385 * Params: zipfile - Name of zip file to search. *
386 * stem - Name of stem var to store files in. *
387 * include - Filespec to search for (may include * and ?). *
388 * exclude - Filespec to exclude (may include * and ?). *
389 * mode - Specifies 'F'lat or 'T'ree mode. Umm, this is *
390 * hard to explain so I'll give an example, too. *
391 * Assuming a file unzip.zip containing: *
392 * unzip.c *
393 * unshrink.c *
394 * extract.c *
395 * os2/makefile.os2 *
396 * os2/os2.c *
397 * os2/dll/dll.def *
398 * os2/dll/unzipapi.c *
399 * *
400 * -- In flat mode, each file is stored in *
401 * stem.fullname i.e. stem."os2/dll/unzipapi.c" *
402 * A list of files is created in stem.<index> *
403 * *
404 * Flat mode returns: *
405 * stem.0 = 7 *
406 * stem.1 = unzip.c *
407 * stem.2 = unshrink.c *
408 * stem.3 = extract.c *
409 * stem.4 = os2/makefile.os2 *
410 * stem.5 = os2/os2.c *
411 * stem.6 = os2/dll/dll.def *
412 * stem.7 = os2/dll/unzipapi.c *
413 * *
414 * And the following contain the contents of the *
415 * various programs: *
416 * stem.unzip.c *
417 * stem.unshrink.c *
418 * stem.extract.c *
419 * stem.os2/makefile.os2 *
420 * stem.os2/os2.c *
421 * stem.os2/dll/dll.def *
422 * stem.os2/dll/unzipapi.c *
423 * *
424 * -- In tree mode, slashes are converted to periods*
425 * in the pathname thus the above file would have*
426 * been stored in stem.os2.dll.unzipapi.c *
427 * The index would then be stored in stem.OS2. *
428 * DLL.<index>. *
429 * *
430 * NOTE: All path names are converted to uppercase *
431 * *
432 * Tree mode returns: *
433 * stem.0 = 4 *
434 * stem.1 = unzip.c *
435 * stem.2 = unshrink.c *
436 * stem.3 = extract.c *
437 * stem.4 = OS2/ *
438 * *
439 * stem.OS2.0 = 3 *
440 * stem.OS2.1 = makefile.os2 *
441 * stem.OS2.2 = os2.c *
442 * stem.OS2.3 = DLL/ *
443 * *
444 * stem.OS2.DLL.0 = 2 *
445 * stem.OS2.DLL.1 = def *
446 * stem.OS2.DLL.2 = unzipapi.c *
447 * *
448 * And the following contain the contents of the *
449 * various programs: *
450 * stem.unzip.c *
451 * stem.unshrink.c *
452 * stem.extract.c *
453 * stem.OS2.makefile.os2 *
454 * stem.OS2.os2.c *
455 * stem.OS2.DLL.dll.def *
456 * stem.OS2.DLL.unzipapi.c *
457 * *
458 * *
459 * Return: NO_UTIL_ERROR - Successful. *
460 * ERROR_NOMEM - Out of memory. *
461 *************************************************************************/
462
463 ULONG UZUnZipToStem(CHAR *name, ULONG numargs, RXSTRING args[],
464 CHAR *queuename, RXSTRING *retstr)
465 {
466 char *incname[2];
467 char *excname[2];
468 CONSTRUCTGLOBALS();
469 /* validate arguments */
470 if (numargs < 2 || numargs > 5 ||
471 !RXVALIDSTRING(args[0]) ||
472 !RXVALIDSTRING(args[1]) ||
473 args[0].strlength > 255) {
474 DESTROYGLOBALS();
475 return INVALID_ROUTINE; /* Invalid call to routine */
476 }
477 /* initialize data area */
478 G.wildzipfn = args[0].strptr;
479 G.process_all_files = TRUE;
480
481 uO.C_flag = 1;
482 G.extract_flag = TRUE;
483 SetOutputVarStem(__G__ args[1].strptr);
484 G.redirect_data = 3;
485 G.redirect_text = 0;
486
487 if (numargs >= 3 && /* check third option */
488 !RXNULLSTRING(args[2]) &&
489 args[2].strlength > 0) { /* a zero length string isn't */
490 if (!(G.filespecs = CompoundToStringArray(__G__ &G.pfnames,args[2].strptr))) {
491 G.pfnames = incname;
492 incname[0] = args[2].strptr;
493 incname[1] = NULL;
494 G.filespecs = 1;
495 }
496 G.process_all_files = FALSE;
497 }
498
499 if (numargs >= 4 && /* check third option */
500 !RXNULLSTRING(args[3]) &&
501 args[3].strlength > 0) { /* a zero length string isn't */
502 if (!(G.xfilespecs = CompoundToStringArray(__G__ &G.pxnames,args[3].strptr))) {
503 G.pxnames = excname;
504 excname[0] = args[3].strptr;
505 excname[1] = NULL;
506 G.xfilespecs = 1;
507 }
508 G.process_all_files = FALSE;
509 }
510
511 if (numargs == 5 && /* check third option */
512 !RXNULLSTRING(args[4]) &&
513 (*args[4].strptr & 0x5f) == 'T') {
514 G.redirect_data++;
515 G.os2.request.shvnext = NULL;
516 EZRXSTRING(G.os2.request.shvname, args[4].strptr);
517 G.os2.request.shvnamelen = G.os2.request.shvname.strlength;
518 G.os2.request.shvcode = RXSHV_SYDRO;
519 G.os2.request.shvret = 0;
520 RexxVariablePool(&G.os2.request);
521 }
522
523
524 uO.qflag = 2;
525
526 process_zipfiles(__G);
527 if (G.filespecs > 0 && G.pfnames != incname)
528 KillStringArray(G.pfnames);
529 if (G.xfilespecs > 0 && G.pxnames != excname)
530 KillStringArray(G.pxnames);
531 if (G.redirect_data == 3)
532 SetOutputVarLength(__G);
533 return RexxReturn(__G__ 0,retstr); /* no error on call */
534 }
535
536
537 /*************************************************************************
538 * Function: UZLoadFuncs *
539 * *
540 * Syntax: call UZLoadFuncs [option] *
541 * *
542 * Params: none *
543 * *
544 * Return: null string *
545 *************************************************************************/
546
547 ULONG UZLoadFuncs(CHAR *name, ULONG numargs, RXSTRING args[],
548 CHAR *queuename, RXSTRING *retstr)
549 {
550 INT entries; /* Num of entries */
551 INT j; /* Counter */
552
553 retstr->strlength = 0; /* set return value */
554 /* check arguments */
555 if (numargs > 0)
556 return INVALID_ROUTINE;
557
558 entries = sizeof(RxFncTable)/sizeof(PSZ);
559
560 for (j = 0; j < entries; j++) {
561 RexxRegisterFunctionDll(RxFncTable[j],
562 "UNZIP32", RxFncTable[j]);
563 }
564 return VALID_ROUTINE;
565 }
566
567
568
569 /*************************************************************************
570 * Function: UZVer *
571 * *
572 * Syntax: call UZVer *
573 * *
574 * Return: Version of Unzip *
575 *************************************************************************/
576
577 ULONG UZVer(CHAR *name, ULONG numargs, RXSTRING args[],
578 CHAR *queuename, RXSTRING *retstr)
579 {
580 if (numargs > 1) /* validate arg count */
581 return INVALID_ROUTINE;
582
583 if (numargs == 0 || (*args[0].strptr & 0x5f) != 'L')
584 /* strcpy( retstr->strptr, UZ_VERNUM ); "5.13a BETA" */
585 sprintf( retstr->strptr, "%d.%d%d%s", UZ_MAJORVER, UZ_MINORVER,
586 PATCHLEVEL, BETALEVEL );
587 else
588 /* strcpy( retstr->strptr, UZ_VERSION ); UZ_VERNUM" of 26 Sep 94" */
589 sprintf( retstr->strptr, "%d.%d%d%s of %s", UZ_MAJORVER, UZ_MINORVER,
590 PATCHLEVEL, BETALEVEL, VERSION_DATE );
591 retstr->strlength = strlen(retstr->strptr);
592 return VALID_ROUTINE;
593 }
594
595
596 /*************************************************************************
597 * Function: UZUnZip *
598 * *
599 * Syntax: call UZUnZip *
600 * *
601 * Return: Unzip return code *
602 *************************************************************************/
603
604 ULONG UZUnZip(CHAR *name, ULONG numargs, RXSTRING args[],
605 CHAR *queuename, RXSTRING *retstr)
606 {
607 char *argv[30];
608 char *scan;
609 int argc=0;
610 int idx;
611 CONSTRUCTGLOBALS();
612
613 if (numargs < 1 || numargs > 2 ||
614 args[0].strlength > 255) {
615 DESTROYGLOBALS();
616 return INVALID_ROUTINE; /* Invalid call to routine */
617 }
618 /* initialize data area */
619 if (numargs == 2)
620 SetOutputVarStem(__G__ args[1].strptr);
621
622 scan = args[0].strptr;
623 argv[argc++] = ""; /* D:\\SOURCECODE\\UNZIP51S\\UNZIP.COM"; */
624 while (*scan == ' ')
625 scan++;
626 argv[argc++] = scan;
627 while ( (scan = strchr(scan,' ')) != NULL) {
628 *scan++ = 0;
629 while (*scan == ' ')
630 scan++;
631 argv[argc++] = scan;
632 }
633 if (*argv[argc-1] == 0)
634 argc--;
635 argv[argc] = 0;
636
637 /* GRR: should resetMainFlags() be called in here somewhere? */
638
639 sprintf(retstr->strptr, "%d", unzip(__G__ argc, argv)); /* a.k.a. MAIN() */
640 if (numargs == 2)
641 SetOutputVarLength(__G);
642 retstr->strlength = strlen(retstr->strptr);
643 return RexxReturn(__G__ 1,retstr);
644 }
645
646 int varmessage(__GPRO__ uch *buf, ulg size)
647 {
648 if (size > 0)
649 memcpy(G.os2.buffer+G.os2.putchar_idx,buf,size);
650 G.os2.putchar_idx = TextSetNext(__G__ G.os2.buffer, size+G.os2.putchar_idx,0);
651 return 0;
652 }
653
654 int varputchar(__GPRO__ int c)
655 {
656 G.os2.buffer[G.os2.putchar_idx++] = c;
657 if (c == '\n') {
658 G.os2.buffer[G.os2.putchar_idx] = 0;
659 if (G.os2.output_var[0])
660 G.os2.putchar_idx = TextSetNext(__G__ G.os2.buffer, G.os2.putchar_idx,0);
661 else {
662 G.os2.buffer[--G.os2.putchar_idx] = 0;
663 puts(G.os2.buffer);
664 G.os2.putchar_idx = 0;
665 }
666 }
667 return 1;
668 }
669
670
671
672 int SetOutputVarStem(__GPRO__ const char *name)
673 {
674 int len=strlen(name);
675 G.redirect_text=1;
676 G.os2.output_idx = 0;
677 strcpy(G.os2.output_var, name);
678 if (len) {
679 strupr(G.os2.output_var); /* uppercase the name */
680 if (*(G.os2.output_var+len-1) != '.') {
681 *(G.os2.output_var+len) = '.';
682 len++;
683 *(G.os2.output_var+len) = 0;
684 }
685 WriteToVariable(__G__ G.os2.output_var,"",0);
686 }
687 G.os2.stem_len = len;
688 return G.os2.stem_len;
689 }
690
691 int SetOutputVar(__GPRO__ const char *name)
692 {
693 int len=strlen(name);
694 G.redirect_text=1;
695 G.os2.output_idx = 0;
696 strcpy(G.os2.output_var, name);
697 strupr(G.os2.output_var); /* uppercase the name */
698 if (*(name+len-1) == '.')
699 G.os2.stem_len = len;
700 else
701 G.os2.stem_len = 0;
702 return G.os2.stem_len;
703 }
704
705 int SetOutputVarLength(__GPRO)
706 {
707 if (G.os2.stem_len > 0) {
708 if (G.os2.putchar_idx)
709 TextSetNext(__G__ G.os2.buffer,G.os2.putchar_idx,1);
710 return PrintToSubVariable(__G__ 0,"%d",G.os2.output_idx);
711 }
712 return 0;
713 }
714
715 int PrintToVariable(__GPRO__ const char *name, const char *format,...)
716 {
717 va_list arg_ptr;
718 int ret;
719
720 va_start(arg_ptr, format);
721 ret = _PrintToVariable(__G__ name, format, arg_ptr);
722 va_end(arg_ptr);
723 return ret;
724 }
725
726 int WriteToVariable(__GPRO__ const char *name, char *buffer, int len)
727 {
728 G.os2.request.shvnext = NULL;
729 EZRXSTRING(G.os2.request.shvname, name);
730 G.os2.request.shvnamelen = G.os2.request.shvname.strlength;
731 G.os2.request.shvvalue.strptr = buffer;
732 G.os2.request.shvvalue.strlength = len;
733 G.os2.request.shvvaluelen = len;
734 G.os2.request.shvcode = RXSHV_SET;
735 G.os2.request.shvret = 0;
736 switch (RexxVariablePool(&G.os2.request)) {
737 case RXSHV_BADN:
738 G.os2.rexx_error = INVALID_ROUTINE;
739 break;
740 case RXSHV_MEMFL:
741 G.os2.rexx_mes = ERROR_NOMEM;
742 break;
743 case RXSHV_OK:
744 return 0;
745 }
746 return INVALID_ROUTINE; /* error on non-zero */
747 }
748
749 int _PrintToVariable(__GPRO__ const char *name, const char *format, va_list arg_ptr)
750 {
751 int ret = vsprintf(G.os2.buffer, format, arg_ptr);
752 WriteToVariable(__G__ name, G.os2.buffer, strlen(G.os2.buffer));
753 return ret;
754 }
755
756 int PrintToSubVariable(__GPRO__ int idx, const char *format, ...)
757 {
758 va_list arg_ptr;
759 int ret;
760
761 if (G.os2.stem_len == 0)
762 return INVALID_ROUTINE; /* error on non-zero */
763 sprintf(G.os2.output_var+G.os2.stem_len,"%d",idx);
764
765 va_start(arg_ptr, format);
766 ret = _PrintToVariable(__G__ G.os2.output_var, format, arg_ptr);
767 va_end(arg_ptr);
768 return ret;
769 }
770
771
772 int WriteToNextVariable(__GPRO__ char *buffer, int len)
773 {
774 if (G.os2.stem_len > 0) {
775 G.os2.output_idx++;
776 sprintf(G.os2.output_var+G.os2.stem_len,"%d",G.os2.output_idx);
777 }
778 return WriteToVariable(__G__ G.os2.output_var, buffer, len);
779 }
780
781
782 int TextSetNext(__GPRO__ char *buffer, int len, int all)
783 {
784 char *scan = buffer, *next, *base=buffer;
785 int remaining=len;
786 int ret;
787
788 while ((next = strchr(scan,'\n')) != NULL && remaining > 0) {
789 if (next > scan && *(next-1) == 0xd)
790 *(next-1) = 0;
791 else
792 *next = 0;
793 if (WriteToNextVariable(__G__ scan,strlen(scan)))
794 return 0;
795 next++;
796 remaining -= (next-scan);
797 scan = next;
798 }
799 if (remaining > 0)
800 if (all) {
801 *(scan+remaining) = 0;
802 WriteToNextVariable(__G__ scan,remaining);
803 } else {
804 memcpy(buffer,scan,remaining);
805 return remaining;
806 }
807
808 return 0;
809 }
810
811 int finish_REXX_redirect(__GPRO)
812 {
813 char *scan, *ptr;
814 int idx=0, first=1, offset;
815
816 if (!G.redirect_size)
817 return 0;
818 switch(G.redirect_data) {
819 case 1:
820 break;
821 case 2:
822 TextSetNext(__G__ G.redirect_buffer, G.redirect_size, 1);
823 SetOutputVarLength(__G);
824 DosFreeMem(G.redirect_buffer);
825 G.redirect_buffer = NULL;
826 G.redirect_size = 0;
827 break;
828 case 3:
829 WriteToNextVariable(__G__ G.filename,strlen(G.filename));
830 sprintf(G.os2.output_var+G.os2.stem_len,G.filename);
831 WriteToVariable(__G__ G.os2.output_var, G.redirect_buffer, G.redirect_size);
832 DosFreeMem(G.redirect_buffer);
833 G.redirect_buffer = NULL;
834 G.redirect_size = 0;
835 break;
836 case 4:
837 if ((scan = strrchr(G.filename,'/')) != NULL) {
838 idx = *scan;
839 *scan = 0;
840 strupr(G.filename);
841 *scan = idx;
842 }
843 scan = G.os2.output_var+G.os2.stem_len;
844 strcpy(scan,G.filename);
845 while ((scan = strchr(scan,'/')) != NULL)
846 *scan = '.';
847 WriteToVariable(__G__ G.os2.output_var, G.redirect_buffer, G.redirect_size);
848 DosFreeMem(G.redirect_buffer);
849 G.redirect_buffer = NULL;
850 G.redirect_size = 0;
851 strcpy(G.os2.getvar_buf, G.os2.output_var);
852 do {
853 if ((scan = strrchr(G.filename,'/')) == NULL)
854 offset = 0;
855 else
856 offset = scan-G.filename+1;
857 if (first || !GetVariable(__G__ G.os2.output_var)) {
858 ptr = G.os2.getvar_buf+offset+G.os2.stem_len;
859 *ptr = '0';
860 *(ptr+1) = 0;
861 if (!GetVariable(__G__ G.os2.getvar_buf))
862 idx = 1;
863 else
864 idx = atoi(G.os2.buffer)+1;
865 PrintToVariable(__G__ G.os2.getvar_buf,"%d",idx);
866 sprintf(ptr,"%d",idx);
867 if (!first) {
868 PrintToVariable(__G__ G.os2.output_var,"%d",idx);
869 idx = strlen(G.filename);
870 *(G.filename+idx) = '/';
871 *(G.filename+idx+1) = 0;
872 }
873 WriteToVariable(__G__ G.os2.getvar_buf,G.filename+offset,strlen(G.filename+offset));
874 first=0;
875 }
876 if (offset) {
877 *(G.os2.output_var+G.os2.stem_len+offset-1) = 0;
878 *scan = 0;
879 }
880 } while (offset);
881 break;
882 }
883 return 0;
884 }
885
886 #endif /* OS2DLL */