]> granicus.if.org Git - re2c/commitdiff
Generate better code with '--skeleton': C90-compliant, free resources on errors.
authorUlya Trofimovich <skvadrik@gmail.com>
Thu, 17 Sep 2015 09:27:57 +0000 (10:27 +0100)
committerUlya Trofimovich <skvadrik@gmail.com>
Thu, 17 Sep 2015 09:27:57 +0000 (10:27 +0100)
re2c/src/codegen/skeleton/generate_code.cc

index 352f0f3cf7f8c83e353659623d551eca577ba8c3..584c2c9897863bc27037e2d371a1dddb5cf30450 100644 (file)
@@ -33,16 +33,55 @@ static void exact_uint (OutputFile & o, size_t width)
 void Skeleton::emit_prolog (OutputFile & o)
 {
        o << "\n" << "#include <stdio.h>";
-       o << "\n" << "#include <stdlib.h> // malloc, free";
-       o << "\n" << "#include <string.h> // memset";
+       o << "\n" << "#include <stdlib.h> /* malloc, free */";
        o << "\n";
-       o << "\n" << "static size_t filesize (FILE * f)";
+       o << "\n" << "static void * read_file";
+       o << "\n" << indString << "( const char * fname";
+       o << "\n" << indString << ", size_t unit";
+       o << "\n" << indString << ", size_t padding";
+       o << "\n" << indString << ", size_t * pfsize";
+       o << "\n" << indString << ")";
        o << "\n" << "{";
-       o << "\n" << indString << "const long pos = ftell (f);";
+       o << "\n" << indString << "void * buffer = NULL;";
+       o << "\n" << indString << "size_t fsize = 0;";
+       o << "\n";
+       o << "\n" << indString << "/* open file */";
+       o << "\n" << indString << "FILE * f = fopen (fname, \"rb\");";
+       o << "\n" << indString << "if (f == NULL)";
+       o << "\n" << indString << "{";
+       o << "\n" << indString << indString << "goto error;";
+       o << "\n" << indString << "}";
+       o << "\n";
+       o << "\n" << indString << "/* get file size */";
        o << "\n" << indString << "fseek (f, 0, SEEK_END);";
-       o << "\n" << indString << "const long size = ftell (f);";
-       o << "\n" << indString << "fseek (f, pos, SEEK_SET);";
-       o << "\n" << indString << "return (size_t) size;";
+       o << "\n" << indString << "fsize = (size_t) ftell (f) / unit;";
+       o << "\n" << indString << "fseek (f, 0, SEEK_SET);";
+       o << "\n";
+       o << "\n" << indString << "/* allocate memory for file and padding */";
+       o << "\n" << indString << "buffer = malloc (unit * (fsize + padding));";
+       o << "\n" << indString << "if (buffer == NULL)";
+       o << "\n" << indString << "{";
+       o << "\n" << indString << indString << "goto error;";
+       o << "\n" << indString << "}";
+       o << "\n";
+       o << "\n" << indString << "/* read the whole file in memory */";
+       o << "\n" << indString << "if (fread (buffer, unit, fsize, f) != fsize)";
+       o << "\n" << indString << "{";
+       o << "\n" << indString << indString << "goto error;";
+       o << "\n" << indString << "}";
+       o << "\n";
+       o << "\n" << indString << "fclose (f);";
+       o << "\n" << indString << "*pfsize = fsize;";
+       o << "\n" << indString << "return buffer;";
+       o << "\n";
+       o << "\n" << "error:";
+       o << "\n" << indString << "fprintf (stderr, \"error: cannot read file '%s'\\n\", fname);";
+       o << "\n" << indString << "free (buffer);";
+       o << "\n" << indString << "if (f != NULL)";
+       o << "\n" << indString << "{";
+       o << "\n" << indString << indString << "fclose (f);";
+       o << "\n" << indString << "}";
+       o << "\n" << indString << "return NULL;";
        o << "\n" << "}";
        o << "\n";
 }
@@ -112,49 +151,49 @@ void Skeleton::emit_start (OutputFile & o, uint32_t maxfill) const
        o << "\n";
        o << "\n" << "int lex_" << name << " ()";
        o << "\n" << "{";
-       o << "\n" << indString << "const char * finput_name = \"" << o.file_name << "." << name << ".input\";";
-       o << "\n" << indString << "FILE * finput = fopen (finput_name, \"rb\");";
-       o << "\n" << indString << "if (!finput)";
-       o << "\n" << indString << "{";
-       o << "\n" << indString << indString << "fprintf (stderr, \"cannot open file '%s'\\n\", finput_name);";
-       o << "\n" << indString << indString << "return 1;";
-       o << "\n" << indString << "}";
-       o << "\n" << indString << "const size_t input_len = filesize (finput) / sizeof (YYCTYPE);";
-       o << "\n" << indString << "const size_t padding = " << maxfill << "; // YYMAXFILL";
-       o << "\n" << indString << "YYCTYPE * input = (YYCTYPE *) malloc ((input_len + padding) * sizeof (YYCTYPE));";
-       o << "\n" << indString << "if (fread (input, sizeof (YYCTYPE), input_len, finput) != input_len)";
-       o << "\n" << indString << "{";
-       o << "\n" << indString << indString << "fprintf (stderr, \"cannot read file '%s'\\n\", finput_name);";
-       o << "\n" << indString << indString << "return 1;";
-       o << "\n" << indString << "}";
-       o << "\n" << indString << "fclose (finput);";
-       o << "\n" << indString << "memset (input + input_len, 0, padding * sizeof (YYCTYPE));";
+       o << "\n" << indString << "const size_t padding = " << maxfill << "; /* YYMAXFILL */";
+       o << "\n" << indString << "int status = 0;";
+       o << "\n" << indString << "size_t input_len = 0;";
+       o << "\n" << indString << "size_t keys_count = 0;";
+       o << "\n" << indString << "YYCTYPE * input = NULL;";
+       o << "\n" << indString << "YYKEYTYPE * keys = NULL;";
+       o << "\n" << indString << "const YYCTYPE * cursor = NULL;";
+       o << "\n" << indString << "const YYCTYPE * marker = NULL;";
+       o << "\n" << indString << "const YYCTYPE * ctxmarker = NULL;";
+       o << "\n" << indString << "const YYCTYPE * limit = NULL;";
+       o << "\n" << indString << "const YYCTYPE * eof = NULL;";
+       o << "\n" << indString << "unsigned int i = 0;";
        o << "\n";
-       o << "\n" << indString << "const char * fkeys_name = \"" << o.file_name << "." << name << ".keys\";";
-       o << "\n" << indString << "FILE * fkeys = fopen (fkeys_name, \"rb\");";
-       o << "\n" << indString << "if (!fkeys)";
+       o << "\n" << indString << "input = (YYCTYPE *) read_file";
+       o << "\n" << indString << indString << "(\"" << o.file_name << "." << name << ".input\"";
+       o << "\n" << indString << indString << ", sizeof (YYCTYPE)";
+       o << "\n" << indString << indString << ", padding";
+       o << "\n" << indString << indString << ", &input_len";
+       o << "\n" << indString << indString << ");";
+       o << "\n" << indString << "if (input == NULL)";
        o << "\n" << indString << "{";
-       o << "\n" << indString << indString << "fprintf (stderr, \"cannot open file '%s'\\n\", fkeys_name);";
-       o << "\n" << indString << indString << "return 1;";
+       o << "\n" << indString << indString << "status = 1;";
+       o << "\n" << indString << indString << "goto end;";
        o << "\n" << indString << "}";
-       o << "\n" << indString << "const size_t keys_size = filesize (fkeys);";
-       o << "\n" << indString << "YYKEYTYPE * keys = (YYKEYTYPE *) malloc (keys_size);";
-       o << "\n" << indString << "if (fread (keys, 1, keys_size, fkeys) != keys_size)";
+       o << "\n";
+       o << "\n" << indString << "keys = (YYKEYTYPE *) read_file";
+       o << "\n" << indString << indString << "(\"" << o.file_name << "." << name << ".keys\"";
+       o << "\n" << indString << indString << ", 3 * sizeof (YYKEYTYPE)";
+       o << "\n" << indString << indString << ", 0";
+       o << "\n" << indString << indString << ", &keys_count";
+       o << "\n" << indString << indString << ");";
+       o << "\n" << indString << "if (keys == NULL)";
        o << "\n" << indString << "{";
-       o << "\n" << indString << indString << "fprintf (stderr, \"cannot read file '%s'\\n\", fkeys_name);";
-       o << "\n" << indString << indString << "return 1;";
+       o << "\n" << indString << indString << "status = 1;";
+       o << "\n" << indString << indString << "goto end;";
        o << "\n" << indString << "}";
-       o << "\n" << indString << "fclose (fkeys);";
-       o << "\n" << indString << "const size_t keys_count = keys_size / (3 * sizeof (YYKEYTYPE));";
        o << "\n";
-       o << "\n" << indString << "const YYCTYPE * cursor = input;";
-       o << "\n" << indString << "const YYCTYPE * marker = input;";
-       o << "\n" << indString << "const YYCTYPE * ctxmarker = input;";
-       o << "\n" << indString << "const YYCTYPE * const limit = input + input_len + padding;";
-       o << "\n" << indString << "const YYCTYPE * const eof = input + input_len;";
+       o << "\n" << indString << "cursor = input;";
+       o << "\n" << indString << "marker = input;";
+       o << "\n" << indString << "ctxmarker = input;";
+       o << "\n" << indString << "limit = input + input_len + padding;";
+       o << "\n" << indString << "eof = input + input_len;";
        o << "\n";
-       o << "\n" << indString << "int status = 0;";
-       o << "\n" << indString << "unsigned int i;";
        o << "\n" << indString << "for (i = 0; status == 0 && cursor < eof && i < keys_count; ++i)";
        o << "\n" << indString << "{";
        o << "\n" << indString << indString << "const YYCTYPE * token = cursor;";
@@ -184,6 +223,8 @@ void Skeleton::emit_end (OutputFile & o) const
        o << "\n" << indString << indString << indString << "fprintf (stderr, \"error: " << incond (cond) << "unused keys left\\n\");";
        o << "\n" << indString << indString << "}";
        o << "\n" << indString << "}";
+       o << "\n";
+       o << "\n" << "end:";
        o << "\n" << indString << "free (input);";
        o << "\n" << indString << "free (keys);";
        o << "\n";