/* * Handle initial connection protocol. */ static int tftp(struct testcase *test, struct tftphdr *tp, ssize_t size) { char *cp; int first = 1, ecode; struct formats *pf; char *filename, *mode = NULL; int error; FILE *server; /* Open request dump file. */ server = fopen(REQUEST_DUMP, "ab"); if(!server) { error = ERRNO; logmsg("fopen() failed with error: %d %s", error, strerror(error)); logmsg("Error opening file: %s", REQUEST_DUMP); return -1; } /* store input protocol */ fprintf(server, "opcode: %x\n", tp->th_opcode); cp = (char *)&tp->th_stuff; filename = cp; again: while (cp < buf + size) { if (*cp == '\0') break; cp++; } if (*cp) { nak(EBADOP); fclose(server); return 3; } if (first) { mode = ++cp; first = 0; goto again; } /* store input protocol */ fprintf(server, "filename: %s\n", filename); for (cp = mode; *cp; cp++) if(ISUPPER(*cp)) *cp = (char)tolower((int)*cp); /* store input protocol */ fprintf(server, "mode: %s\n", mode); fclose(server); for (pf = formata; pf->f_mode; pf++) if (strcmp(pf->f_mode, mode) == 0) break; if (!pf->f_mode) { nak(EBADOP); return 2; } ecode = validate_access(test, filename, tp->th_opcode); if (ecode) { nak(ecode); return 1; } if (tp->th_opcode == opcode_WRQ) recvtftp(test, pf); else sendtftp(test, pf); return 0; }
/* ** void MakeExpandedName(char ARG_PTR *pszFileName, BYTE byteExtensionChar); ** ** Create expanded output file name. ** ** Arguments: pszFileName - expanded file name to change ** byteExtensionChar - expanded file name extension character to ** use ** ** Returns: void ** ** Globals: none */ VOID MakeExpandedName(CHAR ARG_PTR *pszFileName, BYTE byteExtensionChar) { CHAR ARG_PTR *pszExt; INT nExtLen; // Is there any extension to change? if ((pszExt = ExtractExtension(pszFileName)) != NULL) { // Determine case of extension character. Match case of first non-DB // character in name. If all characters are DB, leave case alone. if (ISLETTER(byteExtensionChar)) { // Find first alphabetic character in name. while (*pszFileName) { #ifdef DBCS if (IsDBCSLeadByte(*pszFileName)) pszFileName += 2; else #endif if (ISLETTER(*pszFileName)) break; else pszFileName++; } // Here pszFileName points to the first alphabetic character in the // name or to the null terminator. Set the case of the extension // character. if (ISLOWER(*pszFileName)) byteExtensionChar = (BYTE)TOLOWERCASE(byteExtensionChar); else if (ISUPPER(*pszFileName)) byteExtensionChar = (BYTE)TOUPPERCASE(byteExtensionChar); } #ifdef DBCS if ((nExtLen = STRLEN(pszExt)) > 0) { // Find the underscore character to replace, if it exists. // Assert: The underscore is either the last character in the // extension, or it is the first character in the extension followed // by a double-byte character. if (! IsDBCSLeadByte(*pszExt) && *pszExt == chEXTENSION_CHAR && IsDBCSLeadByte(pszExt[1])) // Here the underscore is followed by a double-byte character. *pszExt = byteExtensionChar; else { // Here the underscore is the last character in the extension, if // there is an underscore at all. CHAR ARG_PTR *psz, *pszPrevious; for (psz = pszPrevious = pszExt; *psz != '\0'; psz = AnsiNext(psz)) pszPrevious = psz; if (! IsDBCSLeadByte(*pszPrevious) && *pszPrevious == chEXTENSION_CHAR) *pszPrevious = byteExtensionChar; } } #else if ((nExtLen = STRLEN(pszExt)) > 0 && pszExt[nExtLen - 1] == chEXTENSION_CHAR) // Handle expected renamed form. pszExt[nExtLen - 1] = byteExtensionChar; #endif // Get rid of trailing dot with no extension. if (*pszExt == '\0' && *(pszExt - 1) == PERIOD) *(pszExt - 1) = '\0'; } }
/* * Convert a string to a long integer. * * Ignores `locale' stuff. Assumes that the upper and lower case * alphabets and digits are each contiguous. */ long strtol(const char *nptr, char **endptr, register int base) { register const char *s = nptr; register unsigned long acc; register int c; register unsigned long cutoff; register int neg = 0, any, cutlim; /* * Skip white space and pick up leading +/- sign if any. * If base is 0, allow 0x for hex and 0 for octal, else * assume decimal; if base is already 16, allow 0x. */ do { c = *s++; } while (ISSPACE(c)); if (c == '-') { neg = 1; c = *s++; } else if (c == '+') c = *s++; if ((base == 0 || base == 16) && c == '0' && (*s == 'x' || *s == 'X')) { c = s[1]; s += 2; base = 16; } if (base == 0) base = c == '0' ? 8 : 10; /* * Compute the cutoff value between legal numbers and illegal * numbers. That is the largest legal value, divided by the * base. An input number that is greater than this value, if * followed by a legal input character, is too big. One that * is equal to this value may be valid or not; the limit * between valid and invalid numbers is then based on the last * digit. For instance, if the range for longs is * [-2147483648..2147483647] and the input base is 10, * cutoff will be set to 214748364 and cutlim to either * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated * a value > 214748364, or equal but the next digit is > 7 (or 8), * the number is too big, and we will return a range error. * * Set any if any `digits' consumed; make it negative to indicate * overflow. */ cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; cutlim = cutoff % (unsigned long)base; cutoff /= (unsigned long)base; for (acc = 0, any = 0;; c = *s++) { if (ISDIGIT(c)) c -= '0'; else if (ISALPHA(c)) c -= ISUPPER(c) ? 'A' - 10 : 'a' - 10; else break; if (c >= base) break; if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) any = -1; else { any = 1; acc *= base; acc += c; } } if (any < 0) { acc = neg ? LONG_MIN : LONG_MAX; #if 0 errno = ERANGE; #endif } else if (neg) acc = -acc; if (endptr != 0) *endptr = (char *) (any ? s - 1 : nptr); return (acc); }
/* ARGSUSED */ int desckey(int f, int n) { KEYMAP *curmap; PF funct; int c, m, i, num; char *pep; char dprompt[80]; #ifndef NO_MACRO if (inmacro) return (TRUE); /* ignore inside keyboard macro */ #endif /* !NO_MACRO */ num = strlcpy(dprompt, "Describe key briefly: ", sizeof(dprompt)); if (num >= sizeof(dprompt)) num = sizeof(dprompt) - 1; pep = dprompt + num; key.k_count = 0; m = curbp->b_nmodes; curmap = curbp->b_modes[m]->p_map; for (;;) { for (;;) { ewprintf("%s", dprompt); pep[-1] = ' '; pep = getkeyname(pep, sizeof(dprompt) - (pep - dprompt), key.k_chars[key.k_count++] = c = getkey(FALSE)); if ((funct = doscan(curmap, c, &curmap)) != NULL) break; *pep++ = '-'; *pep = '\0'; } if (funct != rescan) break; if (ISUPPER(key.k_chars[key.k_count - 1])) { funct = doscan(curmap, TOLOWER(key.k_chars[key.k_count - 1]), &curmap); if (funct == NULL) { *pep++ = '-'; *pep = '\0'; continue; } if (funct != rescan) break; } nextmode: if (--m < 0) break; curmap = curbp->b_modes[m]->p_map; for (i = 0; i < key.k_count; i++) { funct = doscan(curmap, key.k_chars[i], &curmap); if (funct != NULL) { if (i == key.k_count - 1 && funct != rescan) goto found; funct = rescan; goto nextmode; } } *pep++ = '-'; *pep = '\0'; } found: if (funct == rescan || funct == selfinsert) ewprintf("%k is not bound to any function"); else if ((pep = (char *)function_name(funct)) != NULL) ewprintf("%k runs the command %s", pep); else ewprintf("%k is bound to an unnamed function"); return (TRUE); }
/* * static int * inet_net_pton_ipv4(src, dst, size) * convert IPv4 network number from presentation to network format. * accepts hex octets, hex strings, decimal octets, and /CIDR. * "size" is in bytes and describes "dst". * return: * number of bits, either imputed classfully or specified with /CIDR, * or -1 if some failure occurred (check errno). ENOENT means it was * not an IPv4 network specification. * note: * network byte order assumed. this means 192.5.5.240/28 has * 0b11110000 in its fourth octet. * note: * On Windows we store the error in the thread errno, not * in the winsock error code. This is to avoid loosing the * actual last winsock error. So use macro ERRNO to fetch the * errno this funtion sets when returning (-1), not SOCKERRNO. * author: * Paul Vixie (ISC), June 1996 */ static int inet_net_pton_ipv4(const char *src, unsigned char *dst, size_t size) { static const char xdigits[] = "0123456789abcdef"; static const char digits[] = "0123456789"; int n, ch, tmp = 0, dirty, bits; const unsigned char *odst = dst; ch = *src++; if (ch == '0' && (src[0] == 'x' || src[0] == 'X') && ISXDIGIT(src[1])) { /* Hexadecimal: Eat nybble string. */ if (!size) goto emsgsize; dirty = 0; src++; /* skip x or X. */ while ((ch = *src++) != '\0' && ISXDIGIT(ch)) { if (ISUPPER(ch)) ch = tolower(ch); n = (int)(strchr(xdigits, ch) - xdigits); if (dirty == 0) tmp = n; else tmp = (tmp << 4) | n; if (++dirty == 2) { if (!size--) goto emsgsize; *dst++ = (unsigned char) tmp; dirty = 0; } } if (dirty) { /* Odd trailing nybble? */ if (!size--) goto emsgsize; *dst++ = (unsigned char) (tmp << 4); } } else if (ISDIGIT(ch)) { /* Decimal: eat dotted digit string. */ for (;;) { tmp = 0; do { n = (int)(strchr(digits, ch) - digits); tmp *= 10; tmp += n; if (tmp > 255) goto enoent; } while ((ch = *src++) != '\0' && ISDIGIT(ch)); if (!size--) goto emsgsize; *dst++ = (unsigned char) tmp; if (ch == '\0' || ch == '/') break; if (ch != '.') goto enoent; ch = *src++; if (!ISDIGIT(ch)) goto enoent; } } else goto enoent; bits = -1; if (ch == '/' && ISDIGIT(src[0]) && dst > odst) { /* CIDR width specifier. Nothing can follow it. */ ch = *src++; /* Skip over the /. */ bits = 0; do { n = (int)(strchr(digits, ch) - digits); bits *= 10; bits += n; } while ((ch = *src++) != '\0' && ISDIGIT(ch)); if (ch != '\0') goto enoent; if (bits > 32) goto emsgsize; } /* Firey death and destruction unless we prefetched EOS. */ if (ch != '\0') goto enoent; /* If nothing was written to the destination, we found no address. */ if (dst == odst) goto enoent; /* If no CIDR spec was given, infer width from net class. */ if (bits == -1) { if (*odst >= 240) /* Class E */ bits = 32; else if (*odst >= 224) /* Class D */ bits = 8; else if (*odst >= 192) /* Class C */ bits = 24; else if (*odst >= 128) /* Class B */ bits = 16; else /* Class A */ bits = 8; /* If imputed mask is narrower than specified octets, widen. */ if (bits < ((dst - odst) * 8)) bits = (int)(dst - odst) * 8; /* * If there are no additional bits specified for a class D * address adjust bits to 4. */ if (bits == 8 && *odst == 224) bits = 4; } /* Extend network to cover the actual mask. */ while (bits > ((dst - odst) * 8)) { if (!size--) goto emsgsize; *dst++ = '\0'; } return (bits); enoent: SET_ERRNO(ENOENT); return (-1); emsgsize: SET_ERRNO(EMSGSIZE); return (-1); }
/* * Format the given command into a buffer, returning the resulting string. * * It is too dangerous to leave any URL that may come along unquoted. They * often contain '&', ';', and '?' chars, and who knows what else may occur. * Prevent spoofing of the shell. Dunno how this needs to be modified for VMS * or DOS. - kw */ static char *format_command(char *command, char *param) { char *cmdbuf = NULL; #if defined(WIN_EX) char pram_string[LY_MAXPATH]; char *escaped = NULL; if (strncasecomp("file://localhost/", param, 17) == 0) { /* decode local path parameter for programs to be able to interpret - TH */ LYStrNCpy(pram_string, param, sizeof(pram_string) - 1); decode_string(pram_string); param = pram_string; } else { /* encode or escape URL parameter - TH */ escaped = escapeParameter(param); param = escaped; } if (isMAILTO_URL(param)) { format(&cmdbuf, command, param + 7); } else if (strncasecomp("telnet://", param, 9) == 0) { char host[sizeof(pram_string)]; int last_pos; LYStrNCpy(host, param + 9, sizeof(host)); last_pos = (int) strlen(host) - 1; if (last_pos > 1 && host[last_pos] == '/') host[last_pos] = '\0'; format(&cmdbuf, command, host); } else if (strncasecomp("file://localhost/", param, 17) == 0) { char e_buff[LY_MAXPATH], *p; p = param + 17; delete_danger_characters(p); *e_buff = 0; if (StrChr(p, ':') == NULL) { sprintf(e_buff, "%.3s/", windows_drive); } strncat(e_buff, p, sizeof(e_buff) - strlen(e_buff) - 1); p = strrchr(e_buff, '.'); if (p) { trimPoundSelector(p); } /* Less ==> short filename with backslashes, * less ==> long filename with forward slashes, may be quoted */ if (ISUPPER(command[0])) { char *short_name = HTDOS_short_name(e_buff); p = quote_pathname(short_name); format(&cmdbuf, command, p); FREE(p); } else { p = quote_pathname(e_buff); format(&cmdbuf, command, p); FREE(p); } } else { format(&cmdbuf, command, param); } FREE(escaped); #else format(&cmdbuf, command, param); #endif return cmdbuf; }
static mrb_bool is_const_id(mrb_state *mrb, const char *name) { if (!name) return FALSE; return ISUPPER(name[0]); }
static int loop(const unsigned char *pattern, const unsigned char *string) { loop_state state = CURLFNM_LOOP_DEFAULT; unsigned char *p = (unsigned char *)pattern; unsigned char *s = (unsigned char *)string; unsigned char charset[CURLFNM_CHSET_SIZE] = { 0 }; int rc = 0; for(;;) { switch(state) { case CURLFNM_LOOP_DEFAULT: if(*p == '*') { while(*(p+1) == '*') /* eliminate multiple stars */ p++; if(*s == '\0' && *(p+1) == '\0') return CURL_FNMATCH_MATCH; rc = loop(p + 1, s); /* *.txt matches .txt <=> .txt matches .txt */ if(rc == CURL_FNMATCH_MATCH) return CURL_FNMATCH_MATCH; if(*s) /* let the star eat up one character */ s++; else return CURL_FNMATCH_NOMATCH; } else if(*p == '?') { if(ISPRINT(*s)) { s++; p++; } else if(*s == '\0') return CURL_FNMATCH_NOMATCH; else return CURL_FNMATCH_FAIL; /* cannot deal with other character */ } else if(*p == '\0') { if(*s == '\0') return CURL_FNMATCH_MATCH; else return CURL_FNMATCH_NOMATCH; } else if(*p == '\\') { state = CURLFNM_LOOP_BACKSLASH; p++; } else if(*p == '[') { unsigned char *pp = p+1; /* cannot handle with pointer to register */ if(setcharset(&pp, charset)) { int found = FALSE; if(charset[(unsigned int)*s]) found = TRUE; else if(charset[CURLFNM_ALNUM]) found = ISALNUM(*s); else if(charset[CURLFNM_ALPHA]) found = ISALPHA(*s); else if(charset[CURLFNM_DIGIT]) found = ISDIGIT(*s); else if(charset[CURLFNM_XDIGIT]) found = ISXDIGIT(*s); else if(charset[CURLFNM_PRINT]) found = ISPRINT(*s); else if(charset[CURLFNM_SPACE]) found = ISSPACE(*s); else if(charset[CURLFNM_UPPER]) found = ISUPPER(*s); else if(charset[CURLFNM_LOWER]) found = ISLOWER(*s); else if(charset[CURLFNM_BLANK]) found = ISBLANK(*s); else if(charset[CURLFNM_GRAPH]) found = ISGRAPH(*s); if(charset[CURLFNM_NEGATE]) found = !found; if(found) { p = pp+1; s++; memset(charset, 0, CURLFNM_CHSET_SIZE); } else return CURL_FNMATCH_NOMATCH; } else return CURL_FNMATCH_FAIL; } else { if(*p++ != *s++) return CURL_FNMATCH_NOMATCH; } break; case CURLFNM_LOOP_BACKSLASH: if(ISPRINT(*p)) { if(*p++ == *s++) state = CURLFNM_LOOP_DEFAULT; else return CURL_FNMATCH_NOMATCH; } else return CURL_FNMATCH_FAIL; break; } } }
static mrb_bool symname_p(const char *name) { const char *m = name; mrb_bool localid = FALSE; if (!m) return FALSE; switch (*m) { case '\0': return FALSE; case '$': if (is_special_global_name(++m)) return TRUE; goto id; case '@': if (*++m == '@') ++m; goto id; case '<': switch (*++m) { case '<': ++m; break; case '=': if (*++m == '>') ++m; break; default: break; } break; case '>': switch (*++m) { case '>': case '=': ++m; break; default: break; } break; case '=': switch (*++m) { case '~': ++m; break; case '=': if (*++m == '=') ++m; break; default: return FALSE; } break; case '*': if (*++m == '*') ++m; break; case '!': switch (*++m) { case '=': case '~': ++m; } break; case '+': case '-': if (*++m == '@') ++m; break; case '|': if (*++m == '|') ++m; break; case '&': if (*++m == '&') ++m; break; case '^': case '/': case '%': case '~': case '`': ++m; break; case '[': if (*++m != ']') return FALSE; if (*++m == '=') ++m; break; default: localid = !ISUPPER(*m); id: if (*m != '_' && !ISALPHA(*m)) return FALSE; while (is_identchar(*m)) m += 1; if (localid) { switch (*m) { case '!': case '?': case '=': ++m; default: break; } } break; } return *m ? FALSE : TRUE; }
/* * cut -- * Put a range of lines/columns into a TEXT buffer. * * There are two buffer areas, both found in the global structure. The first * is the linked list of all the buffers the user has named, the second is the * unnamed buffer storage. There is a pointer, too, which is the current * default buffer, i.e. it may point to the unnamed buffer or a named buffer * depending on into what buffer the last text was cut. Logically, in both * delete and yank operations, if the user names a buffer, the text is cut * into it. If it's a delete of information on more than a single line, the * contents of the numbered buffers are rotated up one, the contents of the * buffer named '9' are discarded, and the text is cut into the buffer named * '1'. The text is always cut into the unnamed buffer. * * In all cases, upper-case buffer names are the same as lower-case names, * with the exception that they cause the buffer to be appended to instead * of replaced. Note, however, that if text is appended to a buffer, the * default buffer only contains the appended text, not the entire contents * of the buffer. * * !!! * The contents of the default buffer would disappear after most operations * in historic vi. It's unclear that this is useful, so we don't bother. * * When users explicitly cut text into the numeric buffers, historic vi became * genuinely strange. I've never been able to figure out what was supposed to * happen. It behaved differently if you deleted text than if you yanked text, * and, in the latter case, the text was appended to the buffer instead of * replacing the contents. Hopefully it's not worth getting right, and here * we just treat the numeric buffers like any other named buffer. * * PUBLIC: int cut __P((SCR *, ARG_CHAR_T *, MARK *, MARK *, int)); */ int cut(SCR *sp, ARG_CHAR_T *namep, MARK *fm, MARK *tm, int flags) { CB *cbp; ARG_CHAR_T name = '\0'; db_recno_t lno; int append, copy_one, copy_def; /* * If the user specified a buffer, put it there. (This may require * a copy into the numeric buffers. We do the copy so that we don't * have to reference count and so we don't have to deal with things * like appends to buffers that are used multiple times.) * * Otherwise, if it's supposed to be put in a numeric buffer (usually * a delete) put it there. The rules for putting things in numeric * buffers were historically a little strange. There were three cases. * * 1: Some motions are always line mode motions, which means * that the cut always goes into the numeric buffers. * 2: Some motions aren't line mode motions, e.g. d10w, but * can cross line boundaries. For these commands, if the * cut crosses a line boundary, it goes into the numeric * buffers. This includes most of the commands. * 3: Some motions aren't line mode motions, e.g. d`<char>, * but always go into the numeric buffers, regardless. This * was the commands: % ` / ? ( ) N n { } -- and nvi adds ^A. * * Otherwise, put it in the unnamed buffer. */ append = copy_one = copy_def = 0; if (namep != NULL) { name = *namep; if (LF_ISSET(CUT_NUMREQ) || (LF_ISSET(CUT_NUMOPT) && (LF_ISSET(CUT_LINEMODE) || fm->lno != tm->lno))) { copy_one = 1; cb_rotate(sp); } if ((append = ISUPPER(name)) == 1) { if (!copy_one) copy_def = 1; name = TOLOWER(name); } namecb: CBNAME(sp, cbp, name); } else if (LF_ISSET(CUT_NUMREQ) || (LF_ISSET(CUT_NUMOPT) && (LF_ISSET(CUT_LINEMODE) || fm->lno != tm->lno))) { name = '1'; cb_rotate(sp); goto namecb; } else cbp = &sp->wp->dcb_store; copyloop: /* * If this is a new buffer, create it and add it into the list. * Otherwise, if it's not an append, free its current contents. */ if (cbp == NULL) { CALLOC_RET(sp, cbp, CB *, 1, sizeof(CB)); cbp->name = name; CIRCLEQ_INIT(&cbp->textq); LIST_INSERT_HEAD(&sp->wp->cutq, cbp, q); } else if (!append) {
/* helper function for the posxxx() functions */ static void do_pos1( int iSwitch ) { if( ( ISCHAR( 1 ) ) /* all functions need string as 1st param */ && ( ( iSwitch != DO_POS1_POSRANGE ) /* that's the only condition for all funcs _except_ POSRANGE */ || ( ( iSwitch == DO_POS1_POSRANGE ) /* In addition, POSRANGE needs .. */ && ( ISCHAR( 2 ) ) /* .. string as 2nd .. */ && ( ISCHAR( 3 ) ) /* .. and 3rd param */ ) ) ) { unsigned char * pcString; size_t sStrLen; unsigned char * puc, ucChar1 = ' ', ucChar2 = ' '; int iMode; size_t sIgnore; int iParamShift = 0; if( iSwitch == DO_POS1_POSRANGE ) { if( hb_parclen( 1 ) == 0 ) { hb_retnl( 0 ); return; } else { ucChar1 = *( hb_parc( 1 ) ); } if( hb_parclen( 2 ) == 0 ) { hb_retnl( 0 ); return; } else { ucChar2 = *( hb_parc( 2 ) ); } iParamShift += 2; } pcString = ( unsigned char * ) hb_parc( iParamShift + 1 ); sStrLen = ( size_t ) hb_parclen( iParamShift + 1 ); if( ISLOG( iParamShift + 2 ) ) iMode = hb_parl( iParamShift + 2 ); else iMode = 0; if( ISNUM( iParamShift + 3 ) ) sIgnore = ( size_t ) hb_parnl( iParamShift + 3 ); else sIgnore = 0; for( puc = pcString + sIgnore; puc < pcString + sStrLen; puc++ ) { int iDoRet = 0; switch( iSwitch ) { case DO_POS1_POSALPHA: { iDoRet = ISALPHA( *puc ); }; break; case DO_POS1_POSLOWER: { iDoRet = ISLOWER( *puc ); }; break; case DO_POS1_POSRANGE: { iDoRet = ( ( ucChar1 <= *puc ) && ( ucChar2 >= *puc ) ); }; break; case DO_POS1_POSUPPER: { iDoRet = ISUPPER( *puc ); }; break; } if( ( iMode && ! iDoRet ) || ( ! iMode && iDoRet ) ) { hb_retns( puc - pcString + 1 ); return; } } hb_retnl( 0 ); } else /* ISCHAR (1) etc. */ { PHB_ITEM pSubst = NULL; int iArgErrorMode = ct_getargerrormode(); if( iArgErrorMode != CT_ARGERR_IGNORE ) { switch( iSwitch ) { case DO_POS1_POSALPHA: { pSubst = ct_error_subst( ( USHORT ) iArgErrorMode, EG_ARG, CT_ERROR_POSALPHA, NULL, "POSALPHA", 0, EF_CANSUBSTITUTE, 3, hb_paramError( 1 ), hb_paramError( 2 ), hb_paramError( 3 ) ); }; break; case DO_POS1_POSLOWER: { pSubst = ct_error_subst( ( USHORT ) iArgErrorMode, EG_ARG, CT_ERROR_POSLOWER, NULL, "POSLOWER", 0, EF_CANSUBSTITUTE, 3, hb_paramError( 1 ), hb_paramError( 2 ), hb_paramError( 3 ) ); }; break; case DO_POS1_POSRANGE: { pSubst = ct_error_subst( ( USHORT ) iArgErrorMode, EG_ARG, CT_ERROR_POSRANGE, NULL, "POSRANGE", 0, EF_CANSUBSTITUTE, 5, hb_paramError( 1 ), hb_paramError( 2 ), hb_paramError( 3 ), hb_paramError( 4 ), hb_paramError( 5 ) ); }; break; case DO_POS1_POSUPPER: { pSubst = ct_error_subst( ( USHORT ) iArgErrorMode, EG_ARG, CT_ERROR_POSUPPER, NULL, "POSUPPER", 0, EF_CANSUBSTITUTE, 3, hb_paramError( 1 ), hb_paramError( 2 ), hb_paramError( 3 ) ); }; break; } } if( pSubst != NULL ) { hb_itemRelease( hb_itemReturnForward( pSubst ) ); } else { hb_retnl( 0 ); } } }
struct symbol *parser( ) { register struct symbol *psym; register char *pline; struct varent *pvar; struct strent *pstr; char *cp, *plc, *pn; long lnc; int i; double complex tem; /* reference for old Whitesmiths compiler: */ /* *extern FILE *stdout; */ pline = interl; /* get current location in command string */ /* If at beginning of string, must ask for more input */ if( pline == line ) { if( maccnt > 0 ) { --maccnt; cp = maclin; plc = pline; while( (*plc++ = *cp++) != 0 ) ; goto mstart; } if( takptr < 0 ) { /* no take file active: prompt keyboard input */ printf("* "); } /* Various ways of typing in a command line. */ /* * Old Whitesmiths call to print "*" immediately * use RT11 .GTLIN to get command string * from command file or terminal */ /* * fflush(stdout); * gtlin(line); */ #if USE_READLINE if (takptr < 0) { if (line_read) { free (line_read); line_read = (char *)NULL; } /* Get a line from the user. */ line_read = readline (""); /* If the line has any text in it, save it on the history. */ if (line_read && *line_read) add_history (line_read); /* Copy to local buffer. */ strcpy(line,line_read); } else #endif zgets( line, TRUE ); /* keyboard input for other systems: */ mstart: uposs = 1; /* unary operators possible at start of line */ } ignore: /* Skip over spaces */ while( *pline == ' ' ) ++pline; /* unary minus after operator */ if( uposs && (*pline == '-') ) { psym = &oprtbl[2]; /* UMINUS */ ++pline; goto pdon3; } /* COMP */ /* if( uposs && (*pline == '~') ) { psym = &oprtbl[3]; ++pline; goto pdon3; } */ if( uposs && (*pline == '+') ) /* ignore leading plus sign */ { ++pline; goto ignore; } /* end of null terminated input */ if( (*pline == '\n') || (*pline == '\0') || (*pline == '\r') ) { pline = line; goto endlin; } if( *pline == ';' ) { ++pline; endlin: psym = &oprtbl[1]; /* EOL */ goto pdon2; } /* parser() */ /* Test for numeric input */ if( (ISDIGIT(*pline)) || (*pline == '.') ) { lnc = 0; /* initialize numeric input to zero */ qnc = 0.0; if( *pline == '0' ) { /* leading "0" may mean octal or hex radix */ ++pline; if( *pline == '.' ) goto decimal; /* 0.ddd */ /* leading "0x" means hexadecimal radix */ if( (*pline == 'x') || (*pline == 'X') ) { ++pline; while( ISXDIGIT(*pline) ) { i = *pline++ & 0xff; if( i >= 'a' ) i -= 047; if( i >= 'A' ) i -= 07; i -= 060; lnc = (lnc << 4) + i; qnc = lnc; } goto numdon; } else { while( ISOCTAL( *pline ) ) { i = ((*pline++) & 0xff) - 060; lnc = (lnc << 3) + i; qnc = lnc; } goto numdon; } } else { /* no leading "0" means decimal radix */ /******/ decimal: pn = number; while( (ISDIGIT(*pline)) || (*pline == '.') ) *pn++ = *pline++; /* get possible exponent field */ if( (*pline == 'e') || (*pline == 'E') ) *pn++ = *pline++; else goto numcvt; if( (*pline == '-') || (*pline == '+') ) *pn++ = *pline++; while( ISDIGIT(*pline) ) *pn++ = *pline++; numcvt: *pn++ = ' '; *pn++ = 0; #if 0 #if NE == 6 asctoe64( number, &qnc ); #else asctoe113( number, &qnc ); #endif #endif sscanf( number, "%le", (double *) &qnc ); } /* output the number */ numdon: /* search the symbol table of constants */ pvar = &contbl[0]; for( i=0; i<NCONST; i++ ) { if( (pvar->attrib & BUSY) == 0 ) goto confnd; tem = *pvar->value; if( tem == qnc ) { psym = (struct symbol *)pvar; goto pdon2; } ++pvar; } printf( "no room for constant\n" ); /* psym = (struct symbol *)&contbl[0]; */ pvfs.pvar = &contbl[0]; psym = pvfs.psym; goto pdon2; confnd: pvar->spel= contbl[0].spel; pvar->attrib = CONST | BUSY; *pvar->value = qnc; psym = (struct symbol *)pvar; goto pdon2; } /* check for operators */ psym = &oprtbl[3]; for( i=0; i<NOPR; i++ ) { if( *pline == *(psym->spel) ) goto pdon1; ++psym; } /* if quoted, it is a string variable */ if( *pline == '"' ) { /* find an empty slot for the string */ pstr = strtbl; /* string table */ for( i=0; i<NSTRNG-1; i++ ) { if( (pstr->attrib & BUSY) == 0 ) goto fndstr; ++pstr; } printf( "No room for string\n" ); pstr->attrib |= ILLEG; psym = (struct symbol *)pstr; goto pdon0; fndstr: pstr->attrib |= BUSY; plc = pstr->string; ++pline; for( i=0; i<39; i++ ) { *plc++ = *pline; if( (*pline == '\n') || (*pline == '\0') || (*pline == '\r') ) { illstr: pstr = &strtbl[NSTRNG-1]; pstr->attrib |= ILLEG; printf( "Missing string terminator\n" ); psym = (struct symbol *)pstr; goto pdon0; } if( *pline++ == '"' ) goto finstr; } goto illstr; /* no terminator found */ finstr: --plc; *plc = '\0'; psym = (struct symbol *)pstr; goto pdon2; } /* If none of the above, search function and symbol tables: */ /* copy character string to array lc[] */ plc = &lc[0]; while( ISALPHA(*pline) ) { /* convert to lower case characters */ if( ISUPPER( *pline ) ) *pline += 040; *plc++ = *pline++; } *plc = 0; /* Null terminate the output string */ /* parser() */ psym = (struct symbol *)menstk[menptr]; /* function table */ plc = &lc[0]; cp = psym->spel; do { if( strcmp( plc, cp ) == 0 ) goto pdon3; /* following unary minus is possible */ ++psym; cp = psym->spel; } while( *cp != '\0' ); /* psym = (struct symbol *)&indtbl[0]; */ /* indirect symbol table */ pvfs.pvar = &indtbl[0]; psym = pvfs.psym; plc = &lc[0]; cp = psym->spel; do { if( strcmp( plc, cp ) == 0 ) goto pdon2; ++psym; cp = psym->spel; } while( *cp != '\0' ); pdon0: pline = line; /* scrub line if illegal symbol */ goto pdon2; pdon1: ++pline; if( (psym->attrib & 0xf) == RPAREN ) pdon2: uposs = 0; else pdon3: uposs = 1; interl = pline; return( psym ); } /* end of parser */
/* * Handle initial connection protocol. */ static int do_tftp(struct testcase *test, struct tftphdr *tp, ssize_t size) { char *cp; int first = 1, ecode; struct formats *pf; char *filename, *mode = NULL; int error; FILE *server; #ifdef USE_WINSOCK DWORD recvtimeout, recvtimeoutbak; #endif /* Open request dump file. */ server = fopen(REQUEST_DUMP, "ab"); if(!server) { error = errno; logmsg("fopen() failed with error: %d %s", error, strerror(error)); logmsg("Error opening file: %s", REQUEST_DUMP); return -1; } /* store input protocol */ fprintf(server, "opcode: %x\n", tp->th_opcode); cp = (char *)&tp->th_stuff; filename = cp; again: while (cp < &buf.storage[size]) { if (*cp == '\0') break; cp++; } if (*cp) { nak(EBADOP); fclose(server); return 3; } if (first) { mode = ++cp; first = 0; goto again; } /* store input protocol */ fprintf(server, "filename: %s\n", filename); for (cp = mode; cp && *cp; cp++) if(ISUPPER(*cp)) *cp = (char)tolower((int)*cp); /* store input protocol */ fprintf(server, "mode: %s\n", mode); fclose(server); for (pf = formata; pf->f_mode; pf++) if (strcmp(pf->f_mode, mode) == 0) break; if (!pf->f_mode) { nak(EBADOP); return 2; } ecode = validate_access(test, filename, tp->th_opcode); if (ecode) { nak(ecode); return 1; } #ifdef USE_WINSOCK recvtimeout = sizeof(recvtimeoutbak); getsockopt(peer, SOL_SOCKET, SO_RCVTIMEO, (char*)&recvtimeoutbak, (int*)&recvtimeout); recvtimeout = TIMEOUT*1000; setsockopt(peer, SOL_SOCKET, SO_RCVTIMEO, (const char*)&recvtimeout, sizeof(recvtimeout)); #endif if (tp->th_opcode == opcode_WRQ) recvtftp(test, pf); else sendtftp(test, pf); #ifdef USE_WINSOCK recvtimeout = recvtimeoutbak; setsockopt(peer, SOL_SOCKET, SO_RCVTIMEO, (const char*)&recvtimeout, sizeof(recvtimeout)); #endif return 0; }
static int domatch(const uchar *p, const uchar *text) { int matched, special; uchar ch, prev; #ifdef WILD_TEST_ITERATIONS wildmatch_iteration_count++; #endif for ( ; (ch = *p) != '\0'; text++, p++) { if (*text == '\0' && ch != '*') return FALSE; switch (ch) { case '\\': /* Literal match with following character. Note that the test * in "default" handles the p[1] == '\0' failure case. */ ch = *++p; /* FALLTHROUGH */ default: if (*text != ch) return FALSE; continue; case '?': /* Match anything but '/'. */ if (*text == '/') return FALSE; continue; case '*': if (*++p == '*') { while (*++p == '*') {} special = TRUE; } else special = FALSE; if (*p == '\0') { /* Trailing "**" matches everything. Trailing "*" matches * only if there are no more slash characters. */ return special? TRUE : strchr((char*)text, '/') == NULL; } for ( ; *text; text++) { if ((matched = domatch(p, text)) != FALSE) { if (!special || matched != ABORT_TO_STARSTAR) return matched; } else if (!special && *text == '/') return ABORT_TO_STARSTAR; } return ABORT_ALL; case '[': ch = *++p; #ifdef NEGATE_CLASS2 if (ch == NEGATE_CLASS2) ch = NEGATE_CLASS; #endif /* Assign literal TRUE/FALSE because of "matched" comparison. */ special = ch == NEGATE_CLASS? TRUE : FALSE; if (special) { /* Inverted character class. */ ch = *++p; } prev = 0; matched = FALSE; do { if (!ch) return ABORT_ALL; if (ch == '\\') { ch = *++p; if (!ch) return ABORT_ALL; if (*text == ch) matched = TRUE; } else if (ch == '-' && prev && p[1] && p[1] != ']') { ch = *++p; if (ch == '\\') { ch = *++p; if (!ch) return ABORT_ALL; } if (*text <= ch && *text >= prev) matched = TRUE; ch = 0; /* This makes "prev" get set to 0. */ } else if (ch == '[' && p[1] == ':') { const uchar *s; int i; for (s = p += 2; (ch = *p) && ch != ']'; p++) {} if (!ch) return ABORT_ALL; i = p - s - 1; if (i < 0 || p[-1] != ':') { /* Didn't find ":]", so treat like a normal set. */ p = s - 2; ch = '['; if (*text == ch) matched = TRUE; continue; } if (CC_EQ(s,i, "alnum")) { if (ISALNUM(*text)) matched = TRUE; } else if (CC_EQ(s,i, "alpha")) { if (ISALPHA(*text)) matched = TRUE; } else if (CC_EQ(s,i, "blank")) { if (ISBLANK(*text)) matched = TRUE; } else if (CC_EQ(s,i, "cntrl")) { if (ISCNTRL(*text)) matched = TRUE; } else if (CC_EQ(s,i, "digit")) { if (ISDIGIT(*text)) matched = TRUE; } else if (CC_EQ(s,i, "graph")) { if (ISGRAPH(*text)) matched = TRUE; } else if (CC_EQ(s,i, "lower")) { if (ISLOWER(*text)) matched = TRUE; } else if (CC_EQ(s,i, "print")) { if (ISPRINT(*text)) matched = TRUE; } else if (CC_EQ(s,i, "punct")) { if (ISPUNCT(*text)) matched = TRUE; } else if (CC_EQ(s,i, "space")) { if (ISSPACE(*text)) matched = TRUE; } else if (CC_EQ(s,i, "upper")) { if (ISUPPER(*text)) matched = TRUE; } else if (CC_EQ(s,i, "xdigit")) { if (ISXDIGIT(*text)) matched = TRUE; } else /* malformed [:class:] string */ return ABORT_ALL; ch = 0; /* This makes "prev" get set to 0. */ } else if (*text == ch) matched = TRUE; } while (prev = ch, (ch = *++p) != ']'); if (matched == special || *text == '/') return FALSE; continue; } } return *text == '\0'; }
static int internal_function FCT (const CHAR *pattern, const CHAR *string, const CHAR *string_end, bool no_leading_period, int flags) { register const CHAR *p = pattern, *n = string; register UCHAR c; #ifdef _LIBC # if WIDE_CHAR_VERSION const char *collseq = (const char *) _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC); # else const UCHAR *collseq = (const UCHAR *) _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQMB); # endif #endif while ((c = *p++) != L('\0')) { bool new_no_leading_period = false; c = FOLD (c); switch (c) { case L('?'): if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') { int res; res = EXT (c, p, n, string_end, no_leading_period, flags); if (res != -1) return res; } if (n == string_end) return FNM_NOMATCH; else if (*n == L('/') && (flags & FNM_FILE_NAME)) return FNM_NOMATCH; else if (*n == L('.') && no_leading_period) return FNM_NOMATCH; break; case L('\\'): if (!(flags & FNM_NOESCAPE)) { c = *p++; if (c == L('\0')) /* Trailing \ loses. */ return FNM_NOMATCH; c = FOLD (c); } if (n == string_end || FOLD ((UCHAR) *n) != c) return FNM_NOMATCH; break; case L('*'): if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') { int res; res = EXT (c, p, n, string_end, no_leading_period, flags); if (res != -1) return res; } if (n != string_end && *n == L('.') && no_leading_period) return FNM_NOMATCH; for (c = *p++; c == L('?') || c == L('*'); c = *p++) { if (*p == L('(') && (flags & FNM_EXTMATCH) != 0) { const CHAR *endp = END (p); if (endp != p) { /* This is a pattern. Skip over it. */ p = endp; continue; } } if (c == L('?')) { /* A ? needs to match one character. */ if (n == string_end) /* There isn't another character; no match. */ return FNM_NOMATCH; else if (*n == L('/') && __builtin_expect (flags & FNM_FILE_NAME, 0)) /* A slash does not match a wildcard under FNM_FILE_NAME. */ return FNM_NOMATCH; else /* One character of the string is consumed in matching this ? wildcard, so *??? won't match if there are less than three characters. */ ++n; } } if (c == L('\0')) /* The wildcard(s) is/are the last element of the pattern. If the name is a file name and contains another slash this means it cannot match, unless the FNM_LEADING_DIR flag is set. */ { int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH; if (flags & FNM_FILE_NAME) { if (flags & FNM_LEADING_DIR) result = 0; else { if (MEMCHR (n, L('/'), string_end - n) == NULL) result = 0; } } return result; } else { const CHAR *endp; endp = MEMCHR (n, (flags & FNM_FILE_NAME) ? L('/') : L('\0'), string_end - n); if (endp == NULL) endp = string_end; if (c == L('[') || (__builtin_expect (flags & FNM_EXTMATCH, 0) != 0 && (c == L('@') || c == L('+') || c == L('!')) && *p == L('('))) { int flags2 = ((flags & FNM_FILE_NAME) ? flags : (flags & ~FNM_PERIOD)); bool no_leading_period2 = no_leading_period; for (--p; n < endp; ++n, no_leading_period2 = false) if (FCT (p, n, string_end, no_leading_period2, flags2) == 0) return 0; } else if (c == L('/') && (flags & FNM_FILE_NAME)) { while (n < string_end && *n != L('/')) ++n; if (n < string_end && *n == L('/') && (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags) == 0)) return 0; } else { int flags2 = ((flags & FNM_FILE_NAME) ? flags : (flags & ~FNM_PERIOD)); int no_leading_period2 = no_leading_period; if (c == L('\\') && !(flags & FNM_NOESCAPE)) c = *p; c = FOLD (c); for (--p; n < endp; ++n, no_leading_period2 = false) if (FOLD ((UCHAR) *n) == c && (FCT (p, n, string_end, no_leading_period2, flags2) == 0)) return 0; } } /* If we come here no match is possible with the wildcard. */ return FNM_NOMATCH; case L('['): { /* Nonzero if the sense of the character class is inverted. */ register bool not; CHAR cold; UCHAR fn; if (posixly_correct == 0) posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; if (n == string_end) return FNM_NOMATCH; if (*n == L('.') && no_leading_period) return FNM_NOMATCH; if (*n == L('/') && (flags & FNM_FILE_NAME)) /* `/' cannot be matched. */ return FNM_NOMATCH; not = (*p == L('!') || (posixly_correct < 0 && *p == L('^'))); if (not) ++p; fn = FOLD ((UCHAR) *n); c = *p++; for (;;) { if (!(flags & FNM_NOESCAPE) && c == L('\\')) { if (*p == L('\0')) return FNM_NOMATCH; c = FOLD ((UCHAR) *p); ++p; if (c == fn) goto matched; } else if (c == L('[') && *p == L(':')) { /* Leave room for the null. */ CHAR str[CHAR_CLASS_MAX_LENGTH + 1]; size_t c1 = 0; #if defined _LIBC || WIDE_CHAR_SUPPORT wctype_t wt; #endif const CHAR *startp = p; for (;;) { if (c1 == CHAR_CLASS_MAX_LENGTH) /* The name is too long and therefore the pattern is ill-formed. */ return FNM_NOMATCH; c = *++p; if (c == L(':') && p[1] == L(']')) { p += 2; break; } if (c < L('a') || c >= L('z')) { /* This cannot possibly be a character class name. Match it as a normal range. */ p = startp; c = L('['); goto normal_bracket; } str[c1++] = c; } str[c1] = L('\0'); #if defined _LIBC || WIDE_CHAR_SUPPORT wt = IS_CHAR_CLASS (str); if (wt == 0) /* Invalid character class name. */ return FNM_NOMATCH; # if defined _LIBC && ! WIDE_CHAR_VERSION /* The following code is glibc specific but does there a good job in speeding up the code since we can avoid the btowc() call. */ if (_ISCTYPE ((UCHAR) *n, wt)) goto matched; # else if (ISWCTYPE (BTOWC ((UCHAR) *n), wt)) goto matched; # endif #else if ((STREQ (str, L("alnum")) && ISALNUM ((UCHAR) *n)) || (STREQ (str, L("alpha")) && ISALPHA ((UCHAR) *n)) || (STREQ (str, L("blank")) && ISBLANK ((UCHAR) *n)) || (STREQ (str, L("cntrl")) && ISCNTRL ((UCHAR) *n)) || (STREQ (str, L("digit")) && ISDIGIT ((UCHAR) *n)) || (STREQ (str, L("graph")) && ISGRAPH ((UCHAR) *n)) || (STREQ (str, L("lower")) && ISLOWER ((UCHAR) *n)) || (STREQ (str, L("print")) && ISPRINT ((UCHAR) *n)) || (STREQ (str, L("punct")) && ISPUNCT ((UCHAR) *n)) || (STREQ (str, L("space")) && ISSPACE ((UCHAR) *n)) || (STREQ (str, L("upper")) && ISUPPER ((UCHAR) *n)) || (STREQ (str, L("xdigit")) && ISXDIGIT ((UCHAR) *n))) goto matched; #endif c = *p++; } #ifdef _LIBC else if (c == L('[') && *p == L('=')) { UCHAR str[1]; uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); const CHAR *startp = p; c = *++p; if (c == L('\0')) { p = startp; c = L('['); goto normal_bracket; } str[0] = c; c = *++p; if (c != L('=') || p[1] != L(']')) { p = startp; c = L('['); goto normal_bracket; } p += 2; if (nrules == 0) { if ((UCHAR) *n == str[0]) goto matched; } else { const int32_t *table; # if WIDE_CHAR_VERSION const int32_t *weights; const int32_t *extra; # else const unsigned char *weights; const unsigned char *extra; # endif const int32_t *indirect; int32_t idx; const UCHAR *cp = (const UCHAR *) str; /* This #include defines a local function! */ # if WIDE_CHAR_VERSION # include <locale/weightwc.h> # else # include <locale/weight.h> # endif # if WIDE_CHAR_VERSION table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC); weights = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC); extra = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC); indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC); # else table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); weights = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); indirect = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); # endif idx = findidx (&cp); if (idx != 0) { /* We found a table entry. Now see whether the character we are currently at has the same equivalance class value. */ int len = weights[idx]; int32_t idx2; const UCHAR *np = (const UCHAR *) n; idx2 = findidx (&np); if (idx2 != 0 && len == weights[idx2]) { int cnt = 0; while (cnt < len && (weights[idx + 1 + cnt] == weights[idx2 + 1 + cnt])) ++cnt; if (cnt == len) goto matched; } } } c = *p++; } #endif else if (c == L('\0')) /* [ (unterminated) loses. */ return FNM_NOMATCH; else { bool is_range = false; #ifdef _LIBC bool is_seqval = false; if (c == L('[') && *p == L('.')) { uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); const CHAR *startp = p; size_t c1 = 0; while (1) { c = *++p; if (c == L('.') && p[1] == L(']')) { p += 2; break; } if (c == '\0') return FNM_NOMATCH; ++c1; } /* We have to handling the symbols differently in ranges since then the collation sequence is important. */ is_range = *p == L('-') && p[1] != L('\0'); if (nrules == 0) { /* There are no names defined in the collation data. Therefore we only accept the trivial names consisting of the character itself. */ if (c1 != 1) return FNM_NOMATCH; if (!is_range && *n == startp[1]) goto matched; cold = startp[1]; c = *p++; } else { int32_t table_size; const int32_t *symb_table; # ifdef WIDE_CHAR_VERSION char str[c1]; size_t strcnt; # else # define str (startp + 1) # endif const unsigned char *extra; int32_t idx; int32_t elem; int32_t second; int32_t hash; # ifdef WIDE_CHAR_VERSION /* We have to convert the name to a single-byte string. This is possible since the names consist of ASCII characters and the internal representation is UCS4. */ for (strcnt = 0; strcnt < c1; ++strcnt) str[strcnt] = startp[1 + strcnt]; # endif table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB); symb_table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_TABLEMB); extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); /* Locate the character in the hashing table. */ hash = elem_hash (str, c1); idx = 0; elem = hash % table_size; second = hash % (table_size - 2); while (symb_table[2 * elem] != 0) { /* First compare the hashing value. */ if (symb_table[2 * elem] == hash && c1 == extra[symb_table[2 * elem + 1]] && memcmp (str, &extra[symb_table[2 * elem + 1] + 1], c1) == 0) { /* Yep, this is the entry. */ idx = symb_table[2 * elem + 1]; idx += 1 + extra[idx]; break; } /* Next entry. */ elem += second; } if (symb_table[2 * elem] != 0) { /* Compare the byte sequence but only if this is not part of a range. */ # ifdef WIDE_CHAR_VERSION int32_t *wextra; idx += 1 + extra[idx]; /* Adjust for the alignment. */ idx = (idx + 3) & ~3; wextra = (int32_t *) &extra[idx + 4]; # endif if (! is_range) { # ifdef WIDE_CHAR_VERSION for (c1 = 0; (int32_t) c1 < wextra[idx]; ++c1) if (n[c1] != wextra[1 + c1]) break; if ((int32_t) c1 == wextra[idx]) goto matched; # else for (c1 = 0; c1 < extra[idx]; ++c1) if (n[c1] != extra[1 + c1]) break; if (c1 == extra[idx]) goto matched; # endif } /* Get the collation sequence value. */ is_seqval = true; # ifdef WIDE_CHAR_VERSION cold = wextra[1 + wextra[idx]]; # else /* Adjust for the alignment. */ idx += 1 + extra[idx]; idx = (idx + 3) & ~4; cold = *((int32_t *) &extra[idx]); # endif c = *p++; } else if (c1 == 1) { /* No valid character. Match it as a single byte. */ if (!is_range && *n == str[0]) goto matched; cold = str[0]; c = *p++; } else return FNM_NOMATCH; } } else # undef str #endif { c = FOLD (c); normal_bracket: /* We have to handling the symbols differently in ranges since then the collation sequence is important. */ is_range = (*p == L('-') && p[1] != L('\0') && p[1] != L(']')); if (!is_range && c == fn) goto matched; cold = c; c = *p++; } if (c == L('-') && *p != L(']')) { #if _LIBC /* We have to find the collation sequence value for C. Collation sequence is nothing we can regularly access. The sequence value is defined by the order in which the definitions of the collation values for the various characters appear in the source file. A strange concept, nowhere documented. */ uint32_t fcollseq; uint32_t lcollseq; UCHAR cend = *p++; # ifdef WIDE_CHAR_VERSION /* Search in the `names' array for the characters. */ fcollseq = __collseq_table_lookup (collseq, fn); if (fcollseq == ~((uint32_t) 0)) /* XXX We don't know anything about the character we are supposed to match. This means we are failing. */ goto range_not_matched; if (is_seqval) lcollseq = cold; else lcollseq = __collseq_table_lookup (collseq, cold); # else fcollseq = collseq[fn]; lcollseq = is_seqval ? cold : collseq[(UCHAR) cold]; # endif is_seqval = false; if (cend == L('[') && *p == L('.')) { uint32_t nrules = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); const CHAR *startp = p; size_t c1 = 0; while (1) { c = *++p; if (c == L('.') && p[1] == L(']')) { p += 2; break; } if (c == '\0') return FNM_NOMATCH; ++c1; } if (nrules == 0) { /* There are no names defined in the collation data. Therefore we only accept the trivial names consisting of the character itself. */ if (c1 != 1) return FNM_NOMATCH; cend = startp[1]; } else { int32_t table_size; const int32_t *symb_table; # ifdef WIDE_CHAR_VERSION char str[c1]; size_t strcnt; # else # define str (startp + 1) # endif const unsigned char *extra; int32_t idx; int32_t elem; int32_t second; int32_t hash; # ifdef WIDE_CHAR_VERSION /* We have to convert the name to a single-byte string. This is possible since the names consist of ASCII characters and the internal representation is UCS4. */ for (strcnt = 0; strcnt < c1; ++strcnt) str[strcnt] = startp[1 + strcnt]; # endif table_size = _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_SYMB_HASH_SIZEMB); symb_table = (const int32_t *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_TABLEMB); extra = (const unsigned char *) _NL_CURRENT (LC_COLLATE, _NL_COLLATE_SYMB_EXTRAMB); /* Locate the character in the hashing table. */ hash = elem_hash (str, c1); idx = 0; elem = hash % table_size; second = hash % (table_size - 2); while (symb_table[2 * elem] != 0) { /* First compare the hashing value. */ if (symb_table[2 * elem] == hash && (c1 == extra[symb_table[2 * elem + 1]]) && memcmp (str, &extra[symb_table[2 * elem + 1] + 1], c1) == 0) { /* Yep, this is the entry. */ idx = symb_table[2 * elem + 1]; idx += 1 + extra[idx]; break; } /* Next entry. */ elem += second; } if (symb_table[2 * elem] != 0) { /* Compare the byte sequence but only if this is not part of a range. */ # ifdef WIDE_CHAR_VERSION int32_t *wextra; idx += 1 + extra[idx]; /* Adjust for the alignment. */ idx = (idx + 3) & ~4; wextra = (int32_t *) &extra[idx + 4]; # endif /* Get the collation sequence value. */ is_seqval = true; # ifdef WIDE_CHAR_VERSION cend = wextra[1 + wextra[idx]]; # else /* Adjust for the alignment. */ idx += 1 + extra[idx]; idx = (idx + 3) & ~4; cend = *((int32_t *) &extra[idx]); # endif } else if (symb_table[2 * elem] != 0 && c1 == 1) { cend = str[0]; c = *p++; } else return FNM_NOMATCH; } # undef str } else { if (!(flags & FNM_NOESCAPE) && cend == L('\\')) cend = *p++; if (cend == L('\0')) return FNM_NOMATCH; cend = FOLD (cend); } /* XXX It is not entirely clear to me how to handle characters which are not mentioned in the collation specification. */ if ( # ifdef WIDE_CHAR_VERSION lcollseq == 0xffffffff || # endif lcollseq <= fcollseq) { /* We have to look at the upper bound. */ uint32_t hcollseq; if (is_seqval) hcollseq = cend; else { # ifdef WIDE_CHAR_VERSION hcollseq = __collseq_table_lookup (collseq, cend); if (hcollseq == ~((uint32_t) 0)) { /* Hum, no information about the upper bound. The matching succeeds if the lower bound is matched exactly. */ if (lcollseq != fcollseq) goto range_not_matched; goto matched; } # else hcollseq = collseq[cend]; # endif } if (lcollseq <= hcollseq && fcollseq <= hcollseq) goto matched; } # ifdef WIDE_CHAR_VERSION range_not_matched: # endif #else /* We use a boring value comparison of the character values. This is better than comparing using `strcoll' since the latter would have surprising and sometimes fatal consequences. */ UCHAR cend = *p++; if (!(flags & FNM_NOESCAPE) && cend == L('\\')) cend = *p++; if (cend == L('\0')) return FNM_NOMATCH; /* It is a range. */ if (cold <= fn && fn <= cend) goto matched; #endif c = *p++; } } if (c == L(']')) break; } if (!not) return FNM_NOMATCH; break; matched: /* Skip the rest of the [...] that already matched. */ do { ignore_next: c = *p++; if (c == L('\0')) /* [... (unterminated) loses. */ return FNM_NOMATCH; if (!(flags & FNM_NOESCAPE) && c == L('\\')) { if (*p == L('\0')) return FNM_NOMATCH; /* XXX 1003.2d11 is unclear if this is right. */ ++p; } else if (c == L('[') && *p == L(':')) { int c1 = 0; const CHAR *startp = p; while (1) { c = *++p; if (++c1 == CHAR_CLASS_MAX_LENGTH) return FNM_NOMATCH; if (*p == L(':') && p[1] == L(']')) break; if (c < L('a') || c >= L('z')) { p = startp; goto ignore_next; } } p += 2; c = *p++; } else if (c == L('[') && *p == L('=')) { c = *++p; if (c == L('\0')) return FNM_NOMATCH; c = *++p; if (c != L('=') || p[1] != L(']')) return FNM_NOMATCH; p += 2; c = *p++; } else if (c == L('[') && *p == L('.')) { ++p; while (1) { c = *++p; if (c == '\0') return FNM_NOMATCH; if (*p == L('.') && p[1] == L(']')) break; } p += 2; c = *p++; } } while (c != L(']')); if (not) return FNM_NOMATCH; } break; case L('+'): case L('@'): case L('!'): if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') { int res; res = EXT (c, p, n, string_end, no_leading_period, flags); if (res != -1) return res; } goto normal_match; case L('/'): if (NO_LEADING_PERIOD (flags)) { if (n == string_end || c != (UCHAR) *n) return FNM_NOMATCH; new_no_leading_period = true; break; } /* FALLTHROUGH */ default: normal_match: if (n == string_end || c != FOLD ((UCHAR) *n)) return FNM_NOMATCH; } no_leading_period = new_no_leading_period; ++n; } if (n == string_end) return 0; if ((flags & FNM_LEADING_DIR) && n != string_end && *n == L('/')) /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ return 0; return FNM_NOMATCH; }
/* ARGSUSED */ int upperword(int f, int n) { int c, s; RSIZE size; if ((s = checkdirty(curbp)) != TRUE) return (s); if (curbp->b_flag & BFREADONLY) { ewprintf("Buffer is read-only"); return (FALSE); } if (n < 0) return (FALSE); while (n--) { while (inword() == FALSE) { if (forwchar(FFRAND, 1) == FALSE) return (TRUE); } size = countfword(); undo_add_change(curwp->w_dotp, curwp->w_doto, size); while (inword() != FALSE) { c = lgetc(curwp->w_dotp, curwp->w_doto); #ifndef MRUBY if (ISLOWER(c) != FALSE) { c = TOUPPER(c); #else if (MG_ISLOWER(c) != FALSE) { c = MG_TOUPPER(c); #endif /* !MRUBY */ lputc(curwp->w_dotp, curwp->w_doto, c); lchange(WFFULL); } if (forwchar(FFRAND, 1) == FALSE) return (TRUE); } } return (TRUE); } /* * Move the cursor forward by the specified number of words. As you move * convert characters to lower case. */ /* ARGSUSED */ int lowerword(int f, int n) { int c, s; RSIZE size; if ((s = checkdirty(curbp)) != TRUE) return (s); if (curbp->b_flag & BFREADONLY) { ewprintf("Buffer is read-only"); return (FALSE); } if (n < 0) return (FALSE); while (n--) { while (inword() == FALSE) { if (forwchar(FFRAND, 1) == FALSE) return (TRUE); } size = countfword(); undo_add_change(curwp->w_dotp, curwp->w_doto, size); while (inword() != FALSE) { c = lgetc(curwp->w_dotp, curwp->w_doto); #ifndef MRUBY if (ISUPPER(c) != FALSE) { c = TOLOWER(c); #else if (MG_ISUPPER(c) != FALSE) { c = MG_TOLOWER(c); #endif /* !MRUBY */ lputc(curwp->w_dotp, curwp->w_doto, c); lchange(WFFULL); } if (forwchar(FFRAND, 1) == FALSE) return (TRUE); } } return (TRUE); } /* * Move the cursor forward by the specified number of words. As you move * convert the first character of the word to upper case, and subsequent * characters to lower case. Error if you try to move past the end of the * buffer. */ /* ARGSUSED */ int capword(int f, int n) { int c, s; RSIZE size; if ((s = checkdirty(curbp)) != TRUE) return (s); if (curbp->b_flag & BFREADONLY) { ewprintf("Buffer is read-only"); return (FALSE); } if (n < 0) return (FALSE); while (n--) { while (inword() == FALSE) { if (forwchar(FFRAND, 1) == FALSE) return (TRUE); } size = countfword(); undo_add_change(curwp->w_dotp, curwp->w_doto, size); if (inword() != FALSE) { c = lgetc(curwp->w_dotp, curwp->w_doto); #ifndef MRUBY if (ISLOWER(c) != FALSE) { c = TOUPPER(c); #else if (MG_ISLOWER(c) != FALSE) { c = MG_TOUPPER(c); #endif /* !MRUBY */ lputc(curwp->w_dotp, curwp->w_doto, c); lchange(WFFULL); } if (forwchar(FFRAND, 1) == FALSE) return (TRUE); while (inword() != FALSE) { c = lgetc(curwp->w_dotp, curwp->w_doto); #ifndef MRUBY if (ISUPPER(c) != FALSE) { c = TOLOWER(c); #else if (MG_ISUPPER(c) != FALSE) { c = MG_TOLOWER(c); #endif /* !MRUBY */ lputc(curwp->w_dotp, curwp->w_doto, c); lchange(WFFULL); } if (forwchar(FFRAND, 1) == FALSE) return (TRUE); } } } return (TRUE); } /* * Count characters in word, from current position */ RSIZE countfword() { RSIZE size; struct line *dotp; int doto; dotp = curwp->w_dotp; doto = curwp->w_doto; size = 0; while (inword() != FALSE) { if (forwchar(FFRAND, 1) == FALSE) /* hit the end of the buffer */ goto out; ++size; } out: curwp->w_dotp = dotp; curwp->w_doto = doto; return (size); } /* * Kill forward by "n" words. */ /* ARGSUSED */ int delfword(int f, int n) { RSIZE size; struct line *dotp; int doto; int s; if ((s = checkdirty(curbp)) != TRUE) return (s); if (curbp->b_flag & BFREADONLY) { ewprintf("Buffer is read-only"); return (FALSE); } if (n < 0) return (FALSE); /* purge kill buffer */ if ((lastflag & CFKILL) == 0) kdelete(); thisflag |= CFKILL; dotp = curwp->w_dotp; doto = curwp->w_doto; size = 0; while (n--) { while (inword() == FALSE) { if (forwchar(FFRAND, 1) == FALSE) /* hit the end of the buffer */ goto out; ++size; } while (inword() != FALSE) { if (forwchar(FFRAND, 1) == FALSE) /* hit the end of the buffer */ goto out; ++size; } } out: curwp->w_dotp = dotp; curwp->w_doto = doto; return (ldelete(size, KFORW)); } /* * Kill backwards by "n" words. The rules for success and failure are now * different, to prevent strange behavior at the start of the buffer. The * command only fails if something goes wrong with the actual delete of the * characters. It is successful even if no characters are deleted, or if you * say delete 5 words, and there are only 4 words left. I considered making * the first call to "backchar" special, but decided that that would just be * weird. Normally this is bound to "M-Rubout" and to "M-Backspace". */ /* ARGSUSED */ int delbword(int f, int n) { RSIZE size; int s; if ((s = checkdirty(curbp)) != TRUE) return (s); if (curbp->b_flag & BFREADONLY) { ewprintf("Buffer is read-only"); return (FALSE); } if (n < 0) return (FALSE); /* purge kill buffer */ if ((lastflag & CFKILL) == 0) kdelete(); thisflag |= CFKILL; if (backchar(FFRAND, 1) == FALSE) /* hit buffer start */ return (TRUE); /* one deleted */ size = 1; while (n--) { while (inword() == FALSE) { if (backchar(FFRAND, 1) == FALSE) /* hit buffer start */ goto out; ++size; } while (inword() != FALSE) { if (backchar(FFRAND, 1) == FALSE) /* hit buffer start */ goto out; ++size; } } if (forwchar(FFRAND, 1) == FALSE) return (FALSE); /* undo assumed delete */ --size; out: return (ldelete(size, KBACK)); }
/* returns 1 (true) if pattern is OK, 0 if is bad ("p" is pattern pointer) */ static int setcharset(unsigned char **p, unsigned char *charset) { setcharset_state state = CURLFNM_SCHS_DEFAULT; unsigned char rangestart = 0; unsigned char lastchar = 0; bool something_found = FALSE; unsigned char c; for(;;) { c = **p; switch(state) { case CURLFNM_SCHS_DEFAULT: if(ISALNUM(c)) { /* ASCII value */ rangestart = c; charset[c] = 1; (*p)++; state = CURLFNM_SCHS_MAYRANGE; something_found = TRUE; } else if(c == ']') { if(something_found) return SETCHARSET_OK; else something_found = TRUE; state = CURLFNM_SCHS_RIGHTBR; charset[c] = 1; (*p)++; } else if(c == '[') { char c2 = *((*p)+1); if(c2 == ':') { /* there has to be a keyword */ (*p) += 2; if(parsekeyword(p, charset)) { state = CURLFNM_SCHS_DEFAULT; } else return SETCHARSET_FAIL; } else { charset[c] = 1; (*p)++; } something_found = TRUE; } else if(c == '?' || c == '*') { something_found = TRUE; charset[c] = 1; (*p)++; } else if(c == '^' || c == '!') { if(!something_found) { if(charset[CURLFNM_NEGATE]) { charset[c] = 1; something_found = TRUE; } else charset[CURLFNM_NEGATE] = 1; /* negate charset */ } else charset[c] = 1; (*p)++; } else if(c == '\\') { c = *(++(*p)); if(ISPRINT((c))) { something_found = TRUE; state = CURLFNM_SCHS_MAYRANGE; charset[c] = 1; rangestart = c; (*p)++; } else return SETCHARSET_FAIL; } else if(c == '\0') { return SETCHARSET_FAIL; } else { charset[c] = 1; (*p)++; something_found = TRUE; } break; case CURLFNM_SCHS_MAYRANGE: if(c == '-') { charset[c] = 1; (*p)++; lastchar = '-'; state = CURLFNM_SCHS_MAYRANGE2; } else if(c == '[') { state = CURLFNM_SCHS_DEFAULT; } else if(ISALNUM(c)) { charset[c] = 1; (*p)++; } else if(c == '\\') { c = *(++(*p)); if(ISPRINT(c)) { charset[c] = 1; (*p)++; } else return SETCHARSET_FAIL; } else if(c == ']') { return SETCHARSET_OK; } else return SETCHARSET_FAIL; break; case CURLFNM_SCHS_MAYRANGE2: if(c == '\\') { c = *(++(*p)); if(!ISPRINT(c)) return SETCHARSET_FAIL; } if(c == ']') { return SETCHARSET_OK; } else if(c == '\\') { c = *(++(*p)); if(ISPRINT(c)) { charset[c] = 1; state = CURLFNM_SCHS_DEFAULT; (*p)++; } else return SETCHARSET_FAIL; } if(c >= rangestart) { if((ISLOWER(c) && ISLOWER(rangestart)) || (ISDIGIT(c) && ISDIGIT(rangestart)) || (ISUPPER(c) && ISUPPER(rangestart))) { charset[lastchar] = 0; rangestart++; while(rangestart++ <= c) charset[rangestart-1] = 1; (*p)++; state = CURLFNM_SCHS_DEFAULT; } else return SETCHARSET_FAIL; } break; case CURLFNM_SCHS_RIGHTBR: if(c == '[') { state = CURLFNM_SCHS_RIGHTBRLEFTBR; charset[c] = 1; (*p)++; } else if(c == ']') { return SETCHARSET_OK; } else if(c == '\0') { return SETCHARSET_FAIL; } else if(ISPRINT(c)) { charset[c] = 1; (*p)++; state = CURLFNM_SCHS_DEFAULT; } else /* used 'goto fail' instead of 'return SETCHARSET_FAIL' to avoid a * nonsense warning 'statement not reached' at end of the fnc when * compiling on Solaris */ goto fail; break; case CURLFNM_SCHS_RIGHTBRLEFTBR: if(c == ']') { return SETCHARSET_OK; } else { state = CURLFNM_SCHS_DEFAULT; charset[c] = 1; (*p)++; } break; } } fail: return SETCHARSET_FAIL; }