view src/gearsTools/generate_context.pl @ 52:1adde248a61f default tip

merge
author anatofuz <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Fri, 07 Jun 2019 17:30:15 +0900
parents 233a68a261fe
children
line wrap: on
line source

#!/usr/bin/perl

use Getopt::Std;
use strict;

# 
# generrate Gears OS context heaader and initializer from CbC sources
#
# CodeGear
# 
# get stub information from # *.c
#     __code taskManager_stub(struct Context* context) {
# 
# generate CodeGear indexn in context.h
#     C_taskManager,
# 
# generate CodeGear stub reference in context.h
#     extern __code taskManager_stub(struct Context*);
# 
# generate CodeGear stub reference in $name-context.h for each module
#     context->code[C_taskManager]   = taskManager_stub;
# 
# DataGear
# 
# get DataGear information from context.h
#     struct Worker {
#         int id;
#         struct Context* contexts;
#         enum Code execute;
#         enum Code taskSend;
#         enum Code taskRecive;
#         enum Code shutdown;
#         struct Queue* tasks;
#     } Worker;
# 
# generate typedefs and DataGear index in context.h
#     typedef struct Worker Worker;
#     D_Worker,
# 
# generate DataGear allocator in context.h
#      ALLOC_DATA(context, Worker);
#

my $ddir = "c";

our($opt_o,$opt_d,$opt_h);
getopts('o:d:h');

my $name = $opt_o?$opt_o:"gears";

if ($opt_d) {
    $ddir = $opt_d;
}

if ( ! -d $ddir) {
    mkdir $ddir;
}

if ($opt_h) {
    print "$0  [-d distdir] [-h]\n";
    exit;
}

my %codeGear;
my %dataGear;
my %constructor;

# gather module Information for code table initialization
for (@ARGV) {
    next if (/context.c/);
    &getStubInfo($_);
}

my (%mCodeGear) = (%codeGear);

# anyway we gather all Gears Information
while (<*.c test/*.c>) {
    next if (/context.c/);
    &getStubInfo($_);
}

&generateContext();

sub getStubInfo {
    my ($filename) = @_;
    open my $fd,"<",$filename or die("can't open $filename $!");
    while (<$fd>) {
        if (/^__code (\w+)_stub\(struct  *Context *\* *context\)/) {
            $codeGear{$1} = $filename;
        } elsif (/^(\w+)(\*)+  *create(\w+)\(([^]]*)\)/) {
            my $interface = $1;
            my $implementation = $3;
            my $constructorArgs = $4;
            $constructor{$implementation} = [$interface, $constructorArgs];
        }
    }

    open my $cx,"<","context.h" or die("can't open context.h $!");
    my $inUnionData = 0;
    while (<$cx>) {
        if (! $inUnionData) {
            if ( /^union Data/) {
                $inUnionData = 1;
            }
            next;
        }
        last if (/union Data end/);
        if (/struct (\w+) \{/) {
            $dataGear{$1} = 'struct';
        } elsif (/^\s{4}(\w+) (\w+);/) { # primitive type
            $dataGear{$1} = 'primitive';
        }
        $dataGear{"Context"} = "struct";
    }
}

sub generateContext {
    $codeGear{"start_code"} = "$ddir/$name-context.c";
    $codeGear{"exit_code"} = "$ddir/$name-context.c";
    $mCodeGear{"start_code"} = "$ddir/$name-context.c";
    $mCodeGear{"exit_code"} = "$ddir/$name-context.c";
    open my $fd,">","$ddir/extern.h" or die("can't open $ddir/extern.h $!");
    for my $code ( sort keys %codeGear ) {
        print $fd "extern __code ${code}_stub(struct Context*);\n";
    }
    for my $impl ( sort keys %constructor ) {
        my ($interface, $constructorArgs) = @{$constructor{$impl}};
        print $fd "extern ${interface}* create${impl}($constructorArgs);\n";
    }
    print $fd "\n";

    open my $fd,">","$ddir/enumCode.h" or die("can't open $ddir/enumCode.h $!");
    print $fd "enum Code {\n";
    for my $code ( sort keys %codeGear ) {
        print $fd "    C_${code},\n";
    }
    print $fd "};\n";
   
    my $code_init = ''; 
    for my $code ( sort keys %mCodeGear ) {
        $code_init .=  "    context->code[C_${code}]    = ${code}_stub;\n";
    }

    my $data_num = keys(%dataGear);
    $data_num++;
my $context_c = << "EOFEOF";
#ifndef CBCXV6
#include <stdlib.h>
#endif

#include "../context.h"

void initContext(struct Context* context) {
    context->heapLimit = sizeof(union Data)*ALLOCATE_SIZE;
    context->code = (__code(**) (struct Context*)) NEWN(ALLOCATE_SIZE, void*);
    context->data = NEWN(ALLOCATE_SIZE, union Data*);
    context->heapStart = NEWN(context->heapLimit, char);
    context->heap = context->heapStart;
    // context->codeNum = Exit;

$code_init

#include "dataGearInit.c"
    context->dataNum = $data_num;
}
EOFEOF

    open my $fd,">","$ddir/$name-context.c" or die("can't open $ddir/$name-context.c $!");
    print $fd $context_c;

my $meta_call = <<"EOFEOF";
__code meta(struct Context* context, enum Code next) {
    // printf("meta %d\\n",next);
    goto (context->code[next])(context);
}

__code parGotoMeta(struct Context* context, enum Code next) {
    context->task     = NULL;
    context->taskList = NULL;
    goto (context->code[Gearef(context, TaskManager)->taskManager->TaskManager.spawnTasks])(context);
}

__code start_code(struct Context* context) {
    goto meta(context, context->next);
}

__code start_code_stub(struct Context* context) {
    goto start_code(context);
}

__code exit_code(struct Context* context) {
    free(context->code);
    free(context->data);
    free(context->heapStart);
    goto exit(0);
}

__code exit_code_stub(struct Context* context) {
    goto exit_code(context);
}    

// end context_c
EOFEOF

print $fd $meta_call;

open my $fd,">","$ddir/enumData.h" or die("can't open $ddir/enumData.h $!");
print $fd "enum DataType {\n";
print $fd "    D_Code,\n";
for my $data ( sort keys %dataGear ) {
    print $fd "    D_${data},\n";
}
print $fd "};\n\n";

open my $fd,">","$ddir/typedefData.h" or die("can't open $ddir/typedefData.h $!");
for my $data ( sort keys %dataGear ) {
    if ($dataGear{$data} eq 'struct') {
        print $fd "typedef struct ${data} ${data};\n";
    }
}

open my $fd,">","$ddir/dataGearInit.c" or die("can't open $ddir/dataGearInit.c $!");
for my $data ( sort keys %dataGear ) {
    print $fd "    ALLOC_DATA(context, ${data});\n";
}
}

# end