home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / perl-5.003-base.tgz / perl-5.003-base.tar / fsf / perl / x2p / str.c < prev    next >
C/C++ Source or Header  |  1995-06-07  |  10KB  |  469 lines

  1. /* $RCSfile: str.c,v $$Revision: 4.1 $$Date: 92/08/07 18:29:26 $
  2.  *
  3.  *    Copyright (c) 1991, Larry Wall
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  * $Log:    str.c,v $
  9.  */
  10.  
  11. #include "EXTERN.h"
  12. #include "a2p.h"
  13. #include "util.h"
  14.  
  15. void
  16. str_numset(str,num)
  17. register STR *str;
  18. double num;
  19. {
  20.     str->str_nval = num;
  21.     str->str_pok = 0;        /* invalidate pointer */
  22.     str->str_nok = 1;        /* validate number */
  23. }
  24.  
  25. char *
  26. str_2ptr(str)
  27. register STR *str;
  28. {
  29.     register char *s;
  30.  
  31.     if (!str)
  32.     return "";
  33.     GROWSTR(&(str->str_ptr), &(str->str_len), 24);
  34.     s = str->str_ptr;
  35.     if (str->str_nok) {
  36.     sprintf(s,"%.20g",str->str_nval);
  37.     while (*s) s++;
  38.     }
  39.     *s = '\0';
  40.     str->str_cur = s - str->str_ptr;
  41.     str->str_pok = 1;
  42. #ifdef DEBUGGING
  43.     if (debug & 32)
  44.     fprintf(stderr,"0x%lx ptr(%s)\n",str,str->str_ptr);
  45. #endif
  46.     return str->str_ptr;
  47. }
  48.  
  49. double
  50. str_2num(str)
  51. register STR *str;
  52. {
  53.     if (!str)
  54.     return 0.0;
  55.     if (str->str_len && str->str_pok)
  56.     str->str_nval = atof(str->str_ptr);
  57.     else
  58.     str->str_nval = 0.0;
  59.     str->str_nok = 1;
  60. #ifdef DEBUGGING
  61.     if (debug & 32)
  62.     fprintf(stderr,"0x%lx num(%g)\n",str,str->str_nval);
  63. #endif
  64.     return str->str_nval;
  65. }
  66.  
  67. void
  68. str_sset(dstr,sstr)
  69. STR *dstr;
  70. register STR *sstr;
  71. {
  72.     if (!sstr)
  73.     str_nset(dstr,No,0);
  74.     else if (sstr->str_nok)
  75.     str_numset(dstr,sstr->str_nval);
  76.     else if (sstr->str_pok)
  77.     str_nset(dstr,sstr->str_ptr,sstr->str_cur);
  78.     else
  79.     str_nset(dstr,"",0);
  80. }
  81.  
  82. void
  83. str_nset(str,ptr,len)
  84. register STR *str;
  85. register char *ptr;
  86. register int len;
  87. {
  88.     GROWSTR(&(str->str_ptr), &(str->str_len), len + 1);
  89.     bcopy(ptr,str->str_ptr,len);
  90.     str->str_cur = len;
  91.     *(str->str_ptr+str->str_cur) = '\0';
  92.     str->str_nok = 0;        /* invalidate number */
  93.     str->str_pok = 1;        /* validate pointer */
  94. }
  95.  
  96. void
  97. str_set(str,ptr)
  98. register STR *str;
  99. register char *ptr;
  100. {
  101.     register int len;
  102.  
  103.     if (!ptr)
  104.     ptr = "";
  105.     len = strlen(ptr);
  106.     GROWSTR(&(str->str_ptr), &(str->str_len), len + 1);
  107.     bcopy(ptr,str->str_ptr,len+1);
  108.     str->str_cur = len;
  109.     str->str_nok = 0;        /* invalidate number */
  110.     str->str_pok = 1;        /* validate pointer */
  111. }
  112.  
  113. void
  114. str_chop(str,ptr)    /* like set but assuming ptr is in str */
  115. register STR *str;
  116. register char *ptr;
  117. {
  118.     if (!(str->str_pok))
  119.     str_2ptr(str);
  120.     str->str_cur -= (ptr - str->str_ptr);
  121.     bcopy(ptr,str->str_ptr, str->str_cur + 1);
  122.     str->str_nok = 0;        /* invalidate number */
  123.     str->str_pok = 1;        /* validate pointer */
  124. }
  125.  
  126. void
  127. str_ncat(str,ptr,len)
  128. register STR *str;
  129. register char *ptr;
  130. register int len;
  131. {
  132.     if (!(str->str_pok))
  133.     str_2ptr(str);
  134.     GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1);
  135.     bcopy(ptr,str->str_ptr+str->str_cur,len);
  136.     str->str_cur += len;
  137.     *(str->str_ptr+str->str_cur) = '\0';
  138.     str->str_nok = 0;        /* invalidate number */
  139.     str->str_pok = 1;        /* validate pointer */
  140. }
  141.  
  142. void
  143. str_scat(dstr,sstr)
  144. STR *dstr;
  145. register STR *sstr;
  146. {
  147.     if (!(sstr->str_pok))
  148.     str_2ptr(sstr);
  149.     if (sstr)
  150.     str_ncat(dstr,sstr->str_ptr,sstr->str_cur);
  151. }
  152.  
  153. void
  154. str_cat(str,ptr)
  155. register STR *str;
  156. register char *ptr;
  157. {
  158.     register int len;
  159.  
  160.     if (!ptr)
  161.     return;
  162.     if (!(str->str_pok))
  163.     str_2ptr(str);
  164.     len = strlen(ptr);
  165.     GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1);
  166.     bcopy(ptr,str->str_ptr+str->str_cur,len+1);
  167.     str->str_cur += len;
  168.     str->str_nok = 0;        /* invalidate number */
  169.     str->str_pok = 1;        /* validate pointer */
  170. }
  171.  
  172. char *
  173. str_append_till(str,from,delim,keeplist)
  174. register STR *str;
  175. register char *from;
  176. register int delim;
  177. char *keeplist;
  178. {
  179.     register char *to;
  180.     register int len;
  181.  
  182.     if (!from)
  183.     return Nullch;
  184.     len = strlen(from);
  185.     GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + len + 1);
  186.     str->str_nok = 0;        /* invalidate number */
  187.     str->str_pok = 1;        /* validate pointer */
  188.     to = str->str_ptr+str->str_cur;
  189.     for (; *from; from++,to++) {
  190.     if (*from == '\\' && from[1] && delim != '\\') {
  191.         if (!keeplist) {
  192.         if (from[1] == delim || from[1] == '\\')
  193.             from++;
  194.         else
  195.             *to++ = *from++;
  196.         }
  197.         else if (strchr(keeplist,from[1]))
  198.         *to++ = *from++;
  199.         else
  200.         from++;
  201.     }
  202.     else if (*from == delim)
  203.         break;
  204.     *to = *from;
  205.     }
  206.     *to = '\0';
  207.     str->str_cur = to - str->str_ptr;
  208.     return from;
  209. }
  210.  
  211. STR *
  212. str_new(len)
  213. int len;
  214. {
  215.     register STR *str;
  216.     
  217.     if (freestrroot) {
  218.     str = freestrroot;
  219.     freestrroot = str->str_link.str_next;
  220.     }
  221.     else {
  222.     str = (STR *) safemalloc(sizeof(STR));
  223.     bzero((char*)str,sizeof(STR));
  224.     }
  225.     if (len)
  226.     GROWSTR(&(str->str_ptr), &(str->str_len), len + 1);
  227.     return str;
  228. }
  229.  
  230. void
  231. str_grow(str,len)
  232. register STR *str;
  233. int len;
  234. {
  235.     if (len && str)
  236.     GROWSTR(&(str->str_ptr), &(str->str_len), len + 1);
  237. }
  238.  
  239. /* make str point to what nstr did */
  240.  
  241. void
  242. str_replace(str,nstr)
  243. register STR *str;
  244. register STR *nstr;
  245. {
  246.     Safefree(str->str_ptr);
  247.     str->str_ptr = nstr->str_ptr;
  248.     str->str_len = nstr->str_len;
  249.     str->str_cur = nstr->str_cur;
  250.     str->str_pok = nstr->str_pok;
  251.     if (str->str_nok = nstr->str_nok)
  252.     str->str_nval = nstr->str_nval;
  253.     safefree((char*)nstr);
  254. }
  255.  
  256. void
  257. str_free(str)
  258. register STR *str;
  259. {
  260.     if (!str)
  261.     return;
  262.     if (str->str_len)
  263.     str->str_ptr[0] = '\0';
  264.     str->str_cur = 0;
  265.     str->str_nok = 0;
  266.     str->str_pok = 0;
  267.     str->str_link.str_next = freestrroot;
  268.     freestrroot = str;
  269. }
  270.  
  271. int
  272. str_len(str)
  273. register STR *str;
  274. {
  275.     if (!str)
  276.     return 0;
  277.     if (!(str->str_pok))
  278.     str_2ptr(str);
  279.     if (str->str_len)
  280.     return str->str_cur;
  281.     else
  282.     return 0;
  283. }
  284.  
  285. char *
  286. str_gets(str,fp)
  287. register STR *str;
  288. register FILE *fp;
  289. {
  290. #if defined(USE_STDIO_PTR) && defined(STDIO_PTR_LVALUE) && defined(STDIO_CNT_LVALUE)
  291.     /* Here is some breathtakingly efficient cheating */
  292.  
  293.     register char *bp;        /* we're going to steal some values */
  294.     register int cnt;        /*  from the stdio struct and put EVERYTHING */
  295.     register STDCHAR *ptr;    /*   in the innermost loop into registers */
  296.     register char newline = '\n';    /* (assuming at least 6 registers) */
  297.     int i;
  298.     int bpx;
  299.  
  300.     cnt = FILE_cnt(fp);            /* get count into register */
  301.     str->str_nok = 0;            /* invalidate number */
  302.     str->str_pok = 1;            /* validate pointer */
  303.     if (str->str_len <= cnt)        /* make sure we have the room */
  304.     GROWSTR(&(str->str_ptr), &(str->str_len), cnt+1);
  305.     bp = str->str_ptr;            /* move these two too to registers */
  306.     ptr = FILE_ptr(fp);
  307.     for (;;) {
  308.     while (--cnt >= 0) {
  309.         if ((*bp++ = *ptr++) == newline)
  310.         if (bp <= str->str_ptr || bp[-2] != '\\')
  311.             goto thats_all_folks;
  312.         else {
  313.             line++;
  314.             bp -= 2;
  315.         }
  316.     }
  317.     
  318.     FILE_cnt(fp) = cnt;        /* deregisterize cnt and ptr */
  319.     FILE_ptr(fp) = ptr;
  320.     i = _filbuf(fp);        /* get more characters */
  321.     cnt = FILE_cnt(fp);
  322.     ptr = FILE_ptr(fp);        /* reregisterize cnt and ptr */
  323.  
  324.     bpx = bp - str->str_ptr;    /* prepare for possible relocation */
  325.     GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + cnt + 1);
  326.     bp = str->str_ptr + bpx;    /* reconstitute our pointer */
  327.  
  328.     if (i == newline) {        /* all done for now? */
  329.         *bp++ = i;
  330.         goto thats_all_folks;
  331.     }
  332.     else if (i == EOF)        /* all done for ever? */
  333.         goto thats_all_folks;
  334.     *bp++ = i;            /* now go back to screaming loop */
  335.     }
  336.  
  337. thats_all_folks:
  338.     FILE_cnt(fp) = cnt;            /* put these back or we're in trouble */
  339.     FILE_ptr(fp) = ptr;
  340.     *bp = '\0';
  341.     str->str_cur = bp - str->str_ptr;    /* set length */
  342.  
  343. #else /* USE_STDIO_PTR && STDIO_PTR_LVALUE && STDIO_CNT_LVALUE */
  344.     /* The big, slow, and stupid way */
  345.  
  346.     static char buf[4192];
  347.  
  348.     if (fgets(buf, sizeof buf, fp) != Nullch)
  349.     str_set(str, buf);
  350.     else
  351.     str_set(str, No);
  352.  
  353. #endif /* USE_STDIO_PTR && STDIO_PTR_LVALUE && STDIO_CNT_LVALUE */
  354.  
  355.     return str->str_cur ? str->str_ptr : Nullch;
  356. }
  357.  
  358. void
  359. str_inc(str)
  360. register STR *str;
  361. {
  362.     register char *d;
  363.  
  364.     if (!str)
  365.     return;
  366.     if (str->str_nok) {
  367.     str->str_nval += 1.0;
  368.     str->str_pok = 0;
  369.     return;
  370.     }
  371.     if (!str->str_pok) {
  372.     str->str_nval = 1.0;
  373.     str->str_nok = 1;
  374.     return;
  375.     }
  376.     for (d = str->str_ptr; *d && *d != '.'; d++) ;
  377.     d--;
  378.     if (!isdigit(*str->str_ptr) || !isdigit(*d) ) {
  379.         str_numset(str,atof(str->str_ptr) + 1.0);  /* punt */
  380.     return;
  381.     }
  382.     while (d >= str->str_ptr) {
  383.     if (++*d <= '9')
  384.         return;
  385.     *(d--) = '0';
  386.     }
  387.     /* oh,oh, the number grew */
  388.     GROWSTR(&(str->str_ptr), &(str->str_len), str->str_cur + 2);
  389.     str->str_cur++;
  390.     for (d = str->str_ptr + str->str_cur; d > str->str_ptr; d--)
  391.     *d = d[-1];
  392.     *d = '1';
  393. }
  394.  
  395. void
  396. str_dec(str)
  397. register STR *str;
  398. {
  399.     register char *d;
  400.  
  401.     if (!str)
  402.     return;
  403.     if (str->str_nok) {
  404.     str->str_nval -= 1.0;
  405.     str->str_pok = 0;
  406.     return;
  407.     }
  408.     if (!str->str_pok) {
  409.     str->str_nval = -1.0;
  410.     str->str_nok = 1;
  411.     return;
  412.     }
  413.     for (d = str->str_ptr; *d && *d != '.'; d++) ;
  414.     d--;
  415.     if (!isdigit(*str->str_ptr) || !isdigit(*d) || (*d == '0' && d == str->str_ptr)) {
  416.         str_numset(str,atof(str->str_ptr) - 1.0);  /* punt */
  417.     return;
  418.     }
  419.     while (d >= str->str_ptr) {
  420.     if (--*d >= '0')
  421.         return;
  422.     *(d--) = '9';
  423.     }
  424. }
  425.  
  426. /* make a string that will exist for the duration of the expression eval */
  427.  
  428. STR *
  429. str_mortal(oldstr)
  430. STR *oldstr;
  431. {
  432.     register STR *str = str_new(0);
  433.     static long tmps_size = -1;
  434.  
  435.     str_sset(str,oldstr);
  436.     if (++tmps_max > tmps_size) {
  437.     tmps_size = tmps_max;
  438.     if (!(tmps_size & 127)) {
  439.         if (tmps_size)
  440.         tmps_list = (STR**)saferealloc((char*)tmps_list,
  441.             (tmps_size + 128) * sizeof(STR*) );
  442.         else
  443.         tmps_list = (STR**)safemalloc(128 * sizeof(char*));
  444.     }
  445.     }
  446.     tmps_list[tmps_max] = str;
  447.     return str;
  448. }
  449.  
  450. STR *
  451. str_make(s)
  452. char *s;
  453. {
  454.     register STR *str = str_new(0);
  455.  
  456.     str_set(str,s);
  457.     return str;
  458. }
  459.  
  460. STR *
  461. str_nmake(n)
  462. double n;
  463. {
  464.     register STR *str = str_new(0);
  465.  
  466.     str_numset(str,n);
  467.     return str;
  468. }
  469.