diff --git a/php-linter b/php-linter index a2ac5a4..c793c79 100755 --- a/php-linter +++ b/php-linter @@ -1,5 +1,7 @@ #!/bin/bash +DIR=`dirname $(realpath $0)`; + usage(){ echo -e "Usage: php-linter {path}\n"; } @@ -36,12 +38,12 @@ if [ -d $FILENAME ]; then count=`expr $count + 1`; echo "($count) file $phpfile"; - ./src/linter $phpfile; + exec $DIR/src/linter $phpfile; done; else ## {2} Exec file ## - ./src/linter $FILENAME; + exec $DIR/src/linter $FILENAME; fi; diff --git a/src/lib/automate/automate.c b/src/lib/automate/automate.c index b06aca7..5401e01 100644 --- a/src/lib/automate/automate.c +++ b/src/lib/automate/automate.c @@ -29,13 +29,13 @@ int browse(struct Automate pAutomate, const char* pString){ /* (1) Check if the current char can lead to a state ---------------------------------------------------------*/ /* (1) Check current state choices */ - i = 0; l = pAutomate.states[pAutomate.state].n; + i = 0; l = pAutomate.states[pAutomate.sCurrent].n; for( ; i < l ; i++ ){ /* (2) If part of set */ - if( is_part(pString[strIndex], pAutomate.set[pAutomate.states[pAutomate.state].set[i]]) == 1 ){ - pAutomate.state = pAutomate.states[pAutomate.state].state[i]; + if( is_part(pString[strIndex], pAutomate.set[pAutomate.states[pAutomate.sCurrent].set[i]]) == 1 ){ + pAutomate.sCurrent = pAutomate.states[pAutomate.sCurrent].state[i]; strIndex++; } @@ -43,7 +43,7 @@ int browse(struct Automate pAutomate, const char* pString){ } - return pAutomate.state; + return pAutomate.sCurrent; } @@ -58,7 +58,127 @@ int browse(struct Automate pAutomate, const char* pString){ +struct Automate buildFromRegExp(const char* pRegExp){ + /* [0] Initialize variables + =========================================================*/ + struct Automate result; + +} + + + + + + +struct Automate createAutomate(){ + + /* [0] Initialize variables + =========================================================*/ + struct Automate automate; + + /* [1] Create n values + =========================================================*/ + automate.n_state = 0; + automate.n_set = 0; + automate.sCurrent = 0; + automate.sFinal = 0; + + /* [2] First allocation + =========================================================*/ + automate.states = malloc( 0 ); + automate.set = malloc( 0 ); + + + /* [3] Return initialized automate + =========================================================*/ + return automate; +} + + + +char addState(struct Automate* pAutomate){ + + /* [0] Initialize variables + =========================================================*/ + char index = pAutomate->n_state++; + + + /* [1] Reallocate memory for the state + =========================================================*/ + pAutomate->states = realloc( pAutomate->states, sizeof(struct AutomateState) * pAutomate->n_state ); + + + /* [2] Allocate memory for the state data + initalize n + =========================================================*/ + pAutomate->states[index].n = 0; + pAutomate->states[index].set = malloc( 0 ); + pAutomate->states[index].state = malloc( 0 ); + + + /* [3] Set new state as final + =========================================================*/ + pAutomate->sFinal = index; + + + return index; +} + + +char addSet(struct Automate* pAutomate, const char* pSet){ + + /* [0] Initialize variables + =========================================================*/ + char index = pAutomate->n_set++; + + + /* [1] Add the set + =========================================================*/ + /* (1) Reallocate memory for the set */ + pAutomate->set = realloc( pAutomate->set, sizeof(char*) * pAutomate->n_set ); + pAutomate->set[index] = realloc( pAutomate->set[index], strlen(pSet) + 1 ); + + /* (2) Copy the set */ + strcpy(pAutomate->set[index], pSet); + + return index; +} + + +void linkStates(struct Automate* pAutomate, const unsigned int pIn, const unsigned int pOut, const char* pSet){ + + /* [0] Initialize variables + =========================================================*/ + char c; // counter + int setIndex = -1; + char index = pAutomate->states[pIn].n++; + + + /* [1] Reallocate memory for link + =========================================================*/ + pAutomate->states[pIn].set = realloc( pAutomate->states[pIn].set, pAutomate->states[pIn].n ); + pAutomate->states[pIn].state = realloc( pAutomate->states[pIn].state, pAutomate->states[pIn].n ); + + + /* [2] Search for set in set list + =========================================================*/ + /* (1) Search for existing set */ + for( c = 0 ; c < pAutomate->n_set ; c++ ) + if( strcmp(pAutomate->set[c], pSet) == 0 ) + setIndex = c; + + /* (2) If not found, create one */ + if( setIndex == -1 ) + setIndex = addSet(pAutomate, pSet); + + + /* [3] Create the link + =========================================================*/ + pAutomate->states[pIn].set[index] = setIndex; + pAutomate->states[pIn].state[index] = pOut; + + +} diff --git a/src/lib/automate/automate.h b/src/lib/automate/automate.h index 006740a..a95a3b1 100644 --- a/src/lib/automate/automate.h +++ b/src/lib/automate/automate.h @@ -11,6 +11,7 @@ #define _LIB_AUTOMATE_AUTOMATE_H_ #include + #include struct AutomateState{ @@ -20,11 +21,12 @@ }; struct Automate{ - struct AutomateState* states; // states - unsigned int n_state; // Max state index - unsigned int state; // current state index - unsigned int n_set; // Max set index - char** set; // list of sets + struct AutomateState* states; // states + char n_state; // Max state index + char sCurrent; // current state index + char sFinal; // final state index + char n_set; // Max set index + char** set; // list of sets }; @@ -40,6 +42,45 @@ int browse(struct Automate pAutomate, const char* pString); + /* Builds an automate from a regexp + * + * @pRegExp Regular expression to build from + * + * @return pAutomate The created automate + * + */ + struct Automate buildFromRegExp(const char* pRegExp); + + + + /* Initializes an automate + * + */ + struct Automate createAutomate(); + + + /* Adds a state to an automate + * + * @return index The created state index + * + */ + char addState(struct Automate* pAutomate); + + + /* Adds a set to an automate + * + * @return index The created set index + * + */ + char addSet(struct Automate* pAutomate, const char* pSet); + + + /* Adds a link between 2 states with a set + * + */ + void linkStates(struct Automate* pAutomate, const unsigned int pIn, const unsigned int pOut, const char* pSet); + + /* Checks if a char is part of a set * diff --git a/src/lib/regex/regex.c b/src/lib/regex/regex.c new file mode 100644 index 0000000..9b607fd --- /dev/null +++ b/src/lib/regex/regex.c @@ -0,0 +1,300 @@ +/************************** +* Scope * +*************************** +* Designed & Developed by * +* Adrien Marquès * +* * +*************************** +* doowap31@gmail.com * +**************************/ +#include "regex.h" + +// int match(const char* pPattern, char* pBuffer); + +char madeOfSet(char* pBuffer, const char* pSet){ + + unsigned int a, b; + unsigned int A = strlen(pBuffer); + unsigned int B = strlen(pSet); + char in = 0; + + /* [1] For each char of pBuffer + =========================================================*/ + for( a = 0 ; a < A ; a++ ){ + + /* (2) Check if char is one of each of @pSet + ---------------------------------------------------------*/ + for( b = 0 ; b < B ; b++ ) + if( pBuffer[a] == pSet[b] ) + break; + + /* If char not in */ + if( b == B ) + return 0; + } + + return 1; +} + + + + + +int developSingle(const char* pPattern, struct RegExpDevSets* pCases, struct RegExpDevSets* pGroups){ + + /* [0] Init vars + =========================================================*/ + unsigned int level = 0; + unsigned int c, c2, C = strlen(pPattern); + unsigned int start, end; + int pair[2]; + char recursive[2] = { 0, 0 }; // no [] into [] ; no () in () + + + + /* [1] Get all level-0 groups + =========================================================*/ + c = 0; + pair[0] = 0; + pair[1] = 0; + + while( c < C ){ + + /* (1) Seek GROUP START char + ---------------------------------------------------------*/ + for( ; c < C ; c++ ){ + if( pPattern[c] == REGEX_CASE_START ) pair[0]++; + if( pPattern[c] == REGEX_CASE_STOP ) pair[0]--; + if( pPattern[c] == REGEX_GROUP_START ) pair[1]++; + if( pPattern[c] == REGEX_GROUP_STOP ) pair[1]--; + + if( pair[0] == 2 ) recursive[0] = 1; + if( pair[1] == 2 ) recursive[1] = 1; + + /* (1) If found and level-0 -> got it */ + if( pPattern[c] == REGEX_GROUP_START && pair[0] == 0 && pair[1] == 1 ) + break; + } + + /* (2) If not found -> exit */ + if( c >= C ) + break; + + /* (3) else -> store */ + start = c++; + + + /* (2) Seek GROUP STOP char + ---------------------------------------------------------*/ + for( ; c < C ; c++ ){ + if( pPattern[c] == REGEX_CASE_START ) pair[0]++; + if( pPattern[c] == REGEX_CASE_STOP ) pair[0]--; + if( pPattern[c] == REGEX_GROUP_START ) pair[1]++; + if( pPattern[c] == REGEX_GROUP_STOP ) pair[1]--; + + if( pair[0] == 2 ) recursive[0] = 1; + if( pair[1] == 2 ) recursive[1] = 1; + + /* (1) If found and level-0 -> got it */ + if( pPattern[c] == REGEX_GROUP_STOP && pair[0] == 0 && pair[1] == 0 ) + break; + } + + /* (2) If not found -> exit */ + if( c >= C ) + break; + + /* (3) else -> store */ + end = c++; + + + + /* (3) Save set to groups + ---------------------------------------------------------*/ + /* (1) Store set */ + pGroups->n++; + pGroups->sets = realloc(pGroups->sets, sizeof(struct RegExpDevSet) * pGroups->n ); + pGroups->sets[pGroups->n-1].start = start; + pGroups->sets[pGroups->n-1].end = end; + pGroups->sets[pGroups->n-1].n = end-start-1; + pGroups->sets[pGroups->n-1].set = malloc( pGroups->sets[pGroups->n-1].n +1 ); + sprintf(pGroups->sets[pGroups->n-1].set, "%.*s", pGroups->sets[pGroups->n-1].n, pPattern+pGroups->sets[pGroups->n-1].start+1); + + /* (2) Try to find quantifier */ + c++; + if( pPattern[c-1] == REGEX_QUANTIFIER_BINARY ) + pGroups->sets[pGroups->n-1].quantifier = REGEX_QUANTIFIER_BINARY; + else if( pPattern[c-1] == REGEX_QUANTIFIER_ANY ) + pGroups->sets[pGroups->n-1].quantifier = REGEX_QUANTIFIER_ANY; + else if( pPattern[c-1] == REGEX_QUANTIFIER_MULTI ) + pGroups->sets[pGroups->n-1].quantifier = REGEX_QUANTIFIER_MULTI; + else + c--; + + } + + + /* [2] Get all level-0 cases + =========================================================*/ + c = 0; + pair[0] = 0; + pair[1] = 0; + while( c < C ){ + + /* (1) Seek CASE START char + ---------------------------------------------------------*/ + for( ; c < C ; c++ ){ + if( pPattern[c] == REGEX_CASE_START ) pair[0]++; + if( pPattern[c] == REGEX_CASE_STOP ) pair[0]--; + if( pPattern[c] == REGEX_GROUP_START ) pair[1]++; + if( pPattern[c] == REGEX_GROUP_STOP ) pair[1]--; + + if( pair[0] == 2 ) recursive[0] = 1; + if( pair[1] == 2 ) recursive[1] = 1; + + /* (1) If found and level-0 -> got it */ + if( pPattern[c] == REGEX_CASE_START && pair[0] == 1 && pair[1] == 0 ) + break; + } + + /* (2) If not found -> exit */ + if( c >= C ) + break; + + /* (3) else -> store */ + start = c++; + + + /* (2) Seek CASE STOP char + ---------------------------------------------------------*/ + for( ; c < C ; c++ ){ + if( pPattern[c] == REGEX_CASE_START ) pair[0]++; + if( pPattern[c] == REGEX_CASE_STOP ) pair[0]--; + if( pPattern[c] == REGEX_GROUP_START ) pair[1]++; + if( pPattern[c] == REGEX_GROUP_STOP ) pair[1]--; + + if( pair[0] == 2 ) recursive[0] = 1; + if( pair[1] == 2 ) recursive[1] = 1; + + /* (1) If found and level-0 -> got it */ + if( pPattern[c] == REGEX_CASE_STOP && pair[0] == 0 && pair[1] == 0 ) + break; + } + + /* (2) If not found -> error */ + if( c >= C ) + break; + + /* (3) else -> store */ + end = c++; + + + /* (3) Save set to cases + ---------------------------------------------------------*/ + /* (1) Store set */ + pCases->n++; + pCases->sets = realloc(pCases->sets, sizeof(struct RegExpDevSet) * pCases->n ); + pCases->sets[pCases->n-1].start = start; + pCases->sets[pCases->n-1].end = end; + pCases->sets[pCases->n-1].n = end-start-1; + pCases->sets[pCases->n-1].set = malloc( pCases->sets[pCases->n-1].n +1 ); + sprintf(pCases->sets[pCases->n-1].set, "%.*s", pCases->sets[pCases->n-1].n, pPattern+pCases->sets[pCases->n-1].start+1); + + /* (2) Try to find quantifier */ + c++; + if( pPattern[c-1] == REGEX_QUANTIFIER_BINARY ) + pCases->sets[pCases->n-1].quantifier = REGEX_QUANTIFIER_BINARY; + else if( pPattern[c-1] == REGEX_QUANTIFIER_ANY ) + pCases->sets[pCases->n-1].quantifier = REGEX_QUANTIFIER_ANY; + else if( pPattern[c-1] == REGEX_QUANTIFIER_MULTI ) + pCases->sets[pCases->n-1].quantifier = REGEX_QUANTIFIER_MULTI; + else + c--; + + } + + + /* [2] If no set found return 1 + =========================================================*/ + if( recursive[0] == 1 || recursive[1] == 1 ) + return 2; + + if( pCases->n+pGroups->n == 0 ) + return 1; + + + /* [3] Try to develop recursively + =========================================================*/ + // printf("Got %d cases\n", cases.n); + // for( c = 0 ; c < cases.n ; c++ ) + // printf("\tCase.%d: '%.*s' (quantifier: %c)\n", c, cases.sets[c].end-cases.sets[c].start-1, pPattern+cases.sets[c].start+1, cases.sets[c].quantifier); + // printf("Got %d groups\n", groups.n); + // for( c = 0 ; c < groups.n ; c++ ) + // printf("\tGroup.%d: '%.*s' (quantifier: %c)\n", c, groups.sets[c].end-groups.sets[c].start-1, pPattern+groups.sets[c].start+1, groups.sets[c].quantifier); + + + + + + + return 0; +} + + + + +int developMulti(const char* pPattern, struct RegExpDevSets* pCases, struct RegExpDevSets* pGroups, const char pDepth){ + + /* [0] Init vars + =========================================================*/ + char depth = pDepth; + unsigned int c, d; + unsigned int boundary[2]; + struct RegExpDevSets groups = { 0, malloc(1) }; + struct RegExpDevSets cases = { 0, malloc(1) }; + int devRtn; + char buffer[MAX_DEV_SIZE]; + + + + /* [1] Get all level-0 groups+cases + =========================================================*/ + boundary[0] = 0; // min boundary + boundary[1] = strlen(pPattern); // max boundary + + // while there is a depth to do + do{ + + strncpy(buffer, pPattern+boundary[0], boundary[1]); + devRtn = developSingle(buffer, pGroups, pCases); + + // if( devRtn == 0 ){ + // groups = realloc(groups, sizeof(struct RegExpDevSets) * depth); + // cases = realloc(cases, sizeof(struct RegExpDevSets) * depth); + // } + + + for( c = 0 ; c < pGroups->n ; c++ ){ + for( d = 0 ; d < depth ; d++ ) printf(" "); + printf("Group.%d-%d: '%s' (quantifier: %c)\n", depth, c, pGroups->sets[c].set, pGroups->sets[c].quantifier); + + strcpy(buffer, pGroups->sets[c].set); + for( d = 0 ; d < depth ; d++ ) printf(" "); + printf("dev: %d\n", developMulti(buffer, &groups, &cases, depth+1)); + + } + + for( c = 0 ; c < pCases->n ; c++ ){ + for( d = 0 ; d < depth ; d++ ) printf(" "); + printf("Case.%d-%d: '%s' (quantifier: %c)\n", depth, c, pCases->sets[c].set, pCases->sets[c].quantifier); + + strcpy(buffer, pCases->sets[c].set); + for( d = 0 ; d < depth ; d++ ) printf(" "); + printf("dev: %d\n", developMulti(buffer, &groups, &cases, depth+1)); + } + + }while( devRtn == 10 ); + + + return 0; +} \ No newline at end of file diff --git a/src/lib/regex/regex.h b/src/lib/regex/regex.h new file mode 100644 index 0000000..35c62c6 --- /dev/null +++ b/src/lib/regex/regex.h @@ -0,0 +1,80 @@ +/************************** +* Scope * +*************************** +* Designed & Developed by * +* Adrien Marquès * +* * +*************************** +* doowap31@gmail.com * +**************************/ +#ifndef _LIB_REGEX_REGEX_H_ + #define _LIB_REGEX_REGEX_H_ + + + /* CONSTANTS */ + #define MAX_MATCH_SIZE 256 + #define MAX_DEV_SIZE 512 + + #define REGEX_GROUP_START '(' + #define REGEX_GROUP_STOP ')' + #define REGEX_CASE_START '[' + #define REGEX_CASE_STOP ']' + #define REGEX_CASE_DELIMITER '|' + #define REGEX_QUANTIFIER_BINARY '?' + #define REGEX_QUANTIFIER_ANY '*' + #define REGEX_QUANTIFIER_MULTI '+' + #define REGEX_SET_ALPHA_LOWER '\5' + #define REGEX_SET_ALPHA_UPPER '\6' + #define REGEX_SET_DIGIT '\7' + #define REGEX_SET_ALPHANUMERIC '\8' + #define REGEX_SET_PHPVAR '\9' + + #define REGEX_ALPHA_LOWER "[abcdefghijklmnopqrstuvwxyz]" + #define REGEX_ALPHA_UPPER "[ABCDEFGHIJKLMNOPQRSTUVWXYZ]" + #define REGEX_DIGIT "[0123456789]" + #define REGEX_ALPHANUMERIC "[\1\2\3]" + #define REGEX_PHPVAR "[\1\2_][\4_]+" + + /* TYPES */ + struct RegExpMatch{ + char match[MAX_MATCH_SIZE]; + unsigned int start; + unsigned int end; + }; + + struct RegExpMatches{ + unsigned int n; + struct RegExpMatch* matches; + }; + + struct RegExpDevSet{ + unsigned int start; + unsigned int end; + char quantifier; + char* set; + char n; + }; + + struct RegExpDevSets{ + unsigned int n; + struct RegExpDevSet* sets; + }; + + + /* GLOBAL */ + #include + #include + #include + + /* SIGNATURES */ + // struct RegExpMatches match(const char* pPattern, char* pBuffer); + + /* Check if buffer is made of characters from pSet */ + char madeOfSet(char* pBuffer, const char* pSet); + + /* Develops a pattern's sets (error:-1, else:0) */ + int developSingle(const char* pPattern, struct RegExpDevSets* pCases, struct RegExpDevSets* pGroups); + + int developMulti(const char* pPattern, struct RegExpDevSets* pCases, struct RegExpDevSets* pGroups, const char pDepth); + +#endif \ No newline at end of file diff --git a/src/lib/regex/usecase.c b/src/lib/regex/usecase.c new file mode 100644 index 0000000..33fe940 --- /dev/null +++ b/src/lib/regex/usecase.c @@ -0,0 +1,55 @@ +int main(){ + + struct RegExpMatches matches; + + + matches = match("([(public)(private)] )?(static )?function\(($\a)\)"); + + "[abc]*" == "(a|b|c)*" // Any of the chars inside any time + "[abc]?" == "(a|b|c)?" // Any of the chars inside zero or one time + "[abc]+" == "(a|b|c)+" // Any of the chars inside at least one time + + "(abc)*" // The chain inside any time + "(abc)?" // The chain inside zero or one time + "(abc)+" // The chain inside at least one time + + "(abc|xyz)*" // Any of the chains inside any time + "(abc|xyz)?" // Any of the chains inside zero or one time + "(abc|xyz)+" // Any of the chains inside at least one time + + "." // Any character + "[a-z]" // Any letters between 'a' and 'z' (included) + "[0-8]" // Any letters between '0' and '8' (included) + + "(a[bx]c)" == "(abc|axc)" + "[a(bx)c]" == "(a|bx|c)" + "(a[bc]d[ef]g)" == "(abdeg|abdfg|acdeg|acdfg)" + "[a(bc)d(ef)g]" == "(a|bc|d|ef|g)" + + "* The NF is a group '()' with no case '[]'" + + "* For instance with the undevelopped form: " + "((public|private) *)?(static *)? *function\([abc]*\)" + "* Will be developped into: " + "(((public|private) *)?(static *)? *function\([abc]*\))" // surrounding with '(' and ')' + "(((public|private) *)?(static *)? *function\((a|b|c)\))" // develop cases '[...]' + + "* For instance with the undevelopped form: " + "[a-z0-9_\.]+@[a-z0-9_\.]\.[a-z]+" + "* Will be developped into: " + "([a-z0-9_\.]+@[a-z0-9_\.]\.[a-z]+)" + "((a-z|0-9|_|\.)+@(a-z|0-9|_|\.)\.(a-z)+)" + "((a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|0|1|2|3|4|5|6|7|8|9|_|\.)+@(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|0|1|2|3|4|5|6|7|8|9|_|\.)\.(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z)+)" + + + "* For instance with the undevelopped form: " + "[ \t]*$[a-zA-Z_][a-zA-Z0-9_]+ *[+-/*|&]?= *.+" + "* Will be developped into: " + "([ \t]*$[a-zA-Z_][a-zA-Z0-9_]+ *[+-/*|&]?= *.+)" // surrounding by () + "([ \t]*$[a-zA-Z_][a-zA-Z0-9_]+( )*[+-/*|&]?=( )*(.)+)" // replacing non-captured chains + "(( |\t)*$(a-z|A-Z|_)(a-z|A-Z|0-9|_)+( )*(+|-|/|*|||&)?=( )*(.)+)" // develop [] + + "* So we have the following matching automate :" + "( |\t)*$(a-z|A-Z|_)(a-z|A-Z|0-9|_)+( )*(+|-|/|*|||&)?=( )*(.)+)" // develop [] + +} \ No newline at end of file diff --git a/src/lib/scope/scope.c b/src/lib/scope/scope.c new file mode 100644 index 0000000..604b958 --- /dev/null +++ b/src/lib/scope/scope.c @@ -0,0 +1,10 @@ +/************************** +* Scope * +*************************** +* Designed & Developed by * +* Adrien Marquès * +* * +*************************** +* doowap31@gmail.com * +**************************/ +#include "scope.h" \ No newline at end of file diff --git a/src/lib/scope/scope.h b/src/lib/scope/scope.h new file mode 100644 index 0000000..31989bd --- /dev/null +++ b/src/lib/scope/scope.h @@ -0,0 +1,24 @@ +/************************** +* Scope * +*************************** +* Designed & Developed by * +* Adrien Marquès * +* * +*************************** +* doowap31@gmail.com * +**************************/ +#ifndef _LIB_SCOPE_SCOPE_H_ + #define _LIB_SCOPE_SCOPE_H_ + + /* GLOBAL */ + #include + #include + + /* LOCAL */ + #include "../php-const.h" + + /* SIGNATURES */ + int is_function_start(char* pLine); + + +#endif \ No newline at end of file diff --git a/src/linter.c b/src/linter.c index 0fc2cde..a350e78 100644 --- a/src/linter.c +++ b/src/linter.c @@ -12,19 +12,97 @@ int main(int argc, char* argv[]){ + /* [0] Init variables + =========================================================*/ + FILE* source; + char* line = malloc( MAX_LINE ); + char c; + char eof = 0; + + + /** TEST **/ + /** BUILD AUTOMATE **/ + struct Automate a = createAutomate(); + + addState(&a); + addState(&a); + addState(&a); + + addSet(&a, "ba\0"); + addSet(&a, "be\0"); + addSet(&a, "bi\0"); + + linkStates(&a, 0, 1, "ba\0"); + linkStates(&a, 1, 1, "be\0"); + linkStates(&a, 1, 2, "bi\0"); + + printf("browse 'aei' : %d\n", browse(a, "aei")); + printf("browse 'bbb' : %d\n", browse(a, "bbb")); + printf("browse 'abi' : %d\n", browse(a, "abi")); + printf("browse 'abb' : %d\n", browse(a, "abb")); + printf("browse 'i' : %d\n", browse(a, "i")); + printf("browse 'b' : %d\n", browse(a, "b")); + /** TEST **/ + { /* [1] Check arguments =========================================================*/ /* (1) argc */ - if( argc < 2 ) + if( argc < 2 ){ + fprintf(stderr, "Missing argument."); return EXIT_FAILURE; + } /* (2) argv[1] : absolute path */ - if( argv[1][0] != '/' ) + if( argv[1][0] != '/' ){ + fprintf(stderr, "Path must be absolute.\n"); return EXIT_FAILURE; + } /* (3) argv[1] : */ - if( access(argv[1], F_OK) == -1 ) + if( access(argv[1], F_OK) == -1 ){ + fprintf(stderr, "Path unknown.\n"); return EXIT_FAILURE; + } + + } + + { /* [2] Read file line by line + =========================================================*/ + /* (1) Open file */ + source = fopen(argv[1], "r"); + + if( source == NULL ){ + fprintf(stderr, "Cannot read the file.\n"); + return EXIT_FAILURE; + } + + /* (2) For each line + ---------------------------------------------------------*/ + while( 1 ){ + + /* (1) Get each line */ + if( fgets(line, MAX_LINE, source) == NULL ) + if( feof(source) ) return EXIT_SUCCESS; + else return EXIT_FAILURE; + + /* (2) Remove trailing EOL */ + if( line[strlen(line)-1] == '\n' ) + line[strlen(line)-1] = 0; + + /* (3) Get indentation level */ + int indentLevel = getIndentation(line, strlen(line)); + + /* (4) Isolate line */ + isolate_line(line, strlen(line)); + + printf("line/%d: '%s'\n", indentLevel, line); + + } + + + + /* (n) Close file */ + fclose(source); } @@ -32,6 +110,5 @@ int main(int argc, char* argv[]){ - return EXIT_SUCCESS; } \ No newline at end of file diff --git a/src/linter.h b/src/linter.h index c703d26..82a3cf2 100644 --- a/src/linter.h +++ b/src/linter.h @@ -11,8 +11,17 @@ #ifndef _LINTER_H_ #define _LINTER_H_ + /* GLOBAL */ #include #include + #include #include + #include + + /* LOCAL */ + #include "lib/php-const.h" + #include "lib/common/common.h" + #include "lib/scope/scope.h" + #include "lib/automate/automate.h" #endif \ No newline at end of file