This is Unofficial EPICS BASE Doxygen Site
misc.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2002 The University of Chicago, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * EPICS BASE is distributed subject to a Software License Agreement found
7 * in file LICENSE that is included with this distribution.
8 \*************************************************************************/
9 /* misc - miscellaneous flex routines */
10 
11 /*-
12  * Copyright (c) 1990 The Regents of the University of California.
13  * All rights reserved.
14  *
15  * This code is derived from software contributed to Berkeley by
16  * Vern Paxson.
17  *
18  * The United States Government has rights in this work pursuant
19  * to contract no. DE-AC03-76SF00098 between the United States
20  * Department of Energy and the University of California.
21  *
22  * Redistribution and use in source and binary forms are permitted provided
23  * that: (1) source distributions retain this entire copyright notice and
24  * comment, and (2) distributions including binaries display the following
25  * acknowledgement: ``This product includes software developed by the
26  * University of California, Berkeley and its contributors'' in the
27  * documentation or other materials provided with the distribution and in
28  * all advertising materials mentioning features or use of this software.
29  * Neither the name of the University nor the names of its contributors may
30  * be used to endorse or promote products derived from this software without
31  * specific prior written permission.
32  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
33  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
34  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
35  */
36 
37 #include <ctype.h>
38 #include "flexdef.h"
39 #include <assert.h>
40 
41 /* ANSI C does not guarantee that isascii() is defined */
42 #ifndef isascii
43 #define isascii(c) ((c) <= 0177)
44 #endif
45 
46 
47 
48 /* declare functions that have forward references */
49 
50 void dataflush (void);
51 int otoi (Char []);
52 
53 
54 /* action_out - write the actions from the temporary file to lex.yy.c
55  *
56  * synopsis
57  * action_out();
58  *
59  * Copies the action file up to %% (or end-of-file) to lex.yy.c
60  */
61 
62 void action_out(void)
63 {
64  char buf[MAXLINE];
65 
66  while ( fgets( buf, MAXLINE, temp_action_file ) != NULL )
67  if ( buf[0] == '%' && buf[1] == '%' )
68  break;
69  else
70  fputs( buf, stdout );
71  }
72 
73 
74 /* allocate_array - allocate memory for an integer array of the given size */
75 
76 void *allocate_array(int size, int element_size)
77 {
78  void *mem;
79 
80  /* on 16-bit int machines (e.g., 80286) we might be trying to
81  * allocate more than a signed int can hold, and that won't
82  * work. Cheap test:
83  */
84  if ( element_size * size <= 0 )
85  flexfatal( "request for < 1 byte in allocate_array()" );
86 
87  mem = (void *) malloc( (unsigned) (element_size * size) );
88 
89  if ( mem == NULL )
90  flexfatal( "memory allocation failed in allocate_array()" );
91 
92  return ( mem );
93  }
94 
95 
96 /* all_lower - true if a string is all lower-case
97  *
98  * synopsis:
99  * Char *str;
100  * int all_lower();
101  * true/false = all_lower( str );
102  */
103 
105 {
106  while ( *str )
107  {
108  if ( ! isascii( (int) *str ) || ! islower( (int) *str ) )
109  return ( 0 );
110  ++str;
111  }
112 
113  return ( 1 );
114  }
115 
116 
117 /* all_upper - true if a string is all upper-case
118  *
119  * synopsis:
120  * Char *str;
121  * int all_upper();
122  * true/false = all_upper( str );
123  */
124 
126 {
127  while ( *str )
128  {
129  if ( ! isascii( (int) *str ) || ! isupper( (int) *str ) )
130  return ( 0 );
131  ++str;
132  }
133 
134  return ( 1 );
135  }
136 
137 
138 /* bubble - bubble sort an integer array in increasing order
139  *
140  * synopsis
141  * int v[n], n;
142  * bubble( v, n );
143  *
144  * description
145  * sorts the first n elements of array v and replaces them in
146  * increasing order.
147  *
148  * passed
149  * v - the array to be sorted
150  * n - the number of elements of 'v' to be sorted */
151 
152 void bubble(int v[], int n)
153 {
154  int i, j, k;
155 
156  for ( i = n; i > 1; --i )
157  for ( j = 1; j < i; ++j )
158  if ( v[j] > v[j + 1] ) /* compare */
159  {
160  k = v[j]; /* exchange */
161  v[j] = v[j + 1];
162  v[j + 1] = k;
163  }
164  }
165 
166 
167 /* clower - replace upper-case letter to lower-case
168  *
169  * synopsis:
170  * Char clower();
171  * int c;
172  * c = clower( c );
173  */
174 
175 Char clower(int c)
176 {
177  return ( (isascii( c ) && isupper( c )) ? tolower( c ) : c );
178  }
179 
180 
181 /* copy_string - returns a dynamically allocated copy of a string
182  *
183  * synopsis
184  * char *str, *copy, *copy_string();
185  * copy = copy_string( str );
186  */
187 
188 char *copy_string(char *str)
189 {
190  char *c;
191  char *copy;
192 
193  /* find length */
194  for ( c = str; *c; ++c )
195  ;
196 
197  copy = malloc( (unsigned) ((c - str + 1) * sizeof( char )) );
198 
199  if ( copy == NULL )
200  flexfatal( "dynamic memory failure in copy_string()" );
201 
202  for ( c = copy; (*c++ = *str++); )
203  ;
204 
205  return ( copy );
206  }
207 
208 
209 /* copy_unsigned_string -
210  * returns a dynamically allocated copy of a (potentially) unsigned string
211  *
212  * synopsis
213  * Char *str, *copy, *copy_unsigned_string();
214  * copy = copy_unsigned_string( str );
215  */
216 
218 {
219  Char *c;
220  Char *copy;
221 
222  /* find length */
223  for ( c = str; *c; ++c )
224  ;
225 
226  copy = (Char *) malloc( (unsigned) ((c - str + 1) * sizeof( Char )) );
227 
228  if ( copy == NULL )
229  flexfatal( "dynamic memory failure in copy_unsigned_string()" );
230 
231  for ( c = copy; (*c++ = *str++); )
232  ;
233 
234  return ( copy );
235  }
236 
237 
238 /* cshell - shell sort a character array in increasing order
239  *
240  * synopsis
241  *
242  * Char v[n];
243  * int n, special_case_0;
244  * cshell( v, n, special_case_0 );
245  *
246  * description
247  * does a shell sort of the first n elements of array v.
248  * If special_case_0 is true, then any element equal to 0
249  * is instead assumed to have infinite weight.
250  *
251  * passed
252  * v - array to be sorted
253  * n - number of elements of v to be sorted
254  */
255 
256 void cshell(Char *v, int n, int special_case_0)
257 {
258  int gap, i, j, jg;
259  Char k;
260 
261  for ( gap = n / 2; gap > 0; gap = gap / 2 )
262  for ( i = gap; i < n; ++i )
263  for ( j = i - gap; j >= 0; j = j - gap )
264  {
265  jg = j + gap;
266 
267  if ( special_case_0 )
268  {
269  if ( v[jg] == 0 )
270  break;
271 
272  else if ( v[j] != 0 && v[j] <= v[jg] )
273  break;
274  }
275 
276  else if ( v[j] <= v[jg] )
277  break;
278 
279  k = v[j];
280  v[j] = v[jg];
281  v[jg] = k;
282  }
283  }
284 
285 
286 /* dataend - finish up a block of data declarations
287  *
288  * synopsis
289  * dataend();
290  */
291 
292 void dataend(void)
293 {
294  if ( datapos > 0 )
295  dataflush();
296 
297  /* add terminator for initialization */
298  puts( " } ;\n" );
299 
300  dataline = 0;
301  datapos = 0;
302  }
303 
304 
305 
306 /* dataflush - flush generated data statements
307  *
308  * synopsis
309  * dataflush();
310  */
311 
312 void dataflush(void)
313 {
314  putchar( '\n' );
315 
316  if ( ++dataline >= NUMDATALINES )
317  {
318  /* put out a blank line so that the table is grouped into
319  * large blocks that enable the user to find elements easily
320  */
321  putchar( '\n' );
322  dataline = 0;
323  }
324 
325  /* reset the number of characters written on the current line */
326  datapos = 0;
327  }
328 
329 
330 /* flexerror - report an error message and terminate
331  *
332  * synopsis
333  * char msg[];
334  * flexerror( msg );
335  */
336 
337 void flexerror(char *msg)
338 {
339  fprintf( stderr, "%s: %s\n", program_name, msg );
340 
341  flexend( 1 );
342  }
343 
344 
345 /* flexfatal - report a fatal error message and terminate
346  *
347  * synopsis
348  * char msg[];
349  * flexfatal( msg );
350  */
351 
352 void flexfatal(char *msg)
353 {
354  fprintf( stderr, "%s: fatal internal error, %s\n", program_name, msg );
355  flexend( 1 );
356  }
357 
358 
359 /* flex_gettime - return current time
360  *
361  * synopsis
362  * char *flex_gettime(), *time_str;
363  * time_str = flex_gettime();
364  *
365  * note
366  * the routine name has the "flex_" prefix because of name clashes
367  * with Turbo-C
368  */
369 
370 /* include sys/types.h to use time_t and make lint happy */
371 
372 #ifndef MS_DOS
373 #include <sys/types.h>
374 #endif
375 
376 #ifdef MS_DOS
377 #include <time.h>
378 typedef long time_t;
379 #endif
380 
381 char *flex_gettime(void)
382 {
383  time_t t, time(time_t *);
384  char *result, *ctime(const time_t *), *copy_string(char *str);
385 
386  t = time( NULL );
387 
388  result = copy_string( ctime( &t ) );
389 
390  /* get rid of trailing newline */
391  result[24] = '\0';
392 
393  return ( result );
394  }
395 
396 
397 /* lerrif - report an error message formatted with one integer argument
398  *
399  * synopsis
400  * char msg[];
401  * int arg;
402  * lerrif( msg, arg );
403  */
404 
405 void lerrif(char *msg, int arg)
406 {
407  char errmsg[MAXLINE];
408  (void) sprintf( errmsg, msg, arg );
409  flexerror( errmsg );
410  }
411 
412 
413 /* lerrsf - report an error message formatted with one string argument
414  *
415  * synopsis
416  * char msg[], arg[];
417  * lerrsf( msg, arg );
418  */
419 
420 void lerrsf(char *msg, char *arg)
421 {
422  char errmsg[MAXLINE];
423 
424  (void) sprintf( errmsg, msg, arg );
425  flexerror( errmsg );
426  }
427 
428 
429 /* htoi - convert a hexadecimal digit string to an integer value
430  *
431  * synopsis:
432  * int val, htoi();
433  * Char str[];
434  * val = htoi( str );
435  */
436 
437 int htoi(unsigned char *str)
438 {
439  int result;
440 
441  (void) sscanf( (char *) str, "%x", &result );
442 
443  return ( result );
444  }
445 
446 
447 /* is_hex_digit - returns true if a character is a valid hex digit, false
448  * otherwise
449  *
450  * synopsis:
451  * int true_or_false, is_hex_digit();
452  * int ch;
453  * val = is_hex_digit( ch );
454  */
455 
456 int is_hex_digit(int ch)
457 {
458  if ( isdigit( ch ) )
459  return ( 1 );
460 
461  switch ( clower( ch ) )
462  {
463  case 'a':
464  case 'b':
465  case 'c':
466  case 'd':
467  case 'e':
468  case 'f':
469  return ( 1 );
470 
471  default:
472  return ( 0 );
473  }
474  }
475 
476 
477 /* line_directive_out - spit out a "# line" statement */
478 
480 {
481  if ( infilename && gen_line_dirs )
482  fprintf( output_file_name, "# line %d \"%s\"\n", linenum, infilename );
483  }
484 
485 
486 /* mk2data - generate a data statement for a two-dimensional array
487  *
488  * synopsis
489  * int value;
490  * mk2data( value );
491  *
492  * generates a data statement initializing the current 2-D array to "value"
493  */
494 void mk2data(int value)
495 {
496  if ( datapos >= NUMDATAITEMS )
497  {
498  putchar( ',' );
499  dataflush();
500  }
501 
502  if ( datapos == 0 )
503  /* indent */
504  fputs( " ", stdout );
505 
506  else
507  putchar( ',' );
508 
509  ++datapos;
510 
511  printf( "%5d", value );
512  }
513 
514 
515 /* mkdata - generate a data statement
516  *
517  * synopsis
518  * int value;
519  * mkdata( value );
520  *
521  * generates a data statement initializing the current array element to
522  * "value"
523  */
524 void mkdata(int value)
525 {
526  if ( datapos >= NUMDATAITEMS )
527  {
528  putchar( ',' );
529  dataflush();
530  }
531 
532  if ( datapos == 0 )
533  /* indent */
534  fputs( " ", stdout );
535 
536  else
537  putchar( ',' );
538 
539  ++datapos;
540 
541  printf( "%5d", value );
542  }
543 
544 
545 /* myctoi - return the integer represented by a string of digits
546  *
547  * synopsis
548  * Char array[];
549  * int val, myctoi();
550  * val = myctoi( array );
551  *
552  */
553 
554 int myctoi(Char *array)
555 {
556  int val = 0;
557 
558  (void) sscanf( (char *) array, "%d", &val );
559 
560  return ( val );
561  }
562 
563 
564 /* myesc - return character corresponding to escape sequence
565  *
566  * synopsis
567  * Char array[], c, myesc();
568  * c = myesc( array );
569  *
570  */
571 
572 Char myesc(Char *array)
573 {
574  Char c, esc_char;
575  int sptr;
576 
577  switch ( array[1] )
578  {
579  case 'a': return ( '\a' );
580  case 'b': return ( '\b' );
581  case 'f': return ( '\f' );
582  case 'n': return ( '\n' );
583  case 'r': return ( '\r' );
584  case 't': return ( '\t' );
585  case 'v': return ( '\v' );
586 
587  case '0':
588  case '1':
589  case '2':
590  case '3':
591  case '4':
592  case '5':
593  case '6':
594  case '7':
595  case '8':
596  case '9':
597  { /* <octal> */
598  sptr = 1;
599 
600  while ( isascii( array[sptr] ) && isdigit( array[sptr] ) )
601  /* don't increment inside loop control because if
602  * isdigit() is a macro it might expand into multiple
603  * increments ...
604  */
605  ++sptr;
606 
607  c = array[sptr];
608  array[sptr] = '\0';
609 
610  esc_char = otoi( array + 1 );
611 
612  array[sptr] = c;
613 
614  return ( esc_char );
615  }
616 
617  case 'x':
618  { /* \x<hex> */
619  int sptr = 2;
620 
621  while ( isascii( array[sptr] ) && is_hex_digit( array[sptr] ) )
622  /* don't increment inside loop control because if
623  * isdigit() is a macro it might expand into multiple
624  * increments ...
625  */
626  ++sptr;
627 
628  c = array[sptr];
629  array[sptr] = '\0';
630 
631  esc_char = htoi( array + 2 );
632 
633  array[sptr] = c;
634 
635  return ( esc_char );
636  }
637 
638  default:
639  return ( array[1] );
640  }
641  }
642 
643 
644 /* otoi - convert an octal digit string to an integer value
645  *
646  * synopsis:
647  * int val, otoi();
648  * Char str[];
649  * val = otoi( str );
650  */
651 
652 int otoi(Char *str)
653 {
654  int result;
655 
656  (void) sscanf( (char *) str, "%o", &result );
657 
658  return ( result );
659  }
660 
661 
662 /* readable_form - return the the human-readable form of a character
663  *
664  * synopsis:
665  * int c;
666  * char *readable_form();
667  * <string> = readable_form( c );
668  *
669  * The returned string is in static storage.
670  */
671 
672 char *readable_form(int c)
673 {
674  static char rform[10];
675 
676  if ( (c >= 0 && c < 32) || c >= 127 )
677  {
678  switch ( c )
679  {
680  case '\n': return ( "\\n" );
681  case '\t': return ( "\\t" );
682  case '\f': return ( "\\f" );
683  case '\r': return ( "\\r" );
684  case '\b': return ( "\\b" );
685 
686  default:
687  (void) sprintf( rform, "\\%.3o", c );
688  return ( rform );
689  }
690  }
691 
692  else if ( c == ' ' )
693  return ( "' '" );
694 
695  else
696  {
697  rform[0] = c;
698  rform[1] = '\0';
699 
700  return ( rform );
701  }
702  }
703 
704 
705 /* reallocate_array - increase the size of a dynamic array */
706 
707 void *reallocate_array(void *array, int size, int element_size)
708 {
709  void *new_array;
710 
711  /* same worry as in allocate_array(): */
712  if ( size * element_size <= 0 )
713  flexfatal( "attempt to increase array size by less than 1 byte" );
714 
715  new_array =
716  (void *) realloc( (char *)array, (unsigned) (size * element_size ));
717 
718  if ( new_array == NULL )
719  flexfatal( "attempt to increase array size failed" );
720 
721  return ( new_array );
722  }
723 
724 
725 /* skelout - write out one section of the skeleton file
726  *
727  * synopsis
728  * skelout();
729  *
730  * DESCRIPTION
731  * Copies from skelfile to stdout until a line beginning with "%%" or
732  * EOF is found.
733  */
734 void skelout(void)
735 {
736  char buf[MAXLINE];
737 
738  while ( fgets( buf, MAXLINE, skelfile ) != NULL )
739  if ( buf[0] == '%' && buf[1] == '%' )
740  break;
741  else
742  fputs( buf, stdout );
743  }
744 
745 
746 /* transition_struct_out - output a yy_trans_info structure
747  *
748  * synopsis
749  * int element_v, element_n;
750  * transition_struct_out( element_v, element_n );
751  *
752  * outputs the yy_trans_info structure with the two elements, element_v and
753  * element_n. Formats the output with spaces and carriage returns.
754  */
755 
756 void transition_struct_out(int element_v, int element_n)
757 {
758  printf( "%7d, %5d,", element_v, element_n );
759 
761 
762  if ( datapos >= 75 )
763  {
764  putchar( '\n' );
765 
766  if ( ++dataline % 10 == 0 )
767  putchar( '\n' );
768 
769  datapos = 0;
770  }
771  }
Definition: link.h:174
pvac::PutEvent result
Definition: clientSync.cpp:117
int myctoi(Char *array)
Definition: misc.c:554
int i
Definition: scan.c:967
void mkdata(int value)
Definition: misc.c:524
int is_hex_digit(int ch)
Definition: misc.c:456
#define printf
Definition: epicsStdio.h:41
Char clower(int c)
Definition: misc.c:175
void action_out(void)
Definition: misc.c:62
#define NULL
Definition: catime.c:38
void flexfatal(char *msg)
Definition: misc.c:352
int linenum
Definition: flex.c:71
#define str(v)
#define NUMDATALINES
Definition: flexdef.h:104
int htoi(unsigned char *str)
Definition: misc.c:437
char * readable_form(int c)
Definition: misc.c:672
int all_upper(Char *str)
Definition: misc.c:125
void copy(PVValueArray< T > &pvFrom, size_t fromOffset, size_t fromStride, PVValueArray< T > &pvTo, size_t toOffset, size_t toStride, size_t count)
Copy a subarray from one scalar array to another.
char * flex_gettime(void)
Definition: misc.c:381
void mk2data(int value)
Definition: misc.c:494
#define puts
Definition: epicsStdio.h:46
void line_directive_out(FILE *output_file_name)
Definition: misc.c:479
void flexerror(char *msg)
Definition: misc.c:337
void bubble(int v[], int n)
Definition: misc.c:152
#define putchar
Definition: epicsStdio.h:51
char * copy_string(char *str)
Definition: misc.c:188
Char myesc(Char *array)
Definition: misc.c:572
#define Char
Definition: flexdef.h:59
char * infilename
Definition: flex.c:73
int otoi(Char[])
int datapos
Definition: flex.c:71
#define NUMDATAITEMS
Definition: flexdef.h:99
#define stdout
Definition: epicsStdio.h:30
#define MAXLINE
Definition: flexdef.h:72
int gen_line_dirs
Definition: flex.c:68
int all_lower(Char *str)
Definition: misc.c:104
Char * copy_unsigned_string(Char *str)
Definition: misc.c:217
char * program_name
Definition: flex.c:108
#define TRANS_STRUCT_PRINT_LENGTH
Definition: flexdef.h:107
void lerrsf(char *msg, char *arg)
Definition: misc.c:420
void flexend(int status)
Definition: flex.c:196
void dataend(void)
Definition: misc.c:292
FILE * temp_action_file
Definition: flex.c:103
void * reallocate_array(void *array, int size, int element_size)
Definition: misc.c:707
void dataflush(void)
Definition: misc.c:312
FILE * skelfile
Definition: flex.c:72
int dataline
Definition: flex.c:71
void * allocate_array(int size, int element_size)
Definition: misc.c:76
#define stderr
Definition: epicsStdio.h:32
#define isascii(c)
Definition: misc.c:43
char * output_file_name
Definition: antelope.c:39
void skelout(void)
Definition: misc.c:734
void cshell(Char *v, int n, int special_case_0)
Definition: misc.c:256
void transition_struct_out(int element_v, int element_n)
Definition: misc.c:756
void lerrif(char *msg, int arg)
Definition: misc.c:405