diff --git a/src/db/atdb.c b/src/db/atdb.c index 25be97983..e06999a39 100644 --- a/src/db/atdb.c +++ b/src/db/atdb.c @@ -1,5 +1,5 @@ /*atodb.c*/ -/* share/src/db $Id$ */ +/* base/src/db $Id$ */ /* * * Author: Marty Kraimer diff --git a/src/db/callback.c b/src/db/callback.c index deb6630f6..6147aa02c 100644 --- a/src/db/callback.c +++ b/src/db/callback.c @@ -1,5 +1,5 @@ /* callback.c */ -/* share/src/db $Id$ */ +/* base/src/db $Id$ */ /* general purpose callback tasks */ /* diff --git a/src/db/dbBkpt.c b/src/db/dbBkpt.c new file mode 100644 index 000000000..d613c9672 --- /dev/null +++ b/src/db/dbBkpt.c @@ -0,0 +1,997 @@ +/* dbBkpt.c */ +/* base/src/db $Id$ */ +/* + * Author: Matthew Needes + * Date: 8-30-93 + * + * Experimental Physics and Industrial Control System (EPICS) + * + * Copyright 1991, the Regents of the University of California, + * and the University of Chicago Board of Governors. + * + * This software was produced under U.S. Government contracts: + * (W-7405-ENG-36) at the Los Alamos National Laboratory, + * and (W-31-109-ENG-38) at Argonne National Laboratory. + * + * Initial development by: + * The Controls and Automation Group (AT-8) + * Ground Test Accelerator + * Accelerator Technology Division + * Los Alamos National Laboratory + * + * Co-developed with + * The Controls and Computing Group + * Accelerator Systems Division + * Advanced Photon Source + * Argonne National Laboratory + * + * Modification Log: + * ----------------- + */ + +/* + * Database Breakpoint Manipulation and User Interface + * + * USER COMMANDS + * dbb(record_name) Set a breakpoint in a record + * dbd(record_name) Delete a record's breakpoint + * dbc(record_name) Resume record processing + * dbs(record_name) Step through record processing through + * IO links, forward process links, etc. + * dbstat() Display status of stopped records in lock sets. + * dbap(record_name) Toggle automatic print after processing. + * dbp(record_name) Print out fields from record currently stopped. + * dbprc(record_name) Processes a record once without printing it. + * (Unless autoprint is on) + * + * INTERNAL FUNCTIONS + * dbBkpt() Process breakpoints, called by dbProcess(). + * dbPrint() Prints record if autoprint enabled. + * dbBkptCont() The task that continues and steps through + * records that are stopped at a breakpoint. + */ + +/* #define BKPT_DIAG */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* private routines */ +static void remove_lset_from_stack(); +static void dbBkptCont(); +static long FIND_CONT_NODE(); + +/* + * Breakpoints are used as a debugging instrument to suspend the + * processing of database records. Once suspended, record + * processing may continue if either a continue (dbc()) or a + * step (dbs()) command is then issued. The current record's + * contents may be printed either with dbp(), or immediately + * after processing (use dbap() to toggle the BKPT_PRINT bit). + * + * dbb() and dbd() add a breakpoint to a record or delete one + * from a record. dbstat() prints out comprehensive breakpoint + * status information. + * + * Breakpoints may be set on a per lockset basis. When a + * breakpoint is set in a lockset, a new task is created. A + * separate task gets created for _every_ lockset containing + * a breakpoint. Thus multiple locksets may be debugged + * simultaneously. The breakpoint handler then schedules future + * processing in that lockset to this task. The separate task is + * used so that locksets that do not have breakpoints are isolated + * from locksets that do. This allows the processing of other + * locksets to continue uninterupted, even if they exist on the same + * scan list as a lockset containing a breakpoint. + * + * An entrypoint is the first record that gets processed in a lockset. + * This type of record is the basis for subsequent recursive executions + * of dbProcess(). The breakpoint handler monitors and schedules + * these entrypoints to the breakpoint tasks. + * + * Two hooks have been inserted in dbProcess() to manage breakpoints, + * dbBkpt() and dbPrint(). The former does two things: + * + * 1. Schedule entrypoints with the breakpoint task. + * 2. Suspend record processing when a breakpoint is detected. + * + * 1 occurs only if dbProcess() is called outside of the breakpoint + * task. Number 2 only occurs when dbProcess() is called from + * _within_ the breakpoint task's context. Number 1 is used for + * detection and scheduling, while 2 is used for suspending the task. + * + * The dbPrint() hook is used to print out a record's contents immediately + * _after_ a record has been processed. + * + * The dbBkptCont, or breakpoint task, pends on a semaphore that gets + * released whenever new entrypoints are scheduled for it. When + * released, this task then runs down its entrypoint queue and + * processes each entrypoint in turn. In this context, dbProcess + * will execute the dbBkpt() hook in mode 2, allowing this task to + * be suspended whenever a breakpoint is detected. + * + * NOTE: This is not a very "real-time" implementation (even for those + * locksets not containing a breakpoint). I may fix this later. + * + * Final comment: The scary thing is, I don't think this can be done + * more simply... + * + */ + +/* + * Flag used by dbProcess() to determine if there are + * any breakpoints. This is so that there is only + * a single comparison in the critical path during + * normal record execution, i.e. when there aren't + * any breakpoints set. + */ +long lset_stack_not_empty = 0; + +/* + * Stack--in which each entry represents a different + * lock set with either breakpoints and/or stopped + * execution. (Breakpoints may be disabled even + * though execution is stopped). The order of the + * list is maintained so that the entry on the top + * of stack is used as a default for dbc() and dbs(). + * The semaphore is used to prevent conflicts while + * operating with this stack. + */ +static LIST lset_stack; +static SEM_ID bkpt_stack_sem; + +/* + * Stores the last lockset continued or stepped from. + * dbs() and dbc() will print a message if the current + * lockset to be continued from differs from this + * variable. + */ +static short last_lset = 0; + +/* + * FIND_LOCKSET() finds the stack entry + * whose l_num field matches precord's + * lset field. The node that is found + * is returned in "pnode." + */ +#define FIND_LOCKSET(precord, pnode) \ + pnode = (struct LS_LIST *) lstFirst(&lset_stack); \ + while ((pnode) != NULL) { \ + if ((pnode)->l_num == (precord)->lset) break; \ + pnode = (struct LS_LIST *) lstNext((NODE *)pnode); \ + } \ + +/* + * FIND_QUEUE_ENTRY() matches entries in an + * entry point queue. pep_queue is the queue + * being searched, pqe is the pointer to the + * queue entry found, and precord is the record + * being searched for in *pep_queue. + */ +#define FIND_QUEUE_ENTRY(pep_queue, pqe, precord) \ + pqe = (struct EP_LIST *) lstFirst(pep_queue); \ + while ((pqe) != NULL) { \ + if ((pqe)->entrypoint == (precord)) break; \ + pqe = (struct EP_LIST *) lstNext((NODE *)pqe); \ + } \ + +/* + * Fills out pnode and precord structures for dbc() and dbs() + * MUST LOCK OUT STACK BEFORE ENTRY + */ +static long FIND_CONT_NODE( + char *record_name, + struct LS_LIST **ppnode, + struct dbCommon **pprecord) +{ + struct dbAddr addr; + struct LS_LIST *pnode; + struct dbCommon *precord = NULL; + long status = 0; + + if (record_name == NULL) { + /* + * Search through stack, taking the first entry that + * is currently stopped at a breakpoint. + */ + pnode = (struct LS_LIST *) lstFirst(&lset_stack); + while (pnode != NULL) { + if (pnode->precord != NULL) { + precord = pnode->precord; + break; + } + pnode = (struct LS_LIST *) lstNext((NODE *)pnode); + } + + if (pnode == NULL) { + printf(" BKPT> No records are currently stopped\n"); + return(S_db_notStopped); + } + } + else { + /* + * Convert name to address + */ + status = dbNameToAddr(record_name, &addr); + if (status == S_db_notFound) + printf(" BKPT> Record %s not found\n", record_name); + if (status != 0) + return(status); + + precord = addr.precord; + + FIND_LOCKSET(precord, pnode); + + if (pnode == NULL || pnode->precord == NULL) { + printf(" BKPT> Currently not stopped in this lockset\n"); + return(S_db_notStopped); + } + } + + *pprecord = precord; + *ppnode = pnode; + return(0); +} + + +/* + * Add breakpoint to a lock set + * 1. Convert name to address and check breakpoint mask. + * 2. Lock database. + * 3. If empty, initialize lock set stack and its semaphore. + * 4. Take that semaphore. + * 5. Find lockset in the list. If it doesn't exist, create it. + * 6. Turn on breakpoint field in record. + * 7. Add breakpoint to list of breakpoints in structure. + * 8. Spawn continuation task if it isn't already running. + */ +long dbb(char *record_name) +{ + struct dbAddr addr; + struct LS_LIST *pnode; + struct BP_LIST *pbl; + struct dbCommon *precord; + long status; + + /* + * Convert name to address + */ + status = dbNameToAddr(record_name, &addr); + if (status == S_db_notFound) + printf(" BKPT> Record %s not found\n", record_name); + if (status != 0) return(status); + + precord = addr.precord; + + if (precord->bkpt & BKPT_ON_MASK) { + printf(" BKPT> Breakpoint already set in this record\n"); + return(S_db_bkptSet); + } + + dbScanLock(precord); + + /* + * Add lock set to the stack of lock sets that + * contain breakpoints and/or stopped records. + */ + if (! lset_stack_not_empty) { + /* initialize list and semaphore */ + bkpt_stack_sem = semBCreate(SEM_Q_FIFO, SEM_FULL); + if (bkpt_stack_sem == NULL) { + printf(" BKPT> Out of memory\n"); + dbScanUnlock(precord); + return(1); + } + lstInit(&lset_stack); + lset_stack_not_empty = 1; + } + + semTake(bkpt_stack_sem, WAIT_FOREVER); + + FIND_LOCKSET(precord, pnode); + + if (pnode == NULL) { + /* lockset not found, create node, add to end of list */ + pnode = (struct LS_LIST *) malloc(sizeof(struct LS_LIST)); + if (pnode == NULL) { + printf(" BKPT> Out of memory\n"); + dbScanUnlock(precord); + semGive(bkpt_stack_sem); + return(1); + } + pnode->precord = NULL; + + /* initialize breakpoint list */ + lstInit(&pnode->bp_list); + + /* initialize entry point queue */ + lstInit(&pnode->ep_queue); + + /* create execution semaphore */ + pnode->ex_sem = semBCreate(SEM_Q_FIFO, SEM_EMPTY); + if (pnode->ex_sem == NULL) { + printf(" BKPT> Out of memory\n"); + dbScanUnlock(precord); + semGive(bkpt_stack_sem); + return(1); + } + + pnode->taskid = 0; + pnode->step = 0; + pnode->l_num = precord->lset; + lstAdd(&lset_stack, (NODE *)pnode); + } + + /* + * Add record to breakpoint list + */ + pbl = (struct BP_LIST *) malloc(sizeof(struct BP_LIST)); + if (pbl == NULL) { + printf(" BKPT> Out of memory\n"); + dbScanUnlock(precord); + semGive(bkpt_stack_sem); + return(1); + } + pbl->precord = precord; + lstAdd(&pnode->bp_list, (NODE *)pbl); + + /* + * Turn on breakpoint field in record + */ + precord->bkpt |= BKPT_ON_MASK; + + if (! pnode->taskid) { + +#ifdef BKPT_DIAG + printf(" BKPT> Spawning task: %s\n", precord->name); +#endif BKPT_DIAG + /* + * Spawn continuation task + */ + pnode->taskid = taskSpawn(BKPT_CONT_NAME, PERIODSCAN_PRI, BKPT_CONT_OPT, + BKPT_CONT_STACK, (FUNCPTR) dbBkptCont,(int) precord, + 0,0,0,0,0,0,0,0,0); + + if (pnode->taskid == ERROR) { + printf(" BKPT> Cannot spawn task to process record\n"); + pnode->taskid = 0; + dbScanUnlock(precord); + semGive(bkpt_stack_sem); + return(1); + } + } + + semGive(bkpt_stack_sem); + dbScanUnlock(precord); + return(0); +} + +/* + * Remove breakpoint from a record + * 1. Convert name to address and check breakpoint mask. + * 2. Lock database and take stack semaphore. + * 3. Find structure for record's lockset (in stack). + * 4. Find and delete record from breakpoint list. + * 5. Turn off break point field. + * 6. Give up semaphore to "signal" bkptCont task to quit. + */ +long dbd(char *record_name) +{ + struct dbAddr addr; + struct LS_LIST *pnode; + struct BP_LIST *pbl; + struct dbCommon *precord; + long status; + + /* + * Convert name to address + */ + status = dbNameToAddr(record_name, &addr); + if (status == S_db_notFound) + printf(" BKPT> Record %s not found\n", record_name); + if (status != 0) return(status); + + precord = addr.precord; + + if (! precord->bkpt & BKPT_ON_MASK) { + printf(" BKPT> No breakpoint set in this record\n"); + return(S_db_bkptNotSet); + } + + dbScanLock(precord); + + semTake(bkpt_stack_sem, WAIT_FOREVER); + + FIND_LOCKSET(precord, pnode); + + if (pnode == NULL) { + /* not found, error ! */ + printf(" BKPT> Logic Error in dbd()\n"); + precord->bkpt &= BKPT_OFF_MASK; + + semGive(bkpt_stack_sem); + dbScanUnlock(precord); + return(S_db_bkptLogic); + } + + /* + * Remove record from breakpoint list + */ + + /* find record in list */ + pbl = (struct BP_LIST *) lstFirst(&pnode->bp_list); + while (pbl != NULL) { + if (pbl->precord == precord) { + lstDelete(&pnode->bp_list, (NODE *)pbl); + free(pbl); + break; + } + pbl = (struct BP_LIST *) lstNext((NODE *)pbl); + } + + if (pbl == NULL) { + printf(" BKPT> Logic Error in dbd()\n"); + precord->bkpt &= BKPT_OFF_MASK; + semGive(bkpt_stack_sem); + dbScanUnlock(precord); + return(S_db_bkptLogic); + } + + /* + * Turn off breakpoint field in record + */ + precord->bkpt &= BKPT_OFF_MASK; + + /* + * If there are no more breakpoints, give up semaphore + * to cause the bkptCont task to quit. + */ + if (lstCount(&pnode->bp_list) == 0) + semGive(pnode->ex_sem); + + semGive(bkpt_stack_sem); + + dbScanUnlock(precord); + return(0); +} + +/* + * Continue processing in a lock set + * 1. Find top node in the lockset stack. + * 2. Turn off stepping mode. + * 2. Resume dbBkptCont. + */ +long dbc(char *record_name) +{ + struct LS_LIST *pnode; + struct dbCommon *precord = NULL; + long status = 0; + int taskid; + + semTake(bkpt_stack_sem, WAIT_FOREVER); + + status = FIND_CONT_NODE(record_name, &pnode, &precord); + if (status) { + semGive(bkpt_stack_sem); + return(status); + } + + if (record_name == NULL && last_lset != pnode->l_num); + printf(" BKPT> Continuing: %s\n", pnode->precord->name); + + last_lset = pnode->l_num; + + /* + * Turn off stepping mode + */ + pnode->step = 0; + + /* + * Resume dbBkptCont() until dbProcess() is executed + * for a record with a breakpoint. This occurs + * because stepping mode has been switched off. + */ + if (taskResume(pnode->taskid) == ERROR) { + printf(" BKPT> Cannot continue\n"); + semGive(bkpt_stack_sem); + return(S_db_cntCont); + } + + semGive(bkpt_stack_sem); + return(0); +} + +/* + * Step through record processing + * 1. Find top node in lockset stack. + * 2. Resume dbBkptCont. + */ +long dbs(char *record_name) +{ + struct LS_LIST *pnode; + static struct dbAddr addr; + struct dbCommon *precord = NULL; + long status = 0; + + semTake(bkpt_stack_sem, WAIT_FOREVER); + + status = FIND_CONT_NODE(record_name, &pnode, &precord); + if (status) { + semGive(bkpt_stack_sem); + return(status); + } + + if (last_lset != pnode->l_num && record_name == NULL) + printf(" BKPT> Stepping: %s\n", pnode->precord->name); + + last_lset = pnode->l_num; + + if (taskResume(pnode->taskid) == ERROR) { + printf(" BKPT> Cannot step\n"); + semGive(bkpt_stack_sem); + return(S_db_cntCont); + } + + semGive(bkpt_stack_sem); + return(0); +} + +/* + * Task for continuing record processing + * 1. Find lockset in stack for precord. + * DO 2-3 while breakpoints exist in the lockset. + * 2. Wait on execution semaphore ... + * 3. Run through every entrypoint in queue, processing + * those that are scheduled. + * 4. Free resources for lockset, and exit task. + */ +static void dbBkptCont(struct dbCommon *precord) +{ + struct LS_LIST *pnode; + struct EP_LIST *pqe = NULL; + + /* + * Reset breakpoint, process record, and + * reset bkpt field in record + */ + semTake(bkpt_stack_sem, WAIT_FOREVER); + + FIND_LOCKSET(precord, pnode); + + if (pnode == NULL) { + printf(" BKPT> Logic error in dbBkptCont()\n"); + return; + } + + /* + * For every entrypoint scheduled, process. Run process + * until there are no more breakpoints remaining in a + * lock set. + */ + do { + /* Give up semaphore before waiting to run ... */ + semGive(bkpt_stack_sem); + + /* Wait to run */ + semTake(pnode->ex_sem, WAIT_FOREVER); + + /* Bkpt stack must still be stable ! */ + semTake(bkpt_stack_sem, WAIT_FOREVER); + + pqe = (struct EP_LIST *) lstFirst(&pnode->ep_queue); + + /* Run through entrypoint queue */ + while (pqe != NULL) { + /* check if entrypoint is currently scheduled */ + if (pqe->sched) { + /* save current entrypoint */ + pnode->current_ep = pqe->entrypoint; + + /* lock the lockset, process record, unlock */ + dbScanLock(precord); + dbProcess(pqe->entrypoint); + dbScanUnlock(precord); + + /* reset schedule and stepping flag - Do this AFTER processing */ + pqe->sched = 0; + pnode->step = 0; + } + pqe = (struct EP_LIST *) lstNext((NODE *)pqe); + } + + /* Reset precord. (Since no records are at a breakpoint) */ + pnode->precord = NULL; + } + while (lstCount(&pnode->bp_list) != 0); + + /* remove node from lockset stack */ + lstDelete(&lset_stack, (NODE *)pnode); + + /* free entrypoint queue */ + lstFree(&pnode->ep_queue); + + /* remove execution semaphore */ + semDelete(pnode->ex_sem); + + printf("\n BKPT> End debug of lockset %d\n-> ", pnode->l_num); + + /* free list node */ + free(pnode); + + /* if last node on stack ... */ + if (lstCount(&lset_stack) == 0) { + /* Unset flag, delete stack semaphore */ + lset_stack_not_empty = 0; + semDelete(bkpt_stack_sem); + } + + if (lset_stack_not_empty) + semGive(bkpt_stack_sem); +} + +/* + * Process breakpoint + * Returns a zero if dbProcess() is to execute + * record support, a one if dbProcess() is to + * skip over record support. See dbProcess(). + * + * 1. See if there is at least a breakpoint set somewhere + * in precord's lockset. If not, return immediately. + * 2. Check the disable flag. + * 3. Add entry points to the queue for future stepping and + * schedule new entrypoints for the continuation task. + * 4. Check the pact flag. + * 5. Check to see if there is a breakpoint set in a record, and + * if so, turn on stepping mode. + * 6. If stepping mode is set, stop and report the breakpoint. + */ +int dbBkpt(struct dbCommon *precord) +{ + struct LS_LIST *pnode; + struct EP_LIST *pqe; + long nRequest = 1, options = 0; + + /* + * It is crucial that operations in dbBkpt() execute + * in the correct order or certain features in the + * breakpoint handler will not work as expected. + */ + + FIND_LOCKSET(precord, pnode); + + if (pnode == NULL) { + /* no breakpoints in precord's lockset */ + return(0); + } + + /* Check disable flag */ + recGblGetFastLink(&precord->sdis, (void *) precord, &precord->disa); + + if (precord->disa == precord->disv) { + /* + * Do not process breakpoints if the record is disabled, + * but allow disable alarms. Alarms will be raised + * in dbProcess() because returning 0 allows dbProcess() + * to continue. However processing will be prevented + * because disa and disv will be examined again in + * dbProcess(). Note that checking for pact will occur + * before checking for disa and disv in dbProcess(). + */ + return(0); + } + + /* + * Queue entry points for future stepping. The taskid comparison + * is used to determine if the source of processing is the + * continuation task or an external source. If it is an external + * source, queue its execution, but dump out of dbProcess without + * calling record support. + */ + if (pnode->taskid && (taskIdSelf() != pnode->taskid)) { + /* CONTINUE TASK CANNOT ENTER HERE */ + + /* + * Add an entry point to queue, if it does + * not already exist. + */ + FIND_QUEUE_ENTRY(&pnode->ep_queue, pqe, precord); + + if (pqe == NULL) { + + pqe = (struct EP_LIST *) malloc(sizeof(struct EP_LIST)); + if (pqe == NULL) + return(1); + + + pqe->entrypoint = precord; + pqe->count = 1; + pqe->time = tickGet(); + pqe->sched = 0; + +#ifdef BKPT_DIAG + printf(" BKPT> Adding entrypoint %s to queue\n", precord->name); +#endif BKPT_DIAG + + /* + * Take semaphore, wait on continuation task + */ + semTake(bkpt_stack_sem, WAIT_FOREVER); + + /* Add entry to queue */ + lstAdd(&pnode->ep_queue, (NODE *)pqe); + + semGive(bkpt_stack_sem); + } + else { + if (pqe->count < MAX_EP_COUNT) + pqe->count++; + } + + /* check pact */ + if (! precord->pact) { + /* schedule if pact not set */ + pqe->sched = 1; + + /* + * Release the semaphore, letting the continuation + * task begin execution of the new entrypoint. + */ + semGive(pnode->ex_sem); + } + return(1); + } + + /* + * Don't mess with breakpoints if pact set! Skip + * over rest of dbProcess() since we don't want + * alarms going off. The pact flag is checked + * AFTER entry point queuing so that the record + * timing feature will work properly. + */ + if (precord->pact) + return(1); + + /* Turn on stepping mode if a breakpoint is found */ + if (precord->bkpt & BKPT_ON_MASK) { + pnode->step = 1; + +#ifdef BKPT_DIAG + printf(" BKPT> Bkpt detected: %s\n", precord->name); +#endif BKPT_DIAG + } + + /* + * If we are currently stepping through the lockset, + * suspend task. + */ + if (pnode->step) { + printf("\n BKPT> Stopped at: %s within Entrypoint: %s\n-> ", + precord->name, pnode->current_ep->name); + + pnode->precord = precord; + + /* Move current lockset to top of stack */ + lstDelete(&lset_stack, (NODE *)pnode); + lstInsert(&lset_stack, NULL, (NODE *)pnode); + /* + * Unlock database while the task suspends itself. This + * is done so that dbb() dbd() dbc() dbs() may be used + * when the task is suspended. Scan tasks that also + * use the scan lock feature will not be hung during + * a breakpoint, so that records in other locksets will + * continue to be processed. Cross your fingers, this + * might actually work ! + */ + semGive(bkpt_stack_sem); + dbScanUnlock(precord); + taskSuspend(pnode->taskid); + dbScanLock(precord); + semTake(bkpt_stack_sem, WAIT_FOREVER); + } + return(0); +} + +/* print record after processing */ +void dbPrint(struct dbCommon *precord) +{ + struct LS_LIST *pnode; + + if (! (precord->bkpt & BKPT_PRINT_MASK)) + return; + + FIND_LOCKSET(precord, pnode); + + /* do not print if lockset does not currently contain breakpoints */ + if (pnode == NULL) + return; + + printf("\n"); + dbpr(precord->name, 2); + printf("-> "); +} + +/* print stopped record */ +long dbp(char *record_name, int interest_level) +{ + struct LS_LIST *pnode; + struct dbCommon *precord; + int status; + + semTake(bkpt_stack_sem, WAIT_FOREVER); + + /* find pnode and precord pointers */ + status = FIND_CONT_NODE(record_name, &pnode, &precord); + if (status) { + semGive(bkpt_stack_sem); + return(status); + } + + /* print out record's fields */ + dbpr(precord->name, (interest_level == 0) ? 2 : interest_level); + + semGive(bkpt_stack_sem); + return(0); +} + +/* toggle printing after processing a certain record */ +long dbap(char *record_name) +{ + struct dbAddr addr; + struct LS_LIST *pnode; + struct dbCommon *precord; + long status; + + /* + * Convert name to address + */ + status = dbNameToAddr(record_name, &addr); + if (status == S_db_notFound) + printf(" BKPT> Record %s not found\n", record_name); + if (status != 0) return(status); + + precord = addr.precord; + + /* + * Toggle print after process field in record + */ + if (precord->bkpt & BKPT_PRINT_MASK) { + printf(" BKPT> Auto print off for record %s\n", precord->name); + precord->bkpt &= BKPT_PRINT_OFF_MASK; + } + else { + printf(" BKPT> Auto print on for record %s\n", precord->name); + precord->bkpt |= BKPT_PRINT_MASK; + } + + return(0); +} + +/* print list of stopped records, and breakpoints set in locksets */ +long dbstat() +{ + struct LS_LIST *pnode; + struct BP_LIST *pbl; + struct EP_LIST *pqe; + unsigned long time; + int i, j; + + semTake(bkpt_stack_sem, WAIT_FOREVER); + + time = tickGet(); + + /* + * Traverse list, reporting stopped records + */ + pnode = (struct LS_LIST *) lstFirst(&lset_stack); + while (pnode != NULL) { + if (pnode->precord != NULL) { + + printf("LSet: %5.5d Stopped at: %-28.28s #B: %5.5d T: 0x%7.7x\n", + pnode->l_num, pnode->precord->name, lstCount(&pnode->bp_list), pnode->taskid); + + /* for each entrypoint detected, print out entrypoint statistics */ + pqe = (struct EP_LIST *) lstFirst(&pnode->ep_queue); + while (pqe != NULL) { + if (time - pqe->time) { + printf(" Entrypoint: %-28.28s #C: %5.5lu C/S: %7.1lf\n", + pqe->entrypoint->name, pqe->count, + vxTicksPerSecond*pqe->count/((double)(time-pqe->time))); + } + pqe = (struct EP_LIST *) lstNext((NODE *)pqe); + } + } + else { + printf("LSet: %5.5d #B: %5.5d T: 0x%7.7x\n", + pnode->l_num, lstCount(&pnode->bp_list), pnode->taskid); + } + + /* + * Print out breakpoints set in the lock set + */ + pbl = (struct BP_LIST *) lstFirst(&pnode->bp_list); + while (pbl != NULL) { + printf(" Breakpoint: %-28.28s", pbl->precord->name); + + /* display auto print flag */ + if (pbl->precord->bkpt & BKPT_PRINT_MASK) + printf(" (ap)\n"); + else + printf("\n"); + + pbl = (struct BP_LIST *) lstNext((NODE *)pbl); + } + + pnode = (struct LS_LIST *) lstNext((NODE *)pnode); + } + + semGive(bkpt_stack_sem); + return(0); +} + +/* + * Process a record without printing it. + */ +long dbprc(char *record_name) +{ + struct dbAddr addr; + struct dbCommon *precord; + long status; + + /* + * Convert name to address + */ + status = dbNameToAddr(record_name, &addr); + if (status == S_db_notFound) + printf(" BKPT> Record %s not found\n", record_name); + if (status != 0) return(status); + + precord = addr.precord; + + /* lock lockset, process record, unlock lockset */ + dbScanLock(precord); + status = dbProcess(precord); + dbScanUnlock(precord); + + return(status); +} + +#ifdef BKPT_DIAG + +/* Reset breakpoints */ +int dbreset() +{ + semGive(bkpt_stack_sem); + + return(0); +} + +#endif BKPT_DIAG + diff --git a/src/db/dbCaDblink.c b/src/db/dbCaDblink.c index 9a7673798..daa4bf093 100644 --- a/src/db/dbCaDblink.c +++ b/src/db/dbCaDblink.c @@ -1,5 +1,5 @@ /* dbCaDblink.c */ -/* share/src/db $Id$ */ +/* base/src/db $Id$ */ /**************************************************************** * diff --git a/src/db/dbCaLink.c b/src/db/dbCaLink.c index 035579c93..a1d775254 100644 --- a/src/db/dbCaLink.c +++ b/src/db/dbCaLink.c @@ -1,5 +1,5 @@ /* dbCaLink.c */ -/* share/src/db $Id$ */ +/* base/src/db $Id$ */ /**************************************************************** * diff --git a/src/db/dbFastLinkConv.c b/src/db/dbFastLinkConv.c new file mode 100644 index 000000000..69b546a34 --- /dev/null +++ b/src/db/dbFastLinkConv.c @@ -0,0 +1,1276 @@ +/* dbFastLinkConv.c */ +/* base/src/db $Id$ */ +/* + * Author: Matthew Needes + * Date: 12-9-93 + * + * Experimental Physics and Industrial Control System (EPICS) + * + * Copyright 1991, the Regents of the University of California, + * and the University of Chicago Board of Governors. + * + * This software was produced under U.S. Government contracts: + * (W-7405-ENG-36) at the Los Alamos National Laboratory, + * and (W-31-109-ENG-38) at Argonne National Laboratory. + * + * Initial development by: + * The Controls and Automation Group (AT-8) + * Ground Test Accelerator + * Accelerator Technology Division + * Los Alamos National Laboratory + * + * Co-developed with + * The Controls and Computing Group + * Accelerator Systems Division + * Advanced Photon Source + * Argonne National Laboratory + * + * Modification Log: + * ----------------- + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern struct dbBase *pdbBase; + +/* + * In the following functions: + * + * cvt_y_z(ARGS) + * + * converts from type y to type z. If + * type y and z are the same, it merely copies. + * + * where st - string + * c - char + * uc - unsigned char + * s - short + * us - unsigned short + * l - long + * ul - unsigned long + * f - float + * d - double + * e - enum + * + * These functions are _single_ value functions, + * i.e.: do not deal with array types. + */ + +/* + * A DB_LINK that is not initialized with recGblInitFastXXXLink() + * will have this conversion. + */ + +/* Uninitialized Conversion */ +long cvt_uninit( + void *from, + void *to, + struct dbAddr *paddr) +{ + printf("Error in record support, uninitialized link.\n"); + return(-1); +} + +/* + * Dummy Conversion + * In the case of an unsupported conversion, run this + * dummy function instead to avoid a bus error. + */ +long cvt_dummy( + void *from, + void *to, + struct dbAddr *paddr) +{ return(-1); } + +/* Convert String to String */ +static long cvt_st_st( + char *from, + char *to, + struct dbAddr *paddr) + { + char size = paddr->field_size; + + if (size >= MAX_STRING_SIZE) + size = MAX_STRING_SIZE - 1; + + strncpy(to, from, size); + *(to+size) = '\000'; + + return(0); + } + +/* Convert String to Char */ +static long cvt_st_c( + char *from, + char *to, + struct dbAddr *paddr) + { + short value; + + if (sscanf(from, "%hd", &value) == 1) { + *to = (char) value; + return(0); + } + + return(-1); /* Change to SYMBOL */ + } + +/* Convert String to Unsigned Char */ +static long cvt_st_uc( + char *from, + unsigned char *to, + struct dbAddr *paddr) + { + short value; + + if (sscanf(from, "%hu", &value) == 1) { + *to = (unsigned char) value; + return(0); + } + + return(-1); /* Change to SYMBOL */ + } + +/* Convert String to Short */ +static long cvt_st_s( + char *from, + short *to, + struct dbAddr *paddr) + { + short value; + + if (sscanf(from, "%hd", &value) == 1) { + *to = value; + return(0); + } + + return(-1); /* Change to SYMBOL */ + } + +/* Convert String to Unsigned Short */ +static long cvt_st_us( + char *from, + unsigned short *to, + struct dbAddr *paddr) + { + short value; + + if (sscanf(from, "%hu", &value) == 1) { + *to = (unsigned short) value; + return(0); + } + + return(-1); /* Change to SYMBOL */ + } + +/* Convert String to Long */ +static long cvt_st_l( + char *from, + long *to, + struct dbAddr *paddr) + { + long value; + + if (sscanf(from, "%ld", &value) == 1) { + *to = value; + return(0); + } + + return(-1); /* Change to SYMBOL */ + } + +/* Convert String to Unsigned Long */ +static long cvt_st_ul( + char *from, + unsigned long *to, + struct dbAddr *paddr) + { + unsigned long value; + + if (sscanf(from, "%lu", &value) == 1) { + *to = value; + return(0); + } + + return(-1); /* Change to SYMBOL */ + } + +/* Convert String to Float */ +static long cvt_st_f( + char *from, + float *to, + struct dbAddr *paddr) + { + float value; + + if (sscanf(from, "%f", &value) == 1) { + *to = value; + return(0); + } + + return(-1); /* Change to SYMBOL */ + } + +/* Convert String to Double */ +static long cvt_st_d( + char *from, + double *to, + struct dbAddr *paddr) + { + double value; + + if (sscanf(from, "%lf", &value) == 1) { + *to = value; + return(0); + } + + return(-1); /* Change to SYMBOL */ + } + +/* Convert String to Enumerated */ +static long cvt_st_e( + char *from, + unsigned short *to, + struct dbAddr *paddr) + { + struct rset *prset; + long status; + + prset = GET_PRSET(pdbBase->precSup, paddr->record_type); + + if (prset && prset->put_enum_str) + return (*prset->put_enum_str)(paddr, from); + + status = S_db_noRSET; + recGblRecSupError(status, paddr, "dbPutField", "put_enum_str"); + return(S_db_badDbrtype); + } + +/* Convert String to Global Choice */ +static long cvt_st_gbl( + char *from, + unsigned short *to, + struct dbAddr *paddr) + { + char *pchoice; + struct choiceSet *pchoiceSet; + unsigned short i; + + pchoiceSet = GET_PCHOICE_SET(pdbBase->pchoiceGbl, paddr->choice_set); + + if (pchoiceSet) { + for (i=0; i < pchoiceSet->number; i++) { + pchoice = pchoiceSet->papChoice[i]; + if (!pchoice) + continue; + if (strcmp(pchoice, from) == 0) { + *to = i; + return(0); + } + } + } + + recGblDbaddrError(S_db_badChoice, paddr, "dbPut(putStringGchoice)"); + return(S_db_badChoice); + } + +/* Convert String to Cvt Choice */ +static long cvt_st_cvt( + char *from, + unsigned short *to, + struct dbAddr *paddr) + { + char *pchoice; + struct choiceSet *pchoiceSet; + unsigned short i; + + pchoiceSet = pdbBase->pchoiceCvt; + + if (pchoiceSet) { + for (i=0; i < pchoiceSet->number; i++) { + pchoice = pchoiceSet->papChoice[i]; + if (!pchoice) + continue; + if (strcmp(pchoice, from) == 0) { + *to = i; + return(0); + } + } + } + + recGblDbaddrError(S_db_badChoice, paddr, "dbPut(putStringCchoice)"); + return(S_db_badChoice); + } + +/* Convert String to Rec Choice */ +static long cvt_st_rec( + char *from, + unsigned short *to, + struct dbAddr *paddr) + { + char *pchoice; + struct choiceSet *pchoiceSet; + struct arrChoiceSet *parrChoiceSet; + unsigned short i; + + parrChoiceSet = GET_PARR_CHOICE_SET(pdbBase->pchoiceRec, paddr->record_type); + + if (parrChoiceSet) { + pchoiceSet = GET_PCHOICE_SET(parrChoiceSet, paddr->choice_set); + + if (pchoiceSet) { + for (i=0; i < pchoiceSet->number; i++) { + pchoice = pchoiceSet->papChoice[i]; + if (!pchoice) + continue; + if (strcmp(pchoice, from) == 0) { + *to = i; + return(0); + } + } + } + } + + recGblDbaddrError(S_db_badChoice, paddr, "dbPut(putStringRchoice)"); + return(S_db_badChoice); + } + +/* Convert String to Dev Choice */ +static long cvt_st_dev( + char *from, + unsigned short *to, + struct dbAddr *paddr) + { + char *pchoice; + struct devChoiceSet *pdevChoiceSet; + unsigned short i; + + pdevChoiceSet = GET_PDEV_CHOICE_SET(pdbBase->pchoiceDev, paddr->record_type); + + if (pdevChoiceSet) { + for (i=0; i < pdevChoiceSet->number; i++) { + pchoice = pdevChoiceSet->papDevChoice[i]->pchoice; + if (!pchoice) + continue; + if (strcmp(pchoice, from) == 0) { + *to = i; + return(0); + } + } + } + recGblDbaddrError(S_db_badChoice, paddr, "dbPut(putStringDchoice)"); + return(S_db_badChoice); + } + +/* Convert Char to String */ +static long cvt_c_st( + char *from, + char *to, + struct dbAddr *paddr) +{ cvtCharToString(*from, to); return(0); } + +/* Convert Char to Char */ +static long cvt_c_c( + char *from, + char *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Char to Unsigned Char */ +static long cvt_c_uc( + char *from, + unsigned char *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Char to Short */ +static long cvt_c_s( + char *from, + short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Char to Unsigned Short */ +static long cvt_c_us( + char *from, + unsigned short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Char to Long */ +static long cvt_c_l( + char *from, + long *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Char to Unsigned Long */ +static long cvt_c_ul( + char *from, + unsigned long *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Char to Float */ +static long cvt_c_f( + char *from, + float *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Char to Double */ +static long cvt_c_d( + char *from, + double *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Char to Enumerated */ +static long cvt_c_e( + char *from, + unsigned short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Char to String */ +static long cvt_uc_st( + unsigned char *from, + char *to, + struct dbAddr *paddr) +{ cvtUcharToString(*from, to); return(0); } + +/* Convert Unsigned Char to Char */ +static long cvt_uc_c( + unsigned char *from, + char *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Char to Unsigned Char */ +static long cvt_uc_uc( + unsigned char *from, + unsigned char *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Char to Short */ +static long cvt_uc_s( + unsigned char *from, + short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Char to Unsigned Short */ +static long cvt_uc_us( + unsigned char *from, + unsigned short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Char to Long */ +static long cvt_uc_l( + unsigned char *from, + long *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Char to Unsigned Long */ +static long cvt_uc_ul( + unsigned char *from, + unsigned long *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Char to Float */ +static long cvt_uc_f( + unsigned char *from, + float *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Char to Double */ +static long cvt_uc_d( + unsigned char *from, + double *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Char to Enumerated */ +static long cvt_uc_e( + unsigned char *from, + unsigned short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Short to String */ +static long cvt_s_st( + short *from, + char *to, + struct dbAddr *paddr) +{ cvtShortToString(*from, to); return(0); } + +/* Convert Short to Char */ +static long cvt_s_c( + short *from, + char *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Short to Unsigned Char */ +static long cvt_s_uc( + short *from, + unsigned char *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Short to Short */ +static long cvt_s_s( + short *from, + short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Short to Unsigned Short */ +static long cvt_s_us( + short *from, + unsigned short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Short to Long */ +static long cvt_s_l( + short *from, + long *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Short to Unsigned Long */ +static long cvt_s_ul( + short *from, + unsigned long *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Short to Float */ +static long cvt_s_f( + short *from, + float *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Short to Double */ +static long cvt_s_d( + short *from, + double *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Short to Enumerated */ +static long cvt_s_e( + short *from, + unsigned short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Short to String */ +static long cvt_us_st( + unsigned short *from, + char *to, + struct dbAddr *paddr) +{ cvtUshortToString(*from, to); return(0); } + +/* Convert Unsigned Short to Char */ +static long cvt_us_c( + unsigned short *from, + char *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Short to Unsigned Char */ +static long cvt_us_uc( + unsigned short *from, + unsigned char *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Short to Short */ +static long cvt_us_s( + unsigned short *from, + short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Short to Unsigned Short */ +static long cvt_us_us( + unsigned short *from, + unsigned short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Short to Long */ +static long cvt_us_l( + unsigned short *from, + long *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Short to Unsigned Long */ +static long cvt_us_ul( + unsigned short *from, + unsigned long *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Short to Float */ +static long cvt_us_f( + unsigned short *from, + float *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Short to Double */ +static long cvt_us_d( + unsigned short *from, + double *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Short to Enumerated */ +static long cvt_us_e( + unsigned short *from, + unsigned short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Long to String */ +static long cvt_l_st( + long *from, + char *to, + struct dbAddr *paddr) +{ cvtLongToString(*from, to); return(0); } + +/* Convert Long to Char */ +static long cvt_l_c( + long *from, + char *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Long to Unsigned Char */ +static long cvt_l_uc( + long *from, + unsigned char *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Long to Short */ +static long cvt_l_s( + long *from, + short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Long to Unsigned Short */ +static long cvt_l_us( + long *from, + unsigned short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Long to Long */ +static long cvt_l_l( + long *from, + long *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Long to Unsigned Long */ +static long cvt_l_ul( + long *from, + unsigned long *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Long to Float */ +static long cvt_l_f( + long *from, + float *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Long to Double */ +static long cvt_l_d( + long *from, + double *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Long to Enumerated */ +static long cvt_l_e( + long *from, + unsigned short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Long to String */ +static long cvt_ul_st( + unsigned long *from, + char *to, + struct dbAddr *paddr) +{ cvtUlongToString(*from, to); return(0); } + +/* Convert Unsigned Long to Char */ +static long cvt_ul_c( + unsigned long *from, + char *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Long to Unsigned Char */ +static long cvt_ul_uc( + unsigned long *from, + unsigned char *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Long to Short */ +static long cvt_ul_s( + unsigned long *from, + short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Long to Unsigned Short */ +static long cvt_ul_us( + unsigned long *from, + unsigned short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Long to Long */ +static long cvt_ul_l( + unsigned long *from, + long *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Long to Unsigned Long */ +static long cvt_ul_ul( + unsigned long *from, + unsigned long *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Long to Float */ +static long cvt_ul_f( + unsigned long *from, + float *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Long to Double */ +static long cvt_ul_d( + unsigned long *from, + double *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Unsigned Long to Enumerated */ +static long cvt_ul_e( + unsigned long *from, + unsigned short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Float to String */ +static long cvt_f_st( + float *from, + char *to, + struct dbAddr *paddr) + { + struct rset *prset; + long status = 0; + long precision = 2; + + prset = GET_PRSET(pdbBase->precSup, paddr->record_type); + + if (prset && prset->get_precision) + (*prset->get_precision)(paddr, &precision); + else + status = S_db_precision; + + if (!RTN_SUCCESS(status)) { + recGblRecSupError(status, paddr, "dbGetField", "get_precision"); + return(status); + } + + cvtFloatToString(*from, to, precision); + + return(status); + } + +/* Convert Float to Char */ +static long cvt_f_c( + float *from, + char *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Float to Unsigned Char */ +static long cvt_f_uc( + float *from, + unsigned char *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Float to Short */ +static long cvt_f_s( + float *from, + short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Float to Unsigned Short */ +static long cvt_f_us( + float *from, + unsigned short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Float to Long */ +static long cvt_f_l( + float *from, + long *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Float to Unsigned Long */ +static long cvt_f_ul( + float *from, + unsigned long *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Float to Float */ +static long cvt_f_f( + float *from, + float *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Float to Double */ +static long cvt_f_d( + float *from, + double *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Float to Enumerated */ +static long cvt_f_e( + float *from, + unsigned short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Double to String */ +static long cvt_d_st( + double *from, + char *to, + struct dbAddr *paddr) + { + struct rset *prset; + long status = 0; + long precision = 2; + + prset = GET_PRSET(pdbBase->precSup, paddr->record_type); + + if (prset && prset->get_precision) + (*prset->get_precision)(paddr, &precision); + else + status = S_db_precision; + + if (!RTN_SUCCESS(status)) { + recGblRecSupError(status, paddr, "dbGetField", "get_precision"); + return(status); + } + + cvtDoubleToString(*from, to, precision); + + return(status); + } + +/* Convert Double to Char */ +static long cvt_d_c( + double *from, + char *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Double to Unsigned Char */ +static long cvt_d_uc( + double *from, + unsigned char *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Double to Short */ +static long cvt_d_s( + double *from, + short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Double to Unsigned Short */ +static long cvt_d_us( + double *from, + unsigned short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Double to Long */ +static long cvt_d_l( + double *from, + long *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Double to Unsigned Long */ +static long cvt_d_ul( + double *from, + unsigned long *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Double to Float */ +static long cvt_d_f( + double *from, + float *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Double to Double */ +static long cvt_d_d( + double *from, + double *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Double to Enumerated */ +static long cvt_d_e( + double *from, + unsigned short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Enumerated to Char */ +static long cvt_e_c( + unsigned short *from, + char *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Enumerated to Unsigned Char */ +static long cvt_e_uc( + unsigned short *from, + unsigned char *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Enumerated to Short */ +static long cvt_e_s( + unsigned short *from, + short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Enumerated to Unsigned Short */ +static long cvt_e_us( + unsigned short *from, + unsigned short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Enumerated to Long */ +static long cvt_e_l( + unsigned short *from, + long *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Enumerated to Unsigned Long */ +static long cvt_e_ul( + unsigned short *from, + unsigned long *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Enumerated to Float */ +static long cvt_e_f( + unsigned short *from, + float *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Enumerated to Double */ +static long cvt_e_d( + unsigned short *from, + double *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Enumerated to Enumerated */ +static long cvt_e_e( + unsigned short *from, + unsigned short *to, + struct dbAddr *paddr) + { *to=*from; return(0); } + +/* Convert Choices And Enumerated Types To String ... */ + +/* Get Enumerated to String */ +static long cvt_e_st_get( + unsigned short *from, + char *to, + struct dbAddr *paddr) + { + struct rset *prset; + long status; + + prset = GET_PRSET(pdbBase->precSup, paddr->record_type); + + if (prset && prset->get_enum_str) + return (*prset->get_enum_str)(paddr, to); + + status = S_db_noRSET; + recGblRecSupError(status, paddr, "dbGetField", "get_enum_str"); + + return(S_db_badDbrtype); + } + +/* Put Enumerated to String */ +static long cvt_e_st_put( + unsigned short *from, + char *to, + struct dbAddr *paddr) + { cvtUshortToString(*from, to); return(0); } + +/* Get Gbl Choice to String */ +static long cvt_gbl_st( + unsigned short *from, + char *to, + struct dbAddr *paddr) + { + struct choiceSet *pchoiceSet; + char *pchoice; + + pchoiceSet = GET_PCHOICE_SET(pdbBase->pchoiceGbl, paddr->choice_set); + + if (pchoiceSet) { + pchoice = GET_CHOICE(pchoiceSet, *from); + + if (pchoice) { + strncpy(to, pchoice, MAX_STRING_SIZE); + return(0); + } + } + + recGblDbaddrError(S_db_badChoice, paddr, "dbGetField(getGchoiceString)"); + return(S_db_badChoice); + } + +/* Get Cvt Choice to String */ +static long cvt_cvt_st( + unsigned short *from, + char *to, + struct dbAddr *paddr) + { + char *pchoice; + + pchoice = GET_CHOICE(pdbBase->pchoiceCvt, *from); + + if (pchoice) { + strncpy(to, pchoice, MAX_STRING_SIZE); + return(0); + } + + recGblDbaddrError(S_db_badChoice, paddr, "dbGetField(getCchoiceString)"); + return(S_db_badChoice); + } + +/* Get Record Choice to String */ +static long cvt_rec_st( + unsigned short *from, + char *to, + struct dbAddr *paddr) + { + struct choiceSet *pchoiceSet; + struct arrChoiceSet *parrChoiceSet; + char *pchoice; + + parrChoiceSet = GET_PARR_CHOICE_SET(pdbBase->pchoiceRec, paddr->record_type); + + if (parrChoiceSet) { + pchoiceSet = GET_PCHOICE_SET(parrChoiceSet, paddr->choice_set); + + if (pchoiceSet) { + pchoice = GET_CHOICE(pchoiceSet, *from); + + if (pchoice) { + strncpy(to, pchoice, MAX_STRING_SIZE); + return(0); + } + } + } + + recGblDbaddrError(S_db_badChoice, paddr, "dbGetField(getRchoiceString)"); + return(S_db_badChoice); +} + +/* Get Dev Choice to String */ +static long cvt_dev_st( + unsigned short *from, + char *to, + struct dbAddr *paddr) + { + struct devChoiceSet *pdevChoiceSet; + struct devChoice *pdevChoice; + + pdevChoiceSet = GET_PDEV_CHOICE_SET(pdbBase->pchoiceDev, paddr->record_type); + + if (pdevChoiceSet) { + pdevChoice = GET_DEV_CHOICE(pdevChoiceSet, *from); + + if (pdevChoice) { + strncpy(to, pdevChoice->pchoice, MAX_STRING_SIZE); + return(0); + } + } + + recGblDbaddrError(S_db_badChoice, paddr, "dbGetField(getRchoiceString)"); + return(S_db_badChoice); + } + +/* + * Get conversion routine lookup table + * + * Converts type X to ... + * + * DBR_STRING, DBR_CHR, DBR_UCHAR, DBR_SHORT, DBR_USHORT, + * DBR_LONG, DBR_ULONG, DBR_FLOAT, DBR_DOUBLE, DBR_ENUM + * + * NULL implies the conversion is not supported. + */ + +long (*get_cvt_table[DBF_DEVCHOICE+1][DBR_ENUM+1])() = { + + /* Convert DBF_STRING to ... */ +{ cvt_st_st, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, + + /* Convert DBF_CHAR to ... */ +{ cvt_c_st, cvt_c_c, cvt_c_uc, cvt_c_s, cvt_c_us, cvt_c_l, cvt_c_ul, cvt_c_f, cvt_c_d, cvt_c_e }, + + /* Convert DBF_UCHAR to ... */ +{ cvt_uc_st, cvt_uc_c, cvt_uc_uc, cvt_uc_s, cvt_uc_us, cvt_uc_l, cvt_uc_ul, cvt_uc_f, cvt_uc_d, cvt_uc_e }, + + /* Convert DBF_SHORT to ... */ +{ cvt_s_st, cvt_s_c, cvt_s_uc, cvt_s_s, cvt_s_us, cvt_s_l, cvt_s_ul, cvt_s_f, cvt_s_d, cvt_s_e }, + + /* Convert DBF_USHORT to ... */ +{ cvt_us_st, cvt_us_c, cvt_us_uc, cvt_us_s, cvt_us_us, cvt_us_l, cvt_us_ul, cvt_us_f, cvt_us_d, cvt_us_e }, + + /* Convert DBF_LONG to ... */ +{ cvt_l_st, cvt_l_c, cvt_l_uc, cvt_l_s, cvt_l_us, cvt_l_l, cvt_l_ul, cvt_l_f, cvt_l_d, cvt_l_e }, + + /* Convert DBF_ULONG to ... */ +{ cvt_ul_st, cvt_ul_c, cvt_ul_uc, cvt_ul_s, cvt_ul_us, cvt_ul_l, cvt_ul_ul, cvt_ul_f, cvt_ul_d, cvt_ul_e }, + + /* Convert DBF_FLOAT to ... */ +{ cvt_f_st, cvt_f_c, cvt_f_uc, cvt_f_s, cvt_f_us, cvt_f_l, cvt_f_ul, cvt_f_f, cvt_f_d, cvt_f_e }, + + /* Convert DBF_DOUBLE to ... */ +{ cvt_d_st, cvt_d_c, cvt_d_uc, cvt_d_s, cvt_d_us, cvt_d_l, cvt_d_ul, cvt_d_f, cvt_d_d, cvt_d_e }, + + /* Convert DBF_ENUM to ... */ +{ cvt_e_st_get, cvt_e_c, cvt_e_uc, cvt_e_s, cvt_e_us, cvt_e_l, cvt_e_ul, cvt_e_f, cvt_e_d, cvt_e_e }, + + /* Convert DBF_GBLCHOICE to ... */ +{ cvt_gbl_st, cvt_e_c, cvt_e_uc, cvt_e_s, cvt_e_us, cvt_e_l, cvt_e_ul, cvt_e_f, cvt_e_d, cvt_e_e }, + + /* Convert DBF_CVTCHOICE to ... */ +{ cvt_cvt_st, cvt_e_c, cvt_e_uc, cvt_e_s, cvt_e_us, cvt_e_l, cvt_e_ul, cvt_e_f, cvt_e_d, cvt_e_e }, + + /* Convert DBF_RECCHOICE to ... */ +{ cvt_rec_st, cvt_e_c, cvt_e_uc, cvt_e_s, cvt_e_us, cvt_e_l, cvt_e_ul, cvt_e_f, cvt_e_d, cvt_e_e }, + + /* Convert DBF_DEVCHOICE to ... */ +{ cvt_dev_st, cvt_e_c, cvt_e_uc, cvt_e_s, cvt_e_us, cvt_e_l, cvt_e_ul, cvt_e_f, cvt_e_d, cvt_e_e } }; + +/* + * Put conversion routine lookup table + * + * Converts type X to ... + * + * DBF_STRING DBF_CHAR DBF_UCHAR DBF_SHORT DBF_USHORT + * DBF_LONG DBF_ULONG DBF_FLOAT DBF_DOUBLE DBF_ENUM + * DBF_GBLCHOICE DBF_CVTCHOICE DBF_RECCHOICE DBF_DEVCHOICE + * + * NULL implies the conversion is not supported. + */ + +long (*put_cvt_table[DBR_ENUM+1][DBF_DEVCHOICE+1])() = { + + /* Convert DBR_STRING to ... */ +{ cvt_st_st, cvt_st_c, cvt_st_uc, cvt_st_s, cvt_st_us, cvt_st_l, cvt_st_ul, cvt_st_f, cvt_st_d, cvt_st_e, cvt_st_gbl, cvt_st_cvt, cvt_st_rec, cvt_st_dev }, + + /* Convert DBR_CHAR to ... */ +{ cvt_c_st, cvt_c_c, cvt_c_uc, cvt_c_s, cvt_c_us, cvt_c_l, cvt_c_ul, cvt_c_f, cvt_c_d, cvt_c_e, cvt_c_e, cvt_c_e, cvt_c_e, cvt_c_e }, + + /* Convert DBR_UCHAR to ... */ +{ cvt_uc_st, cvt_uc_c, cvt_uc_uc, cvt_uc_s, cvt_uc_us, cvt_uc_l, cvt_uc_ul, cvt_uc_f, cvt_uc_d, cvt_uc_e, cvt_uc_e, cvt_uc_e, cvt_uc_e, cvt_uc_e }, + + /* Convert DBR_SHORT to ... */ +{ cvt_s_st, cvt_s_c, cvt_s_uc, cvt_s_s, cvt_s_us, cvt_s_l, cvt_s_ul, cvt_s_f, cvt_s_d, cvt_s_e, cvt_s_e, cvt_s_e, cvt_s_e, cvt_s_e }, + + /* Convert DBR_USHORT to ... */ +{ cvt_us_st, cvt_us_c, cvt_us_uc, cvt_us_s, cvt_us_us, cvt_us_l, cvt_us_ul, cvt_us_f, cvt_us_d, cvt_us_e, cvt_us_e, cvt_us_e, cvt_us_e, cvt_us_e }, + + /* Convert DBR_LONG to ... */ +{ cvt_l_st, cvt_l_c, cvt_l_uc, cvt_l_s, cvt_l_us, cvt_l_l, cvt_l_ul, cvt_l_f, cvt_l_d, cvt_l_e, cvt_l_e, cvt_l_e, cvt_l_e, cvt_l_e }, + + /* Convert DBR_ULONG to ... */ +{ cvt_ul_st, cvt_ul_c, cvt_ul_uc, cvt_ul_s, cvt_ul_us, cvt_ul_l, cvt_ul_ul, cvt_ul_f, cvt_ul_d, cvt_ul_e, cvt_ul_e, cvt_ul_e, cvt_ul_e, cvt_ul_e }, + + /* Convert DBR_FLOAT to ... */ +{ cvt_f_st, cvt_f_c, cvt_f_uc, cvt_f_s, cvt_f_us, cvt_f_l, cvt_f_ul, cvt_f_f, cvt_f_d, cvt_f_e, cvt_f_e, cvt_f_e, cvt_f_e, cvt_f_e }, + + /* Convert DBR_DOUBLE to ... */ +{ cvt_d_st, cvt_d_c, cvt_d_uc, cvt_d_s, cvt_d_us, cvt_d_l, cvt_d_ul, cvt_d_f, cvt_d_d, cvt_d_e, cvt_d_e, cvt_d_e, cvt_d_e, cvt_d_e }, + + /* Convert DBR_ENUM to ... */ +{ cvt_e_st_put, cvt_e_c, cvt_e_uc, cvt_e_s, cvt_e_us, cvt_e_l, cvt_e_ul, cvt_e_f, cvt_e_d, cvt_e_e, cvt_e_e, cvt_e_e, cvt_e_e, cvt_e_e } }; + diff --git a/src/db/dbLink.c b/src/db/dbLink.c new file mode 100644 index 000000000..be266ff97 --- /dev/null +++ b/src/db/dbLink.c @@ -0,0 +1,5503 @@ +/* dbLink.c */ +/* base/src/db $Id$ */ +/* + * Original Author: Bob Dalesio + * Current Author: Marty Kraimer + * Date: 11-7-90 + * + * Experimental Physics and Industrial Control System (EPICS) + * + * Copyright 1991, the Regents of the University of California, + * and the University of Chicago Board of Governors. + * + * This software was produced under U.S. Government contracts: + * (W-7405-ENG-36) at the Los Alamos National Laboratory, + * and (W-31-109-ENG-38) at Argonne National Laboratory. + * + * Initial development by: + * The Controls and Automation Group (AT-8) + * Ground Test Accelerator + * Accelerator Technology Division + * Los Alamos National Laboratory + * + * Co-developed with + * The Controls and Computing Group + * Accelerator Systems Division + * Advanced Photon Source + * Argonne National Laboratory + * + * Modification Log: + * ----------------- + * .01 07-26-91 mrk Allow choices to be retrieved as numeric + * .02 08-13-91 mrk Support db_field_log for dbGetField + * .03 09-30-91 mrk Support for TPRO and DISP + * .04 10-03-91 jba Bug fix in putStringUchar + * .05 11-06-91 jba Moved processing message before record process + * .06 11-26-91 jba Added return to dbGetLink + * Fixed bug in special processing of SPC_MOD (100) + * .07 12-02-91 jba Writing to PROC will always force record process + * .08 02-05-92 jba Changed function arguments from paddr to precord + * .09 03-02-92 jba Added function dbValueSize to replace db_value_size + * .10 04-17-92 rcz put in mrk's dbNameToAddr changes for dbBase + * .11 05-18-92 mrk Changes for database internal structures + * .12 07-16-92 jba Added disable alarm severity, ansi c changes + * .13 08-05-92 jba Removed all references to dbr_field_type + * .14 09-18-92 jba replaced get of disa code with recGblGetLinkValue call + * .15 07-15-93 mrk Changes for new dbStaticLib + * .16 02-02-94 mrk added dbPutNotify and caching + * .17 02-02-94 mrk added init code for tsel + */ + + +/* + * dbGetLink Get via a database link + * dbPutLink Put via a link + * dbGetField Get from outside database + * dbPutField Put from outside database + * dbGet Common get routine + * dbPut Common put routine + * + * dbBufferSize Compute buffer size + * dbValueSizeA Compute size for a field + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern struct dbBase *pdbBase; + +/* Added for Channel Access Links */ +long dbCaAddInlink(); +long dbCaGetLink(); +long dbCommonInit(); + + +long dbGetField( +struct dbAddr *paddr, +short dbrType, +void *pbuffer, +long *options, +long *nRequest, +void *pflin +) +{ + struct dbCommon *precord = (struct dbCommon *)(paddr->precord); + long status; + + dbScanLock(precord); + status = dbGet(paddr,dbrType,pbuffer,options,nRequest,pflin); + dbScanUnlock(precord); + return(status); +} + +long dbGetLink( + struct db_link *pdblink, + struct dbCommon *pdest, + short dbrType, + void *pbuffer, + long *options, + long *nRequest +) +{ + struct dbAddr *paddr=(struct dbAddr*)(pdblink->pdbAddr); + struct dbCommon *psource=paddr->precord; + long status; + + if(pdblink->process_passive && psource->scan==0) { + status=dbScanPassive(pdest,psource); + if(status) return(status); + } + if(pdblink->maximize_sevr) recGblSetSevr(pdest,LINK_ALARM,psource->sevr); + + status= dbGet(paddr,dbrType,pbuffer,options,nRequest,NULL); + if(status) recGblRecordError(status,(void *)pdest,"dbGetLink"); + return(status); +} + +long dbPutLink( + struct db_link *pdblink, + struct dbCommon *psource, + short dbrType, + void *pbuffer, + long nRequest +) +{ + struct dbAddr *paddr=(struct dbAddr*)(pdblink->pdbAddr); + struct dbCommon *pdest=paddr->precord; + long status; + + status=dbPut(paddr,dbrType,pbuffer,nRequest); + if(pdblink->maximize_sevr) recGblSetSevr(pdest,LINK_ALARM,psource->sevr); + if(status) return(status); + + if((paddr->pfield==(void *)&pdest->proc) + || (pdblink->process_passive && pdest->scan==0)) { + /*Note: If ppn then dbNotifyCancel will handle reprocessing*/ + /*if dbPutField caused asyn record to process ask for reprocessing*/ + if(!psource->ppn && pdest->putf) pdest->rpro = TRUE; + /* otherwise ask for the record to be processed*/ + else status=dbScanLink(psource,pdest); + } + return(status); +} + +long dbPutField( + struct dbAddr *paddr, + short dbrType, + void *pbuffer, + long nRequest +) +{ + long status; + struct fldDes *pfldDes=(struct fldDes *)(paddr->pfldDes); + struct dbCommon *precord = (struct dbCommon *)(paddr->precord); + + /*check for putField disabled*/ + if(precord->disp) { + if((void *)(&precord->disp) != paddr->pfield) return(0); + } + dbScanLock(precord); + status=dbPut(paddr,dbrType,pbuffer,nRequest); + if(status) recGblDbaddrError(status,paddr,"dbPutField"); + if(status==0){ + if((paddr->pfield==(void *)&precord->proc) + ||(pfldDes->process_passive && precord->scan==0)) { + if(precord->pact) { + precord->rpro = TRUE; + } else { + /*indicate that dbPutField called dbProcess*/ + precord->putf = TRUE; + status=dbProcess(precord); + } + } + } + dbScanUnlock(precord); + return(status); +} + +static void notifyCallback(CALLBACK *pcallback) +{ + PUTNOTIFY *ppn=NULL; + long status; + + callbackGetUser(ppn,pcallback); + if(ppn->cmd==notifyCmdRepeat) { + status = dbPutNotify(ppn); + } else if(ppn->cmd==notifyCmdCallUser) { + (ppn->userCallback)(ppn); + } else {/*illegal request*/ + recGblRecordError(-1,ppn->paddr->precord,"dbNotifyCompletion: illegal callback request"); + } +} + +static void notifyCancel(PUTNOTIFY *ppn) +{ + struct dbCommon *precord = ppn->list; + + while(precord) { + void *pnext; + + if(precord->rpro) { + precord->rpro = FALSE; + scanOnce(precord); + } + precord->ppn = NULL; + pnext = precord->ppnn; + precord->ppnn = NULL; + precord = pnext; + } + ppn->list = NULL; +} + +void dbNotifyCancel(PUTNOTIFY *ppn) +{ + struct dbCommon *precord = ppn->list; + + dbScanLock(precord); + notifyCancel(ppn); + dbScanUnlock(precord); +} + +long dbPutNotify(PUTNOTIFY *ppn) +{ + struct dbAddr *paddr = ppn->paddr; + short dbrType = ppn->dbrType; + void *pbuffer = ppn->pbuffer; + long nRequest = ppn->nRequest; + long status=0; + struct fldDes *pfldDes=(struct fldDes *)(paddr->pfldDes); + struct dbCommon *precord = (struct dbCommon *)(paddr->precord); + + callbackSetCallback(notifyCallback,&ppn->callback); + callbackSetUser(ppn,&ppn->callback); + callbackSetPriority(priorityLow,&ppn->callback); + /*check for putField disabled*/ + if(precord->disp) { + if((void *)(&precord->disp) != paddr->pfield) { + ppn->cmd = notifyCmdCallUser; + ppn->status = S_db_putDisabled; + notifyCallback(&ppn->callback); + return(S_db_putDisabled); + } + } + dbScanLock(precord); + status=dbPut(paddr,dbrType,pbuffer,nRequest); + if(status) recGblDbaddrError(status,paddr,"dbPutField"); + ppn->status = status; + if(status==0){ + if((paddr->pfield==(void *)&precord->proc) + ||(pfldDes->process_passive && precord->scan==0)) { + if(precord->ppn) { + /*record already has attached ppn. Blocked*/ + + ppn->status = status = S_db_Blocked; + return(status); + } + ppn->nwaiting = 1; + ppn->rescan = FALSE; + ppn->list = NULL; + precord->ppn = ppn; + precord->ppnn = NULL; + if(precord->pact) {/*blocked wait for dbNotifyCompletion*/ + ppn->rescan = TRUE; + ppn->status = status = S_db_Pending; + return(status); + } + status=dbProcess(precord); + if(status==0) { + if(!precord->pact) { + precord->ppn = NULL; + } else { + precord->ppnn = ppn->list; + ppn->list = precord; + } + ppn->status = status = ((ppn->nwaiting == 0) ? 0 : S_db_Pending); + } else { + ppn->status = status; + notifyCancel(ppn); + } + } else { /*Make callback immediately*/ + ppn->cmd = notifyCmdCallUser; + ppn->status = 0; + notifyCallback(&ppn->callback); + } + } + dbScanUnlock(precord); + return(status); +} + +void dbNotifyCompletion(PUTNOTIFY *ppn) +{ + + if(ppn->status!=0 && ppn->status!=S_db_Pending) { + ppn->cmd = notifyCmdCallUser; + notifyCancel(ppn); + callbackRequest(&ppn->callback); + return; + } + /*decrement number of records being waited on*/ + if(ppn->nwaiting<=0) { + recGblRecordError(-1,ppn->paddr->precord,"dbNotifyCompletion: nwaiting<-0 LOGIC"); + return; + } + if(--ppn->nwaiting == 0) {/*original request completed*/ + notifyCancel(ppn); + if(ppn->rescan) { + ppn->cmd = notifyCmdRepeat; + callbackRequest(&ppn->callback); + } else { + /*issue completion callback*/ + ppn->cmd = notifyCmdCallUser; + if(ppn->status==S_db_Pending) ppn->status = 0; + callbackRequest(&ppn->callback); + } + } +} + +long dbValueSize( + short dbr_type +) +{ + /* sizes for value associated with each DBR request type */ + static long size[] = { + MAX_STRING_SIZE, /* STRING */ + sizeof(char), /* CHAR */ + sizeof(unsigned char), /* UCHAR */ + sizeof(short), /* SHORT */ + sizeof(unsigned short), /* USHORT */ + sizeof(long), /* LONG */ + sizeof(unsigned long), /* ULONG */ + sizeof(float), /* FLOAT */ + sizeof(double), /* DOUBLE */ + sizeof(unsigned short)}; /* ENUM */ + + return(size[dbr_type]); +} + +long dbBufferSize( + short dbr_type, + long options, + long no_elements +) +{ + long nbytes=0; + + nbytes += dbValueSize(dbr_type) * no_elements; + if(options & DBR_STATUS) nbytes += dbr_status_size; + if(options & DBR_UNITS) nbytes += dbr_units_size; + if(options & DBR_PRECISION) nbytes += dbr_precision_size; + if(options & DBR_TIME) nbytes += dbr_time_size; + if(options & DBR_ENUM_STRS) nbytes += dbr_enumStrs_size; + if(options & DBR_GR_LONG) nbytes += dbr_grLong_size; + if(options & DBR_GR_DOUBLE) nbytes += dbr_grDouble_size; + if(options & DBR_CTRL_LONG) nbytes += dbr_ctrlLong_size; + if(options & DBR_CTRL_DOUBLE)nbytes += dbr_ctrlDouble_size; + if(options & DBR_AL_LONG) nbytes += dbr_alLong_size; + if(options & DBR_AL_DOUBLE) nbytes += dbr_alDouble_size; + return(nbytes); +} + +/* DATABASE ACCESS GET CONVERSION SUPPORT */ + +static long getStringString(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *psrc=paddr->pfield; + short size=paddr->field_size; + short sizeto; + + /* always force result string to be null terminated*/ + sizeto = size; + if(sizeto>=MAX_STRING_SIZE) sizeto = MAX_STRING_SIZE-1; + + if(nRequest==1 && offset==0) { + strncpy(pbuffer,psrc,sizeto); + *(pbuffer+sizeto) = 0; + return(0); + } + psrc+= (size*offset); + while (nRequest) { + strncpy(pbuffer,psrc,sizeto); + *(pbuffer+sizeto) = 0; + pbuffer += MAX_STRING_SIZE; + if(++offset==no_elements) + psrc=paddr->pfield; + else + psrc += size; + nRequest--; + } + return(0); +} + +static long getCharString(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *psrc=(char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + cvtCharToString(*psrc,pbuffer); + return(0); + } + psrc += offset; + while (nRequest) { + cvtCharToString(*psrc,pbuffer); + pbuffer += MAX_STRING_SIZE; + if(++offset==no_elements) + psrc=(char *)paddr->pfield; + else + psrc++; + nRequest--; + } + return(0); +} + +static long getCharChar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *psrc=(char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getCharUchar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *psrc=(char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getCharShort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *psrc=(char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getCharUshort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *psrc=(char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getCharLong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *psrc=(char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getCharUlong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *psrc=(char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getCharFloat(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +float *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *psrc=(char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getCharDouble(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +double *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *psrc=(char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getCharEnum(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *psrc=(char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUcharString(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned char *psrc=(unsigned char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + cvtUcharToString(*psrc,pbuffer); + return(0); + } + psrc += offset; + while (nRequest) { + cvtUcharToString(*psrc,pbuffer); + pbuffer += MAX_STRING_SIZE; + if(++offset==no_elements) + psrc=(unsigned char *)paddr->pfield; + else + psrc++; + nRequest--; + } + return(0); +} + +static long getUcharChar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned char *psrc=(unsigned char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUcharUchar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned char *psrc=(unsigned char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUcharShort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned char *psrc=(unsigned char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUcharUshort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned char *psrc=(unsigned char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUcharLong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned char *psrc=(unsigned char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUcharUlong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned char *psrc=(unsigned char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUcharFloat(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +float *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned char *psrc=(unsigned char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUcharDouble(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +double *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned char *psrc=(unsigned char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUcharEnum(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned char *psrc=(unsigned char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getShortString(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + short *psrc=(short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + cvtShortToString(*psrc,pbuffer); + return(0); + } + psrc += offset; + while (nRequest) { + cvtShortToString(*psrc,pbuffer); + pbuffer += MAX_STRING_SIZE; + if(++offset==no_elements) + psrc=(short *)paddr->pfield; + else + psrc++; + nRequest--; + } + return(0); +} + +static long getShortChar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + short *psrc=(short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getShortUchar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + short *psrc=(short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(short *)paddr->pfield; + nRequest--; + } + return(0); +} +static long getShortShort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + short *psrc=(short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getShortUshort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + short *psrc=(short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getShortLong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + short *psrc=(short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getShortUlong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + short *psrc=(short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getShortFloat(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +float *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + short *psrc=(short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getShortDouble(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +double *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + short *psrc=(short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getShortEnum(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + short *psrc=(short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUshortString(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *psrc=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + cvtUshortToString(*psrc,pbuffer); + return(0); + } + psrc += offset; + while (nRequest) { + cvtUshortToString(*psrc,pbuffer); + pbuffer += MAX_STRING_SIZE; + if(++offset==no_elements) + psrc=(unsigned short *)paddr->pfield; + else + psrc++; + nRequest--; + } + return(0); +} + +static long getUshortChar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *psrc=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUshortUchar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *psrc=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} +static long getUshortShort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *psrc=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUshortUshort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *psrc=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUshortLong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *psrc=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUshortUlong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *psrc=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUshortFloat(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +float *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *psrc=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUshortDouble(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +double *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *psrc=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUshortEnum(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *psrc=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getLongString(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + long *psrc=(long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + cvtLongToString(*psrc,pbuffer); + return(0); + } + psrc += offset; + while (nRequest) { + cvtLongToString(*psrc,pbuffer); + pbuffer += MAX_STRING_SIZE; + if(++offset==no_elements) + psrc=(long *)paddr->pfield; + else + psrc++; + nRequest--; + } + return(0); +} + +static long getLongChar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + long *psrc=(long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getLongUchar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + long *psrc=(long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getLongShort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + long *psrc=(long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getLongUshort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + long *psrc=(long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getLongLong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + long *psrc=(long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getLongUlong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + long *psrc=(long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getLongFloat(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +float *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + long *psrc=(long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getLongDouble(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +double *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + long *psrc=(long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getLongEnum(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + long *psrc=(long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUlongString(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned long *psrc=(unsigned long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + cvtUlongToString(*psrc,pbuffer); + return(0); + } + psrc += offset; + while (nRequest) { + cvtUlongToString(*psrc,pbuffer); + pbuffer += MAX_STRING_SIZE; + if(++offset==no_elements) + psrc=(unsigned long *)paddr->pfield; + else + psrc++; + nRequest--; + } + return(0); +} + +static long getUlongChar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned long *psrc=(unsigned long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUlongUchar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned long *psrc=(unsigned long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUlongShort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned long *psrc=(unsigned long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUlongUshort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned long *psrc=(unsigned long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUlongLong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned long *psrc=(unsigned long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUlongUlong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned long *psrc=(unsigned long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUlongFloat(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +float *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned long *psrc=(unsigned long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUlongDouble(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +double *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned long *psrc=(unsigned long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getUlongEnum(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned long *psrc=(unsigned long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getFloatString(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + float *psrc=(float *)(paddr->pfield); + long status; + int precision; + short record_type=paddr->record_type; + struct rset *prset; + + if((prset=GET_PRSET(pdbBase->precSup,record_type)) && (prset->get_precision)) + status = (*prset->get_precision)(paddr,&precision); + else + status=S_db_precision; + if(!RTN_SUCCESS(status)) { + recGblRecSupError(status,paddr,"dbGet","get_precision"); + return(status); + } + + if(nRequest==1 && offset==0) { + cvtFloatToString(*psrc,pbuffer,precision); + return(0); + } + psrc += offset; + while (nRequest) { + cvtFloatToString(*psrc,pbuffer,precision); + pbuffer += MAX_STRING_SIZE; + if(++offset==no_elements) + psrc=(float *)paddr->pfield; + else + psrc++; + nRequest--; + } + return(0); +} + +static long getFloatChar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + float *psrc=(float *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(float *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getFloatUchar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + float *psrc=(float *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(float *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getFloatShort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + float *psrc=(float *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(float *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getFloatUshort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + float *psrc=(float *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(float *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getFloatLong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + float *psrc=(float *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(float *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getFloatUlong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + float *psrc=(float *)(paddr->pfield); + long ltemp; /*vxWorks does not support float to unsigned long*/ + + if(nRequest==1 && offset==0) { + ltemp = *psrc; + *pbuffer = ltemp; + return(0); + } + psrc += offset; + while (nRequest) { + ltemp = *psrc++; + *pbuffer++ = ltemp; + if(++offset==no_elements) psrc=(float *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getFloatFloat(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +float *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + float *psrc=(float *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(float *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getFloatDouble(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +double *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + float *psrc=(float *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(float *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getFloatEnum(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + float *psrc=(float *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(float *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getDoubleString(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + double *psrc=(double *)(paddr->pfield); + long status; + int precision; + short record_type=paddr->record_type; + struct rset *prset; + + if((prset=GET_PRSET(pdbBase->precSup,record_type)) && (prset->get_precision)) + status = (*prset->get_precision)(paddr,&precision); + else + status=S_db_precision; + if(!RTN_SUCCESS(status)) { + recGblRecSupError(status,paddr,"dbGet","get_precision"); + return(status); + } + + if(nRequest==1 && offset==0) { + cvtDoubleToString(*psrc,pbuffer,precision); + return(0); + } + psrc += offset; + while (nRequest) { + cvtDoubleToString(*psrc,pbuffer,precision); + pbuffer += MAX_STRING_SIZE; + if(++offset==no_elements) + psrc=(double *)paddr->pfield; + else + psrc++; + nRequest--; + } + return(0); +} + +static long getDoubleChar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + double *psrc=(double *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(double *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getDoubleUchar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + double *psrc=(double *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(double *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getDoubleShort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + double *psrc=(double *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(double *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getDoubleUshort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + double *psrc=(double *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(double *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getDoubleLong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + double *psrc=(double *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(double *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getDoubleUlong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + double *psrc=(double *)(paddr->pfield); + long ltemp; /*vxWorks does not support double to unsigned long*/ + + if(nRequest==1 && offset==0) { + ltemp = *psrc; + *pbuffer = ltemp; + return(0); + } + psrc += offset; + while (nRequest) { + ltemp = *psrc++; + *pbuffer++ = ltemp; + if(++offset==no_elements) psrc=(double *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getDoubleFloat(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +float *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + double *psrc=(double *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(double *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getDoubleDouble(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +double *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + double *psrc=(double *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(double *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getDoubleEnum(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + double *psrc=(double *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(double *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getEnumString(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + struct rset *prset; + short record_type=(paddr->record_type); + long status; + + if((prset=GET_PRSET(pdbBase->precSup,record_type)) && (prset->get_enum_str)) + return( (*prset->get_enum_str)(paddr,pbuffer) ); + status=S_db_noRSET; + recGblRecSupError(status,paddr,"dbGet","get_enum_str"); + return(S_db_badDbrtype); +} + +static long getEnumChar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *psrc=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getEnumUchar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *psrc=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getEnumShort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *psrc=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getEnumUshort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *psrc=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getEnumLong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *psrc=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getEnumUlong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *psrc=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getEnumFloat(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +float *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *psrc=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getEnumDouble(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +double *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *psrc=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getEnumEnum(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *psrc=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pbuffer = *psrc; + return(0); + } + psrc += offset; + while (nRequest) { + *pbuffer++ = *psrc++; + if(++offset==no_elements) psrc=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long getGchoiceString(paddr,pbuffer,nRequest,no_elements,offset) + struct dbAddr *paddr; + char *pbuffer; + long nRequest; + long no_elements; + long offset; +{ + short choice_set=paddr->choice_set; + short choice_ind= *((short*)paddr->pfield); + char *pchoice; + struct choiceSet *pchoiceSet; + + if(no_elements!=1){ + recGblDbaddrError(S_db_onlyOne,paddr,"dbGet(getGchoiceString)"); + return(S_db_onlyOne); + } + if((!(pchoiceSet=GET_PCHOICE_SET(pdbBase->pchoiceGbl,choice_set))) + || (!(pchoice=GET_CHOICE(pchoiceSet,choice_ind))) ) { + recGblDbaddrError(S_db_badChoice,paddr,"dbGet(getGchoiceString)"); + return(S_db_badChoice); + } + strncpy(pbuffer,pchoice,MAX_STRING_SIZE); + return(0); +} + +static long getCchoiceString(paddr,pbuffer,nRequest,no_elements,offset) + struct dbAddr *paddr; + char *pbuffer; + long nRequest; + long no_elements; + long offset; +{ + short choice_ind= *((short*)paddr->pfield); + char *pchoice; + + if(no_elements!=1){ + recGblDbaddrError(S_db_onlyOne,paddr,"dbGet(getCchoiceString)"); + return(S_db_onlyOne); + } + if (!(pchoice=GET_CHOICE(pdbBase->pchoiceCvt,choice_ind))) { + recGblDbaddrError(S_db_badChoice,paddr,"dbGet(getCchoiceString)"); + return(S_db_badChoice); + } + strncpy(pbuffer,pchoice,MAX_STRING_SIZE); + return(0); +} + + +static long getRchoiceString(paddr,pbuffer,nRequest,no_elements,offset) + struct dbAddr *paddr; + char *pbuffer; + long nRequest; + long no_elements; + long offset; +{ + short choice_set=paddr->choice_set; + short choice_ind= *((short*)paddr->pfield); + struct choiceSet *pchoiceSet; + struct arrChoiceSet *parrChoiceSet; + char *pchoice; + + if(no_elements!=1){ + recGblDbaddrError(S_db_onlyOne,paddr,"dbGet(getRchoiceString)"); + return(S_db_onlyOne); + } + if((!(parrChoiceSet=GET_PARR_CHOICE_SET(pdbBase->pchoiceRec,(paddr->record_type)))) + || (!(pchoiceSet=GET_PCHOICE_SET(parrChoiceSet,choice_set))) + || (!(pchoice=GET_CHOICE(pchoiceSet,choice_ind))) ) { + recGblDbaddrError(S_db_badChoice,paddr,"dbGet(getRchoiceString)"); + return(S_db_badChoice); + } + strncpy(pbuffer,pchoice,MAX_STRING_SIZE); + return(0); +} + + +static long getDchoiceString(paddr,pbuffer,nRequest,no_elements,offset) + struct dbAddr *paddr; + char *pbuffer; + long nRequest; + long no_elements; + long offset; +{ + short choice_ind= *((short*)paddr->pfield); + struct devChoiceSet *pdevChoiceSet; + struct devChoice *pdevChoice; + + if(no_elements!=1){ + recGblDbaddrError(S_db_onlyOne,paddr,"dbGet(getDchoiceString)"); + return(S_db_onlyOne); + } + if((!(pdevChoiceSet=GET_PDEV_CHOICE_SET(pdbBase->pchoiceDev,paddr->record_type))) + || (!(pdevChoice=GET_DEV_CHOICE(pdevChoiceSet,choice_ind))) ) { + recGblDbaddrError(S_db_badChoice,paddr,"dbGet(getRchoiceString)"); + return(S_db_badChoice); + } + strncpy(pbuffer,pdevChoice->pchoice,MAX_STRING_SIZE); + return(0); +} + +/* This is the table of routines for converting database fields */ +/* the rows represent the field type of the database field */ +/* the columns represent the types of the buffer in which they are placed */ + +/* buffer types are******************************************************** + DBR_STRING, DBR_CHR, DBR_UCHAR, DBR_SHORT, DBR_USHORT, + DBR_LONG, DBR_ULONG, DBR_FLOAT, DBR_DOUBLE, DBR_ENUM + ***************************************************************************/ + +long (*get_convert_table[DBF_DEVCHOICE+1][DBR_ENUM+1])() = { + +/* source is a DBF_STRING */ +{getStringString, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL}, +/* source is a DBF_CHAR */ +{getCharString, getCharChar, getCharUchar, getCharShort, getCharUshort, + getCharLong, getCharUlong, getCharFloat, getCharDouble, getCharEnum}, +/* source is a DBF_UCHAR */ +{getUcharString, getUcharChar, getUcharUchar, getUcharShort, getUcharUshort, + getUcharLong, getUcharUlong, getUcharFloat, getUcharDouble, getUcharEnum}, +/* source is a DBF_SHORT */ +{getShortString, getShortChar, getShortUchar, getShortShort, getShortUshort, + getShortLong, getShortUlong, getShortFloat, getShortDouble, getShortEnum}, +/* source is a DBF_USHORT */ +{getUshortString, getUshortChar, getUshortUchar, getUshortShort, getUshortUshort, + getUshortLong, getUshortUlong, getUshortFloat, getUshortDouble, getUshortEnum}, +/* source is a DBF_LONG */ +{getLongString, getLongChar, getLongUchar, getLongShort, getLongUshort, + getLongLong, getLongUlong, getLongFloat, getLongDouble, getLongEnum}, +/* source is a DBF_ULONG */ +{getUlongString, getUlongChar, getUlongUchar, getUlongShort, getUlongUshort, + getUlongLong, getUlongUlong, getUlongFloat, getUlongDouble, getUlongEnum}, +/* source is a DBF_FLOAT */ +{getFloatString, getFloatChar, getFloatUchar, getFloatShort, getFloatUshort, + getFloatLong, getFloatUlong, getFloatFloat, getFloatDouble, getFloatEnum}, +/* source is a DBF_DOUBLE */ +{getDoubleString, getDoubleChar, getDoubleUchar, getDoubleShort, getDoubleUshort, + getDoubleLong, getDoubleUlong, getDoubleFloat, getDoubleDouble, getDoubleEnum}, +/* source is a DBF_ENUM */ +{getEnumString, getEnumChar, getEnumUchar, getEnumShort, getEnumUshort, + getEnumLong, getEnumUlong, getEnumFloat, getEnumDouble, getEnumEnum}, +/* source is a DBF_GBLCHOICE */ +{getGchoiceString,getEnumChar, getEnumUchar, getEnumShort, getEnumUshort, + getEnumLong, getEnumUlong, getEnumFloat, getEnumDouble, getEnumEnum}, +/* source is a DBF_CVTCHOICE */ +{getCchoiceString,getEnumChar, getEnumUchar, getEnumShort, getEnumUshort, + getEnumLong, getEnumUlong, getEnumFloat, getEnumDouble, getEnumEnum}, +/* source is a DBF_RECCHOICE */ +{getRchoiceString,getEnumChar, getEnumUchar, getEnumShort, getEnumUshort, + getEnumLong, getEnumUlong, getEnumFloat, getEnumDouble, getEnumEnum}, +/* source is a DBF_DEVCHOICE */ +{getDchoiceString,getEnumChar, getEnumUchar, getEnumShort, getEnumUshort, + getEnumLong, getEnumUlong, getEnumFloat, getEnumDouble, getEnumEnum} +}; + + +/* forward references for private routines used by dbGet */ +static void get_enum_strs(struct dbAddr *paddr,void **ppbuffer, + struct rset *prset,long *options); +static void get_graphics(struct dbAddr *paddr,void **ppbuffer, + struct rset *prset,long *options); +static void get_control(struct dbAddr *paddr,void **ppbuffer, + struct rset *prset,long *options); +static void get_alarm(struct dbAddr *paddr,void **ppbuffer, + struct rset *prset,long *options); + +long dbGet( +struct dbAddr *paddr, +short dbrType, +void *pbuffer, +long *options, +long *nRequest, +void *pflin +) +{ + db_field_log *pfl= (db_field_log *)pflin; + long no_elements=paddr->no_elements; + long offset; + struct rset *prset; + short field_type=paddr->field_type; + long (*pconvert_routine)(); + struct dbCommon *pcommon; + long status; + long *perr_status=NULL; + + + prset=GET_PRSET(pdbBase->precSup,paddr->record_type); + + if(!(*options)) goto GET_DATA; + + /* Process options */ + pcommon = (struct dbCommon *)(paddr->precord); + if( (*options) & DBR_STATUS ) { + if(pfl!=NULL) { + *((unsigned short *)pbuffer)++ = pfl->stat; + *((unsigned short *)pbuffer)++ = pfl->sevr; + } else { + *((unsigned short *)pbuffer)++ = pcommon->stat; + *((unsigned short *)pbuffer)++ = pcommon->sevr; + } + *((unsigned short *)pbuffer)++ = pcommon->acks; + *((unsigned short *)pbuffer)++ = pcommon->ackt; + *perr_status = 0; + } + if( (*options) & DBR_UNITS ) { + if( prset && prset->get_units ){ + (*prset->get_units)(paddr,pbuffer); + } else { + memset(pbuffer,'\0',dbr_units_size); + *options = (*options) ^ DBR_UNITS; /*Turn off DBR_UNITS*/ + } + pbuffer += dbr_units_size; + } + if( (*options) & DBR_PRECISION ) { + struct dbr_precision *pdbr_precision=( struct dbr_precision *)pbuffer; + + if((field_type==DBF_FLOAT || field_type==DBF_DOUBLE) && prset && prset->get_precision ){ + (*prset->get_precision)(paddr,pbuffer); + if(pdbr_precision->field_width<=0) + pdbr_precision->field_width = pdbr_precision->precision + 5; + } else { + memset(pbuffer,'\0',dbr_precision_size); + *options = (*options) ^ DBR_PRECISION; /*Turn off DBR_PRECISION*/ + } + pbuffer += dbr_precision_size; + } + if( (*options) & DBR_TIME ) { + if(pfl!=NULL) { + *((unsigned long *)pbuffer)++ = pfl->time.secPastEpoch; + *((unsigned long *)pbuffer)++ = pfl->time.nsec; + } else { + *((unsigned long *)pbuffer)++ = pcommon->time.secPastEpoch; + *((unsigned long *)pbuffer)++ = pcommon->time.nsec; + } + } + if( (*options) & DBR_ENUM_STRS ) get_enum_strs(paddr,&pbuffer,prset,options); + if( (*options) & (DBR_GR_LONG|DBR_GR_DOUBLE )) + get_graphics(paddr,&pbuffer,prset,options); + if((*options) & (DBR_CTRL_LONG | DBR_CTRL_DOUBLE )) + get_control(paddr,&pbuffer,prset,options); + if((*options) & (DBR_AL_LONG | DBR_AL_DOUBLE )) + get_alarm(paddr,&pbuffer,prset,options); + + +GET_DATA: + + if(*nRequest==0) return(0); + /* Check for valid request */ + if( INVALID_DB_REQ(dbrType) || (field_type>DBF_DEVCHOICE) ){ + char message[80]; + + sprintf(message,"dbGet - database request type is %d",dbrType); + recGblDbaddrError(S_db_badDbrtype,paddr,message); + if(perr_status) *perr_status = S_db_badDbrtype; + return(S_db_badDbrtype); + } + + /* check for array */ + if( no_elements>1 && prset && (prset->get_array_info) ) { + status = (*prset->get_array_info)(paddr,&no_elements,&offset); + } + else offset=0; + if(no_elements<(*nRequest)) *nRequest = no_elements; + if(!(pconvert_routine=get_convert_table[field_type][dbrType])) { + char message[80]; + + sprintf(message,"dbGet - database request type is %d",dbrType); + recGblDbaddrError(S_db_badDbrtype,paddr,message); + if(perr_status) *perr_status = S_db_badDbrtype; + return(S_db_badDbrtype); + } + /* convert database field to buffer type and place it in the buffer */ + if(pfl!=NULL) { + struct dbAddr localAddr; + + memcpy(&localAddr,paddr,sizeof(localAddr)); + /*Use longest field size*/ + localAddr.pfield = (char *)&pfl->field; + status=(*pconvert_routine)(&localAddr,pbuffer,*nRequest, + no_elements,offset); + } else { + status=(*pconvert_routine)(paddr,pbuffer,*nRequest, + no_elements,offset); + } + if(perr_status) *perr_status = status; + return(status); +} + +static void get_enum_strs(struct dbAddr *paddr,void **ppbuffer, + struct rset *prset,long *options) +{ + short field_type=paddr->field_type; + struct choiceSet *pchoiceSet; + struct arrChoiceSet *parrChoiceSet; + struct devChoice *pdevChoice; + struct devChoiceSet *pdevChoiceSet; + unsigned long no_str; + char *ptemp; + struct dbr_enumStrs *pdbr_enumStrs=(struct dbr_enumStrs*)(*ppbuffer); + int i; + + memset(pdbr_enumStrs,'\0',dbr_enumStrs_size); + switch(field_type) { case DBF_ENUM: if( prset && prset->get_enum_strs ) { + (*prset->get_enum_strs)(paddr,pdbr_enumStrs); + } else { + *options = (*options)^DBR_ENUM_STRS;/*Turn off option*/ + } + break; + case DBF_GBLCHOICE: + pchoiceSet=GET_PCHOICE_SET(pdbBase->pchoiceGbl,paddr->choice_set); + goto choice_common; + case DBF_CVTCHOICE: + pchoiceSet=pdbBase->pchoiceCvt; + goto choice_common; + case DBF_RECCHOICE: + parrChoiceSet=GET_PARR_CHOICE_SET(pdbBase->pchoiceRec, + paddr->record_type); + pchoiceSet=GET_PCHOICE_SET(parrChoiceSet,paddr->choice_set); +choice_common: + if(pchoiceSet==NULL) { + *options = (*options)^DBR_ENUM_STRS;/*Turn off option*/ + break; + } + i = sizeof(pdbr_enumStrs->strs)/sizeof(pdbr_enumStrs->strs[0]); + no_str=min(pchoiceSet->number,i); + pdbr_enumStrs->no_str = no_str; + ptemp = &(pdbr_enumStrs->strs[0][0]); + for (i=0; ipapChoice[i]==NULL) *ptemp=0; + else { + strncpy(ptemp,pchoiceSet->papChoice[i],sizeof(pdbr_enumStrs->strs[0])); + *(ptemp+sizeof(pdbr_enumStrs->strs[0])-1) = 0; + } + ptemp += sizeof(pdbr_enumStrs->strs[0]); + } + break; + case DBF_DEVCHOICE: + pdevChoiceSet=GET_PDEV_CHOICE_SET(pdbBase->pchoiceDev, + paddr->record_type); + if(pdevChoiceSet==NULL) { + *options = (*options)^DBR_ENUM_STRS;/*Turn off option*/ + break; + } + i = sizeof(pdbr_enumStrs->strs)/sizeof(pdbr_enumStrs->strs[0]); + no_str=min(pdevChoiceSet->number,i); + pdbr_enumStrs->no_str = no_str; + ptemp = &(pdbr_enumStrs->strs[0][0]); + for (i=0; ipchoice==NULL) + *ptemp=0; + else { + strncpy(ptemp,pdevChoice->pchoice,sizeof(pdbr_enumStrs->strs[0])); + *(ptemp+sizeof(pdbr_enumStrs->strs[0])-1) = 0; + } + ptemp += sizeof(pdbr_enumStrs->strs[0]); + } + break; + default: + *options = (*options)^DBR_ENUM_STRS;/*Turn off option*/ + break; + } + *ppbuffer += dbr_enumStrs_size; + return; +} + +static void get_graphics(struct dbAddr *paddr,void **ppbuffer, + struct rset *prset,long *options) +{ + struct dbr_grDouble grd; + int got_data=FALSE; + + if( prset && prset->get_graphic_double ) { + (*prset->get_graphic_double)(paddr,&grd); + got_data=TRUE; + } + if( (*options) & (DBR_GR_LONG) ) { + char *pbuffer=*ppbuffer; + + if(got_data) { + struct dbr_grLong *pgr=(struct dbr_grLong*)pbuffer; + pgr->upper_disp_limit = grd.upper_disp_limit; + pgr->lower_disp_limit = grd.lower_disp_limit; + } else { + memset(pbuffer,'\0',dbr_grLong_size); + *options = (*options) ^ DBR_GR_LONG; /*Turn off option*/ + } + *ppbuffer += dbr_grLong_size; + } + if( (*options) & (DBR_GR_DOUBLE) ) { + char *pbuffer=*ppbuffer; + + if(got_data) { + struct dbr_grDouble *pgr=(struct dbr_grDouble*)pbuffer; + pgr->upper_disp_limit = grd.upper_disp_limit; + pgr->lower_disp_limit = grd.lower_disp_limit; + } else { + memset(pbuffer,'\0',dbr_grDouble_size); + *options = (*options) ^ DBR_GR_DOUBLE; /*Turn off option*/ + } + *ppbuffer += dbr_grDouble_size; + } + return; +} + +static void get_control(struct dbAddr *paddr,void **ppbuffer, + struct rset *prset,long *options) +{ + struct dbr_ctrlDouble ctrld; + int got_data=FALSE; + + if( prset && prset->get_control_double ) { + (*prset->get_control_double)(paddr,&ctrld); + got_data=TRUE; + } + if( (*options) & (DBR_CTRL_LONG) ) { + char *pbuffer=*ppbuffer; + + if(got_data) { + struct dbr_ctrlLong *pctrl=(struct dbr_ctrlLong*)pbuffer; + pctrl->upper_ctrl_limit = ctrld.upper_ctrl_limit; + pctrl->lower_ctrl_limit = ctrld.lower_ctrl_limit; + } else { + memset(pbuffer,'\0',dbr_ctrlLong_size); + *options = (*options) ^ DBR_CTRL_LONG; /*Turn off option*/ + } + *ppbuffer += dbr_ctrlLong_size; + } + if( (*options) & (DBR_CTRL_DOUBLE) ) { + char *pbuffer=*ppbuffer; + + if(got_data) { + struct dbr_ctrlDouble *pctrl=(struct dbr_ctrlDouble*)pbuffer; + pctrl->upper_ctrl_limit = ctrld.upper_ctrl_limit; + pctrl->lower_ctrl_limit = ctrld.lower_ctrl_limit; + } else { + memset(pbuffer,'\0',dbr_ctrlDouble_size); + *options = (*options) ^ DBR_CTRL_DOUBLE; /*Turn off option*/ + } + *ppbuffer += dbr_ctrlDouble_size; + } + return; +} + +static void get_alarm(struct dbAddr *paddr,void **ppbuffer, + struct rset *prset,long *options) +{ + struct dbr_alDouble ald; + int got_data=FALSE; + + if( prset && prset->get_alarm_double ) { + (*prset->get_alarm_double)(paddr,&ald); + got_data=TRUE; + } + if( (*options) & (DBR_AL_LONG) ) { + char *pbuffer=*ppbuffer; + + if(got_data) { + struct dbr_alLong *pal=(struct dbr_alLong*)pbuffer; + pal->upper_alarm_limit = ald.upper_alarm_limit; + pal->upper_warning_limit = ald.upper_warning_limit; + pal->lower_warning_limit = ald.lower_warning_limit; + pal->lower_alarm_limit = ald.lower_alarm_limit; + } else { + memset(pbuffer,'\0',dbr_alLong_size); + *options = (*options) ^ DBR_AL_LONG; /*Turn off option*/ + } + *ppbuffer += dbr_alLong_size; + } + if( (*options) & (DBR_AL_DOUBLE) ) { + char *pbuffer=*ppbuffer; + + if(got_data) { + struct dbr_alDouble *pal=(struct dbr_alDouble*)pbuffer; + pal->upper_alarm_limit = ald.upper_alarm_limit; + pal->upper_warning_limit = ald.upper_warning_limit; + pal->lower_warning_limit = ald.lower_warning_limit; + pal->lower_alarm_limit = ald.lower_alarm_limit; + } else { + memset(pbuffer,'\0',dbr_alDouble_size); + *options = (*options) ^ DBR_AL_DOUBLE; /*Turn off option*/ + } + *ppbuffer += dbr_alDouble_size; + } + return; +} + +/* DATABASE ACCESS PUT CONVERSION SUPPORT */ + +static long putStringString(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *pdest=paddr->pfield; + short size=paddr->field_size; + + if(nRequest==1 && offset==0) { + strncpy(pdest,pbuffer,size); + *(pdest+size-1) = 0; + return(0); + } + pdest+= (size*offset); + while (nRequest) { + strncpy(pdest,pbuffer,size); + *(pdest+size-1) = 0; + pbuffer += MAX_STRING_SIZE; + if(++offset==no_elements) + pdest=paddr->pfield; + else + pdest += size; + nRequest--; + } + return(0); +} + +static long putStringChar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *pdest=(char *)paddr->pfield; + short value; + + if(nRequest==1 && offset==0) { + if(sscanf(pbuffer,"%hd",&value) == 1) { + *pdest = (char)value; + return(0); + } + else return(-1); + } + return(-1); +} + +static long putStringUchar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned char *pdest=(unsigned char *)paddr->pfield; + unsigned short value; + + if(nRequest==1 && offset==0) { + if(sscanf(pbuffer,"%hu",&value) == 1) { + *pdest = (unsigned char)value; + return(0); + } + else return(-1); + } + return(-1); +} + +static long putStringShort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + short *pdest=(short *)paddr->pfield; + short value; + + if(nRequest==1 && offset==0) { + if(sscanf(pbuffer,"%hd",&value) == 1) { + *pdest = value; + return(0); + } + else return(-1); + } + return(-1); +} + +static long putStringUshort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *pdest=(unsigned short *)paddr->pfield; + unsigned short value; + + if(nRequest==1 && offset==0) { + if(sscanf(pbuffer,"%hu",&value) == 1) { + *pdest = value; + return(0); + } + else return(-1); + } + return(-1); +} + +static long putStringLong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + long *pdest=(long *)paddr->pfield; + long value; + + if(nRequest==1 && offset==0) { + if(sscanf(pbuffer,"%ld",&value) == 1) { + *pdest = value; + return(0); + } + else return(-1); + } + return(-1); +} + +static long putStringUlong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned long *pdest=(unsigned long *)paddr->pfield; + unsigned long value; + + if(nRequest==1 && offset==0) { + if(sscanf(pbuffer,"%lu",&value) == 1) { + *pdest = value; + return(0); + } + else return(-1); + } + return(-1); +} + +static long putStringFloat(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + float *pdest=(float *)paddr->pfield; + float value; + + if(nRequest==1 && offset==0) { + if(sscanf(pbuffer,"%f",&value) == 1) { + *pdest = value; + return(0); + } + } + return(-1); +} + +static long putStringDouble(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + double *pdest=(double *)paddr->pfield; + double value; + + if(nRequest==1 && offset==0) { + if(sscanf(pbuffer,"%lf",&value) == 1) { + *pdest = value; + return(0); + } + } + return(-1); +} + +static long putStringEnum(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + struct rset *prset; + short record_type=(paddr->record_type); + long status; + + if((prset=GET_PRSET(pdbBase->precSup,record_type)) && (prset->put_enum_str)) + return( (*prset->put_enum_str)(paddr,pbuffer) ); + status=S_db_noRSET; + recGblRecSupError(status,paddr,"dbPutField","put_enum_str"); + return(S_db_badDbrtype); +} + +static long putStringGchoice(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + short choice_set=paddr->choice_set; + unsigned short *pfield= (unsigned short*)(paddr->pfield); + char *pchoice; + struct choiceSet *pchoiceSet; + unsigned short i; + + if(no_elements!=1){ + recGblDbaddrError(S_db_onlyOne,paddr,"dbPut(putStringGchoice)"); + return(S_db_onlyOne); + } + if(pchoiceSet=GET_PCHOICE_SET(pdbBase->pchoiceGbl,choice_set)) { + for(i=0; inumber; i++) { + if(!(pchoice=pchoiceSet->papChoice[i])) continue; + if(strcmp(pchoice,pbuffer)==0) { + *pfield=i; + return(0); + } + } + } + recGblDbaddrError(S_db_badChoice,paddr,"dbPut(putStringGchoice)"); + return(S_db_badChoice); +} + +static long putStringCchoice(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *pfield= (unsigned short*)(paddr->pfield); + char *pchoice; + struct choiceSet *pchoiceSet; + unsigned short i; + + if(no_elements!=1){ + recGblDbaddrError(S_db_onlyOne,paddr,"dbPut(putStringCchoice)"); + return(S_db_onlyOne); + } + if(pchoiceSet=pdbBase->pchoiceCvt) { + for(i=0; inumber; i++) { + if(!(pchoice=pchoiceSet->papChoice[i])) continue; + if(strcmp(pchoice,pbuffer)==0) { + *pfield=i; + return(0); + } + } + } + recGblDbaddrError(S_db_badChoice,paddr,"dbPut(putStringCchoice)"); + return(S_db_badChoice); +} + +static long putStringRchoice(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + short choice_set=paddr->choice_set; + unsigned short *pfield= (unsigned short*)(paddr->pfield); + char *pchoice; + struct choiceSet *pchoiceSet; + struct arrChoiceSet *parrChoiceSet; + unsigned short i; + + if(no_elements!=1){ + recGblDbaddrError(S_db_onlyOne,paddr,"dbPut(putStringRchoice)"); + return(S_db_onlyOne); + } + if((parrChoiceSet=GET_PARR_CHOICE_SET(pdbBase->pchoiceRec,(paddr->record_type))) + && (pchoiceSet=GET_PCHOICE_SET(parrChoiceSet,choice_set))) { + for(i=0; inumber; i++) { + if(!(pchoice=pchoiceSet->papChoice[i])) continue; + if(strcmp(pchoice,pbuffer)==0) { + *pfield=i; + return(0); + } + } + } + recGblDbaddrError(S_db_badChoice,paddr,"dbPut(putStringRchoice)"); + return(S_db_badChoice); +} + +static long putStringDchoice(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *pfield= (unsigned short*)(paddr->pfield); + struct devChoiceSet *pdevChoiceSet; + char *pchoice; + unsigned short i; + + if(no_elements!=1){ + recGblDbaddrError(S_db_onlyOne,paddr,"dbPut(putStringDchoice)"); + return(S_db_onlyOne); + } + if(pdevChoiceSet=GET_PDEV_CHOICE_SET(pdbBase->pchoiceDev,paddr->record_type)) { + for(i=0; inumber; i++) { + if(!(pchoice=pdevChoiceSet->papDevChoice[i]->pchoice)) continue; + if(strcmp(pchoice,pbuffer)==0) { + *pfield=i; + return(0); + } + } + } + recGblDbaddrError(S_db_badChoice,paddr,"dbPut(putStringDchoice)"); + return(S_db_badChoice); +} + +static long putCharString(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *pdest=(char *)(paddr->pfield); + short size=paddr->field_size; + + + if(nRequest==1 && offset==0) { + cvtCharToString(*pbuffer,pdest); + return(0); + } + pdest += (size*offset); + while (nRequest) { + cvtCharToString(*pbuffer,pdest); + pbuffer++; + if(++offset==no_elements) + pdest=paddr->pfield; + else + pdest += size; + nRequest--; + } + return(0); +} + +static long putCharChar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *pdest=(char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putCharUchar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned char *pdest=(unsigned char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putCharShort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + short *pdest=(short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putCharUshort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *pdest=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putCharLong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + long *pdest=(long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putCharUlong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned long *pdest=(unsigned long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putCharFloat(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + float *pdest=(float *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(float *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putCharDouble(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + double *pdest=(double *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(double *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putCharEnum(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *pdest=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUcharString(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *pdest=(char *)(paddr->pfield); + short size=paddr->field_size; + + + if(nRequest==1 && offset==0) { + cvtUcharToString(*pbuffer,pdest); + return(0); + } + pdest += (size*offset); + while (nRequest) { + cvtUcharToString(*pbuffer,pdest); + pbuffer++; + if(++offset==no_elements) + pdest=paddr->pfield; + else + pdest += size; + nRequest--; + } + return(0); +} + +static long putUcharChar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *pdest=(char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUcharUchar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned char *pdest=(unsigned char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUcharShort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + short *pdest=(short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUcharUshort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *pdest=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUcharLong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + long *pdest=(long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUcharUlong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned long *pdest=(unsigned long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUcharFloat(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + float *pdest=(float *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(float *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUcharDouble(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + double *pdest=(double *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(double *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUcharEnum(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned char *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *pdest=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putShortString(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *pdest=(char *)(paddr->pfield); + short size=paddr->field_size; + + + if(nRequest==1 && offset==0) { + cvtShortToString(*pbuffer,pdest); + return(0); + } + pdest += (size*offset); + while (nRequest) { + cvtShortToString(*pbuffer,pdest); + pbuffer++; + if(++offset==no_elements) + pdest=(char *)paddr->pfield; + else + pdest += size; + nRequest--; + } + return(0); +} + +static long putShortChar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *pdest=(char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putShortUchar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned char *pdest=(unsigned char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putShortShort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + short *pdest=(short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putShortUshort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *pdest=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putShortLong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + long *pdest=(long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putShortUlong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned long *pdest=(unsigned long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putShortFloat(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + float *pdest=(float *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(float *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putShortDouble(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + double *pdest=(double *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(double *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putShortEnum(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *pdest=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUshortString(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *pdest=(char *)(paddr->pfield); + short size=paddr->field_size; + + + if(nRequest==1 && offset==0) { + cvtUshortToString(*pbuffer,pdest); + return(0); + } + pdest += (size*offset); + while (nRequest) { + cvtUshortToString(*pbuffer,pdest); + pbuffer++; + if(++offset==no_elements) + pdest=(char *)paddr->pfield; + else + pdest += size; + nRequest--; + } + return(0); +} + +static long putUshortChar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *pdest=(char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUshortUchar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned char *pdest=(unsigned char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUshortShort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + short *pdest=(short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUshortUshort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *pdest=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUshortLong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + long *pdest=(long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUshortUlong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned long *pdest=(unsigned long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUshortFloat(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + float *pdest=(float *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(float *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUshortDouble(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + double *pdest=(double *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(double *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUshortEnum(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *pdest=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putLongString(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *pdest=(char *)(paddr->pfield); + short size=paddr->field_size; + + + if(nRequest==1 && offset==0) { + cvtLongToString(*pbuffer,pdest); + return(0); + } + pdest += (size*offset); + while (nRequest) { + cvtLongToString(*pbuffer,pdest); + pbuffer++; + if(++offset==no_elements) + pdest=(char *)paddr->pfield; + else + pdest += size; + nRequest--; + } + return(0); +} + +static long putLongChar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *pdest=(char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putLongUchar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned char *pdest=(unsigned char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putLongShort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + short *pdest=(short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putLongUshort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *pdest=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putLongLong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + long *pdest=(long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putLongUlong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned long *pdest=(unsigned long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putLongFloat(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + float *pdest=(float *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(float *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putLongDouble(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + double *pdest=(double *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(double *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putLongEnum(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *pdest=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUlongString(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *pdest=(char *)(paddr->pfield); + short size=paddr->field_size; + + + if(nRequest==1 && offset==0) { + cvtUlongToString(*pbuffer,pdest); + return(0); + } + pdest += (size*offset); + while (nRequest) { + cvtUlongToString(*pbuffer,pdest); + pbuffer++; + if(++offset==no_elements) + pdest=(char *)paddr->pfield; + else + pdest += size; + nRequest--; + } + return(0); +} + +static long putUlongChar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *pdest=(char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUlongUchar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned char *pdest=(unsigned char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUlongShort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + short *pdest=(short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUlongUshort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *pdest=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUlongLong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + long *pdest=(long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUlongUlong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned long *pdest=(unsigned long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUlongFloat(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + float *pdest=(float *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(float *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUlongDouble(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + double *pdest=(double *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(double *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putUlongEnum(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned long *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *pdest=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putFloatString(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +float *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *pdest=(char *)(paddr->pfield); + long status; + int precision; + short record_type=paddr->record_type; + struct rset *prset; + short size=paddr->field_size; + + if((prset=GET_PRSET(pdbBase->precSup,record_type)) && (prset->get_precision)) + status = (*prset->get_precision)(paddr,&precision); + else + status=S_db_precision; + if(!RTN_SUCCESS(status)) { + recGblRecSupError(status,paddr,"dbPutField","get_precision"); + return(status); + } + + if(nRequest==1 && offset==0) { + cvtFloatToString(*pbuffer,pdest,precision); + return(0); + } + pdest += (size*offset); + while (nRequest) { + cvtFloatToString(*pbuffer,pdest,precision); + pbuffer++; + if(++offset==no_elements) + pdest=(char *)paddr->pfield; + else + pdest += size; + nRequest--; + } + return(0); +} + +static long putFloatChar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +float *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *pdest=(char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putFloatUchar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +float *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned char *pdest=(unsigned char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putFloatShort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +float *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + short *pdest=(short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putFloatUshort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +float *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *pdest=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putFloatLong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +float *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + long *pdest=(long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putFloatUlong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +float *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned long *pdest=(unsigned long *)(paddr->pfield); + long ltemp;/*vxWorks does not support float to unsigned long*/ + + if(nRequest==1 && offset==0) { + ltemp = *pbuffer; + *pdest = ltemp; + return(0); + } + pdest += offset; + while (nRequest) { + ltemp = *pbuffer++; + *pdest++ = ltemp; + if(++offset==no_elements) pdest=(unsigned long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putFloatFloat(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +float *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + float *pdest=(float *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(float *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putFloatDouble(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +float *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + double *pdest=(double *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(double *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putFloatEnum(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +float *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *pdest=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putDoubleString(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +double *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *pdest=(char *)(paddr->pfield); + long status; + int precision; + short record_type=paddr->record_type; + struct rset *prset; + short size=paddr->field_size; + + if((prset=GET_PRSET(pdbBase->precSup,record_type)) && (prset->get_precision)) + status = (*prset->get_precision)(paddr,&precision); + else + status=S_db_precision; + if(!RTN_SUCCESS(status)) { + recGblRecSupError(status,paddr,"dbPutField","get_precision"); + return(status); + } + + if(nRequest==1 && offset==0) { + cvtDoubleToString(*pbuffer,pdest,precision); + return(0); + } + pdest += (size*offset); + while (nRequest) { + cvtDoubleToString(*pbuffer,pdest,precision); + pbuffer++; + if(++offset==no_elements) + pdest=(char *)paddr->pfield; + else + pdest += size; + nRequest--; + } + return(0); +} + +static long putDoubleChar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +double *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *pdest=(char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putDoubleUchar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +double *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned char *pdest=(unsigned char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putDoubleShort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +double *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + short *pdest=(short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putDoubleUshort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +double *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *pdest=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putDoubleLong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +double *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + long *pdest=(long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putDoubleUlong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +double *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned long *pdest=(unsigned long *)(paddr->pfield); + long ltemp;/*vxWorks does not support double to unsigned long*/ + + if(nRequest==1 && offset==0) { + ltemp = *pbuffer; + *pdest = ltemp; + return(0); + } + pdest += offset; + while (nRequest) { + ltemp = *pbuffer++; + *pdest++ = ltemp; + if(++offset==no_elements) pdest=(unsigned long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putDoubleFloat(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +double *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + float *pdest=(float *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(float *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putDoubleDouble(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +double *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + double *pdest=(double *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(double *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putDoubleEnum(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +double *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *pdest=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putEnumString(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *pdest=(char *)(paddr->pfield); + short size=paddr->field_size; + + + if(nRequest==1 && offset==0) { + cvtUshortToString(*pbuffer,pdest); + return(0); + } + pdest += (size*offset); + while (nRequest) { + cvtUshortToString(*pbuffer,pdest); + pbuffer++; + if(++offset==no_elements) + pdest=(char *)paddr->pfield; + else + pdest += size; + nRequest--; + } + return(0); +} + +static long putEnumChar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + char *pdest=(char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putEnumUchar(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned char *pdest=(unsigned char *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned char *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putEnumShort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + short *pdest=(short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putEnumUshort(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *pdest=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putEnumLong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + long *pdest=(long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putEnumUlong(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned long *pdest=(unsigned long *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned long *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putEnumFloat(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + float *pdest=(float *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(float *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putEnumDouble(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + double *pdest=(double *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(double *)paddr->pfield; + nRequest--; + } + return(0); +} + +static long putEnumEnum(paddr,pbuffer,nRequest,no_elements,offset) +struct dbAddr *paddr; +unsigned short *pbuffer; +long nRequest; +long no_elements; +long offset; +{ + unsigned short *pdest=(unsigned short *)(paddr->pfield); + + if(nRequest==1 && offset==0) { + *pdest = *pbuffer; + return(0); + } + pdest += offset; + while (nRequest) { + *pdest++ = *pbuffer++; + if(++offset==no_elements) pdest=(unsigned short *)paddr->pfield; + nRequest--; + } + return(0); +} + +/* This is the table of routines for converting database fields */ +/* the rows represent the buffer types */ +/* the columns represent the field types */ + +/* field types are******************************************************** + DBF_STRING, DBF_CHAR, DBF_UCHAR, DBF_SHORT, DBF_USHORT, + DBF_LONG, DBF_ULONG, DBF_FLOAT, DBF_DOUBLE, DBF_ENUM + DBF_GBLCHOICE, DBF_CVTCHOICE, DBF_RECCHOICE, DBF_DEVCHOICE + ***************************************************************************/ + +long (*put_convert_table[DBR_ENUM+1][DBF_DEVCHOICE+1])() = { +/* source is a DBR_STRING */ +{putStringString, putStringChar, putStringUchar, putStringShort, putStringUshort, + putStringLong, putStringUlong, putStringFloat, putStringDouble, putStringEnum, + putStringGchoice,putStringCchoice,putStringRchoice,putStringDchoice}, +/* source is a DBR_CHAR */ +{putCharString, putCharChar, putCharUchar, putCharShort, putCharUshort, + putCharLong, putCharUlong, putCharFloat, putCharDouble, putCharEnum, + putCharEnum, putCharEnum, putCharEnum, putCharEnum}, +/* source is a DBR_UCHAR */ +{putUcharString, putUcharChar, putUcharUchar, putUcharShort, putUcharUshort, + putUcharLong, putUcharUlong, putUcharFloat, putUcharDouble, putUcharEnum, + putUcharEnum, putUcharEnum, putUcharEnum, putUcharEnum}, +/* source is a DBR_SHORT */ +{putShortString, putShortChar, putShortUchar, putShortShort, putShortUshort, + putShortLong, putShortUlong, putShortFloat, putShortDouble, putShortEnum, + putShortEnum, putShortEnum, putShortEnum, putShortEnum}, +/* source is a DBR_USHORT */ +{putUshortString, putUshortChar, putUshortUchar, putUshortShort, putUshortUshort, + putUshortLong, putUshortUlong, putUshortFloat, putUshortDouble, putUshortEnum, + putUshortEnum, putUshortEnum, putUshortEnum, putUshortEnum}, +/* source is a DBR_LONG */ +{putLongString, putLongChar, putLongUchar, putLongShort, putLongUshort, + putLongLong, putLongUlong, putLongFloat, putLongDouble, putLongEnum, + putLongEnum, putLongEnum, putLongEnum, putLongEnum}, +/* source is a DBR_ULONG */ +{putUlongString, putUlongChar, putUlongUchar, putUlongShort, putUlongUshort, + putUlongLong, putUlongUlong, putUlongFloat, putUlongDouble, putUlongEnum, + putUlongEnum, putUlongEnum, putUlongEnum, putUlongEnum}, +/* source is a DBR_FLOAT */ +{putFloatString, putFloatChar, putFloatUchar, putFloatShort, putFloatUshort, + putFloatLong, putFloatUlong, putFloatFloat, putFloatDouble, putFloatEnum, + putFloatEnum, putFloatEnum, putFloatEnum, putFloatEnum}, +/* source is a DBR_DOUBLE */ +{putDoubleString, putDoubleChar, putDoubleUchar, putDoubleShort, putDoubleUshort, + putDoubleLong, putDoubleUlong, putDoubleFloat, putDoubleDouble, putDoubleEnum, + putDoubleEnum, putDoubleEnum, putDoubleEnum, putDoubleEnum}, +/* source is a DBR_ENUM */ +{putEnumString, putEnumChar, putEnumUchar, putEnumShort, putEnumUshort, + putEnumLong, putEnumUlong, putEnumFloat, putEnumDouble, putEnumEnum, + putEnumEnum, putEnumEnum, putEnumEnum, putEnumEnum} +}; + +long dbPut( + struct dbAddr *paddr, + short dbrType, + void *pbuffer, + long nRequest +) +{ + long no_elements=paddr->no_elements; + long dummy; + long offset; + long (*pconvert_routine)(); + long int (*pspecial)()=NULL; + struct rset *prset; + struct dbCommon *precord=(struct dbCommon *)(paddr->precord); + long status=0; + static char val[4]={'V','A','L',' '}; + long *pval=(long *)&val[0]; + struct fldDes *pfldDes; + long *pfield_name; + long special=paddr->special; + short field_type=paddr->field_type; + unsigned short acks=precord->acks; + + /* Check for valid request */ + if( INVALID_DB_REQ(dbrType) || (field_type>DBF_DEVCHOICE) + || (!(pconvert_routine=put_convert_table[dbrType][field_type])) ) + { + char message[80]; + + sprintf(message,"dbPut - database request type is %d",dbrType); + recGblDbaddrError(S_db_badDbrtype,paddr,message); + return(S_db_badDbrtype); + } + + prset=GET_PRSET(pdbBase->precSup,paddr->record_type); + + /* check for special processing is required */ + if(special) { + if(special<100) { /*global processing*/ + if(special==SPC_NOMOD) { + return(S_db_noMod); + }else if(special==SPC_SCAN){ + scanDelete(precord); + } + } + else { + if( prset && (pspecial = (prset->special))) { + status=(*pspecial)(paddr,0); + if(!RTN_SUCCESS(status)) return(status); + } else { + recGblRecSupError(S_db_noSupport,paddr,"dbPut", + "special"); + return(S_db_noSupport); + } + } + } + + /* check for array */ + if( no_elements>1 && prset && (prset->get_array_info) ) { + status= (*prset->get_array_info)(paddr,&dummy,&offset); + } + else offset=0; + if(no_elements<(nRequest)) nRequest = no_elements; + + /* convert database field to buffer type and place it in the buffer */ + status=(*pconvert_routine)(paddr,pbuffer,nRequest,no_elements,offset); + + /* update array info */ + if( no_elements>1 && prset && (prset->put_array_info) ) { + status= (*prset->put_array_info)(paddr,nRequest); + } + + if(!RTN_SUCCESS(status)) return(status); + + /* check for special processing is required */ + if(special) { + if(special<100) { /*global processing*/ + if(special==SPC_SCAN) { + scanAdd(precord); + } else if(special==SPC_ALARMACK) { + if(paddr->pfield == (void *)&precord->acks) { + if(acks>0 && acks<=precord->acks) { + precord->acks = 0; + db_post_events(precord,&precord->acks,DBE_VALUE); + } else { /*Undo change*/ + precord->acks = acks; + } + }else if(paddr->pfield == (void *)&precord->ackt) { + if(!precord->ackt && precord->acks>precord->sevr) { + precord->acks = precord->sevr; + db_post_events(precord,&precord->acks,DBE_VALUE); + } + } + } else if(special==SPC_AS) { + asChangeGroup(&precord->asp,precord->asg); + } + } + else { + status=(*pspecial)(paddr,1); + if(!RTN_SUCCESS(status)) return(status); + } + } + + /* propagate events for this field */ + /* if the field is VAL and process_passive is true dont propagate*/ + pfldDes = (struct fldDes *)(paddr->pfldDes); + pfield_name = (long *)&(pfldDes->fldname[0]); + /* if field is val set udf FALSE */ + if (*pval == *pfield_name) precord->udf=FALSE; + if(precord->mlis.count && + ((*pval != *pfield_name) || (!pfldDes->process_passive))) + db_post_events(precord,paddr->pfield,DBE_VALUE); + + return(status); +} diff --git a/src/db/dbScan.c b/src/db/dbScan.c index 01f4a79c0..6a45e294b 100644 --- a/src/db/dbScan.c +++ b/src/db/dbScan.c @@ -1,5 +1,5 @@ /* dbScan.c */ -/* share/src/db $Id$ */ +/* base/src/db $Id$ */ /* tasks and subroutines to scan the database */ /* diff --git a/src/db/dbStaticLib.c b/src/db/dbStaticLib.c index 077b515cd..a4b8372a0 100644 --- a/src/db/dbStaticLib.c +++ b/src/db/dbStaticLib.c @@ -1,5 +1,5 @@ /*dbStaticLib.c*/ -/* share/src/db $Id$ */ +/* base/src/db $Id$ */ /* * * Authors: Marty Kraimer diff --git a/src/db/dbTest.c b/src/db/dbTest.c index 2e0882228..6715543a8 100644 --- a/src/db/dbTest.c +++ b/src/db/dbTest.c @@ -1,5 +1,5 @@ /* dbTest.c */ -/* share/src/db $Id$ */ +/* base/src/db $Id$ */ /* database access test subroutines */ /* * Original Author: Bob Dalesio @@ -39,6 +39,7 @@ * .08 07-21-92 jba ansi c changes * .09 09-24-93 jbk adjusted dbpr to print vxi links correctly * .10 02-02-94 mrk added dbtpn (test dbPutNotify) + * .11 03-18-94 mcn added dbgrep and timing routines. */ /* Global Database Test Routines - All can be invoked via vxWorks shell @@ -52,6 +53,9 @@ * dbl(ptypeName) list record names. * char *ptypeName; Record type. If null all record types * + * dbgrep(pmask) list record names that match the mask + * char *pmask; + * * dbgf(pname) get field * char *pname; * @@ -85,6 +89,10 @@ * dblls(ptypeName) list lock sets * char *ptypeName; Record type. If null all record types * + * dbt(record_name) time 100 executions of "record_name" + * (includes what records are processed + * as a result of that record) + * */ #include @@ -232,6 +240,105 @@ long dbl(char *precdesname) return(0); } +static int specified_by(char *ptest, char *pspec) +{ + short inx; + short wild_card_start; + + /* check if the specification begins with a wild card */ + if (*pspec == '*') wild_card_start = TRUE; + else wild_card_start = FALSE; + + /* check for specification */ + while (TRUE) { + /* skip any wild cards */ + while (*pspec == '*') pspec++; + + /* find the specification chars to compare */ + inx = 0; + while ( (*(pspec+inx) != '*') && (*(pspec+inx)) ) + inx++; + + /* check for specification ending with wildcard */ + if (inx == 0) return(TRUE); + + /* find the spec chars in the test string */ + while ((strlen(ptest) >= inx) + && (strncmp(ptest,pspec,inx) != 0) ) { + + /* check variable beginning */ + if (!wild_card_start) return(FALSE); + else ptest++; + } + + /* check segment found */ + if (strlen(ptest) < inx) return(FALSE); + + /* adjust pointers and wild card indication */ + wild_card_start = TRUE; + ptest += inx; + pspec += inx; + + /* check for end of specification */ + if (*pspec == NULL) { + if (*ptest == NULL) return(TRUE); + else return(FALSE); + } + } +} + +long dbgrep(char *pmask) +{ + int rectype, beg, end; + struct recLoc *precLoc; + struct dbCommon *precord; + char *pstr; + char name[PVNAME_SZ+1]; + struct recType *precType; + struct recHeader *precHeader; + RECNODE *precNode; + + if (!pdbBase) { + printf("No database\n"); + return(0); + } + + if (!(precType = pdbBase->precType)) + return(0); + + if (!(precHeader = pdbBase->precHeader)) + return(0); + + beg = 0; + end = precHeader->number - 1; + + for (rectype = beg; rectype <= end; rectype++) { + + if (!(precLoc = GET_PRECLOC(precHeader, rectype))) + continue; + + /* + * Check if there are any record instances defined. + */ + if (precLoc->preclist == NULL) + continue; + + precNode = (RECNODE *) ellFirst(precLoc->preclist); + + for (; precNode != NULL; precNode = (RECNODE *) ellNext(&precNode->node)) { + precord = precNode->precord; + if (precord == NULL) continue; + if (precord->name == NULL) continue; + if (precord->name[0] == 0) continue; /* deleted record */ + + if (specified_by(precord->name, pmask)) { + printf("%s\n", precord->name); + } + } + } + return(0); +} + long dbgf(char *pname) { /* declare buffer long just to ensure correct alignment */ @@ -1660,3 +1767,53 @@ static struct recTypDes *dbprGetRecTypDes(short type) return (NULL); return (precTypDes); } + +/* + * Call dbProcess() 100 times to make + * sure Measurement is accurate, since + * timexN() makes use of the 60Hz clock + */ +static void timing_routine(precord) +struct dbCommon *precord; +{ + int i; + + for (i = 0; i <100; i++) { + dbProcess(precord); + } +} + +/* + * Time execution of record "record_name" + */ +long dbt(record_name) +char *record_name; +{ + struct dbAddr address; + struct dbCommon *precord; + long status = 0; + + /* + * Convert Name To Address + */ + status = dbNameToAddr(record_name, &address); + + if (status != 0) { + printf("Cannot locate %s.\n", record_name); + return(status); + } + + precord = address.precord; + + printf("!! Time for 100 executions of %s: !!\n", record_name); + + /* + * Time the record + */ + dbScanLock(precord); + timexN(timing_routine, precord); + dbScanUnlock(precord); + + return(0); +} + diff --git a/src/db/db_access.c b/src/db/db_access.c index fa6146a1b..a40c3269b 100644 --- a/src/db/db_access.c +++ b/src/db/db_access.c @@ -1,5 +1,5 @@ /* db_access.c */ -/* share/src/db $Id$ */ +/* base/src/db $Id$ */ /* db_access.c - Interface between old database access and new */ /* * Author: Bob Dalesio diff --git a/src/db/db_test.c b/src/db/db_test.c index a1ad57b5f..af9807bf4 100644 --- a/src/db/db_test.c +++ b/src/db/db_test.c @@ -1,4 +1,4 @@ -/* share/src/db $Id$ */ +/* base/src/db $Id$ */ /* database access subroutines */ /* * Author: Bob Dalesio diff --git a/src/db/dbta.c b/src/db/dbta.c index d202b77a5..c5be157dc 100644 --- a/src/db/dbta.c +++ b/src/db/dbta.c @@ -1,5 +1,5 @@ /*dbta.c*/ -/* share/src/db $Id$ */ +/* base/src/db $Id$ */ /* * * Author: Marty Kraimer diff --git a/src/db/devLib.c b/src/db/devLib.c index 9f259ccd7..4494ac566 100644 --- a/src/db/devLib.c +++ b/src/db/devLib.c @@ -1,5 +1,5 @@ /* devLib.c - support for allocation of common device resources */ -/* $Id$ */ +/* base/src/db $Id$ */ /* * Original Author: Marty Kraimer diff --git a/src/db/initHooks.c b/src/db/initHooks.c index 9ec003ab0..cd64163f4 100644 --- a/src/db/initHooks.c +++ b/src/db/initHooks.c @@ -1,5 +1,5 @@ /* initHooks.c ioc initialization hooks */ -/* share/src/db $Id$ */ +/* base/src/db $Id$ */ /* * Author: Marty Kraimer * Date: 06-01-91 diff --git a/src/db/iocInit.c b/src/db/iocInit.c index d95dd9968..c7810756a 100644 --- a/src/db/iocInit.c +++ b/src/db/iocInit.c @@ -1,5 +1,5 @@ /* iocInit.c ioc initialization */ -/* share/src/db $Id$ */ +/* base/src/db $Id$ */ /* * Author: Marty Kraimer * Date: 06-01-91 @@ -53,9 +53,11 @@ * .23 09-10-92 rcz changed funcptr pinitHooks from ret long to void * .24 09-11-92 rcz moved setMasterTimeToSelf to a seperate C file * .25 07-15-93 mrk Changed dbLoad for new dbStaticLib support - * .26 02-09-94 jbk changed to new time stamp support software ts_init() - * .27 03-23-94 mrk Added asInit - * +<<<<<<< iocInit.c + * .26 02-09-94 jbk changed to new time stamp support software ts_init() + * .27 03-18-94 mcn added comments + * .28 03-23-94 mrk Added asInit + * .29 04-04-94 mcn added code for uninitialized conversions (link conversion field) */ #include @@ -92,6 +94,7 @@ #include #include #include + /*This module will declare and initilize module_type variables*/ #define MODULE_TYPES_INIT 1 #include @@ -118,6 +121,9 @@ static long initialProcess(void); static long getResources(char *fname); void setMasterTimeToSelf(void); +/* + * Initialize EPICS on the IOC. + */ int iocInit(char * pResourceFilename) { long status; @@ -126,85 +132,206 @@ int iocInit(char * pResourceFilename) void (*pinitHooks)() = NULL; SYM_TYPE type; - if(initialized) { + if (initialized) { logMsg("iocInit can only be called once\n",0,0,0,0,0,0); return(-1); } + if (!pdbBase) { logMsg("iocInit aborting because No database loaded by dbLoad\n",0,0,0,0,0,0); return(-1); } - if((errSymBld())!=0) { + + /* + * Build the data structure for error reporting + */ + if ((errSymBld()) != 0) { logMsg("iocInit aborting because errSymBld failed to initialize \n",0,0,0,0,0,0); return(-1); } - /* if function initHooks exists setup ptr pinitHooks */ - strcpy(name,"_"); - strcat(name,"initHooks"); - rtnval = symFindByName(sysSymTbl,name,(void *)&pinitHooks,&type); - if( rtnval==OK && !(type&N_TEXT!=0)) { + + /* + * Setup initialization hooks, but only if an initHooks routine has been defined. + */ + strcpy(name, "_"); + strcat(name, "initHooks"); + rtnval = symFindByName(sysSymTbl, name, (void *) &pinitHooks, &type); + + /* + * Check to see if initHooks defined, and make sure it is a TEXT symbol (code) + * rather than any other kind of vxWorks symbol type. + */ + if (rtnval == OK && !((type & N_TEXT) != 0)) { logMsg("iocInit - WARNING symbol initHooks has wrong type - skipping all init hooks\n",0,0,0,0,0,0); pinitHooks=NULL; } + + /* Call the user-defined initialization hook before anything else is done */ if (pinitHooks) (*pinitHooks)(INITHOOKatBeginning); + + /* + * Print out version of iocCore + */ coreRelease(); + + /* + * Read EPICS environment + */ epicsSetEnvParams(); + + /* Hook after environment has been set */ if (pinitHooks) (*pinitHooks)(INITHOOKafterSetEnvParams); - status=getResources(pResourceFilename); - if(status!=0) { + + /* + * Read EPICS resources. + */ + status = getResources(pResourceFilename); + if (status != 0) { logMsg("iocInit aborting because getResources failed\n",0,0,0,0,0,0); return(-1); } + + /* Call hook for after resources are read. */ if (pinitHooks) (*pinitHooks)(INITHOOKafterGetResources); + + /* Initialize log client, and call hook */ status = iocLogInit(); - if(status!=0){ + if (status!=0) { logMsg("iocInit Failed to Initialize Ioc Log Client \n",0,0,0,0,0,0); } if (pinitHooks) (*pinitHooks)(INITHOOKafterLogInit); + + + /* + * After this point, further calls to iocInit() are disallowed. + */ initialized = TRUE; + + /* + * Initialize the watchdog task. These is different from vxWorks watchdogs, + * this task is assigned to watching and reporting if the vxWorks tasks + * (that it has been told to watch) are suspended. + */ taskwdInit(); + + /* + * Initialize EPICS callback tasks + */ callbackInit(); - /* wait 1/10 second */ + + /* + * Wait 1/10 second to make sure that the above initializations + * are complete. + */ (void)taskDelay(sysClkRateGet()/10); + + /* Hook after callbacks are initialized */ if (pinitHooks) (*pinitHooks)(INITHOOKafterCallbackInit); - /* added for Channel Access Links */ + /* + * Initialize Channel Access Link mechanism. Pass #1 + * Call hook after CA links are initialized + */ dbCaLinkInit((int) 1); + if (pinitHooks) (*pinitHooks)(INITHOOKafterCaLinkInit1); - if(initDrvSup()!=0) logMsg("iocInit: Drivers Failed during Initialization\n",0,0,0,0,0,0); + /* + * Initialize Driver Support, Record Support, and finally Device Support. + */ + if (initDrvSup() != 0) + logMsg("iocInit: Drivers Failed during Initialization\n",0,0,0,0,0,0); + if (pinitHooks) (*pinitHooks)(INITHOOKafterInitDrvSup); - if(initRecSup()!=0) logMsg("iocInit: Record Support Failed during Initialization\n",0,0,0,0,0,0); + + if (initRecSup() != 0) + logMsg("iocInit: Record Support Failed during Initialization\n",0,0,0,0,0,0); + if (pinitHooks) (*pinitHooks)(INITHOOKafterInitRecSup); - if(initDevSup()!=0) logMsg("iocInit: Device Support Failed during Initialization\n",0,0,0,0,0,0); + + if (initDevSup() != 0) + logMsg("iocInit: Device Support Failed during Initialization\n",0,0,0,0,0,0); + if (pinitHooks) (*pinitHooks)(INITHOOKafterInitDevSup); + + /* + * Initialize the time stamp code. This starts up the time-stamp task. + */ /* ts_init(); */ /* old time stamp driver (jbk) */ TSinit(); /* new time stamp driver (jbk) */ + if (pinitHooks) (*pinitHooks)(INITHOOKafterTS_init); - if(initDatabase()!=0) logMsg("iocInit: Database Failed during Initialization\n",0,0,0,0,0,0); + + /* + * First pass at initializing the database structure + */ + if (initDatabase() != 0) + logMsg("iocInit: Database Failed during Initialization\n",0,0,0,0,0,0); + createLockSets(); + if (pinitHooks) (*pinitHooks)(INITHOOKafterInitDatabase); - /* added for Channel Access Links */ + + /* added for Channel Access Links */ dbCaLinkInit((int) 2); if (pinitHooks) (*pinitHooks)(INITHOOKafterCaLinkInit2); - if(finishDevSup()!=0) logMsg("iocInit: Device Support Failed during Finalization\n",0,0,0,0,0,0); + + /* + * Finish initializing device support + */ + if (finishDevSup() != 0) + logMsg("iocInit: Device Support Failed during Finalization\n",0,0,0,0,0,0); + if (pinitHooks) (*pinitHooks)(INITHOOKafterFinishDevSup); + + /* + * Initialize Scan tasks + */ scanInit(); + + /* wait 1/2 second to make sure all tasks are started*/ + + /* initialize access security */ asInit(); - /* wait 1/2 second to make sure all tasks are started*/ + (void)taskDelay(sysClkRateGet()/2); + if (pinitHooks) (*pinitHooks)(INITHOOKafterScanInit); + + /* + * Enable scan tasks and some driver support functions. + */ interruptAccept=TRUE; + if (pinitHooks) (*pinitHooks)(INITHOOKafterInterruptAccept); - if(initialProcess()!=0) logMsg("iocInit: initialProcess Failed\n",0,0,0,0,0,0); + + /* + * Process all records that have their "process at initialization" + * field set (pini). + */ + if (initialProcess() != 0) + logMsg("iocInit: initialProcess Failed\n",0,0,0,0,0,0); + if (pinitHooks) (*pinitHooks)(INITHOOKafterInitialProcess); + + /* + * Start up CA server + */ rsrv_init(); + logMsg("iocInit: All initialization complete\n",0,0,0,0,0,0); + if (pinitHooks) (*pinitHooks)(INITHOOKatEnd); return(0); } +/* + * Initialize Driver Support + * Locate all driver support entry tables. + * Call the initialization routine (init) for each + * driver type. + */ static long initDrvSup(void) /* Locate all driver support entry tables */ { char *pname; @@ -216,31 +343,63 @@ static long initDrvSup(void) /* Locate all driver support entry tables */ long rtnval; STATUS vxstatus; struct drvSup *pdrvSup; + + /* + * Make sure at least one device driver is defined in + * the ASCII file. + */ - if(!(pdrvSup=pdbBase->pdrvSup)) { + if (!(pdrvSup=pdbBase->pdrvSup)) { status = S_drv_noDrvSup; errMessage(status,"No device drivers are defined"); return(status); } + + /* + * For every driver support module, look up the name + * for that function in the vxWorks symbol table. If + * a driver entry table doesn't exist, report that + * fact. + */ for(i=0; i< (pdrvSup->number); i++) { - if(!(pname = pdrvSup->papDrvName[i])) continue; + if (!(pname = pdrvSup->papDrvName[i])) continue; + strcpy(name,"_"); strcat(name,pname); - vxstatus = symFindByName(sysSymTbl,name,(void *)&(pdrvSup->papDrvet[i]),&type); - if( vxstatus!=OK || ( type&N_TEXT == 0) ) { + + vxstatus = symFindByName(sysSymTbl, name, (void *) &(pdrvSup->papDrvet[i]), &type); + + /* Make sure it is program text */ + if (vxstatus != OK || (type & N_TEXT == 0)) { strcpy(message,"driver entry table not found for "); strcat(message,pname); status = S_drv_noDrvet; errMessage(status,message); continue; } - if(!(pdrvSup->papDrvet[i]->init)) continue; + + /* + * If an initialization routine is defined (not NULL), + * for the driver support call it. + */ + if (!(pdrvSup->papDrvet[i]->init)) + continue; rtnval = (*(pdrvSup->papDrvet[i]->init))(); - if(status==0) status = rtnval; + + if (status == 0) + status = rtnval; } return(status); } +/* + * Initialize Record Support + * Allocate a record support structure for every record type + * plus space for an array of pointers to RSETs. + * Locate all record support entry tables. + * Call the initialization routine (init) for each + * record type. + */ static long initRecSup(void) { char name[40]; @@ -259,36 +418,76 @@ static long initRecSup(void) errMessage(status,"No record types defined"); return(status); } - nbytes = sizeof(struct recSup) + precType->number*sizeof(void *); + + /* + * Allocate record support structure, and a list of pointers + * after it to point to the Record Support Entry Tables (RSETs) + * of individual record types. + */ + nbytes = sizeof(struct recSup) + precType->number * sizeof(void *); precSup = dbCalloc(1,nbytes); pdbBase->precSup = precSup; + + /* The number of record support entry tables equals the number of record types */ precSup->number = precType->number; + + /* + * The pointer to the array of pointers of Record Support Entry Tables + * exists at the end of the record support structure. + */ precSup->papRset = (void *)((long)precSup + (long)sizeof(struct recSup)); + + /* + * For every record support module, look up the name + * for that function in the vxWorks symbol table. If + * a record support entry table doesn't exist, report + * that fact. + */ for(i=0; i< (precSup->number); i++) { - if(precType->papName[i] == NULL)continue; + if (precType->papName[i] == NULL) + continue; + + /* + * Create string that is the name of the RSET + * (record support entry table) structure for + * each record type. + */ strcpy(name,"_"); strcat(name,precType->papName[i]); strcat(name,"RSET"); - vxstatus = symFindByName(sysSymTbl,name, - (void *)(&precSup->papRset[i]),&type); - if( vxstatus!=OK || ( type&N_TEXT == 0) ) { + + /* Lookup name in vxWorks symbol table - and make sure it is program text */ + vxstatus = symFindByName(sysSymTbl, name, + (void *) (&precSup->papRset[i]), &type); + + if (vxstatus != OK || ((type & N_TEXT) == 0)) { strcpy(message,"record support entry table not found for "); strcat(message,name); status = S_rec_noRSET; errMessage(status,message); continue; } - if(!(precSup->papRset[i]->init)) continue; + + /* If an initialization routine exists for a record type, execute it */ + if (!(precSup->papRset[i]->init)) + continue; else { rtnval = (*(precSup->papRset[i]->init))(); - if(status==0) status = rtnval; + if (status==0) + status = rtnval; } } return(status); } -static long initDevSup(void) /* Locate all device support entry tables */ +/* + * Initialize Device Support + * Locate all device support entry tables. + * Call the initialization routine (init) for each + * device type (First Pass). + */ +static long initDevSup(void) { char *pname; char name[40]; @@ -301,47 +500,91 @@ static long initDevSup(void) /* Locate all device support entry tables */ struct recDevSup *precDevSup; struct devSup *pdevSup; - if(!(precDevSup=pdbBase->precDevSup)) { + if (!(precDevSup = pdbBase->precDevSup)) { status = S_dev_noDevSup; errMessage(status,"No device support is defined"); return(status); } - for(i=0; i< (precDevSup->number); i++) { - if((pdevSup = precDevSup->papDevSup[i]) == NULL) continue; + + /* + * For all possible records, initialize their device support + * routines. There is usually more than one device support + * routine defined for every record type, this accounts for + * the doubly nested for() loops. precDevSup->number = number + * of record types. + */ + for (i=0; i< (precDevSup->number); i++) { + /* + * Find the device support routine in the array of pointers + */ + if ((pdevSup = precDevSup->papDevSup[i]) == NULL) + continue; + + /* For every device support module defined for a record type... */ for(j=0; j < (pdevSup->number); j++) { - if(!(pname = pdevSup->papDsetName[j])) continue; - strcpy(name,"_"); - strcat(name,pname); - vxstatus = (long)symFindByName(sysSymTbl,name, - (void *)&(pdevSup->papDset[j]),&type); - if( vxstatus!=OK || ( type&N_TEXT == 0) ) { + /* Create the name */ + if (!(pname = pdevSup->papDsetName[j])) + continue; + strcpy(name, "_"); + strcat(name, pname); + + /* Lookup name in vxWorks symbol table - make sure it is program text */ + vxstatus = (long) symFindByName(sysSymTbl, name, + (void *) &(pdevSup->papDset[j]), &type); + + if (vxstatus != OK || ((type & N_TEXT) == 0)) { pdevSup->papDset[j]=NULL; - strcpy(message,"device support entry table not found for "); - strcat(message,pname); + strcpy(message, "device support entry table not found for "); + strcat(message, pname); status = S_dev_noDSET; - errMessage(status,message); + errMessage(status, message); continue; } - if(!(pdevSup->papDset[j]->init)) continue; + + /* If an init routine exists for the device support module, execute it */ + if (!(pdevSup->papDset[j]->init)) + continue; + rtnval = (*(pdevSup->papDset[j]->init))(0); - if(status==0) status = rtnval; + + if (status == 0) + status = rtnval; } } return(status); } +/* + * Calls the second pass for each device support + * initialization routine. The second pass is made + * after the database records have been initialized and + * placed into lock sets. + */ static long finishDevSup(void) { int i,j; struct recDevSup *precDevSup; struct devSup *pdevSup; - - if(!(precDevSup=pdbBase->precDevSup)) return(0); + + /* Find pointer to device support for all record types */ + if (!(precDevSup=pdbBase->precDevSup)) + return(0); + + /* For every record type... */ for(i=0; i< (precDevSup->number); i++) { - if((pdevSup = precDevSup->papDevSup[i]) == NULL) continue; + /* Find pointer to device support for an individual record type */ + if ((pdevSup = precDevSup->papDevSup[i]) == NULL) + continue; + + /* For every device support module defined for a record type */ for(j=0; j < (pdevSup->number); j++) { - if(!(pdevSup->papDset[j])) continue; - if(!(pdevSup->papDset[j]->init)) continue; + if (!(pdevSup->papDset[j])) + continue; + + /* Call the second pass of the initialization, if the routine exists */ + if (!(pdevSup->papDset[j]->init)) + continue; + (*(pdevSup->papDset[j]->init))(1); } @@ -369,28 +612,63 @@ static long initDatabase(void) struct devSup *pdevSup; struct recSup *precSup; struct recType *precType; - + + /* Find the record type and record support structures */ if(!(precType=pdbBase->precType)) return(0); if(!(precSup=pdbBase->precSup)) return(0); - if(!(precHeader = pdbBase->precHeader)) { + + /* + * Locate database record header + * This structure contains a pointer to an array of pointers to + * record location structures. A record location structure + * exists for every record type. It contains a pointer to a + * linked list of all instances of records with that type. + */ + if (!(precHeader = pdbBase->precHeader)) { status = S_record_noRecords; errMessage(status,"No database records are defined"); return(status); } - if(!(precDes = pdbBase->precDes)) { + + /* + * Find record descriptions + * The record descriptions contain every piece of information + * you ever wanted to know about the individual fields in a + * particular record type. See header file for more information. + */ + if (!(precDes = pdbBase->precDes)) { status = S_record_noRecords; errMessage(status,"Database record descriptions were not defined"); return(status); } + + /* For every record type ... */ for(i=0; i< (precHeader->number); i++) { - if(!(precLoc = precHeader->papRecLoc[i]))continue; - if(!precLoc->preclist) continue; + /* Get pointer to location structure for instances of record type 'i' */ + if (!(precLoc = precHeader->papRecLoc[i]))continue; + + if (!precLoc->preclist) continue; + + /* + * Find record support entry table, record description, and device + * support associated with record type 'i' + */ prset = GET_PRSET(precSup,i); precTypDes = precDes->papRecTypDes[i]; pdevSup = GET_PDEVSUP(pdbBase->precDevSup,i); - for(precNode=(RECNODE *)ellFirst(precLoc->preclist); - precNode; precNode = (RECNODE *)ellNext(&precNode->node)) { - if(!prset) { + + /* + * For all instances of record type 'i '... + * These records are contained in the linked list + */ + for (precNode=(RECNODE *)ellFirst(precLoc->preclist); + precNode; precNode = (RECNODE *)ellNext(&precNode->node)) { + + /* + * If there is not record support entry table for record + * type 'i', report message, and break from for loop. + */ + if (!prset) { strcpy(name,precType->papName[i]); strcat(name,"RSET"); strcpy(message,"record support entry table not found for "); @@ -399,60 +677,126 @@ static long initDatabase(void) errMessage(status,message); break; } + /* Find pointer to record instance */ precord = precNode->precord; + /* If NAME is null then skip this record*/ if(!(precord->name[0])) continue; - /*initialize fields rset*/ + + /* Initialize record's record support entry table field */ precord->rset = prset; - /* initialize mlok and mlis*/ + + /* + * Initialize mlok and mlis. + * (The monitor lock - basically a semaphore) and the + * monitor list field. The list of "applications" + * observing changes in a database field. + */ FASTLOCKINIT(&precord->mlok); ellInit(&(precord->mlis)); + + /* Reset the process active field */ precord->pact=FALSE; - /* Init DSET NOTE that result may be NULL*/ + + /* Init DSET NOTE that result may be NULL */ precord->dset=(struct dset *)GET_PDSET(pdevSup,precord->dtyp); - /* call record support init_record routine - First pass */ + + /* Initialize dbCommon structure of the record - First pass (pass=0) */ rtnval = dbCommonInit(precord,0); - if(!(precSup->papRset[i]->init_record)) continue; + + /* + * Call record support init_record routine - First pass + * (pass=0). (only if init_record is defined...) + */ + if (!(precSup->papRset[i]->init_record)) continue; + rtnval = (*(precSup->papRset[i]->init_record))(precord,0); - if(status==0) status = rtnval; + + if (status==0) + status = rtnval; } } - /* Second pass to resolve links*/ + + /* + * Second pass to resolve links + */ + /* For all record types */ for(i=0; i< (precHeader->number); i++) { - if(!(precLoc = precHeader->papRecLoc[i]))continue; - if(!precLoc->preclist) continue; + /* Find record instances */ + if (!(precLoc = precHeader->papRecLoc[i]))continue; + + if (!precLoc->preclist) continue; + + /* Find record field descriptions */ precTypDes = precDes->papRecTypDes[i]; - for(precNode=(RECNODE *)ellFirst(precLoc->preclist); - precNode; precNode = (RECNODE *)ellNext(&precNode->node)) { + + /* For all record instances of type 'i' in the linked list... */ + for (precNode=(RECNODE *)ellFirst(precLoc->preclist); + precNode; precNode = (RECNODE *)ellNext(&precNode->node)) { precord = precNode->precord; + /* If NAME is null then skip this record*/ - if(!(precord->name[0])) continue; - /* Convert all PV_LINKs to DB_LINKs or CA_LINKs*/ + if (!(precord->name[0])) continue; + + /* + * Convert all PV_LINKs to DB_LINKs or CA_LINKs + * Figures out what type of link to use. A + * database link local to the IOC, or a channel + * access link across the network. + */ + /* For all the links in the record type... */ for(j=0; jno_links; j++) { pfldDes = precTypDes->papFldDes[precTypDes->link_ind[j]]; + + /* + * The actual link structure is located at this offset + * within the link structure. + */ plink = (struct link *)((char *)precord + pfldDes->offset); - if(plink->type == PV_LINK) { + + /* + * Link type should be PV_LINK, unless it is + * constant or hardware-specific + */ + if (plink->type == PV_LINK) { strncpy(name,plink->value.pv_link.pvname,PVNAME_SZ); + + /* create record name */ name[PVNAME_SZ]=0; strcat(name,"."); strncat(name,plink->value.pv_link.fldname,FLDNAME_SZ); - if(dbNameToAddr(name,&dbAddr) == 0) { + + /* + * Lookup record name in database + * If a record is _not_ local to the IOC, it is a + * channel access link, otherwise it is a + * database link. + */ + if (dbNameToAddr(name,&dbAddr) == 0) { plink->type = DB_LINK; plink->value.db_link.pdbAddr = dbCalloc(1,sizeof(struct dbAddr)); *((struct dbAddr *)(plink->value.db_link.pdbAddr))=dbAddr; + /* + * Initialize conversion to "uninitialized" conversion + */ + plink->value.db_link.conversion = cvt_uninit; } else { - /* not a local pvar ... assuming a CA_LINK */ - /* only supporting NPP, Input MS/NMS, and */ - /* Output NMS links ... checking here. */ - + /* + * Not a local process variable ... assuming a CA_LINK + * Only supporting Non Process Passive links, Input Maximize + * Severity/No Maximize Severity(MS/NMS), and output NMS + * links ... The following code checks for this. + */ if (plink->value.db_link.process_passive || (pfldDes->field_type == DBF_OUTLINK && plink->value.db_link.maximize_sevr)) { - /* link PP and/or Outlink MS ... */ - /* neither supported under CA_LINKs */ + /* + * Link PP and/or Outlink MS ... + * neither supported under CA_LINKs + */ strncpy(message,precord->name,PVNAME_SZ); message[PVNAME_SZ]=0; strcat(message,"."); @@ -469,28 +813,46 @@ static long initDatabase(void) } } } - /* Call init_record for second time */ + + /* + * Call record support init_record routine - Second pass + */ + /* For all record types... */ for(i=0; i< (precHeader->number); i++) { - if(!(precLoc = precHeader->papRecLoc[i]))continue; - if(!precLoc->preclist) continue; - if(!(prset=GET_PRSET(precSup,i))) continue; + if (!(precLoc = precHeader->papRecLoc[i])) continue; + if (!precLoc->preclist) continue; + if (!(prset=GET_PRSET(precSup,i))) continue; precTypDes = precDes->papRecTypDes[i]; - for(precNode=(RECNODE *)ellFirst(precLoc->preclist); + + /* For all record instances of type 'i' */ + for (precNode=(RECNODE *)ellFirst(precLoc->preclist); precNode; precNode = (RECNODE *)ellNext(&precNode->node)) { + /* Locate name of record */ precord = precNode->precord; - /* If NAME is null then skip this record*/ - if(!(precord->name[0])) continue; + /* If NAME is null then skip this record*/ + if (!(precord->name[0])) continue; rtnval = dbCommonInit(precord,1); - if(status==0) status = rtnval; - /* call record support init_record routine - Second pass */ - if(!(precSup->papRset[i]->init_record)) continue; - rtnval = (*(precSup->papRset[i]->init_record))(precord,1); - if(status==0) status = rtnval; + if (status==0) status = rtnval; + /* call record support init_record routine - Second pass (pass = 1) */ + if (!(precSup->papRset[i]->init_record)) continue; + rtnval = (*(precSup->papRset[i]->init_record))(precord, 1); + if (status == 0) status = rtnval; } } return(status); } +/* + * Create lock sets for records + * A lock set is a set of records that must be locked + * with a semaphore so as to prevent mutual exclusion + * hazards. Lock sets are determined by examining the + * links interconnecting the records. If a link connecting + * two records is not an NPP/NMS single-valued input link, + * then the two records are considered part of the same + * lock set. Records connected by forward links are + * definately considered part of the same lockset. + */ static void createLockSets(void) { int i,link; @@ -518,7 +880,17 @@ static void createLockSets(void) /* If NAME is null then skip this record*/ if(!(precord->name[0])) continue; if(precord->lset) continue; /*already in a lock set*/ + + /* + * At First, assume record is in a different lockset + * We shall see later if this assumption is incorrect. + */ precord->lset = maxnset = ++nset; + + /* + * Use the process active flag to eliminate traversing + * cycles in the database "graph" + */ precord->pact = TRUE; again = TRUE; while(again) { again = FALSE; @@ -526,15 +898,41 @@ static void createLockSets(void) struct dbAddr *pdbAddr; pfldDes = precTypDes->papFldDes[precTypDes->link_ind[link]]; + + /* + * Find link structure, which is at an offset in the record + */ plink = (struct link *)((char *)precord + pfldDes->offset); + /* Ignore link if type is constant, channel access, or hardware specific */ if(plink->type != DB_LINK) continue; + pdbAddr = (struct dbAddr *)(plink->value.db_link.pdbAddr); - if( pfldDes->field_type==DBF_INLINK - && ( !(plink->value.db_link.process_passive) - && !(plink->value.db_link.maximize_sevr) ) - && pdbAddr->no_elements<=1) continue; + + /* The current record is in a different lockset -IF- + * 1. Input link + * 2. Not Process Passive + * 3. Not Maximize Severity + * 4. Not An Array Operation - single element only + */ + if (pfldDes->field_type==DBF_INLINK + && ( !(plink->value.db_link.process_passive) + && !(plink->value.db_link.maximize_sevr)) + && pdbAddr->no_elements<=1) continue; + + /* + * Combine the lock sets of the current record with the + * remote record pointed to by the link. (recursively) + */ newset = makeSameSet(pdbAddr,precord->lset); - if(newset!=precord->lset) { + + /* + * Perform an iteration of the while-loop again + * if we find that the record pointed to by + * the link has its lockset set earlier. If + * it has, set the current record's lockset to + * that of the link's endpoint. + */ + if (newset!=precord->lset) { if(precord->lset==maxnset && maxnset==nset) nset--; precord->lset = newset; again = TRUE; @@ -548,7 +946,7 @@ static void createLockSets(void) dbScanLockInit(nset); } -static short makeSameSet( struct dbAddr *paddr, short lset) +static short makeSameSet(struct dbAddr *paddr, short lset) { struct dbCommon *precord = paddr->precord; short link; @@ -558,11 +956,35 @@ static short makeSameSet( struct dbAddr *paddr, short lset) struct recDes *precDes; int again; + /* + * Use the process active flag to eliminate traversing + * cycles in the database "graph." Effectively converts + * the arbitrary database "graph" (where edges are + * defined as links) into a tree structure. + */ if(precord->pact) return(((precord->lsetlset : lset)); + + /* + * If the lock set of the link's endpoint is already set + * to the lockset we are setting it to, return... + */ if(lset == precord->lset) return(lset); + + /* + * If the record has an uninitialized lock set field, + * we set it here. + */ if(precord->lset == 0) precord->lset = lset; + + /* + * If the record is already in a lockset determined earlier, + * return that lock set. + */ if(precord->lset < lset) return(precord->lset); + if(!(precDes = pdbBase->precDes)) return(0); + + /* set pact to prevent cycles */ precord->lset = lset; precord->pact = TRUE; again = TRUE; while(again) { again = FALSE; @@ -591,6 +1013,10 @@ static short makeSameSet( struct dbAddr *paddr, short lset) return(precord->lset); } +/* + * Process database records at initialization if + * their pini (process at init) field is set. + */ static long initialProcess(void) { short i; diff --git a/src/db/recGbl.c b/src/db/recGbl.c index dc62fb896..c5a3ba389 100644 --- a/src/db/recGbl.c +++ b/src/db/recGbl.c @@ -1,5 +1,5 @@ /* recGbl.c - Global record processing routines */ -/* share/src/db/recGbl.c $Id$ */ +/* base/src/db $Id$ */ /* * Author: Marty Kraimer @@ -38,6 +38,7 @@ * .08 09-15-92 jba changed error parm in recGblRecordError calls * .09 09-17-92 jba ANSI C changes * .10 01-27-93 jba set pact to true during calls to dbPutLink + * .11 03-21-94 mcn Added fast link routines */ #include @@ -475,3 +476,136 @@ double *prangeValue; } return; } + +/* Fast link initialization routines */ +/* + * Get and Put conversion routine lookup tables + */ +extern long (*get_cvt_table[DBF_DEVCHOICE+1][DBR_ENUM+1])(); +extern long (*put_cvt_table[DBR_ENUM+1][DBF_DEVCHOICE+1])(); + +/* + * String if bad database request type chosen + */ +static char *bad_in_req_type = "recGblInitFastInLink: Bad database request type"; +static char *bad_out_req_type = "recGblInitFastInLink: Bad database request type"; + +/* + * Initialize fast input links. + */ +long recGblInitFastInLink( + struct link *plink, + void *precord, + short dbrType, + char *fld_name) +{ + long status = 0; + struct db_link *pdb_link = &(plink->value.db_link); + struct dbAddr *pdb_addr = (struct dbAddr *) (pdb_link->pdbAddr); + long (*cvt_func)(); + + /* + * Check for CA_LINK + */ + if (plink->type == PV_LINK) { + status = dbCaAddInlink(plink, (struct dbCommon *) precord, fld_name); + return(status); + } + + /* + * Return if not database link (A constant link, for example) + */ + if (plink->type != DB_LINK) + return(0); + + /* + * Check for legal conversion range... + */ + if ((pdb_addr->field_type < DBF_STRING) || + (pdb_addr->field_type > DBF_DEVCHOICE) || + ( dbrType < DBR_STRING) || + ( dbrType > DBR_ENUM)) { + + pdb_link->conversion = cvt_dummy; + recGblDbaddrError(S_db_badDbrtype, pdb_addr, bad_in_req_type); + return(S_db_badDbrtype); + } + + /* + * Lookup conversion function + */ + cvt_func = get_cvt_table[pdb_addr->field_type][dbrType]; + + if (cvt_func == NULL) { + pdb_link->conversion = cvt_dummy; + recGblDbaddrError(S_db_badDbrtype, pdb_addr, bad_in_req_type); + return(S_db_badDbrtype); + } + + /* + * Put function it into conversion field (Run Time Link) + */ + pdb_link->conversion = cvt_func; + + return(0); +} + +/* + * Initialize fast output links. + */ +long recGblInitFastOutLink( + struct link *plink, + void *precord, + short dbrType, + char *fld_name) +{ + long status = 0; + struct db_link *pdb_link = &(plink->value.db_link); + struct dbAddr *pdb_addr = (struct dbAddr *) (pdb_link->pdbAddr); + long (*cvt_func)(); + + /* + * Check for CA_LINK + */ + if (plink->type == PV_LINK) { + status = dbCaAddOutlink(plink, (struct dbCommon *) precord, fld_name); + return(status); + } + + /* + * Return if not database link (A constant link, for example) + */ + if (plink->type != DB_LINK) + return(0); + + /* + * Check for legal conversion range... + */ + if ((pdb_addr->field_type < DBF_STRING) || + (pdb_addr->field_type > DBF_DEVCHOICE) || + ( dbrType < DBR_STRING) || + ( dbrType > DBR_ENUM)) { + + pdb_link->conversion = cvt_dummy; + recGblDbaddrError(S_db_badDbrtype, pdb_addr, bad_out_req_type); + return(S_db_badDbrtype); + } + /* + * Lookup conversion function + */ + cvt_func = put_cvt_table[dbrType][pdb_addr->field_type]; + + if (cvt_func == NULL) { + pdb_link->conversion = cvt_dummy; + recGblDbaddrError(S_db_badDbrtype, pdb_addr, bad_out_req_type); + return(S_db_badDbrtype); + } + + /* + * Put function it into conversion field (Run Time Link) + */ + pdb_link->conversion = cvt_func; + + return(0); +} + diff --git a/src/db/setMasterTimeToSelf.c b/src/db/setMasterTimeToSelf.c index 7075f4957..8a263e40a 100644 --- a/src/db/setMasterTimeToSelf.c +++ b/src/db/setMasterTimeToSelf.c @@ -1,5 +1,5 @@ /* setMasterTimeToSelf.c ioc initialization */ -/* share/src/db $Id$ */ +/* base/src/db $Id$ */ /* * Author: Bob Zieman * Date: 09-11-92 diff --git a/src/db/taskwd.c b/src/db/taskwd.c index dce7751cf..757408672 100644 --- a/src/db/taskwd.c +++ b/src/db/taskwd.c @@ -1,5 +1,5 @@ /* taskwd.c */ -/* share/src/db $Id$ */ +/* base/src/db $Id$ */ /* tasks and subroutines for a general purpose task watchdog */ /* @@ -50,7 +50,10 @@ struct task_list { ELLNODE node; VOIDFUNCPTR callback; void *arg; - int tid; + union { + int tid; + void *userpvt; + } id; int suspended; }; @@ -91,20 +94,20 @@ void taskwdInsert(int tid,VOIDFUNCPTR callback,void *arg) pt = allocList(); ellAdd(&list,(void *)pt); pt->suspended = FALSE; - pt->tid = tid; + pt->id.tid = tid; pt->callback = callback; pt->arg = arg; FASTUNLOCK(&lock); } -void taskwdAnyInsert(int tid,VOIDFUNCPTR callback,void *arg) +void taskwdAnyInsert(void *userpvt,VOIDFUNCPTR callback,void *arg) { struct task_list *pt; FASTLOCK(&anylock); pt = allocList(); ellAdd(&anylist,(void *)pt); - pt->tid = tid; + pt->id.userpvt = userpvt; pt->callback = callback; pt->arg = arg; FASTUNLOCK(&anylock); @@ -117,7 +120,7 @@ void taskwdRemove(int tid) FASTLOCK(&lock); pt = (struct task_list *)ellFirst(&list); while(pt!=NULL) { - if (tid == pt->tid) { + if (tid == pt->id.tid) { ellDelete(&list,(void *)pt); freeList(pt); FASTUNLOCK(&lock); @@ -129,14 +132,14 @@ void taskwdRemove(int tid) errMessage(-1,"taskwdRemove failed"); } -void taskwdAnyRemove(int tid) +void taskwdAnyRemove(void *userpvt) { struct task_list *pt; FASTLOCK(&anylock); pt = (struct task_list *)ellFirst(&anylist); while(pt!=NULL) { - if (tid == pt->tid) { + if (userpvt == pt->id.userpvt) { ellDelete(&anylist,(void *)pt); freeList(pt); FASTUNLOCK(&anylock); @@ -158,20 +161,20 @@ static void taskwdTask(void) pt = (struct task_list *)ellFirst(&list); while(pt) { next = (struct task_list *)ellNext((void *)pt); - if(taskIsSuspended(pt->tid)) { + if(taskIsSuspended(pt->id.tid)) { char *pname; char message[100]; - pname = taskName(pt->tid); + pname = taskName(pt->id.tid); if(!pt->suspended) { struct task_list *ptany,*anynext; pt->suspended = TRUE; - sprintf(message,"task %x %s suspended",pt->tid,pname); + sprintf(message,"task %x %s suspended",pt->id.tid,pname); errMessage(-1,message); ptany = (struct task_list *)ellFirst(&anylist); while(ptany) { - if(ptany->callback) (ptany->callback)(ptany->arg,pt->tid); + if(ptany->callback) (ptany->callback)(ptany->arg,pt->id.tid); ptany = (struct task_list *)ellNext((ELLNODE *)ptany); } if(pt->callback) { @@ -185,6 +188,8 @@ static void taskwdTask(void) break; } } + } else { + pt->suspended = FALSE; } pt = next; } diff --git a/src/vxWorks/db/devLib.c b/src/vxWorks/db/devLib.c index 9f259ccd7..4494ac566 100644 --- a/src/vxWorks/db/devLib.c +++ b/src/vxWorks/db/devLib.c @@ -1,5 +1,5 @@ /* devLib.c - support for allocation of common device resources */ -/* $Id$ */ +/* base/src/db $Id$ */ /* * Original Author: Marty Kraimer