⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 readtags.c

📁 ctags-5.5.4.tar.gz,一个很好的代码开发以及编辑源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/**   $Id: readtags.c,v 1.24 2003/07/20 18:46:30 darren Exp $**   Copyright (c) 1996-2003, Darren Hiebert**   This source code is released into the public domain.**   This module contains functions for reading tag files.*//**   INCLUDE FILES*/#include <stdlib.h>#include <string.h>#include <ctype.h>#include <stdio.h>#include <errno.h>#include <sys/types.h>	/* to declare off_t */#include "readtags.h"/**   MACROS*/#define TAB '\t'/**   DATA DECLARATIONS*/typedef struct {    size_t size;    char *buffer;} vstring;/* Information about current tag file */struct sTagFile {	/* has the file been opened and this structure initialized? */    short initialized;	/* format of tag file */    short format;	/* how is the tag file sorted? */    sortType sortMethod;	/* pointer to file structure */    FILE* fp;	/* file position of first character of `line' */    off_t pos;	/* size of tag file in seekable positions */    off_t size;	/* last line read */    vstring line;	/* name of tag in last line read */    vstring name;	/* defines tag search state */    struct {		/* file position of last match for tag */	    off_t pos; 		/* name of tag last searched for */	    const char *name;		/* length of name for partial matches */	    size_t nameLength;		/* peforming partial match */	    short partial;		/* ignoring case */	    short ignorecase;    } search;	/* miscellaneous extension fields */    struct {		/* number of entries in `list' */	    unsigned short max;		/* list of key value pairs */	    tagExtensionField *list;    } fields;	/* buffers to be freed at close */    struct {	    /* name of program author */	char *author;	    /* name of program */	char *name;	    /* URL of distribution */	char *url;	    /* program version */	char *version;    } program;};/**   DATA DEFINITIONS*/const char *const EmptyString = "";const char *const PseudoTagPrefix = "!_";/**   FUNCTION DEFINITIONS*//* * Compare two strings, ignoring case. * Return 0 for match, < 0 for smaller, > 0 for bigger * Make sure case is folded to uppercase in comparison (like for 'sort -f') * This makes a difference when one of the chars lies between upper and lower * ie. one of the chars [ \ ] ^ _ ` for ascii. (The '_' in particular !) */static int struppercmp (const char *s1, const char *s2){    int result;    do    {	result = toupper ((int) *s1) - toupper ((int) *s2);    } while (result == 0  &&  *s1++ != '\0'  &&  *s2++ != '\0');    return result;}static int strnuppercmp (const char *s1, const char *s2, size_t n){    int result;    do    {	result = toupper ((int) *s1) - toupper ((int) *s2);    } while (result == 0  &&  --n > 0  &&  *s1++ != '\0'  &&  *s2++ != '\0');    return result;}static int growString (vstring *s){    int result = 0;    size_t newLength;    char *newLine;    if (s->size == 0)    {	newLength = 128;	newLine = (char*) malloc (newLength);	*newLine = '\0';    }    else    {	newLength = 2 * s->size;	newLine = (char*) realloc (s->buffer, newLength);    }    if (newLine == NULL)	perror ("string too large");    else    {	s->buffer = newLine;	s->size = newLength;	result = 1;    }    return result;}/* Copy name of tag out of tag line */static void copyName (tagFile *const file){    size_t length;    const char *end = strchr (file->line.buffer, '\t');    if (end == NULL)    {	end = strchr (file->line.buffer, '\n');	if (end == NULL)	    end = strchr (file->line.buffer, '\r');    }    if (end != NULL)	length = end - file->line.buffer;    else	length = strlen (file->line.buffer);    while (length >= file->name.size)	growString (&file->name);    strncpy (file->name.buffer, file->line.buffer, length);    file->name.buffer [length] = '\0';}static int readTagLineRaw (tagFile *const file){    int result = 1;    int reReadLine;    /*  If reading the line places any character other than a null or a     *  newline at the last character position in the buffer (one less than     *  the buffer size), then we must resize the buffer and reattempt to read     *  the line.     */    do    {	char *const pLastChar = file->line.buffer + file->line.size - 2;	char *line;	file->pos = ftell (file->fp);	reReadLine = 0;	*pLastChar = '\0';	line = fgets (file->line.buffer, (int) file->line.size, file->fp);	if (line == NULL)	{	    /* read error */	    if (! feof (file->fp))		perror ("readTagLine");	    result = 0;	}	else if (*pLastChar != '\0'  &&		    *pLastChar != '\n'  &&  *pLastChar != '\r')	{	    /*  buffer overflow */	    growString (&file->line);	    fseek (file->fp, file->pos, SEEK_SET);	    reReadLine = 1;	}	else	{	    size_t i = strlen (file->line.buffer);	    while (i > 0  &&		   (file->line.buffer [i - 1] == '\n' || file->line.buffer [i - 1] == '\r'))	    {		file->line.buffer [i - 1] = '\0';		--i;	    }	}    } while (reReadLine  &&  result);    if (result)	copyName (file);    return result;}static int readTagLine (tagFile *const file){    int result;    do    {	result = readTagLineRaw (file);    } while (result && *file->name.buffer == '\0');    return result;}static tagResult growFields (tagFile *const file){    tagResult result = TagFailure;    unsigned short newCount = 2 * file->fields.max;    tagExtensionField *newFields = (tagExtensionField*)	    realloc (file->fields.list, newCount * sizeof (tagExtensionField));    if (newFields == NULL)	perror ("too many extension fields");    else    {	file->fields.list = newFields;	file->fields.max = newCount;	result = TagSuccess;    }    return result;}static void parseExtensionFields (tagFile *const file, tagEntry *const entry,				  char *const string){    char *p = string;    while (p != NULL  &&  *p != '\0')    {	while (*p == TAB)	    *p++ = '\0';	if (*p != '\0')	{	    char *colon;	    char *field = p;	    p = strchr (p, TAB);	    if (p != NULL)		*p++ = '\0';	    colon = strchr (field, ':');	    if (colon == NULL)		entry->kind = field;	    else	    {		const char *key = field;		const char *value = colon + 1;		*colon = '\0';		if (strcmp (key, "kind") == 0)		    entry->kind = value;		else if (strcmp (key, "file") == 0)		    entry->fileScope = 1;		else if (strcmp (key, "line") == 0)		    entry->address.lineNumber = atol (value);		else		{		    if (entry->fields.count == file->fields.max)			growFields (file);		    file->fields.list [entry->fields.count].key = key;		    file->fields.list [entry->fields.count].value = value;		    ++entry->fields.count;		}	    }	}    }}static void parseTagLine (tagFile *file, tagEntry *const entry){    int i;    char *p = file->line.buffer;    char *tab = strchr (p, TAB);    int fieldsPresent = 0;    entry->fields.list = NULL;    entry->fields.count = 0;    entry->kind = NULL;    entry->fileScope = 0;    entry->name = p;    if (tab != NULL)    {	*tab = '\0';	p = tab + 1;	entry->file = p;	tab = strchr (p, TAB);	if (tab != NULL)	{	    *tab = '\0';	    p = tab + 1;	    if (*p == '/'  ||  *p == '?')	    {		/* parse pattern */		int delimiter = *(unsigned char*) p;		entry->address.lineNumber = 0;		entry->address.pattern = p;		do		{		    p = strchr (p + 1, delimiter);		} while (p != NULL  &&  *(p - 1) == '\\');		if (p == NULL)		{		    /* invalid pattern */		}		else		    ++p;	    }	    else if (isdigit ((int) *(unsigned char*) p))	    {		/* parse line number */		entry->address.pattern = p;		entry->address.lineNumber = atol (p);		while (isdigit ((int) *(unsigned char*) p))		    ++p;	    }	    else	    {		/* invalid pattern */	    }	    fieldsPresent = (strncmp (p, ";\"", 2) == 0);	    *p = '\0';	    if (fieldsPresent)		parseExtensionFields (file, entry, p + 2);	}    }    if (entry->fields.count > 0)	entry->fields.list = file->fields.list;    for (i = entry->fields.count  ;  i < file->fields.max  ;  ++i)    {	file->fields.list [i].key = NULL;	file->fields.list [i].value = NULL;    }}static char *duplicate (const char *str){    char *result = NULL;    if (str != NULL)    {	result = (char*) malloc (strlen (str) + 1);	if (result == NULL)	    perror (NULL);	else	    strcpy (result, str);    }    return result;}static void readPseudoTags (tagFile *const file, tagFileInfo *const info){    fpos_t startOfLine;    const size_t prefixLength = strlen (PseudoTagPrefix);    if (info != NULL)    {	info->file.format     = 1;	info->file.sort       = TAG_UNSORTED;	info->program.author  = NULL;	info->program.name    = NULL;	info->program.url     = NULL;	info->program.version = NULL;    }    while (1)    {	fgetpos (file->fp, &startOfLine);	if (! readTagLine (file))	    break;	if (strncmp (file->line.buffer, PseudoTagPrefix, prefixLength) != 0)	    break;	else	{	    tagEntry entry;	    const char *key, *value;	    parseTagLine (file, &entry);	    key = entry.name + prefixLength;	    value = entry.file;	    if (strcmp (key, "TAG_FILE_SORTED") == 0)		file->sortMethod = (sortType) atoi (value);	    else if (strcmp (key, "TAG_FILE_FORMAT") == 0)		file->format = atoi (value);	    else if (strcmp (key, "TAG_PROGRAM_AUTHOR") == 0)		file->program.author = duplicate (value);	    else if (strcmp (key, "TAG_PROGRAM_NAME") == 0)		file->program.name = duplicate (value);	    else if (strcmp (key, "TAG_PROGRAM_URL") == 0)		file->program.url = duplicate (value);	    else if (strcmp (key, "TAG_PROGRAM_VERSION") == 0)		file->program.version = duplicate (value);	    if (info != NULL)	    {		info->file.format     = file->format;		info->file.sort       = file->sortMethod;		info->program.author  = file->program.author;		info->program.name    = file->program.name;		info->program.url     = file->program.url;		info->program.version = file->program.version;	    }	}    }    fsetpos (file->fp, &startOfLine);}static void gotoFirstLogicalTag (tagFile *const file){    fpos_t startOfLine;    const size_t prefixLength = strlen (PseudoTagPrefix);    rewind (file->fp);    while (1)    {	fgetpos (file->fp, &startOfLine);	if (! readTagLine (file))	    break;	if (strncmp (file->line.buffer, PseudoTagPrefix, prefixLength) != 0)	    break;    }    fsetpos (file->fp, &startOfLine);}static tagFile *initialize (const char *const filePath, tagFileInfo *const info){    tagFile *result = (tagFile*) malloc (sizeof (tagFile));    if (result != NULL)    {	memset (result, 0, sizeof (tagFile));	growString (&result->line);	growString (&result->name);	result->fields.max = 20;	result->fields.list = (tagExtensionField*) malloc (	    result->fields.max * sizeof (tagExtensionField));	result->fp = fopen (filePath, "r");	if (result->fp == NULL)	{	    free (result);	    result = NULL;	    info->status.error_number = errno;	}	else	{	    fseek (result->fp, 0, SEEK_END);	    result->size = ftell (result->fp);	    rewind (result->fp);	    readPseudoTags (result, info);	    info->status.opened = 1;	    result->initialized = 1;	}    }    return result;}static void terminate (tagFile *const file){    fclose (file->fp);    free (file->line.buffer);    free (file->name.buffer);    free (file->fields.list);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -