glsl: Add preprocessor purifier.

This commit is contained in:
Michal Krol 2009-06-11 14:04:39 +02:00
parent 970823978c
commit 0bbf59c305
4 changed files with 267 additions and 0 deletions

View File

@ -1,6 +1,7 @@
Import('*')
SConscript('gallium/SConscript')
SConscript('glsl/pp/SConscript')
if 'mesa' in env['statetrackers']:
SConscript('mesa/SConscript')

21
src/glsl/pp/SConscript Normal file
View File

@ -0,0 +1,21 @@
Import('*')
if env['platform'] not in ['windows']:
Return()
env = env.Clone()
glsl = env.StaticLibrary(
target = 'glsl',
source = [
'sl_pp_purify.c',
],
)
env = env.Clone()
if env['platform'] == 'windows':
env.PrependUnique(LIBS = [
'user32',
])
env.Prepend(LIBS = [glsl])

204
src/glsl/pp/sl_pp_purify.c Normal file
View File

@ -0,0 +1,204 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include <stdlib.h>
#include "sl_pp_purify.h"
/*
* Preprocessor purifier performs the following tasks.
* - Convert all variants of newlines into a Unix newline.
* - Merge continued lines into a single long line.
* - Remove line comments and replace block comments with whitespace.
*/
static unsigned int
_purify_newline(const char *input,
char *out)
{
if (input[0] == '\n') {
*out = '\n';
if (input[1] == '\r') {
/*
* The GLSL spec is not explicit about whether this
* combination is a valid newline or not.
* Let's assume it is acceptable.
*/
return 2;
}
return 1;
}
if (input[0] == '\r') {
*out = '\n';
if (input[1] == '\n') {
return 2;
}
return 1;
}
*out = input[0];
return 1;
}
static unsigned int
_purify_backslash(const char *input,
char *out)
{
unsigned int eaten = 0;
for (;;) {
if (input[0] == '\\') {
char next;
unsigned int next_eaten;
eaten++;
input++;
next_eaten = _purify_newline(input, &next);
if (next == '\n') {
/*
* If this is really a line continuation sequence, eat
* it and do not exit the loop.
*/
eaten += next_eaten;
input += next_eaten;
} else {
/*
* It is an error to put anything between a backslash
* and a newline and still expect it to behave like a line
* continuation sequence.
* Even if it is an innocent whitespace.
*/
*out = '\\';
break;
}
} else {
eaten += _purify_newline(input, out);
break;
}
}
return eaten;
}
static unsigned int
_purify_comment(const char *input,
char *out)
{
unsigned int eaten;
char curr;
eaten = _purify_backslash(input, &curr);
input += eaten;
if (curr == '/') {
char next;
unsigned int next_eaten;
next_eaten = _purify_backslash(input, &next);
if (next == '/') {
eaten += next_eaten;
input += next_eaten;
/* Replace a line comment with either a newline or nil. */
for (;;) {
next_eaten = _purify_backslash(input, &next);
eaten += next_eaten;
input += next_eaten;
if (next == '\n' || next == '\0') {
*out = next;
return eaten;
}
}
} else if (next == '*') {
eaten += next_eaten;
input += next_eaten;
/* Replace a block comment with a whitespace. */
for (;;) {
next_eaten = _purify_backslash(input, &next);
eaten += next_eaten;
input += next_eaten;
while (next == '*') {
next_eaten = _purify_backslash(input, &next);
eaten += next_eaten;
input += next_eaten;
if (next == '/') {
*out = ' ';
return eaten;
}
}
}
}
}
*out = curr;
return eaten;
}
int
sl_pp_purify(const char *input,
const struct sl_pp_purify_options *options,
char **output)
{
char *out = NULL;
unsigned int out_len = 0;
unsigned int out_max = 0;
for (;;) {
char c;
input += _purify_comment(input, &c);
if (out_len >= out_max) {
unsigned int new_max = out_max;
if (new_max < 0x100) {
new_max = 0x100;
} else if (new_max < 0x10000) {
new_max *= 2;
} else {
new_max += 0x10000;
}
out = realloc(out, new_max);
if (!out) {
return -1;
}
out_max = new_max;
}
out[out_len++] = c;
if (c == '\0') {
break;
}
}
*output = out;
return 0;
}

View File

@ -0,0 +1,41 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef SL_PP_PURIFY_H
#define SL_PP_PURIFY_H
struct sl_pp_purify_options {
unsigned int preserve_columns:1;
unsigned int tab_width:4;
};
int
sl_pp_purify(const char *input,
const struct sl_pp_purify_options *options,
char **output);
#endif /* SL_PP_PURIFY_H */