#include #include #include #include #include #include #include "list.h" #include "mapcalc.h" #include "map.h" typedef MAP *(*m_func)(void); typedef MAP *(*m_func_m)(void *m0); typedef MAP *(*m_func_mm)(void *m0, void *m1); typedef struct Mapfunc { char *name; void *func; char *proto; }MAPFUNC; static MAP *testmap (MAP *m); static MAP *test2map (MAP *m, MAP *n); static MAP *map_op_func_plus (MAP *m, MAP *n); static void find_maps (void); void init_map (void); void showmap (SYMBOL *map); void setmap (SYMBOL *var, SYMBOL *map); SYMBOL *mkmapvar (SYMBOL *var, SYMBOL *map); SYMBOL *mapfunc (SYMBOL *func, SYMBOL *arglist); SYMBOL *mapop (int op, SYMBOL *map1, SYMBOL *map2); static MAPFUNC mf[] = { { "testmap", testmap, "m" }, { "test2map", test2map, "mm" }, { "map_op_func_+", map_op_func_plus, "mm" }, { NULL, NULL, NULL } }; /************************************************************************* * This function represents a built-in map function. * Should probably go to another file */ static MAP * testmap (MAP *m) { char namebuf[128]; /* * The map name always exists, as it represents data on disk, but * might be a temporary name, when it should not be displayed * (should it?). */ printf ("Performing 1 arg map function on map %s\n", m->name); sprintf (namebuf, "t-%s", m->name); m = (MAP *)listitem (sizeof (MAP)); m->name = strdup (namebuf); return m; } static MAP * test2map (MAP *m, MAP *n) { char namebuf[128]; printf ("Performing 2 arg map function on maps %s and %s\n", m->name, n->name); sprintf (namebuf, "%s.%s", m->name, n->name); m = (MAP *)listitem (sizeof (MAP)); m->name = strdup (namebuf); return m; } static MAP * map_op_func_plus (MAP *m, MAP *n) { char namebuf[128]; printf ("Performing map %s + %s\n", m->name, n->name); sprintf (namebuf, "%s.%s", m->name, n->name); m = (MAP *)listitem (sizeof (MAP)); m->name = strdup (namebuf); return m; } /* * end of move to other file ***********************************************************************/ static void find_maps (void) { char *gisdbase, *location, *mapset; char basepath[4096], subdirpath[4096], path[4096]; DIR *dir, *subdir; struct dirent *ent, *subent; gisdbase = getenv ("GISDBASE"); if (!gisdbase) gisdbase = "."; location = getenv ("LOCATION_NAME"); if (!location) location = "."; mapset = getenv ("MAPSET"); if (!mapset) mapset = "."; /* * Now, if I'm not in grass, I can simulate the existence of a vector * map creating a directory vector with one subdirectory for each `map' * having a file `head' */ sprintf (basepath, "%s/%s/%s/vector", gisdbase, location, mapset); dir = opendir (basepath); if (!dir) return; while ((ent = readdir (dir)) != NULL) { struct stat buf; if (!strcmp (ent->d_name, ".") || !strcmp (ent->d_name, "..")) continue; strcpy (path, basepath); strcat (path, "/"); strcat (path, ent->d_name); if (stat (path, &buf)) continue; if (S_ISDIR (buf.st_mode)) { strcpy (subdirpath, path); subdir = opendir (subdirpath); if (!subdir) continue; while ((subent = readdir (subdir)) != NULL) { if (!strcmp (subent->d_name, ".") || !strcmp (subent->d_name, "..")) continue; if (!strcmp (subent->d_name, "head")) { MAP *map; SYMBOL *sym; map = (MAP *)listitem (sizeof (MAP)); map->name = strdup (ent->d_name); map->refcnt++; sym = putsym (map->name); sym->type = sym->itype = st_map; sym->v.p = map; } } closedir (subdir); } } closedir (dir); } void init_map (void) { SYMBOL *sym; int i; for (i = 0; mf[i].name; i++) { sym = putsym (mf[i].name); sym->type = sym->itype = st_mfunc; sym->v.p = mf[i].func; sym->proto = mf[i].proto; sym->rettype = st_map; } find_maps (); } void printmap (SYMBOL *sym) { MAP *map; map = (MAP *)sym->v.p; if (map->name) printf ("\t%s\n", map->name); } void showmap (SYMBOL *sym) { MAP *map; map = (MAP *)sym->v.p; printmap (sym); if (--map->refcnt > 0) sym->v.p = NULL; freesym (sym); } MAP * freemap (MAP *map) { if (map) { if (map->refcnt > 0) return map; if (map->name) G_free (map->name); if (map->mapinfo) G_free (map->mapinfo); /* call grass to handle map */ G_free (map); } return NULL; } void setmap (SYMBOL *var, SYMBOL *map) { SYMBOL *sym; if (var->name) { sym = getsym (var->name); if (sym) { sym->v.p = freemap (sym->v.p); sym->v.p = map->v.p; } } freemap (var->v.p); var->v.p = NULL; freesym (var); printmap (map); map->v.p = NULL; freesym (map); } SYMBOL * mkmapvar (SYMBOL *var, SYMBOL *map) { var->type = var->itype = st_map; var->name = var->v.p; var->v.p = map->v.p; map->v.p = NULL; freesym (map); symtab = (SYMBOL *)listadd ((LIST *)symtab, (LIST *)var, cmpsymsym); printmap (var); return var; } SYMBOL * mapfunc (SYMBOL *func, SYMBOL *arglist) { SYMBOL *sym; MAP *res = NULL; int argc = -1; if (!func || !func->v.p || func->type != st_mfunc) { parseerror = 1; printf ("Can't call bad map-function\n"); } else argc = listcnt ((LIST *)arglist); if (argc == 0 && (!func->proto || !*func->proto)) res = (*(m_func)func->v.p)(); else if (argc == 1 && !strcmp (func->proto, "m")) res = (*(m_func_m)func->v.p)(arglist->v.p); else if (argc == 2 && !strcmp (func->proto, "mm")) res = (*(m_func_mm)func->v.p)(arglist->v.p, arglist->next->v.p); else { printf ("Bad arguments to mapfunc %s (argc = %d)\n", func->name, argc); parseerror = 1; } listdelall ((LIST *)func, freesym); listdelall ((LIST *)arglist, freesym); sym = (SYMBOL *)listitem (sizeof (SYMBOL)); sym->type = st_map; sym->v.p = res; return sym; } SYMBOL * mapop (int op, SYMBOL *map1, SYMBOL *map2) { SYMBOL *func, *arglist, *res = NULL; char buf[32]; sprintf (buf, "map_op_func_%c", op); func = getsym (buf); if (!func) { printf ("No function defined to perform map %c map\n", op); parseerror = 1; } else { res = (SYMBOL *)listitem (sizeof (SYMBOL)); symcpy (res, func); res->next = NULL; func = res; arglist = (SYMBOL *)listapp (NULL, (LIST *)map1); arglist = (SYMBOL *)listapp ((LIST *)arglist, (LIST *)map2); res = mapfunc (func, arglist); } /* free map1/map2 ? only if they have no name? */ return res; }