1 /*
2 *
3 *   Copyright (c) 2000-2001, Darren Hiebert
4 *
5 *   This source code is released for free distribution under the terms of the
6 *   GNU General Public License version 2 or (at your option) any later version.
7 *
8 *   This module contains functions for generating tags for diff files (based on Sh parser).
9 */
10 
11 /*
12 *   INCLUDE FILES
13 */
14 #include "general.h"	/* must always come first */
15 
16 #include <ctype.h>
17 #include <string.h>
18 
19 #include "parse.h"
20 #include "routines.h"
21 #include "read.h"
22 #include "vstring.h"
23 
24 /*
25 *   DATA DEFINITIONS
26 */
27 typedef enum {
28 	K_FUNCTION
29 } diffKind;
30 
31 static kindDefinition DiffKinds [] = {
32 	{ true, 'f', "function", "functions"}
33 };
34 
35 enum {
36 	DIFF_DELIM_MINUS = 0,
37 	DIFF_DELIM_PLUS
38 };
39 
40 static const char *DiffDelims[2] = {
41 	"--- ",
42 	"+++ "
43 };
44 
45 /*
46 *   FUNCTION DEFINITIONS
47 */
48 
stripAbsolute(const unsigned char * filename)49 static const unsigned char *stripAbsolute (const unsigned char *filename)
50 {
51 	const unsigned char *tmp;
52 
53 	/* strip any absolute path */
54 	if (*filename == '/' || *filename == '\\')
55 	{
56 		bool skipSlash = true;
57 
58 		tmp = (const unsigned char*) strrchr ((const char*) filename,  '/');
59 		if (tmp == NULL)
60 		{	/* if no / is contained try \ in case of a Windows filename */
61 			tmp = (const unsigned char*) strrchr ((const char*) filename, '\\');
62 			if (tmp == NULL)
63 			{	/* last fallback, probably the filename doesn't contain a path, so take it */
64 				tmp = filename;
65 				skipSlash = false;
66 			}
67 		}
68 
69 		/* skip the leading slash or backslash */
70 		if (skipSlash)
71 			tmp++;
72 	}
73 	else
74 		tmp = filename;
75 
76 	return tmp;
77 }
78 
findDiffTags(void)79 static void findDiffTags (void)
80 {
81 	vString *filename = vStringNew ();
82 	const unsigned char *line, *tmp;
83 	int delim = DIFF_DELIM_MINUS;
84 
85 	while ((line = readLineFromInputFile ()) != NULL)
86 	{
87 		const unsigned char* cp = line;
88 
89 		if (strncmp ((const char*) cp, DiffDelims[delim], 4u) == 0)
90 		{
91 			cp += 4;
92 			if (isspace ((int) *cp)) continue;
93 			/* when original filename is /dev/null use the new one instead */
94 			if (delim == DIFF_DELIM_MINUS &&
95 				strncmp ((const char*) cp, "/dev/null", 9u) == 0 &&
96 				(cp[9] == 0 || isspace (cp[9])))
97 			{
98 				delim = DIFF_DELIM_PLUS;
99 				continue;
100 			}
101 
102 			tmp = stripAbsolute (cp);
103 
104 			if (tmp != NULL)
105 			{
106 				while (! isspace(*tmp) && *tmp != '\0')
107 				{
108 					vStringPut(filename, *tmp);
109 					tmp++;
110 				}
111 
112 				makeSimpleTag (filename, K_FUNCTION);
113 				vStringClear (filename);
114 			}
115 
116 			/* restore default delim */
117 			delim = DIFF_DELIM_MINUS;
118 		}
119 	}
120 	vStringDelete (filename);
121 }
122 
DiffParser(void)123 extern parserDefinition* DiffParser (void)
124 {
125 	static const char *const patterns [] = { "*.diff", "*.patch", NULL };
126 	static const char *const extensions [] = { "diff", NULL };
127 	parserDefinition* const def = parserNew ("Diff");
128 	def->kindTable  = DiffKinds;
129 	def->kindCount  = ARRAY_SIZE (DiffKinds);
130 	def->patterns   = patterns;
131 	def->extensions = extensions;
132 	def->parser     = findDiffTags;
133 	return def;
134 }
135