1: #include "../h/config.h" 2: /* 3: * Icon runtime startup. This routine gets Icon rolling and is called 4: * by main. The basic functions of this routine are to initialize 5: * memory with a call to init, and then invoke the main procedure with 6: * single argument that is a list composed of command line arguments. 7: */ 8: Global(__cleanup) /* close files on exit */ 9: Global(_init) /* initialize memory */ 10: Global(_invoke) /* procedure invocation */ 11: Global(_llist) /* form a literal list */ 12: #ifdef AZ 13: Global(_monitor) /* turn profiling on/off */ 14: #endif AZ 15: Global(_runerr) /* runtime error processor */ 16: Global(_globals) /* icon global data region */ 17: Global(_monres) /* profile resolution */ 18: Global(_c_exit) 19: Global(_boundary) 20: Global(_tended) 21: Global(_etended) 22: Global(_mstart) 23: #ifdef VAX 24: .text 25: _mstart: 26: /* 27: * mstart(argv) -- start up Icon. 28: */ 29: Mask 0x0000 # don't need to save any registers 30: movl 8(ap),r9 # point r9 at first word of argv list 31: 32: /* 33: * Call init to initialize memory and set environment variables 34: */ 35: pushl 4(r9) # pass file name to be interpreted to init 36: calls $1,_init # init(file) 37: /* 38: * Create a dummy expression frame so that main procedure is no 39: * different from other procedures. 40: */ 41: pushl $0 # old expression frame pointer 42: movl sp,efp # point the expression frame pointer 43: # at this word. 44: pushl $0 # old generator frame pointer 45: pushl $flab # failure label, we branch to flab 46: # if the expression (the evaluation 47: # of main()) fails 48: 49: /* 50: * Prepare to invoke main(), which should be first global variable. 51: * Note that _globals contains the address of the first 52: * global variable. 53: */ 54: movl _globals,r0 # point r0 at first global variable 55: cmpl $D_PROC,(r0) # see if it's a procedure [*] 56: bneq nomain 57: movq (r0),-(sp) # Push variable 'main' onto stack 58: clrq -(sp) # Push &null to receive result of llist() 59: 60: tstl (r9)+ # r9 points to arg0, which is program 61: # name. We ignore it, moving r9 62: # on to point at the first actual 63: # argument to the program 64: tstl (r9)+ # arg1 is the name of the file to 65: # interpret, so we ignore it as well 66: /* 67: * Now we're ready to make an Icon list out of the program arguments. 68: * We build string descriptors one at a time on the stack and then 69: * call llist which makes a list out of its arguments. 70: */ 71: clrl r8 # r8 counts args, 0 to start with 72: b1: 73: movl (r9)+,r7 # get address of next argument 74: beql f2 # if 0, we're at end of argument list, 75: pushl r7 # otherwise we push the address of the arg 76: incl r8 # count one more argument 77: locc $0,$0xffff,(r7) # calculate length of string, the 0xffff 78: # constant is 65k, which specifies the 79: # maximum distance to look to for the 80: # 0 (null byte) that terminates the string 81: subl3 r7,r1,-(sp) # push length of string, note that r1 82: # was automagically set by the locc 83: # instruction 84: jbr b1 # loop around until we get to the 0 word 85: # at the end of the argument list 86: 87: /* 88: * llist is called as llist(nargs,argn,...,arg1). We now have argn through 89: * arg1 on the stack. We push nargs (number of arguments) and then 90: * we calculate the number of words occupied by the argument list 91: * because the calls instruction uses it. 92: */ 93: f2: 94: pushl r8 # push nargs 95: calls $0,_llist # make a list of the arguments 96: ashl $1,r8,r8 # calc number of words in the argument list, 97: # each descriptor is 2 words, so we multiply 98: # nargs by 2. 99: incl r8 # nargs itself also takes a word, so we add 1 100: ashl $2,r8,r8 # r8 is length in bytes of argument list 101: addl2 r8,sp 102: 103: /* 104: * Invoke main() with one argument (the list of command line arguments). 105: */ 106: clrl gfp # clear generator frame pointer 107: clrl r13 # clear procedure frame pointer 108: pushl $1 # push nargs 109: calls $3,_invoke 110: 111: /* 112: * If main() returns we end up here. Call _c_exit to exit with 0 status. 113: */ 114: f9: 115: pushl $0 # exit status = 0 116: calls $1,_c_exit 117: 118: /* 119: * If there was no main procedure we call runerr(117,0). 120: */ 121: nomain: 122: pushl $0 123: pushl $117 124: calls $2,_runerr 125: pushl $1 126: calls $1,_c_exit 127: 128: 129: /* 130: * c_exit(i) - flush all buffers and exit with status i. 131: */ 132: _c_exit: 133: Mask 0 134: #ifdef AZ 135: tstl _monres # if we're monitoring, 136: beql f1 137: pushl $0 # we turn it off with 138: calls $1,_monitor # monitor(0) 139: #endif AZ 140: /* 141: * We call __cleanup to clean up the i/o system and then 142: * call exit(i), where "i" is the argument to _c_exit. 143: */ 144: f1: 145: calls $0,__cleanup 146: pushl 4(ap) 147: calls $1,_exit 148: .data 149: 150: /* 151: * waste first few bytes of memory, because all pointers must be 152: * greater than MAXTYPE, lest we confuse the garbage collector. 153: */ 154: .space 60 155: 156: /* 157: * flab is "branched to" by the interpreter if the main procedure 158: * fails. The 0 is a "quit" opcode for the interpreter. 159: */ 160: flab: 161: .byte 0 162: 163: /* 164: * The boundary marks the point where the stack is C above and 165: * Icon below. 166: */ 167: _boundary: 168: .long 0 169: /* 170: * The tended descriptors. 171: */ 172: _tended: 173: .long 0,0 # tended[0] 174: .long 0,0 # tended[1] 175: .long 0,0 # tended[2] 176: .long 0,0 # tended[3] 177: .long 0,0 # tended[4] 178: .long 0,0 # tended[5] 179: _etended: 180: 181: 182: #endif VAX 183: #ifdef PORT 184: DummyFcn(_mstart) 185: DummyFcn(_c_exit) 186: DummyData(_boundary) 187: DummyData(_tended) 188: DummyData(_etended) 189: #endif PORT 190: 191: #ifdef PDP11 192: Global(csv) 193: #include <sys.s> 194: / 195: / Icon runtime startup 196: / 197: #ifdef NOFP 198: Global(fptrap) 199: signal = 48. 200: #endif NOFP 201: 202: .text 203: _mstart: 204: /* 205: * mstart(argv) -- start up Icon 206: */ 207: / Register usage: 208: / r1: counter for scanning argument list 209: / r2: nargs - number of arguments to the program 210: / r3: character pointer, for finding length of each argument string 211: / r4: pointer to dummy expression frame marker 212: / r5: pointer to command line argument list 213: 214: jsr r5,csv 215: clr _boundary / undo boundary setting 216: #ifdef NOFP 217: / Use software floating point 218: sys signal; 4; fptrap 219: setd 220: #else 221: / Enable floating point traps, double precision. 222: ldfps $3200 223: #endif NOFP 224: 225: / Create a dummy expression frame. 226: 227: clr -(sp) / old r4 228: mov sp,r4 229: clr -(sp) / old r3 230: mov $flab,-(sp) / failure label 231: 232: / Initialize memory. 233: mov 6(r5),r0 / point at argv 234: mov 2(r0),-(sp) / push address of arg1, the file name 235: clr -(sp) / pass nargs to init() for set/clrbound 236: jsr pc,_init 237: tst (sp)+ 238: / Prepare to invoke procedure main, which should be first global variable. 239: mov _globals,r0 240: cmp $D_PROC,(r0) / make sure procedure main exists 241: bne nomain 242: mov 2(r0),-(sp) / push variable "main" on stack 243: mov (r0),-(sp) 244: / Build a list from the command line arguments. 245: 246: clr -(sp) / push &null for result from llist() 247: clr -(sp) 248: mov 4(r5),r1 / r1 <- nargs 249: mov 6(r5),r5 / point r5 at argv[0] 250: add $4.,r5 251: dec r1 / don't count argument 0 (command name) 252: dec r1 / or argument 1 (icon program name) 253: mov r1,r2 254: bgt 1f 255: clr r2 256: br 3f 257: 1: 258: mov (r5)+,r3 / build string descriptors for args 259: mov r3,-(sp) / push pointer to string 260: clr -(sp) / push string length of 0 261: 2: 262: tstb (r3)+ / calculate length of string 263: beq 2f 264: inc (sp) / increment string length 265: br 2b 266: 2: 267: sob r1,1b 268: 3: 269: mov r2,-(sp) / push nargs 270: jsr pc,_llist / make a list of the arguments 271: 272: / Invoke main() with one argument (the list of command line arguments). 273: 274: mov $1,-(sp) 275: clr r3 / clear generator frame pointer 276: clr r5 / clear procedure frame pointer 277: jsr pc,_invoke 278: 279: / If main() fails or returns, exit with 0 status. 280: 9: 281: clr -(sp) / exit status = 0 282: jsr pc,*$_c_exit 283: sys exit 284: 285: / Issue runerr(117,NULL) if main() is missing. 286: 287: nomain: / runtime error if procedure main missing 288: clr -(sp) 289: mov $117.,-(sp) 290: jsr pc,_runerr 291: sys exit 292: 293: / c_exit(i) - flush all buffers and exit with status i. 294: 295: _c_exit: 296: mov r5,-(sp) 297: mov sp,r5 298: #ifdef AZ 299: tst _monres / is monitoring on? 300: beq 1f 301: clr -(sp) 302: jsr pc,_monitor / yes, turn it off 303: tst (sp)+ 304: #endif AZ 305: 1: 306: jsr pc,__cleanup 307: mov 4(r5),r0 308: sys exit 309: 310: .data 311: 312: / Waste first 30 or so bytes of memory, because all pointers must be 313: / greater than MAXTYPE. 314: 315: .=.+30. 316: 317: / Failure label for outermost expression (used if main() fails) 318: 319: flab: 0 / terminate program 320: 321: / Reserve storage for general use tended descriptors. 322: 323: 324: _tended: 325: 0; 0 / tended[0] 326: 0; 0 / tended[1] 327: 0; 0 / tended[2] 328: 0; 0 / tended[3] 329: 0; 0 / tended[4] 330: 0; 0 / tended[5] 331: _etended: 332: 333: _boundary: 0 334: 335: .bss 336: .data 337: #endif PDP11 338: 339: /* 340: * The following DummyRefs force the loader to load everything that 341: * iconx needs. 342: */ 343: DummyRef(_clrbound) 344: DummyRef(_ckadd) 345: DummyRef(_ckmul) 346: DummyRef(_cksub) 347: DummyRef(_coact) 348: DummyRef(_cofail) 349: DummyRef(_coret) 350: DummyRef(_efail) 351: DummyRef(_efail) 352: DummyRef(_esusp) 353: DummyRef(_fail) 354: DummyRef(_gcollect) 355: DummyRef(_interp) 356: DummyRef(_invoke) 357: DummyRef(_lsusp) 358: DummyRef(_pfail) 359: DummyRef(_pret) 360: DummyRef(_psusp) 361: DummyRef(_setbound) 362: DummyRef(_suspend)