1d173714eSMasatake YAMATO /*
2d173714eSMasatake YAMATO *
3d173714eSMasatake YAMATO * Copyright (c) 2000-2001, Darren Hiebert
4d173714eSMasatake YAMATO *
5d173714eSMasatake YAMATO * This source code is released for free distribution under the terms of the
60ce38835Sviccuad * GNU General Public License version 2 or (at your option) any later version.
7d173714eSMasatake YAMATO *
8d173714eSMasatake YAMATO * This module contains functions for generating tags for diff files (based on Sh parser).
9d173714eSMasatake YAMATO */
10d173714eSMasatake YAMATO
11d173714eSMasatake YAMATO /*
12d173714eSMasatake YAMATO * INCLUDE FILES
13d173714eSMasatake YAMATO */
14d173714eSMasatake YAMATO #include "general.h" /* must always come first */
15d173714eSMasatake YAMATO
16d173714eSMasatake YAMATO #include <ctype.h>
17d173714eSMasatake YAMATO #include <string.h>
18d173714eSMasatake YAMATO
197049fd45SMasatake YAMATO #include "entry.h"
20d173714eSMasatake YAMATO #include "parse.h"
213db72c21SMasatake YAMATO #include "routines.h"
22d173714eSMasatake YAMATO #include "read.h"
23d173714eSMasatake YAMATO #include "vstring.h"
24d173714eSMasatake YAMATO
25d173714eSMasatake YAMATO /*
26d173714eSMasatake YAMATO * DATA DEFINITIONS
27d173714eSMasatake YAMATO */
28d173714eSMasatake YAMATO typedef enum {
29d173714eSMasatake YAMATO K_MODIFIED_FILE,
30d173714eSMasatake YAMATO K_NEW_FILE,
317049fd45SMasatake YAMATO K_DELETED_FILE,
32d173714eSMasatake YAMATO K_HUNK,
33d173714eSMasatake YAMATO } diffKind;
34d173714eSMasatake YAMATO
35e112e8abSMasatake YAMATO static kindDefinition DiffKinds [] = {
36ce990805SThomas Braun { true, 'm', "modifiedFile", "modified files"},
37ce990805SThomas Braun { true, 'n', "newFile", "newly created files"},
38ce990805SThomas Braun { true, 'd', "deletedFile", "deleted files"},
39ce990805SThomas Braun { true, 'h', "hunk", "hunks"},
40d173714eSMasatake YAMATO };
41d173714eSMasatake YAMATO
42d173714eSMasatake YAMATO enum {
43d173714eSMasatake YAMATO DIFF_DELIM_MINUS = 0,
44d173714eSMasatake YAMATO DIFF_DELIM_PLUS
45d173714eSMasatake YAMATO };
46d173714eSMasatake YAMATO
47d173714eSMasatake YAMATO static const char *DiffDelims[2] = {
48d173714eSMasatake YAMATO "--- ",
49d173714eSMasatake YAMATO "+++ "
50d173714eSMasatake YAMATO };
51d173714eSMasatake YAMATO
527049fd45SMasatake YAMATO static const char *HunkDelim[2] = {
537049fd45SMasatake YAMATO "@@ ",
547049fd45SMasatake YAMATO " @@",
557049fd45SMasatake YAMATO };
567049fd45SMasatake YAMATO
57d173714eSMasatake YAMATO /*
58d173714eSMasatake YAMATO * FUNCTION DEFINITIONS
59d173714eSMasatake YAMATO */
60d173714eSMasatake YAMATO
stripAbsolute(const unsigned char * filename)61d173714eSMasatake YAMATO static const unsigned char *stripAbsolute (const unsigned char *filename)
62d173714eSMasatake YAMATO {
63d173714eSMasatake YAMATO const unsigned char *tmp;
64d173714eSMasatake YAMATO
65d173714eSMasatake YAMATO /* strip any absolute path */
66d173714eSMasatake YAMATO if (*filename == '/' || *filename == '\\')
67d173714eSMasatake YAMATO {
68ce990805SThomas Braun bool skipSlash = true;
69d173714eSMasatake YAMATO
70d173714eSMasatake YAMATO tmp = (const unsigned char*) strrchr ((const char*) filename, '/');
71d173714eSMasatake YAMATO if (tmp == NULL)
72d173714eSMasatake YAMATO { /* if no / is contained try \ in case of a Windows filename */
73d173714eSMasatake YAMATO tmp = (const unsigned char*) strrchr ((const char*) filename, '\\');
74d173714eSMasatake YAMATO if (tmp == NULL)
75d173714eSMasatake YAMATO { /* last fallback, probably the filename doesn't contain a path, so take it */
76d173714eSMasatake YAMATO tmp = filename;
77ce990805SThomas Braun skipSlash = false;
78d173714eSMasatake YAMATO }
79d173714eSMasatake YAMATO }
80d173714eSMasatake YAMATO
81d173714eSMasatake YAMATO /* skip the leading slash or backslash */
82d173714eSMasatake YAMATO if (skipSlash)
83d173714eSMasatake YAMATO tmp++;
84d173714eSMasatake YAMATO }
85d173714eSMasatake YAMATO else
86d173714eSMasatake YAMATO tmp = filename;
87d173714eSMasatake YAMATO
88d173714eSMasatake YAMATO return tmp;
89d173714eSMasatake YAMATO }
90d173714eSMasatake YAMATO
parseHunk(const unsigned char * cp,vString * hunk,int scope_index)917049fd45SMasatake YAMATO static int parseHunk (const unsigned char* cp, vString *hunk, int scope_index)
927049fd45SMasatake YAMATO {
937049fd45SMasatake YAMATO /*
947049fd45SMasatake YAMATO example input: @@ -0,0 +1,134 @@
957049fd45SMasatake YAMATO expected output: -0,0 +1,134
967049fd45SMasatake YAMATO */
977049fd45SMasatake YAMATO
987049fd45SMasatake YAMATO const char *next_delim;
997049fd45SMasatake YAMATO const char *start, *end;
1007049fd45SMasatake YAMATO const char *c;
101f6027918SMasatake YAMATO int i = CORK_NIL;
1027049fd45SMasatake YAMATO
1037049fd45SMasatake YAMATO cp += 3;
1047049fd45SMasatake YAMATO start = (const char*)cp;
1057049fd45SMasatake YAMATO
1067049fd45SMasatake YAMATO if (*start != '-')
1077049fd45SMasatake YAMATO return i;
1087049fd45SMasatake YAMATO
1097049fd45SMasatake YAMATO next_delim = strstr ((const char*)cp, HunkDelim[1]);
1107049fd45SMasatake YAMATO if ((next_delim == NULL)
1117049fd45SMasatake YAMATO || (! (start < next_delim )))
1127049fd45SMasatake YAMATO return i;
1137049fd45SMasatake YAMATO end = next_delim;
1147049fd45SMasatake YAMATO if (! ( '0' <= *( end - 1 ) && *( end - 1 ) <= '9'))
1157049fd45SMasatake YAMATO return i;
1167049fd45SMasatake YAMATO for (c = start; c < end; c++)
1177049fd45SMasatake YAMATO if (*c == '\t')
1187049fd45SMasatake YAMATO return i;
1197049fd45SMasatake YAMATO vStringNCopyS (hunk, start, end - start);
12016a2541cSMasatake YAMATO i = makeSimpleTag (hunk, K_HUNK);
1217049fd45SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (i);
122*3671ad72SMasatake YAMATO if (e && scope_index > CORK_NIL)
1237049fd45SMasatake YAMATO e->extensionFields.scopeIndex = scope_index;
1247049fd45SMasatake YAMATO return i;
1257049fd45SMasatake YAMATO }
1267049fd45SMasatake YAMATO
markTheLastTagAsDeletedFile(int scope_index)1277049fd45SMasatake YAMATO static void markTheLastTagAsDeletedFile (int scope_index)
1287049fd45SMasatake YAMATO {
1297049fd45SMasatake YAMATO tagEntryInfo *e = getEntryInCorkQueue (scope_index);
130*3671ad72SMasatake YAMATO
131*3671ad72SMasatake YAMATO if (e)
132f92e6bf2SMasatake YAMATO e->kindIndex = K_DELETED_FILE;
1337049fd45SMasatake YAMATO }
1347049fd45SMasatake YAMATO
findDiffTags(void)135d173714eSMasatake YAMATO static void findDiffTags (void)
136d173714eSMasatake YAMATO {
137d173714eSMasatake YAMATO vString *filename = vStringNew ();
1387049fd45SMasatake YAMATO vString *hunk = vStringNew ();
139d173714eSMasatake YAMATO const unsigned char *line, *tmp;
140d173714eSMasatake YAMATO int delim = DIFF_DELIM_MINUS;
1412c584527SMasatake YAMATO diffKind kind;
142f6027918SMasatake YAMATO int scope_index = CORK_NIL;
143d173714eSMasatake YAMATO
1441b312fe7SMasatake YAMATO while ((line = readLineFromInputFile ()) != NULL)
145d173714eSMasatake YAMATO {
146d173714eSMasatake YAMATO const unsigned char* cp = line;
147d173714eSMasatake YAMATO
148d173714eSMasatake YAMATO if (strncmp ((const char*) cp, DiffDelims[delim], 4u) == 0)
149d173714eSMasatake YAMATO {
150f6027918SMasatake YAMATO scope_index = CORK_NIL;
151d173714eSMasatake YAMATO cp += 4;
152d173714eSMasatake YAMATO if (isspace ((int) *cp)) continue;
153d173714eSMasatake YAMATO /* when original filename is /dev/null use the new one instead */
154d173714eSMasatake YAMATO if (delim == DIFF_DELIM_MINUS &&
155d173714eSMasatake YAMATO strncmp ((const char*) cp, "/dev/null", 9u) == 0 &&
156d173714eSMasatake YAMATO (cp[9] == 0 || isspace (cp[9])))
157d173714eSMasatake YAMATO {
158d173714eSMasatake YAMATO delim = DIFF_DELIM_PLUS;
159d173714eSMasatake YAMATO continue;
160d173714eSMasatake YAMATO }
161d173714eSMasatake YAMATO
162d173714eSMasatake YAMATO tmp = stripAbsolute (cp);
163d173714eSMasatake YAMATO
164d173714eSMasatake YAMATO if (tmp != NULL)
165d173714eSMasatake YAMATO {
166d173714eSMasatake YAMATO while (! isspace(*tmp) && *tmp != '\0')
167d173714eSMasatake YAMATO {
168d173714eSMasatake YAMATO vStringPut(filename, *tmp);
169d173714eSMasatake YAMATO tmp++;
170d173714eSMasatake YAMATO }
171d173714eSMasatake YAMATO
1722c584527SMasatake YAMATO if (delim == DIFF_DELIM_PLUS)
1732c584527SMasatake YAMATO kind = K_NEW_FILE;
1742c584527SMasatake YAMATO else
1752c584527SMasatake YAMATO kind = K_MODIFIED_FILE;
17616a2541cSMasatake YAMATO scope_index = makeSimpleTag (filename, kind);
177d173714eSMasatake YAMATO vStringClear (filename);
178d173714eSMasatake YAMATO }
179d173714eSMasatake YAMATO
180d173714eSMasatake YAMATO /* restore default delim */
181d173714eSMasatake YAMATO delim = DIFF_DELIM_MINUS;
182d173714eSMasatake YAMATO }
183f6027918SMasatake YAMATO else if ((scope_index > CORK_NIL)
1847049fd45SMasatake YAMATO && (strncmp ((const char*) cp, DiffDelims[1], 4u) == 0))
1857049fd45SMasatake YAMATO {
1867049fd45SMasatake YAMATO cp += 4;
1877049fd45SMasatake YAMATO if (isspace ((int) *cp)) continue;
1887049fd45SMasatake YAMATO /* when modified filename is /dev/null, the original name is deleted. */
1897049fd45SMasatake YAMATO if (strncmp ((const char*) cp, "/dev/null", 9u) == 0 &&
1907049fd45SMasatake YAMATO (cp[9] == 0 || isspace (cp[9])))
1917049fd45SMasatake YAMATO markTheLastTagAsDeletedFile (scope_index);
192d173714eSMasatake YAMATO }
1937049fd45SMasatake YAMATO else if (strncmp ((const char*) cp, HunkDelim[0], 3u) == 0)
1947049fd45SMasatake YAMATO {
195f6027918SMasatake YAMATO if (parseHunk (cp, hunk, scope_index) != CORK_NIL)
1967049fd45SMasatake YAMATO vStringClear (hunk);
1977049fd45SMasatake YAMATO }
1987049fd45SMasatake YAMATO }
1997049fd45SMasatake YAMATO vStringDelete (hunk);
200d173714eSMasatake YAMATO vStringDelete (filename);
201d173714eSMasatake YAMATO }
202d173714eSMasatake YAMATO
DiffParser(void)203d173714eSMasatake YAMATO extern parserDefinition* DiffParser (void)
204d173714eSMasatake YAMATO {
205d173714eSMasatake YAMATO static const char *const extensions [] = { "diff", "patch", NULL };
206d173714eSMasatake YAMATO parserDefinition* const def = parserNew ("Diff");
20709ae690fSMasatake YAMATO def->kindTable = DiffKinds;
2083db72c21SMasatake YAMATO def->kindCount = ARRAY_SIZE (DiffKinds);
209d173714eSMasatake YAMATO def->extensions = extensions;
210d173714eSMasatake YAMATO def->parser = findDiffTags;
2116b1a862eSMasatake YAMATO def->useCork = CORK_QUEUE;
212d173714eSMasatake YAMATO return def;
213d173714eSMasatake YAMATO }
214