diff options
| author | Michael R Sweet <michael.r.sweet@gmail.com> | 1998-10-06 18:21:25 +0000 |
|---|---|---|
| committer | Michael R Sweet <michael.r.sweet@gmail.com> | 1998-10-06 18:21:25 +0000 |
| commit | f9039b2ae21988783feae9b362818e7923e82d14 (patch) | |
| tree | 6d6fe3679d73448758f9794e7d4d4f6b22a4adad /fluid/Fl_Function_Type.cxx | |
| parent | 67e89232f9ba067825a158734a09e0fa21aacbe3 (diff) | |
Initial revision
git-svn-id: file:///fltk/svn/fltk/trunk@2 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'fluid/Fl_Function_Type.cxx')
| -rw-r--r-- | fluid/Fl_Function_Type.cxx | 669 |
1 files changed, 669 insertions, 0 deletions
diff --git a/fluid/Fl_Function_Type.cxx b/fluid/Fl_Function_Type.cxx new file mode 100644 index 000000000..21bdb5b37 --- /dev/null +++ b/fluid/Fl_Function_Type.cxx @@ -0,0 +1,669 @@ +/* Fl_Function_Type_Type.C + + Type describing a C function output by Fluid. + +*/ + +#include <FL/Fl.H> +#include "Fl_Type.H" +#include <FL/fl_show_input.H> +#include <string.h> +#include <stdio.h> +#include <ctype.h> + +//////////////////////////////////////////////////////////////// +// quick check of any C code for legality, returns an error message +// these currently require comments to parse correctly! + +static char buffer[128]; // for error messages + +// check a quoted string ending in either " or ' or >: +const char *_q_check(const char * & c, int type) { + for (;;) switch (*c++) { + case '\0': + sprintf(buffer,"missing %c",type); + return buffer; + case '\\': + if (*c) c++; + break; + default: + if (*(c-1) == type) return 0; + } +} + +// check normal code, match braces and parenthesis: +const char *_c_check(const char * & c, int type) { + const char *d; + for (;;) switch (*c++) { + case 0: + if (!type) return 0; + sprintf(buffer, "missing %c", type); + return buffer; + case '{': + if (type==')') goto UNEXPECTED; + d = _c_check(c,'}'); if (d) return d; break; + case '(': + d = _c_check(c,')'); if (d) return d; break; + case '\"': + d = _q_check(c,'\"'); if (d) return d; break; + case '\'': + d = _q_check(c,'\''); if (d) return d; break; + case '}': + case ')': + case '#': + UNEXPECTED: + if (type == *(c-1)) return 0; + sprintf(buffer, "unexpected %c", *(c-1)); + return buffer; + } +} + +const char *c_check(const char *c, int type) { + return _c_check(c,type); +} + +//////////////////////////////////////////////////////////////// + +class Fl_Function_Type : public Fl_Type { + const char* return_type; + char public_, constructor, havewidgets; +public: + Fl_Type *make(); + void write_declare(); + void write_code1(); + void write_code2(); + void open(); + int ismain() {return name_ == 0;} + virtual const char *type_name() {return "Function";} + virtual const char *title() { + return name() ? name() : "main()"; + } + int is_parent() const {return 1;} + int is_code_block() const {return 1;} + void write_properties(); + void read_property(const char *); +}; + +Fl_Type *Fl_Function_Type::make() { + Fl_Type *p = Fl_Type::current; + while (p && !p->is_decl_block()) p = p->parent; + Fl_Function_Type *o = new Fl_Function_Type(); + o->name("make_window()"); + o->return_type = 0; + o->add(p); + o->factory = this; + o->public_ = 1; + return o; +} + +void Fl_Function_Type::write_properties() { + Fl_Type::write_properties(); + if (!public_) write_string("private"); + if (return_type) { + write_string("return_type"); + write_word(return_type); + } +} + +void Fl_Function_Type::read_property(const char *c) { + if (!strcmp(c,"private")) { + public_ = 0; + } else if (!strcmp(c,"return_type")) { + storestring(read_word(),return_type); + } else { + Fl_Type::read_property(c); + } +} + +#include "function_panel.H" +#include <FL/fl_ask.H> + +void Fl_Function_Type::open() { + if (!function_panel) make_function_panel(); + f_return_type_input->static_value(return_type); + f_name_input->static_value(name()); + f_public_button->value(public_); + function_panel->show(); + const char* message = 0; + for (;;) { // repeat as long as there are errors + if (message) fl_alert(message); + for (;;) { + Fl_Widget* w = Fl::readqueue(); + if (w == f_panel_cancel) goto BREAK2; + else if (w == f_panel_ok) break; + else if (!w) Fl::wait(); + } + const char*c = f_name_input->value(); + while (isspace(*c)) c++; + message = c_check(c); if (message) continue; + const char *d = c; + for (; *d != '('; d++) if (isspace(*d) || !*d) break; + if (*c && *d != '(') { + message = "must be name(arguments), try again:"; continue; + } + c = f_return_type_input->value(); + message = c_check(c); if (message) continue; + name(f_name_input->value()); + storestring(c, return_type); + public_ = f_public_button->value(); + break; + } + BREAK2: + function_panel->hide(); +} + +Fl_Function_Type Fl_Function_type; + +void Fl_Function_Type::write_declare() { + ::write_declare("#include <FL/Fl.H>"); +} + +extern const char* subclassname(Fl_Type*); + +void Fl_Function_Type::write_code1() { + constructor=0; + havewidgets = 0; + Fl_Type *child; + const char* widget_type = 0; + for (child = next; child && child->level > level; child = child->next) + if (child->is_widget()) { + havewidgets = 1; + widget_type = subclassname(child); + break; + } + write_c("\n"); + if (ismain()) + write_c("int main(int argc, char **argv) {\n"); + else { + const char* t = return_type; + const char* star = ""; + if (!t) { + if (havewidgets) {t = widget_type; star = "*";} + else t = "void"; + } + const char* k = class_name(); + if (k) { + write_public(public_); + if (name()[0] == '~') + constructor = 1; + else { + size_t n; for (n=0; name()[n] && name()[n]!='('; n++); + if (n == strlen(k) && !strncmp(name(), k, n)) constructor = 1; + } + write_h(" "); + if (!constructor) {write_h("%s%s ", t, star); write_c("%s%s ", t,star);} + write_h("%s;\n", name()); + write_c("%s::%s {\n", k, name()); + } else { + if (public_) write_h("%s%s %s;\n", t, star, name()); + else write_c("static "); + write_c("%s%s %s {\n", t, star, name()); + } + } + if (havewidgets) write_c(" %s* w;\n", widget_type); + indentation += 2; +} + +void Fl_Function_Type::write_code2() { + if (ismain()) { + if (havewidgets) write_c(" w->show(argc, argv);\n"); + write_c(" return Fl::run();\n"); + } else if (havewidgets && !constructor) + write_c(" return w;\n"); + write_c("}\n"); + indentation = 0; +} + +//////////////////////////////////////////////////////////////// + +class Fl_Code_Type : public Fl_Type { +public: + Fl_Type *make(); + void write_declare(); + void write_code1(); + void write_code2(); + void open(); + virtual const char *type_name() {return "code";} + int is_code_block() const {return 0;} +}; + +Fl_Type *Fl_Code_Type::make() { + Fl_Type *p = Fl_Type::current; + while (p && !p->is_code_block()) p = p->parent; + if (!p) { + fl_message("Please select a function"); + return 0; + } + Fl_Code_Type *o = new Fl_Code_Type(); + o->name("printf(\"Hello, World!\\n\");"); + o->add(p); + o->factory = this; + return o; +} + +void Fl_Code_Type::open() { + if (!code_panel) make_code_panel(); + code_input->static_value(name()); + code_panel->show(); + const char* message = 0; + for (;;) { // repeat as long as there are errors + if (message) fl_alert(message); + for (;;) { + Fl_Widget* w = Fl::readqueue(); + if (w == code_panel_cancel) goto BREAK2; + else if (w == code_panel_ok) break; + else if (!w) Fl::wait(); + } + const char*c = code_input->value(); + message = c_check(c); if (message) continue; + name(c); + break; + } + BREAK2: + code_panel->hide(); +} + +Fl_Code_Type Fl_Code_type; + +void Fl_Code_Type::write_declare() {} + +void Fl_Code_Type::write_code1() { + const char* c = name(); + if (!c) return; + write_c("%s%s\n", indent(), c); +} + +void Fl_Code_Type::write_code2() {} + +//////////////////////////////////////////////////////////////// + +class Fl_CodeBlock_Type : public Fl_Type { + const char* after; +public: + Fl_Type *make(); + void write_declare(); + void write_code1(); + void write_code2(); + void open(); + virtual const char *type_name() {return "codeblock";} + int is_code_block() const {return 1;} + int is_parent() const {return 1;} + void write_properties(); + void read_property(const char *); +}; + +Fl_Type *Fl_CodeBlock_Type::make() { + Fl_Type *p = Fl_Type::current; + while (p && !p->is_code_block()) p = p->parent; + if (!p) { + fl_message("Please select a function"); + return 0; + } + Fl_CodeBlock_Type *o = new Fl_CodeBlock_Type(); + o->name("if (test())"); + o->after = 0; + o->add(p); + o->factory = this; + return o; +} + +void Fl_CodeBlock_Type::write_properties() { + Fl_Type::write_properties(); + if (after) { + write_string("after"); + write_word(after); + } +} + +void Fl_CodeBlock_Type::read_property(const char *c) { + if (!strcmp(c,"after")) { + storestring(read_word(),after); + } else { + Fl_Type::read_property(c); + } +} + +void Fl_CodeBlock_Type::open() { + if (!codeblock_panel) make_codeblock_panel(); + code_before_input->static_value(name()); + code_after_input->static_value(after); + codeblock_panel->show(); + const char* message = 0; + for (;;) { // repeat as long as there are errors + if (message) fl_alert(message); + for (;;) { + Fl_Widget* w = Fl::readqueue(); + if (w == codeblock_panel_cancel) goto BREAK2; + else if (w == codeblock_panel_ok) break; + else if (!w) Fl::wait(); + } + const char*c = code_before_input->value(); + message = c_check(c); if (message) continue; + name(c); + c = code_after_input->value(); + message = c_check(c); if (message) continue; + storestring(c, after); + break; + } + BREAK2: + codeblock_panel->hide(); +} + +Fl_CodeBlock_Type Fl_CodeBlock_type; + +void Fl_CodeBlock_Type::write_declare() {} + +void Fl_CodeBlock_Type::write_code1() { + const char* c = name(); + write_c("%s%s {\n", indent(), c ? c : ""); + indentation += 2; +} + +void Fl_CodeBlock_Type::write_code2() { + indentation += 2; + if (after) write_c("%s} %s\n", indent(), after); + else write_c("%s}\n", indent()); +} + +//////////////////////////////////////////////////////////////// + +class Fl_Decl_Type : public Fl_Type { + char public_; +public: + Fl_Type *make(); + void write_declare(); + void write_code1(); + void write_code2(); + void open(); + virtual const char *type_name() {return "decl";} + void write_properties(); + void read_property(const char *); +}; + +Fl_Type *Fl_Decl_Type::make() { + Fl_Type *p = Fl_Type::current; + while (p && !p->is_decl_block()) p = p->parent; + Fl_Decl_Type *o = new Fl_Decl_Type(); + o->public_ = 0; + o->name("int x;"); + o->add(p); + o->factory = this; + return o; +} + +void Fl_Decl_Type::write_properties() { + Fl_Type::write_properties(); + if (public_) write_string("public"); +} + +void Fl_Decl_Type::read_property(const char *c) { + if (!strcmp(c,"public")) { + public_ = 1; + } else { + Fl_Type::read_property(c); + } +} + +void Fl_Decl_Type::open() { + if (!decl_panel) make_decl_panel(); + decl_input->static_value(name()); + decl_public_button->value(public_); + decl_panel->show(); + const char* message = 0; + for (;;) { // repeat as long as there are errors + if (message) fl_alert(message); + for (;;) { + Fl_Widget* w = Fl::readqueue(); + if (w == decl_panel_cancel) goto BREAK2; + else if (w == decl_panel_ok) break; + else if (!w) Fl::wait(); + } + const char*c = decl_input->value(); + while (isspace(*c)) c++; + message = c_check(c&&c[0]=='#' ? c+1 : c); + if (message) continue; + name(c); + public_ = decl_public_button->value(); + break; + } + BREAK2: + decl_panel->hide(); +} + +Fl_Decl_Type Fl_Decl_type; + +void Fl_Decl_Type::write_declare() {} + +void Fl_Decl_Type::write_code1() { + const char* c = name(); + if (!c) return; + // handle putting #include or extern into decl: + if (!isalpha(*c) || !strncmp(c,"extern",6)) { + if (public_) + write_h("%s\n", c); + else + write_c("%s\n", c); + return; + } + // lose all trailing semicolons so I can add one: + const char* e = c+strlen(c); + while (e>c && e[-1]==';') e--; + if (class_name()) { + write_public(public_); + write_h(" %.*s;\n", e-c, c); + } else { + if (public_) { + write_h("extern %.*s;\n", e-c, c); + write_c("%.*s;\n", e-c, c); + } else { + write_c("static %.*s;\n", e-c, c); + } + } +} + +void Fl_Decl_Type::write_code2() {} + +//////////////////////////////////////////////////////////////// + +class Fl_DeclBlock_Type : public Fl_Type { + const char* after; +public: + Fl_Type *make(); + void write_declare(); + void write_code1(); + void write_code2(); + void open(); + virtual const char *type_name() {return "declblock";} + void write_properties(); + void read_property(const char *); + int is_parent() const {return 1;} + int is_decl_block() const {return 1;} +}; + +Fl_Type *Fl_DeclBlock_Type::make() { + Fl_Type *p = Fl_Type::current; + while (p && !p->is_decl_block()) p = p->parent; + Fl_DeclBlock_Type *o = new Fl_DeclBlock_Type(); + o->name("#if 1"); + o->after = strdup("#endif"); + o->add(p); + o->factory = this; + return o; +} + +void Fl_DeclBlock_Type::write_properties() { + Fl_Type::write_properties(); + write_string("after"); + write_word(after); +} + +void Fl_DeclBlock_Type::read_property(const char *c) { + if (!strcmp(c,"after")) { + storestring(read_word(),after); + } else { + Fl_Type::read_property(c); + } +} + +void Fl_DeclBlock_Type::open() { + if (!declblock_panel) make_declblock_panel(); + decl_before_input->static_value(name()); + decl_after_input->static_value(after); + declblock_panel->show(); + const char* message = 0; + for (;;) { // repeat as long as there are errors + if (message) fl_alert(message); + for (;;) { + Fl_Widget* w = Fl::readqueue(); + if (w == declblock_panel_cancel) goto BREAK2; + else if (w == declblock_panel_ok) break; + else if (!w) Fl::wait(); + } + const char*c = decl_before_input->value(); + while (isspace(*c)) c++; + message = c_check(c&&c[0]=='#' ? c+1 : c); + if (message) continue; + name(c); + c = decl_after_input->value(); + while (isspace(*c)) c++; + message = c_check(c&&c[0]=='#' ? c+1 : c); + if (message) continue; + storestring(c,after); + break; + } + BREAK2: + declblock_panel->hide(); +} + +Fl_DeclBlock_Type Fl_DeclBlock_type; + +void Fl_DeclBlock_Type::write_declare() {} + +void Fl_DeclBlock_Type::write_code1() { + const char* c = name(); + if (c) write_c("%s\n", c); +} + +void Fl_DeclBlock_Type::write_code2() { + const char* c = after; + if (c) write_c("%s\n", c); +} + +//////////////////////////////////////////////////////////////// + +class Fl_Class_Type : public Fl_Type { + const char* subclass_of; + char public_; +public: + // state variables for output: + char write_public_state; // true when public: has been printed + Fl_Class_Type* parent_class; // save class if nested +// + Fl_Type *make(); + void write_declare(); + void write_code1(); + void write_code2(); + void open(); + virtual const char *type_name() {return "class";} + int is_parent() const {return 1;} + int is_decl_block() const {return 1;} + int is_class() const {return 1;} + void write_properties(); + void read_property(const char *); +}; + +const char* Fl_Type::class_name() const { + Fl_Type* p = parent; + while (p) {if (p->is_class()) return p->name(); p = p->parent;} + return 0; +} + +Fl_Type *Fl_Class_Type::make() { + Fl_Type *p = Fl_Type::current; + while (p && !p->is_decl_block()) p = p->parent; + Fl_Class_Type *o = new Fl_Class_Type(); + o->name("UserInterface"); + o->subclass_of = 0; + o->public_ = 1; + o->add(p); + o->factory = this; + return o; +} + +void Fl_Class_Type::write_properties() { + Fl_Type::write_properties(); + if (subclass_of) { + write_string(":"); + write_word(subclass_of); + } + if (!public_) write_string("private"); +} + +void Fl_Class_Type::read_property(const char *c) { + if (!strcmp(c,"private")) { + public_ = 0; + } else if (!strcmp(c,":")) { + storestring(read_word(), subclass_of); + } else { + Fl_Type::read_property(c); + } +} + +void Fl_Class_Type::open() { + if (!class_panel) make_class_panel(); + c_name_input->static_value(name()); + c_subclass_input->static_value(subclass_of); + c_public_button->value(public_); + class_panel->show(); + const char* message = 0; + for (;;) { // repeat as long as there are errors + if (message) fl_alert(message); + for (;;) { + Fl_Widget* w = Fl::readqueue(); + if (w == c_panel_cancel) goto BREAK2; + else if (w == c_panel_ok) break; + else if (!w) Fl::wait(); + } + const char*c = c_name_input->value(); + while (isspace(*c)) c++; + if (!*c) goto OOPS; + while (is_id(*c)) c++; + while (isspace(*c)) c++; + if (*c) {OOPS: message = "class name must be C++ identifier"; continue;} + c = c_subclass_input->value(); + message = c_check(c); if (message) continue; + name(c_name_input->value()); + storestring(c, subclass_of); + public_ = c_public_button->value(); + break; + } + BREAK2: + class_panel->hide(); +} + +Fl_Class_Type Fl_Class_type; + +void Fl_Class_Type::write_declare() {} + +static Fl_Class_Type *current_class; +extern int varused_test; +void write_public(int state) { + if (!current_class || varused_test) return; + if (current_class->write_public_state == state) return; + current_class->write_public_state = state; + write_h(state ? "public:\n" : "private:\n"); +} + +void Fl_Class_Type::write_code1() { + parent_class = current_class; + current_class = this; + write_public_state = 0; + write_h("\nclass %s ", name()); + if (subclass_of) write_h(": %s ", subclass_of); + write_h("{\n"); +} + +void Fl_Class_Type::write_code2() { + write_h("};\n"); + current_class = parent_class; +} |
