+ return completionSymbolName(text, state);
+}
+
+char *completionCmdDelUserBp(const char *text, int state)
+{
+ static breakp *bp;
+ static int k;
+
+ if (state == 0)
+ {
+ if (completionHelper_GetCurrTokenNumber() != 1)
+ return NULL;
+
+ if (!userBpPresent)
+ return NULL;
+
+ bp = hTabFirstItem(bptable,&k);
+ }
+ else
+ bp = hTabNextItem(bptable,&k);
+
+ for ( ; bp ; bp = hTabNextItem(bptable,&k))
+ {
+ if (bp->bpType == USER || bp->bpType == TMPUSER)
+ {
+ char buff[20];
+ sprintf(buff, "%d", bp->bpnum);
+ return strdup(buff);
+ }
+ }
+
+ return NULL;
+}
+
+// readline completion function for "undisplay" command
+char *completionCmdUnDisplay(const char *text, int state)
+{
+ static dsymbol *dsym;
+
+ if (state == 0)
+ {
+ if (completionHelper_GetCurrTokenNumber() != 1)
+ return NULL;
+ dsym = setFirstItem(dispsymbols);
+ }
+
+ if (dsym)
+ {
+ char buff[30];
+ sprintf(buff, "%d", dsym->dnum);
+ dsym = setNextItem(dispsymbols);
+ return strdup(buff);
+ }
+ return NULL;
+}
+
+char *completionCmdSetUserBp(const char *text, int state)
+{
+ static int internal_state; // 0=calling completionFunctionName(text, state, 0)
+ // 1=calling completionFunctionName(text, 1, 1)
+ if (state == 0)
+ {
+ if (completionHelper_GetCurrTokenNumber() != 1)
+ return NULL;
+
+ internal_state = 0;
+ }
+ if (internal_state == 0)
+ {
+ char *p = completionFunctionName(text, state, 0);
+ if (p)
+ return p;
+ internal_state = 1;
+ return completionFunctionName(text, 0, 1);
+ }
+ else
+ {
+ return completionFunctionName(text, 1, 1);
+ }
+}
+
+char *completionCmdSetOption(const char *text, int state)
+{
+ static char *ptr;
+ static int currtok;
+
+ if (state == 0)
+ {
+ int start,end;
+
+ currtok = completionHelper_GetCurrTokenNumber();
+
+ if (currtok == 2 || currtok == 3)
+ {
+ // make sure token 1 == "variable"
+ completionHelper_GetTokenNumber(1, &start, &end);
+ if (end - start != 8 ||
+ strncmp(rl_line_buffer+start,"variable",8))
+ return NULL;
+ }
+ else if (currtok != 1)
+ {
+ return NULL;
+ }
+ }
+
+ switch (currtok)
+ {
+ case 1:
+ return completionCompleteFromStrList(text, state,
+#ifdef SDCDB_DEBUG
+ "debug\0"
+#endif
+ "srcmode\0listsize\0variable\0");
+ case 2:
+ return completionSymbolName(text, state);
+
+ case 3:
+ return completionCompleteFromStrList(text, state, "=\0");
+ }
+}
+
+// our main readline completion function
+// calls the other completion functions as needed.
+char *completionMain(const char *text, int state)
+{
+ static rl_compentry_func_t *compl_func;
+ int i, start, end, len;
+
+ if (state == 0) // new completion?
+ {
+ compl_func = NULL;
+
+ if (completionHelper_GetCurrTokenNumber() == 0)
+ compl_func = &completionCommandsList;
+ else
+ { // not completing first token, find the right completion
+ // function according to the first token the user typed.
+ completionHelper_GetTokenNumber(0, &start, &end);
+ len = end-start;
+
+ for (i=0; i < (sizeof(cmdTab)/sizeof(struct cmdtab)) ; i++)
+ {
+ if (!strncmp(rl_line_buffer+start,cmdTab[i].cmd,len) &&
+ cmdTab[i].cmd[len] == '\0')
+ {
+ compl_func = cmdTab[i].completion_func;
+ break;
+ }
+ }
+ }
+ if (!compl_func)
+ return NULL;
+ }
+
+ return (*compl_func)(text,state);
+}
+#endif /* HAVE_READLINE_COMPLETITION */
+
+/*-----------------------------------------------------------------*/
+/* commandLoop - the main command loop or loop over command file */
+/*-----------------------------------------------------------------*/
+static void commandLoop(FILE *cmdfile)
+{
+ char *line, save_ch, *s;
+ char *line_read;
+
+#ifdef HAVE_LIBREADLINE
+ FILE *old_rl_instream, *old_rl_outstream;
+ actualcmdfile = cmdfile;
+
+#ifdef HAVE_READLINE_COMPLETITION
+ rl_completion_entry_function = completionMain;
+#endif /* HAVE_READLINE_COMPLETITION */
+ rl_readline_name = "sdcdb"; // Allow conditional parsing of the ~/.inputrc file.
+
+ // save readline's input/output streams
+ // this is done to support nested calls to commandLoop()
+ // i wonder if it works...
+ old_rl_instream = rl_instream;
+ old_rl_outstream = rl_outstream;
+
+ // set new streams for readline
+ if ( cmdfile == stdin )
+ rl_instream = rl_outstream = NULL; // use stdin/stdout pair
+ else
+ rl_instream = rl_outstream = cmdfile;
+
+ while (1)
+ {
+ if ( cmdfile == stdin )
+ {
+ if (sim_cmd_mode)
+ line_read = (char*)readline ("(sim) ");
+ else
+ line_read = (char*)readline ("(sdcdb) ");
+ }
+ else
+ line_read = (char*)readline ("");
+
+ if (line_read)
+ {
+ /* If the line has any text in it,
+ save it on the history. */
+ if (line_read && *line_read)
+ add_history (line_read);
+
+ // FIX: readline returns malloced string.
+ // should check the source to verify it can be used
+ // directly. for now - just copy it to cmdbuff.
+ strcpy(cmdbuff,line_read);
+#if defined(_WIN32) || defined(HAVE_RL_FREE)
+ rl_free(line_read);
+#else
+ free(line_read);
+#endif
+ line_read = NULL;
+ }
+ else
+ break; // EOF
+#else
+ actualcmdfile = cmdfile;
+
+ while (1)
+ {
+ if ( cmdfile == stdin )
+ {
+ if (sim_cmd_mode)
+ printf("(sim) ");
+ else
+ fprintf(stdout,"(sdcdb) ");
+ fflush(stdout);
+ }
+ //fprintf(stderr,"commandLoop actualcmdfile=%p cmdfile=%p\n",
+ // actualcmdfile,cmdfile);
+ if (fgets(cmdbuff,sizeof(cmdbuff),cmdfile) == NULL)
+ break;
+#endif /* HAVE_LIBREADLINE */
+
+ if (interpretCmd(cmdbuff))
+ break;
+
+ while ( actualcmds )
+ {
+ strcpy(cmdbuff,actualcmds);
+ actualcmds = NULL;
+ stopcmdlist= 0;
+ for ( line = cmdbuff; *line ; line = s )
+ {
+ if ( (s=strchr(line ,'\n')))
+ {
+ save_ch = *++s;
+ *s = '\0';
+ }
+ else
+ {
+ s += strlen( line );
+ save_ch = '\0';
+ }
+ if (interpretCmd( line ))
+ {
+ *s = save_ch;
+ break;
+ }
+ *s = save_ch;
+ if ( stopcmdlist )
+ break;
+ }
+ }
+ }
+#ifdef HAVE_LIBREADLINE
+ // restore readline's input/output streams
+ rl_instream = old_rl_instream;
+ rl_outstream = old_rl_outstream;
+#endif /* HAVE_LIBREADLINE */