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

📄 options.c

📁 ultraEdit的Ctag标签工具的实现源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
    toLowerString (etags);
#endif
    if (strstr (execName, etags) != NULL)
    {
	verbose ("Running in etags mode\n");
	setEtagsMode ();
    }
}

/*
 *  Cooked argument parsing
 */

static void parseShortOption (cookedArgs *const args)
{
    args->simple [0] = *args->shortOptions++;
    args->simple [1] = '\0';
    args->item = args->simple;
    if (! isCompoundOption (*args->simple))
	args->parameter = "";
    else if (*args->shortOptions == '\0')
    {
	argForth (args->args);
	if (argOff (args->args))
	    args->parameter = NULL;
	else
	    args->parameter = argItem (args->args);
	args->shortOptions = NULL;
    }
    else
    {
	args->parameter = args->shortOptions;
	args->shortOptions = NULL;
    }
}

static void parseLongOption (cookedArgs *const args, const char *item)
{
    const char* const equal = strchr (item, '=');
    if (equal == NULL)
    {
	args->item = eStrdup (item);
	args->parameter = "";
    }
    else
    {
	const size_t length = equal - item;
	args->item = xMalloc (length + 1, char);
	strncpy (args->item, item, length);
	args->item [length] = '\0';
	args->parameter = equal + 1;
    }
    Assert (args->item != NULL);
    Assert (args->parameter != NULL);
}

static void cArgRead (cookedArgs *const current)
{
    char* item;

    Assert (current != NULL);
    if (! argOff (current->args))
    {
	item = argItem (current->args);
	current->shortOptions = NULL;
	Assert (item != NULL);
	if (strncmp (item, "--", (size_t) 2) == 0)
	{
	    current->isOption = TRUE;
	    current->longOption = TRUE;
	    parseLongOption (current, item + 2);
	    Assert (current->item != NULL);
	    Assert (current->parameter != NULL);
	}
	else if (*item == '-')
	{
	    current->isOption = TRUE;
	    current->longOption = FALSE;
	    current->shortOptions = item + 1;
	    parseShortOption (current);
	}
	else
	{
	    current->isOption = FALSE;
	    current->longOption = FALSE;
	    current->item = item;
	    current->parameter = NULL;
	}
    }
}

extern cookedArgs* cArgNewFromString (const char* string)
{
    cookedArgs* const result = xMalloc (1, cookedArgs);
    memset (result, 0, sizeof (cookedArgs));
    result->args = argNewFromString (string);
    cArgRead (result);
    return result;
}

extern cookedArgs* cArgNewFromArgv (char* const* const argv)
{
    cookedArgs* const result = xMalloc (1, cookedArgs);
    memset (result, 0, sizeof (cookedArgs));
    result->args = argNewFromArgv (argv);
    cArgRead (result);
    return result;
}

extern cookedArgs* cArgNewFromFile (FILE* const fp)
{
    cookedArgs* const result = xMalloc (1, cookedArgs);
    memset (result, 0, sizeof (cookedArgs));
    result->args = argNewFromFile (fp);
    cArgRead (result);
    return result;
}

extern cookedArgs* cArgNewFromLineFile (FILE* const fp)
{
    cookedArgs* const result = xMalloc (1, cookedArgs);
    memset (result, 0, sizeof (cookedArgs));
    result->args = argNewFromLineFile (fp);
    cArgRead (result);
    return result;
}

extern void cArgDelete (cookedArgs* const current)
{
    Assert (current != NULL);
    argDelete (current->args);
    memset (current, 0, sizeof (cookedArgs));
    eFree (current);
}

static boolean cArgOptionPending (cookedArgs* const current)
{
    boolean result = FALSE;
    if (current->shortOptions != NULL)
	if (*current->shortOptions != '\0')
	    result = TRUE;
    return result;
}

extern boolean cArgOff (cookedArgs* const current)
{
    Assert (current != NULL);
    return (boolean) (argOff (current->args) && ! cArgOptionPending (current));
}

extern boolean cArgIsOption (cookedArgs* const current)
{
    Assert (current != NULL);
    return current->isOption;
}

extern const char* cArgItem (cookedArgs* const current)
{
    Assert (current != NULL);
    return current->item;
}

extern void cArgForth (cookedArgs* const current)
{
    Assert (current != NULL);
    Assert (! cArgOff (current));
    if (cArgOptionPending (current))
	parseShortOption (current);
    else
    {
	Assert (! argOff (current->args));
	argForth (current->args);
	if (! argOff (current->args))
	    cArgRead (current);
	else
	{
	    current->isOption = FALSE;
	    current->longOption = FALSE;
	    current->shortOptions = NULL;
	    current->item = NULL;
	    current->parameter = NULL;
	}
    }
}

/*
 *  File extension and language mapping
 */

static void addExtensionList (stringList *const slist,
			      const char *const elist, const boolean clear)
{
    char *const extensionList = eStrdup (elist);
    const char *extension = NULL;
    boolean first = TRUE;

    if (clear)
    {
	verbose ("      clearing\n");
	stringListClear (slist);
    }
    verbose ("      adding: ");
    if (elist != NULL  &&  *elist != '\0')
    {
	extension = extensionList;
	if (elist [0] == EXTENSION_SEPARATOR)
	    ++extension;
    }
    while (extension != NULL)
    {
	char *separator = strchr (extension, EXTENSION_SEPARATOR);
	if (separator != NULL)
	    *separator = '\0';
	verbose ("%s%s", first ? "" : ", ",
		*extension == '\0' ? "(NONE)" : extension);
	stringListAdd (slist, vStringNewInit (extension));
	first = FALSE;
	if (separator == NULL)
	    extension = NULL;
	else
	    extension = separator + 1;
    }
    if (Option.verbose)
    {
	printf ("\n      now: ");
	stringListPrint (slist);
	putchar ('\n');
    }
    eFree (extensionList);
}

static boolean isFalse (const char *parameter)
{
    return (boolean) (
	strcasecmp (parameter, "0"  ) == 0  ||
	strcasecmp (parameter, "n"  ) == 0  ||
	strcasecmp (parameter, "no" ) == 0  ||
	strcasecmp (parameter, "off") == 0);
}

static boolean isTrue (const char *parameter)
{
    return (boolean) (
	strcasecmp (parameter, "1"  ) == 0  ||
	strcasecmp (parameter, "y"  ) == 0  ||
	strcasecmp (parameter, "yes") == 0  ||
	strcasecmp (parameter, "on" ) == 0);
}

/*  Determines whether the specified file name is considered to be a header
 *  file for the purposes of determining whether enclosed tags are global or
 *  static.
 */
extern boolean isIncludeFile (const char *const fileName)
{
    boolean result = FALSE;
    const char *const extension = fileExtension (fileName);
    if (Option.headerExt != NULL)
	result = stringListExtensionMatched (Option.headerExt, extension);
    return result;
}

/*
 *  Specific option processing
 */

static void processEtagsInclude (
	const char *const option, const char *const parameter)
{
    if (! Option.etags)
	error (FATAL, "Etags must be enabled to use \"%s\" option", option);
    else
    {
	vString *const file = vStringNewInit (parameter);
	if (Option.etagsInclude == NULL)
	    Option.etagsInclude = stringListNew ();
	stringListAdd (Option.etagsInclude, file);
	FilesRequired = FALSE;
    }
}

static void processExcludeOption (
	const char *const option __unused__, const char *const parameter)
{
    const char *const fileName = parameter + 1;
    if (parameter [0] == '\0')
	freeList (&Excluded);
    else if (parameter [0] == '@')
    {
	stringList* const sl = stringListNewFromFile (fileName);
	if (sl == NULL)
	    error (FATAL | PERROR, "cannot open \"%s\"", fileName);
	if (Excluded == NULL)
	    Excluded = sl;
	else
	    stringListCombine (Excluded, sl);
	verbose ("    adding exclude patterns from %s\n", fileName);
    }
    else
    {
	vString *const item = vStringNewInit (parameter);
	if (Excluded == NULL)
	    Excluded = stringListNew ();
	stringListAdd (Excluded, item);
	verbose ("    adding exclude pattern: %s\n", parameter);
    }
}

extern boolean isExcludedFile (const char* const name)
{
    const char* base = baseFilename (name);
    boolean result = FALSE;
    if (Excluded != NULL)
    {
	result = stringListFileMatched (Excluded, base);
	if (! result  &&  name != base)
	    result = stringListFileMatched (Excluded, name);
    }
#ifdef AMIGA
    /* not a good solution, but the only one which works often */
    if (! result)
	result = (boolean) (strcmp (name, TagFile.name) == 0);
#endif
    return result;
}

static void processExcmdOption (
	const char *const option, const char *const parameter)
{
    switch (*parameter)
    {
	case 'm': Option.locate = EX_MIX;	break;
	case 'n': Option.locate = EX_LINENUM;	break;
	case 'p': Option.locate = EX_PATTERN;	break;
	default:
	    error (FATAL, "Invalid value for \"%s\" option", option);
	    break;
    }
}

static void processExtraTagsOption (
	const char *const option, const char *const parameter)
{
    struct sInclude *const inc = &Option.include;
    const char *p = parameter;
    boolean mode = TRUE;
    int c;

    if (*p != '+'  &&  *p != '-')
    {
	inc->fileNames		= FALSE;
	inc->qualifiedTags	= FALSE;
#if 0
	inc->fileScope		= FALSE;
#endif
    }
    while ((c = *p++) != '\0') switch (c)
    {
	case '+': mode = TRUE;			break;
	case '-': mode = FALSE;			break;

	case 'f': inc->fileNames	= mode;	break;
	case 'q': inc->qualifiedTags	= mode;	break;
#if 0
	case 'F': inc->fileScope	= mode;	break;
#endif

	default: error(WARNING, "Unsupported parameter '%c' for \"%s\" option",
		       c, option);
	    break;
    }
}

static void processFieldsOption (
	const char *const option, const char *const parameter)
{
    struct sExtFields *field = &Option.extensionFields;
    const char *p = parameter;
    boolean mode = TRUE;
    int c;

    if (*p != '+'  &&  *p != '-')
    {
	field->access		= FALSE;
	field->fileScope	= FALSE;
	field->implementation	= FALSE;
	field->inheritance	= FALSE;
	field->kind		= FALSE;
	field->kindKey		= FALSE;
	field->kindLong		= FALSE;
	field->language		= FALSE;
	field->scope		= FALSE;
    }
    while ((c = *p++) != '\0') switch (c)
    {
	case '+': mode = TRUE;			break;
	case '-': mode = FALSE;			break;

	case 'a': field->access		= mode;	break;
	case 'f': field->fileScope	= mode;	break;
	case 'm': field->implementation	= mode;	break;
	case 'i': field->inheritance	= mode;	break;
	case 'k': field->kind		= mode;	break;
	case 'K': field->kindLong	= mode;	break;
	case 'l': field->language	= mode;	break;
	case 'n': field->lineNumber	= mode;	break;
	case 's': field->scope		= mode;	break;
	case 'S': field->signature	= mode;	break;
	case 'z': field->kindKey	= mode;	break;

	default: error(WARNING, "Unsupported parameter '%c' for \"%s\" option",
		       c, option);
	    break;
    }
}

static void processFilterTerminatorOption (
	const char *const option __unused__, const char *const parameter)
{
    freeString (&Option.filterTerminator);
    Option.filterTerminator = stringCopy (parameter);
}

static void processFormatOption (
	const char *const option, const char *const parameter)
{
    unsigned int format;

    if (sscanf (parameter, "%u", &format) < 1)
	error (FATAL, "Invalid value for \"%s\" option",option);
    else if (format <= (unsigned int) MaxSupportedTagFormat)
	Option.tagFileFormat = format;
    else
	error (FATAL, "Unsupported value for \"%s\" option", option);
}

static void printInvocationDescription (void)
{
    printf (INVOCATION, getExecutableName ());
}

static void printOptionDescriptions (const optionDescription *const optDesc)
{
    int i;
    for (i = 0 ; optDesc [i].description != NULL ; ++i)

⌨️ 快捷键说明

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