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 3359c8e88eSDag-Erling Smørgrav static int 3459c8e88eSDag-Erling Smørgrav get_atom_byte(int *ch, struct diff_atom *atom, off_t off) 3559c8e88eSDag-Erling Smørgrav { 3659c8e88eSDag-Erling Smørgrav off_t cur; 3759c8e88eSDag-Erling Smørgrav 3859c8e88eSDag-Erling Smørgrav if (atom->at != NULL) { 3959c8e88eSDag-Erling Smørgrav *ch = atom->at[off]; 4059c8e88eSDag-Erling Smørgrav return 0; 4159c8e88eSDag-Erling Smørgrav } 4259c8e88eSDag-Erling Smørgrav 4359c8e88eSDag-Erling Smørgrav cur = ftello(atom->root->f); 4459c8e88eSDag-Erling Smørgrav if (cur == -1) 4559c8e88eSDag-Erling Smørgrav return errno; 4659c8e88eSDag-Erling Smørgrav 4759c8e88eSDag-Erling Smørgrav if (cur != atom->pos + off && 4859c8e88eSDag-Erling Smørgrav fseeko(atom->root->f, atom->pos + off, SEEK_SET) == -1) 4959c8e88eSDag-Erling Smørgrav return errno; 5059c8e88eSDag-Erling Smørgrav 5159c8e88eSDag-Erling Smørgrav *ch = fgetc(atom->root->f); 5259c8e88eSDag-Erling Smørgrav if (*ch == EOF && ferror(atom->root->f)) 5359c8e88eSDag-Erling Smørgrav return errno; 5459c8e88eSDag-Erling Smørgrav 5559c8e88eSDag-Erling Smørgrav return 0; 5659c8e88eSDag-Erling Smørgrav } 5759c8e88eSDag-Erling Smørgrav 5859c8e88eSDag-Erling Smørgrav #define DIFF_OUTPUT_BUF_SIZE 512 5959c8e88eSDag-Erling Smørgrav 6059c8e88eSDag-Erling Smørgrav int 6159c8e88eSDag-Erling Smørgrav diff_output_lines(struct diff_output_info *outinfo, FILE *dest, 6259c8e88eSDag-Erling Smørgrav const char *prefix, struct diff_atom *start_atom, 6359c8e88eSDag-Erling Smørgrav unsigned int count) 6459c8e88eSDag-Erling Smørgrav { 6559c8e88eSDag-Erling Smørgrav struct diff_atom *atom; 6659c8e88eSDag-Erling Smørgrav off_t outoff = 0, *offp; 6759c8e88eSDag-Erling Smørgrav uint8_t *typep; 6859c8e88eSDag-Erling Smørgrav int rc; 6959c8e88eSDag-Erling Smørgrav 7059c8e88eSDag-Erling Smørgrav if (outinfo && outinfo->line_offsets.len > 0) { 7159c8e88eSDag-Erling Smørgrav unsigned int idx = outinfo->line_offsets.len - 1; 7259c8e88eSDag-Erling Smørgrav outoff = outinfo->line_offsets.head[idx]; 7359c8e88eSDag-Erling Smørgrav } 7459c8e88eSDag-Erling Smørgrav 7559c8e88eSDag-Erling Smørgrav foreach_diff_atom(atom, start_atom, count) { 7659c8e88eSDag-Erling Smørgrav off_t outlen = 0; 7759c8e88eSDag-Erling Smørgrav int i, ch, nbuf = 0; 78*b95e9602SDag-Erling Smørgrav size_t len = atom->len, wlen; 79*b95e9602SDag-Erling Smørgrav char buf[DIFF_OUTPUT_BUF_SIZE + 1 /* '\n' */]; 8059c8e88eSDag-Erling Smørgrav size_t n; 8159c8e88eSDag-Erling Smørgrav 8259c8e88eSDag-Erling Smørgrav n = strlcpy(buf, prefix, sizeof(buf)); 8359c8e88eSDag-Erling Smørgrav if (n >= DIFF_OUTPUT_BUF_SIZE) /* leave room for '\n' */ 8459c8e88eSDag-Erling Smørgrav return ENOBUFS; 8559c8e88eSDag-Erling Smørgrav nbuf += n; 8659c8e88eSDag-Erling Smørgrav 8759c8e88eSDag-Erling Smørgrav if (len) { 8859c8e88eSDag-Erling Smørgrav rc = get_atom_byte(&ch, atom, len - 1); 8959c8e88eSDag-Erling Smørgrav if (rc) 9059c8e88eSDag-Erling Smørgrav return rc; 9159c8e88eSDag-Erling Smørgrav if (ch == '\n') 9259c8e88eSDag-Erling Smørgrav len--; 9359c8e88eSDag-Erling Smørgrav } 9459c8e88eSDag-Erling Smørgrav 9559c8e88eSDag-Erling Smørgrav for (i = 0; i < len; i++) { 9659c8e88eSDag-Erling Smørgrav rc = get_atom_byte(&ch, atom, i); 9759c8e88eSDag-Erling Smørgrav if (rc) 9859c8e88eSDag-Erling Smørgrav return rc; 9959c8e88eSDag-Erling Smørgrav if (nbuf >= DIFF_OUTPUT_BUF_SIZE) { 100*b95e9602SDag-Erling Smørgrav wlen = fwrite(buf, 1, nbuf, dest); 101*b95e9602SDag-Erling Smørgrav if (wlen != nbuf) 10259c8e88eSDag-Erling Smørgrav return errno; 103*b95e9602SDag-Erling Smørgrav outlen += wlen; 10459c8e88eSDag-Erling Smørgrav nbuf = 0; 10559c8e88eSDag-Erling Smørgrav } 10659c8e88eSDag-Erling Smørgrav buf[nbuf++] = ch; 10759c8e88eSDag-Erling Smørgrav } 10859c8e88eSDag-Erling Smørgrav buf[nbuf++] = '\n'; 109*b95e9602SDag-Erling Smørgrav wlen = fwrite(buf, 1, nbuf, dest); 110*b95e9602SDag-Erling Smørgrav if (wlen != nbuf) 11159c8e88eSDag-Erling Smørgrav return errno; 112*b95e9602SDag-Erling Smørgrav outlen += wlen; 11359c8e88eSDag-Erling Smørgrav if (outinfo) { 11459c8e88eSDag-Erling Smørgrav ARRAYLIST_ADD(offp, outinfo->line_offsets); 11559c8e88eSDag-Erling Smørgrav if (offp == NULL) 11659c8e88eSDag-Erling Smørgrav return ENOMEM; 11759c8e88eSDag-Erling Smørgrav outoff += outlen; 11859c8e88eSDag-Erling Smørgrav *offp = outoff; 11959c8e88eSDag-Erling Smørgrav ARRAYLIST_ADD(typep, outinfo->line_types); 12059c8e88eSDag-Erling Smørgrav if (typep == NULL) 12159c8e88eSDag-Erling Smørgrav return ENOMEM; 12259c8e88eSDag-Erling Smørgrav *typep = *prefix == ' ' ? DIFF_LINE_CONTEXT : 12359c8e88eSDag-Erling Smørgrav *prefix == '-' ? DIFF_LINE_MINUS : 12459c8e88eSDag-Erling Smørgrav *prefix == '+' ? DIFF_LINE_PLUS : DIFF_LINE_NONE; 12559c8e88eSDag-Erling Smørgrav } 12659c8e88eSDag-Erling Smørgrav } 12759c8e88eSDag-Erling Smørgrav 12859c8e88eSDag-Erling Smørgrav return DIFF_RC_OK; 12959c8e88eSDag-Erling Smørgrav } 13059c8e88eSDag-Erling Smørgrav 13159c8e88eSDag-Erling Smørgrav int 13259c8e88eSDag-Erling Smørgrav diff_output_chunk_left_version(struct diff_output_info **output_info, 13359c8e88eSDag-Erling Smørgrav FILE *dest, 13459c8e88eSDag-Erling Smørgrav const struct diff_input_info *info, 13559c8e88eSDag-Erling Smørgrav const struct diff_result *result, 13659c8e88eSDag-Erling Smørgrav const struct diff_chunk_context *cc) 13759c8e88eSDag-Erling Smørgrav { 13859c8e88eSDag-Erling Smørgrav int rc, c_idx; 13959c8e88eSDag-Erling Smørgrav struct diff_output_info *outinfo = NULL; 14059c8e88eSDag-Erling Smørgrav 14159c8e88eSDag-Erling Smørgrav if (diff_range_empty(&cc->left)) 14259c8e88eSDag-Erling Smørgrav return DIFF_RC_OK; 14359c8e88eSDag-Erling Smørgrav 14459c8e88eSDag-Erling Smørgrav if (output_info) { 14559c8e88eSDag-Erling Smørgrav *output_info = diff_output_info_alloc(); 14659c8e88eSDag-Erling Smørgrav if (*output_info == NULL) 14759c8e88eSDag-Erling Smørgrav return ENOMEM; 14859c8e88eSDag-Erling Smørgrav outinfo = *output_info; 14959c8e88eSDag-Erling Smørgrav } 15059c8e88eSDag-Erling Smørgrav 15159c8e88eSDag-Erling Smørgrav /* Write out all chunks on the left side. */ 15259c8e88eSDag-Erling Smørgrav for (c_idx = cc->chunk.start; c_idx < cc->chunk.end; c_idx++) { 15359c8e88eSDag-Erling Smørgrav const struct diff_chunk *c = &result->chunks.head[c_idx]; 15459c8e88eSDag-Erling Smørgrav 15559c8e88eSDag-Erling Smørgrav if (c->left_count) { 15659c8e88eSDag-Erling Smørgrav rc = diff_output_lines(outinfo, dest, "", 15759c8e88eSDag-Erling Smørgrav c->left_start, c->left_count); 15859c8e88eSDag-Erling Smørgrav if (rc) 15959c8e88eSDag-Erling Smørgrav return rc; 16059c8e88eSDag-Erling Smørgrav } 16159c8e88eSDag-Erling Smørgrav } 16259c8e88eSDag-Erling Smørgrav 16359c8e88eSDag-Erling Smørgrav return DIFF_RC_OK; 16459c8e88eSDag-Erling Smørgrav } 16559c8e88eSDag-Erling Smørgrav 16659c8e88eSDag-Erling Smørgrav int 16759c8e88eSDag-Erling Smørgrav diff_output_chunk_right_version(struct diff_output_info **output_info, 16859c8e88eSDag-Erling Smørgrav FILE *dest, 16959c8e88eSDag-Erling Smørgrav const struct diff_input_info *info, 17059c8e88eSDag-Erling Smørgrav const struct diff_result *result, 17159c8e88eSDag-Erling Smørgrav const struct diff_chunk_context *cc) 17259c8e88eSDag-Erling Smørgrav { 17359c8e88eSDag-Erling Smørgrav int rc, c_idx; 17459c8e88eSDag-Erling Smørgrav struct diff_output_info *outinfo = NULL; 17559c8e88eSDag-Erling Smørgrav 17659c8e88eSDag-Erling Smørgrav if (diff_range_empty(&cc->right)) 17759c8e88eSDag-Erling Smørgrav return DIFF_RC_OK; 17859c8e88eSDag-Erling Smørgrav 17959c8e88eSDag-Erling Smørgrav if (output_info) { 18059c8e88eSDag-Erling Smørgrav *output_info = diff_output_info_alloc(); 18159c8e88eSDag-Erling Smørgrav if (*output_info == NULL) 18259c8e88eSDag-Erling Smørgrav return ENOMEM; 18359c8e88eSDag-Erling Smørgrav outinfo = *output_info; 18459c8e88eSDag-Erling Smørgrav } 18559c8e88eSDag-Erling Smørgrav 18659c8e88eSDag-Erling Smørgrav /* Write out all chunks on the right side. */ 18759c8e88eSDag-Erling Smørgrav for (c_idx = cc->chunk.start; c_idx < cc->chunk.end; c_idx++) { 18859c8e88eSDag-Erling Smørgrav const struct diff_chunk *c = &result->chunks.head[c_idx]; 18959c8e88eSDag-Erling Smørgrav 19059c8e88eSDag-Erling Smørgrav if (c->right_count) { 19159c8e88eSDag-Erling Smørgrav rc = diff_output_lines(outinfo, dest, "", c->right_start, 19259c8e88eSDag-Erling Smørgrav c->right_count); 19359c8e88eSDag-Erling Smørgrav if (rc) 19459c8e88eSDag-Erling Smørgrav return rc; 19559c8e88eSDag-Erling Smørgrav } 19659c8e88eSDag-Erling Smørgrav } 19759c8e88eSDag-Erling Smørgrav 19859c8e88eSDag-Erling Smørgrav return DIFF_RC_OK; 19959c8e88eSDag-Erling Smørgrav } 20059c8e88eSDag-Erling Smørgrav 20159c8e88eSDag-Erling Smørgrav int 20259c8e88eSDag-Erling Smørgrav diff_output_trailing_newline_msg(struct diff_output_info *outinfo, FILE *dest, 20359c8e88eSDag-Erling Smørgrav const struct diff_chunk *c) 20459c8e88eSDag-Erling Smørgrav { 20559c8e88eSDag-Erling Smørgrav enum diff_chunk_type chunk_type = diff_chunk_type(c); 20659c8e88eSDag-Erling Smørgrav struct diff_atom *atom, *start_atom; 20759c8e88eSDag-Erling Smørgrav unsigned int atom_count; 20859c8e88eSDag-Erling Smørgrav int rc, ch; 20959c8e88eSDag-Erling Smørgrav off_t outoff = 0, *offp; 21059c8e88eSDag-Erling Smørgrav uint8_t *typep; 21159c8e88eSDag-Erling Smørgrav 21259c8e88eSDag-Erling Smørgrav 21359c8e88eSDag-Erling Smørgrav if (chunk_type == CHUNK_MINUS || chunk_type == CHUNK_SAME) { 21459c8e88eSDag-Erling Smørgrav start_atom = c->left_start; 21559c8e88eSDag-Erling Smørgrav atom_count = c->left_count; 21659c8e88eSDag-Erling Smørgrav } else if (chunk_type == CHUNK_PLUS) { 21759c8e88eSDag-Erling Smørgrav start_atom = c->right_start; 21859c8e88eSDag-Erling Smørgrav atom_count = c->right_count; 21959c8e88eSDag-Erling Smørgrav } else 22059c8e88eSDag-Erling Smørgrav return EINVAL; 22159c8e88eSDag-Erling Smørgrav 22259c8e88eSDag-Erling Smørgrav /* Locate the last atom. */ 22359c8e88eSDag-Erling Smørgrav if (atom_count == 0) 22459c8e88eSDag-Erling Smørgrav return EINVAL; 22559c8e88eSDag-Erling Smørgrav atom = &start_atom[atom_count - 1]; 22659c8e88eSDag-Erling Smørgrav 22759c8e88eSDag-Erling Smørgrav rc = get_atom_byte(&ch, atom, atom->len - 1); 22859c8e88eSDag-Erling Smørgrav if (rc != DIFF_RC_OK) 22959c8e88eSDag-Erling Smørgrav return rc; 23059c8e88eSDag-Erling Smørgrav 23159c8e88eSDag-Erling Smørgrav if (ch != '\n') { 23259c8e88eSDag-Erling Smørgrav if (outinfo && outinfo->line_offsets.len > 0) { 23359c8e88eSDag-Erling Smørgrav unsigned int idx = outinfo->line_offsets.len - 1; 23459c8e88eSDag-Erling Smørgrav outoff = outinfo->line_offsets.head[idx]; 23559c8e88eSDag-Erling Smørgrav } 23659c8e88eSDag-Erling Smørgrav rc = fprintf(dest, "\\ No newline at end of file\n"); 23759c8e88eSDag-Erling Smørgrav if (rc < 0) 23859c8e88eSDag-Erling Smørgrav return errno; 23959c8e88eSDag-Erling Smørgrav if (outinfo) { 24059c8e88eSDag-Erling Smørgrav ARRAYLIST_ADD(offp, outinfo->line_offsets); 24159c8e88eSDag-Erling Smørgrav if (offp == NULL) 24259c8e88eSDag-Erling Smørgrav return ENOMEM; 24359c8e88eSDag-Erling Smørgrav outoff += rc; 24459c8e88eSDag-Erling Smørgrav *offp = outoff; 24559c8e88eSDag-Erling Smørgrav ARRAYLIST_ADD(typep, outinfo->line_types); 24659c8e88eSDag-Erling Smørgrav if (typep == NULL) 24759c8e88eSDag-Erling Smørgrav return ENOMEM; 24859c8e88eSDag-Erling Smørgrav *typep = DIFF_LINE_NONE; 24959c8e88eSDag-Erling Smørgrav } 25059c8e88eSDag-Erling Smørgrav } 25159c8e88eSDag-Erling Smørgrav 25259c8e88eSDag-Erling Smørgrav return DIFF_RC_OK; 25359c8e88eSDag-Erling Smørgrav } 25459c8e88eSDag-Erling Smørgrav 25559c8e88eSDag-Erling Smørgrav static bool 256*b95e9602SDag-Erling Smørgrav is_function_prototype(char ch) 25759c8e88eSDag-Erling Smørgrav { 2585fbe8912SDag-Erling Smørgrav return (isalpha((unsigned char)ch) || ch == '_' || ch == '$' || 2595fbe8912SDag-Erling Smørgrav ch == '-' || ch == '+'); 26059c8e88eSDag-Erling Smørgrav } 26159c8e88eSDag-Erling Smørgrav 26259c8e88eSDag-Erling Smørgrav #define begins_with(s, pre) (strncmp(s, pre, sizeof(pre)-1) == 0) 26359c8e88eSDag-Erling Smørgrav 26459c8e88eSDag-Erling Smørgrav int 26559c8e88eSDag-Erling Smørgrav diff_output_match_function_prototype(char *prototype, size_t prototype_size, 26659c8e88eSDag-Erling Smørgrav int *last_prototype_idx, const struct diff_result *result, 2675fbe8912SDag-Erling Smørgrav int chunk_start_line) 26859c8e88eSDag-Erling Smørgrav { 26959c8e88eSDag-Erling Smørgrav struct diff_atom *start_atom, *atom; 27059c8e88eSDag-Erling Smørgrav const struct diff_data *data; 271*b95e9602SDag-Erling Smørgrav char buf[DIFF_FUNCTION_CONTEXT_SIZE]; 27259c8e88eSDag-Erling Smørgrav const char *state = NULL; 27359c8e88eSDag-Erling Smørgrav int rc, i, ch; 27459c8e88eSDag-Erling Smørgrav 2755fbe8912SDag-Erling Smørgrav if (result->left->atoms.len > 0 && chunk_start_line > 0) { 27659c8e88eSDag-Erling Smørgrav data = result->left; 2775fbe8912SDag-Erling Smørgrav start_atom = &data->atoms.head[chunk_start_line - 1]; 27859c8e88eSDag-Erling Smørgrav } else 27959c8e88eSDag-Erling Smørgrav return DIFF_RC_OK; 28059c8e88eSDag-Erling Smørgrav 28159c8e88eSDag-Erling Smørgrav diff_data_foreach_atom_backwards_from(start_atom, atom, data) { 28259c8e88eSDag-Erling Smørgrav int atom_idx = diff_atom_root_idx(data, atom); 28359c8e88eSDag-Erling Smørgrav if (atom_idx < *last_prototype_idx) 28459c8e88eSDag-Erling Smørgrav break; 28559c8e88eSDag-Erling Smørgrav rc = get_atom_byte(&ch, atom, 0); 28659c8e88eSDag-Erling Smørgrav if (rc) 28759c8e88eSDag-Erling Smørgrav return rc; 288*b95e9602SDag-Erling Smørgrav buf[0] = ch; 28959c8e88eSDag-Erling Smørgrav if (!is_function_prototype(buf[0])) 29059c8e88eSDag-Erling Smørgrav continue; 29159c8e88eSDag-Erling Smørgrav for (i = 1; i < atom->len && i < sizeof(buf) - 1; i++) { 29259c8e88eSDag-Erling Smørgrav rc = get_atom_byte(&ch, atom, i); 29359c8e88eSDag-Erling Smørgrav if (rc) 29459c8e88eSDag-Erling Smørgrav return rc; 29559c8e88eSDag-Erling Smørgrav if (ch == '\n') 29659c8e88eSDag-Erling Smørgrav break; 297*b95e9602SDag-Erling Smørgrav buf[i] = ch; 29859c8e88eSDag-Erling Smørgrav } 29959c8e88eSDag-Erling Smørgrav buf[i] = '\0'; 30059c8e88eSDag-Erling Smørgrav if (begins_with(buf, "private:")) { 30159c8e88eSDag-Erling Smørgrav if (!state) 30259c8e88eSDag-Erling Smørgrav state = " (private)"; 30359c8e88eSDag-Erling Smørgrav } else if (begins_with(buf, "protected:")) { 30459c8e88eSDag-Erling Smørgrav if (!state) 30559c8e88eSDag-Erling Smørgrav state = " (protected)"; 30659c8e88eSDag-Erling Smørgrav } else if (begins_with(buf, "public:")) { 30759c8e88eSDag-Erling Smørgrav if (!state) 30859c8e88eSDag-Erling Smørgrav state = " (public)"; 30959c8e88eSDag-Erling Smørgrav } else { 31059c8e88eSDag-Erling Smørgrav if (state) /* don't care about truncation */ 31159c8e88eSDag-Erling Smørgrav strlcat(buf, state, sizeof(buf)); 31259c8e88eSDag-Erling Smørgrav strlcpy(prototype, buf, prototype_size); 31359c8e88eSDag-Erling Smørgrav break; 31459c8e88eSDag-Erling Smørgrav } 31559c8e88eSDag-Erling Smørgrav } 31659c8e88eSDag-Erling Smørgrav 31759c8e88eSDag-Erling Smørgrav *last_prototype_idx = diff_atom_root_idx(data, start_atom); 31859c8e88eSDag-Erling Smørgrav return DIFF_RC_OK; 31959c8e88eSDag-Erling Smørgrav } 32059c8e88eSDag-Erling Smørgrav 32159c8e88eSDag-Erling Smørgrav struct diff_output_info * 32259c8e88eSDag-Erling Smørgrav diff_output_info_alloc(void) 32359c8e88eSDag-Erling Smørgrav { 32459c8e88eSDag-Erling Smørgrav struct diff_output_info *output_info; 32559c8e88eSDag-Erling Smørgrav off_t *offp; 32659c8e88eSDag-Erling Smørgrav uint8_t *typep; 32759c8e88eSDag-Erling Smørgrav 32859c8e88eSDag-Erling Smørgrav output_info = malloc(sizeof(*output_info)); 32959c8e88eSDag-Erling Smørgrav if (output_info != NULL) { 33059c8e88eSDag-Erling Smørgrav ARRAYLIST_INIT(output_info->line_offsets, 128); 33159c8e88eSDag-Erling Smørgrav ARRAYLIST_ADD(offp, output_info->line_offsets); 33259c8e88eSDag-Erling Smørgrav if (offp == NULL) { 33359c8e88eSDag-Erling Smørgrav diff_output_info_free(output_info); 33459c8e88eSDag-Erling Smørgrav return NULL; 33559c8e88eSDag-Erling Smørgrav } 33659c8e88eSDag-Erling Smørgrav *offp = 0; 33759c8e88eSDag-Erling Smørgrav ARRAYLIST_INIT(output_info->line_types, 128); 33859c8e88eSDag-Erling Smørgrav ARRAYLIST_ADD(typep, output_info->line_types); 33959c8e88eSDag-Erling Smørgrav if (typep == NULL) { 34059c8e88eSDag-Erling Smørgrav diff_output_info_free(output_info); 34159c8e88eSDag-Erling Smørgrav return NULL; 34259c8e88eSDag-Erling Smørgrav } 34359c8e88eSDag-Erling Smørgrav *typep = DIFF_LINE_NONE; 34459c8e88eSDag-Erling Smørgrav } 34559c8e88eSDag-Erling Smørgrav return output_info; 34659c8e88eSDag-Erling Smørgrav } 34759c8e88eSDag-Erling Smørgrav 34859c8e88eSDag-Erling Smørgrav void 34959c8e88eSDag-Erling Smørgrav diff_output_info_free(struct diff_output_info *output_info) 35059c8e88eSDag-Erling Smørgrav { 35159c8e88eSDag-Erling Smørgrav ARRAYLIST_FREE(output_info->line_offsets); 35259c8e88eSDag-Erling Smørgrav ARRAYLIST_FREE(output_info->line_types); 35359c8e88eSDag-Erling Smørgrav free(output_info); 35459c8e88eSDag-Erling Smørgrav } 35559c8e88eSDag-Erling Smørgrav 35659c8e88eSDag-Erling Smørgrav const char * 35759c8e88eSDag-Erling Smørgrav diff_output_get_label_left(const struct diff_input_info *info) 35859c8e88eSDag-Erling Smørgrav { 35959c8e88eSDag-Erling Smørgrav if (info->flags & DIFF_INPUT_LEFT_NONEXISTENT) 36059c8e88eSDag-Erling Smørgrav return "/dev/null"; 36159c8e88eSDag-Erling Smørgrav 36259c8e88eSDag-Erling Smørgrav return info->left_path ? info->left_path : "a"; 36359c8e88eSDag-Erling Smørgrav } 36459c8e88eSDag-Erling Smørgrav 36559c8e88eSDag-Erling Smørgrav const char * 36659c8e88eSDag-Erling Smørgrav diff_output_get_label_right(const struct diff_input_info *info) 36759c8e88eSDag-Erling Smørgrav { 36859c8e88eSDag-Erling Smørgrav if (info->flags & DIFF_INPUT_RIGHT_NONEXISTENT) 36959c8e88eSDag-Erling Smørgrav return "/dev/null"; 37059c8e88eSDag-Erling Smørgrav 37159c8e88eSDag-Erling Smørgrav return info->right_path ? info->right_path : "b"; 37259c8e88eSDag-Erling Smørgrav } 373