diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..874c63c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.o + diff --git a/Parameter.c b/Parameter.c new file mode 100644 index 0000000..6566f12 --- /dev/null +++ b/Parameter.c @@ -0,0 +1,1148 @@ +#include "mwcc_decomp.h" + +#define OPTION_ASSERT(cond) do { if (!(cond)) { printf("%s:%u: failed assertion\n", __FILE__, __LINE__); abort(); } } while(0) + +char curparam[4096]; +char *descparam = &curparam[0]; +char *helpparam = &curparam[1024]; +char *defaultparam = &curparam[2048]; + +#define copy_8(dst, src) \ +do { \ +((unsigned char *) (dst))[0] = ((unsigned char *) (src))[0]; \ +} while (0) + +#define copy_16(dst, src) \ +do { \ +((unsigned char *) (dst))[0] = ((unsigned char *) (src))[0]; \ +((unsigned char *) (dst))[1] = ((unsigned char *) (src))[1]; \ +} while (0) + +#define copy_32(dst, src) \ +do { \ +((unsigned char *) (dst))[0] = ((unsigned char *) (src))[0]; \ +((unsigned char *) (dst))[1] = ((unsigned char *) (src))[1]; \ +((unsigned char *) (dst))[2] = ((unsigned char *) (src))[2]; \ +((unsigned char *) (dst))[3] = ((unsigned char *) (src))[3]; \ +} while (0) + +#define inline_write_32(dst, val) do { \ +union {unsigned char bytes[4]; unsigned long lg;} _val, _arg; \ +copy_32(_arg.bytes, val); \ +_val.lg = _arg.lg; \ +copy_32(dst, _val.bytes); \ +} while (0) + +#define inline_write_16(dst, val) do { \ +union {unsigned char bytes[2]; unsigned short sh;} _val, _arg; \ +copy_16(_arg.bytes, val); \ +_val.sh = _arg.sh; \ +copy_16(dst, _val.bytes); \ +} while (0) + +#define inline_write_8(ptr, val) copy_8(ptr, val) + +#define inline_andor_32(dst, and, or) do { \ +union {unsigned char bytes[4]; unsigned long lg;} _val, _arg, _arg2; \ +copy_32(_val.bytes, dst); \ +copy_32(_arg.bytes, and); \ +copy_32(_arg2.bytes, or); \ +_val.lg = (_val.lg & ~_arg.lg) | _arg2.lg; \ +copy_32(dst, _val.bytes); \ +} while(0) + +#define inline_andor_16(dst, and, or) do { \ +union {unsigned char bytes[2]; unsigned short sh;} _val, _arg, _arg2; \ +copy_16(_val.bytes, dst); \ +copy_16(_arg.bytes, and); \ +copy_16(_arg2.bytes, or); \ +_val.sh = (_val.sh & ~_arg.sh) | _arg2.sh; \ +copy_16(dst, _val.bytes); \ +} while(0) + +#define inline_andor_8(dst, and, or) do { \ +((unsigned char *) (dst))[0] = (((unsigned char *) (dst))[0] & ~((unsigned char *) (and))[0]) | ((unsigned char *) (or))[0]; \ +} while(0) + +#define inline_xor_32(dst, arg) do { \ +union {unsigned char bytes[4]; unsigned long lg;} _val, _arg; \ +copy_32(_val.bytes, dst); \ +copy_32(_arg.bytes, arg); \ +_val.lg = _val.lg ^ _arg.lg; \ +copy_32(dst, _val.bytes); \ +} while(0) + +#define inline_xor_16(dst, arg) do { \ +union {unsigned char bytes[2]; unsigned short sh;} _val, _arg; \ +copy_16(_val.bytes, dst); \ +copy_16(_arg.bytes, arg); \ +_val.sh = _val.sh ^ _arg.sh; \ +copy_16(dst, _val.bytes); \ +} while(0) + +#define inline_xor_8(dst, arg) do { \ +((unsigned char *) (dst))[0] = (((unsigned char *) (dst))[0] ^ ((unsigned char *) (arg))[0]); \ +} while(0) + +// forward declaration +static int Param_GetArgument(PARAM_T *param, const char **cparam, int exec); +static int Param_Parse(PARAM_T *param, const char *cparam, int flags); + +static int Param_None(PARAM_T *p, const char *pstr, int flags) { + return 1; +} + +static void DescHelpParam_None(PARAM_T *p, const char **desc, const char **help, const char **defaul) { + *desc = 0; + *help = 0; + *defaul = 0; +} + +static int CompareParam_None(PARAM_T *p) { + return 0; +} + +static void DescHelpParam_Number(NUM_T *p, const char **desc, const char **help, const char **defaul) { + unsigned long value; + unsigned char value8; + unsigned short value16; + + value = 0; + *desc = 0; + if (p->myname) + *desc = p->myname; + + if (p->size == 1) { + if (!*desc) + *desc = "byte"; + if (p->num) copy_8(&value8, p->num); + value = value8; + } else if (p->size == 2) { + if (!*desc) + *desc = "short"; + if (p->num) copy_16(&value16, p->num); + value = value16; + } else if (p->size == 4) { + if (!*desc) + *desc = "long"; + if (p->num) copy_32(&value, p->num); + } + + if (p->size == 4) { + if (p->lo != p->hi) + sprintf(helpparam, "range 0x%x - 0x%x", p->lo, p->hi); + *help = helpparam; + if (value <= 0x10000) + sprintf(defaultparam, "%u", value); + else + sprintf(defaultparam, "0x%x", value); + *defaul = defaultparam; + } else { + if (p->lo != p->hi) + sprintf(helpparam, "range %u - %u", p->lo, p->hi); + *help = helpparam; + sprintf(defaultparam, "%u", value); + *defaul = defaultparam; + } + + if (!p->num) + *defaul = 0; + if (p->lo == p->hi) + *help = 0; +} + +static int CompareParam_Number(NUM_T *p) { + return 0; +} + +static int Param_Number(NUM_T *p, const char *pstr, int flags) { + unsigned long val; + unsigned long lo; + unsigned long hi; + const char *opstr; + + val = 0; + opstr = pstr; + if (!pstr[0]) { + Param_Error(5, "", pstr); + return 0; + } + + if (((*pstr == '0') && my_tolower(pstr[1]) == 'x') || (*pstr == '$')) { + // 218 + if (pstr[0] == '$') + pstr += 1; + else + pstr += 2; + + while (*pstr) { + if (!my_isxdigit(*pstr)) { + Param_Error(5, "hexadecimal ", opstr); + return 0; + } + + if (val > 0xFFFFFFF) { + Param_Error(4, opstr); + return 0; + } + + val = (val << 4) | (my_isdigit(*pstr) ? (*pstr - '0') : (my_tolower(*pstr) - 'a' + 10)); + ++pstr; + } + } else if (pstr[0] == '0') { + pstr += 1; + + while (*pstr) { + if (*pstr < '0' || *pstr >= '8') { + Param_Error(5, "octal ", opstr); + return 0; + } + + if (val > 0x1FFFFFFF) { + Param_Error(4, opstr); + return 0; + } + + val = (val << 3) | (*pstr - '0'); + ++pstr; + } + } else { + while (*pstr) { + if (!my_isdigit(*pstr)) { + Param_Error(5, "decimal ", opstr); + return 0; + } + + if (val > 0x19999999) { + Param_Error(4, opstr); + return 0; + } + + val = (val * 10) + (*pstr - '0'); + ++pstr; + } + } + + if (p->lo == p->hi) { + if (p->size == 1) { + lo = 0; + hi = 0xFF; + } else if (p->size == 2) { + lo = 0; + hi = 0xFFFF; + } else { + lo = 0; + hi = 0xFFFFFFFF; + } + } else { + lo = p->lo; + hi = p->hi; + } + + if (!p->fit && (val < lo || val > hi)) { + Param_Error(6, val, lo, hi); + return 0; + } + + if (val < lo) { + Param_Warning(7, val, lo, hi, lo); + val = lo; + } else if (val > hi) { + Param_Warning(7, val, lo, hi, hi); + val = hi; + } + + if (p->size == 1) { + unsigned char val8 = val; + inline_write_8(p->num, &val8); + } + + if (p->size == 2) { + unsigned short val16 = val; + inline_write_16(p->num, &val16); + } else if (p->size == 4) { + unsigned long val32 = val; + inline_write_32(p->num, &val32); + } + + return 1; +} + +static void DescHelpParam_FTypeCreator(FTYPE_T *p, const char **desc, const char **help, const char **defaul) { + if (p->myname) + *desc = p->myname; + else if (p->iscreator) + *desc = "creator"; + else + *desc = "type"; + + if (!p->fc) { + *defaul = 0; + } else { + unsigned long tmp; + unsigned char *ptr; + + ptr = (unsigned char *) defaultparam; + tmp = *p->fc; + ptr[0] = '\''; + ptr[1] = tmp & 0xFF; + ptr[2] = (tmp >> 8) & 0xFF; + ptr[3] = (tmp >> 16) & 0xFF; + ptr[4] = (tmp >> 24) & 0xFF; + ptr[5] = '\''; + ptr[6] = 0; + *defaul = defaultparam; + } +} + +static int CompareParam_FTypeCreator(FTYPE_T *p) { + return 0; +} + +static int Param_FTypeCreator(FTYPE_T *p, const char *pstr, int flags) { + char x[4] = " "; + int cnt; + const char *opstr; + + cnt = 0; + opstr = pstr; + while (*pstr && cnt < 4) { + x[cnt++] = *(pstr++); + } + + if (*pstr) { + Param_Error(8, opstr); + return 0; + } + + inline_write_32(p->fc, &x); + return 1; +} + +static void DescHelpParam_String(STRING_T *p, const char **desc, const char **help, const char **defaul) { + if (p->myname) + *desc = p->myname; + else + *desc = "string"; + + if (!p->str) { + *help = 0; + *defaul = 0; + } else { + sprintf(helpparam, "maximum length %d chars", p->maxlen - 1); + *help = helpparam; + + if (*p->str) { + sprintf(defaultparam, "'%s'", p->str); + *defaul = defaultparam; + } else { + *defaul = "none"; + } + } +} + +static int CompareParam_String(STRING_T *p) { + return 0; +} + +static int Param_String(STRING_T *p, const char *pstr, int flags) { + int len; + + len = strlen(pstr); + strncpy(p->str, pstr, p->maxlen - 1); + if (p->pstring) + c2pstr(p->str); + + if (len > p->maxlen) { + Param_Error(9, pstr, pstr + len - 5, p->maxlen - 1); + return 0; + } + + return 1; +} + +static void DescHelpParam_ID_or_SYM(STRING_T *p, const char **desc, const char **help, const char **defaul) { + if (p->myname) + *desc = p->myname; + else if (p->which == PARAMWHICH_Id) + *desc = "identifier"; + else + *desc = "symbol"; + + if (!p->str) { + *help = *defaul = 0; + } else { + sprintf(helpparam, "maximum length %d chars", p->maxlen - 1); + *help = helpparam; + + if (*p->str) { + sprintf(defaultparam, "'%s'", p->str); + *defaul = defaultparam; + } else { + *defaul = "none"; + } + } +} + +static int CompareParam_ID_or_SYM(STRING_T *p) { + return 0; +} + +static int Param_ID_or_SYM(STRING_T *p, const char *pstr, int flags) { + const char *ptr; + const char *x; + + if (Param_String(p, pstr, flags)) { + if (p->which == PARAMWHICH_Id) { + x = "$_"; + } else if (p->which == PARAMWHICH_Sym) { + x = "_.$@?#"; + } + + for (ptr = pstr; *ptr; ++ptr) { + if (ptr == pstr && my_isdigit(*ptr)) + Param_Warning(10, pstr); + + if (!my_isalnum(*ptr) && !strchr(x, *ptr)) + Param_Warning(11, pstr, *ptr); + } + + return 1; + } else { + return 0; + } +} + +static void DescHelpParam_OnOff(ONOFF_T *p, const char **desc, const char **help, const char **defaul) { + unsigned char def; + + if (p->myname) + *desc = p->myname; + else + *desc = "on|off"; + + *help = 0; + if (!p->var) { + *defaul = 0; + } else { + if (p->var) + *((unsigned char *) &def) = *((unsigned char *) p->var); + if (def) + *defaul = "on"; + else + *defaul = "off"; + } +} + +static int CompareParam_OnOff(ONOFF_T *p) { + return 0; +} + +static int Param_OnOff(ONOFF_T *p, const char *pstr, int flags) { + Boolean mytrue = (flags & PARAMPARSEFLAGS_8) == 0; + + if (!ustrcmp(pstr, "on")) { + *(p->var) = mytrue; + } else if (!ustrcmp(pstr, "off")) { + *(p->var) = mytrue == 0; + } else { + Param_Error(12, pstr); + return 0; + } + + return 1; +} + +static void DescHelpParam_OffOn(ONOFF_T *p, const char **desc, const char **help, const char **defaul) { + unsigned char def; + + if (p->myname) + *desc = p->myname; + else + *desc = "off|on"; + + *help = 0; + if (!p->var) { + *defaul = 0; + } else { + if (p->var) + *((unsigned char *) &def) = *((unsigned char *) p->var); + if (!def) + *defaul = "on"; + else + *defaul = "off"; + } +} + +static int CompareParam_OffOn(OFFON_T *p) { + return 0; +} + +static int Param_OffOn(OFFON_T *p, const char *pstr, int flags) { + Boolean mytrue = (flags & PARAMPARSEFLAGS_8) == 0; + + if (!ustrcmp(pstr, "off")) { + *(p->var) = mytrue; + } else if (!ustrcmp(pstr, "on")) { + *(p->var) = mytrue == 0; + } else { + Param_Error(12, pstr); + return 0; + } + + return 1; +} + +static void DescHelpParam_FilePath(FILEPATH_T *p, const char **desc, const char **help, const char **defaul) { + if (p->myname) + *desc = p->myname; + else + *desc = "filepath"; + + *help = 0; + *defaul = p->defaultstr; +} + +static int CompareParam_FilePath(FILEPATH_T *p) { + return 0; +} + +static int Param_FilePath(FILEPATH_T *p, const char *pstr, int flags) { + int err; + OSSpec spec; + char canon[256]; + int clen; + + if (!pstr[0]) { + ((unsigned char *) p->filename)[0] = 0; + return 1; + } + + err = OS_MakeFileSpec(pstr, &spec); + if (err) { + Param_Error(18, pstr, OS_GetErrText(err)); + return 0; + } + + OS_SpecToString(&spec, canon, sizeof(canon)); + if (p->fflags & 1) { + c2pstrcpy(p->filename, canon); + } else { + clen = strlen(canon); + if (clen > p->maxlen) { + Param_Error(13, canon + clen - 32, canon); + return 0; + } + strcpy(p->filename, canon); + } + + return 1; +} + +static void DescHelpParam_Mask(MASK_T *p, const char **desc, const char **help, const char **defaul) { + *help = 0; + *desc = 0; + *defaul = 0; +} + +static int CompareParam_Mask(MASK_T *p) { + if (p->size == 1) { + unsigned char or8 = p->ormask, and8 = p->andmask, val8; + if (p->num) copy_8(&val8, p->num); + return ((val8 & ~and8) | or8) == val8; + } else if (p->size == 2) { + unsigned short or16 = p->ormask, and16 = p->andmask, val16; + if (p->num) copy_16(&val16, p->num); + return ((val16 & ~and16) | or16) == val16; + } else { + unsigned long or32 = p->ormask, and32 = p->andmask, val32; + if (p->num) copy_32(&val32, p->num); + return ((val32 & ~and32) | or32) == val32; + } +} + +static int Param_Mask(MASK_T *p, const char *pstr, int flags) { + if (p->size == 1) { + unsigned char or8 = p->ormask, and8 = p->andmask, tmp8; + if (flags & PARAMPARSEFLAGS_8) { + tmp8 = and8; + and8 = and8 | or8; + or8 = tmp8; + } + inline_andor_8(p->num, &and8, &or8); + } else if (p->size == 2) { + unsigned short or16 = p->ormask, and16 = p->andmask, tmp16; + if (flags & PARAMPARSEFLAGS_8) { + tmp16 = and16; + and16 = and16 | or16; + or16 = tmp16; + } + inline_andor_16(p->num, &and16, &or16); + } else { + unsigned long or32 = p->ormask, and32 = p->andmask, tmp32; + if (flags & PARAMPARSEFLAGS_8) { + tmp32 = and32; + and32 = and32 | or32; + or32 = tmp32; + } + inline_andor_32(p->num, &and32, &or32); + } + return 1; +} + +static void DescHelpParam_Toggle(TOGGLE_T *p, const char **desc, const char **help, const char **defaul) { + *help = 0; + *desc = 0; + *defaul = 0; +} + +static int CompareParam_Toggle(TOGGLE_T *p) { + if (p->size == 1) { + unsigned char mask8, val8; + mask8 = (unsigned char) p->mask; + if (p->num) copy_8(&val8, p->num); + return (val8 ^ mask8) == val8; + } else if (p->size == 2) { + unsigned short mask16, val16; + mask16 = (unsigned short) p->mask; + if (p->num) copy_16(&val16, p->num); + return (val16 ^ mask16) == val16; + } else { + unsigned long mask32, val32; + mask32 = p->mask; + if (p->num) copy_16(&val32, p->num); // BUG ALERT + return (val32 ^ mask32) == val32; + } +} + +static int Param_Toggle(TOGGLE_T *p, const char *pstr, int flags) { + if (p->size == 1) { + unsigned char val8; + val8 = (unsigned char) p->mask; + inline_xor_8(p->num, &val8); + } else if (p->size == 2) { + unsigned short val16; + val16 = (unsigned short) p->mask; + inline_xor_16(p->num, &val16); + } else { + inline_xor_32(p->num, &p->mask); + } + return 1; +} + +static void DescHelpParam_Set(SET_T *p, const char **desc, const char **help, const char **defaul) { + *help = 0; + *desc = 0; + *defaul = 0; +} + +static int CompareParam_Set(SET_T *p) { + if (p->size == 1) { + unsigned char set8, val8; + set8 = (unsigned char) p->value; + if (p->num) copy_8(&val8, p->num); + return set8 == val8; + } else if (p->size == 2) { + unsigned short set16, val16; + set16 = (unsigned short) p->value; + if (p->num) copy_16(&val16, p->num); + return set16 == val16; + } else { + unsigned long set32, val32; + set32 = p->value; + if (p->num) copy_32(&val32, p->num); + return set32 == val32; + } +} + +static int Param_Set(SET_T *p, const char *pstr, int flags) { + if (p->size == 1) { + unsigned char val8; + val8 = (unsigned char) p->value; + if ((flags & PARAMPARSEFLAGS_8) && val8 <= 1) + val8 = (val8 == 0); + inline_write_8(p->num, &val8); + } else if (p->size == 2) { + unsigned short val16; + val16 = (unsigned short) p->value; + if ((flags & PARAMPARSEFLAGS_8) && val16 <= 1) + val16 = (val16 == 0); + inline_write_16(p->num, &val16); + } else { + unsigned long val32; + val32 = p->value; + if ((flags & PARAMPARSEFLAGS_8) && val32 <= 1) + val32 = (val32 == 0); + inline_write_32(p->num, &val32); + } + return 1; +} + +static void DescHelpParam_SetString(SETSTRING_T *p, const char **desc, const char **help, const char **defaul) { + *help = 0; + *desc = 0; + *defaul = 0; +} + +static int CompareParam_SetString(SETSTRING_T *p, int flags) { + if (p->pstring) + return pstrcmp((const unsigned char *) p->var, (const unsigned char *) p->value) == 0; + else + return strcmp(p->var, p->value) == 0; +} + +static int Param_SetString(SETSTRING_T *p, const char *pstr, int flags) { + if (p->pstring) + memcpy(p->var, p->value, p->value[0]); + else + strcpy(p->var, p->value); + return 1; +} + +static void DescHelpParam_Generic(GENERIC_T *p, const char **desc, const char **help, const char **defaul) { + if (p->myname) + *desc = p->myname; + else if ((p->flags & PARAMFLAGS_3) != 1) + *desc = "xxx"; + else + *desc = 0; + *help = p->help; + *defaul = 0; +} + +static int CompareParam_Generic(GENERIC_T *p) { + return 0; +} + +static int Param_Generic(GENERIC_T *p, const char *pstr, int flags) { + return p->parse(curopt, p->var, pstr, flags); +} + +static void DescHelpParam_Setting(SETTING_T *p, const char **desc, const char **help, const char **defaul) { + char *dptr = descparam; + + dptr += sprintf(dptr, "%s", p->myname ? p->myname : "var"); + if ((p->flags & PARAMFLAGS_3) != 1) { + sprintf(dptr, + "%s=%s%s", + (p->flags & PARAMFLAGS_2) ? "[" : "", + p->valuename ? p->valuename : "...", + (p->flags & PARAMFLAGS_2) ? "]" : "" + ); + } + *desc = descparam; + *help = 0; + *defaul = 0; +} + +static int CompareParam_Setting(SETTING_T *p) { + return 0; +} + +static int Param_Setting(SETTING_T *p, const char *pstr, int flags) { + char savevar[256]; + const char *vstr; + ArgToken *tok; + Boolean equals = 0; + + if (!pstr) { + Param_Error(40); + return 0; + } + + strncpy(savevar, pstr, sizeof(savevar)); + tok = Arg_PeekToken(); + if (tok && tok->val == ATK_4) { + Arg_UsedToken(); + equals = 1; + if (!Param_GetArgument((PARAM_T *) p, &vstr, flags)) + return 0; + } else { + vstr = 0; + } + + if (!vstr && equals) + vstr = ""; + + return p->parse(savevar, vstr); +} + +static void DescHelpParam_IfArg(IFARG_T *p, const char **desc, const char **help, const char **defaul) { + const char *d1 = 0; + const char *d2 = 0; + const char *h1 = 0; + const char *h2 = 0; + const char *df1 = 0; + const char *df2 = 0; + char desclocal[1024]; + char *dptr = desclocal; + char helplocal[1024]; + char *hptr = helplocal; + const char *ind; + + desclocal[0] = 0; + helplocal[0] = 0; + + if (p->parg) + Param_DescHelp(p->parg, &d1, &h1, &df1); + if (p->pnone) + Param_DescHelp(p->pnone, &d2, &h2, &df2); + + if (p->helpa && p->helpn) { + if (df1) + hptr += sprintf(hptr, "%s (default is %s), else %s", p->helpa, df1, p->helpn); + else + hptr += sprintf(hptr, "%s, else %s", p->helpa, p->helpn); + } else if (p->helpa) { + hptr += sprintf(hptr, "%s", p->helpa); + if (df1) + hptr += sprintf(hptr, "; default is %s", df1); + } else if (p->helpn) { + hptr += sprintf(hptr, "nothing, else %s", p->helpn); + } + + if (d1) { + if (p->myname) { + dptr += sprintf(dptr, "[%s]", p->myname ? p->myname: "param"); + } else if (h1) { + ind = strchr(d1, '\n'); + if (!ind) + ind = d1 + strlen(d1); + dptr += sprintf(dptr, "[%.*s]", ind - d1, d1); + } else { + dptr += sprintf(dptr, "[%s]", d1); + d1 = 0; + } + } + + if (h1 || h2) { + dptr += sprintf(dptr, "\n\t"); + hptr += sprintf(hptr, "\n\t"); + if (h1) { + if (d1) + dptr += sprintf(dptr, "%s", d1); + if (h1) + hptr += sprintf(hptr, "%s", h1); + if (h2) { + dptr += sprintf(dptr, "\b\t"); + hptr += sprintf(hptr, "\b\t"); + } + } + if (h2) { + if (d2) + dptr += sprintf(dptr, "%s", d2); + else + dptr += sprintf(dptr, "(if blank)"); + if (h2) + hptr += sprintf(hptr, "%s", h2); + dptr += sprintf(dptr, "\n"); + hptr += sprintf(hptr, "\n"); + } + dptr += sprintf(dptr, "\b"); + hptr += sprintf(hptr, "\b"); + } + + if (dptr != desclocal) { + strcpy(descparam, desclocal); + *desc = descparam; + } else { + *desc = 0; + } + + if (hptr != helplocal) { + strcpy(helpparam, helplocal); + *help = helpparam; + } else { + *help = 0; + } + + *defaul = 0; +} + +static int CompareParam_IfArg(IFARG_T *p) { + return 0; +} + +static int Param_IfArg(IFARG_T *p, const char *pstr, int flags) { + if (pstr) + return Param_Parse(p->parg, pstr, flags); + else if (p->pnone) + return Param_Parse(p->pnone, pstr, flags); + else + return 1; +} + +typedef int (*PARSE_FUNC)(PARAM_T *, const char *, int); +PARSE_FUNC ParamParsers[16] = { + (PARSE_FUNC) &Param_None, + (PARSE_FUNC) &Param_FTypeCreator, + (PARSE_FUNC) &Param_FilePath, + (PARSE_FUNC) &Param_Number, + (PARSE_FUNC) &Param_String, + (PARSE_FUNC) &Param_ID_or_SYM, + (PARSE_FUNC) &Param_ID_or_SYM, + (PARSE_FUNC) &Param_OnOff, + (PARSE_FUNC) &Param_OffOn, + (PARSE_FUNC) &Param_Mask, + (PARSE_FUNC) &Param_Toggle, + (PARSE_FUNC) &Param_Set, + (PARSE_FUNC) &Param_SetString, + (PARSE_FUNC) &Param_Generic, + (PARSE_FUNC) &Param_IfArg, + (PARSE_FUNC) &Param_Setting +}; + +static int Param_Parse(PARAM_T *param, const char *cparam, int flags) { + if (!param) + CLPFatalError("PARAM_T is NULL"); + + if (param->which >= PARAMWHICH_None && param->which < PARAMWHICH_MAX) { + return ParamParsers[param->which](param, cparam, flags); + } else { + CLPFatalError("Unhandled PARAM_T (%d)", param->which); + return 0; + } +} + +typedef void (*DESC_HELP_FUNC)(PARAM_T *, const char **, const char **, const char **); +DESC_HELP_FUNC DescHelpParams[16] = { + (DESC_HELP_FUNC) &DescHelpParam_None, + (DESC_HELP_FUNC) &DescHelpParam_FTypeCreator, + (DESC_HELP_FUNC) &DescHelpParam_FilePath, + (DESC_HELP_FUNC) &DescHelpParam_Number, + (DESC_HELP_FUNC) &DescHelpParam_String, + (DESC_HELP_FUNC) &DescHelpParam_ID_or_SYM, + (DESC_HELP_FUNC) &DescHelpParam_ID_or_SYM, + (DESC_HELP_FUNC) &DescHelpParam_OnOff, + (DESC_HELP_FUNC) &DescHelpParam_OffOn, + (DESC_HELP_FUNC) &DescHelpParam_Mask, + (DESC_HELP_FUNC) &DescHelpParam_Toggle, + (DESC_HELP_FUNC) &DescHelpParam_Set, + (DESC_HELP_FUNC) &DescHelpParam_SetString, + (DESC_HELP_FUNC) &DescHelpParam_Generic, + (DESC_HELP_FUNC) &DescHelpParam_IfArg, + (DESC_HELP_FUNC) &DescHelpParam_Setting +}; +void Param_DescHelp(PARAM_T *param, const char **desc, const char **help, const char **defaul) { + *desc = 0; + *help = 0; + *defaul = 0; + + if (!param) { + CLPFatalError("PARAM_T is NULL"); + return; + } + + if (param->which >= PARAMWHICH_None && param->which < PARAMWHICH_MAX) { + DescHelpParams[param->which](param, desc, help, defaul); + } else { + CLPFatalError("Unhandled PARAM_T (%d)", param->which); + } +} + +typedef int (*COMPARE_FUNC)(PARAM_T *); +COMPARE_FUNC CompareParams[16] = { + (COMPARE_FUNC) &CompareParam_None, + (COMPARE_FUNC) &CompareParam_FTypeCreator, + (COMPARE_FUNC) &CompareParam_FilePath, + (COMPARE_FUNC) &CompareParam_Number, + (COMPARE_FUNC) &CompareParam_String, + (COMPARE_FUNC) &CompareParam_ID_or_SYM, + (COMPARE_FUNC) &CompareParam_ID_or_SYM, + (COMPARE_FUNC) &CompareParam_OnOff, + (COMPARE_FUNC) &CompareParam_OffOn, + (COMPARE_FUNC) &CompareParam_Mask, + (COMPARE_FUNC) &CompareParam_Toggle, + (COMPARE_FUNC) &CompareParam_Set, + (COMPARE_FUNC) &CompareParam_SetString, + (COMPARE_FUNC) &CompareParam_Generic, + (COMPARE_FUNC) &CompareParam_IfArg, + (COMPARE_FUNC) &CompareParam_Setting +}; +int Param_Compare(PARAM_T *param) { + if (!param) + CLPFatalError("PARAM_T is NULL"); + + if (param->which >= PARAMWHICH_None && param->which < PARAMWHICH_MAX) { + return CompareParams[param->which](param); + } else { + CLPFatalError("Unhandled PARAM_T (%d)", param->which); + return 0; + } +} + +static void Param_PushParam(const char *param) { + Args_Push(4, (void *) param, 0); +} + +static void Param_PopParam() { + Args_Pop(4); +} + +static Boolean Param_IsNonTextFile(const char *fname, Boolean warn) { + OSSpec tmp; + CWDataType mactype; + Boolean isfile; + + if (!OS_MakeSpec(fname, &tmp, &isfile)) { + if (isfile) { + if (!OS_Status(&tmp)) { + if (!OS_GetMacFileType(&tmp, &mactype)) { + if (mactype != 'TEXT') { + if (warn) + Param_Warning(77, fname); + return 1; + } + } + } + } + } + + return 0; +} + +static int Param_GetArgument(PARAM_T *param, const char **cparam, int exec) { + int subparse; + short nextOpt; + short nextParam; + short lastOpt; + ArgToken *tok; + + subparse = (exec & PARAMPARSEFLAGS_4) != 0; + nextOpt = !subparse ? ATK_1 : ATK_5; + nextParam = !subparse ? ATK_5 : ATK_4; + lastOpt = !subparse ? ATK_0 : ATK_1; + + tok = Arg_PeekToken(); +#line 1467 + OPTION_ASSERT(tok); + + if ((param->flags & PARAMFLAGS_3) == 0) { + if (tok->val == nextParam || tok->val == ATK_4) + tok = Arg_UsedToken(); + if (tok->val == nextOpt || tok->val == nextParam || tok->val == lastOpt) { + Param_Error(34); + return 0; + } + if (tok->val != ATK_2) { + Param_Error(57, "parameter", Arg_GetTokenName(tok)); + return 0; + } + Arg_GetTokenText(tok, curparam, sizeof(curparam), 1); + Arg_UsedToken(); + *cparam = curparam; + + if (param->flags & PARAMFLAGS_8) { + tok = Arg_PeekToken(); + if (tok->val == ATK_4) + Arg_UsedToken(); + } + } else if (param->flags & PARAMFLAGS_1) { + *cparam = 0; + if (tok->val == ATK_4 && !subparse) { + if (!(exec & PARAMPARSEFLAGS_40)) { + Param_Error(37); + return 0; + } + Arg_UsedToken(); + } + } else if (param->flags & PARAMFLAGS_2) { + if (tok->val == nextOpt || tok->val == lastOpt) { + *cparam = 0; + } else if (tok->val == nextParam) { + tok = Arg_UsedToken(); + if (tok->val == ATK_2) { + Arg_GetTokenText(tok, curparam, sizeof(curparam), 1); + if ((param->flags & PARAMFLAGS_12) && Param_IsNonTextFile(curparam, !(exec & PARAMPARSEFLAGS_1))) { + *cparam = 0; + } else { + Arg_UsedToken(); + *cparam = curparam; + } + } else { + *cparam = 0; + } + } else if (tok->val == ATK_2 && !tok->text[0]) { + tok = Arg_UsedToken(); + if (tok->val == nextParam) + Arg_UsedToken(); + *cparam = 0; + } else if ((exec & PARAMPARSEFLAGS_4) && tok->val != ATK_4) { + *cparam = 0; + } else { + if (tok->val == ATK_4) + tok = Arg_UsedToken(); + if (tok->val == ATK_2) { + Arg_GetTokenText(tok, curparam, sizeof(curparam), 1); + if ((param->flags & PARAMFLAGS_12) && Param_IsNonTextFile(curparam, !(exec & PARAMPARSEFLAGS_1))) { + *cparam = 0; + } else { + Arg_UsedToken(); + *cparam = curparam; + } + } else { + *cparam = 0; + } + } + } else { + CLPFatalError("Unknown parameter type"); + } + + if (pTool->TYPE == CWDROPINCOMPILERTYPE && (exec & PARAMPARSEFLAGS_2) && *cparam) { + if (!(exec & PARAMPARSEFLAGS_10)) { + if (subparse) + Arg_AddToToolArgs(&linkargs, ATK_4, 0); + else + Arg_AddToToolArgs(&linkargs, ATK_5, 0); + } + Param_PushParam(*cparam); + Args_AddToToolArgs(&linkargs); + Param_PopParam(); + } + + return 1; +} + +int Params_Parse(PARAM_T *param, int flags) { + const char *cparam; + flags |= PARAMPARSEFLAGS_10; + + if (param) { + while (param) { + if (flags & PARAMPARSEFLAGS_20) + flags |= PARAMPARSEFLAGS_40; + + if (!Param_GetArgument(param, &cparam, flags)) + return 0; + + if (!(flags & PARAMPARSEFLAGS_1)) { + if (!Param_Parse(param, cparam, flags | (short) ((param->flags & PARAMFLAGS_4) ? PARAMPARSEFLAGS_20 : 0))) + return 0; + } else if (param->flags & PARAMFLAGS_4) { + if (!Param_GetArgument(param, &cparam, flags | PARAMPARSEFLAGS_4)) + return 0; + } + + if (cparam) + flags &= ~PARAMPARSEFLAGS_10; + flags &= ~PARAMPARSEFLAGS_40; + param = param->next; + } + } + + return 1; +} + +void Param_Error(short id, ...) { + va_list va; + va_start(va, id); + Option_ParamError(id, va); + va_end(va); +} + +void Param_Warning(short id, ...) { + va_list va; + va_start(va, id); + Option_ParamWarning(id, va); + va_end(va); +} diff --git a/mwcc_decomp.h b/mwcc_decomp.h index e462bae..dcafa5b 100644 --- a/mwcc_decomp.h +++ b/mwcc_decomp.h @@ -86,7 +86,7 @@ typedef struct GENERIC_T { char flags; char *myname; PARAM_T *next; - void (*parse)(); // TODO missing sig + int (*parse)(const char *opt, void *var, const char *pstr, int flags); void *var; char *help; } GENERIC_T; @@ -95,7 +95,7 @@ typedef struct SETTING_T { char flags; char *myname; PARAM_T *next; - void (*parse)(); // TODO missing sig + int (*parse)(const char *a, const char *b); // TODO name these args char *valuename; } SETTING_T; typedef struct TOGGLE_T { @@ -256,8 +256,8 @@ enum { PARAMWHICH_FilePath = 2, PARAMWHICH_Number = 3, PARAMWHICH_String = 4, - PARAMWHICH_5 = 5, - PARAMWHICH_6 = 6, + PARAMWHICH_Id = 5, + PARAMWHICH_Sym = 6, PARAMWHICH_OnOff = 7, PARAMWHICH_OffOn = 8, PARAMWHICH_Mask = 9, @@ -266,14 +266,29 @@ enum { PARAMWHICH_SetString = 0xC, PARAMWHICH_Generic = 0xD, PARAMWHICH_IfArg = 0xE, - PARAMWHICH_Setting = 0xF + PARAMWHICH_Setting = 0xF, + PARAMWHICH_MAX = 0x10 }; enum { PARAMFLAGS_1 = 1, PARAMFLAGS_2 = 2, PARAMFLAGS_3 = 3, PARAMFLAGS_4 = 4, - PARAMFLAGS_8 = 8 + PARAMFLAGS_8 = 8, + PARAMFLAGS_10 = 0x10, + PARAMFLAGS_12 = 0x12 +}; +enum { + PARAMPARSEFLAGS_0 = 0, + PARAMPARSEFLAGS_1 = 1, + PARAMPARSEFLAGS_2 = 2, + PARAMPARSEFLAGS_4 = 4, + PARAMPARSEFLAGS_8 = 8, + PARAMPARSEFLAGS_10 = 0x10, + PARAMPARSEFLAGS_20 = 0x20, + PARAMPARSEFLAGS_40 = 0x40, + PARAMPARSEFLAGS_80 = 0x80, + PARAMPARSEFLAGS_100 = 0x100 }; enum { SLFLAGS_1 = 1, @@ -1745,85 +1760,24 @@ extern void CLPProgress(short errid, ...); extern void CLPStatus(short errid, ...); extern void CLPFatalError(const char *format, ...); +extern char curopt[1024]; + /********************************/ /* Utils.c */ -extern int my_tolower(char c); -extern int my_isdigit(char c); -extern int my_isalpha(char c); -extern int my_isalnum(char c); -extern int my_isxdigit(char c); +// something is weird with these parameters +// they're supposed to be just "char"... +extern int my_tolower(unsigned char c); +extern int my_isdigit(unsigned char c); +extern int my_isalpha(unsigned char c); +extern int my_isalnum(unsigned char c); +extern int my_isxdigit(unsigned char c); extern char *Utils_SpellList(char *list, char *buffer, char opts); extern int Utils_CompareOptionString(const char *a, const char *b, int cased, int sticky); /********************************/ /* Parameter.c */ -//static int Param_None(); -//static void DescHelpParam_None(PARAM_T *p, const char **desc, const char **help, const char **defaul); -//static int CompareParam_None(); - -//static void DescHelpParam_Number(NUM_T *p, const char **desc, const char **help, const char **defaul); -//static int CompareParam_Number(); -//static int Param_Number(NUM_T *p, const char *pstr); - -//static void DescHelpParam_FTypeCreator(FTYPE_T *p, const char **desc, const char **help, const char **defaul); -//static int CompareParam_FTypeCreator(); -//static int Param_FTypeCreator(FTYPE_T *p, const char *pstr); - -//static void DescHelpParam_String(STRING_T *p, const char **desc, const char **help, const char **defaul); -//static int CompareParam_String(); -//static int Param_String(STRING_T *p, const char *pstr); - -//static void DescHelpParam_ID_or_SYM(STRING_T *p, const char **desc, const char **help, const char **defaul); -//static int CompareParam_ID_or_SYM(); -//static int Param_ID_or_SYM(STRING_T *p, const char *pstr); - -//static void DescHelpParam_OnOff(ONOFF_T *p, const char **desc, const char **help, const char **defaul); -//static int CompareParam_OnOff(); -//static int Param_OnOff(ONOFF_T *p, const char *pstr); - -//static void DescHelpParam_OffOn(ONOFF_T *p, const char **desc, const char **help, const char **defaul); -//static int CompareParam_OffOn(); -//static int Param_OffOn(OFFON_T *p, const char *pstr); - -//static void DescHelpParam_FilePath(FILEPATH_T *p, const char **desc, const char **help, const char **defaul); -//static int CompareParam_FilePath(); -//static int Param_FilePath(FILEPATH_T *p, const char *pstr); - -//static void DescHelpParam_Mask(MASK_T *p, const char **desc, const char **help, const char **defaul); -//static int CompareParam_Mask(MASK_T *p); -//static int Param_Mask(MASK_T *p, const char *pstr, int flags); - -//static void DescHelpParam_Toggle(TOGGLE_T *p, const char **desc, const char **help, const char **defaul); -//static int CompareParam_Toggle(TOGGLE_T *p); -//static int Param_Toggle(TOGGLE_T *p, const char *pstr); - -//static void DescHelpParam_Set(SET_T *p, const char **desc, const char **help, const char **defaul); -//static int CompareParam_Set(SET_T *p); -//static int Param_Set(SET_T *p, const char *pstr, int flags); - -//static void DescHelpParam_SetString(SETSTRING_T *p, const char **desc, const char **help, const char **defaul); -//static int CompareParam_SetString(SETSTRING_T *p); -//static int Param_SetString(SETSTRING_T *p, const char *pstr, int flags); - -//static void DescHelpParam_Generic(GENERIC_T *p, const char **desc, const char **help, const char **defaul); -//static int CompareParam_Generic(GENERIC_T *p); -//static int Param_Generic(GENERIC_T *p, const char *pstr, int flags); - -//static void DescHelpParam_Setting(SETTING_T *p, const char **desc, const char **help, const char **defaul); -//static int CompareParam_Setting(SETTING_T *p); -//static int Param_Setting(SETTING_T *p, const char *pstr, int flags); - -//static void DescHelpParam_IfArg(IFARG_T *p, const char **desc, const char **help, const char **defaul); -//static int CompareParam_IfArg(IFARG_T *p); -//static int Param_IfArg(IFARG_T *p, const char *pstr, int flags); - -//static int Param_Parse(PARAM_T *param, const char *cparam, int flags); extern void Param_DescHelp(PARAM_T *param, const char **desc, const char **help, const char **defaul); extern int Param_Compare(PARAM_T *param); -//static void Param_PushParam(const char *param); -//static void Param_PopParam(); -//static Boolean Param_IsNonTextFile(const char *fname, Boolean warn); -//static int Param_GetArgument(PARAM_T *param, const char *cparam, int exec); extern int Params_Parse(PARAM_T *param, int flags); extern void Param_Error(short id, ...); extern void Param_Warning(short id, ...);