├── 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 | 68min0456b7016a916a4b178dd72b947c152b766 admin 0 456b7016a916a4b178dd72b947c152b7 0 15 boo 1
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------