windows-nt/Source/XPSP1/NT/sdktools/rcdll/getflags.c
2020-09-26 16:20:57 +08:00

282 lines
9.7 KiB
C

/************************************************************************/
/* */
/* RCPP - Resource Compiler Pre-Processor for NT system */
/* */
/* GETFLAGS.C - Parse Command Line Flags */
/* */
/* 27-Nov-90 w-BrianM Update for NT from PM SDK RCPP */
/* */
/************************************************************************/
#include "rc.h"
/************************************************************************/
/* Define function specific macros and global vars */
/************************************************************************/
static WCHAR *ErrString; /* Store string pointer in case of error */
/************************************************************************/
/* Local Function Prototypes */
/************************************************************************/
int getnumber (WCHAR *);
int isita (WCHAR *, WCHAR);
void substr (struct cmdtab *, WCHAR *, int);
int tailmatch (WCHAR *, WCHAR *);
/************************************************************************
* crack_cmd(table, string, func, dup)
* set flags determined by the string based on table.
* func will get the next word.
* if dup is set, any strings stored away will get pstrduped
* see getflags.h for specific matching and setting operators
*
* for flags which take parameters, a 'char' following the flag where 'char' is
* '#' : says the parameter string may be separated from the option.
* ie, "-M#" accepts "-Mabc" and "-M abc"
* '*' : says the parameter must be concatenated with the flag
* ie, "-A*" accepts only "-Axyz" not "-A xyz"
* if neither is specified a space is required between parameter and flag
* ie, "-o" accepts only "-o file" and not "-ofile"
*
* Modified by: Dave Weil D001
* recognize '-' and '/' as equivalent on MSDOS
*
************************************************************************/
int
crack_cmd(
struct cmdtab *tab,
WCHAR *string,
WCHAR *(*next)(void),
int _dup
)
{
register WCHAR *format, *str;
if (!string) {
return(0);
}
ErrString = string;
for (; tab->type; tab++) /* for each format */ {
format = tab->format;
str = string;
for (; ; ) /* scan the string */
switch (*format) {
/* optional space between flag and parameter */
case L'#':
if ( !*str ) {
substr(tab, (*next)(), _dup);
} else {
substr(tab, str, _dup);
}
return(tab->retval);
break;
/* no space allowed between flag and parameter */
case L'*':
if (*str && tailmatch(format, str))
substr(tab, str, _dup);
else
goto notmatch;
return(tab->retval);
break;
/* space required between flag and parameter */
case 0:
if (*str) { /* str left, no good */
goto notmatch;
} else if (tab->type & TAKESARG) { /* if it takes an arg */
substr(tab, (*next)(), _dup);
} else { /* doesn't want an arg */
substr(tab, (WCHAR *)0, _dup);
}
return(tab->retval);
break;
case L'-':
if (L'-' == *str) {
str++;
format++;
continue;
} else {
goto notmatch;
}
default:
if (*format++ == *str++)
continue;
goto notmatch;
}
notmatch:
;
}
return(0);
}
/************************************************************************/
/* set the appropriate flag(s). called only when we know we have a match */
/************************************************************************/
void
substr(
struct cmdtab *tab,
register WCHAR *str,
int _dup
)
{
register struct subtab *q;
LIST * list;
WCHAR *string = str;
switch (tab->type) {
case FLAG:
*(int *)(tab->flag) = 1;
return;
case UNFLAG:
*(int *)(tab->flag) = 0;
return;
case NOVSTR:
if (*(WCHAR **)(tab->flag)) {
/* before we print it out in the error message get rid of the
* arg specifier (e.g. #) at the end of the format.
*/
// string = _wcsdup(tab->format);
// string[wcslen(string)-1] = L'\0';
//
// message 1046 doesn't exist and don't know what it should be
// Msg_Temp = GET_MSG(1046);
// SET_MSG (Msg_Text, sizeof(Msg_Text), Msg_Temp, string, *(WCHAR **)(tab->flag), str);
Msg_Temp = GET_MSG(1000);
fatal(1000);
return;
}
/* fall through */
case STRING:
*(WCHAR **)(tab->flag) = (_dup ? _wcsdup(str) : str);
return;
case NUMBER:
*(int *)(tab->flag) = getnumber (str);
return;
case PSHSTR:
list = (LIST * )(tab->flag);
if (list->li_top > 0)
list->li_defns[--list->li_top] = (_dup ? _wcsdup(str) : str);
else {
Msg_Temp = GET_MSG(1047);
SET_MSG (Msg_Text, sizeof(Msg_Text), Msg_Temp, tab->format, str);
fatal(1047);
}
return;
case SUBSTR:
for ( ; *str; ++str) { /* walk the substring */
for (q = (struct subtab *)tab->flag; q->letter; q++) {
/*
** for every member in the table
*/
if (*str == (WCHAR)q->letter)
switch (q->type) {
case FLAG:
*(q->flag) = 1;
goto got_letter;
case UNFLAG:
*(q->flag) = 0;
goto got_letter;
default:
goto got_letter;
}
}
got_letter:
if (!q->letter) {
Msg_Temp = GET_MSG(1048);
SET_MSG (Msg_Text, sizeof(Msg_Text), Msg_Temp, *str, ErrString);
fatal(1048);
}
}
return;
default:
return;
}
}
/************************************************************************/
/* Parse the string and return a number 0 <= x < 0xffff (64K) */
/************************************************************************/
int
getnumber (
WCHAR *str
)
{
long i = 0;
WCHAR *ptr = str;
for (; iswspace(*ptr); ptr++)
;
if (!iswdigit(*ptr) || (((i = wcstol(ptr, NULL, 10)) >= 65535) || i < 0)) {
Msg_Temp = GET_MSG(1049);
SET_MSG (Msg_Text, sizeof(Msg_Text), Msg_Temp, str);
fatal(1049); /* invalid numerical argument, 'str' */
}
return ((int) i);
}
/************************************************************************/
/* is the letter in the string? */
/************************************************************************/
int
isita (
register WCHAR *str,
register WCHAR let
)
{
if (str)
while (*str)
if (*str++ == let)
return(1);
return(0);
}
/************************************************************************/
/* compare a tail format (as in *.c) with a string. if there is no */
/* tail, anything matches. (null strings are detected elsewhere) */
/* the current implementation only allows one wild card */
/************************************************************************/
int
tailmatch (
WCHAR *format,
WCHAR *str
)
{
register WCHAR *f = format;
register WCHAR *s = str;
if (f[1] == 0) /* wild card is the last thing in the format, it matches */
return(1);
while (f[1]) /* find char in front of null in format */
f++;
while (s[1]) /* find char in front of null in string to check */
s++;
while (*s == *f) { /* check chars walking towards front */
s--;
f--;
}
/*
** if we're back at the beginning of the format
** and
** the string is either at the beginning or somewhere inside
** then we have a match.
**
** ex format == "*.c", str == "file.c"
** at this point *f = '*' and *s == 'e', since we've kicked out of the above
** loop. since f==format and s>=str this is a match.
** but if format == "*.c" and str == "file.asm" then
** *f == 'c' and *s = 'm', f != format and no match.
*/
return((f == format) && (s >= str));
}