<commit_before>/*
 * Copyright (C) 1984-2012  <NAME>
 * Modified for use with illumos by <NAME>.
 * Copyright 2014 <NAME> <<EMAIL>>
 *
 * You may distribute under the terms of either the GNU General Public
 * License or the Less License, as specified in the README file.
 *
 * For more information, see the README file.
 */

#include "less.h"

#define	WHITESP(c)	((c) == ' ' || (c) == '\t')

char *tags = "tags";

static int total;
static int curseq;

extern int linenums;
extern volatile sig_atomic_t sigs;

enum tag_result {
	TAG_FOUND,
	TAG_NOFILE,
	TAG_NOTAG,
	TAG_NOTYPE,
	TAG_INTR
};

/*
 * Tag type
 */
enum {
	T_CTAGS,	/* 'tags': standard and extended format (ctags) */
	T_CTAGS_X,	/* stdin: cross reference format (ctags) */
	T_GTAGS,	/* 'GTAGS': function defenition (global) */
	T_GRTAGS,	/* 'GRTAGS': function reference (global) */
	T_GSYMS,	/* 'GSYMS': other symbols (global) */
	T_GPATH		/* 'GPATH': path name (global) */
};

static enum tag_result findctag();
static enum tag_result findgtag();
static char *nextgtag();
static char *prevgtag();
static off_t ctagsearch();
static off_t gtagsearch();
static int getentry();

/*
 * The list of tags generated by the last findgtag() call.
 *
 * Use either pattern or line number.
 * findgtag() always uses line number, so pattern is always NULL.
 * findctag() uses either pattern (in which case line number is 0),
 * or line number (in which case pattern is NULL).
 */
struct taglist {
	struct tag *tl_first;
	struct tag *tl_last;
};
#define	TAG_END  ((struct tag *)&taglist)
static struct taglist taglist = { TAG_END, TAG_END };
struct tag {
	struct tag *next, *prev; /* List links */
	char *tag_file;		/* Source file containing the tag */
	LINENUM tag_linenum;	/* Appropriate line number in source file */
	char *tag_pattern;	/* Pattern used to find the tag */
	int tag_endline;	/* True if the pattern includes '$' */
};
static struct tag *curtag;

#define	TAG_INS(tp) \
	(tp)->next = TAG_END; \
	(tp)->prev = taglist.tl_last; \
	taglist.tl_last->next = (tp); \
	taglist.tl_last = (tp);

#define	TAG_RM(tp) \
	(tp)->next->prev = (tp)->prev; \
	(tp)->prev->next = (tp)->next;

/*
 * Delete tag structures.
 */
void
cleantags(void)
{
	struct tag *tp;

	/*
	 * Delete any existing tag list.
	 * {{ Ideally, we wouldn't do this until after we know that we
	 *    can load some other tag information. }}
	 */
	while ((tp = taglist.tl_first) != TAG_END) {
		TAG_RM(tp);
		free(tp);
	}
	curtag = NULL;
	total = curseq = 0;
}

/*
 * Create a new tag entry.
 */
static struct tag *
maketagent(char *file, LINENUM linenum, char *pattern, int endline)
{
	struct tag *tp;

	tp = ecalloc(sizeof (struct tag), 1);
	tp->tag_file = save(file);
	tp->tag_linenum = linenum;
	tp->tag_endline = endline;
	if (pattern == NULL)
		tp->tag_pattern = NULL;
	else
		tp->tag_pattern = save(pattern);
	return (tp);
}

/*
 * Get tag mode.
 */
static int<commit_msg>Plug memory leak<commit_after>/*
 * Copyright (C) 1984-2012  <NAME>
 * Modified for use with illumos by <NAME>.
 * Copyright 2014 <NAME> <<EMAIL>>
 *
 * You may distribute under the terms of either the GNU General Public
 * License or the Less License, as specified in the README file.
 *
 * For more information, see the README file.
 */

#include "less.h"

#define	WHITESP(c)	((c) == ' ' || (c) == '\t')

char *tags = "tags";

static int total;
static int curseq;

extern int linenums;
extern volatile sig_atomic_t sigs;

enum tag_result {
	TAG_FOUND,
	TAG_NOFILE,
	TAG_NOTAG,
	TAG_NOTYPE,
	TAG_INTR
};

/*
 * Tag type
 */
enum {
	T_CTAGS,	/* 'tags': standard and extended format (ctags) */
	T_CTAGS_X,	/* stdin: cross reference format (ctags) */
	T_GTAGS,	/* 'GTAGS': function defenition (global) */
	T_GRTAGS,	/* 'GRTAGS': function reference (global) */
	T_GSYMS,	/* 'GSYMS': other symbols (global) */
	T_GPATH		/* 'GPATH': path name (global) */
};

static enum tag_result findctag();
static enum tag_result findgtag();
static char *nextgtag();
static char *prevgtag();
static off_t ctagsearch();
static off_t gtagsearch();
static int getentry();

/*
 * The list of tags generated by the last findgtag() call.
 *
 * Use either pattern or line number.
 * findgtag() always uses line number, so pattern is always NULL.
 * findctag() uses either pattern (in which case line number is 0),
 * or line number (in which case pattern is NULL).
 */
struct taglist {
	struct tag *tl_first;
	struct tag *tl_last;
};
#define	TAG_END  ((struct tag *)&taglist)
static struct taglist taglist = { TAG_END, TAG_END };
struct tag {
	struct tag *next, *prev; /* List links */
	char *tag_file;		/* Source file containing the tag */
	LINENUM tag_linenum;	/* Appropriate line number in source file */
	char *tag_pattern;	/* Pattern used to find the tag */
	int tag_endline;	/* True if the pattern includes '$' */
};
static struct tag *curtag;

#define	TAG_INS(tp) \
	(tp)->next = TAG_END; \
	(tp)->prev = taglist.tl_last; \
	taglist.tl_last->next = (tp); \
	taglist.tl_last = (tp);

#define	TAG_RM(tp) \
	(tp)->next->prev = (tp)->prev; \
	(tp)->prev->next = (tp)->next;

/*
 * Delete tag structures.
 */
void
cleantags(void)
{
	struct tag *tp;

	/*
	 * Delete any existing tag list.
	 * {{ Ideally, we wouldn't do this until after we know that we
	 *    can load some other tag information. }}
	 */
	while ((tp = taglist.tl_first) != TAG_END) {
		TAG_RM(tp);
		free(tp->tag_file);
		free(tp->tag_pattern);
		free(tp);
	}
	curtag = NULL;
	total = curseq = 0;
}

/*
 * Create a new tag entry.
 */
static struct tag *
maketagent(char *file, LINENUM linenum, char *pattern, int endline)
{
	struct tag *tp;

	tp = ecalloc(sizeof (struct tag), 1);
	tp->tag_file = save(file);
	tp->tag_linenum = linenum;
	tp->tag_endline = endline;
	if (pattern == NULL)
		tp->tag_pattern = NULL;
	else
		tp->tag_pattern = save(pattern);
	return (tp);
}

/*
 * Get tag mode.
 */
static int
{'fraction_non_alphanumeric': 0.14368799178925762, 'fraction_numerical': 0.005131713992473486, 'mean_word_length': 3.629453681710214, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2900040', 'n_tokens_mistral': 2182, 'n_tokens_neox': 2102, 'n_words': 691}