home *** CD-ROM | disk | FTP | other *** search
/ Boldly Go Collection / version40.iso / TS / 17A / DRWIN101.ZIP / STRUTIL.C < prev    next >
C/C++ Source or Header  |  1991-10-27  |  45KB  |  970 lines

  1. /*
  2.   This module contains c utility routines.
  3. */
  4. #include <stdio.h>
  5. #include <conio.h>
  6. #include <string.h>
  7. #include <alloc.h>
  8. #include <dos.h>
  9. #include <ctype.h>
  10.  
  11.  
  12. #include "strutil.h"
  13.  
  14. char* _hextab="0123456789ABCDEF0";     /*used for hex translations*/
  15. int  pnum;                             //number of parameters parsed
  16. int  ppos[MAX_PARAMS];                 //offset of each parameter
  17. int  plen[MAX_PARAMS];                 //length of each parameter
  18.  
  19.  
  20. /****************************************************************************/
  21. /*  strgetch                                                                */
  22. /****************************************************************************/
  23. /*-----------------------------Description----------------------------------*/
  24. /*  This function returns the key pressed.  If a special function key is    */
  25. /*  pressed, it returns the scan code of the key + 256.                     */
  26. /*  Constants are defined in [cutil.h] for use with this function.          */
  27. /*-----------------------------Arguments------------------------------------*/
  28. /*-----------------------------Return value---------------------------------*/
  29. /*  Returns 256+scan code for special keys, ASCII value for others.         */
  30. /*-----------------------------Global constants-----------------------------*/
  31. /*-------------------Mod-------Global variables-----------------------------*/
  32. /*-----------------------------Functions called-----------------------------*/
  33. /*-----------------------------Constraints----------------------------------*/
  34. /*--Date--------Programmer---------Comments---------------------------------*/
  35. /*  1990.01.01  D. Rogers          initial code                             */
  36. /****************************************************************************/
  37. int strgetch(void)
  38. {
  39.   int c;
  40.   c=getch();
  41.   if (c)
  42.     return(c);
  43.   else
  44.     return(0x0100+getch());
  45. }   /*strgetch*/
  46. /****************************************************************************/
  47.  
  48.  
  49. /****************************************************************************/
  50. /*  strdattim                                                               */
  51. /****************************************************************************/
  52. /*-----------------------------Description----------------------------------*/
  53. /*  This function returns a string which contains the current date and      */
  54. /*  time in a format which depends on the argument:                         */
  55. /*    0   YYYY.MM.DD HH:MM:SS                                               */
  56. /*    1   MM/DD/YY HH:MM:SS                                                 */
  57. /*    2   DD/MM/YY HH:MM:SS                                                 */
  58. /*-----------------------------Arguments------------------------------------*/
  59. /*-----------------------------Return value---------------------------------*/
  60. /*-----------------------------Global constants-----------------------------*/
  61. /*-------------------Mod-------Global variables-----------------------------*/
  62. /*-----------------------------Functions called-----------------------------*/
  63. /*-----------------------------Constraints----------------------------------*/
  64. /*--Date--------Programmer-------------Comments-----------------------------*/
  65. /*  1989.10.XX  Doug Rogers                                                 */
  66. /****************************************************************************/
  67. char *strdattim(WORD form)
  68. {
  69.   static char dt[40];
  70.   struct date d;
  71.   struct time t;
  72.  
  73.   getdate(&d);
  74.   gettime(&t);
  75.   switch (form) {
  76.     case 2:
  77.       sprintf(dt,"%02d/%02d/%02d %02d:%02d:%02d",
  78.         d.da_day,d.da_mon,d.da_year%100,t.ti_hour,t.ti_min,t.ti_sec);
  79.       break;
  80.     case 1:
  81.       sprintf(dt,"%02d/%02d/%02d %02d:%02d:%02d",
  82.         d.da_mon,d.da_day,d.da_year%100,t.ti_hour,t.ti_min,t.ti_sec);
  83.       break;
  84.     case 0:
  85.     default:
  86.       sprintf(dt,"%04d.%02d.%02d %02d:%02d:%02d",
  87.         d.da_year,d.da_mon,d.da_day,t.ti_hour,t.ti_min,t.ti_sec);
  88.   }   /*switch*/
  89.   return (dt);
  90. }   /*strdattim*/
  91. /****************************************************************************/
  92.  
  93.  
  94. /****************************************************************************/
  95. /*  strsub                                                                  */
  96. /****************************************************************************/
  97. /*-----------------------------Description----------------------------------*/
  98. /*  Copies substring of length len starting at position pos in s into the   */
  99. /*  destination string d.                                                   */
  100. /*-----------------------------Arguments------------------------------------*/
  101. /*  char* s            source string for operation                          */
  102. /*  int pos            position (offset) in source string for substring     */
  103. /*  int len            length of substring                                  */
  104. /*  char* d            destination string to hold substring                 */
  105. /*-----------------------------Return value---------------------------------*/
  106. /*  Returns the destination string pointer, d.                              */
  107. /*-----------------------------Global constants-----------------------------*/
  108. /*-------------------Mod-------Global variables-----------------------------*/
  109. /*-----------------------------Functions called-----------------------------*/
  110. /*-----------------------------Examples-------------------------------------*/
  111. /*-----------------------------Constraints/Gotchas--------------------------*/
  112. /*  No check is performed on the size of the destination string.            */
  113. /*--Date--------Programmer----------Comments--------------------------------*/
  114. /*  1990.01.01  A. Turing           initial code                            */
  115. /****************************************************************************/
  116. char* strsub(char *s,int pos,int len,char *d)
  117. {
  118.   s=&s[pos];
  119.   while (len-- && *s) *d++=*s++;
  120.   *d=0;
  121.   return d;
  122. }   /*strsub*/
  123.  
  124.  
  125. /****************************************************************************/
  126. /*  strNcpy                                                                 */
  127. /****************************************************************************/
  128. /*-----------------------------Description----------------------------------*/
  129. /*  Copies from source string s to destination up to n characters.  If n    */
  130. /*  is specified as 0, no length checking is performed.  This differs from  */
  131. /*  strncpy() in that it always places a 0 in the (n-1)st offset of d.      */
  132. /*-----------------------------Arguments------------------------------------*/
  133. /*  char* d            destination string pointer                           */
  134. /*  char* s            source string pointer                                */
  135. /*  int n              number of characters to copy, max, including term    */
  136. /*-----------------------------Return value---------------------------------*/
  137. /*  Returns d.                                                              */
  138. /*-----------------------------Global constants-----------------------------*/
  139. /*-------------------Mod-------Global variables-----------------------------*/
  140. /*-----------------------------Functions called-----------------------------*/
  141. /*-----------------------------Examples-------------------------------------*/
  142. /*-----------------------------Constraints/Gotchas--------------------------*/
  143. /*--Date--------Programmer----------Comments--------------------------------*/
  144. /*  1990.01.01  A. Turing           initial code                            */
  145. /****************************************************************************/
  146. char* strNcpy(char* d,char* s,int n)
  147. {
  148.   n--;                                 /*leave room for terminator*/
  149.   if (n<0)                             /*if infinite copy..*/
  150.     strcpy(d,s);                       /*..copy forever*/
  151.   else {                               /*otherwise..*/
  152.     strncpy(d,s,n);                    /*..copy up to n*/
  153.     d[n]=0;                            /*..make sure terminator is there*/
  154.   }   /*else limit*/
  155.   return d;
  156. }   /*strNcpy*/
  157.  
  158.  
  159. /****************************************************************************/
  160. /*  strisalnum                                                              */
  161. /****************************************************************************/
  162. /*-----------------------------Description----------------------------------*/
  163. /*  Determines if the string s contains only alphanumerics.                 */
  164. /*-----------------------------Arguments------------------------------------*/
  165. /*  char* s            string to check                                      */
  166. /*-----------------------------Return value---------------------------------*/
  167. /*-----------------------------Global constants-----------------------------*/
  168. /*-------------------Mod-------Global variables-----------------------------*/
  169. /*-----------------------------Functions called-----------------------------*/
  170. /*-----------------------------Examples-------------------------------------*/
  171. /*-----------------------------Constraints/Gotchas--------------------------*/
  172. /*--Date--------Programmer----------Comments--------------------------------*/
  173. /*  1990.01.01  A. Turing           initial code                            */
  174. /****************************************************************************/
  175. int strisalnum(char *s)
  176. {
  177.   while (*s) if (!isalnum(*s++)) return 0;
  178.   return 1;
  179. }   /*strisalnum*/
  180.  
  181.  
  182. /****************************************************************************/
  183. /*  strcmpshort, stricmpshort                                               */
  184. /****************************************************************************/
  185. /*-----------------------------Description----------------------------------*/
  186. /*  Compares two strings up to the length of string t.  strcmpshort() is    */
  187. /*  case-sensitive, stricmpshort() is not.                                  */
  188. /*-----------------------------Arguments------------------------------------*/
  189. /*  char* s            pointer to string to compare                         */
  190. /*  char* t            pointer to string to compare against                 */
  191. /*-----------------------------Return value---------------------------------*/
  192. /*  Return 1 if s is greater than t, 0 if they are equal, and -1 if s is    */
  193. /*  less than t.                                                            */
  194. /*-----------------------------Global constants-----------------------------*/
  195. /*-------------------Mod-------Global variables-----------------------------*/
  196. /*-----------------------------Functions called-----------------------------*/
  197. /*-----------------------------Examples-------------------------------------*/
  198. /*-----------------------------Constraints/Gotchas--------------------------*/
  199. /*  These functions do NOT return 1 is the strings are equal.  They are     */
  200. /*  like the <string.h> strcmp() and stricmp() functions.                   */
  201. /*--Date--------Programmer----------Comments--------------------------------*/
  202. /*  1990.01.01  A. Turing           initial code                            */
  203. /****************************************************************************/
  204. int  strcmpshort(char* s,char* t)
  205. {
  206.   while (*t) {
  207.     if (*s<*t) return -1;
  208.     if (*s>*t) return +1;
  209.     s++;
  210.     t++;
  211.   }   /*while*/
  212.   return 0;
  213. }   /*strcmpshort*/
  214.  
  215.  
  216. int  stricmpshort(char* s,char* t)
  217. {
  218.   char sc,tc;
  219.   while (*t) {
  220.     sc=*s;
  221.     tc=*t;
  222.     if (_upper(sc)<_upper(tc)) return -1;
  223.     if (_upper(sc)>_upper(tc)) return +1;
  224.     s++;
  225.     t++;
  226.   }   /*while*/
  227.   return 0;
  228. }    /*stricmpshort*/
  229.  
  230.  
  231. /****************************************************************************/
  232. /*  strcompress                                                             */
  233. /****************************************************************************/
  234. /*-----------------------------Description----------------------------------*/
  235. /*  Strips all extraneous whitespace from a string.  Whitespace at the      */
  236. /*  beginning and the end of the string is deleted and all other            */
  237. /*  whitespace is reduced to a single space.                                */
  238. /*  If quoted text (either with ' or ") appears, that text is left          */
  239. /*  unaltered.  n is the size of the destination, including termination.    */
  240. /*  If n is specified as 0, no limit will be placed on the size of the      */
  241. /*  destination string.                                                     */
  242. /*-----------------------------Arguments------------------------------------*/
  243. /*  char* d            place to put resulting string (could be same as s)   */
  244. /*  char* s            string to compress                                   */
  245. /*  int n              size of destination string                           */
  246. /*-----------------------------Return value---------------------------------*/
  247. /*  Returns d.                                                              */
  248. /*-----------------------------Global constants-----------------------------*/
  249. /*-------------------Mod-------Global variables-----------------------------*/
  250. /*-----------------------------Functions called-----------------------------*/
  251. /*-----------------------------Examples-------------------------------------*/
  252. /*-----------------------------Constraints/Gotchas--------------------------*/
  253. /*--Date--------Programmer----------Comments--------------------------------*/
  254. /*  1990.01.01  A. Turing           initial code                            */
  255. /****************************************************************************/
  256. char* strcompress(char* d,char* s,int n)
  257. {
  258.   enum {START,INWORD,WHITE,QUOTE,END};
  259.   int j=0;
  260.   int state;
  261.   char q,c;
  262.  
  263.   n--;                                 /*leave room for NUL*/
  264.   state=START;                         /*starting state*/
  265.   for (;*s && ((j<n)||(n<0));s++) {
  266.     c=*s;
  267.     switch (state) {
  268.       case START:
  269.         if ((c=='\"') || (c=='\'')) {
  270.           q=c;
  271.           d[j++]=c;
  272.           state=QUOTE;
  273.         }   /* if 1 */
  274.         else if (!isspace(c)) {
  275.           d[j++]=c;
  276.           state=INWORD;
  277.         }   /* else 1 */
  278.         break;     /* case START */
  279.       case INWORD:
  280.         if ((c=='\"') || (c=='\'')) {
  281.           q=c;
  282.           d[j++]=c;
  283.           state=QUOTE;
  284.         }
  285.         else if (isspace(c)) {
  286.           d[j++]=' ';
  287.           state=WHITE;
  288.         }
  289.         else {
  290.           d[j++]=c;
  291.         }
  292.         break;     /* case INWORD */
  293.       case WHITE:
  294.         if ((c=='\"') || (c=='\'')) {
  295.           q=c;
  296.           d[j++]=c;
  297.           state=QUOTE;
  298.         }
  299.         else if (!isspace(c)) {
  300.           d[j++]=c;
  301.           state=INWORD;
  302.         }
  303.         break;     /* case WHITE */
  304.       case QUOTE:
  305.         if (c==q) {
  306.           d[j++]=c;
  307.           state=INWORD;
  308.         }
  309.         else
  310.           d[j++]=c;
  311.         break;     /* case QUOTE */
  312.       default : state=INWORD; break;
  313.     }   /* switch */
  314.   }   /* for */
  315.   if (state==WHITE) j--;
  316.   d[j]=0;
  317.   return d;
  318. }   /*strcompress*/
  319.  
  320.  
  321. /* strcomment ***************************************************************/
  322. /*                                                                          */
  323. /*  This routine places a NUL at the position of the first comment char.    */
  324. /*                                                                          */
  325. /*************************************************** Doug Rogers 1989.01.12 */
  326. char* strcomment(char *s,char comchar)
  327. {
  328.   enum {START,NORMAL,WHITE,QUOTE,END};
  329.   int i,state;
  330.   char q;
  331.  
  332.   state=START;
  333.   for (i=0;(s[i]!=0)&&(state!=END);i++) {
  334.     switch (state) {
  335.       case START:
  336.         if (s[i]==comchar) {
  337.           s[i]=0;
  338.           state=END;
  339.         }
  340.         else if ((s[i]=='\"') || (s[i]=='\'')) {
  341.           q=s[i];
  342.           state=QUOTE;
  343.         }   /* if 1 */
  344.         else if (!isspace(s[i])) {
  345.           state=NORMAL;
  346.         }   /* else 1 */
  347.         break;     /* case START */
  348.       case NORMAL:
  349.         if (s[i]==comchar) {
  350.           s[i]=0;
  351.           state=END;
  352.         }
  353.         else if ((s[i]=='\"') || (s[i]=='\'')) {
  354.           q=s[i];
  355.           state=QUOTE;
  356.         }
  357.         else if (isspace(s[i])) {
  358.           state=WHITE;
  359.         }
  360.         else {
  361.         }
  362.         break;     /* case NORMAL */
  363.       case WHITE:
  364.         if (s[i]==comchar) {
  365.           s[i]=0;
  366.           state=END;
  367.         }
  368.         else if ((s[i]=='\"') || (s[i]=='\'')) {
  369.           q=s[i];
  370.           state=QUOTE;
  371.         }
  372.         else if (!isspace(s[i])) {
  373.           state=NORMAL;
  374.         }
  375.         break;     /*case WHITE*/
  376.       case QUOTE:
  377.         if (s[i]==q) {
  378.           state=NORMAL;
  379.         }
  380.         break;     /*case QUOTE*/
  381.       default : state=END; break;
  382.     }   /*switch*/
  383.   }   /*for*/
  384.   return (s);
  385. }   /*strcomment*/
  386.  
  387.  
  388. /****************************************************************************/
  389. /*  strcchr, strcstr                                                        */
  390. /****************************************************************************/
  391. /*-----------------------------Description----------------------------------*/
  392. /*  This procedure converts string s into d in a C-like manner.  The        */
  393. /*  special characters are:                                                 */
  394. /*        \0    NUL (00h)          \a    BEL (07h)                          */
  395. /*        \b    BS  (08h)          \t    TAB (09h)                          */
  396. /*        \n    LF  (0Ah)          \v    VT  (0Bh)                          */
  397. /*        \f    FF  (0Ch)          \r    CR  (0Dh)                          */
  398. /*      * \e    ESC (1Bh)          \\    \   (5Ch)                          */
  399. /*        \"    "   (22h)          \'    '   (27h)                          */
  400. /*        \OOO  up to three octal digits for ASCII code (1st D: 1<=D<=9)    */
  401. /*        \xHH  up to two hex digits for ASCII code (\XHH)                  */
  402. /*      * \dDDD up to three decimal digits                                  */
  403. /*    *=non-standard conversion                                             */
  404. /*  strcchr:                                                                */
  405. /*  Sets only one character (pointed to by d).  Returns a pointer to the    */
  406. /*  next character in the source string.                                    */
  407. /*  strcstr:                                                                */
  408. /*  Returns the length of the new string.                                   */
  409. /*  n is the size of the destination, including the terminating NUL char.   */
  410. /*  If n is specified as 0, no limit will be placed on the size of the      */
  411. /*  destination string.                                                     */
  412. /*-----------------------------Arguments------------------------------------*/
  413. /*  char* d            destination string                                   */
  414. /*  char* s            source string                                        */
  415. /*  int maxn           size of destination string                           */
  416. /*-----------------------------Return value---------------------------------*/
  417. /*  strcchr:                                                                */
  418. /*  Returns pointer to next char in source string.                          */
  419. /*  strcstr:                                                                */
  420. /*  Returns length of destination string.                                   */
  421. /*-----------------------------Global constants-----------------------------*/
  422. /*-------------------Mod-------Global variables-----------------------------*/
  423. /*-----------------------------Functions called-----------------------------*/
  424. /*-----------------------------Examples-------------------------------------*/
  425. /*-----------------------------Constraints/Gotchas--------------------------*/
  426. /*--Date--------Programmer----------Comments--------------------------------*/
  427. /*  1990.01.01  A. Turing           initial code                            */
  428. /****************************************************************************/
  429. int  /*inline*/ digval(char c)
  430. {
  431.   if ((c>='0')&&(c<='9')) return c-'0';
  432.   if ((c>='A')&&(c<='Z')) return c-'A'+10;
  433.   if ((c>='a')&&(c<='z')) return c-'a'+10;
  434.   return 37;
  435. }   /*digval*/
  436.  
  437.  
  438. char* strcchr(char* d,char* s)
  439. {
  440.   int n=0;
  441.   int dig=0;
  442.   int base=8;
  443.   char c;
  444.  
  445.   c=*s++;
  446.   if (c!='\\') {                       //if not a special char
  447.     *d=c;                              //..just copy it
  448.     return s;                          //..and quit
  449.   }   //if not escape char
  450.  
  451.   c=*s++;
  452.   switch (c) {
  453.   case 0:    *d=0x5C; s--; return s;   //\-terminated string, leave in
  454.   case 'a':  *d=0x07; return s;        //special chars...
  455.   case 'b':  *d=0x08; return s;
  456.   case 't':  *d=0x09; return s;
  457.   case 'n':  *d=0x0A; return s;
  458.   case 'v':  *d=0x0B; return s;
  459.   case 'f':  *d=0x0C; return s;
  460.   case 'r':  *d=0x0D; return s;
  461.   case 'e':  *d=0x1B; return s;        //extension to the standard (<ESC>)
  462.   case '\"': *d=0x22; return s;
  463.   case '\'': *d=0x27; return s;
  464.   case '\\': *d=0x5C; return s;
  465.   default:
  466.     if      ((c=='x')||(c=='X')) { n=0;     dig=0; base=16; }
  467.     else if ((c=='d')||(c=='D')) { n=0;     dig=0; base=10; }
  468.     else if ((c>='0')&&(c<='7')) { n=c-'0'; dig=1; base=8; }
  469.     else { *d=c;  return s; }          //ignore ill-used \ char
  470.   }   /*switch*/
  471.  
  472.   while (dig<3) {
  473.     c=digval(*s++);
  474.     if (c<base) {
  475.       n = n*base + c;
  476.       dig++;
  477.     }
  478.     else {
  479.       s--;
  480.       break;
  481.     }   //if base 16
  482.   }   //while
  483.   if (dig)
  484.     *d = n;
  485.   else {
  486.     s--;
  487.     *d = *s++;
  488.   }
  489.   return s;
  490. }   /*strcchr*/
  491.  
  492.  
  493. int strcstr(char *d,char *s,int maxn)
  494. {
  495.   int i=0;
  496.   if (maxn--)                          /*reduce by 1 for terminator*/
  497.     while (*s && (i<maxn)) s=strcchr(&d[i++],s);
  498.   else
  499.     while (*s) s=strcchr(&d[i++],s);
  500.   d[i]=0;
  501.   return i;
  502. }   /*strcstr*/
  503.  
  504.  
  505. /****************************************************************************/
  506. /*  str2cchr, str2cstr                                                      */
  507. /****************************************************************************/
  508. /*-----------------------------Description----------------------------------*/
  509. /*  Converts from characters to C-type character sequences.  See the        */
  510. /*  description of strcchr() for a list of the conversions.  Sequences      */
  511. /*  requiring a numeric value will be converted to the \xHH format.         */
  512. /*-----------------------------Arguments------------------------------------*/
  513. /*  char* d            destination string                                   */
  514. /*  char c             (str2cchr()) character to convert                    */
  515. /*  char* s            (str2cstr()) string to convert                       */
  516. /*  int maxn           (str2cstr()) size of destination (0==no limit)       */
  517. /*-----------------------------Return value---------------------------------*/
  518. /*  Both functions return the number of characters in the destination       */
  519. /*  string.                                                                 */
  520. /*-----------------------------Global constants-----------------------------*/
  521. /*-------------------Mod-------Global variables-----------------------------*/
  522. /*-----------------------------Functions called-----------------------------*/
  523. /*-----------------------------Examples-------------------------------------*/
  524. /*-----------------------------Constraints/Gotchas--------------------------*/
  525. /*--Date--------Programmer----------Comments--------------------------------*/
  526. /*  1990.01.01  A. Turing           initial code                            */
  527. /****************************************************************************/
  528. int  str2cchr(char* d,char c)
  529. {
  530.   int i=0;
  531.  
  532.   if ((c>=' ')&&(c<='~')&&(c!='\\')&&(c!='\"'))
  533.     d[i++]=c;
  534.   else {
  535.     d[i++]='\\';
  536.     switch (c) {
  537.     case 0x00: d[i++]='0'; break;
  538.     case 0x07: d[i++]='a'; break;
  539.     case 0x08: d[i++]='b'; break;
  540.     case 0x09: d[i++]='t'; break;
  541.     case 0x0a: d[i++]='n'; break;
  542.     case 0x0b: d[i++]='v'; break;
  543.     case 0x0c: d[i++]='f'; break;
  544.     case 0x0d: d[i++]='r'; break;
  545.     case 0x1b: d[i++]='e'; break;
  546.     case 0x5c: d[i++]='\\'; break;
  547.     case 0x22: d[i++]='\"'; break;
  548.     case 0x27: d[i++]='\''; break;
  549.     default:
  550.       d[i++]='x';
  551.       d[i++]=HEX1(c);
  552.       d[i++]=HEX0(c);
  553.     }   //switch
  554.   }   //else special
  555.   return i;
  556. }   //str2cchr
  557.  
  558.  
  559. int str2cstr(char* d,char *s,int maxn)
  560. {
  561.   int i=0,j,l;
  562.   char tmp[5];
  563.  
  564.   if (maxn==0)                         //if no limit on size..
  565.     while (*s) i+=str2cchr(&d[i],*s++);
  566.   else {
  567.     maxn--;
  568.     while (*s && (i<maxn)) {
  569.       l=str2cchr(tmp,*s++);
  570.       if ((i+l)>=maxn) break;
  571.       for (j=0;j<l;j++) d[i++]=tmp[j];
  572.     }   //while
  573.   }   //else limiting size
  574.   d[i]=0;
  575.   return i;
  576. }   //str2cstr
  577.  
  578.  
  579. /****************************************************************************/
  580. /*  strparse                                                                */
  581. /****************************************************************************/
  582. /*-----------------------------Description----------------------------------*/
  583. /*  Parses the input string into a list of parameters specified by their    */
  584. /*  position within the source string s and their length.  The string s is  */
  585. /*  also copied into the structure pointed to by sp.  If sp is specified    */
  586. /*  as NULL, the module global variable strp is used.                       */
  587. /*  Text enclosed in quotes (either ' or ") is considered to be a single    */
  588. /*  parameter without the quotes appearing (that is, the pos field of sp    */
  589. /*  will point just past the first quote and the length will stop short of  */
  590. /*  the closing quote).  If psep is 0, the copy of the source string, str   */
  591. /*  of sp, will remain identical to the source string.  If 1, each          */
  592. /*  parameter in the str string will have a terminating NUL set at its      */
  593. /*  end (str will be divided into sp->num separate Z-strings).              */
  594. /*  Parameters are always delimited by whitespace (except those enclosed    */
  595. /*  in quotes).                                                             */
  596. /*-----------------------------Arguments------------------------------------*/
  597. /* char* s             source string to be parsed; it is left unaffected    */
  598. /* STR_PARAM* sp       parameter list structure, defaults to strp           */
  599. /* int psep            flag indicating parameter separation desired         */
  600. /*-----------------------------Return value---------------------------------*/
  601. /*  Returns the number of parameters encountered on the line.               */
  602. /*-----------------------------Global constants-----------------------------*/
  603. /*-------------------Mod-------Global variables-----------------------------*/
  604. /*-----------------------------Functions called-----------------------------*/
  605. /*-----------------------------Examples-------------------------------------*/
  606. /*-----------------------------Constraints/Gotchas--------------------------*/
  607. /*--Date--------Programmer----------Comments--------------------------------*/
  608. /*  1990.01.01  A. Turing           initial code                            */
  609. /****************************************************************************/
  610. int   strparse(char *s,int psep)             //returns pnum
  611. {
  612.   enum {START,NORMAL,WHITE,QUOTE,END};
  613.   int i,state;
  614.   char q;
  615.   char c;
  616.  
  617.   state=START;
  618.   pnum=0;                              /*reset count*/
  619.   for (i=0;(c=s[i])!=0;i++) {
  620.     switch (state) {
  621.     case START:
  622.       if ((c=='\"') || (c=='\'')) {
  623.     if (pnum<MAX_PARAMS) {
  624.           plen[pnum]=0;
  625.           ppos[pnum]=i+1;
  626.     }
  627.     q=c;
  628.     state=QUOTE;
  629.       }   /* if 1 */
  630.       else if (!isspace(c)) {
  631.     if (pnum<MAX_PARAMS) {
  632.           plen[pnum]=1;
  633.           ppos[pnum]=i;
  634.     }
  635.     state=NORMAL;
  636.       }   /* else 1 */
  637.       break;     /* case START */
  638.     case NORMAL:
  639.       if ((c=='\"') || (c=='\'')) {
  640.     pnum++;
  641.     if (pnum<MAX_PARAMS) {
  642.           plen[pnum]=0;
  643.           ppos[pnum]=i+1;
  644.     }
  645.     q=c;
  646.     state=QUOTE;
  647.       }
  648.       else if (isspace(c))
  649.     state=WHITE;
  650.       else {
  651.     if (pnum<MAX_PARAMS) plen[pnum]++;
  652.       }
  653.       break;     /* case NORMAL */
  654.     case WHITE:
  655.       if ((c=='\"') || (c=='\'')) {
  656.     pnum++;
  657.     if (pnum<MAX_PARAMS) {
  658.           plen[pnum]=0;
  659.           ppos[pnum]=i+1;
  660.     }
  661.     q=c;
  662.     state=QUOTE;
  663.       }
  664.       else if (!isspace(c)) {
  665.     pnum++;
  666.     if (pnum<MAX_PARAMS) {
  667.           plen[pnum]=1;
  668.           ppos[pnum]=i;
  669.     }
  670.     state=NORMAL;
  671.       }
  672.       break;     /* case WHITE */
  673.     case QUOTE:
  674.       if (c==q)
  675.     state=WHITE;
  676.       else
  677.     if (pnum<MAX_PARAMS) plen[pnum]++;
  678.       break;     /* case QUOTE */
  679.     default :
  680.       state=WHITE;
  681.     }   /* switch */
  682.   }   /* for */
  683.  
  684.   if (state!=START) {
  685.     pnum++;
  686.   }   /*if not an empty line*/
  687.  
  688.   if (psep) strparamsep(s);                    /*if separating*/
  689.   return pnum;
  690. }   /*strparse*/
  691.  
  692.  
  693. /****************************************************************************/
  694. /*  strparam                                                                */
  695. /****************************************************************************/
  696. /*-----------------------------Description----------------------------------*/
  697. /*  Copies parameter p (its string characters) from the str field of the    */
  698. /*  given STR_PARAM sp.  n limits the size of d (including terminator),     */
  699. /*  the destination string.  If sp is NULL, the global STR_PARAM strp will  */
  700. /*  be used.  If d is NULL, nothing will be copied, but the appropriate     */
  701. /*  pointer into the str field for the specified parameter will be          */
  702. /*  returned.  If n is 0, no size checking will be performed when writing   */
  703. /*  the value into destination string.                                      */
  704. /*-----------------------------Arguments------------------------------------*/
  705. /*  char* d            destination string pointer, NULL=just return ptr     */
  706. /*  char *s            pointer to parameter list structure, default strp    */
  707. /*  int p              parameter to load and/or return pointer to           */
  708. /*-----------------------------Return value---------------------------------*/
  709. /*  Returns pointer to destination string if d is specified.  Returns       */
  710. /*  pointer to the parameter's position (sp->pos) within the str field if   */
  711. /*  d is passed as NULL.                                                    */
  712. /*-----------------------------Global constants-----------------------------*/
  713. /*-------------------Mod-------Global variables-----------------------------*/
  714. /*-----------------------------Functions called-----------------------------*/
  715. /*-----------------------------Examples-------------------------------------*/
  716. /*-----------------------------Constraints/Gotchas--------------------------*/
  717. /*--Date--------Programmer----------Comments--------------------------------*/
  718. /*  1990.01.01  A. Turing           initial code                            */
  719. /****************************************************************************/
  720. char* strparam(char* d,int p,char* s)  //returns d
  721. {
  722.   int i;                               /*index*/
  723.  
  724.   if (p>=pnum) return NULL;            /*parameter too big for this*/
  725.   for (i=0;i<plen[p];i++)
  726.     d[i]=s[ppos[p]+i];
  727.   d[i]=0;
  728.   return d;                            /*return pointer to destination*/
  729. }   /*strparam*/
  730.  
  731.  
  732. /****************************************************************************/
  733. /*  strparamint                                                             */
  734. /****************************************************************************/
  735. /*-----------------------------Description----------------------------------*/
  736. /*  Gets an integer from the specified parameter p and puts it in the int   */
  737. /*  pointed to by ip.  If the STR_PARAM pointer sp is NULL, the global      */
  738. /*  strp structure is used.                                                 */
  739. /*-----------------------------Arguments------------------------------------*/
  740. /*  STR_PARAM* sp      pointer to parameter list structure, NULL-->strp     */
  741. /*  int p              parameter to use to load int                         */
  742. /*  int* ip            pointer to integer to hold read value                */
  743. /*-----------------------------Return value---------------------------------*/
  744. /*  Returns 1 if successfully read an int, 0 on failure.                    */
  745. /*-----------------------------Global constants-----------------------------*/
  746. /*-------------------Mod-------Global variables-----------------------------*/
  747. /*-----------------------------Functions called-----------------------------*/
  748. /*-----------------------------Examples-------------------------------------*/
  749. /*-----------------------------Constraints/Gotchas--------------------------*/
  750. /*--Date--------Programmer----------Comments--------------------------------*/
  751. /*  1990.01.01  A. Turing           initial code                            */
  752. /****************************************************************************/
  753. int   strparamint(char* s,int p,int *ip)     //1 if parsed to int
  754. {
  755.   if (p>=pnum) return 0;              /*oops. bad parameter number*/
  756.   return (sscanf(&s[ppos[p]],"%d",ip)==1);
  757. }   /*strparamint*/
  758.  
  759.  
  760. /* param_sep -- puts \0 at end of each parameter -- call strparse() first */
  761. int   strparamsep(char* s)                   //puts \0 after each param
  762. {
  763.   int i;
  764.   for (i=0;i<pnum;i++) s[ppos[i]+plen[i]]=0;
  765.   return pnum;
  766. }   /*strparamsep*/
  767.  
  768.  
  769. /****************************************************************************/
  770. /*  strmatch                                                                */
  771. /****************************************************************************/
  772. /*-----------------------------Description----------------------------------*/
  773. /*  This function matches a target string against a match mask which        */
  774. /*  contains wildcard characters (* and ?).  The * matches all sequences.   */
  775. /*  The ? matches any single character and requires that one be present.    */
  776. /*  For example:                                                            */
  777. /*    strmatch("?23","123")==1                                              */
  778. /*    strmatch("?123","123")==0, but strmatch("*123","123")==1              */
  779. /*    strmatch("12*34*56","123a34bcde56")==1                                */
  780. /*  etc.                                                                    */
  781. /*-----------------------------Arguments------------------------------------*/
  782. /*  char *m            match mask with wildcards                            */
  783. /*  char *s            target string to test against mask                   */
  784. /*-----------------------------Return value---------------------------------*/
  785. /*  Returns 1 if matched, 0 otherwise.                                      */
  786. /*-----------------------------Global constants-----------------------------*/
  787. /*-------------------Mod-------Global variables-----------------------------*/
  788. /*-----------------------------Functions called-----------------------------*/
  789. /*-----------------------------Constraints----------------------------------*/
  790. /*--Date--------Programmer-------------Comments-----------------------------*/
  791. /*  1990.04.??  D. Rogers              initial code                         */
  792. /****************************************************************************/
  793. int  strmatch(char *m,char *s)
  794. {
  795. #define WILD_ONE       '?'             /*single-char wildcard match*/
  796. #define WILD_ALL       '*'             /*variable length wildcard match*/
  797.   enum { MUST_MATCH, SEEK_MATCH, PART_MATCH };  /*states for match-checking*/
  798.   char *curm;                          /*current pointer to match str*/
  799.   char *curs;                          /*current pointer to target string*/
  800.   char state=MUST_MATCH;               /*start checking the match*/
  801.  
  802.   curm=m;                              /*start at same place*/
  803.   curs=s;
  804.   while (1) {                          /*go 'til end of match*/
  805.     switch(state) {                    /*depends on state*/
  806.     case MUST_MATCH:                   /*if normal char, must match*/
  807.       if (*curm==WILD_ALL) {           /*check for variable wild char*/
  808.         while (*curm==WILD_ALL) curm++;  /*go to next char to match*/
  809.         if (*curm==0) return 1;        /*nothing left to match, so quit*/
  810.         state=SEEK_MATCH;              /*look for next section of match str*/
  811.         break;
  812.       }   /*if wild-all found*/
  813.       if (!*curm) {                    /*no more to match; done, 1way|other*/
  814.         if (*curs) return 0; else return 1;   /*if extra, bad; if not, match*/
  815.       }   /*if end of match string*/
  816.       if (!*curs) return 0;            /*found end of line*/
  817.       if ((*curm!=WILD_ONE)&&(*curm!=*curs)) return 0;  /*no match!*/
  818.       curm++;                          /*point to next match character*/
  819.       curs++;                          /*point to next target character*/
  820.       break;
  821.     case SEEK_MATCH:                   /*looking for match*/
  822.       if (!*curs) return 0;            /*no chars left for match*/
  823.       if ((*curm==WILD_ONE)||(*curm==*curs)) {   /*see if matched*/
  824.         curs++;                        /*point to next target position*/
  825.         s=curs;                        /*point to target position*/
  826.         m=curm;                        /*point to match position*/
  827.         m++;                           /*point to next match position*/
  828.         state=PART_MATCH;              /*we're on to one!*/
  829.         break;
  830.       }   /*if match started*/
  831.       curs++;                          /*try next position*/
  832.       break;
  833.     case PART_MATCH:                   /*started matching after WILD_ALL*/
  834.       if (!*m) {                       /*no more to match; done, 1way|other*/
  835.         if (*s) return 0; else return 1;   /*if extra, bad; if not, match*/
  836.       }   /*if end of match string*/
  837.       if (*m==WILD_ALL) {              /*if up to next WILD_ALL*/
  838.         curm=m;                        /*skip up to now*/
  839.         curs=s;                        /*skip up to now on target, too*/
  840.         state=MUST_MATCH;              /*great, now go back to start*/
  841.         break;
  842.       }   /*if end of this section of must-match*/
  843.       if (!*s) return 0;               /*match mask not done but we are, bad*/
  844.       if ((*m!=WILD_ONE)&&(*m!=*s)) {  /*not aligned -- bad*/
  845.         state=SEEK_MATCH;              /*go back and scan for a match*/
  846.         break;
  847.       }   /*if*/
  848.       m++;                             /*looks good, go to next char*/
  849.       s++;                             /*in target, too*/
  850.       break;
  851.     default:                           /*should never reach here*/
  852.       return 0;                        /*..so get out*/
  853.     }   /*switch*/
  854.   }   /*while forever*/
  855. }   /*strmatch*/
  856.  
  857.  
  858. //***************************************************************************
  859. //  strasc2ul
  860. //***************************************************************************
  861. //-----------------------------Description-----------------------------------
  862. //  Fills the unsigned long pointed to by ul with the value specified in the
  863. //  ASCIIZ string s.  The following prefixes are allowed:
  864. //    0<number>        <number> is in octal
  865. //    0x<number>       <number> is in hexadecimal
  866. //  All other initial sequences (other than the same ones capitalized)
  867. //  will be read in the given default base.  Initial white-space is skipped.
  868. //  Numbers may be preceded by a single '-' or '+'.
  869. //-----------------------------Arguments-------------------------------------
  870. //  char* s            ASCIIZ string to be converted
  871. //  unsigned long* ul  pointer to DWORD to be changed
  872. //  unsigned base      default base (0-->decimal)
  873. //-----------------------------Return value----------------------------------
  874. //  Returns the number of characters processed -- NOT the number of fields.
  875. //  Returns 0 if no value was loaded (due to absence or error).
  876. //-----------------------------Global constants------------------------------
  877. //-------------------Mod-------Global variables------------------------------
  878. //-----------------------------Functions called------------------------------
  879. //-----------------------------Examples--------------------------------------
  880. //-----------------------------Constraints/Gotchas---------------------------
  881. //--Date--------Programmer----------Comments---------------------------------
  882. //  1991.07.26  A. Turing           initial code
  883. //***************************************************************************
  884. int  strasc2ul(char* s,unsigned long* ul,unsigned base)
  885. {
  886. #define DIGIT(c) ( (c<'0')?-1:(c<='9')?c-'0':(c<'A')?-1:(c>'Z')?-1:c+10-'A' )
  887.   unsigned long val=0;
  888.   int i=0;
  889.   unsigned dig;
  890.   char c;
  891.   char minus=0;
  892.  
  893.   while (s[i] && isspace(s[i])) i++;
  894.   if (!s[i]) return 0;
  895.  
  896.   if ((base<2)||(base>36)) base=10;    //make sure the base is ok
  897.  
  898.   if      (s[i]=='-') { minus=1; i++; }  //look for -<number>
  899.   else if (s[i]=='+') { minus=0; i++; }
  900.   else if (s[i]=='0') {                  //could be a base indicator
  901.     i++;
  902.     if      ((s[i]=='x')||(s[i]=='X')) { base=16; i++; }
  903.     else if ((s[i]<'0')||(s[i]>'7')) { *ul=0; return i; }  //end if not octal
  904.     else base=8;
  905.   }   //if checking for base
  906.  
  907.   c=toupper(s[i++]);                   //check first digit
  908.   dig=DIGIT(c);
  909.   if (dig>=base) return 0;             //first digit was bad
  910.   val=dig;                             //start first digit
  911.  
  912.   while (1) {
  913.     c=toupper(s[i]);
  914.     dig=DIGIT(c);
  915.     if (dig>=base) break;              //reached end of line
  916.     val=val*base+dig;                  //good char, so insert
  917.     i++;
  918.   }   //while
  919.   if (minus) *ul=-val; else *ul=val;
  920.   return i;
  921. }   //strasc2ul
  922.  
  923.  
  924. //***************************************************************************
  925. //  strul2asc
  926. //***************************************************************************
  927. //-----------------------------Description-----------------------------------
  928. //  Writes an unsigned long int ul to an ASCIIZ string s in the given base.
  929. //  The base may be from 2 to 36.  No initial characters are inserted (like
  930. //  "0x" for base 16).
  931. //-----------------------------Arguments-------------------------------------
  932. //  char* s            string into which to write the converted longword
  933. //  unsigned long ul   longword to write
  934. //  unsigned base      base for conversion
  935. //-----------------------------Return value----------------------------------
  936. //  Returns the number of characters written (not including the terminating
  937. //  0).
  938. //-----------------------------Global constants------------------------------
  939. //-------------------Mod-------Global variables------------------------------
  940. //-----------------------------Functions called------------------------------
  941. //-----------------------------Examples--------------------------------------
  942. //-----------------------------Constraints/Gotchas---------------------------
  943. //--Date--------Programmer----------Comments---------------------------------
  944. //  1990.07.26  A. Turing           initial code
  945. //***************************************************************************
  946. int  strul2asc(char* s,unsigned long ul,unsigned base)
  947. {
  948.   static char basechar[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  949.   int i=0;
  950.   unsigned dig;
  951.   char c;
  952.   if ((base<2)||(base>36)) base=10;
  953.   if (ul==0UL) { s[i++]='0'; s[i]=0; return i; }   //easy if zero
  954.  
  955.   while (ul) {                         //convert to ascii
  956.     dig=(unsigned) (ul%(unsigned long)base);
  957.     s[i++]=basechar[dig];
  958.     ul/=(unsigned long)base;
  959.   }   //while
  960.   for (dig=0;dig<(i/2);dig++) {        //reverse order
  961.     c=s[dig];
  962.     s[dig]=s[i-dig-1];
  963.     s[i-dig-1]=c;
  964.   }   //for
  965.   s[i]=0;
  966.   return i;
  967. }   //strul2asc
  968.  
  969.  
  970.