Remove some __STDC__ checks.
[dragonfly.git] / usr.bin / lex / misc.c
CommitLineData
984263bc
MD
1/* misc - miscellaneous flex routines */
2
3/*-
4 * Copyright (c) 1990 The Regents of the University of California.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Vern Paxson.
9 *
10 * The United States Government has rights in this work pursuant
11 * to contract no. DE-AC03-76SF00098 between the United States
12 * Department of Energy and the University of California.
13 *
14 * Redistribution and use in source and binary forms are permitted provided
15 * that: (1) source distributions retain this entire copyright notice and
16 * comment, and (2) distributions including binaries display the following
17 * acknowledgement: ``This product includes software developed by the
18 * University of California, Berkeley and its contributors'' in the
19 * documentation or other materials provided with the distribution and in
20 * all advertising materials mentioning features or use of this software.
21 * Neither the name of the University nor the names of its contributors may
22 * be used to endorse or promote products derived from this software without
23 * specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
25 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27 */
28
29/* $Header: /home/daffy/u0/vern/flex/RCS/misc.c,v 2.47 95/04/28 11:39:39 vern Exp $ */
30/* $FreeBSD: src/usr.bin/lex/misc.c,v 1.5 1999/10/27 07:56:45 obrien Exp $ */
31
32#include "flexdef.h"
33
34
1d1731fa 35void action_define(char *defname, int value)
984263bc
MD
36 {
37 char buf[MAXLINE];
38
39 if ( (int) strlen( defname ) > MAXLINE / 2 )
40 {
41 format_pinpoint_message( _( "name \"%s\" ridiculously long" ),
42 defname );
43 return;
44 }
45
46 sprintf( buf, "#define %s %d\n", defname, value );
47 add_action( buf );
48 }
49
50
1d1731fa 51void add_action(char *new_text)
984263bc
MD
52 {
53 int len = strlen( new_text );
54
55 while ( len + action_index >= action_size - 10 /* slop */ )
56 {
57 int new_size = action_size * 2;
58
59 if ( new_size <= 0 )
60 /* Increase just a little, to try to avoid overflow
61 * on 16-bit machines.
62 */
63 action_size += action_size / 8;
64 else
65 action_size = new_size;
66
67 action_array =
68 reallocate_character_array( action_array, action_size );
69 }
70
71 strcpy( &action_array[action_index], new_text );
72
73 action_index += len;
74 }
75
76
77/* allocate_array - allocate memory for an integer array of the given size */
78
1d1731fa 79void *allocate_array(int size, size_t element_size)
984263bc 80 {
6bd457ed 81 void *mem;
984263bc
MD
82 size_t num_bytes = element_size * size;
83
84 mem = flex_alloc( num_bytes );
85 if ( ! mem )
86 flexfatal(
87 _( "memory allocation failed in allocate_array()" ) );
88
89 return mem;
90 }
91
92
93/* all_lower - true if a string is all lower-case */
94
6bd457ed 95int all_lower(char *str)
984263bc
MD
96 {
97 while ( *str )
98 {
99 if ( ! isascii( (Char) *str ) || ! islower( *str ) )
100 return 0;
101 ++str;
102 }
103
104 return 1;
105 }
106
107
108/* all_upper - true if a string is all upper-case */
109
6bd457ed 110int all_upper(char *str)
984263bc
MD
111 {
112 while ( *str )
113 {
114 if ( ! isascii( (Char) *str ) || ! isupper( *str ) )
115 return 0;
116 ++str;
117 }
118
119 return 1;
120 }
121
122
123/* bubble - bubble sort an integer array in increasing order
124 *
125 * synopsis
126 * int v[n], n;
127 * void bubble( v, n );
128 *
129 * description
130 * sorts the first n elements of array v and replaces them in
131 * increasing order.
132 *
133 * passed
134 * v - the array to be sorted
135 * n - the number of elements of 'v' to be sorted
136 */
137
1d1731fa 138void bubble(int *v, int n)
984263bc 139 {
6bd457ed 140 int i, j, k;
984263bc
MD
141
142 for ( i = n; i > 1; --i )
143 for ( j = 1; j < i; ++j )
144 if ( v[j] > v[j + 1] ) /* compare */
145 {
146 k = v[j]; /* exchange */
147 v[j] = v[j + 1];
148 v[j + 1] = k;
149 }
150 }
151
152
153/* check_char - checks a character to make sure it's within the range
154 * we're expecting. If not, generates fatal error message
155 * and exits.
156 */
157
1d1731fa 158void check_char(int c)
984263bc
MD
159 {
160 if ( c >= CSIZE )
161 lerrsf( _( "bad character '%s' detected in check_char()" ),
162 readable_form( c ) );
163
164 if ( c >= csize )
165 lerrsf(
166 _( "scanner requires -8 flag to use the character %s" ),
167 readable_form( c ) );
168 }
169
170
171
172/* clower - replace upper-case letter to lower-case */
173
6bd457ed 174Char clower(int c)
984263bc
MD
175 {
176 return (Char) ((isascii( c ) && isupper( c )) ? tolower( c ) : c);
177 }
178
179
180/* copy_string - returns a dynamically allocated copy of a string */
181
6bd457ed 182char *copy_string(const char *str)
984263bc 183 {
6bd457ed
DR
184 const char *c1;
185 char *c2;
984263bc
MD
186 char *copy;
187 unsigned int size;
188
189 /* find length */
190 for ( c1 = str; *c1; ++c1 )
191 ;
192
193 size = (c1 - str + 1) * sizeof( char );
194 copy = (char *) flex_alloc( size );
195
196 if ( copy == NULL )
197 flexfatal( _( "dynamic memory failure in copy_string()" ) );
198
199 for ( c2 = copy; (*c2++ = *str++) != 0; )
200 ;
201
202 return copy;
203 }
204
205
206/* copy_unsigned_string -
207 * returns a dynamically allocated copy of a (potentially) unsigned string
208 */
209
6bd457ed 210Char *copy_unsigned_string(Char *str)
984263bc 211 {
6bd457ed 212 Char *c;
984263bc
MD
213 Char *copy;
214
215 /* find length */
216 for ( c = str; *c; ++c )
217 ;
218
219 copy = allocate_Character_array( c - str + 1 );
220
221 for ( c = copy; (*c++ = *str++) != 0; )
222 ;
223
224 return copy;
225 }
226
227
228/* cshell - shell sort a character array in increasing order
229 *
230 * synopsis
231 *
232 * Char v[n];
233 * int n, special_case_0;
234 * cshell( v, n, special_case_0 );
235 *
236 * description
237 * Does a shell sort of the first n elements of array v.
238 * If special_case_0 is true, then any element equal to 0
239 * is instead assumed to have infinite weight.
240 *
241 * passed
242 * v - array to be sorted
243 * n - number of elements of v to be sorted
244 */
245
1d1731fa 246void cshell(Char *v, int n, int special_case_0)
984263bc
MD
247 {
248 int gap, i, j, jg;
249 Char k;
250
251 for ( gap = n / 2; gap > 0; gap = gap / 2 )
252 for ( i = gap; i < n; ++i )
253 for ( j = i - gap; j >= 0; j = j - gap )
254 {
255 jg = j + gap;
256
257 if ( special_case_0 )
258 {
259 if ( v[jg] == 0 )
260 break;
261
262 else if ( v[j] != 0 && v[j] <= v[jg] )
263 break;
264 }
265
266 else if ( v[j] <= v[jg] )
267 break;
268
269 k = v[j];
270 v[j] = v[jg];
271 v[jg] = k;
272 }
273 }
274
275
276/* dataend - finish up a block of data declarations */
277
1d1731fa 278void dataend(void)
984263bc
MD
279 {
280 if ( datapos > 0 )
281 dataflush();
282
283 /* add terminator for initialization; { for vi */
284 outn( " } ;\n" );
285
286 dataline = 0;
287 datapos = 0;
288 }
289
290
291/* dataflush - flush generated data statements */
292
1d1731fa 293void dataflush(void)
984263bc
MD
294 {
295 outc( '\n' );
296
297 if ( ++dataline >= NUMDATALINES )
298 {
299 /* Put out a blank line so that the table is grouped into
300 * large blocks that enable the user to find elements easily.
301 */
302 outc( '\n' );
303 dataline = 0;
304 }
305
306 /* Reset the number of characters written on the current line. */
307 datapos = 0;
308 }
309
310
311/* flexerror - report an error message and terminate */
312
1d1731fa 313void flexerror(const char *msg)
984263bc
MD
314 {
315 fprintf( stderr, "%s: %s\n", program_name, msg );
316 flexend( 1 );
317 }
318
319
320/* flexfatal - report a fatal error message and terminate */
321
1d1731fa 322void flexfatal(const char *msg)
984263bc
MD
323 {
324 fprintf( stderr, _( "%s: fatal internal error, %s\n" ),
325 program_name, msg );
326 exit( 1 );
327 }
328
329
330/* htoi - convert a hexadecimal digit string to an integer value */
331
1d1731fa 332int htoi(Char *str)
984263bc
MD
333 {
334 unsigned int result;
335
336 (void) sscanf( (char *) str, "%x", &result );
337
338 return result;
339 }
340
341
342/* lerrif - report an error message formatted with one integer argument */
343
1d1731fa 344void lerrif(const char *msg, int arg)
984263bc
MD
345 {
346 char errmsg[MAXLINE];
347 (void) sprintf( errmsg, msg, arg );
348 flexerror( errmsg );
349 }
350
351
352/* lerrsf - report an error message formatted with one string argument */
353
1d1731fa 354void lerrsf(const char *msg, const char *arg)
984263bc
MD
355 {
356 char errmsg[MAXLINE];
357
358 (void) sprintf( errmsg, msg, arg );
359 flexerror( errmsg );
360 }
361
362
363/* line_directive_out - spit out a "#line" statement */
364
1d1731fa 365void line_directive_out(FILE *output_file, int do_infile)
984263bc
MD
366 {
367 char directive[MAXLINE], filename[MAXLINE];
368 char *s1, *s2, *s3;
369 static char line_fmt[] = "#line %d \"%s\"\n";
370
371 if ( ! gen_line_dirs )
372 return;
373
374 if ( (do_infile && ! infilename) || (! do_infile && ! outfilename) )
375 /* don't know the filename to use, skip */
376 return;
377
378 s1 = do_infile ? infilename : outfilename;
379 s2 = filename;
380 s3 = &filename[sizeof( filename ) - 2];
381
382 while ( s2 < s3 && *s1 )
383 {
384 if ( *s1 == '\\' )
385 /* Escape the '\' */
386 *s2++ = '\\';
387
388 *s2++ = *s1++;
389 }
390
391 *s2 = '\0';
392
393 if ( do_infile )
394 sprintf( directive, line_fmt, linenum, filename );
395 else
396 {
397 if ( output_file == stdout )
398 /* Account for the line directive itself. */
399 ++out_linenum;
400
401 sprintf( directive, line_fmt, out_linenum, filename );
402 }
403
404 /* If output_file is nil then we should put the directive in
405 * the accumulated actions.
406 */
407 if ( output_file )
408 {
409 fputs( directive, output_file );
410 }
411 else
412 add_action( directive );
413 }
414
415
416/* mark_defs1 - mark the current position in the action array as
417 * representing where the user's section 1 definitions end
418 * and the prolog begins
419 */
1d1731fa 420void mark_defs1(void)
984263bc
MD
421 {
422 defs1_offset = 0;
423 action_array[action_index++] = '\0';
424 action_offset = prolog_offset = action_index;
425 action_array[action_index] = '\0';
426 }
427
428
429/* mark_prolog - mark the current position in the action array as
430 * representing the end of the action prolog
431 */
1d1731fa 432void mark_prolog(void)
984263bc
MD
433 {
434 action_array[action_index++] = '\0';
435 action_offset = action_index;
436 action_array[action_index] = '\0';
437 }
438
439
440/* mk2data - generate a data statement for a two-dimensional array
441 *
442 * Generates a data statement initializing the current 2-D array to "value".
443 */
1d1731fa 444void mk2data(int value)
984263bc
MD
445 {
446 if ( datapos >= NUMDATAITEMS )
447 {
448 outc( ',' );
449 dataflush();
450 }
451
452 if ( datapos == 0 )
453 /* Indent. */
454 out( " " );
455
456 else
457 outc( ',' );
458
459 ++datapos;
460
461 out_dec( "%5d", value );
462 }
463
464
465/* mkdata - generate a data statement
466 *
467 * Generates a data statement initializing the current array element to
468 * "value".
469 */
1d1731fa 470void mkdata(int value)
984263bc
MD
471 {
472 if ( datapos >= NUMDATAITEMS )
473 {
474 outc( ',' );
475 dataflush();
476 }
477
478 if ( datapos == 0 )
479 /* Indent. */
480 out( " " );
481 else
482 outc( ',' );
483
484 ++datapos;
485
486 out_dec( "%5d", value );
487 }
488
489
490/* myctoi - return the integer represented by a string of digits */
491
1d1731fa 492int myctoi(char *array)
984263bc
MD
493 {
494 int val = 0;
495
496 (void) sscanf( array, "%d", &val );
497
498 return val;
499 }
500
501
502/* myesc - return character corresponding to escape sequence */
503
1d1731fa 504Char myesc(Char *array)
984263bc
MD
505 {
506 Char c, esc_char;
507
508 switch ( array[1] )
509 {
510 case 'b': return '\b';
511 case 'f': return '\f';
512 case 'n': return '\n';
513 case 'r': return '\r';
514 case 't': return '\t';
984263bc
MD
515 case 'a': return '\a';
516 case 'v': return '\v';
984263bc
MD
517
518 case '0':
519 case '1':
520 case '2':
521 case '3':
522 case '4':
523 case '5':
524 case '6':
525 case '7':
526 { /* \<octal> */
527 int sptr = 1;
528
529 while ( isascii( array[sptr] ) &&
530 isdigit( array[sptr] ) )
531 /* Don't increment inside loop control
532 * because if isdigit() is a macro it might
533 * expand into multiple increments ...
534 */
535 ++sptr;
536
537 c = array[sptr];
538 array[sptr] = '\0';
539
540 esc_char = otoi( array + 1 );
541
542 array[sptr] = c;
543
544 return esc_char;
545 }
546
547 case 'x':
548 { /* \x<hex> */
549 int sptr = 2;
550
551 while ( isascii( array[sptr] ) &&
552 isxdigit( (char) array[sptr] ) )
553 /* Don't increment inside loop control
554 * because if isdigit() is a macro it might
555 * expand into multiple increments ...
556 */
557 ++sptr;
558
559 c = array[sptr];
560 array[sptr] = '\0';
561
562 esc_char = htoi( array + 2 );
563
564 array[sptr] = c;
565
566 return esc_char;
567 }
568
569 default:
570 return array[1];
571 }
572 }
573
574
575/* otoi - convert an octal digit string to an integer value */
576
1d1731fa 577int otoi(Char *str)
984263bc
MD
578 {
579 unsigned int result;
580
581 (void) sscanf( (char *) str, "%o", &result );
582 return result;
583 }
584
585
586/* out - various flavors of outputing a (possibly formatted) string for the
587 * generated scanner, keeping track of the line count.
588 */
589
1d1731fa 590void out(const char *str)
984263bc
MD
591 {
592 fputs( str, stdout );
593 out_line_count( str );
594 }
595
1d1731fa 596void out_dec(const char *fmt, int n)
984263bc
MD
597 {
598 printf( fmt, n );
599 out_line_count( fmt );
600 }
601
1d1731fa 602void out_dec2(const char *fmt, int n1, int n2)
984263bc
MD
603 {
604 printf( fmt, n1, n2 );
605 out_line_count( fmt );
606 }
607
1d1731fa 608void out_hex(const char *fmt, unsigned int x)
984263bc
MD
609 {
610 printf( fmt, x );
611 out_line_count( fmt );
612 }
613
1d1731fa 614void out_line_count(const char *str)
984263bc 615 {
6bd457ed 616 int i;
984263bc
MD
617
618 for ( i = 0; str[i]; ++i )
619 if ( str[i] == '\n' )
620 ++out_linenum;
621 }
622
1d1731fa 623void out_str(const char *fmt, const char *str)
984263bc
MD
624 {
625 printf( fmt, str );
626 out_line_count( fmt );
627 out_line_count( str );
628 }
629
1d1731fa 630void out_str3(const char *fmt, const char *s1, const char *s2, const char *s3)
984263bc
MD
631 {
632 printf( fmt, s1, s2, s3 );
633 out_line_count( fmt );
634 out_line_count( s1 );
635 out_line_count( s2 );
636 out_line_count( s3 );
637 }
638
1d1731fa 639void out_str_dec(const char *fmt, const char *str, int n)
984263bc
MD
640 {
641 printf( fmt, str, n );
642 out_line_count( fmt );
643 out_line_count( str );
644 }
645
1d1731fa 646void outc(int c)
984263bc
MD
647 {
648 putc( c, stdout );
649
650 if ( c == '\n' )
651 ++out_linenum;
652 }
653
1d1731fa 654void outn(const char *str)
984263bc
MD
655 {
656 puts( str );
657 out_line_count( str );
658 ++out_linenum;
659 }
660
661
662/* readable_form - return the the human-readable form of a character
663 *
664 * The returned string is in static storage.
665 */
666
6bd457ed 667char *readable_form(int c)
984263bc
MD
668 {
669 static char rform[10];
670
671 if ( (c >= 0 && c < 32) || c >= 127 )
672 {
673 switch ( c )
674 {
675 case '\b': return "\\b";
676 case '\f': return "\\f";
677 case '\n': return "\\n";
678 case '\r': return "\\r";
679 case '\t': return "\\t";
984263bc
MD
680 case '\a': return "\\a";
681 case '\v': return "\\v";
984263bc
MD
682
683 default:
684 (void) sprintf( rform, "\\%.3o",
685 (unsigned int) c );
686 return rform;
687 }
688 }
689
690 else if ( c == ' ' )
691 return "' '";
692
693 else
694 {
695 rform[0] = c;
696 rform[1] = '\0';
697
698 return rform;
699 }
700 }
701
702
703/* reallocate_array - increase the size of a dynamic array */
704
1d1731fa 705void *reallocate_array(void *array, int size, size_t element_size)
984263bc 706 {
6bd457ed 707 void *new_array;
984263bc
MD
708 size_t num_bytes = element_size * size;
709
710 new_array = flex_realloc( array, num_bytes );
711 if ( ! new_array )
712 flexfatal( _( "attempt to increase array size failed" ) );
713
714 return new_array;
715 }
716
717
718/* skelout - write out one section of the skeleton file
719 *
720 * Description
721 * Copies skelfile or skel array to stdout until a line beginning with
722 * "%%" or EOF is found.
723 */
1d1731fa 724void skelout(void)
984263bc
MD
725 {
726 char buf_storage[MAXLINE];
727 char *buf = buf_storage;
728 int do_copy = 1;
729
730 /* Loop pulling lines either from the skelfile, if we're using
731 * one, or from the skel[] array.
732 */
733 while ( skelfile ?
734 (fgets( buf, MAXLINE, skelfile ) != NULL) :
735 ((buf = (char *) skel[skel_ind++]) != 0) )
736 { /* copy from skel array */
737 if ( buf[0] == '%' )
738 { /* control line */
739 switch ( buf[1] )
740 {
741 case '%':
742 return;
743
744 case '+':
745 do_copy = C_plus_plus;
746 break;
747
748 case '-':
749 do_copy = ! C_plus_plus;
750 break;
751
752 case '*':
753 do_copy = 1;
754 break;
755
756 default:
757 flexfatal(
758 _( "bad line in skeleton file" ) );
759 }
760 }
761
762 else if ( do_copy )
763 {
764 if ( skelfile )
765 /* Skeleton file reads include final
766 * newline, skel[] array does not.
767 */
768 out( buf );
769 else
770 outn( buf );
771 }
772 }
773 }
774
775
776/* transition_struct_out - output a yy_trans_info structure
777 *
778 * outputs the yy_trans_info structure with the two elements, element_v and
779 * element_n. Formats the output with spaces and carriage returns.
780 */
781
1d1731fa 782void transition_struct_out(int element_v, int element_n)
984263bc
MD
783 {
784 out_dec2( " {%4d,%4d },", element_v, element_n );
785
786 datapos += TRANS_STRUCT_PRINT_LENGTH;
787
788 if ( datapos >= 79 - TRANS_STRUCT_PRINT_LENGTH )
789 {
790 outc( '\n' );
791
792 if ( ++dataline % 10 == 0 )
793 outc( '\n' );
794
795 datapos = 0;
796 }
797 }
798
799
800/* The following is only needed when building flex's parser using certain
801 * broken versions of bison.
802 */
1d1731fa 803void *yy_flex_xmalloc(int size)
984263bc
MD
804 {
805 void *result = flex_alloc( (size_t) size );
806
807 if ( ! result )
808 flexfatal(
809 _( "memory allocation failed in yy_flex_xmalloc()" ) );
810
811 return result;
812 }
813
814
815/* zero_out - set a region of memory to 0
816 *
817 * Sets region_ptr[0] through region_ptr[size_in_bytes - 1] to zero.
818 */
819
1d1731fa 820void zero_out(char *region_ptr, size_t size_in_bytes )
984263bc 821 {
6bd457ed 822 char *rp, *rp_end;
984263bc
MD
823
824 rp = region_ptr;
825 rp_end = region_ptr + size_in_bytes;
826
827 while ( rp < rp_end )
828 *rp++ = 0;
829 }