1 /* ------------------------------------------------------------------------
2 * $Id: daVinci.c,v 1.3 2003/08/01 14:58:48 panne Exp $
4 * Copyright (C) 1995-2000 University of Oxford
6 * Permission to use, copy, modify, and distribute this software,
7 * and to incorporate it, in whole or in part, into other software,
8 * is hereby granted without fee, provided that
9 * (1) the above copyright notice and this permission notice appear in
10 * all copies of the source code, and the above copyright notice
11 * appear in clearly visible form on all supporting documentation
12 * and distribution media;
13 * (2) modified versions of this software be accompanied by a complete
14 * change history describing author, date, and modifications made;
16 * (3) any redistribution of the software, in original or modified
17 * form, be without fee and subject to these same conditions.
18 * --------------------------------------------------------------------- */
24 static char* extra_space(int);
25 static void recur_graphToDaVinci(int,Matrix *, Matrix *,char*,int);
26 static char *parse_word(char**);
27 static char *parse_quoted(char**);
28 static char *dup_str(char*);
29 double this_total_time,
30 this_total_comp_max, this_total_comp_avg,
31 this_total_comm_max, this_total_comm_avg,
32 this_total_comp_idle_max, this_total_comp_idle_avg;
33 long int this_hrel_max, this_hrel_avg;
38 /* -----------------------------------------------------------------------------
39 * Send a command with ok return value daVinci
40 * -------------------------------------------------------------------------- */
42 void cmdDaVinci(char* format,...) {
45 va_start(args, format);
46 vfprintf(stdout, format, args);
47 fprintf(stdout, "\n");
50 lastDavinciCmd = format;
53 /* -----------------------------------------------------------------------------
55 * -------------------------------------------------------------------------- */
58 cmdDaVinci("window(title(\"GHC profiler: cost-centre-stack view\"))\n");
59 cmdDaVinci("set(font_size(8))");
60 cmdDaVinci("set(animation_speed(0))");
61 cmdDaVinci("set(scrolling_on_selection(false))");
63 /* cmdDaVinci("set(no_cache(true)))"); */
64 cmdDaVinci("app_menu(create_icons(["
65 "icon_entry(\"delete\","
67 "\"Delete node and its children\"),"
68 "icon_entry(\"undo\","
72 "icon_entry(\"time\","
74 "\"Cost metric view\"),"
75 "icon_entry(\"percent\","
77 "\"Percentage view\"),"
79 "icon_entry(\"compress\","
81 "\"Compressed node view\"),"
82 "icon_entry(\"uncompress\","
84 "\"Uncompressed node view\"),"
86 "icon_entry(\"absolute\","
88 "\"Display inherited profile results\"),"
89 "icon_entry(\"absdelta\","
91 "\"Display flat profile results\"),"
92 "icon_entry(\"reldelta\","
94 "\"Trim zero-cost sub-trees\"),"
95 "icon_entry(\"weightdelta\","
96 "\"weightdelta.xbm\","
97 "\"Trim zero-cost nodes\"),"
99 "icon_entry(\"sync\","
102 "icon_entry(\"comp\","
104 "\"SCCs critical path\"),"
105 "icon_entry(\"comm\","
107 "\"Computation time critical path\"),"
108 "icon_entry(\"wait\","
110 "\"Heap usage critical path\"),"
111 "icon_entry(\"hrel\","
115 "icon_entry(\"help\","
120 activateDaVinciMenu("default");
121 cmdDaVinci("app_menu(create_menus([menu_entry_mne(\"jump\",\"Goto a node\",\"G\",control,\"G\")]))\n");
123 // cmdDaVinci("app_menu(activate_menus([\"jump\"]))");
126 /* -----------------------------------------------------------------------------
128 * -------------------------------------------------------------------------- */
130 void activateDaVinciMenu(char *pressed) {
131 static int compress=1,time=1,critical_type=0,critical=0,undo=1,delete=0;
133 if (strcmp(pressed,"absolute")==0) critical_type=0;
134 if (strcmp(pressed,"absdelta")==0) critical_type=1;
135 if (strcmp(pressed,"reldelta")==0) critical_type=2;
136 if (strcmp(pressed,"weightdelta")==0) critical_type=3;
138 if (strcmp(pressed,"sync")==0) critical=0;
139 if (strcmp(pressed,"comp")==0) critical=1;
140 if (strcmp(pressed,"comm")==0) critical=2;
141 if (strcmp(pressed,"wait")==0) critical=3;
142 if (strcmp(pressed,"hrel")==0) critical=4;
144 if (strcmp(pressed,"compress")==0 || strcmp(pressed,"uncompress")==0)
147 if (strcmp(pressed,"time")==0 || strcmp(pressed,"percent")==0)
150 if (strcmp(pressed,"undo")==0) {undo=!undo;}
151 if (strcmp(pressed,"delete")==0) {delete=!delete;}
153 printf("app_menu(activate_icons([");
154 if (critical_type!=0) printf("\"absolute\",");
155 if (critical_type!=1) printf("\"absdelta\",");
156 if (critical_type!=2) printf("\"reldelta\",");
157 if (critical_type!=3) printf("\"weightdelta\",");
159 if (critical!=0) printf("\"sync\",");
160 if (critical!=1) printf("\"comp\",");
161 if (critical!=2) printf("\"comm\",");
162 if (critical!=3) printf("\"wait\",");
163 if (critical!=4) printf("\"hrel\",");
165 if (!compress) printf("\"compress\",");
166 if (compress) printf("\"uncompress\",");
167 if (!time) printf("\"time\",");
168 if (time) printf("\"percent\",");
169 if (!delete) printf("\"delete\",");
170 if (!undo) printf("\"undo\",");
172 cmdDaVinci("\"help\"]))");
175 /* -----------------------------------------------------------------------------
177 * -------------------------------------------------------------------------- */
179 void graphToDaVinci(int root,Matrix *graph, Matrix *costs, int removezerocosts) {
182 char zeronodes[MAX_PROFILE_LINE_LENGTH*2]; // is this a sen. MAX
183 char TEMPzeronodes[MAX_PROFILE_LINE_LENGTH*2];
184 char* p_zeronodes = zeronodes;
185 char* TEMPp_zeronodes = TEMPzeronodes;
187 printf("graph(new([");
189 /* I have implemented some name changes here. They are purely for output and */
190 /* following the relation (comp = scc, comm = ticks, wait = bytes */
191 printf("l(\"info\",n(\"\",["
192 "a(\"COLOR\",\"gold\"),"
193 "a(\"FONTFAMILY\",\"courier\"),"
194 //"a(\"_GO\",\"icon\"),"
195 //"a(\"ICONFILE\",\"oxpara.xbm\"),"
197 "Program statistics\\n\\n"
198 "Time elapsed = %6.2f ticks\\n"
199 "Heap usage = %6.2f bytes\\n"
200 "Total scc count = %6.2f (scc)\\n"
202 TotalComm,TotalCompIdle,
210 ptr = &Mat(object_cost,*costs,root,0);
211 this_total_comp_max = ptr->comp_max;
212 this_total_comp_avg = ptr->comp_avg;
213 this_total_comm_max = ptr->comm_max;
214 this_total_comm_avg = ptr->comm_avg;
215 this_total_comp_idle_max= ptr->comp_idle_max;
216 this_total_comp_idle_avg= ptr->comp_idle_avg;
217 this_total_time = 0.00001 +
218 this_total_comp_max+ this_total_comm_max;
219 this_hrel_max = ptr->hrel_max;
220 this_hrel_avg = ptr->hrel_avg;
221 this_syncs = ptr->syncs;
222 recur_graphToDaVinci(root,graph,costs,p_zeronodes,removezerocosts);
226 cmdDaVinci("special(focus_node(\"%d\"))\n",root);
228 /* graph will have been altered so that visted elements are marked
229 by a negative value. These are reset */
230 for(i=0;i<graph->rows;i++) {
231 for(j=0;j<graph->cols;j++) {
232 if (Mat_dense(*graph,i,j))
233 if (Mat(int,*graph,i,j)<0) Mat(int,*graph,i,j)=1;
237 if (removezerocosts==1)
239 if (strlen(p_zeronodes)>0)
240 { strncpy(TEMPp_zeronodes,p_zeronodes,strlen(p_zeronodes)-1);
241 printf("select_nodes_labels([%s])\n",TEMPp_zeronodes);
243 strcpy(TEMPp_zeronodes,"");
244 strcpy(p_zeronodes,"");
249 static char *printCompressNode(int node, object_cost *ptr) {
250 char name[MAX_FUNNAME+20];
251 char comp[MAX_FUNNAME+20];
252 char comm[MAX_FUNNAME+20];
253 static char res[(MAX_FUNNAME+20)*4];
254 char tempstring[MAX_FUNNAME+20];
257 char delimiter[] = "&";
259 if (symbol_table[node].type==CG_SSTEP)
260 sprintf(name,"%d %s",
261 symbol_table[node].lineno,symbol_table[node].filename);
264 strcpy(tempstring,symbol_table[node].filename);
265 sprintf(name,"%s",strtok(tempstring,delimiter));
269 /* changed this for GHC stats */
270 sprintf(comp,"\\nTime %6.2fticks\\n",ptr->comm_max);
271 sprintf(comm,"Bytes %6.2funits",ptr->comp_idle_max);
273 sprintf(comp,"\\nTime %6.2f%%\\n",(ptr->comm_max/TotalComm)*100.0);
274 sprintf(comm,"Bytes %6.2f%%",(ptr->comp_idle_max/TotalCompIdle)*100.0);
276 /* Slightly arbitrary choice for max display length of CC string */
277 /* If it is larger than this the display nodes look bad */
278 if (strlen(name)>20) name[20]='\0';
280 if (((20-(strlen(name)+3))/2)>19)
281 padding = extra_space(0);
283 padding = extra_space((20-(strlen(name)+3))/2); /* includes \\n */
291 static char *printUncompressNode(int node, object_cost *ptr) {
292 char name [MAX_FUNNAME+40];
293 char module [MAX_FUNNAME+40];
294 char group [MAX_FUNNAME+40];
295 char syncs[MAX_FUNNAME+40];
296 char head [MAX_FUNNAME+40];
297 char comp [MAX_FUNNAME+40];
298 char comm [MAX_FUNNAME+40];
299 char wait [MAX_FUNNAME+40];
300 char hrel [MAX_FUNNAME+40];
301 char tempstring[MAX_FUNNAME+20];
302 char tempstring2[MAX_FUNNAME+20];
305 char tempstring4[MAX_FUNNAME+20];
306 char delimiter[] = "&";
309 static char res[(MAX_FUNNAME+40)*7];
313 if (symbol_table[node].type==CG_SSTEP)
314 sprintf(name,"%s line %d\\n",
315 symbol_table[node].filename,symbol_table[node].lineno);
318 strcpy(tempstring,symbol_table[node].filename);
319 strcpy(tempstring2,symbol_table[node].filename);
320 sprintf(name,"%s",strtok(tempstring,delimiter));
321 strcpy(tempstring4,tempstring2);
322 tempstring5 = strpbrk(tempstring4,delimiter);
323 sprintf(module,"%s",strtok(tempstring5+1,delimiter));
324 tempstring3 = strrchr(tempstring2,'&');
325 sprintf(group,"%s",tempstring3+1);
331 sprintf(head, "Metric Total \\n");
332 sprintf(comp, " Time %6.2ft \\n",ptr->comm_max);
333 sprintf(comm, " Bytes %6.2fu \\n",ptr->comp_idle_max);
334 sprintf(wait, " SCC %6.2fc \\n",ptr->comp_max);
339 sprintf(head, "Metric Total \\n");
340 sprintf(comp, " Time %5.1f%% \\n",100.0*SAFEDIV(ptr->comm_max,TotalComm));
341 sprintf(comm, " Bytes %5.1f%% \\n",100.0*SAFEDIV(ptr->comp_idle_max,TotalCompIdle));
342 sprintf(wait, " SCC %5.1f%% \\n",100.0*SAFEDIV(ptr->comp_max,TotalComp));
346 if ((x=strlen(name))>width) width=x;
347 if ((x=strlen(hrel))>width) width=x;
348 padding = extra_space((width-strlen(name)+3)/2); /* includes \\n */
349 /* strcpy(res,padding); */
350 strcpy(res,"Cost centre: ");
353 strcat(res,"Module : ");
356 strcat(res,"Group : ");
358 strcat(res,"\\n\\n");
360 /* padding = extra_space((width-strlen(syncs)+3)/2); */
361 //strcat(res,padding);
367 /* strcat(res,hrel); */
372 double nodeColour(object_cost *cost) {
374 switch (CriticalPath + CriticalType) {
375 case CRITTYPE_ABSOLUTE+CRITICAL_SYNCS:
376 case CRITTYPE_ABSDELTA+CRITICAL_SYNCS:
377 case CRITTYPE_RELDELTA+CRITICAL_SYNCS:
378 case CRITTYPE_WEIGHTDELTA+CRITICAL_SYNCS:
379 return SAFEDIV(((double)cost->syncs),((double)this_syncs));
381 case CRITTYPE_ABSOLUTE+CRITICAL_COMP:
382 return SAFEDIV(cost->comp_max,this_total_comp_max);
384 case CRITTYPE_ABSOLUTE+CRITICAL_COMM:
385 return SAFEDIV(cost->comm_max,this_total_comm_max);
387 case CRITTYPE_ABSOLUTE+CRITICAL_WAIT:
388 return SAFEDIV(cost->comp_idle_max,this_total_comp_idle_max);
390 case CRITTYPE_ABSOLUTE+CRITICAL_HREL:
391 return SAFEDIV(((double) cost->hrel_max),((double)this_hrel_max));
393 case CRITTYPE_ABSDELTA+CRITICAL_COMP:
394 return SAFEDIV(cost->comp_max,TotalComp);
396 case CRITTYPE_ABSDELTA+CRITICAL_COMM:
397 return SAFEDIV(cost->comm_max,TotalComm);
399 case CRITTYPE_ABSDELTA+CRITICAL_WAIT:
400 return SAFEDIV(cost->comp_idle_max,TotalCompIdle);
402 case CRITTYPE_ABSDELTA+CRITICAL_HREL:
403 return SAFEDIV(((double) (cost->hrel_max - cost->hrel_avg)),
404 ((double) (this_hrel_max-this_hrel_avg)));
406 case CRITTYPE_RELDELTA+CRITICAL_COMP:
407 return SAFEDIV((cost->comp_max-cost->comp_avg),
408 (cost->comp_avg*DeltaNormalise));
410 case CRITTYPE_RELDELTA+CRITICAL_COMM:
411 return SAFEDIV((cost->comm_max-cost->comm_avg),
412 (cost->comm_avg*DeltaNormalise));
414 case CRITTYPE_RELDELTA+CRITICAL_WAIT:
415 return SAFEDIV((cost->comp_idle_max-cost->comp_idle_avg),
416 (cost->comp_idle_avg*DeltaNormalise));
418 case CRITTYPE_RELDELTA+CRITICAL_HREL:
419 return SAFEDIV(((double) (cost->hrel_max - cost->hrel_avg)),
420 ((double) (cost->hrel_avg*DeltaNormalise)));
422 case CRITTYPE_WEIGHTDELTA+CRITICAL_COMP:
423 return (SAFEDIV((cost->comp_max-cost->comp_avg),
424 (cost->comp_avg*DeltaNormalise))*
425 SAFEDIV(cost->comp_max,this_total_comp_max));
427 case CRITTYPE_WEIGHTDELTA+CRITICAL_COMM:
428 return (SAFEDIV((cost->comm_max-cost->comm_avg),
429 (cost->comm_avg*DeltaNormalise))*
430 SAFEDIV(cost->comm_max,this_total_comm_max));
432 case CRITTYPE_WEIGHTDELTA+CRITICAL_WAIT:
433 return (SAFEDIV((cost->comp_idle_max-cost->comp_idle_avg),
434 (cost->comp_idle_avg*DeltaNormalise))*
435 SAFEDIV(cost->comp_idle_max,this_total_comp_idle_max));
437 case CRITTYPE_WEIGHTDELTA+CRITICAL_HREL:
438 return (SAFEDIV(((double) (cost->hrel_max - cost->hrel_avg)),
439 ((double) (cost->hrel_avg*DeltaNormalise)))*
440 SAFEDIV(((double) cost->hrel_max),((double)this_hrel_max)));
446 int percentToColour(double colour) {
447 int range=255,base=0;
453 if (colour>1.0) return (base+range);
454 else if (colour<0.0) return base;
455 else return (((int) (((double)range)*colour))+base);
458 /* -----------------------------------------------------------------------------
459 * Recursively draw the graph
460 * -------------------------------------------------------------------------- */
462 static void recur_graphToDaVinci(int node,Matrix *graph,Matrix *costs,char* p_zeronodes, int mode){
464 int i,j,no_children=0,*children,colour;
466 char tempnode[MAX_FUNNAME];
467 if (Mat(int,*graph,node,node)<0) {
468 printf("r(\"%d\") ",node);
470 for(i=0;i<graph->cols;i++)
471 if (node!=i && Mat_dense(*graph,node,i)) no_children++;
474 children = calloc(no_children,sizeof(int));
475 if (children==NULL) {
476 fprintf(stderr,"{printDaVinci} unable to allocate %d ",no_children);
479 for((i=0,j=0);i<graph->cols;i++)
480 if (node!=i && Mat_dense(*graph,node,i)) children[j++]=i;
482 qsort(children,no_children,sizeof(int),
483 (int (*)(const void *,const void *)) cmp_symbol_entry);
485 ptr = &Mat(object_cost,*costs,node,0);
486 node_str=(NodeviewCompress)?
487 printCompressNode(node,ptr):
488 printUncompressNode(node,ptr);
489 printf("l(\"%d\",n(\"\",[a(\"OBJECT\",\"%s\"),",node,node_str);
490 printf("a(\"FONTFAMILY\",\"courier\"),");
493 // hide the CAF:REPOSITORY as default
494 if (!strncmp(node_str,"Cost centre: CAF:REPOSITORY",26))
495 printf("a(\"HIDDEN\",\"true\"),"); // when uncompressed
496 if (!strncmp(node_str," CAF:REPOSITORY",12))
497 printf("a(\"HIDDEN\",\"true\"),"); // when compressed
502 if ((ptr->comm_max+ptr->comp_idle_max+ptr->comp_max) <= 0.0)
503 printf("a(\"HIDDEN\",\"true\"),");
505 //for pruning all zero-cost nodes
508 if ((ptr->comm_max+ptr->comp_idle_max+ptr->comp_max) <= 0.0)
509 { fprintf(logFile,"Node %d %s is a candidate for deletion\n",node, node_str);
510 sprintf(tempnode,"\"%d\",",node);
511 strcat(p_zeronodes,tempnode);
515 colour=percentToColour(1.0-nodeColour(ptr));
516 printf("a(\"COLOR\",\"#ff%.2x%.2x\")",colour,colour);
518 Mat(int,*graph,node,node)=-1;
519 for(i=0;i<no_children;i++) {
521 printf("e(\"%d->%d\",[],",node,children[i]);
523 recur_graphToDaVinci(children[i],graph,costs,p_zeronodes,mode);
525 if (i<(no_children-1)) {printf(",");}
533 static void recur_graphToDaVinci_old(int node,Matrix *graph, Matrix *costs) {
535 int i,j,no_children=0,*children,colour;
537 if (Mat(int,*graph,node,node)<0) {
538 fprintf(logFile,"r(\"%d\") ",node);
539 printf("r(\"%d\") ",node);
541 for(i=0;i<graph->cols;i++)
542 if (node!=i && Mat_dense(*graph,node,i)) no_children++;
545 children = calloc(no_children,sizeof(int));
546 if (children==NULL) {
547 fprintf(stderr,"{printDaVinci} unable to allocate %d ",no_children);
550 for((i=0,j=0);i<graph->cols;i++)
551 if (node!=i && Mat_dense(*graph,node,i)) children[j++]=i;
553 qsort(children,no_children,sizeof(int),
554 (int (*)(const void *,const void *)) cmp_symbol_entry);
556 ptr = &Mat(object_cost,*costs,node,0);
557 node_str=(NodeviewCompress)?
558 printCompressNode(node,ptr):
559 printUncompressNode(node,ptr);
560 fprintf(logFile,"l(\"%d\",n(\"\",[a(\"OBJECT\",\"%s\"),",node,node_str);
561 printf("l(\"%d\",n(\"\",[a(\"OBJECT\",\"%s\"),",node,node_str);
562 fprintf(logFile,"a(\"FONTFAMILY\",\"courier\"),");
563 printf("a(\"FONTFAMILY\",\"courier\"),");
564 if (symbol_table[node].type==CG_SSTEP)
565 printf("a(\"BORDER\",\"double\"),");
567 //if (prune subgraphs of zero cost node)
568 // minNodeSize hardwired
569 if ((ptr->comm_max+ptr->comp_idle_max+ptr->comp_max) < minNodeSize)
570 printf("a(\"HIDDEN\",\"true\"),");
572 //if ((ptr->comm_max+ptr->comp_idle_max+ptr->comp_max) < 0.01)
577 colour=percentToColour(1.0-nodeColour(ptr));
579 fprintf(logFile,"a(\"COLOR\",\"#ff%.2x%.2x\")",colour,colour);
580 printf("a(\"COLOR\",\"#ff%.2x%.2x\")",colour,colour);
582 // printf("a(\"COLOR\",\"yellow\"),");
583 fprintf(logFile,"],[");
585 Mat(int,*graph,node,node)=-1;
586 for(i=0;i<no_children;i++) {
589 fprintf(logFile,"e(\"%d->%d\",[],",node,children[i]);
590 printf("e(\"%d->%d\",[],",node,children[i]);
592 // printf("e(\"%d->%d\",[a(\"EDGECOLOR\",\"yellow\")],",node,children[i]);
594 recur_graphToDaVinci_old(children[i],graph,costs);
595 fprintf(logFile,")");
597 if (i<(no_children-1)) {fprintf(logFile,","); printf(",");}
599 fprintf(logFile,"]))");
605 /* -----------------------------------------------------------------------------
607 * -------------------------------------------------------------------------- */
609 void updateColours(int root, Matrix *graph, Matrix *costs) {
612 printf("graph(change_attr([");
613 for(last=costs->rows-1;last>=0;last--)
614 if (Mat_dense(*graph,last,last)) break;
616 for(i=0;i<costs->rows;i++) {
617 if (Mat_dense(*graph,i,i)) {
618 colour = percentToColour(1.0-nodeColour(&Mat(object_cost,*costs,i,0)));
619 printf("node(\"%d\",[a(\"COLOR\",\"#ff%.2x%.2x\")])",
621 if (i<last) printf(",");
627 /* -----------------------------------------------------------------------------
628 * Parse answer from daVinci
629 * -------------------------------------------------------------------------- */
631 davinciCmd parseDaVinciCmd(char *input) {
638 for(crp=input;*crp;crp++)
639 if (*crp==',') result.size++;
642 word = parse_word(&crp);
643 if (Verbose) fprintf(logFile,"{parseDaVinciCmd}=%s size=%d\n",word,result.size);
644 if (strcmp(word,"node_selections_labels")==0) {
645 result.type=DAVINCI_NODE;
646 result.list =calloc(result.size,sizeof(char*));
647 if (result.list==NULL) {
648 fprintf(stderr,"{parseDaVinciCmd} failed to allocate storage");
653 word = parse_quoted(&crp);
654 result.list[i++] = dup_str(word);
655 while (*crp++==',') {
656 word = parse_quoted(&crp);
657 result.list[i++] = dup_str(word);
659 } else if (strcmp(word,"icon_selection")==0) {
660 result.type=DAVINCI_ICON;
661 result.list =calloc(result.size,sizeof(char*));
662 if (result.list==NULL) {
663 fprintf(stderr,"{parseDaVinciCmd} failed to allocate storage");
668 word = parse_quoted(&crp);
669 result.list[i++] = dup_str(word);
670 } else if (strcmp(word,"tcl_answer")==0) {
671 result.type=DAVINCI_TCL;
672 result.list =calloc(result.size,sizeof(char*));
673 if (result.list==NULL) {
674 fprintf(stderr,"{parseDaVinciCmd} failed to allocate storage");
679 word = parse_quoted(&crp);
680 result.list[i++] = dup_str(word);
681 } else if (strcmp(word,"menu_selection")==0) {
682 result.type=DAVINCI_MENU;
683 result.list =calloc(result.size,sizeof(char*));
684 if (result.list==NULL) {
685 fprintf(stderr,"{parseDaVinciCmd} failed to allocate storage");
690 word = parse_quoted(&crp);
691 result.list[i++] = dup_str(word);
692 }else if (strcmp(word,"node_double_click")==0) {
693 result.type=DAVINCI_OK;
694 } else if (strcmp(word,"edge_selection_labels")==0) {
695 result.type=DAVINCI_OK;
696 } else if (strcmp(word,"ok")==0) {
697 result.type=DAVINCI_OK;
698 } else if (strcmp(word,"quit")==0) {
699 result.type=DAVINCI_QUIT;
701 result.type=DAVINCI_ERROR;
706 /* -----------------------------------------------------------------------------
708 * -------------------------------------------------------------------------- */
711 /* Function that returns a string containing \texttt{x} spaces. */
712 static char* extra_space(int x) {
713 static char space[MAX_FUNNAME+1];
716 if (Verbose) fprintf(logFile,"Padding is %d\n",x);
717 for(i=0;(i<x)&&(i<MAX_FUNNAME);i++) space[i]=' ';
723 static char *parse_word(char **crp) {
724 static char result[MAX_FUNNAME];
727 while(islower(**crp) || **crp=='_') {
735 static char *parse_quoted(char **crp) {
736 static char result[MAX_FUNNAME];
740 while (**crp != '\"') {
750 static char *dup_str(char *xs) {
753 if (xs==NULL) return NULL;
755 result = malloc(strlen(xs)+1);
757 fprintf(stderr,"{dup_str}: unable to allocate bytes");