Move parser constants to new file
This commit is contained in:
parent
bf61fcdd30
commit
cf5bef048e
|
@ -5,23 +5,23 @@
|
||||||
|
|
||||||
// INTERNAL FUNCTIONS
|
// INTERNAL FUNCTIONS
|
||||||
// Information gathering
|
// Information gathering
|
||||||
bool existstr(STRINGLIST* strs, char* str);
|
bool existstr(STRINGLIST* strs, const char* str);
|
||||||
bool existclass(CLASS* c, char* name);
|
bool existclass(CLASS* c, const char* name);
|
||||||
DEBUGINFO* getdebuginfo(OBJ* obj);
|
DEBUGINFO* getdebuginfo(OBJ* obj);
|
||||||
|
|
||||||
// Error messages
|
// Error messages
|
||||||
void doubledeclaration(char* name, DEBUGINFO* debug, OBJ* other);
|
void doubledeclaration(const char* name, DEBUGINFO* debug, OBJ* other);
|
||||||
void ensurenoduplicate(SCOPE* s, char* name, DEBUGINFO* debug);
|
void ensurenoduplicate(SCOPE* s, const char* name, DEBUGINFO* debug);
|
||||||
|
|
||||||
// Scope handling
|
// Scope handling
|
||||||
void popscope(SCOPE** s); // may be removed
|
void popscope(SCOPE** s); // may be removed
|
||||||
|
|
||||||
// Single type getters
|
// Single type getters
|
||||||
VARDEC* getvardec(SCOPE* s, char* name);
|
VARDEC* getvardec(SCOPE* s, const char* name);
|
||||||
CLASSVARDEC* getclassvardec(SCOPE* s, char* name);
|
CLASSVARDEC* getclassvardec(SCOPE* s, const char* name);
|
||||||
|
|
||||||
// Generic getters
|
// Generic getters
|
||||||
OBJ* getbynamelist(SCOPE* s, STRINGLIST* names, char** retname);
|
OBJ* getbynamelist(SCOPE* s, STRINGLIST* names, const char** retname);
|
||||||
|
|
||||||
// Scope adding
|
// Scope adding
|
||||||
void addclassvardec(SCOPE* s, CLASSVARDEC* v);
|
void addclassvardec(SCOPE* s, CLASSVARDEC* v);
|
||||||
|
@ -31,7 +31,7 @@ void addclass(SCOPE* s, CLASS* c);
|
||||||
|
|
||||||
// DEFINITIONS
|
// DEFINITIONS
|
||||||
// Information gathering
|
// Information gathering
|
||||||
bool existstr(STRINGLIST* strs, char* str) {
|
bool existstr(STRINGLIST* strs, const char* str) {
|
||||||
while(strs != NULL) {
|
while(strs != NULL) {
|
||||||
if(!strcmp(strs->content, str))
|
if(!strcmp(strs->content, str))
|
||||||
return true;
|
return true;
|
||||||
|
@ -40,7 +40,7 @@ bool existstr(STRINGLIST* strs, char* str) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool existclass(CLASS* c, char* name) {
|
bool existclass(CLASS* c, const char* name) {
|
||||||
while(c != NULL) {
|
while(c != NULL) {
|
||||||
if(!strcmp(c->name, name))
|
if(!strcmp(c->name, name))
|
||||||
return true;
|
return true;
|
||||||
|
@ -77,14 +77,14 @@ VARDEC* tovardec(OBJ* obj) {
|
||||||
|
|
||||||
// Error messages
|
// Error messages
|
||||||
|
|
||||||
void doubledeclaration(char* name, DEBUGINFO* debug, OBJ* other) {
|
void doubledeclaration(const char* name, DEBUGINFO* debug, OBJ* other) {
|
||||||
DEBUGINFO* debugother = other->getdebug(other);
|
DEBUGINFO* debugother = other->getdebug(other);
|
||||||
eprintf("Double declaration of '%s' at '%s', line %i; previously defined at '%s', line %i\n",
|
eprintf("Double declaration of '%s' at '%s', line %i; previously defined at '%s', line %i\n",
|
||||||
name, debug->file, debug->definedat, debugother->file, debugother->definedat);
|
name, debug->file, debug->definedat, debugother->file, debugother->definedat);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void notdeclared(char* name, DEBUGINFO* debug) {
|
void notdeclared(const char* name, DEBUGINFO* debug) {
|
||||||
eprintf("'%s' not declared; file '%s', line %i\n", name, debug->file, debug->definedat);
|
eprintf("'%s' not declared; file '%s', line %i\n", name, debug->file, debug->definedat);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -94,14 +94,14 @@ void invalidparent(SUBROUTCALL* call) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ensurenoduplicate(SCOPE* s, char* name, DEBUGINFO* debug) {
|
void ensurenoduplicate(SCOPE* s, const char* name, DEBUGINFO* debug) {
|
||||||
OBJ* other = getbyname(s, name);
|
OBJ* other = getbyname(s, name);
|
||||||
if(other != NULL)
|
if(other != NULL)
|
||||||
doubledeclaration(name, debug, other);
|
doubledeclaration(name, debug, other);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ensurenoduplicates(SCOPE* s, STRINGLIST* names, DEBUGINFO* debug) {
|
void ensurenoduplicates(SCOPE* s, STRINGLIST* names, DEBUGINFO* debug) {
|
||||||
char* othername;
|
const char* othername;
|
||||||
OBJ* other = getbynamelist(s, names, &othername);
|
OBJ* other = getbynamelist(s, names, &othername);
|
||||||
if(other != NULL)
|
if(other != NULL)
|
||||||
doubledeclaration(othername, debug, other);
|
doubledeclaration(othername, debug, other);
|
||||||
|
@ -126,7 +126,7 @@ void popscope(SCOPE** s) { // might be useless
|
||||||
}
|
}
|
||||||
|
|
||||||
// Single type getters
|
// Single type getters
|
||||||
VARDEC* getvardec(SCOPE* s, char* name) {
|
VARDEC* getvardec(SCOPE* s, const char* name) {
|
||||||
VARDEC* curr = s->vardecs;
|
VARDEC* curr = s->vardecs;
|
||||||
while(curr != NULL) {
|
while(curr != NULL) {
|
||||||
if(existstr(curr->names, name))
|
if(existstr(curr->names, name))
|
||||||
|
@ -138,7 +138,7 @@ VARDEC* getvardec(SCOPE* s, char* name) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
CLASSVARDEC* getclassvardec(SCOPE* s, char* name) {
|
CLASSVARDEC* getclassvardec(SCOPE* s, const char* name) {
|
||||||
CLASSVARDEC* curr = s->classvardecs;
|
CLASSVARDEC* curr = s->classvardecs;
|
||||||
while(curr != NULL) {
|
while(curr != NULL) {
|
||||||
if(existstr(curr->base->names, name))
|
if(existstr(curr->base->names, name))
|
||||||
|
@ -150,7 +150,7 @@ CLASSVARDEC* getclassvardec(SCOPE* s, char* name) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBROUTDEC* getsubroutdec(SCOPE* s, char* name) {
|
SUBROUTDEC* getsubroutdec(SCOPE* s, const char* name) {
|
||||||
SUBROUTDEC* curr = s->subroutines;
|
SUBROUTDEC* curr = s->subroutines;
|
||||||
while(curr != NULL) {
|
while(curr != NULL) {
|
||||||
if(!strcmp(curr->name, name))
|
if(!strcmp(curr->name, name))
|
||||||
|
@ -162,7 +162,7 @@ SUBROUTDEC* getsubroutdec(SCOPE* s, char* name) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
CLASS* getclass(SCOPE* s, char* name) {
|
CLASS* getclass(SCOPE* s, const char* name) {
|
||||||
CLASS* curr = s->classes;
|
CLASS* curr = s->classes;
|
||||||
while(curr != NULL) {
|
while(curr != NULL) {
|
||||||
if(!strcmp(curr->name, name))
|
if(!strcmp(curr->name, name))
|
||||||
|
@ -174,7 +174,7 @@ CLASS* getclass(SCOPE* s, char* name) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBROUTDEC* getsubroutdecfromclass(CLASS* c, char* name) {
|
SUBROUTDEC* getsubroutdecfromclass(CLASS* c, const char* name) {
|
||||||
SUBROUTDEC* curr = c->subroutdecs;
|
SUBROUTDEC* curr = c->subroutdecs;
|
||||||
while(curr != NULL) {
|
while(curr != NULL) {
|
||||||
if(!strcmp(curr->name, name))
|
if(!strcmp(curr->name, name))
|
||||||
|
@ -218,7 +218,7 @@ SUBROUTDEC* getsubroutdecfromcall(SCOPE* s, SUBROUTCALL* call) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generic getters
|
// Generic getters
|
||||||
OBJ* getbyname(SCOPE* s, char* name) {
|
OBJ* getbyname(SCOPE* s, const char* name) {
|
||||||
OBJ* o = (OBJ*)malloc(sizeof(OBJ));
|
OBJ* o = (OBJ*)malloc(sizeof(OBJ));
|
||||||
|
|
||||||
CLASSVARDEC* cvd = getclassvardec(s, name);
|
CLASSVARDEC* cvd = getclassvardec(s, name);
|
||||||
|
@ -257,7 +257,7 @@ OBJ* getbyname(SCOPE* s, char* name) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
OBJ* getbynamelist(SCOPE* s, STRINGLIST* names, char** retname) {
|
OBJ* getbynamelist(SCOPE* s, STRINGLIST* names, const char** retname) {
|
||||||
while(names != NULL) {
|
while(names != NULL) {
|
||||||
OBJ* o = getbyname(s, names->content);
|
OBJ* o = getbyname(s, names->content);
|
||||||
if(o != NULL) {
|
if(o != NULL) {
|
||||||
|
|
|
@ -42,10 +42,10 @@ void addclasses(SCOPE* s, CLASS* c);
|
||||||
SCOPE* mkscope(SCOPE* prev);
|
SCOPE* mkscope(SCOPE* prev);
|
||||||
|
|
||||||
// Single type getters
|
// Single type getters
|
||||||
SUBROUTDEC* getsubroutdec(SCOPE* s, char* name);
|
SUBROUTDEC* getsubroutdec(SCOPE* s, const char* name);
|
||||||
SUBROUTDEC* getsubroutdecfromcall(SCOPE* s, SUBROUTCALL* call);
|
SUBROUTDEC* getsubroutdecfromcall(SCOPE* s, SUBROUTCALL* call);
|
||||||
CLASS* getclass(SCOPE* s, char* name);
|
CLASS* getclass(SCOPE* s, const char* name);
|
||||||
|
|
||||||
// Generic getters
|
// Generic getters
|
||||||
OBJ* getbyname(SCOPE* s, char* name);
|
OBJ* getbyname(SCOPE* s, const char* name);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef PARSER_CONSTANTS_H
|
||||||
|
#define PARSER_CONSTANTS_H
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
const char* keywordsarr[] = { "true", "false", "null", "this" };
|
||||||
|
const char* opsarr[] = { "+", "-", "*", "/", "&", "|", "<", ">", "=" };
|
||||||
|
const char* classvartypesarr[] = { "static", "field" };
|
||||||
|
const char* vartypesarr[] = { "int", "char", "boolean" };
|
||||||
|
const char* subroutclassesarr[] = { "constructor", "function", "method" };
|
||||||
|
const char* tokentypesarr[] = { "keyword", "identifier", "symbol", "integerConstant", "stringConstant" };
|
||||||
|
|
||||||
|
#define mkstrlist(name, array) STRINGARRAY name = { .items = array, .size = strcount(array) }
|
||||||
|
mkstrlist(keywordconstants, keywordsarr);
|
||||||
|
mkstrlist(operators, opsarr);
|
||||||
|
mkstrlist(classvartypes, classvartypesarr);
|
||||||
|
mkstrlist(vartypes, vartypesarr);
|
||||||
|
mkstrlist(subroutclasses, subroutclassesarr);
|
||||||
|
mkstrlist(tokentypes, tokentypesarr);
|
||||||
|
#undef mkstrlist
|
||||||
|
#endif
|
56
parser.c
56
parser.c
|
@ -3,6 +3,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
#include "parser-constants.h"
|
||||||
|
|
||||||
char* parseidentifier(PARSER* p);
|
char* parseidentifier(PARSER* p);
|
||||||
STATEMENT* parsestatements(PARSER* p);
|
STATEMENT* parsestatements(PARSER* p);
|
||||||
|
@ -10,35 +11,6 @@ SUBROUTCALL* parsesubroutcall(PARSER* p);
|
||||||
TERM* parseexpression(PARSER* p);
|
TERM* parseexpression(PARSER* p);
|
||||||
TERM* parseterm(PARSER* p);
|
TERM* parseterm(PARSER* p);
|
||||||
|
|
||||||
const char* keywordconstants[] = {
|
|
||||||
"true", "false", "null", "this"
|
|
||||||
};
|
|
||||||
const int keywordconstantssize = sizeof(keywordconstants) / sizeof(char*);
|
|
||||||
|
|
||||||
const char* ops[] = {
|
|
||||||
"+", "-", "*", "/", "&", "|", "<", ">", "="
|
|
||||||
};
|
|
||||||
const int opssize = sizeof(ops) / sizeof(char*);
|
|
||||||
|
|
||||||
const char* classvartypes[] = {
|
|
||||||
"static", "field"
|
|
||||||
};
|
|
||||||
const int classvartypessize = sizeof(classvartypes) / sizeof(char*);
|
|
||||||
|
|
||||||
const char* vardectypes[] = {
|
|
||||||
"int", "char", "boolean"
|
|
||||||
};
|
|
||||||
const int vardectypessize = sizeof(vardectypes) / sizeof(char*);
|
|
||||||
|
|
||||||
const char* subroutclasses[] = {
|
|
||||||
"constructor", "function", "method"
|
|
||||||
};
|
|
||||||
const int subroutclassessize = sizeof(subroutclasses) / sizeof(char*);
|
|
||||||
|
|
||||||
const char* tokentypes[] = {
|
|
||||||
"keyword", "identifier", "symbol", "integerConstant", "stringConstant"
|
|
||||||
};
|
|
||||||
|
|
||||||
DEBUGINFO* getdebug(PARSER* p) {
|
DEBUGINFO* getdebug(PARSER* p) {
|
||||||
DEBUGINFO* d = (DEBUGINFO*)malloc(sizeof(DEBUGINFO));
|
DEBUGINFO* d = (DEBUGINFO*)malloc(sizeof(DEBUGINFO));
|
||||||
d->file = p->file;
|
d->file = p->file;
|
||||||
|
@ -59,7 +31,7 @@ void restorecp(PARSER* p) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void unexpectedtoken(PARSER* p) {
|
void unexpectedtoken(PARSER* p) {
|
||||||
fprintf(stderr, "Unexpected token '%s' (of type %s); line %i, file '%s'\n", p->current->token, tokentypes[p->current->type], p->current->definedat, p->file);
|
fprintf(stderr, "Unexpected token '%s' (of type %s); line %i, file '%s'\n", p->current->token, tokentypes.items[p->current->type], p->current->definedat, p->file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unexpected(PARSER* p) {
|
void unexpected(PARSER* p) {
|
||||||
|
@ -75,7 +47,7 @@ void checkcontent(PARSER* p, const char* content) {
|
||||||
|
|
||||||
void checktype(PARSER* p, TOKENTYPE type) {
|
void checktype(PARSER* p, TOKENTYPE type) {
|
||||||
if(p->current->type != type) {
|
if(p->current->type != type) {
|
||||||
fprintf(stderr, "Unexpected %s; line %i, file '%s'\n", tokentypes[p->current->type], p->current->definedat, p->file);
|
fprintf(stderr, "Unexpected %s; line %i, file '%s'\n", tokentypes.items[p->current->type], p->current->definedat, p->file);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,8 +66,8 @@ TERM* parsetermnullified(PARSER* p) {
|
||||||
} else if(p->current->type == keyword) {
|
} else if(p->current->type == keyword) {
|
||||||
t->type = keywordconstant;
|
t->type = keywordconstant;
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
for(int i = 0; i < keywordconstantssize; i++)
|
for(int i = 0; i < keywordconstants.size; i++)
|
||||||
if(!strcmp(p->current->token, keywordconstants[i]))
|
if(!strcmp(p->current->token, keywordconstants.items[i]))
|
||||||
valid = true;
|
valid = true;
|
||||||
if(!valid)
|
if(!valid)
|
||||||
unexpected(p);
|
unexpected(p);
|
||||||
|
@ -136,8 +108,8 @@ TERM* parsetermnullified(PARSER* p) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isop(TOKEN* t) {
|
bool isop(TOKEN* t) {
|
||||||
for(int i = 0; i < opssize; i++)
|
for(int i = 0; i < operators.size; i++)
|
||||||
if(!strcmp(t->token, ops[i]))
|
if(!strcmp(t->token, operators.items[i]))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -338,8 +310,8 @@ STATEMENT* parsestatements(PARSER* p) {
|
||||||
char* parsetype(PARSER* p, bool* primitive) {
|
char* parsetype(PARSER* p, bool* primitive) {
|
||||||
char* result = p->current->token;
|
char* result = p->current->token;
|
||||||
if(p->current->type == keyword)
|
if(p->current->type == keyword)
|
||||||
for(int i = 0; i < vardectypessize; i++) {
|
for(int i = 0; i < vartypes.size; i++) {
|
||||||
if(!strcmp(p->current->token, vardectypes[i])) {
|
if(!strcmp(p->current->token, vartypes.items[i])) {
|
||||||
next(p);
|
next(p);
|
||||||
*primitive = true;
|
*primitive = true;
|
||||||
return result;
|
return result;
|
||||||
|
@ -354,19 +326,19 @@ char* parsetype(PARSER* p, bool* primitive) {
|
||||||
unexpected(p);
|
unexpected(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
int parsepossibilities(PARSER* p, const char** strings, int sz) {
|
int parsepossibilities(PARSER* p, STRINGARRAY* poss) {
|
||||||
for(int i = 0; i < sz; i++)
|
for(int i = 0; i < poss->size; i++)
|
||||||
if(!strcmp(p->current->token, strings[i]))
|
if(!strcmp(p->current->token, poss->items[i]))
|
||||||
return i;
|
return i;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
CLASSVARTYPE parseclassvartype(PARSER* p) {
|
CLASSVARTYPE parseclassvartype(PARSER* p) {
|
||||||
return parsepossibilities(p, classvartypes, classvartypessize);
|
return parsepossibilities(p, &classvartypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
SUBROUTCLASS parsesubroutclass(PARSER* p) {
|
SUBROUTCLASS parsesubroutclass(PARSER* p) {
|
||||||
return parsepossibilities(p, subroutclasses, subroutclassessize);
|
return parsepossibilities(p, &subroutclasses);
|
||||||
}
|
}
|
||||||
|
|
||||||
char* parseidentifier(PARSER* p) {
|
char* parseidentifier(PARSER* p) {
|
||||||
|
|
1
parser.h
1
parser.h
|
@ -3,7 +3,6 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "tokenizer.h"
|
#include "tokenizer.h"
|
||||||
#include "parser-tree.h"
|
#include "parser-tree.h"
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
TOKEN* tokens;
|
TOKEN* tokens;
|
||||||
|
|
33
util.c
33
util.c
|
@ -2,20 +2,20 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
char* heapstr(char* str, int len) {
|
char* heapstr(const char* str, int len) {
|
||||||
int sz = sizeof(char) * (len + 1);
|
int size = sizeof(char) * (len + 1);
|
||||||
char* outstr = (char*)malloc(sz);
|
char* outstr = (char*)malloc(size);
|
||||||
strcpy(outstr, str);
|
strcpy(outstr, str);
|
||||||
return outstr;
|
return outstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* ezheapstr(char* str) {
|
char* ezheapstr(const char* str) {
|
||||||
return heapstr(str, strlen(str));
|
return heapstr(str, strlen(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
void* copy(void* v, int sz) {
|
void* copy(void* v, int size) {
|
||||||
void* copy = malloc(sz);
|
void* copy = malloc(size);
|
||||||
memcpy(copy, v, sz);
|
memcpy(copy, v, size);
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,12 +34,25 @@ int countplaces(int n) {
|
||||||
}
|
}
|
||||||
|
|
||||||
char* itoa(int i) {
|
char* itoa(int i) {
|
||||||
int sz = sizeof(char)*(countplaces(i)+1);
|
int size = sizeof(char)*(countplaces(i)+1);
|
||||||
char* a = (char*)malloc(sz);
|
char* a = (char*)malloc(size);
|
||||||
snprintf(a, sz, "%i", i);
|
snprintf(a, size, "%i", i);
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
STRINGLIST* initstrlist(const char** strs, int count) {
|
||||||
|
STRINGLIST* strlist = (STRINGLIST*)malloc(sizeof(STRINGLIST));
|
||||||
|
STRINGLIST* curr = strlist;
|
||||||
|
for(int i = 0; i < count-1; i++) {
|
||||||
|
curr->content = ezheapstr(strs[i]);
|
||||||
|
curr->next = (STRINGLIST*)malloc(sizeof(STRINGLIST));
|
||||||
|
curr = curr->next;
|
||||||
|
}
|
||||||
|
curr->content = ezheapstr(strs[count-1]);
|
||||||
|
curr->next = NULL;
|
||||||
|
return strlist;
|
||||||
|
}
|
||||||
|
|
||||||
void printstrlist(STRINGLIST* strlist, FILE* stream) {
|
void printstrlist(STRINGLIST* strlist, FILE* stream) {
|
||||||
while(strlist != NULL) {
|
while(strlist != NULL) {
|
||||||
fprintf(stream, "%s\n", strlist->content);
|
fprintf(stream, "%s\n", strlist->content);
|
||||||
|
|
14
util.h
14
util.h
|
@ -11,16 +11,22 @@
|
||||||
#define strcount(array) count(array, char*)
|
#define strcount(array) count(array, char*)
|
||||||
|
|
||||||
typedef struct stringlist {
|
typedef struct stringlist {
|
||||||
char* content;
|
const char* content;
|
||||||
struct stringlist* next;
|
struct stringlist* next;
|
||||||
} STRINGLIST;
|
} STRINGLIST;
|
||||||
|
|
||||||
char* heapstr(char* str, int len);
|
typedef struct {
|
||||||
char* ezheapstr(char* str);
|
const char** items;
|
||||||
|
const int size;
|
||||||
|
} STRINGARRAY;
|
||||||
|
|
||||||
|
char* heapstr(const char* str, int len);
|
||||||
|
char* ezheapstr(const char* str);
|
||||||
int countplaces(int n);
|
int countplaces(int n);
|
||||||
char* itoa(int i);
|
char* itoa(int i);
|
||||||
void* copy(void* v, int sz);
|
void* copy(void* v, int size);
|
||||||
|
|
||||||
|
STRINGLIST* initstrlist(const char** strs, int count);
|
||||||
void printstrlist(STRINGLIST* strlist, FILE* stream);
|
void printstrlist(STRINGLIST* strlist, FILE* stream);
|
||||||
void freestrlist(STRINGLIST* strlist);
|
void freestrlist(STRINGLIST* strlist);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue