rjhead 0.2.88
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +5 -0
- data/LICENSE +20 -0
- data/README.rdoc +18 -0
- data/Rakefile +57 -0
- data/VERSION +1 -0
- data/ext/changes.txt +351 -0
- data/ext/exif.c +1629 -0
- data/ext/extconf.rb +0 -0
- data/ext/gpsinfo.c +217 -0
- data/ext/iptc.c +205 -0
- data/ext/jhead.1 +409 -0
- data/ext/jhead.c +1697 -0
- data/ext/jhead.h +251 -0
- data/ext/jhead.spec +149 -0
- data/ext/jpgfile.c +738 -0
- data/ext/make.bat +1 -0
- data/ext/makefile +23 -0
- data/ext/makefile-win32 +27 -0
- data/ext/makernote.c +184 -0
- data/ext/myglob.c +305 -0
- data/ext/paths.c +140 -0
- data/ext/readme.txt +60 -0
- data/ext/usage.html +469 -0
- data/lib/rjhead.rb +0 -0
- data/rjhead.gemspec +73 -0
- data/setup.rake +1 -0
- data/test/rjhead_test.rb +7 -0
- data/test/test_helper.rb +10 -0
- metadata +94 -0
data/ext/make.bat
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
nmake -f makefile-win32
|
data/ext/makefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#--------------------------------
|
2
|
+
# jhead makefile for Unix
|
3
|
+
#--------------------------------
|
4
|
+
OBJ=.
|
5
|
+
SRC=.
|
6
|
+
CFLAGS= -O3 -Wall
|
7
|
+
|
8
|
+
all: jhead
|
9
|
+
|
10
|
+
objs = $(OBJ)/jhead.o $(OBJ)/jpgfile.o $(OBJ)/paths.o \
|
11
|
+
$(OBJ)/exif.o $(OBJ)/iptc.o $(OBJ)/gpsinfo.o $(OBJ)/makernote.o
|
12
|
+
|
13
|
+
$(OBJ)/%.o:$(SRC)/%.c
|
14
|
+
${CC} $(CFLAGS) -c $< -o $@
|
15
|
+
|
16
|
+
jhead: $(objs) jhead.h
|
17
|
+
${CC} -o jhead $(objs) -lm
|
18
|
+
|
19
|
+
clean:
|
20
|
+
rm -f $(objs) jhead
|
21
|
+
|
22
|
+
install:
|
23
|
+
mkdir -p ../bin; cp jhead ../bin/jhead
|
data/ext/makefile-win32
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#--------------------------------
|
2
|
+
# jhead makefile for Win32
|
3
|
+
#--------------------------------
|
4
|
+
|
5
|
+
CC=cl /nologo
|
6
|
+
CFLAGS=-c -G3 -Ox -W3 -Zp -Zd
|
7
|
+
LINKER=link
|
8
|
+
LINKCON = /nologo
|
9
|
+
|
10
|
+
all:jhead.exe
|
11
|
+
|
12
|
+
OBJ = .
|
13
|
+
|
14
|
+
OBJECTS_JHEAD = $(OBJ)\jhead.obj \
|
15
|
+
$(OBJ)\jpgfile.obj \
|
16
|
+
$(OBJ)\myglob.obj \
|
17
|
+
$(OBJ)\paths.obj \
|
18
|
+
$(OBJ)\exif.obj \
|
19
|
+
$(OBJ)\iptc.obj \
|
20
|
+
$(OBJ)\gpsinfo.obj \
|
21
|
+
$(OBJ)\makernote.obj
|
22
|
+
|
23
|
+
$(OBJECTS_JHEAD): $(@B).c jhead.h
|
24
|
+
$(CC) /Fo$(OBJ)\ $(CFLAGS) $(@B).c
|
25
|
+
|
26
|
+
jhead.exe: $(OBJECTS_JHEAD)
|
27
|
+
$(LINKER) $(LINKCON) -OUT:jhead.exe $(OBJECTS_JHEAD)
|
data/ext/makernote.c
ADDED
@@ -0,0 +1,184 @@
|
|
1
|
+
//--------------------------------------------------------------------------
|
2
|
+
// Parse some maker specific onformation.
|
3
|
+
// (Very limited right now - add maker specific stuff to this module)
|
4
|
+
//--------------------------------------------------------------------------
|
5
|
+
#include "jhead.h"
|
6
|
+
|
7
|
+
//--------------------------------------------------------------------------
|
8
|
+
// Process exif format directory, as used by Cannon maker note
|
9
|
+
//--------------------------------------------------------------------------
|
10
|
+
void ProcessCanonMakerNoteDir(unsigned char * DirStart, unsigned char * OffsetBase,
|
11
|
+
unsigned ExifLength)
|
12
|
+
{
|
13
|
+
int de;
|
14
|
+
int a;
|
15
|
+
int NumDirEntries;
|
16
|
+
|
17
|
+
NumDirEntries = Get16u(DirStart);
|
18
|
+
#define DIR_ENTRY_ADDR(Start, Entry) (Start+2+12*(Entry))
|
19
|
+
|
20
|
+
{
|
21
|
+
unsigned char * DirEnd;
|
22
|
+
DirEnd = DIR_ENTRY_ADDR(DirStart, NumDirEntries);
|
23
|
+
if (DirEnd > (OffsetBase+ExifLength)){
|
24
|
+
ErrNonfatal("Illegally sized Exif makernote subdir (%d entries)",NumDirEntries,0);
|
25
|
+
return;
|
26
|
+
}
|
27
|
+
|
28
|
+
if (DumpExifMap){
|
29
|
+
printf("Map: %05d-%05d: Directory (makernote)\n",(int)(DirStart-OffsetBase), (int)(DirEnd-OffsetBase));
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
if (ShowTags){
|
34
|
+
printf("(dir has %d entries)\n",NumDirEntries);
|
35
|
+
}
|
36
|
+
|
37
|
+
for (de=0;de<NumDirEntries;de++){
|
38
|
+
int Tag, Format, Components;
|
39
|
+
unsigned char * ValuePtr;
|
40
|
+
int ByteCount;
|
41
|
+
unsigned char * DirEntry;
|
42
|
+
DirEntry = DIR_ENTRY_ADDR(DirStart, de);
|
43
|
+
|
44
|
+
Tag = Get16u(DirEntry);
|
45
|
+
Format = Get16u(DirEntry+2);
|
46
|
+
Components = Get32u(DirEntry+4);
|
47
|
+
|
48
|
+
if ((Format-1) >= NUM_FORMATS) {
|
49
|
+
// (-1) catches illegal zero case as unsigned underflows to positive large.
|
50
|
+
ErrNonfatal("Illegal Exif number format %d for maker tag %04x", Format, Tag);
|
51
|
+
continue;
|
52
|
+
}
|
53
|
+
|
54
|
+
if ((unsigned)Components > 0x10000){
|
55
|
+
ErrNonfatal("Too many components (%d) for Exif maker tag %04x", Components, Tag);
|
56
|
+
continue;
|
57
|
+
}
|
58
|
+
|
59
|
+
ByteCount = Components * BytesPerFormat[Format];
|
60
|
+
|
61
|
+
if (ByteCount > 4){
|
62
|
+
unsigned OffsetVal;
|
63
|
+
OffsetVal = Get32u(DirEntry+8);
|
64
|
+
// If its bigger than 4 bytes, the dir entry contains an offset.
|
65
|
+
if (OffsetVal+ByteCount > ExifLength){
|
66
|
+
// Bogus pointer offset and / or bytecount value
|
67
|
+
ErrNonfatal("Illegal value pointer for Exif maker tag %04x", Tag,0);
|
68
|
+
continue;
|
69
|
+
}
|
70
|
+
ValuePtr = OffsetBase+OffsetVal;
|
71
|
+
|
72
|
+
if (DumpExifMap){
|
73
|
+
printf("Map: %05d-%05d: Data for makernote tag %04x\n",OffsetVal, OffsetVal+ByteCount, Tag);
|
74
|
+
}
|
75
|
+
}else{
|
76
|
+
// 4 bytes or less and value is in the dir entry itself
|
77
|
+
ValuePtr = DirEntry+8;
|
78
|
+
}
|
79
|
+
|
80
|
+
if (ShowTags){
|
81
|
+
// Show tag name
|
82
|
+
printf(" Canon maker tag %04x Value = ", Tag);
|
83
|
+
}
|
84
|
+
|
85
|
+
// Show tag value.
|
86
|
+
switch(Format){
|
87
|
+
|
88
|
+
case FMT_UNDEFINED:
|
89
|
+
// Undefined is typically an ascii string.
|
90
|
+
|
91
|
+
case FMT_STRING:
|
92
|
+
// String arrays printed without function call (different from int arrays)
|
93
|
+
if (ShowTags){
|
94
|
+
printf("\"");
|
95
|
+
for (a=0;a<ByteCount;a++){
|
96
|
+
int ZeroSkipped = 0;
|
97
|
+
if (ValuePtr[a] >= 32){
|
98
|
+
if (ZeroSkipped){
|
99
|
+
printf("?");
|
100
|
+
ZeroSkipped = 0;
|
101
|
+
}
|
102
|
+
putchar(ValuePtr[a]);
|
103
|
+
}else{
|
104
|
+
if (ValuePtr[a] == 0){
|
105
|
+
ZeroSkipped = 1;
|
106
|
+
}
|
107
|
+
}
|
108
|
+
}
|
109
|
+
printf("\"\n");
|
110
|
+
}
|
111
|
+
break;
|
112
|
+
|
113
|
+
default:
|
114
|
+
if (ShowTags){
|
115
|
+
PrintFormatNumber(ValuePtr, Format, ByteCount);
|
116
|
+
printf("\n");
|
117
|
+
}
|
118
|
+
}
|
119
|
+
if (Tag == 1 && Components > 16){
|
120
|
+
int IsoCode = Get16u(ValuePtr + 16*sizeof(unsigned short));
|
121
|
+
if (IsoCode >= 16 && IsoCode <= 24){
|
122
|
+
ImageInfo.ISOequivalent = 50 << (IsoCode-16);
|
123
|
+
}
|
124
|
+
}
|
125
|
+
|
126
|
+
if (Tag == 4 && Format == FMT_USHORT){
|
127
|
+
if (Components > 7){
|
128
|
+
int WhiteBalance = Get16u(ValuePtr + 7*sizeof(unsigned short));
|
129
|
+
switch(WhiteBalance){
|
130
|
+
// 0=Auto, 6=Custom
|
131
|
+
case 1: ImageInfo.LightSource = 1; break; // Sunny
|
132
|
+
case 2: ImageInfo.LightSource = 1; break; // Cloudy
|
133
|
+
case 3: ImageInfo.LightSource = 3; break; // Thungsten
|
134
|
+
case 4: ImageInfo.LightSource = 2; break; // Fourescent
|
135
|
+
case 5: ImageInfo.LightSource = 4; break; // Flash
|
136
|
+
}
|
137
|
+
}
|
138
|
+
if (Components > 19 && ImageInfo.Distance <= 0) {
|
139
|
+
// Indicates the distance the autofocus camera is focused to.
|
140
|
+
// Tends to be less accurate as distance increases.
|
141
|
+
int temp_dist = Get16u(ValuePtr + 19*sizeof(unsigned short));
|
142
|
+
if (temp_dist != 65535){
|
143
|
+
ImageInfo.Distance = (float)temp_dist/100;
|
144
|
+
}else{
|
145
|
+
ImageInfo.Distance = -1 /* infinity */;
|
146
|
+
}
|
147
|
+
}
|
148
|
+
}
|
149
|
+
}
|
150
|
+
}
|
151
|
+
|
152
|
+
//--------------------------------------------------------------------------
|
153
|
+
// Show generic maker note - just hex bytes.
|
154
|
+
//--------------------------------------------------------------------------
|
155
|
+
void ShowMakerNoteGeneric(unsigned char * ValuePtr, int ByteCount)
|
156
|
+
{
|
157
|
+
int a;
|
158
|
+
for (a=0;a<ByteCount;a++){
|
159
|
+
if (a > 10){
|
160
|
+
printf("...");
|
161
|
+
break;
|
162
|
+
}
|
163
|
+
printf(" %02x",ValuePtr[a]);
|
164
|
+
}
|
165
|
+
printf(" (%d bytes)", ByteCount);
|
166
|
+
printf("\n");
|
167
|
+
|
168
|
+
}
|
169
|
+
|
170
|
+
//--------------------------------------------------------------------------
|
171
|
+
// Process maker note - to the limited extent that its supported.
|
172
|
+
//--------------------------------------------------------------------------
|
173
|
+
void ProcessMakerNote(unsigned char * ValuePtr, int ByteCount,
|
174
|
+
unsigned char * OffsetBase, unsigned ExifLength)
|
175
|
+
{
|
176
|
+
if (strstr(ImageInfo.CameraMake, "Canon")){
|
177
|
+
ProcessCanonMakerNoteDir(ValuePtr, OffsetBase, ExifLength);
|
178
|
+
}else{
|
179
|
+
if (ShowTags){
|
180
|
+
ShowMakerNoteGeneric(ValuePtr, ByteCount);
|
181
|
+
}
|
182
|
+
}
|
183
|
+
}
|
184
|
+
|
data/ext/myglob.c
ADDED
@@ -0,0 +1,305 @@
|
|
1
|
+
//--------------------------------------------------------------------------------
|
2
|
+
// Module to do recursive directory file matching under windows.
|
3
|
+
//
|
4
|
+
// Tries to do pattern matching to produce similar results as Unix, but using
|
5
|
+
// the Windows _findfirst to do all the pattern matching.
|
6
|
+
//
|
7
|
+
// Also hadles recursive directories - "**" path component expands into
|
8
|
+
// any levels of subdirectores (ie c:\**\*.c matches ALL .c files on drive c:)
|
9
|
+
//
|
10
|
+
// Matthias Wandel Nov 5 2000
|
11
|
+
//--------------------------------------------------------------------------------
|
12
|
+
#include <stdio.h>
|
13
|
+
#include <stdlib.h>
|
14
|
+
#include <string.h>
|
15
|
+
#include <errno.h>
|
16
|
+
#include <ctype.h>
|
17
|
+
#include <io.h>
|
18
|
+
#include "jhead.h"
|
19
|
+
|
20
|
+
#define TRUE 1
|
21
|
+
#define FALSE 0
|
22
|
+
|
23
|
+
//#define DEBUGGING
|
24
|
+
|
25
|
+
typedef struct {
|
26
|
+
char * Name;
|
27
|
+
int attrib;
|
28
|
+
}FileEntry;
|
29
|
+
|
30
|
+
|
31
|
+
#ifdef DEBUGGING
|
32
|
+
//--------------------------------------------------------------------------------
|
33
|
+
// Dummy function to show operation.
|
34
|
+
//--------------------------------------------------------------------------------
|
35
|
+
void ShowName(const char * FileName)
|
36
|
+
{
|
37
|
+
printf(" %s\n",FileName);
|
38
|
+
}
|
39
|
+
#endif
|
40
|
+
|
41
|
+
//--------------------------------------------------------------------------------
|
42
|
+
// Simple path splicing (assumes no '\' in either part)
|
43
|
+
//--------------------------------------------------------------------------------
|
44
|
+
static void SplicePath(char * dest, const char * p1, const char * p2)
|
45
|
+
{
|
46
|
+
int l;
|
47
|
+
l = strlen(p1);
|
48
|
+
if (!l){
|
49
|
+
strcpy(dest, p2);
|
50
|
+
}else{
|
51
|
+
if (l+strlen(p2) > _MAX_PATH-2){
|
52
|
+
fprintf(stderr,"Path too long\n");
|
53
|
+
exit(-1);
|
54
|
+
}
|
55
|
+
memcpy(dest, p1, l+1);
|
56
|
+
if (dest[l-1] != '\\' && dest[l-1] != ':'){
|
57
|
+
dest[l++] = '\\';
|
58
|
+
}
|
59
|
+
strcpy(dest+l, p2);
|
60
|
+
}
|
61
|
+
}
|
62
|
+
|
63
|
+
//--------------------------------------------------------------------------------
|
64
|
+
// Qsort compare function
|
65
|
+
//--------------------------------------------------------------------------------
|
66
|
+
int CompareFunc(const void * f1, const void * f2)
|
67
|
+
{
|
68
|
+
return strcmp(((FileEntry *)f1)->Name,((FileEntry *)f2)->Name);
|
69
|
+
}
|
70
|
+
|
71
|
+
//--------------------------------------------------------------------------------
|
72
|
+
// Decide how a particular pattern should be handled, and call function for each.
|
73
|
+
//--------------------------------------------------------------------------------
|
74
|
+
void MyGlob(const char * Pattern , void (*FileFuncParm)(const char * FileName))
|
75
|
+
{
|
76
|
+
char BasePattern[_MAX_PATH];
|
77
|
+
char MatchPattern[_MAX_PATH];
|
78
|
+
char PatCopy[_MAX_PATH*2+1];
|
79
|
+
|
80
|
+
int a;
|
81
|
+
|
82
|
+
int MatchFiles, MatchDirs;
|
83
|
+
int BaseEnd, PatternEnd;
|
84
|
+
int SawPat;
|
85
|
+
int RecurseAt;
|
86
|
+
|
87
|
+
strcpy(PatCopy, Pattern);
|
88
|
+
|
89
|
+
#ifdef DEBUGGING
|
90
|
+
printf("Called with '%s'\n",Pattern);
|
91
|
+
#endif
|
92
|
+
|
93
|
+
DoRecursion:
|
94
|
+
MatchFiles = FALSE;
|
95
|
+
MatchDirs = TRUE;
|
96
|
+
BaseEnd = 0;
|
97
|
+
PatternEnd = 0;
|
98
|
+
|
99
|
+
SawPat = FALSE;
|
100
|
+
RecurseAt = -1;
|
101
|
+
|
102
|
+
// Split the path into base path and pattern to match against using findfirst.
|
103
|
+
for (a=0;;a++){
|
104
|
+
if (PatCopy[a] == '*' || PatCopy[a] == '?'){
|
105
|
+
SawPat = TRUE;
|
106
|
+
}
|
107
|
+
|
108
|
+
if (PatCopy[a] == '*' && PatCopy[a+1] == '*'){
|
109
|
+
if (a == 0 || PatCopy[a-1] == '\\' || PatCopy[a-1] == ':'){
|
110
|
+
if (PatCopy[a+2] == '\\' || PatCopy[a+2] == '\0'){
|
111
|
+
// x\**\y ---> x\y x\*\**\y
|
112
|
+
RecurseAt = a;
|
113
|
+
if (PatCopy[a+2]){
|
114
|
+
memcpy(PatCopy+a, PatCopy+a+3, strlen(PatCopy)-a-1);
|
115
|
+
}else{
|
116
|
+
PatCopy[a+1] = '\0';
|
117
|
+
}
|
118
|
+
}
|
119
|
+
}
|
120
|
+
}
|
121
|
+
|
122
|
+
if (PatCopy[a] == '\\' || (PatCopy[a] == ':' && PatCopy[a+1] != '\\')){
|
123
|
+
PatternEnd = a;
|
124
|
+
if (SawPat) break; // Findfirst can only match one level of wildcard at a time.
|
125
|
+
BaseEnd = a+1;
|
126
|
+
}
|
127
|
+
if (PatCopy[a] == '\0'){
|
128
|
+
PatternEnd = a;
|
129
|
+
MatchFiles = TRUE;
|
130
|
+
MatchDirs = FALSE;
|
131
|
+
break;
|
132
|
+
}
|
133
|
+
}
|
134
|
+
|
135
|
+
if (!SawPat){
|
136
|
+
// No pattern. This should refer to a file.
|
137
|
+
FileFuncParm(PatCopy);
|
138
|
+
return;
|
139
|
+
}
|
140
|
+
|
141
|
+
strncpy(BasePattern, PatCopy, BaseEnd);
|
142
|
+
BasePattern[BaseEnd] = 0;
|
143
|
+
|
144
|
+
strncpy(MatchPattern, PatCopy, PatternEnd);
|
145
|
+
MatchPattern[PatternEnd] = 0;
|
146
|
+
|
147
|
+
#ifdef DEBUGGING
|
148
|
+
printf("Base:%s Pattern:%s Files:%d dirs:%d\n",BasePattern, MatchPattern, MatchFiles, MatchDirs);
|
149
|
+
#endif
|
150
|
+
|
151
|
+
{
|
152
|
+
FileEntry * FileList = NULL;
|
153
|
+
int NumAllocated = 0;
|
154
|
+
int NumHave = 0;
|
155
|
+
|
156
|
+
struct _finddata_t finddata;
|
157
|
+
long find_handle;
|
158
|
+
|
159
|
+
find_handle = _findfirst(MatchPattern, &finddata);
|
160
|
+
|
161
|
+
for (;;){
|
162
|
+
if (find_handle == -1) break;
|
163
|
+
|
164
|
+
// Eliminate the obvious patterns.
|
165
|
+
if (!memcmp(finddata.name, ".",2)) goto next_file;
|
166
|
+
if (!memcmp(finddata.name, "..",3)) goto next_file;
|
167
|
+
|
168
|
+
if (finddata.attrib & _A_SUBDIR){
|
169
|
+
if (!MatchDirs) goto next_file;
|
170
|
+
}else{
|
171
|
+
if (!MatchFiles) goto next_file;
|
172
|
+
}
|
173
|
+
|
174
|
+
// Add it to the list.
|
175
|
+
if (NumAllocated <= NumHave){
|
176
|
+
NumAllocated = NumAllocated+10+NumAllocated/2;
|
177
|
+
FileList = realloc(FileList, NumAllocated * sizeof(FileEntry));
|
178
|
+
if (FileList == NULL) goto nomem;
|
179
|
+
}
|
180
|
+
a = strlen(finddata.name);
|
181
|
+
FileList[NumHave].Name = malloc(a+1);
|
182
|
+
if (FileList[NumHave].Name == NULL){
|
183
|
+
nomem:
|
184
|
+
printf("malloc failure\n");
|
185
|
+
exit(-1);
|
186
|
+
}
|
187
|
+
memcpy(FileList[NumHave].Name, finddata.name, a+1);
|
188
|
+
FileList[NumHave].attrib = finddata.attrib;
|
189
|
+
NumHave++;
|
190
|
+
|
191
|
+
next_file:
|
192
|
+
if (_findnext(find_handle, &finddata) != 0) break;
|
193
|
+
}
|
194
|
+
_findclose(find_handle);
|
195
|
+
|
196
|
+
// Sort the list...
|
197
|
+
qsort(FileList, NumHave, sizeof(FileEntry), CompareFunc);
|
198
|
+
|
199
|
+
|
200
|
+
// Use the list.
|
201
|
+
for (a=0;a<NumHave;a++){
|
202
|
+
char CombinedName[_MAX_PATH*2+1];
|
203
|
+
if (FileList[a].attrib & _A_SUBDIR){
|
204
|
+
if (MatchDirs){
|
205
|
+
// Need more directories.
|
206
|
+
SplicePath(CombinedName, BasePattern, FileList[a].Name);
|
207
|
+
strncat(CombinedName, PatCopy+PatternEnd, _MAX_PATH*2-strlen(CombinedName));
|
208
|
+
MyGlob(CombinedName,FileFuncParm);
|
209
|
+
}
|
210
|
+
}else{
|
211
|
+
if (MatchFiles){
|
212
|
+
// We need files at this level.
|
213
|
+
SplicePath(CombinedName, BasePattern, FileList[a].Name);
|
214
|
+
FileFuncParm(CombinedName);
|
215
|
+
}
|
216
|
+
}
|
217
|
+
free(FileList[a].Name);
|
218
|
+
}
|
219
|
+
free(FileList);
|
220
|
+
}
|
221
|
+
|
222
|
+
if(RecurseAt >= 0){
|
223
|
+
strcpy(MatchPattern, PatCopy+RecurseAt);
|
224
|
+
PatCopy[RecurseAt] = 0;
|
225
|
+
strncpy(PatCopy+RecurseAt, "*\\**\\", _MAX_PATH*2-RecurseAt);
|
226
|
+
strncat(PatCopy, MatchPattern, _MAX_PATH*2-strlen(PatCopy));
|
227
|
+
|
228
|
+
#ifdef DEBUGGING
|
229
|
+
printf("Recurse with '%s'\n",PatCopy);
|
230
|
+
#endif
|
231
|
+
|
232
|
+
// As this function context is no longer needed, we can just goto back
|
233
|
+
// to the top of it to avoid adding another context on the stack.
|
234
|
+
goto DoRecursion;
|
235
|
+
}
|
236
|
+
}
|
237
|
+
|
238
|
+
//--------------------------------------------------------------------------------
|
239
|
+
// Flip slashes to native OS representation (for Windows)
|
240
|
+
//--------------------------------------------------------------------------------
|
241
|
+
void SlashToNative(char * Path)
|
242
|
+
{
|
243
|
+
int a;
|
244
|
+
for (a=0;Path[a];a++){
|
245
|
+
if (Path[a] == '/') Path[a] = SLASH;
|
246
|
+
}
|
247
|
+
}
|
248
|
+
|
249
|
+
|
250
|
+
#ifdef DEBUGGING
|
251
|
+
//--------------------------------------------------------------------------------
|
252
|
+
// The main program.
|
253
|
+
//--------------------------------------------------------------------------------
|
254
|
+
int main (int argc, char **argv)
|
255
|
+
{
|
256
|
+
int argn;
|
257
|
+
char * arg;
|
258
|
+
int Subdirs = 0;
|
259
|
+
|
260
|
+
for (argn=1;argn<argc;argn++){
|
261
|
+
arg = argv[argn];
|
262
|
+
if (arg[0] != '-') break; // Filenames from here on.
|
263
|
+
if (!strcmp(arg,"-r")){
|
264
|
+
printf("do recursive\n");
|
265
|
+
Subdirs = 1;
|
266
|
+
}else{
|
267
|
+
fprintf(stderr, "Argument '%s' not understood\n",arg);
|
268
|
+
}
|
269
|
+
}
|
270
|
+
if (argn == argc){
|
271
|
+
fprintf(stderr,"Error: Must supply a file name\n");
|
272
|
+
}
|
273
|
+
|
274
|
+
for (;argn<argc;argn++){
|
275
|
+
MyGlob(argv[argn], ShowName);
|
276
|
+
}
|
277
|
+
return EXIT_SUCCESS;
|
278
|
+
}
|
279
|
+
#endif
|
280
|
+
|
281
|
+
/*
|
282
|
+
|
283
|
+
non-recursive test cases:
|
284
|
+
|
285
|
+
e:\make*\*
|
286
|
+
\make*\*
|
287
|
+
e:*\*.c
|
288
|
+
\*\*.c
|
289
|
+
\*
|
290
|
+
c:*.c
|
291
|
+
c:\*
|
292
|
+
..\*.c
|
293
|
+
|
294
|
+
|
295
|
+
recursive test cases:
|
296
|
+
**
|
297
|
+
**\*.c
|
298
|
+
c:\**\*.c
|
299
|
+
c:**\*.c
|
300
|
+
.\**
|
301
|
+
..\**
|
302
|
+
|
303
|
+
*/
|
304
|
+
|
305
|
+
|