use m4_normalize on the output strings to remove trailing spaces/tabs and consolidate...
[AROS.git] / workbench / c / Join.c
blob24a0ab18b506abee0fc6f99f5e13b17b205e3419
1 /*
2 Copyright © 1995-2007, The AROS Development Team. All rights reserved.
3 $Id$
5 Join - Create a single file from several.
6 */
8 /******************************************************************************
11 NAME
13 Join [FILE] {(file | pattern)} AS|TO (filename)
15 SYNOPSIS
17 FILE/M/A,AS=TO/K/A
19 LOCATION
23 FUNCTION
25 Join makes one big file of all listed files by putting them together
26 in the order given. The destination file may not have the same name
27 as any of input files. You must supply a destination file name. The
28 original files remain unchanged. Any number of files can be Join:ed in
29 one operation.
31 INPUTS
33 FILE -- files to join
34 TO=AS -- the name of the combined file
36 RESULT
38 NOTES
40 EXAMPLE
42 Join Text1.doc Text2.doc AS Text.doc
43 (This will merge the two text files into one.)
45 BUGS
47 SEE ALSO
49 INTERNALS
51 ******************************************************************************/
53 #define DEBUG 0
54 #include <aros/debug.h>
56 #include <exec/types.h>
57 #include <exec/memory.h>
58 #include <dos/dos.h>
59 #include <dos/dosasl.h>
61 #include <proto/exec.h>
62 #include <proto/dos.h>
64 #define ARG_TEMPLATE "FILE/M/A,AS=TO/K/A"
65 #define ARG_FILE 0
66 #define ARG_AS 1
67 #define ARG_COUNT 2
69 #define BUFFERSIZE 32768 /* Buffersize used when reading & writing */
71 /****** StringID's for getstring() **************************************/
73 #define STR_ABORTED 1 /* Aborted */
74 #define STR_REMOVINGDEST 2 /* Removing destination-file */
75 #define STR_ERR_OPENREAD 3 /* Error opening file for reading */
76 #define STR_ERR_NOMEM 4 /* Error allocating memory */
77 #define STR_ERR_WRITING 5 /* Error while writing to file */
78 #define STR_ERR_OPENWRITE 6 /* Error opening file for writing */
79 #define STR_ERR_READING 7 /* Error while reading from file */
81 /****** Version- and error-header ***************************************/
83 const TEXT version[] = "$VER: Join 41.1 (7.9.1999)";
84 static char ERROR_HEADER[] = "Join";
86 /****** Prototypes for local functions **********************************/
88 LONG append( BPTR destfile , STRPTR srcfilename );
89 STRPTR getstring( LONG stringid );
90 int doJoin(STRPTR *files, BPTR destfile);
92 /****** Functions *******************************************************/
94 int main( void )
96 struct RDArgs *rda = NULL ;
98 IPTR args[ARG_COUNT] = { (IPTR) NULL , (IPTR) NULL };
99 STRPTR *files;
100 STRPTR destination;
101 BPTR destfile = BNULL;
102 LONG rc = RETURN_OK;
104 if( (rda = ReadArgs( ARG_TEMPLATE , args , NULL )) )
106 if( args[ARG_FILE] && args[ARG_AS] )
108 destination = (STRPTR)args[ARG_AS];
109 files = (STRPTR *)args[ARG_FILE];
111 if( (destfile = Open( destination , MODE_NEWFILE )) )
113 rc = doJoin(files, destfile);
114 Close(destfile);
115 if (rc != RETURN_OK)
117 Printf(", %s.\n", getstring(STR_REMOVINGDEST));
118 DeleteFile(destination);
121 else
123 PrintFault(IoErr() , ERROR_HEADER);
124 rc = RETURN_FAIL;
127 else
129 rc = RETURN_FAIL;
132 FreeArgs(rda);
134 else
136 PrintFault(IoErr(), ERROR_HEADER);
137 rc = RETURN_FAIL;
140 return rc;
144 #define MAX_PATH_LEN 512
147 int doJoin(STRPTR *files, BPTR destfile)
149 struct AnchorPath *ap;
151 LONG i; /* Loop variable over patterns */
152 LONG match; /* Loop variable over files */
153 LONG rc = RETURN_OK;
154 ULONG numfiles;
156 ap = (struct AnchorPath *)AllocVec(sizeof(struct AnchorPath) +
157 MAX_PATH_LEN, MEMF_CLEAR);
159 if (ap == NULL)
161 SetIoErr(ERROR_NO_FREE_STORE);
162 return RETURN_FAIL;
165 ap->ap_Strlen = MAX_PATH_LEN;
167 /* Loop over the arguments */
168 for (i = 0; files[i] != NULL; i++)
170 ap->ap_BreakBits = SIGBREAKF_CTRL_C;
171 ap->ap_FoundBreak = 0;
172 numfiles = 0;
173 for (match = MatchFirst(files[i], ap); match == 0;
174 match = MatchNext(ap))
176 if(append(destfile, ap->ap_Buf) != RETURN_OK )
178 Printf("%s: %s", ERROR_HEADER, getstring(STR_ABORTED));
179 rc = RETURN_FAIL;
180 break;
182 numfiles++;
185 MatchEnd(ap);
186 if (ap->ap_FoundBreak & SIGBREAKF_CTRL_C)
188 SetIoErr(ERROR_BREAK);
189 numfiles = 0;
191 if (!numfiles)
193 PrintFault(IoErr(), NULL);
194 rc = RETURN_FAIL;
195 break;
199 FreeVec(ap);
201 return rc;
205 LONG append(BPTR destfile, STRPTR srcfilename)
207 BYTE *buffer = NULL;
208 LONG actualLength = 0;
209 BPTR srcfile = BNULL;
211 BOOL rc = RETURN_OK;
213 if ( (buffer = AllocMem( BUFFERSIZE , MEMF_ANY )) )
215 if ( (srcfile = Open( srcfilename , MODE_OLDFILE )) )
217 ULONG brk;
218 while(!(brk = SetSignal(0,0) & SIGBREAKF_CTRL_C) && (actualLength = Read(srcfile, buffer, BUFFERSIZE)) != -1 )
220 if (Write(destfile, buffer, actualLength) != actualLength )
222 Printf("%s: %s.\n", ERROR_HEADER, getstring(STR_ERR_WRITING));
223 rc = RETURN_FAIL;
225 break;
228 if (actualLength < BUFFERSIZE)
230 break;
233 if (actualLength == -1)
235 PrintFault(IoErr(), NULL);
236 Printf( "%s: %s.\n", (IPTR)ERROR_HEADER,
237 (IPTR)getstring(STR_ERR_READING));
238 rc = RETURN_FAIL;
241 if (brk)
243 PrintFault(ERROR_BREAK, NULL);
244 SetIoErr(ERROR_BREAK);
245 rc = RETURN_FAIL;
248 Close(srcfile);
250 else
252 PrintFault(IoErr(), NULL);
253 Printf("%s: %s: '%s'\n",
254 ERROR_HEADER,
255 getstring(STR_ERR_OPENREAD),
256 srcfilename);
258 rc = RETURN_FAIL;
261 FreeMem(buffer, BUFFERSIZE);
263 else
265 Printf("%s: %s.\n", ERROR_HEADER, getstring(STR_ERR_NOMEM));
266 rc = RETURN_FAIL;
269 return rc;
273 STRPTR getstring(LONG stringid)
275 switch(stringid)
277 case STR_ABORTED:
278 return "Aborted";
280 case STR_REMOVINGDEST:
281 return "removed incomplete destination-file";
283 case STR_ERR_OPENREAD:
284 return "Could not open file for reading";
286 case STR_ERR_NOMEM:
287 return "Could not allocate memory";
289 case STR_ERR_WRITING:
290 return "Error while writing";
292 case STR_ERR_OPENWRITE:
293 return "Could not open file for writing";
295 case STR_ERR_READING:
296 return "Error while writing";
298 default:
299 return "[Error: Unknown StringID]";