209 lines
5.8 KiB
Plaintext
209 lines
5.8 KiB
Plaintext
/*
|
|
* This file is part of flex.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* Neither the name of the University nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
* PURPOSE.
|
|
*/
|
|
|
|
%{
|
|
/* A scanner file to build "scanner.c".
|
|
Input language is any text made of spaces, newlines, and alphanumerics.
|
|
|
|
We create N_THREADS number of threads. Each thread has it's own scanner.
|
|
Each thread selects one of the files specified in ARGV, scans it, then
|
|
closes it. This is repeated N_SCANS number of times for each thread.
|
|
|
|
The idea is to press the scanner to break under threads.
|
|
If we see "Scanner Jammed", then we know
|
|
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <config.h>
|
|
|
|
#ifdef HAVE_PTHREAD_H
|
|
#include <pthread.h>
|
|
#endif
|
|
|
|
/* A naive test for segfaults when accessing yytext. */
|
|
static int process_text(char* s, yyscan_t scanner);
|
|
|
|
%}
|
|
|
|
%option 8bit prefix="test"
|
|
%option nounput nomain nodefault noinput
|
|
%option yywrap
|
|
%option reentrant
|
|
%option warn
|
|
|
|
/* Arbitrary states.*/
|
|
%x STATE_1
|
|
%x STATE_2
|
|
|
|
%%
|
|
|
|
#define NUMBER 200
|
|
#define WORD 201
|
|
|
|
<INITIAL>[[:digit:]]+ { BEGIN(STATE_1); process_text(yytext,yyscanner); return NUMBER; }
|
|
<INITIAL>[[:alpha:]]+ { BEGIN(STATE_2); process_text(yytext,yyscanner); return WORD; }
|
|
|
|
<STATE_1>[[:alpha:]]+ { BEGIN(0); process_text(yytext,yyscanner); return WORD; }
|
|
<STATE_1>[[:digit:]]+ { BEGIN(0); process_text(yytext,yyscanner); return NUMBER; }
|
|
|
|
<STATE_2>[[:alpha:]]+ { BEGIN(0); process_text(yytext,yyscanner); return WORD; }
|
|
<STATE_2>[[:digit:]]+ { BEGIN(0); process_text(yytext,yyscanner); return NUMBER; }
|
|
|
|
<INITIAL,STATE_1,STATE_2>" "|\t|\r|\n { process_text(yytext,yyscanner); }
|
|
<INITIAL,STATE_1,STATE_2>[^[:alnum:][:space:]\t\r\n] {
|
|
/*fprintf(stderr,"*** Error: bad input char '%c'.\n", yytext[0]); */
|
|
yyterminate();
|
|
}
|
|
<INITIAL,STATE_1,STATE_2>[[:space:]\r\n]+ { }
|
|
%%
|
|
|
|
int testwrap( yyscan_t scanner) {
|
|
(void)scanner;
|
|
return 1;
|
|
}
|
|
static int process_text(char* s, yyscan_t scanner)
|
|
{
|
|
(void)scanner;
|
|
return (int)(*s) + (int) *(s + testget_leng(scanner)-1);
|
|
}
|
|
|
|
int main(int ARGC, char *ARGV[]);
|
|
|
|
#ifndef HAVE_PTHREAD_H
|
|
int main (int ARGC, char *ARGV[]) {
|
|
puts(
|
|
"TEST ABORTED because pthread library not available \n"
|
|
"-- This is expected on some systems. It is not a flex error.");
|
|
/* Exit status for a skipped test */
|
|
return 77;
|
|
}
|
|
#else
|
|
|
|
#define N_THREADS 4
|
|
#define N_SCANS 20
|
|
|
|
/* Each thread selects the next file to scan in round-robin fashion.
|
|
If there are less files than threads, some threads may block. */
|
|
|
|
static pthread_mutex_t next_lock = PTHREAD_MUTEX_INITIALIZER;
|
|
static pthread_mutex_t go_ahead = PTHREAD_MUTEX_INITIALIZER;
|
|
static int n_files, next_file;
|
|
|
|
static pthread_mutex_t *file_locks;
|
|
static char **filenames;
|
|
|
|
|
|
static void * thread_func ( void* arg )
|
|
{
|
|
int i;
|
|
|
|
(void)arg;
|
|
|
|
/* Wait for go-ahead. */
|
|
pthread_mutex_lock( &go_ahead);
|
|
pthread_mutex_unlock(&go_ahead);
|
|
|
|
for( i =0 ; i < N_SCANS ; i++ )
|
|
{
|
|
int next;
|
|
yyscan_t scanner;
|
|
FILE * fp;
|
|
|
|
pthread_mutex_lock ( &next_lock );
|
|
next = (next_file++) % n_files;
|
|
pthread_mutex_unlock ( &next_lock );
|
|
|
|
pthread_mutex_lock ( &file_locks[ next ] );
|
|
|
|
testlex_init( &scanner );
|
|
/*printf("Scanning file %s #%d\n",filenames[next],i); fflush(stdout); */
|
|
if((fp = fopen(filenames[next],"r"))==NULL) {
|
|
perror("fopen");
|
|
return NULL;
|
|
}
|
|
testset_in(fp,scanner);
|
|
|
|
while( testlex( scanner) != 0)
|
|
{
|
|
}
|
|
fclose(fp);
|
|
testlex_destroy(scanner);
|
|
pthread_mutex_unlock ( &file_locks[ next ] );
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
int main (int ARGC, char *ARGV[])
|
|
{
|
|
int i;
|
|
pthread_t threads[N_THREADS];
|
|
|
|
if( ARGC < 2 ) {
|
|
fprintf(stderr,"*** Error: No filenames specified.\n");
|
|
exit(-1);
|
|
}
|
|
|
|
/* Allocate and initialize the locks. One for each filename in ARGV. */
|
|
file_locks = malloc((size_t) (ARGC-1) * sizeof(pthread_mutex_t));
|
|
for( i = 0; i < ARGC-1; i++)
|
|
pthread_mutex_init( &file_locks[i], NULL );
|
|
|
|
n_files = ARGC -1;
|
|
filenames = ARGV + 1;
|
|
next_file = 0;
|
|
|
|
/* prevent threads from starting until all threads have been created. */
|
|
pthread_mutex_lock(&go_ahead);
|
|
|
|
/* Create N threads then wait for them. */
|
|
for(i =0; i < N_THREADS ; i++ ) {
|
|
if( pthread_create( &threads[i], NULL, thread_func, NULL) != 0)
|
|
{
|
|
fprintf(stderr, "*** Error: pthread_create failed.\n");
|
|
exit(-1);
|
|
}
|
|
printf("Created thread %d.\n",i); fflush(stdout);
|
|
}
|
|
|
|
/* Tell threads to begin. */
|
|
pthread_mutex_unlock(&go_ahead);
|
|
|
|
for(i =0; i < N_THREADS ; i++ ) {
|
|
pthread_join ( threads[i], NULL );
|
|
printf("Thread %d done.\n", i ); fflush(stdout);
|
|
}
|
|
|
|
for( i = 0; i < ARGC-1; i++)
|
|
pthread_mutex_destroy( &file_locks[i] );
|
|
|
|
pthread_mutex_destroy( &next_lock );
|
|
pthread_mutex_destroy( &go_ahead );
|
|
free( file_locks );
|
|
printf("TEST RETURNING OK.\n");
|
|
return 0;
|
|
}
|
|
|
|
#endif /* HAVE_PTHREAD_H */
|
|
|