コード例 #1
0
ファイル: CFCType.c プロジェクト: hernan604/lucy
CFCType*
CFCType_new_object(int flags, CFCParcel *parcel, const char *specifier,
                   int indirection) {
    // Validate params.
    if (indirection != 1) {
        CFCUtil_die("Parameter 'indirection' can only be 1");
    }
    if (!specifier || !strlen(specifier)) {
        CFCUtil_die("Missing required param 'specifier'");
    }
    if ((flags & CFCTYPE_INCREMENTED) && (flags & CFCTYPE_DECREMENTED)) {
        CFCUtil_die("Can't be both incremented and decremented");
    }

    // Use default parcel if none supplied.
    if (!parcel) {
        parcel = CFCParcel_default_parcel();
    }

    // Add flags.
    flags |= CFCTYPE_OBJECT;
    if (strstr(specifier, "String")) {
        // Determine whether this type is a string type.
        flags |= CFCTYPE_STRING_TYPE;
    }

    // Validate specifier.
    if (!isalpha(*specifier)) {
        CFCUtil_die("Invalid specifier: '%s'", specifier);
    }
    const char *small_specifier = specifier;
    while (!isupper(*small_specifier)) {
        if (!isalnum(*small_specifier) && *small_specifier != '_') {
            CFCUtil_die("Invalid specifier: '%s'", specifier);
        }
        small_specifier++;
    }
    if (!CFCSymbol_validate_class_name_component(small_specifier)) {
        CFCUtil_die("Invalid specifier: '%s'", specifier);
    }

    int acceptable_flags = CFCTYPE_OBJECT
                           | CFCTYPE_STRING_TYPE
                           | CFCTYPE_CONST
                           | CFCTYPE_NULLABLE
                           | CFCTYPE_INCREMENTED
                           | CFCTYPE_DECREMENTED;
    S_check_flags(flags, acceptable_flags, "Object");

    return CFCType_new(flags, parcel, specifier, 1);
}
コード例 #2
0
ファイル: CFCParcel.c プロジェクト: pavansondur/lucy
CFCParcel*
CFCParcel_fetch(const char *name) {
    // Return the default parcel for either a blank name or a NULL name.
    if (!name || !strlen(name)) {
        return CFCParcel_default_parcel();
    }

    for (size_t i = 0; i < num_registered ; i++) {
        CFCParcel *existing = registry[i];
        if (strcmp(existing->name, name) == 0) {
            return existing;
        }
    }

    return NULL;
}
コード例 #3
0
ファイル: CFCParcel.c プロジェクト: pavansondur/lucy
void
CFCParcel_register(CFCParcel *self) {
    CFCParcel *existing = CFCParcel_fetch(self->name);
    if (existing) {
        CFCUtil_die("Parcel '%s' already registered", self->name);
    }
    if (!num_registered) {
        // Init default parcel as first.
        registry = (CFCParcel**)CALLOCATE(3, sizeof(CFCParcel*));
        CFCParcel *def = CFCParcel_default_parcel();
        registry[0] = (CFCParcel*)CFCBase_incref((CFCBase*)def);
        num_registered++;
    }
    size_t size = (num_registered + 2) * sizeof(CFCParcel*);
    registry = (CFCParcel**)REALLOCATE(registry, size);
    registry[num_registered++] = (CFCParcel*)CFCBase_incref((CFCBase*)self);
    registry[num_registered]   = NULL;
}
コード例 #4
0
ファイル: CFCClass.c プロジェクト: hernan604/lucy
CFCClass*
CFCClass_do_create(CFCClass *self, struct CFCParcel *parcel,
                   const char *exposure, const char *class_name,
                   const char *cnick, const char *micro_sym,
                   CFCDocuComment *docucomment, CFCFileSpec *file_spec,
                   const char *parent_class_name, int is_final, int is_inert) {
    CFCUTIL_NULL_CHECK(class_name);
    exposure  = exposure  ? exposure  : "parcel";
    micro_sym = micro_sym ? micro_sym : "class";
    parcel    = parcel    ? parcel    : CFCParcel_default_parcel();
    CFCSymbol_init((CFCSymbol*)self, parcel, exposure, class_name, cnick,
                   micro_sym);
    if (!is_inert
        && !parent_class_name
        && strcmp(class_name, "Clownfish::Obj") != 0
       ) {
        parent_class_name = "Clownfish::Obj";
    }
    self->parent     = NULL;
    self->tree_grown = false;
    self->children        = (CFCClass**)CALLOCATE(1, sizeof(CFCClass*));
    self->num_kids        = 0;
    self->functions       = (CFCFunction**)CALLOCATE(1, sizeof(CFCFunction*));
    self->num_functions   = 0;
    self->methods         = (CFCMethod**)CALLOCATE(1, sizeof(CFCMethod*));
    self->num_methods     = 0;
    self->member_vars     = (CFCVariable**)CALLOCATE(1, sizeof(CFCVariable*));
    self->num_member_vars = 0;
    self->inert_vars      = (CFCVariable**)CALLOCATE(1, sizeof(CFCVariable*));
    self->num_inert_vars  = 0;
    self->parent_class_name = CFCUtil_strdup(parent_class_name);
    self->docucomment
        = (CFCDocuComment*)CFCBase_incref((CFCBase*)docucomment);
    self->file_spec = (CFCFileSpec*)CFCBase_incref((CFCBase*)file_spec);

    // Cache several derived symbols.
    const char *last_colon = strrchr(class_name, ':');
    self->struct_sym = last_colon
                       ? CFCUtil_strdup(last_colon + 1)
                       : CFCUtil_strdup(class_name);
    const char *prefix = CFCClass_get_prefix(self);
    size_t struct_sym_len = strlen(self->struct_sym);
    self->short_vtable_var = (char*)MALLOCATE(struct_sym_len + 1);
    size_t i;
    for (i = 0; i < struct_sym_len; i++) {
        self->short_vtable_var[i] = toupper(self->struct_sym[i]);
    }
    self->short_vtable_var[struct_sym_len] = '\0';
    self->full_struct_sym   = CFCUtil_sprintf("%s%s", prefix, self->struct_sym);
    self->ivars_struct      = CFCUtil_sprintf("%sIVARS", self->struct_sym);
    self->full_ivars_struct = CFCUtil_sprintf("%sIVARS", self->full_struct_sym);
    self->ivars_func        = CFCUtil_sprintf("%s_IVARS", CFCClass_get_cnick(self));
    self->full_ivars_func   = CFCUtil_sprintf("%s%s_IVARS", prefix,
                                              CFCClass_get_cnick(self));
    self->full_ivars_offset = CFCUtil_sprintf("%s_OFFSET", self->full_ivars_func);
    size_t full_struct_sym_len = strlen(self->full_struct_sym);
    self->full_vtable_var = (char*)MALLOCATE(full_struct_sym_len + 1);
    for (i = 0; self->full_struct_sym[i] != '\0'; i++) {
        self->full_vtable_var[i] = toupper(self->full_struct_sym[i]);
    }
    self->full_vtable_var[i] = '\0';
    self->privacy_symbol = CFCUtil_sprintf("C_%s", self->full_vtable_var);

    // Build the relative path to the autogenerated C header file.
    if (file_spec) {
        const char *path_part = CFCFileSpec_get_path_part(self->file_spec);
        self->include_h = CFCUtil_sprintf("%s.h", path_part);
    }
    else {
        self->include_h = CFCUtil_strdup("class.h");
    }

    self->is_final    = !!is_final;
    self->is_inert    = !!is_inert;

    if (file_spec && CFCFileSpec_included(file_spec)) {
        if (!CFCParcel_included(parcel)) {
            CFCUtil_die("Class %s from include dir found in parcel %s from"
                        " source dir",
                        class_name, CFCParcel_get_name(parcel));
        }
    }
    else {
        if (CFCParcel_included(parcel)) {
            CFCUtil_die("Class %s from source dir found in parcel %s from"
                        " include dir",
                        class_name, CFCParcel_get_name(parcel));
        }
    }

    // Store in registry.
    S_register(self);

    return self;
}
コード例 #5
0
ファイル: CFCType.c プロジェクト: pavansondur/lucy
CFCType*
CFCType_new_object(int flags, CFCParcel *parcel, const char *specifier,
                   int indirection) {
    // Validate params.
    if (indirection != 1) {
        CFCUtil_die("Parameter 'indirection' can only be 1");
    }
    if (!specifier || !strlen(specifier)) {
        CFCUtil_die("Missing required param 'specifier'");
    }
    if ((flags & CFCTYPE_INCREMENTED) && (flags & CFCTYPE_DECREMENTED)) {
        CFCUtil_die("Can't be both incremented and decremented");
    }

    // Use default parcel if none supplied.
    if (!parcel) {
        parcel = CFCParcel_default_parcel();
    }

    // Add flags.
    flags |= CFCTYPE_OBJECT;
    if (strstr(specifier, "CharBuf")) {
        // Determine whether this type is a string type.
        flags |= CFCTYPE_STRING_TYPE;
    }

    const size_t MAX_SPECIFIER_LEN = 256;
    char full_specifier[MAX_SPECIFIER_LEN + 1];
    char small_specifier[MAX_SPECIFIER_LEN + 1];
    if (isupper(*specifier)) {
        const char *prefix = CFCParcel_get_prefix(parcel);
        if (strlen(prefix) + strlen(specifier) > MAX_SPECIFIER_LEN) {
            CFCUtil_die("Specifier and/or parcel prefix too long");
        }
        sprintf(full_specifier, "%s%s", prefix, specifier);
        strcpy(small_specifier, specifier);
    }
    else if (!isalpha(*specifier)) {
        CFCUtil_die("Invalid specifier: '%s'", specifier);
    }
    else {
        if (strlen(specifier) > MAX_SPECIFIER_LEN) {
            CFCUtil_die("Specifier too long");
        }
        const char *probe = specifier;
        while (*probe) {
            if (isupper(*probe)) {
                break;
            }
            else if (!isalnum(*probe) && *probe != '_') {
                CFCUtil_die("Invalid specifier: '%s'", specifier);
            }
            probe++;
        }
        strcpy(full_specifier, specifier);
        strcpy(small_specifier, probe);
    }

    if (!CFCSymbol_validate_class_name_component(small_specifier)) {
        CFCUtil_die("Invalid specifier: '%s'", specifier);
    }

    // Cache C representation.
    char c_string[MAX_SPECIFIER_LEN + 10];
    if (flags & CFCTYPE_CONST) {
        sprintf(c_string, "const %s*", full_specifier);
    }
    else {
        sprintf(c_string, "%s*", full_specifier);
    }

    int acceptable_flags = CFCTYPE_OBJECT
                           | CFCTYPE_STRING_TYPE
                           | CFCTYPE_CONST
                           | CFCTYPE_NULLABLE
                           | CFCTYPE_INCREMENTED
                           | CFCTYPE_DECREMENTED;
    S_check_flags(flags, acceptable_flags, "Object");

    return CFCType_new(flags, parcel, full_specifier, 1, c_string);
}
コード例 #6
0
ファイル: CFCTestSymbol.c プロジェクト: hernan604/lucy
static void
S_run_tests(CFCTest *test) {
    CFCParcel *parcel = CFCParcel_default_parcel();

    {
        static const char *exposures[4] = {
            "public", "private", "parcel", "local"
        };
        static int (*accessors[4])(CFCSymbol *sym) = {
            CFCSymbol_public,
            CFCSymbol_private,
            CFCSymbol_parcel,
            CFCSymbol_local
        };
        for (int i = 0; i < 4; ++i) {
            CFCSymbol *symbol
                = CFCSymbol_new(parcel, exposures[i], NULL, NULL, "sym");
            for (int j = 0; j < 4; ++j) {
                int has_exposure = accessors[j](symbol);
                if (i == j) {
                    OK(test, has_exposure, "exposure %s", exposures[i]);
                }
                else {
                    OK(test, !has_exposure, "%s means not %s", exposures[i],
                       exposures[j]);
                }
            }
            CFCBase_decref((CFCBase*)symbol);
        }
    }

    {
        CFCSymbol *foo = CFCSymbol_new(parcel, "parcel", "Foo", NULL, "sym");
        CFCSymbol *foo_jr
            = CFCSymbol_new(parcel, "parcel", "Foo::FooJr", NULL, "sym");

        int equal = CFCSymbol_equals(foo, foo_jr);
        OK(test, !equal, "different class_name spoils equals");
        const char *foo_jr_name = CFCSymbol_get_class_name(foo_jr);
        STR_EQ(test, foo_jr_name, "Foo::FooJr", "get_class_name");
        const char *foo_jr_cnick = CFCSymbol_get_class_cnick(foo_jr);
        STR_EQ(test, foo_jr_cnick, "FooJr",
               "derive class_cnick from class_name");

        CFCBase_decref((CFCBase*)foo);
        CFCBase_decref((CFCBase*)foo_jr);
    }

    {
        CFCSymbol *public_exposure
            = CFCSymbol_new(parcel, "public", NULL, NULL, "sym");
        CFCSymbol *parcel_exposure
            = CFCSymbol_new(parcel, "parcel", NULL, NULL, "sym");
        int equal = CFCSymbol_equals(public_exposure, parcel_exposure);
        OK(test, !equal, "different exposure spoils equals");
        CFCBase_decref((CFCBase*)public_exposure);
        CFCBase_decref((CFCBase*)parcel_exposure);
    }

    {
        CFCParcel *lucifer_parcel
            = CFCParcel_new("Lucifer", NULL, NULL, false);
        CFCParcel_register(lucifer_parcel);
        CFCSymbol *lucifer
            = CFCSymbol_new(lucifer_parcel, "parcel", NULL, NULL, "sym");

        CFCParcel *symbol_parcel = CFCSymbol_get_parcel(lucifer);
        OK(test, symbol_parcel == lucifer_parcel, "derive parcel");
        const char *prefix = CFCSymbol_get_prefix(lucifer);
        STR_EQ(test, prefix, "lucifer_", "get_prefix");
        const char *Prefix = CFCSymbol_get_Prefix(lucifer);
        STR_EQ(test, Prefix, "Lucifer_", "get_Prefix");
        const char *PREFIX = CFCSymbol_get_PREFIX(lucifer);
        STR_EQ(test, PREFIX, "LUCIFER_", "get_PREFIX");

        CFCParcel *luser_parcel = CFCParcel_new("Luser", NULL, NULL, false);
        CFCParcel_register(luser_parcel);
        CFCSymbol *luser
            = CFCSymbol_new(luser_parcel, "parcel", NULL, NULL, "sym");
        int equal = CFCSymbol_equals(lucifer, luser);
        OK(test, !equal, "different exposure spoils equals");

        CFCBase_decref((CFCBase*)lucifer_parcel);
        CFCBase_decref((CFCBase*)lucifer);
        CFCBase_decref((CFCBase*)luser_parcel);
        CFCBase_decref((CFCBase*)luser);
    }

    {
        CFCSymbol *ooga = CFCSymbol_new(parcel, "parcel", NULL, NULL, "ooga");
        CFCSymbol *booga
            = CFCSymbol_new(parcel, "parcel", NULL, NULL, "booga");
        int equal = CFCSymbol_equals(ooga, booga);
        OK(test, !equal, "different micro_sym spoils equals");
        CFCBase_decref((CFCBase*)ooga);
        CFCBase_decref((CFCBase*)booga);
    }

    {
        CFCParcel *eep_parcel = CFCParcel_new("Eep", NULL, NULL, false);
        CFCParcel_register(eep_parcel);
        CFCSymbol *eep
            = CFCSymbol_new(eep_parcel, "parcel", "Op::Ork", NULL, "ah_ah");
        const char *short_sym = CFCSymbol_short_sym(eep);
        STR_EQ(test, short_sym, "Ork_ah_ah", "short_sym");
        const char *full_sym = CFCSymbol_full_sym(eep);
        STR_EQ(test, full_sym, "eep_Ork_ah_ah", "full_sym");
        CFCBase_decref((CFCBase*)eep_parcel);
        CFCBase_decref((CFCBase*)eep);
    }

    CFCParcel_reap_singletons();
}