(root)/
flex-2.6.4/
src/
buf.c
       1  /* flex - tool to generate fast lexical analyzers */
       2  
       3  /*  Copyright (c) 1990 The Regents of the University of California. */
       4  /*  All rights reserved. */
       5  
       6  /*  This code is derived from software contributed to Berkeley by */
       7  /*  Vern Paxson. */
       8  
       9  /*  The United States Government has rights in this work pursuant */
      10  /*  to contract no. DE-AC03-76SF00098 between the United States */
      11  /*  Department of Energy and the University of California. */
      12  
      13  /*  This file is part of flex. */
      14  
      15  /*  Redistribution and use in source and binary forms, with or without */
      16  /*  modification, are permitted provided that the following conditions */
      17  /*  are met: */
      18  
      19  /*  1. Redistributions of source code must retain the above copyright */
      20  /*     notice, this list of conditions and the following disclaimer. */
      21  /*  2. Redistributions in binary form must reproduce the above copyright */
      22  /*     notice, this list of conditions and the following disclaimer in the */
      23  /*     documentation and/or other materials provided with the distribution. */
      24  
      25  /*  Neither the name of the University nor the names of its contributors */
      26  /*  may be used to endorse or promote products derived from this software */
      27  /*  without specific prior written permission. */
      28  
      29  /*  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR */
      30  /*  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED */
      31  /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */
      32  /*  PURPOSE. */
      33  
      34  #include "flexdef.h"
      35  
      36  /* Take note: The buffer object is sometimes used as a String buffer (one
      37   * continuous string), and sometimes used as a list of strings, usually line by
      38   * line.
      39   * 
      40   * The type is specified in buf_init by the elt_size. If the elt_size is
      41   * sizeof(char), then the buffer should be treated as string buffer. If the
      42   * elt_size is sizeof(char*), then the buffer should be treated as a list of
      43   * strings.
      44   *
      45   * Certain functions are only appropriate for one type or the other. 
      46   */
      47  
      48  /* global buffers. */
      49  struct Buf userdef_buf;		/**< for user #definitions triggered by cmd-line. */
      50  struct Buf defs_buf;		/**< for #define's autogenerated. List of strings. */
      51  struct Buf yydmap_buf;		/**< string buffer to hold yydmap elements */
      52  struct Buf m4defs_buf;          /**< m4 definitions. List of strings. */
      53  struct Buf top_buf;             /**< contains %top code. String buffer. */
      54  
      55  struct Buf *buf_print_strings(struct Buf * buf, FILE* out)
      56  {
      57      int i;
      58  
      59      if(!buf || !out)
      60          return buf;
      61  
      62      for (i=0; i < buf->nelts; i++){
      63          const char * s = ((char**)buf->elts)[i];
      64          if(s)
      65              fprintf(out, "%s", s);
      66      }
      67      return buf;
      68  }
      69  
      70  /* Append a "%s" formatted string to a string buffer */
      71  struct Buf *buf_prints (struct Buf *buf, const char *fmt, const char *s)
      72  {
      73  	char   *t;
      74          size_t tsz;
      75  
      76  	tsz = strlen(fmt) + strlen(s) + 1;
      77  	t = malloc(tsz);
      78  	if (!t)
      79  	    flexfatal (_("Allocation of buffer to print string failed"));
      80  	snprintf (t, tsz, fmt, s);
      81  	buf = buf_strappend (buf, t);
      82  	free(t);
      83  	return buf;
      84  }
      85  
      86  /** Append a line directive to the string buffer.
      87   * @param buf A string buffer.
      88   * @param filename file name
      89   * @param lineno line number
      90   * @return buf
      91   */
      92  struct Buf *buf_linedir (struct Buf *buf, const char* filename, int lineno)
      93  {
      94      char *dst, *t;
      95      const char *src;
      96      size_t tsz;
      97  
      98      if (gen_line_dirs)
      99  	return buf;
     100  
     101      tsz = strlen("#line \"\"\n")                +   /* constant parts */
     102                 2 * strlen (filename)            +   /* filename with possibly all backslashes escaped */
     103                 (size_t) (1 + ceil (log10 (abs (lineno)))) +   /* line number */
     104                 1;                                   /* NUL */
     105      t = malloc(tsz);
     106      if (!t)
     107        flexfatal (_("Allocation of buffer for line directive failed"));
     108      for (dst = t + snprintf (t, tsz, "#line %d \"", lineno), src = filename; *src; *dst++ = *src++)
     109        if (*src == '\\')   /* escape backslashes */
     110          *dst++ = '\\';
     111      *dst++ = '"';
     112      *dst++ = '\n';
     113      *dst   = '\0';
     114      buf = buf_strappend (buf, t);
     115      free(t);
     116      return buf;
     117  }
     118  
     119  
     120  /** Append the contents of @a src to @a dest.
     121   * @param @a dest the destination buffer
     122   * @param @a dest the source buffer
     123   * @return @a dest
     124   */
     125  struct Buf *buf_concat(struct Buf* dest, const struct Buf* src)
     126  {
     127      buf_append(dest, src->elts, src->nelts);
     128      return dest;
     129  }
     130  
     131  
     132  /* Appends n characters in str to buf. */
     133  struct Buf *buf_strnappend (struct Buf *buf, const char *str, int n)
     134  {
     135  	buf_append (buf, str, n + 1);
     136  
     137  	/* "undo" the '\0' character that buf_append() already copied. */
     138  	buf->nelts--;
     139  
     140  	return buf;
     141  }
     142  
     143  /* Appends characters in str to buf. */
     144  struct Buf *buf_strappend (struct Buf *buf, const char *str)
     145  {
     146  	return buf_strnappend (buf, str, (int) strlen (str));
     147  }
     148  
     149  /* appends "#define str def\n" */
     150  struct Buf *buf_strdefine (struct Buf *buf, const char *str, const char *def)
     151  {
     152  	buf_strappend (buf, "#define ");
     153  	buf_strappend (buf, " ");
     154  	buf_strappend (buf, str);
     155  	buf_strappend (buf, " ");
     156  	buf_strappend (buf, def);
     157  	buf_strappend (buf, "\n");
     158  	return buf;
     159  }
     160  
     161  /** Pushes "m4_define( [[def]], [[val]])m4_dnl" to end of buffer.
     162   * @param buf A buffer as a list of strings.
     163   * @param def The m4 symbol to define.
     164   * @param val The definition; may be NULL.
     165   * @return buf
     166   */
     167  struct Buf *buf_m4_define (struct Buf *buf, const char* def, const char* val)
     168  {
     169      const char * fmt = "m4_define( [[%s]], [[[[%s]]]])m4_dnl\n";
     170      char * str;
     171      size_t strsz;
     172  
     173      val = val?val:"";
     174      strsz = strlen(fmt) + strlen(def) + strlen(val) + 2;
     175      str = malloc(strsz);
     176      if (!str)
     177          flexfatal (_("Allocation of buffer for m4 def failed"));
     178  
     179      snprintf(str, strsz, fmt, def, val);
     180      buf_append(buf, &str, 1);
     181      return buf;
     182  }
     183  
     184  /** Pushes "m4_undefine([[def]])m4_dnl" to end of buffer.
     185   * @param buf A buffer as a list of strings.
     186   * @param def The m4 symbol to undefine.
     187   * @return buf
     188   */
     189  struct Buf *buf_m4_undefine (struct Buf *buf, const char* def)
     190  {
     191      const char * fmt = "m4_undefine( [[%s]])m4_dnl\n";
     192      char * str;
     193      size_t strsz;
     194  
     195      strsz = strlen(fmt) + strlen(def) + 2;
     196      str = malloc(strsz);
     197      if (!str)
     198          flexfatal (_("Allocation of buffer for m4 undef failed"));
     199  
     200      snprintf(str, strsz, fmt, def);
     201      buf_append(buf, &str, 1);
     202      return buf;
     203  }
     204  
     205  /* create buf with 0 elements, each of size elem_size. */
     206  void buf_init (struct Buf *buf, size_t elem_size)
     207  {
     208  	buf->elts = NULL;
     209  	buf->nelts = 0;
     210  	buf->elt_size = elem_size;
     211  	buf->nmax = 0;
     212  }
     213  
     214  /* frees memory */
     215  void buf_destroy (struct Buf *buf)
     216  {
     217  	if (buf) {
     218  		free(buf->elts);
     219  		buf->elts = NULL;
     220  	}
     221  }
     222  
     223  
     224  /* appends ptr[] to buf, grow if necessary.
     225   * n_elem is number of elements in ptr[], NOT bytes.
     226   * returns buf.
     227   * We grow by mod(512) boundaries.
     228   */
     229  
     230  struct Buf *buf_append (struct Buf *buf, const void *ptr, int n_elem)
     231  {
     232  	int     n_alloc = 0;
     233  
     234  	if (!ptr || n_elem == 0)
     235  		return buf;
     236  
     237  	/* May need to alloc more. */
     238  	if (n_elem + buf->nelts > buf->nmax) {
     239  
     240  		/* exact count needed... */
     241  		n_alloc = n_elem + buf->nelts;
     242  
     243  		/* ...plus some extra */
     244  		if ((((size_t) n_alloc * buf->elt_size) % 512) != 0
     245  		    && buf->elt_size < 512)
     246  			n_alloc += (int)
     247  				((512 -
     248  				 (((size_t) n_alloc * buf->elt_size) % 512)) /
     249  				buf->elt_size);
     250  
     251  		if (!buf->elts)
     252  			buf->elts =
     253  				allocate_array ((int) n_alloc, buf->elt_size);
     254  		else
     255  			buf->elts =
     256  				reallocate_array (buf->elts, (int) n_alloc,
     257  						  buf->elt_size);
     258  
     259  		buf->nmax = n_alloc;
     260  	}
     261  
     262  	memcpy ((char *) buf->elts + (size_t) buf->nelts * buf->elt_size, ptr,
     263  		(size_t) n_elem * buf->elt_size);
     264  	buf->nelts += n_elem;
     265  
     266  	return buf;
     267  }
     268  
     269  /* vim:set tabstop=8 softtabstop=4 shiftwidth=4: */