📄 ckclib.c
字号:
char * cklibv = "C-Kermit library, 7.0.009, 29 Nov 1999";#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, 2000, 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. Most 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). ckstrncpy() - Similar to strncpy() but different (see comments). chartostr() - Converts a char to a string (self or ctrl char name). ckstrchr() - Portable strchr(). cklower() - Lowercase a string (in place). ckindex() - Left or right index. ckitoa() - Converts int to string. ckltoa() - Converts long to string. 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. makelist() - Splits "{{item}{item}...}" into an array. makestr() - Careful malloc() front end. xmakestr() - ditto (see comments). fileselect() - Select a file based on size, date, excption list, etc. radix() - Convert number radix (2-36). b8tob64() - Convert data to base 64. b64tob8() - Convert base 64 to data. chknum() - Checks if string is an integer. rdigits() - Checks if string is composed only of 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. Prototypes are in ckclib.h.*/#include "ckcsym.h"#include "ckcdeb.h"#include "ckcasc.h"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"};/* 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 had 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.*/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, x; 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 H A R T O S T R *//* Convert 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]); 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.*/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 L O W E R -- Lowercase a string *//* 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 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, 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 */ p = numbuf + numbp; q = p; s = buf + k; while (*p++ = *s++ ) ; /* Copy */ if (numbp >= NUMBUF) /* Update pointer */ numbp = 0; else numbp += k; return(q); /* Return pointer */}/* C K I T O A -- Int to string -- FOR DISCIPLINED USE ONLY */char *ckitoa(n) int n; { /* See comments with ckltoa(). */ long nn; nn = n; return(ckltoa(nn));}/* C K I N D E X -- C-Kermit's index function *//* We can't depend on C libraries to have one, so here is our own. Call with: s1 - String to look for. s2 - String to look in. t - Offset from right or left of s2, 0 based; -1 for rightmost char in s2. r - 0 for left-to-right search, non-0 for right-to-left. icase 0 for case independence, non-0 if alphabetic case matters. Returns 0 if string not found, otherwise a 1-based result. Also returns 0 on any kind of error, e.g. junk parameters.*/intckindex(s1,s2,t,r,icase) char *s1, *s2; int t, r, icase; { int len1, len2, i, j, x, ot = t; /* ot = original t */ char * s; if (!s1 || !s2) return(0); len1 = (int)strlen(s1); /* length of string to look for */ len2 = (int)strlen(s = s2); /* length of string to look in */ if (t < 0) t = len2 - 1; if (len1 < 0) return(0); /* paranoia */ if (len2 < 0) return(0); j = len2 - len1; /* length difference */ if (j < 0 || (r == 0 && t > j)) /* search string is longer */ return(0); if (r == 0) { /* Index */ s = s2 + t; /* Point to beginning of target */ for (i = 0; i <= (j - t); i++) { /* Now compare */ x = ckstrcmp(s1,s++,len1,icase); if (!x) return(i+1+t); } } else { /* Reverse Index */ i = len2 - len1; /* Where to start looking */ if (ot > 0) /* Figure in offset if any */ i -= t; for (j = i; j > -1; j--) { if (!ckstrcmp(s1,&s2[j],len1,icase)) return(j+1); } } return(0);}/* B R S T R I P -- Strip enclosing braces from arg string, in place *//* Call with: Pointer to string that can be poked. Returns: Pointer to string without enclosing braces. If original string was not braced, this is the arg pointer; otherwise it is 1 + the arg pointer, with the matching closing brace zero'd out. If the string starts with a brace but does not end with a matching brace, the original pointer to the original string is returned. If the arg pointer is NULL, a pointer to an empty string is returned.*/char *brstrip(p) char *p; { if (!p) return(""); if (*p == '{') { int x; x = (int)strlen(p) - 1; if (p[x] == '}') { p[x] = NUL; p++; } } return(p);}/* M A K E L I S T --- Breaks {{s1}{s2}..{sn}} into an array of strings *//* Call with: s = pointer to string to break up. list = array of string pointers. len = number of elements in array. NOTE: The array must be preinitialized to all NULL pointers. If any array element is not NULL, it is assumed to have been malloc'd and is therefore freed. Do NOT call this function with an unitialized array, or with an array that has had any static elements assigned to it.*/VOIDmakelist(s,list,len) char * s; char *list[]; int len; { int i, n, q, bc = 0; char *p = NULL, *s2 = NULL; debug(F110,"makelist s",s,0); if (!s) { /* Check for null or empty string */ list[0] = NULL; return; } n = strlen(s); if (n == 0) { list[0] = NULL; return; } if (s2 = (char *)malloc(n+1)) { /* Safe copy for poking */ strcpy(s2,s); /* (no need for ckstrncpy here) */ s = s2; } s = brstrip(s); /* Strip braces */ n = strlen(s); /* Get length */ if (*s != '{') { /* Outer braces only */ if (p = (char *)malloc(n+1)) { /* So just one pattern */ strcpy(p,s); /* (no need for ckstrncpy here) */ if (list[0]) free(list[0]); list[0] = p; } if (s2) free(s2); return; } q = 0; /* Inner ones too */ i = 0; /* so a list of patterns. */ n = 0; while (*s && i < len) { if (*s == CMDQ) { /* Quote... */ q = 1; s++; n++; continue; } if (*s == '{' && !q) { /* Opening brace */ if (bc++ == 0) { /* Beginning of a group */ p = ++s; n = 0; } else { /* It's a brace inside the group */ n++; s++; } continue; } else if (*s == '}' && !q) { /* Closing brace */ if (--bc == 0) { /* End of a group */ *s++ = NUL; debug(F111,"makelist element",p,i); if (list[i]) free(list[i]); if (list[i] = (char *)malloc(n+1)) { ckstrncpy(list[i],p,n+1); /* Note: n+1 */ i++; } while (*s == SP) s++; p = s; n = 0; continue; } else { /* Within a group */ n++; s++; } } else { /* Regular character */ q = 0; s++; n++; } } if (*p && i < len) { /* Last one */ if (list[i]) free(list[i]); if (list[i] = (char *)malloc(n+1)) { ckstrncpy(list[i],p,n+1); debug(F111,"makelist last element",p,i); } } if (s2) free(s2);}/* M A K E S T R -- Creates a dynamically allocated string. Makes a new copy of string s and sets pointer p to its address. Handles degenerate cases, like when buffers overlap or are the same, one or both arguments are NULL, etc. The target pointer must be either NULL or else a pointer to a previously malloc'ed buffer. If not, expect a core dump or segmentation fault. Note: The caller can tell whether this routine failed as follows: malloc(&p,q); if (q & !p) { makestr() failed };*/VOID#ifdef CK_ANSICmakestr(char **p, const char *s)#elsemakestr(p,s) char **p, *s;#endif/* makestr */ { int x; char *q = NULL; if (*p == s) /* The two pointers are the same. */ return; /* Don't do anything. */ if (!s) { /* New definition is null? */ if (*p) /* Free old storage. */ free(*p); *p = NULL; /* Return null pointer. */ return; } if ((x = strlen(s)) >= 0) { /* Get length, even of empty string. */ q = malloc(x+1); /* Get and point to temp storage. */ if (q) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -