misc.c 16 KB

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