├── README ├── isql.dat ├── isql.db ├── isql.l ├── isql.y ├── isql_main.c ├── isql_main.h └── makefile /README: -------------------------------------------------------------------------------- 1 | #README 2 | 3 | #文件树 4 | ================================================== 5 | .isql 6 | |--isql.l flex文件,用于isql的词法分析 7 | |--isql.y bison文件,用于isql的语法分析及语法树构建 8 | |--isql_main.h isql的主要函数,结构及宏声明 9 | |--isql_main.c isql的主要函数实现 10 | |--isql.db/dat isql的数据库文件 11 | |--isql isql可执行文件 12 | |--makefile Makefile 13 | |--README.txt 说明文件 14 | 15 | #关于版本和版权 16 | ================================================== 17 | version 1.0 18 | 为isql的第一个版本,很多不完善的地方,下面会具体说明功能及缺陷,2.0在大三考试结束后推出 19 | 任何人都可以自由修改和使用源码 20 | 如有问题与我联系:roselonelh@gmail.com 21 | 22 | #运行方法 23 | ================================================== 24 | linux平台开发,使用flex && bison进行语法词法生成 25 | 现给出Ubuntu下的配置方法,其他发行版类似 26 | 27 | 1,isql使用c语言编写,首选需要安装build-essential,gcc,flex,bison,命令如下: 28 | $ sudo apt-get install build-essential gcc flex bison 29 | 2,老一套,直接make即可,编译过程参见makefile 30 | $ make 31 | 3,运行,默任生成到当前目录,文件名isql 32 | $ ./isql 33 | 4,身份验证 34 | 管理员用户名和密码都为admin,登录即可 35 | 36 | # version 1.0 已实现的功能 37 | ================================================== 38 | 1,部分支持SQL规范 39 | 2,识别大小写 40 | 3,可以识别的语法 41 | a创建用户,数据库,表 | CREATE 42 | b删除数据库,表 | DROP 43 | c用户权限分配和收回 | GRANT REVOKE 44 | d插入 查询 表数据 | INSERT SELECT 45 | e删除 修改 表数据 | DELETE UPDATE 46 | 4,完成a~d的语法树构建及语法制导翻译 47 | 5,登录身份的MD5验证 48 | 6,物理存储结构设计及实现 49 | 50 | # version 1.0 的缺陷 [在下一版中会改进和实现] 51 | ================================================== 52 | 1,不支持查询嵌套 53 | 2,未实现e功能 54 | 3,where子句查询有bug,先屏蔽掉了 55 | 4,数据库操作权限验证查询有bug,先屏蔽掉了 56 | 5,没有异常处理 57 | 6,仅支持int和string两种数据类型 58 | 7,没有数据库数据空间整理,会不断增长 59 | 8,物理存储设计在实验阶段,所能创建的用户和数据库数量有限,这个只要修改配置文件即可,不影响整体的物理结构设计 60 | 9,用户密码是明文输入,没有用****代替 61 | 62 | #关于安全机制 63 | ================================================== 64 | 1,用户密码使用MD5加密存储 65 | 使用md5sum进行MD5校验(128-bit) 66 | GNU coreutils 项目主页: 67 | 使用bash shell调用MD5SUM计算:echo PASSWD | md5sum 68 | 69 | 2,数据库操作权限验证方法 70 | #define P_SELECT 0001 71 | #define P_INSERT 0010 72 | #define P_UPDATE 0100 73 | #define P_DELETE 1000 74 | admin用户默认权限:1111,用户编码为0,且只有admin可以进行权力的授予和收回。 75 | 验证权限:POWER & POWER_NEEDED 76 | 授予权限:POWER | POWER_GRANT 77 | 收回权限:~(POWER & POWER_REVOKE) 78 | 79 | #物理存储 80 | ================================================== 81 | isql.db 用于存储数据库结构信息 82 | isql.dat 用于存储数据库数据信息 83 | 84 | 以下三个函数用于数据库文件操作: 85 | char *read_D(FILE *fin, int offset, int length); 86 | void write_D(FILE *fin, int offset, char *str); 87 | void fill_D(FILE *fin, int offset, int length, char t); 88 | 89 | 寻址采用类似内存的基址+偏移量方式 90 | 数据信息存储文件isql.dat采用类似FAT12的管理方式 91 | 92 | -------------------------------------------------------------------------------- /isql.dat: -------------------------------------------------------------------------------- 1 | 68min0456b7016a916a4b178dd72b947c152b766admin0456b7016a916a4b178dd72b947c152b7015boo1 -------------------------------------------------------------------------------- /isql.l: -------------------------------------------------------------------------------- 1 | /************************************** 2 | * filename isql.l 3 | * scanner for SQL lex file 4 | * Copyright (c) 2011, RL. All rights reserved. 5 | * flex -o isql.lex.c isql.l 6 | **************************************/ 7 | 8 | %option noyywrap nodefault yylineno case-insensitive 9 | 10 | %{ 11 | #include "isql.tab.h" 12 | #include "isql_main.h" 13 | #include 14 | #include 15 | #include 16 | %} 17 | 18 | %X COMMENT 19 | 20 | %% 21 | 22 | /*KEYWORDS*/ 23 | 24 | CREATE { return CREATE; } 25 | DATABASE { return DATABASE; } 26 | DATABASES { return DATABASES; } 27 | SHOW { return SHOW; } 28 | USE { return USE; } 29 | TABLE { return TABLE; } 30 | TABLES { return TABLES; } 31 | DROP { return DROP; } 32 | INSERT { return INSERT; } 33 | INTO { return INTO; } 34 | VALUES { return VALUES; } 35 | SELECT { return SELECT; } 36 | FROM { return FROM; } 37 | WHERE { return WHERE; } 38 | AND { return AND; } 39 | OR { return OR; } 40 | DELETE { return DELETE; } 41 | UPDATE { return UPDATE; } 42 | SET { return SET; } 43 | IF[ \t\n]+EXISTS {return IF_EXISTS;} 44 | SCHEMA {return SCHEMA;} 45 | INT { return INT; } 46 | CHAR { return CHAR; } 47 | ROLE { return ROLE; } 48 | GRANT { return GRANT; } 49 | TO { return TO; } 50 | ON { return ON; } 51 | REVOKE { return REVOKE; } 52 | CASCADE { return CASCADE; } 53 | WITH { return WITH; } 54 | OPTION { return OPTION; } 55 | EXIT { yyterminate(); } 56 | 57 | /*NUMBERS*/ 58 | 59 | -?[0-9]+ { yylval.intval = atoi(yytext); return INTNUM; } /*int*/ 60 | -?[0-9]+"."[0-9]* | 61 | -?"."[0-9]+ | 62 | -?[0-9]+E[-+]?[0-9]+ | 63 | -?[0-9]+"."[0-9]*E[-+]?[0-9]+ | 64 | -?"."[0-9]*E[-+]?[0-9]+ { yylval.floatval = atof(yytext); return APPROXNUM; } /*float*/ 65 | 66 | /*BOOLEANS*/ 67 | 68 | TRUE { yylval.intval = 1; return BOOL; } 69 | FALSE { yylval.intval = 1; return BOOL; } 70 | UNKNOWN { yylval.intval = 1; return BOOL; } 71 | 72 | /*strings*/ 73 | 74 | '(\\.|''|[^'\n])*' { 75 | yylval.strval = strdup(yytext); 76 | yylval.strval=(char *)(yylval.strval+1); //去掉单引号 77 | yylval.strval[strlen(yylval.strval)-1]='\0'; 78 | return STRING; } 79 | [A-Za-z][A-Za-z0-9_]* { yylval.strval = strdup(yytext); return NAME; } 80 | 81 | /*OPERATORS*/ 82 | 83 | [-+*/(),.;] {return yytext[0]; } 84 | "=" { yylval.subtok = 1; return CMP; } 85 | "!=" { yylval.subtok = 2; return CMP; } 86 | "<" { yylval.subtok = 3; return CMP; } 87 | ">" { yylval.subtok = 4; return CMP; } 88 | "<=" { yylval.subtok = 5; return CMP; } 89 | ">=" { yylval.subtok = 6; return CMP; } 90 | 91 | /*COMMENT*/ 92 | 93 | "/*" { BEGIN COMMENT; } 94 | "*/" ; 95 | .|\n ; 96 | <> { yyerror("unclosed comment"); } 97 | 98 | [ \t\n] /*white space*/ 99 | . { yyerror("UNKNOW WORDS '%c'",*yytext); } 100 | 101 | %% 102 | -------------------------------------------------------------------------------- /isql.y: -------------------------------------------------------------------------------- 1 | /************************************** 2 | * filename isql.y 3 | * Parser for SQL yacc file 4 | * Copyright (c) 2011, RL. All rights reserved. 5 | * bison -d isql.y 6 | **************************************/ 7 | 8 | %{ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "isql_main.h" 14 | 15 | extern int DT_HANDLE; 16 | extern int pFList; 17 | extern struct _fieldList FList[]; 18 | 19 | %} 20 | 21 | %union { 22 | int intval; 23 | double floatval; 24 | char *strval; 25 | int subtok; 26 | struct _expr *Expr; 27 | struct ast_createD *createD; 28 | struct ast_createDefinition *createDefinition; 29 | struct ast_createCol_list *createCol_list; 30 | struct ast_createTable *createTable; 31 | struct ast_wordList *wordList; 32 | struct ast_tableInto *tableInto; 33 | struct ast_valList *valList; 34 | struct ast_insertRecord *insertRecord; 35 | struct ast_selectRecord *selectRecord; 36 | struct ast_permission *permission; 37 | } 38 | 39 | /*names and literal values*/ 40 | 41 | %token NAME 42 | %token STRING 43 | %token INTNUM 44 | %token BOOL 45 | %token APPROXNUM 46 | 47 | /*operators and precedence levels*/ 48 | 49 | %left OR 50 | %left AND 51 | %left CMP /* = != < > <= >= */ 52 | %left '+' '-' 53 | %left '*' '/' 54 | %nonassoc UMINUS 55 | 56 | %token CREATE 57 | %token DATABASE 58 | %token DATABASES 59 | %token SHOW 60 | %token USE 61 | %token TABLE 62 | %token TABLES 63 | %token DROP 64 | %token INSERT 65 | %token INTO 66 | %token VALUES 67 | %token SELECT 68 | %token FROM 69 | %token WHERE 70 | %token ADD 71 | %token OR 72 | %token DELETE 73 | %token UPDATE 74 | %token SET 75 | %token IF_EXISTS 76 | %token SCHEMA 77 | %token CMP 78 | %token INT 79 | %token CHAR 80 | %token ROLE 81 | %token GRANT 82 | %token TO 83 | %token ON 84 | %token REVOKE 85 | %token CASCADE 86 | %token WITH 87 | %token OPTION 88 | 89 | 90 | %type drop_obj show_obj data_type opt_length power power_lists 91 | %type create_definition 92 | %type create_col_list 93 | %type create_table_stmt 94 | %type insert_expr_list select_expr_list table_references users 95 | %type table_into 96 | %type insert_vals_list insert_vals 97 | %type insert_stmt 98 | %type expr opt_where 99 | %type table_reference passwd 100 | %type select_stmt 101 | %type usermanage_stmt 102 | 103 | %start stmt_list 104 | 105 | %% 106 | 107 | /*expressions*/ 108 | expr: NAME { $$=malloc(sizeof(struct _expr));$$->type=0; $$->string=$1; FList[pFList].name=$1; pFList++; } 109 | /* | NAME '.' NAME */ 110 | | STRING { $$=malloc(sizeof(struct _expr));$$->type=1; $$->string=$1; } 111 | | INTNUM { $$=malloc(sizeof(struct _expr));$$->type=2; $$->intval=$1; } 112 | /* | APPROXNUM 113 | | BOOL */ 114 | ; 115 | 116 | expr: '(' expr ')' { $$=$2; } 117 | | expr '+' expr { $1->intval=$1->intval+$3->intval; $$=$1; } 118 | | expr '-' expr { $1->intval=$1->intval-$3->intval; $$=$1; } 119 | | expr '*' expr { $1->intval=$1->intval*$3->intval; $$=$1; } 120 | | expr '/' expr 121 | /* | '-' expr %prec UMINUS */ 122 | | expr CMP expr { $$=malloc(sizeof(struct _expr)); $$->type=$2+2; $$->left=$1; $$->right=$3; } 123 | | expr AND expr { $$=malloc(sizeof(struct _expr)); $$->type=9; $$->left=$1; $$->right=$3; } 124 | | expr OR expr { $$=malloc(sizeof(struct _expr)); $$->type=10; $$->left=$1; $$->right=$3; } 125 | ; 126 | 127 | /*start*/ 128 | stmt_list: 129 | | stmt_list ';' { printf("> "); } 130 | | stmt_list stmt ';' { printf("> "); } 131 | | stmt_list error { yyclearin; yyerrok; printf("> "); } 132 | ; 133 | 134 | /*stmt:select statement*/ 135 | stmt: select_stmt { 136 | // if (DT_HANDLE==-1) {yyerror("Please choose a DATABASE !");} 137 | // else { 138 | // select_Record($1); 139 | // } 140 | } 141 | ; 142 | 143 | select_stmt: SELECT select_expr_list FROM table_references opt_where { 144 | if (DT_HANDLE==-1) {yyerror("Please choose a DATABASE !");} 145 | else { 146 | $$=malloc(sizeof(struct ast_selectRecord)); 147 | $$->wordlist=$2; 148 | $$->where_tree=$5; 149 | while ($4!=NULL){ 150 | $$->name=$4->name; 151 | select_Record($$); 152 | $4=$4->next; 153 | } 154 | } 155 | pFList=0; 156 | } 157 | ; 158 | 159 | select_expr_list: NAME { 160 | $$=malloc(sizeof(struct ast_wordList)); 161 | $$->name=$1; 162 | $$->next=NULL; 163 | } 164 | | select_expr_list ',' NAME { $$=add_wordList($1,$3); } 165 | | '*' { $$=NULL; } 166 | ; 167 | 168 | table_references: table_reference { 169 | $$=malloc(sizeof(struct ast_wordList)); 170 | $$->name=$1; 171 | $$->next=NULL; 172 | } 173 | | table_references ',' table_reference { $$=add_wordList($1,$3); } 174 | ; 175 | 176 | table_reference: NAME { $$=$1; } 177 | ; 178 | 179 | opt_where: { $$=NULL; } 180 | | WHERE expr { $$=$2; } 181 | ; 182 | 183 | /*stmt:delete statement*/ 184 | 185 | stmt: delete_stmt 186 | ; 187 | 188 | delete_stmt: DELETE FROM table_references opt_where 189 | ; 190 | 191 | /*stmt:insert statement*/ 192 | 193 | stmt: insert_stmt { 194 | if (DT_HANDLE==-1) {yyerror("Please choose a DATABASE !");} 195 | else { 196 | insert_Record($1); 197 | } 198 | } 199 | ; 200 | 201 | insert_stmt: INSERT INTO table_into VALUES insert_vals_list { 202 | $$=malloc(sizeof(struct ast_insertRecord)); 203 | $$->tableinto=$3; 204 | $$->vallist=$5; 205 | } 206 | ; 207 | 208 | table_into: NAME { $$=malloc(sizeof(struct ast_tableInto)); $$->name=$1; $$->wordlist=NULL; } 209 | | NAME '(' insert_expr_list ')' { 210 | $$=malloc(sizeof(struct ast_tableInto)); 211 | $$->name=$1; 212 | $$->wordlist=$3; 213 | } 214 | ; 215 | 216 | insert_expr_list: NAME { 217 | $$=malloc(sizeof(struct ast_wordList)); 218 | $$->name=$1; 219 | $$->next=NULL; 220 | } 221 | | insert_expr_list ',' NAME { $$=add_wordList($1,$3); } 222 | ; 223 | 224 | insert_vals_list: '(' insert_vals ')' { $$=$2; } 225 | ; 226 | 227 | insert_vals: expr { 228 | $$=malloc(sizeof(struct ast_valList)); 229 | $$->expr=$1; 230 | $$->next=NULL; 231 | } 232 | | insert_vals ',' expr { $$=add_Vals($1,$3); } 233 | ; 234 | 235 | /*stmt:update statement*/ 236 | 237 | stmt: update_stmt 238 | ; 239 | 240 | update_stmt: UPDATE table_references 241 | SET update_asgn_list 242 | opt_where 243 | ; 244 | 245 | update_asgn_list: NAME CMP expr 246 | /* | NAME '.' NAME CMP expr */ 247 | | update_asgn_list ',' NAME CMP expr 248 | /* | update_asgn_list ',' NAME '.' NAME CMP expr */ 249 | ; 250 | 251 | /*stmt:create database*/ 252 | 253 | stmt: create_database_stmt 254 | ; 255 | 256 | create_database_stmt: CREATE DATABASE opt_if_not_exists NAME 257 | { 258 | FILE *fin; 259 | if(!(fin=fopen("isql.db","r+"))){ 260 | printf("cannot open file isql.db\n"); 261 | } 262 | int num=atoi(read_D(fin,0,8)); 263 | int i; 264 | int flag=0; 265 | char *tmp; 266 | for (i=0;iname=$4; 300 | $$->col_list=$6; 301 | } 302 | /* | CREATE TABLE opt_if_not_exists NAME '.' NAME '(' create_col_list ')'*/ 303 | ; 304 | 305 | create_col_list: create_definition { $$=malloc(sizeof(struct ast_createCol_list)); 306 | $$->createDefinition=$1; 307 | $$->next=NULL; 308 | } 309 | | create_col_list ',' create_definition { $$=add_createCol_list($1,$3); } 310 | ; 311 | 312 | create_definition: NAME data_type opt_length { 313 | $$=new_CDefinition($1,$2,$3); 314 | } 315 | ; 316 | 317 | data_type: INT { $$=0; } 318 | | CHAR { $$=1; } 319 | ; 320 | 321 | opt_length: { $$=8; } 322 | | '(' INTNUM ')' { $$=$2; } 323 | ; 324 | 325 | /*stmt: show statement*/ 326 | 327 | stmt: show_stmt 328 | ; 329 | 330 | show_stmt: SHOW show_obj { 331 | if (!$2){ 332 | FILE *fin; 333 | if(!(fin=fopen("isql.db","r+"))){ 334 | printf("cannot open file isql.db\n"); 335 | } 336 | int num=atoi(read_D(fin,0,8)); 337 | int i; 338 | char *tmp; 339 | for (i=0;iflag=0; 454 | $$->permission=$2; 455 | $$->tablelist=$5; 456 | $$->userlist=$7; 457 | } 458 | /* | GRANT users TO users */ 459 | | REVOKE power_lists ON TABLE table_references FROM users { 460 | $$=malloc(sizeof(struct ast_permission)); 461 | $$->flag=1; 462 | $$->permission=$2; 463 | $$->tablelist=$5; 464 | $$->userlist=$7; 465 | } 466 | ; 467 | 468 | passwd: NAME { $$=$1; } 469 | ; 470 | 471 | power_lists: power { $$=0|$1; } 472 | | power_lists ',' power { $$=$1|$3; } 473 | ; 474 | 475 | power: SELECT { $$=1; } /*0001*/ 476 | | INSERT { $$=2; } /*0010*/ 477 | | UPDATE { $$=4; } /*0100*/ 478 | | DELETE { $$=8; } /*1000*/ 479 | ; 480 | 481 | users: NAME { 482 | $$=malloc(sizeof(struct ast_wordList)); 483 | $$->name=$1; 484 | $$->next=NULL; 485 | } 486 | | users ',' NAME { $$=add_wordList($1,$3); } 487 | ; 488 | 489 | %% 490 | 491 | 492 | -------------------------------------------------------------------------------- /isql_main.c: -------------------------------------------------------------------------------- 1 | /************************************** 2 | * filename isql_main.c 3 | * c file for SQL main func 4 | * Copyright (c) 2011, RL. All rights reserved. 5 | * cc -c -o isql_main.o isql_main.c 6 | * ************************************/ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "isql_main.h" 14 | 15 | int DT_HANDLE; 16 | int USER_NUM; 17 | struct _fieldList FList[50]; 18 | int pFList; 19 | 20 | char* read_D(FILE *fin,int offset,int length){ 21 | char *tmp=(char*)malloc(sizeof(char)*length); 22 | fseek(fin,offset,SEEK_SET); 23 | fread(tmp,sizeof(char),length,fin); 24 | return tmp; 25 | } 26 | 27 | void write_D(FILE *fin,int offset,char *str){ 28 | fseek(fin,offset,SEEK_SET); 29 | int num=fwrite(str,sizeof(char),strlen(str),fin); 30 | return ; 31 | } 32 | 33 | void fill_D(FILE *fin, int offset, int length, char t){ 34 | int i; 35 | fseek(fin,offset,SEEK_SET); 36 | for(i=0;iname=name; 94 | tmp->data_type=data_type; 95 | tmp->opt_length=opt_length; 96 | return tmp; 97 | } 98 | 99 | struct ast_createCol_list *add_createCol_list(struct ast_createCol_list *list,struct ast_createDefinition *nextDefinition){ 100 | struct ast_createCol_list *tmp=list; 101 | while (tmp->next!=NULL) tmp=tmp->next; 102 | struct ast_createCol_list *added=malloc(sizeof(struct ast_createCol_list)); 103 | added->createDefinition=nextDefinition; 104 | added->next=NULL; 105 | tmp->next=added; 106 | return list; 107 | } 108 | 109 | void create_Table(struct ast_createTable *table){ 110 | FILE *fin,*fout; 111 | if (!(fin=fopen("isql.db","r+"))){ 112 | printf("cannot open file isql.db\n"); 113 | } 114 | if (!(fout=fopen("isql.dat","r+"))){ 115 | printf("cannot open file isql.dat!\n"); 116 | } 117 | int offset=D_PAGE*PAGE_SIZE+DT_HANDLE*D_HEAD_SIZE; 118 | int table_num=atoi(read_D(fin,offset+D_NAME_SIZE,32)); //D中现有table数 119 | fseek(fin,offset+D_NAME_SIZE,SEEK_SET); 120 | fprintf(fin,"%d",table_num+1); //下一个table 121 | 122 | offset=T_LIST_PAGE*PAGE_SIZE+DT_HANDLE*T_LIST_SIZE+table_num*T_HEAD_SIZE; 123 | int tmpoff=offset; 124 | fill_D(fin,offset,T_HEAD_SIZE,null); //初始化为空 125 | write_D(fin,offset,table->name); 126 | int num=atoi(read_D(fin,8,12)); //字段表地址页 127 | fseek(fin,offset+T_NAME_SIZE,SEEK_SET); 128 | fprintf(fin,"%d",num); 129 | fseek(fin,offset+T_NAME_SIZE+T_PAGE+T_USERNUM,SEEK_SET); 130 | fprintf(fin,"%d",0); //初始表中没有记录 131 | fseek(fin,8,SEEK_SET); 132 | fprintf(fin,"%d",num+1); //下一个字段表 133 | 134 | /*建立用户表*/ 135 | if (USER_NUM==0) { fseek(fin,offset+T_NAME_SIZE+T_PAGE,SEEK_SET);fprintf(fin,"%d",1); } 136 | else {fseek(fin,offset+T_NAME_SIZE+T_PAGE,SEEK_SET);fprintf(fin,"%d",2); } 137 | offset=U_LISTPAGE*PAGE_SIZE+(num-18)*U_LISTSIZE; 138 | fseek(fout,offset,SEEK_SET); //admin用户 139 | fprintf(fout,"%d",0); 140 | fseek(fout,offset+U_NUM,SEEK_SET); 141 | fprintf(fout,"%d",15); 142 | if (USER_NUM!=0){ 143 | offset=offset+U_WORDSIZE; 144 | fseek(fout,offset,SEEK_SET); 145 | fprintf(fout,"%d",USER_NUM); 146 | fseek(fout,offset+8,SEEK_SET); 147 | fprintf(fout,"%d",15); 148 | } 149 | 150 | struct ast_createCol_list *tmplist=table->col_list; 151 | offset=num*PAGE_SIZE; 152 | int word=0; 153 | write_D(fin,offset+word*WORD_SIZE,tmplist->createDefinition->name); 154 | fseek(fin,offset+word*WORD_SIZE+W_NAME_SIZE,SEEK_SET); 155 | fprintf(fin,"%d",tmplist->createDefinition->data_type); 156 | fseek(fin,offset+word*WORD_SIZE+W_NAME_SIZE+W_TYPE,SEEK_SET); 157 | fprintf(fin,"%d",tmplist->createDefinition->opt_length); 158 | fseek(fin,offset+word*WORD_SIZE+W_NAME_SIZE+W_TYPE+W_LENGTH,SEEK_SET); 159 | num=atoi(read_D(fout,0,8)); //从16页开始 160 | fprintf(fin,"%d",num); 161 | while (tmplist->next!=NULL){ 162 | tmplist=tmplist->next; 163 | word++;num++; 164 | write_D(fin,offset+word*WORD_SIZE,tmplist->createDefinition->name); 165 | fseek(fin,offset+word*WORD_SIZE+W_NAME_SIZE,SEEK_SET); 166 | fprintf(fin,"%d",tmplist->createDefinition->data_type); 167 | fseek(fin,offset+word*WORD_SIZE+W_NAME_SIZE+W_TYPE,SEEK_SET); 168 | fprintf(fin,"%d",tmplist->createDefinition->opt_length); 169 | fseek(fin,offset+word*WORD_SIZE+W_NAME_SIZE+W_TYPE+W_LENGTH,SEEK_SET); 170 | 171 | fprintf(fin,"%d",num); 172 | } 173 | fseek(fin,tmpoff+T_NAME_SIZE+T_PAGE+T_USERNUM+T_COUNT,SEEK_SET); 174 | fprintf(fin,"%d",word+1); //字段数 175 | fseek(fout,0,SEEK_SET); 176 | fprintf(fout,"%d",num+1); 177 | fclose(fin); 178 | fclose(fout); 179 | return ; 180 | } 181 | 182 | struct ast_valList *add_Vals(struct ast_valList *list,struct _expr *nextExpr){ 183 | struct ast_valList *tmp=list; 184 | while (tmp->next!=NULL) tmp=tmp->next; 185 | struct ast_valList *added=malloc(sizeof(struct ast_valList)); 186 | added->expr=nextExpr; 187 | added->next=NULL; 188 | tmp->next=added; 189 | return list; 190 | } 191 | 192 | struct ast_wordList *add_wordList(struct ast_wordList *list, char *nextname){ 193 | struct ast_wordList *tmp=list; 194 | while (tmp->next!=NULL) tmp=tmp->next; 195 | struct ast_wordList *added=malloc(sizeof(struct ast_wordList)); 196 | added->name=nextname; 197 | added->next=NULL; 198 | tmp->next=added; 199 | return list; 200 | } 201 | 202 | void insert_Record(struct ast_insertRecord *record){ 203 | struct ast_tableInto *tableinto=record->tableinto; 204 | struct ast_valList *vallist=record->vallist; 205 | 206 | FILE *fin,*fout; 207 | if (!(fin=fopen("isql.db","r+"))){ 208 | printf("cannot open file isql.db\n"); 209 | } 210 | if (!(fout=fopen("isql.dat","r+"))){ 211 | printf("cannot open file isql.dat!\n"); 212 | } 213 | 214 | // if (!judge(fin,fout,tableinto->name,P_INSERT)) goto end_insert; 215 | 216 | struct _table table; 217 | table.name=tableinto->name; 218 | table.D_HANDLE=DT_HANDLE; 219 | 220 | char *tmp; 221 | int i; 222 | int flag=0; 223 | int offset=D_PAGE*PAGE_SIZE+DT_HANDLE*D_HEAD_SIZE; 224 | int table_num=atoi(read_D(fin,offset+D_NAME_SIZE,D_TABLE_NUM)); 225 | offset=T_LIST_PAGE*PAGE_SIZE+DT_HANDLE*T_LIST_SIZE; 226 | for (i=0;iname)){ 229 | flag=1; 230 | fseek(fin,offset+i*T_HEAD_SIZE+T_NAME_SIZE,SEEK_SET); 231 | table.T_HANDLE=atoi(read_D(fin,offset+i*T_HEAD_SIZE+T_NAME_SIZE,T_PAGE)); 232 | table.count=atoi(read_D(fin,offset+i*T_HEAD_SIZE+T_NAME_SIZE+T_PAGE,T_COUNT)); 233 | fill_D(fin,offset+i*T_HEAD_SIZE+T_NAME_SIZE+T_PAGE,T_COUNT,null); 234 | fseek(fin,offset+i*T_HEAD_SIZE+T_NAME_SIZE+T_PAGE,SEEK_SET); 235 | fprintf(fin,"%d",table.count+1); 236 | table.words=atoi(read_D(fin,offset+(i+1)*T_HEAD_SIZE-T_WORDS,T_WORDS)); 237 | break; 238 | } 239 | } 240 | if (!flag) { yyerror("Table:%s didn't exist!\n",tableinto->name); return ;} 241 | 242 | table.list=(struct _fieldList **)malloc(sizeof(struct _fieldList *)*table.words); 243 | offset=table.T_HANDLE*PAGE_SIZE; 244 | for (i=0;iname=read_D(fin,offset+i*WORD_SIZE,W_NAME_SIZE); 247 | table.list[i]->type=atoi(read_D(fin,offset+i*WORD_SIZE+W_NAME_SIZE,W_TYPE)); 248 | table.list[i]->length=atoi(read_D(fin,offset+i*WORD_SIZE+W_NAME_SIZE+W_TYPE,W_LENGTH)); 249 | table.list[i]->page=atoi(read_D(fin,offset+i*WORD_SIZE+W_NAME_SIZE+W_TYPE+W_LENGTH,W_PAGE)); 250 | } 251 | 252 | struct ast_wordList *wordlist=tableinto->wordlist; 253 | if (wordlist==NULL){ //按顺序插入 254 | for (i=0;ipage*PAGE_SIZE+table.count*table.list[i]->length,SEEK_SET); 256 | if (!table.list[i]->type) 257 | fprintf(fout,"%d",vallist->expr->intval); 258 | else fprintf(fout,"%s",vallist->expr->string); 259 | vallist=vallist->next; 260 | } 261 | } 262 | else{ 263 | int **a=malloc(sizeof(int*)*table.words); 264 | for (i=0;iname,wordlist->name)){ 268 | (*a[i])=1; 269 | fseek(fout,table.list[i]->page*PAGE_SIZE+table.count*table.list[i]->length,SEEK_SET); 270 | //printf("%s:",table.list[i]->name); 271 | if (!table.list[i]->type){ 272 | fprintf(fout,"%d",vallist->expr->intval); 273 | // printf("%d\n",vallist->expr->intval); 274 | } 275 | else { 276 | fprintf(fout,"%s",vallist->expr->string); 277 | // printf("%s\n",vallist->expr->string); 278 | } 279 | break; 280 | } 281 | } 282 | wordlist=wordlist->next; 283 | vallist=vallist->next; 284 | } 285 | for (i=0;ipage*PAGE_SIZE+table.count*table.list[i]->length,SEEK_SET); 288 | fprintf(fout,"%s","NULL"); 289 | } 290 | } 291 | } 292 | end_insert: 293 | fclose(fin); 294 | fclose(fout); 295 | } 296 | 297 | int judge_Where(struct _expr *tree){ 298 | if (tree==NULL || tree->type<3) return 1; 299 | int i1,i2; 300 | char *s1,*s2; 301 | int type; 302 | if (tree->type>2 && tree->type<9) { 303 | switch (tree->left->type){ 304 | case 0:if(FList[pFList].type==0) { 305 | type=0;i1=FList[pFList].intval; 306 | } 307 | else { type=1; s1=FList[pFList].charval; } 308 | pFList++; 309 | break; 310 | case 1:type=1; s1=tree->left->string; break; 311 | case 2:type=0; i1=tree->left->intval; break; 312 | } 313 | switch (tree->right->type){ 314 | case 0:if(FList[pFList].type==0) i2=FList[pFList].intval; 315 | else s2=FList[pFList].charval; 316 | pFList++; 317 | break; 318 | case 1:s2=tree->right->string; break; 319 | case 2:i2=tree->right->intval; break; 320 | } 321 | } 322 | if (tree->type==9 || tree->type==10){ 323 | i1=judge_Where(tree->left); 324 | i2=judge_Where(tree->right); 325 | } 326 | switch (tree->type){ 327 | case 3:if (!type) tree->judge=(i1==i2?1:0); 328 | else tree->judge=(strcmp(s1,s2)==0?1:0); 329 | break; 330 | case 4:if (!type) tree->judge=(i1!=i2?1:0); 331 | else tree->judge=(strcmp(s1,s2)!=0?1:0); 332 | break; 333 | case 5:tree->judge=(i1judge=(i1>i2)?1:0;break; 335 | case 7:tree->judge=(i1<=i2)?1:0;break; 336 | case 8:tree->judge=(i1>=i2)?1:0;break; 337 | case 9:tree->judge=i1 & i2; break; 338 | case 10:tree->judge=i1 | i2; break; 339 | } 340 | return tree->judge; 341 | } 342 | 343 | void select_Record(struct ast_selectRecord *record){ 344 | FILE *fin,*fout; 345 | if (!(fin=fopen("isql.db","r+"))){ 346 | printf("cannot open file isql.db\n"); 347 | } 348 | if (!(fout=fopen("isql.dat","r+"))){ 349 | printf("cannot open file isql.dat!\n"); 350 | } 351 | // if (!judge(fin,fout,record->name,P_SELECT)) goto end_select; 352 | 353 | struct _table table; 354 | table.name=record->name; 355 | table.D_HANDLE=DT_HANDLE; 356 | 357 | 358 | char *tmp; 359 | int i; 360 | int flag=0; 361 | int offset=D_PAGE*PAGE_SIZE+DT_HANDLE*D_HEAD_SIZE; 362 | int table_num=atoi(read_D(fin,offset+D_NAME_SIZE,D_TABLE_NUM)); 363 | offset=T_LIST_PAGE*PAGE_SIZE+DT_HANDLE*T_LIST_SIZE; 364 | for (i=0;iname=read_D(fin,offset+i*WORD_SIZE,W_NAME_SIZE); 382 | table.list[i]->type=atoi(read_D(fin,offset+i*WORD_SIZE+W_NAME_SIZE,W_TYPE)); 383 | table.list[i]->length=atoi(read_D(fin,offset+i*WORD_SIZE+W_NAME_SIZE+W_TYPE,W_LENGTH)); 384 | table.list[i]->page=atoi(read_D(fin,offset+i*WORD_SIZE+W_NAME_SIZE+W_TYPE+W_LENGTH,W_PAGE)); 385 | } 386 | 387 | struct ast_wordList *wordlist=record->wordlist; 388 | int j; 389 | if (wordlist==NULL){ 390 | for (i=0;iname); 391 | printf("\n---------------------------------------------------\n"); 392 | for (j=0;jname)){ 399 | tmp=read_D(fout,table.list[i]->page*PAGE_SIZE+j*table.list[i]->length,table.list[i]->length); //null没有处理 400 | FList[k].type=table.list[i]->type; 401 | if (tmp[0]!=0x00) { 402 | flag2=1; 403 | if (!FList[k].type) FList[k].intval=atoi(tmp); 404 | else FList[k].charval=tmp; 405 | } 406 | break; 407 | } 408 | } 409 | } 410 | if (pFList==0) flag2=1; 411 | pFList=0; 412 | if (flag2 && judge_Where(record->where_tree)){ 413 | for (i=0;ipage*PAGE_SIZE+j*table.list[i]->length,table.list[i]->length); 415 | if (tmp[0]!=0x00){ 416 | printf("%-16s",tmp); 417 | flag=1; 418 | } 419 | } 420 | if (flag) printf("\n"); 421 | } 422 | } 423 | } 424 | else{ 425 | struct ast_wordList *tmplist=wordlist; 426 | while (tmplist!=NULL) { printf("%-16s",tmplist->name);tmplist=tmplist->next; } 427 | printf("\n---------------------------------------------------\n"); 428 | for (j=0;jname,table.list[i]->name)){ 434 | tmp=read_D(fout,table.list[i]->page*PAGE_SIZE+j*table.list[i]->length,table.list[i]->length); 435 | if (tmp[0]!=0x00){ 436 | printf("%-16s",tmp); 437 | flag=1; 438 | } 439 | break; 440 | } 441 | } 442 | tmplist=tmplist->next; 443 | } 444 | if (flag) printf("\n"); 445 | } 446 | } 447 | end_select: 448 | fclose(fin); 449 | fclose(fout); 450 | } 451 | 452 | char *get_MD5(char *str){ 453 | FILE *stream; 454 | char *buf=malloc(sizeof(char)*33); 455 | char cmd[100]; 456 | memset(buf,'\0',sizeof(buf)); 457 | memset(cmd,'\0',sizeof(cmd)); 458 | strcpy(cmd,"echo "); //5 459 | strcpy((char *)cmd+5,str); 460 | strcpy((char *)cmd+5+strlen(str)," | md5sum"); 461 | stream=popen(cmd,"r"); 462 | fread(buf,sizeof(char),32,stream); 463 | // printf("%s\n",buf); 464 | return buf; 465 | } 466 | 467 | void create_Role(char *username,char *passwd){ 468 | if (USER_NUM!=0) { 469 | yyerror("You don't have the right to create role !\n"); 470 | } 471 | else { 472 | FILE *fin,*fout; 473 | if (!(fin=fopen("isql.db","r+"))){ 474 | printf("cannot open file isql.db\n"); 475 | } 476 | if (!(fout=fopen("isql.dat","r+"))){ 477 | printf("cannot open file isql.dat!\n"); 478 | } 479 | int num=atoi(read_D(fin,20,8)); 480 | int offset=U_PAGE*PAGE_SIZE+num*U_HEAD_SIZE; 481 | write_D(fout,offset,username); 482 | fseek(fout,offset+U_NAME,SEEK_SET); 483 | fprintf(fout,"%d",num); 484 | write_D(fout,offset+U_NAME+U_NUM,get_MD5(passwd)); 485 | fseek(fin,20,SEEK_SET); 486 | fprintf(fin,"%d",num+1); 487 | } 488 | return; 489 | } 490 | 491 | int find_UNUM(char *name){ 492 | FILE *fin,*fout; 493 | if (!(fin=fopen("isql.db","r+"))){ 494 | printf("cannot open file isql.db\n"); 495 | } 496 | if (!(fout=fopen("isql.dat","r+"))){ 497 | printf("cannot open file isql.dat!\n"); 498 | } 499 | int num=atoi(read_D(fin,20,8)); 500 | int offset=U_PAGE*PAGE_SIZE; 501 | int i; 502 | for (i=0;itablelist; 513 | struct ast_wordList *userlist =pchange->userlist; 514 | FILE *fin,*fout; 515 | if (!(fin=fopen("isql.db","r+"))){ 516 | printf("cannot open file isql.db\n"); 517 | } 518 | if (!(fout=fopen("isql.dat","r+"))){ 519 | printf("cannot open file isql.dat!\n"); 520 | } 521 | 522 | char *tmp; 523 | int i; 524 | int flag; 525 | int offset=D_PAGE*PAGE_SIZE+DT_HANDLE*D_HEAD_SIZE; 526 | int table_num=atoi(read_D(fin,offset+D_NAME_SIZE,D_TABLE_NUM)); 527 | int users,usernum,k; 528 | struct ast_wordList *tmplist; 529 | 530 | while (tablelist!=NULL){ 531 | flag=0; 532 | offset=T_LIST_PAGE*PAGE_SIZE+DT_HANDLE*T_LIST_SIZE; 533 | for (i=0;iname)){ 536 | flag=1; 537 | users=atoi(read_D(fin,offset+i*T_HEAD_SIZE+T_NAME_SIZE,T_PAGE))-18; 538 | usernum=atoi(read_D(fin,offset+i*T_HEAD_SIZE+T_NAME_SIZE+T_PAGE,T_USERNUM)); 539 | break; 540 | } 541 | } 542 | if (!flag) { yyerror("Table:%s didn't exist!\n",tablelist->name); return ;} 543 | offset=U_LISTPAGE*PAGE_SIZE+users*U_LISTSIZE+usernum*U_WORDSIZE; 544 | k=0; 545 | tmplist=userlist; 546 | while (tmplist!=NULL){ 547 | fseek(fout,offset,SEEK_SET); 548 | fprintf(fout,"%d",find_UNUM(tmplist->name)); 549 | int org=atoi(read_D(fout,offset+U_NUM,U_POWER)); 550 | if (!pchange->flag) 551 | pchange->permission=pchange->permission | org; 552 | else 553 | pchange->permission=~pchange->permission & org; 554 | fseek(fout,offset+U_NUM,SEEK_SET); 555 | fprintf(fout,"%d",pchange->permission); 556 | offset=offset+U_WORDSIZE; 557 | tmplist=tmplist->next; 558 | } 559 | tablelist=tablelist->next; 560 | } 561 | fclose(fin); 562 | fclose(fout); 563 | } 564 | 565 | void init_File(void){ 566 | //db :0页:8位当前数据库数+12位当前字段表地址+8位用户数 567 | //dat:0页:16位字段数据地址 568 | FILE *fin,*fout; 569 | if (!(fin=fopen("isql.db","r+"))){ 570 | printf("cannot open file isql.db\n"); 571 | } 572 | if (!(fout=fopen("isql.dat","r+"))){ 573 | printf("cannot open file isql.dat!\n"); 574 | } 575 | 576 | int num; 577 | num=atoi(read_D(fin,8,12)); 578 | if (num==0) { fseek(fin,8,SEEK_SET); fprintf(fin,"%d",18); } 579 | num=atoi(read_D(fin,20,8)); 580 | if (num==0) { 581 | fseek(fin,20,SEEK_SET); 582 | fprintf(fin,"%d",1); 583 | //sudo admin admin 584 | int offset=U_PAGE*PAGE_SIZE; 585 | write_D(fout,offset,"admin"); 586 | fseek(fout,offset+U_NAME,SEEK_SET); 587 | fprintf(fout,"%d",0); 588 | write_D(fout,offset+U_NAME+U_NUM,get_MD5("admin")); 589 | } 590 | num=atoi(read_D(fout,0,16)); 591 | if (num==0) { fseek(fout,0,SEEK_SET); fprintf(fout,"%d",66); } 592 | 593 | fclose(fin); 594 | fclose(fout); 595 | 596 | DT_HANDLE=-1; 597 | USER_NUM=-1; 598 | pFList=0; 599 | return ; 600 | } 601 | 602 | void verify(void){ 603 | printf("\n*************** welcome to ISQL ****************\n"); 604 | printf("* version 1.0 *\n"); 605 | printf("* Designed by RL *\n"); 606 | printf("* Copyright (c) 2011, RL. All rights reserved *\n"); 607 | printf("************************************************\n\n"); 608 | char username[32]; 609 | char passwd[32]; 610 | char *md5,*vmd5; 611 | FILE *fin,*fout; 612 | int usernum,i,offset; 613 | if (!(fin=fopen("isql.db","r+"))){ 614 | printf("cannot open file isql.db\n"); 615 | } 616 | if (!(fout=fopen("isql.dat","r+"))){ 617 | printf("cannot open file isql.dat!\n"); 618 | } 619 | usernum=atoi(read_D(fin,20,8)); 620 | while (USER_NUM==-1){ 621 | printf(">username:"); 622 | scanf("%s",username); 623 | printf(">password:"); 624 | scanf("%s",passwd); 625 | md5=get_MD5(passwd); 626 | for (i=0;i "); 645 | return yyparse(); 646 | } 647 | -------------------------------------------------------------------------------- /isql_main.h: -------------------------------------------------------------------------------- 1 | /************************************** 2 | * filename isql.h 3 | * header for SQL head file 4 | * Copyright (c) 2011, RL. All rights reserved. 5 | * CFLAGS = isql_main.h 6 | * ************************************/ 7 | 8 | #ifndef _ISQL_H 9 | #define _ISQL_H 10 | 11 | #define PAGE_SIZE 2048 12 | 13 | //db :0页:8位当前数据库数+12位当前字段表地址+8位用户数 14 | //dat:0页:16位字段数据地址 15 | 16 | #define D_PAGE 1 //起始页,最多32个数据库 17 | #define D_HEAD_SIZE 64 // 18 | #define D_NAME_SIZE 32 //数据库名 19 | #define D_TABLE_NUM 32 //>=数据库table数(最多16个) 20 | 21 | #define T_LIST_PAGE 2 //起始页,2-17页 22 | #define T_LIST_SIZE 1024 23 | #define T_HEAD_SIZE 64 24 | #define T_NAME_SIZE 32 25 | #define T_PAGE 12 //>=18 $$-18就是用户表的偏移量 26 | #define T_USERNUM 4 //一个table最多16个用户 27 | #define T_COUNT 11 //最多1<<12条记录 28 | #define T_WORDS 5 //最多1<<6个字段 29 | 30 | #define WORD_SIZE 64 //最多32个字段 31 | #define W_NAME_SIZE 32 //字段名 32 | #define W_TYPE 8 //字段类型 0:int 1:char 其他未编码 33 | #define W_LENGTH 8 //字段长度 最长1<<8位 34 | #define W_PAGE 16 //字段存储位置偏移 2字节和dat连接表对应 35 | 36 | #define U_PAGE 1 //dat文件中 37 | #define U_HEAD_SIZE 64 //最多32个用户 38 | #define U_NAME 24 39 | #define U_NUM 8 //用户编号 40 | #define U_PASSWD 32 //md5 41 | 42 | #define P_SELECT 1 43 | #define P_INSERT 2 44 | #define P_UPDATE 4 45 | #define P_DELETE 8 46 | 47 | #define U_LISTPAGE 2 //2-65,64页 64*8条记录 对应table数32*16 48 | #define U_LISTSIZE 256 //最多16个用户 对应T_USERNUM 49 | #define U_WORDSIZE 16 //8位用户编号+4位权限+4位可扩展 50 | #define U_POWER 4 51 | 52 | 53 | static char null=(char)0x00; 54 | 55 | void yyerror(char *s, ...); 56 | void eat_to_newline(); 57 | void emit(char *s, ...); 58 | //void shell_exec(char *cmd); popen(cmd,"r"); echo fuckyou | md5sum 59 | char *get_MD5(char *str); 60 | char *read_D(FILE *fin, int offset, int length); 61 | void write_D(FILE *fin, int offset, char *str); 62 | void fill_D(FILE *fin, int offset, int length, char t); 63 | 64 | struct ast_createD{ 65 | char *D_name; 66 | }; 67 | 68 | struct ast_createDefinition{ 69 | char *name; 70 | int data_type; 71 | int opt_length; 72 | }; 73 | 74 | struct ast_createCol_list{ 75 | struct ast_createDefinition *createDefinition; 76 | struct ast_createCol_list *next; 77 | }; 78 | 79 | struct ast_createTable{ 80 | char *name; 81 | struct ast_createCol_list *col_list; 82 | }; 83 | 84 | struct ast_wordList{ 85 | char *name; 86 | struct ast_wordList *next; 87 | }; 88 | 89 | struct ast_valList{ 90 | struct _expr *expr; 91 | struct ast_valList *next; 92 | }; 93 | 94 | struct ast_tableInto{ 95 | char *name; 96 | struct ast_wordList *wordlist; 97 | }; 98 | 99 | struct ast_insertRecord{ 100 | struct ast_tableInto *tableinto; 101 | struct ast_valList *vallist; 102 | }; 103 | 104 | struct ast_selectRecord{ 105 | char *name; 106 | struct ast_wordList *wordlist; 107 | struct _expr *where_tree; 108 | }; 109 | 110 | struct ast_permission{ 111 | int flag; //0:grant 1:revoke 112 | int permission; 113 | struct ast_wordList *tablelist; 114 | struct ast_wordList *userlist; 115 | }; 116 | 117 | struct _expr{ 118 | int type; //0:name 1:string 2:intnum 'a':and 'o':or 3-8 = != < > <= >= 119 | char *string; 120 | int intval; 121 | int judge; //0 false 1 true -1 null 122 | struct _expr *left,*right; 123 | }; 124 | 125 | struct _table{ 126 | char *name; 127 | char *database; 128 | int D_HANDLE; 129 | int T_HANDLE; 130 | int count; 131 | int words; 132 | struct _fieldList **list; 133 | }; 134 | 135 | struct _fieldList{ 136 | char *name; 137 | int type; 138 | int length; 139 | int page; 140 | int intval; 141 | char *charval; 142 | }; 143 | 144 | struct ast_createDefinition *new_CDefinition(char *name, int data_type, int opt_length); 145 | struct ast_createCol_list *add_createCol_list(struct ast_createCol_list *list,struct ast_createDefinition *nextDefinition); 146 | void create_Table(struct ast_createTable *table); 147 | struct ast_valList *add_Vals(struct ast_valList *list,struct _expr *nextExpr); 148 | 149 | struct ast_wordList *add_wordList(struct ast_wordList *list,char *nextname); 150 | void insert_Record(struct ast_insertRecord *record); 151 | void select_Record(struct ast_selectRecord *record); 152 | 153 | void create_Role(char *username,char *passwd); 154 | void user_Manage(struct ast_permission *pchange); 155 | 156 | #endif 157 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -DYYDEBUG=1 2 | all:isql clean 3 | 4 | #isql: isql.l isql.y 5 | # bison -d isql.y 6 | # flex -o isql.lex.c isql.l 7 | # cc -o $@ isql.tab.c isql.lex.c 8 | 9 | isql: isql.tab.o isql.lex.o isql_main.o 10 | cc -g -o $@ isql.tab.o isql.lex.o isql_main.o -lm 11 | 12 | isql.tab.c isql.tab.h: isql.y 13 | bison -vd isql.y 14 | 15 | isql.lex.c: isql.l 16 | flex -o $@ $< 17 | 18 | isql.lex.o: isql.lex.c isql.tab.h 19 | 20 | isql_main.o: isql_main.c isql_main.h 21 | 22 | clean: 23 | rm -f isql.lex.o isql.tab.o isql_main.o 24 | 25 | cleanall: 26 | rm -f isql isql.tab.c isql.tab.h isql.lex.c isql.output isql.lex.o isql.tab.o isql_main.o 27 | --------------------------------------------------------------------------------