summaryrefslogtreecommitdiff
path: root/flip.cpp
blob: cfe8fe7a951a30e6079682d23df498129e2b9eef (plain)
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
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
//
// Programmer:    Stef
// Last Modified: Tue Aug 31 22:34:27 GMT+0700 1999
// $Smake:        cc -ansi -m486 -O -o %b %f -lg++ && strip %b
// $Smake-linux:  g++ -ansi -m486 -O3 -o %b %f && strip %b
//
//
// Original idea from Craig Stuart Sapp <craig@ccrma.stanford.edu>
// Modified by Stef to support input of filenames from STDIN
// And to ignore Binary Files
//
// Description: Utility program to convert text files between
//		UNIX newlines and DOS linefeed + newlines
//
//              Unix uses the character 0x0a to start a new line
//		while DOS uses two characters: 0x0d 0x0a
//
//		Options are:
//			-u make the file Unix/MAC conformant
//			-d make the file DOS conformant
//			-f force it to process binary files
//			-l read a list of files from STDIN
//
//		Multiple files can be processed at once on the command line
//

#include <iostream.h>
#include <fstream.h>
#include <strstrea.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h> 

// Added By Stef
#define MAX_PATH	256

void exit_usage(const char* command);
int translate_to_unix(istream& in, ostream& out);
int translate_to_dos(istream& in, ostream& out);
void process_file(const char* filename);

// Globals
char g_cMode;	// Current Mode
bool g_bForce;	// Force Binary Mode
bool g_nRet;	// ErrorLevel Return value


int main(int argc, char* argv[]) 
{
	// Sanity Syntax Check
   if (argc < 2) 
	   exit_usage(argv[0]);
   if (argv[1][0] != '-' && argv[1][0] != '/') 
	   exit_usage(argv[0]);

   // Set Defaults
   g_cMode = '\0';
   g_bForce = false;
   g_nRet = 0;
   bool bStdIn = true;	// Should we read from STDIN
   bool bFiles = false;	// Read Files (not data) from STDIN

   // Process Arguments
   for(int nCnt = 1; nCnt < argc; nCnt++)
   {
		// Is it a parameter?	
		if(argv[nCnt][0] == '-' || argv[nCnt][0] == '/')
		{
			switch(argv[nCnt][1])
			{
			case 'u':
			case 'd':
				g_cMode = argv[nCnt][1];
				break;
			case 'l':
				bFiles = true;
				break;
			case 'f':
				g_bForce = true;
				break;
			default:
				break;
			}

			continue;
		}

		// If no mode set yet then syntax prob
		if(g_cMode == '\0')
			exit_usage(argv[0]);

		// Don't read from StdIn
		bStdIn = false;
		process_file(argv[nCnt]);
	}

	if(bStdIn)
	{
		// Read file list from stin
		if(bFiles)
		{
			char szBuff[MAX_PATH];
			while(!cin.eof())
			{
				// Get a line
				cin.get(szBuff, MAX_PATH, '\n');
				cin.get();

				// Process it if there's something
				if(strlen(szBuff))
					process_file(szBuff);
			}
		}
		else
			// Just process the stdin raw
			process_file(NULL);
	}

	return g_nRet;
}

////////////////////////////////
//
// process_file

void process_file(const char* filename)
{
	char fileTemp[MAX_PATH];	// Backup Filename
	int nRet = 0;				// Return Value

	// If filename is NULL means stdin -> stdout (below)
	if(filename)
	{
		// Construct Backup File Name
		strcpy(fileTemp, filename);
		strcat(fileTemp, "._x");
		strcat(fileTemp, &g_cMode);

		// If it exists dump it
		remove(fileTemp);

		// Rename original to backup
		if(rename(filename, fileTemp))
		{
			cerr << "Error: ";
			perror(filename);
			g_nRet++; return;
		}

		// Open original file
		fstream infile(fileTemp, ios::in | ios::binary | ios::nocreate);
		if (!infile) {
			cerr << "Error: cannot find file " << fileTemp << endl;
			g_nRet++; return;
		}

		// Open output file
		fstream outfile(filename, ios::out | ios::binary);
		if (!outfile) {
			cerr << "Error: cannot write to file: " << filename << endl;
			g_nRet++; return;
		}

		// Translate File
		if (g_cMode == 'd') 
			nRet = translate_to_dos(infile, outfile);
		else if (g_cMode == 'u') 
			nRet = translate_to_unix(infile, outfile);

		// Clean Up
		infile.close();
		outfile.close();

		// If errors then move everything back
		if(nRet)
		{
			remove(filename);
			rename(fileTemp, filename);
		}
	}
	// stdin -> stdout
	else
	{

		if (g_cMode == 'd') 
			nRet = translate_to_dos(cin, cout);
		else if (g_cMode == 'u') 
			nRet = translate_to_unix(cin, cout);

	}

	// Put file name at end of conversion error message
	if(nRet)
	{
		g_nRet++;
		cerr << filename << endl;
	}
}


//////////////////////////////
//
// translate_to_dos
//

int translate_to_dos(istream& in, ostream& out) 
{
	char szBuff[1024];	// Read at most 1K at a time
	int nLen = 0;		// Length of current line

	while (!in.eof()) 
	{
		in.getline(szBuff, 1024);

		nLen = strlen(szBuff);

		// Check for Binary characters for now that's ASCII 0 - 31
		// excluding \n \r \t
		if(!g_bForce) 
		{
			char* psz = szBuff;
			for(; psz < szBuff + nLen; psz++)
			{
				if(psz[0] < 0x20 && psz[0] > -1 &&
					psz[0] != '\n' && psz[0] != '\t' && psz[0] != '\r')
				{
					cerr << "Error: File is Binary: "; // process_file puts filename
					return 1;
				}
			}
		}

		// Remove Line ending
		if(szBuff[nLen - 1] == 0x0a)
			nLen--;
		if(szBuff[nLen - 1] == 0x0d)
			nLen--;

		out.write(szBuff, nLen);

		if (in.eof())
			break;

		// Add DOS ending
		out.put((char)0x0d);
		out.put((char)0x0a);
   }
     
   return 0;
}



//////////////////////////////
//
// translate_to_unix
//

int translate_to_unix(istream& in, ostream& out) 
{
	char szBuff[1024];	// Read at most 1K at a time
	int nLen = 0;		// Length of current line

	while (!in.eof()) 
	{
		in.getline(szBuff, 1024);

		nLen = strlen(szBuff);

		// Check for Binary characters for now that's ASCII 0 - 31
		// excluding \n \r \t
		if(!g_bForce)
		{
			char* psz = szBuff;
			for(; psz < szBuff + nLen; psz++)
			{
				if(psz[0] < 0x20 && psz[0] > -1 &&
					psz[0] != '\n' && psz[0] != '\t' && psz[0] != '\r')
				{
					cerr << "Error: File is Binary: "; // process_file puts filename
					return 1;
				}
			}
		}

		// Remove ending
		if(szBuff[nLen - 1] == 0x0a)
			nLen--;
		if(szBuff[nLen - 1] == 0x0d)
			nLen--;

		out.write(szBuff, nLen);

		if (in.eof())
			break;

		// Add Unix Ending
		out.put((char)0x0a);

	}

	return 0;
}
         
//////////////////////////////
//
// exit_usage
//

void exit_usage(const char* commandName) 
{
   cout << endl;
   cout << "Usage: " << commandName << " option filename[s]" << endl;
   cout << "   Converts ascii files to either unix or dos format" << endl;
   cout << "   If no file parameters reads from stdin" << endl;
   cout << endl;
   cout << "   Options: " << endl;
   cout << "      -u  =  convert to unix format (newline)" << endl;
   cout << "      -d  =  convert to dos format (linefeed + newline)" << endl;
   cout << "      -f  =  force conversion even if binary found" << endl;
   cout << "      -l  =  read a list of filenames from stdin" << endl;
   cout << endl;
   cout << endl;

   exit(1);
}