示例#1
0
文件: options.c 项目: Feechka/UOBP
static int
ensureSetting (
  OptionProcessingInformation *info,
  const OptionEntry *option,
  const char *value
) {
  unsigned char *ensured = &info->ensuredSettings[option->letter];

  if (!*ensured) {
    *ensured = 1;

    if (option->argument) {
      if (option->setting.string) {
        if (option->flags & OPT_Extend) {
          if (!extendSetting(option->setting.string, value, 1)) return 0;
        } else {
          if (!(*option->setting.string = strdup(value))) {
            logMallocError();
            return 0;
          }
        }
      }
    } else {
      if (option->setting.flag) {
        if (wordMeansTrue(value)) {
          *option->setting.flag = 1;
        } else if (wordMeansFalse(value)) {
          *option->setting.flag = 0;
        } else if (!(option->flags & OPT_Extend)) {
          logMessage(LOG_ERR, "%s: %s", gettext("invalid flag setting"), value);
          info->warning = 1;
        } else {
          int count;
          if (isInteger(&count, value) && (count >= 0)) {
            *option->setting.flag = count;
          } else {
            logMessage(LOG_ERR, "%s: %s", gettext("invalid counter setting"), value);
            info->warning = 1;
          }
        }
      }
    }
  }

  return 1;
}
示例#2
0
文件: options.c 项目: junwuwei/brltty
static void
processCommandLine (
  OptionProcessingInformation *info,
  int *argumentCount,
  char ***argumentVector,
  const char *argumentsSummary
) {
  int lastOptInd = -1;

  const char resetPrefix = '+';
  const char *reset = NULL;
  int resetLetter;

#ifdef ALLOW_DOS_OPTION_SYNTAX
  const char dosPrefix = '/';
  int dosSyntax = 0;
#endif /* ALLOW_DOS_OPTION_SYNTAX */

  int optHelp = 0;
  int optHelpAll = 0;
  const OptionEntry *optionEntries[0X100];
  char shortOptions[1 + (info->optionCount * 2) + 1];

#ifdef HAVE_GETOPT_LONG
  struct option longOptions[(info->optionCount * 2) + 1];

  {
    struct option *opt = longOptions;

    for (unsigned int index=0; index<info->optionCount; ++index) {
      const OptionEntry *entry = &info->optionTable[index];

      if (entry->word) {
        opt->name = entry->word;
        opt->has_arg = entry->argument? required_argument: no_argument;
        opt->flag = NULL;
        opt->val = entry->letter;
        opt += 1;

        if (!entry->argument && entry->setting.flag) {
          static const char *const noPrefix = "no-";
          size_t noLength = strlen(noPrefix);
          char *name;

          if (strncasecmp(noPrefix, entry->word, noLength) == 0) {
            name = strdup(&entry->word[noLength]);
          } else {
            size_t size = noLength + strlen(entry->word) + 1;

            if ((name = malloc(size))) {
              snprintf(name, size, "%s%s", noPrefix, entry->word);
            }
          }

          if (name) {
            opt->name = name;
            opt->has_arg = no_argument;
            opt->flag = &resetLetter;
            opt->val = entry->letter;
            opt += 1;
          } else {
            logMallocError();
          }
        }
      }
    }

    memset(opt, 0, sizeof(*opt));
  }
#endif /* HAVE_GETOPT_LONG */

  for (unsigned int index=0; index<0X100; index+=1) {
    optionEntries[index] = NULL;
  }

  {
    char *opt = shortOptions;
    *opt++ = '+';

    for (unsigned int index=0; index<info->optionCount; ++index) {
      const OptionEntry *entry = &info->optionTable[index];
      optionEntries[entry->letter] = entry;

      *opt++ = entry->letter;
      if (entry->argument) *opt++ = ':';

      if (entry->argument) {
        if (entry->setting.string) *entry->setting.string = NULL;
      } else {
        if (entry->setting.flag) *entry->setting.flag = 0;
      }
    }

    *opt = 0;
  }

  if (*argumentCount > 1)
#ifdef ALLOW_DOS_OPTION_SYNTAX
    if (*(*argumentVector)[1] == dosPrefix) dosSyntax = 1;
#endif /* ALLOW_DOS_OPTION_SYNTAX */

  opterr = 0;
  optind = 1;

  while (1) {
    int option;
    char prefix = '-';

    if (optind == *argumentCount) {
      option = -1;
    } else {
      char *argument = (*argumentVector)[optind];

#ifdef ALLOW_DOS_OPTION_SYNTAX
      if (dosSyntax) {
        prefix = dosPrefix;
        optind++;

        if (*argument != dosPrefix) {
          option = -1;
        } else {
          char *name = argument + 1;
          size_t nameLength = strcspn(name, ":");
          char *value = (nameLength == strlen(name))? NULL: (name + nameLength + 1);
          const OptionEntry *entry;

          if (nameLength == 1) {
            entry = optionEntries[option = *name];
          } else {
            int count = info->optionCount;
            entry = info->optionTable;
            option = -1;

            while (count--) {
              if (entry->word) {
                size_t wordLength = strlen(entry->word);

                if ((wordLength == nameLength) &&
                    (strncasecmp(entry->word, name, wordLength) == 0)) {
                  option = entry->letter;
                  break;
                }
              }

              entry++;
            }

            if (option < 0) {
              option = 0;
              entry = NULL;
            }
          }

          optopt = option;
          optarg = NULL;

          if (!entry) {
            option = '?';
          } else if (entry->argument) {
            if (!(optarg = value)) option = ':';
          } else if (value) {
            if (!entry->setting.flag) goto dosBadFlagValue;

            if (!wordMeansTrue(value)) {
              if (wordMeansFalse(value)) {
                resetLetter = option;
                option = 0;
              } else {
              dosBadFlagValue:
                option = '?';
              }
            }
          }
        }
      } else
#endif /* ALLOW_DOS_OPTION_SYNTAX */

      if (reset) {
        prefix = resetPrefix;

        if (!(option = *reset++)) {
          reset = NULL;
          optind++;
          continue;
        }

        {
          const OptionEntry *entry = optionEntries[option];
          if (entry && !entry->argument && entry->setting.flag) {
            resetLetter = option;
            option = 0;
          } else {
            optopt = option;
            option = '?';
          }
        }
      } else {
        if (optind != lastOptInd) {
          lastOptInd = optind;
          if ((reset = (*argument == resetPrefix)? argument+1: NULL)) continue;
        }

#ifdef HAVE_GETOPT_LONG
        option = getopt_long(*argumentCount, *argumentVector, shortOptions, longOptions, NULL);
#else /* HAVE_GETOPT_LONG */
        option = getopt(*argumentCount, *argumentVector, shortOptions);
#endif /* HAVE_GETOPT_LONG */
      }
    }
    if (option == -1) break;

    /* continue on error as much as possible, as often we are typing blind
     * and won't even see the error message unless the display comes up.
     */
    switch (option) {
      default: {
        const OptionEntry *entry = optionEntries[option];

        if (entry->argument) {
          if (!*optarg) {
            info->ensuredSettings[option] = 0;
            break;
          }

          if (entry->setting.string) {
            if (entry->flags & OPT_Extend) {
              extendStringSetting(entry->setting.string, optarg, 0);
            } else {
              changeStringSetting(entry->setting.string, optarg);
            }
          }
        } else {
          if (entry->setting.flag) {
            if (entry->flags & OPT_Extend) {
              *entry->setting.flag += 1;
            } else {
              *entry->setting.flag = 1;
            }
          }
        }

        info->ensuredSettings[option] = 1;
        break;
      }

      case 0: {
        const OptionEntry *entry = optionEntries[resetLetter];
        *entry->setting.flag = 0;
        info->ensuredSettings[resetLetter] = 1;
        break;
      }

      case '?':
        logMessage(LOG_ERR, "%s: %c%c", gettext("unknown option"), prefix, optopt);
        info->syntaxError = 1;
        break;

      case ':': /* An invalid option has been specified. */
        logMessage(LOG_ERR, "%s: %c%c", gettext("missing operand"), prefix, optopt);
        info->syntaxError = 1;
        break;

      case 'H':                /* help */
        optHelpAll = 1;
      case 'h':                /* help */
        optHelp = 1;
        break;
    }
  }
  *argumentVector += optind, *argumentCount -= optind;

  if (optHelp) {
    printHelp(info, stdout, 79, argumentsSummary, optHelpAll);
    info->exitImmediately = 1;
  }

#ifdef HAVE_GETOPT_LONG
  {
    struct option *opt = longOptions;

    while (opt->name) {
      if (opt->flag) free((char *)opt->name);
      opt += 1;
    }
  }
#endif /* HAVE_GETOPT_LONG */
}