📄 ckclib.c
字号:
char * cklibv = "C-Kermit library, 8.0.033, 16 Mar 2003";#define CKCLIB_C/* C K C L I B . C -- C-Kermit Library routines. *//* Author: Frank da Cruz <fdc@columbia.edu>, Columbia University Academic Information Systems, New York City. Copyright (C) 1999, 2004, Trustees of Columbia University in the City of New York. All rights reserved. See the C-Kermit COPYING.TXT file or the copyright text in the ckcmai.c module for disclaimer and permissions.*//* General-purpose, system/platform/compiler-independent routines for use by all modules. Many are replacements for commonly used C library functions that are not found on every platform, and/or that lack needed functionality (e.g. caseless string search/compare) or safety features. ckstrncpy() - Similar to strncpy() but different (see comments). ckstrncat() - Similar to strncat() but different (see comments). chartostr() - Converts a char to a string (self or ctrl char name). ckstrchr() - Portable strchr(). ckstrpbrk() - Portable strpbrk(). cklower() - Lowercase a string (in place). ckupper() - Uppercase a string (in place). ckindex() - Left or right index. ckstrstr() - Portable strstr(). ckitoa() - Converts int to string. ckuitoa() - Converts unsigned int to string. ckltoa() - Converts long to string. ckultoa() - Converts unsigned long to string. ckctoa() - Converts char to string. ckmakmsg() - Constructs a message from 4 source strings. ckmakxmsg() - Constructs a message from 12 source strings. ckmatch() - Pattern matching. ckmemcpy() - Portable memcpy(). ckrchar() - Rightmost character of a string. ckstrcmp() - Possibly caseless string comparison. ckstrpre() - Caseless string prefix comparison. sh_sort() - Sorts an array of strings, many options. brstrip() - Strips enclosing braces (and doublequotes). makelist() - Splits "{{item}{item}...}" into an array. makestr() - Careful malloc() front end. xmakestr() - ditto (see comments). ckradix() - Convert number radix (2-36). b8tob64() - Convert data to base 64. b64tob8() - Convert base 64 to data. chknum() - Checks if string is a (possibly signed) integer. rdigits() - Checks if string is composed only of decimal digits. isfloat() - Checks if string is a valid floating-point number. parnam() - Returns parity name string. hhmmss() - Converts seconds to hh:mm:ss string. lset() - Write fixed-length field left-adjusted into a record. rset() - Write fixed-length field right-adjusted into a record. ulongtohex() - Converts an unsigned long to a hex string. hextoulong() - Converts a hex string to an unsigned long. cksplit() - Splits a string into an array of words. Prototypes are in ckclib.h. Note: This module should not contain any extern declarations.*/#include "ckcsym.h"#include "ckcdeb.h"#include "ckcasc.h"/* Public variables */int dblquo = 1; /* Nonzero if doublequotes can be used for grouping */char *ccntab[] = { /* Names of ASCII (C0) control characters 0-31 */ "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL", "BS", "HT", "LF", "VT", "FF", "CR", "SO", "SI", "DLE", "DC1", "DC2", "DC3", "DC4", "NAK", "SYN", "ETB", "CAN", "EM", "SUB", "ESC", "FS", "GS", "RS", "US"};char *c1tab[] = { /* Names of ISO 6429 (C1) control characters 0-32 */ "XXX", "XXX", "BPH", "NBH", "IND", "NEL", "SSA", "ESA", "HTS", "HTJ", "VTS", "PLD", "PLU", "RI", "SS2", "SS3", "DCS", "PU1", "PU2", "STS", "CCH", "MW", "SPA", "EPA", "SOS", "XXX", "SCI", "CSI", "ST", "OSC", "PM", "APC", "NBS"};#define RXRESULT 127static char rxdigits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";static char rxresult[RXRESULT+1];/* C K S T R N C P Y *//* Copies a NUL-terminated string into a buffer whose total length is given, ensuring that the result is NUL-terminated even if it has to be truncated. Call with: dest = pointer to destination buffer src = pointer to source string len = length of destination buffer (the actual length, not one less). Returns: int, The number of bytes copied, 0 or more. NOTE: This is NOT a replacement for strncpy(): . strncpy() does not require its source string to be NUL-terminated. . strncpy() does not necessarily NUL-terminate its result. . strncpy() right-pads dest with NULs if it is longer than src. . strncpy() treats the length argument as the number of bytes to copy. . ckstrncpy() treats the length argument as the size of the dest buffer. . ckstrncpy() doesn't dump core if given NULL string pointers. . ckstrncpy() returns a number. Use ckstrncpy() when you want to: . Copy an entire string into a buffer without overrun. . Get the length of the string back. Use strncpy() when you want to: . Copy a piece of a string.*/int#ifdef CK_ANSICckstrncpy(char * dest, const char * src, int len)#elseckstrncpy(dest,src,len) char * dest, * src; int len;#endif /* CK_ANSIC */{ int i; if (len < 1 || !src || !dest) { /* Nothing or nowhere to copy */ if (dest) *dest = NUL; return(0); }#ifndef NOCKSTRNCPY for (i = 0; src[i] && (i < len-1); i++) /* Args OK, copy */ dest[i] = src[i]; dest[i] = NUL;#else i = strlen(src); if (i > len) i = len; strncpy(dest,src,i); dest[len] = NUL;#endif /* NOCKSTRNCPY */ return(i);}/* C K S T R N C A T *//* Appends a NUL-terminated string to a buffer whose total length is given, ensuring that the result is NUL-terminated even if it had to be truncated. Call with: dest = pointer to destination buffer containing a null-terminated string src = pointer to null-terminated source string len = length of destination buffer (the actual length, not one less). Returns: int, The number of bytes copied, 0 or more.*/int#ifdef CK_ANSICckstrncat(char * dest, const char * src, int len)#elseckstrncat(dest,src,len) char * dest, * src; int len;#endif /* CK_ANSIC */{ register int i, j;#ifdef NOCKSTRNCPY register char * s1, * s2;#endif /* NOCKSTRNCPY */ if (len < 1 || !src || !dest) { /* Nothing or nowhere to copy */ if (dest) *dest = NUL; return(0); }#ifndef NOCKSTRNCPY /* Args OK, copy */ for (i = 0, j = strlen(dest); src[i] && (i < len-j-1); i++) dest[i+j] = src[i]; dest[i+j] = NUL;#else j = 0; s1 = dest; while (*s1++) j++; /* j = strlen(dest); */ s1--; /* (back up over NUL) */ i = 0; s2 = src; while (*s2++) i++; /* i = strlen(src); */ if (i > (len-j)) i = len - j; if (i <= 0) return(0);#ifdef COMMENT strncpy(&dest[j],src,i);#else j = i; /* This should be a bit faster... */ s2 = src; /* depends on strcpy implementation; */ while ((*s1++ = *s2++) && j--) /* at least it shouldn't be slower. */ ; dest[len-1] = NUL; /* In case of early exit. */#endif /* COMMENT */#endif /* NOCKSTRNCPY */ return(i);}/* C K M A K M S G *//* Constructs a message from up to 4 pieces with length checking. Result is always NUL terminated. Call with: buf: Pointer to buffer for constructing message. len: Length of buffer. s1-s4: String pointers (can be NULL). Returns: 0: Nothing was copied. n: (positive number) n bytes copied, all args copied successfully. -n: n bytes were copied, destination buffer not big enough for all. Also see: ckmakxmsg() -- accepts 12 string args. ckitoa(), ckltoa(), ckctoa(), ckitox(), etc. Use ckmak[x]msg() plus ck?to?() as a safe replacement for sprintf().*/int#ifdef CK_ANSICckmakmsg(char * buf, int len, char *s1, char *s2, char *s3, char *s4)#else /* CK_ANSIC */ckmakmsg(buf,len,s1,s2,s3,s4) char *buf, *s1, *s2, *s3, *s4; int len;#endif /* CK_ANSIC */{ int i, n = 0, m = 0; char *s; char *p, *a[4]; if (!buf) return(n); /* No destination */ if (len < 1) return(n); /* No size */ s = buf; /* Point to destination */ a[0] = s1; a[1] = s2; a[2] = s3; a[3] = s4; /* Array of source strings */ for (i = 0; i < 4; i++) { /* Loop thru array */ p = a[i]; /* Point to this element */ if (p) { /* If pointer not null */ n = ckstrncpy(s,p,len); /* Copy safely */ m += n; /* Accumulate total */ if (p[n]) /* Didn't get whole thing? */ return(-m); /* return indicating buffer full */ len -= n; /* Deduct from space left */ s += n; /* Otherwise advance dest pointer */ } } return(m); /* Return total bytes copied */}/* C K M A K X M S G *//* Exactly like ckmakmsg(), but accepts 12 string arguments. */int#ifdef CK_ANSICckmakxmsg(char * buf, int len, char *s1, char *s2, char *s3, char *s4, char *s5, char *s6, char *s7, char *s8, char *s9, char *s10, char *s11, char *s12)#else /* CK_ANSIC */ckmakxmsg(buf,len,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s12) char *buf, *s1, *s2, *s3, *s4, *s5, *s6, *s7, *s8, *s9, *s10, *s11, *s12; int len;#endif /* CK_ANSIC */{ int i, n = 0, m = 0; char *s; char *p, *a[12]; if (!buf) return(n); /* No destination */ if (len < 1) return(n); /* No size */ s = buf; /* Point to destination */ a[0] = s1; a[1] = s2; a[2] = s3; a[3] = s4; /* Source-string array */ a[4] = s5; a[5] = s6; a[6] = s7; a[7] = s8; a[8] = s9; a[9] = s10; a[10] = s11; a[11] = s12; for (i = 0; i < 12; i++) { /* Loop thru array */ p = a[i]; /* Point to this element */ if (p) { /* If pointer not null */ n = ckstrncpy(s,p,len); /* Copy safely */ m += n; /* Accumulate total */ if (p[n]) /* Didn't get whole thing? */ return(-m); /* return indicating buffer full */ len -= n; /* Deduct from space left */ s += n; /* Otherwise advance dest pointer */ } } return(m); /* Return total bytes copied */}/* C H A R T O S T R *//* Converts a character to a string, interpreting controls. */char *chartostr(x) int x; { /* Call with char x */ static char buf[2]; /* Returns string pointer. */ if (x < 32) return(ccntab[x]); if (x == 127) return("DEL"); if (x > 127 && x < 161) return(c1tab[x - 128]); if (x == 0xAD) return("SHY"); buf[1] = NUL; buf[0] = (unsigned)(x & 0xff); return((char *)buf);}/* C K R C H A R *//* Returns the rightmost character of the given null-terminated string */intckrchar(s) char * s; { register CHAR c = '\0', *p; p = (CHAR *)s; if (!p) p = (CHAR *)""; /* Null pointer == empty string */ if (!*p) return(0); while (*p) /* Crawl to end of string */ c = *p++; return((unsigned)(c & 0xff)); /* Return final character */}/* C K S T R C H R *//* Replacement for strchr(), which is not universal. *//* Call with: s = pointer to string to look in. c = character to look for. Returns: NULL if c not found in s or upon any kind of error, or: pointer to first occurrence of c in s, searching from left to right.*/char *#ifdef CK_ANSICckstrchr(char * s, char c)#elseckstrchr(s,c) char *s, c;#endif /* CK_ANSIC *//* ckstrchr */ { if (!s) return(NULL); while (*s && *s != c) s++; return((*s == c) ? s : NULL);}/* C K S T R R C H R *//* Replacement for strrchr(), which is not universal. *//* Call with: s = pointer to string to look in. c = character to look for. Returns: NULL if c not found in s or upon any kind of error, or: pointer to first occurrence of c in s, searching from right to left.*/char *#ifdef CK_ANSICckstrrchr(char * s, char c)#elseckstrrchr(s,c) char *s, c;#endif /* CK_ANSIC *//* ckstrchr */ { char * s2 = NULL; if (!s) return(NULL); while (*s) { if (*s == c) s2 = s; s++; } return(s2);}/* C K S T R P B R K -- Portable replacement for strpbrk() *//* Returns pointer to first char in s1 that is also in s2, or NULL */char *ckstrpbrk(s1, s2) char * s1, * s2; { char c1, c2, * s3; if (!s1 || !s2) return(NULL); if (!*s1 || !*s2) return(NULL); while ((c1 = *s1++)) { s3 = s2; while ((c2 = *s3++)) { if (c2 == c1) return(s1-1); } } return(NULL);}/* C K L O W E R -- Lowercase a string IN PLACE *//* Returns the length of the string */intcklower(s) char *s; { int n = 0; if (!s) return(0); while (*s) { if (isupper(*s)) *s = (char) tolower(*s); s++, n++; } return(n);}/* C K U P P E R -- Uppercase a string IN PLACE *//* Returns the length of the string */intckupper(s) char *s; { int n = 0; if (!s) return(0); while (*s) { if (islower(*s)) *s = (char) toupper(*s); s++, n++; } return(n);}/* C K L T O A -- Long to string -- FOR DISCIPLINED USE ONLY */#define NUMBUF 1024static char numbuf[NUMBUF+32] = { NUL, NUL };static int numbp = 0;/* ckltoa() and ckitoa() are like atol() and atoi() in the reverse direction, returning a pointer to the string representation of the given number without the caller having to worry about allocating or defining a buffer first. They manage their own internal buffer, so successive calls return different pointers. However, to keep memory consumption from growing without bound, the buffer recycles itself. So after several hundred calls (depending on the size of the numbers), some of the earlier pointers might well find themselves referencing something different. Moral: You can't win in C. Therefore, these routines are intended mainly for generating numeric strings for short-term use, e.g. for passing numbers in string form as parameters to functions. For long-term use, the result must be copied to a safe place.*/char *#ifdef CK_ANSICckltoa(long n)#elseckltoa(n) long n;#endif /* CK_ANSIC *//* ckltoa */ { char buf[32]; /* Internal working buffer */ char * p, * s, * q; int k, x, len = 0, sign = 0; if (n < 0L) { /* Sign */ n = 0L - n; sign = 1; } buf[31] = NUL; for (k = 30; k > 0; k--) { /* Convert number to string */ x = n % 10L; buf[k] = x + '0'; n = n / 10L; if (!n) break; } if (sign) buf[--k] = '-'; /* Add sign if necessary */ len = 31 - k; if (len + numbp > NUMBUF) numbp = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -