Improve the process for GNU tools
[minix3.git] / external / bsd / flex / dist / tests / test-pthread / scanner.l
blob8603873808a65e457bc83676df074f6456057868
1 /*
2  * This file is part of flex.
3  * 
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 
14  * Neither the name of the University nor the names of its contributors
15  * may be used to endorse or promote products derived from this software
16  * without specific prior written permission.
17  * 
18  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE.
22  */
25 /* A scanner file to build "scanner.c".
26    Input language is any text made of spaces, newlines, and alphanumerics.
28    We create N_THREADS number of threads. Each thread has it's own scanner.
29    Each thread selects one of the files specified in ARGV, scans it, then
30    closes it. This is repeated N_SCANS numebr of times for each thread.
32    The idea is to press the scanner to break under threads.
33    If we see  "Scanner Jammed", then we know
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <config.h>
40 #ifdef HAVE_PTHREAD_H
41 #include <pthread.h>
42 #endif
44 /* A naive test for segfaults when accessing yytext. */
45 static int process_text(char* s, yyscan_t  scanner);
49 %option 8bit outfile="scanner.c" prefix="test"
50 %option nounput nomain nodefault
51 %option yywrap
52 %option reentrant
53 %option warn
55     /* Arbitrary states.*/
56 %x STATE_1
57 %x STATE_2
61     #define NUMBER 200
62     #define WORD   201
64 <INITIAL>[[:digit:]]+ { BEGIN(STATE_1); process_text(yytext,yyscanner); return NUMBER; }
65 <INITIAL>[[:alpha:]]+ { BEGIN(STATE_2); process_text(yytext,yyscanner); return WORD; }
67 <STATE_1>[[:alpha:]]+ { BEGIN(0); process_text(yytext,yyscanner); return WORD; }
68 <STATE_1>[[:digit:]]+ { BEGIN(0); process_text(yytext,yyscanner); return NUMBER; }
70 <STATE_2>[[:alpha:]]+ { BEGIN(0); process_text(yytext,yyscanner); return WORD; }
71 <STATE_2>[[:digit:]]+ { BEGIN(0); process_text(yytext,yyscanner); return NUMBER; }
73 <INITIAL,STATE_1,STATE_2>" "|\t|\r|\n { process_text(yytext,yyscanner); }
74 <INITIAL,STATE_1,STATE_2>[^[:alnum:][:space:]\t\r\n] {
75         /*fprintf(stderr,"*** Error: bad input char '%c'.\n", yytext[0]); */
76         yyterminate();
77     }
78 <INITIAL,STATE_1,STATE_2>[[:space:]\r\n]+  { }
81 int yywrap( yyscan_t  scanner) { return 1; }
82 static int process_text(char* s, yyscan_t  scanner)
84     return (int)(*s) + (int) *(s + yyget_leng(scanner)-1);
87 int main(int ARGC, char *ARGV[]);
89 #ifndef HAVE_LIBPTHREAD
90   int main (int ARGC, char *ARGV[]) {
91     printf(
92        "TEST ABORTED because pthread library not available \n"
93        "-- This is expected on some systems. It is not a flex error.\n" );
94     return 0;
95   }
96 #else
98 #define N_THREADS 4
99 #define N_SCANS   20
100 #define INPUT_FILE "test.input"
102 /* Each thread selects the next file to scan in round-robin fashion.
103    If there are less files than threads, some threads may block. */
105 static pthread_mutex_t next_lock = PTHREAD_MUTEX_INITIALIZER;
106 static pthread_mutex_t go_ahead  = PTHREAD_MUTEX_INITIALIZER;
107 static int n_files, next_file;
109 static pthread_mutex_t *file_locks;
110 static char **filenames;
113 void * thread_func ( void* arg )
115     int i;
117     /* Wait for go-ahead. */
118     pthread_mutex_lock( &go_ahead);
119     pthread_mutex_unlock(&go_ahead);
121     for( i =0 ; i < N_SCANS ; i++ )
122     {
123         int main(int ARGC, char *ARGV[]);
125         int next;
126         yyscan_t  scanner;
127         FILE * fp;
129         pthread_mutex_lock ( &next_lock );
130         next = (next_file++) % n_files;
131         pthread_mutex_unlock ( &next_lock );
133         pthread_mutex_lock ( &file_locks[ next ] );
135         yylex_init( &scanner );
136         /*printf("Scanning file %s  #%d\n",filenames[next],i); fflush(stdout); */
137         if((fp = fopen(filenames[next],"r"))==NULL) {
138             perror("fopen");
139             return NULL;
140         }
141         yyset_in(fp,scanner);
143         while( yylex( scanner) != 0)
144         {
145         }
146         fclose(fp);
147         yylex_destroy(scanner);
148         pthread_mutex_unlock ( &file_locks[ next ] );
149     }
150     return NULL;
153 int main (int ARGC, char *ARGV[])
155     int i;
156     pthread_t threads[N_THREADS];
158     if( ARGC < 2 ) {
159         fprintf(stderr,"*** Error: No filenames specified.\n");
160         exit(-1);
161     }
163     /* Allocate and initialize the locks. One for each filename in ARGV. */
164     file_locks = (pthread_mutex_t*)malloc( (ARGC-1) * sizeof(pthread_mutex_t));
165     for( i = 0; i < ARGC-1; i++)
166         pthread_mutex_init( &file_locks[i], NULL );
168     n_files = ARGC -1;
169     filenames = ARGV + 1;
170     next_file = 0;
172     /* prevent threads from starting until all threads have been created. */
173     pthread_mutex_lock(&go_ahead);
175     /* Create N threads then wait for them. */
176     for(i =0; i < N_THREADS ; i++ ) {
177         if( pthread_create( &threads[i], NULL, thread_func, NULL) != 0)
178         {
179             fprintf(stderr, "*** Error: pthread_create failed.\n");
180             exit(-1);
181         }
182         printf("Created thread %d.\n",i); fflush(stdout);
183     }
185     /* Tell threads to begin. */
186     pthread_mutex_unlock(&go_ahead);
188     for(i =0; i < N_THREADS ; i++ ) {
189         pthread_join ( threads[i], NULL );
190         printf("Thread %d done.\n", i ); fflush(stdout);
191     }
193     for( i = 0; i < ARGC-1; i++)
194         pthread_mutex_destroy( &file_locks[i] );
196     pthread_mutex_destroy( &next_lock );
197     pthread_mutex_destroy( &go_ahead );
198     free( file_locks );
199     printf("TEST RETURNING OK.\n");
200     return 0;
203 #endif /* HAVE_LIBPTHREAD */