~ubuntu-branches/ubuntu/vivid/silversearcher-ag/vivid-proposed

« back to all changes in this revision

Viewing changes to src/print.c

  • Committer: Package Import Robot
  • Author(s): Hajime Mizuno
  • Date: 2013-02-13 20:31:42 UTC
  • Revision ID: package-import@ubuntu.com-20130213203142-drq8ipcuy51r5kyp
Tags: upstream-0.0~20130213+git55028b4e
ImportĀ upstreamĀ versionĀ 0.0~20130213+git55028b4e

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <stdarg.h>
 
2
#include <stdio.h>
 
3
#include <stdlib.h>
 
4
#include <string.h>
 
5
 
 
6
#include "ignore.h"
 
7
#include "log.h"
 
8
#include "options.h"
 
9
#include "print.h"
 
10
#include "util.h"
 
11
 
 
12
int first_file_match = 1;
 
13
 
 
14
const char *color_reset = "\e[0m\e[K";
 
15
 
 
16
void print_path(const char* path, const char sep) {
 
17
    log_debug("printing path");
 
18
    path = normalize_path(path);
 
19
 
 
20
    if (opts.ackmate) {
 
21
        fprintf(out_fd, ":%s%c", path, sep);
 
22
    } else {
 
23
        if (opts.color) {
 
24
            fprintf(out_fd, "%s%s%s%c", opts.color_path, path, color_reset, sep);
 
25
        } else {
 
26
            fprintf(out_fd, "%s%c", path, sep);
 
27
        }
 
28
    }
 
29
}
 
30
 
 
31
void print_binary_file_matches(const char* path) {
 
32
    path = normalize_path(path);
 
33
    print_file_separator();
 
34
    fprintf(out_fd, "Binary file %s matches.\n", path);
 
35
}
 
36
 
 
37
void print_file_matches(const char* path, const char* buf, const int buf_len, const match matches[], const int matches_len) {
 
38
    int line = 1;
 
39
    char **context_prev_lines = NULL;
 
40
    int prev_line = 0;
 
41
    int last_prev_line = 0;
 
42
    int prev_line_offset = 0;
 
43
    int cur_match = 0;
 
44
    /* TODO the line below contains a terrible hack */
 
45
    int lines_since_last_match = 1000000; /* if I initialize this to INT_MAX it'll overflow */
 
46
    int lines_to_print = 0;
 
47
    int last_printed_match = 0;
 
48
    char sep = '-';
 
49
    int i, j;
 
50
    int in_a_match = FALSE;
 
51
    int printing_a_match = FALSE;
 
52
 
 
53
    if (opts.ackmate) {
 
54
        sep = ':';
 
55
    }
 
56
 
 
57
    print_file_separator();
 
58
 
 
59
    if (opts.print_heading == TRUE) {
 
60
        print_path(path, '\n');
 
61
    }
 
62
 
 
63
    context_prev_lines = ag_calloc(sizeof(char*), (opts.before + 1));
 
64
 
 
65
    for (i = 0; i <= buf_len && (cur_match < matches_len || lines_since_last_match <= opts.after); i++) {
 
66
        if (cur_match < matches_len && i == matches[cur_match].end) {
 
67
            /* We found the end of a match. */
 
68
            cur_match++;
 
69
            in_a_match = FALSE;
 
70
        }
 
71
 
 
72
        if (cur_match < matches_len && i == matches[cur_match].start) {
 
73
            in_a_match = TRUE;
 
74
            /* We found the start of a match */
 
75
            if (cur_match > 0 && opts.context && lines_since_last_match > (opts.before + opts.after + 1)) {
 
76
                fprintf(out_fd, "--\n");
 
77
            }
 
78
 
 
79
            if (lines_since_last_match > 0 && opts.before > 0) {
 
80
                /* TODO: better, but still needs work */
 
81
                /* print the previous line(s) */
 
82
                lines_to_print = lines_since_last_match - (opts.after + 1);
 
83
                if (lines_to_print < 0) {
 
84
                    lines_to_print = 0;
 
85
                } else if (lines_to_print > opts.before) {
 
86
                    lines_to_print = opts.before;
 
87
                }
 
88
 
 
89
                for (j = (opts.before - lines_to_print); j < opts.before; j++) {
 
90
                    prev_line = (last_prev_line + j) % opts.before;
 
91
                    if (context_prev_lines[prev_line] != NULL) {
 
92
                        if (opts.print_heading == 0) {
 
93
                            print_path(path, ':');
 
94
                        }
 
95
                        print_line_number(line - (opts.before - j), sep);
 
96
                        fprintf(out_fd, "%s\n", context_prev_lines[prev_line]);
 
97
                    }
 
98
                }
 
99
            }
 
100
            lines_since_last_match = 0;
 
101
        }
 
102
 
 
103
        /* We found the end of a line. */
 
104
        if (buf[i] == '\n' && opts.before > 0) {
 
105
            if (context_prev_lines[last_prev_line] != NULL) {
 
106
                free(context_prev_lines[last_prev_line]);
 
107
            }
 
108
            /* We don't want to strcpy the \n */
 
109
            context_prev_lines[last_prev_line] =
 
110
                ag_strndup(&buf[prev_line_offset], i - prev_line_offset);
 
111
            last_prev_line = (last_prev_line + 1) % opts.before;
 
112
        }
 
113
 
 
114
        if (buf[i] == '\n' || i == buf_len) {
 
115
            if (lines_since_last_match == 0) {
 
116
                if (opts.print_heading == 0 && !opts.search_stream) {
 
117
                    print_path(path, ':');
 
118
                }
 
119
 
 
120
                if (opts.ackmate) {
 
121
                    /* print headers for ackmate to parse */
 
122
                    print_line_number(line, ';');
 
123
                    for (; last_printed_match < cur_match; last_printed_match++) {
 
124
                        fprintf(out_fd, "%i %i",
 
125
                              (matches[last_printed_match].start - prev_line_offset),
 
126
                              (matches[last_printed_match].end - matches[last_printed_match].start)
 
127
                        );
 
128
                        last_printed_match == cur_match - 1 ? fputc(':', out_fd) : fputc(',', out_fd);
 
129
                    }
 
130
                    j = prev_line_offset;
 
131
                    /* print up to current char */
 
132
                    for (; j <= i; j++) {
 
133
                        fputc(buf[j], out_fd);
 
134
                    }
 
135
                } else {
 
136
                    print_line_number(line, ':');
 
137
                    if (opts.column) {
 
138
                        fprintf(out_fd, "%i:", (matches[last_printed_match].start - prev_line_offset) + 1);
 
139
                    }
 
140
 
 
141
                    if (printing_a_match && opts.color) {
 
142
                        fprintf(out_fd, "%s", opts.color_match);
 
143
                    }
 
144
                    for (j = prev_line_offset; j <= i; j++) {
 
145
                        if (j == matches[last_printed_match].end && last_printed_match < matches_len) {
 
146
                            if (opts.color) {
 
147
                                fprintf(out_fd, "%s", color_reset);
 
148
                            }
 
149
                            printing_a_match = FALSE;
 
150
                            last_printed_match++;
 
151
                        }
 
152
                        if (j == matches[last_printed_match].start && last_printed_match < matches_len) {
 
153
                            if (opts.color) {
 
154
                                fprintf(out_fd, "%s", opts.color_match);
 
155
                            }
 
156
                            printing_a_match = TRUE;
 
157
                        }
 
158
                        fputc(buf[j], out_fd);
 
159
                    }
 
160
                    if (printing_a_match && opts.color) {
 
161
                        fprintf(out_fd, "%s", color_reset);
 
162
                    }
 
163
                }
 
164
            } else if (lines_since_last_match <= opts.after) {
 
165
                /* print context after matching line */
 
166
                if (opts.print_heading == 0) {
 
167
                    print_path(path, ':');
 
168
                }
 
169
                print_line_number(line, sep);
 
170
 
 
171
                for (j = prev_line_offset; j < i; j++) {
 
172
                    fputc(buf[j], out_fd);
 
173
                }
 
174
                fputc('\n', out_fd);
 
175
            }
 
176
 
 
177
            prev_line_offset = i + 1; /* skip the newline */
 
178
            line++;
 
179
            if (!in_a_match) {
 
180
                lines_since_last_match++;
 
181
            }
 
182
        }
 
183
    }
 
184
 
 
185
    for (i = 0; i < opts.before; i++) {
 
186
        if (context_prev_lines[i] != NULL) {
 
187
            free(context_prev_lines[i]);
 
188
        }
 
189
    }
 
190
    free(context_prev_lines);
 
191
}
 
192
 
 
193
void print_line_number(const int line, const char sep) {
 
194
    if (!opts.print_line_numbers) {
 
195
        return;
 
196
    }
 
197
    log_debug("printing line number");
 
198
 
 
199
    if (opts.color) {
 
200
        fprintf(out_fd, "%s%i%s%c", opts.color_line_number, line, color_reset, sep);
 
201
    } else {
 
202
        fprintf(out_fd, "%i%c", line, sep);
 
203
    }
 
204
}
 
205
 
 
206
void print_file_separator() {
 
207
    if (first_file_match == 0 && opts.print_break) {
 
208
        log_debug("printing file separator");
 
209
        fprintf(out_fd, "\n");
 
210
    }
 
211
    first_file_match = 0;
 
212
}
 
213
 
 
214
const char* normalize_path(const char* path) {
 
215
    if (strlen(path) >= 3 && path[0] == '.' && path[1] == '/') {
 
216
        return path + 2;
 
217
    } else {
 
218
        return path;
 
219
    }
 
220
}