Sweep-fix comparing pointers with 0 (and assigning 0 to pointers).
[dragonfly.git] / usr.bin / lex / misc.c
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
35 void action_define(char *defname, int value)
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
51 void add_action(char *new_text)
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
79 void *allocate_array(int size, size_t element_size)
80         {
81         void *mem;
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
95 int all_lower(char *str)
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
110 int all_upper(char *str)
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
138 void bubble(int *v, int n)
139         {
140         int i, j, k;
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
158 void check_char(int c)
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
174 Char clower(int c)
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
182 char *copy_string(const char *str)
183         {
184         const char *c1;
185         char *c2;
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
210 Char *copy_unsigned_string(Char *str)
211         {
212         Char *c;
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
246 void cshell(Char *v, int n, int special_case_0)
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
278 void dataend(void)
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
293 void dataflush(void)
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
313 void flexerror(const char *msg)
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
322 void flexfatal(const char *msg)
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
332 int htoi(Char *str)
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
344 void lerrif(const char *msg, int arg)
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
354 void lerrsf(const char *msg, const char *arg)
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
365 void line_directive_out(FILE *output_file, int do_infile)
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  */
420 void mark_defs1(void)
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  */
432 void mark_prolog(void)
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  */
444 void mk2data(int value)
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  */
470 void mkdata(int value)
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
492 int myctoi(char *array)
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
504 Char myesc(Char *array)
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';
515                 case 'a': return '\a';
516                 case 'v': return '\v';
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
577 int otoi(Char *str)
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
590 void out(const char *str)
591         {
592         fputs( str, stdout );
593         out_line_count( str );
594         }
595
596 void out_dec(const char *fmt, int n)
597         {
598         printf( fmt, n );
599         out_line_count( fmt );
600         }
601
602 void out_dec2(const char *fmt, int n1, int n2)
603         {
604         printf( fmt, n1, n2 );
605         out_line_count( fmt );
606         }
607
608 void out_hex(const char *fmt, unsigned int x)
609         {
610         printf( fmt, x );
611         out_line_count( fmt );
612         }
613
614 void out_line_count(const char *str)
615         {
616         int i;
617
618         for ( i = 0; str[i]; ++i )
619                 if ( str[i] == '\n' )
620                         ++out_linenum;
621         }
622
623 void out_str(const char *fmt, const char *str)
624         {
625         printf( fmt, str );
626         out_line_count( fmt );
627         out_line_count( str );
628         }
629
630 void out_str3(const char *fmt, const char *s1, const char *s2, const char *s3)
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
639 void out_str_dec(const char *fmt, const char *str, int n)
640         {
641         printf( fmt, str, n );
642         out_line_count( fmt );
643         out_line_count( str );
644         }
645
646 void outc(int c)
647         {
648         putc( c, stdout );
649
650         if ( c == '\n' )
651                 ++out_linenum;
652         }
653
654 void outn(const char *str)
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
667 char *readable_form(int c)
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";
680                         case '\a': return "\\a";
681                         case '\v': return "\\v";
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
705 void *reallocate_array(void *array, int size, size_t element_size)
706         {
707         void *new_array;
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  */
724 void skelout(void)
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++]) != NULL) )
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
782 void transition_struct_out(int element_v, int element_n)
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  */
803 void *yy_flex_xmalloc(int size)
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
820 void zero_out(char *region_ptr, size_t size_in_bytes )
821         {
822         char *rp, *rp_end;
823
824         rp = region_ptr;
825         rp_end = region_ptr + size_in_bytes;
826
827         while ( rp < rp_end )
828                 *rp++ = 0;
829         }