159c8e88eSDag-Erling Smørgrav /* Common parts for printing diff output */ 259c8e88eSDag-Erling Smørgrav /* 359c8e88eSDag-Erling Smørgrav * Copyright (c) 2020 Neels Hofmeyr <neels@hofmeyr.de> 459c8e88eSDag-Erling Smørgrav * 559c8e88eSDag-Erling Smørgrav * Permission to use, copy, modify, and distribute this software for any 659c8e88eSDag-Erling Smørgrav * purpose with or without fee is hereby granted, provided that the above 759c8e88eSDag-Erling Smørgrav * copyright notice and this permission notice appear in all copies. 859c8e88eSDag-Erling Smørgrav * 959c8e88eSDag-Erling Smørgrav * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1059c8e88eSDag-Erling Smørgrav * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1159c8e88eSDag-Erling Smørgrav * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1259c8e88eSDag-Erling Smørgrav * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1359c8e88eSDag-Erling Smørgrav * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1459c8e88eSDag-Erling Smørgrav * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1559c8e88eSDag-Erling Smørgrav * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1659c8e88eSDag-Erling Smørgrav */ 1759c8e88eSDag-Erling Smørgrav 1859c8e88eSDag-Erling Smørgrav #include <ctype.h> 1959c8e88eSDag-Erling Smørgrav #include <errno.h> 2059c8e88eSDag-Erling Smørgrav #include <stdbool.h> 2159c8e88eSDag-Erling Smørgrav #include <stdint.h> 2259c8e88eSDag-Erling Smørgrav #include <stdio.h> 2359c8e88eSDag-Erling Smørgrav #include <stdlib.h> 2459c8e88eSDag-Erling Smørgrav #include <string.h> 2559c8e88eSDag-Erling Smørgrav #include <unistd.h> 2659c8e88eSDag-Erling Smørgrav 2759c8e88eSDag-Erling Smørgrav #include <arraylist.h> 2859c8e88eSDag-Erling Smørgrav #include <diff_main.h> 2959c8e88eSDag-Erling Smørgrav #include <diff_output.h> 3059c8e88eSDag-Erling Smørgrav 3159c8e88eSDag-Erling Smørgrav #include "diff_internal.h" 3259c8e88eSDag-Erling Smørgrav 33*4e859e67SDag-Erling Smørgrav static bool color; 34*4e859e67SDag-Erling Smørgrav static const char *del_code = "31"; 35*4e859e67SDag-Erling Smørgrav static const char *add_code = "32"; 36*4e859e67SDag-Erling Smørgrav 37*4e859e67SDag-Erling Smørgrav void 38*4e859e67SDag-Erling Smørgrav diff_output_set_colors(bool _color, 39*4e859e67SDag-Erling Smørgrav const char *_del_code, 40*4e859e67SDag-Erling Smørgrav const char *_add_code) 41*4e859e67SDag-Erling Smørgrav { 42*4e859e67SDag-Erling Smørgrav color = _color; 43*4e859e67SDag-Erling Smørgrav if (_del_code) 44*4e859e67SDag-Erling Smørgrav del_code = _del_code; 45*4e859e67SDag-Erling Smørgrav if (_add_code) 46*4e859e67SDag-Erling Smørgrav add_code = _add_code; 47*4e859e67SDag-Erling Smørgrav } 48*4e859e67SDag-Erling Smørgrav 4959c8e88eSDag-Erling Smørgrav static int 5059c8e88eSDag-Erling Smørgrav get_atom_byte(int *ch, struct diff_atom *atom, off_t off) 5159c8e88eSDag-Erling Smørgrav { 5259c8e88eSDag-Erling Smørgrav off_t cur; 5359c8e88eSDag-Erling Smørgrav 5459c8e88eSDag-Erling Smørgrav if (atom->at != NULL) { 5559c8e88eSDag-Erling Smørgrav *ch = atom->at[off]; 5659c8e88eSDag-Erling Smørgrav return 0; 5759c8e88eSDag-Erling Smørgrav } 5859c8e88eSDag-Erling Smørgrav 5959c8e88eSDag-Erling Smørgrav cur = ftello(atom->root->f); 6059c8e88eSDag-Erling Smørgrav if (cur == -1) 6159c8e88eSDag-Erling Smørgrav return errno; 6259c8e88eSDag-Erling Smørgrav 6359c8e88eSDag-Erling Smørgrav if (cur != atom->pos + off && 6459c8e88eSDag-Erling Smørgrav fseeko(atom->root->f, atom->pos + off, SEEK_SET) == -1) 6559c8e88eSDag-Erling Smørgrav return errno; 6659c8e88eSDag-Erling Smørgrav 6759c8e88eSDag-Erling Smørgrav *ch = fgetc(atom->root->f); 6859c8e88eSDag-Erling Smørgrav if (*ch == EOF && ferror(atom->root->f)) 6959c8e88eSDag-Erling Smørgrav return errno; 7059c8e88eSDag-Erling Smørgrav 7159c8e88eSDag-Erling Smørgrav return 0; 7259c8e88eSDag-Erling Smørgrav } 7359c8e88eSDag-Erling Smørgrav 7459c8e88eSDag-Erling Smørgrav #define DIFF_OUTPUT_BUF_SIZE 512 7559c8e88eSDag-Erling Smørgrav 7659c8e88eSDag-Erling Smørgrav int 7759c8e88eSDag-Erling Smørgrav diff_output_lines(struct diff_output_info *outinfo, FILE *dest, 7859c8e88eSDag-Erling Smørgrav const char *prefix, struct diff_atom *start_atom, 7959c8e88eSDag-Erling Smørgrav unsigned int count) 8059c8e88eSDag-Erling Smørgrav { 8159c8e88eSDag-Erling Smørgrav struct diff_atom *atom; 8259c8e88eSDag-Erling Smørgrav off_t outoff = 0, *offp; 8359c8e88eSDag-Erling Smørgrav uint8_t *typep; 8459c8e88eSDag-Erling Smørgrav int rc; 85*4e859e67SDag-Erling Smørgrav bool colored; 8659c8e88eSDag-Erling Smørgrav 8759c8e88eSDag-Erling Smørgrav if (outinfo && outinfo->line_offsets.len > 0) { 8859c8e88eSDag-Erling Smørgrav unsigned int idx = outinfo->line_offsets.len - 1; 8959c8e88eSDag-Erling Smørgrav outoff = outinfo->line_offsets.head[idx]; 9059c8e88eSDag-Erling Smørgrav } 9159c8e88eSDag-Erling Smørgrav 92*4e859e67SDag-Erling Smørgrav if (color) { 93*4e859e67SDag-Erling Smørgrav colored = true; 94*4e859e67SDag-Erling Smørgrav if (*prefix == '-' || *prefix == '<') 95*4e859e67SDag-Erling Smørgrav printf("\033[%sm", del_code); 96*4e859e67SDag-Erling Smørgrav else if (*prefix == '+' || *prefix == '>') 97*4e859e67SDag-Erling Smørgrav printf("\033[%sm", add_code); 98*4e859e67SDag-Erling Smørgrav else 99*4e859e67SDag-Erling Smørgrav colored = false; 100*4e859e67SDag-Erling Smørgrav } else { 101*4e859e67SDag-Erling Smørgrav colored = false; 102*4e859e67SDag-Erling Smørgrav } 103*4e859e67SDag-Erling Smørgrav 10459c8e88eSDag-Erling Smørgrav foreach_diff_atom(atom, start_atom, count) { 10559c8e88eSDag-Erling Smørgrav off_t outlen = 0; 10659c8e88eSDag-Erling Smørgrav int i, ch, nbuf = 0; 107b95e9602SDag-Erling Smørgrav size_t len = atom->len, wlen; 108b95e9602SDag-Erling Smørgrav char buf[DIFF_OUTPUT_BUF_SIZE + 1 /* '\n' */]; 10959c8e88eSDag-Erling Smørgrav size_t n; 11059c8e88eSDag-Erling Smørgrav 11159c8e88eSDag-Erling Smørgrav n = strlcpy(buf, prefix, sizeof(buf)); 112*4e859e67SDag-Erling Smørgrav if (n >= DIFF_OUTPUT_BUF_SIZE) { /* leave room for '\n' */ 113*4e859e67SDag-Erling Smørgrav rc = ENOBUFS; 114*4e859e67SDag-Erling Smørgrav goto out; 115*4e859e67SDag-Erling Smørgrav } 11659c8e88eSDag-Erling Smørgrav nbuf += n; 11759c8e88eSDag-Erling Smørgrav 11859c8e88eSDag-Erling Smørgrav if (len) { 11959c8e88eSDag-Erling Smørgrav rc = get_atom_byte(&ch, atom, len - 1); 12059c8e88eSDag-Erling Smørgrav if (rc) 121*4e859e67SDag-Erling Smørgrav goto out; 12259c8e88eSDag-Erling Smørgrav if (ch == '\n') 12359c8e88eSDag-Erling Smørgrav len--; 12459c8e88eSDag-Erling Smørgrav } 12559c8e88eSDag-Erling Smørgrav 12659c8e88eSDag-Erling Smørgrav for (i = 0; i < len; i++) { 12759c8e88eSDag-Erling Smørgrav rc = get_atom_byte(&ch, atom, i); 12859c8e88eSDag-Erling Smørgrav if (rc) 129*4e859e67SDag-Erling Smørgrav goto out; 13059c8e88eSDag-Erling Smørgrav if (nbuf >= DIFF_OUTPUT_BUF_SIZE) { 131b95e9602SDag-Erling Smørgrav wlen = fwrite(buf, 1, nbuf, dest); 132*4e859e67SDag-Erling Smørgrav if (wlen != nbuf) { 133*4e859e67SDag-Erling Smørgrav rc = errno; 134*4e859e67SDag-Erling Smørgrav goto out; 135*4e859e67SDag-Erling Smørgrav } 136b95e9602SDag-Erling Smørgrav outlen += wlen; 13759c8e88eSDag-Erling Smørgrav nbuf = 0; 13859c8e88eSDag-Erling Smørgrav } 13959c8e88eSDag-Erling Smørgrav buf[nbuf++] = ch; 14059c8e88eSDag-Erling Smørgrav } 14159c8e88eSDag-Erling Smørgrav buf[nbuf++] = '\n'; 142b95e9602SDag-Erling Smørgrav wlen = fwrite(buf, 1, nbuf, dest); 143*4e859e67SDag-Erling Smørgrav if (wlen != nbuf) { 144*4e859e67SDag-Erling Smørgrav rc = errno; 145*4e859e67SDag-Erling Smørgrav goto out; 146*4e859e67SDag-Erling Smørgrav } 147b95e9602SDag-Erling Smørgrav outlen += wlen; 14859c8e88eSDag-Erling Smørgrav if (outinfo) { 14959c8e88eSDag-Erling Smørgrav ARRAYLIST_ADD(offp, outinfo->line_offsets); 150*4e859e67SDag-Erling Smørgrav if (offp == NULL) { 151*4e859e67SDag-Erling Smørgrav rc = ENOMEM; 152*4e859e67SDag-Erling Smørgrav goto out; 153*4e859e67SDag-Erling Smørgrav } 15459c8e88eSDag-Erling Smørgrav outoff += outlen; 15559c8e88eSDag-Erling Smørgrav *offp = outoff; 15659c8e88eSDag-Erling Smørgrav ARRAYLIST_ADD(typep, outinfo->line_types); 157*4e859e67SDag-Erling Smørgrav if (typep == NULL) { 158*4e859e67SDag-Erling Smørgrav rc = ENOMEM; 159*4e859e67SDag-Erling Smørgrav goto out; 160*4e859e67SDag-Erling Smørgrav } 16159c8e88eSDag-Erling Smørgrav *typep = *prefix == ' ' ? DIFF_LINE_CONTEXT : 16259c8e88eSDag-Erling Smørgrav *prefix == '-' ? DIFF_LINE_MINUS : 16359c8e88eSDag-Erling Smørgrav *prefix == '+' ? DIFF_LINE_PLUS : DIFF_LINE_NONE; 16459c8e88eSDag-Erling Smørgrav } 16559c8e88eSDag-Erling Smørgrav } 16659c8e88eSDag-Erling Smørgrav 167*4e859e67SDag-Erling Smørgrav rc = DIFF_RC_OK; 168*4e859e67SDag-Erling Smørgrav out: 169*4e859e67SDag-Erling Smørgrav if (colored) 170*4e859e67SDag-Erling Smørgrav printf("\033[m"); 171*4e859e67SDag-Erling Smørgrav return rc; 17259c8e88eSDag-Erling Smørgrav } 17359c8e88eSDag-Erling Smørgrav 17459c8e88eSDag-Erling Smørgrav int 17559c8e88eSDag-Erling Smørgrav diff_output_chunk_left_version(struct diff_output_info **output_info, 17659c8e88eSDag-Erling Smørgrav FILE *dest, 17759c8e88eSDag-Erling Smørgrav const struct diff_input_info *info, 17859c8e88eSDag-Erling Smørgrav const struct diff_result *result, 17959c8e88eSDag-Erling Smørgrav const struct diff_chunk_context *cc) 18059c8e88eSDag-Erling Smørgrav { 18159c8e88eSDag-Erling Smørgrav int rc, c_idx; 18259c8e88eSDag-Erling Smørgrav struct diff_output_info *outinfo = NULL; 18359c8e88eSDag-Erling Smørgrav 18459c8e88eSDag-Erling Smørgrav if (diff_range_empty(&cc->left)) 18559c8e88eSDag-Erling Smørgrav return DIFF_RC_OK; 18659c8e88eSDag-Erling Smørgrav 18759c8e88eSDag-Erling Smørgrav if (output_info) { 18859c8e88eSDag-Erling Smørgrav *output_info = diff_output_info_alloc(); 18959c8e88eSDag-Erling Smørgrav if (*output_info == NULL) 19059c8e88eSDag-Erling Smørgrav return ENOMEM; 19159c8e88eSDag-Erling Smørgrav outinfo = *output_info; 19259c8e88eSDag-Erling Smørgrav } 19359c8e88eSDag-Erling Smørgrav 19459c8e88eSDag-Erling Smørgrav /* Write out all chunks on the left side. */ 19559c8e88eSDag-Erling Smørgrav for (c_idx = cc->chunk.start; c_idx < cc->chunk.end; c_idx++) { 19659c8e88eSDag-Erling Smørgrav const struct diff_chunk *c = &result->chunks.head[c_idx]; 19759c8e88eSDag-Erling Smørgrav 19859c8e88eSDag-Erling Smørgrav if (c->left_count) { 19959c8e88eSDag-Erling Smørgrav rc = diff_output_lines(outinfo, dest, "", 20059c8e88eSDag-Erling Smørgrav c->left_start, c->left_count); 20159c8e88eSDag-Erling Smørgrav if (rc) 20259c8e88eSDag-Erling Smørgrav return rc; 20359c8e88eSDag-Erling Smørgrav } 20459c8e88eSDag-Erling Smørgrav } 20559c8e88eSDag-Erling Smørgrav 20659c8e88eSDag-Erling Smørgrav return DIFF_RC_OK; 20759c8e88eSDag-Erling Smørgrav } 20859c8e88eSDag-Erling Smørgrav 20959c8e88eSDag-Erling Smørgrav int 21059c8e88eSDag-Erling Smørgrav diff_output_chunk_right_version(struct diff_output_info **output_info, 21159c8e88eSDag-Erling Smørgrav FILE *dest, 21259c8e88eSDag-Erling Smørgrav const struct diff_input_info *info, 21359c8e88eSDag-Erling Smørgrav const struct diff_result *result, 21459c8e88eSDag-Erling Smørgrav const struct diff_chunk_context *cc) 21559c8e88eSDag-Erling Smørgrav { 21659c8e88eSDag-Erling Smørgrav int rc, c_idx; 21759c8e88eSDag-Erling Smørgrav struct diff_output_info *outinfo = NULL; 21859c8e88eSDag-Erling Smørgrav 21959c8e88eSDag-Erling Smørgrav if (diff_range_empty(&cc->right)) 22059c8e88eSDag-Erling Smørgrav return DIFF_RC_OK; 22159c8e88eSDag-Erling Smørgrav 22259c8e88eSDag-Erling Smørgrav if (output_info) { 22359c8e88eSDag-Erling Smørgrav *output_info = diff_output_info_alloc(); 22459c8e88eSDag-Erling Smørgrav if (*output_info == NULL) 22559c8e88eSDag-Erling Smørgrav return ENOMEM; 22659c8e88eSDag-Erling Smørgrav outinfo = *output_info; 22759c8e88eSDag-Erling Smørgrav } 22859c8e88eSDag-Erling Smørgrav 22959c8e88eSDag-Erling Smørgrav /* Write out all chunks on the right side. */ 23059c8e88eSDag-Erling Smørgrav for (c_idx = cc->chunk.start; c_idx < cc->chunk.end; c_idx++) { 23159c8e88eSDag-Erling Smørgrav const struct diff_chunk *c = &result->chunks.head[c_idx]; 23259c8e88eSDag-Erling Smørgrav 23359c8e88eSDag-Erling Smørgrav if (c->right_count) { 23459c8e88eSDag-Erling Smørgrav rc = diff_output_lines(outinfo, dest, "", c->right_start, 23559c8e88eSDag-Erling Smørgrav c->right_count); 23659c8e88eSDag-Erling Smørgrav if (rc) 23759c8e88eSDag-Erling Smørgrav return rc; 23859c8e88eSDag-Erling Smørgrav } 23959c8e88eSDag-Erling Smørgrav } 24059c8e88eSDag-Erling Smørgrav 24159c8e88eSDag-Erling Smørgrav return DIFF_RC_OK; 24259c8e88eSDag-Erling Smørgrav } 24359c8e88eSDag-Erling Smørgrav 24459c8e88eSDag-Erling Smørgrav int 24559c8e88eSDag-Erling Smørgrav diff_output_trailing_newline_msg(struct diff_output_info *outinfo, FILE *dest, 24659c8e88eSDag-Erling Smørgrav const struct diff_chunk *c) 24759c8e88eSDag-Erling Smørgrav { 24859c8e88eSDag-Erling Smørgrav enum diff_chunk_type chunk_type = diff_chunk_type(c); 24959c8e88eSDag-Erling Smørgrav struct diff_atom *atom, *start_atom; 25059c8e88eSDag-Erling Smørgrav unsigned int atom_count; 25159c8e88eSDag-Erling Smørgrav int rc, ch; 25259c8e88eSDag-Erling Smørgrav off_t outoff = 0, *offp; 25359c8e88eSDag-Erling Smørgrav uint8_t *typep; 25459c8e88eSDag-Erling Smørgrav 25559c8e88eSDag-Erling Smørgrav 25659c8e88eSDag-Erling Smørgrav if (chunk_type == CHUNK_MINUS || chunk_type == CHUNK_SAME) { 25759c8e88eSDag-Erling Smørgrav start_atom = c->left_start; 25859c8e88eSDag-Erling Smørgrav atom_count = c->left_count; 25959c8e88eSDag-Erling Smørgrav } else if (chunk_type == CHUNK_PLUS) { 26059c8e88eSDag-Erling Smørgrav start_atom = c->right_start; 26159c8e88eSDag-Erling Smørgrav atom_count = c->right_count; 26259c8e88eSDag-Erling Smørgrav } else 26359c8e88eSDag-Erling Smørgrav return EINVAL; 26459c8e88eSDag-Erling Smørgrav 26559c8e88eSDag-Erling Smørgrav /* Locate the last atom. */ 26659c8e88eSDag-Erling Smørgrav if (atom_count == 0) 26759c8e88eSDag-Erling Smørgrav return EINVAL; 26859c8e88eSDag-Erling Smørgrav atom = &start_atom[atom_count - 1]; 26959c8e88eSDag-Erling Smørgrav 27059c8e88eSDag-Erling Smørgrav rc = get_atom_byte(&ch, atom, atom->len - 1); 27159c8e88eSDag-Erling Smørgrav if (rc != DIFF_RC_OK) 27259c8e88eSDag-Erling Smørgrav return rc; 27359c8e88eSDag-Erling Smørgrav 27459c8e88eSDag-Erling Smørgrav if (ch != '\n') { 27559c8e88eSDag-Erling Smørgrav if (outinfo && outinfo->line_offsets.len > 0) { 27659c8e88eSDag-Erling Smørgrav unsigned int idx = outinfo->line_offsets.len - 1; 27759c8e88eSDag-Erling Smørgrav outoff = outinfo->line_offsets.head[idx]; 27859c8e88eSDag-Erling Smørgrav } 27959c8e88eSDag-Erling Smørgrav rc = fprintf(dest, "\\ No newline at end of file\n"); 28059c8e88eSDag-Erling Smørgrav if (rc < 0) 28159c8e88eSDag-Erling Smørgrav return errno; 28259c8e88eSDag-Erling Smørgrav if (outinfo) { 28359c8e88eSDag-Erling Smørgrav ARRAYLIST_ADD(offp, outinfo->line_offsets); 28459c8e88eSDag-Erling Smørgrav if (offp == NULL) 28559c8e88eSDag-Erling Smørgrav return ENOMEM; 28659c8e88eSDag-Erling Smørgrav outoff += rc; 28759c8e88eSDag-Erling Smørgrav *offp = outoff; 28859c8e88eSDag-Erling Smørgrav ARRAYLIST_ADD(typep, outinfo->line_types); 28959c8e88eSDag-Erling Smørgrav if (typep == NULL) 29059c8e88eSDag-Erling Smørgrav return ENOMEM; 29159c8e88eSDag-Erling Smørgrav *typep = DIFF_LINE_NONE; 29259c8e88eSDag-Erling Smørgrav } 29359c8e88eSDag-Erling Smørgrav } 29459c8e88eSDag-Erling Smørgrav 29559c8e88eSDag-Erling Smørgrav return DIFF_RC_OK; 29659c8e88eSDag-Erling Smørgrav } 29759c8e88eSDag-Erling Smørgrav 29859c8e88eSDag-Erling Smørgrav static bool 299b95e9602SDag-Erling Smørgrav is_function_prototype(char ch) 30059c8e88eSDag-Erling Smørgrav { 3015fbe8912SDag-Erling Smørgrav return (isalpha((unsigned char)ch) || ch == '_' || ch == '$' || 3025fbe8912SDag-Erling Smørgrav ch == '-' || ch == '+'); 30359c8e88eSDag-Erling Smørgrav } 30459c8e88eSDag-Erling Smørgrav 30559c8e88eSDag-Erling Smørgrav #define begins_with(s, pre) (strncmp(s, pre, sizeof(pre)-1) == 0) 30659c8e88eSDag-Erling Smørgrav 30759c8e88eSDag-Erling Smørgrav int 30859c8e88eSDag-Erling Smørgrav diff_output_match_function_prototype(char *prototype, size_t prototype_size, 30959c8e88eSDag-Erling Smørgrav int *last_prototype_idx, const struct diff_result *result, 3105fbe8912SDag-Erling Smørgrav int chunk_start_line) 31159c8e88eSDag-Erling Smørgrav { 31259c8e88eSDag-Erling Smørgrav struct diff_atom *start_atom, *atom; 31359c8e88eSDag-Erling Smørgrav const struct diff_data *data; 314b95e9602SDag-Erling Smørgrav char buf[DIFF_FUNCTION_CONTEXT_SIZE]; 31559c8e88eSDag-Erling Smørgrav const char *state = NULL; 31659c8e88eSDag-Erling Smørgrav int rc, i, ch; 31759c8e88eSDag-Erling Smørgrav 3185fbe8912SDag-Erling Smørgrav if (result->left->atoms.len > 0 && chunk_start_line > 0) { 31959c8e88eSDag-Erling Smørgrav data = result->left; 3205fbe8912SDag-Erling Smørgrav start_atom = &data->atoms.head[chunk_start_line - 1]; 32159c8e88eSDag-Erling Smørgrav } else 32259c8e88eSDag-Erling Smørgrav return DIFF_RC_OK; 32359c8e88eSDag-Erling Smørgrav 32459c8e88eSDag-Erling Smørgrav diff_data_foreach_atom_backwards_from(start_atom, atom, data) { 32559c8e88eSDag-Erling Smørgrav int atom_idx = diff_atom_root_idx(data, atom); 32659c8e88eSDag-Erling Smørgrav if (atom_idx < *last_prototype_idx) 32759c8e88eSDag-Erling Smørgrav break; 32859c8e88eSDag-Erling Smørgrav rc = get_atom_byte(&ch, atom, 0); 32959c8e88eSDag-Erling Smørgrav if (rc) 33059c8e88eSDag-Erling Smørgrav return rc; 331b95e9602SDag-Erling Smørgrav buf[0] = ch; 33259c8e88eSDag-Erling Smørgrav if (!is_function_prototype(buf[0])) 33359c8e88eSDag-Erling Smørgrav continue; 33459c8e88eSDag-Erling Smørgrav for (i = 1; i < atom->len && i < sizeof(buf) - 1; i++) { 33559c8e88eSDag-Erling Smørgrav rc = get_atom_byte(&ch, atom, i); 33659c8e88eSDag-Erling Smørgrav if (rc) 33759c8e88eSDag-Erling Smørgrav return rc; 33859c8e88eSDag-Erling Smørgrav if (ch == '\n') 33959c8e88eSDag-Erling Smørgrav break; 340b95e9602SDag-Erling Smørgrav buf[i] = ch; 34159c8e88eSDag-Erling Smørgrav } 34259c8e88eSDag-Erling Smørgrav buf[i] = '\0'; 34359c8e88eSDag-Erling Smørgrav if (begins_with(buf, "private:")) { 34459c8e88eSDag-Erling Smørgrav if (!state) 34559c8e88eSDag-Erling Smørgrav state = " (private)"; 34659c8e88eSDag-Erling Smørgrav } else if (begins_with(buf, "protected:")) { 34759c8e88eSDag-Erling Smørgrav if (!state) 34859c8e88eSDag-Erling Smørgrav state = " (protected)"; 34959c8e88eSDag-Erling Smørgrav } else if (begins_with(buf, "public:")) { 35059c8e88eSDag-Erling Smørgrav if (!state) 35159c8e88eSDag-Erling Smørgrav state = " (public)"; 35259c8e88eSDag-Erling Smørgrav } else { 35359c8e88eSDag-Erling Smørgrav if (state) /* don't care about truncation */ 35459c8e88eSDag-Erling Smørgrav strlcat(buf, state, sizeof(buf)); 35559c8e88eSDag-Erling Smørgrav strlcpy(prototype, buf, prototype_size); 35659c8e88eSDag-Erling Smørgrav break; 35759c8e88eSDag-Erling Smørgrav } 35859c8e88eSDag-Erling Smørgrav } 35959c8e88eSDag-Erling Smørgrav 36059c8e88eSDag-Erling Smørgrav *last_prototype_idx = diff_atom_root_idx(data, start_atom); 36159c8e88eSDag-Erling Smørgrav return DIFF_RC_OK; 36259c8e88eSDag-Erling Smørgrav } 36359c8e88eSDag-Erling Smørgrav 36459c8e88eSDag-Erling Smørgrav struct diff_output_info * 36559c8e88eSDag-Erling Smørgrav diff_output_info_alloc(void) 36659c8e88eSDag-Erling Smørgrav { 36759c8e88eSDag-Erling Smørgrav struct diff_output_info *output_info; 36859c8e88eSDag-Erling Smørgrav off_t *offp; 36959c8e88eSDag-Erling Smørgrav uint8_t *typep; 37059c8e88eSDag-Erling Smørgrav 37159c8e88eSDag-Erling Smørgrav output_info = malloc(sizeof(*output_info)); 37259c8e88eSDag-Erling Smørgrav if (output_info != NULL) { 37359c8e88eSDag-Erling Smørgrav ARRAYLIST_INIT(output_info->line_offsets, 128); 37459c8e88eSDag-Erling Smørgrav ARRAYLIST_ADD(offp, output_info->line_offsets); 37559c8e88eSDag-Erling Smørgrav if (offp == NULL) { 37659c8e88eSDag-Erling Smørgrav diff_output_info_free(output_info); 37759c8e88eSDag-Erling Smørgrav return NULL; 37859c8e88eSDag-Erling Smørgrav } 37959c8e88eSDag-Erling Smørgrav *offp = 0; 38059c8e88eSDag-Erling Smørgrav ARRAYLIST_INIT(output_info->line_types, 128); 38159c8e88eSDag-Erling Smørgrav ARRAYLIST_ADD(typep, output_info->line_types); 38259c8e88eSDag-Erling Smørgrav if (typep == NULL) { 38359c8e88eSDag-Erling Smørgrav diff_output_info_free(output_info); 38459c8e88eSDag-Erling Smørgrav return NULL; 38559c8e88eSDag-Erling Smørgrav } 38659c8e88eSDag-Erling Smørgrav *typep = DIFF_LINE_NONE; 38759c8e88eSDag-Erling Smørgrav } 38859c8e88eSDag-Erling Smørgrav return output_info; 38959c8e88eSDag-Erling Smørgrav } 39059c8e88eSDag-Erling Smørgrav 39159c8e88eSDag-Erling Smørgrav void 39259c8e88eSDag-Erling Smørgrav diff_output_info_free(struct diff_output_info *output_info) 39359c8e88eSDag-Erling Smørgrav { 39459c8e88eSDag-Erling Smørgrav ARRAYLIST_FREE(output_info->line_offsets); 39559c8e88eSDag-Erling Smørgrav ARRAYLIST_FREE(output_info->line_types); 39659c8e88eSDag-Erling Smørgrav free(output_info); 39759c8e88eSDag-Erling Smørgrav } 39859c8e88eSDag-Erling Smørgrav 39959c8e88eSDag-Erling Smørgrav const char * 40059c8e88eSDag-Erling Smørgrav diff_output_get_label_left(const struct diff_input_info *info) 40159c8e88eSDag-Erling Smørgrav { 40259c8e88eSDag-Erling Smørgrav if (info->flags & DIFF_INPUT_LEFT_NONEXISTENT) 40359c8e88eSDag-Erling Smørgrav return "/dev/null"; 40459c8e88eSDag-Erling Smørgrav 40559c8e88eSDag-Erling Smørgrav return info->left_path ? info->left_path : "a"; 40659c8e88eSDag-Erling Smørgrav } 40759c8e88eSDag-Erling Smørgrav 40859c8e88eSDag-Erling Smørgrav const char * 40959c8e88eSDag-Erling Smørgrav diff_output_get_label_right(const struct diff_input_info *info) 41059c8e88eSDag-Erling Smørgrav { 41159c8e88eSDag-Erling Smørgrav if (info->flags & DIFF_INPUT_RIGHT_NONEXISTENT) 41259c8e88eSDag-Erling Smørgrav return "/dev/null"; 41359c8e88eSDag-Erling Smørgrav 41459c8e88eSDag-Erling Smørgrav return info->right_path ? info->right_path : "b"; 41559c8e88eSDag-Erling Smørgrav } 416