misc.c 15 KB

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