xref: /netbsd-src/external/bsd/flex/dist/tests/pthread.l (revision 9573673d78c64ea1eac42d7f2e9521be89932ae5)
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  */
23 
24 %{
25 /* A scanner file to build "scanner.c".
26    Input language is any text made of spaces, newlines, and alphanumerics.
27 
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.
31 
32    The idea is to press the scanner to break under threads.
33    If we see  "Scanner Jammed", then we know
34 
35 */
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <config.h>
39 
40 #ifdef HAVE_PTHREAD_H
41 #include <pthread.h>
42 #endif
43 
44 /* A naive test for segfaults when accessing yytext. */
45 static int process_text(char* s, yyscan_t  scanner);
46 
47 %}
48 
49 %option 8bit prefix="test"
50 %option nounput nomain nodefault noinput
51 %option yywrap
52 %option reentrant
53 %option warn
54 
55     /* Arbitrary states.*/
56 %x STATE_1
57 %x STATE_2
58 
59 %%
60 
61     #define NUMBER 200
62     #define WORD   201
63 
64 <INITIAL>[[:digit:]]+ { BEGIN(STATE_1); process_text(yytext,yyscanner); return NUMBER; }
65 <INITIAL>[[:alpha:]]+ { BEGIN(STATE_2); process_text(yytext,yyscanner); return WORD; }
66 
67 <STATE_1>[[:alpha:]]+ { BEGIN(0); process_text(yytext,yyscanner); return WORD; }
68 <STATE_1>[[:digit:]]+ { BEGIN(0); process_text(yytext,yyscanner); return NUMBER; }
69 
70 <STATE_2>[[:alpha:]]+ { BEGIN(0); process_text(yytext,yyscanner); return WORD; }
71 <STATE_2>[[:digit:]]+ { BEGIN(0); process_text(yytext,yyscanner); return NUMBER; }
72 
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]+  { }
79 %%
80 
81 int yywrap( yyscan_t  scanner) {
82     (void)scanner;
83     return 1;
84 }
85 static int process_text(char* s, yyscan_t  scanner)
86 {
87     (void)scanner;
88     return (int)(*s) + (int) *(s + yyget_leng(scanner)-1);
89 }
90 
91 int main(int ARGC, char *ARGV[]);
92 
93 #ifndef HAVE_LIBPTHREAD
94   int main (int ARGC, char *ARGV[]) {
95     printf(
96        "TEST ABORTED because pthread library not available \n"
97        "-- This is expected on some systems. It is not a flex error.\n" );
98     return 0;
99   }
100 #else
101 
102 #define N_THREADS 4
103 #define N_SCANS   20
104 #define INPUT_FILE "test.input"
105 
106 /* Each thread selects the next file to scan in round-robin fashion.
107    If there are less files than threads, some threads may block. */
108 
109 static pthread_mutex_t next_lock = PTHREAD_MUTEX_INITIALIZER;
110 static pthread_mutex_t go_ahead  = PTHREAD_MUTEX_INITIALIZER;
111 static int n_files, next_file;
112 
113 static pthread_mutex_t *file_locks;
114 static char **filenames;
115 
116 
117 void * thread_func ( void* arg )
118 {
119     int i;
120 
121     (void)arg;
122 
123     /* Wait for go-ahead. */
124     pthread_mutex_lock( &go_ahead);
125     pthread_mutex_unlock(&go_ahead);
126 
127     for( i =0 ; i < N_SCANS ; i++ )
128     {
129         int main(int ARGC, char *ARGV[]);
130 
131         int next;
132         yyscan_t  scanner;
133         FILE * fp;
134 
135         pthread_mutex_lock ( &next_lock );
136         next = (next_file++) % n_files;
137         pthread_mutex_unlock ( &next_lock );
138 
139         pthread_mutex_lock ( &file_locks[ next ] );
140 
141         yylex_init( &scanner );
142         /*printf("Scanning file %s  #%d\n",filenames[next],i); fflush(stdout); */
143         if((fp = fopen(filenames[next],"r"))==NULL) {
144             perror("fopen");
145             return NULL;
146         }
147         yyset_in(fp,scanner);
148 
149         while( yylex( scanner) != 0)
150         {
151         }
152         fclose(fp);
153         yylex_destroy(scanner);
154         pthread_mutex_unlock ( &file_locks[ next ] );
155     }
156     return NULL;
157 }
158 
159 int main (int ARGC, char *ARGV[])
160 {
161     int i;
162     pthread_t threads[N_THREADS];
163 
164     if( ARGC < 2 ) {
165         fprintf(stderr,"*** Error: No filenames specified.\n");
166         exit(-1);
167     }
168 
169     /* Allocate and initialize the locks. One for each filename in ARGV. */
170     file_locks = (pthread_mutex_t*)malloc( (ARGC-1) * sizeof(pthread_mutex_t));
171     for( i = 0; i < ARGC-1; i++)
172         pthread_mutex_init( &file_locks[i], NULL );
173 
174     n_files = ARGC -1;
175     filenames = ARGV + 1;
176     next_file = 0;
177 
178     /* prevent threads from starting until all threads have been created. */
179     pthread_mutex_lock(&go_ahead);
180 
181     /* Create N threads then wait for them. */
182     for(i =0; i < N_THREADS ; i++ ) {
183         if( pthread_create( &threads[i], NULL, thread_func, NULL) != 0)
184         {
185             fprintf(stderr, "*** Error: pthread_create failed.\n");
186             exit(-1);
187         }
188         printf("Created thread %d.\n",i); fflush(stdout);
189     }
190 
191     /* Tell threads to begin. */
192     pthread_mutex_unlock(&go_ahead);
193 
194     for(i =0; i < N_THREADS ; i++ ) {
195         pthread_join ( threads[i], NULL );
196         printf("Thread %d done.\n", i ); fflush(stdout);
197     }
198 
199     for( i = 0; i < ARGC-1; i++)
200         pthread_mutex_destroy( &file_locks[i] );
201 
202     pthread_mutex_destroy( &next_lock );
203     pthread_mutex_destroy( &go_ahead );
204     free( file_locks );
205     printf("TEST RETURNING OK.\n");
206     return 0;
207 }
208 
209 #endif /* HAVE_LIBPTHREAD */
210 
211